How to add Admob Interstitial before Segue? - swift

I'v been trying to deal with this problem for a good while but cant figure out how to fix it.
Currently I'v added Admob to my project and the interstitial's are displaying but when I exit the interstitial it returns me to my previous VC (where the interstitial instance is made).
As you can see below im trying to add them to my Tabbar functions. But the segue never happens nor do the alerts show before the interstitial. I wanted to show the the ad then segue to the VC. And I want the user to see the alert and press "OK" before seeing the interstitial.
Any help would be awesome!
//TabBar Functions
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
if (item.tag == 1) {
if (self.interstitial.isReady) {
self.interstitial.presentFromRootViewController(self)
}
self.performSegueWithIdentifier("showStore", sender: nil)
} else if (item.tag == 2) {
let alert = UIAlertController(title: "Coming Soon!", message: "Loadout", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Got It!", style: .Default, handler: nil))
if (self.interstitial.isReady) {
self.interstitial.presentFromRootViewController(self)
}
self.presentViewController(alert, animated: true, completion: nil)
return
} else if (item.tag == 3) {
let alert = UIAlertController(title: "Coming Soon!", message: "God's Tower", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Got It!", style: .Default, handler: nil))
if (self.interstitial.isReady) {
self.interstitial.presentFromRootViewController(self)
}
self.presentViewController(alert, animated: true, completion: nil)
return
}
}

Set your GADInterstitial's delegate and then segue once the ad has been dismissed.
// Add this where you're creating your GADInterstitial
interstitial.delegate = self
func interstitialDidDismissScreen(ad: GADInterstitial!) {
// Segue to your view controller here
}
For a complete list of ad events refer to GADInterstitialDelegate implementation.

Related

Why is the completion not working? completion issue

Why is the completion not working ?
After the alert appears, its not transitioning to the other viewController
self.present(self.alertController2, animated: true, completion: {
self.performSegue(withIdentifier:"goToLogin", sender: self)
})
Self.present using for add this action into view . You need to add this code into your handler handler mean It means what will I do when you click OK
let alertbutton = UIAlertAction(title: "OK", style: .destructive, handler: {
(UIAlertAction) in
self.performSegue(withIdentifier: "your id", sender: self)
})
Complete example :
let alert = UIAlertController(title: "Its empty", message: "Going another view", preferredStyle: .alert)
let alertaction = UIAlertAction(title: "OK", style: .destructive, handler: { (UIAlertAction) in
self.performSegue(withIdentifier: "your segue id", sender: self)
})
alert.addAction(alertaction)
self.present(alert, animated: true, completion: nil)
You should write code first move into new view code run then show alert in main thread for displaying alert.
DispatchQueue.main.async {
// AlertView.showAlert(title: Messages.Network.title, message: Messages.Network.message)
// }

Does replaykit allow to record the screen and then broadcast the screen?

Im having a problem where after I broadcast my screen live, I then try to record the screen but it doesn't work. Same thing happens when I record my screen and then I try to broadcast the screen live. Im not trying to do them together btw. This is after one is done and I try to use the other one. Let me know if you need to see code or more info. Im in Swift 3 and using the new replay kit framework. Thanks!
EDIT: THIS IS THE CODE IM USING
//LIVE STREAM REPLAYKIT=====================================================================
func broadcastActivityViewController(_ broadcastAVC: RPBroadcastActivityViewController, didFinishWith broadcastController: RPBroadcastController?, error: Error?) {
print("=====hello delegate \(broadcastController?.broadcastURL) (error)")
self.broadcastController = broadcastController
self.broadcastController?.delegate = self
broadcastAVC.dismiss(animated: true) {
self.broadcastController?.startBroadcast(handler: { error in
print("start broadcast \(error)")
print("\(broadcastController?.broadcastExtensionBundleID)")
print("==url=\(broadcastController?.broadcastURL)")
print("==serviceInfo=\(broadcastController?.serviceInfo)")
//This is called when the broadcast is live
})
}
}
func broadcastController(_ broadcastController: RPBroadcastController, didFinishWithError error: Error?) {
print("broadcastController====delegate")
let alert = UIAlertController(title: "Alert", message: "There was an error broadcasting your screen. Please try again", preferredStyle: UIAlertControllerStyle.alert)
// show the alert
self.view!.window?.rootViewController!.present(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "Okay", style: UIAlertActionStyle.destructive, handler: { action in
// add action
}))
}
func broadcastController(_ broadcastController: RPBroadcastController, didUpdateServiceInfo serviceInfo: [String : NSCoding & NSObjectProtocol]) {
print("broadcastController====didUpdateServiceInfo")
}
//LIVE STREAM REPLAYKIT=========================================================
//RECORD SCREEN REPLAYKIT-------------------------------------------------------------------
func startRecoding() {
let recorder = RPScreenRecorder.shared()
if recorder.isAvailable {
recorder.startRecording(handler: { (error) in
if error == nil { // Recording has started
} else {
// Handle error
print("Dont Allow Recording")
}
})
} else {
print("Did not record screen")
//if iphone or ipad doesnt support replaykit
// create the alert
let alert = UIAlertController(title: "Alert", message: "Please make sure your device supports ReplayKit!", preferredStyle: UIAlertControllerStyle.alert)
// show the alert
self.view!.window?.rootViewController!.present(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "Try Again!", style: UIAlertActionStyle.destructive, handler: { action in
// add action
}))
}
}
func stopRecording() {
let sharedRecorder = RPScreenRecorder.shared()
sharedRecorder.stopRecording(handler: { (previewViewController: RPPreviewViewController?, error) in
if previewViewController != nil {
print("stopped recording")
previewViewController!.previewControllerDelegate = self
let alertController = UIAlertController(title: "Recording", message: "Tap view to watch, edit, share, or save your screen recording!", preferredStyle: .alert)
let viewAction = UIAlertAction(title: "View", style: .default, handler: { (action: UIAlertAction) -> Void in
self.view?.window?.rootViewController?.present(previewViewController!, animated: true, completion: nil)
})
alertController.addAction(viewAction)
self.previewViewController = previewViewController!
self.previewViewController.modalPresentationStyle = UIModalPresentationStyle.fullScreen
self.view?.window?.rootViewController!.present(alertController, animated: true, completion: nil)
}
else {
print("recording stopped working")
//create the alert================================
let alert = UIAlertController(title: "Alert", message: "Sorry, there was an error recording your screen. Please Try Again!", preferredStyle: UIAlertControllerStyle.alert)
// show the alert
self.view!.window?.rootViewController!.present(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "Try Again!", style: UIAlertActionStyle.destructive, handler: { action in
// add action
}))
}
})
}
func previewControllerDidFinish(_ previewViewController: RPPreviewViewController) {
print("cancel and save button pressed")
previewViewController.dismiss(animated: true, completion: nil)
//dismiss preview view controller when save or cancel button pressed
}
I believe that this is a bug in ReplayKit, I'm not sure if it has been resolved as of 10.1 or not, but it is worth trying the 10.1 beta to see if it solves your issue.

