Swift is just fucking great.
Author: mmuszynski
Swift
I’ve been writing a lot of Swift recently and really liking it (but sometimes really hating it). The strong-type nature can lead to some really unhelpful situations when coming at things from the perspective of weakly-typed languages like Objective-C.
Often times, I find myself looking at something in Swift and wondering, “What class is this object?” which is something with an easy answer in Objective-C:
[someObject class]
But in Swift, a different question becomes a lot more important: “Is this a certain type of class?”
let anObject = someObject as? SomeClass
Note that this assignment creates anObject, a variable of type SomeClass?, which is an Optional – specifically, a type of object that can potentially be nil. Swift is specific about non-optional types returning a value always, so Optionals must be used in situations where a nil value might be returned:
override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath?
Notice that Apple expects this function to return an Optional NSIndexPath. According to Apple, this function “Tells the delegate that the specified row is now selected.” What happens if we want to do something, but not select the row? Simply return nil.
Since optional assignment can return nil, the assignment itself can be used as the argument of an if statement (something that I remember being excited about when learning PHP in high school). But this leads to a really easy use that I came up with today when implementing a custom isEqual method on a class I have been writing. It’s completely obvious if you are looking at things from the Swift perspective, but something that really just clicked for me today.
Here’s a way I might check for equality of a custom object in Objective-C:
-(BOOL) isEqual:(id)object {
if ( ![object isKindOfClass:[self class]] ) {
//test important, identifying features
if( object.property1 == self.property1 &&
object.property2 == self.property2 … etc) {
return YES;
}
}
return NO;
}
override func isEqual(object: AnyObject) {
if let someObject = object as? SomeClass {
//test important, identifying features here
if someObject.property1 == someObject.property2 etc {
return true
}
}
return false
}
Suddenly, it starts to make so much sense. I’m starting to see things that I have done for years in Objective-C work idiomatically the Swift way. A lot of it is super cool and really exciting to delve into as I get more comfortable with it.
Undefined symbols for architecture
I ran across my favorite error again today. Often times these are really difficult to understand if you don’t know what they are referring to. Here’s the one that I got:
Undefined symbols for architecture x86_64:
“_CATransform3DMakeRotation”, referenced from:
-[SOFViewController updateScaleName] in SOFViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Turns out this is super easy. In this case, the symbol is undefined because the QuartzCore library isn’t included, despite the inclusion of #include <QuartzCore/QuartzCore.h>.
The binary needs to be linked with the library, conveniently in the “link binary with libraries” section under build phases in Xcode.
Shortcuts
Hey, shortcuts are nice, but what about this Objective-C monstrosity:
NSMutableArray *returnArray = [@[] mutableCopy];
Guh. I kind of wrote this because I could, but I think this is much better:
NSMutableArray *returnArray = [NSMutableArray new];
While we’re at it, since this is for a function that is going to return an immutable NSArray, why not go for a name that reflects what is actually going on?
NSMutableArray *mutableReturnArray = [NSMutableArray new];
Finally, when it’s time:
return [mutableReturnArray copy];
A word of warning, this last step seems to be unnecessary for the running of an app, but I’m told that this doesn’t make much sense, since the debugger will still see this as a mutable array. It might seem pedantic, but it’s apparently correct. Has this ever bitten you?
Personal Milestone
I’ve been using git for about a year now. Today, I refactored some code and hit a personal milestone:
9 files changed, 153 insertions(+), 162 deletions(-)
First time that a refactor has removed more code than it’s inserted. I feel pretty good about that, but it was pretty easy, seeing as there was a bunch of redundant, encapsulated stuff that had no business spanning multiple methods.
Still, here’s to brevity.
Linker Command Failed
Linker Command turns one year old today, and I’m in my last days at the place that I started it for the Summer, so I wanted to share the error behind the name.
Last summer, I was getting really angry at seeing this error come up over and over again. If you’re new to C like I am, and you something that starts like this:
Ld /Volumes/Storage/Users/mike/Library/Developer/Xcode/DerivedData/PedalCharts-gvryltpjsvqnwraultwngecnzbsd/Build/Products/Debug-iphonesimulator/PedalCharts.app/PedalCharts normal x86_64
cd /Volumes/Storage/Users/mike/Documents/Cocoa/Bitbucket/PedalCharts
export IPHONEOS_DEPLOYMENT_TARGET=7.0
export PATH=“/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin”
ETC ETC ETC
You are going to look at this and say, I have no idea what to do with this garbage. The important stuff is in the second half (and Xcode is much more forthcoming with this than it used to be):
duplicate symbol _OBJC_METACLASS_$_PedalChart in:
/Volumes/Storage/Users/mike/Library/Developer/Xcode/DerivedData/PedalCharts-gvryltpjsvqnwraultwngecnzbsd/Build/Intermediates/PedalCharts.build/Debug-iphonesimulator/PedalCharts.build/Objects-normal/x86_64/PCStaffView.o
/Volumes/Storage/Users/mike/Library/Developer/Xcode/DerivedData/PedalCharts-gvryltpjsvqnwraultwngecnzbsd/Build/Intermediates/PedalCharts.build/Debug-iphonesimulator/PedalCharts.build/Objects-normal/x86_64/PedalChart-45484887584B8F82.o
duplicate symbol _OBJC_CLASS_$_PedalChart in:
/Volumes/Storage/Users/mike/Library/Developer/Xcode/DerivedData/PedalCharts-gvryltpjsvqnwraultwngecnzbsd/Build/Intermediates/PedalCharts.build/Debug-iphonesimulator/PedalCharts.build/Objects-normal/x86_64/PCStaffView.o
/Volumes/Storage/Users/mike/Library/Developer/Xcode/DerivedData/PedalCharts-gvryltpjsvqnwraultwngecnzbsd/Build/Intermediates/PedalCharts.build/Debug-iphonesimulator/PedalCharts.build/Objects-normal/x86_64/PedalChart-45484887584B8F82.o
ld: 2 duplicate symbols for architecture x86_64
Along with, finally, the familiar:
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The important part here is the duplicate symbols. The linker is part of the C architecture that links the functions and variables you write with the places they are used in your code. In this case, the linker is complaining that the class PedalChart has been defined in two places. Today, it’s because I used this typo in my PCStaffView Class:
#import “PedalChart.m”
So, this is a big problem, because, instead of importing the header with the declaration of the class, I’ve tried to import the implementation file. The linker doesn’t like this and will throw the error on build time. This is the most likely cause of the error for me, and it’s due to a typo that can be autocompleted.
Personally, I don’t know why you’d want to link an implementation file, but much of this is way over my head anyway.
Buckets and Hashes
I thought it might be interesting to share the differences between the isEqual methods used by NSDictionary and my new class to shed some more light on the situation.
Here’s the way I set up Skill Plan items prior to writing the custom class:
[[NSDictionary dictionaryWithObjectsAndKeys: [EVESkill skillWithID:@2345], @“skill”, [NSNumber numberWithInteger:1], @“level”, nil];
Here’s the way that I set them up now:
[EVESkillPlanItem skillPlanItemWithSkill: [EVESkill skillWithID:@2345] atLevel:1];
Now, I can’t speak specifically to the code that Apple uses to write NSDictionary’s isEqual method, but here are the things that are called when I profiled with that first method:
-[NSDictionary isEqual:]
-[NSDictionary isEqualToDictionary:]
-[NSDictionary countForKey:]
-[NSDictionary objectForKey:]
-[__NSDictionaryl objectForKey:]
-[EVESkill isEqual:]
-[__NSCFNumber isEqual:]
-[__NSCFNumber isEqualToNumber:]
…
And on and on and on! All of this to find whether the dictionary I’m looking for is contained in the set. It would be much easier if there were some quicker way of doing this, and there is.
The reason that the object method is so much faster is that it sets up not only a custom isEqual method, but a hash function that speeds up the lookups. If you haven’t looked into hashing and buckets, Apple has a good video from WWDC 13 called “Designing Code for Performance” which discusses hash-based organization, about halfway through the video (note that you will need a developer account to watch the video):
Long story short, things are arranged in buckets based on the value of the hash function. If there are multiple objects with the same hash, then the hash is not sufficient to check for equality in the set or array. What does NSDictionary return for hash? I wrote a small piece of code that outputs the hash function for a dictionary of random elements with random keys. And it turns out that in this case the hash is equal to the number of objects in the table. No wonder it is so spectacularly slow for my case. Every dictionary must be compared.
So here’s a better hash function for my class:
-(NSUInteger)hash {
return _skill.hash ^ _level;
}
Easy. And it produces a hash function that is much closer to uniqueness than the dictionary method which was exactly the opposite of unique. I don’t know if it is truly unique, but it certainly collides less than “every time.” For clarity, _skill.hash basically just returns the internal Skill ID number from the EVE Database, which is guaranteed to be unique. The bitwise or with the level number makes it such that the same skill of a different level does not produce the same hash.
So there you have it. When we need to know if the EVESkillPlanItem is in the Skill Plan NSOrderedSet, we have an O(1) lookup instead of an O(n). Pretty nifty, eh?
Speed and Profiling
I’m embarking on the most difficult project I’ve written so far, and I have been making extensive use of Instruments, especially the Time Profiler. If you’re like me, you opened up Instruments after downloading Xcode for the first time because it looked cool. Then you shut the computer and cried for a while. But recently, I’ve been noticing that my application tends to be sluggish during some dragging operations, and I wanted to figure out precisely why.
First, let’s talk a little about the project and why it slows down where it does. I’ve been playing a game called EVE Online. One of the core mechanics of this MMO is that your character trains skills 24 hours a day, whether you are online or not. But skills can only be queued if they will start within 24 hours. And certain skills can’t even be trained until other skills have been reached. As a result, people really want help in planning longer skill queues. There’s a really good program for this called EVEMon… which runs only on the PC.
Enter fledgling developer. EVE Online has not been available on the mac for very long, so the options for us are quite slim. I’m hoping to come up with something that works well and eliminates the need for Wine (which doesn’t run EVEMon well) or Bootcamp (which is annoying).
So, I’ve downloaded all of the skill information, set it up in arrays and dictionaries, etc etc. Next I created a class called EVESkillPlan, which works with my EVESkill items. These are my Models (although I’ve integrated some Controller functionality in the EVESkillPlan, which is supposed to be a big no-no – more on this in another post).
Here’s where the Instruments comes into play.
I’ve set up a drag and drop interface. New skills are dragged from the source list on the left to the right:

Dragging into an NSTableView gives you two opportunities to validate the operation, once to give feedback to the user as to whether or not the drop will succeed (tableView:validateDrop:proposedRow:proposedDropOperation) and once to actually tell the data object to follow through with the data manipulation (tableView:acceptDrop:row:dropOperation:). The problem in my app is that the validation operation takes too long, and performance begins to suffer as the drag operation continues.
So what’s causing the slowdown? This is where Instruments is helpful.

It turns out there is an extensive test of the validation method when the application loads character files from dis (or when they are downloaded from the EVE API), as the program attempts to make an EVESkillPlan instance from the skills that the character has already trained. This is probably a really bad way of doing things, as the skills that the character has already trained can be assumed to be valid, because the game won’t allow them to be trained out of order, so the validity test is unnecessary. But if it works well now, I don’t care. In any case, at this point, testing the loading time for the characters can show us where the slowdowns happen. Here’s an example trace as the application ran last week:



4.24s doesn’t seem like a lot of time, but it represents the slowest part of the drag operation. Can we speed it up?
You can use the Time Profiler to determine what is taking the longest amount of time in the app. Previous to today’s improvements, the code stored data in an NSDictionary that contained the EVESkill instance and an NSInteger for the level (skills range from Level 1 to Level 5, and must be trained in order of increasing level). If you look closely at the trace, you’ll find that the lookups for these NSDictionaries takes a considerable amount of time, owing to the fact that the NSDictionary equality test has a number of steps. What if we created a class that uses a faster isEqual: method?
EVESkillPlanItem is a simple class that does just that. It has two properties, an EVESkill instance and a NSInteger for the level of the skill. Equality requires that the EVESkill object and the level number are equal. This cuts out at least one step from each equality statement, since the NSDictionary first makes sure that the two dictionaries have the same number of items. Who needs that when you’re sure that they will? In any case, here’s the trace for the updated code:


Voila, 1.58s. Huge, huge improvement. Notice that the isEqual: method for EVESkillPlanItem is almost three times faster than the corresponding method for NSDictionary.
And I find that dragging is much speedier as well, so the main goal is fixed for the time being. It’s possible there may be more improvements to be made, but I can live with the performance for now. Interesting how much things got better. Time Profiler is your friend!