Ein UITextField in einer UITableViewCell haben

178

Ich versuche das jetzt seit ein paar Tagen, und nachdem ich Tonnen von Nachrichten von Leuten gelesen habe, die das auch versuchen, kann ich immer noch nicht voll arbeiten UITextField in einigen von mirUITableViewCells , genau wie in diesem Beispiel:

Bildschirmfoto

Entweder funktioniert das Formular, aber der Text ist nicht sichtbar (obwohl ich seine Farbe auf Blau gesetzt habe). Die Tastatur wird auf dem Feld angezeigt, wenn ich darauf klicke, und ich konnte die Tastaturereignisse nicht korrekt implementieren. Ich habe es mit einer Reihe von Beispielen von Apple versucht (hauptsächlich UICatalog, wo es ein ähnliches Steuerelement gibt), aber es funktioniert immer noch nicht richtig.

Kann mir jemand helfen (und all den Leuten, die versuchen, diese Kontrolle zu realisieren) und eine einfache Implementierung von a UITextFieldin a posten UITableViewCell, die gut funktioniert?

Mathieu
quelle
Ich habe es funktionieren lassen. Aber nur für ein paar Felder. Stoßen Sie auf Probleme, wenn Sie mehrere Felder in der Tabelle haben oder nur eines?
PEZ
Ich brauche es nur für 2 Felder ... Es funktioniert momentan nicht, selbst wenn ich es für ein Feld versuche. Können Sie Ihre Implementierung veröffentlichen, die funktioniert? Vielen Dank, dass Sie PEZ!
Mathieu
Haben Sie das Beispiel EditableDetailView ausprobiert? Schreiben Sie die Frage auch hier, da Sie die Antworten noch nicht kommentieren können.
PEZ
Hallo Freunde, es ist möglich, mehrere Textfelder in der Tabellenansicht Stackoverflow.com/questions/19621732/…
Siva
2
Warum laufen alle Antworten im Web darauf hinaus CGRectMake(A_MAGIC_NUMBER, ANOTHER_MAGIC_NUMBER, YET_ANOTHER_HARDCODED_MAGIC_NUMBER, OH_HERES_ANOTHER_MYSTERIOUS_HARDCODED_MAGIC_NUMBER)? Woher kommen diese Zahlen?
Jameshfisher

Antworten:

222

Probieren Sie es aus. Funktioniert wie ein Zauber für mich (auf iPhone-Geräten). Ich habe diesen Code einmal für einen Anmeldebildschirm verwendet. Ich habe die Tabellenansicht so konfiguriert, dass sie zwei Abschnitte enthält. Sie können natürlich die Abschnittsbedingungen loswerden.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                   reuseIdentifier:kCellIdentifier] autorelease];
    cell.accessoryType = UITableViewCellAccessoryNone;

    if ([indexPath section] == 0) {
        UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
        playerTextField.adjustsFontSizeToFitWidth = YES;
        playerTextField.textColor = [UIColor blackColor];
        if ([indexPath row] == 0) {
            playerTextField.placeholder = @"[email protected]";
            playerTextField.keyboardType = UIKeyboardTypeEmailAddress;
            playerTextField.returnKeyType = UIReturnKeyNext;
        }
        else {
            playerTextField.placeholder = @"Required";
            playerTextField.keyboardType = UIKeyboardTypeDefault;
            playerTextField.returnKeyType = UIReturnKeyDone;
            playerTextField.secureTextEntry = YES;
        }       
        playerTextField.backgroundColor = [UIColor whiteColor];
        playerTextField.autocorrectionType = UITextAutocorrectionTypeNo; // no auto correction support
        playerTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; // no auto capitalization support
        playerTextField.textAlignment = UITextAlignmentLeft;
        playerTextField.tag = 0;
        //playerTextField.delegate = self;

        playerTextField.clearButtonMode = UITextFieldViewModeNever; // no clear 'x' button to the right
        [playerTextField setEnabled: YES];

        [cell.contentView addSubview:playerTextField];

        [playerTextField release];
    }
}
if ([indexPath section] == 0) { // Email & Password Section
    if ([indexPath row] == 0) { // Email
        cell.textLabel.text = @"Email";
    }
    else {
        cell.textLabel.text = @"Password";
    }
}
else { // Login button section
    cell.textLabel.text = @"Log in";
}
return cell;    
}

