Updating UITextField with contact info selected from iPhone Contacts - objective-c

After calling the PeoplePicker and selecting an entry from Contacts I can't seem to get the selected contact information to display in my view. Following Apple's Address Book Programming Guide for iOS, I display the People Picker modally and make a selection. Apple's code examples have the information being displayed in UILabels while I, because I also allow the user to manually input information into the text fields in the same view controller, need to have the information displayed in UITextFields. I've proved that the selected data winds up in the target UITextField (which is named "contactName") by printing to the console. The problem is, the selected data is not displayed in the view. When the user inputs manually, there is no problem. I just can't figure out how to transfer the data from the Address Book into the UITextFields in the view controller.
I've been trying for days, but can't resolve this issue. I'm probably overlooking something very basic. I'm new at this, so any help will be appreciated.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
// NSString* name = (NSString *)ABRecordCopyValue(person,kABPersonFirstNameProperty);
NSString *name = [NSString stringWithFormat:#"%# %#",ABRecordCopyValue(person,kABPersonFirstNameProperty), ABRecordCopyValue(person,kABPersonLastNameProperty)];
self.contactName.text = name; // 11/17/11
NSLog(#"%#", name);
// [name release]; Commenting out this code prevents the app from freezing when a name is selected from the picker. 11/25/11
NSLog(#"%#",self.contactName.text); // 11/17/11
// 11/16/11 add additional contact info here
[self dismissModalViewControllerAnimated:YES];
return NO;
}

As of iOS 6, [self dismissModalViewControllerAnimated] is deprecated. If you try this, your code will work.
[self dismissViewControllerAnimated:YES completion:^(void) {
NSString *name = [NSString stringWithFormat:#"%#", ABRecordCopyValue(person, kABPersonFirstNameProperty)];
contactName.text=name;
}];

-(IBAction)addToAddressbook:(id)sender{
NSString *fname=#"firstname";
NSString *lname=#"lastname";
NSArray *arrayAdd=[[NSArray alloc]initWithObjects:#"street Name",#"city Name",#"country code",#"zip",nil];
UIImage *image=[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"ambani.png" ofType:nil]];
[self addContact:fname:lname:arrayAdd:image];
}
-(void) addContact:(NSString *)firstname:(NSString *)lastname:(NSArray *)arrayAddress:(UIImage *)currentImage
{
ABAddressBookRef addressBook=ABAddressBookCreate();
ABRecordRef person=ABPersonCreate();
//set Image
NSData * dataRef = UIImagePNGRepresentation(currentImage);
ABPersonSetImageData(person, (CFDataRef)dataRef, nil);
//set FirstName and LastName
ABRecordSetValue(person, kABPersonFirstNameProperty,firstname, nil);
ABRecordSetValue(person, kABPersonLastNameProperty,lastname, nil);
//Add Address
ABMutableMultiValueRef address=ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
NSMutableDictionary *addressDictionary=[[NSMutableDictionary alloc]init];
[addressDictionary setObject:[arrayAddress objectAtIndex:0] forKey:(NSString *)kABPersonAddressStreetKey];
[addressDictionary setObject:[arrayAddress objectAtIndex:1]forKey:(NSString *)kABPersonAddressCityKey];
[addressDictionary setObject:[arrayAddress objectAtIndex:2] forKey:(NSString *)kABPersonAddressCountryCodeKey];
[addressDictionary setObject:[arrayAddress objectAtIndex:3] forKey:(NSString *)kABPersonAddressCountryKey];
ABMultiValueAddValueAndLabel(address, addressDictionary, kABHomeLabel, nil);
ABRecordSetValue(person, kABPersonAddressProperty, address, nil);
ABAddressBookAddRecord(addressBook,person, nil);
ABAddressBookSave(addressBook,nil);
objABPersonViewController=[[ABUnknownPersonViewController alloc]init];
objABPersonViewController.displayedPerson=person;
[self.navigationController pushViewController:objABPersonViewController animated:YES];
CFRelease(person);
}
-(void) validateAndDisplayContacts
{
if([firstName length]==0)
{
firstName=#" ";
}
lblName.text=[NSString stringWithFormat:#"%# : %#",#"First Name",name];
[firstName release];
if([mobile length]==0)
{
mobile=#" ";
}
lblPhone.text=[NSString stringWithFormat:#"%# : %#",#"Mobile",mobile];
[mobile release];
if([email length]==0)
{
email=#" ";
}
lblEmail.text=[NSString stringWithFormat:#"%# : %#",#"Email",email];
[email release];
}
- (void)unknownPersonViewController:(ABUnknownPersonViewController *) unknownCardViewController didResolveToPerson:(ABRecordRef)person
{
[objABPersonViewController dismissModalViewControllerAnimated:YES];
}

Related

Photo Not Uploading on Check In Using Facebook iOS

So I'm creating an iPhone app that needs to be able to upload a photo when the user checks into a location using the Facebook Graph API.
Right now my code is this:
if (![delegate.facebook isSessionValid])
[delegate.facebook authorize:[NSArray arrayWithObjects:#"publish_stream", #"offline_access", #"publish_checkins", nil]];
parameters = [NSMutableDictionary dictionaryWithObjectsAndKeys:[placeDictionary objectForKey:#"id"] , #"place",
serialisedCoordinates, #"coordinates",
message, #"message",
pickedImage, #"picture",
#"Via the official REDACTED app", #"application", nil];
[delegate.facebook requestWithGraphPath:#"me/checkins" andParams:parameters andHttpMethod:#"POST" andDelegate:fbCheckInResultHandler];
Where 'pickedImage' is the UIImage returned from a UIImagePickerController.
Even when I pick an image (i.e., pickedImage != nil), no picture is uploaded when checked in. The check in appears on Facebook with the message, coordinates and app information, just no image.
Really hope someone can help.
Cheers,
Kiran
Here is the whole function that is being called when a checkin is made:
-(void)fbPostCheckInWithMessage:(NSString *)message andFriends:(NSArray *)friends {
if (![delegate.facebook isSessionValid]) {
NSLog(#"Session invalid");
[delegate.facebook authorize:[NSArray arrayWithObjects:#"publish_stream", #"offline_access", #"publish_checkins", nil]];
} else {
NSLog(#"Session valid");
}
NSMutableString *friendsIDString;
friendsIDString = [NSMutableString stringWithFormat:#"%#", [[friends objectAtIndex:0] userID]];
if ([friends count] > 1) {
for (User *f in taggedFriends) {
if (f != [taggedFriends objectAtIndex:0]) {
[friendsIDString appendString:[NSString stringWithFormat:#", %#", f.userID]];
}
}
}
NSLog(#"Tagged Friends: %#", friendsIDString);
SBJSON *jsonWriter = [SBJSON new];
NSMutableDictionary *locationDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:#"%f", userLocation.coordinate.latitude], #"latitude",
[NSString stringWithFormat:#"%f", userLocation.coordinate.longitude], #"longitude", nil];
NSString *serialisedCoordinates = [jsonWriter stringWithObject:locationDictionary];
NSData *pictureData = UIImagePNGRepresentation(pickedImage);
NSLog(#"picture: %#", pictureData);
NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithObjectsAndKeys:[placeDictionary objectForKey:#"id"] , #"place",
serialisedCoordinates, #"coordinates",
pictureData, #"message",
pickedImage, #"picture",
#"Via the official REDACTED app", #"application", nil];
[delegate.facebook requestWithGraphPath:#"me/checkins" andParams:parameters andHttpMethod:#"POST" andDelegate:fbCheckInResultHandler];
}
I am using the friendsIDString to get the IDs of the friends the user with. I've removed this functionality from the example here because it was all commented out because I was trying to isolate what was causing the problem (which was the photo tagging). Just wanted to clear that up.
--UPDATE--
Here's how I'm setting pickedImage. I use the delegate methods from the UIImagePickerController:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
NSLog(#"Picked image");
pickedImage = [[UIImage alloc] init];
pickedImage = image;
[imagePickerController dismissModalViewControllerAnimated:YES];
}
You can upload photos to facebook using :- UIImagePNGRepresentation,UIImageJPEGRepresentation,etc based on type of image or imagewithdata from UIImage class..
NSData *yourImageData= UIImagePNGRepresentation(yourImage);
Initialize the dictionary :-
NSMutableDictionary *mutableDictWithParam= [NSMutableDictionary dictionaryWithObjectsAndKeys:#"Your text", #"message", yourImageWithData, #"theSource", nil];
finally send post :-
[facebook requestWithGraphPath:#"/me/photos" andParams:mutableDictWithParam andHttpMethod:#"POST" andDelegate:self];
In you app i think you have not initialized your NSData object(pickedimage) ..else everything seems fine.
As Per Our Discussion You can use this to compress image:-
NSData* UIImageJPEGRepresentation(UIImage *image, CGFloat compressionQuality);
NSData *compressedImage = UIImagePNGRepresentation(yourIMage, .5)//quality is ensured through second argument lies between o and 1

How Can I Save This Array of Images?

I'm very new to programming, and I jumped right into a project (I know thats not the smartest thing to do, but I'm learning as I go). The app that I'm writing has 10 UIImageViews that display a picture from the users camera roll. The code I'm using needs each of the UIImageViews to have tags. I'm currently using NSData to save the array images, and it works great, but I can't use this method anymore because NSData doesn't support the use of tags. I also can't use NSUserDefaults, because I can't save images to a plist. Here is how I'm attempting to do this (using the NSData method, which works but I have to edit this so that my tags work.)
This is my current code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
if (imageView.image == nil) {
imageView.image = img;
[self.array addObject:imageView.image];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
if (imageView2.image == nil) {
imageView2.image = img;
NSLog(#"The image is a %#", imageView);
[self.array addObject:imageView2.image];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
...
- (void)applicationDidEnterBackground:(UIApplication*)application {
NSLog(#"Image on didenterbackground: %#", imageView);
[self.array addObject:imageView.image];
[self.array addObject:imageView2.image];
[self.user setObject:self.array forKey:#"images"];
[user synchronize];
}
- (void)viewDidLoad
{
self.user = [NSUserDefaults standardUserDefaults];
NSLog(#"It is %#", self.user);
self.array = [[self.user objectForKey:#"images"]mutableCopy];
imageView.image = [[self.array objectAtIndex:0] copy];
imageView2.image = [[self.array objectAtIndex:1] copy];
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:app];
[super viewDidLoad];
}
Any help or suggestions on how to edit this code so that I can save the images, while using tags is much appreciated, thanks!
EDIT: Here is my updated code:
-(IBAction)saveButtonPressed:(id)sender {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) objectAtIndex:0];
for (UIImageView *imageView in self.array) {
NSInteger tag = self.imageView.tag;
UIImage *image = self.imageView.image;
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
}
NSLog(#"Saved Button Pressed");
}
- (void)applicationDidEnterBackground:(UIApplication*)application {
}
-(void)viewDidLoad {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
NSArray *docFiles = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:docsDir error:NULL];
for (NSString *fileName in docFiles) {
if ([fileName hasSuffix:#".png"]) {
NSString *fullPath = [docsDir stringByAppendingPathComponent:fileName];
UIImage *loadedImage = [UIImage imageWithContentsOfFile:fullPath];
if (!imageView.image) {
imageView.image = loadedImage;
} else {
imageView2.image = loadedImage;
}
}
}
}
You need to use "Fast Enumeration" to parse the array's objects, and write each object to disk sequentially. First, you're going to need to add the UIImageView objects to the array instead of the UIImage property of the UIImageView, so you can recover the tag. So instead of writing
[self.array addObject:imageView.image];
It will be
[self.array addObject:imageView];
Try to follow along with my code. I inserted comments on each line to help.
-(void)applicationDidEnterBackground:(UIApplication *)application {
//Obtain the documents directory
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainmask,YES) objectAtIndex:0];
//begin fast enumeration
//this is special to ObjC: it will iterate over any array one object at a time
//it's easier than using for (i=0;i<array.count;i++)
for (UIImageView *imageView in self.array) {
//get the imageView's tag to append to the filename
NSInteger tag = imageView.tag;
//get the image from the imageView;
UIImage *image = imageView.image;
//create a filename, in this case "ImageTAGNUM.png"
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
//concatenate the docsDirectory and the filename
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
}
}
To load the images from disk, you'll have to look at your viewDidLoad method
-(void)viewDidLoad {
//get the contents of the docs directory
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainmask,YES) objectAtIndex:0];
//Get the list of files from the file manager
NSArray *docFiles = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:docsDir error:NULL]);
//use fast enumeration to iterate the list of files searching for .png extensions and load those
for (NSString *fileName in docFiles) {
//check to see if the file is a .png file
if ([fileName hasSuffix:#".png"]) {
NSString *fullPath = [docsDir stringByAppendingPathComponent:fileName];
UIImage *loadedImage = [UIImage imageWithContentsOfFile:fullPath];
//you'll have to sort out how to put these images in their proper place
if (!imageView1.image) {
imageView1.image = loadedImage;
} else {
imageView2.image = loadedImage;
}
}
}
}
Hope this helps
One thing you need to be aware of is that when an app enters the background it has about 5 seconds to clean up its act before it's suspended. The UIPNGRepresentation() function takes a significant amount of time and is not instantaneous. You should be aware of this. It would probably be better to write some of this code in other places and do it earlier than at app backgrounding. FWIW
You can use the [NSbundle Mainbundel] to store that images.
To get path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
First, there's still a problem in your for loop.
for (UIImageView *imageView in self.array) {
NSInteger tag = self.imageView.tag;
UIImage *image = self.imageView.image;
// ...
}
Before you make any other changes, you must understand why. imageView is your for loop control variable, which changes on each iteration through the loop. self.imageView is a different thing. It is the first of the 10 imageViews attached to your viewController. Every time this loop cycles, it looks at the first imageView, and only the first.
As for why saving doesn't work, it's probably because the arrays elsewhere aren't working. Add some logging to make sure there's something in the array, and that it has as many elements as you expect.
-(IBAction)saveButtonPressed:(id)sender {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) objectAtIndex:0];
// Log to make sure the views expected have previously been stored.
// If the array is empty, or shorter than expected, the problem is elsewhere.
NSLog(#"Image view array before saving = %#", self.array);
for (UIImageView *imageViewToSave in self.array) {
NSInteger tag = imageViewToSave.tag;
UIImage *image = imageViewToSave.image;
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
// Log the image and path being saved. If either of these are nil, nothing will be written.
NSLog(#"Saving %# to %#", image, imagePath);
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:NO];
}
NSLog(#"Save Button Pressed");
}

Archive the uiview controls (uiimageview,uiscrollview,uitableview,uibutton)

Am archive and unarchive the uiview and display the view in ipad this controls (uiimageview,uiscrollview,uitableview,uibutton) were not displayed....but uiview subviews all controls are there ....Is it possible to get that controls(uiimageview,uiscrollview,uitableview,uibutton) in view? possible means how to get that controls to display in view.
uiview *viewForArchive;
uiview *newCir=[uiview alloc ]initwithframe:cgrectmake(0,0,768,1024)];
//archiving
NSMutableData *d= [NSMutableData data];
NSKeyedArchiver *kA=[[NSKeyedArchiver alloc] initForWritingWithMutableData:d];
[kA encodeObject:newCir forKey:#"view"];
[kA finishEncoding];
if ([d writeToFile:[NSHomeDirectory() stringByAppendingPathComponent:#"archiveView"] options:NSAtomicWrite error:nil] == NO)
{
NSLog(#"writeToFile error");
}
else
{
NSLog(#"Written!");
}
//unarchiving
NSData *theData = [NSData dataWithContentsOfFile:[NSHomeDirectory() stringByAppendingPathComponent:#"archiveView"]];
NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
NSDictionary *dict= [decoder decodeObjectForKey:#"view"];
[decoder finishDecoding];
if ([theData writeToFile:[NSHomeDirectory() stringByAppendingPathComponent:#"unarchiveView"] options:NSAtomicWrite error:nil] == NO) {
NSLog(#"writeToFile error");
}
else {
if ([dict isKindOfClass:[UIView class]]) {
viewForArchive=(UIView *)dict;
NSLog(#"view:%#",viewForArchive.subviews );
viewForArchive.backgroundColor=[UIColor whiteColor];
[self.view addsubview:viewForArchive];
}
NSLog(#"Written!");
}
this is the uiview archiver coding....
In this coding to print the viewForArchive.subviews all controls are there....in my application this controls (uiimageview,uiscrollview,uitableview,uibutton) were not displayed...what is the problem in this coding...
If your point is to save specific states of your objects, you can store strings in the NSUserDefaults and set the objects according to your strings. Alternatively, you can create the xib files, which automatically will store your objects?

cancel button on search bar does not cancel correctly

I have a search bar, i can search now, but when I enter a text to search, and click the cancel button. It does not give me back my first stage, meaning full of the items in the table.
For example: I search the item with word: a, it gives me all the a items, yes, it is right now, but when i hit the cancel button, i want the programme gives me all the items exist, not just a items.
Here is the code: please help me out. Thank you so much.
- (void)searchBarCancelButtonClicked:(UISearchBar *)aSearchBar
{
searchBar.text = #"";
[searchBar resignFirstResponder];
letUserSelectRow = YES;
searching = NO;
self.tableView.scrollEnabled = YES;
NSLog(#"what text after cancel now: %#", searchBar.text);
[self.tableView reloadData];
}
- (NSMutableArray *) searchTableView {
NSString *searchText = searchBar.text;
NSLog(#"search text: %#", searchText);
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSMutableArray *tempArr = [[NSMutableArray alloc] init];
for (NSDictionary *dTemp in arrayData)
{
NSString *tempStr = [dTemp objectForKey:#"url"];
NSLog(#"sTemp string: %#",[ NSString stringWithFormat:#"%#", tempStr]);
NSRange titleResultsRange = [tempStr rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
{
NSLog(#"1 count :%d", [resultArray count]);
[resultArray addObject:dTemp];
NSLog(#"2 count :%d", [resultArray count]);
[tempArr addObject:resultArray];
[resultArray release];
resultArray = [NSMutableArray new];
}
}
if (resultArray != nil) {
[resultArray release];
}
return tempArr;
}
- (void)searchBar:(UISearchBar *)aSearchBar textDidChange:(NSString *)searchText
{
NSLog(#"what text after cancel now: %#", searchBar.text);
if([searchText length] > 0) {
[sortedArray removeAllObjects];
searching = YES;
letUserSelectRow = YES;
self.tableView.scrollEnabled = YES;
NSMutableArray *searchArray = [self searchTableView];
sortedArray = [[NSMutableArray alloc] initWithArray:searchArray copyItems:YES];
for (int i = 0; i<[sortedArray count]; i++) {
NSLog(#"this is the search array: %#", [[sortedArray objectAtIndex:i] class]);
}
NSLog(#"sorted array: %d", [sortedArray count]);
}
else {
searching = NO;
letUserSelectRow = NO;
self.tableView.scrollEnabled = NO;
}
[self.tableView reloadData];
}
You don't need to override any of UISearchBar methods to accomplish this. The new way of doing this relies on the UISearchDisplay controller instead (specifically on shouldReloadTableForSearchString).
Declare your view controller to conform to UISearchDisplayDelegate protocol, and keep two instance variables: your model as NSArray (all data) and a filtered array as NSMutableArray (a subset of your data). The code you presently have in "searchTableView" would filter the content of the model and place it into the filtered NSMutableArray. Then you would override the following UITableView methods: -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section and -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath. In each, before returning, make a comparison to determine whether your tableView argument is equal to self.searchDisplayController.searchResultsTableView. If it is, the user is looking at the filtered list and your should use the content of the filtered NSMutableArray to create the view, otherwise, the user is looking at the whole data set and you should use the content of the NSArray that holds your model. Take a look at the following Apple code for a simple example of what I described:
http://developer.apple.com/library/ios/#samplecode/TableSearch/Introduction/Intro.html

iOS 4 bug? Image files saved to folder are overwritten after a random number of images saved

I have an APP (SDK 4.3) which saves images being attachmemnts for a waypoint on a google map.
The file save is pretty standard (afaik) UIImagePickerController code.
Rather than saving to the camera roll I was saving the image and then the thumbnail to a subfolder. I need that.
At seemingly random points with no errors being trapped at all and logged, the images will not save to the folder but instead over-write previously saved image files!
It looks for all the world like a FIFO pop going on.
It is seriously odd and I have even built a small test APP and fired it up as soon as the spookiness appeared...saving a series of camera images to the same folders but see the same effect. The images get over-written once the random magic file number is reached!
Random in the sense that after 7 saved images, the overwriting begins...even after a reboot of the phone to ensure memory leaks is not the issue. Wipe the APP and try again...
This time it will happen after 16 oR 23 image files saved.
I have gone to all sorts of extremes and cannot find the source of the issue.
In the small test APP, in the same method I save out to the camera roll as well. It will save there but overwrite in the folder. The file names are 10 character random generated alpha-numeric.
I am now leaning to understand this as a bug. I can always reproduce the error but not predictably. It arises randomly.
I would appreciate help as I am tearing my hair out.
Here is the code...
//tester.h
#import <UIKit/UIKit.h>
#interface tester : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
UIImagePickerController *imgPicker;
IBOutlet UIButton *pressit;
IBOutlet UIButton *seeya;
UIActivityIndicatorView *activity;
}
#property (retain )UIImagePickerController *imgPicker;
#property (nonatomic,retain)IBOutlet UIButton *pressit;
#property (nonatomic,retain)IBOutlet UIButton *seeya;
#property (nonatomic,retain)UIActivityIndicatorView *activity;
-(NSString *) genRandStringLength:(int) len ;
-(void)saveImagesFromPickerInTheBackgroundUsingImage:(UIImage *)img;
-(NSArray *)buildFilePaths;
- (IBAction)snapShots:(UIButton *)button;
-(IBAction)byebye:(id)sender;
#end
//=====================
//tester.m
#import "tester.h"
#import "MultiMediaUtilities.h"
#implementation tester
#synthesize imgPicker;
#synthesize pressit,seeya,activity;
//Image size constants
#define MAX_THUMBNAIL_RES_SIZE 103
#define MAX_IMAGE_RES_SIZE 640
- (IBAction)snapShots:(UIButton *)button
{
if (!imgPicker) imgPicker = [[UIImagePickerController alloc]init];
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imgPicker.delegate = self;
[self presentModalViewController:imgPicker animated:YES];
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *memoImage = [[MultiMediaUtilities scaleAndRotateImage:[info objectForKey:#"UIImagePickerControllerOriginalImage"] toResolution:MAX_IMAGE_RES_SIZE ]retain];
UIImageWriteToSavedPhotosAlbum(memoImage, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
[self saveImagesFromPickerInTheBackgroundUsingImage:memoImage];
// Dismiss the camera
[self dismissModalViewControllerAnimated:YES];
}
//builds paths to files in system with components
-(NSArray *)buildFilePaths
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *docsPath = [documentsDirectory stringByAppendingPathComponent:#"imagesfolder"];
NSString *fullDocsPath = [docsPath stringByAppendingPathComponent:#"assets"];
NSString *fullThumbsPath = [fullDocsPath stringByAppendingPathComponent:#"thumbs"];
NSArray * retArray = [NSArray arrayWithObjects:fullDocsPath,fullThumbsPath,nil];
return retArray;
}
-(void)saveImagesFromPickerInTheBackgroundUsingImage:(UIImage *)img
{
#try
{
NSFileManager *NSFm = [NSFileManager defaultManager];
NSArray *pathsArray = [NSArray arrayWithArray:[self buildFilePaths]];
NSString *fullDocsPath = [NSString stringWithFormat:#"%#", (NSString *)[pathsArray objectAtIndex:0]];
NSString *fullThumbsPath = [NSString stringWithFormat:#"%#", (NSString *)[pathsArray objectAtIndex:1]];
//Ensure Folders exist
BOOL isDir=YES;
NSError *error;
if(![NSFm fileExistsAtPath:fullDocsPath isDirectory:&isDir])
if(![NSFm createDirectoryAtPath:fullDocsPath withIntermediateDirectories:YES attributes:nil error:&error])
NSLog(#"Error: Create Images folder failed");
//create thumbs folder too
if(![NSFm fileExistsAtPath:fullThumbsPath isDirectory:&isDir])
if(![NSFm createDirectoryAtPath:fullThumbsPath withIntermediateDirectories:YES attributes:nil error:&error])
NSLog(#"Error: Create Thumbs folder failed");
//build the filenames & paths
NSString *newImageName= [NSString stringWithFormat:#"%#.png", [self genRandStringLength:10]];
NSString *imagePath = [[fullDocsPath stringByAppendingPathComponent:newImageName]retain];
NSLog(#"SavingIMage ImagePath = %#",imagePath);
NSString *thumbPath = [[fullThumbsPath stringByAppendingPathComponent:newImageName]retain];
NSLog(#"SavingIMage thumbPAth = %#",thumbPath);
//Write the files out
NSData *imgData = UIImagePNGRepresentation(img);
[imgData writeToFile:imagePath options:NSDataWritingAtomic error:&error];
if (!error) {
NSLog(#"Error writing image %#",error.description);
}
NSData *thumbData = UIImagePNGRepresentation(img);
[thumbData writeToFile:thumbPath options:NSDataWritingAtomic error:&error];
if (!error) {
NSLog(#"Error writing thumb %#",error.description);
}
}
#catch (NSException * e)
{
NSLog(#"Exception: %#", e);
}
}
-(NSString *) genRandStringLength:(int) len
{
NSString *letters = #"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
NSMutableString *randomString = [NSMutableString stringWithCapacity: len];
for (int i=0; i<len; i++)
{
[randomString appendFormat: #"%c", [letters characterAtIndex: rand()%[letters length]]];
}
return randomString;
}
- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
NSString *message;
NSString *title;
if (!error)
{
title = #"Camera...";
message = #"Image saved!...Just as well.";
}
else
{
title = #"Error";
message = [error description];
}
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:title
message:message
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
if (image !=NULL){
[image release];
image=nil;
}
if(info !=NULL)
{
[info release];
info=nil;
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(void)dealloc
{
[imgPicker release];
[pressit release];
[seeya release];
[activity release];
[super dealloc];
}
#end
Even seeded, this is an inappropriate use of random numbers.
Three approaches:
Use an incremented sequence number. (1, 2, 3, etc.)
Use a UUID from [[NSProcessInfo processInfo] globallyUniqueString]
Use a filename constructed from the date & time.
As Mats said, if you don't initialize your random number generator with srand, rand() will behave strangely and don't expect it to generate random numbers. This can cause the same filenames you experience.