Сбой назначения элемента класса NSStringto
Я работаю над приложением C++ и Objective-C++. Там у меня есть класс C++, который вызывает класс Objective-C++. В заголовке C++ я создаю void * следующим образом:
void *m_self;
Затем в конструкторе я создаю экземпляр target-C++ следующим образом:
m_self = [[InfoForMac alloc] init];
В деструкторе я делаю это:
[(__bridge id)m_self release];
Класс target-C++ имеет такой интерфейс:
@interface InfoForMac : NSObject
@property (nonatomic, copy) NSString* data1;
@property (nonatomic, copy) NSString* data2;
@property (nonatomic, assign) int val;
Его метод инициализации:
- (id) init
{
if ( (self = [super init]) ) {
self.data1 = @"";
self.data2 = @"";
self.val = -1;
}
return self;
}
И его деструктор:
-(void)dealloc
{
[self.data1 release];
[self.data2 release];
[super dealloc];
}
И я вызываю методы target-C++ из C++ следующим образом:
[(__bridge id)m_self getData1];
QString dataFromMac = QString::from NSString([(__bridge id)m_self data1]);
И соответствующий метод заключается в следующем:
- (void) getData1
{
NSRunningApplication* activeApp = nil;
activeApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
if (activeApp) {
NSString* activeAppLocalizedName = [activeApp localizedName];
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
if (windowList) {
NSArray *windows = (__bridge NSArray*)(windowList);
for (NSDictionary *window in windows) {
NSString* owner = [window objectForKey:@"kCGWindowOwnerName"];
if (activeAppLocalizedName != nil &&
[owner isEqualToString:activeAppLocalizedName]) {
self.data1 = activeAppLocalizedName;
}
}
CFRelease(windowList);
}
}
}
Класс C++ уничтожен и воссоздан. Проблема в том, что после уничтожения класса, когда я воссоздаю его и вызываю метод getData1, я получаю сбой здесь:
self.data1 = activeAppLocalizedName;
Проверка с помощью трассировки стека отладчика показывает этот вызов, а затем objc_msgSend. Я прочитал, и кажется, что сбой может быть из-за дополнительного выпуска или повреждения.
Может ли кто-нибудь помочь мне понять, что происходит, пожалуйста?
Спасибо заранее и всего наилучшего
1 ответ
Несколько вещей кажутся мне странными в коде, который вы даете:
Мостовая отливка в коде MRC
Почему вы ведете кастинг перед выпуском? Вы должны либо соединить (используя ARC), либо освободить. Но вы, кажется, делаете оба. Может ли быть так, что вы на самом деле не отключили ARC в своем коде и теперь выпускаете объекты, которые ARC все еще считает принадлежащими ему?
Как правило, вы выполняете бридж в точке, где вы назначаете указатель ObjC для void*
или когда вы хотите переместить void*
обратно в указатель ObjC (т. е. приведения мостов всех форм указывают на переход от ручной обработки к разрешению ARC и обратно).
Приведение к мосту указателя ObjC, поддерживающего свойство ObjC перед его освобождением, не требуется.
Освобождение объектов через их аксессоры
Я не думаю, что это ваша большая проблема (она должна быть функционально эквивалентна), но она все еще кажется странной: как правило, либо выпускают переменную экземпляра
[_data1 release];
или же
[self->_data1 release];
или присваивает NIL и позволяет автору доступа выполнить высвобождение
self.data1 = nil;
Вы просите аксессор для объекта, а затем отпустите его. Это должно быть хорошо (это должен быть тот же объект), но это странно, и средство доступа обычно добавляет свой объект в текущий пул автоматического выпуска, поэтому ваш объект может быть освобожден позже, чем вы думали.