title: AVAudioSession setAggregatedIOPreference:error: Error Domain=NSOSStatusErrorDomain Code=560030580 "(null)"
body: <p>I have been getting this error and I have been at it for a couple of hours now without any success. Please help. Many thanks. Attached code below. </p>
  
  <p>Error Message: AVAudioSession setAggregatedIOPreference:error: Error Domain=NSOSStatusErrorDomain Code=560030580 "(null)"</p>
  
  <p>Last printed message was: Call disconnected</p>
  
  <pre><code>class callTwilioViewController: UIViewController ,PKPushRegistryDelegate, TVONotificationDelegate, TVOCallDelegate, AVAudioPlayerDelegate, UITextFieldDelegate {
  
  @IBOutlet weak var placeCallButton: UIButton!
  @IBOutlet weak var iconView: UIImageView!
  @IBOutlet weak var outgoingValue: UITextField!
  @IBOutlet weak var callControlView: UIView!
  @IBOutlet weak var muteSwitch: UISwitch!
  @IBOutlet weak var speakerSwitch: UISwitch!
  
  var deviceTokenString:String?
  
  var voipRegistry:PKPushRegistry
  var incomingPushCompletionCallback: (()-&gt;Swift.Void?)? = nil
  
  var isSpinning: Bool
  var incomingAlertController: UIAlertController?
  
  var callInvite:TVOCallInvite?
  var call:TVOCall?
  
  var ringtonePlayer:AVAudioPlayer?
  var ringtonePlaybackCallback: (() -&gt; ())?
  
  required init?(coder aDecoder: NSCoder) {
      isSpinning = false
      voipRegistry = PKPushRegistry.init(queue: DispatchQueue.main)
  
      super.init(coder: aDecoder)
  
      voipRegistry.delegate = self
      voipRegistry.desiredPushTypes = Set([PKPushType.voIP])
  }
  
  override func viewDidLoad() {
      super.viewDidLoad()
  
      toggleUIState(isEnabled: true, showCallControl: false)
      outgoingValue.delegate = self
  }
  
  override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
  }
  
  func fetchAccessToken() -&gt; String? {
      let endpointWithIdentity = String(format: "%@?identity=%@", accessTokenEndpoint, identity)
      guard let accessTokenURL = URL(string: baseURLString + endpointWithIdentity) else {
          return nil
      }
  
      return try? String.init(contentsOf: accessTokenURL, encoding: .utf8)
  }
  
  func toggleUIState(isEnabled: Bool, showCallControl: Bool) {
      placeCallButton.isEnabled = isEnabled
      if (showCallControl) {
          callControlView.isHidden = false
          muteSwitch.isOn = false
          speakerSwitch.isOn = true
      } else {
          callControlView.isHidden = true
      }
  }
  
  @IBAction func placeCall(_ sender: UIButton) {
      if (self.call != nil) {
          self.call?.disconnect()
          self.toggleUIState(isEnabled: false, showCallControl: false)
      } else {
          playOutgoingRingtone(completion: { [weak self] in
              if let strongSelf = self {
                  strongSelf.makeCall(strongSelf.outgoingValue.text!)
              }
          })
  
          self.toggleUIState(isEnabled: false, showCallControl: false)
          self.startSpin()
      }
  }
  
  func makeCall(_ to: String) {
      guard let accessToken = fetchAccessToken() else {
          return
      }
  
      let connectOptions: TVOConnectOptions = TVOConnectOptions(accessToken: accessToken) { (builder) in
          builder.params = [twimlParamTo : to]
      }
  
      self.checkRecordPermission { (permissionGranted) in
          if (!permissionGranted) {
              let alertController: UIAlertController = UIAlertController(title: "Voice Quick Start",
                                                                         message: "Microphone permission not granted",
                                                                         preferredStyle: .alert)
  
              let continueWithMic: UIAlertAction = UIAlertAction(title: "Continue without microphone",
                                                                 style: .default,
                                                                 handler: { (action) in
                                                                  self.call = TwilioVoice.connect(with: connectOptions, delegate: self)
              })
              alertController.addAction(continueWithMic)
  
              let goToSettings: UIAlertAction = UIAlertAction(title: "Settings",
                                                              style: .default,
                                                              handler: { (action) in
                                                                  UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!,
                                                                                            options: [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly: false],
                                                                                            completionHandler: nil)
              })
              alertController.addAction(goToSettings)
  
              let cancel: UIAlertAction = UIAlertAction(title: "Cancel",
                                                        style: .cancel,
                                                        handler: { (action) in
                                                          self.toggleUIState(isEnabled: true, showCallControl: false)
                                                          self.stopSpin()
              })
              alertController.addAction(cancel)
  
              self.present(alertController, animated: true, completion: nil)
          } else {
              self.call = TwilioVoice.connect(with: connectOptions, delegate: self)
          }
      }
  }
  
  func checkRecordPermission(completion: @escaping (_ permissionGranted: Bool) -&gt; Void) {
      let permissionStatus: AVAudioSession.RecordPermission = AVAudioSession.sharedInstance().recordPermission
  
      switch permissionStatus {
      case AVAudioSessionRecordPermission.granted:
          // Record permission already granted.
          completion(true)
          break
      case AVAudioSessionRecordPermission.denied:
          // Record permission denied.
          completion(false)
          break
      case AVAudioSessionRecordPermission.undetermined:
          // Requesting record permission.
          // Optional: pop up app dialog to let the users know if they want to request.
          AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
              completion(granted)
          })
          break
      default:
          completion(false)
          break
      }
  }
  
  @IBAction func muteSwitchToggled(_ sender: UISwitch) {
      if let call = call {
          call.isMuted = sender.isOn
      } else {
          NSLog("No active call to be muted")
      }
  }
  
  @IBAction func speakerSwitchToggled(_ sender: UISwitch) {
      toggleAudioRoute(toSpeaker: sender.isOn)
  }
  
  // MARK: UITextFieldDelegate
  func textFieldShouldReturn(_ textField: UITextField) -&gt; Bool {
      outgoingValue.resignFirstResponder()
      return true
  }
  
  // MARK: PKPushRegistryDelegate
  func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
      NSLog("pushRegistry:didUpdatePushCredentials:forType:");
  
      if (type != .voIP) {
          return
      }
  
      guard let accessToken = fetchAccessToken() else {
          return
      }
  
      let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined()
  
      TwilioVoice.register(withAccessToken: accessToken, deviceToken: deviceToken) { (error) in
          if let error = error {
              NSLog("An error occurred while registering: \(error.localizedDescription)")
          }
          else {
              NSLog("Successfully registered for VoIP push notifications.")
          }
      }
  
      self.deviceTokenString = deviceToken
  }
  
  func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
      NSLog("pushRegistry:didInvalidatePushTokenForType:")
  
      if (type != .voIP) {
          return
      }
  
      guard let deviceToken = deviceTokenString, let accessToken = fetchAccessToken() else {
          return
      }
  
      TwilioVoice.unregister(withAccessToken: accessToken, deviceToken: deviceToken) { (error) in
          if let error = error {
              NSLog("An error occurred while unregistering: \(error.localizedDescription)")
          }
          else {
              NSLog("Successfully unregistered from VoIP push notifications.")
          }
      }
  
      self.deviceTokenString = nil
  }
  
  /**
   * Try using the `pushRegistry:didReceiveIncomingPushWithPayload:forType:withCompletionHandler:` method if
   * your application is targeting iOS 11. According to the docs, this delegate method is deprecated by Apple.
   */
  func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
      NSLog("pushRegistry:didReceiveIncomingPushWithPayload:forType:")
  
      if (type == PKPushType.voIP) {
          TwilioVoice.handleNotification(payload.dictionaryPayload, delegate: self)
      }
  }
  
  /**
   * This delegate method is available in iOS 11 and above. Call the completion handler once the
   * notification payload is passed to the `TwilioVoice.handleNotification()` method.
   */
  func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -&gt; Void) {
      NSLog("pushRegistry:didReceiveIncomingPushWithPayload:forType:completion:")
      // Save for later when the notification is properly handled.
      self.incomingPushCompletionCallback = completion
  
      if (type == PKPushType.voIP) {
          TwilioVoice.handleNotification(payload.dictionaryPayload, delegate: self)
      }
  
  
  }
  
  func incomingPushHandled() {
      if let completion = self.incomingPushCompletionCallback {
          completion()
          self.incomingPushCompletionCallback = nil
      }
  }
  
  // MARK: TVONotificaitonDelegate
  func callInviteReceived(_ callInvite: TVOCallInvite) {
  
      NSLog("callInviteReceived:")
  
      if (self.callInvite != nil) {
          NSLog("A CallInvite is already in progress. Ignoring the incoming CallInvite from \(callInvite.from)")
          self.incomingPushHandled()
          return
      } else if (self.call != nil &amp;&amp; self.call?.state == .connected) {
          NSLog("Already an active call. Ignoring incoming CallInvite from \(callInvite.from)");
          self.incomingPushHandled()
          return;
      }
  
      self.callInvite = callInvite;
  
      let from = callInvite.from
      let alertMessage = "From: \(from)"
  
      playIncomingRingtone()
  
      let incomingAlertController = UIAlertController(title: "Incoming",
                                                      message: alertMessage,
                                                      preferredStyle: .alert)
  
      let rejectAction = UIAlertAction(title: "Reject", style: .default) { [weak self] (action) in
          if let strongSelf = self {
              strongSelf.stopIncomingRingtone()
              callInvite.reject()
              strongSelf.callInvite = nil
  
              strongSelf.incomingAlertController = nil
              strongSelf.toggleUIState(isEnabled: true, showCallControl: false)
          }
      }
      incomingAlertController.addAction(rejectAction)
  
      let ignoreAction = UIAlertAction(title: "Ignore", style: .default) { [weak self] (action) in
          if let strongSelf = self {
              /* To ignore the CallInvite, you don't have to do anything but just literally ignore it */
  
              strongSelf.callInvite = nil
              strongSelf.stopIncomingRingtone()
              strongSelf.incomingAlertController = nil
              strongSelf.toggleUIState(isEnabled: true, showCallControl: false)
          }
      }
      incomingAlertController.addAction(ignoreAction)
  
      let acceptAction = UIAlertAction(title: "Accept", style: .default) { [weak self] (action) in
          if let strongSelf = self {
              strongSelf.stopIncomingRingtone()
              let acceptOptions: TVOAcceptOptions = TVOAcceptOptions(callInvite: callInvite) { (builder) in
                  builder.uuid = strongSelf.callInvite?.uuid
              }
              strongSelf.call = callInvite.accept(with: acceptOptions, delegate: strongSelf)
              strongSelf.callInvite = nil
  
              strongSelf.incomingAlertController = nil
              strongSelf.startSpin()
          }
      }
      incomingAlertController.addAction(acceptAction)
  
      toggleUIState(isEnabled: false, showCallControl: false)
      present(incomingAlertController, animated: true, completion: nil)
      self.incomingAlertController = incomingAlertController
  
      // If the application is not in the foreground, post a local notification
      if (UIApplication.shared.applicationState != UIApplication.State.active) {
          let content = UNMutableNotificationContent()
          content.title = "Incoming Call"
          content.body = "Call Invite from \(callInvite.from)"
          content.sound = UNNotificationSound.default
  
          let request = UNNotificationRequest(identifier: "VoiceLocaNotification",
                                              content: content, trigger: nil)
  
          let center = UNUserNotificationCenter.current()
          center.add(request) { (error) in
              if (error != nil) {
                  print("Failed to add notification reqeust: \(error!.localizedDescription)")
              }
          }
      }
  
      self.incomingPushHandled()
  }
  
  func cancelledCallInviteReceived(_ cancelledCallInvite: TVOCancelledCallInvite) {
      NSLog("cancelledCallInviteCanceled:")
  
      if (self.callInvite == nil ||
          self.callInvite!.callSid != cancelledCallInvite.callSid) {
          NSLog("No matching pending CallInvite. Ignoring the Cancelled CallInvite")
          return
      }
  
      self.stopIncomingRingtone()
      playDisconnectSound()
  
      if (incomingAlertController != nil) {
          dismiss(animated: true) { [weak self] in
              if let strongSelf = self {
                  strongSelf.incomingAlertController = nil
                  strongSelf.toggleUIState(isEnabled: true, showCallControl: false)
              }
          }
      }
  
      self.callInvite = nil
  
      UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
  
      self.incomingPushHandled()
  }
  
  // MARK: TVOCallDelegate
  func callDidStartRinging(_ call: TVOCall) {
      NSLog("callDidStartRinging:")
  
      self.placeCallButton.setTitle("Ringing", for: .normal)
  }
  
  func callDidConnect(_ call: TVOCall) {
      NSLog("callDidConnect:")
  
      self.call = call
  
      self.placeCallButton.setTitle("Hang Up", for: .normal)
  
      toggleUIState(isEnabled: true, showCallControl: true)
      stopSpin()
      toggleAudioRoute(toSpeaker: true)
  
  
  }
  
  func call(_ call: TVOCall, isReconnectingWithError error: Error) {
  
  
  
  
  
      NSLog("call:isReconnectingWithError:")
  
      self.placeCallButton.setTitle("Reconnecting", for: .normal)
  
      toggleUIState(isEnabled: false, showCallControl: false)
  }
  
  func callDidReconnect(_ call: TVOCall) {
      NSLog("callDidReconnect:")
  
      self.placeCallButton.setTitle("Hang Up", for: .normal)
  
      toggleUIState(isEnabled: true, showCallControl: true)
  }
  
  func call(_ call: TVOCall, didFailToConnectWithError error: Error) {
      NSLog("Call failed to connect: \(error.localizedDescription)")
  
      callDisconnected()
  }
  
  func call(_ call: TVOCall, didDisconnectWithError error: Error?) {
      if let error = error {
          NSLog("Call failed: \(error.localizedDescription)")
      } else {
          NSLog("Call disconnected")
      }
  
      callDisconnected()
  }
  
  func callDisconnected() {
      self.call = nil
  
      playDisconnectSound()
      toggleUIState(isEnabled: true, showCallControl: false)
      stopSpin()
      self.placeCallButton.setTitle("Call", for: .normal)
  }
  
  
  // MARK: AVAudioSession
  func toggleAudioRoute(toSpeaker: Bool) {
      // The mode set by the Voice SDK is "VoiceChat" so the default audio route is the built-in receiver. Use port override to switch the route.
      let audioDevice: TVODefaultAudioDevice = TwilioVoice.audioDevice as! TVODefaultAudioDevice
      audioDevice.block = {
          kTVODefaultAVAudioSessionConfigurationBlock()
  
  
          do {
              if (toSpeaker) {
                  try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
  
  
              } else {
                  try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
              }
          } catch {
              NSLog(error.localizedDescription)
          }
      }
      audioDevice.block()
  }
  
  
  
  
  // MARK: Ringtone player &amp; AVAudioPlayerDelegate
  func playOutgoingRingtone(completion: @escaping () -&gt; ()) {
      self.ringtonePlaybackCallback = completion
  
      let ringtonePath = URL(fileURLWithPath: Bundle.main.path(forResource: "outgoing", ofType: "wav")!)
      do {
          self.ringtonePlayer = try AVAudioPlayer(contentsOf: ringtonePath)
          self.ringtonePlayer?.delegate = self
  
          playRingtone()
      } catch {
          NSLog("Failed to initialize audio player")
          self.ringtonePlaybackCallback?()
      }
  }
  
  
  
  func playIncomingRingtone() {
      let ringtonePath = URL(fileURLWithPath: Bundle.main.path(forResource: "incoming", ofType: "wav")!)
      do {
          self.ringtonePlayer = try AVAudioPlayer(contentsOf: ringtonePath)
          self.ringtonePlayer?.delegate = self
          self.ringtonePlayer?.numberOfLoops = -1
  
          playRingtone()
      } catch {
          NSLog("Failed to initialize audio player")
      }
  }
  
  func stopIncomingRingtone() {
      if (self.ringtonePlayer?.isPlaying == false) {
          return
      }
  
      self.ringtonePlayer?.stop()
  
      do {
          try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord)
      } catch {
          NSLog(error.localizedDescription)
      }
  
      //Shit
  
      do {
  
          try AVAudioSession.sharedInstance().setAggregatedIOPreference(.aggregated)
  
      } catch {
          NSLog(error.localizedDescription)
      }
  }
  
  func playDisconnectSound() {
      let ringtonePath = URL(fileURLWithPath: Bundle.main.path(forResource: "disconnect", ofType: "wav")!)
      do {
          self.ringtonePlayer = try AVAudioPlayer(contentsOf: ringtonePath)
          self.ringtonePlayer?.delegate = self
          self.ringtonePlaybackCallback = nil
  
          playRingtone()
      } catch {
          NSLog("Failed to initialize audio player")
      }
  }
  
  func playRingtone() {
      do {
          try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
      } catch {
          NSLog(error.localizedDescription)
      }
  
      self.ringtonePlayer?.volume = 1.0
      self.ringtonePlayer?.play()
  }
  
  func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
      if (self.ringtonePlaybackCallback != nil) {
          DispatchQueue.main.async {
              self.ringtonePlaybackCallback!()
          }
      }
  
      do {
          try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord)
      } catch {
          NSLog(error.localizedDescription)
      }
  }
  
  
  // MARK: Icon spinning
  func startSpin() {
      if (isSpinning != true) {
          isSpinning = true
          spin(options: UIView.AnimationOptions.curveEaseIn)
      }
  }
  
  func stopSpin() {
      isSpinning = false
  }
  
  func spin(options: UIView.AnimationOptions) {
      UIView.animate(withDuration: 0.5,
                     delay: 0.0,
                     options: options,
                     animations: { [weak iconView] in
                      if let iconView = iconView {
                          iconView.transform = iconView.transform.rotated(by: CGFloat(Double.pi/2))
                      }
      }) { [weak self] (finished: Bool) in
          guard let strongSelf = self else {
              return
          }
  
          if (finished) {
              if (strongSelf.isSpinning) {
                  strongSelf.spin(options: UIView.AnimationOptions.curveLinear)
              } else if (options != UIView.AnimationOptions.curveEaseOut) {
                  strongSelf.spin(options: UIView.AnimationOptions.curveEaseOut)
              }
          }
      }
  }
  </code></pre>
  
  <p>}</p>