eDistantObject supports Swift as Swift is fundamentally interoperable with Objective-C. More details in Apple doc around MixAndMatch. However, pure Swift calls are statically linked, therefore, invocations are not through the Objective-C runtime. There are three different scenarios when working with Swift.
This works naturally when importing Objective-C headers as Swift will invoke those methods already in an Objective-C manner and trigger the runtime to forward invocations. As is usual with Swift, these method definitions must be exposed in a bridging header.
The methods need to be annotated with @objc
so that it can be exported to
Objective-C and is visible. Once the invocation is fired in Objective-C, it will
properly be forwarded to the remote site.
The above two scenarios should work as long as the methods are tagged with @objc.
In the Objective-C case, the compiler needs to see the header in order to know how to run your code. However, there is no header in Swift. The workaround is to define a protocol, to serve as a header, and then expose the object to work with as a protocol.
For example:
// In Swift
@objc
public protocol RemoteInterface {
func remoteFoo() -> Bar
}
@objc
public protocol StubbedClassExtension {
func remoteInterface() -> RemoteInterface
}
class ActualImplementation : RemoteInterface {
func remoteFoo() -> Bar {
// Your actual implementation.
}
}
@objc
extension AlreadyStubbedClass : StubbedClassExtension {
// The client calling this method to require the remote object.
func remoteInterface() -> RemoteInterface {
// return the actual implementation of RemoteInterface
}
}
// In Objective-C
// Define a Objective-C bridge so Swift can extend.
@interface AlreadyStubbedClass
@end
In the code above, AlreadyStubbedClass
is defined in Objective-C and will be
imported as a regular eDistantObject in both Swift files. This will then be used
as an entry point to return the protocol RemoteInterface
. The remote
invocation will be:
RemoteInterface remote = unsafeCast(AlreadyStubbedClass.sharedClass, to:StubbedClassExtension.self).remoteInstance
remote.remoteFoo()
Here the unsafeCast
lets the compiler know the AlreadyStubbedClass
has the
extension. Working example is shown
here.
The block is also supported but it may confuse the compiler and the runtime as the calling convention can be different. Adding @escaping to let both the runtime and the compiler to know how to handle the block scope. For example.