Using #define to create styles - objective-c

I am wondering if I can use a series of #DEFINE to create style options for my app.
For example,
#DEFINE style1: backGroundColor = [UIColor: colorNamed whiteColor];
txtColor = [UIColor blackColor]; #DEFINE style2....
My question is: What is the syntax for this statement?

While it is certainly possible to use DEFINE statements to create style options for your app, I'm wondering if the use of preprocessor directives makes sense for functionality such as styles, which are going to be collections to properties. If you use DEFINE statements to define your styles, it makes it difficult to ultimately provide style selection as a run-time option to your users.
Instead, I tend to think you will be better off creating a class hierarchy for this, and implementing it as a singleton. With a class hierarchy, you can define any general style behaviors in your root class, and then inherit from that to implement specific styles. Later on, you can expose the ability to select styles to your user if you want.

#define backgroundColor [UIColor whiteColor] then to use it you would say UIColor *txtColor = backgroundColor;.
Although you may only be able to use whiteColor as the definition instead of [UIColor whiteColor]. You would then call [UIColor backgroundColor]; instead of the above example.
I would not do this to generate stylings. Defining various settings outside of code would be a good idea but using defines is pretty binding and defeats the purpose of de-coupling the UI from code.
In a #define do not put a semicolon anywhere. When the preprocessor inserts the definition it will insert whatever semicolon is there exactly as it is; you do not want the preprocessor inserting semicolons. When writing the definition you probably don't know all the places you'll write it, therefore you shouldn't have a semicolon in it because you may write it inline an expression.
Another option is to use const instead.
In code I've written I have #defines for string literals #"literal string" and numbers. In other places I use the const declaration which looks like this:
//static type *const variableName = assignment;
static NSString *const kConstantString = #"Constant variable";
Constants don't use the preprocessor to fill in the information. If you access a define frequently and it uses some computation it might may be better suited to a constant declaration which is stored only once.
The other big reason I used const instead of #define is that define is not type-checked as it's handled by the preprocessor. Define basically turns off the compiler warnings and only gives you errors; strict warnings are extremely helpful and can save a lot of frustration.

Maybe you are looking for this syntax:
Setting a style
#define STYLE1
//#define STYLE2
and then anywhere in your code (class level or method level, header or implementation file).
#ifdef STYLE1
//code for the first style
UIColor* backgroundColor = [UIColor redColor];
#elif STYLE2
//code for the second style
UIColor* backgroundColor = [UIColor greenColor];
#else
//code for the third style
UIColor* backgroundColor = [UIColor clearColor];
#endif
More about C preprocessor: http://en.wikipedia.org/wiki/C_preprocessor

Related

What is the recommended method of styling an iOS app?

