I'm trying to access a strings file I use in my iOS app project, from a mac console app I'm writing.
Obviously with my ios app I can access this directly via the bundle...
NSString *fname = [[NSBundle mainBundle] pathForResource:#"whatever" ofType:#"strings"];
NSDictionary *d = [NSDictionary dictionaryWithContentsOfFile:fname];
NSString *loc = [d objectForKey:#"LABEL_001"];
However, I want to retain the parsing functionality but access the strings file directly.
I haven't been able to find a method to do this?
Related
I would like to be able to set app preferences at build time in my iOS project. I know that I can create different targets in xcode but I think with the amount of preferences I might end of making I could end up with a nightmarish amount of targets in my project.
An easy example is setting the a default integer for a default called 'amount'. Currently 'amount' is defined in a plist file in my app called 'preferences.plist'. I load that plist file and register defaults with that plist on NSUserDefaults.
NSURL *preferencesFile = [[NSBundle mainBundle] URLForResource:#"preferences" withExtension:#"plist"];
NSDictionary *defaultPreferences = [NSDictionary dictionaryWithContentsOfURL:defaultPreferencesFile];
[[NSUserDefaults standardUserDefaults] registerDefaults:preferences];
I assume I could write a script to modify the preferences.plist file before I build, then build it. However I think might become a nightmare when I need to mod a bunch of different preferences.
End game is to have jenkins build my IPAs. I would like to easily create multiple jenkins builds that will point to the same code based but build my app with different preferences.
Android has flavors, and the ability to set resource values. Does iOS have a something similar that I can use to build these different 'flavors' of apps?
I use a Jenkins build action to inject the appropriate variables into the plist before the Xcode build:
plutil -replace MyBuildBranch -string ${BRANCH} MyProj/MyProj-Info.plist
I then read that value at runtime using something like:
NSBundle * bundle = [NSBundle bundleForClass:[AppDelegate class]];
NSString * myBuildBranch = bundle.infoDictionary[#"MyBuildBranch"]
I don't have enough working experience with Android.
I'd approach this with multiple plists.. One for each flavor..
And i'll try either of the below options --
I'd have Jenkins swap the plist based on the flavor i am trying to build.. the script will pick the right plist for a given flavor
I will define compile-time MACROS for each flavor and load the appropriate plist.. something like this
#ifdef FLAVOUR1
NSURL *preferencesFile = [[NSBundle mainBundle] URLForResource:#"preferences-flavour1" withExtension:#"plist"];
NSDictionary *defaultPreferences = [NSDictionary dictionaryWithContentsOfURL:defaultPreferencesFile];
[[NSUserDefaults standardUserDefaults] registerDefaults:preferences];
#endif
#ifdef FLAVOUR2
NSURL *preferencesFile = [[NSBundle mainBundle] URLForResource:#"preferences-flavour2" withExtension:#"plist"];
NSDictionary *defaultPreferences = [NSDictionary dictionaryWithContentsOfURL:defaultPreferencesFile];
[[NSUserDefaults standardUserDefaults] registerDefaults:preferences];
#endif
#ifdef FLAVOUR2
NSURL *preferencesFile = [[NSBundle mainBundle] URLForResource:#"preferences-flavour3" withExtension:#"plist"];
NSDictionary *defaultPreferences = [NSDictionary dictionaryWithContentsOfURL:defaultPreferencesFile];
[[NSUserDefaults standardUserDefaults] registerDefaults:preferences];
#endif
In the app I'm making I have a lot of huge strings. I don't want to hardcode these into my code because it makes the code unbearably messy. When I made a similar android app, it was a simple matter of declaring the string in strings.xml as
<string name="hello_world">Hello World!!</string>
and accessing it in the java file with
getString(R.string.hello_world);
How can I do something like this with iOS?
You could put them into a .plist file and load them using the following code (which assumes a file called strings.plist which has been copied into the app bundle):
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"strings" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];
NSString *string1 = [dict objectForKey:#"string1"];
However if you want to internationalize your app, then using Apple's Internationalization and Localization technology might be something to look at instead.
EDIT: you'll want to load that file/dictionary only once and keep it around the entire app lifetime; don't use the above code for every string access!
I am creating a quiz app for iPhone. I store all the questions in an NSArray that is loaded from a .xml file every time the app is opened. That file will be the same accross all "instances" of the app, and it will never be changed by the user.
I could hard-code all the questions with code, but I found it more elegant to have it in a file that is easily edited by any text editor.
But how do I give each app "instance" of the app a copy of that file? That file should be bundled along with the rest of the application files.
This is the code I use so far (in app delegate).
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *path = documentPaths[0];
path = [path stringByAppendingPathComponent:#"questions.archive"];
NSArray *fileQuestions = [[NSArray alloc] initWithContentsOfFile:path];
if (!fileQuestions)
{
// Code to add three default questions…
[fileQuestions writeToFile:path
atomically:YES];
}
// And here the "file questions" are transformed to instances of my question class
No need to try to store the file in Documents directory. Just store it right there in the app bundle itself. This works exactly like an image file, a sound file, or any other resource. Make the file part of the project; make sure it is part of the app target, so that it will be copied into the app bundle as part of the build process. In the running app, get its path with [[NSBundle mainBundle] pathForResource:ofType:], and read it as you would any file of this type.
I am having problems updating an app to iOS7 SDK. Before I've used iOS 6 SDK and accessed my mp3 file using a NSURL for the folder like this:
NSURL *folderURL = [[NSBundle mainBundle] URLForResource:#"" withExtension:#"" subdirectory:#"AudioGuide"];
Now, using the iOS 7 SDK I always get nil as the value for folderURL and my audio guide doesn't find the mp3's anymore.
I've already looked into the generated .app-Bundle for the simulator (in ~/Library/Application Support/...), and I can see the "AudioGuide" folder in the root. So it's definitly there.
I am not that iOS guru and didn't really follow iOS7 updates. Has there been any changes made on how to access own assets in an app? How do I access my files?
Apple doc for - (NSURL *)URLForResource:(NSString *)name withExtension:(NSString *)extension subdirectory:(NSString *)subpath
Returns the file URL for the resource file identified by the specified
name and extension and residing in a given bundle directory.
what that means is you can get the file URL with specific type in a given subdirectory, so you should use this method call with your file name and extension.
If you are trying to read the list of files under that directory, what you can do is bundle all of your audio files in a single zip or gzipped file and you extract it in your Documents or Application Support directory when it is accessed for the very first time, then you can read it using the code below.
NSArray *directories = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *directory = [directories objectAtIndex:0];
NSString *audioDirectoryPath = [directory stringByAppendingPathComponent:#"AudioGuide"];
NSArray *audioFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:audioDirectoryPath];
Hope this helps!
Currently using:
NSString* path = [[NSBundle mainBundle] pathForResource:#"filename"
ofType:#"txt"];
This only works however after I manually add the file into the application bundle.
I can use the documents directory but that's even worse.
After resetting the sim, the file goes away. How do I get it to stay?
How would I write out the file from somewhere to there? Like from a file in source? I don't want to alloc a several megabyte NSString object.
Credit goes to Lyle42 on freenode irc (#iphonedev):
I wasn't aware this field even existed. By adding any file into the copy files build phase (under build phases), they persist across builds.
Then this code:
NSString *_filePath = [[NSBundle mainBundle] pathForResource:#"filename" ofType:#"txt"];
NSLog(#"%#",_filePath);
NSData *_binary = [NSData dataWithContentsOfFile:_filePath];
NSString *_fileContents = [[NSString alloc] initWithData:_binary encoding:NSUTF8StringEncoding];
Works just great. (loads contents of file into an NSString).
You can use this to get your path for the file
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [documentPaths objectAtIndex:0];
filePath = [path stringByAppendingPathComponent:file_name];
you can get the file from your app bundle using
NSString *pathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:file_name];
I can use the documents directory but that's even worse.
Not really. The documents directory is persistent, and the recommended directory for essential documents created by your application. In addition, it's backed up by iTunes, and can be specified for iCloud backup. The app bundle just can't compete with that!
After resetting the sim, the file goes away. How do I get it to stay?
You can't, once the simulator has been "reset" (and I mean a hard wipe of all data and apps), nothing is saved. In between test builds, however, data copied out of the app bundle should survive unless you're storing things in /tmp. In addition, objects in the bundle are "refreshed" (recopied) in the build phase, meaning your resource isn't wiped out, merely reset to the one specified in your project.
How would I write out the file from somewhere to there? Like from a
file in source? I don't want to alloc a several megabyte NSString
object.
To read the file into memory, it would have to turn into a "several megabyte NSString" eventually, but if you really want to add a little IO to your plans for a massive string object, have a look at NSFileManager.