前言
問(wèn)題背景:自定義cell中有一個(gè)UITextField類型的子控件。我們經(jīng)常要在tableView中拿到某個(gè)cell內(nèi)textField的文本內(nèi)容進(jìn)行一些操作。比如某些app的注冊(cè)界面就是以tableView的形式存在的,注冊(cè)時(shí)往往需要注冊(cè)姓名、昵稱、郵箱、地址、聯(lián)系方式等信息。然后點(diǎn)擊注冊(cè)或者提交,這些信息就會(huì)被提交到遠(yuǎn)程服務(wù)器。有人說(shuō),注冊(cè)頁(yè)面就那么固定的幾行cell,沒(méi)必要搞得那么復(fù)雜,完全可以用靜態(tài)cell實(shí)現(xiàn)。但還有一些情況,當(dāng)前頁(yè)面的tableView的cell的行數(shù)是不確定的(比如當(dāng)前頁(yè)面顯示多好行cell由上一個(gè)頁(yè)面決定或者由用戶決定),這種情況下不太適合使用靜態(tài)cell。也不能夠通過(guò)分支語(yǔ)句的方式一一枚舉出各個(gè)case。所以需要一中通用的動(dòng)態(tài)的方法。那么我們?cè)趺丛趖ableView中準(zhǔn)確的拿到每一行cell中textField的text呢?以下我將要分四個(gè)方法分別介紹并逐一介紹他們的優(yōu)缺點(diǎn),大家可以在開(kāi)發(fā)中根據(jù)實(shí)際情況有選擇的采用不同的方法。
如下圖,就是我之前開(kāi)發(fā)的一個(gè)app中用xib描述的一個(gè)cell,當(dāng)用戶點(diǎn)擊“注冊(cè)”或者“提交”button時(shí)候,我需要在控制器中拿到諸如“法人姓名”這一類的信息:
四個(gè)方法告訴你如何在tableView中拿到每一個(gè)cell中的textField.text
四個(gè)方法分別如下:
- 通過(guò)控制器的textField屬性來(lái)拿到每一個(gè)cell內(nèi)textField.text
- 通過(guò)系統(tǒng)默認(rèn)發(fā)送的通知來(lái)拿到每一個(gè)cell內(nèi)textField.text
- 通過(guò)自定義的通知來(lái)拿到每一個(gè)cell內(nèi)textField.text
- 通過(guò)block來(lái)拿到每一個(gè)cell內(nèi)textField.text
方法一(方法1請(qǐng)略過(guò))
1.cell的.h文件聲明一個(gè)IBOutlet的屬性,使其和xib描述的cell中的textField進(jìn)行關(guān)聯(lián)。
1.在tableViewController.m的類擴(kuò)展中聲明為每一個(gè)cell的textField都聲明一個(gè)UITextField類型的屬性,一一對(duì)應(yīng)。
2.在cellForRowAtIndexPath:數(shù)據(jù)源方法中給控制器的每個(gè)UITextField類型屬性賦值為cell.textField。
TableViewCell.h文件中的contentTextField引用xib中的textField:
#import <UIKit/UIKit.h>
@interface TableViewCell : UITableViewCell
/**
* cell的標(biāo)題
*/
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
/**
* cell的文本框
*/
@property (weak, nonatomic) IBOutlet UITextField *contentTextField;
@end
控制器中聲明UITextField類型的屬性。
@interface YQBInfoViewController ()
/**
* 標(biāo)題
*/
@property(nonatomic, strong) NSArray *titles;
/**
* 占位文字
*/
@property(nonatomic, strong) NSArray *placeHolders;
/**
* 姓名
*/
@property(nonatomic, weak) UITextField *nameTextField;
/**
* 年齡
*/
@property(nonatomic, weak) UITextField *ageTextField;
/**
* 地址
*/
@property(nonatomic, weak) UITextField *addressTextField;
@end
數(shù)據(jù)源方法cellForRowAtIndexPath:中給控制器的UITextField類型屬性賦值。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 在這里把每個(gè)cell的textField 賦值給 事先聲明好的UITextField類型的屬性
// 以后直接操作控制器的這些屬性就可以拿到每個(gè)textField的值
switch (indexPath.row) {
case 0:
// 姓名
self.nameTextField = cell.contentTextField;
break;
case 1:
// 年齡
self.ageTextField = cell.contentTextField;
break;
case 2:
// 地址
self.addressTextField = cell.contentTextField;
break;
default:
break;
}
return cell;
}
但是,這個(gè)方法還是有一些小問(wèn)題,因?yàn)閏ell被重用時(shí),存在存在的內(nèi)容錯(cuò)亂的現(xiàn)象。有人說(shuō),因?yàn)槲覀冊(cè)赾ellForRowAtIndexPath用一個(gè)UITextField屬性引用了cell的contentTextfield,我們可以在willDisplayCell:方法中對(duì)cell的contentTextField的內(nèi)容再次配置回來(lái)。而事實(shí)上,因?yàn)閏ell此時(shí)被重用了,所以,我們的tableViewController的那些分別指向每一行cell的UITextField的屬性此時(shí)也指向了其他行。所以,這個(gè)方法對(duì)于cell存在重用的情況是不適合的!
以下是方法一的demo地址
方法二(發(fā)送系統(tǒng)通知)
我們知道UITextField內(nèi)容改變時(shí)會(huì)發(fā)送通知。與UITextField相關(guān)的通知有三個(gè),如下:
UIKIT_EXTERN NSString *const UITextFieldTextDidBeginEditingNotification;
UIKIT_EXTERN NSString *const UITextFieldTextDidEndEditingNotification;
UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification;
1.我們只需要讓tableVeiw控制器注冊(cè)UITextFieldTextDidChangeNotification/UITextFieldTextDidEndEditingNotification通知。
2.在數(shù)據(jù)源方法cellForRowAtIndexPath:中對(duì)cell.textField.tag賦值為indexPath.row。這樣就可以區(qū)分每一行的textField。
3.然后在監(jiān)聽(tīng)到通知后調(diào)用的方法中,根據(jù)textField.tag拿到textField的內(nèi)容。
但是,問(wèn)題來(lái)了,如果tableView是grouped樣式的呢?
這樣就有可能存在兩個(gè)textField具有相同的tag!所以,以上提供的思路只適用于plained樣式的tableView。grouped樣式的tableView建議用下面的方法。
解決方法:自定義textField,給textField添加NSIndexPath類型的屬性indexPath
。我們這次給textField的indexPath賦值而不是tag。這樣就可以在監(jiān)聽(tīng)到通知后調(diào)用的方法中,根據(jù)indexPath來(lái)區(qū)分不同的section和row。
自定義UITextField
#import <UIKit/UIKit.h>
@interface CustomTextField : UITextField
/**
* indexPath屬性用于區(qū)分不同行cell
*/
@property (strong, nonatomic) NSIndexPath *indexPath;
@end
注意:
如果你自定義的cell是用xib描述的,不要忘記給cell的textField指定類型為你自定義的textField,此例中我自定義的是CustomTextField,如下圖:
控制器注冊(cè)通知
// 注冊(cè)通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentTextFieldDidEndEditing:) name:UITextFieldTextDidEndEditingNotification object:nil];
給自定義的textField的indexPath屬性賦值
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
AliyunSalesUnifiedEditCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// 如果不止一個(gè)section,那么傳遞indexPath.row有可能沖突
// cell.contentTextField.tag = indexPath.row;
// 所以傳遞indexPath,相當(dāng)于把section也傳遞給contentTextField
cell.contentTextField.indexPath = indexPath;
return cell;
}
監(jiān)聽(tīng)到通知后調(diào)用的方法
// 在這個(gè)方法中,我們就可以通過(guò)自定義textField的indexPath屬性區(qū)分不同行的cell,然后拿到textField.text
- (void)contentTextFieldDidEndEditing:(NSNotification *)noti {
CustomTextField *textField = noti.object;
if (textField.indexPath.section == 0) {
NSString *text = textField.text;
NSInteger row =textField.indexPath.row;
if (text && text.length) {
[self.contents replaceObjectAtIndex:row withObject:text];
}
} else if (textField.indexPath.section == 1) {
// 同上,請(qǐng)自行腦補(bǔ)
} else if (textField.indexPath.section == 2) {
// 同上,請(qǐng)自行腦補(bǔ)
} else {
// 同上,請(qǐng)自行腦補(bǔ)
}
}
切記:對(duì)于cell的重用,當(dāng)在willDisplayCell方法中重新配置cell時(shí)候,有if,就必須有else。因?yàn)橹捌聊簧铣霈F(xiàn)的cell離開(kāi)屏幕被緩存起來(lái)時(shí)候,cell上的內(nèi)容并沒(méi)有清空,當(dāng)cell被重用時(shí),系統(tǒng)并不會(huì)給我們把cell上之前配置的內(nèi)容清空掉,所以我們?cè)趀lse中對(duì)contentTextField內(nèi)容進(jìn)行重新配置或者清空(根據(jù)自己的業(yè)務(wù)場(chǎng)景而定)
以下是方法二的demo地址
方法三(發(fā)送自定義通知)
其實(shí)方法三和方法二很像,都需要給自定義的textField添加indexPath屬性,也需要發(fā)送通知,然后在通知中心對(duì)這個(gè)通知注冊(cè)監(jiān)聽(tīng)。區(qū)別在于,方法二發(fā)送的是系統(tǒng)自帶的通知UITextFieldTextDidEndEditingNotification
,而方法三將要發(fā)送自定義通知。
1>給CustomTextField添加indexPath屬性。
2>給自定義cell添加CustomTextField類型contentTextField屬性。
3>cell遵守UITextFieldDelegate協(xié)議,成為textField屬性的delegate。
4>cell實(shí)現(xiàn)協(xié)議方法-textFieldDidEndEditing:(UITextField *)textField
5>textFieldDidEndEditing:協(xié)議方法中發(fā)送一個(gè)自定義的通知,并且把textField.text通過(guò)userInfo字典發(fā)出去。
具體實(shí)現(xiàn)代碼:
給CustomTextField添加indexPath屬性
#import <UIKit/UIKit.h>
@interface CustomTextField : UITextField
/**
* indexPath屬性用于區(qū)分不同的cell
*/
@property (strong, nonatomic) NSIndexPath *indexPath;
@end
給自定義cell添加CustomTextField類型contentTextField屬性
#import <UIKit/UIKit.h>
@class CustomTextField;
@interface TableViewCell : UITableViewCell
/**
* cell的標(biāo)題
*/
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
/**
* cell的文本框
*/
@property (weak, nonatomic) IBOutlet CustomTextField *contentTextField;
@end
遵守協(xié)議,設(shè)置delegate,實(shí)現(xiàn)協(xié)議方法
#import "TableViewCell.h"
#import "CustomTextField.h"
@interface TableViewCell ()<UITextFieldDelegate>
@end
@implementation TableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.contentTextField.delegate = self;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 使contentTextField聚焦變成第一響應(yīng)者
[self.contentTextField becomeFirstResponder];
}
#pragma mark - UITextFieldDelegate
- (void)textFieldDidEndEditing:(UITextField *)textField
{
NSDictionary *userInfo = @{
@"textFieldText":self.contentTextField.text
};
[[NSNotificationCenter defaultCenter] postNotificationName:@"CustomTextFieldDidEndEditingNotification" object:self.contentTextField userInfo:userInfo];
}
6>控制器注冊(cè)并監(jiān)聽(tīng)該通知
7>在監(jiān)聽(tīng)到通知的方法中通過(guò)userInfo拿到textField的text屬性
8>- (void)viewWillDisappear:(BOOL)animated方法中移除監(jiān)聽(tīng)
9>完畢
注冊(cè)通知
// 如果不能保證控制器的dealloc方法肯定會(huì)被調(diào)用,不要在viewDidLoad方法中注冊(cè)通知。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// 注意:此處監(jiān)聽(tīng)的通知是:UITextFieldTextDidEndEditingNotification,textField結(jié)束編輯發(fā)送的通知,textField結(jié)束編輯時(shí)才會(huì)發(fā)送這個(gè)通知。
// 想實(shí)時(shí)監(jiān)聽(tīng)textField的內(nèi)容的變化,你也可以注冊(cè)這個(gè)通知:UITextFieldTextDidChangeNotification,textField值改變就會(huì)發(fā)送的通知。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cellTextFieldDidEndEditing:) name:@"CustomTextFieldDidEndEditingNotification" object:nil];
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentTextFieldDidEndEditing:) name:UITextFieldTextDidEndEditingNotification object:nil];
}
移除通知
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// 在這個(gè)方法里移除通知,因?yàn)椋? // 防止控制器被強(qiáng)引用導(dǎo)致-dealloc方法沒(méi)有調(diào)用
// 其他界面也有textField,其他界面的textField也會(huì)發(fā)送同樣的通知,導(dǎo)致頻繁的調(diào)用監(jiān)聽(tīng)到通知的方法,而這些通知是這個(gè)界面不需要的,所以在視圖將要消失的時(shí)候移除通知 同樣,在視圖將要顯示的時(shí)候注冊(cè)通知
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"CustomTextFieldDidEndEditingNotification" object:nil];
}
接收到通知回調(diào)方法
// 接收到注冊(cè)監(jiān)聽(tīng)的通知后調(diào)用
- (void)cellTextFieldDidEndEditing:(NSNotification *)noti {
CustomTextField *textField = noti.object;
if (!textField.indexPath) {
return;
}
NSString *userInfoValue = [noti.userInfo objectForKey:@"textFieldText"];
NSLog(@"text:%@,userInfoValue:%@",textField.text,userInfoValue);
// 如果涉及到多個(gè)section,可以使用二維數(shù)組,此處不再贅述
if (textField.indexPath.section == 0) {
[self.contents replaceObjectAtIndex:textField.indexPath.row withObject:userInfoValue];
} else if (textField.indexPath.section == 1) {
// 同上,請(qǐng)自行腦補(bǔ)
} else if (textField.indexPath.section == 2) {
// 同上,請(qǐng)自行腦補(bǔ)
} else {
// 同上,請(qǐng)自行腦補(bǔ)
}
}
切記:對(duì)于cell的重用,當(dāng)在willDisplayCell方法中重新配置cell時(shí)候,有if,就必須有else。因?yàn)橹捌聊簧铣霈F(xiàn)的cell離開(kāi)屏幕被緩存起來(lái)時(shí)候,cell上的內(nèi)容并沒(méi)有清空,當(dāng)cell被重用時(shí),系統(tǒng)并不會(huì)給我們把cell上之前配置的內(nèi)容清空掉,所以我們?cè)趀lse中對(duì)contentTextField內(nèi)容進(jìn)行重新配置或者清空(根據(jù)自己的業(yè)務(wù)場(chǎng)景而定)
以下是方法三的demo地址
方法三相對(duì)于方法二的好處在于:
方法三發(fā)送的是自定義通知,而方法二發(fā)送的是系統(tǒng)自帶的通知。
因?yàn)轫?xiàng)目開(kāi)發(fā)中,受項(xiàng)目復(fù)雜度影響,難免會(huì)出現(xiàn)不同的控制器界面都會(huì)有UITextField類型(或者其子類型)的對(duì)象而沒(méi)有釋放,當(dāng)textField開(kāi)始編輯、內(nèi)容發(fā)生改變、結(jié)束編輯時(shí),都會(huì)發(fā)送相同的通知。此時(shí)如果我們采用監(jiān)聽(tīng)系統(tǒng)自帶的通知的方法,就有可能監(jiān)聽(tīng)到我們不需要的改變從而影響了業(yè)務(wù)數(shù)據(jù)。
舉個(gè)例子:A和B控制器都是UITableViewController類型的對(duì)象,A、B控制器界面上都有UITextField類型(或者其子類型)的子控件。并且A、B控制器都注冊(cè)了系統(tǒng)自帶的UITextField的通知UITextFieldTextDidChangeNotification,且監(jiān)聽(tīng)到通知后都會(huì)調(diào)用各自的contentTextFieldTextDidChange:方法。當(dāng)A控制器pushB控制器后,我們?cè)贐控制器界面上的TextField編輯內(nèi)容,A控制器此時(shí)也監(jiān)聽(tīng)了該通知,所以,A控制器上的contentTextFieldTextDidChange:方法也會(huì)被調(diào)用。這是我們不想得到的,所以,采用自定義通知的方法可以避免這一問(wèn)題。
當(dāng)然,我們也可以在viewWillAppear:方法中注冊(cè)通知,然后在viewWillDisAppear:方法中移除通知,這樣同樣可以避免這一為題。
另外,值得提醒的是,如果我們不能保證控制器被pop時(shí)肯定會(huì)調(diào)用dealloc方法,那么建議在控制器的viewWillDisAppear:方法中移除通知,而非dealloc方法中移除。
否則,用戶反復(fù)push、pop控制器時(shí),控制器可能會(huì)注冊(cè)多份相同的通知。
方法四(使用block)
1>給cell添加一個(gè)block屬性,該block屬性帶有一個(gè)NSString *類型的參數(shù)。
2>給cell的textField添加target,觸發(fā)方法的事件是UIControlEventEditingChanged
3>textField觸發(fā)的方法中調(diào)用cell的這個(gè)block屬性,并把contentTextField.text作為block的參數(shù)傳進(jìn)去
4>數(shù)據(jù)源方法cellForRowAtIndexPath:中對(duì)cell的block屬性賦值(也就是拿到cell.contentTextField.text)
5>數(shù)據(jù)源方法willDisplayCell:中對(duì)cell重新配置。
給cell添加一個(gè)block屬性
#import <UIKit/UIKit.h>
@interface TableViewCell : UITableViewCell
/**
* block 參數(shù)為textField.text
*/
@property (copy, nonatomic) void(^block)(NSString *);
/**
* cell的標(biāo)題
*/
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
/**
* cell的文本框
*/
@property (weak, nonatomic) IBOutlet UITextField *contentTextField;
@end
給textField addTarget
在事件觸發(fā)方法中調(diào)用block并傳遞參數(shù)
#import "TableViewCell.h"
@interface TableViewCell ()
@end
@implementation TableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self.contentTextField addTarget:self action:@selector(textfieldTextDidChange:) forControlEvents:UIControlEventEditingChanged];
// 注意:不是 UIControlEventValueChanged
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self.contentTextField becomeFirstResponder];
}
#pragma mark - private method
- (void)textfieldTextDidChange:(UITextField *)textField
{
self.block(self.contentTextField.text);
}
@end
在cellforRowAtIndexPath:方法中為每個(gè)cell的block賦值
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *customCell = [tableView dequeueReusableCellWithIdentifier:ID];
__weak typeof(self) weakSelf = self;
if (indexPath.section == 0) {
customCell.block = ^(NSString * text) {
// 更新數(shù)據(jù)源
[weakSelf.contents replaceObjectAtIndex:indexPath.row withObject:text];
};
} else if (indexPath.section == 1) {
// 同上,請(qǐng)自行腦補(bǔ)
} else {
// 同上,請(qǐng)自行腦補(bǔ)
}
return customCell;
}
在willDisplayCell:方法中對(duì)cell進(jìn)行配置:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *customCell = (TableViewCell *)cell;
customCell.titleLabel.text = self.titles[indexPath.row];
customCell.contentTextField.placeholder = self.placeHolders[indexPath.row];
if (indexPath.section == 0) {
customCell.contentTextField.text = [self.contents objectAtIndex:indexPath.row];
// 必須有else!
} else {
// 切記:對(duì)于cell的重用,有if,就必須有else。因?yàn)橹捌聊簧铣霈F(xiàn)的cell離開(kāi)屏幕被緩存起來(lái)時(shí)候,cell上的內(nèi)容并沒(méi)有清空,當(dāng)cell被重用時(shí),系統(tǒng)并不會(huì)給我們把cell上之前配置的內(nèi)容清空掉,所以我們?cè)趀lse中對(duì)contentTextField內(nèi)容進(jìn)行重新配置或者清空(根據(jù)自己的業(yè)務(wù)場(chǎng)景而定)
customCell.contentTextField.text = [NSString stringWithFormat:@"第%ld組,第%ld行",indexPath.section,indexPath.row];
}
}
切記:對(duì)于cell的重用,當(dāng)在willDisplayCell方法中重新配置cell時(shí)候,有if,就必須有else。因?yàn)橹捌聊簧铣霈F(xiàn)的cell離開(kāi)屏幕被緩存起來(lái)時(shí)候,cell上的內(nèi)容并沒(méi)有清空,當(dāng)cell被重用時(shí),系統(tǒng)并不會(huì)給我們把cell上之前配置的內(nèi)容清空掉,所以我們?cè)趀lse中對(duì)contentTextField內(nèi)容進(jìn)行重新配置或者清空(根據(jù)自己的業(yè)務(wù)場(chǎng)景而定)
以下是方法四的demo地址
方法四相對(duì)于方法二和方法三的好處在于:方法四沒(méi)有采用通知的方式來(lái)獲取contentTextField.text,而是采用靈活的block。并且方法四也無(wú)需自定義textField。
方法五(使用delegate實(shí)現(xiàn))
方法五和方法四很像,只不過(guò)方法五采用了delegate方式,更好的做到了解耦。
0>和方法二、方法三一樣,cell的textField屬性都需要使用自定義類型,因?yàn)槲覀冃枰otextField綁定indexPath屬性。
1>給cell制定一份協(xié)議,協(xié)議中有一個(gè)方法,帶有兩個(gè)參數(shù),一個(gè)是textField的text,另一個(gè)是indexPath。同時(shí)給cell添加一個(gè)delegate屬性。
2>給cell的textField添加target,觸發(fā)方法的事件是UIControlEventEditingChanged
3>textField觸發(fā)的方法中調(diào)用cell的協(xié)議方法,并把contentTextField.indexPath作為協(xié)議方法的參數(shù)傳進(jìn)去
4>數(shù)據(jù)源方法cellForRowAtIndexPath:中對(duì)cell的indexPath賦值為當(dāng)前的indexPath。對(duì)cell的delegate賦值為當(dāng)前controller
5>控制器實(shí)現(xiàn)cell的協(xié)議方法,在協(xié)議方法里可以拿到textField的文本。
6>在tableView:willDisplayCell:forRowAtIndexPath:方法內(nèi)刷新tableView。
#import <UIKit/UIKit.h>
@class CustomTextField;
@protocol CustomCellCellDelegate <NSObject>
@required
// cell 的contentTextField的文本發(fā)生改變時(shí)調(diào)用
- (void)contentDidChanged:(NSString *)text forIndexPath:(NSIndexPath *)indexPath;
@end
@interface TableViewCell : UITableViewCell
/**
* cell的標(biāo)題
*/
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
/**
* cell的文本框
*/
@property (weak, nonatomic) IBOutlet CustomTextField *contentTextField;
/**
* delegate
*/
@property (weak, nonatomic) id<CustomCellCellDelegate> delegate;
cell.m文件
- (void)awakeFromNib {
[super awakeFromNib];
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self.contentTextField addTarget:self action:@selector(contentDidChanged:) forControlEvents:UIControlEventEditingChanged];
}
- (void)contentDidChanged:(id)sender {
// 調(diào)用代理方法,告訴代理,哪一行的文本發(fā)生了改變
if (self.delegate && [self.delegate respondsToSelector:@selector(contentDidChanged:forIndexPath:)]) {
[self.delegate contentDidChanged:self.contentTextField.text forIndexPath:self.contentTextField.indexPath];
}
}
controller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
cell.contentTextField.indexPath = indexPath;
cell.delegate = self;
return cell;
}
// cell的代理方法中拿到text進(jìn)行保存
- (void)contentDidChanged:(NSString *)text forIndexPath:(NSIndexPath *)indexPath {
[self.contents replaceObjectAtIndex:indexPath.row withObject:text];
}
// 更新UI
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
TableViewCell *customCell = (TableViewCell *)cell;
customCell.titleLabel.text = self.titles[indexPath.row];
customCell.contentTextField.placeholder = self.placeHolders[indexPath.row];
customCell.contentTextField.text = self.contents[indexPath.row];
}
以下是方法五的demo地址
文/VV木公子(簡(jiǎn)書作者)
PS:如非特別說(shuō)明,所有文章均為原創(chuàng)作品,著作權(quán)歸作者所有,轉(zhuǎn)載轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),并注明出處,所有打賞均歸本人所有!
如果您是iOS開(kāi)發(fā)者,請(qǐng)關(guān)注本人,或者對(duì)本篇文章感興趣,請(qǐng)點(diǎn)擊喜歡,后續(xù)會(huì)更新更多相關(guān)文章!敬請(qǐng)期待!
如果有技術(shù)問(wèn)題,歡迎加入QQ群進(jìn)行交流,群聊號(hào)碼:194236752。