Implementing iAd Banner - objective-c

I just published an application on the App Store with an iAd banner. When I downloaded it to check for the advertisement, I just saw a plain white horizontal rectangle even though it says "Live: This app is receiving live ads." in development.
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
[adView setCurrentContentSizeIdentifier:ADBannerContentSizeIdentifierLandscape];
[adView setDelegate:self];
[self.view addSubview:adView];
[self.view bringSubviewToFront:adView];
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
return YES;
}
Everything in my performance chart is zero, except for the 715 requests. What does this mean?
Also, is it possible for iAd to determine the user's location so that apple can put ads from local companies? For example, the user is in Japan, will iAd only show ads from Japan?

Does it work in the simulator, i don't think it's a programming error but rather a technical error from apples side. Manny developers is experiencing this:
Can not see iAd in program?

I think there is no ad available so your app receives a nil value. I don't see any check for that, so regardless if it's nil or not, your app tries to display what it got, which may be nil. So you end up with a blank ad with no link what you see there.
I suggest in the next version to check for that and/or use some fallback method like AdMob or something.

You need to check if your ADBannerView received an ad or not and then display or hide it accordingly.
-(void)bannerViewDidLoadAd:(ADBannerView *)banner {
// Display banner
adView.alpha = 1.0;
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
// Hide banner
adView.alpha = 0.0;
}

Related

Complex Multi-Device Orientation Handling

