3

I am trying to add a record to a realm DB table.

I have a class Connection which represents a table I need in my DB and have created dynamic vars which are to represent the columns:

import Foundation
import RealmSwift
import Realm

open class ConnectionState: Object {

    open dynamic var _id : String = NSUUID().uuidString
    open dynamic var a : String = ""
    open dynamic var b : String = ""
    open dynamic var c : Int = 0

    open override class func primaryKey() -> String? {
        return "_id"
    }

    required public init() {
        super.init()
    }

    required public init(realm: RLMRealm, schema: RLMObjectSchema) {
        super.init(realm: realm, schema: schema)
    }

    required public init(value: Any, schema: RLMSchema) {
        fatalError("init(value:schema:) has not been implemented")
    }
}

Then in my code I am trying to write and commit the write transaction like so:

let ConnectionState = ConnectionState()
ConnectionState.a = "a"
ConnectionState.b = "b"
ConnectionState.c = 1
try! self.realm.write {
     self.realm.add(ConnectionState)
}

try! self.realm.commitWrite()

When running this code, I am receiving the error:

Can't commit a non-existing write transaction

What am I missing? Do I need to have inits in my ConnectionState class? Before adding in the commitWrite, I was trying to view the db with realm browser. I found my device in xCode and chose to download the container but it was empty. Then I thought I needed to add in commitWrite

user2363025
  • 6,365
  • 19
  • 48
  • 89

2 Answers2

4
try! self.realm.write {
     self.realm.add(ConnectionState)
}

This code is somewhat equivalent to (possibly with some additional error handling):

realm.beginWrite()
...
try! realm.commitWrite()

Which means you're trying to commit your writes twice.

Just change your code like this:

try! self.realm.write {
     self.realm.add(ConnectionState)
}

// try! self.realm.commitWrite()
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • Ok thanks for clearing that up. But when I choose to show Container for my app, there is nothing there? How can I see this record in the realm browser. Testing on device, not simulator – user2363025 Jan 11 '17 at 10:44
  • If your device is connected to your developer machine - you can output the location of the Realm data file (Swift = Realm.Configuration.defaultConfiguration.fileURL) and then open that using the Realm Browser. – Ian Bradbury Jan 11 '17 at 14:19
4

In your example you called commitWrite without having called beginWrite. You cannot commit a write transaction because you did not start one. Either start a write transaction or delete the commitWrite line.

  1. Start transaction and commit it

    self.realm.beginWrite()
    
    self.realm.add(ConnectionState)
    
    try! self.realm.commitWrite()
    
  2. Delete commitWrite

    try! self.realm.write {
         self.realm.add(ConnectionState)
    }
    

The Realm docs have two examples of adding data to the database.

  1. Use the realm.write method

    // Use them like regular Swift objects
    let myDog = Dog()
    myDog.name = "Rex"
    myDog.age = 1
    print("name of dog: \(myDog.name)")
    
    // Get the default Realm
    let realm = try! Realm()
    
    // Query Realm for all dogs less than 2 years old
    let puppies = realm.objects(Dog.self).filter("age < 2")
    puppies.count // => 0 because no dogs have been added to the Realm yet
    
    // Persist your data easily
    try! realm.write {
        realm.add(myDog)
    }
    
  2. Use realm.beginWrite() and realm.commitWrite() to start the write transaction and commit data to the database

    let realm = try! Realm()
    
    // Break up the writing blocks into smaller portions
    // by starting a new transaction
    for idx1 in 0..<1000 {
      realm.beginWrite()
    
      // Add row via dictionary. Property order is ignored.
      for idx2 in 0..<1000 {
        realm.create(Person.self, value: [
          "name": "\(idx1)",
          "birthdate": Date(timeIntervalSince1970: TimeInterval(idx2))
        ])
      }
    
      // Commit the write transaction
      // to make this data available to other threads
      try! realm.commitWrite()
    }
    
Yannick
  • 3,210
  • 1
  • 21
  • 30
  • I mistakenly added in the commitWrite as I couldn't find any record when searching for my realm db. I have downloaded the container and chosen to show package contents but there is no default.realm for me to open with the browser. Any idea why this would be? – user2363025 Jan 11 '17 at 10:56
  • If you cannot find your file then have a look at http://stackoverflow.com/questions/28465706/how-to-find-my-realm-file/28465803#28465803 – Yannick Jan 11 '17 at 11:02
  • Yes I have followed the instructions in that SO as per my comment above. The problem is that once I get into AppData and documents there is no default.realm. I have set my realm to a specified location as part of an app group container. My realm file path is file:///private/var/mobile/Containers/Shared/AppGroup/B4D9C8F6-6A72-4539-A144-6AD622873A0A/db.realm – user2363025 Jan 11 '17 at 11:06
  • You have to follow the path that you just copied – Yannick Jan 11 '17 at 11:13
  • When selecting showPackage contents from my container, the only folders available are AppData which itself has Documents, Library and tmp. I don't see any folders such as Shared, Containers, AppGroup as per the path – user2363025 Jan 11 '17 at 11:16
  • It would be easier if you just test it on a simulator or ask a new question on SO cause I cannot help you with that. Hope this answer helps solved your problem though. – Yannick Jan 11 '17 at 11:21
  • Ok I've found the problem. It isn't current possible to view containers of an app group in this way. I don't think : http://stackoverflow.com/questions/29727337/how-to-export-shared-container-of-an-ios-app-with-xcode6-2 – user2363025 Jan 11 '17 at 11:22