ios - 领域丢失函数外的数据
问题描述
我仍然是编码新手,我在使用 Realm Cloud 时遇到了一些问题,无论我多么努力,我似乎都无法解决。我正在尝试创建一个“点击并收集”订单跟踪器的示例,当orderState
对象属性在 1-4 之间更改(数字代表不同的阶段)时,它会将 UI 更改为相应的屏幕。我订阅了Results<Order>
对象的 Realm 观察,在发生观察和通知的函数中currentOrder
包含正确的Order
对象。但是,我有一个changes
观察开关,它调用一个函数来更新到正确的 UI。在这个被调用的函数内部currentOrder
突然不包含任何数据,currentOrder
是在全局范围内定义的,所以我不明白为什么会这样。我过滤Results<Order>
只查询匹配的ID(当通过主键匹配并绕过时,观察似乎对我不起作用Results
)。
我将在此处添加整个 VC,唯一重要的注意事项是该currentOrderID
属性是从先前将对象写入 Realm 的 VC 传递过来的。如果您向下滚动直到func prepareRealm
&func changeUIBasedOnStatus
这就是问题所在,我还在结尾处包含了控制台消息。打印报表结果。
//
// 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
是它抛出“意外发现 nil ...”错误的地方。
我知道这有点啰嗦,所以提前感谢您的帮助。
[编辑]
为澄清起见,我已经从prepareRealm
函数中删除了与 Realm 通知有关的所有代码,我将 分配给了currentOrder[0]
一个被调用的变量thisOrder
,以使 this 成为 typeObject
而不是 type Results
。然后我打印thisOrder
订单正确打印值的值。唉,然后我thisOrder
在计时器闭包内打印,它现在打印为 [invalid object]。计时器在某种意义上是象征性的,每当值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 更新到最新版本,一切都开始工作了!我认为这是问题的原因,但是我一直在构建不同的元素和测试等。突然间它每次都开始这样做,我觉得这可能是 Realm 的问题向他们提交错误。
解决方案
Order
必须将所有属性标记为dynamic
修饰符,Realm 才能覆盖 getter/setter。
所以你的订单看起来像这样:
class Order: Object {
@objc dynamic var firstName = ""
@objc dynamic var lastName = ""
....
}
推荐阅读
- visual-studio - Azure Functions、Entity Framework 和 Oracle DB - 基本 POC 失败
- sql-server - 如何使用 vba 将表从 access 2013 复制/升迁到 sql server
- java - JAX-WS,模拟服务实现的超时
- python - 从移动的目录加载 tensorflow 模型
- php - 使用 Laravel Auth 和加密用户表发送重置链接
- c++ - 错误 C2064:术语不计算为采用 1 个参数的函数 - Lambda 函数
- php - 如何将 API 返回字符串放入数组
- r - R - 在 grep 中隐含 x 对象
- xamarin - 如何在 Xamarin.UITest 中使用 App.ClearText 清除特定文本
- php - 如何在 PHP 中回显一个数组?并显示特定值数组 val