is it possible to retain data within a model class - swift

I'm new to and starting to look at swift.
is it possible to store and retrieve data in swift without having to use NSObject?
here I what I'm trying to achieve. I have a set of 4 ViewControllers.
On the first ViewController I want to record a name.
In my last ViewController I want to read that name.
I tried to store it in a simple model as shown:
class infoModel
{
var m_name : String
init(_name: String) {
self.m_name = _name
}
func getName() -> String {
return m_name
}
}
when I call getName from my fourth View its null?
I know its possible to pass data in segue or use NSUserDefaults, but I'm curious if its possible for the model object to retain the value?
Thank you in advance for your time

I think this is general programming rule for objected oriented languages.
As long as you have reference to the same object, you will have the object with the same data. And its up to you how you pass this data between other objects; using delegates or just assigning some variable, etc.
Also there are ways how to save data which allows you to save data somewhere else and then retrieve them. To saving small amount of data you can use in Swift UserDefaults, but for bigger amount of data you should work with some database (e.g. Realm, CoreData).

Related

Pass a copy of an object in storage without the reference to avoid users from modifying the object in storage

pub fun getAddresses(): {Address: Bool} {
return Contract.account.borrow<&{Address: Bool}>(from: storage/dict) as! {Address: Bool}
}
In other words, I don’t want to pass back to the caller the reference to the dictionary because then they will be able to modify the actual dictionary object in storage. I just want a copy of the dictionary object returned, but don’t want to create a copy through looping over the address dictionary as that will be computationally expensive… Is there any way to remove the reference?
Have you consider storing a struct in your storage that has this as a field? Then you can get a reference to the struct and then send this field back?

Passing a huge 2d array between 2 view controllers

I usually use a segue to pass some data between 2 ViewControllers. But now I have a 2D array (About 40Meg of data and in the future it may go to over 100Meg. It's a .json file). I read a few articles that tell all the different ways. But most ways (if not all) will make a copy of that data, and that takes time (in the launch screen it's acceptable but not when switching of ViewControllers). What method would you recommend? Putting my huge array as a global works fine, but it is frowned by many.
class ArrayWapper {
var array: [[Int]] = [[]] // Set your array .
}
And send an instance from that class to the second UIViewController
as, #vacawama mentioned since its class it will pass the reference rather than a value copy of that array.
So in the second UIViewController you would have a variable of ArrayWapper class type, instead of simply [[Int]] array.

How to pass data from an api in a tableViewCell, to another tableViewCell in swift 4?

I am working on a tv tracking app where you can search for tv shows and save them to see when a new episode comes out.
My question is, how would I get the movie data from the cell in the searchTableViewController and present the selected data into the cell on myShowsTableViewController?
This is a very broad question and is generally not suitable for StackOverflow, which is for more "granular questions".
That said, I would recommend creating a class called DataManager or something like that. In terms of making your API calls, I would recommend using something like Alamofire for making API calls. Lastly, I would recommend reading up on the Codable protocol for decoding the JSON the API sends back. When you decode your JSON, you'll want to store the structs somewhere where your view controller can see it.
To use CocoaPods, here's a good primer (You'd use them for Alamofire).
Your data manager would look something like this (I'll use NSObject for simplicity's sake, but you could just create your own class):
struct Shows: Codable {
// Whatever the API sends back, you've got to map it here
}
class DataManager: NSObject {
var shows: [Shows] = [] // empty array of shows to start
func methodToGetAPIResponse() {
// Alamofire call & JSON decoding here
// Once you get a valid response, shows = try JSONDecoder().decode...
}
}
You could so something like this for your DataManager in your view controller class:
let dataManager = DataManager()
Then, in your UITableViewDataSource methods, numberOfRowsAtIndexPath would be return dataManager.shows.count and cellForRowAtIndexPath you'd get a hold of the object to populate your labels like so:
let show = dataManager.shows[indexPath.row]
Anyway, that ought to be enough to get you started. Good luck! Try to be more granular with your questions in the future.

Array pass by value by default & thread-safety

