TableView从NSUserDefaults清空

时间:2017-01-26 22:30:47

标签: ios swift uitableview nsuserdefaults nskeyedarchiver

在我的Swift iOS应用程序中,我有一个表视图,它应该显示来自mysql服务器的JSON对象,比如博客阅读器应用程序。但是现在表格视图显示为空,因为当用户单击每行上的按钮移动到另一个部分时,我尝试实现NSUserDefaults来保存。我基本上保存了用户点击的行的indexPath和部分,因此当用户下次打开应用程序时,它会记住它被移动到的位置。但是表格视图显示为空,我不知道如何解决它,希望有人在这里做。谢谢!

我在代码中收到警告 warning in code

ViewController.swift

// Outlets and Variables
@IBOutlet weak var myTableView: UITableView!

let searchController = UISearchController(searchResultsController: nil)

var jsonArray: NSMutableArray = []
var testArray = [Test]()
var followedArray = [Test]()
var filteredArray = [Test]()

// NSUserDefaults
var data: [Any]?
var items: [[Any]]?

override func viewDidLoad() {
    super.viewDidLoad()

    // Custom Cell
    self.myTableView.dataSource = self
    self.myTableView.delegate = self

    // Load Data from Server
    self.retrieveData()

    // NSUserDefaults
    self.fetchData()
}

// Number of Rows in Section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return self.items?[section].count ?? 0
}

// Number of Sections
func numberOfSections(in tableView: UITableView) -> Int {

    return self.items?.count ?? 0
}

// CellForRowAt indexPath
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let CellIdentifier = "Cell"
    var cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as! CustomCell

    if cell != cell {
        cell = CustomCell(style: UITableViewCellStyle.default, reuseIdentifier: CellIdentifier)
    }

    // Configuring the cell
    var testObject: Test

    if !(searchController.isActive && searchController.searchBar.text != "") {
        if indexPath.section == 0 {
            testObject = followedArray[indexPath.row] 
            cell.populateCell(testObject, isFollowed: true, indexPath: indexPath, parentView: self)
        }
        else if indexPath.section == 1 {
            testObject = testArray[indexPath.row] 
            cell.populateCell(testObject, isFollowed: false, indexPath: indexPath, parentView: self)
        }
    }
    else {
        testObject = filteredArray[indexPath.row] 
        cell.populateCell(testObject, isFollowed: false, indexPath: indexPath, parentView: self)
    }

    return cell
}

// Follow Button
@IBAction func followButtonClick(_ sender: UIButton!) {

    // Adding row to tag
    let buttonPosition = (sender as AnyObject).convert(CGPoint.zero, to: self.myTableView)
    if let indexPath = self.myTableView.indexPathForRow(at: buttonPosition) {

        let cell = self.myTableView.cellForRow(at: indexPath) as! CustomCell

        // Change Follow to Following
        (sender as UIButton).setImage(UIImage(named: "follow.png")!, for: .normal)

        // Checking wether to import from testArray or filteredArray to followedArray
        if !(searchController.isActive && searchController.searchBar.text != "") {

            self.myTableView.beginUpdates()

            // ----- Inserting Cell to followedArray -----
            followedArray.insert(testArray[indexPath.row], at: 0)
            myTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .fade)

            // ----- Removing Cell from testArray -----
            testArray.remove(at: indexPath.row)
            let rowToRemove = indexPath.row
            self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 1)], with: .fade)

            self.myTableView.endUpdates()

            // NSUserDefaults
            saveSorting() { "\($0)" }

            myTableView.reloadData()
        }
        else {

            self.myTableView.beginUpdates()

            // ----- Inserting Cell to followedArray -----
            let testObject: Test = filteredArray[indexPath.row]
            let indexOfObjectInArray = testArray.index(of: testObject)

            followedArray.insert(testObject, at: 0)

            // ----- Removing Cell from filteredArray -----
            filteredArray.remove(at: indexPath.row)
            testArray.remove(at: indexOfObjectInArray!)
            let rowToRemove = indexPath.row
            self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 0)], with: .fade)

            self.myTableView.endUpdates()

            // NSUserDefaults
            saveSorting() { "\($0)" }

            myTableView.reloadData()
        }
    }
}

// Retrieving Data from Server
func retrieveData() {

    let getDataURL = "http://exampleip.org/get.php"
    let url: NSURL = NSURL(string: getDataURL)!

    do {

        let data: Data = try Data(contentsOf: url as URL)
        jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

        // Looping through jsonArray
        for i in 0..<jsonArray.count {

            // Create Test Object
            let tID: String = (jsonArray[i] as AnyObject).object(forKey: "id") as! String
            let tName: String = (jsonArray[i] as AnyObject).object(forKey: "testName") as! String

            // Add Test Objects to Test Array
            testArray.append(Test(testName: tName, andTestID: tID))

        }
    }
    catch {
        print("Error: (Retrieving Data)")
    }

    myTableView.reloadData()
}

