I'm trying to subclass UIColor, and I can't seem to figure out what's wrong.
In my PColor.h
#import <Foundation/Foundation.h>
@interface PColor : UIColor {
BOOL isAvailable;
int colorId;
}
@property (nonatomic, assign) BOOL isAvailable;
@property (nonatomic, assign) int colorId;
@end
...and in my PColor.m
#import "PColor.h"
@implementation PColor
@synthesize isAvailable;
@synthesize colorId;
@end
Upon instantiating a PColor object, I get:
//warning: incompatible Objective-C types initializing 'struct UIColor *', expected 'struct PColor *'
PColor *pcolor = [[PColor alloc] initWithHue:1 saturation:0 brightness:0 alpha:1];
Am I missing something? Thanks in advance.
UIColor
is a class cluster use associative references in a category to add properties! All of the custom init methods on UIColor
return a UIColor*
not an id
so you can not easily subclass UIColor
nor should you try.
UIColor+PCOLOR.h
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
@interface UIColor(PCOLOR)
//Properties prefixed to try and avoid future conflicts
@property (nonatomic, assign) BOOL pIsAvailable;
@property (nonatomic, assign) int pColorId;
@end
UIColor+PCOLOR.h
#import "UIColor+PCOLOR.h"
@implementation UIColor(PCOLOR)
static char PCOLOR_ISAVAILABLE_KEY;
static char PCOLOR_COLORID_KEY;
@dynamic pIsAvailable, pColorId;
-(void)setPIsAvailable:(BOOL)pIsAvailable
{
objc_setAssociatedObject(self, &PCOLOR_ISAVAILABLE_KEY, [NSNumber numberWithBool:pIsAvailable], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(BOOL)pIsAvailable
{
return [(NSNumber*)objc_getAssociatedObject(self, &PCOLOR_ISAVAILABLE_KEY) boolValue];
}
-(void)setPColorId:(int)pColorId
{
objc_setAssociatedObject(self, &PCOLOR_COLORID_KEY, [NSNumber numberWithInt:pColorId], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(int)pColorId
{
return [(NSNumber*)objc_getAssociatedObject(self, &PCOLOR_COLORID_KEY) intValue];
}
@end
USAGE
UIColor *pcolor = [[UIColor alloc] initWithHue:1 saturation:0 brightness:0 alpha:1];
pcolor.pColorId = 2352;
pcolor.pIsAvailable = YES;
NSLog(@"\nClass: %@\nColor ID: %d\nIs Availabled: %@",
NSStringFromClass([pcolor class]),
pcolor.pColorId,
pcolor.pIsAvailable ? @"YES" : @"NO");
[pcolor release];
From UIColor Class Reference:
Most developers should have no need to subclass UIColor. The only time doing so might be necessary is if you require support for additional colorspaces or color models.
You should use Category. For example:
@interface UIColor (PColor)
- (BOOL) isAvailable;
- (int) colorId;
@end
In the implementation file:
@implementation UIColor (PColor)
- (BOOL)isAvailable {
// do what you want to do
// return your BOOL
}
- (int)colorId {
// do what you want to do
// return id of color
}
@end
Because UIColor alloc might not do what you expect it to do: allocating an instance of UIColor. It may be kind of a factory method, which looks first what colors have already been used or belong to a standard set of colors and give it back instead of creating a new instance. In which case you will be getting UIColor instead of PColors and what means that inheriting UIColor was not a good idea.
Prefer composition over inheritance - embed UIColor within a PColor. Or use a category on UIColor (you can't have new instance variables in this case).
The init methods of UIColor return a UIColor* rather than id as with most classes, so you would have to assign it to a UIColor rather than your subclass to avoid the warning.