Returning variables from Model to other ViewControllers - swift

I am making a weather application. I basically created a class where I will only get data from API and return them as needed. I have variables like cityName, currentWeather etc.
Problem is sometimes API doesn't provide them all so I need to check if they are nil or not before return them. What comes to my mind is set variables like this first:
private var cityNamePrivate: String!
and then
var cityNamePublic: String {
if cityNamePrivate == nil {
//
}
else { return cityNamePrivate }
But as you can as imagine, its very bad because I have a lots of variables. Is there any better logic for this? Should I just return them and check later in wherever I send them?

The problem here is that you will have many variables to deal with. It's not just returning them from the API, it's also dealing with them in your app and perhaps in some processing code.
One solution is to have a big class or struct with many properties. This will work very well, is straightforward to implement but will require lots of repetitive code. Moreover, it will require to change your API and all your code, whenever some new properties are made available by the remote web service.
Another approach is to have replace the big inflexible class or struct, with a dynamic container, e.g. an array of items [ Item ] or a dictionary that associates names to items [ String : Item ]. If the data is just strings, it's straightforward. If it's several types, you may have to have to implement a small type system for the elements. Example:
var x : [ String: String] = [:]
x["city"]="Strasbourg"
x["temperature"]="34°C"
struct Item {
var name : String
var value : String
}
var y : [ Item ] = [Item(name:"city",value:"Strasbourg"),
Item(name:"temperature", value:"34°C")]
The other advantage of this approach is that you stay loyal to the semantics: an information that is not available in the API (e.g. "unknown") is not the same as a default value. I.e. if the weather API does not return a temperature, you will not display 0 in your app. because 0 is not the same as "unknown". While strings are more robust in this matter, the absence of a name is not the same as an empty name.
This last remark suggests that in your current scheme, of having a big data transfer object, you should consider to keep the properties as optional, and move the responsibility for the processing of unknown data to your app.

Related

How to get the values from Realm List to be used in a UITableview

Using the (modified) examples in the Realm Swift documentation:
class Dog: Object {
dynamic var name = ""
dynamic var age = 0
let puppies = List<Puppies>()
}
class Person: Object {
dynamic var name = ""
dynamic var picture: NSData? = nil // optionals supported
let dogs = List<Dog>()
}
class Puppies: Object {
dynamic var name = ""
}
Let's assume that the Person.name = Bob, and that Bob has several dogs added to his dogs List. I have added another model class called Puppies, which would represent puppies that belong to Bob's dogs. (Apparently Bob owns a kennel.)
How would I get the values to display the names of Bob's dogs and the number of puppies belonging to each dog in a UITableview?
More specifically, what is the code to extract the property values of the List of dogs that belong to Bob. I assume that once I get those values it won't be difficult to list them in the tableview cells.
I decide to use the slightly modified example from the documentation instead of my own code so that those who read this won't have to try and interpret my code, and be able to focus on the solution.
I have been able to save my data and believe I have made the relationships between the objects link properly, but don't know how to get the values of the List objects, based on the primary key I have in my top level model. The problem I have is that (using the example above): the puppies know what dog they belong to, and the dog knows the person it belongs to, but the inverse relationships don't seem to work.
(By the way; I used the LinkingObject examples in the documentation in a playground and it throws and error. I'm not sure if the examples are incomplete in some way.)
In the Realm Browser (displaying the Person object) I can see the data as entered but the link that shows [Dog] has a 0 next to it and when I click on the link, the table that shows is blank. Maybe solving that issues will be the answer to make everything else work.
Please excuse my ignorance. I'm still learning.
Thanks to Ahmad F. for pointing me in the right direction.
Here is the answer:
I did not know how to append to the list property in each of the object classes. Following the example above, it is done by creating a variable that holds the Person object. Then the realm.write function would look something like this.
newDog = Dog()
newDog.name = "Phydeaux"
.....
try! realm.write {
currentPerson?.dogs.append(newDog)

Advantage of computed properties (gettable ones only) vs. stored properties

I would like to clarify if I understand the following concept correctly.
Assume that my goal is to store the String "Good morning, Mike" into the variable var sayGoodMorningToUser.
The String is composed of two variables, namely
var greeting = "Good morning, "
var username = "Mike"
What difference does it make if I use stored properties vs. computed properties, in other words:
var sayGoodMorningToUserStored = greeting + username
vs.
var sayGoodMorningToUserComputed:String {
return greeting + username
}
The only difference I see between these two approaches is that anyone could change the value of sayGoodMorningToUserStored easily and directly, e.g. by writing
var sayGoodMorningToUserStored = "myNewChangedValue"
whereas the variable sayGoodMorningToUserComputed cannot be modified directly, because it cannot simply be set it to a new String value:
var sayGoodMorningToUserComputed = "Hallo" //this would cause an error
Otherwise I cannot understand why people compute the variable instead of simply writing
var sayGoodMorningToUserStored = greeting + username.
Can anyone explain if I understood it correctly? Or are there also other advantages of computed variables vs. stored ones?
I would like to limit my question to gettable variables only, because discussing settable variables here would go beyond the scope.
The difference in your example is this:
var sayGoodMorningToUserStored = "myNewChangedValue"
and
var sayGoodMorningToUserStored = greeting + username
are set when your class is initialized, whereas this:
var sayGoodMorningToUserComputed:String {
return greeting + username
}
is evaluated every time the property is accessed.
The simple example is a class that has a firstName and lastName, but also want fullName. Using a normal property, every time you update firstName or lastName you will also have to update fullName so it will match. Using a computed property, every time you access fullName you will get the up to date information.
Computed Properties
var sayGoodMorningToUserComputed: String {
return greeting + username
}
sayGoodMorningToUserComputed acts just like a function. If a change has been made to greeting or username, then sayGoodMorningToUserComputed will return an up-to-date result that will be the concatenation of the current values.
You would want to use this if you want to ensure your returned value is computed off the latest values of its dependencies (greeting and username).
In the case that both dependencies are final, then it's very likely that the compiler would optimise this computed property into a stored property, because it knows the dependencies can't change
Stored properties
var sayGoodMorningToUserStored = greeting + username
sayGoodMorningToUserStored is just a variable, with nothing special going on. However, it's only set once, whenever the containing scope is initialized. It's computed once, stored and remains constant until it is overwritten by an external source. As such, if greeting or username changes, there will be no effect on sayGoodMorningToUserStored, because it's been computed from the old values, and stored.
You would want to use this if you want to improve performance by caching the result of a computation whose dependencies are constant.

Best practice for array as property in Swift

I have a model class in Swift, whose primary purpose is to contain an array of custom objects, but also has other methods/properties etc.
public class Budget: NSObject, NSCoding {
var lineItems : [LineItem] = []
// Other methods
// Other properties
}
As I understand it, it's best practice to not make the property publicly settable, but I want it to be testable, so lineItems needs to be publicly gettable.
Reading the docs, I could do this:
private(set) public var lineItems : [LineItem] = []
But then I have to write a lot of boilerplate code to recreate array methods, such as insert, removeAtIndex etc.
What is best practice here? At the moment, I don't need to do anything else on insert/removal of items, but I guess I may need to do validation or similar in future, but even so it seems redundant to have to write code that just recreates Array methods.
Would it be better just to make lineItems publicly gettable and settable? Are their circumstances where this would or wouldn't make sense?
Thanks!
Swift's Array is a (immutable) value type, which means that
var a = ["object"]
var b = [String]()
b.append("object")
b == a // true
From this point of view it does not make sense to allow modifying an array and not allow setting it - modifying is basically creating new array and assigning it to variable.

Different types of the same object

So, I'm in Xcode and programming a small program from a friend.
I want to initialize several instances of an object, put them in an array and then iterate through it (via a function that returns a string). Each object adds some text to that string when it's iterated, depending on the variables of the object.
Let's say the class is Tree. The variables in the class are name (string), height(int) and a hasLeaves(bool)(weather it currently has leaves on it or not). I could easily print:
"This is a name that is height meters tall and has leaves.
The problem is that I want the string to be a bit different, depending on which kind of tree it is. Like this:
The oak(name) is big and lifeful, it's height meters tall and has leaves.
Apple trees(name) carries some apples, it's height meters tall and has leaves.
If you ever visit Sweden you should check out the firs(name), they are height tall and haven't got leaves.
I don't want you to write the code for me, but give me a clue. I don't know what to look for. I was thinking about creating a subclass for each Tree, but every subclass would only appear once in the program and I don't know if it's necessary or not.
As you recognize, I'm having a hard time even formulating this question, but if you understand my intentions I'm glad for any clue I can get.
Edit: So this is my attempt to show it in code:
Class:
class tree {
var treeHeight: Int?
var treeWidth: Int?
var hasLeaves: Bool
var treeString: String
init (height: Int?, width: Int?, leaves: Bool, theString: String) {
self.treeHeight = height
self.treeWidth = width
self.hasLeaves = leaves
self.treeString = theString
}
}
Main function:
var oak: tree = tree(height: 1, width: 2, leaves: true, theString:"Oh, the mighty oak")
var appleTree: tree = tree(height: 1, width: 2, leaves: false, theString: "Yummy Apples")
var treeArray: Array = [oak, appleTree]
var resultString = "This is the stories of the trees: "
for tree in treeArray {
if tree.hasLeaves == true {
resultString = resultString + tree.theString
}
}
So, I want the string added to the "resultString" to be different, depending on what kind of tree it is, but I don't want to set that string in the initialization of the object, but rather from what "kind" of tree it is. Does that make it easier to understand?
I want the string (treeString) to be static depending on what "kind" of tree it is. So if it is an oak, the string is always "Oh, the might oak".
It sounds like you want a tree class with some properties like leaves, etc. Maybe you also want to subclass leaves with additional properties like color, etc. I recommend the WWDC 2014 video:
http://youtu.be/W1s9ZjDkSN0
Somewhere around 30 minutes they have a demo of a Car class with RaceCar at subclass.
Regarding creating the objects, you can build each object individually and then collect them in an array as one option. For example, maybe in a form on your app the user inputs data for a class or subclass and then you create an object, store to a master array which you then archive to a file.
So, if anyone stumbles in to this question, this is what I learned:
I was looking for subclasses and protocols. There are methods to determining whether an object is of a certain subclass, and in my case, I could have a protocol called "Tree" with certain methods and/or methods, and then make subclasses to this protocol, called "oak" and "fir".

Shared (or static) variable in Swift

I have a class with an array which values comes from a text file. I would like to read this values once and store them in a shared variable, making possible other classes access that values.
How can I do that in Swift?
UPDATE:
Suppose I have three classes of animals and which of them can be found in a set of places which is load from differents tables (each animal have yours and the structure is different for each one). I would like to be able to use them linking to specific class:
clBirds.Places
clDogs.Places
clCats.Places
Note that I need to load data once. If I dont´t have a shared variable and need to put it outside the class, I need to have different names to the methods, just like:
BirdsPlaces
DogsPlaces
CatsPlaces
And we don´t have heritage in this case
Declare the variable at the top level of a file (outside any classes).
NOTE: variables at the top level of a file are initialized lazily! So you can set the default value for your variable to be the result of reading the file, and the file won't actually be read until your code first asks for the variable's value. Cool!
Similarly, you can declare an enum or struct at the top level of a file (outside any classes), and now it is global. Here's an example from my own code:
struct Sizes {
static let Easy = "Easy"
static let Normal = "Normal"
static let Hard = "Hard"
static func sizes () -> String[] {
return [Easy, Normal, Hard]
}
static func boardSize (s:String) -> (Int,Int) {
let d = [
Easy:(12,7),
Normal:(14,8),
Hard:(16,9)
]
return d[s]!
}
}
Now any class can refer to Sizes.Easy or Sizes.boardSize(Sizes.Easy), and so on. Using this technique, I've removed all the "magic numbers" and "magic strings" (such as NSUserDefault keys) from my code. This is much easier than it was in Objective-C, and it is much cleaner because (as the example shows) the struct (or enum) gives you a kind of miniature namespace.