// NSUserDefaults
func fetchData() {

    // request from remote or local
    data = [testArray]

    // Update the items to first section has 0 elements,
    // and place all data in section 1
    items = [[], data ?? []]

    // apply ordering
    applySorting() { "\($0)" }

    // save ordering
    saveSorting() { "\($0)" }

    // refresh the table view
    myTableView.reloadData()
}

func applySorting(_ dataIdBlock: (Any) -> String) {

    // get all saved ordering
    guard let data = self.data else { return }
    let ordering = DataHandling.allSavedOrdering(data.count)

    var result: [[Any]] = [[], []]

    for (section, ordering) in ordering {
        guard section <= 1 else { continue } // make sure the section is 0 or 1
        let rows = data.filter({ obj -> Bool in
            return ordering.index(where: { $0.dataId == .some(dataIdBlock(obj)) }) != nil
        })
        result[section] = rows
    }

    self.items = result
}

func saveSorting(_ dataIdBlock: (Any) -> String) {

    guard let items = self.items else { return }

    for (section, rows) in items.enumerated() {
        for (row, item) in rows.enumerated() {
            let indexPath = IndexPath(row: row, section: section)
            let dataId = dataIdBlock(item)
            let ordering = DataHandling(dataId: dataId, indexPath: indexPath)
             // Warning is here
            ordering.save(defaults: indexPath.defaultsKey)
            }
        }
    }
}

extension IndexPath {
    var defaultsKey: String {
        return "data_handling_\(section)_\(row)"
    }
}

CustomCell.swift

class CustomCell: UITableViewCell {

func populateCell(_ testObject: Test, isFollowed: Bool, indexPath: IndexPath, parentView: Any) {

    if isFollowed {
        self.followedButton.tag = indexPath.row
        self.followedButton.addTarget(parentView, action: #selector(ViewController.followedButtonClick(_:)), for: .touchUpInside)

        self.followedButton.isHidden = false
        self.followButton.isHidden = true

    }
    else {
        self.followButton.tag = indexPath.row
        self.followButton.addTarget(parentView, action: #selector(ViewController.followButtonClick(_:)), for: .touchUpInside)

        self.followedButton.isHidden = true
        self.followButton.isHidden = false

    }
  }
}

DataHandling.swift 处理NSUserDefault

class DataHandling: NSObject, NSCoding {

var indexPath: IndexPath?
var dataId: String?

init(dataId: String, indexPath: IndexPath) {
    super.init()
    self.dataId = dataId
    self.indexPath = indexPath
}

required init(coder aDecoder: NSCoder) {

    if let dataId = aDecoder.decodeObject(forKey: "dataId") as? String {
        self.dataId = dataId
    }

    if let indexPath = aDecoder.decodeObject(forKey: "indexPath") as? IndexPath {
        self.indexPath = indexPath
    }

}

func encode(with aCoder: NSCoder) {
    aCoder.encode(dataId, forKey: "dataId")
    aCoder.encode(indexPath, forKey: "indexPath")
}

func save(defaults box: String) -> Bool {

    let defaults = UserDefaults.standard
    let savedData = NSKeyedArchiver.archivedData(withRootObject: self)
    defaults.set(savedData, forKey: box)
    return defaults.synchronize()

}

convenience init?(defaults box: String) {

    let defaults = UserDefaults.standard
    if let data = defaults.object(forKey: box) as? Data,
        let obj = NSKeyedUnarchiver.unarchiveObject(with: data) as? DataHandling,
        let dataId = obj.dataId,
        let indexPath = obj.indexPath {
        self.init(dataId: dataId, indexPath: indexPath)
    } else {
        return nil
    }

}

class func allSavedOrdering(_ maxRows: Int) -> [Int: [DataHandling]] {

    var result: [Int: [DataHandling]] = [:]
    for section in 0...1 {
        var rows: [DataHandling] = []
        for row in 0..<maxRows {
            let indexPath = IndexPath(row: row, section: section)
            if let ordering = DataHandling(defaults: indexPath.defaultsKey) {
                rows.append(ordering)
            }
            rows.sort(by: { $0.indexPath! < $1.indexPath! })
        }
        result[section] = rows
    }

    return result

  }

}

0 个答案:

没有答案