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'
Related
Ive tried digging around in old posts, but they were kind of obsolete and years old, so I was concerned things might have changed due to ARC being introduced etc.
Mainly I was looking at some fairly new code that used alloc on an array, which was declared as a property in the header. I was thinking, I don't normally do this and everything is working smoothly. But then came to my mind UIButton and UILabel for example, which has to have alloc invoked, or they won't be added to the view when you want that. Are there any rough guidelines for when its actually needed. I would think any object needs this, but the array vs. button/label thing as I just described made me wonder what is the reasoning behind this.
Thanks in advance
This is 100% dependent on the actual objects being used from the framework. The really great news, though, is that Apple is extremely consistent. If you send a message that contains an "Alloc" in it anywhere, you are responsible for making sure that it has been released.
Here's a super document on it from Apple.
You use alloc always if you create the object on your own.
Which means that sending alloc is normally followed by an init method.
It might sometimes look like it's not always the case, as many classes have convenient constructors that return an already allocated and initialized object to you.
But there is still alloc and init called to create the object.
It's just done for you by the system.
But the difference between convenient constructors and manually creating objects isn't new to ARC, it has always been around.
Example for creating an NSArray on your own:
[[NSArray alloc]initWithObjects:#"Test", nil];
and as NSArray has an convenient constructor here the example for that:
[NSArray arrayWithObjects:#"Test", nil];
If you use ARC, there is no real difference.
Without ARC, the object returned by the convenient constructor would still be autoreleased, while the manually allocated object has to be released by you at a later point (or you have to add an autorelease after the init).
So the main difference is the owner ship:
In the manually created example the object belongs to you, so you are responsible to clean up after you don't need it anymore.
If something is declared in .xib then it is automatically allocated for you. Just use it. While If you are creating a view in code u must alloc it first. And if you have a property NSArray/NSMutableArray etc, u might be doing one of the following:
_array = [NSArray new];
_array = [[NSArray alloc] init];
_array = [NSArray arrayWithObjects: values count:2];
_array = # ["ABC", "xyz"];
etc,
so you are actually allocating it if you are using any of these methods.
I do not really understand, what
they won't be added to the view when you want that.
means, but here is the story:
Every object is allocated using +alloc. To be honest, it is +allocWithZone:, but this does not have any meaning at this place.
The very first message you have to send to the newly created instance object (remember: you sent +alloc to the class object) is an initialization message, something like init…. To put this together you will find code as:
… [[TheClass alloc] init…] …;
Because it is boring typing there are new allocators. They put this messages into one:
… [TheClass new…] …;
(This has some advantages for the class implementor, too, but this is transparent to you. Think of it as sending +alloc, -init….)
In earlier times it has been a good idea to send an autorelease message to it as the next step for some reasons:
… [[[TheClass alloc] init…] autorelease] …;
This has been put together to convenience allocators:
… [TheClass theClass…] …
This is what you find most of the time when reading old code. Using ARC you do not need convenience allocators anymore: There is no autorelease. So there is no reason for convenience allocators anymore. But we had MRR for years and there are still many convenience allocators. (Now called factory methods, but CA's are only a subset of these. A subset you do not have to care about. It's all gone with ARC.) Because there are that many CA's, one still uses them. (And there is a performance issue with them. In nowadays I only write new allocators, which has the advantages of a CA, but not the disadvantage of autorelease.)
To make a long story short: You simply do not see sometimes that +alloc is used.
In a certain portion of code - I am expecting an object to be dellocated but it isn't.
Given that object - how can I check which objects are referencing it?
Also - Is it possible to know every time an objects reference count goes up? (and by which object)
You cant check it. Rather you should use instruments to check the same. They will show the retain count of the object. Perform the steps by running the app on instrument and check for retain count.
Even you should not use retainCount method to check. There is no way to identify that which objects are pointing to you object.
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.
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.
~ Will ARC always release an object the line after the last strong pointer is removed? Or is it undetermined and at some unspecified point in the future it will be released? Similarly, assuming that you don't change anything with your program, will ARC always be the same each time you run and compile your program?
~ How do you deal with handing an object off to other classes? For example, suppose we are creating a Cake object in a Bakery class. This process would probably take a long time and involve many different methods, so it may be reasonable for us to put the cake in a strong property. Now suppose we want to hand this cake object off to a customer. The customer would also probably want to have a strong pointer to it. Is this ok? Having two classes with strong pointers to the same object? Or should we nil out the Bakery's pointer as soon as we hand off?
Your code should be structured so the answer to this doesn't matter - if you want to use an object, keep a pointer to it, don't rely on ARC side effects to keep it around :) And these side effects might change with different compilers.
Two strong pointers is absolutely fine. ARC will only release the object when both pointers are pointing to something else (or nothing!)
ARC will implement the proper retains and releases at compile time. It will not behave any different than if you put them in there yourself so it will always do the same compilation and to answer your question should always behave the same. But that said it does not mean that your object will always be released immediately after the pointer is removed. Because you never call dealloc directly in any form of objective C you are only telling it that there is no reference count and that it is safe to release. This usually means that it will be released right away though.
If you pass an object from one class to another and the receiving class has a strong property associated with it and the class that passes it off eventually nils its pointer it will still have a reference count of at least 1 and will be fine.
Ok, first this answer might helpt you also a little bit: ARC equivalent of autorelease?
Generally after the last strong variable is nilled, the object is released immediately. If you store it in a property, you can nil the property, assign it to something like __strong Foo *temp = self.bar; before you nil, and return that local __strong variable (although arc normally detects the return, and inferes the __strong byitself).
Some more details on that: Handling Pointer-to-Pointer Ownership Issues in ARC
DeanWombourne's answer is correct; but to add to (1).
In particular, the compiler may significantly re-order statements as a part of optimization. While method calls will always occur in the order written in code (because any method call may have side effects), any atomic expression may be re-ordered by the compiler as long as that re-order doesn't impact behavior. Same thing goes for local variable re-use, etc...
Thus, the ARC compiler will guarantee that a pointer is valid for as long as it is needed, no more. But there is no guarantee when the pointed to object might be released other than that it isn't going to happen beyond the scope of declaration. There is also no guarantee that object A is released before B simply because A is declared and last used before B.
IN other words, as long as you write your code without relying on side effects and race conditions, it should all just work.
Please keep you code proper as it has diffrent behaviour on diffrent complier.