Nil while appending data - arrays

I have a type struct Course
struct Course {
let title: String
let subtitle: String
let instructor: String
let color: String
init(title: String, subtitle: String, instructor: String, color: String) {
self.title = title
self.subtitle = subtitle
self.instructor = instructor
self.color = color
}
}
This is my code trying to append the data of type struct Course into courses but end up getting nil error. What should I do?
var courses: [Course]!
courses?.append(Course(title: "Team-Based Mobile Device Application Development", subtitle: "2018SP INFOTC 4500/JOURN 4444 Moore & Musser", instructor: "", color: ""))

You need to initialize your array. All you've do so far is declare it.
Change:
var courses: [Course]!
to:
var courses = [Course]()
This will declare and initialize courses as an empty array of Course.
Then:
courses?.append(Course...
becomes:
courses.append(Course...

You need to initialize a variable before it used.
so need to change
var courses: [Course]!
courses?.append(Course(title: ...
to
var courses: [Course] = []
courses.append(Course(title: ...

The best way for this to work is
var courses: [Course]! = []
with append function
courses.append(Course(title: "Team-Based Mobile Device Application Development", subtitle: "2018SP INFOTC 4500/JOURN 4444 Moore & Musser", instructor: "", color: ""))

Related

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)

Sort array of dictionaries where key is unknown

I have an array of dictionaries of type [[String:SchoolModel]]. The keys are the id of the school and then the school model contains info about the school like its name for example. I want to sort this array by SchoolModel.name, but can't figure out how since my key is a unique id for every element in the array.
struct SchoolModel {
var name: String
var city: String
var state: String
}
You can access the first value of each dictionary iterated to get the name.
struct SchoolModel {
var name: String
var city: String
var state: String
}
let schools: [[String:SchoolModel]] = [
["1": SchoolModel(name: "1", city: "a", state: "x")],
["2": SchoolModel(name: "2", city: "b", state: "y")],
["3": SchoolModel(name: "3", city: "c", state: "z")]
]
print(schools.sorted {
guard
let a = $0.values.first?.name,
let b = $1.values.first?.name else { return false }
return a < b
})
However, you should consider adding an id property to your struct. You can make it optional so you can still initiate a SchoolModel that hasn't been created yet.
struct SchoolModel {
var id: String?
var name: String
var city: String
var state: String
}
Then where ever you are populating the array of dictionaries, append the SchoolModel object without embedding it inside a dictionary, resulting in an array of type [SchoolModel].

Array is nil after appending to it

I have 2 Types, first is Car with property feature and it of the second type Feature.
I have a property cars: [Car], when I append new car to it, it returns nil.
I have created a sample in the snippet below:
class Car {
let make: String
var features: Feature?
let id: String
init(make: String, features: Feature?, id: String) {
self.make = make
self.features = features
self.id = id
}
}
class Feature {
let convertible: String
init(convertible: String) {
self.convertible = convertible
}
}
var cars: [Car]?
var feature: Feature?
let featureElement = Feature(convertible: "yes")
feature = featureElement
let car = Car(make: "SomeMaked", features: feature, id: "ID")
cars?.append(car)
print(cars)
My question is: Shouldn't the array increase its count after appening to it? What am I missing?
Please note that this code is just sample, so ignore typos and coding convention.
You haven't initialized your array.
Replace your var cars: [Car]? with var cars: [Car]? = []

how can I check if a structure is in the array of structures based on its field in Swift3?

In my swift app I have a structure:
open class MyStruct : NSObject {
open var coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
open var username: String? = ""
open var id: String? = ""
}
And I create an Array of it:
var array:[MyStruct] = []
Then I'm creating an object:
let pinOne = MyStruct()
pinOne.coordinate = CLLocationCoordinate2D(latitude: request.latitude, longitude: request.longitude)
pinOne.username = request.username
pinOne.id = request.id
and I want to add it to the array only if the array does not contain it. I tried with this:
if(!(self.array.contains(pinOne))){
self.array.append(pinOne)
}
But it didn't work, so I thought that since I have unique ids, I could use that field for comparing objects. But I don't know how to compare fields of the structures in this case. Can you help me with that?
Instead of creating object of MyStruct before checking its existence you need to create only if its not exist in Array. Also as a suggestion create one init method in the MyStruct like init(coordinate: CLLocationCoordinate2D, name: String, id: String) will reduce your code of initialization of every instance property in new line.
open class MyStruct : NSObject {
open var coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
open var username: String? = ""
open var id: String? = ""
init(coordinate: CLLocationCoordinate2D, name: String, id: String) {
self.coordinate = coordinate
self.username = name
self.id = id
}
}
Now Check for contains like this.
if !array.contains(where: {$0.id == request.id}) {
let pinOne = MyStruct(coordinate: CLLocationCoordinate2D(latitude: request.latitude, longitude: request.longitude), name: request.username, id: request.id)
self.array.append(pinOne)
}
if(array.contains({$0.id==pinOne.Id}))
{
array.addElement(pinOne);
}
Shorter & simpler:
if array.index(where: {$0.id == pineOne.id}) == nil {
array.append(pineOne)
}

Swift 2D array with different types

Is it possible to have a multi-dimentional array that has more than one data type.
Example (I want the last item to be an Int):
var london = [[String]]()
london[0] = ["England", "Chelmsford", 49]
london[1] = ["Wales", "Cardiff", 212]
london[2] = ["Scotland", "Glasgow", 556]
london[3] = ["Germany", "Frankfurt", 640]
I think you are better off with an array of struct or Dictionary:
struct CityInfo {
var country : String
var city : String
var data : Int
}
var london = [CityInfo]()
london.append(CityInfo(country: "England", city: "Chelmsford", data: 49))
london.append(CityInfo(country: "Wales", city: "Cardiff", data: 212))
london.append(CityInfo(country: "Scotland", city: "Glasgow", data: 556))
london.append(CityInfo(country: "Germany", city: "Frankfurt", data: 640))
But you can use 2D array if you want:
var london = [[Any]]()
london.append(["England", "Chelmsford", 49])
london.append(["Wales", "Cardiff", 212])
london.append(["Scotland", "Glasgow", 556])
london.append(["Germany", "Frankfurt", 640])
You use an array with in that array one of 2 options
either make it a class or struct containing the country/city/integer as properties
or
use a tuple
typealias myData = (country: String, city: String, myNumber:Integer)
what use depends on what you'll do with it in your code
If you really want it like how you have it, just use AnyObject as the type
var london = [[AnyObject]]()
london.append(["England", "Chelmsford", 49])
london.append(["Wales", "Cardiff", 212])
london.append(["Scotland", "Glasgow", 556])
london.append(["Germany", "Frankfurt", 640])

Resources