how can I create and access share app group document directory?
Solved
let fileManager = FileManager.default
let url = fileManager.containerURL(forSecurityApplicationGroupIdentifier: "group.companyname.appname")?.appendingPathComponent("logo.png")
// store image in group container
if !fileManager.fileExists(atPath: url!.path) {
let image = UIImage(data: data)
let imageData : Data = UIImagePNGRepresentation(image!) as! Data
fileManager.createFile(atPath: url!.path as String, contents: imageData, attributes: nil)
}
//ACCESS THIS or get store image
let Image1 = UIImage(contentsOfFile: (url?.path)!)!
Create directory in app group container swift
containerURLForSecurityApplicationGroupIdentifier
returns the URL to the group container.
To create a directory append the new directory name as path component
let fileManager = NSFileManager.defaultManager()
if let directory = fileManager.containerURLForSecurityApplicationGroupIdentifier("APP_GROUP_IDENTIFIER") {
let newDirectory = directory.URLByAppendingPathComponent("MyDirectory")
try? fileManager.createDirectoryAtURL(newDirectory, withIntermediateDirectories: false, attributes: nil)
}
Swift 3:
let fileManager = FileManager.default
if let directory = fileManager.containerURL(forSecurityApplicationGroupIdentifier: "APP_GROUP_IDENTIFIER") {
let newDirectory = directory.appendingPathComponent("MyDirectory")
try? fileManager.createDirectory(at: newDirectory, withIntermediateDirectories: false, attributes: nil)
}
How to add files to an App Group shared directory?
The issue was actually using [url absoluteString] vs [url path], changing all the urls to path solved the permissions error.
How to find Apple App Group shared directory
EDIT on 2018-10-12: Updated code for Swift 4.x (Xcode 10). (Older version retained for reference.)
In Swift 4.x:
let sharedContainerURL :URL? = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.etc.etc")
// replace "group.etc.etc" above with your App Group's identifier
NSLog("sharedContainerURL = \(String(describing: sharedContainerURL))")
if let sourceURL :URL = sharedContainerURL?.appendingPathComponent("store.sqlite") {
if let destinationURL :URL = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("copyOfStore.sqlite") {
try! FileManager().copyItem(at: sourceURL, to: destinationURL)
}
}
In older version of Swift (probably Swift 2.x):
let sharedContainerURL :NSURL? = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.etc.etc") // replace "group.etc.etc" with your App Group's identifier
NSLog("sharedContainerURL = \(sharedContainerURL)")
if let sourceURL :NSURL = sharedContainerURL?.URLByAppendingPathComponent("store.sqlite")
{
if let destinationURL :NSURL = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0].URLByAppendingPathComponent("copyOfStore.sqlite")
{
try! NSFileManager().copyItemAtURL(sourceURL, toURL: destinationURL)
}
}
Something like the above will get a file from the app group's shared container to the app's Documents directory. From there, you could use Xcode > Window > Devices to get it to your computer.
You could also use iTunes file sharing to retrieve the file from the app's Documents directory after setting UIFileSharingEnabled
to YES
in the Info.plist
file, but bear in mind that this will expose the directory's contents to the user as well. Should be okay for development/debugging purposes, though.
How can app extension access files in containing app Documents/ folder
In order to make files available to app extension you have to use Group Path
, as App Extension can't access app's Document Folder, for that you have follow these steps,
- Enable App Groups from Project Settings-> Capabilities.
- Add a group extension something like
group.yourappid
. Then use following code.
NSString *docPath=[self groupPath];
NSArray *contents=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:docPath error:nil];
NSMutableArray *images=[[NSMutableArray alloc] init];
for(NSString *file in contents){
if([[file pathExtension] isEqualToString:@"png"]){
[images addObject:[docPath stringByAppendingPathComponent:file]];
}
}
-(NSString *)groupPath{
NSString *appGroupDirectoryPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:group.yourappid].path;
return appGroupDirectoryPath;
}
You can add or change the path extension as per your image extensions you are generating.
Note - Remember you need to generate the images in the group folder rather than in Documents Folder, so it is available to both app and extension.
Cheers.
Swift 3 Update
let fileManager = FileManager.default
let url = fileManager.containerURL(forSecurityApplicationGroupIdentifier: "YOUR_GROUP_ID")?.appendingPathComponent("logo.png")
// Write to Group Container
if !fileManager.fileExists(atPath: url.path) {
let image = UIImage(named: "name")
let imageData = UIImagePNGRepresentation(image!)
fileManager.createFile(atPath: url.path as String, contents: imageData, attributes: nil)
}
// Read from Group Container - (PushNotification attachment example)
// Add the attachment from group directory to the notification content
if let attachment = try? UNNotificationAttachment(identifier: "", url: url!) {
bestAttemptContent.attachments = [attachment]
// Serve the notification content
self.contentHandler!(self.bestAttemptContent!)
}
Two apps in one device and the image uploaded from first app will appear in the second app
Yes you can share some data within groups of app as per new updates in iOS 8.0
and above.
Just you need to create apps group and share your data among that groups app.
Below are few steps to enable app groups.
Step1: Enable App group from Target Setting -> Capabilities -> App Group
Sample Group name : groups.companyname
or groups.appgroupname
Note: Every app which you want in this group must have same group name
in this section.
Step 2: Get General sharing folder where you can store shared data like images DB.
for that you need to get path of that shared folder as mention below
Objective-C :
- (NSString *)getSharedGroupFolderPath:(NSString*)aAppGroupName {
NSURL *aContainerPathURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:aAppGroupName];
return [aContainerPathURL relativePath];
}
Swift:
static func appGroupContainerURL() -> URL? {
// 1
let fileManager = FileManager.default
guard let groupURL = fileManager
.containerURL(forSecurityApplicationGroupIdentifier: <APP_GROUP_NAME>) else {
return nil
}
let storagePathUrl = groupURL.appendingPathComponent("File Provider Storage")
let storagePath = storagePathUrl.path
// 2
if !fileManager.fileExists(atPath: storagePath) {
do {
try fileManager.createDirectory(atPath: storagePath,
withIntermediateDirectories: false,
attributes: nil)
} catch let error {
print("error creating filepath: \(error)")
return nil
}
}
// 3
return storagePathUrl
}
By above method you can get Group container folder path now save your data here which you need to share among multiple Apps.
Step3:
Store your image of file on container path like below
guard let destinationURL = TestFileViewController.fileUrlForDocumentNamed("FileName") else {
return
}
let image = UIImage.init(named: "tests")
if !FileManager.default.fileExists(atPath: destinationURL.path) {
do {
try UIImageJPEGRepresentation(image!, 1.0)!.write(to: destinationURL)
print("file saved")
} catch {
print("error saving file")
}
} else {
print("file already exists")
}
Use below supported method for getting file path :
// Returns the file URL for the file to be saved at
static func fileUrlForDocumentNamed(_ name: String) -> URL? {
guard let baseURL = appGroupContainerURL() else { return nil }
let protectedName: String
if name.isEmpty {
protectedName = "Untitled"
} else {
protectedName = name
}
return baseURL.appendingPathComponent(protectedName)
.appendingPathExtension("your file extension")
}
Hope this will helps you to achieve your requirements.
iOS 8 - Share Documents Directory Between Apps
No, you cannot have a shared documents directory, but you can have a shared folder in which you can use as your documents directory. When you create an app group Create an identifier for each of your apps in the app group.
Then you can use the file manager to get the URL for the directory you want with the given group identifier.
let url = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.com.MTC.DataSender")!
This will return the URL to the directory for the DataSender app. Every app in the app group can access this directory. So in your other app you would do the same thing.
Related Topics
Enum's Rawvalue Property Not Recognized
Swift iOS 9: Section Header Change Position After Reload Data
Swift Error: 'Sequence' Requires the Types 'T' and 'Arrayslice<T>' Be Equivalent
Difficulties to Assign Default Value to a Parameter of a Function
How to Animate Opacity Using Swift
How to Display an Int Without Commas
How to Avoid Duplicate Key Error in Swift When Iterating Over a Dictionary
Cast Any to Float Always Fails in Swift4.1
Create Endless Cgpath Without Framedrops
Firebase Storage Overwriting Files
Comparing Non-Optional Any to Nil Is Always False
Navigationlink Is Grayed Out and Does Not Perform Any Action
How to Scale/Position Nodes Swift Spritekit? Custom View
Unsafemutablepointer<Cftyperef> in Swift 3
Why Specify [Unowned Self] in Blocks Where You Depend on Self Being There
Uiimagepickercontroller Navigation Bar Tint Color Not Working with iOS 13