Make a copy of object with same address in swift - arrays

var empObj : EmployeeModel!
var tempObj : EmployeeModel!
tempObj = empObj.copy() as! EmployeeModel
whenevr I am copy the empObj to tempObj it's memory address is changed.I want to prevent this any idea?

when you copy its actually making a new reference. instead of copying just assign the value . then both will share the same reference
var empObj : EmployeeModel!
var tempObj = empObj

When you want the same address for different values
USE =
for eg.
var ogArray : NSMutableArray()
var tempArray = ogArray

If you are using objects two variables can point at the same object so that changing one changes them both, whereas if you tried that with structs you'd find that Swift creates a full copy so that changing the copy does not affect the original.
If you want to modify copies of a class object so that modifying one object doesn't have an effect on anything else, you can use NSCopying.
Make your class conform to NSCopying. This isn't strictly required
Implement the method copy(with:), where the actual copying happens.
Call copy() on your object.
Example Code for NSCopying
class Person: NSObject, NSCopying {
var firstName: String
var lastName: String
var age: Int
init(firstName: String, lastName: String, age: Int) {
self.firstName = firstName
self.lastName = lastName
self.age = age
}
func copy(with zone: NSZone? = nil) -> Any {
let copy = Person(firstName: firstName, lastName: lastName, age: age)
return copy
}
}
Check the output of this code in Playground
let paul = Person(firstName: "Paul", lastName: "Hudson", age: 36)
let sophie = paul.copy() as! Person
sophie.firstName = "Sophie"
sophie.age = 6
print("\(paul.firstName) \(paul.lastName) is \(paul.age)")
print("\(sophie.firstName) \(sophie.lastName) is \(sophie.age)")
Reference

Related

How do i add objects into an array from a Class in Swift?

This is my Friend class:
class Friend {
var firstName: String = ""
var lastName: String = ""
var age: Int = 0
var description:String = ""
init(firstname: String, lastname: String, age: Int) {
self.firstName = firstname
self.lastName = lastname
self.age = age
}
}
This is where i'm supposed to declare and instantiate 5 Friend objects in the viewDidLoad function and to add them into 'friendList' array.
import UIKit
class ViewController: UIViewController {
var friendsList: [Friend] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
friendsList.append("John", "Doe", 20)
}
}
Swift tells me that "No exact matches in call to instance method 'append'" on the "friendsList.append" line.
you can use like Below if you are creating all friends Initially
let friends = [Friend(firstname: "John", lastname: "Doe", age: 20),Friend(firstname: "doe", lastname: "John", age: 21)]
for friend in friends{
friendsList.append(friend)
}
//////////////////////////////////////
(or) you can directly declare value for your global variable
friendsList = [Friend(firstname: "John", lastname: "Doe", age: 20),Friend(firstname: "doe", lastname: "John", age: 21)]
///////////////////////////////////////////
(or) assign local variable value to your global variable
friendsList = friends
or if you adding One by One,You have to create object first
let friendOne = Friend(firstname: "John", lastname: "Doe", age: 20)
friendsList.append(friendOne)
The Array (Actually collection) function append takes a parameter of type <T> where T is a generic type, "the type of the elements in the array".
So if you have an array of Strings, you need to pass a String into append:
var strings = [String]()
strings.append("a string")
Since you have an array of Friend objects, you need to pass an instance of Friend to the append(_:) function. Does the expression inside the parentheses in your call to append evaluate to a friend object?
friendsList.append("John", "Doe", 20)
It doesn't. You'r passing a comma-separated list of properties. Presumably, those are the first name, last name, and age of a Friend, but the append() function doesn't know that.
You could write it as:
let aFriend = Friend(firstname: "John", lastname: "Doe", age: 20)
friendList.append(aFriend)
Or all in one line with:
friendList.append(Friend(firstname: "John", lastname: "Doe", age: 20))
Both of those variations would work.

Newbie: referencing and initializing structure elements within structures

