So now that I have started writing OS X application for the mac and there are obviously a lot of similarity with iOS I decided to write some companion app on OS X for my new project TennisStats.
Most of the code is quite abstracted between the UI and the data logic behind, which helped a lot, but I embarked upon sharing my main plotting library inherited from ConnectStats. What will it take to share that library between iOS and OS X?
Compiler Macros
The first thing was to figure out the right macros to predicate the code between the two OS. TARGET_OS_IPHONE
and TARGET_OS_MAC
are define and the one to use here. Though one thing I quickly learned was the really I should use TARGET_OS_IPHONE
as TARGET_OS_MAC
is defined both for OS X and iOS.
The key library can then be imported with #if
. Note that CoreGraphics seems to be the same across both.
#if TARGET_OS_IPHONE #import#import #else #import #import #endif #import
UI and NS prefix
A lot of the classes prefixed by UI
provided by apple on iOS have equivalent named with NS
. Was it going to be as easy as using one for the other?
Brief look at the class reference showed a lot of similarity and iOS was derived from OS X, so why not… So I started to add the following typedefs
#if TARGET_OS_IPHONE #define RZColor UIColor #define RZFont UIFont #define RZImage UIImage #define RZView UIView #define RZBezierPath UIBezierPath #else #define RZColor NSColor #define RZFont NSFont #define RZImage NSImage #define RZView NSView #define RZBezierPath NSBezierPath #endif
And the replace each instance of UIColor
, UIView
, etc with the equivalent version prefixed with RZ
. Most of it compiled! NSBezierPath has the most differences, and I had to write an extension to provide the following functions
extern CGContextRef UIGraphicsGetCurrentContext(); extern NSString * NSStringFromCGPoint(CGPoint point); @interface NSBezierPath (QuartzHelper) +(NSBezierPath*)bezierPathWithBezierPath:(NSBezierPath*)other; + (NSBezierPath *)bezierPathWithCGPath:(CGPathRef)CGPath; -(CGPathRef)CGPath; -(void)addLineToPoint:(CGPoint)point; @end
So now it compiles… Will it just work and is that easy?
Oops… A new issue to worry about, the coordinates in OS X and iOS have their Y axis inverted… Luckily I had quite nicely abstracted the CGPoint
calculation in a Geometry
class… So a key target predicate
-(CGPoint)pointForX:(CGFloat)x andY:(CGFloat)y{ #if TARGET_OS_IPHONE return CGPointMake( ( _graphDataRect.origin.x + (x-_dataXYRect.origin.x)* _horizontalScaling), _graphDataRect.origin.y+_graphDataRect.size.height - (y - _dataXYRect.origin.y) * _verticalScaling); #else return CGPointMake( ( _graphDataRect.origin.x + (x-_dataXYRect.origin.x)* _horizontalScaling), _graphDataRect.origin.y+ (y-_dataXYRect.origin.y) * _verticalScaling); #endif }
And a few more around the title and axis location, et voila!
In Summary
It was much easier than I expected. And definitely makes the thought of building an OS X companion app very realistic…