【问题标题】:Converting Objective-C Block into Closure the Swift way以 Swift 的方式将 Objective-C 块转换为闭包
【发布时间】:2014-06-14 16:15:53
【问题描述】:

我已成功将以下方法从Obj-C转换为Swift

在了解了blocks are replaced by closures 如何在 Swift 中使用之后。

Obj-C:

- (RACSignal *)fetchCurrentConditionsForLocation:(CLLocationCoordinate2D)coordinate {
    NSString *urlString = [NSString stringWithFormat:@"http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&units=imperial", coordinate.latitude, coordinate.longitude];
    NSURL *url = [NSURL URLWithString:urlString];

    return [[self fetchJSONFromURL:url] map:^(NSDictionary *json) {
        return [MTLJSONAdapter modelOfClass:[WXCondition class] fromJSONDictionary:json error:nil];
    }];
}

斯威夫特:

func fetchCurrentConditionsForLocation(coordinate: CLLocationCoordinate2D) -> RACSignal {
    let urlString = NSString(format: "http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&units=metric", coordinate.latitude, coordinate.longitude)
    let url = NSURL.URLWithString(urlString)

    return fetchJSONFromURL(url).map { json in
        return MTLJSONAdapter.modelOfClass(WXCondition.self, fromJSONDictionary: json as NSDictionary, error: nil)
    }
}

但是,我在将以下返回映射块转换为 Swift 时遇到了问题:

func fetchHourlyForecastForLocation(coordinate: CLLocationCoordinate2D) -> RACSignal {
    var urlString = NSString(format: "http://api.openweathermap.org/data/2.5/forecast?lat=%f&lon=%f&units=metric&cnt=12", coordinate.latitude, coordinate.longitude)
    let url = NSURL.URLWithString(urlString)

    /* Original Obj-C:

    return [[self fetchJSONFromURL:url] map:^(NSDictionary *json) {
        RACSequence *list = [json[@"list"] rac_sequence];
            return [[list map:^(NSDictionary *item) {
                return [MTLJSONAdapter modelOfClass:[WXCondition class] fromJSONDictionary:item error:nil];
            }] array];
        }];
    }
     */

    // My attempt at conversion to Swift
    // (I can't resolve `rac_sequence` properly). Kind of confused
    // as to how to cast it properly and return
    // it as an "rac_sequence" array.

    return fetchJSONFromURL(url).map { json in
        let list = RACSequence()
        list = [json["list"] rac_sequence]
        return (list).map { item in {
            return MTLJSONAdapter.modelOfClass(WXCondition.self, fromJSONDictionary: item as NSDictionary, error: nil)
        } as NSArray
    }
}

如果有帮助,rac_sequence 就是这样:

- (RACSequence *)rac_sequence {
    return [RACArraySequence sequenceWithArray:self offset:0];
}

RACArraySequence():

+ (instancetype)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset;

编辑: fetch 方法返回 RACSignal 而不是 NSArray

func fetchJSONFromURL(url: NSURL) -> RACSignal {

}

【问题讨论】:

  • 多好的问题!一个快速的评论是始终使用初始化语法。 NSURL(string:urlString) 而不是 NSURL.urlWithString。您将它用于NSString,但没有用于NSURL:p
  • @JackWu:感谢您的建议!欣赏它!使用初始化语法更好的任何特殊原因?
  • 在 Swift 中,这是进行初始化的唯一方法。不再有类初始化器与实例初始化器。 ObjC 初始化器和工厂方法都会自动转换为这种新语法。它的未来!
  • @JackWu:有道理,谢谢。

标签: objective-c closures objective-c-blocks swift reactive-cocoa


【解决方案1】:

看起来你只是忘记了函数声明中的返回类型。声明应如下所示:

func fetchHourlyForecastForLocation(coordinate: CLLocationCoordinate2D) -> RACSignal { //...rest of function

由于现在已命名返回类型,因此您可以在函数末尾的 return 语句中删除 as NSArray 强制转换。希望这会有所帮助!

【讨论】:

  • 我已经更新了fetchJSONFromURL() 返回的内容。它实际上不是NSArray,而是RACSignal
  • 是的,尽管仍有很多代码无法编译。这不是移植该功能所需的唯一更改。
  • 我忘了提一件事:如果你有一个集合,你必须用尖括号来说明它将包含什么(例如,Array<Int> 表示整数列表)。
【解决方案2】:

试试这个:

func fetchHourlyForecastForLocation(coordinate: CLLocationCoordinate2D,completion:(AnyObject) -> Void)  {

   //after getting the NSArray (maping)
   completion(_array)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多