Question

Perhaps this is the wrong way to go about this, but it seems like such a clean and workable approach that I wonder how I can make the compiler warning go away?

@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];

Now, looking at the RelatedClass implementations...

@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

This seems like a valid approach, so I'm left wondering why the warning? Is there a way to better "explain" this to the compiler?

Could someone kindly share if this type of linkage is encouraged or if there is a better way to link two related, interdependent classes that need to communicate with one another?

I can't statically declare the sender object (SomeView) in RelatedClass because that seems to cause a recursion problem, as SomeView is defined with RelatedClass as a member...

Any suggestions?

Was it helpful?

Solution

  1. You can define a protocol and say that your thesender object must conform to it:

    @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. You can send otherMethods message another way (you may need to define theSender as NSObject here):

    if ([theSender respondsToSelector:@selector(otherMethods)])
        [theSender performSelector:@selector(otherMethods)];
    
  3. Edit: Actually you can also define thesender as SomeView* in your RelatedClass using forward class declaration:

    //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
    

OTHER TIPS

In your headers, you can forward declare classes that you want to use. In your implementation files, you can include the full header of those classes that you forward-declared.

For example:


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
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

For the above to generate the warning as you describe, it is entirely because the method -otherMethods has not been declared someplace where the compiler sees the declaration before attempting to compile the call site.

That is, the declaration of the method:

- (void) otherMethods;

Must appear in a header file that is imported -- directly or indirectly -- by the implementation file compiling that particular call site or the method declaration must appear in the @implementation before the call site.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top