我创建了一个自定义反应本机自定义UI组件,该组件应集成第三方ios广告sdk。
这是我的代码:
#import "RDUAdCenterManager.h"
#if __has_include(<React/RCTBridge.h>)
#import <React/RCTBridge.h>
#import <React/RCTUIManager.h>
#import <React/RCTEventDispatcher.h>
#else
#import "RCTBridge.h"
#import "RCTUIManager.h"
#import "RCTEventDispatcher.h"
#endif
/* ———————————————————————————————————————————————————————————————————————— */
@interface NSError (SDK_Util)
/**
* Returns a text representation of the receiver's contents.
*/
- (NSString *)textRepresentation;
@end // NSError (SDK_Util)
@implementation RDUAdCenterManager
RCT_EXPORT_MODULE()
/* ———————————————————————————————————————————————————————————————————————— */
#pragma mark -
#pragma mark —— Construction / Destruction ——
/* ———————————————————————————————————————————————————————————————————————— *
* Deallocates this instance.
*
* [NSObject]
*/
- (void)dealloc
{
[mAdsView prepareForShutdown];
[mAdsView removeFromSuperview];
#if ! __has_feature(objc_arc)
[mAdsView release];
#endif // objc_arc
mAdsView = nil;
#if ! __has_feature(objc_arc)
[super dealloc];
#endif // objc_arc
} /* dealloc */
/* ———————————————————————————————————————————————————————————————————————— */
- (UIView *)view
{
//CGSize room = mAdsView.frame.size;
CGRect adFrame = CGRectMake(0, 0, 300, 250);
mAdsView = [[AdsView alloc] initInlineWithFrame:adFrame delegate:self];
// Add some profile targeting for good measure.
NSError *error = nil;
// Load an ad with the above targeting properties.
if (error == nil)
{
[mAdsView loadCreativeFromNetwork:@"DEMO" withContentUnitID:@"DEMO" error:&error];
}
if (error != nil)
{
NSLog(@" # %@", [error textRepresentation]);
}
return mAdsView;
}
/* ———————————————————————————————————————————————————————————————————————— */
#pragma mark -
#pragma mark —— Protocol Conformance ——
/* ———————————————————————————————————————————————————————————————————————— */
#pragma mark -
#pragma mark — AdsViewDelegate —
/* ———————————————————————————————————————————————————————————————————————— *
* Lets the app developer inform the SDK ahead of time which superview
* they will place the given AdsView in. This information is needed
* for coordinate computations on AdsViews that are not part of a view
* hierarchy at the time when ad loading finishes and MRAID state is
* initialized.
*
* • The superview chain of the view returned must end in a visible
* app window.
*
* [AdsViewDelegate]
*/
- (UIView *)futureSuperviewForAd:(AdsView *)inAdsView
{
return self.view;
} /* futureSuperviewForAd: */
/* ———————————————————————————————————————————————————————————————————————— *
* Takes note that the indicated ad has finished loading into the WebView.
*
* [AdsViewDelegate]
*/
- (void)adFinishedLoading:(AdsView *)inAdsView withSuccessOrError:(NSError *)inError
{
if (inAdsView == mAdsView)
{
if (inError != nil)
{
// An error occured while attempting to load the ad's WebView from local cache.
// Perform last rites...
[inAdsView prepareForShutdown];
[inAdsView removeFromSuperview];
// ... and deallocate.
#if ! __has_feature(objc_arc)
[inAdsView release];
#endif // objc_arc
mAdsView = nil;
NSLog(@" # %@", [inError textRepresentation]);
}
}
} /* adFinishedLoading:withSuccessOrError: */
/* ———————————————————————————————————————————————————————————————————————— *
* Tells the delegate that the indicated ad's internal JS code produced
* the given error while performing an SDK operation (like one of the
* MRAID functionalities).
*/
- (void)runningAd:(AdsView *)inAdsView encounteredError:(NSError *)inError
{
// At least the Development build of your app should log or otherwise handle any & all errors.
NSLog(@" # %@", [inError textRepresentation]);
} /* runningAd:encounteredError: */
/* ———————————————————————————————————————————————————————————————————————— *
* Opens a browser for the given URL, instead of the SDK's built-in browser.
*
* • This minimalistic implementation demonstrates how to let the URL
* be processed by the device's standard app (Safari).
*
* [AdsViewDelegate]
*/
- (void)openBrowserForAd:(AdsView *)inAdsView withURL:(NSURL *)inURL
{
// Pass the URL to the standard handler app.
if (! [[UIApplication sharedApplication] openURL:inURL])
{
// OS doesn't know how to open.
NSLog(@" # Unsupported URL type: %@", inURL);
}
// We don't capture interaction with a modal view in this
// app so we return control to the AdsView immediately.
[inAdsView resumeFromAppDefinedBrowser];
} /* openBrowserForAd:withURL: */
@end
这在我们的测试中效果很好,并且可以正确显示,但是在投入生产的几天后,我们遇到了几次Crashlytics崩溃,它们读为或类似内容:
Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000010
0 libobjc.A.dylib 0x1fc928d70 objc_msgSend + 16
1 MyApp 0x104a2133c -[AdsView passGeometryToWebTierInOrientation:] + 77232
2 MyApp 0x104a216f0 -[AdsView passFeatureInfoToWebTier:] + 78180
3 MyApp 0x104a24618 -[AdsView webViewDidFinishLoad:] + 90252
4 CoreFoundation 0x1fd747600 __invoking___ + 144
5 CoreFoundation 0x1fd625530 -[NSInvocation invoke] + 292
6 CoreFoundation 0x1fd626114 -[NSInvocation invokeWithTarget:] + 60
7 WebKitLegacy 0x20791c548 -[_WebSafeForwarder forwardInvocation:] + 156
8 CoreFoundation 0x1fd7454b4 ___forwarding___ + 640
9 CoreFoundation 0x1fd74745c _CF_forwarding_prep_0 + 92
10 CoreFoundation 0x1fd747600 __invoking___ + 144
11 CoreFoundation 0x1fd625530 -[NSInvocation invoke] + 292
12 WebCore 0x20652b178 HandleDelegateSource(void*) + 144
13 CoreFoundation 0x1fd6d01cc __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
14 CoreFoundation 0x1fd6d014c __CFRunLoopDoSource0 + 88
15 CoreFoundation 0x1fd6cfa30 __CFRunLoopDoSources0 + 176
16 CoreFoundation 0x1fd6ca8fc __CFRunLoopRun + 1040
17 CoreFoundation 0x1fd6ca1cc CFRunLoopRunSpecific + 436
18 GraphicsServices 0x1ff941584 GSEventRunModal + 100
19 UIKitCore 0x22a7fd054 UIApplicationMain + 212
20 MyApp 0x104347938 main (main.m:16)
21 libdyld.dylib 0x1fd18abb4 start + 4
从我的研究中,我发现它可能与不再可用的指针或类似指针相关联,但是我对Objective-C经验不足,也不知道从哪里开始调试。 / p>
在此软件包的android部分中,我们遇到了ReactContext未在后台定义的问题。也许这里很相似。