What is the recommended method of styling an iOS app? For example, if there are multiple labels or text views how can updating font style/color at one place update the style/color at all other places?
I know sub classing could be one way... is there any other way?
You could import a standard header file into all your controllers with several constants set for styling... example:
Styles.h
#define kFontSize 14
#define kFontFamily #"Helevetica"
Controller
#import "Styles.h" // at the top
myLabel.font = [UIFont fontWithName:kFontFamily size:kFontSize];
I personally think Interface Builder is the best way to style, however this answers your question directly.
Update: I would recommend starting by understanding UIAppearance APIs, and seeing how well they suit your needs. UIAppearance is a convenient way to provide custom default stylization of specific controls' attributes at multiple levels (e.g. globally or contextually).
My original answer, which predated UIAppearance's availability:
since we're working with an object based language...
for the implementation, it depends on how you want it to behave/execute. when the implementation becomes nontrivial, i will often create a protocol. you could use class methods or instance methods and significantly optimize these types for your usage because you create fewer intermediate colors, fonts, images, etc.
a basic interface could take the form:
#protocol MONLabelThemeProtocol
- (UIFont *)labelFont;
- (UIColor *)labelTextColor;
- (UITextAlignment)labelTextAlignment;
// ...
#end
#protocol MONTableViewCellThemeProtocol
- (UIFont *)tableViewCellFont;
- (UIColor *)tableViewCellTextColor;
- (UIImage *)tableViewCellImage;
- (NSInteger)tableViewCellIndentationLevel;
- (CGFloat)tableViewCellIndentationWidth;
// ...
#end
then a simple amalgamate theme could be declared like this:
#interface MONAmalgamateThemeBase : NSObject
< MONLabelThemeProtocol, MONTableViewCellThemeProtocol >
{
#protected
/* labels */
UIFont * labelFont;
UIColor * labelTextColor;
UITextAlignment labelTextAlignment;
// ...
/* table view cells */
UIFont * tableViewCellFont;
UIColor * tableViewCellTextColor;
UIImage * tableViewCellImage;
NSInteger tableViewCellIndentationLevel;
CGWidth tableViewCellIndentationWidth;
// ...
}
#end
in this example, the amalgamate defines the getters and dealloc and expects the subclasses to initialize the instance variables. you could also support lazy initialization if initialization times are high (e.g. uses many images).
then a specialization could take the form:
#interface MONDarkTheme : MONAmalgamateThemeBase
#end
#implementation MONDarkTheme
- (id)init
{
self = [super init];
if (nil != self) {
labelFont = [[UIFont boldSystemFontOfSize:15] retain];
labelTextColor = [[UIColor redColor] retain];
// and so on...
}
return self;
}
// ...
#end
/* declare another theme and set it up appropriately */
#interface MONLightTheme : MONAmalgamateThemeBase
#end
then just reuse the theme instances (e.g. MONDarkTheme) throughout the app to stylize the views. if you have a lot of themes or they are not trivial to construct, then you may want to create a collection for themes (theme manager). the amalgamate could also take a parameter, such as init with theme if your needs are simple. you can even configure objects to register for changes to themes, if you need support for dynamic changes.
finally, you can create a simple theme applier to make life easier - like so:
#interface UILabel (MONThemeAdditions)
- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme;
#end
#implementation UILabel (MONThemeAdditions)
- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme
{
assert(theme);
if (nil == theme) return;
self.font = [theme labelFont];
self.textColor = [theme labelTextColor];
self.textAlignment = [theme labelTextAlignment];
}
#end
Frankly, the best way to go about this is to use Interface Builder. While it might seem nice to change a single constant somewhere in the code and have the entire app change styles, it never quite works out that way. Here are my reasonings:
1) Developers don't write interface code as well as interface builder does.
Interface builder is a tool that has been refined, tested, and intreated over years. It offers fonts, text alignment, shadow, etc. It is backwards compatible for as far back as you'd ever want. It provides a very simple way for any number of developers and designers to jump in and work on something very straightforward.
2) There are always edge cases that you'll have to account for. Sure, a simple constant will do what you want most the time, but you'll eventually have to hack something in here and sneak something in there. The "simple" interface code you wrote to start off will grow and grow and grow. Other developers will have to maintain that code. You will have to maintain that code. You will have to file and fix bugs, tweak this, except that, etc. It will inevitably become a steaming pile of mess.
3) The more code you write, the more bugs you write. Interface builder is for building the 'look' of most iOS apps. Use it. Don't get too clever.
NOTE:
I understand that Interface builder cannot do everything for all apps. There are cases that coding an interface is the only solution. This answer is simply a general "best practice" I use in the bulk of my apps.
Similar to Alex's idea, you could create a static class called ThemeManager:
typedef enum
{
defaultStyle,
redStyle,
} ThemeStyles;
#interface Level : NSObject
{
ThemeStyles currentTheme;
}
All classes which can be themed will import ThemeManager. Then, you can create methods like:
+ (UIColor*) fontColor;
Which other classes would call when they want a color for their font. Then, if you want to change themes, you could implement fontColor as:
+ (UIColor*) fontColor
{
switch (currentTheme)
{
case defaultStyle:
return [UIColor blackColor];
case redStyle:
return [UIColor redColor];
}
}
When you want to change the theme, you could have ThemeManager implement a method like:
+ (void) changeTheme:(ThemeStyles)newTheme
{
currentTheme = newTheme;
}
You can use a third-party abstraction of UIAppearance:
NUI: https://github.com/tombenner/nui
Pixate: http://www.pixate.com
Using a Storyboard has a lot of benefits, but many style options aren't available, not the least of which is custom fonts. If you want a deeply-customized UI, you will need some style code to make it happen.
I use plists. Just as I localize strings, I use the same procedure to change themes. I coded a singleton that loads a current theme plist and a fallback plist. Then I replace the names of resources with keys and macro functions that pull the real resource name from the singleton.
Cons: you have to set the resource for each element, not just set it in the NIB.
Pros: once you are done, most of the next theme involves photoshop and textmate, not IB or code.
You may need to look at this library. It supports multiple themes/skins on the fly. Supports images and colors currently. Font support will be added in future.
https://github.com/charithnidarsha/MultiThemeManager

