I have the following code:
twitterAPI?.verifyCredentialsWithUserSuccessBlock({ (userName, password) -> Void in
twitterAPI?.getUserTimelin
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
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'?
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)")
}
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.