Skip to content

A Pattern to Declare an Objective-C Mix-in

The missing piece for creating a full fledged mix-in, or multiple inheritance, language out of Objective-C was the addition of associated references. My earlier post on creating a category that uses associated references is an example of the basic framework to do so. All it was missing was a formal way for the compiler to enforce the types of the mix-in. A protocol provides this mechanism. This post will show how to create and use this convention.

Use Cases

There are, at least, two use cases for a mix-in. First, it is an organizational mechanism for building libraries that can be added to any proprietary class. This has been a common use for categories since they were invented and implemented in Obective-C. Unfortunately, it was always restricted to only adding methods and not ivars to a class. Obviously, using associated references addresses this limitation. Second, it can be used to add functionality to existing classes in a precompiled framework, as in my DDGActivity example adding an indicator to a UIView.

Modifications to DDGActivityViewController

The changes are quite simple. You convert your category into an @protocol. I will show two examples. First, I’ll add a mix-in to support TestFlight’s SDK. TestFlight is an excellent service to support a wide area Ad Hoc app testing program. You can learn about their SDK at http://TestFlightApp.com. There are other companies/open source software projects that provide similar services, such as QuicyKit, http://QuincyKit.net, and HockeyKit, http://HockeyKit.net.

The example’s goal is to use TestFlight during Ad Hoc testing and to compile the code out of the app for deployment. There is some question whether Apple allows apps into the App Store with the crash reporting functionality provided by TestFlight. Hence, I wanted a mechanism that made it trivial to remove TestFlight without placing conditional compilation statements throughout my application. I also added an ivar, lastCheckpoint, to contain the last string saved by the -passCheckpoint: method. This ivar is a proper @property. Hence, you can observe the ivar and do things like collect a history of the checkpoints. I’ve implemented simple logging in the view controller this way.

All of the type information is contained in two files. The first file contains a traditional declaration of a protocol. In this case, it is DDGTestFlight.h. It is name spaced because I wrote it. It more appropriately belongs in the TestFlight.h file in the TestFlight SDK. The second file is a simple modification of the category file in the previous version of this project. It is a very simple change. You import the header and then apply the protocol to the category. As in:

@interface DDGActivityViewController (DDGTestFlight) <DDGTestFlight>

As with any protocol, this allows you to precisely control both the type and which methods are required to be implemented. While the category and the protocol do not need to have the exact same name, that seems like it is a good convention to adopt.

Modifications to DDGView

The category on UIView is similarly simple augmented. A protocol file, DDGView.h, is written and it is included and applied to the category. As in:

@interface UIView (DDGView) <DDGView>

I implement the same naming convention as in DDGTestFlight.

Code Encapsulation Improvements Appear in ModalViewController

A very nice side effect of using protocols instead of categories is the information encapsulation now possible. In ModalViewController, we are able to just test for the protocol and not the class of the mixed-in instance. Your code is now more loosely coupled as a result. Traditionally, this means it is more robust against changes in other parts of your program. This is a good thing.

Summary

Moving to a protocol driven technique of adding both associative references and methods improves the encapsulation of your classes while also partitioning type information in a useful fashion. As it is a pretty simple addition to what you need to do to add associative references anyway, I recommend that you do it. As before, you can get the source code up at GitHub, http://bit.ly/DDGActivityGH.

Postscript to our Friends at TestFlight

As you can see from the above, it is pretty straightforward to add an effective form of conditional compilation to your system. I would raise two issues. First, the team token for DDGActivity in my account is hard compiled into the code. I’m OK with this if you are. Second, more importantly, I want to encourage you to embrace this method of adding a TestFlight mix-in. In your case, I recommend that you create and maintain the TestFlight protocol. Furthermore, as Apple is standardizing on the class name AppDelegate in their Xcode 4 templates, it is almost trivial to change my category implementation to apply to AppDelegate instead of DDGActivityViewController. Unlike the rest of your library, I want to encourage you to keep the source code for this category visible to your licensees.

Steve Jobs RIP

Steve Jobs changed my life.

Outside of my immediate family, I think I can only say that about him.

I wanted to contribute to his vision.

I left graduate school to write Mac software — D2 Software’s MacSpin — to contribute to Jobs’ vision.

I followed the siren call of multiprocessor performance and lead a team to create the TokaMac family of Mac accelerators. People could do more on their Macs with my products.

In the height of irony, I joined IBM to lead IBM’s Mac OS licensing technical team. We were successful. Jobs disapproved.

I spent 11 years in IBM Software Group tracking everything Apple did. Apple once suggested that IBM embrace a Cocoa UI in Java. I countered with a vision of a browser based UI. We now call it AJAX. It was the original programming model for the iPhone.

