I'm testing iAds in XCode 4.
Everything works fine, until the first time a bannerView:didFailToReceiveAdWithError: is received, which I react to by sliding the banner off the screen.
//move the ad back off the screen if an error occurs
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
if (self.bannerIsInScreenBounds)
{
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
// move the banner view off the screen.
banner.frame = CGRectOffset(banner.frame, 320, 0);
[UIView commitAnimations];
}
}
After that, no more bannerViewDidLoadAd: messages are sent to the ADBannerViewDelegate. I'm logging that method right at the top, it's not being called any more.
I'm not releasing the banner or anything, and the ADBannerViewDelegate class is still there and doing other stuff.
What could be wrong?
Thanks.
Why do you expect it load adverts after an error has happened - I think this is the correct behavior.
Looking at the comments it show that the error is "The operation couldn’t be completed. Ad inventory unavailable".
How do you expect it to give you adverts if it can't find any adverts to give ;)
OK, not an ideal solution but here's what I ended up doing.
Whenever I get a didFailToReceiveAdWithError, I wait 10 seconds (to avoid spamming with failures) then recreate the banner.
-(void)replaceAdView {
UIView *adViewSuperview = [adView superview];
[adView removeFromSuperview];
[adView release];
//starting off the screen again
adView = [[NSClassFromString(#"ADBannerView") alloc] initWithFrame:CGRectMake(320, 382, 320, 50)];
adView.delegate = self;
if (adViewSuperview) {
[adViewSuperview addSubview:adView];
}
self.bannerIsInScreenBounds = NO;
}
As my comment at how to implement AdBannerview and ADBannerview delegate, running iphone app in ipad simulator I got didFailToReceiveAdWithError immediately on setting the ADBannerView delegate, and never another delegate call. Running it on the iphone simulator (or changing the app target to universal) the delegate only got called after adding ADBannerView as a subview, and then delegate calls every 30 secs after that.
Related
I am struggling to hide a banner view when a purchase is made.
I have 2 separate versions, one is an Admob banner (bannerView_), the other is actually a view which I called _adView they share the same place but rotate around depending on what is viewing.
Anyhow, the Admob banner hides no problem, but the _adView does not, here is hiding code;
-(void)removeBanner:(NSNotification *) notify {
NSLog(#"Removing:");
if ([MKStoreManager isFeaturePurchased:#"com.fredsworld.ubercool.removeads"]) {
[bannerView_ setHidden:YES];
[_adView setHidden:YES];
NSLog(#"Removed:");
}
}
Basically that runs on a purchase, so it updates the screen instantly,
The _adView code to call it in the viewDidLoad is;
CGFloat y = self.view.frame.size.height - 50.0;
TapForTapAdView *adView = [[TapForTapAdView alloc] initWithFrame: CGRectMake(0, y, 320, 50) delegate: self];
[self.view addSubview: adView];
I have synthesized adView and created it as an object, but still no joy, it does not disappear when the purchase is made.
Although, it DOES work, as if you close the app, then re open, it has gone but obviously I want it to disappear immediately upon purchase.
Any ideas?
it was solved by removing the TapForTapAdView *adView on line 2 and simply changing to self.adView =
I would like to ask the following questions:
1) How to hide iAD when the user clicks on the empty screen?
2) How to identify inactivity i.e. If user has an opened some application and leave the iphone and went away and application remained open?
Update:
According the apple documentation, this method is responsible for dismissing the iAD. but this method is still not working in my code. Any sample or how this method works?
- (void)cancelBannerViewAction
Explanation:
A banner view action can cover your application’s user interface. However, your application continues to run, and receives events normally. If your application receives an event that requires the user’s attention, it can programmatically cancel the action and uncover its interface by calling cancelBannerViewAction. Canceling actions frequently can cause a loss of revenue for your application.
Reference from Apple
But still I am unable to execute? This method is not working properly
You can just do something like below code.
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
if (!self.adBannerViewIsVisible)
{
NSLog(#"\nBanner Success");
[UIView beginAnimations:#"animateAdBannerOn" context:NULL];
// assumes the banner view is offset 50 pixels so that it is not visible.
banner.frame = CGRectOffset(banner.frame,0,-94);
[UIView commitAnimations];
self.adBannerViewIsVisible = YES;
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (self.adBannerViewIsVisible)
{
NSLog(#"\nBanner Failed");
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0, 94);
[UIView commitAnimations];
self.adBannerViewIsVisible = NO;
}
}
Just specify location of iAd in your code then you can change it's position by just changing value in this line
banner.frame = CGRectOffset(banner.frame, 0, 94);`
Hope this may clear what you want.
I have an iAd which shows up fine when connected to the Network. On the iOS simulator or testing on my device, if I open up my app, see the iAd, then go to settings and turn on airplane mode, and return to the app, the banner slide off the screen. Great. Now, if I turn airplane mode back off (network is ON), the iAd doesn't reappear - even after waiting for 10-15 minutes.
So, here are my questions:
Does the iAd Test Advertisement refresh itself the same as a real iAd would (every minute or so)?
Is there a way to force the iAd to refresh and request a new ad when the network is detected?
I just can't find information on the behaviour of the Test Ads anywhere, and I can't test with real Ads until I upload the app to the App Store (right?)
Heres my code:
Where the iAd is created:
- (void)viewDidLoad
{
adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, 410, 320, 50)];
adView.frame = CGRectOffset(adView.frame, 0, 50);
adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
[self.view addSubview:adView];
adView.delegate=self;
self.bannerIsVisible=NO;
[super viewDidLoad];
}
And the delegate methods:
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
NSLog(#"AdWin");
if (!self.bannerIsVisible)
{
[UIView beginAnimations:#"animateAdBannerOn" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0, -50);
[UIView commitAnimations];
self.bannerIsVisible = YES;
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
NSLog(#"AdLose");
if (self.bannerIsVisible)
{
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0, 50);
[UIView commitAnimations];
self.bannerIsVisible = NO;
}
}
The delegate method NSLog calls only appear once - not every minute, like I would expect if the Ad was getting refreshed.
1- yes and like live ads there are some times with no ad at all, it can be hours. I believe the refresh cycle is 3 minutes but it seems apple can change it as they will
2- you shouldn't need to, when properly setup this happens automatically. I have an app with ads and it behaves correctly when switching network or using the airplane setting
Now, there seems to be something about the airplane setting, see this thread : iAds Loading Throttled After Re-Launching App From Background (Also Happens In iAdSuite), but I don't have the final answer. Maybe you could explore more by changing your NSLog in didFail... to NSLog(#"%#", error) to check what it exactly says.
Ah and indeed there is no way to test with real ads until it's accepted in the appstore.
I have an iAd which displays at the top of a fullscreen subview of the main view. The iAd works normally in portrait mode, and I have handled rotation of the iAd banner view into landscape mode. The issue occurs when the iAd is tapped by the user in landscape mode. The test advertisement displays in portrait, sideways on the phone, and when the user taps the x to dismiss the iAd, the banner view and its parent view are pushed offscreen. The iAd behaves normally in portrait mode (i.e. tapping it and closing it results in the view containing the banner to be displayed normally).
Things I have tried:
- (void)bannerViewActionDidFinish:(ADBannerView *)banner{
NSLog(#"Ad was closed, show the adView again");
if(UIInterfaceOrientationIsLandscape(currentInterfaceOrientation)){
[self animateRotationToLandscape:0.3f];
}
else{
[self animateRotationToPortrait:0.3f];
}
}
-(void)animateRotationToPortrait:(NSTimeInterval)duration{
self.adView.currentContentSizeIdentifier =
ADBannerContentSizeIdentifierPortrait;
BOOL iPad = NO;
#ifdef UI_USER_INTERFACE_IDIOM
iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#endif
if (iPad) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:duration];
proUpgradeDescription.frame = CGRectMake(82,313,604,110);
proUpgradePrice.frame = CGRectMake(313,576,142,28);
closeButton.frame = CGRectMake(348,834,72,37);
purchaseButton.frame = CGRectMake(313,431,142,142);
[UIView commitAnimations];
}
else{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:duration];
proUpgradeDescription.frame = CGRectMake(20,80,280,70);
proUpgradePrice.frame = CGRectMake(88,322,142,28);
closeButton.frame = CGRectMake(123,403,72,37);
purchaseButton.frame = CGRectMake(88,172,142,142);
[UIView commitAnimations];
}
}
Which calls code that I use to animate rotation of the display for portrait and landscape mode. This code has no effect.
If anyone has any ideas as to why the test advertisements don't rotate correctly and why they push the parent view controller off the screen I would greatly appreciate it.
I don't know if this addresses all of your problems, but according to the answer on this question, the test ads are only in portrait, and real ads will show up in both orientations.
I know the question is a little old so I'm posting here just in case someone runs into the same problem (I did).
ADBannerView messes with the frame and transform properties of the parent view so all you have to do is to reset them to their original values after it has finished (in bannerViewActionDidFinish:).
I still don't understand why it doesn't put back everything the way it was after it has finished. We shouldn't have to do this.
This drove me nuts too. Delivering only landscape full page ads to the iPad and portrait to the iPhone and not saying so is asking for trouble. I gave up using the iAdSuite code, which caused the Landscape iPad ad to leave the screen in Landscape even when the device was in portrait!
This is my code for banner ads. It is all in the first view controller loaded. It aims to put the banner at the bottom of the screen.
In the header file:
#import "iAd/ADBannerView.h"
#property (strong, nonatomic) ADBannerView* adView;
#interface myViewController : UIViewController <ADBannerViewDelegate,
in viewDidLoad
CGRect contentFrame = self.view.bounds;
CGRect bannerFrame = CGRectZero;
bannerFrame.size = [adView sizeThatFits:contentFrame.size];
bannerFrame.origin.y = contentFrame.size.height-bannerFrame.size.height;
adView = [[ADBannerView alloc] initWithFrame:bannerFrame];
[adView setDelegate:self];
[self.view addSubview:adView];
Then
-(void)viewWillLayoutSubviews {
CGRect contentFrame = self.view.bounds;
CGRect bannerFrame=CGRectZero;
bannerFrame.size = [adView sizeThatFits:contentFrame.size];
if (adView.bannerLoaded) {bannerFrame.origin.y = contentFrame.size.height-bannerFrame.size.height;}
else {bannerFrame.origin.y = contentFrame.size.height;}
[adView setFrame:bannerFrame];}
Then to handle the callbacks from iAd we need to tell the view to redo its layout if something changes:
- (void)bannerViewDidLoadAd:(ADBannerView *)banner{
[UIView animateWithDuration:0.25 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
[UIView animateWithDuration:0.25 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];}
This seems to handle the orientation correctly on both iPad and iPhone except for the test full page ads. However, the screen assume correct orientation after the test ad is dismissed so I am hoping it is all OK.
I just upgraded my iPhone 4 from iOS 4.2.1 to 4.3.2, and to XCode 4.0.2, and I am encountering some bizarre issues with uiview animations. When I first launch my app, code like this executes perfectly:
[UIView beginAnimations:#"fadeAlphaIn" context:nil];
[UIView setAnimationDuration:0.5f];
viewClue.alpha = 1.0f;
[UIView commitAnimations];
But then, after dismissing a presenting and then dismissing a modal view by the standard method:
[self presentModalViewController:more animated:YES];
and
[self dismissModalViewControllerAnimated:YES];
the first animation no longer works. Instead of fading in, for example, the viewClue view simply jumps from alpha = 0 to alpha = 1. Similarly, other animations altering other views' frame property just force the frame to jump from the initial to final value without animation. These animations worked fine before the modal view was presented and dismissed.
I understand that others have experienced animation issues with the upgrade to iOS 4.3.2, but the way the modal view disrupts animation seems very odd. Has anyone else experienced this problem? Any ideas as to a solution? I'm thinking of just adding the modal view as a subview and animation it as it hides and appears, but using the standard modal view method would be much preferred.
Thanks for your help,
James
EDIT: Some more code showing how the app's map is animated
-(void) viewMapfunc
{
AudioServicesPlaySystemSound(soundID);
if(mapvisible){
[UIView animateWithDuration:0.5
delay:0.1
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
map.frame = CGRectMake(0, 350, 320, 27);
mapscroll.frame = CGRectMake(0, 27, 320, 0);
}
completion:nil];
mapvisible = NO;
viewMapLabel.text = #"View Map";
}else {
[UIView animateWithDuration:0.5
delay:0.1
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
map.frame = CGRectMake(0, 50, 320, 300);
mapscroll.frame = CGRectMake(0, 27, 320, 300);
}
completion:nil];
mapvisible = YES;
viewMapLabel.text = #"Hide Map";
}
}
Try to check two things:
Do you commit all started animations? I got all kinds of strange effects after not committing one of them.
Do any animations take place in the same time? Especially with the same view.
Whether any animations take place right after changing properties. Something like:
-
view.alpha = 1;
[UIView beginAnimations:…];
view.alpha = 0;
[UIView commitAnimations:…];
In this example, view will not change it's alpha value from 1 to 0. It will change it instantly. To start an animation you have to extract animations block to another method and call it with performSelectorInMainThread:withObject:afterDelay:. Delay can be even 0.
I solved it by restarting my animation in my UIView subclass:
override func willMove(toWindow newWindow: UIWindow?) {
if newWindow != nil {
spinner.startSpinning() // Restart any animation here
}
}
In the end, I just removed all modal views and implemented them in other ways. For some reason, using modal views messed up animations. Makes no sense, but removing them fixed the problem. If anyone can enlighten me as to why this is going on, it might be nice for memory concerns...
I had the same issue. The root of my trouble was that my animation was being triggered by a notification, and I was adding an observer on each viewWillAppear, but forgot to remove in viewDidDisappear (remember that iOS 6 no longer calls viewDidUnload reliably).
Essentially, I was calling my animation function twice in quick succession, which was causing the visible irregularity. Hopefully this helps someone out down the line!
I've managed to solve this same issue in my own application.
I noticed while debugging that my UIImageViews which I was animating had different memory addresses before and after I pushed my modal view controller(s). At no other time did these UIImageViews switch their memory addresses.
I thought this might have been the root of the issue and it seems I was right.
My client's code had been allocating/initializing my View Controller's UIImageViews in
-viewDidAppear instead of in -viewDidLoad. Thus, every time I launched and dismissed a modal view controller my UIImageViews I was animating would get reinitialized.
Check for yourself if your map object's memory address is changing before and after you launch your modals, and if it is be sure to move your initialization logic to a more proper section of your code.
Hope this helps you!
Dexter
I was using UIView animateWithDuration: and I solved it by not using the completion block. This is code from a subclassed UIView. In the view controller's viewWillAppear: I set self.shouldAnimate to YES, and in the view controller's viewWillDisappear: I set self.shouldAnimate to NO.
-(void)continueRotate {
if (self.shouldAnimate) {
[self rotateRadarView:self.radarInner];
}
}
-(void)rotateRadarView:(UIView *)view {
[UIView animateWithDuration:0.6 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(continueRotate)];
[view setTransform:CGAffineTransformRotate(view.transform, M_PI_2)];
}completion:nil];
}