Search code examples
objective-cxcodeoopproject

Access private variables of a class in other project


I have a huge Objective-C project which I want to split into several ones in a single WorkSpace. Initially I did it, and code compiled well, but I decided also to move one category of a big class to other project, and now linker doesn't understand the situation:

Undefined symbols for architecture x86_64:
  "_OBJC_IVAR_$_MyClass.data", referenced from:
      -[MyClass(Viz) someTask] in MyClass+Viz.o

d: symbol(s) not found for architecture x86_64  
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Briefly, my workspace looks like this:

- MyLib project:
    MyClass.h
    MyClass.m
    MyClass+Inner.h
    MyClass+Inner.m

- MyApp project:
    MyClass+Viz.h
    MyClass+Viz.m

MyLib is compiled into MyLib.framework which is used in MyApp. As I said, before moving MyClass+Viz to MyApp project, all the complex logic worked correctly, so there is probably no problem with projects linking. Also, I checked twice that all the files are marked correctly in Build Phases settings section.

This is the MyClass.h file:

@interface MyClass : NSObject
- (instancetype)init;
- (void)public_methods;
@end

This is the MyClass+Inner.h file:

#import "MyClass.h"

@interface MyClass ()
{
    // Variables placed here
    // so that only class methods can access them
    SomeStruct* data;
    // other fields ...
}
@end

@interface MyClass (Inner)
- (void)private_methods;
@end

And the MyClass+Viz.m file:

#import "MyClass+Viz.h"
#import "MyClass+Inner.h"

@implementation MyClass (Viz)
 - (int)someTask {
    return data->length;
    // this or any other stuff with
    // class variables from MyClass+Inner.h
    // leads to "Undefined symbols" by linker
}
@end

How can I make it work, make linker see class' private variables from other project?


Solution

  • First, you should be using @property and not instance variables, generally.

    Secondly, you would do something like this using multiple header files and class extensions.

    Typcially,

    MyClass.h MyClass_Internal.h MyClass.m MyClass_Internal.m (Not typically used)

    MyClass.m would import both headers. MyClass.h would define the public interface and MyClass_Internal.h would have a class extension to provide the private interface:

    @interface MyClass()
    @property(...) Thing *internalThing;
    @end