Я все еще новичок в кодировании, и у меня возникают некоторые проблемы с Realm Cloud, которые, как бы я ни старался, мне не удается исправить. Я пытаюсь создать образец трекера заказов Click & Collect, который при изменении свойства объекта orderState
между 1-4 (числа представляют разные этапы) изменяет интерфейс на соответствующий экран. Я подписался на наблюдение Царства объекта Results<Order>
, в функции, где наблюдение и уведомления происходят currentOrder
содержит правильный объект Order
. Однако у меня есть переключатель для changes
из наблюдения, который вызывает функцию для обновления до правильного интерфейса. Внутри этой вызванной функции currentOrder
внезапно не содержит данных, currentOrder
был определен в глобальной области видимости, поэтому я не могу понять, почему это происходит. Я фильтрую Results<Order>
только для запроса соответствующего идентификатора (наблюдения, кажется, не работают для меня вообще при сопоставлении по первичному ключу и в обход Results
).
Я собираюсь добавить сюда весь VC, единственное важное замечание - это то, что свойство currentOrderID
передается от предыдущего VC, где объект был записан в Realm. Если вы прокрутите вниз до func prepareRealm
& func changeUIBasedOnStatus
, то здесь кроется проблема, и я также включил консольное сообщение в конце inc. печать результатов выписки.
//
// TrackerViewController.swift
// HG Demo
//
// Created by Adam Woodcock on 12/03/2019.
// Copyright © 2019 Adam Woodcock. All rights reserved.
//
import UIKit
import RealmSwift
import Lottie
import MapKit
import CoreLocation
class TrackerViewController: UIViewController {
//Lottie Views
@IBOutlet weak var orderPlacedAnimation: LOTAnimationView!
@IBOutlet weak var orderConfirmedAnimation: LOTAnimationView!
@IBOutlet weak var orderPickedAnimation: LOTAnimationView!
@IBOutlet weak var orderCompleteAnimation: LOTAnimationView!
//Outlets
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var headingLabel: UILabel!
@IBOutlet weak var bodyLabel: UILabel!
@IBOutlet weak var progressImage: UIImageView!
let config = SyncUser.current?.configuration()
var realm : Realm!
var currentOrder : Results<Order>!
var currentOrderID : String!
var subscription : SyncSubscription<Order>!
var subscriptionToken : NotificationToken?
var notificationToken : NotificationToken?
override func viewDidLoad() {
super.viewDidLoad()
realm = try! Realm(configuration: config!)
currentOrder = realm.objects(Order.self).filter("orderID = %@", currentOrderID!)
prepareRealm()
startOrderPlacedAnimation()
}
//Lottie functions
func startOrderPlacedAnimation() {
orderPlacedAnimation.setAnimation(named: "orderPlaced")
orderPlacedAnimation.play()
orderPlacedAnimation.loopAnimation = true
orderConfirmedAnimation.isHidden = true
orderCompleteAnimation.isHidden = true
headingLabel.text = "Thank you! Your order has been placed!"
bodyLabel.text = "Your order has been successfully placed, we'll notify you once this has been accepted!"
progressImage.image = UIImage(named: "singleCheck")
}
func startOrderConfirmedAnimation() {
orderConfirmedAnimation.isHidden = false
orderConfirmedAnimation.setAnimation(named: "undedited")
orderConfirmedAnimation.play()
orderConfirmedAnimation.loopAnimation = true
orderPlacedAnimation.isHidden = true
orderCompleteAnimation.isHidden = true
headingLabel.text = "It's Official! Your order is confirmed!"
bodyLabel.text = "A team member has confirmed your order, we'll start packing soon!"
progressImage.image = UIImage(named: "doubleCheck")
}
func startOrderPickedAnimation() {
orderPickedAnimation.isHidden = false
orderPickedAnimation.setAnimation(named: "orderPicked")
orderPickedAnimation.play()
orderPickedAnimation.loopAnimation = true
orderPlacedAnimation.isHidden = true
orderConfirmedAnimation.isHidden = true
orderCompleteAnimation.isHidden = true
headingLabel.text = "Woosh! Your order is being packed!"
bodyLabel.text = "A team member with extremely steady hands is currently packing your order!"
progressImage.image = UIImage(named: "tripleCheck")
}
func startOrderCompleteAnimation() {
orderCompleteAnimation.isHidden = false
orderCompleteAnimation.setAnimation(named: "orderComplete")
orderCompleteAnimation.play()
orderCompleteAnimation.loopAnimation = true
orderPlacedAnimation.isHidden = true
orderConfirmedAnimation.isHidden = true
orderPickedAnimation.isHidden = true
headingLabel.text = "Woohoo! Your order is ready to collect!"
bodyLabel.text = "We're as excited as you, so what're you waiting for? Come and grab it!"
progressImage.image = UIImage(named: "quadrupleCheck")
}
func startOrderHasBeenCollectedAnimation() {
}
func startErrorWithOrderAnimation() {
}
//Realm functions
//Assigning the current order to the Order object variable
func prepareRealm() {
subscription = currentOrder.subscribe(named: "current-order", limit: nil)
subscriptionToken = subscription.observe(\.state, options: .initial, { (state) in })
notificationToken = currentOrder.observe({ (changes) in
switch changes {
case .initial:
self.changeUIBasedOnStatus(sender: "Initial")
case .update :
self.changeUIBasedOnStatus(sender: "Update")
case .error(let error):
fatalError(error.localizedDescription)
}
})
print("Realm prepared, this is the object: \(currentOrder!)")
titleLabel.text = "\(String(currentOrder.first!.firstName))'s Order #\(currentOrder.first!.orderID!)"
}
func changeUIBasedOnStatus(sender: String) {
print("The switch realm object contains: \(currentOrder!), sender: \(sender)")
switch currentOrder.first!.orderStatus {
case 1:
startOrderPlacedAnimation()
case 2:
startOrderConfirmedAnimation()
case 3:
startOrderPickedAnimation()
case 4:
startOrderCompleteAnimation()
case 5:
startOrderHasBeenCollectedAnimation()
default:
startErrorWithOrderAnimation()
}
}
//IBActions
@IBAction func callUsTapped(_ sender: Any) {
guard let number = URL(string: "tel://+441522684865") else { return }
UIApplication.shared.open(number, options: [:], completionHandler: nil)
}
@IBAction func openingHoursTapped(_ sender: Any) {
}
@IBAction func directionsTapped(_ sender: Any) {
//Creating an action sheet to ask the user whether they'd like to use Apple Maps or Google Maps
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
//Adding the action and functionality to load Apple maps
alert.addAction(UIAlertAction(title: "Apple Maps", style: .default, handler: { (action) in
//Creating a placemark object to pass into the map item
let placemark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(53.203498, -0.611785))
//Initialising a new map item object with the pre-made placemark object
let mapItem = MKMapItem(placemark: placemark)
mapItem.phoneNumber = "+44 (0) 1522 684865"
//Setting the launch options to default to driving directions
let launchOptions = [MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving]
//Telling the map item object to open that specific location in maps
mapItem.openInMaps(launchOptions: launchOptions)
}))
alert.addAction(UIAlertAction(title: "Google Maps", style: .default, handler: { (action) in
//Add Google maps functionality
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
alert.dismiss(animated: true, completion: nil)
}))
present(alert, animated: true, completion: nil)
}
}
Консольное сообщение:
2019-03-14 17:00:52.132718+0000 HG Demo[51949:3038807] Sync: Connection[1]: Connected to endpoint '3.121.59.66:443' (from '192.168.0.21:64953')
Realm prepared, this is the object: Results<Order> <0x7fdce8c2d370> (
[0] Order {
firstName = Adam;
lastName = Woodcock;
orderID = 4431295;
timestamp = 2019-03-14 17:00:54 +0000;
orderStatus = 1;
isFulfilled = 0;
}
)
The switch realm object contains: Results<Order> <0x7fdce8c2d370> (
), sender: Initial
(lldb)
Неустранимая ошибка в операторе switch в changeUIBased...
, в частности в switch currentOrder.first!.orderStatus
возникает ошибка «Неожиданно найден ноль ...».
Я знаю, что это немного затянуто, поэтому спасибо заранее за любую помощь.
[EDIT]
Для пояснения я удалил весь код, связанный с уведомлениями Realm, из функции prepareRealm
, я присваиваю currentOrder[0]
переменной с именем thisOrder
, чтобы сделать ее типа Object
, а не введите Results
. Затем я печатаю значение thisOrder
, в котором порядок правильно печатает значения. Увы, я тогда печатаю thisOrder
внутри таймера, и теперь он печатается как [неверный объект]. Таймер является символическим в том смысле, что всякий раз, когда значения currentOrder
или thisOrder
передаются вне функции prepareRealm
или для замыкания, объект становится недействительным. Я делал это несколько раз в разных приложениях и даже в этом приложении на отдельном VC, и он работает на 100% гладко, поэтому я действительно не могу понять, почему это происходит.
func prepareRealm() {
realm = try! Realm(configuration: config!)
currentOrder = realm.objects(Order.self).filter("orderID = %@", currentOrderID)
thisOrder = currentOrder[0]
print("This is thisOrder: \(thisOrder!)")
let timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { (timer) in
print(self.thisOrder)
}
}
[РЕДАКТИРОВАТЬ 2]
Я обновил Realm до последней версии, и все стало работать! Я думал, что это было причиной проблемы, однако с тех пор я продолжал создавать различные элементы, тестировать и т.д. отправить ошибку с ними.