How to replace existing UIColors - subclass

I am trying to make a theming system for my app. Is there a way to redefine the default UIColors? I already tried to subclass UIColor:
//.h file
#import <UIKit/UIKit.h>
#interface UIColor(UIColor_themeColor)
+ (UIColor *)blackColor;
#end
//.m file
#import "UIColor+themeColor.h"
#import "DeviceColor.h"
#implementation UIColor(UIColor_themeColor)
+ (UIColor *)blackColor {
return [self blackColor];
}
#end
But then I get the warning Category is implementing a method which will also be implemented by its primary class which is understandable, and the app will crash if I build it.
Is there a way do what I like to do?

The preamble you'll get from everyone, I think: doing what you want to do is a bad idea as a method called blackColor should return the colour black. Methods should always be appropriately named.
Post-preamble:
Use method swizzling. You can't do it directly through declarations but because the Objective-C runtime is dynamic, you can switch the implementations of methods at runtime. You need to talk to the runtime directly, with its C API, but it's not too tricky.
Mike Ash's guide walks you through the theory and shows you the code, much more clearly than I'm likely to here.

Related

XCode: Duplicate Symbol

I have a C function heightParameter that is a simple tool that I use in a couple of my UIViewControllers. I am declaring this only in my main implementation of each UIViewController subclass (in the .m) above my other functions, so that I didn't even have to declare it in the header.
For some reason, I'm getting duplicate symbols in every other subclass that I use it in, despite it being implemented privately. It is within the main #implementation #end block for each subclass and shouldn't be seen by anything else, so how is it being seen globally?
C function names have global scope. Mark it static or make it a method if you want it to be restricted.

Visibility of methods in class extensions in Xcodes code completion