Ergebnis sieht so aus:

Login Formular

Leviathan
quelle
1
Ich versuche fast genau das Gleiche. Das Textfeld wird jedoch nur angezeigt, wenn die Zeile ausgewählt ist. Sonst wird gar nicht gezeichnet. Im obigen Beispiel bekomme ich nur das Etikett, dh Login. Dies ist mit iOS 4.2 auf dem iPad.
David
3
Eine noch bessere Frage: Wie gehen Sie mit dem Tastaturereignis next / return um?
Rob
3
@Rob: Sie können über Ereignisse auf die Daten zugreifen. Ich greife auf den Inhalt des UITextField im editDidEnd-Ereignis zu und richte ihn folgendermaßen ein : [_field addTarget:self action:@selector(editingEnded:) forControlEvents:UIControlEventEditingDidEnd];.
Corey Larson
7
Sie müssen das UITextField als Unteransicht der cell.contentView und nicht der Zelle selbst hinzufügen.
Mark Adams
6
Verwenden [cell addSubview:playerTextField];Sie diese Option, damit es mit iOS 5.0+ funktioniert.
Stunner
47

Hier ist eine Lösung, die unter iOS6 / 7/8/9 gut aussieht .

Update 10.06.2016: Dies funktioniert immer noch mit iOS 9.3.3

Vielen Dank für Ihre Unterstützung. Dies ist jetzt auf CocoaPods / Carthage / SPM unter https://github.com/fulldecent/FDTextFieldTableViewCell möglich

Grundsätzlich nehmen wir das Lager UITableViewCellStyleValue1und heften ein, UITextFieldwo das sein detailTextLabelsoll. Dies gibt uns eine automatische Platzierung für alle Szenarien: iOS6 / 7/8/9, iPhone / iPad, Bild / Kein Bild, Zubehör / Kein Zubehör, Hochformat / Querformat, 1x / 2x / 3x.

Geben Sie hier die Bildbeschreibung ein

Hinweis: Hierbei wird ein Storyboard mit einer Typzelle mit dem UITableViewCellStyleValue1Namen "Wort" verwendet.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    cell = [tableView dequeueReusableCellWithIdentifier:@"word"];
    cell.detailTextLabel.hidden = YES;
    [[cell viewWithTag:3] removeFromSuperview];
    textField = [[UITextField alloc] init];
    textField.tag = 3;
    textField.translatesAutoresizingMaskIntoConstraints = NO;
    [cell.contentView addSubview:textField];
    [cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:cell.textLabel attribute:NSLayoutAttributeTrailing multiplier:1 constant:8]];
    [cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:8]];
    [cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeBottom multiplier:1 constant:-8]];
    [cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:cell.detailTextLabel attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]];
    textField.textAlignment = NSTextAlignmentRight;
    textField.delegate = self;
    return cell;
}
William Entriken
quelle
2
Vielen Dank, dass Sie durch die Berge der Stimmen oben gescrollt haben, um diese Antwort zu sehen!
William Entriken
1
Mit UITableViewCellStyleRightDetailmeinst du UITableViewCellStyleValue1?
ma11hew28
1
Wirft leider nicht in der Lage, Einschränkungen gleichzeitig mit der Textwand in der Konsole zu erfüllen.
Dreamzor
Wenn cell.detailTextLabel auf "hidden" gesetzt ist, wird die rechte ("nachfolgende") Seite überhaupt nicht ausgerichtet.
Dreamzor
Dies stürzt mit Storyboard bei mir ab. Können Sie dies mit Storyboard verwenden?
Siriss
23

So habe ich das erreicht:

TextFormCell.h

#import <UIKit/UIKit.h>

#define CellTextFieldWidth 90.0
#define MarginBetweenControls 20.0

@interface TextFormCell : UITableViewCell {
 UITextField *textField;
}

@property (nonatomic, retain) UITextField *textField;

@end

TextFormCell.m

#import "TextFormCell.h"

@implementation TextFormCell

@synthesize textField;

- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
  // Adding the text field
  textField = [[UITextField alloc] initWithFrame:CGRectZero];
  textField.clearsOnBeginEditing = NO;
  textField.textAlignment = UITextAlignmentRight;
  textField.returnKeyType = UIReturnKeyDone;
  [self.contentView addSubview:textField];
    }
    return self;
}

