I try to test an iPhone (not universal) app on an iPad (device and simulator), but I get this error:
2013-02-09 15:25:23.907 iFormularioNew_Free[5160:c07] CRASH: *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil
2013-02-09 15:25:23.910 iFormularioNew_Free[5160:c07] Stack Trace: (
0 CoreFoundation 0x0204d02e __exceptionPreprocess + 206
1 libobjc.A.dylib 0x0151ee7e objc_exception_throw + 44
2 CoreFoundation 0x02000b6a -[__NSArrayM insertObject:atIndex:] + 314
3 CoreFoundation 0x02000a20 -[__NSArrayM addObject:] + 64
4 UIKit 0x00545894 -[UIViewController _addChildViewController:performHierarchyCheck:notifyWillMove:] + 344
5 UIKit 0x00553b8c -[UIViewController(UIContainerViewControllerProtectedMethods) addChildViewController:] + 68
6 iFormularioNew_Free 0x0003a27c -[BannerViewController loadView] + 348
7 UIKit 0x00543ff8 -[UIViewController loadViewIfRequired] + 73
8 UIKit 0x00544232 -[UIViewController view] + 33
9 iFormularioNew_Free 0x0003aa81 __63-[BannerViewController bannerView:didFailToReceiveAdWithError:]_block_invoke + 49
10 UIKit 0x004ae067 +[UIView(UIViewAnimationWithBlocks) _setupAnimationWithDuration:delay:view:options:animations:start:completion:] + 506
11 UIKit 0x004ae276 +[UIView(UIViewAnimationWithBlocks) animateWithDuration:animations:] + 99
12 iFormularioNew_Free 0x0003a9fb -[BannerViewController bannerView:didFailToReceiveAdWithError:] + 283
13 iAd 0x00072d23 -[ADBannerView _sanitizeAndForwardErrorToDelegate:] + 254
14 iAd 0x00072991 __28-[ADBannerView setDelegate:]_block_invoke_0 + 92
15 iAd 0x00072916 -[ADBannerView setDelegate:] + 266
16 iFormularioNew_Free 0x0003a0ae -[BannerViewController initWithContentViewController:] + 382
17 iFormularioNew_Free 0x0000336e -[AppDelegate application:didFinishLaunchingWithOptions:] + 4718
18 UIKit 0x00460157 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 266
19 UIKit 0x00460747 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1248
20 UIKit 0x0046194b -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 805
21 UIKit 0x00472cb5 -[UIApplication handleEvent:withNewEvent:] + 1022
22 UIKit 0x00473beb -[UIApplication sendEvent:] + 85
23 UIKit 0x00465698 _UIApplicationHandleEvent + 9874
24 GraphicsServices 0x0193adf9 _PurpleEventCallback + 339
25 GraphicsServices 0x0193aad0 PurpleEventCallback + 46
26 CoreFoundation 0x01fc2bf5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
27 CoreFoundation 0x01fc2962 __CFRunLoopDoSource1 + 146
28 CoreFoundation 0x01ff3bb6 __CFRunLoopRun + 2118
29 CoreFoundation 0x01ff2f44 CFRunLoopRunSpecific + 276
30 CoreFoundation 0x01ff2e1b CFRunLoopRunInMode + 123
31 UIKit 0x0046117a -[UIApplication _run] + 774
32 UIKit 0x00462ffc UIApplicationMain + 1211
33 iFormularioNew_Free 0x0000202d main + 141
34 iFormularioNew_Free 0x00001f55 start + 53
)
2013-02-09 15:25:23.953 iFormularioNew_Free[5160:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x204d012 0x151ee7e 0x2000b6a 0x2000a20 0x545894 0x553b8c 0x3a27c 0x543ff8 0x544232 0x3aa81 0x4ae067 0x4ae276 0x3a9fb 0x72d23 0x72991 0x72916 0x3a0ae 0x336e 0x460157 0x460747 0x46194b 0x472cb5 0x473beb 0x465698 0x193adf9 0x193aad0 0x1fc2bf5 0x1fc2962 0x1ff3bb6 0x1ff2f44 0x1ff2e1b 0x46117a 0x462ffc 0x202d 0x1f55)
libc++abi.dylib: terminate called throwing an exception
if I get iADSuite sample code and I change from universal to iphone and I test the application on an ipad (device o r simulator) I get the same error. Where is the problem?
EDIT: code:
here crash:
_bannerViewController = [[BannerViewController alloc] initWithContentViewController:self.tabBarController];
self.window.rootViewController = _bannerViewController;
BannerViewController.m
NSString * const BannerViewActionWillBegin = @"BannerViewActionWillBegin";
NSString * const BannerViewActionDidFinish = @"BannerViewActionDidFinish";
@interface BannerViewController () <ADBannerViewDelegate>
@end
@implementation BannerViewController {
ADBannerView *_bannerView;
UIViewController *_contentController;
}
- (instancetype)initWithContentViewController:(UIViewController *)contentController
{
self = [super init];
if (self != nil) {
// On iOS 6 ADBannerView introduces a new initializer, use it when available.
if ([ADBannerView instancesRespondToSelector:@selector(initWithAdType:)]) {
_bannerView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
} else {
_bannerView = [[ADBannerView alloc] init];
}
_bannerView.delegate = self;
_contentController = contentController;
}
return self;
}
- (void)loadView{
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[contentView addSubview:_bannerView];
[self addChildViewController:_contentController];
[contentView addSubview:_contentController.view];
[_contentController didMoveToParentViewController:self];
self.view = contentView;
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return [_contentController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
#endif
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [_contentController preferredInterfaceOrientationForPresentation];
}
- (NSUInteger)supportedInterfaceOrientations{
return [_contentController supportedInterfaceOrientations];
}
- (void)viewDidLayoutSubviews{
CGRect contentFrame = self.view.bounds, bannerFrame = CGRectZero;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
// If configured to support iOS <6.0, then we need to set the currentContentSizeIdentifier in order to resize the banner properly.
// This continues to work on iOS 6.0, so we won't need to do anything further to resize the banner.
if (contentFrame.size.width < contentFrame.size.height) {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
bannerFrame = _bannerView.frame;
#else
// If configured to support iOS >= 6.0 only, then we want to avoid currentContentSizeIdentifier as it is deprecated.
// Fortunately all we need to do is ask the banner for a size that fits into the layout area we are using.
// At this point in this method contentFrame=self.view.bounds, so we'll use that size for the layout.
bannerFrame.size = [_bannerView sizeThatFits:contentFrame.size];
#endif
if (_bannerView.bannerLoaded) {
contentFrame.size.height -= bannerFrame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
bannerFrame.origin.y = contentFrame.size.height;
}
_contentController.view.frame = contentFrame;
_bannerView.frame = bannerFrame;
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner{
[[NSNotificationCenter defaultCenter] postNotificationName:BannerViewActionWillBegin object:self];
[UIView animateWithDuration:0.25 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
[[NSNotificationCenter defaultCenter] postNotificationName:BannerViewActionDidFinish object:self];
[UIView animateWithDuration:0.25 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];
}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave {
return YES;
}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner{}
I deleted my earlier answer and I am posting this new answer instead.
Look at the stack trace. The problem is due to calling:
_bannerView.delegate = self;
This results in a chain of calls that leads to the loadView
method of BannerViewController
being called while still in the middle of the initWithContentViewController:
being executed. But at this point, the _contentController
ivar isn't set yet.
Given that setting the delegate kicks off ad loads and the need for a view, the best solution is to wait and set the _bannerView.delegate
in the viewDidLoad
method.
Another solution is to reorder the calls in the initWithContentViewController:
method to:
- (instancetype)initWithContentViewController:(UIViewController *)contentController {
self = [super init];
if (self != nil) {
// This must be called before you set the delegate on _bannerView
_contentController = contentController;
// On iOS 6 ADBannerView introduces a new initializer, use it when available.
if ([ADBannerView instancesRespondToSelector:@selector(initWithAdType:)]) {
_bannerView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
} else {
_bannerView = [[ADBannerView alloc] init];
}
_bannerView.delegate = self;
}
return self;
}
Yet another solution would be to get rid of the loadView
implementation and put all of that code (minus creating the content view) at the start of viewDidLoad
.
Without the code I can't point out where the exact problem lay, but the error is clear: you are trying to insert a "nil" object into an NSMutableArray, but this class doesn't allow it!
NS array and dictionary can't store nil as value: if you do it the app rise an exception (and if you don't handle it the app crash).
Edit: From call stack you see the error is in:
6 iFormularioNew_Free 0x0003a27c -[BannerViewController loadView] + 348
so you should look at the loadView method, at line:
[self addChildViewController:_contentController];
I'm sure that when it crash the _contentController is nil (the addChildViewController add the controller to an array of child controller owned by a parent). I leave to you to discover why it is nil ;)
User contributions licensed under CC BY-SA 3.0