2017-06-29 6 views
0

私は、ユーザに設定を表示しなければならないアプリケーションにViewControllerを持っており、ユーザはUISwitchを使って設定をオンまたはオフにすることができます。私は、ローカルデータベースに設定を保存し、その表示データに基づいてアプリ内のユーザーにデータを送信する必要があります。UITableViewがスクロールされるとNSManagedObject Arrayがnilになる

コアデータ管理に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をスクロールすると、すべてのデータがなくなります。 userSetting配列でさえnillです。文脈とは関係がありますが、何が分からないのか分かります。どんな助けでも大歓迎です。

+0

singletonようにするためには良いでしょうか? –

+0

質問を編集してSugarRecordManager.swiftのコードを追加しました –

答えて

1
あなたは CoreDataDefaultStorageあなたがすべての要求を行うたびに、初期化し直すので、あなたがこの問題を持っているあなたの 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 
    }() 

を変更

あなたが作られた後、それlazy - あなたが

基本的にすべてのアプリの生活のために一つだけCoreDataDefaultStorageを持つことになり、それはあなたがSugarRecordManagerクラスを提供することができcoreDataStorage

+0

まず、計算されたプロパティでlazyを使用することはできません。次に、私がcoreDataStorageを計算されたプロパティにするか、それをシングルトンにしても、何の影響もありません。 –

+0

これは計算されたプロパティではありませんが、私の例に示すように、初期化を使ってlazyプロパティにしてください: 'lazy var coreDataStorage:CoreDataDefaultStorage = {// init code here)()' 実際には私の例 –

+0

魅力のように働いた:Dありがとう! –

関連する問題