- (void)dealloc {
 [textField release];
    [super dealloc];
}

#pragma mark -
#pragma mark Laying out subviews

- (void)layoutSubviews {
 CGRect rect = CGRectMake(self.contentView.bounds.size.width - 5.0, 
        12.0, 
        -CellTextFieldWidth, 
        25.0);
 [textField setFrame:rect];
 CGRect rect2 = CGRectMake(MarginBetweenControls,
       12.0,
         self.contentView.bounds.size.width - CellTextFieldWidth - MarginBetweenControls,
         25.0);
 UILabel *theTextLabel = (UILabel *)[self textLabel];
 [theTextLabel setFrame:rect2];
}

Es mag ein bisschen ausführlich erscheinen, aber es funktioniert!

Vergessen Sie nicht, den Delegierten einzustellen!

charlax
quelle
16

Probier diese. Es kann auch gescrollt werden, und Sie können die Zellen wiederverwenden, ohne zuvor hinzugefügte Unteransichten entfernen zu müssen.

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section{
    return 10;
}   

- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:@"Cell"];
    if( cell == nil)
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"] autorelease];   

    cell.textLabel.text = [[NSArray arrayWithObjects:@"First",@"Second",@"Third",@"Forth",@"Fifth",@"Sixth",@"Seventh",@"Eighth",@"Nineth",@"Tenth",nil] 
                           objectAtIndex:indexPath.row];

    if (indexPath.row % 2) {
        UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 21)];
        textField.placeholder = @"Enter Text";
        textField.text = [inputTexts objectAtIndex:indexPath.row/2];
        textField.tag = indexPath.row/2;
        textField.delegate = self;
        cell.accessoryView = textField;
        [textField release];
    } else
        cell.accessoryView = nil;

    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;        
}

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    [inputTexts replaceObjectAtIndex:textField.tag withObject:textField.text];
    return YES;
}

- (void)viewDidLoad {
    inputTexts = [[NSMutableArray alloc] initWithObjects:@"",@"",@"",@"",@"",nil];
    [super viewDidLoad];
}
Ali
quelle
Fehlt diesem Snippet irgendwo eine [inputTexts-Version]? Möglicherweise in der viewDidUnload-Methode, andernfalls liegt ein Speicherverlust vor.
Tim Potter
Alter Beitrag, aber ... Ich kann die Schriftart des Textfelds nicht verkleinern oder vergrößern. Ist es möglich?
Schultz9999
1
Kann jemand eine Swift-Snippet-Lösung anbieten?
Kaptain
14

Das sollte nicht schwierig sein. Fügen Sie beim Erstellen einer Zelle für Ihre Tabelle der Inhaltsansicht der Zelle ein UITextField-Objekt hinzu

UITextField *txtField = [[UITextField alloc] initWithFrame....]
...
[cell.contentView addSubview:txtField]

Legen Sie den Delegaten des UITextField als self fest (dh Ihren Viewcontroller). Geben Sie dem Textfeld ein Tag, damit Sie identifizieren können, welches Textfeld in Ihren Delegatenmethoden bearbeitet wurde. Die Tastatur sollte sich öffnen, wenn der Benutzer auf das Textfeld tippt. Ich habe es so zum Laufen gebracht. Ich hoffe es hilft.

lostInTransit
quelle
Diese Lösung gefällt mir zufällig. Wenn Sie Ihr Textfeld CGRectZerovorab als Rahmen einrichten, stellen Sie sicher, dass Sie den Rahmen Ihres Textfelds einrichten, bevor Sie ihn der Ansichtshierarchie hinzufügen. Das Abrufen der frameEigenschaft der Inhaltsansicht der Zelle ist für eine solche Aufgabe besonders hilfreich.
Ben Kreeger
11

Einzelheiten

  • Xcode 10.2 (10E125), Swift 5

Vollständiger Beispielcode

TextFieldInTableViewCell

import UIKit

protocol TextFieldInTableViewCellDelegate: class {
    func textField(editingDidBeginIn cell:TextFieldInTableViewCell)
    func textField(editingChangedInTextField newText: String, in cell: TextFieldInTableViewCell)
}

class TextFieldInTableViewCell: UITableViewCell {

    private(set) weak var textField: UITextField?
    private(set) weak var descriptionLabel: UILabel?

