iAds trough adWhirl not fully loading - ios

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!

Related

Can not work custom vast tags on IOS (IMA Integration)

I tried to play video advertisements using the Custom Vast tag in the Google IMA integration application on macOS 12.0.1 and Xcode 13.1 but it gives the below error. I tried somany ways to but couldn't fix it. info.plist file I have shown below.
AdvancedExample[1476:21763] Error loading ads: Ads cannot be requested
because this AdsLoader failed to load
info.plist
VideoViewController.m
#import "VideoViewController.h"
#import AVFoundation;
#import "Constants.h"
typedef enum { PlayButton, PauseButton } PlayButtonType;
#interface VideoViewController () <AVPictureInPictureControllerDelegate, IMAAdsLoaderDelegate,
IMAAdsManagerDelegate, UIAlertViewDelegate>
// Tracking for play/pause.
#property(nonatomic) BOOL isAdPlayback;
// Play/Pause buttons.
#property(nonatomic, strong) UIImage *playBtnBG;
#property(nonatomic, strong) UIImage *pauseBtnBG;
// PiP objects.
#property(nonatomic, strong) AVPictureInPictureController *pictureInPictureController;
#property(nonatomic, strong) IMAPictureInPictureProxy *pictureInPictureProxy;
// Storage points for resizing between fullscreen and non-fullscreen
/// Frame for video player in fullscreen mode.
#property(nonatomic, assign) CGRect fullscreenVideoFrame;
/// Frame for video view in portrait mode.
#property(nonatomic, assign) CGRect portraitVideoViewFrame;
/// Frame for video player in portrait mode.
#property(nonatomic, assign) CGRect portraitVideoFrame;
/// Frame for controls in fullscreen mode.
#property(nonatomic, assign) CGRect fullscreenControlsFrame;
/// Frame for controls view in portrait mode.
#property(nonatomic, assign) CGRect portraitControlsViewFrame;
/// Frame for controls in portrait mode.
#property(nonatomic, assign) CGRect portraitControlsFrame;
/// Option for tracking fullscreen.
#property(nonatomic, assign) BOOL fullscreen;
/// Option for tracking load event
#property(nonatomic, assign) BOOL didRequestAds;
/// Gesture recognizer for tap on video.
#property(nonatomic, strong) UITapGestureRecognizer *videoTapRecognizer;
// IMA objects.
#property(nonatomic, strong) IMAAdsManager *adsManager;
#property(nonatomic, strong) IMACompanionAdSlot *companionSlot;
// Content player objects.
#property(nonatomic, strong) AVPlayer *contentPlayer;
#property(nonatomic, strong) AVPlayerLayer *contentPlayerLayer;
#property(nonatomic, strong) id playHeadObserver;
#end
#implementation VideoViewController
#pragma mark Set-up methods
// Set up the new view controller.
- (void)viewDidLoad {
[super viewDidLoad];
[self.topLabel setText:self.video.title];
// Set the play button image.
self.playBtnBG = [UIImage imageNamed:#"play.png"];
// Set the pause button image.
self.pauseBtnBG = [UIImage imageNamed:#"pause.png"];
self.isAdPlayback = NO;
self.fullscreen = NO;
self.didRequestAds = NO;
// Fix iPhone issue of log text starting in the middle of the UITextView
self.automaticallyAdjustsScrollViewInsets = NO;
// Set up CGRects for resizing the video and controls on rotate.
CGRect videoViewBounds = self.videoView.bounds;
self.portraitVideoViewFrame = self.videoView.frame;
self.portraitVideoFrame =
CGRectMake(0, 0, videoViewBounds.size.width, videoViewBounds.size.height);
CGRect videoControlsBounds = self.videoControls.bounds;
self.portraitControlsViewFrame = self.videoControls.frame;
self.portraitControlsFrame =
CGRectMake(0, 0, videoControlsBounds.size.width, videoControlsBounds.size.height);
// Set videoView on top of everything else (for fullscreen support).
[self.view bringSubviewToFront:self.videoView];
[self.view bringSubviewToFront:self.videoControls];
// Check orientation, set to fullscreen if we're in landscape
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft ||
[[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight) {
[self viewDidEnterLandscape];
}
// Set up content player and IMA classes, then request ads. If the user selected "Custom",
// get the ad tag from the pop-up dialog.
[self setUpContentPlayer];
[self setUpIMA];
}
// Makes the request on first appearance only.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (self.didRequestAds) {
return;
}
self.didRequestAds = YES;
if ([self.video.tag isEqual:#"custom"]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Tag"
message:#"Enter your test tag below"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
} else {
[self requestAdsWithTag:self.video.tag];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[self.contentPlayer pause];
// Don't reset if we're presenting a modal view (for example, in-app clickthrough).
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
if (self.adsManager) {
[self.adsManager destroy];
self.adsManager = nil;
}
[self removeObservers];
self.contentPlayer = nil;
}
[super viewWillDisappear:animated];
}
//Remove ContentPlayer Observer
- (void)removeObservers {
if (self.playHeadObserver) {
[self.contentPlayer removeTimeObserver:self.playHeadObserver];
self.playHeadObserver = nil;
}
#try {
[self.contentPlayer removeObserver:self forKeyPath:#"rate"];
[self.contentPlayer removeObserver:self forKeyPath:#"currentItem.duration"];
} #catch (NSException *exception) { }
}
// If pop-up dialog was shown, request ads with provided tag on dialog close.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
[self requestAdsWithTag:[[alertView textFieldAtIndex:0] text]];
}
// Initialize the content player and load content.
- (void)setUpContentPlayer {
// Load AVPlayer with path to our content.
NSURL *contentURL = [NSURL URLWithString:self.video.video];
self.contentPlayer = [AVPlayer playerWithURL:contentURL];
// Playhead observers for progress bar.
__weak VideoViewController *controller = self;
self.playHeadObserver = [controller.contentPlayer
addPeriodicTimeObserverForInterval:CMTimeMake(1, 30)
queue:NULL
usingBlock:^(CMTime time) {
CMTime duration = [controller
getPlayerItemDuration:controller.contentPlayer.currentItem];
[controller updatePlayHeadWithTime:time duration:duration];
}];
[self.contentPlayer addObserver:self forKeyPath:#"rate" options:0 context:#"contentPlayerRate"];
[self.contentPlayer addObserver:self
forKeyPath:#"currentItem.duration"
options:0
context:#"playerDuration"];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(contentDidFinishPlaying:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.contentPlayer.currentItem];
// Set up fullscreen tap listener to show controls.
self.videoTapRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(showFullscreenControls:)];
[self.videoView addGestureRecognizer:self.videoTapRecognizer];
// Create a player layer for the player.
self.contentPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.contentPlayer];
// Size, position, and display the AVPlayer.
self.contentPlayerLayer.frame = self.videoView.layer.bounds;
[self.videoView.layer addSublayer:self.contentPlayerLayer];
// Set ourselves up for PiP.
self.pictureInPictureProxy =
[[IMAPictureInPictureProxy alloc] initWithAVPictureInPictureControllerDelegate:self];
self.pictureInPictureController =
[[AVPictureInPictureController alloc] initWithPlayerLayer:self.contentPlayerLayer];
self.pictureInPictureController.delegate = self.pictureInPictureProxy;
if (![AVPictureInPictureController isPictureInPictureSupported] && self.pictureInPictureButton) {
self.pictureInPictureButton.hidden = YES;
}
}
// Handler for keypath listener that is added for content playhead observer.
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (context == #"contentPlayerRate" && self.contentPlayer == object) {
[self updatePlayHeadState:(self.contentPlayer.rate != 0)];
} else if (context == #"playerDuration" && self.contentPlayer == object) {
[self
updatePlayHeadDurationWithTime:[self getPlayerItemDuration:self.contentPlayer.currentItem]];
}
}
#pragma mark UI handlers
// Handle clicks on play/pause button.
- (IBAction)onPlayPauseClicked:(id)sender {
if (!self.isAdPlayback) {
if (self.contentPlayer.rate == 0) {
[self.contentPlayer play];
} else {
[self.contentPlayer pause];
}
} else {
if (self.playHeadButton.tag == PlayButton) {
[self.adsManager resume];
[self setPlayButtonType:PauseButton];
} else {
[self.adsManager pause];
[self setPlayButtonType:PlayButton];
}
}
}
// Updates play button for provided playback state.
- (void)updatePlayHeadState:(BOOL)isPlaying {
[self setPlayButtonType:isPlaying ? PauseButton : PlayButton];
}
// Sets play button type.
- (void)setPlayButtonType:(PlayButtonType)buttonType {
self.playHeadButton.tag = buttonType;
[self.playHeadButton setImage:buttonType == PauseButton ? self.pauseBtnBG : self.playBtnBG
forState:UIControlStateNormal];
}
// Called when the user seeks.
- (IBAction)playHeadValueChanged:(id)sender {
if (![sender isKindOfClass:[UISlider class]]) {
return;
}
if (self.isAdPlayback == NO) {
UISlider *slider = (UISlider *)sender;
// If the playhead value changed by the user, skip to that point of the
// content is skippable.
[self.contentPlayer seekToTime:CMTimeMake(slider.value, 1)];
}
}
// Used to track progress of ads for progress bar.
- (void)adDidProgressToTime:(NSTimeInterval)mediaTime totalTime:(NSTimeInterval)totalTime {
CMTime time = CMTimeMakeWithSeconds(mediaTime, 1000);
CMTime duration = CMTimeMakeWithSeconds(totalTime, 1000);
[self updatePlayHeadWithTime:time duration:duration];
self.progressBar.maximumValue = totalTime;
}
// Get the duration value from the player item.
- (CMTime)getPlayerItemDuration:(AVPlayerItem *)item {
CMTime itemDuration = kCMTimeInvalid;
if ([item respondsToSelector:#selector(duration)]) {
itemDuration = item.duration;
} else {
if (item.asset && [item.asset respondsToSelector:#selector(duration)]) {
// Sometimes the test app hangs here for ios 4.2.
itemDuration = item.asset.duration;
}
}
return itemDuration;
}
// Updates progress bar for provided time and duration.
- (void)updatePlayHeadWithTime:(CMTime)time duration:(CMTime)duration {
if (CMTIME_IS_INVALID(time)) {
return;
}
Float64 currentTime = CMTimeGetSeconds(time);
if (isnan(currentTime)) {
return;
}
self.progressBar.value = currentTime;
self.playHeadTimeText.text =
[[NSString alloc] initWithFormat:#"%d:%02d", (int)currentTime / 60, (int)currentTime % 60];
[self updatePlayHeadDurationWithTime:duration];
}
// Update the current playhead duration.
- (void)updatePlayHeadDurationWithTime:(CMTime)duration {
if (CMTIME_IS_INVALID(duration)) {
return;
}
Float64 durationValue = CMTimeGetSeconds(duration);
if (isnan(durationValue)) {
return;
}
self.progressBar.maximumValue = durationValue;
self.durationTimeText.text = [[NSString alloc]
initWithFormat:#"%d:%02d", (int)durationValue / 60, (int)durationValue % 60];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
switch (interfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
[self viewDidEnterPortrait];
break;
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationPortraitUpsideDown:
[self viewDidEnterLandscape];
break;
case UIInterfaceOrientationUnknown:
break;
}
}
- (void)viewDidEnterLandscape {
self.fullscreen = YES;
CGRect screenRect = [[UIScreen mainScreen] bounds];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
self.fullscreenVideoFrame = CGRectMake(0, 0, screenRect.size.height, screenRect.size.width);
self.fullscreenControlsFrame =
CGRectMake(0, (screenRect.size.width - self.videoControls.frame.size.height),
screenRect.size.height, self.videoControls.frame.size.height);
} else {
self.fullscreenVideoFrame = CGRectMake(0, 0, screenRect.size.width, screenRect.size.height);
self.fullscreenControlsFrame =
CGRectMake(0, (screenRect.size.height - self.videoControls.frame.size.height),
screenRect.size.width, self.videoControls.frame.size.height);
}
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
[[self navigationController] setNavigationBarHidden:YES];
self.videoView.frame = self.fullscreenVideoFrame;
self.contentPlayerLayer.frame = self.fullscreenVideoFrame;
self.videoControls.frame = self.fullscreenControlsFrame;
self.videoControls.hidden = YES;
}
- (void)viewDidEnterPortrait {
self.fullscreen = NO;
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
[[self navigationController] setNavigationBarHidden:NO];
self.videoView.frame = self.portraitVideoViewFrame;
self.contentPlayerLayer.frame = self.portraitVideoFrame;
self.videoControls.frame = self.portraitControlsViewFrame;
}
- (IBAction)videoControlsTouchStarted:(id)sender {
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:#selector(hideFullscreenControls)
object:self];
}
- (IBAction)videoControlsTouchEnded:(id)sender {
[self startHideControlsTimer];
}
- (void)showFullscreenControls:(UITapGestureRecognizer *)recognizer {
if (self.fullscreen) {
self.videoControls.hidden = NO;
self.videoControls.alpha = 0.9;
[self startHideControlsTimer];
}
}
- (void)startHideControlsTimer {
[self performSelector:#selector(hideFullscreenControls) withObject:self afterDelay:3];
}
- (void)hideFullscreenControls {
[UIView animateWithDuration:0.5
animations:^{
self.videoControls.alpha = 0.0;
}];
}
- (IBAction)onPipButtonClicked:(id)sender {
if ([self.pictureInPictureController isPictureInPictureActive]) {
[self.pictureInPictureController stopPictureInPicture];
} else {
[self.pictureInPictureController startPictureInPicture];
}
}
#pragma mark IMA SDK methods
// Initialize ad display container.
- (IMAAdDisplayContainer *)createAdDisplayContainer {
// Create our AdDisplayContainer. Initialize it with our videoView as the container. This
// will result in ads being displayed over our content video.
if (self.companionView) {
// MOE:strip_line [START ad_display_container_init]
return [[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView
viewController:self
companionSlots:#[ self.companionSlot ]];
// [END ad_display_container_init] MOE:strip_line
} else {
return [[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView
viewController:self
companionSlots:nil];
}
}
// Register companion slots.
- (void)setUpCompanions {
// MOE:strip_line [START companion_slot_declaration]
self.companionSlot =
[[IMACompanionAdSlot alloc] initWithView:self.companionView
width:self.companionView.frame.size.width
height:self.companionView.frame.size.height];
// [END companion_slot_declaration] MOE:strip_line
}
// Initialize AdsLoader.
- (void)setUpIMA {
if (self.adsManager) {
[self.adsManager destroy];
}
[self.adsLoader contentComplete];
self.adsLoader.delegate = self;
if (self.companionView) {
[self setUpCompanions];
}
}
// Request ads for provided tag.
- (void)requestAdsWithTag:(NSString *)adTagUrl {
[self logMessage:#"Requesting ads"];
// Create an ad request with our ad tag, display container, and optional user context.
IMAAdsRequest *request = [[IMAAdsRequest alloc]
initWithAdTagUrl:adTagUrl
adDisplayContainer:[self createAdDisplayContainer]
avPlayerVideoDisplay:[[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.contentPlayer]
pictureInPictureProxy:self.pictureInPictureProxy
userContext:nil];
[self.adsLoader requestAdsWithRequest:request];
}
// Notify IMA SDK when content is done for post-rolls.
- (void)contentDidFinishPlaying:(NSNotification *)notification {
// Make sure we don't call contentComplete as a result of an ad completing.
if (notification.object == self.contentPlayer.currentItem) {
[self.adsLoader contentComplete];
}
}
#pragma mark AdsLoader Delegates
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
// Grab the instance of the IMAAdsManager and set ourselves as the delegate.
self.adsManager = adsLoadedData.adsManager;
self.adsManager.delegate = self;
// Create ads rendering settings to tell the SDK to use the in-app browser.
IMAAdsRenderingSettings *adsRenderingSettings = [[IMAAdsRenderingSettings alloc] init];
adsRenderingSettings.linkOpenerPresentingController = self;
// Initialize the ads manager.
[self.adsManager initializeWithAdsRenderingSettings:adsRenderingSettings];
}
- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
// Something went wrong loading ads. Log the error and play the content.
[self logMessage:#"Error loading ads: %#", adErrorData.adError.message];
self.isAdPlayback = NO;
[self setPlayButtonType:PauseButton];
[self.contentPlayer play];
}
#pragma mark AdsManager Delegates
/*- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
[self logMessage:#"AdsManager event (%#).", event.typeString];
// When the SDK notified us that ads have been loaded, play them.
switch (event.type) {
case kIMAAdEvent_LOADED:
if (![self.pictureInPictureController isPictureInPictureActive]) {
[adsManager start];
}
break;
case kIMAAdEvent_PAUSE:
[self setPlayButtonType:PlayButton];
break;
case kIMAAdEvent_RESUME:
[self setPlayButtonType:PauseButton];
break;
case kIMAAdEvent_TAPPED:
[self showFullscreenControls:nil];
break;
default:
break;
}
}*/
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
[self logMessage:#"AdsManager event (%#).", event.typeString];
switch (event.type) {
case kIMAAdEvent_LOADED:
[adsManager start];
break;
//case kIMAAdEvent_STARTED: {
break;
case kIMAAdEvent_PAUSE:
[self setPlayButtonType:PlayButton];
break;
case kIMAAdEvent_RESUME:
[self setPlayButtonType:PauseButton];
break;
case kIMAAdEvent_TAPPED:
[self showFullscreenControls:nil];
break;
default:
break;
}
}
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdError:(IMAAdError *)error {
// Something went wrong with the ads manager after ads were loaded. Log the error and play the
// content.
[self logMessage:#"AdsManager error: %#", error.message];
self.isAdPlayback = NO;
[self setPlayButtonType:PauseButton];
[self.contentPlayer play];
}
- (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager {
// The SDK is going to play ads, so pause the content.
self.isAdPlayback = YES;
[self setPlayButtonType:PauseButton];
[self.contentPlayer pause];
}
- (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager {
// The SDK is done playing ads (at least for now), so resume the content.
self.isAdPlayback = NO;
[self setPlayButtonType:PauseButton];
[self.contentPlayer play];
}
#pragma mark Utility methods
- (void)logMessage:(NSString *)log, ... {
va_list args;
va_start(args, log);
NSString *s = [[NSString alloc] initWithFormat:[[NSString alloc] initWithFormat:#"%#\n", log]
arguments:args];
self.consoleView.text = [self.consoleView.text stringByAppendingString:s];
NSLog(#"%#", s);
va_end(args);
if (self.consoleView.text.length > 0) {
NSRange bottom = NSMakeRange(self.consoleView.text.length - 1, 1);
[self.consoleView scrollRangeToVisible:bottom];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

How to dealloc a UIView while one of its subviews is animating?

-------->
I am attempting to create a custom UIActivityIndicatorView. The custom view should behave the exactly the same as the standard view, except the image that it spins looks different. I noticed that my custom view would not deallocate when it is removed from its superview in the following test code:
ActivityIndicatorCustomView* v = [[ActivityIndicatorCustomView alloc] initWithFrame:CGRectMake(50.0f, 50.0f, 100.0f, 100.0f)];
[[UIApplication sharedApplication].keyWindow addSubview:v];
[v removeFromSuperview];
The culprit is the animation block, because when it is commented out, dealloc will be called. I believe it is a retain cycle, but I don't see how to solve the issue.
ActivityIndicatorCustomView.h
#import <UIKit/UIKit.h>
#interface ActivityIndicatorCustomView : UIView
#property(nonatomic, assign, readonly) BOOL isAnimating;
- (void)startAnimating;
- (void)stopAnimating;
#end
ActivityIndicatorCustomView.m
static const NSTimeInterval ANIMATION_PERIOD_HALF_LIFE = 1.0f;
#import "ActivityIndicatorCustomView.h"
#interface ActivityIndicatorCustomView ()
#property(nonatomic, strong) UIImageView* imageView;
#property(nonatomic, assign, readwrite) BOOL isAnimating;
- (void)animateWithTransform:(CGAffineTransform)transform;
#end
#implementation ActivityIndicatorCustomView
#pragma mark NSObject
- (void)dealloc
{
NSLog(#"dealloc");
}
#pragma mark UIView
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"activityIndicatorCustom"]];
self.imageView.frame = self.bounds;
[self addSubview:self.imageView];
}
return self;
}
- (void)didMoveToSuperview
{
if (!self.hidden && self.superview != nil) {
[self startAnimating];
}
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
if (newSuperview == nil) {
[self stopAnimating];
}
}
- (void)setHidden:(BOOL)hidden
{
if (hidden) {
[self stopAnimating];
} else if (self.superview != nil) {
[self startAnimating];
}
[super setHidden:hidden];
}
#pragma mark ActivityIndicatorCustomView
- (void)startAnimating
{
if (self.isAnimating) {
return;
}
self.isAnimating = YES;
[self animateWithTransform:CGAffineTransformMakeRotation((CGFloat)M_PI)];
}
- (void)stopAnimating
{
[self.imageView.layer removeAllAnimations];
self.isAnimating = NO;
}
#pragma mark ()
- (void)animateWithTransform:(CGAffineTransform)transform
{
// Must split the animation into two semi-circles. If
// you attempt to rotate a full circle, nothing will
// happen.
__block ActivityIndicatorCustomView* weakSelf = self;
[UIView
animateWithDuration:ANIMATION_PERIOD_HALF_LIFE
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
weakSelf.imageView.transform = transform;
} completion:^(BOOL finished) {
[weakSelf animateWithTransform:CGAffineTransformIsIdentity(transform)
? CGAffineTransformMakeRotation((CGFloat)M_PI)
: CGAffineTransformIdentity
];
}
];
}
#end
I was following a bad tutorial on retain cycles in blocks. It told me to do
__block MyViewController *weakSelf = self;
This is wrong. To create a weak reference, I should do this instead:
__weak ActivityIndicatorCustomView* weakSelf = self;
[UIView
animateWithDuration:ANIMATION_PERIOD_HALF_LIFE
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
weakSelf.imageView.transform = transform;
} completion:^(BOOL finished) {
[weakSelf animateWithTransform:CGAffineTransformIsIdentity(transform)
? CGAffineTransformMakeRotation((CGFloat)M_PI)
: CGAffineTransformIdentity
];
}
];
I think this is because you continue animating (and retain self in next [self animateWithTransform:] call) in the completion block. Try, for example, checking for the superview to decide whether to continue animating:
completion:^(BOOL finished) {
if (self.superview) {
[self animateWithTransform:CGAffineTransformIsIdentity(transform)
? CGAffineTransformMakeRotation((CGFloat)M_PI)
: CGAffineTransformIdentity
];
}
}

Custom alert view in iOS issue

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.

Adding new view controller to custom Sliding ViewController with left, right and main view controller

I have created a SlidingViewController which has a Main, Right, and Left view controllers. Now I want to add a new function/method that is called whenever one of the RightViewController's table view cell is clicked to switch the main view controller to what ever view controller is linked with that table view cell at indexpath.row. The new view controller should still be able to have this right and left view controller available. Anyone have any experience creating their own SlidingViewController or MenuViewController that can help out on how I should approach this? Any help will be gratefully appreciated. Thank you in advance.
SlidingViewController.h
#interface SlidingViewController : UIViewController <UIGestureRecognizerDelegate>
#property (retain) UIViewController *mainViewController;
#property (retain) UIViewController *leftViewController;
#property (retain) UIViewController *rightViewController;
#property (retain) NSNumber *leftSwipeEnabled;
#property (assign) BOOL leftDrawerVisible;
#property (retain) NSNumber *rightSwipeEnabled;
#property (assign) BOOL rightDrawerVisible;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil mainViewController:(UIViewController *)main leftViewController:(UIViewController *)left andRightViewController:(UIViewController *)right;
-(void)toggleLeftDrawer;
-(void)toggleRightDrawer;
#end
SlidingViewController.m
#implementation SlidingViewController
#synthesize mainViewController, leftViewController, rightViewController;
#synthesize leftDrawerVisible, rightDrawerVisible;
#synthesize leftSwipeEnabled, rightSwipeEnabled;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil mainViewController:(UIViewController *)main leftViewController:(UIViewController *)left andRightViewController:(UIViewController *)right
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
mainViewController = main;
leftViewController = left;
rightViewController = right;
leftSwipeEnabled = [NSNumber numberWithBool:NO];
rightSwipeEnabled = [NSNumber numberWithBool:NO];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self addChildViewController:self.mainViewController];
[self.view addSubview:[self.mainViewController view]];
self.mainViewController.view.frame = self.view.frame;
[self.mainViewController didMoveToParentViewController:self];
self.mainViewController.view.layer.shadowColor = [UIColor blackColor].CGColor;
self.mainViewController.view.layer.shadowOpacity = 0.2f;
self.mainViewController.view.layer.shadowRadius = 5.0f;
CGPathRef path = [UIBezierPath bezierPathWithRect:self.mainViewController.view.bounds].CGPath;
self.mainViewController.view.layer.shadowPath = path;
if(self.leftViewController != nil)
{
UISwipeGestureRecognizer *leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipe:)];
leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
leftSwipeRecognizer.delegate = self;
[self.mainViewController.view addGestureRecognizer:leftSwipeRecognizer];
}
if(self.rightViewController != nil)
{
UISwipeGestureRecognizer *rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipe:)];
rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
rightSwipeRecognizer.delegate = self;
[self.mainViewController.view addGestureRecognizer:rightSwipeRecognizer];
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self layoutShadowWithDuration:0];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
if(self.leftDrawerVisible)
[self toggleLeftDrawer];
else if(self.rightDrawerVisible)
[self toggleRightDrawer];
}
-(BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
-(void)handleSwipe:(UISwipeGestureRecognizer *)recognizer
{
if(recognizer.state == UIGestureRecognizerStateEnded)
{
if(recognizer.direction == UISwipeGestureRecognizerDirectionRight && [self.leftSwipeEnabled boolValue])
[self toggleLeftDrawer];
else if(recognizer.direction == UISwipeGestureRecognizerDirectionLeft && [self.rightSwipeEnabled boolValue])
[self toggleRightDrawer];
}
}
-(void)toggleLeftDrawer
{
if (self.rightDrawerVisible)
{
return;
}
if(self.leftDrawerVisible)
{
[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.mainViewController.view.frame = CGRectMake(0.0, 0.0, self.mainViewController.view.frame.size.width, self.mainViewController.view.frame.size.height);}
completion:^(BOOL finished)
{
[self.leftViewController.view removeFromSuperview];
[self.leftViewController willMoveToParentViewController:nil];
[self.leftViewController removeFromParentViewController];
}];
self.leftDrawerVisible = NO;
self.mainViewController.view.userInteractionEnabled = YES;
}
else
{
[self addChildViewController:self.leftViewController];
[self.view insertSubview:[self.leftViewController view] belowSubview:[self.mainViewController view]];
[self.leftViewController didMoveToParentViewController:self];
CGPathRef path = [UIBezierPath bezierPathWithRect:self.mainViewController.view.bounds].CGPath;
self.mainViewController.view.layer.shadowPath = path;
self.mainViewController.view.layer.shadowOffset = CGSizeMake(-3, 0);
NSInteger width = 260;
if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
width = 320;
self.leftViewController.view.frame = CGRectMake(0, 0, width, self.view.bounds.size.height);
[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{ self.mainViewController.view.frame = CGRectMake(width, 0, self.mainViewController.view.frame.size.width, self.mainViewController.view.frame.size.height); }
completion:^(BOOL finished) { self.leftViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin; }];
self.leftDrawerVisible = YES;
self.mainViewController.view.userInteractionEnabled = NO;
}
}
-(void)toggleRightDrawer
{
if(self.leftDrawerVisible)
return;
if(self.rightDrawerVisible)
{
[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.mainViewController.view.frame = CGRectMake(0.0, 0.0, self.mainViewController.view.frame.size.width, self.mainViewController.view.frame.size.height);
}
completion:^(BOOL finished){
[self.rightViewController.view removeFromSuperview];
[self.rightViewController willMoveToParentViewController:nil];
[self.rightViewController removeFromParentViewController];
}];
self.rightDrawerVisible = NO;
self.mainViewController.view.userInteractionEnabled = YES;
}
else
{
[self addChildViewController:self.rightViewController];
[self.view insertSubview:[self.rightViewController view] belowSubview:[self.mainViewController view]];
[self.rightViewController didMoveToParentViewController:self];
CGPathRef path = [UIBezierPath bezierPathWithRect:self.mainViewController.view.bounds].CGPath;
self.mainViewController.view.layer.shadowPath = path;
self.mainViewController.view.layer.shadowOffset = CGSizeMake(3, 0);
NSInteger width = 260;
if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
width = 320;
self.rightViewController.view.frame = CGRectMake(self.view.bounds.size.width- width, 0, width, self.view.bounds.size.height);
[UIView animateWithDuration:0.2 delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.mainViewController.view.frame = CGRectMake(-width, 0, self.mainViewController.view.frame.size.width, self.mainViewController.view.frame.size.height);
}
completion:^(BOOL finished){
self.rightViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin;
}];
self.rightDrawerVisible = YES;
self.mainViewController.view.userInteractionEnabled = NO;
}
}
-(void) layoutShadowWithDuration:(NSTimeInterval)duration
{
CGPathRef oldShadowPath = self.mainViewController.view.layer.shadowPath;
if (oldShadowPath)
{
CFRetain(oldShadowPath);
}
// Update shadow path for the view
CGPathRef path = [UIBezierPath bezierPathWithRect:self.mainViewController.view.bounds].CGPath;
self.mainViewController.view.layer.shadowPath = path;
// You would think setting duration to 0 would cause the animation added below to not animate. You would be wrong.
if (duration != 0)
{
if (oldShadowPath)
{
[self.mainViewController.view.layer addAnimation:((^ {
CABasicAnimation *transition = [CABasicAnimation animationWithKeyPath:#"shadowPath"];
transition.fromValue = (__bridge id)oldShadowPath;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.duration = duration;
return transition;
})()) forKey:#"transition"];
CFRelease(oldShadowPath);
}
else
if (oldShadowPath)
CFRelease(oldShadowPath);
}
else
if (oldShadowPath)
CFRelease(oldShadowPath);
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self layoutShadowWithDuration:duration];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
You can simply do this by "Delegation Design Pattern"
In RightViewController.h add the following lines.
#protocol RightViewControllerDelegate <NSObject>
#required
- (void)somethingClicked : (id)theObject;
#end
#interface RightViewController : UIViewController
#property (nonatomic, assign) id<RightViewControllerDelegate> delegate;
#end
In RightViewController.m add the following lines.
- (void)somethingClicked : (id)theObject
{
[_delegate somethingClicked:theObject];
}
Update MainViewController.h with the following code.
#interface MainViewController : UIViewController <RightViewControllerDelegate>
And Finally add the following code in the MainViewController.m
- (void)somethingClicked : (id)theObject
{
// Perform Your Task
}

iAd covers app content in phonegap?

I have this in my webViewDidFinishLoad:
- (void)setupAdBanner {
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
CGRect adFrame = adView.frame;
if([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait
|| [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown) {
adView.currentContentSizeIdentifier =
ADBannerContentSizeIdentifierPortrait;
adFrame.origin.y = self.view.frame.size.height-adView.frame.size.height;
} else {
adView.currentContentSizeIdentifier =
ADBannerContentSizeIdentifierLandscape;
adFrame.size.width = adView.frame.size.width;
adFrame.origin.y = self.view.frame.size.height-adView.frame.size.height;
}
adView.frame = adFrame;
[self.view addSubview:adView];
}
This overlaps HTML content in my phonegap application. How do I adjust my webview frame sizes to account for the ad banner?
I had this exact problem. I blogged about my solution here http://hawkinbj.wordpress.com/2013/04/16/implement-iad-banner-ads-without-covering-uiwebview-in-phonegap/
You need to implement ADBannerViewDelegateProtocolReference. In MainViewController.h:
#interface MainViewController : CDVViewController <ADBannerViewDelegate>
{
ADBannerView *adView;
}
#end
The rest of the steps are in MainViewController.m.
In webViewDidFinishLoad:
adView.delegate = self;
Add these two methods:
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
CGRect resizedWebView = [super webView].frame;
resizedWebView.size.height = adView.frame.origin.y;
[super webView].frame = resizedWebView;
[self.view bringSubviewToFront:adView];
adView.hidden = NO;
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
CGRect resizedWebView = [super webView].frame;
resizedWebView.size.height = self.view.frame.size.height;
[super webView].frame = resizedWebView;
adView.hidden = YES;
}
The magic is
[self.view bringSubviewToFront:adView];

Resources