Objective-C中流畅的接口模式 [英] Fluent interface pattern in Objective-C
问题描述
我是Objective-c的新手,我想在我的OC类中实现流畅的接口模式。这是我的项目更新和简化的案例:
// .h文件
$
@interface MyLogger:NSObject {
...
}
- (MyLogger *)indent:(BOOL)indent;
- (MyLogger *)debug:(NSString *)message,...;
- (id)warning:(NSString *)message,...;
....
@end
// .m文件
@implement MyLogger {
- (MyLogger *)indent:(BOOL)indent {
//一些代码设置缩进或不缩进
return self; //我认为应该返回[self autorelease];
}
- (MyLogger *)debug:(NSString *)message,... {
//构建消息并记录消息
return [self autorelease]
}
- (id)warning:(NSString *)message,... {
//类似上面,但记录一个警告消息
return self;
}
//。用法在另一个.m
- (id)initAnotherClass {
if(self = [supper init]){
// ...
//实例被定义为MyLogger .h as class var
instance = [[[MyLogger alloc] initWithContext:@AnotherClassName] retain];
// ...
}
return self;
}
- (void)method1 {
[[instance debug:@method1] indent:YES];
...
[实例警告:@一些带obj的调试消息:%@,var];
...
[[instance indent:NO] debug:@method1 DONE];
}
//在我的Xcode输出中我会看到调试输出像
[date time] [app id] [DEBUG] AnotherClassName - method1
[date时间] [应用程序id] [警告] AnotherClassName - 一些调试消息obj:...
[date time] [app id] [DEBUG] AnotherClassName - method1 DONE
$
code>:我返回
[self autorelease]
。它工作正常,如果我只返回self
像debug
。但是,我认为我应该总是返回与在debug
:在OC内存管理方面相同的方式。有任何建议?
更新:我添加了另一个方法
警告
。我应该返回自我作为id类型或我的类类型在OC?它似乎都工作正常,没有编译错误或警告。我好像Cocoa框架类返回id。例如,这里有一些方法在NSString.h+(id)string;
+(id)stringWithString:(NSString *)string;
似乎Cocoa有一些FI模式的方法。应该是id类型比类本身更好吗?
更新:as Pat Wallace 的建议,我实际上在iPhone项目中使用这种模式。
解决方案这里有几个注释:
从方法返回一个现有对象时,如果仍然关心那个对象,你不自动释放它,你只是返回它。在这种情况下,由于即使在调用者获得对它的引用之后你仍然保持你自己的对象,不要向它发送
autorelease
消息。不要认为模式为返回一个autoreleased对象;只有当您在方法中创建对象时才这样做,并且希望返回它而不必自己保留引用。
自己
是一种特殊类型的引用,很少发送self
任何内存管理消息,可能的例外在init
虽然你可以创建一个流畅的消息链模式,注意这不是常见/惯用的Objective-C,你的代码可能不能与其他代码混合,并可能会混淆其他人读它。只是FYI。
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 indebug
: I return[self autorelease]
. It works fine if I only returnself
like indebug
. However, I think I should always return in the same way as I did indebug
: 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
autorelease
message. 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.
self
is sort of a special kind of reference anyway, and it's very rare to be sendingself
any memory management messages, with the possible exception of inside theinit
method.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.
这篇关于Objective-C中流畅的接口模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!