将Objective-C块转换为Swift闭包的方法

4

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

在学习了在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];
    }];
}

Swift:

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时遇到了困难:

enter image description here

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 {

}

1
真是一个格式良好的问题!一个快速的建议是始终使用初始化语法。请使用 NSURL(string:urlString) 代替 NSURL.urlWithString。你已经在 NSString 中使用它了,但没有在 NSURL 中使用 :p - Jack
@JackWu:感谢您的建议!非常感激!为什么使用初始化语法更好,有什么特别的原因吗? - fulvio
1
在Swift中,这是初始化的唯一方式。不再有类初始化程序与实例初始化程序之分。ObjC初始化程序和工厂方法都会自动转换为这个新语法。这是未来! - Jack
@JackWu:有道理,谢谢。 - fulvio
2个回答

0
尝试这个:
func fetchHourlyForecastForLocation(coordinate: CLLocationCoordinate2D,completion:(AnyObject) -> Void)  {

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

0

看起来你在函数声明中忘记了返回类型。声明应该像这样:

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

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


我已经更新了fetchJSONFromURL()返回的内容。它实际上不是一个NSArray,而是一个RACSignal - fulvio
是的,尽管还有很多代码无法编译。这不是将该函数移植过去所需的唯一更改。 - fulvio
有一件事我忘了提:如果你有一个集合,你必须加上尖括号并说明它将包含什么(例如 Array<Int> 表示整数列表)。 - Christian Di Lorenzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接