How can i use UISwitch to turn of local notification? - ios

Can anyone help me how to use the state of a UISwitch to turn on/off local notifications declared in Appdelegate.swift ?
Viewcontroller.swift:
#IBOutlet weak var switchButton: UISwitch!
var switchState = true
let switchKey = "switchState"
#IBAction func saveSwitchPressed(sender: AnyObject) {
NSUserDefaults.standardUserDefaults().setBool(switchButton.on, forKey: "switchState")
}
override public func viewDidLoad() {
super.viewDidLoad()
switchButton.on = NSUserDefaults.standardUserDefaults().boolForKey("switchState")
}
AppDelegate.swift
func handleRegionEvent(region: CLRegion) {
// Show an alert if application is active
if UIApplication.sharedApplication().applicationState == .Active {
if let message = notefromRegionIdentifier(region.identifier) {
if let viewController = window?.rootViewController {
showSimpleAlertWithTitle(nil, message: message, viewController: viewController)
}
}
} else {
// Otherwise present a local notification
let notification = UILocalNotification()
notification.alertBody = notefromRegionIdentifier(region.identifier)
notification.soundName = "Default";
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}
}

This should can be accomplished using targetAction
override public func viewDidLoad() {
super.viewDidLoad()
switchButton.on = NSUserDefaults.standardUserDefaults().boolForKey("switchState")
//Set button to observe target action
switchButton.addTarget(self, action: "presentNotification", forControlEvents: UIControlEvents.ValueChanged)
}
func presentNotification() {
//Do notification stuff here
}

Related

How to keep label results on secondViewController?

