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.
Related
I want to create plist file with multiple array and array as Root type.I can add multiple array in dictionary but I want to add all array in one array programmatically.How is it possible to create plist file programmatically and write array data into it.Please guide me and give some sample links.Thanks.
Here is my code to add array in dictionary :
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Demo.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"Demo" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error];
}
firstArray = [[NSMutableArray alloc] initWithObjects:#"15-5-123",#"15-5-12",nil];
secondArray = [[NSMutableArray alloc] initWithObjects:#"TestFiling",#"TestFiling",nil];
thirdArray = [[NSMutableArray alloc] initWithObjects:#"15132561",#"15135601", nil];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:firstArray forKey:#"firstArray"];
[dictionary setObject:secondArray forKey:#"secondArray"];
[dictionary setObject:thirdArray forKey:#"thirdArray"];
[dictionary writeToFile:path atomically:NO];
NSDictionary *dictionary1;
dictionary1 = [NSDictionary dictionaryWithContentsOfFile:path];
NSLog(#"dictionary1 %#",dictionary1);
this code is working fine for dictionary but i want to add arrays in array.
The first section of your code is fine, you just need to switch the second part to using an array:
NSMutableArray *array = [[NSMutableDictionary alloc] init];
[array addObject:firstArray];
[array addObject:secondArray];
[array addObject:thirdArray];
[array writeToFile:path atomically:NO];
NSArray *array1 = [NSArray arrayWithContentsOfFile:path];
NSLog(#"array1 %#", array1);
I am trying to do something relatively simple. I have a .plist in my bundle and I am trying to save it to the documents directory with encryption. Now before I tried added encryption, it worked fine. However a new crash has arose.
This is how I save my .plist:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Hi.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) {
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"GameSave" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:bundle];
[NSKeyedArchiver archiveRootObject:plistData toFile:path];
plistData = [plistData AES256EncryptWithKey:#"536335"];
[plistData writeToFile:path atomically:YES];
}
Then this is how I retrieve my .plist (and later change a value and re-save)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Hi.plist"];
//Get array and then current level dict
NSData *plistData = [[NSData alloc] initWithContentsOfFile:path];
plistData = [plistData AES256DecryptWithKey:#"1111"];
NSMutableArray *savegameArray = [[NSKeyedUnarchiver unarchiveObjectWithData:plistData] mutableCopy];
int objectIndex = [Singleton sharedInstance].levelNumber - 1;
NSMutableDictionary *levelDict = [[savegameArray objectAtIndex:objectIndex] mutableCopy];
[levelDict setObject:videoID forKey:#"RecordingURL"];
//Now put new dict back in array
[savegameArray replaceObjectAtIndex:objectIndex withObject:levelDict];
NSData *savedarrayData = [NSKeyedArchiver archivedDataWithRootObject:savegameArray];
savedarrayData = [savedarrayData AES256EncryptWithKey:#"1111"];
[savedarrayData writeToFile:path atomically:YES];
However, in the read code every time I get to this line: NSMutableArray *savegameArray = [[NSKeyedUnarchiver unarchiveObjectWithData:plistData] mutableCopy]; There is a SIGABRT crash which prints:
'-[__NSCFArray objectForKey:]: unrecognized selector sent to instance
0x16604140'
What am I doing wrong?
As we discovered through our chat, we had to first convert the decrypted NSData object to a proper NSPropertyListSerialization serialization.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Hi.plist"];
NSData *plistData = [[NSData alloc] initWithContentsOfFile:path];
NSData *newData = [plistData AES256DecryptWithKey:#"1111"];
NSPropertyListFormat format;
NSMutableArray *savegameArray = [[NSPropertyListSerialization propertyListFromData:newData mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:nil]mutableCopy];
NSLog(#"Array: %#",savegameArray);
You just need to allocate memory to your NSMutableArray like...
NSMutableArray *arrayName = [[NSMutableArray alloc] init];
Until you do that crash will arose..
Hope this is helpful.
Thanks,
Rajesh..
I am recently having a memory crash and I am suspecting that I am failing to empty the array, This is my code for the array
- (void)viewDidLoad
{
allImagesArray = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Bottoms";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
collectionBottoms.delegate =self;
collectionBottoms.dataSource=self;
for(NSString *str in directoryContent){
NSLog(#"i");
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
NSData *data = [NSData dataWithContentsOfFile:finalFilePath];
if(data)
{
UIImage *image = [UIImage imageWithData:data];
[allImagesArray addObject:image];
NSLog(#"array:%#",[allImagesArray description]);
}}
}
Ho can I free the memory by releasing the object in the array?
You save the image array in Plist. After save you just re initialize your array it will clear the memory in array. Then are you using ARC or not? Because ARC is more comfortable for this. Then re-initialze or removeAllObject from array in -viewWillDisappear
Hi Just release the memory once object works is over. Here is the code for you.
- (void)viewDidLoad
{
allImagesArray = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Bottoms";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
collectionBottoms.delegate =self;
collectionBottoms.dataSource=self;
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];
NSLog(#"array:%#",[allImagesArray description]);
image = nil;
}
finalFilePath=nil;
data=nil;
}
paths= nil;
documentsDirectory= nil;
location= nil;
fPath= nil;
directoryContent = nil;
}
If you are using this image array, allImagesArray, when the view is visible then put this code in viewWillAppear or viewDidAppear methods of UIViewController.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
allImagesArray = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Bottoms";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
collectionBottoms.delegate =self;
collectionBottoms.dataSource=self;
for(NSString *str in directoryContent){
NSLog(#"i");
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
NSData *data = [NSData dataWithContentsOfFile:finalFilePath];
if(data)
{
UIImage *image = [UIImage imageWithData:data];
[allImagesArray addObject:image];
NSLog(#"array:%#",[allImagesArray description]);
}
}
}
And, then release it in viewWillDisappear/viewDidDisappear methods of UIViewController.
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[allImagesArray removeAllObjects];
//[allImagesArray release]; // (Uncomment) Call this only if you are not using ARC.
}
Alternatively, a quick, dirty but safe fix is (without knowing your usage of allImagesArray) -
- (void)viewDidLoad
{
[super viewDidLoad];
// Remove previously added objects.
if (allImagesArray != nil && allImagesArray.count > 0) {
[allImagesArray removeAllObjects];
}
// Allocate memory if not done earlier (i.e. first time).
if (allImagesArray == nil) {
allImagesArray = [[NSMutableArray alloc] init];
}
// Rest of your code as stated in your question
}
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 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];
}
}