    weak var delegate: TextFieldInTableViewCellDelegate?

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupSubviews()
    }

    private func setupSubviews() {
        let stackView = UIStackView()
        stackView.distribution = .fill
        stackView.alignment = .leading
        stackView.spacing = 8
        contentView.addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.topAnchor.constraint(equalTo: topAnchor, constant: 6).isActive = true
        stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -6).isActive = true
        stackView.leftAnchor.constraint(equalTo: leftAnchor, constant: 16).isActive = true
        stackView.rightAnchor.constraint(equalTo: rightAnchor, constant: -16).isActive = true

        let label = UILabel()
        label.text = "Label"
        stackView.addArrangedSubview(label)
        descriptionLabel = label

        let textField = UITextField()
        textField.textAlignment = .left
        textField.placeholder = "enter text"
        textField.setContentHuggingPriority(.fittingSizeLevel, for: .horizontal)
        stackView.addArrangedSubview(textField)
        textField.addTarget(self, action: #selector(textFieldValueChanged(_:)), for: .editingChanged)
        textField.addTarget(self, action: #selector(editingDidBegin), for: .editingDidBegin)
        self.textField = textField

        stackView.layoutSubviews()
        selectionStyle = .none

        let gesture = UITapGestureRecognizer(target: self, action: #selector(didSelectCell))
        addGestureRecognizer(gesture)
    }

    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
}

extension TextFieldInTableViewCell {
    @objc func didSelectCell() { textField?.becomeFirstResponder() }
    @objc func editingDidBegin() { delegate?.textField(editingDidBeginIn: self) }
    @objc func textFieldValueChanged(_ sender: UITextField) {
        if let text = sender.text { delegate?.textField(editingChangedInTextField: text, in: self) }
    }
}

ViewController

import UIKit

class ViewController: UIViewController {

    private weak var tableView: UITableView?
    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
    }
}

extension ViewController {

    func setupTableView() {

        let tableView = UITableView(frame: .zero)
        tableView.register(TextFieldInTableViewCell.self, forCellReuseIdentifier: "TextFieldInTableViewCell")
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = UITableView.automaticDimension
        tableView.tableFooterView = UIView()
        self.tableView = tableView
        tableView.dataSource = self

        let gesture = UITapGestureRecognizer(target: tableView, action: #selector(UITextView.endEditing(_:)))
        tableView.addGestureRecognizer(gesture)
    }
}

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int { return 1 }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 2 }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TextFieldInTableViewCell") as! TextFieldInTableViewCell
        cell.delegate = self
        return cell
    }
}

extension ViewController: TextFieldInTableViewCellDelegate {

    func textField(editingDidBeginIn cell: TextFieldInTableViewCell) {
        if let indexPath = tableView?.indexPath(for: cell) {
            print("textfield selected in cell at \(indexPath)")
        }
    }

    func textField(editingChangedInTextField newText: String, in cell: TextFieldInTableViewCell) {
        if let indexPath = tableView?.indexPath(for: cell) {
            print("updated text in textfield in cell as \(indexPath), value = \"\(newText)\"")
        }
    }
}

Ergebnis

Geben Sie hier die Bildbeschreibung ein

Wassili Bodnarchuk
quelle
9

Ich hatte dies vermieden, indem ich eine Methode aufgerufen hatte, die [cell.contentView bringSubviewToFront:textField]jedes Mal ausgeführt werden sollte, wenn meine Zellen auftauchten, aber dann entdeckte ich diese relativ einfache Technik:

cell.accessoryView = textField;

Scheint nicht das gleiche Problem mit Hintergrundüberschreitung zu haben, und es richtet sich (etwas) von selbst aus. Außerdem wird das textLabel automatisch abgeschnitten, um ein Überlaufen (oder darunter) zu vermeiden, was praktisch ist.