Say I have a class which has an Array of object Photo:
class PhotoManager {
fileprivate var _photos: [Photo] = []
var photos: [Photo] {
return _photos
}
}
I read one article which says the following:
By default in Swift class instances are passed by reference and
structs passed by value. Swift’s built-in data types like Array and
Dictionary, are implemented as structs.
Meaning that the above getter returns a copy of [Photo] array.
Then, that same article tries to make the getter thread-safe by refactoring the code to:
fileprivate let concurrentPhotoQueue = DispatchQueue(label: "com.raywenderlich.GooglyPuff.photoQueue",
attributes: .concurrent)
fileprivate var _photos: [Photo] = []
var photos: [Photo] {
var photosCopy: [Photo]!
concurrentPhotoQueue.sync {
photosCopy = self._photos
}
return photosCopy
}
The above code explictly make a copy of self._photos in getter.
My questions are:
If by default swift already return an copy (pass by value) like the article said in the first place, why the article copy again to photosCopy to make it thread-safe? I feel myself do not fully understand these two parts mentioned in that article.
Does Swift3 really pass by value by default for Array instance like the article says?
Could someone please clarify it for me? Thanks!
I'll address your questions in reverse:
Does Swift3 really pass by value by default for Array instance like the article says?
Simple Answer: Yes
But I'm guessing that is not what your concern is when asking "Does Swift3 really pass by value". Swift behaves as if the array is copied in its entirety but behind the scenes it optimises the operation and the whole array is not copied until, and if, it needs to be. Swift uses an optimisation known as copy-on-write (COW).
However for the Swift programmer how the copy is done is not so important as the semantics of the operation - which is that after an assignment/copy the two arrays are independent and mutating one does not effect the other.
If by default swift already return an copy (pass by value) like the article said in the first place, why the article copy again to photosCopy to make it thread-safe? I feel myself do not fully understand these two parts mentioned in that article.
What this code is doing is insuring that the copy is done in a thread-safe way.
An array is not a trivial value, it is implemented as multi-field struct and some of those fields reference other structs and/or objects - this is needed to support an arrays ability to grow in size, etc.
In a multi-threaded system one thread could try to copy the array while another thread is trying to change the array. If these are allowed to happen at the same time then things easily can go wrong, e.g. the array could change while the copy is in progress, resulting in an invalid copy - part old value, part new value.
Swift per se is not thread safe; and in particular it will not prevent an array from being changed while a copy is being performed. The code you have addresses this by using a GCD queue so that during any alteration to the array by one thread all other writes or reads to the array in any other thread are blocked until the alteration is complete.
You might also be concerned that their are multiple copies going on here, self._photos to photoCopy, then photoCopy to the return value. While semantically this is what happens in practice there will probably only be one complex copy (and that will be thread safe) as the Swift system will optimise.
HTH
1) In code example what you provided will be returned copy of _photos.
As wrote in article:
The getter for this property is termed a read method as it’s reading
the mutable array. The caller gets a copy of the array and is protected
against mutating the original array inappropriately.
that's mean what you can access to _photos from outside of class, but you can't change them from there. Values of photos could be changed only inside class what make this array protected from it accidental changing.
2)Yes, Array is a value-type struct and it will be passed by value. You can easily check it in Playground
let arrayA = [1, 2, 3]
var arrayB = arrayA
arrayB[1] = 4 //change second value of arrayB
print(arrayA) //but arrayA didn't change
UPD #1
In article they have method func addPhoto(_ photo: Photo) what add new photo to _photos array what makes access to this property not thread-safe. That's mean what value of _photos could be changed on few thread in same time what will lead to issues.
They fixed it by writing photos on concurrentQueue with .barrier what make it thread-safely, _photos array will changed once per time
func addPhoto(_ photo: Photo) {
concurrentPhotoQueue.async(flags: .barrier) { // 1
self._photos.append(photo) // 2
DispatchQueue.main.async { // 3
self.postContentAddedNotification()
}
}
}
Now for ensure thread safety you need to read of _photos array on same queue. That's only reason why they refactored read method

Best way to use my singleton

I started to develop my singleton class but I have a problem.
What I want to do is have a search objects containing the values of the search form that I could use in several views.
I want to have the ability to get the singleton in any view in order to perform the search or build the search form.
So I have a set of values with a boolean for each to know if the variable has been initialized by the user or not, cause not all the search fields needs to be filled in.
For example :
NSString name= Bob;
BOOL nameFilled =True;
NSString adress= nil;
BOOL adressFilled=false;
NSNumber numberOfChilds = 0;
BOOL numberOfChildsFilled = false;
So my problem is that I can't retain the boolean in my header file because it's not a class.
How can I do, is there a better solution than what I presented above?
Hope I have been clear
You dont need to have this BOOLean value to see if it is filled, why not just use the object itself to see if it has been initialized so something like
if(name==nil)
//this means i t hasnt been initialized
else
//this means it has
Instead of using int, use NSNumber. Then, for objects that haven't been specified, use 'nil', which is distinct from an NSNumber with 0 as a value.
You don't need to #retain BOOL or other primitive types in Objective-C - you only need use that for object types.
Seriously, don't implement a singleton. It isn't necessary for this application. You should have a model class to handle this.
Try using dependancy injection and/or plist files to save the information. You'll have a much better time debugging and extending functionality.