How to make Singleton in Swift - ios

I want to use Singleton to show ads, but it doesn't work well.
When I don't use Singleton and use only ViewController, it works well.(can through "vampLoadStart" and "vampDidReceive")
How can I solve it?
Pattern1: when I use Singleton (can't load and show ad)
VAMPAdReward.swift
import Foundation
import UIKit
import VAMP
class VAMPAdReward: NSObject,VAMPDelegate{
static let sharedInstance = VAMPAdReward()
var adReward:VAMP!
override init() {
super.init()
}
func loadAdReward(parentViewController: UIViewController) {
adReward = VAMP()
adReward.setPlacementId("26812") //test ID
adReward.delegate = self
adReward.setRootViewController(self)
}
func showAdReward(){
if adReward.isReady() {
print("show ad")
adReward.show()
}else{
print("couldn't show ad")
}
}
func vampLoadStart(_ placementId: String!, adnwName: String!) {
print("start loading")
}
func vampDidReceive(_ placementId: String!, adnwName: String!) {
print("finished loading")
}
}
ViewController
import UIKit
class ViewController: UIViewController {
var adReward: VAMPAdReward!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
VAMPAdReward.sharedInstance.loadAdReward(parentViewController: self)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
//when touch screen, show Ad
VAMPAdReward.sharedInstance.showAdReward()
}
}
Pattern2: when I don't use Singleton (can load and show ad)
import UIKit
import VAMP
class ViewController: UIViewController, VAMPDelegate {
var ad: VAMP!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
//load ad
ad = VAMP()
ad.setPlacementId("59755") //test ID
ad.delegate = self
ad.setRootViewController(self)
ad.load()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
ad.show()
}
func vampLoadStart(_ placementId: String!, adnwName: String!) {
print("start loading") //through
}
func vampDidReceive(_ placementId: String!, adnwName: String!) {
print("finished loading") //through
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Follow these step for accomplish your singleton class
// MARK: - Singleton
final class Singleton {
// Can't init is singleton
private init() { }
// MARK: Shared Instance
static let shared = Singleton()
// MARK: Local Variable
var emptyStringArray : [String] = []
}

Correct method in singleton
func loadAdReward(parentViewController: UIViewController) {
adReward = VAMP()
adReward.setPlacementId("26812") //test ID
adReward.delegate = self
adReward.setRootViewController(parentViewController)
adReward.load()
}

Related

admob interstitial ad is never ready [duplicate]

This question already exists:
admob interstitial alway returns false
Closed 6 years ago.
i have this game and i created 3 funcions in my gameviewcontroller and here they are
func getInterstitialAd(){
interstitial = GADInterstitial(adUnitID: "ca-app-pub-1782852253088296/5018877964")
let requestInterstitial = GADRequest()
interstitial.load(requestInterstitial)
}
func showAd() {
if (interstitial.isReady == true){
interstitial.present(fromRootViewController: GameViewController())
}else{
print("ad wasn't ready")
interstitial = createAd()
}
}
func createAd() -> GADInterstitial{
let interstital = GADInterstitial(adUnitID: "ca-app-pub-1782852253088296/5018877964")
interstitial.load(GADRequest())
return interstital
}
and in one of my scene called StartMenu , i call those function
var viewController: GameViewController!
and then i call the functions
viewController.getInterstitialAd()
viewController.showAd()
but it always returns ad not ready , and false for interstitial.isReady,
but also the getInterstitial function is always called .
can someone help with that please
Create a new swift file AdMobDelegate :-
import UIKit
import GoogleMobileAds
class AdMobDelegate: NSObject, GADInterstitialDelegate {
var interstitialView: GADInterstitial!
func createAd() -> GADInterstitial {
interstitialView = GADInterstitial(adUnitID: "Your Key")
interstitialView.delegate = self
let request = GADRequest()
interstitialView.loadRequest(request)
return interstitialView
}
func showAd() {
if interstitialView != nil {
if (interstitialView.isReady == true){
interstitialView.present(fromRootViewController:currentVc)
} else {
print("ad wasn't ready")
interstitialView = createAd()
}
} else {
print("ad wasn't ready")
interstitialView = createAd()
}
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
print("Ad Received")
if ad.isReady {
interstitialView.present(fromRootViewController: currentVc)
}
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
print("Did Dismiss Screen")
}
func interstitialWillDismissScreen(ad: GADInterstitial!) {
print("Will Dismiss Screen")
}
func interstitialWillPresentScreen(ad: GADInterstitial!) {
print("Will present screen")
}
func interstitialWillLeaveApplication(ad: GADInterstitial!) {
print("Will leave application")
}
func interstitialDidFailToPresentScreen(ad: GADInterstitial!) {
print("Failed to present screen")
}
func interstitial(ad: GADInterstitial!, didFailToReceiveAdWithError error: GADRequestError!) {
print("\(ad) did fail to receive ad with error \(error)")
}
}
Now you can use the object of this delegate class in other files as follows :-
//Define admobdelegate as global variable
var admobDelegate = AdMobDelegate()
//Declare a global variable currentVc to hold reference to current view controller
var currentVc: UIViewController!
class abc1: UIViewController {
override func viewdidload() {
super.viewdidload()
currentVc = self
admobDelegate.showAd()
}
override func viewDidAppear() {
super.viewDidAppear()
currentVc = self
}
}
class abc2: UIViewController {
override func viewdidload() {
super.viewdidload()
currentVc = self
admobDelegate.showAd()
}
override func viewDidAppear() {
super.viewDidAppear()
currentVc = self
}
}
Code is in Swift 2.2. Write your equivalent code in swift 3 in case of syntax error.

unexpectedly found nil while unwrapping an Optional value On UILabel

In my project I have implemented a protocol which makes some URL call and return result, and my intent is to show result in UILabel. Following is my code :
protocol RestAPIResult
{
func retriveDriverInfo()
}
class RestAPICall : RestAPIResult
{
func retriveDriverInfo()
{
self.dashBoardViewController.getDriverInfo(driverProfile)
// calling another function of Next View for Lable Setup
}
}
getDriverInfo is in NextView which has Outlet of textVIew
class DashBoardViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
restDeledate = RestAPICall()
restDeledate!.retriveDriverInfo()
// IF LABEL SET HERE NO ERROR
//totalTripLabel.text = "Testing" // NO ERROR
}
func getDriverInfo(driverInfoArray : NSArray)
{
totalTripLabel.text = "Testing" // HERE IS ERROR
}
}
If Text is set in ViewDidLoad() it doesn't crash. but when i tried to set value in delegate function it crash saying found null.
protocol RestAPIResult: NSObjectProtocol
{
func retriveDriverInfo(message: String)
}
class RestAPICall : RestAPIResult
{
override func viewDidLoad()
{
super.viewDidLoad()
//create an instance of your vc and
instance.delegate = self
//if you code for push vc then write this line there insatance.delegate = self
}
func retriveDriverInfo(message: String)
{
yourLbaelOutlet.text = message
}
}
class DashBoardViewController: UIViewController
{
weak var delegate: RestAPIResult!
override func viewDidLoad()
{
super.viewDidLoad()
}
func getDriverInfo(driverInfoArray : NSArray)
{
self.delegate.retriveDriverInfo(message: "youMessage")
}
}
*

