Restoring ViewControllers and their Data sources (WIP)

Posted on Fri 25 November 2016 in Tech • Tagged with Swift, iOS

The traditional flow for restoring view controllers in UIKit goes likes this:

  1. (Required) Assign restoration identifiers to the view controllers
  2. (Required) Tell iOS how to create or locate new view controller objects at launch time.
  3. (Optional) Encode current State for later restoration

Recreating the hierarchy of view controllers is indeed easy and mostly automated but a lot of the articles out there gloss over how to restore their dependencies (hint: Grabbing references to singletons in the VC’s decodeRestorableState method is not the correct answer!)

Normally you pass dependencies like a baton between controllers. When restoring a controller, the segue isn’t called and you get an ‘empty’ controller and its up to you to restore the dependencies. It turns out the data source can adopt the same state restoring protocol as the view controller and come along for the ride.

Assign restoration ids for dependencies

Normally as apart of the app launch you’ll have some code to initialise backing data sources for your view controllers. As a small extension to this routine, we also now have to give them an ID so that the VC’s can indirectly reference them on app restore.

The app delegate method willFinishLaunchingWithOptions is called after bootstrapping but before the restoration process so is a good place to register objects.

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

    // Register Data Source

    UIApplication.registerObject(
      forStateRestoration: dataStore,
      restorationIdentifier: "DataSource"
    )
    return true
}

Tell iOS how to create or locate the dependency

Any registered dependency must conform to ‘UIStateRestoring’ protocol (UIViewControllers automatically conform to this) and allows you to define a restoration class

optional var objectRestorationClass: UIObjectRestoration.Type? { get }

If you return nil from this method, UIKIT assumes the app startup code recreated the dependency already and will be able to find it as you’ve registered it to a restoration id.

If you do specify a restoration class, it needs to define the following static method:

static func object(withRestorationIdentifierPath identifierComponents: [String], coder: NSCoder) -> UIStateRestoring?

It can return a reference to a global, init a new instance or return nil if no restoration is possible.

Restoring the Dependency as part of the Controller Decode Process

Now when you restore the view controllers state, any request to decode the datasources’s restoration id will simply be passed the registered instance. Voila! You can now reconstruct the VC’s dependencies.

class controller : UIViewController {
    // ...

    override func decodeRestorableState(with: NSCoder) {
        super.decodeRestorableState(with: with)
        guard
            let object = with.decodeObject(forKey: "DataSource"), // Any 
            let dataSource = object as? DateSourceKlass 
        else {
            return
        }
        self.dataSource = dataSource
    }
}

The one draw back to this approach, as others have noted, is how it separates Controller Restoration and Dependency Restoration into 2 distinct phases. You’ve just lost your paddle if you’ve declared your dependencies as const. I think this hints at UIKits own opinion that controllers don’t actually own their datasources and so should be declared weakly.

References


Note to Unowned Self

Posted on Sun 20 November 2016 in Tech • Tagged with Swift, iOS

Its easy to think that the answer to all closure woes is to just declare self unowned - no more reference cycles for me! However this is a very easy way to crash! Been there, done that, never again.

let me translate what 'unowned' means:

I am not the owner of this reference but I am 100% sure it will exist when I need it.

Said like that, you can see thats a pretty sizeable assumption!

A Weak reference, most of the time, will be a better bet because it makes you deal with possiblity of nil.


Python Bindings for TargetProcess

Posted on Sat 28 May 2016 in Tech • Tagged with Python, RestAPIs

Where can you find them? In one of my side projects: tpapi - an unoffical python client for TargetProcess. It takes care of interacting with the REST api and returns nice model objects for you to interact with. Some useful features worth mentioning:

Transparent Pagination of Resource Requests

Every collection of entities is actually a generator which will lazily send http requests as needed. This way we can expose a standard iterator interface over paginated resources.

Nested Model Lookup

For resource or collection attributes we return an iterator over the correct class automatically so you can continue to chain queries or pluck values.

Theres also a gist showcasing usage: here


Testing Mac Gatekeeper

Posted on Wed 29 April 2015 in Tech • Tagged with Testing, OSX

Gatekeeper on macOS guards against the execution and installation of applications from unknown sources. In order to pass this security check an application needs to be correctly signed which means its a good requirement to check before a release.

The key gotcha to watch out for when testing is to ensure the executable has been quarantined. By that I mean it has the ''com.apple.quarantine'' extended attribute present as Gatekeeper is triggered specifically at the first time you execute or install a quarantined file.

To verify the existence of the quarantine flag, you can show 'ls' output in terminal and look for the '@' at the end of the permission fields. Better yet you can use the 'xattr' command to show any extended attributes that exist on a file.

$ xattr /path/to/file

com.apple.quarantine

A programatic method to verify if the application's signature will pass gate keeper is to run the 'spctl' command.

spctl --assess --type install ./path/to/file

Spctl will exit zero on success or return one if anything failed.

Additionally you can check the actual signature use 'pkgutil' for futher details.

pkgutil --check-signature ./path/to/file

Python Descriptor Notes

Posted on Tue 11 March 2014 in Tech • Tagged with Python

  • Descriptors are any object that conform to the descriptor protocol __get__,__set__ and __del__. Properties are a common example
  • Descriptors are class level objects and you must use the obj reference passed to it in order to access the parent object.
  • This is because the descriptor protocol methods are invoked via an objects __getattribute__ - so be careful when overriding!
  • Weirdly hasattr returns false for testing if an class objects holds a specific property.

Example

References

www.docs.python.org/2/howto/descriptor.html