What am I doing wrong in Swift for calling this Ob

2019-02-23 08:29发布

问题:

I'm using RedditKit to integrate Reddit into an app, and in Objective-C I called the API as follows (and it worked fine):

    [[RKClient sharedClient] signInWithUsername:@"username" password:@"password" completion:^(NSError *error) {
        RKPagination *pagination = [RKPagination paginationWithLimit:100];
        [[RKClient sharedClient] linksInSubredditWithName:subredditSelected pagination:pagination completion:^(NSArray *collection, RKPagination *pagination, NSError *error) {
             // code that executes on completion
        }];
    }];

Here's how I'm calling it in Swift:

RKClient.sharedClient().signInWithUsername("username", password: "password", completion: { (error: NSError!) in
    RKClient.sharedClient().frontPageLinksWithPagination(RKPagination(limit: 50), completion: { (collection: RKLink[]!, pagination: RKPagination!, error: NSError!) in
        // code that executes on completion
    })
})

But I keep getting this error with the Swift version:

Could not find an overload for 'init' that accepts the supplied arguments

EDIT: Here's an example project showing it: http://cl.ly/3K0i2P1r3j1y

回答1:

Note: This issue is the same as in these questions:

animateWithDuration:animations:completion: in Swift

Properly referencing self in dispatch_async


Thanks for adding the example project, the issue is as follows:

From the Swift book: https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/Closures.html

One of the optimizations of Closures is:

Implicit returns from single-expression closures

So... the compiler thinks your closure is returning a value of NSURLSessionDataTask because it is the only line inside the closure block, thus changing the type of the argument.

There are a few ways to solve this, none that are ideal...

The idea is that any other line you add into the closure will fix it, so this will literally work:

      RKClient.sharedClient().signInWithUsername("username", password: "password", completion: { error -> () in
            let a = 1
            RKClient.sharedClient().frontPageLinksWithPagination(nil, completion: nil)
        })

A slightly cleaner way to solve this would be:

RKClient.sharedClient().signInWithUsername("username", password: "password", completion: { error in
    let client = RKClient.sharedClient()
    client.frontPageLinksWithPagination(nil, completion: nil)
})

This wouldn't be an issue if you simply had more code to put into that closure as well!



回答2:

It probably doesn't like your RKLink[]! type for collection as NSArray can theoretically contain any type of object. Try making collection an Array<AnyObject>! or just an NSArray! to confirm.



回答3:

For completeness here's some code that works:

    RKClient.sharedClient().frontPageLinksWithPagination(nil, completion: {
        (collection, pagination, error) in
        if let links = collection as? RKLink[] {
            for link in links {
                println(link.title)
            }
        }
    })