在闭包中调用 Swift 闭包

17

我有以下代码:

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


            twitterAPI?.getUserTimelineWithScreenName(userName, count: 100, successBlock: { ([AnyObject]!) -> Void in



                }, errorBlock: { (error :NSError!) -> Void in

            })



            }, errorBlock: { (error :NSError!) -> Void in

                println("error block")
        })

我遇到了以下错误:

enter image description here

我尝试在外部闭包中使用self,但它没有起作用。我错过了什么吗?

更新:仍然有构建错误:

enter image description here

更新:如果我将getUserTimeline方法放在闭包之外,则它可以工作。这个可以工作。

//        twitterAPI?.getUserTimelineWithScreenName("", successBlock: { (objects :[AnyObject]!) -> Void in
//            
//            }, errorBlock: { (error: NSError!) -> Void in
//        
//        })
但是这个不行:
twitterAPI?.verifyCredentialsWithUserSuccessBlock({ (userName, password) -> Void in


    self.twitterAPI?.getUserTimelineWithScreenName("", successBlock: { (objects :[AnyObject]!) -> Void in

        }, errorBlock: { (error: NSError!) -> Void in

    })



    }, errorBlock: { (error :NSError!) -> Void in


})

更新:getUserTimeLine方法的定义

self.twitterAPI?.getUserTimelineWithScreenName(<#screenName: String!#>, successBlock: <#(([AnyObject]!) -> Void)!##([AnyObject]!) -> Void#>, errorBlock: <#((NSError!) -> Void)!##(NSError!) -> Void#>)

图片描述

更新:现在,我收到一个构建错误,提示缺少参数sinceID。但我甚至没有使用那个构造函数。

 if let twitterAPI = self.twitterAPI {

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

                twitterAPI.getUserTimelineWithScreenName(userName, successBlock: { (objects :[AnyObject]!) -> Void in

                    }, errorBlock: { (error :NSError!) -> Void in

                })


                }, errorBlock: { (error :NSError!) -> Void in

            })

        }

使用 self.twitterAPI?.getUserTimeline....... - danielbeard
我仍然有问题!请检查更新的截图。 - john doe
问题仅出现在闭包内部,当使用self引用时。如果我将getUserTime..方法放在父闭包之外,则可以正常工作。 - john doe
你能否更新问题,展示一下getUserTimelineWithScreenName函数的定义?错误提示表明你正在向该函数传递错误类型或数量的参数。 - danielbeard
刚刚更新了问题,附带了定义和截图。 - john doe
显示剩余3条评论
4个回答

4

尝试:

        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
        })

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

这是一个“单表达式闭包”,其隐式非 Void 返回。

从Xcode 6.2 / Swift 1.1 开始,您需要在此处明确使用 return

或者,使用已解决此问题的 Xcode 6.3 / Swift 1.2。

参见此问题:One-line closure without return typeSwift - 'Bool' is not a subtype of 'Void'?


1

好的,根据你使用的方法名称,我猜测你正在使用STTwitter库。如果是这种情况,你需要像这样做:

    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

        })
    }

注意在使用可选变量 self.twitterAPI 之前调用 let 方法。

谢谢!我已经按照你的方式更新了代码,但现在出现了与sinceID相关的错误。但是我甚至没有使用那个构造函数。我已经在原始问题中更新了代码。 - john doe
是的,我正在使用STTwitter库。我复制粘贴了您的代码,但出现了以下错误:“调用中缺少参数sinceID”。 - john doe

1

Swift 4

这是一个简单的示例。 但最好通过单子来实现。

...
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

这是一个非常误导性的错误信息。问题在于内部变量不能是可选类型,因此您需要使用if/let 语句。

在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:{});

});

代码无法编译,错误信息为:

无法将表达式类型“(IntegerLiteralConvertible, completion:()->()-$T3)”转换为类型“()”

对问题来说并没有太大帮助。

因此,您需要对可选内容进行解包处理。

woot.doThing(3, completion: {

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

});

现在它可以编译了。

至于另一个问题

如果您检查STTwitterAPI.h头文件

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

这只是对完整签名的一种方便。

- (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 到 Swift 的桥接将第一个选择器块后面的所有内容放在括号内,因此方便方法往往会通过代码完成而混淆事情,但不提供规范案例。

所以在您的情况下(没有我有 STTwitter),这就是您想要的。

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


})

如何选择填充sinceIDmaxIDcount取决于您。我从未使用过该API,所以不会猜测。它们可能是可空的。


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