NSCopying copy (with :) - do you really need to return Any?
Can NSCopying be used without a return type object Any
? It always makes me quit. It seems strange. I'm copying an object, shouldn't Swift know it's the same type by the definition of copy ?
Is there another way to copy objects that I am not aware of, or are there some "received" ones that I am missing for what it is required for.
The class is very simple, for example:
class Person {
var name: String
var age: Int
}
It must be a class because I need to have inheritance.
Example:
var john = Person(name: "John", age: 30)
var johnsClone = john.copy() as! Person
I guess I can create an initializer that takes an existing object, but that seems semantically less good than the word "copy".
init(person: Person) {
return Person(name: person.name. age: person.age)
}
The only problem with implementing my own method clone()
is that I would also like to have a protocol that can call clone()
on many of these objects and implicitly return the same object type.
source to share
This is the Objective-C API for the NSObject method copy
:
- (id)copy;
This translates into Swift as:
func copy() -> Any
Thus, the type information is not tied to the new object; why should you quit.
Now, if you don't like that, there is an easy solution for your situation: don't use NSCopying and don't use the built-in NSObject method copy
! Write your own one-off method that clones a human - eg. an instance method called makeClone()
. NSObject copy
is a convenience, but no law requires you to use it (unless there is some other reason why Person should conform to NSCopying, for example it should be used as a key to an NSDictionary, but I'm sure you never face such a reason).
source to share
copy(with:)
- is imported Swift version Objective C method -copyWithZone
. At the time this protocol was established, Objective C had no mechanism for expressing that it copyWithZone
should return the same type as the callee self
. instancetype
was introduced to be able to do just that, but NSCopying
predates existence instancetype
. Switching it from id
to instancetype
would be a change, so it was never done.
source to share
Based on the information above and this post Function func returns Self , this is a way to do it without using NSCopying
.
As the user copy()
returns the object type and NSCopying
copy()
returns Any
, they have a different method signatures, so you can use your own copy()
without ambiguity.
protocol Copyable {
init(copy: Self)
}
extension Copyable {
func copy() -> Self {
return Self.init(copy: self)
}
}
class Person: Copyable{
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
required init(copy: Person) {
self.name = copy.name
self.age = copy.age
}
}
let john = Person(name: "John", age: 30)
let johnsClone = john.copy()
source to share