How do I play a video inside view controller with Swift 2 - 'If let' Error - ios

I have imported both mediaPlayer and AVfoundation
class AuroraViewController: UIViewController {
var moviePlayer: AVPlayer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func playVideo() {
if let
path = NSBundle.mainBundle().pathForResource("Aurora", ofType:"mp4"),
url = NSURL(fileURLWithPath: path),
moviePlayer = AVPlayer(contentURL: url) {
self.moviePlayer = moviePlayer
moviePlayer.view.frame = self.view.bounds
moviePlayer.prepareToPlay()
moviePlayer.scalingMode = .AspectFill
self.view.addSubview(moviePlayer.view)
} else {
debugPrint("oops, something wrong when playing video.m4v")
}
}
I Get an error about the 'if let': Initializer for conditional binding must have Optional type, not 'NSURL'. Is there a different way to do this?
UPDATE Correct code:
import UIKit
import AVFoundation
import AVKit
class myClass: AVPlayerViewController {
private func playVideo() {
if let path = NSBundle.mainBundle().pathForResource("Video Name", ofType: "mp4") {
let url = NSURL(fileURLWithPath: path)
player = AVPlayer(URL: url)
}
else {
print("Oops, something wrong when playing video.m4v")
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
playVideo()
}
}
Hope this helps.

You can only use "if let" for optional values:
if let nonoptional = optional {
}
If the right hand side is not optional, then the if let is just unnecessary.

The url is not an optional,after you got the path you are sure that there is something and the url is not an optional because there you can have an url where the file doesn't exists, but now you are sure that the file exists because you done if let with the path . Try this
private func playVideo() {
if let path = NSBundle.mainBundle().pathForResource("Video Name", ofType: "mp4") {
let url = NSURL(fileURLWithPath: path)
player = AVPlayer(URL: url)
player?.play()
}
else {
print("Oops, something wrong when playing video.m4v")
}
}

Related

fatal error: unexpectedly found nil while unwrapping an Optional value on adding audio Swift

I'm trying to add some audio when a button is pressed and the code I use doesnt have any error until I run then I get the 'fatal error: unexpectedly found nil while unwrapping an Optional value' in the out put this line of code:
let url = Bundle.main.url(forResource:sound, withExtension: "mp3")!
This is my entire code just for reference:
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(contentsOf: url)
audioPlayers.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()
}
}
Error is self-describing: url(forResource: withExtension:) returned nil and force-unwrapping it with ! causes your crash.
To fix this crash re-check that:
all files were added to the project
file names are written right in the code
If the file names are not needed later there is a more reliable way to get all mp3 files in the resources folder
let audioURLs = Bundle.main.urls(forResourcesWithExtension: "mp3", subdirectory: nil)!
for url in audioURLs {
do {
let audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayers.append(audioPlayer)
}
catch {
audioPlayers.append(AVAudioPlayer())
}
}
or - inspired by Alexander's comment – shortly
let audioURLs = Bundle.main.urls(forResourcesWithExtension: "mp3", subdirectory: nil)!
audioPlayers = audioURLs.flatMap{ try? AVAudioPlayer(contentsOf: $0) }

Play multiple songs in iOS

I wrote this code for iOS to play a song, however I'm not sure how to write the code to play multiple songs.
This is the line of code for a song:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player:AVAudioPlayer = AVAudioPlayer()
#IBAction func play(_ sender: AnyObject)
{
player.play()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
do
{
let audioPath = Bundle.main.path(forResource: "Ken", ofType: "mp3")
try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
}
catch
{
//ERROR
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You actually can play it with just two instances of the AVAudioPlayer resp. every sound file needs it's own AVAudioPlayer if you want to play them simultaneously.
I already wrote an answer, so I will post even there is already a correct answer. What palme said is correct. You could use multiple AVAudioPlayer instances to play multiple sounds simultaneously:
import UIKit
import AVFoundation
class ViewController: UIViewController {
let paths = ["a","b"]
var sounds = [AVAudioPlayer]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for path in paths {
do
{
let audioPath = Bundle.main.path(forResource: path, ofType: "mp3")
let player = try AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
sounds.append(player)
}
catch
{
//ERROR
}
}
for sound in sounds {
sound.play()
}
}
}

Swift 3 - AVAudioPlayer is not playing sound

I have a simple program which has one button and its only function is to trigger an sound output.
The app works perfectly when tested on an iOS simulator, but when I test it on an iPhone, the app is not playing any sound. I have tested this on two iPhones.
This was working once upon a time. I don't know if updating to iOS 10 has caused the issue.
Here is my code:
//Code
import UIKit
import AVFoundation
var audioPlayer = AVAudioPlayer()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let music = Bundle.main.path(forResource: "sound", ofType: "wav")
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: music! ))
}
catch{
print(error)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func playSound(_ sender: UIButton) {
audioPlayer.play()
}
}
Would be grateful for any answers.
Thanks.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let music = Bundle.main.path(forResource: "sound", ofType: "wav")
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: music! ))
audioPlayer.delegate = self
audioPlayer.preparedToPlay()
}
catch{
print(error)
}
}
import UIKit
import AVFoundation
class ViewController: UIViewController {
var btnSound: AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
//locate resource
let path = Bundle.main.path(forResource: "sound", ofType: "wav")
let music = URL(fileURLWithPath: path!)
do{
try btnSound = AVAudioPlayer(contentsOf: music)
btnSound.prepareToPlay()
} catch let err as NSError{
print(err.debugDescription)
}
}
}
func playSound(){
if btnSound.isPlaying{
//stop playing sound file if already playing
btnSound.stop()
}
//play sound
btnSound.play()
}
#IBAction func playSound(sender: UIButton){
//call playSound function on pressing the button you attach this function to
playSound()
}