I am currently working on an app and I am stuck on the following: I have my mainVC (ReceiveInputVC), which after I enter an input, it goes to the secondVC (TimeLeftVC) and it updates all of its labels with results from the inputs received from the mainVC. My question is: How can I, after clicking on the arrow to go back to the mainVC or even if I close the app, when I click on the arrow from the mainVC to go to the secondVC have my labels showing the same values as before the user closed the application or returned to the main screen?
import UIKit
extension UIViewController {
func hideKeyboard() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
}
class ReceiveInputVC: UIViewController {
#IBOutlet weak var hourglassButton: UIButton!
#IBOutlet weak var whatIsYourAgeField: UITextField!
#IBOutlet weak var ageToDieField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.hideKeyboard()
}
#IBAction func arrowBtnPressed(_ sender: Any) {
// When pressed should show go to TimeLeftVC and show last result from the first time user entered the inputs, if nothing has been typed yet and no data has been saved an alert should pop up asking the user to enter an input on both fields
}
#IBAction func hourglassBtnPressed(_ sender: Any) {
let checkAgeField: Int? = Int(whatIsYourAgeField.text!)
let checkDyingAgeField: Int? = Int(ageToDieField.text!)
if (whatIsYourAgeField.text == "" || ageToDieField.text == "") || (whatIsYourAgeField.text == "" && ageToDieField.text == "") {
alert(message: "You must enter an input on both fields")
} else if checkAgeField! < 1 || checkDyingAgeField! > 100 {
alert(message: "You must enter an age higher than 1 and a dying age lower than 100")
} else if (checkAgeField! > checkDyingAgeField!) || (checkAgeField! == checkDyingAgeField!) {
alert(message: "You must enter an age lower than a dying age")
} else {
performSegue(withIdentifier: "goToSecondScreen", sender: self)
}
}
func alert(message: String, title: String = "Alert") {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Try Again", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// Passing the data entered from ReceiveInputVC to TimeLeftVC
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToSecondScreen" {
let destinationTimeLeftVC = segue.destination as! TimeLeftVC
destinationTimeLeftVC.ageReceived = whatIsYourAgeField.text
destinationTimeLeftVC.ageToDieReceived = ageToDieField.text
}
}
}
import CircleProgressBar
class TimeLeftVC: UIViewController {
var ageReceived: String! // receive whatIsYourAgeField data from ReceiveInputVC
var ageToDieReceived: String! // receive ageToDieField data from ReceiveInputVC
#IBOutlet weak var yearsLeftLabel: UILabel!
#IBOutlet weak var daysLeftLabel: UILabel!
#IBOutlet weak var hoursLeftLabel: UILabel!
#IBOutlet weak var progressBar: CircleProgressBar!
override func viewDidLoad() {
super.viewDidLoad()
createResults()
}
func createResults() {
if let userAge = Int(ageReceived), let dyingAge = Int(ageToDieReceived) {
let yearsLeft = dyingAge - userAge
let daysLeft = yearsLeft * 365
let hoursLeft = daysLeft * 24
// Update UI
yearsLeftLabel.text = "\(yearsLeft)"
daysLeftLabel.text = "\(daysLeft)"
hoursLeftLabel.text = "\(hoursLeft)"
let percentage = (CGFloat(yearsLeft) / CGFloat(dyingAge)) * 100
let formatted = String(format: "%.1f", percentage)
// Update Circle Progress Bar
progressBar.setHintTextGenerationBlock { (progress) -> String? in
return String.init(format: "\(formatted)%%", arguments: [progress])
}
progressBar.setProgress(percentage/100, animated: true, duration: 4.0)
}
}
Project on GitHub: https://github.com/mvvieira95/Time-Life.git
You can use Coredata or another data base or user default
User default implementation:
#IBAction func arrowBtnPressed(_ sender: Any) {
UserDefaults.standard.set("your input values from text field or ...", forKey: "key")
}
In second view controller get it with
UserDefaults.standard.string(forKey: "key")
You can save and restore states with these methods
application:shouldSaveApplicationState and application:shouldRestoreApplicationStat.
Example:
func application(_ application: UIApplication,
shouldSaveApplicationState coder: NSCoder) -> Bool {
// Save the current app version to the archive.
coder.encode(11.0, forKey: "MyAppVersion")
// Always save state information.
return true
}
func application(_ application: UIApplication,
shouldRestoreApplicationState coder: NSCoder) -> Bool {
// Restore the state only if the app version matches.
let version = coder.decodeFloat(forKey: "MyAppVersion")
if version == 11.0 {
return true
}
// Do not restore from old data.
return false
}
You can explore the document in https://developer.apple.com/documentation/uikit/view_controllers/preserving_your_app_s_ui_across_launches?language=objc
Thanks guys, I came up with a solution:
class ReceiveInputVC: UIViewController {
#IBAction func arrowBtnPressed(_ sender: Any) {
let defaults = UserDefaults.standard
if let _ = defaults.object(forKey: "yearsSaved"), let _ = defaults.object(forKey: "daysSaved"), let _ = defaults.object(forKey: "hoursSaved") {
performSegue(withIdentifier: "goToSecondScreen", sender: self)
} else {
alert(message: "You must first enter an input")
}
}
class TimeLeftVC: UIViewController {
var ageReceived: String! // receive whatIsYourAgeField data from ReceiveInputVC
var ageToDieReceived: String! // receive ageToDieField data from ReceiveInputVC
#IBOutlet weak var yearsLeftLabel: UILabel!
#IBOutlet weak var daysLeftLabel: UILabel!
#IBOutlet weak var hoursLeftLabel: UILabel!
#IBOutlet weak var progressBar: CircleProgressBar!
override func viewDidLoad() {
super.viewDidLoad()
let defaults = UserDefaults.standard
yearsLeftLabel.text = defaults.object(forKey: "yearsSaved") as? String
daysLeftLabel.text = defaults.object(forKey: "daysSaved") as? String
hoursLeftLabel.text = defaults.object(forKey: "hoursSaved") as? String
}
override func viewWillAppear(_ animated: Bool) {
createResults()
}
func createResults() {
if let userAge = Int(ageReceived), let dyingAge = Int(ageToDieReceived) {
let yearsLeft = dyingAge - userAge
let daysLeft = yearsLeft * 365
let hoursLeft = daysLeft * 24
// Update UI
yearsLeftLabel.text = "\(yearsLeft)"
daysLeftLabel.text = "\(daysLeft)"
hoursLeftLabel.text = "\(hoursLeft)"
// Store Data
let defaults = UserDefaults.standard
defaults.set(yearsLeftLabel.text, forKey: "yearsSaved")
defaults.set(daysLeftLabel.text, forKey: "daysSaved")
defaults.set(hoursLeftLabel.text, forKey: "hoursSaved")
// Update Circle Progress Bar
let percentage = (CGFloat(yearsLeft) / CGFloat(dyingAge)) * 100
let formatted = String(format: "%.1f", percentage)
progressBar.setHintTextGenerationBlock { (progress) -> String? in
return String.init(format: "\(formatted)%%", arguments: [progress])
}
progressBar.setProgress(percentage/100, animated: true, duration: 4.0)
}
}
Having troubles now updating that progressBar when I go back to the view...

Value of type 'PlaySoundsViewController' has no member 'recordedAudio'

I've been following Udacity's Intro to iOS App Development with Swift tutorial, but got this error.
Value of type 'PlaySoundsViewController' has no member 'recordedAudio'
Line 84 has the error.
playSoundsVC.recordedAudio = recordedAudioURL
Here is the entire code:
import UIKit
import AVFoundation
class RecordSoundsViewController: UIViewController , AVAudioRecorderDelegate {
#IBOutlet weak var recordingInProgress: UILabel!
#IBOutlet weak var stopButton: UIButton!
#IBOutlet weak var recordButton: UIButton!
var audioRecorder:AVAudioRecorder!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
//TODO: Hide stop button
stopButton.hidden = true
//TODO: Enable recordButton
recordButton.enabled = true
}
#IBAction func recordAudio(sender: AnyObject) {
//TODO: Show text "recording in progress"
recordingInProgress.hidden = false
//TODO: Show stopButton
stopButton.hidden = false
//TODO: Record the user's voice
print("in recordAudio")
//TODO: Disable recording button
recordButton.enabled = false
let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask, true)[0] as String
let recordingName = "recordedVoice.wav"
let pathArray = [dirPath, recordingName]
let filePath = NSURL.fileURLWithPathComponents(pathArray)
print(filePath)
let session = AVAudioSession.sharedInstance()
try! session.setCategory(AVAudioSessionCategoryPlayAndRecord)
try! audioRecorder = AVAudioRecorder(URL: filePath!, settings: [:])
audioRecorder.meteringEnabled = true
audioRecorder.prepareToRecord()
audioRecorder.record()
}
#IBAction func stopRecording(sender: AnyObject) {
//TODO: hide recordingInProgress label
recordingInProgress.hidden = true
recordButton.enabled = true
let audioSession = AVAudioSession.sharedInstance()
try! audioSession.setActive(false)
}
func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {
print("AVAudioRecorder finished saving recording")
if (flag) {
self.performSegueWithIdentifier("stopRecording", sender: audioRecorder.url)
} else {
print("Saving of recording failed")
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "stopRecording") {
let playSoundsVC = segue.destinationViewController as!
PlaySoundsViewController
let recordedAudioURL = sender as! NSURL
playSoundsVC.recordedAudio = recordedAudioURL
}
}
}
class PlaySoundsViewController: UIViewController {
var recordedURL: URL?
override func viewDidLoad() {
super.viewDidLoad()
}
}
Don't forget to add an identifier for segue:
add var recordedAudioURL:URL! to your PlaySoundsViewController file
it is a variable that holds the url in the next class which is been send from the current class.
happy coding :)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "stopRecording") {
let playSoundsVC = segue.destinationViewController as! PlaySoundViewController
let recordedAudioURL = sender as! NSURL
playSoundsVC.recordedAudioURL = recordedAudioURL
}
}

