Recent Changes in Objective-C runtime/ Xcode 4.2 code - objective-c

I've just started learning Obj-C and i'm a little confused. The videos I've been watching on Lynda.com were created with Xcode 4, but there are so many differences that I find it hard to believe that all of them occurred in 2 point releases. For instance:
In the video you could write:
#property NSString * myString
And it would be fine, but now in 4.2 it throws an error unless you write something like:
#property (nonatomic, retain) NSString * myString
In addition, there are no longer init or dealloc methods in the implementation code by default and NSAutoReleasePool is implemented completely differently. What gives?

While I can't guarantee that this list is exhaustive, the differences you'll find on the net are:
Objective-C 1.0 or 2.0
Old or modern runtime
Manual or automatic reference counting
My personal take on the main differences is:
Objective-C 2.0 brought properties and synthesized accessors among other things
The modern runtime has a different way of organizing instance variables (non-fragile instance variables), but you probably won't notice in day-to-day development work
The modern runtime also allows 64-bit apps if the OS supports it
Automatic reference counting lets you do away with retain/release code at the modest cost of following the coding and naming conventions
There are more differences, but these are the most important ones as I see it - personally I rarely have to use autorelease pools, and if I understand correctly the new syntax does not change the functionality.

If you create a project with "automatic reference counting" option "on" then there wouldn't be any init or dealoc methods.

When creating project
CHECK the Use Automatic Reference Counting.

When creating a project you can check the option "Use Automatic Reference Counting". If you do check this, then there won't be any init or dealloc methods, because Xcode automatically does the reference counting.

Related

Objective-C init quirks

In a class interface I define some ivar
#property (strong,nonatomic) id < Protocol > initEst; // Initial estimate
This compiles without a problem but when I run the program it crashes with EXC_BAD_ACCESS and [Object .cxx_destruct] indicated by the debugger as the reason.
What is going on?
It's all about the rules of ARC automatic memory management. An initializer has special rules for how it treats the returned value: it retains and returns. See https://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-init.
Objective-C in general, and ARC in particular, have some pretty strict rules about what names of methods mean. initXXX means "this is an initializer". If this isn't an initializer, don't use the init prefix.
You could turn off ARC entirely and manage memory yourself, but it's easier just to obey the conventions, and it fits better in case of interaction with other languages (such as Swift).
I have tested this some more and there seems to be three conditions for this particular quirk to show up.
In my particular case the ivar's Protocol was also the same as that of the containing class. This seems to be an additional requirement for this problem to surface (refering here to my earlier answer that did not mention this).
So to elaborate on my earlier answer. If
initXXX is an ivar
of id type
that implements a Protocol that is the same as the containing class
then the Objective-C + ARC compiler will happily compile the code but be unable to execute it.
Here is a sample of the code I used to test
#interface Dog : NSObject < Animal >
#property (nonatomic,strong) id < Animal > initState;
#end
Something like this will cause problems simply because the name starts with init. Change the name and all problems disappear.
For reference, the runtime error this generates is
Dog object overreleased while already deallocating
This snippet is pretty abstract but this may bite you in places where you need to specify some initial condition and where it is natural to name some ivar initXxx but beware, if you use Objective-C you do not have that luxury nor will the compiler warn you that it is wrong.
The original error seemed memory allocation related and caused me to suspect the way I used the autoreleasepool but now I am fairly convinced this has nothing to do with the issue.

What is the fragile base class in Objective-C?

