I'm trying to localize the NSPhotoLibraryUsageDescription key defined in the application's info.plist file (reference here).
This key gives you a point to provide custom message when the app is first asking for access to your camera roll.
I'm using ALAssetsLibrary to enumerate assets groups (which triggers the access request message to pop-up).
So far my googling doesn't answer how I could achieve this.
I want to avoid localizing the whole info.plist file as it contain a lot more non-locale dependent content.
Anyone already solved this or have hints how to proceed?
There is a file you can create (which may be created for you when you create a project) called InfoPlist.strings. This file is used and localized much like the file Localizable.strings.
In it you would have and entry something like:
NSPhotoLibraryUsageDescription = "Test of new Photos warnings";
Note that there are no quotation marks around the key
I think as long as the key is included in info.plist, it will localized using the value in InfoPlist.string if it is available for the language. Otherwise it will use whatever is defined in info.plist.
I have my note here https://github.com/onmyway133/notes/issues/290, or you will get
Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.
Once these issues have been corrected, you can then redeliver the corrected binary.
Make sure
You declare the keys in Info.plist
You localize it in InfoPlist.strings
You don't need double quotes, like "NSPhotoLibraryUsageDescription" = "Test of new Photos warnings";, you can just use NSPhotoLibraryUsageDescription = "Test of new Photos warnings";
The only way to make this work for me was in Xcode to:
1) Go to Project target -> Info-> Localization-> Add localization
Added language there. This operation created the <projectName>/<LanguageInitials>.lproj folder.
2) I created file InfoPlist.strings inside the folder <projectName>/<LanguageInitials>.lproj;
3) I added the text:
NSPhotoLibraryUsageDescription = "<Add your translated text here>";
inside that InfoPlist.strings file.
4) I then added that folder to the project with File -> add new files to the project or drag and drop.
Note: to test this I:
Cleaned cache, set the language on simulator to be the new one, edited the language in scheme to be the new one at running on simulator and restarted the simulator.
Related
How do you go about creating files at arbitrary locations given you have the absolute path? I want to create a file in some arbitrary location /Users/me/random/project3/<moreStuffInThePath. How would I go about doing this?
To create a directory I would do:
try FileManager.default.createDirectory(atPath: "/Users/me/random/project3/<directoryName>"
This worked fine for directories.
However the counterpart for creating files does not work:
FileManager.default.createFile(atPath: "Users/me/random/project3/something.txt", contents: someString.data(using: .utf8)) // always returns false
I have checked out other stack overflow threads on creating files. Everything I found was about creating files in the .documentDirectory or it was outdated.
Eg: How to create text file for writing
Create empty file swift
Read and write a String from text file
TLDR: How do I create text files/files with random extensions at arbitrary locations on the pc given I have the absolute path?
I would also be grateful if someone could explain why all tutorials available on this matter are about the document directory. Why is it so significant?
Thank you!
This is most likely because your app is sandboxed.
Go to your project settings, select the macOS target and go to "Signing and Capabilities". You should see something like this:
If your app needs to create files in arbitrary locations, you must remove the app sandbox by clicking on the "x" on the top right. Note that this will cause your app to be rejected from the Mac App Store.
If you want to upload your app to the Mac App Store, then you must keep the sandbox, and write to "user selected locations" only. Select "Read/Write" rather than "Read Only" next to "User Selected File". (Although it says "File", this includes directories too) This allows you to write to locations chosen by a user using something like an NSSavePanel.
Its really hard to find a tutorial to do this as most information relates to Xcode 3. Answer below may help some people.
I sourced most of my information for the answer below from the following sites:
http://meandmark.com/blog/2011/12/creating-custom-xcode-4-project-templates/
http://www.bobmccune.com/2012/03/04/creating-custom-xcode-4-file-templates/
I spent hours searching the web to find information about doing this. Its not actually that hard to set up project templates for Xcode4.5 but its hard to find information on the web that puts it all together! Hopefully the steps below will help you to create your own.
Setting Up
Lets start by getting a copy of an existing Xcode project template to use as a base. Open finder, go to Applications and right click on Xcode to show package contents. Navigate to Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/Application/
[EDIT]
In Xcode 5 the PATH is as follows: ~/Library/Developer/Xcode/Templates/Application/Project Templates. If Templates/Application/Project Templates not exists you should create it too. Credit to seufagner in the comments below for the update although I have not tried this myself.
[/EDIT]
Copy (do not cut/paste!) one of the listed templates.
Open another finder window and navigate to the following directory (to unhide your Library folder type this cmd in terminal: chflags nohidden ~/Library/ or select press the alt/option key when clicking on Finder/Go) /Library/Developer/Xcode/Templates (you may need to create this folder if not already present) /Project Templates/
Create a folder in here. Call it whatever you wish, a suggestion is your company name. This name appears in the left hand menu of the new project dialogue in Xcode. e.g. in the attached image I've called mine Appscore, there's another one there for cocoas2d.
Paste the project template in here and change its folder name to whatever you wish e.g. MySuperProjectTemplate.xctemplate. We are not done yet though as we need to change the template's identifier. Otherwise it will not appear in the Xcode new project dialogue window.
Open the TemplateInfo.plist file in TextEdit. Search for the Identifier key. You should see a string value something similar to "com.apple.dt.unit.XXXXXX". Replace this with whatever you wish as long as its unique. I again suggest adding your company name and a name that describes the template.
If you now open Xcode you should see the project template appearing under your company name in the new project dialogue.
Customising
At the moment you have a copy of an existing project template which is not very useful. I'm guessing you have a number of classes that get reused in nearly all your projects? How about we include them into this template?
Copy the files you wish, and paste them into your new project template i.e. navigate to /Library/Developer/Xcode/Templates/Project Templates//MySuperProjectTemplate.xctemplate/
Open the TemplateInfo.plist file in TextEdit again. First thing we have to do is tell the project template to include the new files so search for a key called "Nodes" that has an array of values. Add the two following lines:
<string>_VARIABLE_classPrefix:identifier_.h</string>
<string>_VARIABLE_classPrefix:identifier_.m</string>
For example if your controller was called BaseViewController the lines would look like:
<string>___VARIABLE_classPrefix:identifier___BaseViewController.h</string> <string>___VARIABLE_classPrefix:identifier___BaseViewController.m</string>
Next find the Definitions key and you should see a dictionary as its value. In here we have to add a reference to the included files. Create a new key and call it ___VARIABLE_classPrefix:identifier___BaseViewController.h (again taking the BaseViewController as an example).
The value of this key is again a dictionary. It contains a key called Path and a string value which is the name of the file e.g. BaseViewController.h
I've attached the following images to show what I mean as I think my description is falling short. You may notice that there is a key in there called "Group", this as you can guess allows you to create groups and input files directly :D
Hope this is actually useful to someone :) Any questions comment below and I'l do my best to answer. I did this a few weeks ago so my memory is a little hazy.
You can also learn a lot from inspecting the existing project templates, which you can find in:
/Xcode.app/Contents/Developer/Library/Xcode/Templates/Project Templates/
for Mac and
/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/
for iOS.
There are few sample templates also on GitHub by Reid Main and another one by Acani. There are also AFNetworking templates, created by Mattt Thompson. See all the examples, including ones built by Apple and then you can start creating your own.
A good overview of all of the variables used in the plist file can be found here: https://gist.github.com/shazron/943736
#bennythemink
Your answer is really very much help full but I want to add some more things in your answer.
When we copy xcode predefine template than this key contains
<key>Ancestors</key>
<array>
<string>com.apple.dt.unit.storyboardApplication</string>
</array>
this value. When we use this key value in Custom template of xcode it will create AppDelegate class by default. Which we can not move to folder only we can shift it into group.
So i suggest to add this:
<key>Ancestors</key>
<array>
<string>com.apple.dt.unit.objectiveCApplication</string>
<string>com.apple.dt.unit.iPhoneBase</string>
<string>com.apple.dt.unit.prefixable</string>
</array>
value in Custom template so that we will have fully empty template in which we can do any custom stuff.
I have almost finished my iPhone app, but want to rename it as I don't like the name I chose in the beginning. Is this easy to do, and if so, how do I do it?
Go to target-> yourApplicationName(double click/get Info)->Build->ProductNAme
Set your new name for that application there
hAPPY cODING...
I don't know what rename does, but there are a possible 5 names to deal with. There's the name of your .xcodeproj file directory, the name of your target within that project, the Product Name under Packaging in the Build Settings, and the Bundle Display name in the Info.plist, and the name you provide for the app in iTunes Connect. None of these 5 names needs to be the same, and you can name them all slightly differently. In fact this is common.
For instance, you might want the Bundle Display Name to be short so that it will fit under the icon, and it can have spaces in it. The Product Name can be much longer and more descriptive, but can't have spaces. You iTunes Connect name might be longer still, with spaces, and you may have change the spelling, etc. slightly if your preferred spelling is already taken, etc.
In the latest version of xcode.
Project > rename.
Choose new name.
I had the same problem recently and tried Project -> Rename, as well as Target -> application name -> Build -> ProductName
Then, I remembered the .plist file. If you double click the .plist file in your app's resources folder, you'll see "Bundle Name". Changing this did the trick for me!
Change your bundle display name in info.plist file
Here's an obscure problem. I'm using an InfoPlist.strings to localize my app name. It's only got one value: CFBundleDisplayName = "Mon App". The strings file is localized (putting it in a directory for that localization).
I've just made an extra target, where I change things like the non-localized app name (different Info.plists), and the icon. I'm also changing the Default.png using a run script build phase (copying different files depending on the app type I'm building).
I've tried using the script to copy different versions of my InfoPlist.strings, but I couldn't make it work. Here's what I used:
if($TARGET_NAME == "MonApp")then
cp fr.lproj/MonApp_InfoPlist.strings fr.lproj/InfoPlist.strings
endif
I've seen a post suggesting wincent strings util for processing strings, but wanted to see if there's an easy way to do this. Any help greatly appreciated.
You don't need to do this.
If you have fr.lprog/InfoPlist.strings and en.lproj/InfoPlist.strings in your project, you should see just one InfoPlist.strings entry, with two subitems fr and en. If you drag and drop the InfoPlist.strings file into a Copy Bundle Resources build phase, all localized versions will be copied into the appropriate .lproj files at build time. You don't need to create a separate target or write a script to do this; the right thing happens.
Is it possible to modify the BundleDisplay name at runtime ???
Thanks
I'd be really surprised if you could, since doing so would require you to edit the Info.plist file, which is in a write-protected directory. Even if you could modify it, it would cause the code signature to no longer match the application bundle, and the app would refuse to launch.
The closest you can get to using a different display name is to provide localized versions of it.
If you set the Bundle Display Name to a variable ie ${MY_BUNDLE_DISPLAY_NAME} and make sure that gets set in your build phases or from your ENV, or from an XCCONFIG file when building from the command line, the name should be replaced with what you set it with.