Objective-c 类扩展在静态库中无效

发布于 2024-09-25 10:15:51 字数 3271 浏览 4 评论 0 原文

在创建将在多个项目中使用的库时,我遇到了一个我无法自行解决的错误。

该库由几个“模块”组成,每个模块都声明其一组类。模块声明一个引用类的头文件。每个模块头都包含在库头中,并且所有模块头都被复制到库目标中。

“GMData”模块定义了库的ORM层,它声明了一个“GMInitializerBase”类,其目的是初始化模块。必须在 UIApplicationDelegate 中调用一次。

“GMModel”模块包含应用程序的基本模型(类别、文章等),它必须将自身注册到“GMData”才能正常运行。

结构:

<Library Root>
    Library.h
    <GMData>
        GMData.h
        GMInitializerBase.{h,m}
    <GMModel>
        GMModel.h
        GMInitializerBase+GMModel.{h,m}

Library.h 的内容

#import "GMData.h"
#import "GMModel.h"

GMData.h 的

#import "... ORM related headers ..."
#import "GMInitializerBase.h"

内容 GMInitializerBase.{h,m}

#import "... ORM Classes ..."

@interface GMInitializerBase : NSObject {

}

+ (void) bootstrap;
+ (GMInitializerBase*) initializer; // autoreleased instance creator

- (void) setup;
- (void) setupStore:(GMManagerFactory*)factory; // Setup database connection
- (void) setupHelpers:(GMHelperFactory*)factory; // Register helpers (abstract)
- (void) setupManagers:(GMManagerFactory*)factory; // Register managers (abstract)

@end

@implementation GMInitializerBase

+ (void) bootstrap {
    GMInitializerBase* initializer = [self initializer];

    [initializer setup];
}

- (void) setup {
    /* Breakpoint 01 */
    GMHelperFactory* helperFactory = [GMHelperFactory sharedInstance];
    GMManagerFactory* managerFactory = [GMManagerFactory sharedInstance];

    [self setupStore:managerFactory];
    [self setupHelpers:helperFactory];
    [self setupManagers:managerFactory];
}

@end

GMModel.h 的

#import "... Base Models files ..."
#import "GMInitializerBase+GMModel.h"

内容 GMInitializerBase+GMModel.{h,m}

@interface GMInitializerBase (GMModel_Additions)

- (void) setup;
- (void) setupGMModelHelpers:(GMHelperFactory*)factory;
- (void) setupGMModelManagers:(GMManagerFactory*)factory;

@end

@implementation GMInitializerBase (GMModel_Additions)

- (void) setup {
    /* Breakpoint 02 */
    GMHelperFactory* helperFactory = [GMHelperFactory sharedInstance];
    GMManagerFactory* managerFactory = [GMManagerFactory sharedInstance];

    // parent implementation
    [self setupStore:managerFactory];

    // current implementation
    [self setupGMModelHelpers:helperFactory];
    [self setupGMModelManagers:managerFactory];

    // parent implementation
    [self setupHelpers:helperFactory];
    [self setupManagers:managerFactory];
}

- (void) setupGMModelHelpers:(GMHelperFactory*)factory { /* ... */ }
- (void) setupGMModelManagers:(GMManagerFactory*)factory { /* ... */ }

@end

的内容 ProjectAppDelegate.m 的内容(位于另一个项目中,包括Library.a 并搜索“Headers”目录)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[GMInitializerBase initializer] setup];
}

在第一个断点处停止(断点 01) 在库中时它崩溃了:

  • 我声明了一个添加而没有重载方法;
  • 我声明了一个 Cocoa 类 ([NSString toto]) 的添加,但没有重载;

在测试项目中的工作中:

  • 我在不重载的情况下声明了 Cocoa 类([NSString toto])的添加;

我没有尝试重载库类,但我认为它也能工作。

我的问题如下:我无法使附加功能正常工作,但我需要它。

感谢您的阅读,感谢您的回答。

while creating a library that will be used on several projects, I encountered an error that I was not able to resolve by myself.

The library is composed of several "modules" that each declares its set of classes. The modules declares a header file that references the classes. Each module header is included in the library header, and all of them are copied to the library target.

The "GMData" module defines the ORM layer of the library, it declares a "GMInitializerBase" class, its purpose is to initialize the module. It must be called once in the UIApplicationDelegate.

The "GMModel" module contains the base model for the application (Categories, Articles, ...), It must register itself to "GMData" in order to function properly.

Structure:

<Library Root>
    Library.h
    <GMData>
        GMData.h
        GMInitializerBase.{h,m}
    <GMModel>
        GMModel.h
        GMInitializerBase+GMModel.{h,m}

Contents of Library.h

#import "GMData.h"
#import "GMModel.h"

Contents of GMData.h

#import "... ORM related headers ..."
#import "GMInitializerBase.h"

Contents of GMInitializerBase.{h,m}

