Getting a fatal error when trying to play sound in Swift - xcode

I have worked my way through this tutorial here. One of the last things you do is have a button make sound when it is pressed. I wanted to then continue using that same logic to make a sound board app. However when I stripped the non-essential parts besides it making noise inside a new project I started getting a fatal error.
Here is my ViewController.swfit file:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var sample : AVAudioPlayer?
func setupAudioPlayerWithFile(file:NSString, type:NSString) -> AVAudioPlayer? {
//1
let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
let url = NSURL.fileURLWithPath(path!)
//2
var audioPlayer:AVAudioPlayer?
// 3
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
return audioPlayer
}
override func viewDidLoad() {
super.viewDidLoad()
if let sample = self.setupAudioPlayerWithFile("Stomach", type:"aif") {
self.sample = sample
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonPressed() {
sample?.play()
}
}
Here is my project when the fatal error hits
I have also tried this solution but I got errors as well.
I am running on El Capitan 10.11.3 with Xcode 7.3

Have you included the an audio file named "Stomach.aif" in your project? If not, pathForResource will return nil and you'll crash when attempting to force unwrap that path. You can use a safer version of this function, although if it can't locate that file it still won't play the audio On the bright side it shouldn't crash.
func setupAudioPlayerWithFile(file:NSString, type:NSString) -> AVAudioPlayer? {
var audioPlayer:AVAudioPlayer? = nil
if let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String) {
let url = NSURL.fileURLWithPath(path)
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
}
return audioPlayer
}

Related

Error with NSBundle.mainBundle when adding sound

I've trying to create a simple sound board for when a button is pressed a sound is made, however when I used this code
let url = NSURL(fileURLWithPath: Bundle.mainBundle().pathForResource(sound, ofType: "mp3")!)
let audioPlayer = try AVAudioPlayer(contentsOfURL: url)
I get an error with "Bundle.mainBundle" orginally it told me to change "Bundle" from "NSBundle" because it has be renamed but when I correct that I get another error saying "Cannot call value for non-function type 'Bundle' "
my entire code:
import UIKit
import AVFoundation
class ViewController: UIViewController {
let soundFilenames = ["60gs", "check", "dada", "danceforme", "eat", "gods", "irelandbaby", "ko'd", "lefthand", "littlewerp", "nocalls", "precision", "sundaymorning", "surprise", "whothefuckisthatguy", "youlldonothing"]
var audioPlayers = [AVAudioPlayer]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for sound in soundFilenames {
do {
let url = Bundle.main.url(forResource:sound, withExtension: "mp3")!
let audioPlayer = try AVAudioPlayer(contentsOfURL: url)
audioPlayer.append(audioPlayer())
}
catch {
audioPlayers.append(AVAudioPlayer())
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonTapped(_ sender: UIButton) {
let audioPlayer = audioPlayers[sender.tag]
audioPlayer.play()
}
}
can anyone help me with this please.
First of all in Swift 3 mainBundle() became main but why not the real short way:
let url = Bundle.main.url(forResource:sound, withExtension: "mp3")!
And the init method has been renamed to
let audioPlayer = try AVAudioPlayer(contentsOf: url)
and change the next line to:
audioPlayers.append(audioPlayer)

Parse api's saveInBackground not working in Swift 3

I'm testing my parse code on Heroku because of parse.com's shutdown. In Swift 3, saveInBackgroundWithBlock has been renamed to saveInBackground, so I updated that syntax in my code as well as the 'NS' prefix issue. But an error still remains. As a learner, I can't possibly take care of this further. I want a kind person to help me solve this. Thanks in advance.
import UIKit
import Parse
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let object = PFObject(className: "testObject")
object["name"] = "Bill"
object["lastname"] = "Alexander"
object.saveInBackground(block: { (success, error) in
if success {
print("Saved in server")
} else {
print(error!)
}
})
}
Here is also my screenshot:
'Expected declaration' error screenshot
You almost there, The syntax is just slightly incorrect. Also check against the error for any issues.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let object = PFObject(className: "testObject")
object["name"] = "Bill"
object["lastname"] = "Alexander"
object.saveInBackground { (success, error) -> Void in
if error == nil {
print("Saved in server")
} else {
print(error!)
}
}
}