In 2009, I asked to be laid off from IBM. The goodbye severance launched a new embrace of Jobs’ vision; I returned to programming with the iPhone.

I am beyond being a fanboy. People who call me that don’t understand the vision.

I am a contributor.

Thank you Steve for making a place to play and contribute.

DDGActivity: An Example of Using Associated References

Object oriented languages have always allowed a programmer to add both methods and ivars to any class. Apple recommends you should not over-ride some Cocoa/Cocoa Touch classes. Hence, you cannot use inheritance to add ivars and methods to those classes. Of course, Objective-C has always offered the category mechanism as a way to add arbitrary methods to any class. But historically, categories cannot add ivars. Apple has addressed this in the modern Objective-C runtime with a mechanism called associated references. I have tested this code on iOS v4+.

The example app shows you how use an associated reference to add a UIActivityIndicatorView to every UIView, just as if it was any other ivar.

UIView (DDG) category

This category adds an @property and a method, -centerIndicator to a UIView. Here is the header:

#import <UIKit/UIKit.h>

extern NSString *const kActivityIndicatorKey;

@interface UIView (DDG)

@property (nonatomic, retain) UIActivityIndicatorView *activityIndicator;

- (void) centerIndicator;

@end

As we are using an @property, I also add a constant string key to support key-value coding. (I do this to allow the Xcode’s function completion to suggest the right key. This, of course, ensures that you don’t inadvertently add a typo to your key.)

How Do You Use It?

Here I create an activityIndicator and add it to a UIViewController‘s UIView.

self.view.activityIndicator = [[[UIActivityIndicatorView alloc]
                                initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleGray]
                               autorelease];
[self.view addSubview: self.view.activityIndicator];
[self.view centerIndicator];

[self.view.activityIndicator startAnimating];

Here I release the activity indicator:

[self.view.activityIndicator removeFromSuperview];
self.view.activityIndicator = nil;

That is straightforward and is used no differently from any other ivar that contains a UIActivityIndicatorView.

A Pleasant Surprise.

One downside of the category mechanism is that it cannot over-ride any arbitrary method. This is a problem. To preclude a memory leak, all instances need to be released. But you cannot override -dealloc with a category. How do we solve this problem? We don’t have to; the Objective-C runtime handles this for us. This is another example of Objective-C evolving into a modern object oriented language that manages its own memory.

The example application allows you to create a modal view. When you dismiss the modal view, the activityIndicator is automatically released by the runtime and not by a -dealloc method. Please run the example app under Instruments’ memory leak tool. You will see this to be true.

How Does It Work?

The activityIndicator is an @dynamic @property. Hence, we need to implement both the setter and getter. All of this code is in UIView+DDG.h/.m files.

Here is the getter:

- (UIActivityIndicatorView *) activityIndicator {

    return objc_getAssociatedObject(self, kActivityIndicatorARKey);

} // -activityIndicator

Here is the setter:

- (void) setActivityIndicator: (UIActivityIndicatorView *) activityIndicator {

    objc_setAssociatedObject(self,
                             kActivityIndicatorARKey, activityIndicator,
                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);

} // -setActivityIndicator:

As you can see, the runtime provides a simple C-function to implement both accessors. The runtime identifies the associated reference by this C-string key:

static const char *kActivityIndicatorARKey =  "ddgActivityIndicatorARKey";

This string could be anything. I chose to namespace it with a DDG prefix and role suffix, "ARKey". Both of these together insure that this symbol will not collide with an Apple name. (As I prefer readability in my code, I chose NOT to namespace the ivar activityIndicator itself. This namespace collision is a risk I’m willing to take.) As these accessors apply to the instance, self is the appropriate object to pass to the function. Finally, the memory management policy is defined by a family of self descriptive constants: OBJC_ASSOCIATION_ASSIGN, OBJC_ASSOCIATION_RETAIN_NONATOMIC, OBJC_ASSOCIATION_COPY_NONATOMIC, OBJC_ASSOCIATION_RETAIN, OBJC_ASSOCIATION_COPY. In the example, I’ve chosen OBJC_ASSOCIATION_RETAIN_NONATOMIC to match the @property (nonatomic, retain) declaration.

DDGActivity Example Application.

The example application is based upon Apple’s single view application template. For clarity and simplicity, most of the template code has been removed. The root view controller, DDGActivityViewController, has just 3 button action methods: -turnOnAction:, -turnOffAction: and -modalViewAction:. The first two toggle the state of the activity indicator and the third, somewhat obviously, shows the modal view.