I'm reading a book of object-c. When talking about inheritence, the book says:
Methods use the self parameter to find the instance variables they
use.
The Objective-C compiler knows the layout of the instance variables in
an object because it has seen the #interface declarations for each of
these classes.
With this important knowledge, the compiler can generate code to find
any instance variable.
Then it says this can cause fragile base class problem:
The compiler works its magic by using a “base plus offset” mechanism.
Given the base address of an object—that is, the memory location of the first byte of the first instance variable—the compiler can find all other instance variables by adding an offset to that address.
When you access some instance variable in a method, the compiler generates code to take the value that self holds and add the value of the offset (4, in this case) to point to the location where the variable’s value is stored.
This does lead to problems over time.
These offsets are now hard-coded into the program generated by the compiler.
Even if Apple’s engineers wanted to add another instance variable to NSObject, they couldn’t, because that would change all of the instance variable offsets.
This is called the fragile base class problem.
Apple has fixed this problem with the new 64-bit Objective-C runtime introduced with Leopard, which uses indirection for determining ivar locations.
I don't understand why adding instance variable in NSObject can cause problem.
If NSOject changes, can't we just recompile the program so the offsets change accordinglly?
Edit: And what if we dont recompile, will the existing code just fail?
Yes, a recompile would fix things, but until you recompile, your program would be broken.
Imagine that you compile your app targeting 10.4. The compiler looks at the headers of NSObject and figures out what the appropriate offset is for each ivar in your subclass. Then 10.5 comes out and they add new ivars to NSObject. Anyone running your app on 10.5 will have problems, because the Foundation framework (which includes NSObject) was compiled against the 10.5 SDK, while your app is still relying on the layout that was present in the 10.4 SDK.
The fragile base class problem meant that Apple could not change the size of any framework class without crashing every app that did not recompile for the new SDK. While in an ideal world, developers would always release updates promptly, that's not reality. So until the fragile base class problem was fixed, Apple's hands were tied.
If Apple adds an ivar to NSObject, all of its subclasses would need to be recompiled, meaning a number very close to the 100% of all the Objective-C code ever written.
Do you see the problem now?
It's not impossible to solve, you just need to have every developer to recompile their code bases, but in the meanwhile every single Objective-C program out there would be broken.
As a further reference, here's a very nice article by Greg Parker on this subject: http://www.sealiesoftware.com/blog/archive/2009/01/27/objc_explain_Non-fragile_ivars.html

how to properly alloc/dealloc this pointer? objective-c

*beginner iOS programmer, please explain with patience
suppose i have 2 classes - Foo, Bar
in class Bar, i have a pointer to an instance of Foo, which i set during init. (and because i dont know how to properly import Foo and Bar with each other, i end up setting the type to id instead of Foo)
#implementation Bar{
id pointerToInstanceOfFoo;
}
how do i write my dealloc function for Bar? or DO I even override the dealloc function?
right now i have
-(void)dealloc{
pointerToInstanceOfFoo = NULL;
[super dealloc];
}
i still want that pointer to Foo to be around when Bar dies, but am i doing things right? several questions:
if Foo and Bar imports from each other, how do i do this? or is this bad software design?
right now i have the pointer "pointerToInstanceOfFoo" set in the #implementation... is this equivalent to declaring a private pointer in class Bar?
should i instead be using
#property (nonatomic, weak) id pointerToInstanceOfFoo
instead? if so, why do i keep getting this error about no weak pointers in ARC?
do i need
delete pointerToInstanceOfFoo;
in the dealloc function??
Sorry for the confusion, any explanations/answers would be greatly appreciated!!
P.S. i'm using XCode 4.4 and running on iOS 5.0 with cocos2d v2.1 beta... i think it's using arc
You are not allowed to use [super dealloc] in ARC. So if that compiles, you are not using ARC and you need cals to retain and release. Writing a whole tutorial on that is not something that will fit in a stack overflow answer. As for your other questions:
1) Just import them in the implementation file, not the header file.
2) Yes
3) If it makes you happy. The error probably means you are targeting below iOS 5.0 (I.e. the deployment target in your project settings is set to less than 5.0), in which weak pointers are not supported, or ARC is turned off. I don't think you've accurately reported the error message since it makes no sense.
4) "delete" is not valid objective-c or valid c.
P.S. No, you don't want that pointer to be around after Bar is deallocated because that would be a memory leak. Perhaps you want a static variable instead of an instance variable?
As borrden mentioned, retain/release and objective-c memory management is a considerably large topic, one that has been extensively dealt with. I'd recommend reading this to get started and do some more research from there.
Though you can (should?) use ARC and save yourself some hassle, understanding the regular retain/release cycles will give you a better understanding of strong/weak references in ARC. While you don't have to understand everything about memory management in objective-c while using ARC, you still need to understand some of it.

