I would want to show all the pictures in my directory however I am creating Folders in the Directory so that I can sort the pictures. I want to show all of the pictures in several folders. I am using the code
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
allImagesArray = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Bottoms"#"Top"#"Right"#"Left"#"Down"#"Up";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
collectionTrash.delegate =self;
collectionTrash.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]);
}}}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
NSLog(#"j");
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [allImagesArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *reuseID = #"ReuseID";
TrashCell *mycell = (TrashCell *) [collectionView dequeueReusableCellWithReuseIdentifier:reuseID forIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[mycell viewWithTag:1];
imageInCell.image = [allImagesArray objectAtIndex:indexPath.row];
NSLog(#"a");
return mycell;
}
If you see my code you can notice that I have put NSLOG i and j. The j comes up but the i does not.... Is my way wrong showing all the pictures that are in several folders? I do not have any error.
If you have multiple folders then you need to iterate over the folders and then the folder contents to process all of it.
While this line:
NSString *location=#"Bottoms"#"Top"#"Right"#"Left"#"Down"#"Up";
Is technically legal, I guess you're thinking it will do some array / iteration thing for you. It won't. It just concatenates all of the strings together. You probably want something more like:
NSArray *locations = #[ #"Bottoms", #"Top", #"Right", #"Left", #"Down", #"Up" ];
Then you can run a loop over the folders and then the contents:
for(NSString *folder in locations) {
// get the folder contents
for(NSString *file in directoryContent) {
// load the image
}
}
Related
Hi in my application in trying display the Flickr images in my UICollectionView but it shows a empty View Control
My code for display the Flickr images.
{
NSMutableArray *photoURLs;
NSMutableArray *photoSetNames;
NSMutableArray *photoids;
}
viewDidLoad code.
- (void)viewDidLoad
{
[super viewDidLoad];
photoURLs = [[NSMutableArray alloc] init];
photoSetNames = [[NSMutableArray alloc] init];
photoids = [[NSMutableArray alloc] init];
[self loadFlickrPhotos];
[self.collectionview reloadData];
}
- (void)loadFlickrPhotos {
NSString *urlString = [NSString stringWithFormat:#"https://www.flickr.com/services/rest/?method=flickr.photosets.getPhotos&format=json&api_key=a6a0c7d5efccffc285b0fe5ee1d938e3&photoset_id=72157644758906604&per_page=10&nojsoncallback=1",nil];
NSLog(#"the url string==%#",urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSLog(#"the str==%#",jsonString);
NSDictionary *results = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
NSArray *photosets = [[results objectForKey:#"photosets"] objectForKey:#"photoset"];
for (NSDictionary *photoset in photosets) {
NSString *title = [[photoset objectForKey:#"title"] objectForKey:#"_content"];
NSLog(#"title==%#",title);
[photoSetNames addObject:(title.length > 0 ? title : #"Untitled")];
NSString *primary = [photoset objectForKey:#"primary"];
NSString *server = [photoset objectForKey:#"server"];
NSString *secret = [photoset objectForKey:#"secret"];
NSString *farm = [photoset objectForKey:#"farm"];
NSString *urlstr=[NSString stringWithFormat:#"http://farm%#.staticflickr.com/%#/%#_%#.jpg",farm,server,primary,secret];
NSLog(#"your photo id==%#",urlstr);
[photoids addObject:urlstr];
}
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [photoids count];
}
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier =#"Cell";
imggpolitical *cell=(imggpolitical *) [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath: indexPath];
cell.imageview.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",[photoids objectAtIndex:indexPath.row]]]]];
return cell;
}
I have used the above to display the Flickr images in UICollectionView but its coming as a empty view please tell me how to resolve this issue.
Thanks.
At the end of -(void)loadFlickrPhotos method, call reloadData on your UICollectionView. You need to tell UICollectionView to refresh its data.
Try [self.collectionview reloadData]
I don't see that you're assigning a delegate or data source. Or for that matter, created your UICollectionView.
I have a list of images in my resources folder that I want to load into a collection view
I have my images file names in an NSAarray from the documents directory.
.h
{
NSArray *fileList;
NSString * searchedImage;
}
.m
NSFileManager *filesm = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSArray *getFilelist= [filesm contentsOfDirectoryAtPath:[paths objectAtIndex:0] error:nil];
BOOL isDirectory;
for (searchedImage in getFilelist){
BOOL fileExistsAtPath = [[NSFileManager defaultManager] fileExistsAtPath:searchedImage isDirectory:&isDirectory];
if (fileExistsAtPath) {
if (isDirectory)
{
//Found Directory
}
}
if ([[searchedImage pathExtension] isEqualToString:#"png"]) {
//This is Image File with .png Extension
NSLog(#"directoryContents = %#",searchedImage);
}
}
//count files
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *pathsAmount = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
fileList= [fm contentsOfDirectoryAtPath:[pathsAmount objectAtIndex:0] error:nil];
int filesCount = [fileList count];
NSLog(#"filesCount:%d", filesCount);
UINib *cellNib = [UINib nibWithNibName:#"NibCell" bundle:nil];
[self.appliancesCollectionView registerNib:cellNib forCellWithReuseIdentifier:#"cvCell"];
}
return self;
}
this reurns my image names correctly as 63293446.png, appliance63293447.png, appliance63293448.png, appliance63293449.png, etc in viewDidLoad
I want to load these into my collection view cells. Currently it returns a null value for my images file names when in the -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath method
What ive tried so far in addtion to researching on here
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return fileList.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cvCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.backgroundView = [[UIImageView alloc] initWithImage: [UIImage imageNamed: [NSString stringWithFormat:#"%#",searchedImage]]];
NSLog(#"cell Bg image %#",searchedImage); <-----------------//returns null
return cell;
}
try this code
cell.backgroundView = [[UIImageView alloc] initWithImage: [UIImage imageNamed: [NSString stringWithFormat:#"%#",[fileList objectAtIndex:indexPath.row]]]];
make sure searchedImage is not nil.
The file name of the image is in your fileList array, not in searchedImage, (this last variable is useless when creating the image).
NSString *fileName = [fileList objectAtIndex:indexPath.row];
cell.backgroundView = [[UIImageView alloc] initWithImage: [UIImage imageNamed: fileName]];
The problem here is that in your code, fileList can contain files that are not images, thus imageNamed: will fail, and return nil. You should filter your fileList array, and make sure it contains only images.
At first make fileList mutable via NSMutableArray *fileList;
next in block add image path to fileList
if ([[searchedImage pathExtension] isEqualToString:#"png"]) {
//This is Image File with .png Extension
NSLog(#"directoryContents = %#",searchedImage);
[fileList addObject:searchedImage]
}
then in cellForItemAtIndexPath: set image with
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[fileList objectAtIndex:indexPath.row]]];
When I load the images to show to the UICollectionView I load all the images from the array like this
- (void)viewDidLoad
{
allImagesArray = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Others";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
collectionOthers.delegate =self;
collectionOthers.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;
}
This is the biggest issue in my app since it uses so many memory. It is because number and size of the images, this could just take up memory. I would only want to load images when they are needed, and discard them when they are no longer needed.However I do not know where and how to change my code so that it will be that way. I am doing this for three month or so and I really need help.
Update
This is my code for the specific part
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *reuseID = #"ReuseID";
OthersCell *mycell = (OthersCell *) [collectionView dequeueReusableCellWithReuseIdentifier:reuseID forIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[mycell viewWithTag:1];
imageInCell.image = [allImagesArray objectAtIndex:indexPath.row];
NSLog(#"a");
return mycell;
}
Clearly, you should load the images just-in-time. One should never hold an array of images (because they take up a lot of memory), but rather just hold an array of filenames. So I'm suggesting you retire allImagesArray and instead define a NSMutableArray called filenames. You could then create the UIImage objects on the fly:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
OthersCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[cell viewWithTag:1];
imageInCell.image = [UIImage imageWithContentsOfFile:filenames[indexPath.item]];
return cell;
}
This, assumes, of course, that you populated this NSMutableArray of filenames in viewDidLoad:
- (void)viewDidLoad
{
filenames = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *location=#"Others";
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
collectionOthers.delegate =self;
collectionOthers.dataSource=self;
for(NSString *str in directoryContent)
{
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
[filenames addObject:fileFilePath];
}
}
This has a problem, though, because imageWithContentsOfFile (as well as loading it into a NSData first and then doing imageWithData) is a bit slow if the images aren't tiny. On slower devices, this can result in a slight stuttering of a quick scroll of a collection view. So, a better approach would be to (a) load the images asynchronously; (b) use a NSCache to optimize performance for when you scroll backwards.
So, first, define a cache:
#property (nonatomic, strong) NSCache *imageCache;
And, instantiate this in viewDidLoad:
self.imageCache = [[NSCache alloc] init];
self.imageCache.name = #"com.company.app.imageCache";
And then, cellForItemAtIndexPath can (a) set the image from the cache; and (b) if not found, retrieve the image asynchronously updating cache and cell appropriately, e.g.:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
OthersCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[cell viewWithTag:1];
NSString *cacheKey = filenames[indexPath.item];
imageInCell.image = [self.imageCache objectForKey:cacheKey];
if (imageInCell.image == nil) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = [UIImage imageWithContentsOfFile:filenames[indexPath.item]];
if (image) {
[self.imageCache setObject:image forKey:cacheKey];
dispatch_async(dispatch_get_main_queue(), ^{
OthersCell *updateCell = (id)[collectionView cellForItemAtIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[updateCell viewWithTag:1];
imageInCell.image = image;
});
}
});
}
return cell;
}
And, obviously, make sure you purge the cache if you receive memory warnings (in iOS 7, the cache doesn't always automatically purge itself under pressure like it used to do):
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[self.imageCache removeAllObjects];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
This is the method in which you should be loading the images.
In viewDidLoad, I'd build the array of NSString file paths to each image, then I'd use the collectionView:cellForItemAtIndexPath: method to load the image from the specific file path for this particular cell.
In viewDidLoad You could just load a list of available images. So remove the for loop: for(NSString *str in directoryContent) { ... } loop there (EDIT: or make it a simple for loop, just to populate an array with filenames for the files having data).
When you update a specific collectionviewcell in collectionView:cellForItemAtIndexPath:, just load the image (only 1). The cell will now hold the image data instead of your view controller. So when the cell is released, so is the image data.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have an error saying Incompatible pointer types sending NSArray to parameter of NSString. I also have used instruments and is very weird that as soon as my app start its around 90mb in memory. What is wrong with my code.
#interface TrashViewController ()
#end
#implementation TrashViewController {
NSMutableArray *Trash ;
}
#synthesize collectionTrash;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
filenames = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *locations = [[NSArray alloc]initWithObjects:#"Bottoms", #"Dress", #"Coats", #"Others", #"hats", #"Tops",nil ];
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:locations];
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
collectionTrash.delegate =self;
collectionTrash.dataSource=self;
for(NSString *str in directoryContent)
{
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
[filenames addObject:finalFilePath];
}
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
NSLog(#"j");
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [filenames count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"ReuseID";
TrashCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[cell viewWithTag:1];
NSString *cacheKey = filenames[indexPath.item];
imageInCell.image = [self.imageCache objectForKey:cacheKey];
if (imageInCell.image == nil) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = [UIImage imageWithContentsOfFile:filenames[indexPath.item]];
if (image) {
[self.imageCache setObject:image forKey:cacheKey];
dispatch_async(dispatch_get_main_queue(), ^{
TrashCell *updateCell = (id)[collectionView cellForItemAtIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[updateCell viewWithTag:1];
imageInCell.image = image;
});
}
});
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"s:%d", [Trash count]);
NSString *trashBin = [Trash objectAtIndex:indexPath.row];
NSLog(#"k%#l",trashBin);
[filenames removeObjectAtIndex:indexPath.row];
[Trash removeObjectAtIndex:indexPath.row];
[self deleteMyFiles:trashBin];
[collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]];
}
NSString *myFileName;
-(void) deleteMyFiles:(NSString*)filePath {
NSError *error;
if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
} else {
NSLog(#"%#",filePath);
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[self.imageCache removeAllObjects];
}
eYour problem is in line 5 of viewDidLoad. The method signature for -stringByAppendingPathComponent is
- (NSString *)stringByAppendingPathComponent:(NSString *)aString
Note that it expects a String, but you are passing an Array.
What you probably want to do is change
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:locations];
To something like
NSInteger someIndex = 0; //this will pick the first object in locations, e.g. #"Bottoms".
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:[locations objectAtIndex:someIndex]];
locations is an Array of Strings, so you need to pick one and not pass the entire Array.
Also, next time please dont just dump your code in here, but tell us which line caused the error. You are much more likely to get a quick response if you can point to the part that couses the problems.
This question already has an answer here:
Don't have the pictures from directory on CollectionView
(1 answer)
Closed 9 years ago.
I am showing the Pictures in all of the Directories however It does not display the pictures. I am putting NSLog in the code so that I can find out which code is working and I only get "j" in the log. I do not see the "a" in the log. What do you think is wrong?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
allImagesArray = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *locations = [[NSArray alloc]initWithObjects:#"Bottoms", #"Dress", #"Coats", #"Others", #"hats", #"Tops",nil ];
NSString *fPath = documentsDirectory;
for(NSString *component in locations)
{
fPath = [fPath stringByAppendingPathComponent:component];
}
NSArray *directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath: fPath];
collectionTrash.delegate =self;
collectionTrash.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]);
}}
for(NSString *folder in locations) {
// get the folder contents
for(NSString *file in directoryContent) {
// load the image
}
}}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
NSLog(#"j");
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [allImagesArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *reuseID = #"ReuseID";
TrashCell *mycell = (TrashCell *) [collectionView dequeueReusableCellWithReuseIdentifier:reuseID forIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[mycell viewWithTag:1];
imageInCell.image = [allImagesArray objectAtIndex:indexPath.row];
NSLog(#"a");
return mycell;
}
Feel free to as for more code.
If you look at the exception, it tells you very precisely what's wrong:
You are trying to calling a 'length' method on an array, which simply does not exist. You want to use count here instead. It's not in the code you posted, though - so just do a search for length and you'll probably find it rather easily if the project isn't huge.
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:locations]; gives you a warning, because locations is an array. Think about it - just doesn't make sense: which of its elements do you want to add to the path?
As I think about it, both errors probably relate to each other: You simply ignored the compile time error - or warning - for the fPath, and now the stringByAppendingPathComponent: method calls length on its parameter, which is a method of the expected NSString.
Bottom line: Do not ignore compiler warnings! If you fix those, you probably reduce crashes, too.