【问题标题】:Saving values to UserDefults from Textfield in TableView : Swift将值从 TableView 中的文本字段保存到 UserDefults:Swift
【发布时间】:2015-07-01 14:25:06
【问题描述】:

我正在尝试保存用户将输入到文本字段的表格视图中的值,问题是我不知道如何访问新值并替换数组中的字符串。

所以基本上应用程序会根据用户的需要显示字段,然后用户可以根据自己的喜好编辑这些值。更新文本字段后,值会再次存储在 userdefaults 中,以便下次打开 tableview 时,会出现更新值。

这就是tableviewcontroller此刻的样子:

//
//  Asset1TableViewController.swift
//  Net Calc 2
//
//  Created by Joshua Peterson on 30/06/2015.
//  Copyright © 2015 Peterson Productions. All rights reserved.
//

import UIKit

class Asset1TableViewController: UITableViewController {


var dataHolder: [NSString] = [NSString]()
var finalDataHolder: [NSString] = [NSString]()
var acountAmountHolder: [NSString] = [NSString]()
var finalAccountAmountHolder: [NSString] = [NSString]()

let defaults = NSUserDefaults.standardUserDefaults()
let key1 = "keySave1"
let key2 = "keySave2"


override func viewDidLoad() {
    super.viewDidLoad()

         dispatch_async(dispatch_get_main_queue(), { () -> Void in
        if let storedTitleValue : NSArray? = self.defaults.arrayForKey(self.key1) {

            if storedTitleValue == nil {
                self.dataHolder = [NSString]()
            } else {
            let readArray : [NSString] = storedTitleValue as! [NSString]


            for element in readArray {
                self.dataHolder.append(element as String)
                self.finalDataHolder.append(element as String)

            }
        }
    }

            if let storedAmountValue : NSArray? = self.defaults.arrayForKey(self.key2) {

                if storedAmountValue == nil {
                    self.acountAmountHolder = [NSString]()
                } else {
                    let readArray : [NSString] = storedAmountValue as! [NSString]


                    for element in readArray {
                        self.acountAmountHolder.append(element as String)
                        self.finalAccountAmountHolder.append(element as String)

                    }

                }
            }
         })
        }

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}


// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataHolder.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Account1Cell", forIndexPath: indexPath) as! Account1Cell

    cell.AccountLabel.text = dataHolder[indexPath.row] as String
    cell.AccountAmount.text = acountAmountHolder[indexPath.row] as String

    return cell
}


@IBAction func addButtonTapped(sender: AnyObject) {

    let newAccounTitle = "Account Name"
    let newAccountAmount = "R0.00"

    dataHolder.append(newAccounTitle)
    acountAmountHolder.append(newAccountAmount)

    tableView.reloadData()
    }

@IBAction func saveButtonTapped(sender: AnyObject) {

    // Save
    defaults.setObject(dataHolder as Array, forKey: key1)
    defaults.setObject(acountAmountHolder as Array, forKey: key2)

    defaults.synchronize()

    }

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true
}

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == UITableViewCellEditingStyle.Delete {
        dataHolder.removeAtIndex(indexPath.row)
        acountAmountHolder.removeAtIndex(indexPath.row)
        tableView.deleteRowsAtIndexPaths([indexPath],  withRowAnimation: UITableViewRowAnimation.Automatic)
    }
}


/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

}
*/

/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return NO if you do not want the item to be re-orderable.
    return true
}
*/
}

我尝试应用我在网站上找到的一些代码,但问题是我实际上无法连接到单元。

好的,经过一些研究,我向自定义单元类添加了一些函数,使其看起来像这样:

import UIKit

protocol TableViewCellDelegate {
  // Indicates that the edit process has begun for the given cell
  func cellDidBeginEditing(editingCell: Account1Cell)
  // Indicates that the edit process has committed for the given cell
  func cellDidEndEditing(editingCell: Account1Cell)
}

