What is a Bundle, and how do you load a resource from it?
Predict first
What does this print?
print(Bundle.main.url(forResource: "nope", withExtension: "json") as Any)
- nil
- Crash
- An empty URL
Predict first
Can you write a file into Bundle.main at runtime?
// try data.write(to: Bundle.main.bundleURL.appendingPathComponent("x"))
- Yes
- No, it is read-only and signed
Mental model. A bundle is a shipping box with a packing list. Asking for a file that is not on the list gives you nothing.
A Bundle is a directory with a known layout that holds code and resources: images, JSON, sounds, Info.plist, and localisation folders. Bundle.main is the app itself. url(forResource:withExtension:) returns an optional: nil means the file is not in that bundle, usually because it is missing from the target’s Copy Bundle Resources phase or the name is misspelled.
The bundle is read-only (it is code-signed), so never write into it. Images in an asset catalogue are compiled into Assets.car, so you load them by name (UIImage(named:)) instead of by file path. Folders added as folder references keep their structure and need a subdirectory:; plain groups are flattened. infoDictionary and object(forInfoDictionaryKey:) read Info.plist.
A missing resource is nil, never an exception. The crash comes later, if you force-unwrap it.
The bundle is part of the signed app. Writable data belongs in Documents, Application Support or Caches.
Common traps
- Force-unwrapping a resource URL. A missing file or wrong target becomes a crash.
- Trying to save into the bundle. It is read-only; write to Documents or Application Support.
They might follow up with
- How do you find a bundle that holds a given class?
Bundle(for: MyClass.self), which works for frameworks and tests. - Why does a file exist in Xcode but not at runtime? It is not in the target’s resources, or it was added as a group and you asked for a subdirectory.
Related questions
- 2.6.2 Why does Bundle.main fail in packages, extensions and tests, and what do you use instead?
- 2.5.6 What is a property list, and where do you meet one?
Why does Bundle.main fail in packages, extensions and tests, and what… →