How do I hide iAd banners when no ads are being served? - iphone

Anyone able to offer a little help on this? I just received feedback from Apple advising my app could not be accepted because it contained adbanners that were still visible when no ads were being served, trouble is I can't figure out quite what to do to prevent this problem.
[QUOTE]
We've completed the review of your
application; however, we cannot post
this version to the App Store because
it displays an empty iAd banner when
ad content is not available. The
banner within the app should be hidden
whenever ad content is not being
served by iAd. We have included
additional details below to help
explain the issue. We hope that you'll
consider revising and resubmitting
your application.
To handle the case where ad content is
not available, you will need to
implement a banner view delegate. An
example code snippet is included here
for your convenience. Additionally,
you may wish to review the section
"Working with Banner Views" of the iAd
Programming Guide for specific
details:
https://developer.apple.com/iphone/prerelease/library/documentation/UserExperience/Conceptual/iAd_Guide/WorkingwithBannerViews/WorkingwithBannerViews.html
Banner View Delegate to Remove a
Banner View When Advertisements are
Not Available:
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (self.bannerIsVisible)
{
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
// assumes the banner view is at the top of the screen.
banner.frame = CGRectOffset(banner.frame, 0, -50);
[UIView commitAnimations];
self.bannerIsVisible = NO;
}
}
Now what I'm struggling withs is what to do with that code, when I've tried putting it in it just throws out several red errors so I come seeking advice, anyone able to help me out here?
EDIT:
Main viewcontroller Code as requested by a poster
//
// MainViewController.m
// GBSoundboard4
//
// Created by David Clarke on 19/06/2010.
// Copyright __MyCompanyName__ 2010. All rights reserved.
//
#import "MainViewController.h"
#import <AVFoundation/AVAudioPlayer.h>
#implementation MainViewController
-(IBAction)goodafternoon {
NSString *path = [[NSBundle mainBundle] pathForResource:#"goodafternoon" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[theAudio play];
}
-(IBAction)jollygood {
NSString *path = [[NSBundle mainBundle] pathForResource:#"jollygood" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[theAudio play];
}
-(IBAction)playSound {
NSString *path = [[NSBundle mainBundle] pathForResource:#"goodmorning" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[theAudio play];
}
-(IBAction)upgrade {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://itunes.apple.com/gb/app/the-great-british-soundboard/id376263018?mt=8"]];
}
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller {
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)showInfo:(id)sender {
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)dealloc {
[super dealloc];
}
#end

What you need to do is this event
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError
*)
Is make your view that is with the bannerView cover up the banner by resizing its frame to cover the bannerView space on your screen and move the origin of the bannerView frame outside the screen
B
then on - (void)bannerViewDidLoadAd:(ADBannerView *)banner
resize your view to make room for the BannerView and move the origin of the bannerView frame back to the space on the screen.

There is a GREAT example of how to implement this in WWDC 2010 session video 112. If you are enrolled in the iPhone developer program, you can download it from iTunes University, as described below.
Assuming you are in the Apple Developer Program, you received an Email entitled "WWDC for everyone." Follow the links in that Email until you get to iTunes University. Then follow the link for frameworks, and pick session 112. I think the implementation is at approximately the 25 minute mark.

You need to do exactly what they describe. First, you need to make your MainViewController the delegate for your ADBannerView instance. Then, just copy and paste the code they've handed you into your MainViewController's implementation. This assumes that your banner appears at the bottom of the screen. If it appears at the top, reverse the direction of animation in the code they've provided.
If your banner fails to load an ad (which it will do until July 1 when the service goes live, and even after that if not attached to the network or if inventory drops), this delegate method will be called. Additionally, you can respond to other delegate callbacks that are described in the ADBannerViewDelegate protocol.
As they suggest, this is covered in the appropriate section of the iAd Programming Guide.

Related

When using storyboards, and changing a view, sound will not stop playing in new view

I am trying to do something similar to what was requested in this question:
Playing audio with controls in iOS
I am using Storyboards with XCode 4.2. On my initial view page, I just have buttons that call other views, and no sounds are played there. These other views contain a UINavigationController with a BarButtonItem to allow you to go back. Other view pages will have buttons that allow one to play a sound. Each sound has its own play button, and there are resume, pause and stop buttons.
All sounds play fine, but if I hit the back button to the main page, the sound keeps playing. The desired behavior is for the sound to stop when navigating back to the main page via the back button.
Before storyboards, I could easily code a back button to stop the audio, but storyboards appear not that simple. It appears that I have to implement the method prepareForSegue. Okay, I can set the Segue identifier can be set in the Attributes Inspector, and referring back to the earlier post, I will use showPlayer.
But I was thinking I could code the prepareForSegue in one of my sound views, as seen in this cool example:
http://www.scott-sherwood.com/?p=219
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"showPlayer"]){
SoundPageController *theAudio = (SoundPageController *)[segue ViewController];
theAudio.delegate = self;
}
}
In the main page ViewController.m, I tried adding:
#property (strong, nonatomic) AVAudioPlayer *theAudio;
And I tried adding something like:
- (void)viewDidLoad {
[super viewDidLoad];
// this is the important part: if we already have something playing, stop it!
if (audioPlayer != nil)
{
[audioPlayer stop];
}
// everything else should happen as normal.
audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:url
error:&error];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
I wasn't able to get this to work, so I reverted the changes back to original. I will put my simplified code below, and if you have suggestions how to do it right, please let me know!
ViewController.h:
#interface ViewController : UIViewController {
}
ViewController.m (pretty much default):
#import "ViewController.h"
#import "AppDelegate.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
SoundPage1.h:
#import
#import <AVFoundation/AVAudioPlayer.h>
#interface occupy : UIViewController <AVAudioPlayerDelegate> {
AVAudioPlayer* theAudio;
}
//-(IBAction)PressBack:(id)sender; now the back button is linked up through storyboard
-(IBAction)pushButton1;
-(IBAction)pushButton2;
-(IBAction)play;
-(IBAction)stop;
-(IBAction)pause;
#end
SoundPage1.m
#import "SoundPage1.h"
#import "AppDelegate.h"
#import "ViewController.h"
#implementation SoundPage1
-(IBAction)pushButton {
NSString *path = [[NSBundle mainBundle] pathForResource:#"sound1" ofType:#"mp3"];
if(theAudio)[theAudio release];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
theAudio.volume = 1.0;
[theAudio play];
}
-(IBAction)pushButton2 {
NSString *path = [[NSBundle mainBundle] pathForResource:#"sound2" ofType:#"mp3"];
if(theAudio)[theAudio release];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
theAudio.volume = 1.0;
[theAudio play];
}
// Old code from XCode 3.x when creating a back button that could stop the audio was easy
//-(IBAction)PressBack:(id)sender{
// [theAudio stop];
// ViewController* myappname = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
// [self.navigationController pushViewController:myappname animated:NO];
// }
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
Add in the code for play, stop and pause for the buttons.
I tried to format this, sorry in advance if it is hard to read.
Thanks for any suggestions!
Rob
You should stop the AVAudioPlayer in viewWillDisappear.
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if(theAudio && theAudio.isPlaying) {
[theAudio stop];
}
}
ViewDidUnload is only called by the program when the device is reaching the end of memory capacity, not when you change views. Only just found this out myself this week, while struggling with the same problem.
Hope that clears things up.

Frustrating UIWebView Delegate Crash issue

I've created an ARC Application that run's perfect. It's got a UINavigationController that I use to push through the views and everything runs fine.
I'm converting the Application to iPad and i've decided to show one of the views as a popover. (I don't like UIPopoverController so i've created my own basic popup). It's added to the view as follows..
MyViewController *hotelinf = [[MyViewController alloc]
initWithNibName:#"MyViewController_iPad" bundle:nil];
[self.view addSubview:hotelinf.view];
The view is added as a subview fine. The view i'm adding contains a UIWebView that has the usual delegate methods in it, but when the view tries to access one of the delegates it simply crashes.
*** -[MyViewController respondsToSelector:]: message sent to deallocated instance 0x7917b90
Specifically, it crashes on this line..
[self.webView loadHTMLString:stringResponse baseURL:nil];
I've displayed views (and UINavigationControllers) as subViews many of times without any issues, although none of them included a UIWebView delegate. I'm guessing I have to set the delegate of my UIViewController istance but i'm not sure how. It's also worth noting that if I push the view in my existing UINavigationController it calls and loads the HTML fine, which surely means it has nothing to do with the code of the view itself.
Any help would be greatly appreciated! Here is the code (in addition to above that shows the controller)..
.h
#interface MyViewController : UIViewController <UIWebViewDelegate, UIActionSheetDelegate> {
//Unrelated IBOutlets
}
#property (nonatomic, strong) UIWebView *webView;
#end
.m
#implementation MyViewController
#synthesize webView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.webView = [[UIWebView alloc]initWithFrame:CGRectMake(317,283,393,354)];
self.webView.delegate = self;
[self.view addSubview:self.webView];
[NSThread detachNewThreadSelector:#selector(getHTMLString) toTarget:self withObject:nil];
}
-(void)getHTMLString {
#autoreleasepool {
//Download a valid HTML String
[self performSelectorOnMainThread:#selector(loadHTML) withObject:nil waitUntilDone:NO];
}
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
self.webView = nil;
}
-(void)loadHTML {
self.webView.opaque = NO;
self.webView.backgroundColor = [UIColor clearColor];
if ([stringResponse isEqualToString:#""]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Could not connect to XXXXX.com. Please verify you are connected to a working 3G/WIFI Network." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
} else {
//it crashes here only when loaded as a subview - the first access to the delegate
[self.webView loadHTMLString:stringResponse baseURL:nil];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self stopIndicator];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
if (error.code == NSURLErrorCancelled) return; // this is Error -999
[self stopIndicator];
// report the error inside the webview
NSString* errorString = [NSString stringWithFormat:
#"<html><center><font size=+10 color='black' face='Helvetica'>An error occurred:<br>%#</font></center></html>",
error.localizedDescription];
[self.webView loadHTMLString:errorString baseURL:nil];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Cannot load URL."
message:#"You have a connection failure. Please verify you are connected to a WIFI or 3G enabled Network."
delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}
#end
The issue has nothing to do with the UIWebView, rather with your controller class. Indeed,
MyViewController *hotelinf = [[MyViewController alloc]
initWithNibName:#"MyViewController_iPad" bundle:nil];
[self.view addSubview:hotelinf.view];
You are allocating the controller and assigning it to a local variable; then you add the controller's view as subview to your current view. Doing that, that view is retained, but what happens to the controller object itself? Are you releasing it? Or it leaks (since it is assigned to a local variable)?
This possibly explains why when later the respondsToSelector method is called, the controller has already been deallocated...
A way to fix this is creating a new property or an ivar in your main controller class and store MyViewController in there. Don't forget to release it in dealloc.
I would also suggest another thing. In:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
self.webView = nil;
}
set the webView delegate to nil before releasing the view:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
self.webView.delegate = nil;
self.webView = nil;
}
And I would also possibly review the reason why you release the webView in viewDidDisappear. On the other hand you allocate it in viewDidLoad. This asymmetry is dangerous, since whenever the main view disappears (for any reason) the webView will be removed and when the view reappears, it is not there anymore.
Better add all the delegate methods. You havent added the first two. Most probably, your code is crashing when message webViewDidStartLoad is sent
– webView:shouldStartLoadWithRequest:navigationType:
– webViewDidStartLoad:
– webViewDidFinishLoad:
– webView:didFailLoadWithError:

cocos2d Scene goes black after GameCenter leaderboard dismissal

Im having a strange problem that only occurs on the iPad version of my game. When I bring up the GameCenter leaderboard, it appears like normal. No issues there. But when you tap the close button the leader board disappears and the cocos2d scene goes black. No errors, nothing. Nothing I do can bring the screen back. Ive tried resuming the director and even tried some solutions on a similar thread.
Here is my code in the cocos2d scene. GCController is just a subclass of the RootViewController, nothing special:
tempVC = [[GCController alloc] init];
GKLeaderboardViewController *leaderboardController = [[[GKLeaderboardViewController alloc] init] autorelease];
if (leaderboardController != nil)
{
leaderboardController.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardController.category = [NSString stringWithFormat:#"%#%#", [self cleanString:selectedSong], #"TotalHD"];
leaderboardController.leaderboardDelegate = self;
[[[CCDirector sharedDirector] openGLView] addSubview:tempVC.view];
[tempVC presentModalViewController:leaderboardController animated:YES];
}
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
[tempVC dismissModalViewControllerAnimated:YES];
[tempVC.view.superview removeFromSuperview];
[tempVC release];
}
Anyone have any ideas? If I can provide any more information let me know. Thanks.
You are not providing enough code. I see no fault in the code you are showing at the moment. Your most likely cause of a black screen (depending on how you do things) is that timers have been interrupted and you may need to reset them with
- (void) onEnter;
or
- (void) onEnterTransitionDidFinish;
If that isn't it then post more code and I will check back. We need to see when the view is presented and what it should return to.
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
[tempVC dismissModalViewControllerAnimated:YES];
**[tempVC.view removeFromSuperview];**
}

