Objective-C instances of objects as as units / making new, unforeseen instances

Discussion in 'Mac Programming' started by Ja Di ksw, Oct 16, 2013.

  1. Ja Di ksw, Oct 16, 2013
    Last edited by a moderator: Oct 16, 2013

    Ja Di ksw macrumors 65816

    Ja Di ksw

    Joined:
    Apr 9, 2003
    #1
    Hi everyone, noobie type question here, I could even just use a link that says "read this for that topic" if it's long to explain.

    I want to have a 2D simulation, with units moving around the screen. Each unit has the same variables as the other units, yet it will have its own values for the variables that can change over time and are unit specific (i.e., a unit runs into "energy" and the energy variable increases in value for that unit, but no other). From what I've read in "Programming in Objective-C, 2nd edition" I thought it would be ideal to have an object class for these units, and have each unit be an instance of that class. And for units that are defined from the start, it's looking good (nowhere near done programming yet).

    However, I wanted the units to be able to "reproduce" (i.e., if the energy variable's value goes above 50, a new unit/object instance is created). Is this possible with each unit being an instance object? I'm asking because when I make a method that returns an object instance (new unit), it looks like I have to define the new instance ahead of time:

    This works:
    Code:
    UnitsClass *newObject = [[UnitsClass alloc] init];
    newObject = [oldObject reproduce];
    This obviously doesn't:
    Code:
    newObject = [oldObject reproduce];
    (error: You are too old to start learning programming and probably drunk)


    But I can't have an alloc init for each new unit/instance that may or may not appear, because depending on how long the program runs it could have 5 new units or 50,000 new units.

    Thanks in advance for any help :)
     
  2. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    The alloc/init pair creates space for a new instance and init initialises it. You should only call this when you want a new/blank instance. In your example your reproduce method would create a new instance and populate it with the correct values. In this case you would not call alloc/init (the reproduce method would). You don't need alloc/init for each variable declaration: they are 100% not linked together.

    As you are going to have lots of instances I would suggest using a NSMutableArray or similar to hold them rather than loads of variables.
     
  3. Ja Di ksw thread starter macrumors 65816

    Ja Di ksw

    Joined:
    Apr 9, 2003
    #3
    Thank you for the help, I'll read up on NSMutableArrays, I'm not quite sure I understand what you mean, though.

    If I use "newObject = [oldObject reproduce];" without first saying that there is a "newObject" is gives the error "Use of undeclared identifier 'newObject'

    FWIW, the reproduce method contains "UnitsClass *newObject = [[UnitsClass alloc] init];" and gives it some values, but that has to be returned to something. I can't just say '[oldObject reproduce]' without setting it to equal another instance, and so don't I have to define that instance first?
     
  4. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    I did not say not to declare the variable. I said not to create a new instance and assign it to the variable. I think you need to step back and understand some fundamentals.

    What does = mean? How does

    Code:
    UnitsClass *newObject;
    
    differ from

    Code:
    UnitsClass *newObject = [[UnitsClass alloc] init];
    
    ?
     
  5. devilofspades, Oct 16, 2013
    Last edited: Oct 16, 2013

    devilofspades macrumors member

    Joined:
    Jul 20, 2011
    #5
    what you are asking to do can't really be done in objective-c, at least not the way you are wanting to go about doing it. you can't dynamically create variables and then allocate them. you would need to "pre configure" in your code variable names that can be accessed. so for instance you can't say "newObject1 = blah blah", and then magically create a newObject2, newObject3, newObject4, etc without statically specifying those names. you can how ever use arrays like the one poster mentioned. an array is a "container" of objects. a "mutable" array is a dynamic container of objects that automatically grows and shirks depending on how many objects are contained within. the objects are accessed by an "index" number handled by the array. so you could do something like

    Code:
    
    NSString *string1 = @"Monday";
    NSString *string2 = @"Tuesday";
    NSString *string3 = @"Wednesday";
    NSString *string4 = @"Thursday";
    NSString *string5 = @"Friday";
    
    NSMutableArray *myStringsArray = [[NSMutableArray alloc] init];
    
    [myStringsArray addObject:string1];
    [myStringsArray addObject:string2];
    [myStringsArray addObject:string3];
    [myStringsArray addObject:string4];
    [myStringsArray addObject:string5];
    
    
    you would then end up with a container of all those strings each accessible by an index number starting at 0. so if i wanted say "string3" i could do something like this

    Code:
     NSLog(@"%@ is Hump Day", [myStringsArray objectAtIndex:2]); 
    the resulting output would be
    Code:
     Wednesday is Hump Day 
    the power of arrays (and dictionaries) are there ability to store vast numbers of objects and to be able to do so dynamically. you can use them in for loops and add a dynamic amount of objects or even methods. so for instance you could do this

    Code:
     [myStringsArray addObject:[oldObject reproduce]]; 

    you could then use that later on and do something like

    Code:
     SomeClass *myNewThing = [myStringsArray objectAtIndex:5]; 
    the outcome would be your "myNewThing" would be the result of "[oldObject reproduce]".


    you can even store arrays & dictionaries in other arrays or dictionaries. this concept is referred to as "nested arrays" or "nested dictionaries".
     
  6. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #6
    Cocoa Core Competencies: Collection:
    https://developer.apple.com/library...conceptual/devpedia-cocoacore/Collection.html

    Collections Programming Topics:
    https://developer.apple.com/library/Mac/DOCUMENTATION/Cocoa/Conceptual/Collections/Collections.html

    These reference docs are already written, have been read by thousands of people, and are kept updated by Apple.


    If you didn't know about NSArray, or any other collection class, then you should probably read a more structured tutorial or book that covers these fundamental classes.
     
  7. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #7
    I prefer:

    Code:
    UnitsClass *newObject = nil;
    newObject = [oldObject reproduce];
    so that newObject isn't junk, even if I forget or mistype the following assignment.
     
  8. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #8
    Just saying: You should turn all reasonable warnings in Xcode, set "warnings = errors", and turn on the static analyzer.

    If you forget or mistype the following assignment, you get a warning that newObject isn't initialised, which is turned into an error, and your program will not build. By initialising newObject to nil, you prevent the compiler from checking.
     
  9. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #9
    I have yet to see evidence that this pedantic style of coding increases productivity for the most interesting software solutions.
     
  10. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #10
    It surely finds errors.

    It finds the mistakes that anybody makes while developing and fixes them quicker.

    It reduces the number of crashes when your code is in the hand of the customer.

    It improves what kind of code you write in the long term.
     
  11. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #11
    It also throws up all sorts of warnings because I'm trying to code in a way that will work for both OS X 10.5.0 (over 6 years old) and beyond OS X 10.9.0 (not yet released.) Supporting Leopard is trivial so I don't see a reason not to... it's supporting both Snow Leopard and Lion that makes me have to do things weird... plus supporting Core Solo...

    With new projects I'm going to be ditching Core Solo and Snow Leopard, but in the meantime since the code was written two years ago to support those platforms I'll just keep supporting them with this project... even though it means a long list of warnings.
     
  12. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #12
    Thus making errors, mistakes and bugs more important, and take up a greater percentage of limited brain cycles and neurons, than good creative solutions.
     
  13. devilofspades macrumors member

    Joined:
    Jul 20, 2011
    #13
    "newObject" well never be junk. objective-c always initializes new objects to nil. that first line of code is just redundant.
     
  14. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #14
    Sorry, that's only true for static storage and for instance vars. An 'auto' variable (i.e. defined within a function or method body, and not declared static) has an undefined value until it's been initialized or assigned a value. The C-recognized keyword for local variables is 'auto', as distinct from C's other storage-class keywords: static and register.

    Since the example is clearly executable code, it can only reside within a function or method body, and the implicit storage class of newObject will be auto.

    This behavior (or misbehavior) is inherited from C, whose standard defines no specific value for uninitialized auto variables.

    http://en.wikipedia.org/wiki/Automatic_variable
     
  15. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #15
    Apple disagree

     
  16. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #16
    When ARC is turned on.

    With ARC, when you set a strong object pointer to any value, the object pointed to before must be released, unless it was nil. If the pointer was uninitialised (filled with rubbish data), that would be impossible to do right, so object pointers can never be allowed to be uninitialised. Even

    Code:
    NSObject* myObject;
    myObject = nil;
    
    couldn't work if the compiler didn't initialise myObject to nil.
     
  17. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #17
    Sorry, the link I posted doesn't go directly to the correct section. I think this one does. It says nothing about ARC. It simply says the compiler will automatically set the variable to nil for you.
     
  18. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #18
    It's in the iOS documentation, and I think they make a strong assumption nowadays that everyone uses ARC on iOS.
     
  19. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #19
  20. devilofspades macrumors member

    Joined:
    Jul 20, 2011
    #20
    you're confusing objects with primitives. as i said, objects will always be set to nil as apple and other posters have said as well.
     
  21. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #21
    Only when ARC is enabled. Without ARC:

    Code:
    int main(int argc, const char * argv[])
    {
    
    	@autoreleasepool {
    		NSString* tmp;
    	    
    	    // insert code here...
    	    NSLog(@"tmp = %@", tmp);
    	    
    	}
        return 0;
    }
    
    Compiler says:
    /Users/.../main.m:18:25: warning: variable 'tmp' is uninitialized when used here /Users/.../main.m:15:16: note: initialize the variable 'tmp' to silence this warning

    Analyser says:
    /Users/../main.m:18:6: Function call argument is an uninitialized value
     
  22. devilofspades macrumors member

    Joined:
    Jul 20, 2011
    #22
    who doesn't use ARC these days? there isn't any rock solid reasons not to be using it at this point.
     
  23. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #23
    It doesn't mention ARC on that page, but the document as a whole definitely strikes me as being written with the assumption that ARC is enabled. AFAICT, they don't actually say this explicitly anywhere, but it becomes apparent in several places if one is already familiar with non-ARC conventions.

    There is a mention of ARC in the Introduction section:
    https://developer.apple.com/library...n.html#//apple_ref/doc/uid/TP40011210-CH1-SW1
    ...
    Objective-C apps use reference counting to determine the lifetime of objects. For the most part, the Automatic Reference Counting (ARC) feature of the compiler takes care of this for you. If you are unable to take advantage of ARC, or need to convert or maintain legacy code that manages an object’s memory manually, you should read Advanced Memory Management Programming Guide.
    Since they don't tell you the Advanced Memory Management Guide is required reading, it strongly suggests to me it that ARC will be used. If ARC weren't being used, or the document covered both memory management models equally, then a very different document would almost certainly result, because retain/release is a fundamental aspect, not a "See Also" one.

    Again, under "Encapsulating Data : Manage the Object Graph through Ownership and Responsibility" the concept of ownership and strong references is presented entirely as ARC rules, not retain/release.
    https://developer.apple.com/library...a.html#//apple_ref/doc/uid/TP40011210-CH5-SW3
    ... In Objective-C, an object is kept alive as long as it has at least one strong reference to it from another object. ...​
    This is clearly an ARC rule, not a retain/release one.

    There are other places throughout the document that the presumption of ARC is evident. The last one I found was in the Revision History:
    https://developer.apple.com/library....html#//apple_ref/doc/uid/TP40011210-CH99-SW1
    2012-07-20 New document that describes elements of best practice when writing code with Objective-C using ARC.
    The way I read that, they wrote a new document that tells how to write Objective-C using ARC.
     
  24. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #24
    Were we discussing that? No, we were discussing the fact that according to Apple's documentation the Objective-C compiler behaves in a way that is totally different from the behaviour of any C compiler in existence. And the fact that Apple's documentation doesn't mention the tiny little detail that it applies only to ARC.

    And there are some pretty good reasons for some people to not use ARC. For example, using non-ARC source code from third parties with a license that makes it very hard legally to make any changes to the source code. Or having an old code base that relies heavily on Core Foundation.

    So it's pretty important for many people that this applies only to ARC. And it is essential for everyone to know that htis applies only to Objective-C pointers, and not to any other pointers.
     
  25. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #25
    It doesn't compile for some targets. I forget which, but I tried using ARC in Battery Status and then discovered that roughly 30% of my users couldn't use the app anymore, so I shelved ARC.

    Same goes for array and dictionary literal notation.
     

Share This Page