我的应用程序具有使用帐单地址的电子商店购买功能。我也有一个账单地址列表,点击列表中的地址单元将进入编辑地址页面。但是,当我运行购买功能并编辑地址,然后返回到“帐单地址列表”页面后,该应用将停止运行。 (如果我不购买就编辑地址,那一切都很好)
错误显示:
Terminating app due to uncaught exception 'RLMException', reason: 'Object has been deleted or invalidated.'
并且:
libc++abi.dylib: terminating with uncaught exception of type NSException
以及 AppDelegate.swift ,
"Thread 1: signal SIGABRT"
此行显示错误:
class AppDelegate: UIResponder, UIApplicationDelegate {
这是帐单地址列表代码(其中包含许多帐单地址单元格,点击该单元格将进入编辑地址功能的内部:
import Foundation
import PKHUD
class ManageBillingAddressVC: _BaseViewController {
@objc var billingAddress: [UserBillingAddress] = [] { //= Address.getAllAddressLists()
didSet {
emptyView.isHidden = billingAddress.count != 0
}
}
let viewModel = BillingAddressViewModel()
@IBOutlet weak var tblBillingAddress: UITableView!
@IBOutlet weak var emptyView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
setUpNavBarWithAttributes(navtitle: "Manage Billing Address", setStatusBarStyle: .default, isTransparent: false, tintColor: .white, titleColor: Color.Tuna.instance(), titleFont: FontBook.AdobePro.navSize(), isBackHidden: false, isShadowIncluded: true, rightBarButton: [showGoldPlusBtn()])
viewModelCallBack()
initTableViews()
observeAdressUpdateNotification()
}
@objc func viewModelCallBack() {
viewModel.beforeApiCall = {
HUD.show(.systemActivity)
}
viewModel.afterApiCall = {
HUD.hide()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: true)
fetchBillingAddress()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
@objc func updateDeliveryAddressTable() {
fetchBillingAddress()
}
@objc func fetchBillingAddress() {
viewModel.getBillingAddress(success: {
self.billingAddress.removeAll()
for address in $0{
if address.crm_address_order != "postal_address"{
self.billingAddress.append(address)
}
}
self.tblBillingAddress.reloadData()
}) {
self.showAlert($0)
}
}
@objc func observeAdressUpdateNotification() {
NotificationCenter.default.addObserver(self, selector: #selector(updateDeliveryAddressTable), name: Constants.billingAddress, object: nil)
}
override func rightBarButtonClicked() {
viewModel.getBillingAddress(success: {
self.billingAddress.removeAll()
for address in $0{
if address.crm_address_order != "postal_address"{
self.billingAddress.append(address)
}
}
if self.billingAddress.count >= 3{
self.showAlert("Addresses are limited to a maximum of 3")
}else{
self.pushViewControllerWithSlideUpEffect(vc: UIStoryboard.AddBillingAddress())
}
self.tblBillingAddress.reloadData()
}) {
self.showAlert($0)
}
}
@objc func initTableViews() {
tblBillingAddress.register(UINib(nibName : "BillingAddressCell", bundle : nil), forCellReuseIdentifier: "BillingAddressCell")
tblBillingAddress.dataSource = self
tblBillingAddress.delegate = self
tblBillingAddress.separatorStyle = .none
tblBillingAddress.contentInset = UIEdgeInsetsMake(20, 0, 20, 0)
tblBillingAddress.rowHeight = UITableViewAutomaticDimension
tblBillingAddress.estimatedRowHeight = 165 //108
}
deinit {
NotificationCenter.default.removeObserver(self)
}
}
extension ManageBillingAddressVC: DeliveryAddressCellDelegate {
@objc func didSelectBillingAddress(address: UserBillingAddress, index: Int) {
guard let vc = UIStoryboard.AddBillingAddress() as? AddBillingAddressVC else { return }
vc.billingAddress = address
pushViewControllerWithSlideUpEffect(vc: vc)
}
}
extension ManageBillingAddressVC: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return billingAddress.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BillingAddressCell" ) as! BillingAddressCell
cell.delegate = self
cell.billingAddress = billingAddress[indexPath.row]
//cell.address = billingAddress[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
}
}
这是我在地址列表代码中的帐单邮寄地址单元格:
import UIKit
class BillingAddressCell: DeliveryAddresCell {
@objc var billingAddress: UserBillingAddress? {
didSet {
billingAddress.flatMap {
lblName.text = "\($0.salutation ?? ""). \($0.firstname ?? "") \($0.lastname ?? "")"
lblAddress.text = $0.street?.first
lblPhoneNo.text = $0.telephone
lblUnitNo.text = $0.unit_number
lblStateCountry.text = "\($0.region?.first?.region ?? ""), \($0.postcode ?? "")"
if let id = $0.country_id, let countryID = Int(id) {
lblCountry.text = CountryList.getCountryName(id: countryID)
}
}
}
}
override func btnEditTapped(_ sender: UIButton) {
delegate?.didSelectBillingAddress(address: billingAddress!, index: tag)
}
}
以下是获取/更新帐单地址的功能:
class UserBillingAddress: UserBillingAddressInformation {
@objc var id : String?
@objc var customerID: String?
required convenience init?(map: Map){
self.init()
}
override func mapping(map: Map){
super.mapping(map: map)
id <- map["id"]
customerID <- map["customer_id"]
}
}
以下是在购买过程中点击“结帐”按钮后发生的代码:
@IBAction func btnCheckoutTapped(_ sender: UIButton) {
guard let card = defaultCreditCard, let address = defaultAddress else { return }
baseViewModel.checkCartLimit(success: { checkLimit in
if let limitErrors = checkLimit.limit_errors {
if limitErrors.count > 0 {
self.baseViewModel.handleCheckLimitError?(checkLimit)
} else {
guard let processingVC = UIStoryboard.ProcessingOrderVC() as? ProcessingOrderVC else { return }
// present processing view
processingVC.modalPresentationStyle = .overCurrentContext
processingVC.defaultAddress = address
processingVC.defaultCreditCard = card
processingVC.isSkyDollarPurchaseForMembership = self.isSkyDollarPurchaseForMembership
processingVC.isMembershipProduct = self.isMembershipProduct
processingVC.isFullSkyDollarPurchase = self.isFullSkyDollarPurchase
self.present(processingVC, animated: true)
}
} else {
guard let processingVC = UIStoryboard.ProcessingOrderVC() as? ProcessingOrderVC else { return }
// present processing view
processingVC.modalPresentationStyle = .overCurrentContext
processingVC.defaultAddress = address
processingVC.defaultCreditCard = card
processingVC.isSkyDollarPurchaseForMembership = self.isSkyDollarPurchaseForMembership
processingVC.isMembershipProduct = self.isMembershipProduct
self.present(processingVC, animated: true)
}
}, failure: { (errorMessage) in
self.showAlert(errorMessage)
})
}
这是点击结帐按钮后的购买处理代码:
import UIKit
class ProcessingOrderVC: UIViewController {
@IBOutlet weak var orderProcessingStackView: UIStackView!
@IBOutlet weak var orderProcessErrorStackView: UIStackView!
@IBOutlet weak var btnOkay: UIButton!
@IBOutlet weak var lblError: UILabel!
@objc var isMembershipProduct : Bool = false
@objc var isSkyDollarPurchaseForMembership : Bool = false
@objc var isFullSkyDollarPurchase: Bool = false
let checkoutViewModel = CheckoutStep2ViewModel()
@objc var defaultAddress = Address()
@objc var defaultCreditCard = CreditCardData()
override func viewDidLoad() {
super.viewDidLoad()
let attributedTitle = NSAttributedString(string: "TRY AGAIN", attributes: [NSAttributedStringKey.kern: 1.3, NSAttributedStringKey.font : FontBook.Bold.of(size: 13.0), NSAttributedStringKey.foregroundColor: UIColor.white])
btnOkay?.setAttributedTitle(attributedTitle, for: .normal)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if isSkyDollarPurchaseForMembership{
self.checkoutViewModel.placeOrderWithSkyDollarForMembership(address: defaultAddress, success: { orderID in
(UIStoryboard.CheckoutStep3VC() as? CheckoutStep3VC).flatMap {
$0.orderID = orderID
$0.hero.modalAnimationType = .fade
self.present($0, animated: false, completion: nil)
}
}) { (error) in
self.showError()
}
}else{
self.checkoutViewModel.placeOrder(address: defaultAddress, card: defaultCreditCard, isFullSkyDollarPurchase: isFullSkyDollarPurchase, success: { orderID in
(UIStoryboard.CheckoutStep3VC() as? CheckoutStep3VC).flatMap {
$0.orderID = orderID
$0.hero.modalAnimationType = .fade
self.present($0, animated: false, completion: nil)
}
}) { (error) in
self.showError()
}
}
}
@IBAction func btnCloseTapped(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
@IBAction func btnOkayTapped(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
@objc func showError() {
orderProcessErrorStackView.isHidden = false
orderProcessingStackView.isHidden = true
}
}
这是defaultAddress变量和地址类:
@objc var defaultAddress = Address()
class Address : Object, Mappable{
@objc dynamic var id: Int = 0
@objc dynamic var customerId: Int = 0
@objc dynamic var region: Region? = nil
@objc dynamic var region_id: Int = 0
@objc dynamic var countryId: String = ""
let streets = List<Street>()
@objc dynamic var telephone: String = ""
@objc dynamic var postcode: String = ""
@objc dynamic var city: String = ""
@objc dynamic var prefix: String = ""
@objc dynamic var company: String = ""
@objc dynamic var firstname: String = ""
@objc dynamic var lastname: String = ""
@objc dynamic var defaultShipping: Bool = false
@objc dynamic var defaultBilling: Bool = false
var addressAttributes = List<AddressAttributes>()
required convenience init?(map: Map){
self.init()
}
没错,购买过程不会更新地址,但是,如果我不购买,那么编辑地址就不会有错误。该错误仅在进行购买过程之后发生。我真的不知道发生了什么谁能建议可能是什么问题?
我在iOS上还很新,所以请更精确地解决问题。非常感谢你!