Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: Build a Resource Bundle via Xcode Target

I want to create a Resource Bundle from resource files of my static library via a xcode target. I saw Three20 having a .bundle file one need to import.

How can I do that?

like image 457
cschuff Avatar asked Dec 10 '11 18:12

cschuff


People also ask

How do I set a build target in Xcode?

Go to project's settings in the Project Navigator panel. Under the Targets sections, right click the existing target and select Duplicate to copy your existing target. 2. Xcode will ask you if your new target is for iPad development.

What is target in iOS Xcode?

A Target specifies a product to build and contains the instructions for building the product from a set of files in a project or workspace. An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.


2 Answers

Important Disclaimer:

Apple does not endorse this solution. When I spoke with a developer at Apple who works on Xcode they informed me that resource bundles were not supported by iOS, and they were surprised that this worked at all.

This solution has worked for me on iOS 9 through 13, both phone and tablet. However it's possible that a future update to iOS may break this. Just be aware of that.

Now on to the answer:

I know it's 8 years late, but since I stumbled across this question there's a good chance someone else will, so I thought I'd provide a helpful answer.

Step 1. Create a new Target

enter image description here

  • Make sure you have your project selected in the Project Navigator
  • Click on the + at the bottom of the Targets list

Step 2. Create a macOS Bundle

enter image description here

We'll convert this to an iOS Bundle in step 3

Step 2 (cont). Create a macOS Bundle

enter image description here

  • Name your bundle
  • Click "Finish"

Step 3. Change the Base SDK from macOS to iOS

enter image description here

  • Make sure you have the new resource bundle target selected
  • Go to Build Settings
  • Look for Base SDK and change this value from macOS to iOS

At this point, you're technically done with your question (creating a Resource Bundle target for iOS), but there's some configuration needed to get it working correctly

Step 4. Replace iOS Bundle Resources

enter image description here

  • Make sure you have your app target selected (not the resource bundle)
  • Go to Build Phases
  • Select all resources
  • Press the - button to remove them

Step 4 (cont). Replace iOS Bundle Resources

enter image description here

  • Press the + button to add a new bundle resource to the iOS app (not pictured)
  • Select your bundle product
  • Click "Add"

Step 5. Set up Dependencies

enter image description here

  • Open the Dependencies section (still under Build Phases and still within your app, not the resource bundle)
  • Click the + button to add a new dependency

Step 5 (cont). Set up Dependencies

enter image description here

  • Select the resource bundle project
  • Click "Add"

Now you're done!

With all of those steps completed, you will be building a resource bundle compatible with iOS and embedding it inside of your application to be loaded. It's not as straight-forward and a lot of articles may say this is unsupported, but I've used this feature in a published app and it works perfectly

Just remember that if you want to add any resources to your app now (PNGs, XIB files, etc) you need to add them to the bundle and not the app, like so:

enter image description here

Important Gotcha

After you've set this up, check out your resource bundle's build settings one more time. Look for the setting titled "Versioning System". This value must be set to None. If this is set to Apple Generic, you will run into issues when you try to push to the app store!

Apple's versioning system will create a *_vers.c file, compile it, and embed this binary into your bundle. As this is not a valid CFBundleExecutable, it will cause your app to be rejected with error ITMS-90171

enter image description here

like image 174
stevendesu Avatar answered Oct 05 '22 21:10

stevendesu


A bundle is just a directory with a special structure and a .bundle extension. You can read more about the specifics in the documentation.

Edit:

The important part is that a bundle is just a normal folder named with a special extension. For instance, if you had a folder named MyBundle.bundle and an image inside named image.png, you can load it with [UIImage imageNamed:@"MyBundle.bundle/image.png"]; Thus, there's no need to build it via an Xcode target. In fact, it's not available on iOS projects. You could have a Copy Files build phase in your project, or a shell script.

This is simple, and powerful. For example, if you conform to the special structure listed at the docs for frameworks, you can build static libs into Frameworks using a simple method, shell scripts or ant tasks or rake files. As long as the output directory conforms to the structure and is named Something.framework, you can use it as a Framework, even on iOS.

like image 24
Don Avatar answered Oct 05 '22 23:10

Don