2010-12-31 20 views
5

私はこれで1日か2日間頭を悩まされていました。私はアドレス帳の連絡先編集ページを模倣しようとしています(私は前に尋ねられたことを知っています)。編集可能なUITableView、セル内のUITextField、完了時にデータを保存する

詳細テキストラベルと同じ場所にあるUITextFieldを含むカスタムUITableViewCellがあります。編集ボタンを押すと、それらは非表示になり、正しい項目が表示されます。

私はUITextFieldDelegateを使用して、テキストフィールドに入力された情報を辞書に格納して、ユーザーが「完了」をクリックするとビュー配列とコアデータモデルにそれらを保存できます。

問題が発生しました: フィールドにテキストが入力されていれば、他のフィールド/セルは選択されずに完了します。変更された情報は無視され、辞書には格納されません。

私のコードでは、辞書の状態が最初に正しいまでセルを更新するという点が表示されないため、完了時にNSLogに辞書の内容を表示するだけです。

UITextFieldDelegateメソッドのすべてをログ出力で表示していますが、それぞれの動作がどのように流れているかをトラッキングするために実行されますが、この特定の問題について私の頭を包み込むのに役立ちませんでした。ここで

コードです:

EditableCellStyle2.h

@interface EditableCellStyle2 : UITableViewCell { 
    CGRect editRect; 
    UITextField *editField; 
} 

@property (nonatomic, readonly, retain) UITextField *editField; 

@end 

EditibleCellStyle2.m

#import "EditableCellStyle2.h" 

@implementation EditableCellStyle2 

@synthesize editField; 

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) { 
     // Initialization code. 
     editRect = CGRectMake(83, 12, self.contentView.bounds.size.width-83, 19); 

     editField = [[UITextField alloc] initWithFrame:editRect]; 
     editField.font = [UIFont boldSystemFontOfSize:15]; 
     editField.textAlignment = UITextAlignmentLeft; 
     editField.textColor = [UIColor blackColor]; 
     editField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight; 

     [self.contentView addSubview:editField]; 

     self.editField.enabled = NO; 
     self.editField.hidden = YES; 
    } 
    return self; 
} 

-(void)layoutSubviews 
{ 
    [super layoutSubviews]; // layouts the cell as UITableViewCellStyleValue2 would normally look like 

    editRect = CGRectMake(self.detailTextLabel.frame.origin.x, self.detailTextLabel.frame.origin.y, self.contentView.frame.size.width-self.detailTextLabel.frame.origin.x, self.detailTextLabel.frame.size.height); 
    editField.frame = editRect; 
} 

- (void)willTransitionToState:(UITableViewCellStateMask)state { 
    [super willTransitionToState:state]; 

    if (state & UITableViewCellStateEditingMask) { 
     self.detailTextLabel.hidden = YES; 
     self.editField.enabled = YES; 
     self.editField.hidden = NO; 
    } 
} 

- (void)didTransitionToState:(UITableViewCellStateMask)state { 
    [super didTransitionToState:state]; 

    if (!(state & UITableViewCellStateEditingMask)) { 
     self.editField.enabled = NO; 
     self.editField.hidden = YES; 
     self.detailTextLabel.hidden = NO; 
     self.editField.text = self.detailTextLabel.text; 
    } 
} 

- (void)dealloc { 
    [editField release]; 

    [super dealloc]; 
} 

@end 

DetailViewController.h

#import <UIKit/UIKit.h> 
#import "Entry.h" 
#import "Station.h" 
#import "EditableCellStyle2.h" 

@interface EntryDetailViewController : UITableViewController <UITextFieldDelegate> { 
    NSManagedObjectContext *currentContext; 
    Entry *passedEntry; 

    NSMutableArray *sectionsArray; 
    NSMutableDictionary *editModeDict; 
} 

@property (nonatomic, retain) NSManagedObjectContext *currentContext; 
@property (nonatomic, retain) Entry *passedEntry; 

-(void)editPressed; 
-(void)donePressed; 
-(void)cancelPressed; 

