简体   繁体   English

Objective-C协议作为变量(实例)

[英]objective-c protocol as variable (instance)

I'm new to objective-c and it is still unclear to me of the following are possible 我是Objective-c的新手,我仍然不清楚以下情况是否可能

  1. Is it possible to instantiate a protocol? 可以实例化协议吗?
  2. If it is possible to instantiate a protocol, how do I implement the required methods? 如果可以实例化协议,如何实现所需的方法?

EDITS: 编辑:

This is how I used and implemented my protocol: 这就是我使用和实现协议的方式:

@protocol myProtocol <NSObject>

@required
    - (void)doneAction:(NSDate *)dateSelected;
@end

@interface datePickerView : UIView

@property (strong, nonatomic) UIDatePicker *datePicker;
@property (strong, nonatomic) UIButton *doneButton;
@property (strong, nonatomic) NSObject<myProtocol> *datePickerProtocol;

- (id)initWithDetails:(UIDatePicker *)datePick doneBtn:(UIButton *)doneBtn;
- (void)show;
@end

Here is the implementation of "datePickerView" 这是“ datePickerView”的实现

@synthesize datePicker = _datePicker;
@synthesize doneButton = _doneButton;
@synthesize datePickerProtocol = _datePickerProtocol;

- (id)initWithDetails:(UIDatePicker *)datePick doneBtn:(UIButton *)doneBtn
{
    _datePicker = datePick;
    _doneButton = doneBtn;
    [_doneButton addTarget:self action:@selector(doneButtonClicked) forControlEvents:UIControlEventTouchUpInside];

    [self addSubview:_datePicker];
    [self addSubview:_doneButton];
}

- (void)doneButtonClicked
{
    /** Code to hide the view goes here **/
    if (_datePickerProtocol != nil)
        [_datePickerProtocol doneAction:_datePicker.date];
}

Here is the class that is using the "datePickerView" 这是使用“ datePickerView”的类

/** .h file **/
@interface myController : UITableViewController <myProtocol>
{
}

@property (strong, nonatomic) IBOutlet UIDatePicker *datePicker;
@property (strong, nonatomic) IBOutlet UIButton *datePickDone;
/** More definitions goes here **/

/** .m file **/
@synthesize datePicker = _datePicker;
@synthesize datePickDone = _datePickDone;
/** More code goes here **/

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *selectedCell = [self.tableView cellForRowAtIndexPath:indexPath];
    if ((![selectedCell.reuseIdentifier isEqualToString:@"dateAppliedCellIdentifier"]) &&
        (![selectedCell.reuseIdentifier isEqualToString:@"closingDateCellIdentifier"]))
        return;

    if (_datePicker.superview == nil)
    {
        datePickerView = [[datePickerView alloc] initWithDetails:_datePicker     doneBtn:_datePickDone];

        [self.view.window addSubview: datePickerView];
    }
    /**
        THIS IS WHERE I WANT TO PASS AN INSTANCE OF THE PROTOCOL (BUT AS ADVISED,
        IT IS NOT POSSIBLE) DEPENDING ON WHICH CELL WAS TAPPED. THE REASON I WANT
        PASS AN INSTANCE OF THE PROTOCOL INSTEAD OF "SELF" IS BECAUSE I WANT
        TO AVOID DOING MULTIPLE "IF" STATEMENTS INSIDE
        "(void)doneAction:(NSDate *)dateSelected" METHOD. I WOULD LIKE TO DO THE IFs
        HERE AND PASS THE CORRECT INSTANCE OF THE PROTOCOL DEPENDING ON WHICH CELL
        WAS TAPPED. EACH INSTANCE OF THE PROTOCOLS HAVE DIFFERENT IMPLEMENTATIONS OF
        "doneAction".
    **/
    [datePickerView setDatePickerProtocol:self];
    [datePickerView show];
}

//implementation of the protocol method
- (void)doneAction:(NSDate *)dateSelected
{
    //IF STATEMENTS GOES HERE DEPENDING ON WHICH CELL WAS TAPPED
    NSLog(@"Done action is called!");
}