How To Make an Alert Only Appear Once

I'm trying to figure out is how to create a pop up window that only appears once when you start the app and then won't appear again unless you close the app and reboot it. However, if you view the code below, you will realize that the alert will pop up every time the ViewController appears. For example, if you go to the settings tab and then return to the main ViewController, then the alert will pop up.
override func viewDidAppear(animated: Bool) {
let alertController = UIAlertController(title: "Disclaimer", message: "WARNING: Please ride carefully!", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Accept", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
}
Just create a global variable that is a Bool. If the app is opened it starts at false. Then once the disclaimer is seen it sets the variable to true. Then present the View Controller based on the value of the variable.
var disclaimerHasBeenDisplayed = false
class ViewController {
override func viewDidAppear(animated: Bool) {
if disclaimerHasBeenDisplayed == false {
disclaimerHasBeenDisplayed = true
let alertController = UIAlertController(title: "Disclaimer", message: "WARNING: Wakeboarding is fun, however it can be highly dangerous.
Wake Dice is not liable for any injuries obtained while wakeboarding. Please ride carefully!", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Accept", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
}
}
}

Why can't won't the MFMailComposerViewController be dismissed?

Whenever I press "Cancel" then "Delete Draft", the mail composer won't be dismissed. The error I'm getting is "Thread 1: EXC_BAD_ACCESS (code=1, address=0x40363380)"
In my TableViewController I have:
#IBAction func mailButton(sender: AnyObject) {
let emailComposer = EmailComposer()
if email != "" {
print(email)
if emailComposer.canSendMail() {
emailComposer.setRecipient(email)
let configuredMailComposeViewController = emailComposer.configuredMailComposeViewController()
presentViewController(configuredMailComposeViewController, animated: true, completion: nil)
}
} else {
let alertController = UIAlertController(title: "Sorry!", message: "No email found for this contact", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
//do nothing
}))
self.presentViewController(alertController, animated: true, completion:nil)
}
}
For those who don't know, EXC_BAD_ACCESS means its trying to access something in memory that is no longer there. I wrongfully created the EmailComposer() object after the button tap so it was going out of scope. So this:
let emailComposer = EmailComposer()
...should have been created here, for example:
class TableViewController: UITableViewController {
let emailComposer = EmailComposer()

How do we create and dismiss an UIAlertController without user input? (Swift)

I've been looking up a lot of tutorials on UIAlertController. Thus far, the way I found was to activate a UIAlertController by linking it to a button or label and then call a IBAction.
I tried to replicate the code to automatically pop an alert when user enters the app (I wanted to ask the user if they want to go through the tutorial). However, I keep getting the error:
Warning: Attempt to present UIAlertController on MainViewController whose view is not in the window hierarchy!
Then I tried to add the UIAlertController to the MainViewController via addChildViewController and addSubview. However, I get the error:
Application tried to present modally an active controller
I figured that I cannot use the presentViewController function and commented it out.
The UIAlertController is displayed BUT when I tried to click on the cancel or the never button, this error occurs.
Trying to dismiss UIAlertController with unknown presenter.
I am really stumped. Can someone share what I am doing wrong? Thank you so much. Here is the code.
func displayTutorial() {
alertController = UIAlertController(title: NSLocalizedString("tutorialAlert", comment: ""), message: NSLocalizedString("tutorialMsg", comment: ""), preferredStyle: .ActionSheet)
self.addChildViewController(alertController)
self.view.addSubview(alertController.view)
alertController.didMoveToParentViewController(self)
alertController.view.frame.origin.x = self.view.frame.midX
alertController.view.frame.origin.y = self.view.frame.midY
//alertController.popoverPresentationController?.sourceView = self.view*/
let OkAction = UIAlertAction(title: NSLocalizedString("yesh", comment: ""), style: .Destructive) { (action) in
}
alertController.addAction(OkAction)
let cancelAction = UIAlertAction(title: NSLocalizedString("notNow", comment: ""), style: .Destructive) { (action) in
//println(action)
self.tutorial = 1
self.presentedViewController?.dismissViewControllerAnimated(true, completion: nil)
}
alertController.addAction(cancelAction)
let neverAction = UIAlertAction(title: NSLocalizedString("never", comment: ""), style: .Cancel) { (action) in
self.tutorial = 1
}
alertController.addAction(neverAction)
//self.presentViewController(alertController, animated: false) {}
}
I found the solution. Apparently, I cannot call the UIAlertController from the func viewDidLoad. I must call the function from viewDidAppear. So my code now is
override func viewDidAppear(animated: Bool) {
if tutorial == 0 {
displayTutorial(self.view)
}
}
func displayTutorial(sender:AnyObject) {
let alertController = UIAlertController(title: NSLocalizedString("tutorialAlert", comment: ""), message: NSLocalizedString("tutorialMsg", comment: ""), preferredStyle: .ActionSheet)
let OkAction = UIAlertAction(title: NSLocalizedString("yesh", comment: ""), style: .Destructive) { (action) in
}
alertController.addAction(OkAction)
let cancelAction = UIAlertAction(title: NSLocalizedString("notNow", comment: ""), style: .Default) { (action) in
//println(action)
self.tutorial = 1
self.presentedViewController?.dismissViewControllerAnimated(true, completion: nil)
}
alertController.addAction(cancelAction)
let neverAction = UIAlertAction(title: NSLocalizedString("never", comment: ""), style: .Cancel) { (action) in
self.tutorial = 1
}
alertController.addAction(neverAction)
self.presentViewController(alertController, animated: true, completion: nil)
if let pop = alertController.popoverPresentationController {
let v = sender as UIView
pop.sourceView = view
pop.sourceRect = v.bounds
}
}
Thanks to this posting: Warning: Attempt to present * on * whose view is not in the window hierarchy - swift
Below UIAlertController with extension would help you show alert with dynamic number of buttons with completion handler for selected index
extension UIViewController {
func displayAlertWith(message:String) {
displayAlertWith(message: message, buttons: ["Dismiss"]) { (index) in
}
}
func displayAlertWith(message:String, buttons:[String], completion:((_ index:Int) -> Void)!) -> Void {
displayAlertWithTitleFromVC(vc: self, title: Bundle.main.infoDictionary!["CFBundleDisplayName"] as! String, andMessage: message, buttons: buttons, completion: completion)
}
func displayAlertWithTitleFromVC(vc:UIViewController, title:String, andMessage message:String, buttons:[String], completion:((_ index:Int) -> Void)!) -> Void {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
for index in 0..<buttons.count {
let action = UIAlertAction(title: buttons[index], style: .default, handler: {
(alert: UIAlertAction!) in
if(completion != nil){
completion(index)
}
})
alertController.addAction(action)
}
DispatchQueue.main.async {
vc.present(alertController, animated: true, completion: nil)
}
}
}
If you need to auto dismiss the alert you can call dismiss on presented view controller after some delay.
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
vc.dismiss(animated: true, completion: nil)
}
Hope this might help you.