Вопрос или проблема
У меня есть следующий код в моем приложении на C++/Objective-C:
#import <YandexMobileAds/YandexMobileAds-Swift.h>
@class AdHook;
namespace MyApp
{
class AdHolder
{
public:
AdHolder(IosInterstitialAd* cpp_ad);
AdHook* m_hook;
};
}
using namespace MyApp;
@interface AdHook : NSObject <YMAInterstitialAdLoaderDelegate, YMAInterstitialAdDelegate>
{
@public IosInterstitialAd* m_cppAd;
@public YMAInterstitialAdLoader* m_loader;
@public YMAInterstitialAd* m_interstitialAd;
}
@end
@implementation AdHook
- (id)initFromCpp:(IosInterstitialAd *)cpp_ad
{
if (self = [super init])
{
m_cppAd = cpp_ad;
m_interstitialAd = nil;
m_loader = [[YMAInterstitialAdLoader alloc]init];
m_loader.delegate = self;
}
return self;
}
AdHolder::AdHolder(IosInterstitialAd* cpp_ad)
{
[YMAMobileAds enableLogging];
m_hook = [[AdHook alloc]initFromCpp:cpp_ad];
}
void SomeOtherClass::load()
{
NSLog(@"IosInterstitialAd::load()");
YMAAdRequestConfiguration* configuration = [[YMAAdRequestConfiguration alloc]initWithAdUnitID:@"demo-interstitial-yandex"];
[m_holder->m_hook->m_loader loadAdWithRequestConfiguration:configuration];
}
Я создаю экземпляр класса AdHolder
в C++ коде, и конструктор AdHolder
создает экземпляр класса Objective-C AdHook
, который, в свою очередь, создает свои внутренние объекты Objective-C.
Но я не совсем понимаю, каков срок жизни m_hook
? И у меня есть подозрение, что он удаляется в какой-то момент, потому что, когда я пытаюсь получить доступ к m_hook->m_interstitialAd
из колбэка YMAInterstitialAdLoaderDelegate
, я получаю неправильное значение, и приложение завершается с ошибкой.
Является ли m_hook
сильной ссылкой? Если нет, то как сделать ее сильной?
Проблема, вероятно, связана с тем, что m_hook
не является сильной ссылкой в вашем классе C++. В интеропе Objective-C/C++ обычные указатели не подразумевают владения. Чтобы создать сильную ссылку, измените свой класс AdHolder
, чтобы использовать указатель на указатель (AdHook** m_hook;). В конструкторе выделите его с помощью m_hook = new AdHook*; *m_hook = [[AdHook alloc] initFromCpp:cpp_ad];
. Добавьте деструктор для очистки: if (m_hook) { [*m_hook release]; delete m_hook; }
. При доступе используйте (*holder()->m_hook)->m_loader
. Это гарантирует, что объект AdHook
не будет неожиданно деаллоцирован. Также убедитесь, что экземпляр AdHolder
остается действительным, когда вы получаете доступ к m_hook
, так как его преждевременное уничтожение может привести к сбоям.
Ответ или решение
Проблема, с которой вы столкнулись, связана с управлением временем жизни объектов в вашей C++/Objective-C программе. Ваш объект m_hook
не сохраняет сильную ссылку на экземпляр класса AdHook
, что может привести к его преждевременной деаллокации и вызывает сбой при обращении к его членам.
В Objective-C, для того чтобы гарантировать, что объект будет жить до тех пор, пока он вам нужен, вы должны использовать сильные ссылки (strong
или retain
).
Для решения вашей проблемы вам нужно внести некоторые изменения в класс AdHolder
, чтобы правильно управлять временем жизни объекта m_hook
. Возможно, вам стоит изменить определение m_hook
так, чтобы он был объектом, а не просто указателем. Вот как это можно сделать:
namespace MyApp
{
class AdHolder
{
public:
AdHolder(IosInterstitialAd* cpp_ad);
~AdHolder();
AdHook* m_hook;
};
}
AdHolder::AdHolder(IosInterstitialAd* cpp_ad)
{
[YMAMobileAds enableLogging];
// Создаем объект AdHook и сохраняем его в m_hook
m_hook = [[AdHook alloc] initFromCpp:cpp_ad];
}
AdHolder::~AdHolder()
{
// Освобождаем объект AdHook
[m_hook release];
}
Это обеспечит то, что m_hook
будет поддерживать сильную ссылку на экземпляр AdHook
, предотвращая его деаллокацию до тех пор, пока экземпляр AdHolder
существует.
Также не забудьте, что вам необходимо следить за тем, чтобы экземпляр AdHolder
, в свою очередь, был доступен на момент вызова любых методов, которые обращаются к m_hook
. Если экземпляр AdHolder
будет деаллокирован, то попытка доступа к m_hook
вызовет сбой.
Проверка времени жизни
Убедитесь, что вы не создаете экземпляры AdHolder
на стеке, если они должны выжить дольше, чем вызов функции, в которой они были созданы. В таких случаях создавайте экземпляры AdHolder
в heap-памяти с помощью оператора new
, чтобы избежать преждевременной деаллокации:
AdHolder* holder = new AdHolder(cpp_ad);
// используйте holder...
delete holder; // не забудьте освободить память, когда закончите
Резюме
- Убедитесь, что
m_hook
является сильной ссылкой, используя подходящую инициализацию и освобождение ресурсов. - Контролируйте время жизни экземпляров классов, чтобы избежать доступа к уже деаллоцированным объектам.
- Используйте
new
иdelete
для управления памятью в C++, если не предполагается, что объекты будут существовать в пределах одной функции.
Следуя этим рекомендациям, вы избежите ошибок, связанных с недоступностью объектов в дальнейшем, и сделаете вашу программу более стабильной.