4

I'm trying that a keyboard extension and app are available to read, write the same realm file, my code is:

DatabaseHelper

class DataBaseHelper
{
    static let DB_VERSION: UInt64 = 1
    //MARK: Creates Methods
    class func createOrUpdateEmoji(_ emoji: Emoji)
    {
        do {
            let realm = try Realm()
            realm.refresh()
            try realm.write {
                realm.create(Emoji.self, value: emoji, update: true)
                debugPrint("--->Emoji added or updated: \(emoji.id),\(emoji.name)")
            }

        } catch {
            debugPrint("Error creating or updating Emoji")
        }
    }

    //MARK: Creates Methods
    class func getEmojis() -> Results<Emoji>?
    {
        do {
            let realm = try Realm()
            return realm.objects(Emoji.self).sorted(byKeyPath: "id", ascending: true)
        } catch {
            return nil
        }
    }

    //MARK: Migrations
    class func DataBaseConnectOrUpdate()
    {
        let migrationBlock: MigrationBlock = { migration, oldSchemaVersion in
            if oldSchemaVersion < 1
            {
            }
            debugPrint("->oldSchemaVersion:\(oldSchemaVersion)")
            debugPrint("Migration complete.")
        }

        var config = Realm.Configuration(schemaVersion: DB_VERSION, migrationBlock: migrationBlock)
        config.fileURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.my.extension")!.appendingPathComponent("database.realm")

        Realm.Configuration.defaultConfiguration = config
        let realm = try! Realm()
        debugPrint("--->Path to realm file:\(String(describing: Realm.Configuration.defaultConfiguration.fileURL?.path))")
        try! FileManager.default.setAttributes([FileAttributeKey.protectionKey:kCFURLFileProtectionNone], ofItemAtPath: (realm.configuration.fileURL?.path)!)
    }
}

Model

import UIKit
import RealmSwift
import SwiftyJSON

class Emoji: Object
{
    @objc dynamic var id = 0
    @objc dynamic var name = ""
    @objc dynamic var code = ""
    @objc dynamic var image = ""

    override static func primaryKey() -> String
    {
        return "id"
    }

    static func fromJson(_ json:JSON) -> Emoji
    {
        let emoji = Emoji()
        emoji.id = json["id"].intValue
        emoji.name = json["name"].stringValue
        emoji.code = json["code"].stringValue
        emoji.image = json["image"].stringValue
        return emoji
    }
}

AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        DataBaseHelper.DataBaseConnectOrUpdate()
        return true
    }

App ViewController

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.syncEmojis()
    }

Keyboard Extension ViewController

var emojisFromDataBase:Results<Emoji>? = nil
override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        DataBaseHelper.DataBaseConnectOrUpdate()
        self.emojisFromDataBase = DataBaseHelper.getEmojis()
        for emoji in emojisFromDataBase!
        {
            debugPrint("emoji:\(emoji.name)")
        }
    }

so when I run on iOS simulator works properly in both cases:

iOS Simulator:

App

"--->Path to realm file:Optional(\"/Users/dmostajo/Library/Developer/CoreSimulator/Devices/LARGE-CODE/data/Containers/Shared/AppGroup/LARGE-CODE-2/database.realm\")"
"--->Emoji added or updated: 1,Satan"
"--->Emoji added or updated: 2,Cthulhu"
"--->Emoji added or updated: 3,Hellboy"
"--->Emoji added or updated: 4,Mercyful Fate"
"--->Emoji added or updated: 5,God"
"--->Emoji added or updated: 6,Virgin Mary"

Keyboard Extension:

"--->Path to realm file:Optional(\"/Users/dmostajo/Library/Developer/CoreSimulator/Devices/LARGE-CODE/data/Containers/Shared/AppGroup/LARGE-CODE-2/database.realm\")"
"emoji:Satan"
"emoji:Cthulhu"
"emoji:Hellboy"
"emoji:Mercyful Fate"
"emoji:God"
"emoji:Virgin Mary"

on Real Device iPhone SE:

App

"--->Path to realm file:Optional(\"/private/var/mobile/Containers/Shared/AppGroup/LARGE-CODE/database.realm")"
"--->Emoji added or updated: 1,Satan"
"--->Emoji added or updated: 2,Cthulhu"
"--->Emoji added or updated: 3,Hellboy"
"--->Emoji added or updated: 4,Mercyful Fate"
"--->Emoji added or updated: 5,God"
"--->Emoji added or updated: 6,Virgin Mary"

CRASH on Keyboard Extension:

Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=2
"Unable to open a realm at path '/private/var/mobile/Containers/Shared/AppGroup/LARGE-CODE/database.realm.lock': open() failed: Operation not permitted."
UserInfo={Error Code=2, NSFilePath=/private/var/mobile/Containers/Shared/AppGroup/LARGE-CODE/database.realm.lock,
Underlying=open("/private/var/mobile/Containers/Shared/AppGroup/LARGE-CODE/database.realm.lock") failed: Operation not permitted,
NSLocalizedDescription=Unable to open a realm at path '/private/var/mobile/Containers/Shared/AppGroup/LARGE-CODE/database.realm.lock': open() failed: Operation not permitted.}: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.74.1/src/swift/stdlib/public/core/ErrorType.swift, line 181

I'm using RealmSwift 3.1.1, Xcode 9.2, iOS 11.1.2, Swift 4, so any help?, am I missing something?, how can I resolve this?

thanks!

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
user_Dennis_Mostajo
  • 2,279
  • 4
  • 28
  • 38
  • 2
    Do you move your realm file in folder described in shared app group? – tereks Feb 13 '18 at 02:26
  • Yes I did, it works on iOS simulator but not in real device, if you see the crash log, it seems like the realm file is locked or is not found, the path is the same – user_Dennis_Mostajo Feb 13 '18 at 13:10
  • Have you tried quit app, and start using keyboard extension first. It looks like realm dB file is locked by app – tereks Feb 13 '18 at 13:42
  • yes I did that too, and nothing, it crashes with the same log, I tried to access to the group's path, but as the documentation says, I can't access to the shared group file when I download the container app – user_Dennis_Mostajo Feb 13 '18 at 14:07
  • @user_Dennis_Mostajo I face same issue, did you fixe it? – Hosny Mar 31 '19 at 21:07

0 Answers0