Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you copy objects in Swift?

Tags:

copy

swift

I have the following class:

class Client {
  let name: String
  let age: Int

  init(name: String, age: Int) {
    self.name = name
    self.age = age
  }
}

let wrongClient = Client(name: "John", age: 9)

How can I create a new version of wrongClient with the right age?

I want something like the following:

let rightClient = Client(wrongClient, age: 42)

For example OCaml lets developers do the following:

type client = {
  name : string;
  age : int;
}

let wrong_client = {name = "John"; age = 25}
let right_client = {wrong_client with age = 42}

Or in Scala:

case class Client(name: String, age: Int)

val wrongClient = Client(name: "John", age: 9)
val rightClient = wrongClient.copy(age=42)

EDIT

I want to experiment with data immutability and data sharing with Swift.

Because immutable data imply "generating" values from other values, "copying" objects can happen often. So my question really is : how can I easily construct new objects from other objects with Swift?

EDIT 2

I'm currently looking at Swiftz' lenses.

like image 477
Antoine Avatar asked Jan 27 '15 15:01

Antoine


People also ask

Can you copy an object?

There are several ways to copy an object, most commonly by a copy constructor or cloning. Copying is done mostly so the copy can be modified or moved, or the current value preserved. If either of these is unneeded, a reference to the original data is sufficient and more efficient, as no copying occurs.

How do I make a deep copy in Swift?

We can create a deep copy of the reference type using the copy() method. According to the documentation, copy() — Returns the object returned by copy(with:) . This is a convenience method for classes that adopt the NSCopying protocol.

How do I copy a view in Swift?

You can make an UIView extension. In example snippet below, function copyView returns an AnyObject so you could copy any subclass of an UIView, ie UIImageView. If you want to copy only UIView you can change the return type to UIView.


3 Answers

You can implement Client as a struct instead of a class since struct is always passed by value.

struct Client {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

var wrongClient = Client(name: "John", age: 18)
var rightClient = wrongClient
rightClient.age = 99

Assigning wrongClient to rightClient creates a copy. When you update the age of rightClient, wrongClient still remains 18.

like image 177
fyell Avatar answered Sep 28 '22 18:09

fyell


There isn't any defined short-hand for it. I'd recommend something like:

class Client {
    let name: String
    let age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    private init(from: Client, age:Int) {
        self.name = from.name
        self.age = age
    }

    func withAge(age:Int) -> Client {
        return Client(from: self, age: age)
    }
}

let right_client = Client(name: "John", age: 9)
let wrong_client = right_client.withAge(42)
like image 31
David Berry Avatar answered Sep 28 '22 17:09

David Berry


You could add another init method.

   required init(name: String, age: Int) {
       self.name = name
       self.age = age
   }

   convenience init(from: Client, withAge: Int) {
       self.init(name: from.name, age: withAge)
   }
like image 23
fred02138 Avatar answered Sep 28 '22 17:09

fred02138