'While loop with NSFileManager directory enumerator not running
I am seeking help to understand why a tutorial I am following is not working for me. I am running macOS 12.3.1, Xcode 13.3.1. The project is in Objective-C and using XIB.
This is a view-based NSTableView, using a folder of PNGs stored on my SSD for the imageView
and the stringByDeletingPathExtension
as stringValue
for the cell's text field. I filled my code with NSLog
calls to try and catch what could have been going awry.
Most setup is happening in applicationDidFinishLaunching:
, where I initialise an NSMutableArray
for the table's content, an NSString
for the file path, then set up the file manager and the directory enumerator with said path (note: all working up to here).
Now comes the loop to populate the table contents' mutable array. I cannot understand why said loop gets skipped entirely! Its condition is to set an NSString
equal to the nextObject
of the directory enumerator. I am sure the loop gets skipped because the NSLog
call after the loop runs!
Here is the entire code of applicationDidFinishLaunching:
, including my comments and logs (I have just replaced my account name with ):
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
_tableContents = [[NSMutableArray alloc] init];
NSString *path = @"/Users/<myUsername>/Developer/Apple-Programming-YT/Cocoa Programming/Flags/PNG/40x30";
// MARK: Debug 1
NSLog(@"path found: %@", path); // the correct path gets printed, as expected
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDirectoryEnumerator *directoryEnum = [fileManager enumeratorAtPath:path];
NSString *file;
// MARK: Debug 2
NSLog(@"Checking that file is empty: %@", file); // (null) gets printed, as expected
// MARK: Debug 3
if (file != directoryEnum.nextObject) {
NSLog(@"File cannot be assigned to the Directory Enumerator");
} else if (file == directoryEnum.nextObject) {
NSLog(@"File properly assigned. Proceed!"); // this gets printed! Is it correct?
} else {
NSLog(@"Something went wrong during assignment of nextObject to file");
}
while (file = [directoryEnum nextObject]) {
NSLog(@"While loop entered!"); // this doesn't get printed! Why?!
// MARK: Debug 4
NSLog(@"File: %@", file);
NSString *filePath = [path stringByAppendingFormat:@"/%@", file];
// MARK: Debug 5
NSLog(@"Image filepath: %@", filePath);
NSDictionary *obj = @{@"image": [[NSImage alloc] initByReferencingFile:filePath],
@"name": [file stringByDeletingPathExtension]};
[self.tableContents addObject:obj];
}
[self.tableView reloadData];
NSLog(@"Table View Reloaded"); // This gets printed!
}
I have uploaded the full app to GitHub, in case you may want to look at it and see if something else could be wrong, but every outlet, delegate, data source is connected. Now for my diagnosis & ideas:
- The Debug 3 mark is what I find most interesting. AFAIK
file
should still be(null)
, so how checking if it is equal todirectoryEnum.nextObject
returnsYES
? - I created Debug 3 because the
NSLog
checking whether the loop had been entered didn't get printed. I therefore assumed the condition for thewhile
loop had a problem. - I then tried to create a
do-while
loop instead of thiswhile
loop and, of course, the code ran. For the log with "Image filepath" it returned the address above followed by(null)
, as if it didn't find the file. But how is it possible if the file is indeed there? Do I require some sort of permission to access it? Being the object empty, the next line in the console was quite clear: "attempt to insert nil object from objects[1]".
But now, how do I solve this?
Any help here is much appreciated. If you download it from GitHub, please replaces the *path
string with a folder of PNGs on your SSD.
Thank you.
Solution 1:[1]
I don't think you can access the filesystem directly with a path like that any more. If you check the value of file
in your code, it is nil, which means that file == directoryEnum.nextObject
will evaluate to true.
You have to create a path starting with NSHomeDirectory()
or similar and add components to it. This makes a path that goes via your application support folder, which contains an alias to the desktop. I'm not sure why that's OK and accessing it directly is not, but I'm not a Mac developer.
I'd have to say following a tutorial as old as that, you're going to struggle with a lot of things.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | jrturton |