#c #ios #objective-c #swift #xcode
#c #iOS #objective-c #swift #xcode
Вопрос:
TLDR: в рабочей области есть два проекта. В одном проекте есть экземпляр объекта Swift, который реализует протокол Objective-C. Как разделить его между двумя проектами в рабочей области и сделать его доступным в файлах mm в этих проектах?
У меня есть рабочее пространство с 2 проектами A и B, где B — это фреймворк, а A зависит от него. Мне нужно совместно использовать объект Swift, созданный в A, среди A и B. Я пытался сделать это со статической переменной и с реализацией класса, но потерпел неудачу — кажется, что каждый из проектов получает свою собственную версию всего. У меня почти нет опыта работы с C и Objective-C / Swift, поэтому я могу упустить что-то очевидное.
Вот как выглядит мой код:
// [ Project A, file Header.h ]
#ifndef Header_h
#define Header_h
// the Swift object must extend this protocol
@protocol CallsProxySingleton
-(void) someImportantMethod
@end
// --- way 1 of attempting to pass the instance: static variable
id<CallsProxySingleton> variableInstance = NULL;
void SetVariableInstance(id<CallsProxySingleton> api) {
variableInstance = api;
}
// --- way 2 of attempting to pass the instance: class
@interface FrameworkLibApi : NSObject
(void) registerAPIForNativeCalls:(id<CallsProxySingleton>) aApi;
@end
// this is used from Swift to install the singleton instance
@implementation FrameworkLibApi
static id<CallsProxySingleton> api = NULL;
(void) registerAPIForNativeCalls:(id<CallsProxySingleton>) aApi {
api = aApi;
}
(id<CallsProxySingleton>) getApi {
return api;
}
(instancetype) getSelf {
return self;
}
@end
#endif
// [ Project A, file CallsProxySingletonSwiftImplementation.swift ]
class CallsProxySingletonSwiftImplementation : NSObject, CallsProxySingleton {
func initialize() {
// --- way 1
SetVariableInstance(self)
// --- way 2
NSClassFromString("FrameworkLibApi")!.registerAPIForNativeCalls(self)
}
// implementing CallsProxySingleton
func someImportantMethod() {}
}
// [ Project A, file NativeInterfaceA.mm ]
extern "C" void SomeMethodThatsCalledFromCppCode() {
// !!! this prints correct values: all pointers are non-null after the CallsProxySingletonSwiftImplementation had been called
NSLog("pointers A: variable=%p, framework.api=%p, framework.self=%p", variableInstance, [FrameworkLibApi getApi], [FrameworkLibApi getSelf])
}
// [ Project B, file NativeInterfaceB.mm ]
extern "C" void SomeOtherMethodThatsCalledFromCppCode() {
// !!! this prints all null pointers (0x0) except for [FrameworkLibApi getSelf] which prints a different pointer than in project A
NSLog("pointers B: variable=%p, framework.api=%p, framework.self=%p", variableInstance, [FrameworkLibApi getApi], [FrameworkLibApi getSelf])
}
Распечатка выглядит следующим образом:
pointers A: variable=0x281e98980, framework.api=0x281e98980, framework.self=0x102bf6c88
pointers B: variable=0x0, framework.api=0x0, framework.self=0x10d6352c0
Итак, все это выглядит так, как будто мой файл заголовка повторно интерпретируется дважды, и второй его «экземпляр», скомпилированный в проекте B, имеет свой собственный набор переменных, который совершенно не связан с переменными в проекте A. [FrameworkLibApi getSelf]
Возврат другого указателя только подтверждает это предположение. Ни установка глобальной переменной, ни класса не помогли совместно использовать переданный экземпляр. С точки зрения организации рабочего пространства Xcode, [ Project A, file Header.h ]
файл добавляется в проект B по ссылке без копирования.
В качестве третьего способа я также попытался переместить [ Project A, file Header.h ]
файл в отдельный проект C и сделать проекты A и B зависимыми от framework C, но это дало абсолютно тот же результат.
Вопрос: Как мне совместно использовать предполагаемый одноэлементный экземпляр объекта Swift для проектов в рабочей области?