1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

Saving UIColor on Exit

Discussion in 'iPhone/iPad Programming' started by larswik, Oct 15, 2011.

  1. macrumors 65816

    #1
    I am trying to save a UIColor to an NSMutableDictionary with other items when I use the back button my my NavController. Everything saves and loads again when I click on a button to create the ViewController from the plist file except for the UIColor which is 'null'? I added some NSLogs to see what was happening.

    If I delete my plist and start fresh here is what happens. This method checks for the plist file and creates it if it is not there, or loads the information.
    Code:
    - (void)readPlist{
        NSString *filePath = [self dataFilePath];
        if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
        {
            savedList = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
            
            
            NSArray *tempArray = [[NSArray alloc] initWithArray: [savedList objectForKey:@"monthly"]];
            checkNumbers = [[NSMutableArray alloc] initWithArray: tempArray copyItems:YES];
            [tempArray release];
            
            
            
            NSArray *tempArrayTwo = [[NSArray alloc] initWithArray: [savedList objectForKey:@"total"]];
            totalPayments = [[NSMutableArray alloc] initWithArray: tempArrayTwo copyItems:YES];
            [tempArrayTwo release];
            
            
            NSArray *tempArrayThree = [[NSArray alloc] initWithArray: [savedList objectForKey:@"item"]];
            NSLog(@"TempArrayThree %@", tempArrayThree);
            clientList = [[NSMutableArray alloc] initWithArray: tempArrayThree copyItems:YES];
            [tempArrayThree release];
            
            
            [COLOR="Red"]CGColorRef tmpColor = [[savedList objectForKey:@"backgroundColor"] CGColor];
            NSLog(@" Temp Color Loaded %@",[savedList objectForKey:@"backgroundColor"]);
            backDropColor = [[UIColor alloc] initWithCGColor:tmpColor];
            [COLOR="Blue"]NSLog(@"Color Loaded %@", backDropColor);[/COLOR][/COLOR]
        } 
        else{
            savedList = [[NSMutableDictionary alloc] init];
            [savedList writeToFile: filePath atomically:YES]; // if it can't find it, it writes a blank file.
            NSLog(@"No Plist on file - created new one");
            checkNumbers = [[NSMutableArray alloc] init];
            totalPayments = [[NSMutableArray alloc] init];
            clientList = [[NSMutableArray alloc] init];
           [COLOR="Red"] backDropColor = [[UIColor alloc] initWithRed: 0.7 green:0.7 blue:0.7 alpha:1.0];[/COLOR]
            [COLOR="Blue"]NSLog(@"BackGround Color load:%@ ", backDropColor);[/COLOR]
        }
    }
    
    When I write to my plist I have an NSLog that checks to see what is going to be saved.

    Code:
    - (void)writePlist{    
       [COLOR="Blue"] NSLog(@"BackGround Color to be saved:%@ ", backDropColor);[/COLOR]
        [savedList setObject:clientList forKey:@"item"];
        [savedList setObject:checkNumbers forKey:@"monthly"];
        [savedList setObject:totalPayments forKey:@"total"];
        [COLOR="Red"][savedList setObject: backDropColor forKey:@"backgroundColor"];[/COLOR]
        [savedList writeToFile:[self dataFilePath] atomically:YES];   
    }
    
    The console print out is this for the NSLog
    But when I try to reload it is returning a 'null'
    Code:
    CGColorRef tmpColor = [[savedList objectForKey:@"backgroundColor"] CGColor];
            [COLOR="Red"]NSLog(@" Temp Color Loaded %@",[savedList objectForKey:@"backgroundColor"]);[/COLOR]
            backDropColor = [[UIColor alloc] initWithCGColor:tmpColor];
            NSLog(@"Color Loaded %@", backDropColor);
    
    What am I over looking?
     
  2. macrumors 603

    ArtOfWarfare

    #2
    Memory management is my weak spot, but I think this is your issue: You never call retain on the color when you get it back. Try this:

    Code:
    CGColorRef tmpColor = [[[savedList objectForKey:@"backgroundColor"] CGColor] retain];
     
  3. macrumors 68040

    #3
    UIColor is not a valid type to store in a property list. You'll need to convert it to NSData first.

    It doesn't matter if tmpColor is not retained, because its just being used to initialize a UIColor a few lines later. tmpColor doesn't need to exist once the method it is in returns.
     
  4. macrumors 65816

    #4
    No I got an error Method -retain not found (return type defaults to ID). I did not think I needed to retain it because within the same method it is being passed to backDropColor which I alloc and init with the tmpColor so I am passing the responsibilities to that object to retain it, which I dealloc later.

    Or am I not allowed to store a UIColor in a Dict?
     
  5. macrumors 68040

    #5
    Look at my last post again.

    P.S. You can't call retain on a CGColorRef because it's a CoreFoundation type and therefore doesn't inherit from NSObject. You -can- call the C functions CGColorRetain and CGColorRelease on it, but as I said that's not the issue.
     
  6. macrumors 603

    #6
    Or get the red, green, and blue values as CGFloats, convert each CGFloat to an NSNumber, then store those NSNumbers in the plist, such as in a sub-dictionary with keys "red", "green", and "blue".
     
  7. macrumors 65816

    #7
    admanimal- I must have cross posted, I did not see the original post. I am actually happy with the responses that you and Chown33 said because in the back of my mind I was thinking of both. I have never used NSData so this will be a good chance. If that would to have failed I thought I might be able to break it down into separate int values and store an an NSNumbers like Chown mentioned and store them in the Dict.

    Thanks for then help and explanation as to why I could not store UIColor in a property list.
     
  8. macrumors 68000

    Sydde

    #8
    UIColor does not have built-in methods for converting to/from NSData, so you will have to use coders, such as NSKeyedArchiver/NSKeyedUnarchiver to handle this if NSData is the way you want to go.
     
  9. macrumors 65816

    #9
    I am already ahead of you on that one :) The code works perfectly now

    Code:
    - (void)writePlist{    
        CGColorRef tmpColor = [self.view.backgroundColor CGColor];
        backDropColor = [[UIColor alloc] initWithCGColor:tmpColor];
        NSData *backGroundColorStorage = [NSKeyedArchiver archivedDataWithRootObject:backDropColor];
        
        [savedList setObject:clientList forKey:@"item"];
        [savedList setObject:checkNumbers forKey:@"monthly"];
        [savedList setObject:totalPayments forKey:@"total"];
        [savedList setObject:backGroundColorStorage forKey:@"backgroundColor"];
        [savedList writeToFile:[self dataFilePath] atomically:YES];
    }
    I don't understand how you guys remember all this stuff. Maybe when you fully understand the paradigm it becomes transparent how everything functions.
     
  10. macrumors 68040

    #10
    We might remember some stuff, but we're also experts at using the documentation.
     
  11. macrumors 603

    #11
    For example, the initial problem was related to loading from a plist file. So a reasonable first guess at which documentation to review would be the Property List Programming Guide. If one didn't remember the name of the document, one could still search for keywords like property list.

    And we don't forget how to break things down into smaller solvable problems. That process works the same no matter what language or framework you're using. So after determining that UIColor isn't allowed in a plist, the way to solve the problem is to break it down. There are a few ways to break it down, as already outlined: NSData, a set of 3 NSNumbers, keyed archiver. It's just a matter of picking one, based on a suitable reason.
     
  12. macrumors 65816

    #12
    I did not think to look at the plist because it seemed to be a couple of steps away from my problem. I knew the colors changed on the screen, and I could NSLog what was stored in my object which returned 3 values for the RGB, so I knew my UIColor was fine.

    The next logical step for 'me' I took was to store it in an NSMutableDict. I knew my UIColor was an object and I could store objects in a Dict, or so I thought. I did not think that it could be the plist at that point.

    I still need to read up on NSData since I don't fully understand what it is doing. I am guessing that it is a wrapper of some kind, kind of like when I need to store an int as an object I need to put it into an NSNumber object 'wrapper'.

    Thank you!
     
  13. macrumors 603

    #13
    Why guess at all? Why draw any preconceived ideas, which may prove to be wrong?

    I think it's much better to approach something unknown with an open mind, rather than preconceptions about it. For one thing, it makes me more likely to see what's really there, rather than interpreting what I see through preconceived expectations. Simple ignorance is easier to remedy than misconceptions, because nothing must first be unlearned.
     
  14. macrumors 65816

    #14
    Ahhh, but the 'unknown' is a tricky area sometimes for me. I try to approach problems in 2 ways, one use the tools I have learned so far to solve the problems, or keep an open mind and learn what I need to do to solve the new problem via doc's, web search or help.

    Originally this did not present its self as an unknown problems since I know how to use NSMutableDicts to store and retrieve object in them. I thought there was a problem with the tools I was already using in my understanding of them. What I learned now is to look past what I think is the obvious problem at hand.

    Thanks Chown33 for you help.
     

Share This Page