In xcode 4.2 I have found it very frustrating because you can't use:
-(void)dealloc {
[label release]; //'release' is unavailable
[super dealloc]; //'dealloc' is forbidden in automatic reference counting
}
Is there another way because autorelease and other deallocs don't work either.
Xcode 4.2 introduces "Automatic Reference Counting" (aka ARC). This is a compiler feature that basically inserts the retain and release calls for you. Under ARC, if you have a pointer to an object, you're retaining it. When your pointer goes out of scope, or is reassigned to point to another object, the original object is released. It's really nice.
So, in short, you just remove all the calls to retain, release, and autorelease, and the compiler will do the right thing for you.
Read up on Automatic Reference Counting. If you write your code properly, you don't need to do any of that anymore.
If you want to use old code without converting, disable ARC. put -fno-objc-arc in the compiler flags for any source modules you don't want to use ARC.
joe
Related
I have a custom NSView class which is layer backed. I make a CAMetalLayer for this NSView which is created in makeBackingLayer.
In makeBackingLayer I create a layer CAMetalLayer *backingLayer = [CAMetalLayer layer]; and set properties as required by me.
My question is, do I need to dealloc this layer explicitly while destructing NSView?
I do not create this layer in an overridden function, is it my responsibility to delete this or the NSView will take care of it?
I do not see any documentation around this. Moreover, all the samples that I see do not mention about deleting layers anywhere.
Thanks
You likely do not need to manually free your layer. Assuming your program has ARC (Automatic Reference Counting) enabled, your NSView should automatically free whichever CALayer is set to its .layer property upon its destruction.
If you're not sure if ARC is enabled, you can go to Build Settings in your Xcode project and search for Automatic Reference Counting. It's been on by default for new Xcode projects for several years now.
Note: Your NSView will only be able to free your layer if it is the only object holding a reference to it. If other objects in your program are holding references to your CAMetalLayer, your layer would not be freed until they remove their references.
I added ARC to an app I'm working on. Unfortunately, it crashes. I found that the automatic script which updates all apps to ARC gave __unsafe_unretained qualifier to all id< protocolName> type.
Why isn't it a weak type? I have deployed the app and all its sub-projects to iOS 5, and therefore I do have weak qualifiers.
My main problem is if I declare those delegates as strong, I'll have a retain-cycle. If I do not, the next time I call them they will be zombies. I checked and before my app crash, the delegate is NSZombie.
What is the cause of this crash and how can it be prevented?
The qualifiers __unsafe_unretained and week have quite a few things in common. They both won't increase the retain count for example. If for example a view controller holds an __unsafe_unretained IBOutlet to a UIView and you remove that very UIView from the view hierarchy, then you (given that you don't retain the view anywhere else) will decrease the retain count and most likely dealloc the UIView. The pointer however will still point to that location and is left dangling. Not nice but also not problematic if you know what happened. Weak properties help you avoiding dangling pointers by nullifying the property when the object gets to a retain count of 0.
Now, if your app crashes or the properties show up as zombies, then they are being released - by whichever class though.
One statement that is not entirely correct is that if you retain the property instead, you'll create a retain cycle. There is the possibility of creating retain cycles though but it really depends on your implementation, not just the property declaration. When you retain an object, you take ownership and until you're done with that object, prevent it from being deallocated by increasing its retain count. If your delegate gets released already while you hold a weak pointer, you won't prevent it from being released. I am assuming you deal with modal view controllers here - UIPopoverController to be precise (just a guess).
You should use instruments and look at the lifecycle of your object and see who retains/releases it. It could be helpful to know. Otherwise, you could paste some code and maybe there will be a nice person here to help you find the issue.
cheers
Ronny
Took some time but i solved it:
I deployed the .xcodeproj projects to iOS 5, but the targets were left in iOS 4.3 deployment. When i fixed it (it's in the 'build settings' for each target) - i could change all '__unsafe_unretained' to '__weak', and all 'unsafe_unretained' to 'weak'.
To avoid retain cycle those delegates should be weak, and they won't be zombies anymore (because they are weak and not unsafe_unretained), and the app won't crash anymore.
If i was still using iOS4.3-, and there isn't unsafe_unretained qualifer, i should only assign nil to those delegates after i don't need them anymore.
a project which is iOS5 only and ARC enabled compiles on Xcode 4.3.1 beta. When compiling on 4.2.1. LLVM is throwing warnings like these:
"ARC forbids synthesizing a property of an Objective-C object with
unspecified ownership or storage attribute"
So the property definitions looks like this:
#property (nonatomic) NSObject* object
ARC is enabled in Build Settings. Adding a strong attribute fixes this warning but this should be default right?
Is there a difference between the Xcode versions in handling those property defaults?
Thanks
Andi
This is not beta specific Xcode 4.2.1 has the same behavior (betas are under NDA and should only legally be discussed in apple's developer forums):
Strong is the default setting for ivars. For ivars if you want __unsafe_unretained or __weak you must specify.
It has always been best practice to specify attributes in property declarations. One example that pops most quickly to mind is the UILabel property text, defined as:
#property(nonatomic,copy) NSString *text; // default is nil
In this example the copy attribute tells me I can pass an NSMutableString reference to the label and it will make a copy and I can go on mutating the string the label will remain the same. The behavior is clearly defined.
And I suspect it's the clearly defined behavior which was the most prominent reason that the ARC compiler forces you to specify storage attributes. Remember with the new runtimes eliminating the need to declare ivars for properties and #synthesize for accessor methods, it's conceivable that the property declaration is the only point you will notice if you accidentally retained a delegate.
Also consider the possibility that a few classes in a project may have been excluded from ARC in these cases there internal implementation would be completely opaque to ARC.
I am using latest Xcode, and trying to find memory leaks.
When i use 'Analyze'
It shows following as potential leak:
+ (UITableViewCell *) method {
UITableViewCell *cell = [[TestX alloc]init];
... do some stuff
return [cell autorelease];
}
Should i just ignore it ?
No, you shouldn't ignore warnings. Sometimes Xcode is buggy and forgets you've changed the code. Try restarting Xcode. Remove do some stuff so that it's just the two lines and see if the analyser stops warning you. It could be the case that you're affecting the retain count in that code somewhere without realising it.
You need to name the method properly to show that it's returning an autoreleased object. I forget the preferred name. Try something like 'newObject'.
I was testing my application and suddenly it had EXC_BAD_ACCESS. Now this has become a semi-regular thing, happening on some builds and not others. It also spits out lots of errors in the debugger such as objc_msgSend_vtable5 What could cause such a weird issue like this?
Looks like it was my fault. To fix it all I needed to do was call retain.
I've recently had just this same error. The short version: it occurred because I had an object that had a delegate that had been released. Make sure you have control over the life cycle of any delegates you assign, be it via Interface Builder or otherwise.
The long version: the error occurs when the Objective-C runtime tries to send a message to an object that's been ultimately released and deallocated. This is different to sending a message to a nil object (a perfectly valid Objective-C operation). In these cases, the runtime knows that the object is nil and responds accordingly. Rather, in this case, Objective-C thinks it has a real, valid object to communicate with and sends a message to an address that contains no object.
In my case, I had an object of type NSTextView which was connected up to a delegate by Interface Builder. When a view or view controller is constructed with a NIB/XIB file, Cocoa hooks up all the child views as instructed, including hooking up any delegates that you might have.
My error was that I had created a subclass of NSView, made it an NSTextViewDelegate and then told Interface Builder to hook up a child NSTextView to that parent view. However, during the various operations I was conducting on the owning NSViewController, I had told Cocoa to remove the NSView from the view hierarchy and reinsert it later.
AppKit specifically tells you not to retain any IBOutlets you might have in your classes, but rather to keep track of these by simple assignment. This is because AppKit handles the memory management of these for you. Little did I know that by asking the view to leave the view hierarchy for a while, I had trigged AppKit to clean up that NSView. Since only AppKit had any retains on the view object itself, [pfft], off it went into the ether. Deallocated.
Since I had no direct control over the NSTextView's delegate, the NSTextView now pointed to a delegate that had been released, even though it had a valid parent view. The next time it tried to send a message to its delegate, the Objective-C runtime fell over.
So, make sure that the delegate is one that you own, or at least know will never get released at an inopportune moment.