How to convert Objective-C block to Swift closure - swift

I have a method that contains an block which defined in Objective - C:
+(void)getNewList:(NewListRequestModel *)model returnInfo:(void(^)(NewListResponseModel* resModel))retModel;
and I invoke it like:
[API getNewList:model returnInfo:^(NewListResponseModel *resModel) {
//code
}];
in Objective - C .
Now I want invoke it in Swift 3.2 :
API.getNewList(model, returnInfo: {(resModel: NewListResponseModel) -> () in
//my code
})
but I always got an error:
Cannot convert value of type '(NewListResponseModel) -> Void' to expected argument type '((NewListResponseModel?) -> Void)!'
can some one help me the right way to invoke it? thanks.

In Swift, closures can be very easily written. The compiler infers the parameter types and return type for you, so all you need to do is write the parameter name and in:
API.getNewList(model, returnInfo: {resModel in
//my code
})
You can also use the trailing closure syntax:
API.getNewList(model) {resModel in
//my code
}
The error occurs because resModel actually is of an optional type. iN the original Objective-C code, resModel was a pointer, which can be null. When this is bridged to swift, it turns into NewListResponseModel?.

Try this:
class func getNewList(model: NewListResponseModel
returnInfo: ((_ resModel: NewListResponseModel?) -> Void)?){
}
API.getNewList(model, returnInfo: {(resModel) in
//my code
})

//MARK: Class function to pass requestModel and get response model
class func getNewList(model: NewListRequesstModel, completion: #escaping (returnModel: NewListResponseModel) -> Void) {
//Your code to get new model for retrun
}
API.getNewList(model: newModelObject, completion: { (retunModelobject) in
//your code
})

Related

How to assign parameter's type of generic callback in swift?

Suppose I have following function:
func fetch<T: Codable>(completion: #escaping (_ response: SimpleResult<[T]>) -> Void) {
completion(parse(result))
}
Xcode does not show any error on above function. But how to use it? If I write following, it shows error:
fetch { result in
}
It says that "Generic parameter T could not be inferred". I suppose that I should indicate type here. But where should I write it?
You need to explicitly state the result type:
fetch { (result: SimpleResult<YOUR_CODABLE_TYPE>) in
}

Closure not called inside object

I am trying to run this simple example using a closure for learning purpose, but doesn't seem to work as I expected:
class Test {
var callback: ((_ value: Int) -> Void)?
func perform() {
callback
}
}
let t = Test()
t.callback = { _ in
print("Test")
}
t.perform()
I was expected that "Test" will get printed, but apparently it's not. Can someone point what the issue is ?
Compiling the code reveals the error:
error: expression resolves to an unused l-value
callback
^~~~~~~~
callback is just the (optional) closure, not a call to the closure.
Apparently the Playground does not complain about the unused expression.
Calling the closure with some argument fixes the problem:
func perform() {
callback?(5)
}

Call a function which expects arguments with SKAction.runBlock()

I'm working with Swift and SpriteKit
I'd like to use SKAction.runBlock() to run a function that expect arguments :
class Tile : SKShapeNode
{
}
override func didMoveToView()
{
let tile = Tile()
tile.runAction(SKAction.runBlock(myFunc(tile)))
}
func myFunc(tile: Tile)
{
}
When I try to create a function that doesn't expect any argument, everything works fine, but the code above returns this:
Cannot convert value of type '()' to expected argument type
'dispatch_block_t' (aka '#convention(block) () -> ()')
What am I not understanding ?
With writing this sort of expression:
SKAction.runBlock(myFunc(tile))
You are passing the result of calling myFunc(tile).
(I believe you do not think this code: SKAction.runBlock(sin(0)), would pass some sort of closure to runBlock.)
And the returned value from myFunc(tile) is a void value, as myFunc is declared to return nothing. A void value can be represented also as (). The error message says () cannot be converted to a closure of type #convention(block) () -> ().
Thus, you need to create a closure of type #convention(block) () -> ().
tile.runAction(SKAction.runBlock({()->() in myFunc(tile)}))
in short:
tile.runAction(SKAction.runBlock({myFunc(tile)}))
You are missing {} Just:
tile.runAction(SKAction.runBlock({
myFunc(tile)}))

Completion Handlers in Swift

I'm fairly new at swift development and trying to get a handle on closures and completion handlers. I have a function with the following declaration inside a struct called ObjectData
func getData(id1:Int, id2:Int, completion: (dataObject? -> Void))
I am trying to call this function like
ObjectData.getData(1, id2: 2){
(let myObject) in
}
but i get the following error
Cannot invoke 'getData' with an argument list of type '(NSNumber, id2:
NSNumber, (_) -> _)'
Please can someone help
For better readability, change the header to this. Remember that you have to declare types, not variable names:
func getData(id1:Int, id2:Int, completion: (ObjectData?) -> (Void))
Now I personally use this syntax to use closures:
self.getData(1, id2: 1) { (data) -> (Void) in
// Some code executed in closure
}
If you want to study further, you can find full syntax of closures here (notice appropriate name of the website).
Hope it helps!
Far away from my Mac now, so I can't test, but try this:
ObjectData.getData(1, id2: 2, (dataObject) -> {
...code...
});
Also can't check now, but I think this also should work:
ObjectData.getData(1, id2: 2)(dataObject){
...code...
}
try to initialize your class first (ex. var objectData = ObjectData()) , and then call function with objectData.getData... it should work that way ..
In SWIFT 3,It is known as completion closure.
func getData(id1:Int, id2:Int, completion:#escaping(dataObject?) -> (Void)) {
//Do the stuff before calling completion closure
completion(value as? dataObject)
}
ObjectData.getData(id1:1, id2: 2,completion:{(data) -> (Void) in
//Do the completion stuff here
}

How do I declare a function that takes *any* block/closure as parameter?

I want to pass any block around as a parameter, without wanting to know the precise block parameter/return type.
func myFunc(block:(xxx) -> yyy) -> AnyObject {
...
}
So xxx in my code should match any number of parameters (including none) of any type. And yyy could be anything from void to AnyObject to an NSObject.
You can make a generic function:
func myFunc<A,B>(block:A -> B) -> AnyObject {
...
}
Unfortunately, you can't do that in Swift. Function Types are defined by their parameters and return types and there is no general function type. Functions also don't conform to Any or AnyObject, so you also can't use those either.
In Swift it's still possible to use the Selector. Maybe you can achieve what you want using that. See sample below:
func myFunc(selector:Selector) -> AnyObject {
self.performSelector(selector)
}
func someSelector() -> String {
return "test"
}
var result: AnyObject = myFunc(Selector("someSelector"))