Open camera and library only in landscape mode in Swift

I would like to open the camera and library in landscape mode, but I not be able to do it.
Please someone could explain and give me an example.
I have used the below code but seems some code is missing (for instance: import library), I will need a complete example, how I could implement, functions to open library and the camera and save in the camera roll.
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
if let connection = self.previewLayer?.connection {
var currentDevice: UIDevice = UIDevice.currentDevice()
var orientation: UIDeviceOrientation = currentDevice.orientation
var previewLayerConnection : AVCaptureConnection = connection
if (previewLayerConnection.supportsVideoOrientation)
{
switch (orientation)
{
case .Portrait:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
break
case .LandscapeRight:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft
break
case .LandscapeLeft:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
break
case .PortraitUpsideDown:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.PortraitUpsideDown
break
default:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
break
}
}
}
}
Also indicate that I already have some code implemented then
I find it easier to implement without the use of additional libraries like AVFoundation.
I am currently using this code in order to open library and camera.
#IBAction func openLibrary(sender: AnyObject) { ///accion del boton Library
imagePicker.allowsEditing = false
imagePicker.sourceType = .PhotoLibrary
presentViewController(imagePicker, animated:true, completion: nil)
}
#IBAction func openCamera(sender: AnyObject) { ///accion del boton Camara
imagePicker.allowsEditing = false
imagePicker.sourceType = .Camera
presentViewController(imagePicker, animated:true, completion: nil)
}
in ur app delegate use this function:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
if let presentedView = self.window?.rootViewController?.presentedViewController as? CameraViewController {
//cameraView
return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}
} else {
//other view
}
}
Swift 2
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
if let presentedView = self.window?.rootViewController?.presentedViewController as? YourCameraViewController {
//cameraView
return UIInterfaceOrientationMask.Landscape
} else {
//other view
// return here ur orientation for other view
}
}

Open Facebook profile in app

