Search
Rich's Mad Rants
Powered by Squarespace

Entries in Objective-C (7)

Saturday
Nov022013

Objective-C Chapter Available Online

I've got good news, bad news and good news again.

Let's start with the good news. Creating iOS Apps: Develop and Design, Second Edition is done! The final layout wrapped up last week, and the files are on their way to the printer.

The book has been completely rewritten for iOS 7. It focuses on modern, best practices like Storyboards, ARC and Auto Layout. It was also designed with iOS 7's new UI paradigm in mind--creating clean, content-focused interfaces that emphasize animation over ornamentation. This includes a detailed exploration of many of iOS 7's new features, like custom transitions, interactive transitions, UIMotionEffects and UIKit dynamics.

The book should be released on November 25th. I'll post links as soon as it shows up on Amazon, iTunes and other online stores.

Now for the bad news. I wrote too much. We couldn't possibly fit everythign in the book. That means a few sections had to be cut, including the entire Objetive-C Chapter.

The good news is that I will make all of these sections available here for free, starting with the Objective-C Chapter.

The Objective-C Bonus Chapter is 91 pages long. It covers everything from the language's fundamental building blocks to the design patterns used in Cocoa and Cocoa Touch. It also includes all the new additions to Objective-C, like instancetype, literal syntax and subscript notation, and 64-bit support.

The file is available in both print and screen resolutions. You can download them here:

Wednesday
Oct102012

FMSSwizzler library added to GitHub

Hey all.

At the risk of repeating myself, I'll be speaking at the MacTech Conference next week in L.A. I'm actually doing two different presentations. One is on iCloud Document Syncing, the other on Metaprogramming in iOS. In my head, I'm king of thinking them as the "useful" talk and the "fun" talk.

As part of my prep, I've been putting together some examples. Here is another library of useful methods for Objective-C metaprogramming. Specifically, I have methods to simplify method- and class-swizzling. Also, unlike traditional Objective-C metaprogramming--I'm using the block-based API for dynamically adding methods to classes.

I've tried to address all the obvious gotchas (class clusters, KVO, nested dymanic subclasses, etc.), but--obviously--mucking around with classes at runtime will always be a bit dangerous. There are probably a few edge cases that I haven't though of. Take a look at the included documentation and the unit tests, if you have any questions. Most importantly, if you use the code in your own projects (not just when doing exploration coding or debugging), be sure to use it judiciously and test it ferociously.

You can find the repository at https://github.com/rikiwarren/FMSSwizzler. And, you can get more informaiton about MacTech Conf here.

Tuesday
Sep182012

Advanced Profiling with the DTPerformanceSession Framework

I spent part of the weekend playing with Instruments and the DTPerformanceSession framework. This framework offers a number of really cool features for fine-tuning performance testing on both iOS and OS X applications. Unfortunately, there's not a lot of documentation out there. In fact, the only thing I could find is the "New Features in Instruments 4.0" user guide.

DTPerformanceSession offers a rich set of features for gathering and recording information from a restricted set of instruments (currently limited to Time Profiler, Allocations, leaks and the Activity Monitor). We can then save the data as a .dtps bundle, which can be opened by instruments. While this opens up possibilities of creating customized test harnesses--it's honestly too much work for most situations. Fortunately, there's an easier option.

DTPerformanceSession also lets us add custom flags to our app during our regular performance testing. We can then access these flags from within instruments, using them to focus in on a very specific portion of our code.

To add signal flags, first we need to add the DTPerformanceSession.framework to our application. We then need to import the DTSignalFlag header file, as shown below:

#import <DTPerformanceSession/DTSignalFlag.h>

Note: for OS X, I also needed to manually set the Runtime Search Path. I'm not sure why this wasn't set automatically--it may be because I was using a version of Xcode installed in a non-standard location. If you run into strange errors, simply copy the Framework Search Path location over to the Runtime Search Path in the target's Build Settings.

We can then add signal flags to our app by calling DTSendSignalFlag(). This method takes three arguments. Honestly, I'm not 100% sure what these arguments do. There's no real documentation--not even in the header file. However, based on the header file and Apple's sample code,  The first appears to be a user id string. This string shows up in Instrument's flag table, and can be used to identify particular signals. Apple's sample code uses a unique C string, beginning with the developer's reverse domain name notation.

The second argument defines the type of signal. Here, we can use DT_POINT_SIGNAL to flag a single location in time. Alternatively, we can use DT_START_SIGNAL and DT_END_SIGNAL to mark off a block of code.

The third argument determines whether or not it adds a backtrace. All of Apple's samples simply passed in YES, so I did the same. 

So, to mark off a section of code, I simply added the following code to my project:

DTSendSignalFlag("com.freelancemadscience.MyProject.importantBlockStart", DT_START_SIGNAL, TRUE);

