问题描述
几年来我一直在快速编程,但最近才尝试更好地了解Objc。 我使用VIPER架构自己做一个小项目。我有一个使用VIPER的示例.swift项目,现在我只想将其“翻译”为objc以了解语法。
.h / .m文件遇到一些问题: 我不知道是否应该在.m或.h文件中(分别)或在.h或.m文件中(与它们所属的类一起)声明协议。 我选择将它们全部放在.h文件中,并创建了一个导入该文件的.m文件。但这似乎真的很糟糕,因为.m为空。 此外,在这些协议中将“ MyViewController”作为类型调用时,还会收到诸如“预期类型”之类的错误。
可以100%确保问题来自标题。我知道必须从“ .m”文件中导入“ .h”才能进行编译,并且我也知道我们不应多次调用标头。 但是,当我拥有A.h / B.h文件时,感觉就像被卡住了,我需要从B的A和B的B中获取一些东西。在这种情况下我该如何解开?
我的协议。h看起来像这样:
@protocol SampleProtocol
+ (MyViewController*) createModule; // Error: Expected a type
- (void) pushToView: (UINavigationController*)navController;
@end
MyViewController.h看起来像这样:
@interface MyViewController : UIViewController
@property id<PresenterToRouterObjcProtocol> protocol;
@end
谢谢您的帮助,希望您能启发我遗失的那一块!
解决方法
在Objective-C中,您通常在自己的.h和.m文件中放置一个类。 界面位于.h中,实现位于.m中。您可以将接口视为可用消息列表,而不包含实现细节,然后实现就是它的实际实现。
它可以追溯到C文件,其中包含.h和.c文件。 .h文件提供了函数的定义,以便使用该文件的其他代码知道如何调用它。
Objective-C协议只是一个没有实现的接口,实现该协议的类必须提供实际的实现。也就是说,一个协议将只有一个.h文件。协议通常会为该类指定必需和可选的消息。
我希望这有助于您了解如何解决您的问题。它并不经常发生,但是有时确实发生了,您需要B中的A,同时也需要A中的B。在这里,我将假设A和B是类,每个类都有自己的.h和.m文件。该问题将是头文件中的问题。
您可能会遇到类似的情况
A.h
#import <Foundation...>
#import "B.h"
// Define class A
@interface A : NSObject
// Say this one has a property B
@property (nonatomic,strong) B * b;
@end
B.h
#import <Foundation...>
#import "A.h"
// Define class B
@interface B : NSObject
// Say this one has a property A
@property (nonatomic,strong) A * a;
@end
现在您遇到了鸡肉和鸡蛋的情况。您不能在不知道B的情况下定义A,反之亦然。您可以通过告诉编译器每种类型都有一个类来解决此问题,如下所示。
A.h(B.h将非常相似)
#import <Foundation...>
// No more import of B.h,but define it for compiler in general terms
@class B; // Now compiler knows there will be a B
// Define class A
@interface A : NSObject
// This will work now as the compiler knows B is coming later
@property (nonatomic,strong) B * b;
@end
编辑
一些细节...以上是一个一般性的答案,要更具体一点,您实际上不应在单个头文件中放置多个类或协议。每个文件都应具有自己的.h文件。为了解决您的问题,请删除导入并使用
@class MyViewController;
代替。