Xcode copy resources to simulator - ios

I want to copy files to the path that the Simulator will use. I'm talking about the path that looks something like this when the Simulator is running
/Users/myUser/Library/Developer/CoreSimulator/Devices/A9A30146-764F-4A4B-BAA2-00D5808D77C2/data/Containers/Data/Application/B85F7B67-FD50-48AA-8E03-2F806858AF71
Is there a way to get that path at build time so that I can copy files there using a Run Script build phase?
Here is why I want to do this:
Currently my app fetches a large amount of resources from the network every time the app is newly installed. The app checks the contents of the local file storage, and if a file is missing or out of date, it will sync them.
To speed up the development feedback cycle, I want to copy those resources from a local directory on my development machine, either during a build step or whenever else makes sense, to the proper destination in the simulator's local storage. This way, I can have a fast development cycle while only needing to delete the build script, or whatever other mechanism, when I'm ready to release the app into production.

This is available to your Run Script build phase as the TARGET_BUILD_DIR environment variable. A reasonable place to copy these files to might be $TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH. This is how CocoaPods installs resources from Pods, see https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/generator/copy_resources_script.rb
However it's not clear why you would do this in a Run Script phase. For many uses you probably just want to use the existing Copy Bundle Resources build phase.
I don't think you have access to the path you are looking for at build time because the app is built prior to being installed and the installation path may not have even been determined when building the app.
To warm your cache or whatever you want to do for local development I see a few options:
Include these resources in your app bundle and then copy them to the appropriate destination directory at startup. This should be reliable and might be something you want to use in release builds if you want to include some default version of these resources in the app which can then be updated as needed when the app is launched. This approach also increases the size of your app bundle and if its not something you want in release builds might be more work to remove or disable in those environments.
Embed a reference to the location of your development files in the app at build time (e.g. a path relative to SRCROOT). Copy those files into place as needed when the app is launched. This would only work in the simulator and relies on the simulator not enforcing sandbox controls (allowing your app to read for a directory outside the simulator).
Download these files from a server as you would normally but host them locally so your development builds can fetch them from some localhost address quickly.
I'd try to use option 3 to mostly closely replicate the release behavior of the app but use whatever works best for your workflow.

You can copy and paste below command to your Run Script build phase
cp -r "Your Resource Path" "`xcrun simctl get_app_container booted ${PRODUCT_BUNDLE_IDENTIFIER}`"
xcrun simctl get_app_container booted ${PRODUCT_BUNDLE_IDENTIFIER} -> This will take currently booted your product's path, you can even check from terminal like:
xcrun simctl get_app_container booted com.your.packagename

Related

iOS build script fails on defaults read command

I have an iOS app with a Build phase script that reads a plist file using the following command:
defaults read "/full/path/to/plist/file" CFBundleExecutable
...but it fails with the following error message:
The domain/default pair of (/full/path/to/plist/file.plist, CFBundleExecutable) does not exist
The full path of the file is correct and I double checked that the file indeed contains the key CFBundleExecutable. I also tried with other keys such as CFBundleName. Running the command both with and without .plist at the end of the full path fails.
I also ran the command in Terminal to see if it works generally, but the command fails there as well.
It turns out that macOS (or the defaults command line tool) seems to have a bug. Folders that are "special" such as Documents and Desktop act differently within the command line environment and as such I observed the following:
If Info.plist is located in a subfolder of Desktop or Documents the defaults read command will fail
As soon as you place Info.plist in any other folder (such as a Developer folder) the same defaults read command will succeed
I am not sure if this is due to the fact that both of these folders require special permissions (macOS asks if an app requests access to either of these) or if it is because they are part of iCloud Drive and perhaps there is some weird symlinking in the background.
Either way, if you run into a similar error, just try to place your project in a subfolder of ~/Developer (or any other non-default, non-special folder).

apache karaf clean start

I'm trying to clean start karaf on Windows using clean option.
It does delete data directory with bundles cache but it copy new bundles into data directory from system directory not local maven repository. But system directory has stale jars in comparison to local maven repository which cause karaf to start with stale bundles.
Is this a 'feature' of clean option? Am I missing something? How could I start Karaf with latest code from maven repo not dealing with file system?
You can't as the system directory is per default the one to use.
The clean does mean to clear up bundles in a awkward state and is only rarely used. Sometimes this happens if you start and stop the karaf container very close to each other then bundle might be in an incomplete state and since those bundle state is kept only a clean will help. Another way of cleaning is to delete the data folder.
So what you look like to be intending is to update certain bundles that are installed from the systems folder. For that you need to install the never version cause Karaf nows which versions are in the systems folder, those bundles are defined in the framework feature which is the basic feature to be used by Karaf itself.
If you have your own bundles in the system folder there is no way of updating those as those are regarded to be bootfeatures. In case you want to update those you'll need to make sure those features aren't boot features anymore and after that just do install the never versions of your bundles and uninstall the older ones. This can be done with the command shell.
One side note, it's usually best to ask those questions on the users mailinglist of Karaf, you get more people to answer your questions there.

Get XCODE to Copy run script converted files to iOS resources bundle?

