Objective-C iOS app not storing data in array of objects - ios

this is a very hard question to ask because I don't want to flood you with all of my code, being that most of it is not pertinent to the problem. So I won't be to surprised if this goes unanswered. Although, it could be something hella simple that I am missing haha. Here it goes:
So my app is storing an array via [encoder] in my appDelegate. The app is full of objects that are creates in a separate NSObject class. Think of it this way for examples sake:
I have my main viewController class. And in appDelegate I define/encode an array of objects.
Now in my main, I fill the array with 10 "cars". My car class has variables such as color, make, model, etc.. Now when I save and relaunch the app, the array that I have saved is now an array containing 10 elements, but it seems to have forgotten all of the variables for each instance of the car class.
When I relaunch the app, If I call NSLog(#"%#",array in appDelegate); It prints 10 lines that look a lot like this:
""
So I know the array is being stored with 10 elements, and 10 elements are saved, but like i said, all of the variables are gone.
Note: On the first run of the app, and the array is being filled for the first time, I can access all the variables perfectly, and nothing is wrong.
Thank you for any help that I can get!!

We need to see the code for your implementation of initWithCoder and encodeWithCoder on the "car" class. If you haven't implemented them, that's your problem.
What is probably happening currently is that only the superclass implementation of these methods is being invoked. This means the correct class will be recreated but no data will be saved or restored.
NSCoding protocol reference doc.

Your main class as well as all the objects you put into the array all need to conform to NSCoding. If the objects in the array aren't NSCoding compliant, they won't get coded automatically.

Related

Cache Array of Custom Objects in Swift3

I need to persist an array of custom objects from session to session for a user. The array will be filled with 1-14 fairly simple and lightweight custom swift objects like so:
[Obj1, Obj2, Obj3]
What I want to do is when viewWillDisappear is called, persist this data so that when the user comes back to the screen, I can use these exact objects again. What is the best way to do this? I've looked into using core data, but I don't want to setup a data model for these objects, just store them as is without any relationships or anything.
Please note that the app makes use of a very computationally taxing algorithm, of which these objects play a central role. As such, I need to keep these objects as light as possible. Therefore, I don't want to make the objects conform to NSCoding as it isn't necessary to the central role of the object
If making your class an Objective-C class that conforms to NSCoding proves to actually have a substantial performance impact (I'm skeptical), then you can make a second container that subclasses NSCoding that's used solely for storage. Add an initializer to your current lightweight Swift class/struct that initializes the instance from this container object, and vice versa. Any time you need to serialize/deserialize, you just use this container object as an intermediate.
This buys you the functionality at minimal cost when reading/writing, but leaves regular usage performance unaffected.
If you can make the object a subclass of NSObject then you can have it conform to NSCoding and use NSKeyedArchiver and NSKeyedUnarchiver to serialize and deserialize your objects.

Transferring the same object between ViewControllers

I have a class, User, that has an NSMutableArray that stores custom NSObjects. I only want one of these to ever be instantiated throughout the entire app, and I would like to be able to call methods on it in each ViewController for getting and setting. My problem is that I don't know how to call the methods so they apply to this one instance, instead of creating a new one each time. I'm new to objective-c, so the learning curve makes me feel I'm missing something a bit obvious. I've been working on this all day and am at a wit's end. Is there a good solution to my dilemma? Should I use a singleton class?
(If it helps, the class User is basically a class that stores a to-do list for each user that uses my app. The custom NSObjects are to-do items. There's probably a better storage method that should be used here, but I'm not sure what it is.)
RandomPleb it sounds like what you're looking for is a Singleton. http://en.wikipedia.org/wiki/Singleton_pattern. I also think this question has been answered before so search around on SO.
Laymen's terms; you create a static reference to the class that you only want one of inside that class, then make a static method in the following way:
//call this from classes that want to modify it
public static getsharedinstance()
{
if(the static instance of this class does not exist){
instantiate instance;
}
return this classes static instance..
}
Hope this helps (and if this is wrong, I hope someone can correct me)
Also in regards to your storing objects, I think NSMutableArray is fine unless it is a very big persistent list where each task has many properties in which case maybe using CoreData would be better.
Fenix

Passing Arrays/Objects between ViewControllers in Swift

Following on from this question: Is there a reason that Swift array assignment is inconsistent (neither a reference nor a deep copy)? -
I have been playing with passing objects in Swift and noticed some strange results.
To clarify the kind of behaviour i'm used to (prior to Swift) would be that of Objective C.
To give an example in one of my Applications (written in Obj C) I have the concept of a 'notification list'. - really just an array of custom objects.
In that App I often pass my global array of 'notifications' to various viewControllers which provide a UI to update the list.
When I pass the global array to a child viewController I assign it to a local array variable in the recipient object. Then, simply by updating/changing the local array these changes are reflected in the global array on the rootViewController. I understand this behaviour is implicit in Objective C as objects as passed by reference, but this is really handy and I have been trying to replicate this behaviour in Swift.
However whilst I have been rewriting my App in Swift I've hit a wall.
I first tried to pass a Swift array of strings (not NSMutableArray) from the rootViewController to a child viewController (as described above).
Here is the behaviour when passing in the array of Strings the child viewController:
I Pass in:
[Bill, Bob, Jack] and then assign this passed array to a local array for local modification,
Then I append the String “Frank” to the local array
The results are:
Local array = [Bill, Bob, Jack, Frank]
Global array = [Bill, Bob, Jack]
No changes to the local array are reflected back to the global array. - The SAME result occurs for a change of element (without changing the length of the array.)
I have also tried the above experiment with a more real world example - passing in an array of my custom 'notification' objects to a child viewController. The SAME result occurs with none of the changes to the locally assigned array of custom objects being reflected to the original global array that was passed in.
This behaviour is not desirable to me, I assume the best practice here is to use delegate protocols to pass the modified array (or whatever object) back to the parent object and then to manually update the global array?? - if so this creates quite an extra workload over the Objective C style behaviour.
Finally I did try the inout keyword, which effectively lets you directly modify the function parameter var thats passed to the destination object.
Changes are reflected back to the global array (or object) However the problem is, if the input parameter is assigned to a local variable (to edit outside of scope of the init function) changes to the local variable are still not reflected in global scope.
I hope the above makes sense - It's really stifling my productivity with Swift.
Am I missing something or is this schizophrenic behaviour expected?
If so what is best practice on passing modified data back, delegates?
The linked question provides the answer - it is for performance.
The behaviour may not be desirable for you, but I would say that relying on side-effects from calling methods to modify parameters is the behaviour that is not considered desirable - particularly in a multi-threaded, multi-core environment where data structures can be corrupted.
A design that relies on side-effects is flawed, in my opinion.
If functions need to modify the "global" then they should either return the new value, or if that isn't possible then you should wrap your array inside an object and provide appropriate functions to manipulate the data values.
Swift blurs the lines between intrinsic and object somewhat with arrays, which makes it a little confusing - in Objective-C an NSMutableArray is an object so it always passed by reference.
For notifying other objects that the data has changed you can use an observer pattern. The typical delegate pattern only has a single registered delegate - With an observer pattern you can have multiple registered observers.
You can do this through NSNotificationCenter or an array of "delegates". The former has the advantage of decoupling the code more than delegation
Why don't you create a Model class that contains the array as a var. Add methods to the Model class to manipulate the array and store the new instance in the property. Create a single instance of the Model class at startup and pass it to the view controllers. They all access the array through the Model or through methods in the Model class. The behavior of Swift (where it copies the array on change of size) will be hidden from all of the view controllers.

A NSZombie of an odd type

so i am getting a NSzombie and it says this
-[__NSArrayI _cfTypeID]: message sent to deallocated instance
Any idea what that is? assumably an array although i thought if it were an NS type it would say.
Yes — that'll be some type of array. Rather than being single classes, most of the foundation types are class clusters. So exactly how you initialise the array affects exactly which subclass of NSArray you get back.
The exact behaviour is undocumented and basically guaranteed to change over time but for example if you created an immutable array with less than a certain number of entries then the system might decide to return a single linked array and perform searches as simple linear searches. If you create one above the threshold then it might instead create an array that adds some sort of hierarchical logic for searching (or, more likely, contains the logic to create suitable hierarchical tables if the user starts trying to search the array).
Related lessons to learn:
never try to subclass a foundation class;
don't expect isMemberOfClass: to work properly;
don't even expect isKindOfClass: necessarily to be able to tell immutable from mutable versions of the foundation classes.
Apple needs a way to differentiate these classes and to flag them as private, so you end up with underscores and suffixes. In practice I think __NSArrayI is a vanilla immutable array.
Basically that means your NSArray object is already deallocated.
Something in Foundation.framework tried to access your NSArray's private method _cfTypeID and crashed.
And about question why there's _cfTypeID method in NSArray object. NSArray Core Foundation counterpart of CFArray. Two type's are interchangeable with "toll-free bridge".
So actually apple uses that method for internal uses.
If you want deeper understand of this. You can visit http://code.google.com/p/cocotron/source/browse/Foundation/NSArray/NSArray.m and this is Cocotron's implementation of NSArray. It is not same with the apple's implementation but still implementations are similar.

isEqualToArray crashes with custom class

I have an application that has an array of 5 objects. These objects are all of a custom class. The next iteration of the loop and after some modifications to a temporary array I run a check to see if the values are the same or different by using isEqualToArray. However, the minute I do that I get an EXC_BAD_ACCESS. Is there something that I need to implement in the class to prevent this from happening.
Without giving away too much information the custom class only stores 5 NSString* variables.
Sounds like your NSString variables have been released and your accessing bad memory.
Do you remove them from the array? Or do you possibly create them with autorelease semantics, put them into the array and then release them too?
Maybe post a little more code and we can tell you exactly what is wrong, but more than likely they have been released.
You can turn on NSZombieEnabled to see exactly what is being 'badly accessed'

Resources