Keep UIButton background change after click - ios

I'm trying to make a button's background change from background1 to background2 when it's clicked and stay on background2 even when the app is restarted.
I've managed to do that, but when I restart the app the background is malformed ( the background2 is a transparent circle) its showing the circle, but the transparent part becomes white..
The button is a custom one.
Any ideas?
Thanks guys

The problem were in the NSUserDefaults saving process, I now use this :
NSData *imageData = UIImagePNGRepresentation(contactImage);
Instead of :
NSData *imageData = UIImageJPEGRepresentation(contactImage, 100);

Hi this will be useful to you..
- (void)viewDidLoad
{
[super viewDidLoad];
NSData *colorData = [[NSUserDefaults standardUserDefaults] objectForKey:#"BackgroundColor"];
if (colorData != nil)
{
NSString *stringColor = [NSKeyedUnarchiver unarchiveObjectWithData:colorData];
CIColor *coreColor = [CIColor colorWithString:stringColor];
UIColor *color = [UIColor colorWithCIColor:coreColor];
[self.btnNext setBackgroundColor:color];
}
}
- (IBAction)next:(id)sender
{
[self.btnNext setBackgroundColor:[UIColor clearColor]];
CGColorRef colorRef = [UIColor clearColor].CGColor;
NSString *colorString = [CIColor colorWithCGColor:colorRef].stringRepresentation;
NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:colorString];
[[NSUserDefaults standardUserDefaults] setObject:colorData forKey:#"BackgroundColor"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
I have checked in ios 7 3.5 inch screen it is working..
but donot know on other deveices...

Related

How to copy a button in iOS using NSKeyedArchiver

To copy a button, this has been working fine:
NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject: btn];
UIButton *newButton = [NSKeyedUnarchiver unarchiveObjectWithData: archivedData];
However since iOS12, this has been deprecated. But using the suggested method, causes the newButton to be nil. What am I doing wrong or indeed is there an alternative way to copy a UIButton. Full code:
// Init originalBtnsArray and
originalBtnsArray = [[NSMutableArray alloc]init];
// Populate originalBtnsArray
for (UIButton *btn in btnsReferencesArray){
// Below works but is now deprecated as of iOS 12
//NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject: btn];
//UIButton *newButton = [NSKeyedUnarchiver unarchiveObjectWithData: archivedData];
NSError* error = nil;
NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:btn requiringSecureCoding:NO error:&error];
NSError* unArchiveError = nil;
UIButton *newButton = [NSKeyedUnarchiver unarchivedObjectOfClass:[UIButton class] fromData:archivedData error:&unArchiveError];
// newButton is nil, which is suboptimal
[originalBtnsArray addObject:newButton];
}
Got it working now:
UIButton *newButton = [[UIButton alloc]init];
newButton.frame = btn.frame;
[originalBtnsArray addObject:newButton];

Star rating view with user default in objective c