// The code we're testing goes here...

DTSendSignalFlag("com.freelancemadscience.MyProject.importantBlockEnd", DT_END_SIGNAL, TRUE);

Now, whenever I run instruments, these flags will be added to my project. Unfortunately, they do not show up by default. Instead, we must open the flag table, by selecting Window > Manage Flags….

Opening Flag Table

This will bring up a list of all the flags in this profiling run. The table shows the flag's name (the user id string we used), a timestamp, and for the start/end flags, it will list a duration. We can also expand the start/end flags, if we wish. 

To display the flags in Instrument's timeline, click on the Displayed Flags button, and select Symbol Flags

Turning On Signal Flags

Even more importantly, we can set Instrument's range filter to the start and end flags by selecting the start flag in the table, then clicking on the cock icon at the bottom of the table.

Time Range

This will highlight the range between the selected start flag and its corresponding end flag, limiting the profiling information to the method calls and allocations that actually occurred within this range. For example, below, I am viewing the Time Profiler data for the code between the selected start and end flags. During this range, my app spent 92% of its time in the test2() method.

As you can see, this gives us a lot of fine control over exactly what we're looking at, letting us focus in on a known problem areas.

Filtered Time Profile

 

 

Friday
Aug312012

To Declare or Not To Declare

Between teaching an intro to iOS class last week, and Colin Wheeler's blog post "Cover up those ivars", I've been thinking a lot about what we declare in Objective-C, and where we should declare them.

Background

Back in the day--and by that I mean just over the last few years--we had to explicitly declare almost everything. For example, we had to declare our iVars in the header file. The compiler needed to know how much memory our class used when it went to make a subclass.

Now, I don't know about you, but I like to keep my header files as clean as possible. Ideally, they should only contain the properties and methods that outside classes are allowed to call. Everything else should be hidden away. Unfortunately, having the iVars in the header file exposed some of my class's implementation details. Worse yet, if developers could see them, they were likely to try and use them. This made it harder to modify my implementations without also breaking their code.

Over time, however, things changed. If we're using a modern OS (iOS, or a 64-bit version of OS X), we don't need to have our iVars in the header file anymore. We don't even need to explicitly declare them. Xcode can auto-generate appropriate iVars from our property declarations.

Even better, with Xcode 4.4, we no longer need to explicitly call @synthesize for our properties. Again, Xcode will handle it (if necessary). The rules on when Xcode auto generates iVars gets a little more complicated--but generally it does the right thing. If it's not synthesizing methods (for example, because I provided custom getters and setters), it won't generate the iVar.

Class extensions also help us move things out of our header files. We can declare private properties, iVars and methods there. Of course, Objective-C doesn't really offer support for private methods, so developers just make methods private by hiding them. If it's not declared in the header file, it should be considered private.

Now, nothing will stop you from calling the method, if you somehow discover its name--but given Objective-C's dynamic and reflexive nature, there's no way anyone could really stop you anyway. Instead, the public/private divide is really about clearly expressing developer intent. If it's not in the header file, you shouldn't use it, period.

Additionally, like C, we don't actually need to declare our methods. We could simply create a "private" method by just defining them in the @implementation block. As long as our methods are defined before they are called, everything works. Unfortunately, this isn't always possible (e.g. mutually recursive methods).

However, with Xcode 4.4, Apple added considerable support for undeclared private methods. Specifically, the compiler is now smart enough to find the method regardless of its position in the implementation file. So, we no longer need to worry about ordering.

What I Declare

Or, more appropriately, what do I leave undeclared.

I never declare iVars directly. Instead, I will create public or private properties and let them generate the iVars for me. If I need to let a subclass access a private property, I can always re-declare it in the subclass and then use the @dynamic property directive in my @implementation block.

Of course, I get a little worried when I do this. It seems like code smell--an indication that something might be wrong with my design. Why does my subclass need access to that property? Should the property actually be a public property? Should I redesign my class hierarchy? Is there maybe a better way to solve this problem (e.g. using aggregation instead of inheritance)? Most of the time, I find that redeclaring the property is not the correct solution--still, it's nice to know that it's there.

I'm actually a little bit surprised by how many developers continue to manually declare their iVars. In many cases, it looks like they're doing it out of habit…like they're afraid to trust their compiler.

Oddly enough, explicitly declaring iVars can actually introduce bugs. If the iVar and property names don't match up correctly, Xcode will happily create a second iVar for you. The property will connect to the auto-generated iVar, not the one you explicitly declared. While the additional memory usage is unlikely to cause any serious problems, it's at least somewhat sloppy. Besides, worse things happen if you start accessing the iVar directly. Then the code that accesses the iVar and the code that uses the property might end up modifying two different variables. These bugs can be very confusing and hard to find.

