Calling Swift Closure Inside Closure

前端 未结 4 1195
礼貌的吻别
礼貌的吻别 2021-01-08 00:26

I have the following code:

  twitterAPI?.verifyCredentialsWithUserSuccessBlock({ (userName, password) -> Void in


            twitterAPI?.getUserTimelin         


        
相关标签:
4条回答
  • 2021-01-08 01:02

    This is a really misleading error message. The problem is that the inner variable can't be of optional type so you need to if/let it.

    Check this out in a playground...

    class Foo:NSObject {
        func doThing(bug:Int,completion:((Void)->(Void))) {
    
        }
    }
    
    let woot = Foo()
    var bar:Foo? = Foo()
    
    bar?.doThing(7, completion: {});
    
    woot.doThing(3, completion: {
    
         bar?.doThing(4, completion:{});
    
    });
    

    It doesnt compile and the message

    Cannot convert the expression type '(IntegerLiteralConvertible, completion:()->()-$T3)' to type '()'

    Isn't exactly illuminating to the problem.

    So you unwrap the optional

    woot.doThing(3, completion: {
    
        if let bar = bar {
            bar.doThing(4, completion:{});
        }
    
    });
    

    And it now compiles.

    And to the other issue

    If you check the STTwitterAPI.h header

    - (NSObject<STTwitterRequestProtocol> *)getUserTimelineWithScreenName:(NSString *)screenName
                                                             successBlock:(void(^)(NSArray *statuses))successBlock
                                                               errorBlock:(void(^)(NSError *error))errorBlock;
    

    is just a convenience for the full signature of this.

    - (NSObject<STTwitterRequestProtocol> *)getUserTimelineWithScreenName:(NSString *)screenName
                                                                  sinceID:(NSString *)sinceID
                                                                    maxID:(NSString *)maxID
                                                                    count:(NSUInteger)count
                                                             successBlock:(void(^)(NSArray *statuses))successBlock
                                                               errorBlock:(void(^)(NSError *error))errorBlock;
    

    Obj-C to Swift bridging places everything after the the first selector chunk inside the brackets so convenience methods tend to confuse things by code completing but not providing the canonical case.

    So in your case (without me having STTwitter) this is what you want.

    twitterAPI?.verifyCredentialsWithUserSuccessBlock({ (userName, password) -> Void in
    
        if let twitterAPI = self.twitterAPI {
           twitterAPI.getUserTimelineWithScreenName("JohnSmith",sinceID:someID,maxID:anotherID,count:1000, successBlock: { (objects)[AnyObject]!) -> Void in
    
            }, errorBlock: { (error: NSError!) -> Void in
    
           })
       }
    
    
        }, errorBlock: { (error :NSError!) -> Void in
    
    
    })
    

    how you choose to populate sinceID , maxID and count is up to you . I've never used the API so won't guess. They might be nil'able

    0 讨论(0)
  • 2021-01-08 01:15

    Try:

            twitterAPI?.verifyCredentialsWithUserSuccessBlock({ (userName, password) -> Void in
                self.twitterAPI?.getUserTimelineWithScreenName(userName, successBlock: { (objects :[AnyObject]!) -> Void in
    
                    }, errorBlock: { (error :NSError!) -> Void in
                })
    
                return  // <-- ADDED
    
                }, errorBlock: { (error :NSError!) -> Void in
            })
    

    In this case

    { (userName, password) -> Void in
        self.twitterAPI?.getUserTimelineWithScreenName("", successBlock: { (objects :[AnyObject]!) -> Void in
        }, errorBlock: { (error: NSError!) -> Void in
        })
    }
    

    is a "single expression closure" that has implicit non Void return.

    As of Xcode 6.2 / Swift 1.1, you need explicit return here.

    Or, use Xcode 6.3 / Swift 1.2 that has fixed this problem.

    See this question: One-line closure without return type or Swift - 'Bool' is not a subtype of 'Void'?

    0 讨论(0)
  • 2021-01-08 01:19

    Swift 4

    Here is the simple example. But better to make an implementation through monad.

    ...
    guard let api = twitterAPI else { return }
    
    api.verifyCredentialsWithUserSuccessBlock({ userName, password in
        api.getUserTimelineWithScreenName(
            userName, 
            count: 100, 
            successBlock: { value in
                // success
            }) { error in 
                print("get user error: \(error)") 
            }
    }) { error in 
        print("verify error: \(error)") 
    }
    
    0 讨论(0)
  • 2021-01-08 01:20

    Ok, by the method names you are using, I'm guessing you are using the STTwitter library. If that's the case, you'll want something like this:

        if let twitterAPI = self.twitterAPI {
            twitterAPI.verifyCredentialsWithSuccessBlock({ (String) -> Void in
                twitterAPI.getUserTimelineWithScreenName("test", successBlock: { (objects: [AnyObject]!) -> Void in
                    println("success")
                    }, errorBlock: { (error: NSError!) -> Void in
                        println("failure")
                })
                }, errorBlock: { (error: NSError!) -> Void in
    
            })
        }
    

    Note the let call before using the optional self.twitterAPI variable.

    0 讨论(0)
提交回复
热议问题