Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I programmatically remove files from the Xcode "copy Bundle resources" list? from a command line tool?

Tags:

xcode

ios

build

The background:

An iOS app I'm building for a client is getting absurdly big due to a large number of multimedia files the client needs to add. (videos, high-res images, and sounds.)

The app drives it's UI from a set of page descriptor files that it reads at runtime. It uses those page descriptor files to load scenes from the app storyboard using unique IDs, and then each page's view controller figures out which multimedia content to display based on it's page descriptor.

I plan on adding a download_from_server flag to the page descriptor file that tells the app that it needs to download a zip file containing all the multimedia content for this page's view controller and all child pages from a server. At runtime, the app will see the flag, stop, and ask the user to tap OK to begin downloading the content, or click cancel to go back to the previous page. If they click OK the app will download the zip file, unzip it into the documents directory, and save a persistent "multimedia content downloaded" flag for that page. The app will know to look for multimedia assets in both the documents directory and the app bundle.

I will write a batch tool that walks the tree of file descriptors. When it finds a descriptor who's download_from_server flag is set, it will build a zipfile from the multimedia content for that page and all of it's child pages. I'll then upload all those zipfiles to the server.

My Question:

Can I make my batch tool modify Xcode's settings for the multimedia files in the project that are being uploaded to the server so those files are no longer copied into the app bundle, and if so, how? I want to be able to delete those entries from the "Copy Bundle Resources" build phase file list. (Or un-check the target membership checkbox, which I believe does the same thing.)

I am not exepert in the intricacies of makefiles and build rules, so I need guidance.

EDIT:

It appears that Xcode uses entries in the project's project.pbxproj file to track which files are copied into the application at build time.

When I made a copy of the project.pbxproj from a project, un-checked the "target membership" checkbox for a file, and made another copy of the project.pbxproj file, and compared them, I found 2 differences. When the file in question has it's "target membership" checkbox checked, it is listed in 3 places in project.pbxproj, and when the checkbox is not checked, it is only listed in 2 places.

The 2 entries that are removed are:

An entry in what looks like an "objects" dictionary at the top of the file, marked with a comment line

/* Begin PBXBuildFile section */

And in a section marked with a comment /* Resources *, in a list with the key "files", that appears to be an array of file IDs (long hex strings.)

Whether the file's target membership checkbox is checked or not, it appears in another array of file IDs marked with the comment /* Begin PBXFileReference section */.

It looks to me like I could delete the entry line in the objects dictionary and in the array of file IDs in the Resources section.

Can anyone reading this chime in on the safety and effectiveness of programmatically modifying an Xcode project's project.pbxproj file to remove files from the Copy Bundle Resources build phase?

like image 288
Duncan C Avatar asked Mar 09 '16 21:03

Duncan C


1 Answers

Instead of manually editing the pbxproj file, you can use a ruby gem called xcodeproj to edit project settings. (Cocoapods uses this also so create pod targets and add files to them). This would be a good starting point.

I don't know how familiar you are with Ruby, but it would worth to check out the Project class and its native_targets array property. You can find your desired target by name and you can access the resource build phase via the resource_build_phase property. You can write a Ruby script like this (not fully checked):

project = Xcodeproj::Project.open('path to .xcodeproj')
target = project.native_targets
                 .select { |target| target.name == 'YourTargetName' }
                 .first

target.resource_build_phase.files.each do |f|
   f.remove_from_project
end

project.save
like image 151
Peteee24 Avatar answered Sep 30 '22 04:09

Peteee24