Quantcast
Channel: [Thinking inside a large box];
Viewing all 69 articles
Browse latest View live

Switching iOS devices and the Keychain

$
0
0

Unfortunately some of my MovieLoggr users ran into the following issue: After switching to a new phone and restoring it from a Backup MovieLoggr would behave unexpectetly (and in some cases crash) because the App could no longer access the user’s password and unfortunately did not handle this gracefully.

Typically iOS applications store passwords in the encrypted Keychain. When creating unencrypted backups, which is the default for creating backups with iTunes, the iOS Keychain is not stored (it is stored if you create an encrypted one or use iCloud backups). This means, after restoring your new device from a backup, all of your apps that now run on your new device can no longer access the passwords they have securely stored on your previous device.

When using the Keychain to store passwords you should be able to handle this case and request the user to re-enter their account credentials when restoring your app from an unecrypted backup.

If the case that I described occurs, the Keychain will inform you that the password you are looking for could not be found, this is where you need to ask the user to re-enter their password. You can reproduce this case for testing purposes by choosing a different ServiceName for accessing the Keychain than you used for creating the Keychain entry.

P.S.: Apple’s Keychain API is pretty arcane so I’m using SSKeychain which provides a nice abstraction instead.


"I didn't know that" is the best way to learn

$
0
0

This is no original thought. Nevertheless I’ve been thinking about it often enough to make it worth spending a few minutes framing it in my own words.

I’m currently working as a Software Engineer. According to Wikipedia that makes me a Knowledge Worker.

Knowledge workers are workers whose main capital is knowledge.

Most Software Engineers that I’ve met in my short career know that knowledge is their main asset. Unfortunately this can have very negative side effects.

Being paid for having knowledge in a scientific field or a certain technology makes it very hard to say “I didn’t know that”. After all, if knowledge is your main asset how could you admit the lack thereof?

I believe that being honest about what we (believe to) know and what we don’t is essential for our learning process as professionals. If it was possible to visualize the knowledge of any two people working in the same profession it would probably look somewhat like this:

image

In the fields we are working today the things we could know about are growing faster than anyone can learn them. We are essentially knowing less and less about our field, every single day.

Whatever sort of formal education you have, that portion is only a very small (yet very important) part of your entire knowledge. The rest of your knowledge is based on your personal experience. The chance that you know something your colleague does not know and vice versa is very high, for any given topic and for any point in time.

I think there are three potential reactions when being confronted with something you don’t know:

  • Nod and pretend you know about it
  • Nod, pretend you know about it and go read about it afterwards
  • Admit that you never heard about it and extract as much knowledge as possible from the conversation

Don’t get me wrong. Reading is great and I think we all should thrive to increase our knowledge in whichever field we are working in. But if you have the chance to learn something you are interested in from a person who knows about it at the small cost of a “I didn’t know that” it wouldn’t be smart to let that opportunity pass by.

Learning from other people is incredibly powerful and one the fastest ways to gain new knowledge. Smart people are happy to share their knowledge. You should ask as many questions as possible.

While writing this I felt like I should come up with a new definition of a knowledge worker, one that is closer to the reality of explosive information growth in the 21st century:

Knowledge workers are workers with a strong understanding of concepts in their field and an ability to quickly acquire new knowledge by the most efficient means.

You know a little, you know a lot. Make the best out of this contradiction.

Breaking Swift with NSObject and Generics

$
0
0

Today, while trying to implement a generic data source in Swift, I ran into my first Swift compiler segmentation fault, yay (looking at Open Radar there seem to be many out there)!

Here’s what I was trying to implement

public class ArrayDataSource<T> : NSObject {

  private var array: Array<T>

  public init(array:Array<T>) {
    self.array = array
  }
}


extension ArrayDataSource : UITableViewDataSource {
  public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 0
  }

  public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    return UITableViewCell()
  }
}

