滚动UITableView时,NSManagedObject Array变为nil

时间:2017-06-29 09:27:08

标签: 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数组也是nill。我知道它与上下文有关,但无法弄清楚是什么。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

像这样更改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

完成lazy之后 - 所有应用生活中只有一个CoreDataDefaultStorage

基本上,将coreDataStorage设为singleton

是件好事