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}
Related
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.
I'm doing a Swift 4 tutorial challenge. I'm using structs, classes, arrays and functions. I have created the struct correctly as well as the class, however within my function I am supposed to append a contact to my contacts array. Below is the code for a better understanding.
This is my code, It works well in adding the name and phonenumber I can see it in the playground. I have trouble appending the createContact to an array and actually printing the array with the contacts. I know I have to return contact and that works but when I try return the appending to the array I receive an array because of what the method should return. Basically I'm in need of help with appending my contact to the contacts array and being able to print it out.
Thank you for the help. I hope my explanation is clear.
struct Contact {
var name:String
let phoneNumber:String
init(name:String, phoneNumber:String) {
self.name = name
self.phoneNumber = phoneNumber
}
}
class ContactsManager {
var contacts: [Contact] = []
init(contacts: [Contact] = []) {
self.contacts = contacts
}
func createContact(name: String, phoneNumber : String) -> Contact {
Contact.init(name: name, phoneNumber: phoneNumber)
contacts.append(Contact.init(name: name, phoneNumber: phoneNumber))
return Contact(name: name, phoneNumber: phoneNumber)
}
}
ContactsManager.init().createContact(name: "Daniel", phoneNumber: "011232342")
ContactsManager.init().contacts
Every time you do anything, you're creating a separate instance of the class/struct. Generally, for one conceptual 'object' you should have one instance, which means you should only call init once:
struct Contact {
var name:String
let phoneNumber:String
init(name:String, phoneNumber:String) {
self.name = name
self.phoneNumber = phoneNumber
}
}
class ContactsManager {
var contacts: [Contact] = []
init(contacts: [Contact] = []) {
self.contacts = contacts
}
func createContact(name: String, phoneNumber : String) -> Contact {
let contact = Contact(name: name, phoneNumber: phoneNumber)
contacts.append(contact)
return contact
}
}
let manager = ContactsManager()
manager.createContact(name: "Daniel", phoneNumber: "011232342")
manager.contacts
Just a note that ContactsManager() is equivalent to ContactsManager.init(), so I used the shorter version.
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
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.
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!