External Constants for UIColor, UIFont, etc

I have a constants.m file that is a centralized collection of many program constants. To set a color, I do this:
#implementation UIColor (UIColor_Constants)
+(UIColor *) defaultResultTableBackgroundColor{
//return [[UIColor colorWithRed:0.6f green:0.004f blue:0.0f alpha:1.0f] retain];
return [[UIColor colorWithRed:0.1f green:0.004f blue:0.3f alpha:0.3f] retain];
}
+(UIColor *) defaultResultHeaderBackgroundColor{
return [[UIColor clearColor] retain];
}
#end
and in the constants.h I have
#interface UIColor (UIColor_Constants)
+(UIColor *) defaultResultTableBackgroundColor;
+(UIColor *) defaultResultHeaderBackgroundColor;
#end
and then just use [UIColor defaultResultTableBackgroundColor] where I want to refer to this constant.
I would like to have some other UIColor and UIFont constants, and, while this works, it seems to be more complicated than it needs to be. Is there an easier way to do this?
I use a constants file for the same purpose. Rather than setting up a whole interface and implementation file, I create the constants file as just the header (.h) file. Then, I define the colors I want to use, such as:
#define globalColor [UIColor colorWithRed:0.1f green:0.004f blue:0.3f alpha:0.3f]
Then, any time you use globalColor it's just like typing in the defined code.
I actually like this way too. One question: why do you retain the uicolor?
This is very dangerous. It's very likely to make a mistake and to create a memory leak.
Here's a great read that explains constants in Objective C:
What is the best way to create constants in Objective-C
Short answer: You're handling this the best way possible.
Macros are not recommended. As some have mentioned, you could #define a macro to handle your colors. That's essentially telling the preprocessor to run find-and-replace on your code. There's a number of downsides to this approach, including scope and type. Apple explicitly recommends against these types of 'constants": https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html
It's also possible to create a constant:
(in your header, file scope)
extern UIColor * const COLOR_LIGHT_BLUE;
(in your implementation, file scope)
UIColor* const COLOR_LIGHT_BLUE = [[UIColor alloc] initWithRed:21.0f/255 green:180.0f/255 blue:1 alpha:1];
You could, of course, #import this header in your prefix header to save even more typing. Ultimately, though, it's not much of an improvement over what you're already doing.
You create a constant header file which contains all your colors and/or fonts like that:
// Define a convenient macro for example
#define HEXCOLOR(c) [UIColor colorWithRed:((c>>16)&0xFF)/255.0 \
green:((c>>8)&0xFF)/255.0 \
blue:c&0xFF/255.0 \
alpha:0xFF/255.0]
// Then define your constants
#define DefaultResultTableBackgroundColor HEXCOLOR(0x151515)
// etc.
Answer is very simple. It can be used for NSArray and NSDictionary etc.
//Font
static UIFont *titleFont() {
static UIFont *font = nil;
if (!font) {
font = [UIFont systemFontOfSize:25 weight:UIFontWeightHeavy];
}
return font;
}
//Color
static UIColor *prettyPurpleColor() {
static UIColor *color = nil;
if (!color) {
color = [[UIColor purpleColor] colorWithAlphaComponent:0.35];
}
return color;
}

Is it possible to suppress Xcode 4 static analyzer warnings?