The modal view exists to show you automatic memory reaping of associated references by the runtime. It does this by not actively releasing the activityIndicator when the modal view is dismissed. All of the memory is automatically reclaimed. No leaks are created. Please verify this by running the app under Instruments’ memory leak tool. The ModalViewController just has two methods: -viewDidLoad and -dismissAction:. They are simple. -viewDidLoad‘s body was copied from -turnOnAction:. -dismissAction: just dismisses itself.

Licensing

Even though there is little likelihood that you will copy and past this code directly into your app, it is covered by an attribution required BSD license. If you use this technique, please consider giving me credit in your licenses or credits view. I write these posts to help grow my development consulting business and would appreciate your help.

Where to get it?

This code lives up on GitHub at: http://bit.ly/DDGActivityGH. The announcement post to my blog is at: http://bit.ly/DDGActivity.

DDGPreferences: A Class for all Settings

Almost every iOS application has individual user preferences. Some apps also use Apple’s Settings app, some don’t. If you develop many different applications, as I do in my development consulting practice, it is tedious to code up a custom preferences class for each app. My class, DDGPreferences, is an attempt to minimize the tedium by providing a very simple API to the NSUserDefaults class for both settings and custom preferences. In addition to DDGPreferences, I have included a set of standard logging macros, DDGMacros, and an example single view iOS app tying all of the pieces together.

The API

I like simple APIs. They are easy to use and easy to share. I wanted this API to be no more than a list of properties. As in:

@interface Preferences : DDGPreferences

@property (nonatomic, copy)   NSString *nameSetting;
@property (nonatomic, assign, getter=isEnabledSetting) BOOL enabledSetting;
@property (nonatomic, assign) CGFloat sliderSetting;

@property (nonatomic, copy)   NSString *namePref;
@property (nonatomic, assign, getter=isEnabledPref) BOOL enabledPref;
@property (nonatomic, assign) CGFloat sliderPref;
@property (nonatomic, retain) NSData *rectPrefData;

@end

Furthermore, the only difference between whether a property was visible in Apple’s settings app should be if a key matching its exact name was present in the Root.plist in the Settings.bundle. In other words, each setting has an identifier/key which is identical to a property name. This post is not a tutorial on how to build an app that uses Apple’s Settings application. That said the example app has only made minor changes to the fields created when you add a Settings.bundle to your app. (In particular, I changed the Key/Identifier from using under bars, _, as word separators to using standard Cocoa camel case.) In other words, I believe a beginner should be able to follow the logic of using this class without too much difficulty.

How do you use DDGPreferences?

Using DDGPreferences is simple. Make your Preferences class a subclass of DDGPreferences and then instantiate it. Really, that is all you have to do. Your preferences are limited to those supported by Apple’s .plist files. This is not as restrictive as it might seem. Later, I’ll show you how to convert an arbitrary NSCoding compliant class to a preference.

If you have default preference values which are different from the state of a freshly initialized object, then you must implement the DDGPreferences protocol’s single method, -setDefaultPreferences. The example application has this method.

What about synchronizing changes between Apple’s Settings app and yours while the app is in the background? When your app returns to the foreground, I recommend you read/write the Settings managed values in response to the UIApplicationDidBecomeActiveNotification, UIApplicationWillResignActiveNotification notification pair. The example app shows one way to do this. All other coordination with the Settings app is handled by DDGPreferences.

The DDGPreferences app:

I’ve included an app showing how to use DDGPreferences. It is a single view iPhone app with an array of identical controls for both Apple’s Settings app and the DDGPreferences app. You can change the preferences for the settings in both apps and they transfer bi-directionally. A simple CGRect is also initialized and stored. It is then displayed in a UILabel. How to store a complex structure, such as a CGRect, is described below. Traditionally, your preferences are stored with your application singleton. In this example, for pedagogical simplicity, I store them in the root view controller.

Saving complex classes:

This is an advanced technique and, if you can, I recommend that you avoid using it. Any NSCoding compliant class can be stored, with care, in DDGPreferences. As DDGPreferences uses the properties to determine what needs to be persisted, you cannot just define a @property for your class that is not one of those supported by Apple’s .plist format; you need to define an NSData typed instance variable to hold an archived instance of your class/structure. In the example, rectPrefData is that property. To access this data as your preferred type, you need to define “old school” Objective-C v1 style accessors. In the example, these are -rectPref/-setRectPref:. Somewhat obviously, these accessors will use rectPrefData to store the value. A example implementation of these methods is:

- (CGRect) rectPref {

    return [[NSKeyedUnarchiver unarchiveObjectWithData:
             self.rectPrefData] CGRectValue];

} // -rectPref