Ben Mosher
quelle
Ich nehme das zurück. Mir gefällt das nicht. = (
Henley Chiu
10
Hisoka - was ist passiert?
Ben Mosher
4

Ich bin auf das gleiche Problem gestoßen. Es scheint, dass das Festlegen der cell.textlabel.textEigenschaft das UILabel an die Vorderseite der Inhaltsansicht der Zelle bringt. Fügen Sie die Textansicht nach dem Einstellen hinzu textLabel.textoder rufen Sie (falls dies nicht möglich ist) Folgendes auf :

[cell.contentView bringSubviewToFront:textField]
Arie Pieter Cammeraat
quelle
2

Ich hatte wirklich Probleme mit dieser Aufgabe auf dem iPad, da Textfelder in UITableView unsichtbar angezeigt wurden und die gesamte Zeile blau wird, wenn sie scharfgestellt wird.

Was am Ende für mich funktioniert hat, war die Technik, die unter "Die Technik für statische Zeileninhalte" im Programmierhandbuch für Tabellenansichten von Apple beschrieben wurde . Ich habe sowohl die Beschriftung als auch das Textfeld in eine UITableViewCell in der NIB für die Ansicht eingefügt und diese Zelle über einen Ausgang herausgezogen cellForRowAtIndexPath:. Der resultierende Code ist viel übersichtlicher als UICatalog.

Bryan
quelle
1

Hier ist, wie es gemacht wird. Ich glaube, der richtige Weg. Es funktioniert auf Ipad und Iphone, als ich es getestet habe. Wir müssen unsere eigenen customCells erstellen, indem wir eine uitableviewcell klassifizieren:

Starten Sie in interfaceBuilder ... erstellen Sie einen neuen UIViewcontroller, nennen Sie ihn customCell (melden Sie sich freiwillig für eine xib an, während Sie dort sind). Stellen Sie sicher, dass customCell eine Unterklasse von uitableviewcell ist

Löschen Sie jetzt alle Ansichten und erstellen Sie eine Ansicht, um die Größe einer einzelnen Zelle zu erhalten. Machen Sie diese Ansicht Unterklasse benutzerdefinierte Zelle. Erstellen Sie nun zwei weitere Ansichten (duplizieren Sie die erste).
Gehen Sie zu Ihrem Verbindungsinspektor und suchen Sie 2 IBOutlets, mit denen Sie jetzt eine Verbindung zu diesen Ansichten herstellen können.

-backgroundView -SelectedBackground

Verbinden Sie diese mit den letzten beiden Ansichten, die Sie gerade dupliziert haben, und sorgen Sie sich nicht um sie. Fügen Sie in der allerersten Ansicht, die customCell erweitert, Ihr Label und Ihr uitextfield ein. bin in customCell.h eingestiegen und verbinde dein Label und dein Textfeld. Stellen Sie die Höhe dieser Ansicht auf 75 (Höhe jeder Zelle) ein.

Stellen Sie in Ihrer customCell.m-Datei sicher, dass der Konstruktor ungefähr so ​​aussieht:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
    // Initialization code
    NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"CustomCell"       owner:self options:nil]; 
    self = [nibArray objectAtIndex:0];
}
return self;
}

Erstellen Sie nun einen UITableViewcontroller und verwenden Sie in dieser Methode die customCell-Klasse wie folgt:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
// lets use our customCell which has a label and textfield already installed for us

customCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    //cell = [[[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];


    NSArray *topLevelsObjects = [[NSBundle mainBundle] loadNibNamed:@"NewUserCustomCell" owner:nil options:nil];
    for (id currentObject in topLevelsObjects){
        if ([currentObject  isKindOfClass:[UITableViewCell class]]){
            cell = (customCell *) currentObject;
            break;
        }
    }

    NSUInteger row = [indexPath row];

switch (row) {
    case 0:
    {

        cell.titleLabel.text = @"First Name"; //label we made (uitextfield also available now)

        break;
    }


        }
return cell;

}}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

return 75.0;
}
j2emanue
quelle
0

Hier ist eine Drop-In-Unterklasse, für UITableViewCelldie das detailTextLabel durch ein bearbeitbares ersetzt wird UITextField(oder im Falle von UITableViewCellStyleDefaultdas textLabel ersetzt ). Dies hat den Vorteil, dass Sie alle bekannten UITableViewCellStyles, Zubehöransichten usw. wiederverwenden können. Jetzt können die Details bearbeitet werden!

@interface GSBEditableTableViewCell : UITableViewCell <UITextFieldDelegate>
@property UITextField *textField;
@end

@interface GSBEditableTableViewCell ()
@property UILabel *replace;
@end