The Xcode 4 static analyzer reports in my code some false positives. Is there any way to suppress them?
I found a solution: false positives (like the Apple singleton design pattern) can be avoided with:
#ifndef __clang_analyzer__
// Code not to be analyzed
#endif
Analyzer will not analyze the code between those preprocessor directives.
Take a look at this page which shows how to use several #defines to annotate objective-c methods and parameters to help the static analyzer (clang) do the right thing
http://clang-analyzer.llvm.org/annotations.html
From that page:
The Clang frontend supports several source-level annotations in the
form of GCC-style attributes and pragmas that can help make using the
Clang Static Analyzer more useful. These annotations can both help
suppress false positives as well as enhance the analyzer's ability to
find bugs.
See my answer here. You can add a compile flag to the files and static analyzer will ignore them. This is probably better for 3rd party code you aren't concerned about, and not for first party code you are writing.
most of the time, using things like CF_RETURNS_RETAINED and following the 'create' rule works for me, but I ran into a case I could NOT suppress.
Finally found a way to suppress the analyzer by looking at llvm source code:
https://llvm.org/svn/llvm-project/cfe/trunk/test/ARCMT/objcmt-arc-cf-annotations.m.result
"Test to see if we suppress an error when we store the pointer to a
global."
static CGLayerRef sSuppressStaticAnalyzer;
static CGLayerRef sDmxImg[2][2][1000]; // a cache of quartz drawings.
CGLayerRef CachedDmxImg(...) // which lives for lifetime of app!
{
...
CGLayerRef img = sDmxImg[isDefault][leadingZeroes][dmxVal];
if ( !img )
{
NSRect imgRect = <some cool rectangle>;
[NSGraphicsContext saveGraphicsState];
CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGLayerRef cgLayerRef = CGLayerCreateWithContext(ctx, imgRect.size, NULL);
CGContextRef layerCtx = CGLayerGetContext(cgLayerRef);
[NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort:layerCtx flipped:YES]];
... draw some gorgeous expensive Quartz stuff ...
img = cgLayerRef;
sDmxImg[isDefault][leadingZeroes][dmxVal] = cgLayerRef;
sSuppressStaticAnalyzer = cgLayerRef; // suppress static analyzer warning!
[NSGraphicsContext restoreGraphicsState];
}
return img;
}
For some reason, assigning to a static array didn't suppress the warning, but assigning to a plain old static 'sSuppressStaticAnalyzer' does.
By the way the above method, using CGLayerRef is the fastest way I've found to redraw cached images (besides OpenGL).

When to use brackets and when to use the period in Objective-C

