当UITableView滚动时,NSManagedObject Array变为零

问题描述:

我的应用程序中有一个ViewController,我必须向用户显示设置,用户可以使用UISwitch打开或关闭设置。我必须将设置存储在本地数据库中,并基于应用程序中的用户显示数据。当UITableView滚动时,NSManagedObject Array变为零

我正在使用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) 

} 

} 

现在,initally的TableView中填充和所有阵列一旦工作正常,但当我滚动TableView时,所有数据都消失了。即使userSetting数组也是nill。我知道这与上下文有关,但无法弄清楚。任何帮助将不胜感激。

+0

你能提供SugarRecordManager类? –

+0

我编辑了问题并添加了SugarRecordManager.swift的代码 –

更改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所有应用程序生命

基本上,这将是很好使coreDataStoragesingleton

+0

首先,您不能对计算属性使用lazy。其次,即使我将coreDataStorage作为计算属性或使其成为单例,它也没有任何影响。 –

+0

使它不是一个计算属性,但使用初始化使其惰性属性,如我的示例中所示:'lazy var coreDataStorage:CoreDataDefaultStorage = {// init code here()' 其实您可以复制粘贴我的示例 –

+0

像魅力一样工作:D非常感谢你! –