Please see my comments on the code, above this line [datePickerView setDatePickerProtocol:self]. 请在此行[datePickerView setDatePickerProtocol:self]上方查看我对代码的评论。 Since I cannot instantiate protocols and assign to variables, is there an alternative or a better way of achieving my goal aside from implementing "myProtocol" from the controller and doing multiple IF statements inside "doneAction" method? 由于我无法实例化协议并分配给变量,除了从控制器实现“ myProtocol”并在“ doneAction”方法中执行多个IF语句之外,还有其他替代方法或更好的方法来实现我的目标吗?

Based from the answers, it seems like I need to define classes that implements "myProtocol" and create instance of those classes and pass to "datePickerView setDatePickerProtocol". 根据答案,似乎我需要定义实现“ myProtocol”的类并创建这些类的实例,然后传递给“ datePickerView setDatePickerProtocol”。 Is my understanding correct or is this reasonable to do? 我的理解是正确的还是这样做合理?

No protocols can not have instances created from them, if you could they would be just classes. 没有协议不能从它们创建实例,如果可以的话,它们仅仅是类。 Protocols are simply a way to define a set of methods that any class can implement, that way you do not have to use inheritance to have two different classes with the same methods. 协议只是定义任何类都可以实现的一组方法的一种方式,您不必使用继承就可以使用相同的方法来拥有两个不同的类。 Subclassing a classes you are sharing bother the interface of the parent class and the implementation, it makes sense to sometime share the interface between classes without sharing any implementation. 对要共享的类进行子类化会打扰父类和实现的接口,有时在不共享任何实现的情况下共享类之间的接口是有意义的。

A protocol is just an interface -- there's no implementation. 协议只是一个接口-没有实现。 So even if you could instantiate a protocol (which you can't), you'd still need some way to supply the implementation of the protocol's interface. 因此,即使您可以实例化协议(您不能实例化),您仍然需要某种方式来提供协议接口的实现。

The whole point of a protocol is that it lets you specify only the interface, and any class can implement that protocol. 协议的全部要点是,它允许您指定接口,任何类都可以实现该协议。 For example, the MapKit framework in iOS provides the MKAnnotation protocol, which defines the interface to a map annotation object. 例如,iOS中的MapKit框架提供了MKAnnotation协议,该协议定义了地图注释对象的接口。 You can implement MKAnnotation in any class you like. 您可以在任何您喜欢的类中实现MKAnnotation If you adopt MKAnnotation in some class of yours, you're essentially promising that that class provides certain methods, namely -coordinate , -setCoordinate: , -title , and -subtitle . 如果采用MKAnnotation在一些类你的,你基本上是看好这个类提供了一定的方法,即-coordinate-setCoordinate: -title-subtitle The ability to do that is important in a single-inheritance language like Objective-C -- it means that you can make any class you like an annotation, you don't have to subclass some provided annotation class. 在像Objective-C这样的单继承语言中,做到这一点的能力很重要-这意味着您可以创建任何喜欢注解的类,而不必对提供的注解类进行子类化。

Your datePickerProtocol property points to an object that implements myProtocol , not an instance of myProtocol itself (again, that wouldn't make sense). 您的datePickerProtocol属性指向实现myProtocol的对象,而不是myProtocol本身的实例(同样,这没有任何意义)。 If that's really what you want, then you're doing it fine... you can declare a pointer to an object that implements someProtocol as id<someProtocol> or NSObject<someProtocol>* . 如果这确实是您想要的,那么您就做得很好……您可以声明一个指向将someProtocol实现为id<someProtocol>NSObject<someProtocol>*的对象的指针。

Alternately, if you want to refer to the actual protocol itself rather than to an object that implements the protocol, you can do that. 或者,如果要引用实际协议本身,而不是引用实现协议的对象,则可以这样做。 Objective-C provides the Protocol type that's similar to the Class type: just as any given class is an object of type Class , any given protocol is an object of type Protocol . 目标C提供了Protocol类型这类似于Class类型:正如任何给定的类是类型的对象Class ,任何给定的协议是类型的对象Protocol You can use the @protocol directive to get the Protocol object for a particular protocol. 您可以使用@protocol指令来获取特定协议的Protocol对象。 There's more information in the Objective-C Runtime Reference . Objective-C运行时参考中有更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM