Reputation: 6620
I've found an Objective-C SocketIO library and am trying to implement it in my first Swift app. Here's the code I'm trying to port:
__weak typeof(self) weakSelf = self;
self.socket.onConnect = ^()
{
weakSelf.socketIsConnected = YES;
[weakSelf mapView: weakSelf.mapView didUpdateUserLocation: weakSelf.mapView.userLocation];
};
From my limited understanding ^() {}
is a block in Objective C. I've looked into it and closures seem to be a loose equivalent Swift. My first obvious question is how do I get the same result in Swift?
I've tried the following but get the error fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)
:
self.socket.onConnect = { () -> Void in
println("Connected!")
}
Also, behind the scenes what's happening here? An asynchronous callback function would seem appropriate but wasn't used and I'd like to understand why.
UPDATE
As pointed out by @jtbandes, socket
was in fact Nil as this code was running outside of the connection callback (I know, a very silly mistake). Solution to first question:
SIOSocket.socketWithHost(server) { (socket: SIOSocket!) in
self.socket = socket
self.socket.onConnect = { () -> Void in
println("Connected!")
}
}
Upvotes: 1
Views: 550
Reputation: 131436
Objective-C blocks and Swift closures are more than loose equivalents. They are direct equivalents.
A block/closure is an anonymous function that inherits it's enclosing scope.
I'm still working in Objective-C, so I'm used to its terminology. I'll use those terms
Blocks are useful in lots of ways.
Completion code is one example.
Without blocks, if you're setting up an async networking class, you might give it a delegate property, and define a protocol with callbacks that the class uses to notify it's delegate about events like download complete, errors, etc.
This makes for a lot of message handling infrastructure in lots of different places. You have to define a protocol. You have to add a delegate property to the networking class. You have to implement a set of delegate messages in the client class. You may have to pass context information to the callbacks, etc.
With blocks, you invoke a method that asks for a networking service, and provide a completion block. When the service is complete, it invokes the provided code block. You might add parameters to the completion block like a pointer to the data, a success boolean, or whatever is appropriate. The code block can have access to all the variables defined in its enclosing scope, which can be very helpful.
You can also save blocks into collections, you can use blocks in sort methods, and int lots of other cases.
The code you posted simply sets a block property on the object in question, self.socket. It looks like it is a block of code that gets called after a socket connection is established.
There are direct equivalents to this in Swift. I've only poked around in Swift however, so I'll leave it to others to help you with the translation.
I suggest browsing through Apple's classes for ideas on how to use blocks. Take a look at NSURLConnection and NSURLSession if you're interested in async networking. Take a look at the block-based view animation methods that take an animation block and a completion block. Those will give you an idea of the ways you can use blocks for handling async events, or passing code to a class to get work done.
Another interesting use of blocks is in handling collections like arrays. There are methods that take an NSComparator block and sort an array, and there are methods that will enumerate through an array, performing a block of code on each element and/or selecting a subset of the elements and returning an index set of the array indexes.
Duncan
Upvotes: 2