Как установить ключ автоматического увеличения в Realm?
У меня есть уникальный ресурс для каждого объекта ChatData.
@interface ChatData : RLMObject
@property NSInteger msgid;
....
@end
Но каждый раз, когда я создаю новый объект, я должен запросить все объекты и получить последнее сообщение.
RLMArray *all = [[ChatData allObjects] arraySortedByProperty:@"msgid" ascending:YES];
ChatData *last = [all lastObject];
ChatData *newData = [[ChataData alloc]init];
newData.msgid = last.msgid+1;
Есть ли эффективный способ заменить эту реализацию?
Ответы
Ответ 1
Царство не имеет автоматического прироста поведения, поэтому вам нужно будет управлять этим самостоятельно. Вопрос, который я хотел бы предложить вам узнать о ваших данных:
Нужно ли иметь последовательные, смежные, целочисленные идентификаторы?
Если нет, то может быть достаточно первичного ключа с уникальной строкой. Затем вы можете использовать что-то вроде [[NSUUID UUID] UUIDString]
для генерации уникальных идентификаторов строк. Самое приятное в этом состоит в том, что эти UUID более или менее гарантированно уникальны даже в многопоточных сценариях.
Если это так, может быть более эффективным всегда сохранять последний номер в памяти, чтобы запросы не требовались каждый раз, когда должен был быть создан новый идентификатор. Если объекты могут быть созданы в нескольких потоках, убедитесь, что ваша функция nextPrimaryKey()
потокобезопасна, иначе она может генерировать один и тот же номер дважды (или больше!).
Ответ 2
Автоинкремент id Realm в Swift 2.0:
вставить код в область класса и использовать объект для записи
import Foundation
import RealmSwift
class Roteiro: Object {
dynamic var id = 0
dynamic var Titulo = ""
dynamic var Observacao = ""
dynamic var status = false
dynamic var cadastrado_dt = NSDate()
override static func primaryKey() -> String? {
return "id"
}
//Incrementa ID
func IncrementaID() -> Int{
let realm = try! Realm()
if let retNext = realm.objects(Roteiro.self).sorted(byKeyPath: "id").first?.id {
return retNext + 1
}else{
return 1
}
}
в использовании записи файла:
let Roteiro_Add = Roteiro()
//increment auto id
Roteiro_Add.id = Roteiro_Add.IncrementaID()
Roteiro_Add.Titulo = TituloDest
Roteiro_Add.Observacao = Observacao
Roteiro_Add.status = false
let realm = try! Realm()
try! realm.write({ () -> Void in
realm.add([Roteiro_Add])
})
Ответ 3
Вы используете этот код для автоматического инкрементного первичного ключа в Swift:
var myvalue = realm.objects(ChatData).map{$0.id}.maxElement() ?? 0
myvalue = myvalue + 1
Ответ 4
Я использовал createDate в моей модели, поэтому я создал Unix timeStamp на основе этой даты и использовал его как primaryKey моего объекта.
Это 99,99% гарантированно будет уникальным в моем случае (потому что временная метка точна для второго), но это может зависеть от вашего варианта использования.
Он менее надежный, чем UUID, но во многих случаях он достаточно.
extension NSDate {
/** Returns a NSDate instance from a time stamp */
convenience init(timeStamp: Double) {
self.init(timeIntervalSince1970: timeStamp)
}
}
extension Double {
/** Returns a timeStamp from a NSDate instance */
static func timeStampFromDate(date: NSDate) -> Double {
return date.timeIntervalSince1970
}
}
Ответ 5
Это, по сути, то, что предлагается в jpsim-ответе, используя UUID
для создания уникальных ключей. Мы запрашиваем перед вставкой, чтобы обеспечить уникальность. Это чаще всего будет выполнять только один запрос; в очень редком случае столкновения он будет продолжаться до тех пор, пока не найдет уникальный идентификатор. Это решение является естественным расширением типа Realm
и является общим по классам, которые наследуются от Object
. Класс должен реализовать primaryKey
и вернуть имя свойства String
.
extension Realm {
func createAutoUnique<T: Object>(_ type: T.Type) -> T {
guard let primaryKey = T.primaryKey() else {
fatalError("createAutoUnique requires that \(T.self) implements primaryKey()")
}
var id: String
var existing: T? = nil
repeat {
id = UUID().uuidString
existing = object(ofType: type, forPrimaryKey: id)
} while (existing != nil)
let value = [
primaryKey: id
]
return create(type, value: value, update: false)
}
}
Ответ 6
В Realm вам нужно управлять идентификатором auto-inc ID, поэтому есть много способов управлять им. Ниже приведены некоторые из них.
func incrementID() -> Int {
let realm = try! Realm()
return (realm.objects(Person.self).max(ofProperty: "id") as Int? ?? 0) + 1
}
вызывать этот метод каждый раз при добавлении записи.