1

我正在构建一个用于控制 iOS 外部附件的静态库。作为其中的一部分,我想展示一组最小的公共头文件,以与编译的库一起分发。

我有一个需要公开的类,但我想在它上面创建一些框架私有方法。我为其中一个公共类创建了一个类别来添加私有方法,包括一个初始化程序。这适用于项目测试,但会生成 -[MyClass initMethodDefinedInCategory:]: unrecognized selector sent to instance 错误。

类别标题:

#import "MyClass.h"

@interface MyClass (LibraryPrivateMethods)
- (id)initMethod:(NSData *)data;
- (int)someOtherMethod:(NSData *)data;
@end

使用类

#import "MyOtherClass.h"
#import "MyClass.h"
#import "MyClass+LibraryPrivateMethods.h"

@implementation MyOtherClass

#pragma mark - Instance Methods
- (id)initWithData:(NSData *)data
{
    self = [super init];
    if(self)
    {

        MyClass *mc = [[MyClass alloc] initMethod:data]; // errors here
        _property = mc;
    }
    return self;
}

我已尝试按照此 Apple 技术说明-ObjC中的建议添加链接器标志。我还尝试按照此 SO answer中的建议添加标志。-all_load

编辑:意识到我只是在 XCode 构建中添加,忘记检查构建脚本,如下所示。

set -ex

INSTALL_PATH=$WORKSPACE/artifacts
[ -z $INSTALL_PATH ] || INSTALL_PATH=$PWD/artifacts

rm -rf $INSTALL_PATH
mkdir -p $INSTALL_PATH

PROJ=$SRCROOT/MyLib.xcodeproj

xcodebuild -project $PROJ -sdk iphoneos INSTALL_ROOT=$INSTALL_PATH/device install
xcodebuild -project $PROJ -sdk iphonesimulator INSTALL_ROOT=$INSTALL_PATH/simulator install

lipo -create -output $INSTALL_PATH/libMyLib.a $INSTALL_PATH/device/libMyLib.a $INSTALL_PATH/simulator/libMyLib.a
mv $INSTALL_PATH/device/Headers $INSTALL_PATH
rm -rf $INSTALL_PATH/device $INSTALL_PATH/simulator

# create zip for distribution.
(cd $INSTALL_PATH; zip -r ../MyLib-release.zip libMyLib.a Headers ../documentation/LibraryDocs/html ../documentation/LibraryDocs/docset)

我应该在哪里将 -ObjC 标志添加到构建脚本中?

有什么理由不能在类别中使用初始化方法吗?正如这个 Apple 文档所说,这似乎是可能的

类别方法可以做任何在类中定义的方法可以做的事情。在运行时,没有区别。类别添加到类的方法被该类的所有子类继承,就像其他方法一样。

然后我尝试使用类扩展,但我不确定如何使该方法仅对框架类可见。

@interface MyClass ()
- (id)initMethod;
@end

如果我随后[[MyClass alloc] initMethod]从库中的另一个类调用,我会收到“MyClass 的无可见 @interface 声明选择器 initMethod”错误。

如何使对象上的方法只能由框架中的其他类访问并且不在 MyClass.h 中导出?

4

3 回答 3

1

将类别声明放在单独的 .h 文件中。将此私有 .h 文件导入框架中需要访问类别方法的任何 .m 文件中。不要将此 .h 文件打包到分发给客户使用的公共 .h 文件集中。

BTW = 不要使用类扩展,使用命名类别。

于 2012-11-06T20:01:43.583 回答
0

无法在为该问题分配的时间内使其工作。我最终删除了该类别并将初始化程序代码移动到 MyOtherClass initWithData 方法中。这编译得很好并且可以工作。

于 2012-11-11T21:53:34.047 回答
0

请参阅Apple 技术说明底部的说明:

重要提示:对于 64 位和 iPhone OS 应用程序,存在阻止 -ObjC 从仅包含类别且不包含类的静态库加载对象文件的链接器错误。解决方法是使用 -all_load 或 -force_load 标志。

由于MyClass+LibraryPrivateMethods.m仅包含类别代码,听起来您看到了注释中描述的错误。

将您的私有实现移动到主 MyClass.m 或尝试-all_loador-force_load标志。

于 2012-11-06T21:01:49.820 回答