It seems there are 2 options for displaying interstitial ads using iAds on iPhone. The documentation on interstitials is out of date, but according to the iAds Additions Reference all one needs to do to set up is:
[UIViewController prepareInterstitialAds];
[self setInterstitialPresentationPolicy:ADInterstitialPresentationPolicyManual];
followed by:
[self requestInterstitialAdPresentation]
(which returns a bool if successful) whenever you'd like to display an ad.
The other options is to manually create an interstitial ad object:
ADInterstitialAd *interstitial;
Then:
interstitial = [[ADInterstitialAd alloc] init];
interstitial.delegate = self;
And when you want to show an ad:
if (interstitial.isLoaded) {
[interstitial presentFromViewController:self];
}
However PresentViewController: is deprecated, and using presentInView:self.view means the ad doesn't have a close button. The compiler also suggests requestInterstitalAdPresentation.
So one would assume option 1 is the preferred approach. I'm a little confused by the answer to this question as it uses a combination of the 2, but it seems requestInterstitalAdPresentation doesn't trigger the delegate methods of the ADInterstitialAd instance and using both is pointless.
So my question is - is the first approach really sufficient? I've found it only displays one ad, and then fails to display any more. I read in another question that the ADInterstitialAd instance needs to be assigned to nil in order to request a new ad, but then requestInterstitialAdPresentation ignores this instance anyway. Is requestInterstitialAdPresentation just simulating low fill rates? Or am I missing a step?
It's only showing 1 ad because there is a delay implemented by apple. You must wait 2 or 3 minutes before they will supply you with your next ad.
As for implementation, the new method calls viewDidAppear in your view controller when the user returns from the ad.
You can see my implementation here...
https://stackoverflow.com/a/27536872/3489816
So to answer your question - Yes, the first approach is sufficient. It will display more ads but you must wait for a bit. You shouldn't use AdInterstitialAd anymore so don't worry about setting it to nil. It's not simulating low fill rates. I don't think you're missing anything... we were just never told we had to wait :)
Side note... I believe setting the interstitialPresentationPolicy also requests your first ad for you (as prepareInterstitialAds does).
The first method you describe is exactly what I've just got working, and it does generate new advertisements, not just one. You have to call
[self requestInterstitialAdPresentation]
every time you want to show an advert. The advert isn't always shown, and your iPhone developer settings can make this worse.
I've got some code that does this and waits for completion here.
Related
I've taken over a project that handles which screen to show first in the "applicationDidBecomeActive" function inside the AppDelegate. This has been causing problems because whenever the app asks for a permission sometimes, not all, it will trigger this block of code and send the user to the incorrect screen. I'm not sure what to do since I've never encountered this before. Any ideas why this is occurring or ways to circumvent this? I've tried adding a flag variable, however, that doesn't seem to work consistently because it looks like it gets un-set before the applicationDidBecomeActive is triggered.
When system notifications such as Permissions are presented, the application is sent to background, or becomes "inactive". When the Permission notification is dismissed, the application becomes "active" again. This would explain why didBecomeActive is triggered.
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive
I've taken over a project that handles which screen to show first in the "applicationDidBecomeActive" function inside the AppDelegate... Any ideas why this is occurring or ways to circumvent this?
The simple answer is: don't do that work in applicationDidBecomeActive(). As you've seen, the application can become inactive and then active again while the app remains in the foreground, so that's not the right state transition for what you're doing. Identify the app state transitions where you really do want to choose a screen. For example, you might want to do it when the app launches, and also when it transitions from background to foreground, so you could use application(_:didFinishLaunchingWithOptions:) and applicationWillEnterForeground(_:). (Obviously, you don't want to put the same code in both places, so put it in a separate method and just call it from those two methods.)
Apple has a document that covers this very topic: Managing Your App's Life Cycle. There's also a lot of information on application states on the UIApplicationDelegate reference page. Both documents include helpful state transition diagrams and descriptions of what the various states mean.
As a solution; you can use the applicationWillEnterForeground(). It's being called before the applicationDidBecomeActive() and not being triggered by permission request.
When I call the first time UIActivityViewController, the interaction is locked. After the first click it will be normal without locking interaction, does anyone know how to not catch the first time?
Maybe this can help. I had a similar issue, UIActivityViewController was pretty slow to appear the first time.
I solved it removing AirDrop from the supported activity types (through excludedActivityTypes) and it became super fast.
So if you are not interested in AirDrop (my case) you can do something like this:
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
activityVC.excludedActivityTypes = #[UIActivityTypeAirDrop];
}
Note that UIActivityTypeAirDrop is only available starting from iOS 7.0.
I don't really understand the problem - you alloc/init a UIActivityViewController and then you present it with presentViewController:animated:completion, correct? Make sure to call the presentViewController... on the main thread. Sometimes UI stuff called on the wrong thread takes seconds to get executed. But it might also just be iOS - UIActivityViewController takes some time to check for available services and stuff, that might be the thing that's slowing it down too.
I'm writing an iOS application and I'd like to pause my app's motion content when the operating system decides to show a Banner Notification like this one:
Is there a system NSNotification that I can observer or a method that gets called which I can react to? I've triedapplicationWillResignActive, but that isn't called in this case.
I took a stab at it this morning, and I'm inclined to say that there's no public API for this.
I tried using the code outlined here, and didn't catch any notifications. Then, I ran a bunch of "tests" to see if I could find anything.
To test, I created a pair of applications, one to schedule notifications (GitHub link), and one to try and "catch" them (GitHub link). In my Sender app, I can send N notifications every N seconds. I picked some arbitrarily high value and sent them.
In my catcher, I've tried looking at visibleRect values up and down the layer hierarchy. (The keyWindow lives in a layer, but it's superview, and super layer.delegate are both nil) I haven't checked constraints, but that shouldn't matter. I've looked at the application's window, it's nil superview, it's layer, it's subviews. The application's bounds aren't effected either. The app is sandboxed so well, that springboard and notification center don't exist in the app's world.
I started going down the path of accessing private frameworks, but decided it wasn't worth the effort.
I've opened Instruments and looked at the transparency levels of the views. (Is it possible to force all views in a hierarchy to be opaque, and then use that to see if the banner is blocking something? Perhaps it's not "blocking" if it's transparent?)
I've also attempted to take a screenshot, and check the colors in the top area of the screen, but that wouldn't work because you need to pass a view in to the context. Even if it would work, it wouldn't be particularly performant.
Another thought I've had would be to listen for push notifications on the push port, but I doubt that Apple would allow you to catch another app's notifications. As a developer, I wouldn't send private info in an alert, but it's still a concern.
The truth is that notification banners don't really cause your application to become inactive, so I'm not sure that this behavior is wrong. If it's a convenience, file a bug.
How about requesting DeviceWillShowNotificationNotification?
I have an app where I have 5 sets of animations that I'm storing in an array. The animations get picked to play randomly after a button touch. This is all working perfectly, however I noticed a bug when I quit the app and reopen immediately, I'll see my main view, then it'll jump to my second view that has the animation in it. (This shouldn't happen since you have to tap the main view in order for it to modally swap in the second view. If I interact with it everything works for a few seconds, then it closes with no crash log.
I finally realized that some of the objects must not be getting released fast enough, since if I close the app and wait three seconds, then reopen, everything executes fine.
I didn't want to put down code to show as this is more of a brainstorming question. I'd love any insight that could point me the right way. I changed a lot of my code to get rid of convenience methods and have all my variables defined and then released in my dealloc.
Is there a way to truly tell the app to kill everything on quit? It's not set to run in the background so this is a bit odd. Thanks for your help I'm still new to this and learning!
Alright, after working on this all weekend and doing more research comparing a barebones version of my app to my prerelease version, I traced memory leaks to the Flurry Analytics api that I am using. Apparently I was suffering from the same issue as the post here: App hangs on restart with latest Flurry SDK and ios4 . I resolved this by setting these optional methods to false, since they take extra time to send data after the app terminates, and depending on the connection it takes a few seconds.
FlurryAnalytics.h
/*
optional session settings that can be changed after start session
*/
+ (void)setSessionReportsOnCloseEnabled:(BOOL)sendSessionReportsOnClose; // default is YES
+ (void)setSessionReportsOnPauseEnabled:(BOOL)setSessionReportsOnPauseEnabled; // default is YES
Hope this helps anyone else who experienced something similar to me!
All apps can enter the background by default. Normally they do not do anything there, but they stay there in a frozen state and when you open them again, your program does not restart, it just picks up where it left off.
Anything that's set as an animation delegate might not get released, since it's retained for that purpose until the animation completes.
You can add an applicationDidEnterBackground: method to your app delegate to get informed when your app is going into the background, but exactly what you need to do depends on the design of your app. You can also add applicationWillEnterForeground: to do anything you need to do differently when restarting, as opposed to newly starting.
You might be able to force your animations to complete by starting a new animation with duration 0.0 (or very short if for some reason you can't do that).
If this happens only if your app goes to bkgnd and comes back AND you don't mind if the app restarts everytime it comes back then just put UIApplicationExitsOnSuspend in your app's plist. In all my cases where these and other bad things happen with apps going to and returning from bkgnd this helped.
While you might still see the app on the buttom when double tapping it is really stopped and will restart. Apps that show on the buttom do not always have to run or be stored in the bkgnd I learned.
ps. don't forget to set the value of UIApplicationExitsOnSuspend to YES
I really don't think this can be done, but still my boss wants me to provide a link where it says so. What he wants is to add an 'are you sure you want to exit?' warning when the user presses the home button, and if the user says 'no' the app won't go inactive.
It can't be done, can it?
No, you cannot do this - the application has no say in this. Ask your boss whether he has ever seen a single example of an iOS application that would do this. There isn't ... not one I would bet.
The application can continue to execute some functionality in the background - streaming music, getting location information for example, but no application can block the home button. If you could do this, you could block an application from ever closing.
A) You couldn't technically do this and
B) Apple wouldn't allow it to be released on the App Store if that was the distribution route you were taking
If you look at the methods stubs created by XCode when you create an application delegate
-(void)applicationWillResignActive:(UIApplication *)application
-(void)applicationWillTerminate:(UIApplication *)application
That are filled will comments about how you can use this method to pause tasks, disable timers, throttle down frame rates, save data - there is nothing about being able to delay, query the user with an "Are you sure" message.
This whole idea is rather counter to the user-experience of the iPhone/Pad/Pod-Touch.
From the App Store guidelines (slightly abbreviated):
Apps that alter the behavior of switches on the device will be
rejected
This is a proposed change the behavior of the home button - so would be rejected.
This is possible on a jail broken device, using un-aproved API's. The concept is in multiple violations of apple's usage policy however so you would never, ever, ever get an app attempting to implement this in any way on the official app store. Here's just a few reasons:
You can't alter the functionality of any buttons (including the volume buttons, some camera apps used to use them to take pictures, but they got booted from the store as a result).
You can't interfere with standard user interactions with the device. The home button takes people home, you can't prevent that, or ask for confirmation as that would be interfering with the interaction.
There is no public API to detect actual usage of the home button. As such you would need a private API, and you can not use private API's without explicit permission from Apple, which they would never give due to #1 and #2 above.
I'm sure there's plenty of more reasons, but regardless it would be in direct violation of app store policies as well as iOS human interface guidelines.
You can detect when the app is about to lose focus, has lost focus, or could loose focus (such as a phone call is coming in) but you can not alter the flow (i.e. not allow the app to lose focus).
You can continue to execute code in the background within the backgrounding guidelines and limitations. The backgrounded code could submit a notification to the user that would allow them to switch back into the app... that's about as close as you could get, and expect apple to reject you if it happens every time the app closes...
Already answered by numerous others, but no, you can't do this. When the user presses the home button, your application delegate's applicationWillResignActive is called which disables touch events to the application. Then applicationDidEnterBackground is called, which, per the Apple docs:
Your delegate’s applicationDidEnterBackground: method has
approximately 5 seconds to finish any tasks and return. In practice,
this method should return as quickly as possible. If the method does
not return before time runs out, your application is killed and purged
from memory
You need proof to show your boss that obviously isn't an iOS developer.
Apple Human Interface Guide
That should be all the proof you need. But to be clear, Apple will not allow an app to override the home button in any way. You can surely put action sheets or pop ups to warn before logging out, but once the home button is pressed, you are on notice to give up your memory, you are being shut down.
You might want to look into the Store Demo Mode of IOS. This way you can disbale the Home button and lock the device in the first app you start after booting.
I know I'm too late to answer this question.
But I recently came with the issue which Samssonart had.
The answer given by #iandotkelly is deprecated with iOS5. Now none of delegate method will be used to distinguish between locking the device or sending app to background using Home button.
you can now use applicationState variable to define what action is triggered.
applicationState is an inbuilt id provided by appDelegate.
**
if it returns 2 then, it will identify the Home button is pressed
if it returns 1 then, it will identify the lock hardware button is pressed
**
So, in your case you can check out this condition in **applicationDidEnterBackground** method
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"decision >> %d",[[UIApplication sharedApplication] applicationState]);
}
Enjoy Programming!
The best reference I can find is this one. It's not quite explicit, but Apple's Human Interface Guidelines have a couple of headings 'Always Be Prepared to Stop', followed by 'Don't Quite Programmatically', which spell out what the home button does and that you shouldn't be implementing your own quitting strategies.
I know this is an old topic, but I just want to update this answer. In iOS 7 this is not working.
So I use screenbrightness when the app will go to the background to identify difference between the Home and Lock button.
-(void)applicationDidEnterBackground:(UIApplication *)application {
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateInactive) {
NSLog(#"Sleep button pressed");
} else if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) {
if ([[UIScreen mainScreen] brightness] > 0.0)
NSLog(#"Home button pressed");
else
NSLog(#"Sleep button pressed");
}
}
I hope this is gonna be of any help for in future for anyone