- (void) setRectPref: (CGRect) rect {

    self.rectPrefData = [NSKeyedArchiver archivedDataWithRootObject:
                         [NSValue valueWithCGRect: rect]];
} // -setRectPref:

They work by taking your NSCoding compliant class and archiving it using the NSKeyedArchiver/NSKeyedUnarchiver classes. The above methods, for pedagogical purposes, are not key-value coding compliant.

Licensing:

DDGPreferences is covered under a public attribution required version of the new BSD license. Why do I require that you acknowledge me publicly in your app? Similarly to many other developers, I make my code available under an open source license as an advertisement for my development consulting services. Hence, I need to be able to easily point to applications that use my code. While it is not necessary, I would appreciate it if you also sent me an email saying in which apps you use DDGPreferences.

From my experience making other code available under an open source license, some folks will write asking to be relieved of my public recognition requirement. Unless the requestor is willing to compensate me to change the licensing terms, I will always decline to change my agreement. I have put some time and care into crafting this class, app and this blog post. That time deserves compensation. I have chosen to be compensated by using this class as a marketing mechanism. I apologize if this does not align with your open source values. I have a family to feed and a mortgage to service. I sell coding services and code to provide for all of us. I hope you understand.

Where to get the code:

This code is available from GitHub at this URL: <https://github.com/adonoho/DDGPreferences>. I will be tracking comments at both GitHub and this post on my personal blog, <http://blog.DDG.com/?p=53>. I, of course, encourage you to send in bug fixes and make suggestions to improve DDGPreferences for all of us.

I hope you find DDGPreferences useful.

In a future post for advanced programmers, I will describe how DDGPreferences functions.

Acknowledgements:

I would like to thank Scott Gustafson and Mason Weems for their suggestions and support. Also, Austin’s local Mac OS X/iOS developer group, Cocoa Coders, organized by Jim Hillhouse and Rajat Datta, has been extremely helpful in my return to software engineering.

Core Data Lessons Learned.

The lessons I’ve learned about using CD are pretty simple.

1) Retain the minimum CD items as necessary to run your app. The CD row cache and fetch requests appear to be quite performant. Rebuilding fetches allows the system to dump memory as needed.

2) -save: is your friend. -save: early and often. Sometimes this will hit your UI’s responsiveness. It’s OK. In particular, you should -save: before starting background operations. Frequent -save:‘s mean that each one is a fast operation.

3) The fetched results controller is “new” code. It has surprising performance “gotchas” and section update bugs. In particular, you should dump it at the first sign of memory pressure. You can recreate it simply. Block oriented fetches are quick.

4) It really helps to go though your program early in a memory warning and dump CD items. Your root view controllers appear to get first crack at dumping memory. If at all possible, do it there. It isn’t clear whether CD gets a chance to dump it’s caches before your -applicationDidReceiveMemoryWarning: gets called. When it did, I then frequently saw a UI-locking loop into the fetched results controller. Also, call -save: in each memory warning routine. If you are observing NSManagedObjectContextDidSaveNotification, it creates a potential dirty loop; KVO observers get fired as the save progresses.

5) The predicate documentation is wholly inadequate. Yes, it is a complete reference. Yet, it is useless as a learning document. The “CD Programming Guide” is much better. The predicate guide needs as thorough a treatment. (Apple is not alone in this lack, one well known book addresses predicates in 3/4 of one page. I feel like such a sucker buying a DB book that doesn’t cover the query language.) For example, I spent a great deal of time banging my head against the fetching limitations of the fetch request. (Of course, if you use a fetched results controller, you have no choice. There is a great need for a block/handler controller.) There are no good examples of the idioms involved with using this predicate language. In particular, when I need to start using text searching, there is little discussion of how the regex engine interacts with the object graph and the row cache.

6) There are surprising interactions between your foreground and background contexts. They can be handled with careful model design and instantiation order. While I don’t think Apple should necessarily document these kinds of problems, some discussion of CD model design guidelines would be helpful. CD is a different way to think about a data model. Apple needs, IMO, to help folks get their heads around the differences.

While you might think that all of my suffering with CD would cause me to walk away from the technology, I’m leaning the other way. As I’ve now crossed a competence threshold, I am seeing good benefits from using an object graph instead of a SQL model. For example, I have a recursive algorithm. Recursive SQL appears to be it’s own special hell. The object graph makes it easy and handles cycles well. While I doubt there is a performance issue, I can pre-fill the row caches with a single fetch request. In addition, my algorithms are well served by object graphs.

The above said, I wish that learning this technology was as straightforward as learning the rest of Cocoa/Cocoa Touch. Apple could do better here.

DNS-SD Configuration “Gotcha”