I've also stopped using @synthesize. It was always somewhat tedious--especially since I always gave my iVars names that began with an underscore. Now, Xcode does that by default, so it saves me a bit of typing.

Oddly, I still declare private methods in my class extension. This used to be rational. I didn't have to worry about how I ordered my method definitions--which gave me more freedom when it came to organizing my code. Also, Xcode seemed to respond better to explicitly declared methods. Code completion seemed to work better, and I seemed to get better warnings and errors.

However, with Xcode 4.4 none of that seems to matter anymore. I ran a few tests, and Xcode seems to handle undeclared and declared private methods equally well. So, I'm starting to rethink this. I still like the explicit declarations, but I'm worried that I may be clinging to them out of inertia.

Where I Declare it

Basically, whenever possible I try to keep things out of the header file. If other classes need access to it, I put it in the header. If not, I hide it away. If in doubt, I err on the side of hiding things. I can always expose them later.

For properties, it gets a little more complex. For example, many times outside classes may need to read data from my class, but won't actually need to change it. In that case, I typically create a readonly property in the header file, and a readwrite property in the class extension. Inside my class, I can read and write to the property as normal--but other classes can only read the data.

Note, the only attribute you can change when redeclaring properties is the readwrite/readonly attribute. This means we need to include a storage attribute (strong, weak, copy, assign) in our readonly property declarations. Yes, that leaks implementation details--but its not worth losing sleep over.

However, I get a bit extreme when it comes to pulling things from my header files. When I'm using a view controller combined with a storyboard/nib, I will also hide my IBOutlets and IBActions in my class extension.

Now, this gets a bit odd, conceptually. Technically, yes. These are elements that--by definition--need to be accessed outside my class. However, in general, they should only be accessed by the system as it loads the nib (remember, storyboards compile down into nib files). And the system can find it just as easily in my class extension. No one else needs to know about it.

Our view controllers manage one or more views to display data and to respond to user interactions. We shouldn't be concerned with how the view controller handles those tasks. Instead, we should just pass it our data, and let it display the data however it wishes.

Or, think about it this way, if I put outlets in the header file, developers (including my future self, when I'm tired or up against a tight deadline) will be tempted to access and modify the outlets directly. This is almost always a mistake. Again, we can pass the data to the controller or call its public methods--but we should let the controller decide when and how it will display the information.

So, what do you declare, and where do you declare it? More importantly, why?

Thursday
Jun212012

Declaring Outlets in Class Extensions

Did you know that you can declare IBOutlets in a class extension? I didn't. Man, I love it when I discover something new.

OK, we all know that we can add an outlet property to our header file as shown below. Then we can draw connections to this outlet in Interface Builder.

@interface MainViewController : UIViewController

@property (weak, nonatomic) IBOutlet UIButton *playButton;

@end

I always assumed the property had to be publicly declared. After all, it's value is set externally when the nib loads. Unfortunately, except for this initial linking, these properties are really an implementation detail. In general, I don't want external code to start mucking about with my outlets.

And, let's face it, it's far too easy to fall into this trap. After all, I have a label. Why shouldn't I just set the label's text. It's quick, it's simple and it works.

controller.titleLabel.text = @"This is my new title";

There are a couple of problems with this. First, if the view has not loaded, then our label won't exist. We will simply be sending the sendText: message to nil--which does nothing. From a more theoretical standpoint, we're also letting external code muck about in what really should be an internal implementation matter. This creates code that is tightly bound and hard to modify or maintain.

A more modular implementation might have a title property. External code might change that property, but our view controller is responsible for determining how the title is displayed.

So, back to the topic at hand. Class extensions allow us to declare methods and define variables that will be added to our class. Typically they are placed in the .m file, above the @implementation block. They are most often used to declare private methods and variables.

Of corse, this comes with the standard Objective-C caveat. Nothing in Objective-C is truly ever private. We can always send any message to any object. However, by removing methods and properties from the header file, we are telling other developers (including our future selves) that those methods and properties are implementation details that could change at any time. They should not be called outside the class itself.

The cool bit is that we can also declare our outlets in our class extension, hiding them away and making them private. However, interface builder can still see them, and we can still draw connections to them. The system will still set them up when the nib loads. It's the best of both worlds.

// the class extension
@implementation MainViewController()

@property (weak, nonatomic) IBOutlet UIButton *playButton;

@end

// the class implementation
@interface MainViewController
@synthesize playButton = _playButton;

// boring details skipped

@end

I'm not sure exactly when Apple added this feature. However, it works in Xcode 4.3.3, and probably in earlier versions as well. I've already converted on of the projects I'm working on--and I really appreciate the cleaner header files.

Ok, back to work….