I am building a static library for controlling an iOS external accessory. As part of this, I want to present a minimal set of public headers to be distributed with the compiled library.
I have a class that needs to be public, but I want to create some framework private methods on it. I created a category for one of the public classes to add the private methods, including an initializer. This works fine for the project tests, but generates -[MyClass initMethodDefinedInCategory:]: unrecognized selector sent to instance error.
Category header:
#import "MyClass.h"
@interface MyClass (LibraryPrivateMethods)
- (id)initMethod:(NSData *)data;
- (int)someOtherMethod:(NSData *)data;
@end
Using class
#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;
}
I have tried adding the -ObjC
linker flag as suggested in this Apple tech note. I also tried adding the -all_load
flag as suggested in this SO answer.
EDIT: Realised I was only adding in XCode build, forgot to check build script, given below.
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)
Where abouts would I add the -ObjC flag to the build script?
Is there any reason that you cannot have an initializer method in a category? It seems possible as this Apple doc says
Category methods can do anything that methods defined in the class proper can do. At runtime, there’s no difference. The methods the category adds to the class are inherited by all the class’s subclasses, just like other methods.
I then tried using a class extension, but i am not sure how to make the method visible to the framework classes only.
@interface MyClass ()
- (id)initMethod;
@end
If I then call [[MyClass alloc] initMethod]
from another class in the library, I get a 'No visible @interface for MyClass declares the selector initMethod' error.
How can I make a method on an object only accessible to other classes in the framework and is not exported in MyClass.h ?