Using Xcode 7.2 (on Yosemite), I can't seem to access custom key from my info.plist from a playground:
import UIKit
var str = "Hello, playground"
let app_id = NSBundle.mainBundle().infoDictionary?["MyAppID"] as? String
Using the above code, app_id is nil. I expected it to be the String "TEST"
I included it in my info.plist like this:
Is there some limitation to playgrounds that I haven't read about?
If I print all of the keys, my custom key is missing:
let dict = NSBundle.mainBundle().infoDictionary!
for k in dict.keys {
print("\(k)")
}
prints the following:
DTSDKName
CFBundleIdentifier
CFBundleSupportedPlatforms
CFBundleInfoDictionaryVersion
LSRequiresIPhoneOS
CFBundleNumericVersion
DTPlatformName
CFBundleShortVersionString
CFBundleVersion
UIViewControllerBasedStatusBarAppearance
UIRequiredDeviceCapabilities
UIStatusBarHidden
CFBundlePackageType
UIDeviceFamily
CFBundleExecutable
CFBundleInfoPlistURL
LSBackgroundOnly
CFBundleName
CFBundleDevelopmentRegion
If I look at the Bundle name, like this:
let name = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String
I see the name of my playground, not the name of the workspace. Can I get at the info.plist for the project?
Playgrounds don't have an Info.plist
file. Playgrounds are self-contained. Adding them to a project does not cause them to access files in the project. They only can access files in their own package.
You can add a plist file to the playground as a resource and read it that way (using pathForResource
and NSDictionary(contentsOfFile:)
, but you can't use objectForInfoDictionaryKey
on it. You can't name it "Info.plist" since that will collide with the auto-genenerated Info.plist playgrounds use to run.
So for example, if you copy a plist into your Resources folder, name it MyInfo.plist
, and load it:
let infoPath = NSBundle.mainBundle().pathForResource("MyInfo.plist", ofType: nil)!
let info = NSDictionary(contentsOfFile: infoPath)!
This isn't exactly the same as a real Info.plist, since things like $(EXECUTABLE_NAME)
won't be expanded.
But the points here are that playgrounds are in their own bundle, unrelated to the application and they dynamically create their own Info.plist when they run. What you're trying to do here doesn't match how playgrounds currently work.
A critical part of understanding all of this is that playgrounds are real applications. They get compiled and built into an executable with its own bundle, which is installed into the build directory. Inspect NSBundle.mainBundle().bundlePath
to see where. By the time the playground is running, it has no idea where its source code came from, let alone some larger directory structure it might have been in. Even the __FILE__
macro is trashed (it returns <EXPR>
).
I have some hope that they'll improve on this in the future, because currently there are many things like this that make them hard to use to explore existing code bases. They're really for exploring small bits of self-contained Swift. I often find myself building small commandline apps rather than playgrounds. For non-UI work, commandline apps can be more powerful.