OK, super-newbie Swift learner here with what I am sure is a simple question, that for some reason I cannot wrap my head around.
In the below code, I am creating a (very) simple address book structure just to understand how to reference and initialize the various elements, especially structures within structures. What am I doing wrong and is there a better way to write this? I am getting errors (using Swift Playground).
Errors on the last three lines:
Instance member 'page' cannot be used on the type 'AddressBookStruct'
Instance member 'subscript' cannot be used on type '[AddressPageStruct]'.
Plus, when I set var page = [AddressBookStrcut] I get the error:
Expected member name or constructor call after type name
Thanks in advance for the understanding nudge. :)
struct AddressPageStruct {
let firstName: String
let lastName: String
let cellPhone: Int
init(f: String, l:String, c:Int) {
firstName = f
lastName = l
cellPhone = c
}
}
struct AddressBookStruct {
let color: String
let size: String
var page = [AddressPageStruct]
}
var littleBlackBook = AddressBookStruct.self
littleBlackBook.init(color: "Black", size: "Little")
littleBlackBook.page[0].cellPhone = 6191234567
littleBlackBook.page[0].firstName = "Bob"
littleBlackBook.page[0].lastName = "Smith"
The struct is value type, please check this.
structure vs class in swift language,
you can't make this littleBlackBook.page[0].cellPhone, because cellPhone is constant you use let, instead use the constructor, also I change the page for empty array of AddressPageStruct
import Cocoa
struct AddressPageStruct {
let firstName: String
let lastName: String
let cellPhone: Int
init(f: String, l:String, c:Int) {
firstName = f
lastName = l
cellPhone = c
}
}
struct AddressBookStruct {
let color: String
let size: String
var page = [AddressPageStruct]()
}
var littleBlackBook = AddressBookStruct(color: "Black", size: "Little")
littleBlackBook.page.append(AddressPageStruct(f: "Bob", l: "Smith", c: 6191234567))
print(littleBlackBook.page)
enter code here
var littleBlackBook = AddressBookStruct(color: "Black", size: "Little")
let item = AddressPageStruct(f: "Bob", l: "Smith", c:6191234567 )
littleBlackBook.page.append(item)
littleBlackBook.page.append(AddressPageStruct(f: "Joe", l: "Blog", c: 3123467))
print(littleBlackBook.page[0])
print(littleBlackBook.page[1])
print(littleBlackBook)

Create a new String Array from class array

I have a class called Person:
class Person {
var firstName: String?
var lastName: String?
let birthPlace = "Belgium"
}
let person = [Person]()
Now the problem is I want to get all first names into a String array ([String]), how can I do it?
you can use flatMap for that:
let firstName = person.flatMap{ return $0.firstName }
First of all, you should rewrite your Person class. firstName and lastName shouldn't be optional, since everyone has both a first and a last name and unless your app will specifically be made for people who were born in Belgium, hardcoding that as the birthPlace is also a bad idea.
Take the time and write an initializer for the class.
class Person {
var firstName: String
var lastName: String
let birthPlace: String
init(firstName: String, lastName: String, birthPlace: String){
self.firstName = firstName
self.lastName = lastName
self.birthPlace = birthPlace
}
}
You can use map to get an array of first names from an array of Person objects.
let people = [Person]()
let firstNames = people.map{$0.firstName}

How to print elements of one class using variable of another class?

