Skip to main content
 首页 » 操作系统

objective-c之将 Objective C 中带回调的 block 转换为 Swift 中的闭包

2024年01月01日36飞鱼

我在 Objective C 的 block 中有以下回调

typedef void (^COMPLETION_BLOCK)(NSString *response, NSError *errorString); 
 
+ (void)responseFromURL:(NSURL *)url completionBlock:(COMPLETION_BLOCK)completionBlock 
{ 
   __block  NSError *error = nil;     
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
        NSString *response = [NSString stringWithContentsOfURL:url 
                                                      encoding:NSUTF8StringEncoding 
                                                         error:&error]; 
 
        dispatch_async(dispatch_get_main_queue(), ^{ 
                completionBlock(response, error); 
        }); 
    }); 
} 

这是我在 Objective C 中的调用方式

[Utilities responseFromURL:NSURL URLWithString:@""] completionBlock:^(NSString *response, NSError *errorString) 
{ 
 
}] 

我已经尝试在 Clousers 中快速转换它 这是代码

class Utilities 
{ 
    typealias COMPLETION_BLOCK = ( response : NSString, error : NSError) -> () 
 
    func responseFromURL(url: NSURL , completionBlock:COMPLETION_BLOCK) 
    { 
        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT 
        var e : NSError?; 
 
        dispatch_async(dispatch_get_global_queue(priority, 0)) 
        { 
            var content:NSString? = NSString(contentsOfURL: url, 
                encoding: NSUTF8StringEncoding, 
                error: &e) 
 
            dispatch_async(dispatch_get_main_queue()) 
            { 
                completionBlock(response: content!,error:  e!); 
            } 
        } 
    } 
} 

我不确定这是否是正确的转换。其次,我应该如何快速调用该 block ?

var urlString = String(format: BASE_URL + "%d", categoryType); 
        var url = NSURL(string :urlString); 

请您参考如下方法:

你快到了。您不需要类型别名,因为您可以在函数定义中指定 completionBlock。

可能会给您带来问题的一件事是强制解包内容,其中一个内容将为零。

这是我的函数版本:

func responseFromURL(url : NSURL, completionBlock : (response : String?, error : NSError?) -> Void) { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) { 
        var error : NSError? = nil 
        let response = String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error) 
 
        dispatch_async(dispatch_get_main_queue()) { 
            completionBlock(response: response, error: error) 
        } 
    } 
} 

并调用它:

responseFromURL(myURL) { (response, error) in 
    if error != nil { 
        // handle error 
    } 
    else if response != nil { 
        // data came back 
    } 
} 

需要注意的几点:

  • 在完成 block 定义中,我指定响应和错误参数都是可选的。您应该取回一个或另一个,但您需要检查是哪一个。
  • 与 Objective-C 不同,您不必发送指向错误的指针。如果需要,完成处理程序会向您发回错误。
  • 我使用了较短形式的 Swift 闭包,但如果您让自动完成完成它的工作,您将得到更长的形式,这可能更具可读性。