I'm very confused. I want to store few user files, but not docs. I'm using:
static var directory: URL {
get {
return FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)[0].appendingPathComponent("Caches").appendingPathComponent("OnlineFiles")
}
}
Always the same. Every time I launch the app I get different URL.
Am I doing something wrong? Is there some magic switch in project file which I need to set?
Once it's something like:
file:///var/mobile/Containers/Data/Application/4547EF22-EB33-4B65-9772-67ED7870E3E9/Library/Caches/OnlineFiles
Other time it's:
file:///var/mobile/Containers/Data/Application/83C8CDD7-B4D0-48B2-8A8E-9BD48C5D1754/Library/Caches/OnlineFiles
This string between /Application/ and /Library/ seems to be random. How to store files in one location when I can access them later when opening app second time?
[EDIT]: how to get path which is not changed every time I update app?
This is apple's security mechanism.Every time you restart the APP, apple sandbox path of APP to encryption, to prevent access to other programs.The encryption keys inside the APP.So before the end of the program, no matter where to access the APP sandbox, return to the path are the same.If you want to know more, you can look at apple's sandbox mechanism.
Related
I'm currently developing an app and i'm trying to add a button which would open another app installed on my phone when the button is tapped
I've tried looking for the URL scheme for the app but i can't find it. Only thing i can find is the bundle ID. So i thought maybe there's a way to use the bundle ID to open the app through private APIs in Swift? My phone is jailbroken if that helps. Below is my code
#IBAction func openAppTapped(_ sender: Any) {
UIApplication.shared.openURL(NSURL(string: "itms-apps://itunes.apple.com/us/app/apspace/id1413678891?mt=8")! as URL)
}
I managed to upon the app on the appstore upon tapping the button but i want a way to open the app directly without using url schemes but instead using the bundle id and/or private APIs. Any help would be really really appreciated!
To open another app, you are either going to have to use some kind of extension provided by that app or figure out their URL scheme and reverse engineer it.
The first thing you could try is looking at the app's Info.plist and seeing if they have defined a URLScheme for their app. If not, and they haven't implemented an extension, then I think you're SOL.
If they did define it, try using it to open their app and see what happens, they might have some code that rejects or accepts a request to open their app based on the format of the URL after their scheme. If you can't figure it out with trial and error, you could use the fact that your phone is jailbroken to decompile their app and hunt down the URL parsing logic which is likely in their AppDelegate. From there you could try and build a URL that you can use to successfully open their app every time.
this question is a lot like Share data between two or more iPhone applications except:
I'm looking for a way to do this in an iOS 8+ (or 9+) application using swift
I want to be able to use the sound file contained in the first app so the easter egg I'm making is only available when the user has both apps installed
since this is part of an easter egg, i don't want to use any method that would cause anything extra to be displayed on screen such as a browser redirect or some kind of permission popup
(this basically rules out using the share sheet and custom url's to pass data as described in the post above)
I am using AVAudioPlayer and AVAudioSession in the first app to play the sound if that is at all helpful.
Use App Group
You can share actual NSData through the NSUserDefaults:
if let userDefaults = NSUserDefaults(suiteName: <group>) {
userDefaults.setObject(obj, forKey: key)
}
and retrieve from another app in the same group like so:
if let userDefaults = NSUserDefaults(suiteName: <group>) {
if let obj = userDefaults.objectForKey(key) {
// magic
}
}
It appears that the only limitation for passing data through the user defaults is the device storage capacity, and since NSUserDefaults accepts NSData as a storage format, it makes a prime candidate for sharing tidbits information.
If both apps are yours you can implement a custom url scheme in the second app, and then from the first app ask if it knows how to open an URL with that scheme. If the answer is yes, the app is installed. The function is called canOpenURL. It's an instance method of UIApplication.
I vaguely remember that in iOS 9 and later, Apple added a restriction that you have to register the URLs you are going to ask about in your info.plist, but I don't remember the details. That won't prevent this scheme from working, but it is an extra step you have to take.
My app got rejected due to not follow iOS App Data Storage Guidelines.
My binary was rejected by the Apple App Store Review Team.
On launch and content download, your app stores 6.34MB on the user's iCloud, which does not comply with the iOS Data Storage Guidelines.
Next Steps
Please verify that only the content that the user creates using your app, e.g., documents, new files, edits, etc. is backed up by iCloud as required by the iOS Data Storage Guidelines. Also, check that any temporary files used by your app are only stored in the /tmp directory; please remember to remove or delete the files stored in this location when it is determined they are no longer needed.
Data that can be recreated but must persist for proper functioning of your app - or because users expect it to be available for offline use - should be marked with the "do not back up" attribute. For NSURL objects, add the NSURLIsExcludedFromBackupKey attribute to prevent the corresponding file from being backed up. For CFURLRef objects, use the corresponding kCRUFLIsExcludedFromBackupKey attribute.
What should I do?
iOS Data Storage Guidelines quick guide
A lot of people are having this problem and often it seems that the review team is automatically claiming that your app does not follow the iOS Storage Guidelines. Either way you need to document where your app store data and what data is stored where. Here's a quick guide that should get you started.
Your app can store files in either /Documents, /Library or /tmp.
Documents/
Use this directory to store user-generated content. The contents of this directory can be made available to the user through file sharing; therefore, his directory should only contain files that you may wish to expose to the user.
The contents of this directory are backed up by iTunes.
Library/
This is the top-level directory for any files that are not user data files. You typically put files in one of several standard subdirectories. iOS apps commonly use the Application Support and Caches subdirectories; however, you can create custom subdirectories.
Use the Library subdirectories for any files you don’t want exposed to the user. Your app should not use these directories for user data files.
The contents of the Library directory (with the exception of the Caches subdirectory) are backed up by iTunes.
tmp/
Use this directory to write temporary files that do not need to persist between launches of your app. Your app should remove files from this directory when they are no longer needed; however, the system may purge this directory when your app is not running.
The contents of this directory are not backed up by iTunes.
Put user data in Documents/.
This is backed up by iTunes/iCloud
Put app-created support files in the Library/Application support/
This is backed up by iTunes/iCloud
Put temporary data in the tmp/ directory.
This is not backed up by iTunes/iCloud
But how do I find out where my files are stored?
Put the script bellow in func application:didFinishLaunchingWithOptions in your appDelegate file. NSSearchPathDirectory is an enum and represents different folder/locations. Some of them are these.
public enum NSSearchPathDirectory : UInt {
case DocumentDirectory
case LibraryDirectory
}
Change the NSSearhPathDirectory(.DocumentDirectory) to desired locations and check what files you are storing there.
let paths: NSArray = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true)
if let documentDirectory = paths.firstObject{
do{
let documents = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(documentDirectory as! String)
for files in documents {
let urlForm = NSURL.fileURLWithPath((documentDirectory as! String) + "/" + files)
do{
try print("\(files): \(urlForm.resourceValuesForKeys([NSURLIsExcludedFromBackupKey])), with filepath: \(urlForm)")
//Prints out folder and files in the desired location
} catch let error as NSError{
print("Can't find key: \(error)")
}
}
}catch let error as NSError{
print("Can't retrieve contents: \(error)")
}
}
My app does not save anything
Lucky you...Write a document to the Apple review team and document your app use of storage. Take screenshots from the logs made out from the script above.
My app saves a lot of user created data
If your app saves a user's data to Documents/ that is fine and write a document documenting that this is made by the user and do follow the iOS Data Storage Guidelines.
If your app downloads data and saves it to the wrong location
Simply follow the iOS Data Storage Guidelines and submit a new binary.
I have files in Documents/ or Library/, but I don't want to back them up
Starting in iOS 5.1, apps can use either NSURLIsExcludedFromBackupKey or kCFURLIsExcludedFromBackupKey file system properties to exclude files and directories from backups. Apps that need to exclude a large number of files can exclude them by creating their own sub-directory and marking that directory as excluded. Apps should create their own directories for exclusion, rather than excluding the system defined directories. Either of these APIs is preferred over the older, deprecated approach of directly setting an extended attribute. All apps running on iOS 5.1 and later should use these APIs to exclude data from backups.
I've created a quick script to handle files that you don't want to backup.
func addSkipBackupAttributeToItemAtPath(filepath: String)-> Bool {
if let url: NSURL = NSURL(fileURLWithPath: filepath) {
let exist = NSFileManager.defaultManager().fileExistsAtPath(String(url))
if exist{
do
{
try url.setResourceValues(["YES" : "NSURLIsExcludedFromBackupKey"])
return true
}
catch let error as NSError
{
print("\(error)")
return false
}
} else
{
print("File does not exist")
return false
}
} else
{
print("Path not recognized")
return false
}
}
If you believe your app's rejection is false write the review team back and explain the situation and your use of storage
Simple guidelines
Bandwidth, network availability, and storage are limited resources and have real, financial consequences for your users. When you design your schema, store in iCloud only information that can’t be re-created.
iCloud-enabled Core Data apps are not only aware of data created on the device, they’re aware of data on other devices. It’s a good idea to keep this fact in mind when designing your Core Data stack.
When you save a managed object context, Core Data creates, in the ubiquity container, a set of transaction changes that are guaranteed to be applied together on other peers. The size of this transaction set, and the frequency with which you save your context, both directly impact the performance of your app.
Resources:
iOS Data Storage Guidelines - Apple Developer
iCloud Programming Guide for Core Data
File System Programming Guide
I'm looking for a way to uncover directory paths in an iOS app, for the purposes of deep linking.
Right now, I know that I can unpack an app's info.plist file and look for the "CFBundleURLScheme." This parameter usually looks like this:
CFBundleURLTypes = (
{ CFBundleURLName = "BUNDLEID";
CFBundleURLSchemes = ( "scheme", "fb1234567891011" );
},
);
From here, I can construct a basic URL scheme to launch the app to the home page, by appending "://" to the end of one of the "CFBundleURLSchemes."
If I enter scheme://
into Safari's URL bar and hit enter, then the app will launch on my iPhone to the app's homepage.
However, there is another deep link I know works - scheme://upgrade/pro- This links to a specific in-app directory, and when launched in Safari, opens the app directly to the upgrade page.
I want to be able to find a list of in-app directories that I can append to the basic URL scheme to be able to link to actual in-app pages.
Is there a file somewhere in an app's bundle or Payload folder that has a list of defined directory paths?
I hope that made sense, thanks in advance for any guidance!
No. The URL goes to an entry-point in the app that is parsed by code. Each app can do it how it wants. It could just be a bunch of if/else statements.
Best bet is to ask the developer -- if they made these entry-points, they probably want people to know about them.
I´m downloading a file to a SD card in the BlackBerry, and when I open that file, my application run. So when my application run, I need to delete that file.
The problem is that I dont know where it is(the file) from my app, because the user could download that file anywhere.
Is there something in the BB OS that let me know the path of that file? With this I can give to my app a parameter or something...
Well, thats it.
If you register with invocation registry so that your app is invoked whenever file needs to be opened, you will get full URL in Invocation object. This URL is sufficient to delete the file via FileConnector.
See this BlackBerry example to properly register your app. Also, in step 6 note invoc.getURL() - this is what you need to use.