Learning Mac programming with iPhone background

Discussion in 'Mac Programming' started by dantastic, May 13, 2011.

  1. macrumors 6502

    dantastic

    Joined:
    Jan 21, 2011
    #1
    Hi there,

    A while back I started developing for the iPhone coming from a mostly Java background. That was fine, plenty of reading material that explained things and drilled in a few best practices along the way.

    I found myself the other day needing a pretty basic app to help me draw out Bezier Curves and getting their coordinates. Not being able to find an app out there I figured it would be a handy learning exercise to write one myself.

    I found first that cocoa was a bit different from cocoa touch so I picked up the most recommended book out there and figured - I'll just start from the beginning. So I'm about 150 pages in to - cocoa programming for mac osx.

    I find because I probably learned things in the wrong order - every page I read the more confused I get!

    I have a pretty good grasp of objective-c but the cocoa part is killing me. Do anyone know of any resources what would be better at explaining these things to someone already proficient in cocoa touch?
     
  2. macrumors 603

    Joined:
    Aug 9, 2009
    #2
    Describe what chapter you're on, and exactly what things are confusing.

    The most common confusing things in Cocoa GUI development is probably first-responder and the whole "file's owner" relationship to a nib. MVC is in there, too. But those are essentially the same between Mac and iOS Cocoa, so I don't see the problem there.

    Mac programs often have multiple windows, but other than document-based designs, that's just a top-level container for NSView objects: again, pretty much the same.
     
  3. thread starter macrumors 6502

    dantastic

    Joined:
    Jan 21, 2011
    #3
    I'm on chapter 8 at the moment - that's when I really hit the wall. I was pulled away on a job at the same time so I got most of the way through chapter 8 but I will have to start that chapter from scratch.

    The first thing I'm not getting is the memory management. After having been on the iPhone for a while now I'm obviously pretty strict but in cocoa - does it just happen automatically?? I see alloc after alloc but no matching release. Then in some places he is setting up autorelease pools - do they cover objects I own as well?

    Where I'm really stuck is in the Bindings - I don't understand what they are. I was blindly following along clicking things in the bindings inspector.

    I understand the MVC design pattern, I understand the language. I think I will understand memory management pretty quickly too - the bindings I don't know what they are :)
     
  4. macrumors 603

    Joined:
    Aug 9, 2009
    #4
    Memory management is the same on Mac as it is on iOS. At least if you're using retain/release. Retain/release is mandatory on iOS, but optional on Mac OS; the latter also offers garbage collection.

    See the Memory Management Guides:
    http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
    http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

    If you look carefully you'll see the documentation is identical.


    Post an example of the "alloc after alloc but no matching release". Are you sure the example isn't using garbage collection? Because that's exactly what I'd expect to see if GC is enabled.

    Also post an example of "setting up autorelease pools". Because those would be unnecessary under GC.
     
  5. thread starter macrumors 6502

    dantastic

    Joined:
    Jan 21, 2011
    #5
    Ok, the application in chapter 3. it's small enough that I can post it in it's entirety here. This here is the example that got me confused about memory management.
    Code:
    #import <Foundation/Foundation.h>
    int main (int argc, const char * argv[])
    {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        NSMutableArray *array = [[NSMutableArray alloc] init];
        for (int i = 0; i < 10; i++) {
            NSNumber *number = [[NSNumber alloc] initWithInt:i * 3];
            [array addObject:number];
        }
        for (int i = 0; i < 10; i++) {
            NSLog(@"index: %i, number: %i", i, [[array objectAtIndex:i] intValue]);
        }
        [pool drain];
        return 0;
    }
    
    In the above there's an autorelease pool created, will that also take care of my NSMutableArray array that I alloc and all the instances of NSNumber I alloc? From my understanding of using autorelease pools in cocoa touch they only release memory of autoreleased objects. ie:
    Code:
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *allocatatedString = [[NSString alloc] initWithString:@"Hello"];
    NSString *autoreleasedString = [NSString stringWithFormat:@"World"];
    [pool drain];
    NSLog(@"%@ %@", allocatatedString, autoreleasedString);
    
    (I haven't tested the above...) But in the above only hello should be printed. the autoreleasedString should be long gone but the contents of the allocatedString should remain untouched by the autorelease pool.
     
  6. macrumors member

    Joined:
    Dec 28, 2010
    Location:
    Scotland
    #6
    The example is from Chapter 3, before Chapter 4 which is Memory Management.

    I would say that example was leaking memory: the NSMutableArray and all the NSNumber objects. I think he's just ignoring the memory management at that point in the book to keep it simple and he does refer you forward to the next chapter in a couple of places, saying that autorelease pools will be discussed there.
     
  7. jiminaus, May 14, 2011
    Last edited: May 14, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #7
    If this is not running in a GC environment, then indeed the NSArray object assigned to array and each of the NSObject objects assigned in turn to number will be leaked. As you know from Cocoa Touch (Cocoa is the same), the autorelease pool won't send release to these objects because they're not sent an autorelease message.

    In a GC environment this code is fine. A drain message sent to an autorelease pool under GC is (virtually) a no-op. An autorelease message is a no-op (short-circuited by the runtime in objc_msgSend). Apple made efforts to allow autorelease pools and retain/release/autorelease to be efficiently used in a GC environment to allow libraries to be used in both GC and non-GC environments.

    Yes I think you're right. The author's just trying to get you used to the syntax at this point. The only reference to destroying an object is on page 34.

     
  8. dantastic, May 14, 2011
    Last edited: May 14, 2011

    thread starter macrumors 6502

    dantastic

    Joined:
    Jan 21, 2011
    #8
    right, so in a GC environment the collector is taking care of all objects I explicitly own as well (though alloc for instance). But then effectively having a autorelease pool in the above snippet is essentially useless at the same time.

    So for the code to be (more) correct I should either release all objects I own - like in a non garbage collected environment (cocoa touch). Or enable GC and remove the autorelease pool altogether.

    In that case, in a GC environment is there any effective difference between
    Code:
    NSString *allocatatedString = [[NSString alloc] initWithString:@"Hello"];
    NSString *autoreleasedString = [NSString stringWithFormat:@"World"];
    
    I'll go through chapter 4 again and hopefully things will click. I'm quite open to the fact that I'm wrong here and I do appreciate the explanations given.
     
  9. macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #9
    In the first example, no autoreleased objects are created in the first place, so the pool does absolutely nothing, neither in a reference counted nor a GC environment.

    Generally speaking (not always), in a reference counted environment, you would want to (auto-)release anything you add to an array if the array is the primary owner of the object (but you already knew that). In a GC environment, autoreleased objects are approximately equivalent to regularly allocated objects. They go away eventually if you do not have them in some object's set of properties (ivars).

    Really, I think GC is not a good thing to teach off the bat. New programmers should learn memory management and use it as much as possible. GC is handy for Q&D applications, but when it comes to larger, more complex programs, I think your overall memory footprint will most likely go up somewhat with GC, since it only "gets around to" releasing garbage.
     
  10. thread starter macrumors 6502

    dantastic

    Joined:
    Jan 21, 2011
    #10
    That's right actually, in that example there are no autoreleased objects created - having that autorelease pool there to begin with is completely futile. I think I get the memory management now. I was just a bit confused by the code samples.

    I'll carry on with the book and I'll try to figure out the bindings as well and what they are.
     
  11. macrumors 603

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #11
    Only if you don't care about portability or reuse. I've been trying to write my Cocoa stuff so that I can reuse as much as possible of it on Cocoa Touch with minimal modification. And vice versa.

    Reason: I've been porting an app from iPad to Mac OS X. Figured out a few improvements to some classes, and ported them back. Figure out some bug fixes and ported them forward. etc. I've been gradually reducing the differences to a few paradigm #ifdefs.

    Also if you don't care about an optional bit of performance. Manual memory management usually requires less CPU cycles and dcache thrashing than GC. I'm old fashioned and hate to waste cycles on GC.
     
  12. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #12
    Draining an autorelease pool is not completely useless under GC.

    From the Garbage Collection API chapter of the Garbage Collection Programming Guide:
    So the motivation for using autorelease pools above and beyond the one's provided by the normal run loop mechanism still applies equally to both GC and non-GC environments.
     

Share This Page