Swift : Player audio file from another class file

First of all, I just want to let you know I'm a newbie in iOS programming ;)
I would like to know if the following scenario is possible or which way I need to update my code to make it work.
I would like to play an audio file located in the player class file within the ViewController file.
I added the file "test.wav" to the root of project.
My problem
When I play the sound by tapping a button, the program can't find the sound file. I have the following error message:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
Main swift file: ViewController.swift
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player1: Player!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func playAudio(sender: AnyObject) {
player1.playAudioFile()
}
}
Class file: Player.swift
import Foundation
import AVFoundation
class Player {
// Variables
var vc: ViewController!
var audioFile: AVAudioPlayer!
// Initializer
init (){
}
// Methods
func playAudioFile() {
if audioFile.playing {
audioFile.stop()
} else {
audioFile.play()
}
}
// Intialize ViewController
init (vc:ViewController!) {
// Set path for the attack sound
let audioSnd = NSBundle.mainBundle().pathForResource("test", ofType: "wav")
let audioFileURL = NSURL(fileURLWithPath: audioSnd!)
do {
try audioFile = AVAudioPlayer(contentsOfURL: audioFileURL, fileTypeHint: nil)
audioFile.prepareToPlay()
} catch let err as NSError {
print(err.debugDescription)
}
}
}
More information
My program has a class "Player", with subclasses such as "Human" and "Monster".
By default, my class player has some audio files for attacks, dying, etc.
Under some conditions, the "player" can become a human or a monster and get custom attack and dying sounds.
Thanks a lot for your help! ;)
Why are you initializing you player with a viewController ? You dont need that.
Change the Player class to:
import Foundation
import AVFoundation
class Player {
// Variables
var audioFile: AVAudioPlayer!
// Initializer
init() {
// Set path for the attack sound
let audioSnd = NSBundle.mainBundle().pathForResource("test", ofType: "wav")
let audioFileURL = NSURL(fileURLWithPath: audioSnd!)
do {
try audioFile = AVAudioPlayer(contentsOfURL: audioFileURL, fileTypeHint: nil)
audioFile.prepareToPlay()
} catch let err as NSError {
print(err.debugDescription)
}
}
// Methods
func playAudioFile() {
if audioFile.playing {
audioFile.stop()
} else {
audioFile.play()
}
}
}
And your ViewController.swift to:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player1: Player!
override func viewDidLoad() {
super.viewDidLoad()
// Note, that you need to initialize the player1 variable
player1 = Player()
}
#IBAction func playAudio(sender: AnyObject) {
player1.playAudioFile()
}
}
Swift is functional programming, so it is way better to separate the audio operation and viewController into different file/class. Then they could be reused in any scenarios.
Audio part
import AVFoundation
class AudioPlayer {
// Singleton to keep audio playing anywhere
static let shared = AudioPlayer()
var player: AVAudioPlayer?
private init() {}
func play(url: URL) {
do {
try AVAudioSession.sharedInstance().setMode(.default)
try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
player = try AVAudioPlayer(contentsOf: url)
guard let player = player else { return }
player.prepareToPlay()
player.play()
} catch {
print("error occurred")
}
}
}
ViewController
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func playAudio(sender: AnyObject) {
let audioSnd = NSBundle.mainBundle().pathForResource("test", ofType: "wav")
// don't use force unwrap
guard let audioFileURL = NSURL(fileURLWithPath: audioSnd) else { return }
// call the shared instance here
AudioPlayer.shared.play(url: url)
}
}

Error when trying to play video in Xcode 7 / Swift 2

I am trying to play a video inside a view controller when I enter it, but a get one error, listed below.Not too familiar with video playback, so is it supposed to be in a viewcontroller and how do I fix that error?The video is stored in xcode. Thanks.
import UIKit
import MediaPlayer
import AVFoundation
class AuroraViewController: UIViewController {
#IBOutlet var AuroraViewController: UIView!
var moviePlayer: AVPlayer?
private func playVideo() {
if let path = NSBundle.mainBundle().pathForResource("Aurora", ofType:"mp4") {
let url = NSURL(fileURLWithPath: path)
The line below is where I get the error of: Type of expression is ambiguous without more context
moviePlayer = AVPlayer(contentURL: url) {
self.moviePlayer = moviePlayer
moviePlayer.AuroraViewController.frame = self.AuroraViewController.bounds
moviePlayer.prepareToPlay()
moviePlayer.scalingMode = .AspectFill
self.AuroraViewController.addSubview(moviePlayer.view)
}
} else {
debugPrint("Ops, something wrong when playing video.m4v")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
playVideo()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
UPDATE Correct code:
import UIKit
import AVFoundation
import AVKit
class AuroraViewController: AVPlayerViewController {
private func playVideo() {
if let path = NSBundle.mainBundle().pathForResource("Aurora", ofType: "mp4") {
let url = NSURL(fileURLWithPath: path)
player = AVPlayer(URL: url)
}
else {
println("Oops, could not find resource Aurora.mp4")
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
playVideo()
}
}
This was a 'total re-write'.
The following did the job:
Add "AVKit.framework" to the "Build Phases" -> "Link Binary With Libraries" in Project settings.
In Storyboard, change the identity of your UIViewController to be AuroraViewController.
The resulting code then is all that's needed:
import UIKit
import AVFoundation
import AVKit
class AuroraViewController: AVPlayerViewController {
private func playVideo() {
if let path = NSBundle.mainBundle().pathForResource("Aurora", ofType: "mp4") {
let url = NSURL(fileURLWithPath: path)
player = AVPlayer(URL: url)
}
else {
println("Oops, could not find resource Aurora.mp4")
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
playVideo()
}
}

Resources