Cancel a local notification and schedule a new one

I have a problem. I have local notifications in my project, here is the code (thanks #leoDabus):
import UIKit
class ViewController: UIViewController {
#IBOutlet var datePicker: UIDatePicker!
#IBOutlet var notificationSwitch: UISwitch!
let localNotification = UILocalNotification()
override func viewDidLoad() {
super.viewDidLoad()
setUpNotificationsOptions()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidAppear(animated: Bool) {
guard let loadedDate = NSUserDefaults().dateForKey("datePicker") else { return }
datePicker.setDate(loadedDate, animated: false)
}
func setUpNotificationsOptions() {
datePicker.datePickerMode = .Time
localNotification.timeZone = NSTimeZone.localTimeZone()
localNotification.repeatInterval = .Day
localNotification.alertAction = "Open App"
localNotification.alertBody = news[0].titleNews
localNotification.soundName = UILocalNotificationDefaultSoundName
}
func toggleNotification() {
if notificationSwitch.on {
localNotification.fireDate = datePicker.date.fireDate
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
} else {
localNotification.fireDate = nil
UIApplication.sharedApplication().cancelLocalNotification(localNotification)
}
}
#IBAction func toggleSwitch(sender: UISwitch) {
toggleNotification()
}
#IBAction func dateChanged(sender: UIDatePicker) {
NSUserDefaults().setDate(sender.date, forKey: "datePicker")
toggleNotification()
} }
extension NSUserDefaults {
func setDate(date: NSDate, forKey:String) {
NSUserDefaults().setObject(date, forKey: forKey)
}
func dateForKey(string:String) -> NSDate? {
return NSUserDefaults().objectForKey(string) as? NSDate
}}
the problem is that my local notification alert Body news[0].titleNews is the result of a parser and it's a value that changes periodically. But with the code above i obtain every day the same string, not the updated one. There is a method to have everyday the updated news? Can I cancel last scheduled notification programmatically and scheduling new one?
Set a unique id in the userInfo property of UILocalNotification and when you get the updated status/news, traverse throught all the scheduled notifications , get your notification with that id you set earlier and now do your work accordingly.
Set your id like the following
localNotification.userInfo = ["notificationID" : "Your Id"]
Code for traversing scheduled notifications
let notificationArr:NSArray? = UIApplication.sharedApplication().scheduledLocalNotifications
notificationArr!.enumerateObjectsUsingBlock({ object, index, stop in
let notification = object as! UILocalNotification;
let userInfo = notification.userInfo! as NSDictionary
let notificationID = userInfo["notificationID"] as! String
if(notificationID == "Your set Id"){
UIApplication.sharedApplication().cancelLocalNotification(notification);
}
})

