How do i remove databases with Realm? - swift

I'd like to delete databases of realm.
I know how to delete that on Java, but I need to do that on swift
like this(Java):
RealmConfiguration realmConfig = new RealmConfiguration.Builder(this).build();
Realm.deleteRealm(realmConfig);
realm = Realm.getInstance(realmConfig);
thanks.

If you want to delete Realm's files
let manager = NSFileManager.defaultManager()
let realmPath = Realm.Configuration.defaultConfiguration.path as! NSString
let realmPaths = [
realmPath as String,
realmPath.stringByAppendingPathExtension("lock")!,
realmPath.stringByAppendingPathExtension("log_a")!,
realmPath.stringByAppendingPathExtension("log_b")!,
realmPath.stringByAppendingPathExtension("note")!
]
for path in realmPaths {
do {
try manager.removeItemAtPath(path)
} catch {
// handle error
}
}
From Realm's official documentation: https://realm.io/docs/swift/latest/#deleting-realm-files

Best thing to do is to call deleteAll() method on realm object like:
let realm = try! Realm()
try! realm.write {
realm.deleteAll()
}

Related

Thread 1: Exception: "Realm accessed from incorrect thread."

I have two views. The first one shows a list of the custom objects made of downloaded data, the second shows a list of objects that are the basis for objects from the first list.
If I choose an object in the second view to save in Realm and go back to the first one, the data to make a list of custom objects is downloaded from database. If I want to delete that object the app crash and this message appears:
Thread 1: Exception: "Realm accessed from incorrect thread."
The same situation is when I delete one, two or more objects in the first screen, go to another one, choose one, two, or more to save in the database and go back to the first one, where data is downloaded from database. App is crashing and same message.
I know it's all about threads, but I don't know how to resolve that.
I tried resolving that by DispatchQueue, but it doesn't work, or i'm doing it wrong. How to resolve this thread problem in my case?
These database functions are using in the first view:
func deleteAddItem(addItem: AddItem) throws {
do {
let realm = try! Realm()
try! realm.write {
if let itemToDelete = realm.object(ofType: AddItem.self, forPrimaryKey: addItem.id) {
realm.delete(itemToDelete)
realm.refresh()
}
}
}
}
}
func fetchStations() throws -> Results<Station> {
do {
realm = try Realm()
return realm!.objects(Station.self)
}
catch {
throw RuntimeError.NoRealmSet
}
}
func fetchSensors() throws -> Results<Sensor> {
do {
realm = try Realm()
return realm!.objects(Sensor.self)
}
catch {
throw RuntimeError.NoRealmSet
}
}
func fetchAddItems() throws -> Results<AddItem> {
do {
realm = try Realm()
return realm!.objects(AddItem.self)
}
catch {
throw RuntimeError.NoRealmSet
}
}
func fetchData() throws -> Results<Data> {
do {
realm = try Realm()
return realm!.objects(Data.self)
}
catch {
throw RuntimeError.NoRealmSet
}
}
If you want more code or information, please let me know.
It appears you have two different Realm threads going
func deleteAddItem(addItem: AddItem) throws {
do {
let realm = try! Realm() <- One realm thread, a local 'let'
and then
func fetchAddItems() throws -> Results<AddItem> {
do {
realm = try Realm() <- A different realm thread, a class var?
that can probably be fixed by using the same realm when deleting
func deleteAddItem(addItem: AddItem) throws {
do {
realm = try! Realm() <- references the same realm as in delete
There are few options to prevent this. Once is simply get the realm, every time you want to use it
let realm = try! Realm()
realm.read or realm.write etc
or create a singleton function (or a RealmService class) that can be accessed throughout the app. In a separate file (or whever you want to put it and this is just a quick example)
import RealmSwift
func gGetRealm() -> Realm? {
do {
let realm = try Realm()
return realm
} catch let error as NSError { //lots of error handling!
print("Error!")
print(" " + error.localizedDescription)
let err = error.code
print(err)
let t = type(of: err)
print(t)
return nil
}
}
Then to use it
if let realm = gGetRealm() {
realm.read, realm.write etc
}
Also, I noticed you appear to be getting an item from realm to just then delete it. That's not necessary.
If the item is already managed by Realm, it can just be deleted directly. Here's an updated delete function
func deleteItem(whichItem: theItemToDelete) {
if let realm = gGetRealm() {
try! realm.write {
realm.delete(theItemToDelete)
}
}
}

How to backup realm db to iCloud with Swift?

I am trying to implement a function to backup realm db to iCloud
https://medium.com/swlh/backup-your-applications-data-with-icloud-and-track-progress-48a00ebd2891
I finished the setting by referring to the site above.
And I entered the code according to the method of the site, but with no success.
So I tried again like below.
Still I can't see the file in the app in settings.
Is there something wrong?
And I am curious about how to restore to realm db in iCloud.
Thank you
func uploadDatabaseToCloudDrive()
{
let fileManager = FileManager.default
//let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents", isDirectory: true)
let iCloudDocumentToCheckURL = iCloudDocumentsURL.appendingPathComponent("default.realm")
let realmArchiveURL = iCloudDocumentToCheckURL
if(fileManager.fileExists(atPath: iCloudDocumentsURL.path ))
{
do
{
try fileManager.removeItem(at: realmArchiveURL)
let realm = try! Realm()
try! realm.writeCopy(toFile: realmArchiveURL)
}catch
{
print("ERR")
}
}
else
{
print("Need to store ")
let realm = try! Realm()
try! realm.writeCopy(toFile: realmArchiveURL)
}
}

Swift realm return zero objects

I have opened my realm database in Realm browser, i can see that there is are actual data (10 entities).
But when i call print("realm objects \(self.realm.objects(CharacterModel.self))")
Result is empty:
realm objects Results<CharacterModel> <0x7f8d8f204a30> (
)
When i put breakpoint and check data base state at this moment data exist. Why is that happening?
realm is declared like that:
static func realm() -> Realm{
do {
let realm = try Realm()
return realm
} catch let error as NSError {
fatalError("Error opening realm: \(error)")
}
}
The answer may reveal itself if we eliminate some variables:
The following code works with a Realm that contains Person() objects
func doPrintData() {
do {
let realm = try Realm()
print("realm objects \(realm.objects(Person.self))")
} catch let error as NSError {
print(error.localizedDescription)
}
}
the following also works
func realm() -> Realm{
do {
let realm = try Realm()
return realm
} catch let error as NSError {
fatalError("Error opening realm: \(error)")
}
}
func doPrintData() {
do {
let realm = self.realm()
print("realm objects \(realm.objects(Person.self))")
} catch let error as NSError {
print(error.localizedDescription)
}
}
There's probably more code involved but try one of the above solutions and see if it makes a difference.

Realm Object Server. Sync initial Local DB

I have a local Realm database, full of 160000 row. I want to copy it to the local path for Realm to be able to use it as official DB, and sync it online. (so my empty Db will be synced). Can I do that? (at this time, doesn't work because it copy the Db in local folder, but not in the user specific folder)
func loginCompletedA(user: SyncUser) {
let realmURL = URL(string: “realm://xxx.compute-1.amazonaws.com:9080/beerUsers”)!
var configuration = Realm.Configuration.defaultConfiguration
configuration.syncConfiguration = SyncConfiguration(user: user, realmURL: realmURL)
let defaultURL = configuration.fileURL!
//let defaultParentURL = defaultURL.deletingLastPathComponent()
if let v0URL = Bundle.main.url(forResource: “default”, withExtension: “realm”){
do {
//if !ifNotExists {
try FileManager.default.removeItem(at: defaultURL)
//}
try FileManager.default.copyItem(at: v0URL, to: defaultURL)
} catch {}
do {
try FileManager.default.copyItem(at: v0URL, to: defaultURL)
} catch {}
}else{
}
let realm = try! Realm(configuration: configuration)
let session = user.session(for: realmURL)!
downloadToken = session.addProgressNotification(for: .download, mode: .reportIndefinitely) {
print(“download progress: \($0)“) // This is never called.
}
uploadToken = session.addProgressNotification(for: .upload, mode: .reportIndefinitely) {
print(“upload progress: \($0)“) // This is never called.
}
}
Just to confirm what I think you're asking. You're pre-bundling a Realm database file, containing 160,000 rows of data along with your app. When a new user logs into the app, the data is then synchronized with their account.
Unsynchronized Realm files and synchronized Realm files are two different file formats, so it's not possible to convert one file to another. Copying a pre-bundled offline Realm to a user-controlled directory and then trying to apply a syncConfiguration object won't do anything.
The easiest solution to this is to make a new synchronized Realm, and then copy the data from the pre-bundled Realm into the synchronized Realm the first time the app launches.
let bundledRealmURL = Bundle.main.url(forResource: “default”, withExtension: “realm”)!
let localConfiguration = Realm.Configuration()
configuration.readOnly = true
configuration.fileURL = bundledRealmURL
let localRealm = try! Realm(configuration: configuration)
let syncConfiguration = Realm.Configuration()
syncConfiguration.syncConfiguration = SyncConfiguration(user: user, realmURL: realmURL)
let syncRealm = try! Realm(configuration: configuration)
let myObjects = localRealm.objects(MyObject.self)
try! syncRealm.write {
for myObject in myObjects {
let newObject = MyObject(value: myObject)
syncRealm.add(newObject)
}
}
We're exploring ways to make it easier to 'prefill' synchronized Realms for a future release of Realm. :)

delete core data entry doesn't work

I try to delete an core data entry using Swift. I also use the fetched results controller for loading the entries. This is my code:
let context = self.fetchedResultsController.managedObjectContext
let fetchRequest = NSFetchRequest(entityName:"Person")
fetchRequest.predicate = NSPredicate(format: "name = '\(item)'")
var error : NSError?
if let results = context.executeFetchRequest(fetchRequest, error:&error),
let managedObject = results.first as? NSManagedObject {
context.deleteObject(managedObject)
}
I don't know why but if this code runs the entry is deleted out of the table but if i restart the app the table includes the task which i've deleted.
This only deletes the object from the managed object context (which is the scratchpad for making changes). To persist anything done in a managed object context to the underlying database you need to save it first:
if let results = context.executeFetchRequest(fetchRequest, error:&error),
let managedObject = results.first as? NSManagedObject {
context.deleteObject(managedObject)
}
let saveError: NSError?
context.save(&saveError)
You need to save.
Swift 1.2
context.save(nil)
Swift 2
do { try context.save() } catch {}