In simulator i will get the obj files from bundle:
NSArray *myArray = [[NSBundle mainBundle] pathsForResourcesOfType:#"obj" inDirectory:nil];
In simulator the obj files are printed alphabetical order:
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app/**banana.obj**,
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app/**plane3.obj**,
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app/**wolverine.obj**,
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app/**Wteapot.obj**,
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app/**XBODY.obj**,
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app/**YLID.obj**
)
But ipad the obj files are not printed alphabetical order.
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app/**wolverine.obj,**
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app**/**Wteapot.obj**,**
/Users/name/Library/Application Support/iPhone Simulator/6.0/Applications/10FF2D60-7B33-4AE9-9CA2-95A951A55C49/3DModels.app/**plane3.obj**,
What is the problem?
Apple Document of pathsForResourcesOfType:inDirectory: says that:
An array containing the full pathnames for all bundle resources
matching the specified criteria. This method returns an empty array if
no matching resource files are found.
It means Apple doesn't say that it will give you path in any particular order but if you need it in some order than you can sort by yourself.
NSArray *sorted = [myArray sortedArrayUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2)
{
return [s1 localizedCaseInsensitiveCompare:s2];
}];
So now you have sorted NSArray of all paths.
I think some of your obj file name starting character is in capital letter. just change those file names starting character is in small letter.
Related
I'm making an app that uses encoding to store objects on the document directory,
On iOS Simulator, the objects are getting saved perfectly, and if i closed the app and got back to it all the data are restored with no issue.
But today i tried my app on the iPhone 5s, the objects are not getting saved when i close the app and go back to it again all the data are getting removed only on the real device, what is the problem ?
I'm using this method to get the directory path:
- (NSString *)pathForTask
{
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories firstObject];
return [documentDirectory stringByAppendingString:#"Tasks"];
}
Archive:
NSString *path = [self pathForTask];
[NSKeyedArchiver archiveRootObject:self.privateTasks toFile:path];
Unarchive:
NSString *path = [self pathForTask];
_privateTasks = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
The following line of code is causing your problem:
return [documentDirectory stringByAppendingString:#"Tasks"];
The results in the returned path being something like:
.../DocumentsTasks
Note the lack of a slash.
Change the line to:
return [documentDirectory stringByAppendingPathComponent:#"Tasks"];
This will return a proper path and your code will work on a device.
It works in the simulator because you end up creating a file named DocumentTasks in some folder on your computer. But on a real device, the folder that this file is trying to be written to is read-only due to sandboxing.
Try getting the documents directory using the following code instead:
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
After getting the documents directory, you can get the path to a specific file by doing:
NSURL *fileURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"[FILE NAME]"];
I'm not sure why your code doesn't work, but this is the code I use on my app and it works in the simulator and the physical device.
Frequently code that works on the sim but not on the device is caused by filename upper/lower case mismatching.
The file system in Mac OS is almost always case-insenstive. (You can use disk volumes who's file system are case sensitive in Mac OS, but they are not by default.)
The simulator runs on Mac OS. It's file system is not case sensitive. So if you save a file as "Tasks" and then load it as "tasks" it works on the sim, but not on an actual iOS device. Make sure you check really carefully for mismatched case in your filenames.
I am attempting to load an executable file from a bundle stored in the apps documents directory. I can create the NSBundle successfully and read the info.plist but whenever I try to load the bundle with [NSBundle load] I always get a similar error no matter how I try to load the bundle:
Cannot find executable for CFBundle 0x..... (not loaded)" or, when using an NSError "The bundle "${PRODUCT_NAME}" couldn't be loaded because its executable couldn't be located
The bundle contains two items, 1) info.plist and 2) Obj-c class header and implementation. I have edited the info.plist to change the Principal class name.
I first copy the bundle into the iPhone simulators documents directory then run the following code after a button press to load the bundle.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *file = [documentsDirectory stringByAppendingPathComponent:#"TestBundle.bundle"];
NSBundle *myBundle = [NSBundle bundleWithPath: file];
[myBundle load];
I understand that you are not supposed to load executables after run time but I have seen a couple of articles/ comments from people who are able to do it, at least on a simulator.
I would basically like to know why i get this error and how to fix it (if possible).
Thanks
I have resources:
Test.png
test1.jpg
tesT2.jpg
tEst3.jpg
I need to show this image in UIImageView. So I wrote:
imgView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[myObject.filename stringByDeletingPathExtension] ofType:[myObject.filename pathExtension]]];
myObject is entity in my model. I get filename from xml, but in xml it have format like:
filename="test.png"
filename="test1.jpg"
filename="test3.jpg"
filename="test3.jpg"
So my Image is (null) because in pathForResource I search #"test" ofType "png", but need #"Test" ofType"png".
How I can get correct resources without renaming them?
If you can't rename the source data (which you should do really), then you would need to use the file manager to get a list of all of the files available and then do a case insensitive filter to get the matching name and use that.
You can get all resources from bundle see answers here Count of images in my NSBundle mainBundle bundlePath and manually check names of image that need to load
You should get the list of files in your bundle with the appropriate extension with
NSArray *files = [[NSBundle mainBundle] pathsForResourcesOfType:[myObject.filename pathExtension] inDirectory:nil];
Now you go through the array files and try to match your filename. This is done using NSArray's method - (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate (clean way) or by looping through the array (old school way).
Predicates are described in the Predicate Programming Guide.
For the old school method, simply loop like this:
for (String *file in files)
{
if ([file caseInsensitiveCompare:myObject.filename] == NSOrderedSame)
{
// do whatever you need to do with the file
break; // stop the loop
}
}
How I can get correct resources without renaming them?
Basically iOS contains HFSX file system which is case sensitive. So without renaming the files it is not possible to get the correct resources. Refer this
Also the other alternative is, as #wain said, if you have file store in any directory, then you can just parse from that directory and then do a case insensitive filter to get the matching name and use that for fetching the exact filename from directory and then pass intopathForResourceofNSBundleapi. Refer this for getting the list of file names from directory
I have a method:
#define ROOT_ASSETS_PATH #"/assets/"
...
-(NSMutableDictionary*) getContentsOfPlist{
NSString *pageContentPlistPath = [[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: ROOT_ASSETS_PATH] stringByAppendingPathComponent:#"content.plist"];
NSMutableDictionary *mDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:pageContentPlistPath];
return mDicitonary;
}
On the simulator. this returns a dictionary. On the iPad, it returns nil. Made sure the extension case matches that in the call as well.
Any ideas?
The issue was case after all. Case of the filename didn't match the case I put in the parameter. OSX doesn't care, but the iPad does.
Try removing the slashes in your #define. stringByAppendingPathComponent will add the slashes for you. Not sure why this would work in the Simulator.
Also it is good idea to use:
[NSPropertyListSerialization propertyListWithData:options:format:error:]
Instead of direct NSDictionary initialization. If something will fail, it should return a nice error for you.
+ (id)dictionaryWithContentsOfFile:(NSString *)path
Parameters
path
A full or relative pathname. The file identified by path must contain
a string representation of a property list whose root object is a
dictionary.
Return Value
A new dictionary that contains the dictionary at path, or nil if there
is a file error or if the contents of the file are an invalid
representation of a dictionary.
So, you have to set a full path to your file (or an appropriate relative path)
Note also that the app bundle is read-write on Simulator but read-only on device.
I'm developing for iOS. how can I put in a NSMutableArray all file names that are present in the app? Thanks a lot
Try
NSString path = [[NSBundle mainBundle] bundlePath];
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
This should give you content inside the .app folder. If you have files inside subfolders, you'll have to check if the file returned is a file or folder, and get the files inside recursively