I have a star rating view which uses custom class RateView.m and .h files to show the star rating image and a label to show how much rating is given as given below:
Now when the rating is clicked, the selected image is shown and when unselected another image is shown.
This Rateview calls a delegate when that rateview is clicked
- (void)rateView:(RateView *)rateView ratingDidChange:(float)rating {
self.statusLabel.text = [NSString stringWithFormat:#"Rating: %0.1f/5.0", rating];
NSString *valueToSave = self.statusLabel.text;
// self.rateView.fullSelectedImage = [UIImage imageNamed:#"yellow-rating.png"];
// UIImage *contactImage = self.rateView.fullSelectedImage;
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:#"ratingSelected"];
// [[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(contactImage) forKey:#"image"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
In viewwillappear method it is as shown:
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSString *savedValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"ratingSelected"];
self.statusLabel.text = savedValue;
NSData *imageData = [[NSUserDefaults standardUserDefaults] objectForKey:#"image"];
// NSLog(#"imagedata is %#",imageData);
UIImage *contactImage = [UIImage imageWithData:imageData];
NSLog(#"contactImage is %#",contactImage);
// self.rateView.fullSelectedImage = contactImage;
self.rateView.fullSelectedImage = [UIImage imageNamed:#"yellow-rating.png"];
}
Now the issue is i can see the label with correct rating,but the image is not saved using userdefault.
How to also save the image using userdefault in my case.
You can save image to disc (for example Document directory) and store only image's path in NSUserDefaults
See this answer

Save user settings in iPhone/iPad app [duplicate]

This question already has answers here:
How to store custom objects in NSUserDefaults
(7 answers)
Closed 8 years ago.
In my app I let users to pick a colour of background, tint and text. How can I save this settings after the app is closed? I mean when user again starts the app he wants to see the background, tint and text colour from previous usage.
This is how I have set the colours.
self.BackgroundView.backgroundColor = [UIColor colorWithRed:248.0/255.0 green:242.0/255.0 blue:229.0/255.0 alpha:1.0];
[[[self navigationController] navigationBar] setTintColor:[UIColor colorWithRed:103.0/255.0 green:10.0/255.0 blue:10.0/255.0 alpha:1.0]];
self.QuoteText.textColor = [UIColor colorWithRed:131.0/255.0 green:21.0/255.0 blue:21.0/255.0 alpha:1.0];
Trying to solve by following Greg's (probably the right) answer gives SIGABRT error by clicking on following button:
- (IBAction)setcolor:(id)sender {
UIColor *backgroundColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:220.0/255.0 alpha:1.0];
self.BackgroundView.backgroundColor = backgroundColor;
UIColor *tintColor = [UIColor colorWithRed:129.0/255.0 green:165.0/255.0 blue:148.0/255.0 alpha:1.0];
[[[self navigationController] navigationBar] setTintColor:tintColor];
UIColor *textColor = [UIColor colorWithRed:0.0/255.0 green:98.0/255.0 blue:139.0/255.0 alpha:1.0];
self.QuoteText.textColor = textColor;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:backgroundColor forKey:#"BACKGCOLOR"];
[defaults setObject:tintColor forKey:#"TINTCOLOR"];
[defaults setObject:textColor forKey:#"TEXTCOLOR"];
[defaults synchronize];
}
If user pick up colour instead of
self.BackgroundView.backgroundColor = [UIColor colorWithRed:248.0/255.0 green:242.0/255.0 blue:229.0/255.0 alpha:1.0];
You can do
UIColor *backgroundColor = [UIColor colorWithRed:248.0/255.0 green:242.0/255.0 blue:229.0/255.0 alpha:1.0];
self.BackgroundView.backgroundColor = backgroundColor;
NSData *backgroundColorData = [NSKeyedArchiver archivedDataWithRootObject:backgroundColor];
UIColor *tintColor = [UIColor colorWithRed:103.0/255.0 green:10.0/255.0 blue:10.0/255.0 alpha:1.0];
[[[self navigationController] navigationBar] setTintColor:tintColor];
NSData *tintColorData = [NSKeyedArchiver archivedDataWithRootObject: tintColor];
UIColor *textColor = [UIColor colorWithRed:131.0/255.0 green:21.0/255.0 blue:21.0/255.0 alpha:1.0];
self.QuoteText.textColor = textColor;
NSData *textColorData = [NSKeyedArchiver archivedDataWithRootObject: textColor];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject: backgroundColorData forKey:#"BACKGCOLOR"];
[defaults setObject:tintColorData forKey:#"TINTCOLOR"];
[defaults setObject:textColorData forKey:#"TEXTCOLOR"];
[defaults synchronize];
You do the same for tint and text colour (just use different key).
In the view controller where you want to change your view colour in viewDidLoad you do:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *backgColorData = [defaults objectForKey:#"BACKGCOLOR"];
UIColor *backgColor = [NSKeyedUnarchiver unarchiveObjectWithData:backgColorData];
NSData *tintColorData = [defaults objectForKey:#"TINTCOLOR"];
UIColor *tintColor = [NSKeyedUnarchiver unarchiveObjectWithData:tintColorData];
NSData *textColorData = [defaults objectForKey:#"TEXTCOLOR"];
UIColor *textColor = [NSKeyedUnarchiver unarchiveObjectWithData: textColorData];
if (backgColor)
self.BackgroundView.backgroundColor = backgColor;
if (tintColor)
[[[self navigationController] navigationBar] setTintColor:tintColor];
if (textColor)
self.QuoteText.textColor = textColor;
Apple is providing the NSUserDefaults for this, it does act like the preferences for your user / application. Example taken from here
Saving :
NSString *valueToSave = #"someValue";
[[NSUserDefaults standardUserDefaults]
setObject:valueToSave forKey:#"preferenceName"];
To get it back later :
NSString *savedValue = [[NSUserDefaults standardUserDefaults]
stringForKey:#"preferenceName"];
Test using nsuserdefaults to save the settings or, write to a plist.

UIGraphicsGetImageFromCurrentImageContext() - Memory Leak

I am opening the camera with UIImagePickerControllerSourceTypeCamera and a custom cameraOverlayView so I can take multiple photos without the "Use Photo" step.
This is working great, but there is a memory leak in the save photo function. Through a lot of debugging and research I have narrowed it down to the UIGraphicsGetImageFromCurrentImageContext function.
Here is a snippet of code where it happens:
UIGraphicsBeginImageContextWithOptions(timestampedImage.frame.size, timestampedImage.opaque, [[UIScreen mainScreen] scale]);
[[timestampedImage layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *finalTimestampImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I have scoured the internet and it seems that the UIGraphicsGetImageFromCurrentImageContext() function (quoted from this SO question) "returns a new autoreleased UIImage and points the finalTimestampImage ivar to it. The previously allocated UIImage is never actually released, the variable to it is just repointed to somewhere else."
I've tried so many solutions that have apparently worked for others:
Adding timestampedImage.layer.contents = nil; after UIGraphicsEndImageContext
Adding CGContextRef context = UIGraphicsGetCurrentContext(); and CGContextRelease(context); after UIGraphicsEndImageContext
Wrapping the above snippet in an NSAutoreleasePool
Wrapping the entire saveThisPhoto function in an NSAutoreleasePool
Creating an NSAutoreleasePool when the camera pops up and calling the [pool release] when didReceiveMemoryWarning is called
Closing the camera popup when didReceiveMemoryWarning is called, hoping it will clear the pool
Every possibly combination of the above
Yet everything I try, when I take photos I can see the Memory Utilized rising and not falling when I'm repeatedly taking photos on the device.
Does anyone know how I can release the autorelease object created by UIGraphicsGetImageFromCurrentImageContext?
Alternatively, is there an alternative way to make a UIImage out of an UIImageView?
Edit:
Here are the full functions as requested. There's a lot of extra releasing added in there just to try make sure everything is cleaned up. I have gone through and tested for the memory leak with each code block in saveThisPhoto systematically, and it only occurs when the UIGraphicsGetImageFromCurrentImageContext block (snippet above) is run.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSLog(#"SAVING PHOTO");
[self saveThisPhoto:info];
picker = nil;
[picker release];
info = nil;
[info release];
}
- (void)saveThisPhoto:(NSDictionary *)info {
// Get photo count for filename so we're not overriding photos
int photoCount = 0;
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"photocount"]) {
photoCount= [[[NSUserDefaults standardUserDefaults] objectForKey:#"photocount"] intValue];
photoCount++;
}
[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:#"%d", photoCount] forKey:#"photocount"];
[[NSUserDefaults standardUserDefaults] synchronize];
// Obtaining saving path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [NSString stringWithFormat:#"ri_%d.jpg", photoCount];
NSString *fileNameThumb = [NSString stringWithFormat:#"ri_%d_thumb.jpg", photoCount];
NSString *imagePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSString *imagePathThumb = [documentsDirectory stringByAppendingPathComponent:fileNameThumb];
// Extracting image from the picker and saving it
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
// SAVE TO IPAD AND DB
if ([mediaType isEqualToString:#"public.image"]){
// Get Image
UIImage *editedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
// Figure out image orientation
CGSize resizedSize;
CGSize thumbSize;
if (editedImage.size.height > editedImage.size.width) {
resizedSize = CGSizeMake(480, 640);
thumbSize = CGSizeMake(150, 200);
} else {
resizedSize = CGSizeMake(640, 480);
thumbSize = CGSizeMake(150, 113);
}
// MAKE NORMAL SIZE IMAGE
UIImage *editedImageResized = [editedImage resizedImage:resizedSize interpolationQuality:0.8];
// clean up the one we won't use any more
editedImage = nil;
[editedImage release];
// ADD TIMESTAMP TO IMAGE
// make the view
UIImageView *timestampedImage = [[UIImageView alloc] initWithImage:editedImageResized];
CGRect thisRect = CGRectMake(editedImageResized.size.width - 510, editedImageResized.size.height - 30, 500, 20);
// clean up
editedImageResized = nil;
[editedImageResized release];
// make the label
UILabel *timeLabel = [[UILabel alloc] initWithFrame:thisRect];
timeLabel.textAlignment = UITextAlignmentRight;
timeLabel.textColor = [UIColor yellowColor];
timeLabel.backgroundColor = [UIColor clearColor];
timeLabel.font = [UIFont fontWithName:#"Arial Rounded MT Bold" size:(25.0)];
timeLabel.text = [self getTodaysDateDatabaseFormat];
[timestampedImage addSubview:timeLabel];
// clean up what we won't use any more
timeLabel = nil;
[timeLabel release];
// make UIIMage out of the imageview -- MEMORY LEAK LOOKS LIKE IT IS IN THIS BLOCK
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIGraphicsBeginImageContextWithOptions(timestampedImage.frame.size, timestampedImage.opaque, [[UIScreen mainScreen] scale]);
[[timestampedImage layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *finalTimestampImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
timestampedImage.layer.contents = nil;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRelease(context);
// clean up the one we won't use any more
timestampedImage = nil;
[timestampedImage release];
// SAVE NORMAL SIZE IMAGE TO DOCUMENTS FOLDER
NSData *webDataResized = UIImageJPEGRepresentation(finalTimestampImage, 1.0); // JPG
[webDataResized writeToFile:imagePath atomically:YES];
// clean up the one we won't use any more
finalTimestampImage = nil;
[finalTimestampImage release];
[pool release]; // to get rid of the context image that is stored
// SAVE TO DATABASE
[sqlite executeNonQuery:#"INSERT INTO inspection_images (agentid,groupid,inspectionid,areaid,filename,filenamethumb,filepath,orderid,type) VALUES (?, ?, ?, ?, ?, ?, ?, ?,?) ",
[NSNumber numberWithInt:loggedIn],
[NSNumber numberWithInt:loggedInGroup],
myInspectionID,
[[tableData objectAtIndex:alertDoMe] objectForKey:#"areaid"],
fileName,
fileNameThumb,
documentsDirectory,
[NSNumber numberWithInt:photoCount],
[NSNumber numberWithInt:isPCR]
];
// Clean up
webDataResized = nil;
[webDataResized release];
} else {
NSLog(#">>> IMAGE ***NOT*** SAVED");
}
NSLog(#"IMAGE SAVED - COMPLETE");
info = nil;
[info release];
}
You're setting your variables to nil before releasing them, and some are already auto released.
Normally when using release you should release and them set to nil.
[var release]
var = nil;
But in some of these you should not be calling release.
The following one is your main culprit.
// clean up the one we won't use any more
timestampedImage = nil;
[timestampedImage release];
// SAVE NORMAL SIZE IMAGE TO DOCUMENTS FOLDER

Can not get color from NSUserDefaults at first app launch

I have a big problem and could not solve it for few days already.
When app loads at first time, I'm saving 4 colors to NSUserDeafaults in first UIViewController.
ViewController.m
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSUserDefaults *sharedDefaults = [NSUserDefaults standardUserDefaults];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger countValue = [defaults integerForKey:#"Array"];
if ([sharedDefaults boolForKey:#"FirstLaunch"])
{
[self openSubView];
[sharedDefaults setBool:NO forKey:#"FirstLaunch"];
[sharedDefaults synchronize];
[self saveColorsToDefaults];
// [prefs synchronize];
} // Do any additional setup after loading the view.
else if(countValue == 1)
{
}
}
-(void)saveColorsToDefaults{
const CGFloat *components1 = CGColorGetComponents([UIColor darkGrayColor].CGColor);
const CGFloat *components2 = CGColorGetComponents([UIColor blueColor].CGColor);
const CGFloat *components3 = CGColorGetComponents([UIColor redColor].CGColor);
const CGFloat *components4 = CGColorGetComponents([UIColor purpleColor].CGColor);
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setFloat:components1[0] forKey:#"cr"];
[prefs setFloat:components1[1] forKey:#"cg"];
[prefs setFloat:components1[2] forKey:#"cb"];
[prefs setFloat:components1[3] forKey:#"ca"];
[prefs setFloat:components2[0] forKey:#"cr2"];
[prefs setFloat:components2[1] forKey:#"cg2"];
[prefs setFloat:components2[2] forKey:#"cb2"];
[prefs setFloat:components2[3] forKey:#"ca2"];
[prefs setFloat:components3[0] forKey:#"cr3"];
[prefs setFloat:components3[1] forKey:#"cg3"];
[prefs setFloat:components3[2] forKey:#"cb3"];
[prefs setFloat:components3[3] forKey:#"ca3"];
[prefs setFloat:components4[0] forKey:#"cr4"];
[prefs setFloat:components4[1] forKey:#"cg4"];
[prefs setFloat:components4[2] forKey:#"cb4"];
[prefs setFloat:components4[3] forKey:#"ca4"];
[prefs synchronize];
NSLog(#"I just saved colors");
}
And after I need to set these colors to `DrawViewControllers drawing instruments.
I can get only last 3 colors but 1st color does not apears.
But when I set color for 1st instrument via colorPicker and save all the colors again to NSUserDefaults it works great!
-(void)LoadColorsAtStart
{
NSUserDefaults *prefers = [NSUserDefaults standardUserDefaults];
UIColor* tColor = [UIColor colorWithRed:[prefers floatForKey:#"cr"] green:[prefers floatForKey:#"cg"] blue:[prefers floatForKey:#"cb"] alpha:[prefers floatForKey:#"ca"]];
UIColor* tColor2 = [UIColor colorWithRed:[prefers floatForKey:#"cr2"] green:[prefers floatForKey:#"cg2"] blue:[prefers floatForKey:#"cb2"] alpha:[prefers floatForKey:#"ca2"]];
UIColor* tColor3 = [UIColor colorWithRed:[prefers floatForKey:#"cr3"] green:[prefers floatForKey:#"cg3"] blue:[prefers floatForKey:#"cb3"] alpha:[prefers floatForKey:#"ca3"]];
UIColor* tColor4 = [UIColor colorWithRed:[prefers floatForKey:#"cr4"] green:[prefers floatForKey:#"cg4"] blue:[prefers floatForKey:#"cb4"] alpha:[prefers floatForKey:#"ca4"]];
[prefers synchronize];
[self extractRGBforBlack:tColor];
[self extractRGBforBlue:tColor2];
[self extractRGBforRed:tColor3];
[self extractRGBforLine:tColor4];
[self.colorBar1 setTextColor:self.blackExtract];
[self.colorBar2 setTextColor:self.blueExtract];
[self.colorBar3 setTextColor:self.redExtract];
[self.colorBar4 setTextColor:self.lineExtract];
NSLog(#"I have extracted colors");
}
I have 5 similar DrawViewControllers and all works with Drawing UIView.
1.Store UIColor as nsdata into nsuserdefaults
NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:color];
2.Retrive UIColor from viewdidload
UIColor *color = [NSKeyedUnarchiver unarchiveObjectWithData:colorData];
Try this it will work without error
1.Store UIColor as NSString into NSUserDefaults
-(void)storeColor
{
NSString *colString = [NSString stringWithFormat:#"%#", [UIColor whiteColor]];
[[NSUserDefaults standardUserDefaults] setObject:colString forKey:#"keyFontColor"];
}
2.Convert string into UIColor while retrieve
-(void)retriveColor
NSArray *values = [[[NSUserDefaults standardUserDefaults] objectForKey:#"keyFontColor"] componentsSeparatedByString:#" "];
NSLog(#"%d",[values count]);
UIColor *def_color = [[UIColor alloc] init];
if ([values count]==5) {
CGFloat red = [[values objectAtIndex:1] floatValue];
CGFloat green = [[values objectAtIndex:2] floatValue];
CGFloat blue = [[values objectAtIndex:3] floatValue];
CGFloat alpha = [[values objectAtIndex:4] floatValue];
def_color = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
self.dateLabel.textColor = def_color;
}
else if ([values count]==3)
{
CGFloat white = [[values objectAtIndex:1] floatValue];
CGFloat alpha = [[values objectAtIndex:2] floatValue];
def_color = [UIColor colorWithWhite:white alpha:alpha];
self.label.textColor = def_color;
}
else
{
// its store default value while app loads first time
self.label.textColor.textColor = [UIColor blackColor];
}
}

Resources