I have a universal application running both on iPads and iPhones. The application starts with a .xib file, built in interface builder, which acts as the launch image. Once the app launched, it switches to the appropriate view controller based on device size set in the app delegate:
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if (screenSize.height <= 568.0f) {
// iPhone 4, 4S, 5, 5C, 5S, SE
self.viewController = [[iPhoneSmallViewController alloc] init];
} else {
// All other iPhones
self.viewController = [[iPhoneLargeViewController alloc] init];
}
} else {
// All iPad models
self.viewController = [[iPadViewController alloc] init];
}
The iPad view controller supports all interface orientations (set in app targets/main setup page), but on iPhones I only allow portrait mode restricted in the view controller as such:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
}
I have two problems with this method:
If the iPhone is held horizontally, the app still loads in portrait mode (as per the restrictions, which is all good) but all measurements are in landscape upon initialization. UI elements stick out on the side because they were measured for a landscape view but placed on a portrait.
I use the window's size to set up everything inside the view by initializing the following variable in the ViewDidLoad method:
windowSize = [[UIScreen mainScreen] bounds].size;
Tt gives me landscape dimensions in phone is held horizontally, even though landscape mode is not allowed.
If the app loads with landscape measurements initially, all my sorting of screen sizes in the app delegate are off since I identify iPhone models by measuring screen width that is only good in portrait mode.
Question: does anyone have a way to handle this complex problem in an elegant and simple way?
Some additional info: I use Xcode 10, support all the way back to iOS9 and do everything programmatically in Objective C.
p.s: I think this method worked before but not any more in iOS 12. But I could be wrong...
Edit: I provide an image of what I want to accomplish, and all help would be greatly appreciated. As I said, this has worked before (the app is quite old), but in recent iOS releases got increasingly buggy and desperately needs a cleanup, which is what I need help with.
One thing that might solve my problem, is if I could somehow restrict interface orientations based on device type in the launchScreen.xib, as I believe that is what causes the faulty behavior on iPhones.
Maybe this SO will be helpful,
They are detecting the device orientation and then rotating the view, look at first answer:
Change orientation programmatically with button - iOS
UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
A better way to detect device is explained here:
iOS detect if user is on an iPad
if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
return YES; /* Device is iPad */
}
I've been experimenting with this for days, and worked out a solution. Although this is probably not the most elegant way to do it, so if anyone has a better solution, please feel free to post it.
It is important to allow all interface orientations in the info.plist because I was unable to restrict them based on device size in the launchScreen.xib.
Create the universal launch screen that supports both iPads and iPhones. Because all interface orientations are allowed in the info.plist, this will have no restrictions.
Below is my current method in the app delegate. This is not the best way to do identifying the smaller iPhones (which I need for reasons... :), but because of the size differences, this works quite well.
At this point, the phone can be in any of the four interface orientations set in the info.plist, but because only the small handsets have a 320-width it is easy to catch it:
// Get screen size
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
// Determine device based on screen dimensions
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if ( (screenSize.height == 320.0f) || (screenSize.width == 320.0f) ){
// iPhone 4, 4S, 5, 5C, 5S, SE
self.viewController = [[iPhoneSmallViewController alloc] init];
} else {
// iPhone 6, 6S, 6P, 6SP, 7, 7P, 8, 8P X, XS, XM, XR
self.viewController = [[iPhoneLargeViewController alloc] init]; //Same as previous
}
} else {
// All iPad models
self.viewController = [[iPadViewController alloc] init];
}
Restrict interface orientations in the iPhone view controllers (all other view controllers will inherit the ones we set in the info.plist).
Do it like so:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait);
}
There is another trick we need to do for the above to work though. When the window loads for the first time, it will not take into consideration the restriction we added to the view controller. That means, if we do our setup in the viewDidLoad method, we will receive landscape screen dimensions if the device is held horizontally (even though this orientation is not allowed). Restriction will be applied once the viewDidLoad method has concluded.
Therefore, to prevent buggy behavior, you need to create a separate method in which you do your setup (such as postViewDidLoad) and call it once the real viewDidLoad had concluded:
- (void) viewDidLoad
{
[super viewDidLoad];
[self performSelector:#selector(postViewDidLoad) withObject:nil afterDelay:0.0f];
}
In this method, you will get access the real screen size based on your restrictions you set in the supportedInterfaceOrientations method.
And that is basically it. If you have multiple views, all with different restrictions, just follow steps 4 and 5 in each of them to properly setup your workflow.

Camera Rotation and OverlayView in iOS8

I am experiencing an issue when using the iPad Camera in iOS 8. I've seen some older questions and a thread on the Apple Developer Forums from during the beta but still haven't find a solution.
There seems to be two parts to this issue.
1) The camera itself rotates when the device orientation rotates, eg the world is on its side
2) When opening the camera in Landscape, the overlay does not appear. When opened in Portrait it is fine.
It is an app using iOS7 as the Base SDK, problem only occurs when running the app on a device that has been upgraded to iOS8. The app is not using storyboards, it is using nibs.
I'm hoping to push out a fix for this with Xcode 5.1.1 before moving onto the iOS8 specific fixes and using it as a Base SDK in the next version.
Here is my code to bring up the camera:
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES) {
// Create Camera
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
imagePicker.showsCameraControls = NO;
// Set up custom controls view
[[NSBundle mainBundle] loadNibNamed:#"OverlayView" owner:self options:nil];
self.overlayView.frame = imagePicker.cameraOverlayView.frame;
imagePicker.cameraOverlayView = self.overlayView;
self.overlayView = nil;
// Show Camera
[self presentViewController:imagePicker animated:NO completion:nil];
[imagePicker release];
}
I have also tried
And the Layout of the Toolbar (sitting at the bottom) of the OverlayView:
If I change that to sit "at the top" it appears in both portrait and landscape! So it must have to do with the view/window/something size, though it's strange how its behaviour would change when the layout has stayed the same.
I have tried it with both showsCameraControls = YES and hashing out the OverlayView block, and problem #1 persists so it's not to do with the overlay at app.
I'm hoping someone has found an answer to this, it seems like quite a common problem.
Please let me know if you need any further details.
Edit 1: Fixed the Overlay (Issue #2)
It wasn't applying the orientation to the OverlayView, fixed it like this:
// Grab the window frame and adjust it for orientation - from http://stackoverflow.com/a/15707997/520902
UIView *rootView = [[[UIApplication sharedApplication] keyWindow]
rootViewController].view;
CGRect originalFrame = [[UIScreen mainScreen] bounds];
CGRect screenFrame = [rootView convertRect:originalFrame fromView:nil];
...
self.overlayView.frame = imagePicker.cameraOverlayView.frame;
I suspect that it's related to the camera not realising it's orientated too, will keep searching for a fix for Problem #1.
Edit 2: Update on Issue #1
Looks like the camera rotating might be an Apple issue. On iOS8 if you open up the Contacts app, edit a contact and choose 'Take Photo', the exact same issue occurs - in a default Apple app!
I still can't find a fix so I am just destroying and recreating the imagePicker on each orientation change for now, it's ugly but will suffice until Apple release a fix or a better solution pops up.
Apple fixed this problem in iOS 8.1.

iOS 7 iAd interstitial ads can not be closed by user

when i display interstitial ads with
[interstitial presentFromViewController:self];
i get the warning that this method is deprecated in iOS 7. But it still works fine!
When i display the ad view with
[self requestInterstitialAdPresentation];
[interstitial presentInView:self.view];
i get no warning and the ad is loading but there is no (X) in the ad that the user can close the ad.
Do somebody knows how to fix this?
hey there this is the troublemaker
[interstitial presentInView:self.view];
instead try this (delegate methods) t'should be removed manualy
-(void)interstitialAdDidLoad:(ADInterstitialAd *)interstitialAd{
if (interstitial != nil){
_adPlaceholderView = [[UIView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_adPlaceholderView];
[interstitial presentInView:_adPlaceholderView];
}
and on did unload
- (void)interstitialAdDidUnload:(ADInterstitialAd *)interstitialAd
{
NSLog(#"ad has been unloaded");
[_adPlaceholderView removeFromSuperview];
_adPlaceholderView = nil;
}
I have the same bug Use the old API or put custom x button .I thinks this is a bug from presentinView . i am not sure it could be apple desired feature there's no documentation on this.At least i haven't seen any.Please share if you find something official on this.

UIPopoverController strange behavior

I am using a UIPopoverController and populating it with a MPMediaPickerController to choose songs from iPod library. I have got it working just fine. However, I added a completely unrelated feature ( touch a button and image scale to large size ) and now the UIPopoverController behaves strangely only after using the new feature.
After using the button scale feature, the UIPopoverController appears in a strange manner. It looks like it is animating from a rotated state off the screen and lands in the correct place, but the expected behavior is that it should just appear in the right location.
// code for if the interface is a an iPhone, do not use popup
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
[self presentModalViewController:picker animated:YES];
// code if not iPhone uses popover media picker
else {
UIPopoverController* pop =
[[UIPopoverController alloc] initWithContentViewController:picker];
self.currentPop = pop;
// checks if the iPad is portrait or landscape and displays the popover media picker accordingly
if (vertMode == TRUE)
{
// if in portrait mode
[pop presentPopoverFromRect:CGRectMake(668.0f, 846.0f, 10.0f, 10.0f) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:NO];
// otherwise if in landscape mode
}
else if (vertMode == FALSE)
{
[pop presentPopoverFromRect:CGRectMake(900.0f, 580.0f, 10.0f, 10.0f) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:NO];
}
[pop release];
}
}
OK, well I feel a bit silly answering my own question, but I hope that it may help someone else in the future.
I am not exactly sure why, but in my function for the button that scales the image to a large size, I forgot to add:
[UIView commitAnimations];
the intention of that was to complete the animated movement of the scaling image, I am guessing because I never commit the animation, that it was still in some state of trying to animating things. Then when I called my popup , it made the weird animation occur.
So I fixed this by just adding the above one line!
I feel SO much better figuring this one out! I hope it helps someone else out there.

How would I develop something like DeskLock from Deskshade?

Sorry to be a nuisance, but I have yet ANOTHER question. How would I do something like DeskLock from macrabbit's Deskshade app? I've made the little window and that's as far as I've come. I know how to "lock" the screen in 10.6 with PresentationOptions, but I don't want to risk it because last time it wouldn't let me back in ;]
EDIT: The DeskShade app actually is meant to cover your desktop, hiding all icons. It also allows you to randomize wallpaper patterns with several fade/swipes. There is one extra feature called DeskLock that actually presents a translucent black bevel (similar to AppSwitcher build into Mac) with a lock icon, and you can place personal text. When you click the lock icon, it presents a modal that asks for a password you can set. You can also just type this password without pressing anything, followed by the Enter key, and it unlocks the screen. This uses the DeskShade feature of hiding the desktop as well.
Thanks!
To create the overlay window you have to subclass NSWindow and set its style mask and background color:
#implementation BigTransparentWindow
- (id)initWithContentRect:(NSRect)contentRect
styleMask:(NSUInteger)windowStyle
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)deferCreation
{
self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask //this makes the window transparent
backing:bufferingType
defer:deferCreation];
if(self)
{
[self setOpaque:NO];
[self setHasShadow:NO];
[self setBackgroundColor:[[NSColor blackColor] colorWithAlphaComponent:0.5]];
}
return self;
}
#end
You then need to set the window's frame so that it covers all screens, and you need to set its window level appropriately:
- (IBAction)showWindow:(id)sender
{
//set the window so it covers all available screens
NSRect screensRect = NSZeroRect;
for(NSScreen* screen in [NSScreen screens])
{
screensRect = NSUnionRect(screensRect,[screen frame]);
}
[yourWindow setFrame:screensRect display:YES];
if(coverScreen)
{
//set the window so it is above all other windows
[yourWindow setLevel:kCGMaximumWindowLevel];
}
else
{
//set the window so it sits just above the desktop icons
[yourWindow setLevel:kCGDesktopIconWindowLevel + 1];
}
}
As you've mentioned, you can use the NSApplicationPresentationOptions settings for NSApp to control how the user can interact with the system. An easy way to test this without locking yourself out is to set an NSTimer that calls a method that pulls the app out of kiosk mode after a timeout period.