从自定义可编辑 UITableViewCell 更新另一个字符串 - 在 swift 中通过引用传递?
Update another string from custom editable UITableViewCell - pass by reference in swift?
我从 UITableViewCell 创建了一个 class,它允许我编辑正确的详细信息文本。它使用 UITextField 作为 editableAccessoryView。下面的代码。
问题是我需要根据更改更新字符串。 IE。编辑完成后,字符串将更新为 textField.text 字符串。
在另一种语言中,我可能在 UITableViewCell subclass 中有一个字符串指针,我会用我想更改的字符串的指针更新它。但是,尽管我可以使用 inout
将指针传递给函数,但我无法弄清楚如何存储该指针。
有什么想法吗?
import UIKit
class EditableRightDetailTableViewCell: UITableViewCell, UITextFieldDelegate {
enum TextFieldType {
case Text
case Numeric
}
var type = TextFieldType.Text
let textField = UITextField(frame: CGRectMake(150, 7, 200, 30))
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
textField.borderStyle = UITextBorderStyle.RoundedRect
textField.textAlignment = NSTextAlignment.Right
textField.clearButtonMode = UITextFieldViewMode.Always
textField.delegate = self
self.editingAccessoryView = textField
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
override func setEditing(editing: Bool, animated: Bool) {
if !self.editing && editing == true {
self.detailTextLabel?.hidden = true
textField.text = self.detailTextLabel?.text
}
else if self.editing && editing == false {
self.detailTextLabel?.hidden = false
self.detailTextLabel?.text = textField.text
}
super.setEditing(editing, animated: animated)
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if type == TextFieldType.Numeric {
// We ignore any change that doesn't add characters to the text field.
// These changes are things like character deletions and cuts, as well
// as moving the insertion point.
//
// We still return true to allow the change to take place.
if count(string) == 0 {
return true
}
// Check to see if the text field's contents still fit the constraints
// with the new content added to it.
// If the contents still fit the constraints, allow the change
// by returning true; otherwise disallow the change by returning false.
let prospectiveText = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
return prospectiveText.isNumeric() && count(prospectiveText) <= 11
}
return true
}
}
不好的做法
您真的不想在 UITableViewCell
中保留指向对象的指针。首先,它们一般都被OS缓存起来,按需加载,总之,你不要企图拥有它们,当然要在里面保留指针。
良好做法
如果您的数据发生变化,请告诉 UITableView
重绘该单元格。您甚至可以重新绘制一个新的、不同的 UITableViewCell
。 (您甚至可以使用通知,进一步将您的视图与模型分离)
Swift
self.tableView.beginUpdates()
let indexPath = NSIndexPath(forRow: row, inSection: section)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
self.tableView.endUpdates()
Obj-C
[self.tableView beginUpdates];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:row inSection:section];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
他是我的实现如果有人感兴趣的话:
editable UITextViewCell。它应该在 IB 中设置为 Right Detail。当 table 视图设置为编辑时,将出现 UITextField。
import UIKit
class EditableRightDetailTableViewCell: UITableViewCell {
let textField = UITextField(frame: CGRectMake(150, 7, 200, 30))
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
textField.borderStyle = UITextBorderStyle.RoundedRect
textField.textAlignment = NSTextAlignment.Right
textField.clearButtonMode = UITextFieldViewMode.Always
self.editingAccessoryView = textField
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func initWithValues(label: String, detail: String) {
self.textLabel!.text = label
self.detailTextLabel?.text = detail
textField.text = detail
}
override func setEditing(editing: Bool, animated: Bool) {
if !self.editing && editing == true {
self.detailTextLabel?.hidden = true
textField.text = self.detailTextLabel?.text
}
else if self.editing && editing == false {
self.detailTextLabel?.hidden = false
self.detailTextLabel?.text = textField.text
textField.endEditing(true)
}
super.setEditing(editing, animated: false)
}
}
这是代表。请注意值已更改的变量。当值被更新时,它可以被分配给 运行 的闭包
import UIKit
class StringFieldDelegate: NSObject, UITextFieldDelegate {
var value: String
var valueChanged: Optional<() -> ()> = nil
func invokeValueChanged() {
self.valueChanged?()
}
init(value: String) {
self.value = value
}
func textFieldDidEndEditing(textField: UITextField) {
value = textField.text
invokeValueChanged()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
value = textField.text
invokeValueChanged()
return true
}
}
然后在ViewController
中我们创建像
这样的变量
var nameField: StringFieldDelegate!
并在 viewDidLoad
中初始化它们
在cell加载部分我们可以设置cell的delegate
cell.textField.delegate = nameField
现在,只要单元格完成编辑或按下 return,nameField 就会更新。 (对于即时更新,您必须实施 shouldChangeCharactersInRange
并更新值并在其中触发 invokeValueChanged
)
您还可以为值更改时分配一个闭包,例如
nameField.valueChanged = { println(nameField.value) }
委托可用于任何 UITextField。如果您实施 shouldChangeCharactersInRange
,您可以执行以下操作:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if count(string) == 0 {
return true
}
let prospectiveText = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
return prospectiveText.isNumeric()
}
这将使文本字段仅接受数字字符,使用扩展名
extension String {
// Returns true if the string represents a proper numeric value.
// This method uses the device's current locale setting to determine
// which decimal separator it will accept.
func isNumeric() -> Bool
{
let scanner = NSScanner(string: self)
// A newly-created scanner has no locale by default.
// We'll set our scanner's locale to the user's locale
// so that it recognizes the decimal separator that
// the user expects (for example, in North America,
// "." is the decimal separator, while in many parts
// of Europe, "," is used).
scanner.locale = NSLocale.currentLocale()
return scanner.scanDecimal(nil) && scanner.atEnd
}
}
我从 UITableViewCell 创建了一个 class,它允许我编辑正确的详细信息文本。它使用 UITextField 作为 editableAccessoryView。下面的代码。
问题是我需要根据更改更新字符串。 IE。编辑完成后,字符串将更新为 textField.text 字符串。
在另一种语言中,我可能在 UITableViewCell subclass 中有一个字符串指针,我会用我想更改的字符串的指针更新它。但是,尽管我可以使用 inout
将指针传递给函数,但我无法弄清楚如何存储该指针。
有什么想法吗?
import UIKit
class EditableRightDetailTableViewCell: UITableViewCell, UITextFieldDelegate {
enum TextFieldType {
case Text
case Numeric
}
var type = TextFieldType.Text
let textField = UITextField(frame: CGRectMake(150, 7, 200, 30))
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
textField.borderStyle = UITextBorderStyle.RoundedRect
textField.textAlignment = NSTextAlignment.Right
textField.clearButtonMode = UITextFieldViewMode.Always
textField.delegate = self
self.editingAccessoryView = textField
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
override func setEditing(editing: Bool, animated: Bool) {
if !self.editing && editing == true {
self.detailTextLabel?.hidden = true
textField.text = self.detailTextLabel?.text
}
else if self.editing && editing == false {
self.detailTextLabel?.hidden = false
self.detailTextLabel?.text = textField.text
}
super.setEditing(editing, animated: animated)
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if type == TextFieldType.Numeric {
// We ignore any change that doesn't add characters to the text field.
// These changes are things like character deletions and cuts, as well
// as moving the insertion point.
//
// We still return true to allow the change to take place.
if count(string) == 0 {
return true
}
// Check to see if the text field's contents still fit the constraints
// with the new content added to it.
// If the contents still fit the constraints, allow the change
// by returning true; otherwise disallow the change by returning false.
let prospectiveText = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
return prospectiveText.isNumeric() && count(prospectiveText) <= 11
}
return true
}
}
不好的做法
您真的不想在 UITableViewCell
中保留指向对象的指针。首先,它们一般都被OS缓存起来,按需加载,总之,你不要企图拥有它们,当然要在里面保留指针。
良好做法
如果您的数据发生变化,请告诉 UITableView
重绘该单元格。您甚至可以重新绘制一个新的、不同的 UITableViewCell
。 (您甚至可以使用通知,进一步将您的视图与模型分离)
Swift
self.tableView.beginUpdates()
let indexPath = NSIndexPath(forRow: row, inSection: section)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
self.tableView.endUpdates()
Obj-C
[self.tableView beginUpdates];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:row inSection:section];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
他是我的实现如果有人感兴趣的话:
editable UITextViewCell。它应该在 IB 中设置为 Right Detail。当 table 视图设置为编辑时,将出现 UITextField。
import UIKit
class EditableRightDetailTableViewCell: UITableViewCell {
let textField = UITextField(frame: CGRectMake(150, 7, 200, 30))
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
textField.borderStyle = UITextBorderStyle.RoundedRect
textField.textAlignment = NSTextAlignment.Right
textField.clearButtonMode = UITextFieldViewMode.Always
self.editingAccessoryView = textField
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func initWithValues(label: String, detail: String) {
self.textLabel!.text = label
self.detailTextLabel?.text = detail
textField.text = detail
}
override func setEditing(editing: Bool, animated: Bool) {
if !self.editing && editing == true {
self.detailTextLabel?.hidden = true
textField.text = self.detailTextLabel?.text
}
else if self.editing && editing == false {
self.detailTextLabel?.hidden = false
self.detailTextLabel?.text = textField.text
textField.endEditing(true)
}
super.setEditing(editing, animated: false)
}
}
这是代表。请注意值已更改的变量。当值被更新时,它可以被分配给 运行 的闭包
import UIKit
class StringFieldDelegate: NSObject, UITextFieldDelegate {
var value: String
var valueChanged: Optional<() -> ()> = nil
func invokeValueChanged() {
self.valueChanged?()
}
init(value: String) {
self.value = value
}
func textFieldDidEndEditing(textField: UITextField) {
value = textField.text
invokeValueChanged()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
value = textField.text
invokeValueChanged()
return true
}
}
然后在ViewController
中我们创建像
var nameField: StringFieldDelegate!
并在 viewDidLoad
在cell加载部分我们可以设置cell的delegate
cell.textField.delegate = nameField
现在,只要单元格完成编辑或按下 return,nameField 就会更新。 (对于即时更新,您必须实施 shouldChangeCharactersInRange
并更新值并在其中触发 invokeValueChanged
)
您还可以为值更改时分配一个闭包,例如
nameField.valueChanged = { println(nameField.value) }
委托可用于任何 UITextField。如果您实施 shouldChangeCharactersInRange
,您可以执行以下操作:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if count(string) == 0 {
return true
}
let prospectiveText = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
return prospectiveText.isNumeric()
}
这将使文本字段仅接受数字字符,使用扩展名
extension String {
// Returns true if the string represents a proper numeric value.
// This method uses the device's current locale setting to determine
// which decimal separator it will accept.
func isNumeric() -> Bool
{
let scanner = NSScanner(string: self)
// A newly-created scanner has no locale by default.
// We'll set our scanner's locale to the user's locale
// so that it recognizes the decimal separator that
// the user expects (for example, in North America,
// "." is the decimal separator, while in many parts
// of Europe, "," is used).
scanner.locale = NSLocale.currentLocale()
return scanner.scanDecimal(nil) && scanner.atEnd
}
}