How to correctly use shouldCompactOnLaunch in RealmSwift

风格不统一 提交于 2019-12-12 13:33:50

问题


The example in the documentation (https://realm.io/docs/swift/latest/#compacting-realms) is not very clear to me, as I don't know if the compaction could be called all the time during app use or only once at startup. Is the implementation below correct or would it be better to make a separate config including shouldCompactOnLaunch to call once on app launch.

If I add shouldCompactOnLaunch to the default configuration I see the block being called every time I create a realm instance.

        Realm.Configuration.defaultConfiguration = Realm.Configuration(schemaVersion: schemaVersion, migrationBlock: migrationBlock,shouldCompactOnLaunch: { totalBytes, usedBytes in
        // totalBytes refers to the size of the file on disk in bytes (data + free space)
        // usedBytes refers to the number of bytes used by data in the file

        // Compact if the file is over 100MB in size and less than 50% 'used'
        let oneHundredMB = 100 * 1024 * 1024
        print ("totalbytes \(totalBytes)")
        print ("usedbytes \(usedBytes)")
        if (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.7{
            print("will compact realm")
        }
        return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.7
    })
    do {
        // Realm is compacted on the first open if the configuration block conditions were met.
        _ = try Realm(configuration: config)
    } catch {
        // handle error compacting or opening Realm
    }

And one more thing would be interesting to me: What happens if the compaction fails? Too little storage would be a reason. Will I still be able to access the data and the compaction will just be skipped?


回答1:


There is additional information in the header file of RLMRealmConfiguration:

/**
 A block called when opening a Realm for the first time during the life
 of a process to determine if it should be compacted before being returned
 to the user. It is passed the total file size (data + free space) and the total
 bytes used by data in the file.

 Return `YES` to indicate that an attempt to compact the file should be made.
 The compaction will be skipped if another process is accessing it.
 */

@property (nonatomic, copy, nullable) RLMShouldCompactOnLaunchBlock shouldCompactOnLaunch;

Admittedly we should make it more apparent in the documentation on the site that this block should only be called on the first time a Realm instance representing a specific Realm file is created.

If you're definitely seeing this block being called for the same Realm file multiple times, please open an issue on the Realm Cocoa GitHub page with detailed steps to reproduce.

Once you've created a Realm instance with a specific Configuration, it's generally best practice to avoid mutating that configuration after the fact. You shouldn't create two different Configuration objects, one with a compaction block and one without. Realm internally caches Realm instances based off its Configuration, so it's possible you'll get unpredictable behavior.

The compaction shouldn't fail. The only major scenario where that would become an issue would be if your device was already on the verge of running out of hard drive space. Depending on how much empty space was in that Realm, compacted Realms are most usually significantly smaller, so the entire operation wouldn't require 2 times the storage size. On iOS, if the system detects its storage space is low, this would trigger a 'Cleaning' phase where the Caches directory of other apps would be purged, which in the vast majority of cases alleviate the problem sufficiently to complete the process.

If all of that failed, the attempt to perform the compaction will throw an exception; which your error handling code should be able to catch.




回答2:


So the solution for me was to create to configs. The configs are identical except of the shouldCompactOnLaunch block. This config with the shouldCompactOnLaunch I just use once at app launch, so it does not get triggered every time.

Here is the link to the Realm github issue

If the compaction fails the app will continue using the uncompacted version of the database.



来源:https://stackoverflow.com/questions/44407812/how-to-correctly-use-shouldcompactonlaunch-in-realmswift

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!