I am using XCode 9.2 and I want "upload" a data - lets say a database - onto my simulator so that when I run the XCode proejct, the data is already on the device. How would I upload a data onto the simulator and how to I get the path to access it in the app?
Is it done through XCode or the Finder? I know that I can access all the simulators here ~/Library/Developer/CoreSimulator/Devices but how do I know which simulator is i.e. the iPad? How do I get the path to the data? And does it matter in which folder I put the data?
You can do this without messing around in the Finder by simply adding the files you want to your Xcode project and making sure they are included in the "copy bundle resources" build phase. Those files will then be available to your app at runtime from within the main bundle, and you can access them like this:
if let url = Bundle.main.url(forResource: "yourfile", withExtension: "ext") {
let data = try Data(contentsOf: url)
// process the data here
}
If you need read/write access to the files, you need to copy them from the bundle to the app's sandbox directories, e.g. to your "application support" directory.
Related
I have created an Xcode project which reads data from a JSON file. My app is working fine in the view preview and when simulated. My question is, does the JSON file automatically get stored with my app when I publish to the App Store? Or do I have to host the JSON file elsewhere (cloudKit, Firebase, etc)?
In other words, is my JSON file a part of the app, in the same way that the app Icon and app assets are part of the app?
In the image below, I have stored my JSON files in a folder called "resources". Will this "resources" be part of the app when it is uploaded to the App Store?
FYI ... I am very, VERY new to Swift and Xcode! Sorry for the stupid question.
Where my JSON file is located in Xcode
As long as the file is bound to the app target then it will be part of the application bundle. You do this by opening the file in Xcode and then in the property inspector ticking the app target in the Target Membership section.
Be aware when you do this you will need to access the file as part of the bundle and not via its file system location.
if let filepath = Bundle.main.path(forResource: "myFile", ofType: "ext") {
// load file
My app downloading and saving some support data to 'Library/Caches' directory. According to documentation,
Use this directory to write any app-specific support files that your app can re-create easily. Your app is generally responsible for managing the contents of this directory and for adding and deleting files as needed.
In iOS 2.2 and later, the contents of this directory are not backed up by iTunes or iCloud. In addition, the system removes files in this directory during a full restoration of the device.
In iOS 5.0 and later, the system may delete the Caches directory on rare occasions when the system is very low on disk space. This will never occur while an app is running. However, be aware that restoring from backup is not necessarily the only condition under which the Caches directory can be erased.
So, system may clean this folder. My app's supporting data not critical, so no need to put it in Documents or somewhere else. But I want to check how it handling if 'Caches' folder will be clear suddenly.
Of course, I can just check using NSFileManager if file exist.. and just use file or re-download. But one trick here exist.
My app can download some files from server in background. While file downloading, it storing at 'Caches/com.apple.nsurlsessiond/[APP_ID]' and there is no way to check if file exist (because file fully managed by SDK on this step). I added error handling for this case to NSURLSession delegate and now need to check it in 'real life'.
Is there any way to directly or indirectly force system to clear 'Caches' directories for all apps?
You can delete all files from Cache folder by
func removeNetworkCache() {
let cachePath = (NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0])
let appId = Bundle.main.infoDictionary!["CFBundleIdentifier"] as! String
do {
let content = try FileManager.default.contentsOfDirectory(atPath: cachePath)
for file in content{
let fullPath = "\(cachePath)/\(appId)/\(file)"
try FileManager.default.removeItem(atPath: fullPath)
}
} catch {
print("ERROR DESCRIPTION: \(error)")
}
}
You could do it the "usual way" and just uninstall the app, or, use this terminal command: xcrun simctl uninstall booted Your.app if you're running on the simulator that is.
Context: Xcode Version 11.0 beta 2/Swift 5
I want to create a bundle to access on a physical iOS device. I tried all the solutions on How to make an iOS asset bundle?, but to no avail.
I have created a bundle in finder containing the file and subsequently moved to Xcode such that my directory structure looks like this:
*Project Name*
*Project Name*Tests
Products
somebundle.bundle
somefile.csv
I keep getting the error
the file "somefile.csv" couldn't be opened because there is no such file
when testing.
I am accessing the file through let text = try String(contentsOfFile: Bundle.main.resourcePath! + "/somebundle.bundle/somefile.csv")
But actually, printing the contents of Bundle.main.resourcePath (FileManager.default.contentsOfDirectory(atPath: Bundle.main.resourcePath!)) shows that the bundle is not located in Bundle.main.resourcePath, as this is the output:
["_CodeSignature", "PlugIns", "Base.lproj", "*Project Name*", "Frameworks", "Info.plist", "PkgInfo"]
So, how do I get the bundle into Bundle.main.resourcePath, as the answers to the question at the top seem to suggest should be the case?
To access the contents of a Bundle when the app is installed on a physical device you need to ensure that it is copied across during the build.
Go to your Project Settings -> Build Phases -> Copy Bundle resources and make sure that your bundle is listed there.
You will only be able to read the contents from there unless you copy it to the documents folder first before trying to edit/save.
How do I install the XCUITest runner app and ipa on a real device and get the results?
I have a runner.app that was generated by building it for testing, and a deployed/signed .ipa.
Now what I would like to happen is to have it installed on a real device, execute it, and get the device log.
You can use bundleId :
let app = XCUIApplication(bundleIdentifier: "yourapp.bundle.id")
You can try to use:
xcodebuild test-without-building -xctestrun somepath/YourAppName_iphoneos14.4-arm64.xctestrun -destination 'platform=iOS, id=some_id'
I moved YourAppName_iphoneos14.4-arm64.xctestrun, YourAppName.app,
YourAppNameUITests-Runner.app to some local folder from a regular Library/Developer/etc.. build folder. Then I opened *.xctestrun file, which is an xml file, and modified paths to my local folder manually.
I couldn't find any official information about it but it seems like the *.xctestrun file is used by xcodebuild in order to find all relevant artefacts i.e both app folders. I would guess that's how they manage to run tests just with app's or ipa's without source code on various clouds...
PS. The question was about IPA, but it's convertible to the app, right? At least there is a thread - How to convert .ipa to .app file?
Edited with answer...
It is possible to achieve this. In order to build an ipa of the UI Testing app bundle you can follow these steps:
Open your project containing in Xcode.
Select the device you'd like to build the ipa for next to the scheme. This can be an actual device or a simulator.
Product > Build For > Testing
Find [your_ui_test_bundle_name].app file in Derived Data.
Derived data by default is located at ~/Library/Developer/Xcode/DerivedData/
To locate this file, dive into DerivedData for your project, navigating to Build > Products and then the respective directory based on what you chose in step 2. If you chose a simulator, look in -iphonesimulator/ or if you chose a device look in -iphoneos/. The UI test bundle .app file should be in that directory.
Create a directory named Payload case sensitive and it must be named this.
Move the .app file into the Payload directory.
Compress the Payload directory.
Rename the compressed directory to have a file extension of .ipa. You'll be prompted and select Keep .ipa.
Now you have you UI test bundle application saved as an ipa. You can also upload this ipa to a device manually in Xcode via the following process (bonus info, yay!)
Window > Devices and Simulators
Select your connected device.
Tap the + button under Installed Apps.
Navigate to and select your UI test .ipa file that you compressed previously.
It should install onto the device.
Credit where it is due: https://medium.com/ios-os-x-development/how-to-run-your-iphone-test-on-aws-device-farm-98f18086811e
I had a sqlite file which was working fine on the simulator and the device.
Under my app folder on the mac, I can also see the file - coredata.sqlite.
I created a new coredata.sqlite. After this, I had to copy it over to the paths which were different for different targets (iphone 5 vs 6 vs 6+) and looked along the lines of :
.../Library/Developer/CoreSimulator/Devices/26292D7B-5001-497E-B23B-99455953F5F4/data/Containers/Data/Application/64849BCC-B86B-45DE-818F-3E67346C4893/Documents/
Just copying over the new sqlite to the apps folder where the old sqlite was present did not work. Copying it to the above mentioned folders fixed it for the simulator.
Now, when I connect to my ios device though, it cant find the new sqlite. If I copy back the old sqlite to the apps folder, it still works but copying the new one to the apps folder, the various destinations for the simulator etc has no effect on the ios device.
Displaying the path where it is looking at shows :
/var/mobile/Containers/Data/Application/80302FBA-6D45-4843-A891-E10A7ED4D445/Documents/CoreData.sqlite
Any help on where the device is picking the sqlite from? Since it works on the simulator and the older one works on the device also, the code seems ok. What can I do to get it to pick my new sqlite?
Device will pick the files from mainBundle. While doing database related functionality we copy the db files from mainBundle to DocumentDirectory, so that it becomes editable.
What you did was that you manually copied the sqlite file to the app data document folder. You should actually add the file to specific target and then it will copy the file during build process.
Your new coredata.sqlite file is not attached to any target. Check inside build phases and see if it is there, otherwise add it. Also you should not have two files with same name inside the bundle, so remove the previous file from target.