iPhone协议问题

时间:2011-04-10 21:39:04

标签: objective-c protocols subclass

我在这里缺少一些东西,我有一个类,EditableCell和协议,EditableCellDelegate,定义为处理表格单元格进行编辑。 (原始代码来自Paul Deitel的“iPhone for Programmers”)。

虽然我已将EditableCell的标头导入到我的文件ClientEditTVC.h中,但在ClientEditTVC.m中无法识别EditableCell的属性和方法。

以下是EditableCell.h和.m:

的预先编写的代码
#import <UIKit/UIKit.h>

@protocol EditableCellDelegate; // declare EditableCellDelegate Protocol

@interface EditableCell : UITableViewCell <UITextFieldDelegate>
{
   id <EditableCellDelegate> delegate; // this class's delegate
   UITextField *textField; // text field the user edits
   UILabel *label; // label on the left side of the cell
} // end instance variables declaration

// declare textField as a property
@property (nonatomic, retain) UITextField *textField;

// declare label as a property
@property (readonly, retain) UILabel *label;

//declare delegate as a property
@property (nonatomic, assign) id <EditableCellDelegate> delegate;

- (void)setLabelText:(NSString *)text; // set the text of label
- (void)clearText; // clear all the text out of textField
@end // end interface EditableCell

@protocol EditableCellDelegate // protocol for the delegate

// called when the user begins editing a cell
- (void)editableCellDidBeginEditing:(EditableCell *)cell;

// called when the user stops editing a cell
- (void)editableCellDidEndEditing:(EditableCell *)cell;

// called when the user touches the Done button on the keyboard
- (void)editableCellDidEndOnExit:(EditableCell *)cell;
@end // end protocol EditableCellDelegate

并且

#import "EditableCell.h"
@implementation EditableCell

@synthesize textField; // synthesize get and set methods for delegate
@synthesize label; // synthesize get and set methods for delegate
@synthesize delegate; // synthesize get and set methods for delegate

// initialize the cell
- (id)initWithStyle:(UITableViewCellStyle)style
    reuseIdentifier:(NSString *)reuseIdentifier
{
   // call the superclass
   if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]))
   {
      // create the label on the left side
      label = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 0, 20)];

      // create the text field to the right of the label
      textField =
         [[UITextField alloc] initWithFrame:CGRectMake(0, 10, 0, 20)];

      [textField setDelegate:self]; // set the delegate to this object

      // call textFieldDidEndOnExit when the Done key is touched
      [textField addTarget:self action:@selector(textFieldDidEndOnExit)
          forControlEvents:UIControlEventEditingDidEndOnExit];
      [self.contentView addSubview:label]; // add label to the cell
      [self.contentView addSubview:textField]; // add textField to cell
   } // end if

   return self; // return this Editable cell
} // end method initWithFrame:reuseIdentifier:

// method is called when the user touches the Done button on the keyboard
- (void)textFieldDidEndOnExit
{
   [textField resignFirstResponder]; // make the keyboard go away
   [delegate editableCellDidEndOnExit:self]; // call the delegate method
} // end method textFieldDidEndOnExit

// set the text of the label
- (void)setLabelText:(NSString *)text
{
   label.text = text; // update the text

   // get the size of the passed text with the current font
   CGSize size = [text sizeWithFont:label.font];
   CGRect labelFrame = label.frame; // get the frame of the label
   labelFrame.size.width = size.width; // size the frame to fit the text
   label.frame = labelFrame; // update the label with the new frame

   CGRect textFieldFrame = textField.frame; // get the frame of textField

   // move textField to 30 pts to the right of label
   textFieldFrame.origin.x = size.width + 30;

   // set the width to fill the remainder of the screen
   textFieldFrame.size.width =
   self.frame.size.width - textFieldFrame.origin.x;
   textField.frame = textFieldFrame; // assign the new frame
} // end method setLabelText:

// clear the text in textField
- (void)clearText
{
   textField.text = @""; // update textField with an empty string
} // end method clearText

// delegate method of UITextField, called when a text field begins editing
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
   [delegate editableCellDidBeginEditing:self]; // inform the delegate
} // end method textFieldDidBeginEditing:

// delegate method of UITextField, called when a text field ends editing
- (void)textFieldDidEndEditing:(UITextField *)textField
{
   [delegate editableCellDidEndEditing:self]; // inform the delegate
} // end method textFieldDidEndEditing:

// free EditableCell's memory
- (void)dealloc
{
  [textField release]; // release the textField UITextField
  [label release]; // release the label UILabel
  [super dealloc]; // call the superclass's dealloc method
} // end method dealloc
@end // end EditableCell class definition

以下是ClientEditTVC.h和.m

的相关代码
#import <UIKit/UIKit.h>
#import "EditableCell.h"


@interface ClientEditTVC : UITableViewController <UITableViewDataSource, EditableCellDelegate> {
    NSArray *fields;
    NSMutableDictionary *data;
    BOOL keyboardShown;
    EditableCell *currentCell;
}


@end

#import "ClientEditTVC.h"


@implementation ClientEditTVC

// stuff here

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

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

    // Configure the cell...
    // get the key for the given index path
    NSString *key =
    [fields objectAtIndex:indexPath.row + indexPath.section * 3];
    [cell setLabelText:key]; // update the cell text with the key

    // update the text in the text field with the value
    //cell.textField.text = [data valueForKey:key];


    return cell;
}

// more stuff here

@end

我在 [cell setLabelText:key]; 行收到警告,UITableViewCell可能无法响应'setTableText'。但是使用断点进行跟踪时,EditableCell中的setTextField代码正在执行。

cell.textField.text 的行(已注释掉)会产生错误,在'UITableViewCell'类型的对象上找不到属性'textField'

显然编译器没有看到我已经将UITableViewCell子类化了,我不知道为什么。对我来说,甚至更奇怪的是 setLableText 方法正在执行。我回到了Deitel提供的示例代码,这些问题都没有发生。我仔细查看了我的代码,并没有看到任何显着的差异。

我很欣赏有关我所忽视的建议。

3 个答案:

答案 0 :(得分:2)

你这样声明cell

UITableViewCell *cell;

所以它不是EditableCell。如果你这样声明:

EditableCell *cell;

它不会给你警告。它可能会警告您将UITableViewCell分配给cell,但您可以使用强制转换来“修复”,即

EditableCell *cell = (EditableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

此外,您需要调整功能的返回类型。这应该消除所有编译器警告。

答案 1 :(得分:1)

cell重新声明为EditableCell *而不是UITableViewCell *,并且该警告应该消失。

答案 2 :(得分:0)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

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

// Configure the cell...
// get the key for the given index path
    NSString *key = [fields objectAtIndex:indexPath.row + indexPath.section * 3];
    [cell setLabelText:key]; // update the cell text with the key

    if ([cell isKindOfClass:[EditableCell class]]) {
        EditableCell* editableCell = (EditableCell*)cell;
// update the text in the text field with the value
        editableCell.textField.text = [data valueForKey:key];
    }
    else {
        assert(0 && "is it alright that this instance is not an EditableCell?");
    }

    return cell;
}