Динамически типизированный класс генерирует предупреждения компилятора о выборе метода - PullRequest
2 голосов
/ 16 февраля 2010

Возможно, это неправильный путь, но мне кажется, что такой чистый и работоспособный подход, что мне интересно, как я могу убрать предупреждение компилятора?

@interface SomeView : UIView {
 NSString *stringOfsomeImportance;
 RelatedClass *niftyService;
}
@property (nonatomic, copy) NSString * stringOfnoImportance;
@property (nonatomic, retain) RelatedClass *niftyService;

@implementation
-(void)someMethod;
-(void)otherMethods;

@implementation    RelatedClass *pvSomeObj = [[RelatedClass alloc] initWithSender:self];
[self setNiftyService:pvSomeObj];

Теперь рассмотрим реализации RelatedClass ...

@interface RelatedClass : NSObject {
  id  thesender;

@property (nonatomic, retain) id thesender;


@implementation

[thesender otherMethods];  // this generates a compiler warning
                           // that otherMethods cannot be found
                           // in SomeView, though it *is* found
                           // and seems to execute just fine

Это похоже на правильный подход, так что мне интересно, почему предупреждение? Есть ли способ лучше "объяснить" это компилятору?

Может ли кто-нибудь поделиться, если этот тип связи поощряется или если есть лучший способ связать два взаимосвязанных, взаимозависимых класса, которые должны общаться друг с другом?

Я не могу статически объявить объект отправителя (SomeView) в RelatedClass, потому что это, кажется, вызывает проблему рекурсии, так как SomeView определено с RelatedClass в качестве члена ...

Есть предложения?

Ответы [ 3 ]

1 голос
/ 16 февраля 2010

В ваших заголовках вы можете форвард объявить классы, которые вы хотите использовать.В ваших файлах реализации вы можете включить полный заголовок тех классов, которые вы объявили вперед.

Например:


SomeView.h

#import <FrameworkHeader.h>

// Here, you are saying that there is a class called RelatedClass, but it will be
// defined later.
@class RelatedClass;

@interface SomeView : UIView
{
    RelatedClass *niftyService;
}

@end

SomeView.m

#import "SomeView.h"
#import "RelatedClass.h"

// By including "RelatedClass.h" you have fulfilled the forward declaration.

@implementation SomeView
// Can use "RelatedClass" methods from within here without warnings.
@end

RelatedClass.h

#import <FrameworkHeader.h>

@class SomeView;

@interface RelatedClass
{
    SomeView *someView;
}
// methods
@end

RelatedClass.m

#import "RelatedClass.h"
#import "SomeView.h"

@implementation RelatedClass
// Can use "SomeView" methods from within here without warnings.
@end
1 голос
/ 16 февраля 2010
  1. Вы можете определить протокол и сказать, что ваш thesender объект должен соответствовать ему:

    @protocol MyProtocol
       -(void)otherMethods;
    @end
    
    @interface RelatedClass : NSObject {
       id<MyProtocol>  thesender; // Now compiler knows that thesender must respond 
                                  // to otherMethods and won't generate warnings
    }
    
  2. Вы можете отправить otherMethods сообщение другим способом (вам может понадобиться определить theSender как NSObject здесь):

    if ([theSender respondsToSelector:@selector(otherMethods)])
        [theSender performSelector:@selector(otherMethods)];
    
  3. Редактировать: На самом деле вы также можете определить отправителя как SomeView * в вашем RelatedClass, используя объявление класса forward:

    //SomeView.h
    @class RelatedClass;
    @interface SomeView : UIView {
       RelatedClass *niftyService;
    }
    // then include RelatedClass.h in SomeView.m
    
    //RelatedView.h
    @class SomeView;
    @interface RelatedClass : NSObject {
       SomeView*  thesender;
    }
    // then include SomeView.h in RelatedClass.m
    
0 голосов
/ 16 февраля 2010
id  thesender = ....;
[thesender otherMethods];  // this generates a compiler warning
                           // that otherMethods cannot be found
                           // in SomeView, though it *is* found
                           // and seems to execute just fine

Для того, чтобы описанное выше сгенерировало предупреждение, как вы описываете, это полностью потому, что метод -otherMethods не был объявлен где-то, где компилятор видит объявление перед попыткой скомпилировать сайт вызова.

То есть объявление метода:

- (void) otherMethods;

должен появляться в заголовочном файле, который импортируется - прямо или косвенно - файлом реализации, компилирующим этот конкретный сайт вызова или , объявление метода должно появляться в @implementation до вызова сайта.

...