Let AVPlayer continue playing when pressing the 'back' button on the UINavigation Controller in Swift 2

I’m developing a Radio Streaming app, it streams OK. Also it plays in background when press on the ‘Home’ button and ‘lock’ button.
The application is embedded into a UINavigationController and when I press on the ‘back’ button in the UINavigationController it stops playing.
My question is: How do I let the UIViewController that contain the AVPlayer to remain active when pressing the ‘back’ button in the navigation controller so that the AVPlayer continue streaming?
My code
import UIKit
import AVFoundation
import MediaPlayer
import Foundation
class RadioFunctionViewController: UIViewController {
#IBOutlet var playButton: UIButton!
#IBOutlet var statusLabel: UILabel!
var player:AVPlayer = AVPlayer()
private let ObservatingKeyPath = "currentItem.status"
private let PlayerStatusObservingContext = UnsafeMutablePointer<Int>(bitPattern: 1)
private var playingState:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
setStatus(4)
getAudioData("http://184.107.179.162:7546/;")
playingState = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonPressed(sender: AnyObject)
{
toggle()
}
func getAudioData(audioURL:String)
{
player = AVPlayer(URL: NSURL(string: audioURL)!)
player.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.Initial, context: nil)
}
func setStatus(rawValue:Int)
{
if rawValue == 1
{
statusLabel.textColor = UIColor.blueColor()
statusLabel.text = "Ready for Streaming"
}else if rawValue == 2
{
statusLabel.textColor = UIColor.redColor()
statusLabel.text = "Failed"
}else if rawValue == 0
{
statusLabel.textColor = UIColor.redColor()
statusLabel.text = "Failed to load data"
}else if rawValue == 3
{
statusLabel.textColor = UIColor.blueColor()
statusLabel.text = "Streaming"
}else if rawValue == 4
{
statusLabel.textColor = UIColor.purpleColor()
statusLabel.text = "Gather data..."
}
print("The raw value send is: \(rawValue)")
}
func audioBackgroundPlayback()
{
do{
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
}catch {
print("Could not play audio in the background")
}
if (NSClassFromString("MPNowPlayingInfoCenter") != nil)
{
let artWorkImage = MPMediaItemArtwork(image: UIImage(named: "ws")!)
let songInfo2: [String: AnyObject] = [MPMediaItemPropertyTitle: "Wide Streamings ABC Edition", MPMediaItemPropertyArtist: "Rumbera Network", MPMediaItemPropertyAlbumTitle: "107.9 FM", MPMediaItemPropertyArtwork: artWorkImage]
MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = songInfo2
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
}
}
func toggle()
{
if playButton.titleLabel?.text == "Play"
{
print("The play option is chosen")
playRadio()
}else{
print("The pause option is chosen")
pauseRadio()
}
}
func playRadio()
{
player.play()
setStatus(3)
playButton.setTitle("Pause", forState: UIControlState.Normal)
audioBackgroundPlayback()
}
func pauseRadio()
{
player.pause()
playButton.setTitle("Play", forState: UIControlState.Normal)
}
override func remoteControlReceivedWithEvent(event: UIEvent?) {
if event?.type == UIEventType.RemoteControl
{
if event?.subtype == UIEventSubtype.RemoteControlPlay
{
toggle()
}else if event?.subtype == UIEventSubtype.RemoteControlPause
{
pauseRadio()
}else if event?.subtype == UIEventSubtype.RemoteControlTogglePlayPause
{
toggle()
}
}
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>)
{
if (keyPath!.containsString("status"))
{
if player.status == AVPlayerStatus.ReadyToPlay
{
player.prerollAtRate(0.001, completionHandler: {(succes:Bool)-> Void in
if succes{
self.setStatus(1)
self.setStatus(3)
self.playRadio()
}else{
self.setStatus(1)
self.setStatus(2)
}
})
}else if player.status == AVPlayerStatus.Failed{
self.setStatus(2)
}else if player.status == AVPlayerStatus.Unknown
{
self.setStatus(0)
}
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.navigationBarHidden = false
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.navigationBarHidden = false
if playingState == true
{
audioBackgroundPlayback()
player.removeObserver(self, forKeyPath: "status")
print("The AVPlayer is playing in background")
}else{
player.removeObserver(self, forKeyPath: "status")
print("The view Dissapear")
}
}
Hope someone could help me out with this one
Thanks in advance
AVPlayer will continue to work as long as it is active. Once the referencing UIViewController is released by popping back AVPlayer will also be discarded from memory.
I would advise you to create a singleton player class and create APIs to start/stop/play/pause AVPlayer in that. Now, you can access it globally from everywhere in your app.
EDIT: For OP convenience (a sample to start with):
class MyAVPlayer {
static let sharedInstance = MyAVPlayer()
var player:AVPlayer = AVPlayer()
func play() {
// Put play code here
}
func playWithURL(url : NSURL) {
// Put play code here
}
}
Call it like (from anywhere in your application):
MyAVPlayer.sharedInstance.playWithURL(myURL)
The problem here is that the player is Embed in your controller
var player:AVPlayer = AVPlayer()
So when you press the back button, the controller is popped and deallocated and your player with it.
What you have to do is to put the player property elsewhere (AppDelegate, Custom navigation controller for exemple) to keep a reference on it that'll keep it alive.
I manage to fix it by doing some modification to the AppDelegate Class.
The modification into the AppDelegate:
var player:AVPlayer = AVPlayer()
internal var avPlayerUpdateNotification = NSNotificationCenter.defaultCenter()
let notificationStateupdate = "RadioStationChangeUpdate"
let radioStationChangeNSString:NSString = "RadioStationChangeNotification"
private var isPlaying:Bool = false
private var selectedRadioStation:String = ""
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
// Override point for customization after application launch.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "setNewSelectedRadioStation:", name: radioStationChangeNSString as String, object: nil)
return true
}
Other functions that has been added into the AppDelegate Class
func streamAudio(audioLink:String)
{
player = AVPlayer(URL: NSURL(string: audioLink)!)
player.play()
isPlaying = true
}
func play()
{
player.play()
isPlaying = true
}
func pause()
{
player.pause()
isPlaying = false
}
func getPlayerState() -> Bool
{
return isPlaying
}
func setCurrentSelectedRadioStation(selectedStation:String)
{
self.selectedRadioStation = selectedStation
}
func getCurrentSelectedRadioStation() -> String
{
return selectedRadioStation
}
func setNewSelectedRadioStation(notification: NSNotification)
{
let radioStation = notification.object!
if (radioStation.containsString("Rumbera network"))
{
if(selectedRadioStation == radioStation as! String)
{
print("Rumbera Network is already playing")
}else{
print("Rumbera Network is selected in AppDelegate")
streamAudio("http://184.107.179.162:7546/;")
setCurrentSelectedRadioStation(radioStation as! String)
}
}else if (radioStation.containsString("RocKorsow"))
{
if(selectedRadioStation == radioStation as! String)
{
print("RocKorsow is already playing")
}else{
print("RocKorsow is selected in AppDelegate")
streamAudio("http://youngfreshfast.serverroom.us:9166")
setCurrentSelectedRadioStation(radioStation as! String)
}
}else if (radioStation.containsString("Pause"))
{
pause()
}else if (radioStation.containsString("Play"))
{
play()
}else{
print("Nothing is found")
}
}
The class that handles the AVPlayer:
import UIKit
import AVFoundation
import MediaPlayer
import Foundation
class RadioFunctionViewController: UIViewController {
#IBOutlet var playButton: UIButton!
var player:AVPlayer = AVPlayer()
private let ObservatingKeyPath = "currentItem.status"
private let PlayerStatusObservingContext = UnsafeMutablePointer<Int>(bitPattern: 1)
private var playingState:Bool = false
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
override func viewDidLoad() {
super.viewDidLoad()
checkPlayerCurrentState()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func performAction(sender: UIButton)
{
let buttonLabel = (sender.titleLabel?.text)!
switch buttonLabel
{
case "Play":
print("The AVPlayer is playing")
NSNotificationCenter.defaultCenter().postNotificationName("RadioStationChangeNotification", object: NSString(string: "Play"))
playButton.setTitle("Pause", forState: UIControlState.Normal)
case "Pause":
print("The AVPlayer is pause")
NSNotificationCenter.defaultCenter().postNotificationName("RadioStationChangeNotification", object: NSString(string: "Pause"))
playButton.setTitle("Play", forState: UIControlState.Normal)
default:
break
}
}
func checkPlayerCurrentState()
{
let player_state = getPlayerState()
if player_state == true
{
print("The AVPlayer is playing")
playButton.setTitle("Pause", forState: UIControlState.Normal)
}else{
print("The AVPlayer is not playing")
playButton.setTitle("Play", forState: UIControlState.Normal)
}
}
func getPlayerState() -> Bool
{
let state = appDelegate.getPlayerState()
return state
}
func audioBackgroundPlayback()
{
do{
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
}catch {
print("Could not play audio in the background")
}
}
Hope my solution could help someone that encounter the same problem.
Thanks guys for your feedback.

recording audio in swift and passing the recorded audio to the next view controller

I am trying to record Audio, and pass the recorded audio, to the next view controller. Here is my code for recording Audio
class RecordSoundsViewController: UIViewController, AVAudioRecorderDelegate {
#IBOutlet weak var recording: UILabel!
#IBOutlet weak var recordButton: UIButton!
#IBOutlet weak var stopButton: UIButton!
var audioRecorder:AVAudioRecorder!
var recordedAudio : RecordedAudio!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
// enables record button
// hides the stop button
recordButton.enabled = true
stopButton.hidden = true
}
#IBAction func recordAudio(sender: UIButton) {
//Shows recording label
recording.hidden = false
//diabling record button
recordButton.enabled = false
stopButton.hidden = false
//Filepath Creation
let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
let currentDateTime = NSDate()
let formatter = NSDateFormatter()
formatter.dateFormat = "ddMMyyyy-HHmmss"
let recordingName = formatter.stringFromDate(currentDateTime)+".wav"
let pathArray = [dirPath, recordingName]
let filePath = NSURL.fileURLWithPathComponents(pathArray)
println(filePath)
// Recording Session
var session = AVAudioSession.sharedInstance()
session.setCategory(AVAudioSessionCategoryPlayAndRecord, error: nil)
audioRecorder = AVAudioRecorder(URL: filePath, settings: nil, error: nil)
audioRecorder.delegate = self
audioRecorder.meteringEnabled = true
audioRecorder.prepareToRecord()
audioRecorder.record()
}
func audioRecorderDidFinishRecording(recorder: AVAudioRecorder!, successfully flag: Bool) {
// ToDo create recorded audio file
if(flag)
{ recordedAudio = RecordedAudio()
recordedAudio.filepathURL = recorder.url
recordedAudio.title = recorder.url.lastPathComponent
// ToDo Perform segue
self.performSegueWithIdentifier("stopRecording", sender: recordedAudio)
}
else {
println("Recording was unsuccessfull")
stopButton.hidden = true
recordButton.enabled = true
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue == "stopRecording") {
let PlaySoundsVC:PlaySoundsViewController = segue.destinationViewController as! PlaySoundsViewController
let data = sender as! RecordedAudio
PlaySoundsVC.receivedAudio = data
}
}
#IBAction func stopAudio(sender: UIButton) {
// Hides recording
recording.hidden = true
audioRecorder.stop()
var audioSession = AVAudioSession.sharedInstance()
audioSession.setActive(false, error: nil)
}
}
My Model class is ,
import Foundation
class RecordedAudio : NSObject{
var filepathURL :NSURL!
var title : String!
}
Here is how My second viewcontroller catch the data and uses it,
class PlaySoundsViewController: UIViewController {
var audioPlayer: AVAudioPlayer!
var receivedAudio: RecordedAudio!
func rateplay (rtt : Float32) {
audioPlayer.stop()
audioPlayer.rate = rtt
audioPlayer.currentTime = 0.0
audioPlayer.play()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// if var filePath = NSBundle.mainBundle().pathForResource("movie_quote", ofType: "mp3")
// {
// // if path is there for mp3
// let filepathurl = NSURL.fileURLWithPath(filePath)
//
// // println(receivedAudio.title)
//
// }
// else {
// println("Path is empty")
//
// }
audioPlayer = AVAudioPlayer(contentsOfURL: receivedAudio.filepathURL, error: nil)
audioPlayer.enableRate = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func playSlow(sender: UIButton) {
// play sloooowllyyyyy
audioPlayer.stop()
audioPlayer.rate = 0.5
audioPlayer.currentTime = 0.0
audioPlayer.play()
}
#IBAction func playFast(sender: UIButton) {
rateplay(1.5)
}
#IBAction func stopAudio(sender: UIButton) {
audioPlayer.stop()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Untill I add the below code,
audioPlayer = AVAudioPlayer(contentsOfURL: receivedAudio.filepathURL, error: nil)
audioPlayer.enableRate = true
I was able to move to the second scene, which means, the audio is successfully recorded. But as soon as i access the data like "receivedAudio.filepathURL" I am getting the error,
fatal error: unexpectedly found nil while unwrapping an Optional value
In the prepareForSegue function of the RecordSoundsViewController you need to write segue.identifier == "stopRecording" as the condition.
Currently you have segue == "stopRecording".
Happy Coding!

Resources