0

I have been scratching my head for awhile trying to figure this one out.

I have the following .h files

//ClassA.h
#import "ClassB.h"

@interface ClassA {
}

@property SomeEnum blah;

@end

//ClassB.h
#import "ClassA.h"

typedef enum SomeEnum
{
     value1,
     value2
}SomeEnum;

@interface ClassB {
}

@property SomeEnum otherblah;

@end

@interface ClassA (Category) {
}

@end

I think the problem is that ClassA needs SomeEnum from ClassB and so it needs to import it, and ClassB needs ClassA for its category so it needs to import it. Is there a problem with them importing each other? Do I need to include a third class?

Here are the compiler errors I'm getting:

In ClassB.h: Cannot find interface declaration for 'ClassA'
In ClassA.h: Unknown type name 'SomeEnum'

EDIT: I got it to work by moving the category declaration into ClassA and then having an @class ClassA in ClassB.h...but I'm still not sure why it wouldn't work in the first place

JPC
  • 8,096
  • 22
  • 77
  • 110
  • This post may help: http://stackoverflow.com/questions/322597/class-vs-import – bryanmac Sep 28 '11 at 23:52
  • Is that the entire `ClassB.h` file? Is it empty except for the import statement (and comments)? – chown Sep 29 '11 at 00:01
  • No it's not... I will edit my post to include more relevant info – JPC Sep 29 '11 at 00:25
  • Is @interface ClassA(Category) actually supposed to be within ClassB? I think that is not legal objective C. – ThomasW Sep 29 '11 at 00:37
  • I can definitely declare categories for other classes. I'm pretty sure at least... It's done other places in my code – JPC Sep 29 '11 at 00:41
  • If your code is exactly as it is above, then this is not legal objective C. You need an @end before the category on ClassA. – ThomasW Sep 29 '11 at 00:43
  • Sorry, typo, I do have that @end there – JPC Sep 29 '11 at 00:47

3 Answers3

2

Do you have (non-category declaration):

@interface ClassB

@end

declared anywhere, usually in ClassB.h?
Or a forward declaration:

@class ClassB

in ClassA.h?


Try this for your ClassA.h:

//ClassA.h

@class ClassB

@interface ClassB (Category)
+ (id)classMethod
@end

Then put #import "ClassB.h" in ClassA.m.


You should put this in ClassA.h:

@interface ClassA (Category) {
}

@end

And then the:

@implementation ClassA (Category)

in ClassA.m above the non-category @implementation ClassA.


Personally, I create seperate files for categories. For example, this is in UIView-Extended.h:

@interface UIView (UIView_Extended)

enum {
    UIViewAutoresizingHorizontal = (UIViewAutoresizingFlexibleLeftMargin | 
                                    UIViewAutoresizingFlexibleWidth | 
                                    UIViewAutoresizingFlexibleRightMargin),
    UIViewAutoresizingVertical = (UIViewAutoresizingFlexibleTopMargin | 
                                  UIViewAutoresizingFlexibleHeight | 
                                  UIViewAutoresizingFlexibleBottomMargin),
    UIViewAutoresizingAll = (UIViewAutoresizingFlexibleLeftMargin | 
                             UIViewAutoresizingFlexibleWidth | 
                             UIViewAutoresizingFlexibleRightMargin | 
                             UIViewAutoresizingFlexibleTopMargin | 
                             UIViewAutoresizingFlexibleHeight | 
                             UIViewAutoresizingFlexibleBottomMargin)
};
typedef NSUInteger UIViewAutoresizing;

- (UIView *)findFirstResponder;
- (UIView *)setFirstResponder:(NSUInteger)viewTag;
- (IBAction)dismissKeyboard:(id)sender;
- (IBAction)nextPrevious:(id)sender;

@end

And then in UIView-Extended.m:

#import "UIView-Extended.h"

@implementation UIView (UIView_Extended)

- (UIView *)findFirstResponder {
    if ([self isFirstResponder]) {
        return self;
    }

    for (UIView *subview in [self subviews]) {
        UIView *firstResponder = [subview findFirstResponder];
        if (firstResponder) {
            return firstResponder;
        }
    }
    return nil;
}

- (UIView *)setFirstResponder:(NSUInteger)viewTag {
    if (self.tag == viewTag) {
        [self becomeFirstResponder];
        return self;
    }
    for (UIView *subview in self.subviews) {
        UIView *v = [subview setFirstResponder:viewTag];
        if (v) {
            return v;
        }
    }
    return nil;
}

- (IBAction)dismissKeyboard:(id)sender {
    [[self findFirstResponder] resignFirstResponder];
}

- (IBAction)nextPrevious:(id)sender {
    UIView *responder = [self findFirstResponder];  
    if (!responder) return;
    NSInteger newTag;
    NSInteger tagMod = 1;
    if (sender) {
        tagMod = (((UISegmentedControl *)sender).selectedSegmentIndex ? 1 : -1);
    }
    UIView *v = [self viewWithTag:responder.tag + tagMod];
    if ([v isKindOfClass:[UITextField class]] || [v isKindOfClass:[UITextView class]]) {
        newTag = responder.tag + tagMod;
        [self setFirstResponder:newTag];
    } else {
        //  do something else... but what??
    }
}

@end

Then, in my Prefix file (Project-Prefix.pch):

#import "UIView-Extended.h"
chown
  • 51,908
  • 16
  • 134
  • 170
  • Try putting `@class ClassB` just above `@interface ClassB (Category)` in your `ClassA.h` file. – chown Sep 28 '11 at 23:57
  • Updated post to include more details – JPC Sep 29 '11 at 00:30
  • Thanks, can you also provide the exact error/warning you are getting? I have also updated my answer with: Try putting the Category declaration in ClassA.h instead of ClassB.h. – chown Sep 29 '11 at 00:43
  • I suppose I could do that but there are other places in my code that do it this way so for parity's sake I would prefer to do it this way. The other places in the code don't have this cross dependency however... – JPC Sep 29 '11 at 00:46
2

You'll want to break out your dependencies. Put the definition of enum SomeEnum in one header file, then include an import for that header in ClassA.h and ClassB.h. In ClassA.h remove the import of ClassB.h.

ThomasW
  • 16,981
  • 4
  • 79
  • 106
0
#import <UIKit/UIKit.h>

you should import <UIKit/UIKit.h> in any object contains "interface declaration"

e.g: UIImage NSDate etc..

Ofir Malachi
  • 1,145
  • 14
  • 20