This question already has answers here:
Class 'ViewController' has no initializers in swift
(8 answers)
Closed 6 years ago.
Im trying to build a simply sound app. I want a button press to play a clip pretty much like a soundboard. problem is when I go to build it says class "ViewController' has no initializers
import UIKit
import AVFoundation
class ViewController: UIViewController {
var audioPlayer: AVAudioPlayer
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.
}
#IBAction func playSound(sender:UIButton){
// Set the sound file name & extention
let audioFilePath = Bundle.main.path(forResource: "emp_learntoknow", ofType: "mp3")
if audioFilePath != nil {
let audioFileUrl = URL.init(fileURLWithPath: audioFilePath!)
do {
audioPlayer = try AVAudioPlayer(contentsOf: audioFileUrl)
audioPlayer.play()
} catch {
print("audio file is not found")
}
}
}
Because it has no initializers. You have a property:
var audioPlayer: AVAudioPlayer
...but you are not initializing it. You have, of course, given it a type, but a type is not a value. All properties must have initial values.
Like Matt has mentioned, it's happening because the property is not initialized.
In Swift, you have to use optionals for variables that could be nil at any point. You'll have to either initialize audioPlayer from the beginning or use an optional type, including the implicitly unwrapped optional if you know it will be set later on and stay that way.
Related
I'm new to swift development and building a simple app for the apple watch. I'd like a short sound to play when a button is tapped. Is this possible?
From what I understand the best way to do this is with AVFoundation and AVAudioPlayer. There seem to have been a lot of updates for this in the last few releases and I'm finding conflicting advice. Based on a few tutorials I've put this simple test together, but I'm getting a "Thread 1:Fatal error: Unexpectedly found nil when unwrapping an Optional value" Here is my code:
import WatchKit
import Foundation
import AVFoundation
var dogSound = AVAudioPlayer()
class InterfaceController: WKInterfaceController {
override func awake(withContext context: Any?) {
super.awake(withContext: context)
// Configure interface objects here.
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
#IBAction func playTapped() {
let path = Bundle.main.path(forResource: "Dog", ofType: ".mp3")!
let url = URL(fileURLWithPath: path)
do {
dogSound = try AVAudioPlayer(contentsOf: url)
dogSound.play()
} catch {
//couldn't load file :(
}
}
}
My audio file is an mp3 named Dog in the Assets.xcassets folder in WatchKit Extension and I have added AVFoundation.framework to the Link Binary with Libraries
What am I doing wrong and is there a tutorial for the right way to implement this? Thanks a lot!
I am new to xcode and Swift and I am getting an error
EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
I've tried searching similar questions on stackoverflow and I saw that people's responses were that it's because the url is not valid, so it's returning nil. However, I am using https://google.com and I am still getting the same error. This is all my code so far. I am only trying to load a single webpage into the view controller.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myWebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = URL(string: "https://www.google.com")
myWebView.loadRequest(URLRequest(url: url!))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
After looking at various documentations and videos on the errors I found that the issue was that I was writing my code in the wrong file for the viewController as the viewController that I was targeting was a second one that I created to be access from the original one. Therefore, for anyone else who is completely new development and to xcode and swift. The original viewController.swift file is only for the first viewController. A new viewController.swift file must be created to add code to any subsequently created viewControllers.
Looks like your outlet is not connected properly and also always try to avoid doing force unwrapped. In order to prevent your crash you can use below check:-
guard let url = URL(string: "https://www.google.com") else { return }
myWebView.loadRequest(URLRequest(url: url))
or
if let url = URL(string: "https://www.google.com") {
myWebView.loadRequest(URLRequest(url: url))
}
Help me, please!!! I've only recently started programming in Swift. This is my first project. I get the errormessage: "Incorrect argument label in call". This is my code:
import UIKit
import AVFoundation
class PlaySoundsViewController: UIViewController {
var audioPlayer:AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if var filePath = NSBundle.mainBundle().pathForResource("psl",ofType: "mp3"){
var filePathUrl = NSURL.fileURLWithPath(filePath)
audioPlayer = AVAudioPlayer(contentsOfURL: filePathUrl, error: nil)
}else {
print("the filepath is empty")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func playSoundSlow(sender: UIButton) {
audioPlayer.play()
I'm not sure what went wrong here is another picture of my code so you can also see the errormessage.My Code
I'm trying to get it to play a mp3 called psl.mp3.
Please, help me!!! I just started and don't know what to do.
P.S. Not a native Englishspeaker, so sorry for mistakes.
Swift 2 adds new error handling, meaning you don't even have to pass in an error parameter:
audioPlayer = try! AVAudioPlayer(contentsOfURL: filePathUrl)
This initializer throws, meaning if there is an error, you can catch it in a do-catch statement. However, since you passed nil for the error parameter, I'm assuming you are sure the player is there. That's why I used try! without a do-catch instead of try in a do-catch.
Read about the new error handling here.
Try this
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: NSURL.fileURLWithPath(path))
audioPlayer.delegate = self
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch {
print("Catch error in playUsingAudioPlayer")
}
This is my function:
func playMusic(filename :String!) {
var playIt : AVAudioPlayer!
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)
if url == nil {
println("could not find \(filename)")
return
}
var error : NSError?
playIt = AVAudioPlayer(contentsOfURL: url, error: &error)
if playIt==nil {
println("could not create audio player")
return
}
playIt.numberOfLoops = -1
playIt.prepareToPlay()
playIt.play()
}
I debugged my app and i saw that the console tells me: could't create audio player
it looks like my playIt var is nil
how do i fix it?
There's another problem with your code: once you find out why playIt is nil and fix that, you'll discover that playMusic runs without errors, but no sound plays. That's because you've declared playIt as a local variable inside playMusic. Just as it starts playing, you reach the end of playMusic, when all its local variables go out of scope and cease to exist. Microseconds after playIt starts to play, it gets wiped out of existence.
To fix this, declare playIt outside playMusic, as an instance variable. Here's the code for a view controller that uses your playMusic method with my one suggested change:
import UIKit
import AVFoundation
class ViewController: UIViewController {
// Declare playIt here instead
var playIt : AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
playMusic("sad trombone.mp3")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonPressed(sender: AnyObject) {
}
func playMusic(filename :String!) {
// var playIt : AVAudioPlayer! *** this is where you originally declared playIt
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)
if url == nil {
println("could not find \(filename)")
return
}
var error : NSError?
playIt = AVAudioPlayer(contentsOfURL: url, error: &error)
if playIt==nil {
println("could not create audio player")
return
}
playIt.numberOfLoops = -1
playIt.prepareToPlay()
playIt.play()
}
}
Try it both ways -- with playIt declared as an instance variable, and playIt as a local variable inside playMusic. You'll want to go with the former.
I'm also seconding nhgrif's suggestion: playMusic should take a String or String? parameter; not String!
First of all let me say that I am very new to programming. What I'm trying to do is add a button that when pressed plays music, and when pressed again the music stops. Ideally when the button is pressed for a third time the music will have reset. Whilst trying to achieve this I'm getting the error message "Expression resolves to an unused function", as I am very new all the help I find online doesn't make any sense to me.
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var janitor: UIImageView!
var pianoSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("C", ofType: "m4a")!)
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
audioPlayer = AVAudioPlayer(contentsOfURL: pianoSound, error: nil)
audioPlayer.prepareToPlay()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func PianoC(sender: AnyObject) {
audioPlayer.play()
if audioPlayer.playing { audioPlayer.stop} else { audioPlayer.play}
}
}
Swooping in here after Martin R's comment ...
if audioPlayer.playing { audioPlayer.stop} else { audioPlayer.play}
On this line, you are not calling the stop and play functions, but simply accessing them. Resolving to an unused function is trying to tell you that you have an expression that is returning a function type, but you are never calling it (audioPlayer.stop and audioPlayer.play are the expressions in question here).
To rid yourself of this error, and probably produce the correct behavior, try calling the functions.
if audioPlayer.playing {
audioPlayer.stop()
} else {
audioPlayer.play()
}
Swift 4:
Just add the braces '()' next to the method name
override func viewWillAppear(_ animated: Bool) {
addView //error: Expression resolves to an unused function
}
func addView(){
}
Solution:
override func viewWillAppear(_ animated: Bool) {
addView()
}
Here's a simplified version of Brian's answer:
audioPlayer.playing
? audioPlayer.stop()
: audioPlayer.play()
if audioPlayer.playing { audioPlayer.stop} else { audioPlayer.play} is just accessing the member variables. It's not doing anything.
I am sure you're intention was to do audioPlayer.stop() and audioPlayer.start().
However just to explain the ERROR and not to solve your issue:
had you done something like
if audioPlayer.playing { self.playerStatus= audioPlayer.stop} else { self.playerStatus = audioPlayer.play}
Then you were actually doing something you were setting a parameter. accessing or just getting a parameter is stupid in the eyes of the compiler :)