I am storing workout information in Realm from this object class:
class Workout: Object {
#objc dynamic var date: Date?
#objc dynamic var name: String?
#objc dynamic var exercise: String?
#objc dynamic var sets = 0
#objc dynamic var reps = 0
#objc dynamic var kg: Double = 0.0
#objc dynamic var notes: String?
}
I have data stored as an array, that I want to write to Realm, like this:
var workoutName = ""
var exercises = [String]()
var sets = [Int]()
var reps = [Int]()
var kg = [Double]()
var notes = [String]()
#IBAction func saveWorkoutButton(_ sender: Any) {
let realm = try! Realm()
print(Realm.Configuration.defaultConfiguration.fileURL!)
let currenDate = Date() // Get the current date
let myWorkout = Workout()
myWorkout.date = currenDate
myWorkout.name = workoutName
for i in 0 ..< exercises.count {
myWorkout.exercise = exercises[i]
myWorkout.sets = sets[i]
myWorkout.reps = reps[i]
myWorkout.kg = kg[i]
myWorkout.notes = notes[i]
realm.add(myWorkout)
}
try! realm.write {
realm.add(myWorkout)
}
}
The problem in this case is that when running the realm.write ... it only adds the last value from the for i in 0 function. I tried putting the realm.write function inside of the for i in 0 loop, but then it crashes. Each of the arrays contains equal numbers of objects. Any ideas?
You can try this code:
var myWorkouts:[Workout] = []
for i in 0 ..< exercises.count {
let myWorkout = Workout()
myWorkout.date = currenDate
myWorkout.name = workoutName
myWorkout.exercise = exercises[i]
myWorkout.sets = sets[i]
myWorkout.reps = reps[i]
myWorkout.kg = kg[i]
myWorkout.notes = notes[i]
myWorkouts.append(myWorkout)
}
try! realm.write {
realm.add(myWorkouts)
}
You should only add and write once if possible for performance optimisation.
Hope this helps.
Related
I use mongoDB to store data. I have a Result array, which array contains multiple same keyword results.
class Keywords: Object {
#objc dynamic var name: String = ""
#objc dynamic var date: Date = Date()
#objc dynamic var rank: Int = 0
#objc dynamic var requestedURL: String = ""
}
Users can not send requests more than once for the same keyword name.
let action = UIAlertAction(title: "Add", style: .default) { action in
if let textSafe = text.text {
let textPrefix = textSafe.removeWhitespace()
if self.keywordModel.keywordNames.count > 0 {
if self.keywordModel.keywordNames.contains(textSafe) {
return
} else {
self.seo.fetchSEO(keyword: textPrefix, requestURL: self.selectedDomain!.domainName, start: 1)
}
} else {
self.seo.fetchSEO(keyword: textPrefix, requestURL: self.selectedDomain!.domainName, start: 1)
}
}
}
My codes are working fine up to this part.
But when users want to refresh to update results there I need to write filter results or somehow must get only the last recent results if keywords are multiple times stored in the database. By the way, I need multiplied keyword data results since I want to use them for date progress charts in the future.
So simply I need to save all results but I want to show only more recent results on UI.
#objc func refresh(_ sender: AnyObject) {
var keywordArray = [String]()
keywordModel.keywordNames.forEach { keyword in
keywordArray.append(keyword)
}
keywordModel.keywordNames = [String]()
keywordModel.keywordRanks = [Double]()
keywordArray.forEach { keyword in
self.seo.fetchSEO(keyword: keyword, requestURL: self.selectedDomain!.domainName)
}
print(keyword!)
let deadLine = DispatchTime.now() + .seconds(3)
DispatchQueue.main.asyncAfter(deadline: deadLine) {
self.refreshControl?.endRefreshing()
}
}
And for further detail, I transfer results to KeywordModel for some calculations, and i manage all tableview through the KeywordModel codes below.
struct KeywordModel {
var keywordRanks = [Double]()
var averageRank: Double? = 0.0
var keywordCount: Int? = 0
var keywordNames = [String]()
var keywordCountString: String? {
return String(keywordCount!)
}
var averageRankString: String? {
return String(format: "%.01f", averageRank!)
}
mutating func averageOfRanks(resultKeyword: Results<Keywords>?) {
keywordCount = resultKeyword?.count
var n = 0
var raw = [Double]()
while n < resultKeyword!.count {
raw.append(Double(resultKeyword![n].rank))
n += 1
}
keywordRanks = raw
let rankSum = keywordRanks.reduce(0, +)
averageRank = rankSum / Double(keywordRanks.count)
}
mutating func saveKeywords(from results: Results<Keywords>?) {
if results!.count > 0 {
var n = 0
var raw = [String]()
while n < results!.count {
raw.append(results![n].name)
n += 1
}
keywordNames = raw
}
}
And there is my loadData method, where I can apply a filter.
func loadData() {
keyword = selectedDomain?.keywords.sorted(byKeyPath: "name")
statisticCalculate(keyword: keyword)
tableView.reloadData()
}
I started a new project and tried to implement Realm but I can't get it to work properly. My problem is that when I kill my app and relaunch it, all my previously added objects have disappeared and I get empty results from realm.objects.
class RealmManager {
static let shared = RealmManager()
let realm: Realm
init() {
realm = try! Realm()
}
func write(_ completion: ()->Void) {
do {
try realm.write() {
completion()
}
} catch {
print(error)
}
}
func add(_ object: Object) {
realm.add(object)
}
func delete(_ object: Object) {
realm.delete(object)
}
func objects<Element>(_ type: Element.Type) -> Results<Element> where Element : Object {
return realm.objects(type)
}
}
I created this singleton so I don't have to repeat this realm = try! Realm()everywhere in my code. I have this exact same class in another project which works fine.
My model looks like this :
class PrepFile: Object {
#objc dynamic var creationDate: Date = Date()
#objc dynamic var lastModificationDate: Date = Date()
#objc dynamic var title: String = "Pas de titre"
#objc dynamic var activityKind: String = ""
#objc dynamic var seanceNumber: Int = 0
#objc dynamic var level: String = ""
#objc dynamic var duration: Int = 0
#objc dynamic var date: Date = Date()
#objc dynamic var cycle: Int = 0
#objc dynamic var mainGoal: String = ""
#objc dynamic var specificGoal: String = ""
#objc dynamic var material: String = ""
#objc dynamic var isDraft: Bool = true
convenience init(title: String? = nil, activityKind: String? = nil, seanceNumber: Int? = nil, level: String? = nil, duration: Int? = nil, date: Date? = nil, cycle: Int? = nil, mainGoal: String? = nil, specificGoal: String? = nil, material: String? = nil, phases: [Phase] = [], isDraft: Bool = true) {
self.init()
if let tt = title {
self.title = tt
}
if let ak = activityKind {
self.activityKind = ak
}
if let sn = seanceNumber {
self.seanceNumber = sn
}
if let lv = level {
self.level = lv
}
if let dt = duration {
self.duration = dt
}
if let dt = date {
self.date = dt
}
if let cl = cycle {
self.cycle = cl
}
if let mg = mainGoal {
self.mainGoal = mg
}
if let sg = specificGoal {
self.specificGoal = sg
}
if let mt = material {
self.material = mt
}
self.isDraft = isDraft
}
required init() {
}
}
Then in my VC here's what I do :
class PrepFileListViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
lazy var prepFiles: Results<PrepFile> = { RealmManager.shared.objects(PrepFile.self) }()
var completePrepFiles: [PrepFile] = []
var draftPrepFiles: [PrepFile] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
RealmManager.shared.write {
for file in prepFiles {
RealmManager.shared.delete(file)
}
}
RealmManager.shared.write() {
RealmManager.shared.add(PrepFile(title: "Fiche de prep 1"))
RealmManager.shared.add(PrepFile(title: "Fiche de prep 2"))
RealmManager.shared.add(PrepFile(title: "Fiche de prep 3"))
RealmManager.shared.add(PrepFile(title: "Fiche de prep 4"))
RealmManager.shared.add(PrepFile(title: "Fiche de prep 5"))
}
}
override func viewWillAppear(_ animated: Bool) {
prepFiles = RealmManager.shared.objects(PrepFile.self)
completePrepFiles = prepFiles.filter({ !$0.isDraft })
draftPrepFiles = prepFiles.filter({ $0.isDraft })
tableView.reloadData()
}
}
Now when I run this, it works fine. My PrepFile are added to Realm and I retrieve them alright with my RealmManager.shared.objects(PrepFile.self). Now, I comment the part where I delete/add my files in the viewDidLoad and I get nothing. I don't get empty objects from RealmManager.shared.objects(PrepFile.self), I get an empty result like nothing was ever saved there.
What am I doing wrong ?
I am using Xcode 12 and running my app on an iPhone 11 / 13.3 simulator. Realm version is 5.5.0.
Hmm from what I can guess, you either have somewhere else a configuration for realm to be "inMemoryIdentifier" or you do not set the proper configuration with fileURL at beggining of the app.
Configuration local realm: https://realm.io/docs/swift/latest/#realms
I'm having a strange issue with objects in Realm. When i fetch an object from Realm database at first time & deleted object from database. unwrapping an optional value nil.
Model:
class Outlet: Object {
#objc dynamic var id:string = ""
#objc dynamic var name:string = ""
#objc dynamic var name1:Double = 0.0
#objc dynamic var name2:Double = 0.0
#objc dynamic var name3:Double = 0.0
#objc dynamic var name4:Double = 0.0
#objc dynamic var name5:Int = 0
let OutletListS = List<OutletList>()
override class func primaryKey() -> String? {
return "id"
}
}
Class:
class DBManager {
private var database: Realm
static let sharedInstance = DBManager()
private init() {
database = try! Realm()
}
func getDataFromDB() -> Outlet {
let result = database.objects(Outlet.self)
return result.first!
}
}
and calling method:
let selectedOutlet = DBManager.sharedInstance.getDataFromDB()
Error:
Printing description of result:
Results <0x7fb64f02c230> (
)
i could't solve it myself. help me please.
I'm using UICollectionView to display various images. I'm storing the path of images in realm.I want to create an array of images and store it in realm with all images in one array.
My code:
My realm Object
class cityDetail: Object {
dynamic var id = UUID().uuidString
dynamic var cityName = ""
dynamic var descrp = ""
dynamic var state = ""
dynamic var season = ""
dynamic var longitude = ""
dynamic var latitude = ""
var imgList = List<cityImage>()
override static func primaryKey() -> String? {
return "id"
}}
class cityImage:Object {
dynamic var imgStr = ""}
My function:
#IBAction func setIMG(_ sender:UIButton) {
self.img.isHidden = true
self.imgArray.append(imgURL)
print(imgArray)
newImage.imgStr = imgURL
citydetails.imgList.append(newImage)
let realm = try! Realm()
try! realm.write {
realm.add(newImage)
}
self.collection.reloadData()
}
Function in which I want array of path of images:
#IBAction func sendData(_ sender:UIButton) {
let citydetails = cityDetail()
let newImage = cityImage()
citydetails.cityName = self.cityName.text!
citydetails.descrp = self.descrp.text!
citydetails.state = self.state.text!
citydetails.season = self.season.text!
citydetails.latitude = String(lon)
citydetails.longitude = String(lat)
citydetails.imgList = newImage
let realm = try! Realm()
do {
try realm.write() {
realm.add(citydetails)
}
} catch {
}
self.collection.reloadData()
self.img.isHidden = true
}
I'm trying to save my array of objects in Realm, but Realm appears to be saving only the last object.
This is my model class:
class ContactEntry: Entry {
dynamic var contactId: Int = 0
dynamic var email: String? = ""
dynamic var phone: String? = ""
dynamic var building: String? = ""
dynamic var room: String? = ""
dynamic var contactDescription: String? = ""
dynamic var worktime: String? = ""
dynamic var address: String? = ""
dynamic var personEntries: PersonEntry?
}
This is the base class:
class Entry: Object {
dynamic var id: Int = 0
override static func primaryKey() -> String? { return "id" }
}
This is code I'm using for saving:
func createOrUpdate(entities: [Entity]) {
let entries = toEntries(entities)
let realm = try! Realm()
try! realm.write {
realm.add(entries, update: true)
}
}
func toEntry(entity: Contact) -> ContactEntry {
let entry = ContactEntry()
entry.contactId = entity.id
entry.email = entity.email
entry.phone = entity.phone
entry.building = entity.building
entry.room = entity.room
entry.contactDescription = entity.description
entry.worktime = entity.worktime
entry.address = entity.address
entry.personEntries = personDAO.toEntry(entity.person)
return entry
}
func toEntry(entity: Person) -> PersonEntry {
let entry = PersonEntry()
entry.personId = entity.id
entry.firstname = entity.firstname
entry.middlename = entity.middlename
entry.lastname = entity.lastname
entry.photo = entity.photo
return entry
}
I think that it may be because I have relationship in my model, but I'm not sure why they'd be a problem.
I'm using them as described in the Realm documentation.