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];
Related
I have a property that I am initializing in viewDidLoad, that is declared in my header file. In viewDidLoad I declare it here:
- (void)viewDidLoad {
[super viewDidLoad];
viewControllerList = [NSMutableArray new];
vc = [self.storyboard instantiateViewControllerWithIdentifier:#"moreSpeedyCafeViewController"];
[self loadDefaults];
self.dataSource = self;
In the loadDefaults method, I am iterating through an array and setting its properties. As I step through in the debugger, the values are nil even after being set. The values in the dictionary are not nil, I have checked that. I'm not sure why this is happening.
for (NSMutableDictionary *newDict in array) {
tempDict = newDict;
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[[tempDict objectForKey:#"ImageUrls"]objectAtIndex:0]]];
vc.dmsImageView.image = [UIImage imageWithData:imageData];
vc.dmsDescriptionLabel.text = [tempDict objectForKey:#"Title"];
vc.dmsLinkText.text = [tempDict objectForKey:#"LinkText"];
vc.index = [array indexOfObject:tempDict];
[viewControllerList addObject:vc];
}
I'm currently working on a video editing part where I capture the screenshots and some key values in dictionary. At the end when recording is done, I've an array of dictionaries.
Now I want this array of dictionary to upload to a server and later I want to download that array.
I've tried converting NSMutableArray to bytes and write it into text file and then I download the text file and convert it back to NSMutableArray.
The issue is that the dictionaries inside that NSMutableArray do not have key values.
Any other better way to upload and download this information on a server?
You should seperate your infomation and images.
Then upload them.
There an example:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//------------------This part is for upload------------------
//Upload info
UIImage* sourceImage = [UIImage imageNamed:#"source.png"];
UIImageView* imgV1 = [[UIImageView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
imgV1.backgroundColor = [UIColor redColor];
imgV1.image = sourceImage;
[self.view addSubview:imgV1];
NSDictionary* uploadDic = [[NSDictionary alloc] initWithObjectsAndKeys:
#"source.png",#"testImage",
nil];
NSData* uploadData = [NSJSONSerialization dataWithJSONObject:uploadDic options:NSJSONWritingPrettyPrinted error:nil];
NSString* uploadString = [[NSString alloc] initWithData:uploadData encoding:NSUTF8StringEncoding];
//Upload image
NSData* imageData = [NSData dataWithContentsOfFile:#"source.png"];
[self uploadInfoToURL:uploadString andImageData:imageData];
//-----------------------------------------------------------
//------------------This part is for upload------------------
//Download info
NSString *downLoadString = uploadString;
NSData* downLoadData = [downLoadString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *downLoadDic = [NSJSONSerialization JSONObjectWithData:downLoadData options:NSJSONReadingMutableContainers error:nil];
UIImageView* imgV2 = [[UIImageView alloc] initWithFrame:CGRectMake(50, 250, 100, 100)];
imgV2.backgroundColor = [UIColor blueColor];
[self.view addSubview:imgV2];
//Download image
NSString* downURL = [NSString stringWithFormat:#"http://youServer/%#",[downLoadDic objectForKey:#"testImage"]];
imgV2.image = [self getImageFromURL:downURL];
//-----------------------------------------------------------
}
-(UIImage *) getImageFromURL:(NSString *)fileURL {
NSLog(#"Begin download");
UIImage * result;
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];
result = [UIImage imageWithData:data];
return result;
}
-(BOOL *) uploadInfoToURL:(NSString *)infoString andImageData:(NSData *)data {
NSLog(#"Begin upload");
//Use http post to upload your image data to you server
// if (nil == error) {
// return YES;
// }
return NO;
}
Hope it can help you.
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...
I am developing one app in that getting images from array and display vertically in ScrollView.
when user double tapped on particular image i want that exact image store into plist according to tag value of that image, and retrieve that image later on when require.
i tried this one
// Store Data into plist.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *path = [NSString stringWithFormat:#"%#/myPlist.plist",
[paths objectAtIndex:0]];
// Place an image in a dictionary that will be stored as a plist
NSMutableDictionary * dictionary=[[NSMutableDictionary alloc]init];
[dictionary setObject:ImgView.tag forKey:#"image"];
NSLog(#"%#",dictionary);
// Write the dictionary to the filesystem as a plist
[NSKeyedArchiver archiveRootObject:dictionary toFile:path];
// For getting data from NSmutable array store it to the scrollview.
int m=0;
AppDelegate * delegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
delegate.front=TRUE;
delegate.back=FALSE;
UIScrollView *scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
[scrollView setPagingEnabled:YES];
[scrollView setShowsHorizontalScrollIndicator:NO];
FrontsCards=[[NSMutableArray alloc]initWithObjects:#"cloub1.png",#"cloub2.png",#"cloub3.png",#"cloub4.png",#"cloub5.png",#"cloub6.png",#"cloub7.png",#"cloub8.png",#"cloub9.png",#"cloub10.png",#"cloub11.png",#"cloub12.png",#"diamond1.png",#"diamond2.png",#"diamond3.png",#"diamond4.png",#"diamond5.png", nil];
for(m=0; m<[FrontsCards count];m++)
{
ImgView.alpha=1;
ImgView.tag=m;
int randIdx=arc4random()%[FrontsCards count];
NSString *imageName=[FrontsCards objectAtIndex:randIdx];
NSString *fullImageName=[NSString stringWithFormat:#"%#",imageName];
int padding=0;
CGRect imageViewFrame=CGRectMake(scrollView.frame.size.width*m+padding, scrollView.frame.origin.y, scrollView.frame.size.width-2*padding, scrollView.frame.size.height);
ImgView=[[UIImageView alloc]initWithFrame:imageViewFrame];
[ImgView setImage:[UIImage imageNamed:fullImageName]];
NSLog(#"%d",m);
// Place an image in a dictionary that will be stored as a plist
//[dictionary setObject:image forKey:#"image"];
// Write the dictionary to the filesystem as a plist
//[NSKeyedArchiver archiveRootObject:dictionary toFile:path];
[scrollView addSubview:ImgView];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapImgView:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.delegate = self;
[self.ImgView addGestureRecognizer:doubleTap];
self.ImgView.userInteractionEnabled=YES;
}
CGSize scrollViewSize=CGSizeMake(scrollView.frame.size.width*[FrontsCards count], scrollView.frame.size.height);
[scrollView setContentSize:scrollViewSize];
[self.view addSubview:scrollView];
help me out this thanks in advance.
Define this MACRO Definition at the top of your .m file
#define LIB_DIR_PATH NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0]
Use this function to Save Image to Plist with Image and Name
- (void)saveImage:(UIImage *)image WithName:(NSString *)imageName
{
// If File Exist then read it otherwise creat new
NSMutableDictionary *imageInfoDict;
if([[NSFileManager defaultManager] fileExistsAtPath:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]])
{
NSData *fileData = [NSData dataWithContentsOfFile:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]];
imageInfoDict = [NSMutableDictionary dictionaryWithDictionary:[NSKeyedUnarchiver unarchiveObjectWithData:fileData]];
}
else
imageInfoDict = [NSMutableDictionary dictionaryWithCapacity:0];
// Add Single Image to Dictionary
[imageInfoDict setValue:image forKey:imageName];
// Convert Main info Dictionary to `NSData` to Save on Disc
[NSKeyedArchiver archiveRootObject:imageInfoDict toFile:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]];
// To Read Stored Image Use Following Code
[self readImageFromPlistByKey:imageName];
}
This function returns image for respective name from Plist
-(UIImage *)readImageFromPlistByKey:(NSString *)keyName
{
// If File Exist then read it otherwise creat new
NSMutableDictionary *imageInfoDict;
if([[NSFileManager defaultManager] fileExistsAtPath:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]])
{
NSData *fileData = [NSData dataWithContentsOfFile:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]];
if([fileData length] > 0)
{
// Read Plist
imageInfoDict = [NSMutableDictionary dictionaryWithDictionary:[NSKeyedUnarchiver unarchiveObjectWithData:fileData]];
// Here is your Image
return imageInfoDict[keyName];
}
}
else
{
// Return Default Image if not Found
return [UIImage imageNamed:#"Default.png"];
}
}
If you are going to just store indexes, you need to have a master imageArray. I added insert/delete when user double taps the imageView twice.
- (void)doubleTapImgView:(UITapGestureRecognizer *)recognizer
{
UIImageView *imageView = (UIImageView *)recognizer.view;
[self insertorDeleteImageIndex:imageView.tag-1];
}
- (NSString *)plistFilePath{
NSString *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
return [documents stringByAppendingPathComponent:#"ImageIndexes.plist"];
}
- (void)insertorDeleteImageIndex:(NSInteger)index{
NSString *filePath = [self plistFilePath];
NSMutableArray *savedIndexes = [NSMutableArray arrayWithContentsOfFile:filePath];
if (!savedIndexes) {
savedIndexes = [NSMutableArray array];
}
if (![savedIndexes containsObject:#(index)]) {
[savedIndexes addObject:#(index)];
}else{
[savedIndexes removeObject:#(index)];
}
[savedIndexes writeToFile:filePath atomically:YES];
}
- (NSArray *)savedImageIndexes{
NSString *filePath = [self plistFilePath];
return [NSArray arrayWithContentsOfFile:filePath];
}
Source code
The code you post above can't be the real code as it wouldn't compile. That said, it shows a few errors:
You can't put basic numbers (NSInteger) into a dictionary, it needs to be boxed in an NSNumber.
You're setting the tag of the image before you create the instance of the image view (so either it will do nothing or set the wrong tag).
For saving the image, if you do want to save the image instead of the tag, you need to save it as data. You can store an image inside a dictionary no problem, but if you then want to store your dictionary as a plist you need to convert the image to NSData. You can get the image data using:
UIImageJPEGRepresentation(imageToSave, 0.8)
I have a tableView where the user can add contacts to. These contacts get saved to a mysql database and then returned to the user. Thing is, he has to update it manually in order to get the updated xml. But I wanna do it when he adds a contact so it gets shown right away. I tried various things and always ended up with either an error or he parsed the database more than once in the tableview. I thought of deleting all contacts and pasting all of them again and then update it, but this also didn't really work.
Here is how I do it at the moment:
To parse the XML:
- (void) doXMLParsing
{
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"Key22"] == nil) {
} else {
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.tabelle count]];
self.tableView.scrollEnabled = YES;
tabelle = [[NSMutableArray alloc] init];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *fileName = [prefs stringForKey:#"Key22"];
NSString *urlString = [NSString stringWithFormat: #"http://www.---.com/%#.xml", fileName];
NSURL *url = [NSURL URLWithString: urlString];
DataFileToObjectParser *myParser = [[DataFileToObjectParser alloc] parseXMLAtUrl:url toObject:#"Telefonbuch" parseError:nil];
for(int i = 0; i < [[myParser items] count]; i++) {
Telefonbuch *new = [[Telefonbuch alloc] init];
new = (Telefonbuch *) [[myParser items] objectAtIndex:i];
[tabelle addObject:new];
[self.tableView reloadData];
}
[XMLActivity stopAnimating];
}
}
In the viewDidLoad:
XMLActivity = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(140.0f, 290.0f, 40.0f, 40.0f)];
[XMLActivity setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:XMLActivity];
[XMLActivity startAnimating];
[self performSelector:#selector(doXMLParsing)
withObject:nil
afterDelay:0];
return;
tabelle = [[NSMutableArray alloc] init];
Everything works fine right now. I just want to reparse the XML after a new contact is added so it will get displayed right away.
Have you tried calling [reloadData][1] on your UITableView?
If this does not answer, could you explain what happens exactly when you parse xml a second time?
The solution was as obvious as simple, and I still wasted way too many time on this.
Here is the solution:
Just put
[self doXMLParsing];
at the end when you added a contact to the database.