So I have a game that has a game over class. I also have an iAd banner at the bottom of the screen, but it stays there for the entire length of the game. I want the banner to appear when the game ends, and disappear when the user presses the restart game button.
In my RootViewController.mm I have the following code
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
ADBannerView *adView = [[ADBannerView alloc] initWithFrame: CGRectMake(0,self.view.frame.size.height - 50, 320, 50)];
[self.view addSubview:adView];
}
How would I go about only displaying an iAd banner when the game ends?
You should create a Shared iAd Banner in your AppDelegate and then present the ADBannerView on which ever ViewController you like. This implementation takes into account that an ADBannerView will not always receive an ad from the iAd network. The ADBannerView's alpha property is set depending on whether it receives an ad or not using the ADBannerView's delegate methods. This way, you can just display and hide the ADBannerView when the game ends and when you reset it knowing that the ADBannerView will only be visible if it has an ad to present.
AppDelegate.h
#import <UIKit/UIKit.h>
#import iAd; // Import iAd
#interface AppDelegate : UIResponder <UIApplicationDelegate, ADBannerViewDelegate> // Include delegate
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ADBannerView *adView;
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Create our one ADBannerView
_adView = [[ADBannerView alloc]init];
// Set delegate and hide banner initially
_adView.delegate = self;
_adView.hidden = YES;
return YES;
}
// iAd delegate methods
-(void)bannerViewDidLoadAd:(ADBannerView *)banner {
NSLog(#"bannerViewDidLoadAd");
_adView.alpha = 1.0;
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
NSLog(#"didFailToReceiveAdWithError: %#",error);
_adView.alpha = 0.0;
}
ViewController.m
#import "ViewController.h"
#import "AppDelegate.h"
#interface ViewController () {
AppDelegate *appDelegate;
}
#end
#implementation ViewController
-(void)viewDidLoad {
[super viewDidLoad];
// Create reference to our app delegate
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// Position
appDelegate.adView.center = CGPointMake(self.view.center.x,
self.view.frame.size.height - appDelegate.adView.frame.size.height / 2);
// Add to view
[self.view addSubview:appDelegate.adView];
// I'm just calling the gameOver function for example
// You should add the contents of the function to something more suitable
[self gameOver];
}
-(void)gameOver {
// Unhide the ADBannerView in which ever function is called first in the gameover view
// I'm guessing you have a UIButton that this would work in
appDelegate.adView.hidden = NO;
}
-(void)gameReset {
// When you reset the game hide the ADBannerView
// I'm guessing you have a UIButton that this would work in also
appDelegate.adView.hidden = YES;
}
You can try this bit of code:
When your game ends: [self showiAdBanner];
When your game begins: [self hideiAdBanner];
If you use this code, you'll want to replace this:
ADBannerView *adView = [[ADBannerView alloc] initWithFrame: CGRectMake(0,self.view.frame.size.height - 50, 320, 50)];
[self.view addSubview:adView];
with this:
[self showiAdBanner];
Two methods to show iad and hide iad:
- (void)showiAdBanner {
if( !_adView ) { // only add to view if it's not already there
_adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 50, 320, 50)]; //initialize it
_adView.delegate = self; // set delegate
}
_adView.hidden = NO; //reveal it
_bannerIsVisible = YES; //set bool to yes
}
- (void)hideiAdBanner {
_adView.hidden = YES; //hide it
_bannerIsVisible = NO; // set bool to no
}
Remember to add this part as well:
#interface RootViewController () <ADBannerViewDelegate>
#property (nonatomic, strong) ADBannerView *adView;
#property (nonatomic) BOOL bannerIsVisible;
#end
If you want to get fancy, instead of hiding it, you can animate/fade it out.
Related
I'm using a 2d game engine called Sprite kit within Xcode and i want to hide my ad banner in specific areas such as the game scene and then show it once it's game over for the player. But i'm having trouble trying to access the hidden property of the banner within other scenes/classes.
GameViewController.h
#import <UIKit/UIKit.h>
#import <SpriteKit/SpriteKit.h>
#import <GoogleMobileAds/GoogleMobileAds.h>
#import <AVFoundation/AVFoundation.h>
#interface GameViewController : UIViewController
-(void) hideBanner;
#end
GameViewController.m
#implementation GameViewController
-(void) hideBanner {
self.bannerView.hidden = YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Create a banner ad and add it to the view hierarchy.
self.bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerPortrait];
//TEST UNIT ID
self.bannerView.adUnitID = #"ca-app-pub-3940256099942544/2934735716";
self.bannerView.rootViewController = self;
[self.view addSubview:self.bannerView];
GADRequest *request = [GADRequest request];
request.testDevices = #[ #"*log id*" ];
[self.bannerView loadRequest:request];
}
GameScene.h
#class GameViewController;
#interface GameScene : SKScene <SKPhysicsContactDelegate>
#property (strong, nonatomic) GameViewController *gameViewController;
#end
GameScene.m
//This line of code will be executed in the "performGameOver" method but it does not work and the banner is still shown?
[self.gameViewController hideBanner];
You should use NSNotification
In viewController.m
- (void)handleNotification:(NSNotification *)notification {
if ([notification.name isEqualToString:#"hideAd"]) {
[self hidesBanner];
}else if ([notification.name isEqualToString:#"showAd"]) {
[self showBanner];
}}
-(void)hidesBanner {
NSLog(#"HIDING BANNER");
[adView setAlpha:0];
self.bannerIsVisible = NO;
}
-(void)showsBanner {
NSLog(#"SHOWING BANNER");
[adView setAlpha:1];
self.bannerIsVisible = YES;
}
In your scene:
Sends message to viewcontroller to show ad.
[[NSNotificationCenter defaultCenter] postNotificationName:#"showAd" object:nil];
Sends message to viewcontroller to hide ad.
[[NSNotificationCenter defaultCenter] postNotificationName:#"hideAd" object:nil];
More info:
https://stackoverflow.com/a/21967530/4078517
I am trying to change self.navigationController.toolbar position to top instead of a bottom.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIToolbarDelegate, UIBarPositioningDelegate>
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
// View did load
- (void)viewDidLoad
{
// Superclass view did load method call
[super viewDidLoad];
// UIToolbarDelegate
self.navigationController.toolbar.delegate = self;
}
- (void)viewDidLayoutSubviews
{
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.frame = CGRectMake(self.navigationController.toolbar.frame.origin.x, 64.0f, self.navigationController.toolbar.frame.size.width, self.navigationController.toolbar.frame.size.height);
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"First", #"Second"]];
segmentedControl.frame = CGRectMake(50.0f, 10.0f, 220.0f, 24.0f);
segmentedControl.selectedSegmentIndex = 1;
[self.navigationController.toolbar addSubview:segmentedControl];
}
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
#end
The position changes at first, but later gets back to the bottom. Please, help me!
First make sure that toolbar delegate method positionForBar: is get called. If not, then your toolbar delegate is not properly set and you've have to define the UIToolbarDelegate protocol inside your header class.
#interface ExampleViewController : UIViewController <UIToolbarDelegate>
...
#end
Then set the delegate and also change the frames for toolbar. However, for the orientation you might have to reconsider the frames of toolbar.
#implementation ExampleViewController
- (void)viewDidLoad {
[super viewDidLoad];
// set the toolbar delegate
self.navigationController.toolbar.delegate = self;
self.navigationController.toolbarHidden = NO;
// create a toolbar child items
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"First", #"Second"]];
segmentedControl.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.with, 24.0f);
segmentedControl.selectedSegmentIndex = 1;
[self.navigationController.toolbar addSubview:segmentedControl];
// set the frames
CGRect toolbarFrame = self.navigationController.toolbar.frame;
toolbarFrame.origin.y = self.navigationController.frame.size.height;
self.navigationController.toolbar.frame = toolbarFrame;
}
// pragma mark - UIToolbarDelegate
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
#end
In your viewDidLoad method, add:
self.navigationController.toolbar.delegate = self;
Adding a iAd banner in my app, but when the banner is empty (white) the banner not become hidden, i try two type of code one is:
on my .h
#import <iAd/iAd.h>
#interface HomeViewController : UIViewController <ADBannerViewDelegate> {
ADBannerView *homeBanner;
}
//----------------------------------iAd BANNER-------------------------//
#property (nonatomic, assign) BOOL bannerIsVisible;
#property (nonatomic, strong) IBOutlet ADBannerView *homeBanner;
#end
on class .m
#synthesize homeBanner, bannerIsVisible;
//------------iAd Banner---------------------------------------//
- (void)bannerViewDidload:(ADBannerView *)abanner {
if (!self.bannerIsVisible){
[UIView beginAnimations:#"animationAdBannerOn" context:NULL];
homeBanner.frame = CGRectOffset(homeBanner.frame, 0.0, 50.0);
[UIView commitAnimations];
self.bannerIsVisible = YES;
}
}
- (void)bannerView:(ADBannerView *)aBanner {
if (!self.bannerIsVisible){
[UIView beginAnimations:#"animationAdBannerOff" context:NULL];
homeBanner.frame = CGRectOffset(homeBanner.frame, 0.0, -320.0);
[UIView commitAnimations];
self.bannerIsVisible = NO;
}
}
with this code if the banner is white, continue showing.
Try to a second code:
on my .h
#import <iAd/iAd.h>
#interface HomeViewController : UIViewController <ADBannerViewDelegate> {
ADBannerView *homeBanner;
}
//----------------------------------iAd BANNER-------------------------//
#property (nonatomic, strong) IBOutlet ADBannerView *homeBanner;
#end
and on .m
- (void)viewDidLoad {
[super viewDidLoad];
[homeBanner setHidden:YES];
}
- (void)bannerViewDidload:(ADBannerView *)banner {
[homeBanner setHidden:NO];
NSLog(#"Showing");
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
[homeBanner setHidden:YES];
NSLog(#"Hidden");
}
and finally have the same problem.
Any idea?
Thanks.
Did you set the delegate for the bannerView?
Try this in you viewDidLoad -
[homeBanner setDelegate:self];
I feel silly again but I don't manage to navigate back and forth between the subviews of my project. I can add as many subviews as I want as long as it just goes forward, but as soon as I want to come back to one of the views previously visited I have a problem...
here is my simplified code:
C4Workspace.h
#import "C4CanvasController.h"
#import "FirstView.h"
#interface C4WorkSpace : C4CanvasController{
FirstView *firstView;
}
#end
C4Workspace.m
#import "C4Workspace.h"
#implementation C4WorkSpace
-(void)setup {
firstView=[FirstView new];
firstView.canvas.frame=CGRectMake(0, 0, self.canvas.width, self.canvas.height);
firstView.canvas.userInteractionEnabled=YES;
[firstView setup];
firstView.mainCanvas=self.canvas;
[self.canvas addSubview:firstView.canvas];
}
#end
FirstView.h
#import "C4CanvasController.h"
#import "SecondView.h"
#interface FirstView : C4CanvasController{
C4Label *goToSecondView;
SecondView *secondView;
}
#property (readwrite, strong) C4Window *mainCanvas;
#end
FirstView.m
#import "FirstView.h"
#implementation FirstView
-(void)setup{
goToSecondView=[C4Label labelWithText:#"go to second View"];
goToSecondView.origin=CGPointMake(20, 50);
[self.canvas addLabel:goToSecondView];
[self listenFor:#"touchesBegan" fromObject:goToSecondView andRunMethod:#"goToSecondView"];
}
-(void)goToSecondView{
[goToSecondView removeFromSuperview];
C4Log(#"second view");
secondView=[SecondView new];
secondView.canvas.frame=CGRectMake(0, 0, self.canvas.width, self.canvas.height);
secondView.canvas.userInteractionEnabled=YES;
[secondView setup];
secondView.mainCanvas=self.canvas;
[self.canvas addSubview:secondView.canvas];
}
#end
SecondView.h
#import "C4CanvasController.h"
#import "FirstView.h"
#interface SecondView : C4CanvasController{
C4Label *goToFirstView;
FirstView *firstView;
}
#property (readwrite, strong) C4Window *mainCanvas;
#end
SecondView.m
#import "SecondView.h"
#implementation SecondView
-(void)setup{
goToFirstView=[C4Label labelWithText:#"go to First View"];
goToFirstView.origin=CGPointMake(20, 50);
[self.canvas addLabel:goToFirstView];
[self listenFor:#"touchesBegan" fromObject:goToFirstView andRunMethod:#"goToFirstView"];
}
-(void)goToFirstView{
[goToFirstView removeFromSuperview];
C4Log(#"first view");
firstview=[FirstView new];
firstview.canvas.frame=CGRectMake(0, 0, self.canvas.width, self.canvas.height);
firstView.canvas.userInteractionEnabled=YES;
[firstView setup];
firstView.mainCanvas=self.canvas;
[self.canvas addSubview:firstView.canvas];
}
#end
I think you're over complicating the procedure.
The "control" of which subview should be done by the containing view controller, so, if the two views are on the canvas then it should be the canvas that deals with the switching instead of the objects themselves.
Thing to help improve your approach:
Get rid of references to the canvas from the subclasses.
The views of your subclassed controllers all post touchesBegan notifications... Use these in the workspace i.e. [self listenFor:#"touchesBegan" fromObject:firstOrSecondView.canvas and runMethod:#"switch:"];
Switch by either changing the zPosition or hiding / revealing the appropriate view...
I reduced your implementations to the following:
FirstView.m
#import "FirstView.h"
#implementation FirstView
-(void)setup{
goToSecondView=[C4Label labelWithText:#"go to second View"];
goToSecondView.origin=CGPointMake(20, 50);
[self.canvas addLabel:goToSecondView];
goToSecondView.userInteractionEnabled = NO;
}
#end
SecondView.m
#import "SecondView.h"
#implementation SecondView
-(void)setup{
goToFirstView=[C4Label labelWithText:#"go to First View"];
goToFirstView.origin=CGPointMake(20, 50);
[self.canvas addLabel:goToFirstView];
goToFirstView.userInteractionEnabled = NO;
}
#end
C4WorkSpace.m
#import "C4Workspace.h"
#import "FirstView.h"
#import "SecondView.h"
#implementation C4WorkSpace {
FirstView *firstView;
SecondView *secondView;
}
-(void)setup {
firstView=[FirstView new];
firstView.canvas.frame = self.canvas.frame;
[firstView setup];
firstView.canvas.userInteractionEnabled = YES;
[self.canvas addSubview:firstView.canvas];
secondView=[SecondView new];
secondView.canvas.frame = self.canvas.frame;
[secondView setup];
secondView.canvas.userInteractionEnabled = YES;
[self.canvas addSubview:secondView.canvas];
secondView.canvas.hidden = YES;
[self listenFor:#"touchesBegan"
fromObjects:#[firstView.canvas, secondView.canvas]
andRunMethod:#"switchView:"];
}
-(void)switchView:(NSNotification *)aNotification {
C4View *v = (C4View *)aNotification.object;
if([v isEqual:firstView.canvas]) {
firstView.canvas.hidden = YES;
secondView.canvas.hidden = NO;
} else {
firstView.canvas.hidden = NO;
secondView.canvas.hidden = YES;
}
}
#end
This should work for you in the case that your views need differing functionality, like FirstView will have significantly different internal functionality than SecondView... If they are the same then you should think about collapsing them into the same subclass.
I'm very new to iOS programming (Coming from Java / C++). I'm trying to set up an app with a TabBarController of which one tab should be a SplitView. I've done my research and I know that UISplitview will not work and everywhere people recommend using the MGSplitViewController. I've looked at the demo but I just can't figure out how to use it without it beeing the app's root view and can't find any sample code that could help
So here is what I do with the classes from the demo in a separate UIViewController class that I afterwards add to the TabBarController: This is my class:
#import <UIKit/UIKit.h>
#import "MGSplitCornersView.h"
#import "RootViewController.h"
#import "DetailViewController.h"
#interface ChannelViewController : UIViewController {
MGSplitViewController *splitViewController;
RootViewController *rootViewController;
DetailViewController *detailViewController;
}
#property (nonatomic, retain) MGSplitViewController *splitViewController;
#property (nonatomic, retain) RootViewController *rootViewController;
#property (nonatomic, retain) DetailViewController *detailViewController;
#end
And this is my desperate try to set it up
- (id)initWithTabBar
{
self = [super init];
//this is the label on the tab button itself
self.title = #"SplitView";
//use whatever image you want and add it to your project
//self.tabBarItem.image = [UIImage imageNamed:#"name_gray.png"];
// set the long name shown in the navigation bar at the top
self.navigationItem.title=#"Nav Title";
self.splitViewController = [[MGSplitViewController alloc] init];
self.rootViewController = [[RootViewController alloc] init];
self.detailViewController = [[DetailViewController alloc] init];
[self.splitViewController setDetailViewController:detailViewController];
[self.splitViewController setMasterViewController:rootViewController];
[self.view addSubview:splitViewController.view];
[self.rootViewController performSelector:#selector(selectFirstRow) withObject:nil afterDelay:0];
[self.detailViewController performSelector:#selector(configureView) withObject:nil afterDelay:0];
if (NO) { // whether to allow dragging the divider to move the split.
splitViewController.splitWidth = 15.0; // make it wide enough to actually drag!
splitViewController.allowsDraggingDivider = YES;
}
return self;
}
I guess I'm doing something wrong with delegates? Or do I have something else mixed up?
Is the demo doing things in the IB that I can't see in the code?
I get the split view but no content and especially no navigation bar with the buttons the demo comes with.
I'd be very thankful for hints or sample code!
Ok manny, here we go. This is my working code for the interface:
#import <UIKit/UIKit.h>
#import "MGSplitViewController.h"
#import "ecbView.h"
#import "ecbCalc.h"
#interface splitMain : MGSplitViewController <UIPopoverControllerDelegate,
MGSplitViewControllerDelegate>
{
IBOutlet UIPopoverController* popoverController;
IBOutlet UINavigationController* naviController;
IBOutlet ecbCalc* viewCalcLeft;
IBOutlet ecbView* euroRatesRight;
UIBarButtonItem* savedButtonItem;
BOOL keepMasterInPortraitMode;
BOOL memoryWasDropped;
BOOL viewLoaded;
}
#property (nonatomic, retain) UIPopoverController* popoverController;
#property (nonatomic, retain) UINavigationController* naviController;
#property (nonatomic, retain) ecbCalc* viewCalcLeft;
#property (nonatomic, retain) ecbView* euroRatesRight;
#property (nonatomic, retain) UIBarButtonItem* savedButtonItem;
#property (nonatomic, readonly) BOOL keepMasterInPortraitMode;
#property (nonatomic, readonly) BOOL memoryWasDropped;
#property (nonatomic, readonly) BOOL viewLoaded;
- (void)dismissPopoverController: (BOOL)animated;
- (void)settingsChanged;
#end
and here excerpts from implementation file:
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
// my initialization...
}
return self;
}
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
CGRect rectFrame = CGRectMake(0.0, 20.0, 768.0, 1004.0 - 48.0); // being above a tab bar!
viewLoaded = NO;
self.view = [[UIView alloc] initWithFrame:rectFrame];
viewCalcLeft = [[ecbCalc alloc] initWithNibName:#"ecbCalc" bundle:nil];
euroRatesRight = [[ecbView alloc] initWithNibName:#"ecbView-iPad" bundle:nil];
naviController = [[UINavigationController alloc] initWithRootViewController:self.viewCalcLeft];
naviController.navigationBar.barStyle = UIBarStyleBlack;
naviController.title = nil;
viewCalcLeft.title = NSLocalizedString(#"BtnTitleCalc", #"");
viewCalcLeft.view.hidden = NO;
NSUserDefaults* prefs = [NSUserDefaults standardUserDefaults];
if ([prefs objectForKey:#"iPadAlwaysSplitTableView"] != nil)
self.keepMasterInPortraitMode = [prefs boolForKey:#"iPadAlwaysSplitTableView"];
else
self.keepMasterInPortraitMode = YES;
NSArray* theViewControllers = [NSArray arrayWithObjects:self.naviController, self.euroRatesRight, nil];
[self setViewControllers:theViewControllers];
[self setDelegate:self];
[self setShowsMasterInPortrait:keepMasterInPortraitMode];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
// protection because this one is called twice
if (viewLoaded)
return;
[super viewDidLoad];
if (memoryWasDropped)
{
if (!self.keepMasterInPortraitMode && UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
{
// recreate popover controller
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:self.viewCalcLeft];
}
}
viewLoaded = YES;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
memoryWasDropped = YES;
// 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;
[self dismissPopoverController:NO];
self.popoverController = nil;
self.naviController = nil;
self.viewCalcLeft = nil;
self.euroRatesRight = nil;
viewLoaded = NO;
}
My MainWindow.xib has a UITabBarController and the button for splitMain is configured for this class but with an empty xib entry. So creation has to go via loadView. Maybe I could have done the viewDidLoad stuff within loadView ... but so I had to protect viewDidLoad from being called twice. That happens in loadView as soon as the view is instantiated from MGSplitViewController class because the initWithCoder there is calling [self setup]. In that function the frame rect is calculated with self.view.bounds so that viewDidLoad is called again because the view doesn't exist yet. Maybe one could implement a workaround within MGSplitViewController.m but I was too lazy doing that.
To get this working on a tab bar controller please make sure you commit most of the changes that are published on the MGSplitViewController's git page. Good luck.