I want to save an image that is displayed in the UIImage. However I want to categorize it in genre for example vegetables, meat, lettuce, etc.
I cannot find a way to do that.
What is the best and easiest way to do this?
Also I want to make the user select which category he wants to save using the picker controller to save.
Thank you! I really need help!!
Update 2
To check if it is saved I went further to construct a collection View controller and I get errors saying at the images part at the [arrayCollectionImages addObject:image]; Can you explain me about this last piece of code. I also have an warning at arrayCollectionImages saying local declaration of arrayColectionImages hide instance variable. –
#interface CollectionViewController (){
NSArray *arrayCollectionImages;
}
#end
#implementation CollectionViewController
- (void)viewDidLoad {
dispatch_queue_t searchQ = dispatch_queue_create("com.awesome", 0);
dispatch_async(searchQ, ^{
NSArray *arrayCollectionImages = [[NSArray alloc ]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Hats";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
for(NSString *str in directoryContent){
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
NSData *data = [NSData dataWithContentsOfFile:finalFilePath];
if(data)
{ dispatch_async(dispatch_get_main_queue(),^{
UIImage *image = [UIImage imageWithData:data];
});
[arrayCollectionImages addObject:images];
}
}
});
[super viewDidLoad];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ReuseID" forIndexPath:indexPath];
[[cell collectionImageView]setImage:[UIImage imageNamed:[arrayCollectionImages objectAtindex:indexPath.item]]];
return cell;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [arrayCollectionImages count];
}
#end
Step 1:
Set up a Picker Controller.
Here is the official reference.
Here is a tutorial.
Try to set it with all the genre values you want. You will learn about its delegate method:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
that will return the genre selected.
Step 2:
Provide a save icon or a save button on each image. On click of that icon/button you should make your picker view appear and make user select any row and the image should be copied to a private variable or a property here, so as to refer it later in the delegate method.
Step 3:
When user selects a row, this delegate method is called. Here we will create a new directory , if not already exists, according to the genre selected In UIPickerView. Then you should write your image to the path.
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//fetch Category Name from the array used to fill the Picker View
NSString *categoryName= [array objectAtIndex:row];
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:categoryName];
NSFileManager *fileManager=[[NSFileManager alloc]init];
[fileManager createDirectoryAtPath:fPath withIntermediateDirectories:YES attributes:NO error:NO];
UIImage *image= captureImage;
NSData *data= UIImagePNGRepresentation(image);
[data writeToFile:fPath atomically:NO];
}
To retrieve images from a particular folder in your documents directory:
Create a path to that folder first. This will depend on a particular genre. Let's say Genre1.
// An array to save all images. You have to do this in some other way if selected images are big in size.
// For that case I suggest retrieving of images only when you are showing them on screen.
NSArray *allImagesArray = [[NSArray alloc ]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Genre1";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
for(NSString *str in directoryContent){
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
NSData *data = [NSData dataWithContentsOfFile:finalFilePath];
if(data)
{
UIImage *image = [UIImage imageWithData:data];
[allImagesArray addObject:image];
}
}
Related
How can I get images from documents directory to poplulate a collection view. So far I get all the images dumped into each cell according to my log, (or at least the image name is printed in the log)
First im getting the image names from the documents directory filelist is an NSMutable array of imageNames.png
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsPath error:nil];
fileList=[[NSMutableArray alloc]init];
for (NSString *filename in dirContents) {
NSString *fileExt = [filename pathExtension];
if ([fileExt isEqualToString:#"png"]) {
[fileList addObject:filename];
}
}
NSLog(#"document folder content list %# ",fileList);
This returns a list of my png file names in my NSMutsableArray fileList. Then I want to get all these images into my collection view
//set up cell from nib in viewDidLoad
UINib *cellNib = [UINib nibWithNibName:#"NibCell" bundle:nil];
[self.appliancesCollectionView registerNib:cellNib forCellWithReuseIdentifier:#"cvCell"];
/////
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return fileList.count;
NSLog(#"collection view count is %#",fileList);
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Setup cell identifier
static NSString *cellIdentifier = #"cvCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
NSString *fileName = [fileList objectAtIndex:indexPath.row];
cell.backgroundView = [[UIImageView alloc] initWithImage: [UIImage imageNamed: fileName]];
NSLog(#"cell Bg image %#",fileList);
return cell;
}
The probelm is nothing shows up in my collection view cells
The problem is that contentsOfDirectoryAtPath returns relative file paths. And you need absolute. Something like following should be used:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsPath error:nil];
fileList=[[NSMutableArray alloc]init];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; // NEW LINE 1
for (NSString *filename in dirContents) {
NSString *fileExt = [filename pathExtension];
if ([fileExt isEqualToString:#"png"]) {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:filename]; // NEW LINE 2
[fileList addObject:fullPath]; // NEW LINE 3
}
}
NSLog(#"document folder content list %# ",fileList);
You need to use imageWithContentsOfFile: instead imageNamed:
NSString * filePath = [[NSBundle mainBundle] pathForResource:<imageNameWithoutExtansion>ofType:<fileExtansion>];
cell.backgroundView = [[UIImageView alloc] initWithImage: [UIImage imageWithContentsOfFile: filePath]];
Usually when you have the images in the project file you use the code
arraycollectionimages = [[NSArray alloc]]initwithobjects
however I want to show the images that are saved in the directories. I have created multiple directories so I just want to recall image for one of them. To make this work I want to use this code however I cannot do this? I just stuck it it in as follows but did not work well.
- (void)viewDidLoad {
NSArray *arrayCollectionImages = [[NSArray alloc ]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Genre1";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
for(NSString *str in directoryContent){
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
NSData *data = [NSData dataWithContentsOfFile:finalFilePath];
if(data)
{
UIImage *image = [UIImage imageWithData:data];
[arrayCollectionImages addObject:image];
}
}
I think your directory search is probably taking long. Try this...
- (void)viewDidLoad {
dispatch_queue_t searchQ = dispatch_queue_create("com.awesome", 0);
dispatch_async(searchQ, ^{
NSArray *arrayCollectionImages = [[NSArray alloc ]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Genre1";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
for(NSString *str in directoryContent){
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
NSData *data = [NSData dataWithContentsOfFile:finalFilePath];
if(data)
{ dispatch_async(dispatch_get_main_queue(),^{
UIImage *image = [UIImage imageWithData:data];
});
[arrayCollectionImages addObject:image];
}
}
});
}
The code basically spawns off another thread on the search and puts the image when its ready.
I do not know how to declare your directory in the .h file. In my View Controller I have written
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSArray *allImagesArray = [[NSArray alloc ]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Hats";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
for(NSString *str in directoryContent){
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
NSData *data = [NSData dataWithContentsOfFile:finalFilePath];
if(data)
{
UIImage *image = [UIImage imageWithData:data];
[allImagesArray addObject:image];
}}}
however of course I get an error saying no visible at interface for"NSMutableArray" declares the selector "addObject".I do not know how to declare my directory called Hats in the .h file. I think you use NSMutableArray or something but I don't know for sure..
You want to use an NSMutableArray instead of an NSArray. You can't alter an NSArray after creation.
NSMutableArray *allImagesArray = [[NSMutableArray alloc ]init];
And then you can do
[allImagesArray addObject:image];
NSArray needs to be populated when it is initialized. So if you want to add some object to an array then you have to use an NSMutableArray.
I am using this code to recall the directory that I have made for each genre. However I get errors saying at the images part at the [arrayCollectionImages addObject:image]; Can you explain what is wrong with the last piece of code. I also have an warning at arrayCollectionImages saying local declaration of arrayColectionImages hide instance variable. It is also telling me that the [[cell collectionImageView]setImage:[UIImage imageNamed:[arrayCollectionImages objectAtindex:indexPath.item]]]; No visible #interface for "NSArray" declares the selector "objectAtindex:;" What did I have done wrong?
#import "CollectionViewController.h"
#import "CollectionCell.h"
#interface CollectionViewController (){
NSArray *arrayCollectionImages;
}
#end
#implementation CollectionViewController
- (void)viewDidLoad {
NSArray *allImagesArray = [[NSArray alloc ]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Genre1";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
for(NSString *str in directoryContent){
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
NSData *data = [NSData dataWithContentsOfFile:finalFilePath];
if(data)
{
UIImage *image = [UIImage imageWithData:data];
[allImagesArray addObject:image];
}
}
[super viewDidLoad];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ReuseID" forIndexPath:indexPath];
[[cell collectionImageView]setImage:[UIImage imageNamed:[arrayCollectionImages objectAtIndex:indexPath.item]]];
return cell;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [arrayCollectionImages count];
}
#end
This is my code for saving to directory
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
FrontCamera = NO;
cameraSwitch.selectedSegmentIndex = 1;
captureImage.hidden = YES;
[pickerViewContainer addSubview:SaveTopicker];
arraygenre = [[NSMutableArray alloc] init];
[arraygenre addObject:#"Tops"];
[arraygenre addObject:#"Pants"];
[arraygenre addObject:#"Coats"];
[arraygenre addObject:#"Shoes"];
[arraygenre addObject:#"Hats"];
[arraygenre addObject:#"Others"];
pickerViewContainer.frame = CGRectMake(0, 800, 320, 261);
}
- (void)viewDidAppear:(BOOL)animated {
[self initializeCamera];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//fetch Category Name from the array used to fill the Picker View
NSString *categoryName= [arraygenre objectAtIndex:row];
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:categoryName];
NSFileManager *fileManager=[[NSFileManager alloc]init];
[fileManager createDirectoryAtPath:fPath withIntermediateDirectories:YES attributes:nil error:nil];
UIImage *image = captureImage.image;
NSData *data = UIImagePNGRepresentation(image);
[data writeToFile:fPath atomically:YES];
}
The method name is objectAtIndex:. You have the "i" in the method name in lower case which is incorrect.
I have used the code given here to save and load images
It works fine when i use it together in one view controller, but when i use the saveImage method in one view controller and try to load the image in another view controller the image returned blank...
In view controller A i use the following to save a image
- (void)saveImage: (UIImage*)image
{
NSLog(#"saveimage called");
if (image != nil)
{
NSLog(#"Image not null");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
#"test.png" ];
NSData* data = UIImagePNGRepresentation(image);
[data writeToFile:path atomically:YES];
QrImageView.image = nil;
}
}
And in view controller say B I'm loading the image using..
- (UIImage*)loadImage
{
NSError *error;
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
#"test.png" ];
UIImage* image = [UIImage imageWithContentsOfFile:path];
// Write out the contents of home directory to console
NSLog(#"Documents directory: %#", [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
return image;
}
I also get the content of the file in console but i dont understand why the image is blank
2013-07-06 14:13:19.750 YouBank[500:c07] Documents directory: (
"test.png"
)
Any idea what I'm doing wrong...
EDIT:
In the view controller B on the viewDidload method i do the following
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
ImageView.image=[self loadImage];
ImageName.text = #"Cash Withdrawal";
}
The problem is that you're updating your UIImageView with the UIImage only upon viewDidLoad. You need to add an update once you are done obtaining it from the filesystem (preferably on a background thread). So it would look something like this:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
UIImage *loadedImage = [self loadImage];
dispatch_async(dispatch_get_main_queue(),^{
ImageView.image = loadedImage;
});
});
I would also recommend to use names starting with lowercase characters for instance names, so you should rename ImageView -> imageView
try this
//Document Directory
#define kAppDirectoryPath NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
#pragma mark - File Functions - Document/Cache Directory Functions
-(void)createDocumentDirectory:(NSString*)pStrDirectoryName
{
NSString *dataPath = [self getDocumentDirectoryPath:pStrDirectoryName];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:NULL];
}
-(NSString*)getDocumentDirectoryPath:(NSString*)pStrPathName
{
NSString *strPath = #"";
if(pStrPathName)
strPath = [[kAppDirectoryPath objectAtIndex:0] stringByAppendingPathComponent:pStrPathName];
return strPath;
}
When your write photo
[self createDocumentDirectory:#"MyPhotos"];
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:strImageName];
[UIImagePNGRepresentation(imgBg.image) writeToFile:pngPath atomically:YES];
When you get the file
Edit
NSError *error = nil;
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[FunctionManager getDocumentDirectoryPath:#"MyPhotos"] error:&error];
if (!error) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self ENDSWITH '.png'"];
NSArray *imagesOnly = [dirContents filteredArrayUsingPredicate:predicate];
for (int i=0;i<[imagesOnly count]; i++) {
[arrSaveImage addObject:[imagesOnly objectAtIndex:i]]; //arrSaveImage is Array of image that fetch one by one image and stored in the array
}
}
NSString *strPath=[self getDocumentDirectoryPath:#"MyPhotos"]; // "MyPhotos" is Your Directory name
strPath=[NSString stringWithFormat:#"%#/%#",strPath,[arrSaveImage objectAtIndex:i]]; //You can set your image name instead of [arrSaveImage objectAtIndex:i]
imgBackScroll.image=[UIImage imageWithData:[NSData dataWithContentsOfFile:strPath]];
it may help you.