class Account1Cell: UITableViewCell,  UITextFieldDelegate {


@IBOutlet weak var AccountLabel: UITextField!
@IBOutlet weak var AccountAmount: UITextField!


var delegate: TableViewCellDelegate?


override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
    AccountLabel.delegate = self

}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
    // close the keyboard on Enter
    AccountLabel.resignFirstResponder()
    return false
}

func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
    // disable editing of completed to-do items
    return true
}

func textFieldDidEndEditing(textField: UITextField) {

    if AccountLabel != nil {
        let newAccountLabel = AccountLabel.text

        print(newAccountLabel) // Prints out the new edited text!!!!!!!!
    }
    if delegate != nil {
        delegate!.cellDidEndEditing(self)
    }
}

func textFieldDidBeginEditing(textField: UITextField) {
    if delegate != nil {
        delegate!.cellDidBeginEditing(self)
    }
 }



}

现在我需要做的是要么替换数组中索引处的值(我认为这将相当复杂),要么创建某种循环来读取所有值并简单地存储所有新的值到 UserDefaults。也许还有别的?

感谢任何帮助!

【问题讨论】:

  • 为什么在“@IBAction func saveButtonTapped”方法中有“func textFieldDidEndEditing(textField: UITextField!)”?
  • @the_pantless_coder 这是我从 * 上的另一篇文章中获取的 sn-p。我试图编辑它以适应我所拥有的 - 但没有成功!关于我能做什么的任何想法?
  • 尝试从“saveButtonTapped”中取出“func textFieldDidEndEditing(textField: UITextField!) {.....}”部分并将其粘贴为自己的函数。然后确保您的 textFields 连接了委托,以便它调用相关的委托函数。我晚上休息,明天回来检查。我会做的主要事情是解决问题,确保 textField 代表正在触发/连接。然后,当您可以确认它工作正常时。使用从 textField 委托中获得的值并将其保存到需要的地方。
  • @the_pantless_coder 非常感谢!今晚我会试着弄清楚,如果我取得任何进展,我会回复你,让你知道。
  • @the_pantless_coder 我一直在尝试组合,但仍然无法正确!我在 textdelegates 上找到了一些信息,但据我所知,它们将在自定义单元格类中定义。您将委托设置为 self.在那之后,它对我来说毫无希望!哈哈。我希望你能找到解决办法!?

标签: swift uitableview nsuserdefaults


【解决方案1】:

你应该在你的自定义单元格中有一个这样的协议,并在单元格中的文本字段被修改时调用它:

protocol TableViewCellToTVController{
    func cellCurrentlyEditing(editingCell: Account1Cell) -> Int
}
....
func textFieldShouldReturn(textField: UITextField) -> Bool {
    // close the keyboard on Enter

    let myrow: Int? = self.delegate_special?.cellCurrentlyEditing(self)
    println("cellCurrentlyEditing got called from delegate" , myrow)

    AccountLabel.resignFirstResponder()
    return false
}

在 tableviewcontroller 中实现这个函数来知道哪一行被选中:

func cellCurrentlyEditing(editingCell: Account1Cell) -> Int{
    var rowNum = 0
    let indexP: NSIndexPath = tableView.indexPathForCell(editingCell)!
    rowNum = indexP.row
    return rowNum
}

还让你的 tableviewcontroller 成为每个单元格的代表:

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Account1Cell", forIndexPath: indexPath) as! Account1Cell

        cell.AccountLabel.text = dataHolder[indexPath.row] as String
        cell.AccountAmount.text = acountAmountHolder[indexPath.row] as String
        cell.delegate_special = self;
        return cell
    }

【讨论】:

  • 无论如何我都不是专业人士,但如果我没记错的话 - 那是 Objective C 吗?关于如何快速实现代码的任何想法?
  • 我修复了一个错误并在我自己的表格视图中检查了它!在您的自定义 Account1Cell 中使用一个额外的协议(我称之为 TableViewCellToTVController)并使 Asset1TableViewController 成为该协议的委托。当您在自定义单元格中编辑完文本字段后触发该协议,您将使用 tableView.indexPathForCell(editingCell) 获得行号!