A class that takes an array and implements UITableViewDataSource using the content of that array (an idea that’s discussed in objc.io issue #1).

The Error

As you can see I didn’t get very far before running into the compiler error. When you compile the above code (in Xcode 6.1.1 or Xcode 6.3) you’ll see the following error message:

Segmentation Fault 11: While emitting IR for source file /Users/benjaminencz/Development/Private/OSS/ListKitDemo/ListKit/ArrayDataSource.swift

Along with a nice stack trace from swift compiler:

Finding a generic reproducable example

Since this issue exists in both Xcode 6.1.1 and Xcode 6.3 I wanted to file a bug report to make sure this gets resolved in future. I played around with different ways to fix the issue, here are two simple ones that worked:

  • Move the conformance to the UITableViewDataSource protocol into the class definition instead of the class extension
  • Remove the generic type from ArrayDataSource

To actually file a bug report I needed to come up with a generalized, short piece of code that can reproduce the issue. After trying multiple combinations I found this to be the one that describes the problem best:

public class D<T>: NSObject {}

extension D: NSObjectProtocol {}

These two lines are enough code to cause the segmentation fault. The underlying issue seems to be a combination of subclassing from NSObject, using generics and conforming to NSObjectProtocol in a class extension while the actual implementation of NSObjectProtocol happens through inheritance of NSObject.

I couldn’t get this minimalistic example to break with any other combination of protocols and subclassing, it seems to be a problem specific to NSObject. If you find a more general case that causes the segmentation fault, I’d love to hear from you.

For now I have filed a bug report with Apple (19889552) and an Open Radar Issue.

Talk: Introduction to FRP on iOS

$
0
0

Back in April I gave a talk at NSMeetup in San Francisco on Functional Reactive Programming on iOS.

The talk discusses the idea & motivation behind FRP and dives into some practical examples using Reactive Cocoa 2.x. The examples are based on a small demo app that I built for that talk.

Once Reactive Cocoa 3.0 has a final release I will likely update this talk to Swift - especially generics are extremely useful when working with the FRP toolset.

You can find a recording of the talk on YouTube. The slides are embedded here and available through Speakerdeck.

iOS 9 Detects Cycles in Layout Trees

$
0
0

A couple of months ago I was faced with an issue that was fairly hard to debug:

What I found out, after about 30 minutes of debugging, was the following:

The hackathon attendee hat mistakenly set the accessoryView of a UITableViewCell to the UITableView in which the cell was contained - causing an endless recursion during the first layout cycle.

This however wasn’t immediately obvious to me since the symptom was an exception within the cellForRowAtIndexPath: method.

Fixed in iOS 9

Today I wanted to see if it is possible to reproduce the issue with Xcode 7 Beta 3.

Indeed, I can still cause the crash. However, instead of causing a stack overflow the app now terminates because CALayer throws an exception:

CrashTableViewCell[33582:11713163] *** Terminating app due to uncaught exception 'CALayerInvalid', reason: 'layer <CALayer: 0x7f875943c730> is a part of cycle in its layer tree

I couldn’t find any reference to this exception in a Stack Overflow exception so I assume the cycle detection is new in iOS 9.

This fix will likely save some headaches!

It also serves as a good real world example of detecting cycles in directed graphs.

Swift Error Handling and Objective-C Interop in Depth

$
0
0

For the impatient reader:

TL;DR

  • The ErrorType protocol has hidden requirements that are automatically fullfilled if you use an enum to implement the protocol
  • Objective-C methods can only be translated to Swift’s error handling mechanism if they return Objective-C objects or boolean values
  • Swift will invoke the catch block if the Objective-C method returns nil/false, independent of whether an NSError was produced or not
  • If an Objective-C method produces an NSErrorand returns a value the catch blocks is not invoked and the error cannot be retrieved
  • GitHub project with examples

Fun With Errors

Recently I’ve spent some time looking into the new error handling mechanism in Swift in depth. I’ve especially focused on its interoperability with Objective-C which is documented fairly lightly as of now (Xcode 7 Beta 4).

It started with the following lines of code, in which I tried to experiment with creating a custom error type using a struct (instead of the canonical example in which we use an enum):

struct MyErrorType: ErrorType {
  var errorDetails: String
}

This results in the following compiler error:

Type 'MyErrorType' does not conform to protocol 'ErrorType'.

That was pretty surprising, given that the protocol definition for ErrorType in Xcode looks like this:

protocol ErrorType {
}

Hidden Protocol Requirements

The error message revealed two hidden protocol requirements:

image

This means the actual protocol definition for ErrorType looks like this:

protocol ErrorType {
    var _domain: String
    var _code: Int
}

When using an enum to define a custom ErrorType these fields are automatically generated and populated (this is discussed in WWDC 2015 Session 402, 08:20 min).

These two fields, domain and code, are also provided by NSError, so I assume these fields are primarily used for compatibility with Objective-C.

You might wonder how these fields are populated when using a custom ErrorType?

Me too! So let’s create this simple error type:

enum MyError: ErrorType {
  case BasicError, FatalError
}

And write a throwing function:

func badFunction() throws {
  throw B.FatalError
}

Along with a catch block to print the _code and _domain members of the error:

do {
  try badFunction()
} catch let error as MyError {
  print("domain: \(error._domain) code:\(error._code)")
} catch {

}

This is the result that you will see in the console:

domain: FunWithErrors.MyError code: 1

The _domain member matches the module name in which the custom ErrorType was defined and the _code matches the raw enum value (BasicError = 0, FatalError = 1).

Nothing too exciting here, but an interesting look under the covers. Next, let’s see how Objective-C’s NSError works with Swift’s error handling.

Throwing From Objective-C

Let’s build the simplest throwing Objective-C method following this rule in the documentation:

If the last non-block parameter of an Objective-C method is of type NSError **, Swift replaces it with the throws keyword, to indicate that the method can throw an error.

Methods That Return void

This is a simple Objective-C class that has a method that should throw:

@interface ErrorProducer : NSObject

+ (void)doWithError:(NSError**)error;

@end

However, when calling this method from Swift we need to provide an NSErrorPointer and the method does not throw:

image

For some reason the automatic translation promised by Swift is not working in this case.

After mutating the method signature multiple times, I found out that the method is only translated to Swift’s error handling mechanism if it returns an Objective-C object or a boolean value.

Methods That Return Objective-C Objects or Boolean Values

This method for example:

+ (NSString *)provideStringWithError:(NSError**)error;

Can be used from Swift as expected:

image

So let’s provide a simple implementation for this method to see how we can catch the thrown NSError in Swift:

+ (NSString *)provideStringWithError:(NSError**)error {
  if (error) {
    *error = [NSError errorWithDomain:@"FunWithErrors" code:0 userInfo:nil];
  }

  return @"";
}

And on the call side we provide a do/catch block:

do {
  try ErrorProducer.provideString()
} catch let error as NSError {
  print("domain: \(error.domain) code: \(error.code)")
}

If you run this code Swift code… nothing will be printed to the console! The catch block will never be reached.

It seems that the return value of an empty string (@"") is indicating that the method returned successfully, even though an error was assigned to the error pointer.

If we change the implementation of the Objective-C method to return nil, the catch block is invoked correctly:

+ (NSString *)provideStringWithError:(NSError**)error {
  if (error) {
    *error = [NSError errorWithDomain:@"FunWithErrors" code:0 userInfo:nil];
  }

  return nil;
}

From Swift’s perspective this makes sense. Every Swift function that throws will return to the caller without providing the expected return value. In Objective-C however, NSError is sometimes used as an additional return value indicating that some minor issue occurred, while the main return value could still be created as expected. In my understanding these NSError instances cannot be retrieved from Swift. It will be interesting to see if and how existing Objective-C frameworks will be modernized to accomodate for this.

There’s one more interesting case I want to look at: It almost seems like the return value is the most important factor for determining whether an Objective-C method throws or not. What happens if we return nil without assigning an NSError to the error pointer?

+ (NSString *)provideNilStringNoErrorWithError:(NSError**)error {
  return nil;
}

This indeed throws as well! Swift provides us with an instance of _SwiftNativeNSError, the domain of the produced error is Foundation._GenericObjCError and the code is 0.

As was pointed out to me, the Cocoa documentation on error handling in Objective-C discusses this emphasis on the return value of a method that can error out:

When dealing with errors passed by reference, it’s important to test the return value of the method to see whether an error occurred, as shown above. Don’t just test to see whether the error pointer was set to point to an error.

Source: Programming with Objective-C | Dealing with Errors

Summary

As of today (Xcode 7 Beta 4) the interopability between Swift’s error handling and Objective-C is lacking some documentation. Here are some interesting findings discussed throughout the blog post:

  • Objective-C methods can only be translated to Swift’s error handling mechanism if they return Objective-C objects or boolean values
  • Swift will invoke the catch block if the Objective-C method returns nil/false, independent of whether an NSError was produced or not
  • If an Objective-C method produces an NSErrorand returns a value, the catch blocks is not invoked and the error cannot be retrieved

You can find a small project that contains all of the examples used in this blog post on GitHub.

Thanks @warrenm for providing feedback and improving this post!

You can find me on twitter, too.

A Flux Inspired Architecture for iOS

$
0
0

This year I spoke at 360iDev about “Safer Swift Code with Value Types”. The goal of the talk was to explore an architecture that uses immutable value types for the model layer.

After reviewing an earlier version of this talk with my developer friend Gerald Monaco, who is a big fan of Facebook’s open source technologies (React, Flux, etc.), I decided to take a look at how a Flux-inspired architecture could be applied to an iOS application.

It turns out that the topic is fairly dense for 45 minutes, but I hope you can extract some interesting ideas from the talk! I know of at least one person that did enjoy it.

You can find the slides and the recoding below and the code for this talk is on GitHub.

If you have any I feedback, I’d love to hear it!

Convenient Error Handling in Swift

$
0
0

Swift 2 introduced an error handling mechanism that includes backwards compatibility with Objective-C.

This is great news, the new mechanism is a lot stricter. Long gone are the days in which one could ignore errors by lavishly throwing nil at methods that expect a pointer to an NSError variable.

Does Every Error Deserve an Individual Catch?

Swift will require you to provide an error handler when you call a method that throws, unless you resort to the try? or try! operator. Here’s an example of try!:

try! NSString(contentsOfFile: "doesNotExist", encoding: NSUTF8StringEncoding)

Using this unfaithful approach an unexpectedly occurring error will cause a crash. You should only use try! if your app cannot continue to work sensibly if the attempted operation fails - i.e. if you fail load the database model for your application from disk.

Alternatively you can use try?, which will transform the result of the operation you are performing into an optional. A successful operation will yield a value, a failed operation will yield nil:

let data = try? NSString(contentsOfFile: "doesNotExist", encoding: NSUTF8StringEncoding)

With this approach all details of an error that occurred will be swallowed entirely which is suboptimal in many cases as well.

But is it worth it writing a custom error handler for every error producing function you call? I don’t think so.

Many kinds of errors deserve your full attention, you can write code to recover from them or, at the very least, notify the user about unexpected behavior with a meaningful error message.

Other errors are less suitable for custom error handlers. You cannot recover from them with reasonable effort and they don’t affect the user experience. The user will not want to be informed about them. Here are examples of errors that, in my opinion, fall into this category:

  • Caching a downloaded image on disk fails
  • Your app cannot connect to the ad service you are using

Depending on the complexity of your app, there might be hundreds of such operations.

Even though you can’t recover from these errors, you should definitely keep track of them through some sort of logging mechanism! How can this be done without writing many individual error handlers?

A Good Compromise?

Can we strike a balance between convenience and due diligence? I believe so. In my latest side project I implemented a default error handler that deals with errors that, for one reason or another, don’t deserve a custom error handler.

This error handler doesn’t swallow the error completely. Instead, it logs the errors using my analytics service. This behavior is useful for any type of error that might occur in my app. It’s the largest common denominator of error handling.

This is what using the API looks like:

let errorHandler = ErrorHandler()

let fileContent = errorHandler.wrap {
    return try NSString(contentsOfFile: "doesNotExist", encoding: NSUTF8StringEncoding)
}

Here are the main characteristics:

  • We wrap the call to call to the error producing function, along with the try keyword, into a closure that gets handed to errorHandler.wrap
  • If the closure returns a value, then errorHandler.wrap will pass it through to its caller
  • errorHandler.wrap always returns an optional type, indicating that the wrapped operation might fail and return nil

In the above example the fileContent variable has a type of String?. We can use this variable in subsequent operations. While we need to check if the optional contains a value before using it, we can ignore the details of a potential error that was thrown. In this case errorHandler.wrap acts as a glorified version of try?.

In most cases I use the default error handler when calling functions without a return value. In these cases the value of the error handler becomes more obvious:

[...]
let errorHandler = ErrorHandler()

errorHandler.wrap {
	try cache.storeImage(image)
}

We can perform a failable operation without writing any code that deals with errors or optional return values, while still capturing details about errors that might occur.

Implementation of the Default Error Handler

The implementation of the error handler is very slim, here’s the entire code:

class ErrorHandler {

    func wrap<ReturnType>(@noescape f: () throws -> ReturnType?) -> ReturnType? {
        do {
            return try f()
        } catch let error {
            logError(error)
            return nil
        }
    }

    func logError(error: ErrorType) {
        let stackSymbols = NSThread.callStackSymbols()
        print("Error: \(error) \n Stack Symbols: \(stackSymbols)")
    }

}

The wrap function takes a function that can throw and that can provide a return type. It executes the function within a do/try block. If the operation is successful it returns the return value of the function. If an error occurs the catch block calls the logError function and then returns nil.

The logError function should be customized to your needs - as an example I am printing the current stack trace along with the error message. In a production environment you would likely want to log these messages using an analytics service such as Fabric or Mixpanel.

Conclusion

Good error handling is incredibly important for a good user experience - I wanted to make the process as easy as possible. Now my analytics dashboard will inform me about any unhandled error that occurs in production. Going from there I can improve error handling in my apps by adding custom handlers for the most frequent errors.

I definitely encourage you and myself to handle as many errors as sensible individually - but I believe there’s a large number of potential errors that are suitable for this generic error handling scheme.

You can find the Source Code for this blog post on GitHub.

How do you tackle error handling? I would love to hear from you!

Acknowledgements


Introducing ReSwift

$
0
0

For the last two months I have been actively working on Swift Flow with the goal of bringing the ideas of the Flux and Redux libraries to Swift developers.

At about the same @ARendtslev started ReduxKit, which had the goal of implementing Redux in Swift. Soon he was joined by @karlbowden who made significant contributions to the project (and provided amazing build and documentation infrastructure for ReduxKit and Swift Flow).

Today we have joined forces under a new name - ReSwift [ri:swɪft]. To put it in Karl’s words:

Swift Flow has adopted the name ReSwift and moved to it’s new home as a nod to it’s Redux roots that remain at it’s core. Going forward, our combined efforts will be focused on ReSwift and surrounding tooling.

The core of ReSwift is close to a 1.0 release, however the exiting stuff is in its infancy. We will be working on declarative routing, time traveling, state persistence & restoration and more.

My hope is that we can provide a viable alternative to MVC by default on iOS by developing a solid core library with great extensions and developer tools.

Either way, it will be a great learning experience for us and everyone involved!

If you’re interested in the core ideas behind ReSwift, you can watch my talk from the SLUG Meetup last December.

In case you missed the link: ReSwift is on GitHub.

How I Write Swift Specs With Quick

$
0
0

I’ve recently tweaked the way I write Quick specs. I came to realize that I was placing a majority of my testing code inside of it blocks. This seems to be common among many code bases that use Quick/Nimble.

I felt that I could gain more readability by focusing on testing expectations within in it blocks and driving the test code outside.

I now structure most of my tests in the following way:

  1. A describe or context block describes the scenario under test
  2. The beforeEach block contains code to implement the scenario
  3. The it block only validates expectations

The result looks somewhat like this, though I have emitted variable declarations in outer scopes for brevity:

// describe the scenario under test
context("when #download is called multiple times with the same URL") {

	// variables which will be used from `it` blocks
	var downloadDescription: DownloadDescription!

    beforeEach {
    	// code to drive the scenario
        downloadDescription = DownloadDescription(
            url: NSURL(string: "http://test.com/download")!,
            priority: 500,
            downloadLocation: NSURL(string: "file://")!
        )

        (1..<10).forEach { _ in
            downloadManager.downloadAsset(downloadDescription)
        }
    }

    // Multiple expectations for that scenario:

    it("only asks the downloader to download the asset once") {
        expect(mockDownloader.receivedCallsToStartDownload)
        .to(haveCount(1))
    }

    it("keeps the ongoing download enqueued") {
        expect(downloadManager.queue)
        .to(contain(downloadDescription))
    }
}

For me it is a lot easier to read these tests, the expectations are clearly separated from the code that drives the test.

This approach has two minor drawbacks:

  • The it block needs to reference variables that are set from within the beforeEach block. We therefore need to declare more variables in the context/describe scope which adds some visual clutter.
  • Having the code that drives the test in beforeEach might look a little awkward at first, as most testing frameworks use these hooks to set up a shared test environment; not to drive the test code.

Future Improvements?

In future it might be nice to be able to place the test driving code directly in the context block. Something along these lines:

context("when multiplying two numbers") {
	let i = 2 * 2

    it("stores the correct result") {
    	expect(i).to(equal(4))
    }
}

I believe this isn’t possible, because Quick can’t register the top-level code within context block to run as part of the tests, though I haven’t looked at the implementation in detail.

This would mitigate the two drawbacks of my current approach and improve the readability of the specs a little more.

For now I’m happy with the beforeEach approach. How do you write your Swift test suites?

Validated: A Swift μ-Library for Somewhat Dependent Types

$
0
0

Today I built & published a μ-library that makes it easier to leverage Swift’s type checking system for program verification: Validated.

Why?

All Swift developers already use the type system to avoid basic type mismatches (e.g. passing an Int where a String is expected), this capability is built into the languge itself.

A type system can however help verifying more than just the abscence of these simple errors. This requires that developers express constraints and semantics of their programs in types. Validated provides a simple way to lift requirements about values into the type system.

Here’s an example from the GitHub Readme:

You might have a function in your code that only knows how to work with a User value when the user is logged in. Usually you will implement this requirement in code & add documentation, but you don’t have an easy way of expressing this invariant in the type signature:

/// Please ever only call with a logged-in user!
func performTaskWithUser(user: User) {
    precondition(
    	user.loggedIn,
    	"It is illegal to call this method with a logged out user!"
    )

	// ...
}

Using Validated you can quickly create a new type that describes this requirement in the type system. That makes it impossible to call the function with a logged-out user and it makes the method signature express your invariant (instead of relying on documentation):

func performTaskWithUser(user: LoggedInUser) {
	// ...
}

In short: Validated allows you to create new types, by taking existing types and adding validations to them. These new types can be used throughout your APIs to express expectations not only about types, but also about values.

I’m very interested in hearing whether this is useful to you & how it could be improved!

To learn how to use this you should head to GitHub!

Squashing Commits With Git Rebase: A Very Quick Guide

$
0
0

Git’s interactive rebase is extremely useful for keeping a somewhat clear commit history. Here’s a very brief guide on how to squash multiple commits into a single one.

Git rebase allows you to rewrite the history of a git repository. Yes, you are right, this can be incredibly dangerous, therefore don’t use this technique on branches that are shared with other developers. To me rebase is most useful for preparing a branch that is about to be merged into the main branch of a project.

Let’s assume our branch’s commit log is in the following state (printed by using git log):

We have a bunch of intermediate commits for stages in which our code was not working as expected ending with a commit that indicates that our feature/bug fix is complete.

Having all of these commits in the history of a project would mean that the commit log would quickly become very difficult to read.

Git rebase allows us to turn these 3 intermediate commits into a single one.

The following command will bring you into git’s interactive rebase mode:

git rebase -i HEAD~3

There are different ways to choose the range of commits you want to rebase. I mostly end up using HEAD~N to rewrite the latest N commits.

This will bring up the following screen:

You can now see the 3 commits you are about to rewrite. There are many different commands available, we are only going to use squash for now.

Type an s for squash in front of the commits that you want to squash together. In our example we choose the final commit along with one intermediate commit to be squashed into the first intermediate commit (this will turn 3 commits into one):

Then close the text editor. Next, git will bring up a screen that will allow you to choose some details for each rebasing step. In our example we only have a single step - the one in which we merge 3 commits into one.

Git will allow you to change the commit message for this new squashed commit. It starts out by showing you the messages of all commits it is about to squash:

Now you can choose a new, descriptive, commit message:

Close the text editor by saving, and you’re done. If you take a look at the new commit history via git log, you should see the following output:

A clean commit history that is ready to merge!

Compile Time vs. Run Time Type Checking in Swift

$
0
0

At some point, when learning how to use Swift’s type system, it is important to understand that Swift (like many other languages) has two different forms of type checking: static and dynamic. Today I want to briefly discuss the difference between them and why headaches might arise when we try to combine them.

Static type checking occurs at compile time and dynamic type checking happens at run time. Each of these two stages come with a different, partially incompatible, toolset.

Compile Time Type Checking

Compile time type checking (or static type checking) operates on the Swift source code. The Swift compiler looks at explicitly stated and inferred types and ensures correctness of our type constraints.

Here’s a trivial example of static type checking:

lettext:String=""// Compile Error: Cannot convert value of // type 'String' to specified type 'Int'letnumber:Int=text

Based on the source code the type checker can decide that text is not of type Int - therefore it will raise a compile error.

Swift’s static type checker can do a lot more powerful things, e.g. verifying generic constraints:

protocolHasName{}protocolHumanType{}structUser:HasName,HumanType{}structVisitor:HasName,HumanType{}structCar:HasName{}// Require a type that is both human and provides a namefuncprintHumanName<T:protocol<HumanType,HasName>>(thing:T){// ...}// Compiles fine:printHumanName(User())// Compiles fine:printHumanName(Visitor())// Compile Error: cannot invoke 'printHumanName' with an // argument list of type '(Car)'printHumanName(Car())

In this example, again, all of the type checking occurs at compile time, solely based on the source code. The swift compiler can verify which function calls provide arguments that match the generic constraints of the printHumanName function; and for ones that don’t it can emit a compile error.

Since Swift’s static type system offers these powerful tools we try to verify as much as possible at compile time. However, in same cases run time type verification is necessary.

Run Time Type Checking

In some unfortunate cases relying on static type checking is not possible. The most common example is reading data from an outside resource (network, database, etc.). In such cases the data and thus the type information is not part of the source code, therefore we cannot prove to the static type checker that our data has a specific type (since the static type checker can only operate on type information it can extract from our source code).

This means instead of being able to define a type statically, we need to verify a type dynamically at run time.

When checking types at run time we rely on the type metadata stored within the memory of all Swift instances). The only tools we have available at this stage are the is and as keywords that use that metadata to confirm whether or not the instance is of a certain type or conforms to a certain protocol.