Mysterious memory leak with UIActivity and UIActivityViewController

I'm running into what looks like a memory leak using Swift on iOS.
Here's a pared-down runnable example — you can tap the screen to show a share sheet, and BadActivity will leak every time.
import UIKit
class ViewController: UIViewController {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let activity = ShareController(activityItems: [""], applicationActivities: [BadActivity(), GoodActivity()])
self.showViewController(activity, sender: nil)
}
}
class ShareController: UIActivityViewController {
deinit { print("ShareController deinit.") }
}
class GoodActivity: UIActivity {
override func activityTitle() -> String { return "Good" }
deinit { print("Good deinit. This is printed.") }
}
class BadActivity: UIActivity {
override func activityTitle() -> String { return "Bad" }
deinit { print("Bad deinit. This is never printed.") }
override func canPerformWithActivityItems(activityItems: [AnyObject]) -> Bool {
return true
}
override func performActivity() {
self.activityDidFinish(true)
}
}
Regardless of whether you cancel the dialog or press export, BadActivity is instantiated but never deallocated – the console output is ShareController deinit. Good deinit.
If you make BadActivity.canPerformWithActivityItems return false instead of true, however, it deallocates normally.

Type 'ViewController' does not conform to protocol 'MPMediaPlayback'

I got this error message when trying to develop video player.
/Users/MNurdin/Documents/iOS/SwiftVideoPlayer/SwiftVideoPlayer/ViewController.swift:12:1:
Type 'ViewController' does not conform to protocol 'MPMediaPlayback'
My code
import UIKit
import MediaPlayer
class ViewController: UIViewController, MPMediaPlayback { //error message here
var isPreparedToPlay: Bool = true
var currentPlaybackRate: Float = 0.0
var currentPlaybackTime: NSTimeInterval = 0.0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func play() {
}
func pause() {
}
func stop() {
}
func prepareToPlay() {
}
func beginSeekingBackward() {
}
func beginSeekingForward() {
}
func endSeeking() {
}
}
What am I missing here?
Source code: https://github.com/datomnurdin/SwiftVideoPlayer
Reference: https://developer.apple.com/library/ios/documentation/MediaPlayer/Reference/MPMediaPlayback_protocol/index.html#//apple_ref/occ/intfp/MPMediaPlayback/currentPlaybackTime

