I'm looking for a way to persist images to an array (or similar) that can be accessed after the app has closed an relaunched -- sorting the images by date is also required. I'm currently able to store the the images to the app's NSDocumentDirectory with the following code:
-(NSString *)currentDateandTime
{
NSDate *today = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MMddyyyy_HHmmss"];
NSString *dateString = [dateFormat stringFromDate:today];
return dateString;
}
-(void)saveImageToDocuments
{
NSData *imageData = UIImagePNGRepresentation(image);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *date = [self currentDateandTime];
NSString *imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#_image.png",date]];
}
This means I've got images where the date/time is in the filenames of the image. What is the best way to go about storing these images in an array or dictionary AND sorting them by date/time. Thanks for reading!
I would save the file names and dates in a plist file which is an array of dictionaries of format: #{ #"filename" : imageFileName, #"date": imageDate }.
When you load that plist into an NSArray, you can easily sort it by date by specifying your own comparison method. e.g:
NSArray *filenames = [[NSArray alloc] initWithContentsOfFile:filePath];
NSArray *sortedFilenames = [filenames sortedArrayUsingComparator:
^NSComparisonResult(NSDictionary *dict1, NSDictionary *dict2)
{
NSDate *date1 = dict1[#"date"];
NSDate *date2 = dict2[#"date"];
return [date1 compare:date2];
}
Store the image data and the dates in some dictionaries, then store those dictionaries in an array, then use NSKeyedArchiver to archive the array.
[NSKeyedArchiver archiveRootObject:imageDictionary toFile:#"imagesArray"];
Then when you want to retrieve it:
NSArray * retrievedImages = [NSKeyedUnarchiver unarchiveObjectWithFile:#"imagesArray"];
Then just compare the dates in the various dictionaries in the retrieved array.
When I save an image taken with the camera without filtering it goes smoothly, but if i filter the image, when I save it, it doesn't work.
i'm using : [CIFilter filterWithName:#"CIColorControls"] and its options to filter.
Here the code used to save the image (wether or not its been filtered).
- (IBAction)save:(id)sender {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSData *binaryImageData = UIImageJPEGRepresentation(_photo, 0.3); // PNG without compression paramenter works too
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"yyyy-MM-dd-HH-mm"];
NSString *imageName = [formatter stringFromDate:[NSDate date]];
[binaryImageData writeToFile:[basePath stringByAppendingPathComponent:imageName] atomically:YES];
}
EDIT :
When I use the breakpoint, the NSData receives (counter) data and becomes nil when I proceed to NSDateFormatter
I am reading info from a sqlite database to a .csv file. I am able to get the file to build, but each new line starts with a ",". I have done some android programming, but not much ios. I am thinking that the issue is componentsJoinedByString:#"," since it joins everything together, but I am not sure how to get rid of the "," at the beginning of each new line using this. Is there another way to join them to write to a csv file or a way to get rid of the first comma?
NSMutableArray *exportBike = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:#"MemberDB.sql"];
FMDatabase *database = [FMDatabase databaseWithPath:path];
[database open];
FMResultSet *resultsBike = [database executeQuery:#"SELECT * FROM bike"];
while([resultsBike next]) {
NSString *name = [resultsBike stringForColumn:#"name"];
NSInteger stage1HR = [resultsBike intForColumn:#"stage1HR"];
NSInteger stage1BP = [resultsBike intForColumn:#"stage1BP"];
NSInteger stage2HR = [resultsBike intForColumn:#"stage2HR"];
NSInteger stage2BP = [resultsBike intForColumn:#"stage2BP"];
NSInteger stage3HR = [resultsBike intForColumn:#"stage3HR"];
NSInteger stage3BP = [resultsBike intForColumn:#"stage3BP"];
NSInteger stage4HR = [resultsBike intForColumn:#"stage4HR"];
NSInteger stage4BP = [resultsBike intForColumn:#"stage4BP"];
NSInteger stage5HR = [resultsBike intForColumn:#"stage5HR"];
NSInteger stage5BP = [resultsBike intForColumn:#"stage5BP"];
NSInteger stage6HR = [resultsBike intForColumn:#"stage6HR"];
NSInteger stage6BP = [resultsBike intForColumn:#"stage6BP"];
NSInteger stage7HR = [resultsBike intForColumn:#"stage7HR"];
NSInteger stage7BP = [resultsBike intForColumn:#"stage7BP"];
NSInteger recoveryHR = [resultsBike intForColumn:#"recoveryHR"];
NSLog(#"%#,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",name, stage1HR, stage1BP, stage2HR, stage2BP, stage3HR, stage3BP, stage4HR, stage4BP, stage5HR, stage5BP, stage6HR, stage6BP, stage7HR, stage7BP, recoveryHR);
[exportBike addObject:[NSString stringWithFormat:#"%#,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d""\n",name, stage1HR, stage1BP, stage2HR, stage2BP, stage3HR, stage3BP, stage4HR, stage4BP, stage5HR, stage5BP, stage6HR, stage6BP, stage7HR, stage7BP, recoveryHR]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *savePath = [paths objectAtIndex:0];
savePath = [savePath stringByAppendingPathComponent:#"bike.csv"];
[[exportBike componentsJoinedByString:#","] writeToFile:savePath atomically:YES encoding:NSUTF8StringEncoding error:NULL];
Change
[exportBike addObject:[NSString stringWithFormat:#"%#,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d""\n",name, stage1HR, stage1BP, stage2HR, stage2BP, stage3HR, stage3BP, stage4HR, stage4BP, stage5HR, stage5BP, stage6HR, stage6BP, stage7HR, stage7BP, recoveryHR]];
[[exportBike componentsJoinedByString:#","] writeToFile:savePath atomically:YES encoding:NSUTF8StringEncoding error:NULL];
to
[exportBike addObject:[NSString stringWithFormat:#"%#,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",name, stage1HR, stage1BP, stage2HR, stage2BP, stage3HR, stage3BP, stage4HR, stage4BP, stage5HR, stage5BP, stage6HR, stage6BP, stage7HR, stage7BP, recoveryHR]];
[[exportBike componentsJoinedByString:#"\n"] writeToFile:savePath atomically:YES encoding:NSUTF8StringEncoding error:NULL];
Instead of "," use "\n" in componentsJoinedByString method and in addObject line remove the "\n" at the end.
As Martin mentioned below, another option is to keep the new line character in addObject line and use [exportBike componentsJoinedByString:#""]. This will add a new line character at the end of the file.
I have this code this code to save an image to the Documents folder.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
UIImage *image = imageView.image; // imageView is my image from camera
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:savedImagePath atomically:NO];
I am looking for a way to be able to save multiple images as this one keeps over writing the savedImage.png name.
I do not mind looking for it on google or whatever, but I need to know what it is called, since looking with the wrong keywords really delays the world:-)
Cheers
You need to change the file name that you are appending to the image documentsDirectory path on line three. Each time you'll need to use a different name that isn't already used. NSFileManager has methods to see if a file exists so you can construct a file name and then test if it exists in that location and if so, increment your duplicate count and try the next one.
if num is an integer you define somewhere and keep around so you know the last one you thought you used (and that you've initialized to 1 somewhere).
// your code to get the directory here, as above
NSFileManager *fm = [NSFileManager ...]
do {
savedImagePath = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat: #"%#-%d.png", #"savedImage", num]];
num += 1; // for next time
if ( ![fm fileExistsAtPath: savedImagePath] )
{
// save your image here using savedImagePath
exit;
}
} while ( //some kind of test for maximum tries/time or whatever )
you'll have to look up the syntax to get an NSFileManager instance and the exact file exists method signature, but that's the gist of it.
If you save file with current dateTime you don't need to worry about same name override problem
-(NSString*)getCurrentDateTimeAsNSString
{
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"yyyyMMddHHmmss"];
NSDate *now = [NSDate date];
NSString *retStr = [format stringFromDate:now];
[format release];
return retStr;
}
you can create a new file each time to do that.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"YOURiMAGEfILE.IMAGEeXTENSION"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
path = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat: #"YOURiMAGEfILE.IMAGEeXTENSION] ];
}
and then you can perform your above operations on the created file.
Hope it help You Working For me!!
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage
{
let i = Int(arc4random())
let str = String(i).appending(".png")
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(str)
print(paths)
let imageData = UIImagePNGRepresentation(image)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
}
else{
print("error")
}
Hi I am trying to write to a file from the accelerometer data. Here is my code:
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
//xax.text = [NSString stringWithFormat:#"X:[%2.6f]",acceleration.x];
//yax.text = [NSString stringWithFormat:#"Y:[%2.6f]",acceleration.y];
//zax.text = [NSString stringWithFormat:#"Z:[%2.6f]",acceleration.z];
NSString *acc_x = [[NSString alloc] initWithFormat:#"X:[%2.6f]",acceleration.x];
NSString *acc_y = [[NSString alloc] initWithFormat:#"Y:[%2.6f]",acceleration.y];
NSString *acc_z = [[NSString alloc] initWithFormat:#"Z:[%2.6f]",acceleration.z];
xax.text = acc_x;
yax.text = acc_y;
zax.text = acc_z;
[acc_x release];
[acc_y release];
[acc_z release];
//wfm == 2 //Initialization of Appending to the file
if (wfm == 2)
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *txtFileName = [[NSString alloc] initWithFormat:#"tmp/%#.txt",txtName.text];
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:txtFileName];
//NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:#"tmp/acc_w_trial2.txt"];
//Current Contents of the file
NSString *fileCurrent = [[NSString alloc] initWithContentsOfFile:fileName];
//Date and Time of each Accelerometer Data
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd 'at' HH:mm:ss:SSS"];
NSDate *date = [NSDate date];
NSString *formattedDateString = [dateFormatter stringFromDate:date];
NSString *msg = [[NSString alloc] initWithFormat:#"%#%# %#%#%# \n",fileCurrent,formattedDateString,xax.text,yax.text,zax.text];
//Convert NSstring to NSData
NSData* data=[msg dataUsingEncoding: [NSString defaultCStringEncoding]];
//bool fileCreationSuccess = [fileManager createFileAtPath:fileName contents:data attributes:nil];
[fileManager createFileAtPath:fileName contents:data attributes:nil];
[msg release];
[dateFormatter release];
[fileCurrent release];
[txtFileName release];
}
}
I get the warning level 1 and level 2. Is there a way I can release the NSFileManager memory to prevent this from locking up?
Your handler method to collect accelerometer data seems not very performant. You are allocating the resources (memory, file) everytime which can take a long time.
You should allocate the needed resources only once (i.e. use dispatch_once) and keep the file open. Use a NSFileHandle (method fileHandleForWritingAtPath) in order to append the data at the end of the file.
Furthermore NSHomeDirectory() is not where you're supposed to save user data, as iOS apps are sandboxed.
Either use NSTemporaryDirectory() or write in the Documents or Library Folder. The following is from Apple's sample code, usually in application delegate class:
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
You can try using an Autorelease Pool.