ios - 滚动 UITableView 时,NSManagedObject 数组变为 nil

标签 ios swift uitableview nsmanagedobject

我的应用程序中有一个 ViewController,我必须在其中向用户显示设置,用户可以使用 UISwitch 打开或关闭设置。我必须将设置存储在本地数据库中,并根据该显示数据在应用程序中向用户显示。

我正在使用 SugarRecord 进行核心数据管理。最初所有的设置都是打开的。

SugarRecordManager.swift

import Foundation
import SugarRecord
import CoreData


class SugarRecordManager
{
static let sharedInstance = SugarRecordManager()
private init(){

}

// Initializing CoreDataDefaultStorage
func coreDataStorage() -> CoreDataDefaultStorage {
    let store = CoreDataStore.named("db")
    let bundle = Bundle(for: type(of: self))
    let model = CoreDataObjectModel.merged([bundle])
    let defaultStorage = try! CoreDataDefaultStorage(store: store, model: model)
    return defaultStorage
}

//MARK:- User Settings methods

//update local settings
func updateSettingsModel(userSettings: [UserSetting]){
    let db = self.coreDataStorage()
    for localSetting in userSettings{
        try! db.operation { (context, save) -> Void in
            if let settingObjectToUpdate = try! context.request(UserSetting.self).filtered(with: "groupName", equalTo: localSetting.groupName!).fetch().first{
                settingObjectToUpdate.groupId = localSetting.groupId! as String
                settingObjectToUpdate.groupName = localSetting.groupName! as String
                settingObjectToUpdate.isGroupActive = localSetting.isGroupActive
                try! context.insert(settingObjectToUpdate)
                save()

            }
        }
    }
}

//retrieve settings from storage
func getAllSettings() -> [UserSetting] {
    let db = self.coreDataStorage()
    var userSettings : [UserSetting]
    do {
        userSettings = try db.fetch(FetchRequest<UserSetting>())
    } catch {
        userSettings = []
    }
    return userSettings
}

//initialise settings for the first time
func initialiseUserSettings(){
    let db = self.coreDataStorage()
    var groupNameArray = UserDefaults.standard.value(forKey: "groupNamesArrayKey") as? [String]
    var groupIdArray = UserDefaults.standard.value(forKey: "groupIdsArrayKey") as? [String]
    for i in 0 ..< groupIdArray!.count  {
        try! db.operation { (context, save) -> Void in
            let settingObject: UserSetting = try! context.new()
            settingObject.groupId = groupIdArray?[i];
            settingObject.groupName = groupNameArray?[i];
            settingObject.isGroupActive = true;
            try! context.insert(settingObject)
            save()
        }
    }
}
}

SettingsViewController.swift

class SettingsViewController: BaseViewController, UITableViewDataSource, UITableViewDelegate, SettingsCellDelegate {

@IBOutlet weak var btnSideNav: UIBarButtonItem!

@IBOutlet weak var settingsTable: UITableView!

var userSetting = [UserSetting]() //array to hold settings from storage

override func viewDidLoad() {
    super.viewDidLoad()
    self.automaticallyAdjustsScrollViewInsets = false;
    btnSideNav.target = revealViewController();
    btnSideNav.action = #selector(SWRevealViewController.revealToggle(_:));
    userSetting = SugarRecordManager.sharedInstance.getAllSettings() //here userSetting contains data and I have checked it
    self.settingsTable.reloadData()
    self.settingsTable.dataSource = self;
    self.settingsTable.delegate = self;
    // Do any additional setup after loading the view.
}

//MARK:- Table View Methods

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    print("Count of cells = \(self.userSetting.count)") //prints 18 which is good
    return self.userSetting.count
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 60;
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let settingsCell : SettingsCell? = tableView.dequeueReusableCell(withIdentifier: "SettingsCell") as? SettingsCell;
    settingsCell?.setUpWithModel(model: self.userSetting[indexPath.row], cell: settingsCell!)
    settingsCell?.delegate = self as SettingsCellDelegate;
    return settingsCell!
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}


func didTappedSwitch(cell: SettingsCell) {
    let indexPath = settingsTable.indexPath(for: cell);
    userSetting[(indexPath?.row)!].isGroupActive? = cell.isGroupActive.isOn as NSNumber
}

@IBAction func btnSaveTapped(_ sender: UIButton) {
    // code to save settings
}
}

SettingsCell.swift

protocol SettingsCellDelegate {
func didTappedSwitch(cell: SettingsCell)
}

class SettingsCell: UITableViewCell {

@IBOutlet weak var groupName: UILabel!

@IBOutlet weak var lblGroupId: UILabel!
@IBOutlet weak var isGroupActive: UISwitch!
var delegate: SettingsCellDelegate!
override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

func setUpWithModel(model: UserSetting, cell: SettingsCell)
{
    cell.groupName.text = model.groupName;
    cell.lblGroupId.text = model.groupId;
    isGroupActive.setOn((model.isGroupActive?.boolValue)!, animated: false)
}


@IBAction func isGroupActiveValueChanged(_ sender: UISwitch) {
    delegate.didTappedSwitch(cell: self)

}

}

现在,最初填充了 TableView,并且所有数组都工作正常,但是一旦我滚动 TableView,所有数据都消失了。甚至 userSetting 数组也是空的。我知道这与上下文有关,但无法弄清楚是什么。任何帮助将不胜感激。

最佳答案

像这样更改您的 func coreDataStorage() -> CoreDataDefaultStorage

// Initializing CoreDataDefaultStorage
    lazy var coreDataStorage: CoreDataDefaultStorage = {
        let store = CoreDataStore.named("db")
        let bundle = Bundle(for: type(of: self))
        let model = CoreDataObjectModel.merged([bundle])
        let defaultStorage = try! CoreDataDefaultStorage(store: store, model: model)
        return defaultStorage
    }()

你有这个问题是因为你每次做任何请求时都重新初始化 CoreDataDefaultStorage

在你让它变得惰性之后——你将只有一个 CoreDataDefaultStorage 用于整个应用程序生命周期

基本上,将coreDataStorage做成singleton会很好

关于ios - 滚动 UITableView 时,NSManagedObject 数组变为 nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44821248/

相关文章:

iphone - iPad Storyboard 如何为模态视图 Controller 提供所需的大小

ios - 如何在ios中知道设备连接到哪个网络主机

ios - 核心数据 - 如何在第二个 TableView Controller 上重新加载 NSSet(子对象)

ios - Json 数据未正确反射(reflect)在 tableView 中

ios - 如何使用 iPhone SDK 创建动态 UITableView 单元格

ios - iOS 8 上的 UICollectionView 自调整单元格将因 UIDynamic flowLayout 和重复调用 _updateVisibleCellsNow 而崩溃

ios - 在 iOS 或 Unity 中更改 Pushwoosh 的参数

ios - iOS 上的图像 IO 错误

iOS 8 Swift - 保存多个实体的数据

iphone - 如何设置表格 View 单元格适应标签?