This is what all the different Swift JSON mapping libraries do - they provide a convenient API for dynamically casting an unknown type to one that matches the type of a specified variable.

In many scenarios dynamic type checking enables us to integrate types that are unknown at compile time with our statically checked Swift code:

functakesHuman(human:HumanType){}varunknownData:Any=User()ifletunknownData=unknownDataas?HumanType{takesHuman(unknownData)}

All we need to do in order to call the function with unknownData is to cast it to the argument type of the function.

However, if we try to use this approach to call a function that defines arguments as generic constraints, we run into issues…

Combining Dynamic and Static Type Checking

Continuing the earlier printHumanName example, let’s assume we have received data from a network request, and we need to call the printHumanName method - if the dynamically detected type allows us to do that.

We know that our type needs to conform to two different protocols in order to be eligible as argument for the printHumanName function. So let’s check that requirement dynamically:

varunknownData:Any=User()ifletunknownData=unknownDataas?protocol<HumanType,HasName>{// Compile Error: cannot invoke 'printHumanName' // with an argument list of type '(protocol<HasName, HumanType>)'printHumanName(unknownData)}

The dynamic type check in the above example actually works correctly. The body of the if let block is only executed for types that conform to our two expected protocols. However, we cannot convey this to the compiler. The compiler expects a concrete type (one that has a fully specified type at compile time) that conforms to HumanType and HasName. All we can offer is a dynamically verified type.

As of Swift 2.2, there is no way to get this to compile. At the end of this post I will briefly touch on which changes to Swift would likely be necessary to make this approach work.

For now, we need a workaround.

Workarounds

In the past I’ve used one of these two approaches:

  • Cast unknowndData to a concrete type instead of casting it to a protocol
  • Provide a second implementation of printHumanName without generic constraints

The concrete type solution would look something like this:

ifletuser=unknownDataas?User{printHumanName(user)}elseifletvisitor=unknownDataas?Visitor{printHumanName(visitor)}

Not beautiful; but it might the best possible solution in some cases.

A solution that involves providing a second implementation of printHumanName might look like this (though there are many other possible solutions):

func_printHumanName(thing:Any){iflethasName=thingas?HasNamewherethingisHumanType{// Put implementation code here// Or call a third function that is shared between// both implementations of `printHumanName`}else{fatalError("Provided Incorrect Type")}}_printHumanName(unknownData)

In this second solution we have substituted the compile time constraints for a run time check. We cast the Any type to HasName, that allows us to access the relevant information for printing a name, and we include an is check to verify that the type is one that conforms to HumanType. We have established a dynamic type check that is equivalent to our generic constraint.

This way we have offered a second implementation that will run code dynamically, if an arbitrary type matches our protocol requirements. In practice I would extract the actual functionality of this function into a third function that gets called from both printHumanName and _printHumanName - that way we can avoid duplicate code.

The solution of the “type erased” function that accept an Any argument isn’t really nice either; but in practice I have used similar approaches in cases where other code guarantees that the function will be called with the correct type, but there wasn’t a way of expressing that within Swift’s type system.

Conclusion

The examples above are extremely simplified, but I hope they demonstrate the issues that can arise from differences in compile time and run time type checking. The key takeaways are:

  • The static type checker runs at compile time, operates on the source code and uses type annotations and constraints for type checking
  • The dynamic type checker uses run time information and casting for type checking
  • We cannot cast a an argument dynamically, in order call a function that has generic constraints.

Is there potential for adding support for this to Swift? I think we would need the ability to dynamically create & use a constrained metatype. One could imagine a syntax that looks somewhat like this:

iflet<T:HumanType,HasName>value=unknownDataas?T{printHumanName(value)}

I know too little about the Swift compiler to know if this is feasible at all. I would assume that the relative cost of implementing this is huge, compared to the benefits it would provide to a very small part of the average Swift codebase.

However, according to this Stack Overflow answer by David Smith, Swift currently checks generic constraints at run time (unless the compiler generates specialized copies of a function for performance optimizations). This means the information about generic constraints is still available at run time and, at least in theory, the idea of dynamically created constrained metatypes might be possible.

For now it is helpful to understand the limitations of mixing static and dynamic type checking and to be aware of the possible workarounds.

I cannot finish this post without a fabulous quote from @AirspeedSwift:

Runtime type checking and compile-time generics are like steak and ice-cream – both are nice but mixing them is a bit weird. - Source: StackOverflow.com

If you have corrections or general thoughts on this post, I would love to hear from you.

Addendum:

Russ Bishop (in the comments) and Joe Groff (on twitter) pointed out that the idea presented in this post is already being discussed as part of extending Swift’s support for generics. The twitter conversation also revealed that all compile time information is available at runtime, too. This opens the door for exciting extensions to Swift’s type system in future.

The relevant conversation on twitter is here:

Decoding Heterogeneous Collections in Swift

$
0
0

The problem of decoding Swift types from an outside data source, such as JSON, has been mostly solved. Since Swift’s release we’ve seen more than a dozen popular JSON mapping libraries pop up.

However, most of the libraries I’ve seen so far deal with decoding individual types, not entire collections of heterogeneous types.

We define how a JSON object representing a user can be mapped to a User type, as in this example:

structUser:Decodable{letname:Stringletage:Intstaticfuncdecode(json:AnyObject)throws->User{returntryUser(name:json=>"name",age:json=>"age")}}

This approach requires the developer to know that a certain piece of JSON will ever only contain user objects.

But how can we handle heterogeneous collections like the following one?

 [
  {
      "type" : "user",
      "name" : "test",
      "age"  : 99
  },
  {
      "type"  : "car",
      "color" : "green"
  },
  {
      "type" : "phone",
      "model" : "iPhone"
  },
  {
      "type"  : "car",
      "color" : "yellow"
  },
  {
      "type" : "phone",
      "model" : "Anroid Device"
  }
]

In this example we have three different types: “user”, “car” and “phone”, that can occur anywhere throughout the JSON array. In order to use one of the JSON mapping libraries we would need to inspect each individual element in this list, identify it’s type, and then call the initializer of the respective Swift type.

Dynamically Mapping JSON Entities and Types

In Objective-C it would be fairly easy to solve this problem automatically. We can rely on the Objective-C runtime to dynamically look up a class by its name and create the relevant instance for each entity we find in the JSON array.

In Swift we cannot rely on these run time mechanisms, but we can still create a mapping between a JSON type and a Swift type.

The first step is to introduce a protocol for all types that can be deserialized with our new mechanism. These types will need to fulfill two requirements:

  1. They need to be able to be initialized with a JSON entity
  2. They need to provide a typeIdentifier string that we can use to match the “type” identifier from our JSON example above.

Here’s what the protocol looks like in my example:

protocolDeserializable:Decodable{staticvartypeIdentifier:String{get}}

Note that I’m relying on the Decodable JSON mapping library to require the JSON initializer for me via the Decodable protocol.

Each of the individual types will now implement this protocol. Here’s an example for the User type:

structUser:Deserializable{staticlettypeIdentifier="user"letname:Stringletage:Intstaticfuncdecode(json:AnyObject)throws->User{returntryUser(name:json=>"name",age:json=>"age")}}

This is mostly the regular JSON mapping code we’re familiar with. The only addition is the static typeIdentifier member that tells us what this type is called in the JSON array.

We also implement this protocol for the other types represented in the JSON array (Carand Phone) but I will spare you the details of that…

Now to the interesting part. We need a component that can take the entire, heterogeneous, array of JSON objects, can iterate over all of them and create the correct Swift instances based on the types it finds.

For this example I’ve called the type Deserializer. Here’s what it looks like:

structDeserializer{privatevarmodelLookupTable:[String:Deserializable.Type]=[:]init(models:[Deserializable.Type]){// Store all types in lookup tableformodelinmodels{self.modelLookupTable[model.typeIdentifier]=model}}funcdeserialize(json:[[String:AnyObject]])->[Deserializable]{varparsedModels:[Deserializable]=[]// Iterate over each entity in the JSON arrayforjsonEntityinjson{// Find metatype for this entityguardlettype=jsonEntity["type"]as?Stringelse{continue}guardletmodelMetatype=modelLookupTable[type]else{continue}// Call initializer on the metatypeifletmodel=try?modelMetatype.decode(jsonEntity){parsedModels.append(model)}}returnparsedModels}}

This type gets initialized with an array of model metatypes ([Deserializable.Type]). This is necessary in order for the component to know which types can appear within the JSON array it will deserialize. Since we cannot dynamically look up types at runtime, we need to require a developer to manually provide all the types as part of the Deserializer setup.

We now store these types in a modelLookupTable. This is a simple dictionary that maps from the types typeIdentifier to the metatype itself. We will use this lookup table within the deserialize method.

The deserialize method takes a JSON array and returns a heterogenous list of Deserializable models. The implementation iterates over each entity in the JSON array. It extracts the “type” property from each entity and uses that string to find the relevant metatype in our modelLookupTable. If we can find a Swift type that matches the JSON type identifier then we will proceed and try to decode that type with the current jsonEntity. If the decoding works successfully, we add the instantiated type to the parsedModels array. At the end of the deserialize function we return the list of decoded models.

With all this in place, we can now create an instance of the deserializer and use it:

letdeserializer=Deserializer(models:[User.self,Car.self,Phone.self])letmodels=deserializer.deserialize(jsonArray)print(models)

The printed output will now be a list of the different instances that have been decoded:

[User(name: "test", age: 99), Car(color: "green"), Phone(model: "iPhone"), Car(color: "yellow"), Phone(model: "Anroid Device")]

I hope this concept is useful to some other Swift developers as well. You can find a playground with the full example code on GitHub.

Beware the UIKit Visitors!

$
0
0

Investigating the Cause of Quadratic Time Complexity When Adding Subviews in UIKit

Yesterday Two weeks ago we identified a performance regression in the PlanGrid app, when entering a view that dynamically adds a large amount of subviews.

I started this blog post back then, but was recently motivated to finish it quickly by seeing other developers running into this issue as well:

For this blog post I wanted to isolate this issue from our code base. I was able to reproduce the issue with this minimal example inside of a blank UIViewController:

overridefuncviewDidAppear(animated:Bool){super.viewDidAppear(animated)self.view.tintColor=.blueColor()foriin1..<10000{letview=UIView()self.view.addSubview(view)}}

The above example is obviously extreme, but it reveals an interesting performance issue: when setting a tintColor on a parent view, and not setting an explicit color on child views the performance of addSubview reduces itself drastically with a large amount of added subviews.

Here’s what I could identify within Instrument’s time profiler:

A majority of the time is adding subviews is spent within [_UITintColorVisitor _visitView:]. In this example it’s 64% of the time; and the proportion only increases with the amount of subviews we’re adding.

We like our custom tint color; but not enough to justify such an impact on performance. By deactivating the custom tint color we bring the overall run time of viewDidAppear from our example project from over 700ms down to ~10ms.

The same affect can be accomplished by specifying the tintColor on each view we’re adding, which stops the expensive _UITintColorVisitor from stopping by too often.

Digging into UIKit

Finding a workaround for this issue is only half of the fun. Let’s try to find out what is causing these poor performance characteristics in the first place. We can start by taking a closer look at the time profiler output:

We can see that the app doesn’t spend too much time in [_UITintColor _visitView] itself. The majority of the time is consumed by objc_msgSend which indicates that this method is causing many, many method invocations or the method itself is being called extremely frequently. Further, we’re spending a lot of time in [NSArray containsObject:] which either means that the array is being searched through too often in the first place, or that a data structure that is more efficient for lookups should be used instead of an array (e.g. a dictionary or a set).

Breakpoints in Framework Functions

We can start by setting a breakpoint within the [_UITintColor _visitView] method; that will give us an idea of how often that method is called.

We can do that by setting a breakpoint early in our program to bring up the lldb console (alternatively we could use lldb from the terminal). Then we can enter the following command to set a breakpoint:

(lldb) b -[_UITintColorVisitor _visitView:]

Now we can continue execution; soon we should trap into our breakpoint:

Checking how often this method is called, I quickly identified that the amount of calls grows with the amount of subviews we have added. As a next step I wanted to see which views exactly are being visited. For that we need to dive into a little bit of assembly code.

Inspecting the Assembly Code

When stepping into the breakpoint in -[_UITintColorVisitor _visitView:] you are greeted with a cryptic wall of assembly code. I started out with very barebones knowledge of understanding/investigating complex assembly code, but this bug forced me to learn some tricks that hopefully are useful to you as well!

Running the Example App on 32-Bit Mode

Update:I have gotten feedback from multiple readers, that Hopper works just as well in 64-Bit mode, and actually makes accessing arguments easier. For my next disassembly adventure I will try 64 instead of 32-Bit.

As a first step, let’s ensure that our app runs in 32-Bit mode in the simulator. This architecture is known as i386. We choose to run the app in 32-Bit mode since i386 has a simpler way of passing function arguments (which will come in handy shortly). In Xcode 7 the easiest way to run on the i386 architecture is to select the iPad 2 simulator.

With this setup in place, we can now inspect which views are visited from within our breakpoint in -[_UITintColorVisitor _visitView:]. Looking at the method signature we can see that this method takes on argument: the view that is being visited. That’s the information that we would like to inspect further. In addition to that explicit argument every method call in Objective-C receives self as the first and the selector as the second implicit argument.

Printing Function Arguments in Assembly

By using this handy reference we can look up where these arguments are stored when a method is called (the reference is old and refers gdb instead of lldb, but the info is still up to date.). The order of these arguments is part of what we call a “calling convention”. It states that on a i386 architecture function arguments are passed as follows:

  • Before prologue:
    • *($esp+4n) ➡ arg(n)
  • After prologue:
    • *($ebp+8+4n) ➡ arg(n)

The n here refers to the index of the argument.

Without getting into too much detail at this point: the “prologue” is a sequence at the beginning of a function call that configures the stack pointer and different stack variables. The variable locations for our function arguments are different before and after the prologue (this blog post by Ari Grant has a good description for what the function prologue and epilogue do). All arguments are offset from the base address that is stored in the esp register.

For now we’ll use the addresses before the prologue, since we’ll access the arguments as soon as we trap into our breakpoint at the beginning of the -[_UITintColorVisitor _visitView:] method.

When we reach that breakpoint we can print all 3 arguments to our function call as following:

(lldb) po *(id *)($esp+4)
<_UITintColorVisitor: 0xc502540>

(lldb) po *(SEL *)($esp+8)
"_visitView:"

(lldb) po *(id *)($esp+12)
<UIView: 0xc131830; frame = (0 0; 768 1024); autoresize = W+H; tintColor = UIDeviceRGBColorSpace 0 0 1 1; layer = <CALayer: 0xc1176d0>>

Now we can use this new ability to print the visited view every time we step into our breakpoint, by calling: po *(id *)($esp+12) (alternatively you can also use a breakpoint command).

Using this technique I identified that after a new subview is added, the parent view and all of its children are passed to calls of -[_UITintColorVisitor _visitView:]. For each added view UIKit will iterate all of its siblings.

Why exactly is that happening? I have not yet been able to track it down definitely, but I have a bunch more clues that I’d like to share.

Let the Guesswork begin

Since we want to know why the _UITintColorVisitor is called so frequently, it makes sense to start by investigating the backtrace. We can do this with the bt lldb command that we can invoke while halted in a breakpoint:

(lldb) bt
* thread #1: tid = 0x156ea9, 0x00e4b61c UIKit`-[_UITintColorVisitor _visitView:], queue = 'com.apple.main-thread', stop reason = breakpoint 9.1
  * frame #0: 0x00e4b61c UIKit`-[_UITintColorVisitor _visitView:]
    frame #1: 0x00e4bfbb UIKit`_UIViewVisitorEntertainVisitors + 107
    frame #2: 0x00e4af30 UIKit`_UIViewVisitorRecursivelyEntertainDescendingVisitors + 162
    frame #3: 0x00e4a8ca UIKit`_UIViewVisitorEntertainDescendingTrackingVisitors + 705
    frame #4: 0x00e4a2be UIKit`_UIViewVisitorEntertainHierarchyTrackingVisitors + 58
    frame #5: 0x00a9ce3f UIKit`__45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 268
    frame #6: 0x005b1440 Foundation`-[NSISEngine withBehaviors:performModifications:] + 150
    frame #7: 0x005b491c Foundation`-[NSISEngine withAutomaticOptimizationDisabled:] + 48
    frame #8: 0x00a9cce4 UIKit`-[UIView(Hierarchy) _postMovedFromSuperview:] + 521
    frame #9: 0x00aac7f1 UIKit`-[UIView(Internal) _addSubview:positioned:relativeTo:] + 2367
    frame #10: 0x00a9acc8 UIKit`-[UIView(Hierarchy) addSubview:] + 56
    frame #11: 0x00002be9 ExampleApp`ViewController.viewDidAppear(animated=false, self=0x0c72cce0) -> () + 825 at ViewController.swift:40
    frame #12: 0x00002cbf ExampleApp`@objc ViewController.viewDidAppear(Bool) -> () + 63 at ViewController.swift:0
    [...]

Up until frame #11 we’re only seeing code that is necessary to set up the example project. frame #10 is the actual starting point for our investigation. It is called whenever a new subview is added and it eventually results in a call to the _UITintColorVisitor.

What is interesting is that addSubview is only ever called on our root view, but the _UITintColorVisitor is called for all of the subviews of that root view. The cause of this problem must lie somewhere between frame #11 and frame #0.

At this point it was not obvious to me why all views were being caused to be visited; at the very end of the next section I might have a likely answer to that question…

Digging Deeper

Since I hit a dead end in identifying why all subviews in the view hierarchy were constantly being revisited, I decided to investigate another interesting aspect about this problem that profiler had revealed.

Earlier we identified that about 25% of the total time is taken up in calls to [NSArray containsObject:] which is called as part of the implementation of [_UITintColorVisitor visitView:]. I have used Hopper Disassembler to try to understand why that’s the case. A disassembler can translate a binary (in machine code) back into assembly instructions which enables us to explore some of the inner workings of closed source software. This is useful, e.g. to explore issues in Apple’s UIKit framework.

If you have never used Hopper before, but would like to follow along, I would recommend reading this brief introduction.

Hopper has a handy feature that can generate pseudo code from the disassembled binary, which makes it somewhat easier to try and grasp the control flow of a program (if, like me, you’re mostly unfamiliar with assembly code).

By browsing throught the pseudo code generated by Hopper I could identify the section of [_UITintColorVisitor _visitView:] that calls containsObject:

I also stepped through the assembly code that corresponds to this pseudo code in the debugger. As part of that effort I identified a few things that are relevant to this snippet:

  • One _UITintColorVisitor instance is used to visit all views (at least in this simple example with only one view hierarchy)
  • The _UITintColorVisitor has a few properties that are persisted between the different invocations of visitView:. Here’s an overview of all properties found in Hopper:

From stepping through the assembly code and investigating different registries I could identify that in the above pseudo code eax refers to the _originalVisitedView and edi refers to the view that is currently being visited.

This means, that as soon as a _UITintColorVisitor has an original visited view (which is true after it visited its first view), the outlined code checks if the subviews array of the originalVisitedView contains the currently visited view. This check scans the full array of subviews; in cases where the originalVisitedView is our root view, the cost of this operation grows linearly with the amount of added subviews.

I investigated this further by creating another breakpoint in UIKit at the point where this check takes place. When disassembling the 32-Bit slice of UIKit and running the app in 32-Bit mode, the address offsets align nicely. By stepping into the breakpoint in -[_UITintColorVisitor visitView:] I could compare the assembly addresses in the debugger and in Hopper and identify that the addresses match up when replacing the 495 in the hopper address with 0xe4b. The relative addresses within UIKit are constant, only the base address at which the framework is loaded is dynamic:

Once we know the memory address offset we can create breakpoints in lldb based on addresses in Hopper.

Knowing this, I created a new breakpoint based on the loc_4956fd in Hopper like this:

b 0xe4b6fd

Within the breakpoint I printed both the eax register and the _originalVisitedView of self (which is stored in the ebx register):

(lldb) po $eax
<UIView: 0xc131830; frame = (0 0; 768 1024); autoresize = W+H; tintColor = UIDeviceRGBColorSpace 0 0 1 1; layer = <CALayer: 0xc1176d0>>

(lldb) po [$ebx valueForKey:@"_originalVisitedView"]
<UIView: 0xc131830; frame = (0 0; 768 1024); autoresize = W+H; tintColor = UIDeviceRGBColorSpace 0 0 1 1; layer = <CALayer: 0xc1176d0>>

With this approach I identified that with the current sample code, eaxalways refers to the root view. This means we are iterating over all subviews of the root view, N times for each subview that is added.

I’m no expert in complexity analysis but it appears that the total cost of [_UITintColor visitView:] sums up to n^2:

(n invocations of [_UITintColor visitView:]) * (n cost of iterating all subviews) where n = amount of added subviews

But why do we have these two code paths outlined above in the first place? Why do we need to check if the currently visited view is a subview of the original visited view?

In both cases, whether it is a subview or not, we end up calling: ___34-[_UITintColorVisitor _visitView:]_block_invoke. In the case of the currently visited view being a subview of the original visited view, we pass two arguments to the block, in the other case we pass only one.

Before moving on, here’s an annotated version of the method we just investigated:

Now let’s take a look at the block that is being invoked from here. By double-clicking onto the call to the block in Hopper, we can jump into the called block. It looks as following:

We can see that this block receives two arguments. Using the address translation technique from earlier I decided to create the following breakpoint to jump into this block using lldb:

(lldb) b 0xe4b7ee

By investigating the registers I found out that ebx refers to the UIView instance that is being visited and *(esi + 0x14) refers to the tint color visitor. The code seems to switch over the _reasons property of the [_UITintColorVisitor] and over some properties of the visited view.

After stepping through the function prologue we can investigate the relevant values:

po [*(id *)($esi+0x14) valueForKey:@"_reasons"]
1

The _reasons property seems to store a bitmask value. Our bitmask is set to 1. The first if statment in the pseudo code checks if the 1 bit of the bitmask is set. A further condition is that the view’s _interactionTintColor needs to be nil (this check likely explains why setting an explicit tintColor on a view fixes our performance issue). Since both conditions are met, we execute the body of the first if block.

Inside of the if block we finally find a key that might help solve this puzzle:

[ebx _setAncestorDefinesTintColor:eax];

Here UIKit is marking this view, noting that its parent is defining a tint color. I’m assuming that this flag is what registers this view in some way to be visited by the _UITintColorVisitor, since we are passing it as an argument to the _setAncestorDefinesTintColor method.

The big question remains why this is flag is set every single time the view is visited and not only in cases where the subview has moved in the view hierarchy or when the parent view changes its tint color. Another interesting question is why the superview property of the visited view is not used instead of iterating over the array of subviews of the parent view. Both of these mysteries will most likely remain unsolved.

However, our new findings help explain the two code paths in the piece of code that calls into this block (which we examined earlier):

If the currently visited view is not a child view of the original visited view, we don’t pass a second argument to this block; which is equivalent to passing nil. This means that ebx will be nil, which in turn means we will never call [ebx _setAncestorDefinesTintColor:eax];.

Conclusion

When I started out diving into this issue I was almost entirely clueless about how to interpret complex disassembled code - now I’m still mostly clueless. However, I learned a few very handy tricks along the way:

  • I learned how to set breakpoints in private methods & and at any address within the assembly code.
  • I learned about the i386 and Objective-C calling conventions, e.g. which arguments are stored in which registers.
  • I learned that the addresses in Hopper match the addresses in the actual framework code (besides a base pointers offset depending on where UIKit is loaded into memory). In hindsight this sounds obvious but it definitely was not the case when starting out. This article was very helpful in getting more comfortable with working with lldb in UIKit alongside of Hopper.

These three tools allowed me to explore the code paths & relevant variables a lot faster which in turn made it a lot easier (yet still hard) to get a grasp of what was going on.

In the end I didn’t find a definite answer on how this issue could be fixed, but I found a lot of clues about how the current visitor pattern is implemented and I think I got fairly close to the underlying issue.

Most importantly I learned how to be more efficient at exploring the inner workings of closed source frameworks which will surely come in handy in future! Attempting to reverse engineer code can be very intimidating and the learning curve is really steep. I hope some day when I have a better grasp myself I can share a beginner friendly guide on all of this!


Thanks a lot to Russ Bishop who tracked down the original issue together with me. He has also filed a radar: 25934331 (fingers crossed)!

I also recommend the following helpful articles for getting started with reverse engineering closed source Cocoa code:


GCD's Main Queue vs. Main Thread

$
0
0

The correct way to ensure that code runs on the main thread / main queue is a recurring issue that causes some confusion among Cocoa developers. The topic came up again this week as part of an issue with ReactiveCocoa and MapKit:

The Problem

When interacting with certain frameworks, e.g. UIKit, we need to ensure that all calls into the framework happen from the main thread. Typically we have some sort of check to determine whether our code is already executing on the main thread or whether we are on a background thread and actively need to dispatch to the main thread.

Let’s take a function that generates an image as a trivial example:

funccreateImageUnsafe(filename:String)->UIImage?{// TODO: Check for Main ThreadreturnUIImage(contentsOfFile:filename)}

The Easy Solution

The easiest way to check if we are currently executing on the main thread is using NSThread.isMainThread() - GCD lacks a similarly convenient API for checking if we are running on the main queue, so many developers use the NSThread API instead. Our updated function will look somewhat like this:

funccreateImage(filename:String)->UIImage?{varimage:UIImage?ifNSThread.isMainThread(){image=UIImage(contentsOfFile:filename)}else{// /!\ Use dispatch_sync cautiously// it can cause deadlocks!dispatch_sync(dispatch_get_main_queue()){image=UIImage(contentsOfFile:filename)}}returnimage}

This works in most cases, until it doesn’t. Here’s the excerpt from the issue on the ReactiveCocoa repo:

The underlying problem is that the VektorKit API is checking if it is being called on the main queue instead of checking that it is running on the main thread. This issue has also been filed as a radar.

While every app will ever only have one main thread, it is possible for many different queues to execute on this one main thread.

Calling an API from a non-main queue that is executing on the main thread will lead to issues if the library (like VektorKit) relies on checking for execution on the main queue.

It is surprisingly easy to get a non-main queue to execute on the main thread. While doing some research for this post I found a commit to libdispatch that ensures that blocks dispatched with dispatch_sync are always executed on the current thread. This means if you use dispatch_sync to dispatch a block from the main queue to a concurrent background queue, the code executing on the background queue will actually be executed on the main thread. While this might not be entirely intuitive, it makes sense: since the main queue needs to wait until the dispatched block completed, the main thread will be available to process blocks from queues other than the main queue.

The Safer Solution

Technically I think this is a MapKit / VektorKit bug, Apple’s UI frameworks typically guarantee to work correctly when being called from the main thread, no part of the documentation mentions that code needs to be executed on the main queue.

However, now that we know that certain APIs rely not only on running on the main thread, but also on the main queue, it is safer to check for the current queue instead of checking for the current thread.

Checking for the current queue also makes better use of the abstraction that GCD provides over threading. Technically we shouldn’t know/care that the main queue is a special kind of queue that is always bound to the main thread.

Unfortunately GCD doesn’t have a very convenient API for checking for the queue we’re currently running on (which most likely is the reason why many developers use NSThread.isMainThread() in the first place).

We need to use the dispatch_queue_set_specific function in order to associate a key-value pair with the main queue; later we can use dispatch_queue_get_specific to check for the presence of key & value. Here’s the updated image function example:

privateletmainQueueKey=UnsafeMutablePointer<Void>.alloc(1)privateletmainQueueValue=UnsafeMutablePointer<Void>.alloc(1)// Associate a key-value pair with the main queuedispatch_queue_set_specific(dispatch_get_main_queue(),mainQueueKey,mainQueueValue,nil)funccreateImage(filename:String)->UIImage?{varimage:UIImage?=nil// Check for presence of key-value pair on current queueif(dispatch_get_specific(mainQueueKey)==mainQueueValue){// if we found right value for key, execute immediatelyimage=UIImage(contentsOfFile:filename)print("main queue")}else{// otherwise dispatch on main queue now// /!\ Use dispatch_sync cautiously// it can cause deadlocks!dispatch_sync(dispatch_get_main_queue()){image=UIImage(contentsOfFile:filename)print("not main queue")}}returnimage}

Both, key and value are simple Void pointers - we only need to use them for an equality check.

The function above will now not only check that we’re running on the main thread, but also ensure we’re on the main queue.

Conclusion

By combining GCD and Cocoa’s NSThread API we are drilling through the abstraction that CGD should provide in the first place. APIs that fully rely on GCD and ignore the presence of the underlying threads can run into problems if you call them on the main thread but not the main queue. This means, especially when calling into other frameworks, we should prefer using dispatch_queue_set_specific and dispatch_get_specific to check if our code is running on the main queue over using NSThread.isMainThread().

Other Blog Posts:

Writing

$
0
0

I’ve spend a fair amount of my time on different writing projects.

Speaking

$
0
0

I enjoy sharing things I’ve learned and spreading ideas. Here are the talks I’ve given in the past & the upcoming ones I’ve got scheduled.

Upcoming

  • Turning UIKit Inside Out @ AltConf, June 2016
  • Leveraging and Enhancing Swift’s Type System @ 360iDev, August 2016

2016

Turning UIKit Inside Out

2015

Unidirectional Data Flow in Swift

  • Swift Language User Group @Realm, San Francisco
  • December 2015
  • Slides
  • Recording

Safer Swift Code With Value Types II

Safer Swift Code With Value Types

Functional Reactive Programming on iOS

Projects

$
0
0

I’ve worked on quite a few things in the last couple of years…

About

$
0
0

Hey there! My name is Benjamin Encz and I currently live in San Francisco. I moved here from Germany in 2013.

Currently I spend most of my time writing software, with a strong focus on iOS development. I’m working for PlanGrid where we are building software that makes the construction industry more efficient.

In the past I’ve been focused on building enterprise software & teaching software development. I’ve also worked for a year as a project manager and spent a decent amount of time with 2D and 3D graphics programming.

In 2015 I started to give talks at meetups and conferences and I’ve recently blogged more frequently. I’ve also started to work on some open source projects, such as ReSwift.

Besides software I love think and talk about economics, philosophy and politics.

In my free time I enjoy hiking the beatiful Bay Area, travelling and watching soccer.

I love getting touch with new folks, so let me know if there’s anything you want to chat about.

Viewing all 69 articles
Browse latest View live