Home > database >  UIButton array is not saved locally. What's wrong?
UIButton array is not saved locally. What's wrong?

Time:10-14

I need to save on exit and then load an array of Buttons. Previously, I only used User Default for a small amount of data. But now I am storing an array of a lot of buttons.

import UIKit

class JobViewController: UIViewController, NSSecureCoding {
static var supportsSecureCoding: Bool{
    return true
}
................
var arrayOfButtons = [UIButton]()

func loadButtonFlat() {
  do{
      let data = try Data(contentsOf: getDocumentDirectory(), options: .alwaysMapped)
  let loadButtons = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [UIButton]
      if loadButtons != nil {
          print(loadButtons!.count)
          arrayOfButtons = loadButtons!
        }
      } catch {
          print("wow!")             
      }
    }

 func saveButtonsFlat() {
 let fileName = "buttonNumber"
 let fullPath = getDocumentDirectory().appendingPathComponent(fileName)
 do{
   let data = try NSKeyedArchiver.archivedData(withRootObject: arrayOfButtons,  requiringSecureCoding: false)
   try data.write(to: fullPath)
      print("!!!")
    } catch {
    print("Couldn't write file")
    }
 }
 func getDocumentDirectory() -> URL {
 let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
 return paths[0]
 }

@IBAction func goToBack(_ sender: Any) {
   saveButtonsFlat()
   self.dismiss(animated: true, completion: nil)
    }
 }

But the data is not saved. Of course they are not read. What's wrong?

CodePudding user response:

Your question has a bad premise: "I need to save on exit and then load an array of Buttons".

No. You should not try to save an array of buttons (UIButton objects).

Buttons are view objects. You should not save them to disk like data.

You either create your UI in code, or use a Storyboard/XIB file to define it.

What you SHOULD save is state information about your view objects. (Whether they are selected, or whatever is appropriate.)


Edit:

In fact, you should represent the state of your app in a model object, and save that to a file. you shouldn't store information about your view objects. If you save the app state to a model object, then when you read that model object, you'd apply information about the model to your views.


Your view controller would then load its views in their initial state, and then load saved state information and apply it to it's views.

As to why you can't do what you are trying to do, buttons and other view objects do conform to NSCoding, so they can be saved to an archive. That is how the XIB/storyboard mechanism saves and loads views. It won't work for saving and loading the runtime state of your view objects however.

CodePudding user response:

The code given at the beginning works well after fixing the error. The error is that there was a call to function getDocumentDirectory() in the loadButtonFlat() function, but function getDocumentDirectory() after exiting does not return the URL. Creating a variable var pathOnDevice to store the URL and further use it solved the problem. All buttons are loaded with all changes. Only the target indicator was not preserved. But this can be easily fixed with the following function:

func buttonsFlat() {
    for button in arrayOfButtons {
        button.addTarget(self, action: #selector(pressButton(sender:)), for: .touchUpInside)            
    }
}
  • Related