UIDevice Not Returning Properly Retained NSStrings?

Discussion in 'iOS Programming' started by kalimba, Feb 11, 2009.

  1. kalimba macrumors regular

    Joined:
    Jun 10, 2008
    #1
    I'm writing a class that uses the UIDevice class to obtain information about the device on which my application is running. My class queries certain properties from the [UIDevice currentDevice] and caches the returned NSStrings in class members.

    On the simulator, for certain UIDevice properties -- 'name' and 'model' -- I'm getting NSStrings returned with retain counts of 2147483647. For the other properties I'm querying -- 'uniqueIdentifier', 'systemName' and 'systemVersion' -- I'm getting NSStrings with (proper) retain count of 1.

    Additionally, when I run on my device, the behavior changes slightly in that the 'name' property suddenly works correctly and returns an NSString with retain count of 1. Although the 'model' property still returns an NSString with retain count of 2147483647.

    Has anyone else seen this behavior? Is this a known issue?
     
  2. caveman_uk Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #2
    The strings returned should all be autoreleased objects.
     
  3. kalimba thread starter macrumors regular

    Joined:
    Jun 10, 2008
    #3
    Right. Which means the 'temp' string in the snippet below should have a retain count of 1, correct?
    Code:
    UIDevice *	device = [UIDevice currentDevice];
    	
    NSString * temp = [device model];
    NSLog( @"temp.retainCount is %u", temp.retainCount );
    
    I'm definitely seeing a retain count of 2147483647 on the NSString returned using this code.
     
  4. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    Why are you using %u? retainCount returns a NSUInteger which is an int (on a 32-bit architecture). %u is for unsigned ints, not signed ones. You should use %i.
     
  5. caveman_uk Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #5
    Isn't 2147483647 = -1 when you use unsigned instead of signed?
     
  6. kalimba thread starter macrumors regular

    Joined:
    Jun 10, 2008
    #6
    I can guarantee that this is not the real problem here. Replacing my %u with a %i won't change the fact that the NSString has a retain count of 2147483647.
     
  7. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #7
    Yes it will: by using %u you are telling NSLog to treat that binary value as unsigned. As it is a signed value you should be using %i. This is very basic Computer Science. I'd suggest reading up on Two's Complement for an explanation of how signed numbers are actually stored. Note the two's complement representation of -1. Now think of how that would be interpreted if it was unsigned. You will soon see that the retain count is not, in fact, 2147483647.
     
  8. kalimba thread starter macrumors regular

    Joined:
    Jun 10, 2008
    #8
    I don't have a hex/decimal calulator handy, but this is also what I suspect. Actually, I was thinking it was 0x7FFFFFFF, and after some Googling I've found that my other suspicion -- that the crazy retain count occurs when static strings are returned -- is probably correct. I suspect the "model" getter is always returning a static string.

    Apparently, this is correct behavior. :eek:
     
  9. kalimba thread starter macrumors regular

    Joined:
    Jun 10, 2008
    #9
    I appreciate the help, but I am aware of points you're trying to make. I understand that interpreting the same pattern of bits as a signed value is different from that as an unsigned value. My point was not that that retain count was "2147483647" vs. "-1", but that it was not the value (1) that I was expecting.

    BTW, in theory, the string formatting change you suggested should have changed the display from "2147483647" to "-1" for the retain count, but even with that change, the value still shows as "2147483647". Weird.
     
  10. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #10
    This is a compiler option I think: to turn static strings in the code (@"My String" style strings) into static objects. It can reduce memory footprint as two identical strings created this way will, in fact, be the same object. As NSStrings are immutable it's perfectly safe to do this...
     
  11. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #11
    I don't believe statics work this way. And you shouldn't need to be worried about the retain count for a static. That's the compiler's job.
     
  12. kalimba thread starter macrumors regular

    Joined:
    Jun 10, 2008
    #12
    I'm not sure if you're saying I shouldn't retain the returned string, or that I just shouldn't worry about the details. I'm obligated to retain whatever NSString UIDevice (or any other class API, for that matter) returns me, whether it is static or not, so that's the approach I'm taking.

    Just for some background, I started peeking at the retain counts to make sure that I was retaining and releasing the NSString objects properly. I was a little confused to find a retain count of 0x7FFFFFFF, but now that I understand what it means, I realize that I'm doing things correctly.
     
  13. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #13
    Are you allocating space for the returned string? Based on your code above, I'd say no. (NSString * temp = [device model];) You're just creating a pointer to the space it already occupies. Therefore, you don't need to retain it.
     
  14. kalimba thread starter macrumors regular

    Joined:
    Jun 10, 2008
    #14
    I am admittedly a newb to Objective-C/Cocoa/iPhone programming, but that goes against nearly everything I've read regarding proper memory management in this environment. Perhaps what you're saying applies to the code snippet I posted which uses the "temp" variable, but if you go back to my OP, you'll see how I'm actually using the NSString objects returned from UIDevice.
    So what I'm doing is querying the UIDevice for the values and keeping them around in my singleton class for the duration of the application. If I don't retain the NSString objects UIDevice returns to me, I run the risk of having a dangling pointer, since those NSString objects are autoreleased.
     
  15. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #15
    I would just define those variables as NSString * then. I don't think you get any benefit from "re-storing" the value of those NSStrings within your singleton. Unless you are planning on changing them...
     

Share This Page