Remote Control event in iOS with Swift

Trying to figure out how to read the Apple headphone's volume buttons to use as a trigger for the camera shutter (as the Apple Camera app does).
From the documentation on Remote Control Events,
Remote Control Received With Event, and this git repo, I've pieced together that I'll probably need an AVAudioPlayer object, .beginReceivingRemoteControlEvents(), and remoteControlReceivedWithEvent, along with making this view canBecomeFirstResponder() return true.
import UIKit
import AVFoundation
class ViewController: UIViewController, AVAudioPlayerDelegate {
var player: AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
var session: AVAudioSession = AVAudioSession.sharedInstance()
session.setActive(true, error: nil)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
println("viewDidAppear worked...")
self.becomeFirstResponder()
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
}
override func canBecomeFirstResponder() -> Bool {
return true
}
override func remoteControlReceivedWithEvent(event: UIEvent) {
let rc = event.subtype
println("does this work? \(rc.rawValue)")
//takePicture()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I expected to get "does this work" when hitting the volume buttons on the headphones, instead I just see it adjust the headphone volume like normal. So I must be missing something, maybe with a delegate or AVSession?
I cross-posted this on r/swift, where I was told it probably requires playing audio (quoted straight from the documentation).
So while this isn't the ideal solution, it works for my own private use.
import UIKit
import AVFoundation
import MediaPlayer
class ViewController: UIViewController, AVAudioPlayerDelegate {
var testPlayer: AVAudioPlayer? = nil
func loadSound(filename: NSString) -> AVAudioPlayer {
let url = NSBundle.mainBundle().URLForResource(filename as String, withExtension: "caf")
var error: NSError? = nil
let player = AVAudioPlayer(contentsOfURL: url, error: &error)
if error != nil {
println("Error loading \(url): \(error?.localizedDescription)")
} else {
player.prepareToPlay()
}
return player
}
override func viewDidLoad() {
super.viewDidLoad()
self.testPlayer = self.loadSound("silence")
self.testPlayer?.numberOfLoops = -1
self.testPlayer?.play()
}
override func canBecomeFirstResponder() -> Bool {
return true
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.becomeFirstResponder()
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
}
override func remoteControlReceivedWithEvent(event: UIEvent) {
let rc = event.subtype
println("rc.rawValue: \(rc.rawValue)")
// take photo
}
}
I noticed that in Apple's camera app, the +/- volume buttons trigger the camera, and the microphone button pauses/plays any audio running in another app, but in this implementation the volume buttons still control the volume (and any audio has been paused when the app is launched).
An rc.rawValue: 103 corresponds to a single click of the microphone button, a double click returns 104, and a triple click returns 105, and then sometimes bumping a couple at a time returns a 108 or 109.
Based on Cody's answer but updated for 2019 (Swift 5)
import UIKit
import AVFoundation
import MediaPlayer
class ViewController: UIViewController, AVAudioPlayerDelegate {
var myPlayer: AVAudioPlayer? = nil
func loadSound(filename: NSString) -> AVAudioPlayer? {
let url = Bundle.main.url(forResource: filename as String, withExtension: "mp3")
do {
let player = try AVAudioPlayer(contentsOf: url ?? URL(fileURLWithPath: ""))
player.prepareToPlay()
return player
}
catch {
print("Error : \(error)")
return nil
}
}
override func viewDidLoad() {
super.viewDidLoad()
guard let testPlayer = loadSound(filename: "silence") else {
print("Not able to load the sound")
return
}
testPlayer.delegate = self
testPlayer.volume = 0.8
testPlayer.numberOfLoops = -1
myPlayer = testPlayer
myPlayer?.play()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.becomeFirstResponder()
UIApplication.shared.beginReceivingRemoteControlEvents()
}
override func remoteControlReceived(with event: UIEvent?) {
let rc = event?.subtype
print("rc.rawValue: \(rc?.rawValue)")
// Do your thing
}
}

Resources