【问题标题】:How should I return an NSError object from a delegate method?我应该如何从委托方法返回一个 NSError 对象?
【发布时间】:2009-05-06 00:17:55
【问题描述】:

我正在设计一个委托方法,当远程服务器需要来自委托的输入时调用该方法。此时的委托负责填写要发送到服务器的数据,并告诉服务器此时是否有错误。

我现在的委托方法是:

-(void)server:(MBServer*)server
 willSendData:(NSMutableString*)data
        error:(NSError**)error;

此时,delegate 可以通过修改传入的 NSMutableString 来为服务器提供要发送的数据。此外,它可以通过将 error 变量设置为新的 NSError 实例来创建要发送回的 NSError。

我遇到的问题是委托方法可能会通过 NSInvocation 从另一个线程调用。委托可以创建一个新的 NSError 对象,但它会在其他线程收到响应之前在当前线程中自动释放。

在单线程应用程序中,这不是问题,因为委托人可以立即保留响应,但在多线程设计中我不能这样做(再次因为当前事件循环会自动释放它)。委托人必须保留错误,以便委托人可以释放它。

这是针对公共 api 的,我不喜欢通过文档要求实现者知道他们必须保留错误对象的想法。好像太不安全了。

// You *must* retain the returned error before
// passing it back or you will crash

-(void)server:(MBServer*)server
 willSendData:(NSMutableString*)data
        error:(NSError**)error;

我想到的其他想法是发送一个 NSError 作为返回值(似乎有些不标准,因为大多数方法返回一个布尔值并采用 NSError 双指针)。它看起来也很奇怪。

-(NSError *)server:(MBServer*)server
      willSendData:(NSMutableString*)data;

我还考虑过传递一个可变字典并要求委托填写错误。然后字典会保留错误,安全地跨线程取回。

// Send your NSError response in the dictionary with the key
// MBServerErrorResponseKey

-(void)server:(MBServer*)server
 willSendData:(NSMutableString*)data
     response:(NSMutableDictionary*)response;

有没有人处理过这个设计问题,如果有,你的解决方案是什么?

谢谢。

【问题讨论】:

    标签: cocoa api


    【解决方案1】:

    这个怎么样:不是直接调用委托方法,而是通过 NSInvocation 调用一个“trampoline”方法。蹦床(您将实现)只会调用委托方法,并在返回之前保留错误。换一种说法:蹦床(可能是你的服务器对象上的一个方法)只会用传递的参数包装对委托的调用,然后保留错误并返回。

    【讨论】:

    • 这是个好主意!这让我可以使用 NSString 而不仅仅是一个可变的。所以我会创建:@implementation MBServer -(void)MB_threadSafeServerWillSendData:(NSString**)string error:(NSError**) { [delegate server:self willSendData:string error:error]; [*字符串保留]; [*错误保留]; } @end 并在单独的线程中调用它?
    • 是的,这听起来对我来说是正确的。不过,我认为如果该方法返回 NSString(甚至是 NSData)可能会更清楚。
    • 实际上,还有一件事:您可能还希望将委托传递给该蹦床 - 否则,如果它在请求调用和调用之间发生变化,您会得到奇怪的行为。 (如果它在蹦床的执行过程中发生变化,那就更奇怪了!)所以也许: -(NSData*)MB_threadSafeDataToSendToDelegate:(id)localDelegate error:(NSError**) { *error = nil; NSData *data = [localDelegate dataToSendForServer:self error:error]; [*错误保留];返回数据; }
    【解决方案2】:

    你可以做的一件事是尝试类似

    -(void)server:(MBServer*)server
     willSendData:(NSMutableString*)data
            shouldStop:(BOOL*)stopFlag;
    -(NSError*)getLastErrorForServer:(MBServer*)server;
    

    这将允许委托通过设置stopFlag 向服务器发出出现问题的信号,然后服务器可以调用getLastErrorForServer: 方法来了解实际出现的问题。让server:WillSendData: 方法返回BOOL 而不是传入指针也可能更有意义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      相关资源
      最近更新 更多