Objective-C中流畅的接口模式 [英] Fluent interface pattern in Objective-C

查看:137
本文介绍了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项目中使用这种模式。

解决方案

这里有几个注释:


  1. 从方法返回一个现有对象时,如果仍然关心那个对象,你不自动释放它,你只是返回它。在这种情况下,由于即使在调用者获得对它的引用之后你仍然保持你自己的对象,不要向它发送 autorelease 消息。不要认为模式为返回一个autoreleased对象;只有当您在方法中创建对象时才这样做,并且希望返回它而不必自己保留引用。


  2. 自己是一种特殊类型的引用,很少发送 self 任何内存管理消息,可能的例外在 init


  3. 虽然你可以创建一个流畅的消息链模式,注意这不是常见/惯用的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 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:

  1. 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.

  2. self is sort of a special kind of reference anyway, and it's very rare to be sending self any memory management messages, with the possible exception of inside the init method.

  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