Comparing Realm Results and finding the object in a List - swift

I need to loop through the objects in the Realm file and see if it is also listed in the List.
When I look at the file with the Realm Browser, it is there, but the following code always renders false.
Can anyone make out what is going on? (I am initiating Try! Realm earlier in the code, it is there, this is just the section that is bobbling my brian. It runs fine BTW.
Thanks,
Blessings,
—Mark
let totalReg = realm.objects(Registry.self)
let totalList = realm.objects(AllServices.self)
if totalReg.count != 0 && totalList.count != 0 { // when the update releases, I will change totalList == 0
print(totalReg.count) // = 2 records
print(totalList.count) // = 1 but when I click and open the list in Realm Browser it shows both records
let a = AllServices().self
for reg in totalReg {
if a.everything.contains(reg) {
print("Here")
} else {
print("not here") //Each loop goes here.
print(a.everything) //this prints: List<Registry> <0x600001d6e070> ( )
print (reg) //This correctly prints all the properties of the object.
}
}
}
This code always defaults to false, even though the Registry Object is in the List.
class Registry: Object {
#objc dynamic var registryId = UUID().uuidString
#objc dynamic var dateTime:String?
#objc dynamic var proper:String?
#objc dynamic var service:String?
#objc dynamic var place:String?
#objc dynamic var sunEuchAttendance:Int = 0
#objc dynamic var otherServiceAttendance:Int = 0
#objc dynamic var EuchVisitor:Int = 0
#objc dynamic var numberOfCommunions:Int = 0
//People serving
#objc dynamic var presiderOfficiant:String?
#objc dynamic var preacher:String?
#objc dynamic var server:String?
#objc dynamic var memo:String?
#objc dynamic var weekendEuch:Int = 0
#objc dynamic var weekdayEuch:Int = 0
#objc dynamic var privateEuch:Int = 0
#objc dynamic var weekendOffice:Int = 0
#objc dynamic var weekdayOffice:Int = 0
#objc dynamic var burrial:Int = 0
#objc dynamic var marraige:Int = 0
#objc dynamic var other:Int = 0
override static func primaryKey() -> String? {
return "registryId"
}
override static func indexedProperties() -> [String] {
return ["service"]
}
}
//List Model
class AllServices: Object {
var everything = List<Registry>()
var eucharist = List<Registry>()
var weekdayEucharist = List<Registry>()
var office = List<Registry>()
var weekdayOffice = List<Registry>()
var marriage = List<Registry>()
var burial = List<Registry>()
var requiem = List<Registry>()
var nuptial = List<Registry>()
var other = List<Registry>()
}

Related

Realm Append managed object to unmanaged object

I want to append managed object to unmanaged object in realm.
Here is the codes
class Schedule3: Object, ObjectKeyIdentifiable {
#objc dynamic var _id: String = UUID().uuidString
#objc dynamic var _partition: String = ""
let scheduleTags = RealmSwift.List<ScheduleTag3>()
#objc dynamic var title: String = ""
override static func primaryKey() -> String? {
return "_id"
}
}
class ScheduleTag3: Object, ObjectKeyIdentifiable {
#objc dynamic var _id: String = UUID().uuidString
#objc dynamic var _partition: String = ""
#objc dynamic var name: String = ""
override static func primaryKey() -> String? {
return "_id"
}
}
When I add managed ScheduleTag3 object to unmanaged Schedule3 object and append #ObsevedResults(Schedule3.self), I get error 'Object is already managed by another Realm. Use create instead to copy it into this Realm.'
Here is the code of append,
struct SchedulePreview: View {
#ObservedResults(Schedule3.self) var schedules
#ObservedResults(ScheduleTag3.self) var tags
#EnvironmentObject var scheduleModel:ScheduleIDModel
var scheduleTitle:String
var scheduleBudget:Int
var areaTag:ScheduleTag3?
#StateRealmObject var thisSchedule = Schedule3()
var body: some View {
TabView(selection: self.$selection) {
...
.navigationBarItems (
trailing: Text("make")
.onTapGesture {
thisSchedule = scheduleModel.addSchedule(scheduleTitle: scheduleTitle, scheduleBudget: scheduleBudget, areaTag: areaTag)
let scheduleId = thisSchedule._id
let areTagId = areaTag?._id
let thisAreaTag = tags.filter("_id == %#", areTagId!).first
thisSchedule.scheduleTags.append(thisAreaTag!)
$schedules.append(thisSchedule)
}
)
}
}
class ScheduleIDModel: ObservableObject {
...
func addSchedule(scheduleTitle:String, scheduleBudget:Int, areaTag:ScheduleTag3?) -> Schedule3 {
let schedule = Schedule3()
if scheduleTitle != "" {
schedule.title = scheduleTitle
}
schedule.budget = scheduleBudget
schedule._partition = "Public"
return schedule
}
}

My ObservableObject Class Array Variable 'timeStep' Fails To Hold Values

I have two ObservableObject classes: CarLotData and StopWatchManager. What I am trying to do is use my StopWatchManager class to load CarLotData property timeStep--which is a array Double type.
Here is my code for StopWatchManager:
import Foundation
import SwiftUI
class StopWatchManager: ObservableObject {
#ObservedObject var carLotData = CarLotData()
var timer = Timer()
#Published var mode: stopWatchMode = .stopped
#Published var secondsElapsed = 0.0
enum stopWatchMode {
case running
case stopped
case paused
}
func start() {
mode = .running
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
self.secondsElapsed = self.secondsElapsed + 0.1
}
}
func stop() {
timer.invalidate()
if carLotData.timeStep.count < 7 {
carLotData.timeStep.append(secondsElapsed)
print(carLotData.timeStep)
mode = .stopped
}
}
}
Here is my code for CarLotData:
import SwiftUI
import Foundation
class CarLotData: ObservableObject {
#Published var carLotData: Int = 0
#Published var carStep: [Double] = []
var id = UUID()
var newUsed: Int = 0
var powerType: Int = 0
var downPayment: Int = 0
var salesmanType: Int = 0
var appointment: Int = 0
var internet: Int = 0
var retail: Int = 0
var carType: Int = 0
var carBrand: Int = 0
var purchaseType: Int = 0
var creditRank: Int = 0
var warranty: Int = 0
var service: Int = 0
var thirdParty: Int = 0
var timeStep: [Double] = []
var salesman: Int = 0
}
Lastly here is my view where I get "timeStep = []" where I want an array of Double values.
import SwiftUI
struct CarLotDataView: View {
#ObservedObject var carLotData = CarLotData()
#ObservedObject var stopWachManager = StopWatchManager()
var body: some View {
List {
Group {
Text("Customer ID: \(carLotData.id)")
Text("Salesman: \(carLotData.salesman)")
Text("New/Used: \(carLotData.newUsed)")
Text("Power Type: \(carLotData.powerType)")
Text("Down Payment: \(carLotData.downPayment)")
Text("Salesman Type: \(carLotData.salesmanType)")
Text("Appointment: \(carLotData.appointment)")
}
Group {
Text("Internet: \(carLotData.internet)")
Text("Retail: \(carLotData.retail)")
Text("Car Type: \(carLotData.carType)")
Text("Car Brand: \(carLotData.carBrand)")
Text("Purchase Type: \(carLotData.purchaseType)")
Text("Credit Rankd: \(carLotData.creditRank)")
Text("Warranty: \(carLotData.warranty)")
Text("Service: \(carLotData.service)")
Text("Third Party: \(carLotData.thirdParty)")
Text("Time Steps: \(carLotData.timeStep)" as String)
}
}
}
}
Everything else works it's just that the values for my timer don't get transferred to my timeStep array. Any insights would be appreciated.
You are trying to access and update CarLotData from StopWatchManager and you are doing, but you are using completely another one in your View, You have to use the same one that you updated!
The trick is always using the same reference you started!
add this line to your CarLotData:
static let shared: CarLotData = CarLotData()
then use this code on StopWatchManager:
let carLotData = CarLotData.shared
Do not use #ObservedObject inside Class, just use let, it will done the job.
At last use this in your View:
#ObservedObject var carLotData = CarLotData.shared
For my personal app, I would use this down code:
#StateObject var carLotData = CarLotData.shared
You are creating CarLotData twice. The right way would be to make sure you access the correct reference.
The other way is to make CarLotData a singleton. But that's only the right approach if you'll be using this data across many views.
class CarLotData: ObservableObject {
static public let shared = CarLotData()
private init() { }
}
Then you'd use it like so. Making sure to never call CarLotData()
Text("Internet: \(CarLotData.shared.internet)")

Swift Realm filter all object with a null value

I have two objects as follow:
class NextAction: Object {
#objc dynamic var title: String = ""
#objc dynamic var notes: String? = ""
#objc dynamic var deadline: Date?
#objc dynamic var deadlineID: String = ""
#objc dynamic var reminder: Date?
#objc dynamic var reminderID: String = ""
#objc dynamic var finished: Bool = false
#objc dynamic var favorite: Bool = false
#objc dynamic var priority: Int = 0
var duration = RealmOptional<Int>()
#objc dynamic var tag: String?
let tags = List<Tag>()
}
class Tag: Object {
#objc dynamic var title: String = ""
let owners = LinkingObjects(fromType: NextAction.self, property: "tags")
}
Not all NextAction objects has a tag, but I want to filter out and show all who are missing one, I have tried
var test = realm.objects(NextAction.self).filter("ANY tags == nil")
But I get this error
'Invalid value', reason: 'Expected object of type Tag for property 'tags' on object of type 'NextAction', but received: (null)'
Your tags cannot be nil.
If you want to find objects whose tags is empty, you can do that this way.
var test = realm.objects(NextAction.self).filter("ANY tags.#count == 0")

Get notified when value in List is updated using realm

I am trying to write an application in OS X using a Realm database. I want to trigger notification when where there is change in value of List which is inside another object
Below is the Class
final class Profile: Object {
#objc dynamic var gradient1 = ""
#objc dynamic var gradient2 = ""
#objc dynamic var fontColor = ""
#objc dynamic var selectedFont = ""
#objc dynamic var selectedTitleFont = ""
#objc dynamic var fontFamily = ""
#objc dynamic var name = ""
#objc dynamic var shortbio = ""
#objc dynamic var avatarSource = ""
#objc dynamic var userid = ""
#objc dynamic var email = ""
var features = List<Features>()
var socialLinkButtons = List<SocialLinkButtons>()
#objc dynamic var appSelectedMetaData : AppMetaData? = nil
override static func primaryKey() -> String?{
return "userid"
}
}
final class Features: Object {
#objc dynamic var uuid = ""
#objc dynamic var id = ""
#objc dynamic var label = ""
#objc dynamic var screen = ""
#objc dynamic var active = false
override static func primaryKey() -> String?{
return "id"
}
convenience init(id: String, uuid: String, label: String, screen: String, active: Bool) {
self.init()
self.id = id
self.uuid = uuid
self.label = label
self.screen = screen
self.active = active
}
}
I want to trigger notifications whenever value inside feature is updated.
You can use Realm Collection Notifications to achieve your goals. You just need to make sure that you store the returned NotificationToken in a variable that doesn't get deallocated until you don't actually need to receive the notifications anymore and that you call .invalidate() on the token when you no longer want to receive notifications.
func observeFeatureChanges(in profile:Profile) -> NotificationToken {
let notificationToken = profile.features.observe { changes in
switch changes {
case .update(_, deletions: let deletionIndices, insertions: let insertionIndices, modifications: let modIndices):
print("Objects deleted from indices: \(deletionIndices)")
print("Objects inserted to indices: \(insertionIndices)")
print("Objects modified at indices: \(modIndices)")
case .error(let error):
print(error)
case .initial(let type):
print(type)
}
}
return notificationToken
}

Property observers Swift 4

struct Kitchen // Coordinator
{
var foodItems = [FoodItem] () // Collection of FoodItem objects.
var wastedItems = [WastedItem]() // Collection of WastedItem
var totalSpend = Double()
var currentSpend = Double()
var weeklyHouseholdFoodBudget = Double()
var wastageCost = Double()
init(aTotal:Double,aCurrent:Double,aBudget:Double,aWastage:Double)
{
self.totalSpend = aTotal
self.currentSpend = aCurrent
self.weeklyHouseholdFoodBudget = aBudget
self.wastageCost = aWastage
}
struct FoodItem : Equatable
{
var itemName = String()
var itemQuantity = Double()
var dateOfUse = String()
var unitOfMeasurement = String()
init(aName:String,aQuantity:Double,aDateOfUse:String,aUnit:String)
{
self.itemName = aName
self.itemQuantity = aQuantity
self.dateOfUse = aDateOfUse
self.unitOfMeasurement = aUnit
}
mutating func listFoodItems()
{
for item in foodItems
{
print("Item Name:", item.getName(),",",
"Qunatity:",item.getItemQuantity(),",",
"Unit:",item.getUnitOfMeasurement(),",",
"Date of use:",item.getDateOfUse())
}
}
mutating func removeFoodItem(aFood:FoodItem)
{
if let anIndex = foodItems.index(of: aFood)
{
foodItems.remove(at: anIndex)
print(aFood.getName(),"Has been removed")
}
}
mutating func useFood(aFoodItem:inout FoodItem,inputQty:Double)
{
if (aFoodItem.getItemQuantity()) - (inputQty) <= 0
{
self.removeFoodItem(aFood: aFoodItem)
}
else
{
aFoodItem.useFoodItem(aQty: inputQty)
}
}
***Updated****
The issue I am having is when I use a func listFoodItems() the updated attribute itemQuantity does not change. I would like to know how to update the collection so when I call the func listFoodItems() it displays value changes.
The removal is ok, when the func runs the collection removes the object.
The issue must be because I am using for item in foodItems to display, I need to reload it with updated values before I do this?
Thank you for any assistance.
Property observers are used on properties.
The simplest example of a property observer.
class Foo {
var bar: String = "Some String" {
didSet {
print("did set value", bar)
}
}
}
Now if you want to display some changes, you will need your own code in didSet method in order to do that. For example call reloadData().