Iphone: controlling text with delay problem with UIWebView

I've opted to use UIWebView so I can control the layout of text I've got contained in a local html document in my bundle. I want the text to display within a UIWebView I've got contained within my view. So the text isn't the whole view, just part of it.
Everything runs fine, but when the web page loads I get a blank screen for a second before the text appears. This looks really bad. can anyone give me an example of how to stop this happening? I'm assuming I have to somehow hide the web view until it has fully loaded? Could someone one tell me how to do this?
At the moment I'm calling my code through the viewDidLoad like this:
[myUIWebView loadRequest: [NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:#"localwebpage" ofType:#"html"] isDirectory:NO]]];
Any help is much appreciated. I've read round a few forums and not seen a good answer to this question, and it seems like it recurs a lot as an issue for beginners like myself.
Thanks for taking the time to read this post!
UPDATED info
Thanks for your response. The suggestions below solves the problem but creates a new one for me as now when my view loads it is totally hidden until I click on my toggle switch. to understand this it's maybe most helpful if I post all my code. Before this though let me explain the setup of my view. I've got a standard view within which I've also got two web views, one on top of the other. each web view contains different text with different styling. the user flicks between views using a toggle switch, which hides/reveals the web views. I'm using the web views because I want to control the style/layout of the text. Below is my full .m code, I can't figure out where it's going wrong. My web views are called oxford & harvard I'm sure its something to do with how/when I'm hiding/revealing views. I've played around with this but can't seem to get it right. Maybe my approach is wrong. A bit of advice ironing this out would be really appreciated:
#implementation ReferenceViewController
#synthesize oxford;
#synthesize harvard;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
[oxford loadRequest: [NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:#"Oxford" ofType:#"html"] isDirectory:NO]]];
[harvard loadRequest: [NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:#"Harvard" ofType:#"html"] isDirectory:NO]]];
[oxford setHidden:YES];
[harvard setHidden:YES];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if([webView hidden]) {
[oxford setHidden:NO];
[harvard setHidden:NO];
}
}
//Toggle controls for toggle switch in UIView to swap between webviews
- (IBAction)toggleControls:(id)sender {
if ([sender selectedSegmentIndex] == kSwitchesSegmentIndex)
{
oxford.hidden = NO;
harvard.hidden = YES;
}
else
{
oxford.hidden = YES;
harvard.hidden = NO;
}
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
[oxford release];
[harvard release];
}
#end
Sure, in your UIViewController's designated initializer, set the hidden property of the UIWebView instance to YES:
[webView setHidden:YES];
Then, implement the UIWebViewDelegate method - (void)webViewDidFinishLoad:, and perform an if check inside the method like this:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if([webView hidden]) {
[webView setHidden:NO];
}
}
Also, don't forget to specify that your class conforms to the UIWebViewDelegate protocol:
#interface YourViewController : UIViewController <UIWebViewDelegate> {...}

how to play different audio files with same media player in a separate view- iphone sdk?

I've been trying and researching for countless hours but for some reason I just cant get my head around it and I know its a simple answer. Please Help!
I have a view with different buttons, -(ScrollViewController1)
the different buttons push in one view, -(b1ViewController)
this view contains the media player,
In a nutshell, I cant figure out how to get the media player to play a different audio file depending on which button in the first view was pressed.
I'm trying not to make a different view with a different media player for every button.
Could someone demonstrate it please so that I can understand it? Thanks a million.
Heres the relevant code-
(ps- theres a reason for the tags, I didnt want to get too much into for the sake of asking a clear question and keeping it straight forward.)
#implementation ScrollViewController1
- (IBAction)pressedb1view {
if (thebutton.tag==101) {
[self performSelector:#selector(dismissb1pop:) withObject:nil afterDelay:0.1];
b1view.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:b1view animated:YES];
}
if (thebutton.tag==102) {
[self performSelector:#selector(dismissb1pop:) withObject:nil afterDelay:0.1];
b1view.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:b1view animated:YES];
}
if (thebutton.tag==103) {
[self performSelector:#selector(dismissb1pop:) withObject:nil afterDelay:0.1];
b1view.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:b1view animated:YES];
}
}
etc, etc, etc....
in the next view which contains the mediaplayer I have-
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#interface b1ViewController : UIViewController {
MPMoviePlayerController *moviePlayer;
NSURL *movieURL;
}
in the .m -
-(void)viewWillAppear:(BOOL)animated {
[[self navigationController] setNavigationBarHidden:NO animated:YES];
NSString *urlStr = [[NSBundle mainBundle] pathForResource:#"music1" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:urlStr];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
[self.view addSubview:moviePlayer.view];
moviePlayer.view.frame = CGRectMake(0, 0, 320, 40);
[moviePlayer play];
}
EDIT:
Im passing text from the first view to a uilabel on the second view using the following in the first view-
[b1view changeSiteText:#"im stuck here"];
in the second view Im doing this in the .h-
- (IBAction) changeSiteText:(NSString *)str;
and in the .m im doing this-
- (IBAction) changeSiteText:(NSString *)str{
lblSiteTxt.text = str;
}
Is there a way to implement a similar method for the mediaplayer,??? maybe doing
something like
NSString *urlStr = [[NSBundle mainBundle] pathForResource:#"%#" ofType:#"mp3", str];
Im stuck!!
Help!
Do you push the view or present it?
Add a method in the player class which when passed various arguments it plays the appropriate track or whatever. Then the different IBActions will invoke this method.