#import "... ORM Classes ..."

@interface GMInitializerBase : NSObject {

}

+ (void) bootstrap;
+ (GMInitializerBase*) initializer; // autoreleased instance creator

- (void) setup;
- (void) setupStore:(GMManagerFactory*)factory; // Setup database connection
- (void) setupHelpers:(GMHelperFactory*)factory; // Register helpers (abstract)
- (void) setupManagers:(GMManagerFactory*)factory; // Register managers (abstract)

@end

@implementation GMInitializerBase

+ (void) bootstrap {
    GMInitializerBase* initializer = [self initializer];

    [initializer setup];
}

- (void) setup {
    /* Breakpoint 01 */
    GMHelperFactory* helperFactory = [GMHelperFactory sharedInstance];
    GMManagerFactory* managerFactory = [GMManagerFactory sharedInstance];

    [self setupStore:managerFactory];
    [self setupHelpers:helperFactory];
    [self setupManagers:managerFactory];
}

@end

Contents of GMModel.h

#import "... Base Models files ..."
#import "GMInitializerBase+GMModel.h"

Contents of GMInitializerBase+GMModel.{h,m}

@interface GMInitializerBase (GMModel_Additions)

- (void) setup;
- (void) setupGMModelHelpers:(GMHelperFactory*)factory;
- (void) setupGMModelManagers:(GMManagerFactory*)factory;

@end

@implementation GMInitializerBase (GMModel_Additions)

- (void) setup {
    /* Breakpoint 02 */
    GMHelperFactory* helperFactory = [GMHelperFactory sharedInstance];
    GMManagerFactory* managerFactory = [GMManagerFactory sharedInstance];

    // parent implementation
    [self setupStore:managerFactory];

    // current implementation
    [self setupGMModelHelpers:helperFactory];
    [self setupGMModelManagers:managerFactory];

    // parent implementation
    [self setupHelpers:helperFactory];
    [self setupManagers:managerFactory];
}

- (void) setupGMModelHelpers:(GMHelperFactory*)factory { /* ... */ }
- (void) setupGMModelManagers:(GMManagerFactory*)factory { /* ... */ }

@end

Contents of ProjectAppDelegate.m (located in another project, it includes the library.a and search the "Headers" directory)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[GMInitializerBase initializer] setup];
}

Stops at the first breakpoint (Breakpoint 01)
It crashed when in the library:

  • I declare an addition without overloading a method;
  • I declare an addition to a Cocoa class ([NSString toto]) without overloading;

In works when in the test project:

  • I declare an addition to a Cocoa class ([NSString toto]) without overloading;

I didn't try to overload a library class but I assume it will work too.

My problem is the following: I can't get the addition workingm and I need it.

Thanks for reading, thanks for answering.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小…楫夜泊 2024-10-02 10:15:51

确保在项目设置的“其他链接器标志”中设置了 -all_load 和 -ObjC 标志。没有它们,库中的类别将无法工作。

Make sure you have the -all_load and -ObjC flags set in the "Other Linker Flags" in the project settings. Categories in a library won't work without them.

浅紫色的梦幻 2024-10-02 10:15:51

在 Objective-C 中,您不应该重写类的类别中的方法。假设你有

@implementation MyClass
-(void)foo
{
    NSLog(@"%@",@"original!");
}
@end

,后来你有

@implementation MyClass (MyCategoryA)
-(void)foo
{
    NSLog(@"%@",@"categoryA!");
}
@end

@implementation MyClass (MyCategoryB)
-(void)foo
{
    NSLog(@"%@",@"categoryB!");
}
@end

那么结果

MyClass* myInstance=...;
[myInstance foo];

不可靠,请参阅 官方文档。文档说,如果您只有一个类别,它就可以工作,但文档同时表示您不应该使用该功能。所以,不要这样做

唯一的例外是+load。如果类别定义了此方法,则运行时会为您定义的每个类别调用它。因此,如果您想为每个类别执行一些初始化任务,+load 就是正确的方法。阅读 官方文档和这个博客文章,作者:Mike Ash。

In Objective-C, you shouldn't override the method in a category of a class. Say you have

@implementation MyClass
-(void)foo
{
    NSLog(@"%@",@"original!");
}
@end

and later you have

@implementation MyClass (MyCategoryA)
-(void)foo
{
    NSLog(@"%@",@"categoryA!");
}
@end

@implementation MyClass (MyCategoryB)
-(void)foo
{
    NSLog(@"%@",@"categoryB!");
}
@end

Then the result of

MyClass* myInstance=...;
[myInstance foo];

is not reliable, see the discussion in the official documentation. The documentation says it works if you have only one category, but the documentation says at the same time you shouldn't use that feature. So, don't do this.

The sole exception is +load. If a category defines this method, the runtime calls it for each category you define. So, if you want to perform some initialization task per category, +load is the way. Read the official documentation and this blog post by Mike Ash.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文