I have a script which converts wav files to caf files, and I'd like to get them copied to my iOS app automatically. The script looks like this:
Xcode doesn't copy it automatically, and i can't find a way to add it to my Copy Build Phase section. It appears that I need to add a line in the script to copy it directly to the app bundle, or to make the destination the app bundle itself.
What would that script/change be? I'm not sure what shell vars to use for the cp command.
Thanks - Henry
The environment variable you're looking for is "BUILT_PRODUCTS_DIR" and you can find the definition of this, and plenty of other useful Xcode-specific environment variables on this handy Apple documentation page.
And what you'd probably want to do is test for the existence of successfully converted files, and if they exist, then copy those files into the "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}" directory.

How can I fix user dir permissions for my Cydia app?

I am having an issue with my application hosted on Cydia.
Users are complaining that the app crashes on startup.
The app uses CoreData, I thought it had something to do with this.
Weird thing is that it works fine using simulator or on my device when testing.
But as soon as it is installed through Cydia it crashes.
Turns out that using "Fix User Dir Permissions" from SBSettings fixes this issue.
Now what can I do about this?
I just had a discussion with the repository guys at BigBoss about this.
I never really got a clear answer, but it looks to me like when Cydia installs your application, it doesn't necessarily set the ownership (explicitly) for your application. That seems bizarre to me. In my case, they were test-installing my app, and seeing that it was owned by user/group = { 1000 / 100 }, which was the linux user id and group id from the machine I was preparing my .deb package on!
I can also see this same behavior if I build a .deb package, deploy it to my own local test repository, and install it with Cydia (pointing at my own repo).
In any case, I explained this to them, and they did something to fix it (without anything more from me).
However, one other option is to manually fix permissions in your post install script. In your .deb package, you would have this folder and file structure:
DEBIAN/control
DEBIAN/postrm
DEBIAN/postinst
DEBIAN/preinst
If you put this in your postinst script, I think it should fix this immediately, without having to go into SBSettings afterwards:
#!/bin/bash
chown -R root.wheel /Applications/MyAppName.app/
exit 0
You can do more than that in the script, if you need other directories created, for example. But, the above will at least suffice to change ownership on the .app directory itself.
This BigBoss link recommends creating additional directories in your app's code, and points out that the installer runs as root, while your app normally runs as user mobile. Depending on what you're doing, it may be better to fix ownership/permissions in postinst (root) or in the app (mobile).

Trigger.io continuous development

I'd like to know if there is any way to develop continuously with Trigger.io and avoid the forge build step with every file change I want to test in my browser or simulator.
I was faced with the same problem and I've got a working solution that uses watchr and watch to automatically rebuild each time I make a change to a source file. If you are running a "web" version of your app you can make a change to a source file and go directly to your browser and see the effect of your changes fairly quickly depending on how long the build takes.
Prerequisites: Ruby, watchr, Unix 'watch', and a terminal.
gem install watchr.
create a new ruby file for watchr to know what files to monitor and what to do when it sees a change. I named my file 'my_watch.rb': https://gist.github.com/3153167
open two terminals. Terminal 1 will run watchr and Terminal two will run 'forge build ...'.
In terminal 1 run 'watchr my_watch.rb' making sure the path to my_watch.rb is correct and make sure you've edited my_watch.rb according to your setup so that the path inside watch(...) reflects the files to be watched. My example watches all files in the same directory (and beneath) as the my_watch.rb script. You can place my_watch.rb in the 'src' folder of your Trigger.io app if you want to match my example and run watchr my_watch.rb directly from the src folder. Also not the shell command and path in the block need to be updated to reflect your environment. Again, in my example 'my_watch.rb' is inside 'src/' so when a change is detected we go up one directory and call 'forge build'.
I tend to develop actively with the 'web' version of my app so I can just open terminal 2 to my forge project directory and 'forge run web'. When I am testing in simulators and on devices, yes I have to run forge build every time I want to see a change. However, I typically don't have to wait for forge build to finish because watchr kicked off the build as soon as I made a change and it happens pretty quickly.
I know this is not an ideal solution but so far developing new features in the 'web' version first and then implementing in mobile versions has been very smooth for me. I've never needed to kill the 'web' version after a build but I maybe just lucky. As for running build each time you want to test the mobile versions if you are good with your keyboard shortcuts it really isn't bad at all. XCode makes you build and run after changes are made to source code when creating native iOS apps so I don't think Trigger is unique in requiring this build step.
I hope this helps and that my answer isn't too specific to me and my setup.
The build phase makes some changes to your source to enable the forge.* APIs - therefore, trying to just use the raw files in your src directory won't work.
You may be tempted to change files directly in the development directory, but this is a pretty bad idea: we delete those files with impunity when we need to!
We have plans on our medium-term roadmap to add a file-system watcher to start builds automatically when changes have occurred.
In the meantime, I just use forge build && forge run PLATFORM which tends to only take a few seconds...
while not perfect... this works for me.
go into development/web
rm src
link to your root src, ie ln -s ../../src src
copy the all.js from the web/forge and add to your index.html
ie
start nodemon web.js
open in browser.
note you will need to comment out the all.js script tag for non web builds.

Resources