I am trying to make that when the user press Facebook button, it opens the Facebook application, or in browser.
Import code:
import Foundation
Extension code:
extension UIApplication {
class func tryURL(urls: [String]) {
let application = UIApplication.sharedApplication()
for url in urls {
if application.canOpenURL(NSURL(string: url)!) {
application.openURL(NSURL(string: url)!)
return
}
}
}
}
Function code:
func fimageTapped()
{
UIApplication.tryURL([
"fb://profile/1357163924", // App
"http://www.facebook.com/1357163924" // Website if app fails
])
}
I get error at line:
class func tryURL(urls: [String]) {
Error message:
Invalid redeclaration of "tryURL"
This is where i found the code from: Xcode swift link to facebook page
Anyone has any idea what is wrong here?
In Swift 3 use this:
let facebookID: String = "000000000000"
let facebookName: String = "name"
let facebookURLID = URL(string: "fb://profile/\(facebookID)")!
let facebookURLWeb = URL(string: "https://m.facebook.com/\(facebookName)?id=\(facebookID)")!
if(UIApplication.shared.canOpenURL(facebookURLID)){
UIApplication.shared.openURL(facebookURLID)
} else {
UIApplication.shared.openURL(facebookURLWeb)
}
Remember that from iOS 9 and 10 you need to declare in the Info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fb</string>
</array>
With this the queries for the Facebook schemes will not fail with a permission error:
"This app is not allowed to query for scheme fb"
Used this, worked fine:
var fbURLWeb: NSURL = NSURL(string: "https://www.facebook.com/ID")!
var fbURLID: NSURL = NSURL(string: "fb://profile/ID")!
if(UIApplication.sharedApplication().canOpenURL(fbURLID)){
// FB installed
UIApplication.sharedApplication().openURL(fbURLID)
} else {
// FB is not installed, open in safari
UIApplication.sharedApplication().openURL(fbURLWeb)
}
Swift 3:
Important: UIApplication is declared in UIKit so make sure you import UIKit aswell.
import Foundation
import UIKit
extension UIApplication {
class func tryURL(_ urls: [String]) {
let application = UIApplication.shared
for url in urls {
if application.canOpenURL(URL(string: url)!) {
application.open(URL(string: url)!, options: [:], completionHandler: nil)
return
}
}
}
}
Furthermore:
application.openURL(NSURL(string: url)!)
have in Swift 3 changed to open and with completionHandler:
application.open(URL(string: url)!, options: [:], completionHandler: nil)
Next in your viewController: declare your facebook app and web-urls above viewDidLoad and create a function or IBAction func where you do your UIapplication.tryURL:
import UIKit
class ViewController: UIViewController {
let fbAppUrl = "facebook://profile/yourFBprofileID"
let fbWebUrl = "https://www.facebook.com/yourFBprofileID"
override func viewDidLoad() {
super.viewDidLoad()
}
func openFacebook() {
UIApplication.tryURL([fbAppUrl, fbWebUrl])
}
}
First iOS will try to open the fbAppUrl but if the facebook app is not installed on the device it will open fbWebUrl in Safari instead.
For Swift 4
let webURL: NSURL = NSURL(string: "https://www.facebook.com/ID")!
let IdURL: NSURL = NSURL(string: "fb://profile/ID")!
if(UIApplication.shared.canOpenURL(IdURL as URL)){
// FB installed
UIApplication.shared.open(webURL as URL, options: [:], completionHandler: nil)
} else {
// FB is not installed, open in safari
UIApplication.shared.open(webURL as URL, options: [:], completionHandler: nil)
}

Force audio file playback through iPhone loud speaker using Swift

I have an App that records and then plays back an audio file. Currently the audio playback is playing through the earpiece speaker. Could someone tell me how Swift would handle coding this to force the audio out the loud speaker instead?
Below is a one of the instances I'm using to play the audio file:
#IBAction func playAudioVader(sender: UIButton) {
playAudioWithVariablePitch(-1000)
}
func playAudioWithVariablePitch(pitch: Float){
audioPlayer.stop()
audioEngine.stop()
audioEngine.reset()
var audioPlayerNode = AVAudioPlayerNode()
audioEngine.attachNode(audioPlayerNode)
var changePitchEffect = AVAudioUnitTimePitch()
changePitchEffect.pitch = pitch
audioEngine.attachNode(changePitchEffect)
audioEngine.connect(audioPlayerNode, to: changePitchEffect, format: nil)
audioEngine.connect(changePitchEffect, to: audioEngine.outputNode, format: nil)
audioPlayerNode.scheduleFile(audioFile, atTime: nil, completionHandler: nil)
audioEngine.startAndReturnError(nil)
audioPlayerNode.play()
}
override func viewDidLoad() {
super.viewDidLoad()
audioPlayer = AVAudioPlayer(contentsOfURL:receivedAudio.filePathURL, error: nil)
audioPlayer.enableRate = true
audioEngine = AVAudioEngine()
audioFile = AVAudioFile(forReading:receivedAudio.filePathURL, error: nil)
}
EDIT July 2017: Refer to Husam's answer for the Swift 2.0 solution.
As of Swift 1.2, you use overrideOutputAudioPort and AVAudioSessionPortOverride. It can be implemented by doing something like this:
if !session.overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker, error:&error) {
println("could not set output to speaker")
if let e = error {
println(e.localizedDescription)
}
}
I'm working on an app that uses this now, and I have a function called setSessionPlayandRecord, which looks like:
func setSessionPlayAndRecord() {
let session:AVAudioSession = AVAudioSession.sharedInstance()
var error: NSError?
if !session.setCategory(AVAudioSessionCategoryPlayAndRecord, error:&error) {
println("could not set session category")
if let e = error {
println(e.localizedDescription)
}
}
if !session.overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker, error:&error) {
println("could not set output to speaker")
if let e = error {
println(e.localizedDescription)
}
}
if !session.setActive(true, error: &error) {
println("could not make session active")
if let e = error {
println(e.localizedDescription)
}
}
}
Swift 2.0 Code
func setSessionPlayerOn()
{
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker)
} catch _ {
}
}
func setSessionPlayerOff()
{
do {
try AVAudioSession.sharedInstance().setActive(false)
} catch _ {
}
}

Resources