I'm a new iPhone/Objective-C developer and as I'm going through different tutorials and open source code, I am having a bit of a problem understanding when to use the square brackets "[ ]" and when to use the period " . " for accessing properties/methods of an object.
For example, this code:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
UIColor *backgroundColor = nil;
if (selected){
backgroundColor = [UIColor clearColor];
} else {
backgroundColor = [UIColor whiteColor];
}
self.todoTextLabel.backgroundColor = backgroundColor;
self.todoTextLabel.highlighted = selected;
self.todoTextLabel.opaque = !selected;
self.todoPriorityLabel.backgroundColor = backgroundColor;
self.todoPriorityLabel.highlighted = selected;
self.todoPriorityLabel.opaque = !selected;
}
Why does [UIColor clearColor] get brackets, but todoTextLabel.backgroundColor get the period?
Could someone explain this easily for me?
The convention I have seen in new code is to use the dot for properties, and always use square brackets for messages/selectors (what you call methods). The dot was introduced in Objective-C 2.0, so the disagreement of information you find online is not entirely unexpected.
It's also entirely possible to use square brackets for everything, still (and I do):
foo = [myObject backgroundColor];
[myObject setBackgroundColor:foo];
is equivalent to
foo = myObject.backgroundColor;
myObject.backgroundColor = foo;
To reiterate, you should not be using the dot for messages, only properties.
To answer your specific question, [UIColor clearColor] belongs in brackets because it is not a property; it's actually a class message to UIColor (+(UIColor)clearColor).
You sound like you come from a Java world, so this might be helpful:
MyObject *foo = [[MyObject alloc] initWithAwesome:YES]; /* MyObject foo = new MyObject(TRUE); */
[foo doSomethingWithNumber:5 andString:"five"]; /* foo.doSomething(5, "five"); */
MyColor *bar = foo.faceColor; /* MyColor bar = foo.faceColor; */
MyColor *baz = [foo faceColor]; /* MyColor baz = foo.faceColor; */
foo.backColor = bar; /* foo.backColor = bar; */
[foo setUndersideColor:baz]; /* foo.undersideColor = baz; */
The "setXXX" and "XXX" messages come from synthesized dynamic properties, and are an Objective-C idiom. The "dot" is simply a shorthand for calling those methods, and is roughly equivalent.
EDIT: Now that I've got some upvotes, time to make some of you reconsider >:)
I never use dots, and neither should you.
I use dot notation for properties because,
for ( Person *person in group.people){ ... }
is a little easier to read than
for ( Person *person in [group people]){ ... }
in the second case readability is interupted by putting your brain into message sending mode, whereas in the first case it is clear you are accessing the people property of the group object.
I will also use it when modifying a collection, for instance:
[group.people addObject:anotherPerson];
is a bit more readable than
[[group people] addObject:anotherPerson];
The emphasis in this case should be in the action of adding an object to the array instead of chaining two messages.
Big Nerd Ranch has some thoughts on the dot notation that are worth reading.
There's also a rebuttal.
By (strong) convention, property accessors are written as methods named after the instance variable for the getter, and the (capitalised) instance variable name prefixed with "set" for the setter (so for instance variable foo you'd have foo and setFoo).
As others have pointed out, as of Objective-C 2.0, if you write object.foo, it will map onto method call [object foo] if getting or [object setFoo: arg] for setting. You can use either form, and some people continue to prefer the full method syntax even when using Objective-C 2.0 exclusively.
A separate, but related, addition to Objective-C 2.0 are the #property/#synthesize/#dynamic keywords for generating the getters and setters. You can mix and match these with dot notation - one does not require the other.
Yep, I just started learning this too:
Unlike other languages, syntax to invoke a method on an object is not objName.someMethod();
It's [objName someMethod]
The dot operator is used to either get or set the value of a property in a class. It's a short way of doing something.
The dot operator, as I have seen it, is always used on an instance of an object whereas the [...] can be used on either an instance of an object or statically (using the class name).
todoTextLabel can use the [] also but using the dot operator is just shorter hand...otherwise you would have to provide parameters, etc, and that's just longer notation.
Hope this helped.

How to base class behaviors on typedef enums, the way Apple does in Objective-C?

Kind of a weird newbie question...I want to use typedef enum declarations in one of my classes . This particular class gets used by other classes, where a client class might say something like "set your style to Style1 (enumerated type)". Then the target class's behavior would change accordingly. This is analogous to the way that UITableViewCellStyles are used in the iPhone SDK.
So, I read through a few UIKit framework headers to get a better idea of how Apple was handling the enumerated types. I see that they declare a bunch of enums everywhere, like so...
typedef enum {
UIBarButtonSystemItemDone,
UIBarButtonSystemItemCancel,
UIBarButtonSystemItemEdit,
UIBarButtonSystemItemSave,
UIBarButtonSystemItemAdd,
...
UIBarButtonSystemItemUndo, // available in iPhone 3.0
UIBarButtonSystemItemRedo, // available in iPhone 3.0
} UIBarButtonSystemItem;
...but I don't see any clues in the header on how they actually handle these types (I'm basically trying to see an example of their implementation, so this isn't a suprise). My instinctive thought as a fairly newb programmer would be to match the int values of each type to some behavior/variable stored in an array, plist etc. But also as a newb programmer I expect that everything that I think will be wrong. So I have two questions:
Anybody have a guess as to how Apple itself handles enum type values to change behaviors?
In general for this type of setup, is there a best design practice that everyone knows about or is this just an open-ended scenario?
Simple enums are usually handled in a switch statement:
typedef enum {
eRedStyle,
eGreenStyle,
eBlueStyle
} MyStyle;
#implementation MyClass
- (void)setStyle:(MyStyle)style {
switch (style) {
case eRedStyle :
self.backgroundColor = [UIColor redColor];
break;
case eGreenStyle :
self.backgroundColor = [UIColor greenColor];
break;
case eBlueStyle :
self.backgroundColor = [UIColor blueColor];
break;
default :
NSLog(#"Bad Style: %d", style);
break;
}
}
An enumeration is (almost but not really) an integer, but made easy to read for the programmer that's using it. Given that, you can have routines that check the value of an enum the same way you would an integer:
void DoMyEnumeratedThing(UIBarButtonSystemItem item)
{
if (item == UIBarButtonSystemItemDone)
DoMyItemDoneThing();
else if (item == UIBarButtonSystemItemCancel)
DoMyItemCancelThing();
// ...and so forth and so on.
}
While I don't know the gory details of Apple's OS internals, every enumeration check essentially boils down to something like the above. As for your "best design practice" question, the answer really depends on what you're trying to accomplish with the enumeration. While every use-case is switch-like, sometimes the enumeration is a set of bits in a bitfield that allow the client to toggle one or more of them at the same time (which is not the case in the example you provide).