@implementation GSBEditableTableViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        _replace = (style == UITableViewCellStyleDefault)? self.textLabel : self.detailTextLabel;
        _replace.hidden = YES;

        // Impersonate UILabel with an identical UITextField
        _textField = UITextField.new;
        [self.contentView addSubview:_textField];
        _textField.translatesAutoresizingMaskIntoConstraints = NO;
        [_textField.leftAnchor constraintEqualToAnchor:_replace.leftAnchor].active = YES;
        [_textField.rightAnchor constraintEqualToAnchor:_replace.rightAnchor].active = YES;
        [_textField.topAnchor constraintEqualToAnchor:_replace.topAnchor].active = YES;
        [_textField.bottomAnchor constraintEqualToAnchor:_replace.bottomAnchor].active = YES;
        _textField.font = _replace.font;
        _textField.textColor = _replace.textColor;
        _textField.textAlignment = _replace.textAlignment;

        // Dont want to intercept UITextFieldDelegate, so use UITextFieldTextDidChangeNotification instead
        [NSNotificationCenter.defaultCenter addObserver:self
                                           selector:@selector(textDidChange:)
                                               name:UITextFieldTextDidChangeNotification
                                             object:_textField];

        // Also need KVO because UITextFieldTextDidChangeNotification not fired when change programmatically
        [_textField addObserver:self forKeyPath:@"text" options:0 context:nil];
    }
    return self;
}

- (void)textDidChange:(NSNotification*)notification
{
    // Update (hidden) UILabel to ensure correct layout
    if (_textField.text.length) {
        _replace.text = _textField.text;
    } else if (_textField.placeholder.length) {
        _replace.text = _textField.placeholder;
    } else {
        _replace.text = @" "; // otherwise UILabel removed from cell (!?)
    }
    [self setNeedsLayout];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ((object == _textField) && [keyPath isEqualToString:@"text"]) [self textDidChange:nil];
}

- (void)dealloc
{
    [_textField removeObserver:self forKeyPath:@"text"];
}

@end

Einfach zu verwenden - erstellen Sie einfach Ihre Zelle wie zuvor, verwenden Sie jetzt cell.textField anstelle von cell.detailTextLabel (oder cell.textLabel im Fall von UITableViewCellStyleDefault). z.B

GSBEditableTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell) cell = [GSBEditableTableViewCell.alloc initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:@"Cell"];

cell.textLabel.text = @"Name";
cell.textField.text = _editablename;
cell.textField.delegate = self; // to pickup edits
...

Inspiriert von und verbessert von FDs Antwort

Tiritea
quelle
0

Für Next / Return-Ereignisse auf mehreren UITextfields in UITableViewCell in dieser Methode hatte ich UITextField im Storyboard übernommen.

@interface MyViewController () {
    NSInteger currentTxtRow;
}
@end
@property (strong, nonatomic) NSIndexPath   *currentIndex;//Current Selected Row

@implementation MyViewController


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL" forIndexPath:indexPath];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        UITextField *txtDetails = (UITextField *)[cell.contentView viewWithTag:100];
        txtDetails.delegate = self;

        txtDetails.placeholder = self.arrReciversDetails[indexPath.row];
        return cell;
}


#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {

    CGPoint point = [textField convertPoint:CGPointZero toView:self.tableView];
    self.currentIndex = [self.tableView indexPathForRowAtPoint:point];//Get Current UITableView row
    currentTxtRow = self.currentIndex.row;
    return YES;
}


- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    currentTxtRow += 1;
    self.currentIndex = [NSIndexPath indexPathForRow:currentTxtRow inSection:0];

    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.currentIndex];
    UITextField *currentTxtfield = (UITextField *)[cell.contentView viewWithTag:100];
    if (currentTxtRow < 3) {//Currently I have 3 Cells each cell have 1 UITextfield
        [currentTxtfield becomeFirstResponder];
    } else {
        [self.view endEditing:YES];
        [currentTxtfield resignFirstResponder];
    }

}  

Um den Text aus dem Textfeld zu holen,

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
      switch (self.currentIndex.row) {

            case 0:
                NSLog(@"%@",[NSString stringWithFormat:@"%@%@",textField.text,string]);//Take current word and previous text from textfield
                break;

            case 1:
                 NSLog(@"%@",[NSString stringWithFormat:@"%@%@",textField.text,string]);//Take current word and previous text from textfield
                break;

            case 2:
                 NSLog(@"%@",[NSString stringWithFormat:@"%@%@",textField.text,string]);//Take current word and previous text from textfield
                break;

            default:
                break;
        }
}
Mohammed Hussain
quelle