Dancing with play/pause app to make your life easy…
DispatchSource making Debugging easy, Analysing view changes, object state changes at run time.
Here i am to describe a way to change your Object state on the go (while running). We can change object state from debugger using breakpoints.
But breakpoint can stop the execution only when applied on code which is to be executed. But if we have to do this anywhere anytime we want.. we can not rely on breakpoints on our custom code..
Solutions to this problem lies in one of the use of DispatchSourceSignal
Most of us know about DispatchQueue, Qos class, using DispatchGroup and so on..
But we are not so aware of the api and functionality provided by DispatchSource.
From Apple Doc :
DispatchSource provides an interface for monitoring low-level system objects such as Mach ports, Unix descriptors, Unix signals, and VFS nodes for activity and submitting event handlers to dispatch queues for asynchronous processing when such activity occurs.
So lets see how this signal monitoring can let us change object state on the go that can come very handy during debug.
This signalling should be used in Debug mode in the app to block your app insight in production environment and saving your app from attackers.
The code will be in swift, so i assume all are aware of swift basic syntax, though same api is available in objectiveC also, so let me know if you need to know that..
Lets add a global property declaration to initiate signalling on passed object.
For my use case. I add this Properties above class declaration..
Signalling is set up from viewDidLoad as follows:
_ = setupSignalHandlerFor(self)
Method Description Step by Step
- As told, we are going to do this setup only on debug mode.
- We declare a optional source signal param.
- Signal is initiated for monitoring the
SIGSTOPUnix signal on the main Queue.
- Event handler is added when ever signal is received.
- Sources start off in suspended state so it is started by calling
Now we have set up signalling for Unix Signal, which can be used to change object State, right ..
Are you asking the same questions, how to use for updating object state ?
Lets solve the mystery
Now run your app in Debug mode and let signalling be set up. Pause the app using the control given here and play it again.
Playing it again will hit your signal and your log statement will be printed.
Now if you put breakpoint on the print Statement, you can intercept the execution anywhere in the app by using pause and play..
Now see how i used it to change the object state..
Write this in debugger:
Will print “<YourModule.ControllerName: 0x7fb43d40fbf0>”
So this means object is our controller instance and its property can be change .
e.g. Toggling button hidden state.
expr object.searchButton.isHidden = false
The Xcode debugger can sometimes be uncooperative in making change on your object instance directly. In that case, we have to declare a debug var pointing to object as follows:
expr let $vc = unsafeBitCast(0x7fb43d40fbf0, to: YourModule.ControllerName.self)
And then your changes will work:
expr $vc.searchButton.isHidden = false
Now when you play the app you can see the searchButton has magically appear.
In short: We can now make change to object state anytime we want with just pause, play and making change from debugger.
Use Case: Since we can change object property anytime, it is kind of a magic wand in hand. You can use it to any extend you want, i have been using it mostly for following changes, and would be interested to know how you used it and how much time does it save for you, since you longer has to run app again and again after such changes :)
- UI changes with dynamic data.
- Flow changes dependent on different states .
- Different UI themes.
It may not be evident of what can it be used for, so i am adding a simple example for one use case.
I have a screen which has a horizontal stack view representing user data (Name, gender, age) and as these are dynamic and optional data, Anyone of it can be nil.
I want to check how will it behave when any of that label is made hidden.
One option is to run it every time with hiding/unhiding the labels.
But this could be time taking and frustrating, suppose we have this screen deep embedded in app flow, and changing it in code and running again and again will take time.
Second option is to use signal handler approach, lets see how it can be used and how it will save our time.
- Add signal observer as explained above.
- Now lets have a pause/play dance.
3. Play it again and we will get this.
4. Pause and play again and again to make more changes
5. We can also make more changes (Color, text etc. )as follows
We were able to check all these changes in one run of app, with just playing with pause/play game.. :)
Here i just described one example of how it can save our time, efforts.
It could also be used to check how design looks in real time..
Really could prove very helpful especially with dynamic data and multiple screen sizes.
This is the end of the small tutorial of making your app adaptive to run time changes..
Let me know how you used it in your app and how effective it has been for you. Will be happy to add any more use cases :)