weLostâ„¢ uses DNS-SD, DNS Service Discovery, to bootstrap the location of its social network servers. While this was a good idea, it had a very subtle “gotcha” in its configuration. The basic configuration instructions are described here in: Static Server Setup. If you do not intend to support browsing for your resources, then things are even simpler but there is still that pesky “gotcha”. To support direct access you only need to implement the third set of DNS records. The one’s labeled: “SRV & TXT records describing each service entity named above”.

If my experience with the iPhone is a guide, the TXT record is not optional. Every service you query MUST have a TXT record. In my case, I neglected to set the TXT record for my narrow web HTTP server. This caused every NSNetService query to timeout. Solving this problem was simple, I entered “txtvers=1″ as the body (minus the quote marks) for the TXT record. This is a default version of the format of all DNS-SD TXT records. There are other values you could use, particularly for HTTP, but this one is both innocuous and sufficient.

Enjoy and Anon,
Andrew

Network Reachability

If you write an iPhone application that uses the network, then you must check if the network is both operating and that your server is reachable. Apple has and will continue to reject applications that do not test reachability. To this end, Apple provides iPhone developers a sample application and class, Reachability, that can easily be used to perform these tests. While the 2.0 version of this code is much better than v1.5, it is still quite raw. (For example, there is a bare [super init]; in a class method [line 175 in Reachability.m]. It does nothing. It also has two routines with misspellings in their names: -startNotifer/-stopNotifer should be -startNotifier/-stopNotifier) To me, these are signs of raw code. To remedy this, I have significantly reengineered this class.

I had three goals when starting this process. First, I wanted to understand how to use this code. It isn’t at all apparent how these routines should be used. What order should they be called in and what do the various tests and values mean? Second, my scan of the code convinced me that it was written by a low level network engineer. They had made implementation decisions that were not terribly friendly to using it in a Cocoa Touch program. I wanted a class that fit in with my coding style. Third, because the core network testing routine -networkStatusForFlags: was not, in my opinion, clear, I did not feel comfortable shipping it in my app, weLostâ„¢. I wanted to have confidence in this code.

This class has two important features: network status transition notifications and easy reachability testing for each server your app touches. Because radios lose connections all of the time, these dynamic notifications help your user understand why they cannot use the networking features of your app.

When I start my app, the first Reachability method I use creates a Reachability instance for the network itself, +(Reachability *) reachabilityForInternetConnection;. This tests the hardware and can immediately provide you with the current network status. Because this reachability test doesn’t leave the phone, there is no network latency. Because hostname reachability instances must resolve your host’s name into an IP address, they are asynchronous. The immediately returned status is that your host is not reachable. (Bear in mind that the subsystem underlying Reachability, SCNetworkReachability, does not actually try to send a packet to your host. It only really knows the state of the radios and whether IP addresses have been allocated for the phone and that your host’s name has resolved into an IP address.)

These Reachability instances do not start notifying you of network transitions upon instantiation. You must turn this on. Before turning on the notifications, I like to register for them. The notification name in the default notification center is: kReachabilityChangedNotification. When your registered method is called, the notification’s object will be the Reachability instance with the changed status. For example, you might register this method:

-(void) networkReachabilityEvent: (NSNotification *) notification;

with the notification center. When it is called for a status change, the Reachability instance is recovered with this line of code:

Reachability *r = [notification object];

A Reachability instance’s notifications are initiated, unsurprisingly, with the -startNotifier method.

Now that you can track gross network transitions, you need to create Reachability instances for each host. In weLost’s case, I track 4 different servers. I use:

+(Reachability *) reachabilityWithHostName: (NSString*) hostName;

to create these instances. These host names must be resolved into addresses before the instance is reachable. (A notification, if you’ve turned them on for this instance, is issued when the resolution is finished.)

This class can be used both synchronously and asynchronously. Typically, you will make synchronous queries of the Reachability instance passed to you after a network status transition. You may also want to do a synchronous test before opening a new view which connects to your host. (One advantage of creating all of your Reachability instances at startup, i.e. before you need them, is that their name resolution does not delay your later network accesses.) My version of Reachability has more methods for synchronously testing network status than Apple’s. Their version also has mixed some tests, such as whether user intervention is required, into the network status method which I think should not be there. I have cracked them out into separate methods. Here are the kinds of network tests you can perform:

  • Test whether this Reachability instance is of interest.
  • If so, then test what kind of network transition it is:
    • Is the host reachable? -(BOOL) isReachable;
      • Is the connection up? -(BOOL) isConnectionRequired;
        • Will it come up automatically? -(BOOL) isConnectionOnDemand;
        • Will the user have to enter a password? -(BOOL) isInterventionRequired;
      • Is the connection slow? -(BOOL) isReachableViaWWAN;
      • Is the connection fast? -(BOOL) isReachableViaWiFi;

