// // FirstViewController.swift // grandfatherrock // // Created by Micah Gomez on 4/15/20. // Copyright © 2020 Micah Gomez. All rights reserved. // import UIKit import AVFoundation import MediaPlayer import StoreKit protocol ObjectSavable { func setObject(_ object: Object, forKey: String) throws where Object: Encodable func getObject(forKey: String, castTo type: Object.Type) throws -> Object where Object: Decodable } enum ObjectSavableError: String, LocalizedError { case unableToEncode = "Unable to encode object into data" case noValue = "No data object found for the given key" case unableToDecode = "Unable to decode object into given type" var errorDescription: String? { rawValue } } extension UserDefaults: ObjectSavable { func setObject(_ object: Object, forKey: String) throws where Object: Encodable { let encoder = JSONEncoder() do { let data = try encoder.encode(object) set(data, forKey: forKey) } catch { throw ObjectSavableError.unableToEncode } } func getObject(forKey: String, castTo type: Object.Type) throws -> Object where Object: Decodable { guard let data = data(forKey: forKey) else { throw ObjectSavableError.noValue } let decoder = JSONDecoder() do { let object = try decoder.decode(type, from: data) return object } catch { throw ObjectSavableError.unableToDecode } } } public class musicHandler{ @objc class func updateMusic(){ timer.invalidate() print("updating song") GlobalVars.hour = Calendar.current.component(.hour, from: Date()) //song = GlobalVars.titleCode + hourPadding + String(GlobalVars.hour) //print(song) let musicPlayer = MPMusicPlayerController.applicationMusicPlayer do{ var mediaPredicate = MPMediaPredicate() switch GlobalVars.selectedMusicList { case 0: if(GlobalVars.musicSelectionID0[GlobalVars.hour] != 0){ mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID0[GlobalVars.hour], forProperty: "persistentID") } else { var searchID:UInt64 = 0 var searchHour:Int = GlobalVars.hour while (searchID == 0) { if(searchHour > 0){ searchHour -= 1 } else { searchHour = 23 } if(searchHour == GlobalVars.hour){ print("no songs found!") break } print("searching ", searchHour) searchID = GlobalVars.musicSelectionID0[searchHour] print(searchID) } print("Song Found!") mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID0[searchHour], forProperty: "persistentID") } case 1: if(GlobalVars.musicSelectionID1[GlobalVars.hour] != 0){ mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID1[GlobalVars.hour], forProperty: "persistentID") } else { var searchID:UInt64 = 0 var searchHour:Int = GlobalVars.hour while (searchID == 0) { if(searchHour > 0){ searchHour -= 1 } else { searchHour = 23 } if(searchHour == GlobalVars.hour){ print("no songs found!") break } print("searching ", searchHour) searchID = GlobalVars.musicSelectionID1[searchHour] print(searchID) } print("Song Found!") mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID1[searchHour], forProperty: "persistentID") } case 2: if(GlobalVars.musicSelectionID2[GlobalVars.hour] != 0){ mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID2[GlobalVars.hour], forProperty: "persistentID") } else { var searchID:UInt64 = 0 var searchHour:Int = GlobalVars.hour while (searchID == 0) { if(searchHour > 0){ searchHour -= 1 } else { searchHour = 23 } if(searchHour == GlobalVars.hour){ print("no songs found!") break } print("searching ", searchHour) searchID = GlobalVars.musicSelectionID2[searchHour] print(searchID) } print("Song Found!") mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID2[searchHour], forProperty: "persistentID") } case 3: if(GlobalVars.musicSelectionID3[GlobalVars.hour] != 0){ mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID3[GlobalVars.hour], forProperty: "persistentID") } else { var searchID:UInt64 = 0 var searchHour:Int = GlobalVars.hour while (searchID == 0) { if(searchHour > 0){ searchHour -= 1 } else { searchHour = 23 } if(searchHour == GlobalVars.hour){ print("no songs found!") break } print("searching ", searchHour) searchID = GlobalVars.musicSelectionID3[searchHour] print(searchID) } print("Song Found!") mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID3[searchHour], forProperty: "persistentID") } case 4: if(GlobalVars.musicSelectionID4[GlobalVars.hour] != 0){ mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID4[GlobalVars.hour], forProperty: "persistentID") } else { var searchID:UInt64 = 0 var searchHour:Int = GlobalVars.hour while (searchID == 0) { if(searchHour > 0){ searchHour -= 1 } else { searchHour = 23 } if(searchHour == GlobalVars.hour){ print("no songs found!") break } print("searching ", searchHour) searchID = GlobalVars.musicSelectionID4[searchHour] print(searchID) } print("Song Found!") mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID4[searchHour], forProperty: "persistentID") } default: if(GlobalVars.musicSelectionID0[GlobalVars.hour] != 0){ mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID0[GlobalVars.hour], forProperty: "persistentID") } else { var searchID:UInt64 = 0 var searchHour:Int = GlobalVars.hour while (searchID == 0) { if(searchHour > 0){ searchHour -= 1 } else { searchHour = 23 } if(searchHour == GlobalVars.hour){ print("no songs found!") break } print("searching ", searchHour) searchID = GlobalVars.musicSelectionID0[searchHour] print(searchID) } print("Song Found!") mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID0[searchHour], forProperty: "persistentID") } } //let mediaPredicate = MPMediaPropertyPredicate(value: GlobalVars.musicSelectionID1[GlobalVars.hour], forProperty: "persistentID") let mediaQuery = MPMediaQuery() mediaQuery.addFilterPredicate(mediaPredicate) //let mediaItemCollection: MPMediaItemCollection = MPMediaItemCollection() musicPlayer.setQueue(with: mediaQuery) print(mediaQuery) //musicPlayer.play() } if(MPMusicPlayerController.applicationMusicPlayer.playbackState == MPMusicPlaybackState.playing){ musicPlayer.play() } if(Calendar.current.component(.minute, from: Date()) == 0){ date = Date().addingTimeInterval(3600) } else{ let currentMinute = Calendar.current.component(.minute, from: Date()) let currentSeconds = Calendar.current.component(.second, from: Date()) let timeTillTopOfTheHour = 3600 - currentSeconds - (currentMinute * 60) date = Date().addingTimeInterval(TimeInterval(timeTillTopOfTheHour)) } print(date) timer = Timer(fireAt: date, interval: 0, target: self, selector: #selector(updateMusic), userInfo: nil, repeats: false) RunLoop.main.add(timer, forMode: RunLoop.Mode.common) } } struct GlobalVars { static var musicSelectionID0:[UInt64] = [UInt64]() static var musicSelection0:[String] = [String]() static var musicSelectionID1:[UInt64] = [UInt64]() static var musicSelection1:[String] = [String]() static var musicSelectionID2:[UInt64] = [UInt64]() static var musicSelection2:[String] = [String]() static var musicSelectionID3:[UInt64] = [UInt64]() static var musicSelection3:[String] = [String]() static var musicSelectionID4:[UInt64] = [UInt64]() static var musicSelection4:[String] = [String]() static var selectedMusicList:Int = 0 static var musicStarted = false static var titleName = UserDefaults.standard.string(forKey: "selectedTitle") static var hour = Calendar.current.component(.hour, from: Date()) } var i = 0 var date = Date() var timer = Timer() let currentSeconds = Calendar.current.component(.second, from: Date()) let currentMinute = Calendar.current.component(.minute, from: Date()) let timeTillTopOfTheHour = 3600 - currentSeconds - (currentMinute * 60) var hourPadding = "" var prevVol = 0.0 class FirstViewController: UIViewController{ let defaults = UserDefaults.standard let musicPlayer = MPMusicPlayerController.applicationMusicPlayer //@IBOutlet weak var dateLabel: UILabel! @IBOutlet weak var timeLabel: UILabel! var labelTimer = Timer() @objc func tick() { //dateLabel.text = DateFormatter.localizedString(from: Date(), dateStyle: .long, timeStyle: .none) timeLabel.text = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .short) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. musicPlayer.stop() GlobalVars.musicStarted = false IAPHandler.shared.fetchAvailableProducts() IAPHandler.shared.purchaseStatusBlock = {[weak self] (type) in guard let strongSelf = self else{ return } if type == .purchased { let alertView = UIAlertController(title: "", message: type.message(), preferredStyle: .alert) let action = UIAlertAction(title: "OK", style: .default, handler: { (alert) in }) alertView.addAction(action) strongSelf.present(alertView, animated: true, completion: nil) } } if(!defaults.bool(forKey: "didRun")){ defaults.set("New Horizons", forKey: "selectedTitle") defaults.set(0, forKey: "titleNo") //defaults.set(true, forKey: "didRun") GlobalVars.musicSelectionID0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] GlobalVars.musicSelection0 = ["","","","","","","","","","","","","","","","","","","","","","","",""] GlobalVars.musicSelectionID1 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] GlobalVars.musicSelection1 = ["","","","","","","","","","","","","","","","","","","","","","","",""] GlobalVars.musicSelectionID2 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] GlobalVars.musicSelection2 = ["","","","","","","","","","","","","","","","","","","","","","","",""] GlobalVars.musicSelectionID3 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] GlobalVars.musicSelection3 = ["","","","","","","","","","","","","","","","","","","","","","","",""] GlobalVars.musicSelectionID4 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] GlobalVars.musicSelection4 = ["","","","","","","","","","","","","","","","","","","","","","","",""] do { try defaults.setObject(GlobalVars.musicSelection0, forKey: "savedMusicSelection0") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID0, forKey: "savedMusicSelectionID0") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelection1, forKey: "savedMusicSelection1") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID1, forKey: "savedMusicSelectionID1") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelection2, forKey: "savedMusicSelection2") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID2, forKey: "savedMusicSelectionID2") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelection3, forKey: "savedMusicSelection3") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID3, forKey: "savedMusicSelectionID3") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelection4, forKey: "savedMusicSelection4") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID4, forKey: "savedMusicSelectionID4") } catch { print(error.localizedDescription) } print("First App run") } else { do { GlobalVars.musicSelection0 = try defaults.getObject(forKey: "savedMusicSelection0", castTo: [String].self) print(GlobalVars.musicSelection0) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelectionID0 = try defaults.getObject(forKey: "savedMusicSelectionID0", castTo: [UInt64].self) print(GlobalVars.musicSelectionID0) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelection1 = try defaults.getObject(forKey: "savedMusicSelection1", castTo: [String].self) print(GlobalVars.musicSelection1) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelectionID1 = try defaults.getObject(forKey: "savedMusicSelectionID1", castTo: [UInt64].self) print(GlobalVars.musicSelectionID1) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelection2 = try defaults.getObject(forKey: "savedMusicSelection2", castTo: [String].self) print(GlobalVars.musicSelection2) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelectionID2 = try defaults.getObject(forKey: "savedMusicSelectionID2", castTo: [UInt64].self) print(GlobalVars.musicSelectionID2) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelection3 = try defaults.getObject(forKey: "savedMusicSelection3", castTo: [String].self) print(GlobalVars.musicSelection3) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelectionID3 = try defaults.getObject(forKey: "savedMusicSelectionID3", castTo: [UInt64].self) print(GlobalVars.musicSelectionID3) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelection4 = try defaults.getObject(forKey: "savedMusicSelection4", castTo: [String].self) print(GlobalVars.musicSelection4) } catch { print(error.localizedDescription) } do { GlobalVars.musicSelectionID4 = try defaults.getObject(forKey: "savedMusicSelectionID4", castTo: [UInt64].self) print(GlobalVars.musicSelectionID4) } catch { print(error.localizedDescription) } do { GlobalVars.selectedMusicList = try defaults.getObject(forKey: "savedSelectedMusicList", castTo: Int.self) print(GlobalVars.selectedMusicList) } catch { print(error.localizedDescription) } print("App Ran Before") } print(currentSeconds) print(currentMinute) print(timeTillTopOfTheHour) //print(GlobalVars.selectedSong) GlobalVars.hour = Calendar.current.component(.hour, from: Date()) date = Date().addingTimeInterval(TimeInterval(timeTillTopOfTheHour)) print(date) timer = Timer(fireAt: date, interval: 0, target: musicHandler.self, selector: #selector(musicHandler.updateMusic), userInfo: nil, repeats: false) RunLoop.main.add(timer, forMode: .common) //dateLabel.text = DateFormatter.localizedString(from: Date(), dateStyle: .long, timeStyle: .none) timeLabel.text = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .short) labelTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector:#selector(self.tick) , userInfo: nil, repeats: true) /*do{ audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: song, ofType: "mp3")!)) audioPlayer.prepareToPlay() audioPlayer.numberOfLoops = -1 let audioSession = AVAudioSession.sharedInstance() do{ try audioSession.setCategory(.playback, mode: .default) try audioSession.setActive(true) } } catch{ print(error) }*/ } @IBOutlet var gradientView: UIView! override func viewDidAppear(_ animated: Bool) { print("fuck!") if (!defaults.bool(forKey: "didRun")){ let fuckAlert = UIAlertController(title: "Welcome!", message: "Please visit the 'Select Music' tab to set your hourly playlist, and come back here and hit play once it's ready!", preferredStyle: .alert) // Create OK button let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in print("Ok button tapped"); } fuckAlert.addAction(OKAction) // Present Dialog message self.present(fuckAlert, animated: true, completion:nil) defaults.set(true, forKey: "didRun") } var foundSong = false switch GlobalVars.selectedMusicList { case 0: for i in GlobalVars.musicSelectionID0 { if (i != 0){ foundSong = true } } case 1: for i in GlobalVars.musicSelectionID1 { if (i != 0){ foundSong = true } } case 2: for i in GlobalVars.musicSelectionID2 { if (i != 0){ foundSong = true } } case 3: for i in GlobalVars.musicSelectionID3 { if (i != 0){ foundSong = true } } case 4: for i in GlobalVars.musicSelectionID4 { if (i != 0){ foundSong = true } } default: for i in GlobalVars.musicSelectionID0 { if (i != 0){ foundSong = true } } } if !foundSong && defaults.bool(forKey: "didRun") { let errorAlert = UIAlertController(title: "Song Error", message: "No songs found in this track. Please visit the 'Select Music' tab to set a song and get started!", preferredStyle: .alert) // Create OK button let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in print("Ok button tapped"); } errorAlert.addAction(OKAction) // Present Dialog message self.present(errorAlert, animated: true, completion:nil) print("Song is missing for at one hour") controlButton.isEnabled = false } else { controlButton.isEnabled = true } self.view.layoutIfNeeded() } override func viewWillAppear(_ animated: Bool) { // create the gradient layer let gradient = CAGradientLayer() gradient.frame = self.view.bounds print("time: ", GlobalVars.hour) if((GlobalVars.hour >= 8) && (GlobalVars.hour <= 19)){ //Daytime print("day") gradient.colors = [UIColor(red: 0.39, green: 0.69, blue: 1.00, alpha: 1).cgColor, UIColor(red: 0.07, green: 0.45, blue: 0.87, alpha: 1).cgColor] } else if((GlobalVars.hour >= 20) && (GlobalVars.hour <= 21)){//Sunset print("sunset") gradient.colors = [UIColor(red: 0.00, green: 0.31, blue: 0.59, alpha: 1).cgColor, UIColor(red: 1.00, green: 0.78, blue: 0.88, alpha: 1).cgColor] } else if((GlobalVars.hour >= 22) || (GlobalVars.hour <= 5)){//Night print("night") gradient.colors = [UIColor(red: 0.08, green: 0.27, blue: 0.59, alpha: 1).cgColor, UIColor(red: 0.00, green: 0.20, blue: 0.29, alpha: 1).cgColor] } else if((GlobalVars.hour >= 6) && (GlobalVars.hour <= 7)){//Sunrise print("sunrise") gradient.colors = [UIColor(red: 0.02, green: 0.26, blue: 0.49, alpha: 1).cgColor, UIColor(red: 0.89, green: 0.68, blue: 0.60, alpha: 1).cgColor] } gradient.locations = [0.00, 1.00] /*let gradientChangeAnimation = CABasicAnimation(keyPath: "colors") gradientChangeAnimation.duration = 5.0 if((GlobalVars.hour >= 8) && (GlobalVars.hour <= 19)){ //Daytime print("day") gradientChangeAnimation.toValue = [UIColor(red: 0.00, green: 0.31, blue: 0.59, alpha: 1).cgColor, UIColor(red: 0.07, green: 0.45, blue: 0.87, alpha: 1).cgColor] } else if((GlobalVars.hour >= 20) && (GlobalVars.hour <= 21)){//Sunset print("sunset") gradientChangeAnimation.toValue = [UIColor(red: 0.00, green: 0.31, blue: 0.59, alpha: 1).cgColor, UIColor(red: 1.00, green: 0.61, blue: 0.43, alpha: 1).cgColor] } else if((GlobalVars.hour >= 22) || (GlobalVars.hour <= 5)){//Night print("night") gradientChangeAnimation.toValue = [ UIColor(red: 0.68, green: 0.67, blue: 1.0, alpha: 1).cgColor, UIColor(red: 1.00, green: 0.00, blue: 0.09, alpha: 1).cgColor ] } else if((GlobalVars.hour >= 6) && (GlobalVars.hour <= 7)){//Sunrise print("sunrise") gradientChangeAnimation.toValue = [UIColor(red: 0.02, green: 0.26, blue: 0.49, alpha: 1).cgColor, UIColor(red: 0.89, green: 0.68, blue: 0.60, alpha: 1).cgColor] } gradientChangeAnimation.autoreverses = true gradientChangeAnimation.fillMode = CAMediaTimingFillMode.forwards gradientChangeAnimation.isRemovedOnCompletion = false gradient.add(gradientChangeAnimation, forKey: "colorChange") */ // add the gradient to the view gradientView.layer.addSublayer(gradient) if (MPMusicPlayerController.applicationMusicPlayer.playbackState == MPMusicPlaybackState.playing) { GlobalVars.musicStarted = true controlButton.setBackgroundImage(UIImage(systemName: "pause.circle"), for: UIControl.State.normal) UIView.animate(withDuration: 0.4, delay: 0,usingSpringWithDamping: 0.5,initialSpringVelocity: 0){ self.PlayButtonSize.constant = 130 } } else { GlobalVars.musicStarted = false controlButton.setBackgroundImage(UIImage(systemName: "play.circle"), for: UIControl.State.normal) UIView.animate(withDuration: 0.4, delay: 0,usingSpringWithDamping: 0.5,initialSpringVelocity: 0){ self.PlayButtonSize.constant = 90 } } } override func viewWillDisappear(_ animated: Bool) { gradientView.layer.sublayers?.forEach { $0.removeFromSuperlayer() } do { try defaults.setObject(GlobalVars.musicSelection0, forKey: "savedMusicSelection0") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID0, forKey: "savedMusicSelectionID0") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelection1, forKey: "savedMusicSelection1") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID1, forKey: "savedMusicSelectionID1") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelection2, forKey: "savedMusicSelection2") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID2, forKey: "savedMusicSelectionID2") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelection3, forKey: "savedMusicSelection3") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID3, forKey: "savedMusicSelectionID3") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelection4, forKey: "savedMusicSelection4") } catch { print(error.localizedDescription) } do { try defaults.setObject(GlobalVars.musicSelectionID4, forKey: "savedMusicSelectionID4") } catch { print(error.localizedDescription) } } @IBOutlet weak var controlButton: UIButton! @IBOutlet var PlayButtonSize: NSLayoutConstraint! @IBAction func play(_ sender: Any) { if(!GlobalVars.musicStarted){ GlobalVars.musicStarted = true musicHandler.updateMusic() let musicPlayer = MPMusicPlayerController.applicationMusicPlayer musicPlayer.play() GlobalVars.musicStarted = true controlButton.setBackgroundImage(UIImage(systemName: "pause.circle"), for: UIControl.State.normal) UIView.animate(withDuration: 0.4,delay:0,usingSpringWithDamping: 0.5,initialSpringVelocity: 0){ self.PlayButtonSize.constant = 130 self.view.layoutIfNeeded() } } else{ let musicPlayer = MPMusicPlayerController.applicationMusicPlayer musicPlayer.pause() GlobalVars.musicStarted = false controlButton.setBackgroundImage(UIImage(systemName: "play.circle"), for: UIControl.State.normal) UIView.animate(withDuration: 0.4, delay: 0,usingSpringWithDamping: 0.5,initialSpringVelocity: 0){ self.PlayButtonSize.constant = 90 self.view.layoutIfNeeded() } } } /*@objc func updateMusic(){ //timer.invalidate() prevVol = Double(audioPlayer.volume) audioPlayer.setVolume(0, fadeDuration: 3) print("updating song") hour = Calendar.current.component(.hour, from: date) if(hour<10){ hourPadding = "0" } else{ hourPadding = "" } song = "acnh" + hourPadding + String(hour) print(song) do{ audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: song, ofType: "mp3")!)) audioPlayer.prepareToPlay() audioPlayer.numberOfLoops = -1 let audioSession = AVAudioSession.sharedInstance() do{ try audioSession.setCategory(.playback, mode: .default) try audioSession.setActive(true) } } catch{ print(error) } if(GlobalVars.musicStarted){ audioPlayer.play() } audioPlayer.setVolume(Float(prevVol), fadeDuration: 1) date = date.addingTimeInterval(3600) print(date) timer = Timer(fireAt: date, interval: 0, target: self, selector: #selector(updateMusic), userInfo: nil, repeats: false) RunLoop.main.add(timer, forMode: RunLoop.Mode.common) }*/ } enum IAPHandlerAlertType{ case disabled case restored case purchased func message() -> String{ switch self { case .disabled: return "Purchases are disabled in your device!" case .restored: return "You've successfully restored your purchase!" case .purchased: return "You've successfully bought this purchase!" } } } class IAPHandler: NSObject { static let shared = IAPHandler() let SMALL_TIP_PRODUCT_ID = "smalltip" let MEDIUM_TIP_PRODUCT_ID = "mediumtip" let LARGE_TIP_PRODUCT_ID = "largetip" fileprivate var productID = "" fileprivate var productsRequest = SKProductsRequest() fileprivate var iapProducts = [SKProduct]() var purchaseStatusBlock: ((IAPHandlerAlertType) -> Void)? // MARK: - MAKE PURCHASE OF A PRODUCT func canMakePurchases() -> Bool { return SKPaymentQueue.canMakePayments() } func purchaseMyProduct(index: Int){ if iapProducts.count == 0 { return } if self.canMakePurchases() { let product = iapProducts[index] let payment = SKPayment(product: product) SKPaymentQueue.default().add(self) SKPaymentQueue.default().add(payment) print("PRODUCT TO PURCHASE: \(product.productIdentifier)") productID = product.productIdentifier } else { purchaseStatusBlock?(.disabled) } } // MARK: - RESTORE PURCHASE func restorePurchase(){ SKPaymentQueue.default().add(self) SKPaymentQueue.default().restoreCompletedTransactions() } // MARK: - FETCH AVAILABLE IAP PRODUCTS func fetchAvailableProducts(){ // Put here your IAP Products ID's let productIdentifiers = NSSet(objects: SMALL_TIP_PRODUCT_ID,MEDIUM_TIP_PRODUCT_ID,LARGE_TIP_PRODUCT_ID ) productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set) productsRequest.delegate = self productsRequest.start() } } extension IAPHandler: SKProductsRequestDelegate, SKPaymentTransactionObserver{ // MARK: - REQUEST IAP PRODUCTS func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) { if (response.products.count > 0) { iapProducts = response.products for product in iapProducts{ let numberFormatter = NumberFormatter() numberFormatter.formatterBehavior = .behavior10_4 numberFormatter.numberStyle = .currency numberFormatter.locale = product.priceLocale let price1Str = numberFormatter.string(from: product.price) print(product.localizedDescription + "\nfor just \(price1Str!)") } } } func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { purchaseStatusBlock?(.restored) } // MARK:- IAP PAYMENT QUEUE func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction:AnyObject in transactions { if let trans = transaction as? SKPaymentTransaction { switch trans.transactionState { case .purchased: print("purchased") SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) purchaseStatusBlock?(.purchased) break case .failed: print("failed") SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) break case .restored: print("restored") SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction) break default: break }}} } }