I saw a similar question addressing differences of the code completion between Xcode 3.2 and Xcode 4. My question addresses a specific behaviour of Xcode (3.2).
When I declare "private" methods in a class extension, these methods are visible in the code completion lists, where they shouldn't be visible.
An example (AClass.m):
#import "AClass.h"
#interface AClass()
- (void)someMethod;
#end
#implementation AClass
//...
- (void)someMethod
{
// do something here
}
//...
#end
When I import AClass.h to some other class and create an AClass-instance...
AClass *test = [[AClass alloc] init];
Xcode's code-completion shows the "private" method "someMethod":
[test som // Shows someMethod, though it shouldn't be visible here
At that point, this method is visible, even if it shouldn't be, because it's unknown here - it's not defined in the header-file. If I send the message [test someMethod] at that point and build the thing, I get a warning, that the object might not respond - as expected.
It actually does respond, but this is confusing behaviour, especially for someone else, who wants to use my class.
That affects #property / #synthesize as well, since they "just substitute methods". I want to access all of my private ivars by properties for a) having homogene code while b) being able to influence the use of ivars (like lazy instantiation). On the other hand all private stuff shouldn't be visible (in code completion) to anyone using my classes, to make it easier to use them.
Is there any way to change this behaviour?
Is the missing validation of context in Xcode 3.2 the reason, why code-completion shows this kind of methods, where they shouldn't be visible?
Is that behaviour different in Xcode 4 (because of context-validation)?
I still use Xcode 3.2, because I wanted to finish a project before switching and adapting myself to Xcode 4.

iOS Xcode 4 properties access

I switched to Xcode 4 recently and I don't really understand this new way to write accessors.
For example, in the application delegate class that is auto-generated when creating a new project, the window object is not declared in the #interface but just this way:
#property (nonatomic, retain) IBOutlet UIWindow *window;
Then, in the implementation file, we have the #synthesize window=_window;.
And in the functions, we have either self.window OR _window.
For example:
[self.window makeKeyAndVisible]; // in didFinishLaunchingWithOptions function
[_window release]; // in dealloc function
Can you explain me the difference, why there is nothing in the #interface, why we do #synthesize window=_window; instead of #synthesize window; and what is the difference between self.window and _window, I mean when do I have to call one more than the other?
I'm a bit lost, and feel like the new code I doing trying to do the same in not working properly...
Thanks!
"Why is there nothing in the #interface"
The runtime is synthesizing the ivar for you.
"Why do we do #synthesize window=_window;
This means that the window property will use an ivar named _window (by default the ivar name is the name of the property)
"What is the difference between self.window and _window?"
The former is using the window "getter" method (ie, foo = [self window]), and the latter is accessing the ivar directly.
"Why do I have to call one more than the other?"
It is generally considered unsafe to use accessor methods in your dealloc method, which means using the ivar is preferred.
This has nothing to do with Xcode 4. This is Objective-C 2.0 (which Xcode 4 uses by default when creating project templates).
I recommend reading the chapter on properties in The Objective-C Programming Language, that should make things much clearer
And doing things "the old way" will still work. You don't have to change everything overnight, simply remove the auto-created code if you don't like it, until you feel comfortable with the new syntax.

Is it good practice to put private API in the .m files and public API in .h files in Cocoa?

Many of my classes in my current project have several properties and methods that are only ever called from within the class itself. Also, they might mess with the working of the class depending on the current state of the class.
Currently, all these interfaces are defined in the main interface declaration in the .h files. Is it considered good practice to put the “private” methods and properties at the top of the .m files?
This won't ever affect anything since I am very likely the only person ever to look at this source code, but of course it would be interesting to know for future projects.
Starting with Objective-C 2.0, the best practice is to put private methods in a "class extension". This allows the compiler to warn you if you haven't implemented one of the methods. Class extensions also let you modify the read/write semantics of #properties so that the public API can, for example, specificy readonly for a property while internally the property can be used as readwrite.
In .h:
#interface MyClass : NSObject
{}
#property (readonly) id myProp;
- (void)aPublicMethod;
#end
In .m:
#interface MyClass ()
#property (readwrite) id myProp; //upgrade myProp to readwrite within the class.
- (id)aPrivateMethod;
#end
#implementation MyClass
#synthesize myProp;
- (void)aPublicMethod { ... }
- (id)aPrivateMethod;
#end
If you forget to implement -aPrivateMethod within the main #implementation block, the compiler will give a warning. This is better than the old way of using a category like #interface MyClass (PrivateMethods) in which case, the compiler couldn't warn you that the method wasn't implemented.
Yes, put them in a category at the top of your .m files.

How Can You Use An Image As A Background For A Text Field In Cocoa?

Is it possible to use an image as a background for a Text Field in Cocoa?
If so, how?
I don't know if this is the "correct" way to do it, but the first thing that comes to mind would be to make a custom subclass of NSTextField, which might look roughly like this:
- (void)awakeFromNib
{
[self setDrawsBackground:NO];
}
- (void)drawRect:(NSRect)rect
{
[super drawRect:rect];
[self lockFocus];
[[NSImage imageNamed:#"<#image filename#>"] drawInRect:rect
fromRect:rect
operation:NSCompositeSourceOver
fraction:1.0];
[self unlockFocus];
}
Again, that's a just rough outline of the essential parts.
Anyways, like I said, I'm not sure if this really the "correct" way to do it (or if there is even a "correct" way, for that matter), but this will give you a background image for your NSTextField.
Edit in response to Joshua's comment (I'm not going to have enough room in that tiny little comment box):
To add the image into your project, you'd drag it from wherever it is into the project window (the main list of files in the middle of the project window, although depending on how you've set up your Xcode editing environment, this might be different for you).
In order to subclass NSTextField, you would want to create a new Objective-C class file (File -> New File…), but edit the header so that the class inherits from NSTextField instead of NSObject. In other words, your header file might look like this:
#import <Cocoa/Cocoa.h>
#interface BGImageTextField : NSTextField
{
}
#end
As for the rest of the code, you would want to add that in the main body of the implementation file (BGImageTextField.m, for example), specifically in between the #implementation and #end keywords.
I'd also like to mention two things. First, I'd recommend picking up a copy of Cocoa Programming for Mac OS X, by Aaron Hillegass—it covers most of the Cocoa basics that I just went over, and is one of the best ways to learn Cocoa in general. Secondly, although my approach works, it's probably not the best approach—especially since I just recently found this post, which seems to hint at a better way of extending NSTextField.
Instead of subclassing NSTextField, just make the background color transparent [NSColor clearColor] and put the image behind it.

Resources