How do you determine if a Reachability instance is of interest? You check its key — a hostname or a dotted quad IP address or one of two constants: kInternetConnection or kLocalWiFiConnection. This is a big change from Apple’s code. I keep a key, an NSString, along with the SCNetworkReachabilityRef. Apple just keeps a boolean and the SCNetworkReachabilityRef. In other words, I make it easy to use Reachability instances in complex Cocoa data structures. I’m sure Apple’s engineer would argue that pointer comparisons are sufficient to determine one’s interest in a notification. That doesn’t mean it is a particularly useful mechanism in a Cocoa program. Also, Apple’s boolean is used just to differentiate one instance type, kLocalWiFiConnection, from all of the other types. While this is useful to the internal functioning of Apple’s code, it isn’t particularly useful to a client of the class. I provide a convenience method, -isEqual:, to compare Reachability instances. To a Cocoa Touch programmer, a key is just more flexible.

Your decision tree to interpret network status transitions is, of course, idiosyncratic to your application. However, there are issues to consider based upon your connection. After you have determined whether your host is reachable, is the network active and connected? For example, if you are connected via the EDGE/3G wireless wide area network (WWAN), your network is always reachable but it may not be active. You start the radios by trying to connect to your host. I have seen this process take tens of seconds. Does your user need to know this? If you are connected via WiFi and if a user must enter a password, you may choose not to connect to the network. If you’ve transitioned from WiFi to WWAN, does the user need to know that things are much slower or they may have lower resolution media? And the converse? Do you enable more features when the network transitions to WiFi from WWAN? And what, exactly, do you do when there is a repeated network flap between WiFi and WWAN? What do you do when your app is brought out of sleep in a new venue? What do you tell your user? You will get a notification for each of these situations.

There are two Reachability instances I have neglected — -reachabilityWithAddress: and -reachabilityForLocalWiFi. -reachabilityWithAddress: takes an internet IP/socket address and can be queried immediately for its status. Its key is a dotted quad IP address, such as @"127.0.0.1". The -reachabilityForLocalWiFi instance is a bit more subtle. It tests for a WiFi connection using an automatic private IP address, 169.254.0.0. If this network is reachable, then your network is active but not routable. Some services, such as Bonjour, will still function fine in this case but not much else. I have not found any use for this instance type. Yet I have preserved Apple’s test criteria for this instance in my code. Perhaps it is of use to you.

Before using my extensions you should probably ask: how compatible is this stack with Apple’s? My answer is: very. My code is a superset of Apple’s API. Other than Apple’s misspelled method names, my code will be a drop in replacement for Apple’s class. It has, as far as I’ve been able to test, identical behavior. My network status test is different. It is supported by empirical observations of the status flags. Because it does not conflate a test for whether a user’s intervention is required with the basic reachability, my network status test is simpler. Nonetheless, if you do not wish to use my extensions, I provide a #define DDG_EXTENSIONS to enable easy comparisons between the two network status policies in your application. Both classes employ NSAssert and NSCAssert. This is aligned with the Cocoa policy to throw exceptions during development to catch programmer errors. These exceptions can be turned off by defining NS_BLOCK_ASSERTIONS during your release builds. Finally, I support a conditionally compiled logging system. To turn it on you need to #define CLASS_DEBUG in the class header and #define DEBUG for the debug builds of your app. Then both the -description method and synchronous logging are turned on. My log entries also list the method name and line number of the source code. Class logging is turned on by default.

This class is packaged in a .zip file here: Reachability 2.0.4ddg.zip. It has two directories: Reachability itself and my version of Apple’s Reachability project. These extensions to Apple’s class are covered by the new BSD license. Hence, if you use my version, I require a public acknowledgement of my contributions in your application.

I hope you find this version of Reachability useful. May your code compile without errors and run like the wind.

NOTE: Allen Brunson found a memory leak in Reachability. This has been corrected and a new version generated, 2.0.2ddg, and placed at the link above.

NOTE: Ling Wang suggested an additional test for a WiFi+VPN condition. This has been added and a new version generated, 2.0.3ddg, and placed at the link above.

NOTE: After complaints about my added NSAssert in the -networkStatusForFlags: method, I have now surrounded the assert with a conditional compile macro. This change has been added and a new version generated, 2.0.4ddg, and placed at the link above.

SQLite Persistent Objects

I use Jeff LaMarche’s and his contributor’s SQLite Persistent Objects library in my upcoming iPhone application. This library was created before version 3 of the iPhone OS was released. Because iPhone OS v3 contained Core Data, Jeff and his contributors ceased further development. Yet, I was dependent on it and, hence, I continued private development.