I have created two classes a Person class and a food class. Now i am making list of all the food items consumed in a year by a particular person. I want to print all of them separated by commas
Here's my code
class Food {
let name: String
var EatenBy: Person?
init(name: String){
self.name = name
}
}
And my Person class is as follows
class Person {
var name: String
var foods: [Food] = []
lazy var foodNames: () -> String = {
return ""
}
init(name: String){
self.name = name
}
func adopt(food: Food){
foods.append(food)
food.EatenBy = self
}
}
Now i want to create different food items using the Food class and then assign it to a person who have consumed them and store it in an array foods.
var person = Person(name: "Test")
var pasta = Food(name: "pasta")
Can anyone help me out how can i use the objects created using Food class and assign it to a object created in the Person class and append them in the foods array ?
My final aim is to print all the elements in the foods array separating them using commas or spaces or such, which i guess can be easily done by looping each of the element through a for loop ?
Using a Person instance, you can access its properties (including the foods array by the dot syntax: person.foods.
For printing the food names, you should declare foodNames as a computed property. As its return value, just use map to get the names of each Food instance, then use [String].joined(separator: ",") to join the contents of the array of Strings into a single String.
class Person {
var name: String
var foods: [Food] = []
var foodNames:String {
return foods.map{$0.name}.joined(separator: ",")
}
init(name: String){
self.name = name
}
func adopt(food: Food){
foods.append(food)
food.EatenBy = self
}
}
class Food {
let name: String
var EatenBy: Person?
init(name: String){
self.name = name
}
}
let john = Person(name: "John")
let pasta = Food(name: "pasta")
john.foods = [pasta, Food(name: "tuna")] //assign an array to the variable directly
john.foods.append(Food(name: "tomato")) //or append the existing array
john.adopt(food: Food(name: "bread")) //you can also use your _adopt_ function to add an element to the _foods_ array of a _Person_ instance
john.foodNames // "pasta, tuna, tomato,bread"
It looks like you are missing some basic concepts of how Swift works (like using the dot syntax to access class properties), so I would recommend reading The Swift Programming Language Guide as a start, it is a really useful starting point for a beginner Swift developer.

Swift generics subclass behaviour in Array

So I walk against this problem.
I have a BaseModel with some variables inside and a few normal "final" Models that inherit from the BaseModel.
If I have an array with class BaseModel with inside a few final models, and then loop trough those models and sent them to a function that uses generics. And check the class of the generics I get back they are from class BaseModel instead of the final class model that I need. How can I retrieve in a dynamic way the class of the final model. And of course I could cast them, but I would love to find a better solution.
See example in the playground I made:
import UIKit
class BaseModel {
var id: Int
init(id: Int) {
self.id = id
}
}
final class PersonModel: BaseModel {
var firstName: String
var surname: String
init(id: Int, firstName: String, surname:String) {
self.firstName = firstName
self.surname = surname
super.init(id: id)
}
}
func genericsTest<C: BaseModel>(with object: C) {
print("Class type: \(C.self)")
}
var person0 = PersonModel(id: 0, firstName: "John", surname: "Doe")
genericsTest(with: person0)
// This prints: "Class type: PersonModel"
var person1 = PersonModel(id: 1, firstName: "John1", surname: "Doe")
var person2 = PersonModel(id: 2, firstName: "John2", surname: "Doe")
var person3 = PersonModel(id: 3, firstName: "John3", surname: "Doe")
var personArray: [BaseModel] = [person0, person1, person2, person3]
for person in personArray {
print("Class type in for loop: \(person.self)")
// This prints: "Class type in for loop: __lldb_expr_195.PersonModel"
genericsTest(with: person)
// This prints: "Class type: BaseModel"
}
So in the for loop if I print the object.self I get the class I expect but in the function with generics do the same call I get the base class.
Edit 1:
So if it would be possible to make Generic C the type of the final model I would be able to create thing like:
func genericsTest<C: BaseModel>(with type: C.Type, and object: C) {
let test = KeyPath<C, Int>
}
Just as example
Have a look at this
Question
You define a array of type 'BaseModel' so in your for loop it basically is saying
for let person: BaseModel in personArray
Making person of type BaseModel
In the function:
func genericsTest<C: BaseModel>(with object: C) {
print("Class type: \(C.self)")
}
You are using the type, in contrary in this code:
print("Class type in for loop: \(model.self)")
You are using the object. If you change the C to object you will get the same result.
Do remember if you going to use this in you project to determine what type of object this is. You need to seriously go back to your drawing board. Because this is not OOP!

Resources