I'm new in Swift and I would like if someone could tell me how can I translate the following code fragment written in Objective-C to Swift.
Code:
id< JavaUtilConcurrentConcurrentNavigableMap > mapVu = mmcache->kvmap_;
The corresponding header:
#interface MemCache : NSObject {
JavaUtilConcurrentConcurrentLinkedDeque *kvqueue_;
}
A bit of confusion later: You cannot access the instance variables of an Objective-C class from within Swift in a regular / proper manner. Take a look at the answer by Leo Natan for how to work around that.
The previous answer below basically focused on the protocol rather than the instance variables
In swift you can just have the protocol as the type:
let mapVu:JavaUtilConcurrentConcurrentNavigableMap = mmcache.kvmap_
See a working example:
protocol JavautilBlaBla {
}
class Class1: JavautilBlaBla {
override init() {
}
}
class Class2 {
var kvmap_:Class1
override init() {
kvmap_ = Class1()
}
}
let mmcache = Class2()
let mapVu:JavautilBlaBla = mmcache.kvmap_
The only current way to access an instance variable is to use valueForKey().
So,
let mapVu = mmcache.valueForKey("kvmap_") as! JavaUtilConcurrentConcurrentNavigableMap!
Related
So I have a protocol setup in swift, and I'd like to add additional information in the methods (like comments) to the classes that use it
Currently its created using
protocol ImportProtocol {
var moc : NSManagedObjectContext { get set }
init(viewContext: NSManagedObjectContext)
// Various methods which aren't an issue
func importDIM()
}
extension ImportProtocol {
// Default implementation of the various methods above
// No implementation of init or importDIM methods
}
Is it possible to make it to that when it adds the importDIM methods it provides some content on the method to begin with? Currently the method is blank but I'd like to make it add with
func importDIM() {
let dim = addDIM()
// Stage 1
}
If you want to achieve this, you have to define a protocol with your methods, and an protocol extension where you can set computed vars and methods with code.
Example :
protocol ImportProtocol {
}
extension ImportProtocol {
func importDIM() {
let dim = addDIM()
// Stage 1
}
}
And then your classes that implements the protocol have also the base methods with code.
Some more documentation about that with more example :
https://cocoacasts.com/how-to-create-an-abstract-class-in-swift
It would be nice to be able to use something similar to "self" as an alias to access the enclosing Struct or Class's static variables. Does swift have an alias to do this?
For example:
struct MyStruct {
static let variable = "Hello"
func accessVariable() {
MyStruct.variable // This works
self.variable // I'd like to be able to do this.
}
}
Or class:
class MyClass {
static let variable = "Hello"
func accessVariable() {
MyClass.variable // This works
self.variable // I'd like to be able to do this.
class.variable // Or this would be nice too!
}
}
There are three ways:
MyStruct.variable
type(of:self).variable
Self.variable
The Self keyword is a relatively recent Swift innovation, and is probably your preferred choice here. The advantage of type(of:) and Self over just saying the name is that they are polymorphic.
I want to write a function that takes a string and then prints the value of the class property with that name. In practice, there would be more than one property to choose form. For example...
class Apple{
var juiciness : Int = 0
init(juiciness: Int){
self.juiciness = juiciness
}
}
var myApple(juiciness : 10)
func printValue(property : String){
print(Apple.property) // <-- I want to use the string to choose a property
}
Obviously, I can't do this code but I know there has to be a better solution than just I series of if statements.
Apple has done this for you. It is known as key-value observing(KVO).
Try the following code in the playground:
let label = UILabel()
print(label.value(forKey: "font"))
Your own class can support KVO by inheriting from NSObject:
class YourClass: NSObject{ ... }
As I understand reflection in Swift is poorly available as of yet. I am currently in the process of converting objective-c code to swift for the sake of performance (I have noticed a considerable difference).
Now what I need is a way to call a Method using reflection. The object the method needs to be called upon extends NSObject to enable the class to be resolved using the following code;
let clazz = NSClassFromString("MyProject.DynamicClass") as NSObject.Type;
let clazzInstance = clazz() as! NSObject;
I am able to retrieve a the number of argument and a reference to the method using the following code;
let selectorMethod = Selector("myCustomMethod:");
let numberOfArguments : UInt32 = method_getNumberOfArguments(selectorMethod);
let referenceToMethod : Method = class_getInstanceMethod(clazz, selector!);
But how do I use/call the referenceToMethod?
Additional
I have also tried calling performSelector but this has been completely removed Swift 2. I also would like to prevent the use of any #objc attributes/annotations.
If you are looking for a completely Swifty way of reflection, the object that has the method that needs to be called does not need to be a NSObject at all, instead all it need is a required initializer. Have a look at below example :
class A {
required init() {}
func printSomething(s: String) {
print(s)
}
}
// initializing object dynamically from class
let clazz = NSClassFromString("MyProject.A") as! A.Type
let clazzInstance = clazz()
// getting and calling its methods in Swifty way
let method = clazzInstance.printSomething
method("something")
The advantage of using this stands on fact that you wont need to use casting at all and also calling method with wrong arguments would trigger a compile time error
A crazy idea, and not perfect:
you can define a var as:
var myFunctionToBe : (() -> AnyObject)?
or even set AnyObject as parameter,
and then in the initiator:
init() {
myFunctionToBe = {
//do something
return whatsdone
}
}
then in reflection you can see the var myFunctionToBe, get it as:
let method = c.value as? (() -> AnyObject)
and invoke it:
method!()
or
let returnVal = method!() as? String
I am trying to use NSXPCConnection in swift.
So, this line:
_connectionToService = [[NSXPCConnection alloc] initWithServiceName:#"SampleXPC"];
can be replaced by this line:
_connectionToService = NSXPCConnection(serviceName: "SampleXPC")
And, this line:
_connectionToService.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:#protocol(StringModifing)];
can be replaced by this line:
_connectionToService.remoteObjectInterface = NSXPCInterface(protocol: <#Protocol#>)
Now I am confused about using the correct replacement for: <#Protocol#> in swift, in objective c I would have used: #protocol(StringModifing), but in swift I am clueless :(
That's a tricky one.
First of all protocol is a reserved keyword and cannot be used as parameter label. A quick look into Apples official doc helped me here. use `protocol`` instead. That means the parameter name contains single quotes.
"[obj class]" is being replaced by "obj.self" in swift. The same syntax is used for protocols. That means in your case "#protocol(StringModifing)" becomes "StringModifing.self".
Unfortunately this still will not work. The problem now is behind the scenes. The xpc mechanism is some kind of low-level stuff and wants ObjC style protocols. That means that you need the keyword #objc in front of your protocol declaration.
All together the solution is:
#objc protocol StringModifing {
func yourProtocolFunction()
}
#objc protocol StringModifingResponse {
func yourProtocolFunctionWhichIsBeingCalledHere()
}
#objc class YourXPCClass: NSObject, StringModifingResponse, NSXPCListenerDelegate {
var xpcConnection:NSXPCConnection!
private func initXpcComponent() {
// Create a connection to our fetch-service and ask it to download for us.
let fetchServiceConnection = NSXPCConnection(serviceName: "com.company.product.xpcservicename")
// The fetch-service will implement the 'remote' protocol.
fetchServiceConnection.remoteObjectInterface = NSXPCInterface(`protocol`: StringModifing.self)
// This object will implement the 'StringModifingResponse' protocol, so the Fetcher can report progress back and we can display it to the user.
fetchServiceConnection.exportedInterface = NSXPCInterface(`protocol`: StringModifingResponse.self)
fetchServiceConnection.exportedObject = self
self.xpcConnection = fetchServiceConnection
fetchServiceConnection.resume()
// and now start the service by calling the first function
fetchServiceConnection.remoteObjectProxy.yourProtocolFunction()
}
func yourProtocolFunctionWhichIsBeingCalledHere() {
// This function is being called remotely
}
}
Swift 4
_connectionToService.remoteObjectInterface = NSXPCInterface(with: StringModifing.self)