2017-06-29 1 views
0

J'ai un ViewController dans mon application où je dois montrer les paramètres à l'utilisateur et l'utilisateur peut activer ou désactiver les paramètres en utilisant UISwitch. Je dois stocker les paramètres dans la base de données locale et sur la base de ces données d'affichage à l'utilisateur dans l'application. J'utilise SugarRecord pour Core Data Management. Initialement, tous les paramètres sont activés.NSManagedObject Array devient nul lorsque UITableView est défilé

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) 

} 

} 

Maintenant, initally la TableView est peuplée et tous les tableaux fonctionnent très bien mais dès comme je fais défiler le TableView toutes les données ont disparu. Même le tableau userSetting est nul. Je sais que c'est quelque chose à voir avec le contexte, mais je n'arrive pas à comprendre quoi. Toute aide serait grandement appréciée.

+0

Pourriez-vous donner la classe SugarRecordManager? –

+0

J'ai édité la question et ajouté le code pour SugarRecordManager.swift –

Répondre

1

Changer votre func coreDataStorage() -> CoreDataDefaultStorage comme celui-ci

// 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 
    }() 

vous avez ce problème parce que vous êtes-init CoreDataDefaultStorage chaque fois que vous faites une demande.

Après avoir fait ce lazy - vous aurez un seul CoreDataDefaultStorage pour toute la vie de l'application

Fondamentalement, il sera bon de faire coreDataStorage comme singleton

+0

Tout d'abord, vous ne pouvez pas utiliser paresseux avec la propriété calculée. Deuxièmement, même si je rend une propriété calculée par coreDataStorage ou la rend singleton, elle n'a aucun effet. –

+0

Ne le rend pas une propriété calculée, mais rend la propriété paresseuse avec l'initialisation comme indiqué dans mon exemple: 'paresseux var coreDataStorage: CoreDataDefaultStorage = {// code init ici)()' En fait, vous pouvez simplement copier-coller mon exemple –

+0

Travaillé comme un charme: D Merci beaucoup! –