@end 

DetailViewController.m

-(void)editPressed 
{ 
    [self setEditing:YES animated:YES]; 
} 

-(void)donePressed 
{ 
    [self setEditing:NO animated:YES]; 

    NSLog(@"%@", editModeDict); 

    [self.tableView reloadData]; 
} 

-(void)cancelPressed 
{ 
    [self setEditing:NO animated:YES]; 
    [editModeDict removeAllObjects]; 
} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    // Return the number of sections. 
    return [sectionsArray count]; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    // Return the number of rows in the section. 
    NSArray *thisSection = [sectionsArray objectAtIndex:section]; 
    return [thisSection count]; 
} 


// Customize the appearance of table view cells. 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"Cell"; 

    EditableCellStyle2 *cell = (EditableCellStyle2 *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[EditableCellStyle2 alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    // Configure the cell... 

    NSArray *array = [sectionsArray objectAtIndex:indexPath.section]; 
    NSDictionary *dictionary = [array objectAtIndex:indexPath.row]; 

    id key = [[dictionary allKeys] objectAtIndex:0]; 

    cell.textLabel.text = [NSString stringWithFormat:@"%@", key]; 
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", [dictionary objectForKey:key]]; 

    // Set the edit field to match the detail label on creation so it doesn't look odd on first edit (slide down) 
    cell.editField.text = cell.detailTextLabel.text; 

    // Set the edit placeholder to match the key 
    cell.editField.placeholder = [NSString stringWithFormat:@"%@", key]; 

    // Set the tag for the edit field for the cell based on what cell is being created 
    // We will use this in the UITextField delegate to store the data in a dictionary 
    if ([cell.textLabel.text isEqualToString:@"Odometer"]) 
     cell.editField.tag = kOdometer; 
    else if ([cell.textLabel.text isEqualToString:@"Quantity"]) 
     cell.editField.tag = kQuantity; 
    else if ([cell.textLabel.text isEqualToString:@"PricePer"]) 
     cell.editField.tag = kPricePer; 
    else if ([cell.textLabel.text isEqualToString:@"PriceTotal"]) 
     cell.editField.tag = kPriceTotal; 
    else if ([cell.textLabel.text isEqualToString:@"Name"]) 
     cell.editField.tag = kStationName; 
    else if ([cell.textLabel.text isEqualToString:@"Address"]) 
     cell.editField.tag = kStationAddress; 
    else if ([cell.textLabel.text isEqualToString:@"City"]) 
     cell.editField.tag = kStationCity; 
    else if ([cell.textLabel.text isEqualToString:@"State"]) 
     cell.editField.tag = kStationState; 
    else if ([cell.textLabel.text isEqualToString:@"Zip"]) 
     cell.editField.tag = kStationZip; 
    else if ([cell.textLabel.text isEqualToString:@"Notes"]) 
     cell.editField.tag = kNotes; 

    // Set the delegate of the edit field to self 
    [cell.editField setDelegate:self]; 

    return cell; 
} 

- (void)setEditing:(BOOL)editing animated:(BOOL)animated { 
    [super setEditing:editing animated:animated]; 

    // When we go into editing mode, hide the back button, when we come out of editing mode, show it. 
    self.navigationItem.hidesBackButton = editing; 

    // Replace the back button with a cancel button that is only active while in edit mode 
    if (editing) { 
     UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelPressed)]; 
     self.navigationItem.leftBarButtonItem = cancelButton; 
     [cancelButton release]; 

     // clear the right bar button (edit) 
     self.navigationItem.rightBarButtonItem = nil; 

     // make the right bar button a done button 
     UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donePressed)]; 
     self.navigationItem.rightBarButtonItem = doneButton; 
     [doneButton release]; 
    } 
    else { 
     // clear out our cancel button 
     self.navigationItem.leftBarButtonItem = nil; 

     // clear out the right bar button (done) 
     self.navigationItem.rightBarButtonItem = nil; 

     // make the right bar button an edit button 
     UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editPressed)]; 
     self.navigationItem.rightBarButtonItem = editButton; 
     [editButton release]; 
    } 
} 

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return UITableViewCellEditingStyleNone; 
} 

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { 
    switch (textField.tag) { 
     case kOdometer: 
      [editModeDict setValue:textField.text forKey:@"Odometer"]; 
      break; 
     case kQuantity: 
      [editModeDict setValue:textField.text forKey:@"Quantity"]; 
      break; 
     case kPricePer: 
      [editModeDict setValue:textField.text forKey:@"PricePer"]; 
      break; 
     case kPriceTotal: 
      [editModeDict setValue:textField.text forKey:@"PriceTotal"]; 
      break; 
     case kStationName: 
      [editModeDict setValue:textField.text forKey:@"Name"]; 
      break; 
     case kStationAddress: 
      [editModeDict setValue:textField.text forKey:@"Address"]; 
      break; 
     case kStationCity: 
      [editModeDict setValue:textField.text forKey:@"City"]; 
      break; 
     case kStationState: 
      [editModeDict setValue:textField.text forKey:@"State"]; 
      break; 
     case kStationZip: 
      [editModeDict setValue:textField.text forKey:@"Zip"]; 
      break; 
     case kNotes: 
      [editModeDict setValue:textField.text forKey:@"Notes"]; 
      break; 
     default: 
      break; 
    } 

    return YES; 
} 

