I am a newbie in Objective-c and I would like to implement fluent interface pattern in my OC class. Here is my updated and simplified case from my project:
// .h file
@interface MyLogger : NSObject {
...
}
- (MyLogger*) indent:(BOOL)indent;
- (MyLogger*) debug:(NSString*)message, ...;
- (id) warning:(NSString*)message, ...;
....
@end
// .m file
@implement MyLogger {
- (MyLogger*) indent:(BOOL)indent {
// some codes to set indent or unindent
return self; // I think it should return [self autorelease];
}
- (MyLogger*) debug:(NSString*)message, ... {
// build message and log the message
return [self autorelease];
}
- (id) warning:(NSString*)message, ... {
// similar as above, but log a warning message
return self;
}
//. usage in another .m
-(id) initAnotherClass {
if (self = [supper init]) {
// ...
// instance was defined as MyLogger in .h as class var
instance = [[[MyLogger alloc] initWithContext:@"AnotherClassName"] retain];
//...
}
return self;
}
-(void)method1 {
[[instance debug:@"method1"] indent:YES];
...
[instance warning:@"some debug message with obj: %@", var];
...
[[instance indent:NO] debug:@"method1 DONE"];
}
// in my Xcode output I'll see debug output like
[date time] [app id] [DEBUG] AnotherClassName - method1
[date time] [app id] [WARNING] AnotherClassName - some debug message with obj: ...
[date time] [app id] [DEBUG] AnotherClassName - method1 DONE
Here in indent, I return self, while in debug: I return [self autorelease]. It works fine if I only return self like in debug. However, I think I should always return in the same way as I did in debug: in terms of OC memory management. Any suggestions?
Updated: I added another method warning with return type of id. Should I return self as id type or my class type in OC? It seems both works fine and there is no compile error or warning. I have seem Cocoa framework classes return id. For example, here are some methods in NSString.h
+ (id)string;
+ (id)stringWithString:(NSString *)string;
It seems that Cocoa has some FI pattern like methods. Should be id type better than the class itself?
Update: as Pat Wallace‘s suggestion, I am actually using this pattern in an iPhone project.
A few notes here:
When you return an existing object from a method, if you still “care” about that object, you don’t autorelease it, you just return it. In this case, since you’re “keeping” your own object around even after the caller gets a reference to it, don’t send it the
autoreleasemessage. Don’t think of the pattern as “return an autoreleased object”; you do that only when you create an object inside a method, and want to return it without keeping a reference yourself. If the caller wants to keep the reference it gets back, it is free to retain it then.selfis sort of a special kind of reference anyway, and it’s very rare to be sendingselfany memory management messages, with the possible exception of inside theinitmethod.Although you can certainly create a Fluent pattern of message chaining like you’re trying to do, just a note that this is not common/idiomatic Objective-C, and your code may not mix well with other code, and may confuse others who read it. Just FYI.