Extension iOS 8 : Document Provider

SelSel Membre
mars 2015 modifié dans Apple Developer Programs #1

Bonjour,


 


Je me penche un peu sur les extensions et leurs possibilités sous iOS 8.


 


Document provider a particulièrement attiré mon attention. Il permet à  d'autres applications d'importer ou ouvrir des fichiers,  les télécharger à  partir de votre serveur si nécessaire & cie.  Les applications peuvent également exporter ou déplacer leurs documents dans le "conteneur partagé".


 


Pourrait-il permettre de partager une base de données entre 2 applications par exemple ?


 


J'ai du mal à  trouver de la documentation (mise à  part la documention Apple) sur Document Provider si vous trouvez, je suis intéressé. Tutoriels ou autre.


 


Merci :)


Réponses

  • En première approximation si la base de données est un document SQLite, cela devrait fonctionner en toute transparence.


    Si la base de données est composée de plusieurs fichiers, il risque de se poser le problème de la garantie de synchronisation entre tous ces fichiers.


  • AliGatorAliGator Membre, Modérateur
    De ce que j'ai compris sur la façon dont fonctionne le Document Provider, quand l'appli A demande un document de l'appli B, via le Document Provider Extension de l'appli B qui va permettre d'exposer ses documents, je me demande si iOS va pas in fine faire une copie du document de B dans le dossier "InBox" de la sandbox de A, le temps que l'application A puisse lire le document, en faire ce qu'il veut, etc.

    Ca reste à  confirmer car j'ai pas fait de tests encore sur des extensions Documents Provider et la doc est un peu loin, mais si c'est le cas, et donc que le document ouvert par A est une copie du document de B, ne t'attends donc pas à  ce que A puisse ajouter des entrées dans ta base SQL que tu aurais "partagé" et que B puisse voire lesdites entrée rajoutées par A... car dans ce cas ça serait une copie de la base SQLite que tu aurais et non un accès direct (du point de vue sécurité en tout cas ça me semblerait bien plus logique " et bien plus rassurant pour éviter les injections " donc j'imagine qu'Apple a plutôt implémenté ça comme ça).

    Et même si jamais ô grand jamais Apple avait pas fait une copie du fichier dans la InBox de l'appli A, mais avait directement donné l'accès à  l'appli A pour aller farfouiller dans la sandbox de l'appli B (ça me paraà®trait gros quand même), faudrait prendre soin d'utiliser un NSFileCoordinator (bon sauf si tu fais du CoreData et que tu utilises un NSPersistentStoreCoordinator qui gère déjà  les mécanismes d'accès concurrents pour toi) pour gérer les accès concurrents à  ton fichier par les 2 process.


    Sinon si tes 2 applications A et B sont des applis à  toi et que tu veux partager des fichiers entre elles, faut plutôt utiliser les AppGroups (et du coup avoir une Sandbox commune à  toutes tes apps qui sont dans le mm AppGroup)
  • FKDEVFKDEV Membre

    En gros, d'après mes souvenirs, le document provider sert à  faire Dropbox et iCloud Drive.


     


    Si tu es l'auteur des deux apps, le meilleur moyen de partager des données est via les app groups.


  • SelSel Membre
    avril 2015 modifié #5

    Je vous remercie pour vos réponses (désolé pour ma réponse tardive...)


     


    Je laisse de côté Document Provider mais si vous avez plus d'informations, je reste intéressé.


     


    Justement, je suis dans le cas où j'ai deux applications dont je suis l'auteur. J'aimerais pourvoir partager une base de données entre elles deux.  Un App Group comme "com.sd.shareapps" peut me permettre de partager une sandbox commune.


     


    Pour le moment, j'ai une application iOS, nommée "A", développée en Swift et j'ai mis en oe“uvre le partage des données entre mon Action Extension iOS 8 et mon containing app via les App Groups et un framework dynamique.

     


    Par contre, une fois, l'application, nommée "B",  ajoutée à  l'App Groups, je ne vois pas comment m'y prendre.


    Comment mettre en place CoreDate dans l'application "B" afin de pouvoir de nouveau manipuler des entités etc. ?


     


     


    La partie ore Data stack  de mon AppDelegate de l'application A et idem pour l'application B



    // MARK: - Core Data stack

    lazy var applicationDocumentsDirectory: NSURL = {
    // The directory the application uses to store the Core Data store file. This code uses a directory named "com.sd.shareapps" in the application's documents Application Support directory.
    let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    return urls[urls.count-1] as NSURL
    }()

    lazy var managedObjectModel: NSManagedObjectModel = {
    // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
    let modelURL = NSBundle.mainBundle().URLForResource("shareapps", withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
    }()

    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {

    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
    // Create the coordinator and store

    var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

    let directory = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("com.sd.shareapps");

    let url = directory?.URLByAppendingPathComponent("shareapps.sqlite")

    //Sarting frehs every time
    NSFileManager.defaultManager().removeItemAtURL(url!, error: nil)

    var error: NSError? = nil
    var failureReason = "There was an error creating or loading the application's saved data."

    if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil {
    coordinator = nil
    // Report any error we got.
    let dict = NSMutableDictionary()
    dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
    dict[NSLocalizedFailureReasonErrorKey] = failureReason
    dict[NSUnderlyingErrorKey] = error
    error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
    // Replace this with code to handle the error appropriately.
    // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
    NSLog("Unresolved error \(error), \(error!.userInfo)")
    abort()
    }
    println("\(coordinator?.persistentStores)")
    return coordinator
    }()


    J'ai ajouté un dans l'application B, les fichiers suivant : 


     


    KeepFive.xcdatamodeld


    Contact.swift


    ContactDetails.swift


  • SelSel Membre
    avril 2015 modifié #6

    Je me permets de revenir sur ce post car ma situation a évolué.


     


    Suivant l'ordre dans lequel j'ouvre mes application ( A et  B ),  j'obtiens différentes erreurs.


     


    Lorsque les  Fetches sont en cause j'obtiens cette erreur :



    CoreData: error: (522) I/O error for database at /private/var/mobile/Containers/Shared/AppGroup/[...].sqlite. SQLite error code:522, 'not an error'

    Lorsque je tente de sauver une entité :



    CoreData: error: (11) Fatal error. The database at /private/var/mobile/Containers/Shared/AppGroup/[...].sqlite is corrupted. SQLite error code:11, 'database disk image is malformed'

    Ou :



    Core Data: error: -executeRequest: encountered exception = error during SQL execution : PRIMARY KEY must be unique with userInfo = { NSFilePath = "/private/var/mobile/Containers/Shared/AppGroup/[...].sqlite"; NSSQLiteErrorDomain = 19; } CoreData: error: (19) PRIMARY KEY must be unique

Connectez-vous ou Inscrivez-vous pour répondre.