My changes were primarily performance enhancements and some reorganization of the main header files to support better life cycle management of the databases. In particular, I added a static variable to hold a static NSDateFormatter. (An NSDateFormatter is surprisingly expensive to create on each SQLite transaction involving a time stamp.) I also defined a new mechanisms to hold the propertiesWithEncodedTypes as a class static. These properties are static with respect to each class. Hence, caching the dictionary, which is used on almost every call to the class, is an excellent performance enhancement.

To use this new feature to optimize your classes, you need to override +propertiesWithEncodedTypes. Here is the code your need to place in your class:

+ (NSDictionary *) propertiesWithEncodedTypes {

	static NSDictionary *classProperties = nil;

	if (classProperties == nil) {

		// Because it is stored in a static, we must retain it.
		classProperties = [[self propertiesWithEncodedTypes_] retain];

	}

	return classProperties;

} // propertiesWithEncodedTypes

Due to these enhancements this library is not thread safe. Because there are other static variables sprinkled throughout the code, which also preclude thread safety, this is not a change in the library’s lack of thread safety.

The license agreement used by this project was legally dubious. With Mr. LaMarche’s formal agreement via email, as the voice of the project, I have edited each project file to be covered by the OSI approved New BSD license. This license, while supporting the values expressed by Jeff during the creation of the project, adds liability protection to each contributor and formally defines the criteria to use the code. Let me be clear, each contributor was facing an unspecified legal liability under the old license. They are now protected. I contribute my changes to this code under the below license.

I hope you find my changes useful and the license agreement a legal improvement. Here is a link to a zip of the archive, 091023 SQLite Persistent Objects.zip. And a link to Jeff’s extremely useful presentation at the 360 iDev Conference.

Enjoy and Anon,

Andrew


SQLite Persistent Objects for Cocoa and Cocoa Touch.

Copyright (c) 2008 – 2009,
Jeff LaMarche,
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of Jeff LaMarche nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

RHView and Delegate Drawing…

The delegate drawing pattern implemented by a RHView is not a decorator pattern. It is a simple delegate pattern. I intend you, though, to use it somewhat differently than a traditional delegate. A traditional delegate would be responsible for drawing directly in the RHView. And, of course, you can use it that way. I use it differently though.

I create all of my drawing commands as methods of the RHView. This allows complex graphics commands to be encapsulated in the view. The delegate becomes a drawing coordinator and does not a directly draw in the view.

Here is a simple example — a subclass of RHView to draw a graph:

#import "RHView.h"
@class Curve;
@interface GraphView : RHView {
@private Curve *curve; }
@property (retain, nonatomic) Curve *curve;
- (void) drawBorder: (CGRect) rect inContext: (CGContextRef) context; - (void) drawCurve: (CGRect) rect inContext: (CGContextRef) context;
@end

It has a single instance variable — a curve. And it has two drawing methods — -drawBorder:inContext: and -drawCurve:inContext:. The delegate object only needs to implement the RHViewDelegate protocol.

Here is a sample delegate implementation:

- (void) drawView: (GraphView *) view inRect: (CGRect) rect inContext: (CGContextRef) context {
[view drawCurve: rect inContext: context]; [view drawBorder: rect inContext: context];
}

All drawing commands are encapsulated in the subclass of RHView. Your view controller is, in my opinion, the natural delegate of the RHView. You then just create new view controllers to coordinate the new behavior. It is totally congruent with the MVC pattern.

This pattern really cleaned up my code. I hope it cleans yours up too.

An aside: the RHViewDelegate is the key mechanism needed to initiate a decorator drawing pattern.

Coordinate Systems and the iPhone…

Interesting iPhone apps draw custom views/widgets. Every platform though makes assumptions that will be good for some applications and bad for others. As the Mac OS X evolved into iPhone OS, one of the graphics assumptions changed — the handedness of the drawing coordinate system. In Mac OS X’s case, the right handed coordinate system was a natural match to traditional graphing which we all learned in high school algebra. iPhone OS uses a left handed coordinate system. The left handed system is very good for drawing text. The big difference is in the direction of the y-axis. In a right handed system, the y-axis points up; a left handed y-axis points down. If you want to draw scatter plots, then a right handed system is just easier to use.

The graphics system is called Quartz 2D. It supports general purpose transformations of every graphics action. This is how the handedness can switch between the Mac and the iPhone — Quartz 2D made it easy. Hence, to return to a right handed system, we need to use this transformation system to flip the coordinate system. We will also need to move the origin of the view from the top-left to the bottom-left corner. Two tasks: flip the coordinate system and translate the origin.