- (BOOL)textFieldShouldReturn:(UITextField *)textField {  
    [textField resignFirstResponder]; 
    return YES; 
} 


- (void)viewDidUnload { 
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand. 
    // For example: self.myOutlet = nil; 

    sectionsArray = nil; 
} 

- (void)dealloc { 
    [sectionsArray release]; 
    [editModeDict release]; 

    [currentContext release]; 
    [passedEntry release]; 

    [super dealloc]; 
} 

@end 
+0

どこに/ init editModeDictを割り当てますか? [editModeDict setValue:forKey:]が呼び出されていますか? NSLog()の出力は何ですか? – Felix

+0

ハ、その部分を残しました。 editModeDictは、viewDidLoadでallocとinitを取得します。間違いなく有効です。 – Chuck

+0

私はそれを働かせているようです。\t [self.view.window endEditing:YES]; donePressedメソッドの開始時に、編集されたがまだ最初のレスポンダのテキストフィールドのすべてが、その辞書を更新するend editメソッドを通過します。 – Chuck

答えて

0

これを試してみてください:

は方法

-(NSString *)getInEditTextFieldValue 
    { 
     if([myTextField isFirstResponder]) 
    { 
      // get the text of myTextField and set it to text. 
      return myTextField.text; 
    } 
    else 
    { 
      return nil; 
    } 
    } 

とあなたのdonePressedで作成します。

-(void)donePressed 
    { 
     NSString* myText = [self getInEditTextFieldValue]; 

     if(myText != nil) 
     { 
       // add myText to your dictionary 
     } 

     // save logic goes here... 

     // reload data for table view... 
    } 

を、私は、コードを試すことができないので、私は今でもMy Macではありませんよしかし、論理は挑戦的に私のために働いた。あなたのUITextFieldDelegateメソッドは、最初のレスポンダ以外のすべてのテキストフィールドの値を取得する必要があります。あなたがしなければならないことは、価値をチェックして取得するためのもう少しの作業です。

希望すると、これが役立ちます。

0

最初にUITableCellにテキストフィールドを正しく参照する必要があります。その後、完了ボタンメソッドをクリックすると、セルオブジェクトを取得することもできます。あなたのタイプオブジェクト(タイプUITextFieldの場合)のcontentViewに基づいて、&を得ることができます。そこからテキストを得ることができます。そうすれば、すべてのフィールドのデータベースを更新できます。

0

あなたのdoneButton()は、textFieldShouldEndEditingの前に呼び出されます。レスポンダを変更しようとすると、doneButtonをクリックした時点で有効になっているデータがデータを保存しないことがわかります。

関連する問題