Reputation: 9690
I have the following code:
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")
})
I am getting the following errors:
I tried saying self inside the outer closure but it did not work. What am I missing?
UPDATED: Still having build errors:
UPDATE: If I put the getUserTimeline method outside the closure then it works. THIS ONE WORKS.
// twitterAPI?.getUserTimelineWithScreenName("", successBlock: { (objects :[AnyObject]!) -> Void in
//
// }, errorBlock: { (error: NSError!) -> Void in
//
// })
But this DOES NOT:
twitterAPI?.verifyCredentialsWithUserSuccessBlock({ (userName, password) -> Void in
self.twitterAPI?.getUserTimelineWithScreenName("", successBlock: { (objects :[AnyObject]!) -> Void in
}, errorBlock: { (error: NSError!) -> Void in
})
}, errorBlock: { (error :NSError!) -> Void in
})
UPDATE: Definition of getUserTimeLine method
self.twitterAPI?.getUserTimelineWithScreenName(<#screenName: String!#>, successBlock: <#(([AnyObject]!) -> Void)!##([AnyObject]!) -> Void#>, errorBlock: <#((NSError!) -> Void)!##(NSError!) -> Void#>)
UPDATE: Now, I am getting a build error saying missing argument sinceID. I am not even using that constructor.
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
})
}
Upvotes: 18
Views: 6769
Reputation: 12697
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)")
}
Upvotes: 1
Reputation: 17378
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
Upvotes: 0
Reputation: 51911
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'?
Upvotes: 4
Reputation: 9149
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.
Upvotes: 1