How does the new Apple LLVM 4.0 "default synthesize" feature operate?

I was going through the release notes for Xcode 4.4 and noticed this:
LLVM 4.0 Compiler
Xcode now includes the Apple LLVM Compiler version 4.0, including the following newObjective-C language features:
Default #synthesize: automatically synthesizes an #property when unimplemented
I'm intrigued about this feature. How does it work? I have tried by deleting the #synthesize, it doesn't work.
It does work actually, make sure that in your project and target settings the Compiler is set to LLVM 4.0. Then when you delete the #synthesize line you can access it in two ways:
through the accessor with self.myProperty or through the respective instance variable with _myProperty (yeah the underbars are added automatically).
There are many cases where it simply doesn't work. These are all outlined as exceptions here:
http://useyourloaf.com/blog/2012/08/01/property-synthesis-with-xcode-4-dot-4.html
but the most important one, to me, is called
Readwrite Property With Non-Default Getter and Setter
This means that, unless your properties are just public-facing ivars, you need to include a #synthesize. Or to put it another way, if you're using encapsulation well and filling up those setters and getters, you cannot use this.
Later Note: I'm not sure about the conditions specified here, but I find that there is a autosynthesized ivar for just about every situation I encounter.

Updating CoreFoundation PriorityQueue implementation to take advantage of ARC for iOS

I found an implementation of a priority queue that primarily uses CFBinaryHeap to work.
I'm currently using the -fno-objc-arc compiler flag to skip the usage of ARC while compiling these files. I attempted to update this code to take advantage of ARC, though I've run into a few snags of understanding.
Is there anyone here who has updated code similar to this for use with ARC?
How do you handle things like free(), and CFRelease()? Can we just get rid of them?
What do you do with the retain and release methods you create for CFBinaryHeapCallBacks?
Do you use __bride or __bridge_transfer to reference the const void * into Objective-C objects? Likewise should you use (__bridge_retained void *) or obj_unretainedPointer() to do the reverse?
ARC basically is a compiler technology that automatically inserts calls to -retain, -release, and -autorelease as needed. It does not remove the need for retains and releases, it just makes them automatic (in the process, optimizing out many that are not required, and playing other tricks to make various common patterns much more efficient than if you did it by hand).
ARC knows nothing about Core Foundation, nor about void* objects, malloc, free, or anything other than ObjC memory management.
This means that as long as you use Core Foundation objects, you should continue to use CFRelease. And if you malloc memory, you should continue to free it.
But.... what if you want to take memory that was created by Core Foundation and transfer it to Cocoa via a toll-free bridge? That's where __bridge* comes in. One of the best sources of information is the clang docs themselves. A great blog article is Everything you need to know about ARC. It includes many useful links to the definitive information.
But here's the short answer (from Transitioning to ARC)
NSString *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef
CFStringRef d = (__bridge_retained CFStringRef)my_id; // returned CFRef is +1
Using __bridge_transfer logically moves a CF object into Cocoa. Using __bridge_retained logically moves a Cocoa object into CF. You use these when you are really transferring ownership of the object. In the above example, you generally shouldn't continue using the my_ variables in my opinion. These are particularly useful in cases where you are returning the result out of the function. These should be used for their logical ownership functionality only. Don't use them as a way to "fake" a manual call to retain or release.
If you just want to have a temporary "bridged" pointer to the object so you can use it in CF or Cocoa without transferring it, then use __bridge. That's a no-op that says "don't do any memory management, just let me pretend for the moment that it's the other kind of object." If you do a lot of toll-free bridging, you'll wind up using __bridge quite a lot (making it seem like a small toll.... :D)
Here is a pure objective-c implementation of PriorityQueue, that supports ARC:
https://github.com/jessedc/JCPriorityQueue/tree/experimental/heap-queue
Is simple to implement non ARC lib into XCode project. Just open "Build Phases"(menu when click on your project target) -> "Compile Sources" and to files, which are not using ARC add by double click flag "-fno-objc-arc" and your're done. So simple :)