Ok, I am going crazy here. I am using Xcode 6.4 and I also tried new 7 beta 3.
What happens is that anything (for example BOOL) that i declare as a global variable can't be seen by certain methods/functions.
-(void)loadView can see it no problem but
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error and some others can't.
I know that globals are dangerous but please let me know what I am doing wrong. Thanks!
my h file:
#interface BannerViewController : UIViewController
{
BOOL isInternetActive;
}
m file:
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
isInternetActive = NO; //it doesn't compile because of this. Error is "Use of undeclared identifier 'isInternetActive'
}
EDITED to show entire h and m file:
h file:
#import <UIKit/UIKit.h>
#import <iAd/iAd.h>
//#import <GoogleMobileAds/GoogleMobileAds.h> //Google
#import GoogleMobileAds;
extern NSString * const BannerViewActionWillBegin;
extern NSString * const BannerViewActionDidFinish;
#interface TestBannerViewController : UIViewController
{
GADBannerView *admobBannerView;
}
#property (nonatomic) BOOL isInternetActive;
- (instancetype)initWithContentViewController:(UIViewController *)contentController;
#end
m file:
#import "TestBannerViewController.h"
//#import <GoogleMobileAds/GoogleMobileAds.h> //Google
#import GoogleMobileAds;
NSString * const BannerViewActionWillBegin = #"BannerViewActionWillBegin";
NSString * const BannerViewActionDidFinish = #"BannerViewActionDidFinish";
#interface TestBannerViewController ()
// This method is used by BannerViewSingletonController to inform instances of TestBannerViewController that the banner has loaded/unloaded.
- (void)updateLayout;
#end
#interface BannerViewManager : NSObject <ADBannerViewDelegate>
#property (nonatomic, readonly) ADBannerView *bannerView;
//#property (nonatomic, weak) GADBannerView *admobBannerView; //Google
+ (BannerViewManager *)sharedInstance;
- (void)addBannerViewController:(TestBannerViewController *)controller;
- (void)removeBannerViewController:(TestBannerViewController *)controller;
#end
#implementation TestBannerViewController {
UIViewController *_contentController;
}
#synthesize isInternetActive;
- (instancetype)initWithContentViewController:(UIViewController *)contentController
{
NSAssert(contentController != nil, #"Attempting to initialize a BannerViewController with a nil contentController.");
self = [super init];
if (self != nil) {
_contentController = contentController;
[[BannerViewManager sharedInstance] addBannerViewController:self];
}
return self;
}
- (void)dealloc
{
[[BannerViewManager sharedInstance] removeBannerViewController:self];
}
- (void)loadView
{
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Setup containment of the _contentController.
[self addChildViewController:_contentController];
[contentView addSubview:_contentController.view];
[_contentController didMoveToParentViewController:self];
NSLog(#"Google Mobile Ads SDK version: %#", [GADRequest sdkVersion]);
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;
ADBannerView *bannerView = [BannerViewManager sharedInstance].bannerView;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
NSString *contentSizeIdentifier;
if (contentFrame.size.width < contentFrame.size.height) {
contentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
contentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
bannerFrame.size = [ADBannerView sizeFromBannerContentSizeIdentifier:contentSizeIdentifier];
#else
bannerFrame.size = [bannerView sizeThatFits:contentFrame.size];
#endif
if (bannerView.bannerLoaded) {
contentFrame.size.height -= bannerFrame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
//contentFrame.size.height -= bannerFrame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
}
_contentController.view.frame = contentFrame;
if (self.isViewLoaded && (self.view.window != nil)) {
[self.view addSubview:bannerView];
bannerView.frame = bannerFrame;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
bannerView.currentContentSizeIdentifier = contentSizeIdentifier;
#endif
}
}
- (void)updateLayout
{
[UIView animateWithDuration:0.25 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.view addSubview:[BannerViewManager sharedInstance].bannerView];
}
- (NSString *)title
{
return _contentController.title;
}
#end
#implementation BannerViewManager {
ADBannerView *_bannerView;
NSMutableSet *_bannerViewControllers;
}
+ (BannerViewManager *)sharedInstance
{
static BannerViewManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[BannerViewManager alloc] init];
});
return sharedInstance;
}
- (instancetype)init
{
self = [super init];
if (self != nil) {
if ([ADBannerView instancesRespondToSelector:#selector(initWithAdType:)]) {
_bannerView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
} else {
_bannerView = [[ADBannerView alloc] init];
}
_bannerView.delegate = self;
_bannerViewControllers = [[NSMutableSet alloc] init];
}
return self;
}
- (void)addBannerViewController:(TestBannerViewController *)controller
{
[_bannerViewControllers addObject:controller];
}
- (void)removeBannerViewController:(TestBannerViewController *)controller
{
[_bannerViewControllers removeObject:controller];
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
for (TestBannerViewController *bvc in _bannerViewControllers) {
[bvc updateLayout];
}
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
for (TestBannerViewController *bvc in _bannerViewControllers) {
[bvc updateLayout];
}
isInternetActive = YES;
}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
[[NSNotificationCenter defaultCenter] postNotificationName:BannerViewActionWillBegin object:self];
return YES;
}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner
{
[[NSNotificationCenter defaultCenter] postNotificationName:BannerViewActionDidFinish object:self];
}
#end
You can create new header file in your project.
In that you can write like this :
static BOOL isInternetActive;
Import this header file where you want to access this bool value.
Hope this helps.
I think I got it. in the m file there are two #implementation files (two classes?) and that is why when declaring global in the h file the last class can't see it.
Related
I'm trying to replicate the implementation In iOS, how do I create a button that is always on top of all other view controllers? in Objective-C.
But the loadView is never called, can someone tell me why?
And how to fix it?
ApplicationFloatingButtonWindow.m
#import "ApplicationFloatingButtonWindow.h"
#import "ApplicationFloatingButtonController.h"
#interface ApplicationFloatingButtonWindow()
#pragma mark - Properties
#property (strong, nonatomic) UIButton *floatingButton;
#property (strong, nonatomic) ApplicationFloatingButtonController *floatingButtonViewController;
#end
#implementation ApplicationFloatingButtonWindow
#pragma mark - Initialization
- (instancetype)init {
self = [super init];
if (self) {
self.backgroundColor = nil; // make background transparent
}
return self;
}
#pragma mark - Gesture Handling
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
if(self.floatingButton) {
CGPoint floatingButtonPoint = [self convertPoint:point toView:self.floatingButton];
return [self.floatingButton pointInside:floatingButtonPoint withEvent:event];
}
return [super pointInside:point withEvent:event];
}
#end
ApplicationFloatingButtonController.h
#import <UIKit/UIKit.h>
#import "ApplicationFloatingButtonWindow.h"
#interface ApplicationFloatingButtonController : UIViewController
#pragma mark - Properties
#property (strong, nonatomic) UIButton *floatingButton;
#property (strong, nonatomic) ApplicationFloatingButtonWindow *window;
#end
ApplicationFloatingButtonController.m
#import "ApplicationFloatingButtonController.h"
#interface ApplicationFloatingButtonController ()
#end
#implementation ApplicationFloatingButtonController
#pragma mark - Initialization
- (instancetype)init {
self = [super initWithNibName:nil bundle:nil];
if (self) {
[self setup];
}
return self;
}
#pragma mark - Setup
- (void)setup {
self.window.windowLevel = CGFLOAT_MAX;
self.window.hidden = NO;
self.window.rootViewController = self;
[NSNotificationCenter.defaultCenter addObserver:self selector:#selector(keyboardDidShow) name:UIKeyboardDidShowNotification object:nil];
}
- (void)setupPanGestureRecognizers {
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panGestureRecognizerAction:)];
[self.floatingButton addGestureRecognizer:panGestureRecognizer];
}
#pragma mark - Lifecycle
- (void)loadView {
UIButton *button = [self createButton];
UIView *view = [UIView new];
[view addSubview:button];
self.view = view;
self.floatingButton = button;
[self setupPanGestureRecognizers];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self snapButtonToBestPosition];
}
#pragma mark - Elements Factory
- (UIButton *)createButton {
UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoDark];
[button setTitle:#"Floating..." forState:UIControlStateNormal];
[button setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
button.backgroundColor = UIColor.whiteColor;
button.layer.shadowColor = UIColor.blackColor.CGColor;
button.layer.shadowRadius = 3;
button.layer.shadowOpacity = 0.8;
button.layer.shadowOffset = CGSizeZero;
[button sizeToFit];
button.frame = CGRectMake(10, 10, 24, 24);
button.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);;
return button;
}
#pragma mark - Selectors
- (void)keyboardDidShow {
// This refreshes the window level and puts it back to the top most view
self.window.windowLevel = 0;
self.window.windowLevel = CGFLOAT_MAX;
}
- (void)panGestureRecognizerAction:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint gestureOffset = [panGestureRecognizer translationInView:self.view];
[panGestureRecognizer setTranslation:CGPointZero inView:self.view];
CGPoint newButtonCenter = self.floatingButton.center;
newButtonCenter.x += gestureOffset.x;
newButtonCenter.y += gestureOffset.y;
self.floatingButton.center = newButtonCenter;
if (panGestureRecognizer.state == UIGestureRecognizerStateEnded || panGestureRecognizer.state == UIGestureRecognizerStateCancelled ) {
[UIView animateWithDuration:0.3 animations:^{
[self snapButtonToBestPosition];
}];
}
}
#pragma mark - Elements Layout and Positioning Methods
- (NSArray *)possibleButtonPositions {
CGSize buttonSize = self.floatingButton.bounds.size;
CGRect rect = CGRectInset(self.view.frame, 4 + buttonSize.width / 2, 4 + buttonSize.height / 2);
NSMutableArray *possiblePositions = [NSMutableArray new];
[possiblePositions addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect))]];
[possiblePositions addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect))]];
[possiblePositions addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect))]];
[possiblePositions addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect))]];
[possiblePositions addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect))]];
return possiblePositions;
}
- (void)snapButtonToBestPosition {
CGPoint bestPositionForButton = CGPointZero;
CGFloat distanceToBestPosition = CGFLOAT_MAX;
CGPoint buttonCenter = self.floatingButton.center;
for (NSValue *possibleButtonPositionAsNSValue in [self possibleButtonPositions]) {
CGPoint possibleButtonPosition = possibleButtonPositionAsNSValue.CGPointValue;
CGFloat distance = hypot(buttonCenter.x - possibleButtonPosition.x, buttonCenter.y - possibleButtonPosition.y);
if (distance < distanceToBestPosition) {
distanceToBestPosition = distance;
bestPositionForButton = possibleButtonPosition;
}
}
self.floatingButton.center = bestPositionForButton;
}
#end
AppDelegate.m
#import "AppDelegate.h"
#import "ApplicationFloatingButtonController.h"
#interface AppDelegate ()
#pragma mark - Properties
#property (strong, nonatomic) ApplicationFloatingButtonController *floatingButtonController;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Configure Floating Button
self.floatingButtonController = [ApplicationFloatingButtonController new];
[self.floatingButtonController.floatingButton addTarget:self action:#selector(floatingButtonDidReceiveTouchUpInside) forControlEvents:UIControlEventTouchUpInside];
return YES;
}
- (void)floatingButtonDidReceiveTouchUpInside {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"My Alert"
message:#"This is an alert."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
#end
The solution and final code is here:
https://github.com/bocato/ApplicationFloatingButton
The Swift version has
private let window = FloatingButtonWindow()
in the FloatingButtonController class. You have created the property, in the .h file, but you don't initialise it anywhere. Try adding
self.window = [ApplicationFloatingButtonWindow new];
to your setup method.
In my app I've to create a custom alert view like the following:
So I followed this tutorial to create a custom alert view. I finished it but I'm getting issue in the following method:
- (void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove {
NSMutableArray *items = [[NSMutableArray alloc]init];
[items addObject:self.buttonOk];
[items addObject:self.buttonClose];
int buttonIndex = (tag == 1);
if (shouldRemove) {
[items removeObjectAtIndex:buttonIndex];
} else {
if (tag == 1) {
[items insertObject:self.buttonOk atIndex:buttonIndex];
} else {
[items insertObject:self.buttonClose atIndex:buttonIndex];
}
}
}
I edited it than the tutorial because I don't need a UIToolBar for buttons. When I run the app it says me that I can't insert a nil object in an NSMutableArray, but I don't understand what's wrong, I hope you can help me to fix this issue.
UPDATE
Here's all the class code I developed:
#import "CustomAlertViewController.h"
#define ANIMATION_DURATION 0.25
#interface CustomAlertViewController ()
- (IBAction)buttonOk:(UIButton *)sender;
- (IBAction)buttonCancel:(UIButton *)sender;
#property (weak, nonatomic) IBOutlet UIButton *buttonClose;
#property (weak, nonatomic) IBOutlet UIButton *buttonOk;
#property (strong, nonatomic) IBOutlet UIView *viewAlert;
-(void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove;
#end
#implementation CustomAlertViewController
- (id)init
{
self = [super init];
if (self) {
[self.viewAlert setFrame:CGRectMake(self.labelAlertView.frame.origin.x,
self.labelAlertView.frame.origin.y,
self.labelAlertView.frame.size.width,
self.viewAlert.frame.size.height)];
[self.buttonOk setTag:1];
[self.buttonClose setTag:0];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)showCustomAlertInView:(UIView *)targetView withMessage:(NSString *)message {
CGFloat statusBarOffset;
if (![[UIApplication sharedApplication] isStatusBarHidden]) {
CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
if (statusBarSize.width < statusBarSize.height) {
statusBarOffset = statusBarSize.width;
} else {
statusBarOffset = statusBarSize.height;
}
} else {
statusBarOffset = 0.0;
}
CGFloat width, height, offsetX, offsetY;
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft ||
[[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) {
width = targetView.frame.size.width;
height = targetView.frame.size.height;
offsetX = 0.0;
offsetY = -statusBarOffset;
}
[self.view setFrame:CGRectMake(targetView.frame.origin.x, targetView.frame.origin.y, width, height)];
[self.view setFrame:CGRectOffset(self.view.frame, offsetX, offsetY)];
[targetView addSubview:self.view];
[self.viewAlert setFrame:CGRectMake(0.0, -self.viewAlert.frame.size.height, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.viewAlert setFrame:CGRectMake(0.0, 0.0, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView commitAnimations];
[self.labelAlertView setText:#"CIAO"];
}
- (void)removeCustomAlertFromView {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.viewAlert setFrame:CGRectMake(0.0, -self.viewAlert.frame.size.height, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView commitAnimations];
[self.view performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION];
}
- (void)removeCustomAlertFromViewInstantly {
[self.view removeFromSuperview];
}
- (BOOL)isOkayButtonRemoved {
if (self.buttonOk == nil) {
return YES;
} else {
return NO;
}
}
- (BOOL)isCancelButtonRemoved {
if (self.buttonClose == nil) {
return YES;
} else {
return NO;
}
}
- (void)removeOkayButton:(BOOL)shouldRemove {
if ([self isOkayButtonRemoved] != shouldRemove) {
[self addOrRemoveButtonWithTag:1 andActionToPerform:shouldRemove];
}
}
- (void)removeCancelButton:(BOOL)shouldRemove {
if ([self isCancelButtonRemoved] != shouldRemove) {
[self addOrRemoveButtonWithTag:0 andActionToPerform:shouldRemove];
}
}
- (void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove {
NSMutableArray *items = [[NSMutableArray alloc]init];
[items addObject:self.buttonOk];
[items addObject:self.buttonClose];
int buttonIndex = (tag == 1);
if (shouldRemove) {
[items removeObjectAtIndex:buttonIndex];
} else {
if (tag == 1) {
[items insertObject:self.buttonOk atIndex:buttonIndex];
} else {
[items insertObject:self.buttonClose atIndex:buttonIndex];
}
}
}
- (IBAction)buttonOk:(UIButton *)sender {
[self.delegate customAlertOk];
}
- (IBAction)buttonCancel:(UIButton *)sender {
[self.delegate customAlertCancel];
}
#end
UPDATE 2
Code in which I use the CustomAlertView:
#import "PromotionsViewController.h"
#import "CustomAlertViewController.h"
#interface PromotionsViewController () <CustomAlertViewControllerDelegate> {
BOOL isDeletingItem;
}
#property(nonatomic,strong) CustomAlertViewController *customAlert;
- (IBAction)buttonBack:(UIButton *)sender;
#property (weak, nonatomic) IBOutlet UIButton *buttonAlert;
- (IBAction)buttonAlert:(UIButton *)sender;
#end
#implementation PromotionsViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.buttonAlert setTitle:self.promotionSelected forState:UIControlStateNormal];
[self.customAlert setDelegate:self];
isDeletingItem = NO;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonBack:(UIButton *)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc]init];
[self.customAlert removeOkayButton:NO];
[self.customAlert removeCancelButton:NO];
NSString *message = [NSString stringWithFormat:#"La tua offerta %# del 20%% è stata convertita in punti IoSi x10", self.promotionSelected];
[self.customAlert showCustomAlertInView:self.view withMessage:message];
isDeletingItem = YES;
}
- (void)customAlertOk {
if (isDeletingItem) {
[self.customAlert removeCustomAlertFromViewInstantly];
} else {
[self.customAlert removeCustomAlertFromView];
}
}
- (void)customAlertCancel {
[self.customAlert removeCustomAlertFromView];
if (isDeletingItem) {
isDeletingItem = NO;
}
}
#end
Maybe you're calling addOrRemoveButtonWithTag:andActionToPerform: at a time where your UI is not fully created, since UI elements are created asynchronously. So if you call this method, right after custom alert view instanciation, you'll get your crash because the buttons in the view are not created.
To solve this issue, you need to call addOrRemoveButtonWithTag:andActionToPerform: only once your custom alert has been added to the view hierarchy.
EDIT :
With the example code you gave in edit 2, you call these lines :
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc]init];
[self.customAlert removeOkayButton:NO];
[self.customAlert removeCancelButton:NO];
}
but when you have just instantiated CustomAlertViewController, its 2 buttons are not yet created, so I suggest you add 2 properties hasOkButton and hasCancelButton and a new constructor to your custom class like this one :
- (instancetype) initWithOk:(BOOL)OkButton AndCancel:(BOOL) CancelButton
{
if(self = [super init])
{
hasOkButton = OkButton;
hasCancelButton = CancelButton;
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// At this time, the custom UI buttons will be created in the UI view hierarchy
[self removeOkayButton: hasOkButton];
[self removeOkayButton: hasCancelButton];
}
And in the caller you can use the following to display a custom alert View:
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc] initWithOk:NO AndCancel:NO];
// ...
}
EDIT #2
I tried your solution in a real project, I made it work by using these lines int the caller :
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [self.storyboard instantiateViewControllerWithIdentifier:#"customAlertView"];
self.customAlert.hasOK = NO;
self.customAlert.hasCancel = YES;
NSString *message = [NSString stringWithFormat:#"La tua offerta %# del 20%% è stata convertita in punti IoSi x10", self.promotionSelected];
[self.customAlert showCustomAlertInView:self.view withMessage:message];
isDeletingItem = YES;
}
In the CustomAlertViewController declare 2 visible properties hasOK and hasCancel in.h.
And modify your .m by adding method :
-(void)viewWillAppear:(BOOL)animated
{
[self removeOkayButton:self.hasOK];
[self removeCancelButton:self.hasCancel];
}
Be sure to modify your storyboard (if eligible) to have the "customAlertView" defined this way :
Don't forget also to bind your UIButton to the controller this can be a mistake too in your implementation :
Hope this will help you :)
I found on the web a tutorial to create custom alert view by using code, if you are interested you can go to this tutorial. I used it for my issue and it worked great! You have to fix a few things, because it uses deprecated command but it's easy to fix it.
If you are interested just take a look about this tutorial. I think you can integrate it in your app and after you can easily use for other stuff if it's necessary. I hope that my answer will help someone.
Note: I am posting this as a reference for other developers that might run into the same issue.
Why do I have a memory leak with this code:
#interface SPWKThing : NSObject
#property (strong, nonatomic) NSArray *things;
#end
#implementation SPWKThing {
BOOL _isKVORegistered;
}
- (id)init
{
self = [super init];
if (self) {
NSLog(#"initing SPWKThing");
[self registerKVO];
}
return self;
}
- (void)didChangeValueForKey:(NSString *)key {
if ([key isEqualToString:#"things"]) {
NSLog(#"didChangeValueForKey: things have changed!");
}
}
#pragma mark - KVO
- (void)registerKVO
{
if (!_isKVORegistered) {
NSLog(#"Registering KVO, and things is %#", _things);
[self addObserver:self forKeyPath:#"things" options:0 context:NULL];
_isKVORegistered = YES;
}
}
- (void)unregisterKVO
{
if (_isKVORegistered) {
NSLog(#"Unregistering KVO");
[self removeObserver:self forKeyPath:#"things"];
_isKVORegistered = NO;
}
}
- (void)dealloc
{
NSLog(#"SPWKThing dealloc");
[self unregisterKVO];
}
#end
#implementation SPWKViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self runDemo];
}
- (void)runDemo
{
SPWKThing *thing = [[SPWKThing alloc] init];
thing.things = #[#"one", #"two", #"three"];
thing = nil;
}
#end
My output is:
initing SPWKThing
Registering KVO, and things is (null)
didChangeValueForKey: things have changed!
dealloc is never called? Why? I am setting thing = nil in the last line of runDemo!
See a demo project here: https://github.com/jfahrenkrug/KVOMemoryLeak
The answer is:
Never override didChangeValueForKey: (at least not without calling super). The documentation does not warn you about this.
Use the correct method observeValueForKeyPath:ofObject:change:context: instead.
This project clearly demonstrates this: https://github.com/jfahrenkrug/KVOMemoryLeak
I'm making a news reading app. I have a ArticleDetailPagingVC which functions as a paging controller. This has a UIScrollView with multiple ArticleDetailViewController's.
Inside the ArticleDetailViewController is a UIWebView which handles the articleText.
After changing some code I got a EXC_BAD_ACCESS when trying to inject a HTML string in the UIWebView. I eventually ended up looking for NSZombie's, which I found:
As seen in the screenshot the NSZombie points to setting the frame of the ArticleDetailViewController, which is not correct in my opinion.
If I comment out the line of code which injects the HTMLString to my UIWebView, the view is shown as it should, without any data in the UIWebView.
The WebView is created as an IBOutlet:
#property (nonatomic) IBOutlet UIWebView *webView;
Delegate is set to self (ArticleDetailViewController)
Also, its crashing before any of the UIWebView Delegate Methods are called.
I'm sure the problem is not:
The HTML String (it was working before & if I load a 'Hello world' string its crashing too)
MultiThreading (everything is handled on the mainthread for testing purposes)
I have no weak properties
I have 0 autoreleasepool's / CFRelease(object) in my code
I have no idea what could have been released too soon to create the crash
So my question is, how do you debug such a NSZombie? Or any other pointers are much appreciated.
PagingVC.h
#import <UIKit/UIKit.h>
#import "DDScrollViewController.h"
#import "ThumbArticle.h"
#import "NewsArticle.h"
#import "MBProgressHUD.h"
#import "DDScrollViewDelegate.h"
#interface ArticleDetailPagingVC : UIViewController <UIScrollViewDelegate,MBProgressHUDDelegate>
//View
#property (nonatomic) IBOutlet UIScrollView *scrollView;
//Data
#property (nonatomic) ThumbArticle *selectedThumbArticle;
#property (nonatomic) NewsArticle *selectedNewsArticle;
#property (nonatomic) int indexOfSelectedArticle;
#property (nonatomic) NSMutableArray *dataList;
#property (nonatomic) NSInteger selectedPage;
#property (nonatomic) BOOL dataSet;
#property (nonatomic) MBProgressHUD *mbProcess;
-(id)initWithDataList:(NSMutableArray*)dataList;
#end
PagingVC.m
#import "ArticleDetailPagingVC.h"
#import "ArticleDetailViewController.h"
#interface ArticleDetailPagingVC ()
-(void)setupView;
-(void)setupViewWithThumbArticles;
-(void)setupViewWithNewsArticles;
#end
#implementation ArticleDetailPagingVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.dataSet = NO;
}
return self;
}
-(id)initWithDataList:(NSMutableArray*)dataList
{
self = [super init];
if (self) {
self.dataSet = NO;
self.dataList = [NSMutableArray arrayWithArray:dataList];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.selectedThumbArticle) {
self.indexOfSelectedArticle = [self.dataList indexOfObject:self.selectedThumbArticle];
} else if (self.selectedNewsArticle) {
self.indexOfSelectedArticle = [self.dataList indexOfObject:self.selectedNewsArticle];
}
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self setupView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark Custom Methods
-(void)setupView
{
if (self.dataList.count > 0) {
id object = [self.dataList objectAtIndex:0];
if ([object isKindOfClass:[NewsArticle class]]) {
} else if ([object isKindOfClass:[ThumbArticle class]]) {
ArticleDetailViewController *articleDetailVC = [[ArticleDetailViewController alloc] init];
articleDetailVC.selectedThumbArticle = [self.dataList objectAtIndex:self.indexOfSelectedArticle];
articleDetailVC.view.frame = CGRectMake(self.indexOfSelectedArticle * self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:articleDetailVC.view];
//[articleDetailVC layoutViewWithThumbArticle:[self.dataList objectAtIndex:self.indexOfSelectedArticle]];
}
self.scrollView.contentSize = CGSizeMake(self.dataList.count * self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView setContentOffset:CGPointMake(self.indexOfSelectedArticle * self.scrollView.frame.size.width, 0) animated:NO];
self.dataSet = YES;
}
}
-(void)setupViewWithThumbArticles
{
//Set the selected article first
/*
ArticleDetailViewController *articleDetailVC = [[ArticleDetailViewController alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
articleDetailVC.view.frame = CGRectMake(indexOfSelectedArticle * self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:articleDetailVC.view];
});
[self.viewControllers replaceObjectAtIndex:indexOfSelectedArticle withObject:articleDetailVC];
[articleDetailVC layoutViewWithThumbArticle:[self.dataList objectAtIndex:indexOfSelectedArticle]];
//Then loop through the rest to add them to the scrollview
*/
int i = 0;
for (ThumbArticle *article in self.dataList) {
if (i != self.indexOfSelectedArticle) {
ArticleDetailViewController *articleDetailVC = [[ArticleDetailViewController alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
articleDetailVC.view.frame = CGRectMake(i * self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:articleDetailVC.view];
});
//[self.viewControllers replaceObjectAtIndex:i withObject:articleDetailVC];
}
i++;
}
dispatch_async(dispatch_get_main_queue(), ^{
self.scrollView.contentSize = CGSizeMake(i * self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView setContentOffset:CGPointMake(self.indexOfSelectedArticle * self.scrollView.frame.size.width, 0) animated:NO];
});
}
-(void)setupViewWithNewsArticles
{
int indexOfSelectedArticle = [self.dataList indexOfObject:self.selectedNewsArticle];
ArticleDetailViewController *articleDetailVC = [[ArticleDetailViewController alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
articleDetailVC.view.frame = CGRectMake(indexOfSelectedArticle * self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:articleDetailVC.view];
});
//[self.viewControllers replaceObjectAtIndex:indexOfSelectedArticle withObject:articleDetailVC];
[articleDetailVC layoutViewWithNewsArticle:[self.dataList objectAtIndex:indexOfSelectedArticle]];
int i = 0;
for (NewsArticle *article in self.dataList) {
if (i != indexOfSelectedArticle) {
ArticleDetailViewController *articleDetailVC = [[ArticleDetailViewController alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
articleDetailVC.view.frame = CGRectMake(i * self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:articleDetailVC.view];
});
//[self.viewControllers replaceObjectAtIndex:i withObject:articleDetailVC];
}
i++;
}
self.scrollView.contentSize = CGSizeMake(i * self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView setContentOffset:CGPointMake(indexOfSelectedArticle * self.scrollView.frame.size.width, 0) animated:NO];
}
#pragma mark -
#pragma mark UIScrollView Delegate Methods
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (fmodf(scrollView.contentOffset.x, scrollView.frame.size.width) == 0) {
if (self.dataSet) {
self.selectedPage = scrollView.contentOffset.x / self.scrollView.frame.size.width;
ArticleDetailViewController *articleDetailVC = [[ArticleDetailViewController alloc] initWithNibName:#"ArticleDetailViewController" bundle:nil];
articleDetailVC.view.frame = CGRectMake(self.selectedPage * self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:articleDetailVC.view];
[articleDetailVC layoutViewWithThumbArticle:[self.dataList objectAtIndex:self.selectedPage]];
}
}
}
#pragma mark -
#pragma mark MBProgressHUDDelegate methods
- (void)hudWasHidden
{
[self.mbProcess removeFromSuperview];
}
#end
ArticleDetailViewController.h
#import "DDViewController.h"
#import "ThumbArticle.h"
#import "NewsArticle.h"
#import "MBProgressHUD.h"
#import "DDAsyncParser+NewsArticles.h"
#interface ArticleDetailViewController : DDViewController <MBProgressHUDDelegate,UIWebViewDelegate,ParserDelegate>
//View
#property (nonatomic,strong) IBOutlet UIView *contentView;
#property (nonatomic) IBOutlet UIImageView *image;
#property (nonatomic) IBOutlet UILabel *labelCategory;
#property (nonatomic) IBOutlet UILabel *labelImgCaption;
#property (nonatomic) IBOutlet UILabel *labelEdition;
#property (nonatomic) IBOutlet UIWebView *webView;
#property (nonatomic) IBOutlet UIActivityIndicatorView *activity;
#property (nonatomic) NSUInteger textFontSize;
#property (nonatomic) MBProgressHUD *mbProcess;
//Data
#property (nonatomic) ThumbArticle *selectedThumbArticle;
ArticleDetailViewController.m
#import "ArticleDetailViewController.h"
#import "DDUtilities.h"
#import "DDUserDefaults.h"
#import "NewsArticle.h"
#import "DDFeedParser.h"
#interface ArticleDetailViewController ()
#property (nonatomic) NewsArticle *parsedNewsArticle;
-(void)loadData;
-(void)updateImageCaptionLabel;
-(void)populateWebView;
#end
#implementation ArticleDetailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
[self.view addSubview:self.contentView];
((UIScrollView*)self.view).contentSize = self.contentView.frame.size;
self.dataSet = NO;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.dataSet) {
[[DDAsyncParser sharedInstance] parseArticleWithXMLURL:self.selectedThumbArticle.articleXMLUrl delegate:self];
}
}
- (void)viewWillUnload
{
[self.webView setDelegate:nil];
[self.webView stopLoading];
}
- (void)viewWillDisappear:(BOOL)animated{
[self.webView setDelegate:nil];
[self.webView stopLoading];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark Public Methods
-(void)layoutViewWithThumbArticle:(ThumbArticle*)article
{
if (!self.dataSet) {
self.selectedThumbArticle = article;
[[DDAsyncParser sharedInstance] parseArticleWithXMLURL:self.selectedThumbArticle.articleXMLUrl delegate:self];
}
}
-(void)layoutViewWithNewsArticle:(NewsArticle*)article
{
if (!self.dataSet) {
self.parsedNewsArticle = article;
[self loadData];
}
}
#pragma mark -
#pragma mark Private Methods
-(void)loadData
{
self.labelCategory.text = self.parsedNewsArticle.articleCategory;
self.labelCategory.font = kCalibriBold14;
self.labelCategory.textColor = kGrayColor;
self.labelEdition.text = self.parsedNewsArticle.articleEdition;
self.labelEdition.font = kCalibriBold14;
self.labelEdition.textColor = kGrayColor;
[self updateImageCaptionLabel];
[self populateWebView];
self.dataSet = YES;
}
-(void)updateImageCaptionLabel
{
self.labelImgCaption.text = #"";
NSString *imgAuthor = #"";
if (self.parsedNewsArticle.articleImgAuthor.length != 0) {
imgAuthor = [NSString stringWithFormat:#"Foto: %#",self.parsedNewsArticle.articleImgAuthor];
}
NSString *imgCaption = #"";
if (self.parsedNewsArticle.articleImgDescription.length != 0) {
imgCaption = [NSString stringWithFormat:#"%# \n%#",self.parsedNewsArticle.articleImgDescription,imgAuthor];
} else {
imgCaption = imgAuthor;
}
self.labelImgCaption.text = imgCaption;
CGSize maximumLabelSize = CGSizeMake(296,9999);
CGSize expectedLabelSize = [imgCaption sizeWithFont:self.labelImgCaption.font
constrainedToSize:maximumLabelSize
lineBreakMode:self.labelImgCaption.lineBreakMode];
CGRect newFrame = self.labelImgCaption.frame;
newFrame.size.height = expectedLabelSize.height;
self.labelImgCaption.frame = newFrame;
}
-(void)populateWebView
{
NSString *htmlContentString = [DDUtilities createHTMLStringForArticleDetail:self.parsedNewsArticle];
[self.webView loadHTMLString:htmlContentString baseURL:nil];
}
-(void)checkSavedTextFontSize
{
self.textFontSize = [[DDUserDefaults getValueForKey:#"textFontSize"]integerValue];
if (self.textFontSize != 0) {
NSString *jsString = [[NSString alloc] initWithFormat:#"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '%d%%'",
self.textFontSize];
[self.webView stringByEvaluatingJavaScriptFromString:jsString];
} else {
self.textFontSize = 100;
}
}
#pragma mark -
#pragma mark UIWebView Delegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if (navigationType == UIWebViewNavigationTypeLinkClicked)
{
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[self checkSavedTextFontSize];
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
dispatch_async(dispatch_get_main_queue(), ^{
self.webView.frame = CGRectMake(frame.origin.x, self.labelImgCaption.frame.origin.y + self.labelImgCaption.frame.size.height + 5.0f, frame.size.width, frame.size.height);
self.contentView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.webView.frame.origin.y + self.webView.frame.size.height + 30.0f);
((UIScrollView*)self.view).contentSize = self.contentView.frame.size;
});
//[DDUtilities setImageView:self.image forLink:self.parsedNewsArticle.articleImgUrl placeholder:YES withActivityIndicator:self.activity];
}
-(void)webViewDidStartLoad:(UIWebView *)webView
{
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
}
#pragma mark -
#pragma mark MBProgressHUDDelegate methods
- (void)hudWasHidden
{
[self.mbProcess removeFromSuperview];
}
#pragma mark -
#pragma mark ParserDelegate methods
-(void)didFinishWithObject:(id)object
{
self.parsedNewsArticle = object;
[self loadData];
}
You create a controller (which has a view). You assign the view as a subview of some other view. That's it. So, ARC will helpfully destroy your article detail controller that you aren't using any more. Anything that it has set itself as the delegate of (like a web view) will now crash when it tries to call the delegate.
Solution: store the article detail controller (add a strong property) so that it is retained while the view is on display.
Or, add the controller as a chile view controller.
I just implemented adWhirl to my app with iAds and adMob. Everything compiles correctly and adMob works perfectly, but my iAd's are not being sized correctly. the ad looks like its the right size, but it actually appears to be cut off. About 1/4 of the ad seems like it is missing. Since i have no bugs i don't know exactly where to look to fix this.
here is a screenshot of what my ad bar looks like.
http://imgur.com/waPPD
any help or just a nudge in the right direction would be appreciated!
here is the AdWhirlAdapteriAd.h
#import "AdWhirlAdNetworkAdapter.h"
#import <iAd/ADBannerView.h>
#interface AdWhirlAdapterIAd : AdWhirlAdNetworkAdapter <ADBannerViewDelegate> {
NSString *kADBannerContentSizeIdentifierPortrait;
NSString *kADBannerContentSizeIdentifierLandscape;
}
+ (AdWhirlAdNetworkType)networkType;
#end
here is AdWhirlAdapteriAd.m
#import "AdWhirlAdapterIAd.h"
#import "AdWhirlAdNetworkConfig.h"
#import "AdWhirlView.h"
#import "AdWhirlLog.h"
#import "AdWhirlAdNetworkAdapter+Helpers.h"
#import "AdWhirlAdNetworkRegistry.h"
#implementation AdWhirlAdapterIAd
+ (AdWhirlAdNetworkType)networkType {
return AdWhirlAdNetworkTypeIAd;
}
+ (void)load {
if(NSClassFromString(#"ADBannerView") != nil) {
[[AdWhirlAdNetworkRegistry sharedRegistry] registerClass:self];
}
}
- (void)getAd {
ADBannerView *iAdView = [[ADBannerView alloc] initWithFrame:CGRectZero];
kADBannerContentSizeIdentifierPortrait =
&ADBannerContentSizeIdentifierPortrait != nil ?
ADBannerContentSizeIdentifierPortrait :
ADBannerContentSizeIdentifierPortrait;
kADBannerContentSizeIdentifierLandscape =
&ADBannerContentSizeIdentifierLandscape != nil ?
ADBannerContentSizeIdentifierLandscape :
ADBannerContentSizeIdentifierPortrait;
iAdView.requiredContentSizeIdentifiers = [NSSet setWithObjects:
kADBannerContentSizeIdentifierPortrait,
kADBannerContentSizeIdentifierLandscape,
nil];
UIDeviceOrientation orientation;
if ([self.adWhirlDelegate respondsToSelector:#selector(adWhirlCurrentOrientation)]) {
orientation = [self.adWhirlDelegate adWhirlCurrentOrientation];
}
else {
orientation = [UIDevice currentDevice].orientation;
}
if (UIDeviceOrientationIsLandscape(orientation)) {
iAdView.currentContentSizeIdentifier = kADBannerContentSizeIdentifierLandscape;
}
else {
iAdView.currentContentSizeIdentifier = kADBannerContentSizeIdentifierPortrait;
}
[iAdView setDelegate:self];
self.adNetworkView = iAdView;
[iAdView release];
}
- (void)stopBeingDelegate {
ADBannerView *iAdView = (ADBannerView *)self.adNetworkView;
if (iAdView != nil) {
iAdView.delegate = nil;
}
}
- (void)rotateToOrientation:(UIInterfaceOrientation)orientation {
ADBannerView *iAdView = (ADBannerView *)self.adNetworkView;
if (iAdView == nil) return;
if (UIInterfaceOrientationIsLandscape(orientation)) {
iAdView.currentContentSizeIdentifier = kADBannerContentSizeIdentifierLandscape;
}
else {
iAdView.currentContentSizeIdentifier = kADBannerContentSizeIdentifierPortrait;
}
// ADBanner positions itself in the center of the super view, which we do not
// want, since we rely on publishers to resize the container view.
// position back to 0,0
CGRect newFrame = iAdView.frame;
newFrame.origin.x = newFrame.origin.y = 0;
iAdView.frame = newFrame;
}
- (BOOL)isBannerAnimationOK:(AWBannerAnimationType)animType {
if (animType == AWBannerAnimationTypeFadeIn) {
return NO;
}
return YES;
}
- (void)dealloc {
[super dealloc];
}
#pragma mark IAdDelegate methods
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
// ADBanner positions itself in the center of the super view, which we do not
// want, since we rely on publishers to resize the container view.
// position back to 0,0
CGRect newFrame = banner.frame;
newFrame.origin.x = newFrame.origin.y = 0;
banner.frame = newFrame;
[adWhirlView adapter:self didReceiveAdView:banner];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
[adWhirlView adapter:self didFailAd:error];
}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication: (BOOL)willLeave {
[self helperNotifyDelegateOfFullScreenModal];
return YES;
}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner {
[self helperNotifyDelegateOfFullScreenModalDismissal];
}
#end
Here is where the ads are being called in the app
MainMenuInterface.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "GameManager.h"
#import "AdWhirlView.h"
#import "AdWhirlDelegateProtocol.h"
#import "Reading_FluencyAppDelegate.h"
#import "RootViewController.h"
enum GameStatePP {
kGameStatePlaying,
kGameStatePaused
};
#interface MainMenuInterface : CCLayer <AdWhirlDelegate>
{
CCMenu *mainMenu;
CCMenu *aboutPage;
RootViewController *viewController;
AdWhirlView *adWhirlView;
enum GameStatePP _state;
}
#property(nonatomic,retain) AdWhirlView *adWhirlView;
#property(nonatomic) enum GameStatePP state;
-(void)displayStartButton;
#end
and here is the important stuff in MainMenuInterface.m
- (void)adWhirlWillPresentFullScreenModal {
if (self.state == kGameStatePlaying) {
//[[SimpleAudioEngine sharedEngine] pauseBackgroundMusic];
[[CCDirector sharedDirector] pause];
}
}
- (void)adWhirlDidDismissFullScreenModal {
if (self.state == kGameStatePaused)
return;
else {
self.state = kGameStatePlaying;
//[[SimpleAudioEngine sharedEngine] resumeBackgroundMusic];
[[CCDirector sharedDirector] resume];
}
}
- (NSString *)adWhirlApplicationKey {
return #"23myapplicationkey39203924";
}
- (UIViewController *)viewControllerForPresentingModalView {
return viewController;
}
-(void)adjustAdSize {
[UIView beginAnimations:#"AdResize" context:nil];
[UIView setAnimationDuration:0.2];
CGSize adSize = [adWhirlView actualAdSize];
CGRect newFrame = adWhirlView.frame;
newFrame.size.height = adSize.height;
CGSize winSize = [CCDirector sharedDirector].winSize;
newFrame.size.width = winSize.width;
newFrame.origin.x = (self.adWhirlView.bounds.size.width - adSize.width)/2;
newFrame.origin.y = (winSize.height - adSize.height);
adWhirlView.frame = newFrame;
[UIView commitAnimations];
}
- (void)adWhirlDidReceiveAd:(AdWhirlView *)adWhirlVieww {
[adWhirlView rotateToOrientation:UIInterfaceOrientationLandscapeRight];
[self adjustAdSize];
}
-(void)onEnter {
viewController = [(Reading_FluencyAppDelegate *)[[UIApplication sharedApplication] delegate] viewController];
self.adWhirlView = [AdWhirlView requestAdWhirlViewWithDelegate:self];
self.adWhirlView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
[adWhirlView updateAdWhirlConfig];
CGSize adSize = [adWhirlView actualAdSize];
CGSize winSize = [CCDirector sharedDirector].winSize;
self.adWhirlView.frame = CGRectMake((winSize.width/2)-(adSize.width/2),winSize.height- adSize.height,winSize.width,adSize.height);
self.adWhirlView.clipsToBounds = YES;
[viewController.view addSubview:adWhirlView];
[viewController.view bringSubviewToFront:adWhirlView];
[super onEnter];
}
-(void)onExit {
if (adWhirlView) {
[adWhirlView removeFromSuperview];
[adWhirlView replaceBannerViewWith:nil];
[adWhirlView ignoreNewAdRequests];
[adWhirlView setDelegate:nil];
self.adWhirlView = nil;
}
[super onExit];
}
-(void)dealloc
{
self.adWhirlView.delegate = nil;
self.adWhirlView = nil;
[super dealloc];
}
Maybe the winSize property for your sharedDirector still thinks your in portrait? What if you flipped it so you had:
newFrame.size.width = winSize.height;
newFrame.origin.x = (self.adWhirlView.bounds.size.width - adSize.width)/2;
newFrame.origin.y = (winSize.width - adSize.height);
adWhirlView.frame = newFrame;
for those that need to know in the future, my problem turned out to be that it was calling ads for landscape instead of portrait, than when it called adjustAdSize() it wasnt getting correct sizing.
i changed
- (void)adWhirlDidReceiveAd:(AdWhirlView *)adWhirlVieww {
[adWhirlView rotateToOrientation:UIInterfaceOrientationLandscapeRight];
[self adjustAdSize];
{
to
- (void)adWhirlDidReceiveAd:(AdWhirlView *)adWhirlVieww {
[adWhirlView rotateToOrientation:UIInterfaceOrientationPortrait];
[self adjustAdSize];
{
and it fixed all my problems!