Each view in Cocoa Touch draws in exactly one method: -drawRect:. Our code needs to intercept this method and transform the coordinate system. Also, because there is a common design pattern in Cocoa Touch, delegation, we should support that too. Finally, because of the ways views are implemented in Cocoa Touch, as CALayers, our class needs to provide some methods to make it easy for layers to be rendered in our new coordinate system.

Two tasks:

  • Flip the coordinate system.
  • Translate the origin.

Three requirements:

  • Intercept -drawRect:
  • Implement a delegate pattern.
  • Provide a utility method for layer drawing.

The Right Hand View Header:

@interface RHView : UIView {
@private
	id <RHViewDelegate> delegate;
}
@property (assign, nonatomic) id <RHViewDelegate> delegate;
// Abstract methods. This must be overridden. - (void) drawRect: (CGRect) rect inContext: (CGContextRef) context;
// Concrete methods. - (CGContextRef) flipContext: (CGContextRef) context; @end

Starting at the top:

This class inherits from UIView, the standard parent class to all views in Cocoa Touch. It’s only instance variable is a pointer to a delegate that implements the RHViewDelegate protocol. As with almost all other delegate instance variables in Cocoa Touch, the delegate is assigned and not retained. It is up to the delegate to keep from being reaped.

This class has two public methods. The first method, -drawRect:inContext:, is an abstract method. It must be overridden by your subclass to draw anything. Or you must use the delegate. You cannot use both at the same time.

The second method, -flipContext:, is a utility method to transform a graphics context between coordinate systems. You should not override this method.

The alternate way to draw is with a delegate that implements the RHViewDelegate protocol.

@protocol RHViewDelegate
@required
// Draw contents into the given view, using the given bounds and context. - (void) drawView: (RHView *) view inRect: (CGRect) rect inContext: (CGContextRef) context;
@end

Because a delegate is unrelated to the view, you need to pass the view to the delegate along with the rectangle that needs to be filled in and the flipped context: -drawView:inRect:inContext:.

How does RHView work?:

I’ll start with simpler of the 2 methods: -flipContext:.

- (CGContextRef) flipContext: (CGContextRef) context {

    // Get the current transformation matrix.
    CGAffineTransform ctm = CGContextGetCTM(context);

    // Toggle the origin's position between the bottom-left and top-left.
    CGAffineTransformTranslate(ctm, 0.0, self.bounds.size.height);

    // Flip the handedness of the coordinate system.
    CGAffineTransformScale(ctm, 1.0, -1.0);

    // Apply the new coordinate system to the CGContext.
    CGContextConcatCTM(context, ctm);

    return context;

} // flipContext:

This method is rather straightforward. It implements our two tasks: flipping and translation. The key thing to recognize is that the new origin is always at the “top” of the current view. In a left handed system, the top-left point is the same as the bottom-left of a right handed system. And this is true, vice versa. The second transform, the CGAffineTransformScale, changes the sign of the y-axis. It changes the handedness of the system. That really is all that is required.

The RHView -drawRect: method has to do both the transformation and delegate dispatch. Unlike a normal UIView, you do not override -drawRect:. Because it is responsible for managing the coordinate system, it has to get the first crack at drawing the view. Hence, you need to override the -drawRect:inContext: method. The only difference between the two methods is that you will use the provided context instead of the default context. Other than that, everything about the new method is treated identically to the classical -drawRect: method. (A note: -drawRect:inContext: is using the same naming pattern as CALayer‘s delegate method -drawLayer:inContext:.)

- (void) drawRect: (CGRect) rect {

    // Convert the coordinate system to be what Quartz 2D expects.
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGAffineTransform ctm = CGContextGetCTM(context);

    // Translate the origin to the bottom left.
    CGAffineTransformTranslate(ctm, 0.0, self.bounds.size.height);

    // Flip the handedness of the coordinate system back to right handed.
    CGAffineTransformScale(ctm, 1.0, -1.0);

    // Convert the update rectangle to the new coordiante system.
    CGRect xformRect = CGRectApplyAffineTransform(rect, ctm);

    // Apply the new coordinate system to the CGContext.
    CGContextConcatCTM(context, ctm);

    if (delegate != nil) {
        // The delegate gets the first crack at rendering the view.
        [delegate drawView: self inRect: xformRect inContext: context];
    } else {
        [self drawRect: xformRect inContext: context];
    }
} // drawRect:

-drawRect: has to do four tasks: 1) get the current graphics context; 2) translate and flip the coordinate system; 3) transform the drawing rectangle; 4) dispatch to either the delegate or subclass.

Getting the Code:

I’ve released this code into the public domain.
It is available here: RHView.zip.

Enjoy!