Tim C
Tim C

Reputation: 58

Subclasssing NSFont

Trying to write some common libraries that work between iOS and OS X. In order to not clutter up the apps by putting tons of #if TARGET_OS_IPHONE in the code I figured I would be able to subclass both UIFont and NSFont using a common .h and just use separate .m files for each build. So I have the following subclass structure MyFont.h and MyFont_iOS.m and MyFont_OSX.m. Each target includes the appropriate .m file. Works fine on iOS but when executing on OSX I get an EXC_BAD_ACCCES creating the font object with a line like

MyFont *myFont = [MyFont fontWithName:@"Arial" size:132.0];

Can I not subclass NSFont?

Here's my basic code sample for the NSFont subclass (note as of this time I have no specialized code in the subclass. This is just a basic subclass)

MyFont.h

#if TARGET_OS_IPHONE
@interface MyFont : UIFont
#else
@interface MyFont : NSFont
#endif
@end

MyFont_iOS.m

#import "MyFont.h"
@implementation MyFont
@end

MyFont_OSX.m

#import "MyFont.h"
@implementation MyFont
@end

Attempted Use of the sub classed font (in iOS App - Works Fine!)

#import "MyFont.h"
...
MyFont *myFont = [MyFont fontWithName:@"Arial" size:45.0];

Attempted Use of the sub classed font (in OS X App - Crashes!)

#import "MyFont.h"
...
MyFont *myFont = [MyFont fontWithName:@"Arial" size:132.0];

FYI - I'm also getting the warning on this line

incompatible pointer types initializing 'MyFont *' with an expression of type 'NSFont *'

So I'm definitely doing something wrong but just don't understand why it's forcing me to use NSFont but works fine on UIFont.

Thanks for any guidance!

Upvotes: 0

Views: 722

Answers (2)

gnasher729
gnasher729

Reputation: 52538

Wrapper is a good way to do this. An alternative: Depending on the target, either

#define MyFont NSFont

or

#define MyFont UIFont

And where both require different code, you can add extensions to the class.

Upvotes: 1

Daij-Djan
Daij-Djan

Reputation: 50089

fontWithName returns a NSFont/UIFont - fixed. IT cant be subclassed

Even if it works, it is not defined behaviour


what you can do is have a wrapper that HOLDS the platform specific font

e.g.

@implementation MyFont {
    PlatformSpecificFont *_font
}
+ (instancetype)fontWithName:... {
    _font = [PlatformSpecificFont fontWithName:...];
    return self;
}

Upvotes: 4

Related Questions