Swift 2 migration problems - ios

I just opened my old project in Xcode 7 beta. The code works perfectly fine in Xcode 6, but now it's showing many error. I don"t know what those are. Can anybody explain why this happened, and how to fix it? Thank you! Here is the Code
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer = AVAudioPlayer()
#IBOutlet weak var firstCardImageView: UIImageView!
#IBOutlet weak var secondCardImageView: UIImageView!
#IBOutlet weak var label: UILabel!
var cardNamesArray:[String] = ["dice1","dice2","dice3","dice4","dice5","dice6"]
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 rollaction(sender: AnyObject) {
updateAction()
}
func updateAction(){
var firstRandomNumber = Int(arc4random_uniform(5))
var firstCardString:String = String(self.cardNamesArray[firstRandomNumber])
var secondRandomNumber = Int(arc4random_uniform(5))
var secondCardString:String = String(self.cardNamesArray[secondRandomNumber])
self.firstCardImageView.image = UIImage(named: firstCardString)
self.secondCardImageView.image = UIImage(named: secondCardString)
var fileLocation = NSBundle.mainBundle().pathForResource("sound", ofType: ".mp3")
var error: NSError? = nil
player = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: fileLocation!), error: &error) //Error: Cannot find an initializer for type 'AVAudioPlayer' that accepts an argument list of type '(contentsOfURL: NSURL, error: inout NSError?)'
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, error: nil) //Error:Extra argument 'error' in call
AVAudioSession.sharedInstance().setActive(true, error: nil) //Error:Extra argument 'error' in call
player.play()
let num = firstRandomNumber + secondRandomNumber + 2
self.label.text = "The sum is \(num)"
}
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent) {
if event.subtype == UIEventSubtype.MotionShake { //Error:Method does not override any method from its superclass
updateAction()
}
}
}

Here's your updateAction() function with Swift 2.0's do/try/catch implementation:
func updateAction(){
var firstRandomNumber = Int(arc4random_uniform(5))
var firstCardString:String = String(self.cardNamesArray[firstRandomNumber])
var secondRandomNumber = Int(arc4random_uniform(5))
var secondCardString:String = String(self.cardNamesArray[secondRandomNumber])
self.firstCardImageView.image = UIImage(named: firstCardString)
self.secondCardImageView.image = UIImage(named: secondCardString)
let fileLocation = NSBundle.mainBundle().pathForResource("sound", ofType: ".mp3")
do {
player = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: fileLocation!))
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
try AVAudioSession.sharedInstance().setActive(true)
}
catch {
print("Something bad happened. Try catching specific errors to narrow things down")
}
player.play()
let num = firstRandomNumber + secondRandomNumber + 2
self.label.text = "The sum is \(num)"
}

Related

Having problems with saving and loading in Swift 3.0 iOS 10

I'm really new to the Swift and iOS programming scene and I am trying to learn a bunch of things. For this app, I want to save and load just one integer, but I am having problems, as everything I found on stack overflow and the Internet just doesn't seem to work on Swift 3. The app crashes immediately, it breaks on:
#IBOutlet weak var StaticLabel: UILabel!
It says "Thread 1: breakpoint 3.5" . Any help and tips would be very much appreciated :)
import UIKit
import AVFoundation
var player: AVAudioPlayer?
var number = 0
class ViewController: UIViewController {
#IBOutlet weak var StaticLabel: UILabel!
#IBOutlet weak var NumberLabel: UILabel!
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
Load()
}
func Load()
{
number = defaults.integer(forKey: "Save")
NumberLabel.text = String(number)
}
func playSound()
{
let path = Bundle.main.path(forResource: "RightYouAre.mp3", ofType: nil)
let url = URL(fileURLWithPath: path!)
do {
let sound = try AVAudioPlayer(contentsOf: url)
player = sound
sound.play()
}
catch {
// couldn't load file :(
}
}
#IBAction func Minus(_ sender: AnyObject) {
number = number - 1
NumberLabel.text = String(number)
defaults.set(number, forKey: "Save")
}
#IBAction func Plus(_ sender: UIButton) {
playSound()
number = number + 1
NumberLabel.text = String(number)
defaults.set(number, forKey: "Save")
}
}
your line of code
number = defaults.integer(forKey: "Save")
user defaults integer for key Save is nil, actually this key does not exist at all in the user defaults
before you load this integer from user defaults , it has to be set first
if defaults.object(forKey: "Save") != nil { number = defaults.integer(forKey: "Save") }
this will make sure the object exists in the user defaults before getting it's value
finally your load function should be
func Load()
{
if defaults.object(forKey: "Save") != nil
{
number = defaults.integer(forKey: "Save")
NumberLabel.text = String(number)
}
}
You need to add null handling to the load function as first time there
will be no value for the key "save" in your UserDefaults.
func Load()
{
if let number = defaults.integer(forKey: "Save")
{
self.number = number
NumberLabel.text = String(number)
}
}

How to get AvPlayer Duration - Swift

How can I get AvPlayer to work like AvAudioPlayer. What I mean is, I cannot seem to get duration to work at all. Here is what I need to convert to AvPlayer:
import UIKit
import AVKit
import AVFoundation
class ModalViewController: UIViewController {
var audioPlayer = AVAudioPlayer()
let varSend = VarSend.sharedInstance
var timer:NSTimer!
var toggleState = 2
#IBOutlet weak var slider: UISlider!
#IBOutlet weak var sermonImage: UIImageView!
#IBOutlet weak var sermont: UILabel!
#IBOutlet weak var sermond: UILabel!
#IBOutlet weak var sermonE: UILabel!
#IBOutlet weak var sermonL: UILabel!
#IBOutlet weak var play: UIButton!
#IBOutlet var layer: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let url = varSend.url
print("Setting up.")
do {
let data1 = NSData(contentsOfURL: NSURL(string:url)!)
audioPlayer = try AVAudioPlayer(data: data1!)
audioPlayer.prepareToPlay()
audioPlayer.volume = 1.0
audioPlayer.play()
} catch {
print("Error getting the audio file")
}
slider.maximumValue = Float(audioPlayer.duration)
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateSlider"), userInfo: nil, repeats: true)
slider.setThumbImage(UIImage(named: "circle"), forState: .Normal)
slider.setThumbImage(UIImage(named: "circle"), forState: .Highlighted)
let title = varSend.sermonName
self.sermont.text = title
let date = varSend.sermonDate
self.sermond.text = date
let image = varSend.sermonPic
ImageLoader.sharedLoader.imageForUrl(image, completionHandler:{(image: UIImage?, url: String) in
self.sermonImage.image = image!
})
}
#IBAction func ChangeAudioTime(sender: AnyObject) {
audioPlayer.stop()
audioPlayer.currentTime = NSTimeInterval(slider.value)
audioPlayer.prepareToPlay()
audioPlayer.volume = 1.0
audioPlayer.play()
}
func updateSlider() {
slider.value = Float(audioPlayer.currentTime)
let currentTime = Int(audioPlayer.currentTime)
let minutes = currentTime / 60
let seconds = currentTime - minutes * 60
let con = Int(audioPlayer.duration)
let currentItem = con - currentTime
let minutesU = Int(currentItem / 60)
let secondsU = Int(currentItem % 60)
sermonE.text = NSString(format: "%02d:%02d", minutes,seconds) as String
let timeLeft = NSString(format: "%02d:%02d", minutesU,secondsU) as String
sermonL.text = "-\(timeLeft)"
if currentItem == 1 {
//audioPlayer.pause()
toggleState = 1
print(toggleState)
play.setImage(UIImage(named:"play.png"),forState:UIControlState.Normal)
}
}
#IBAction func playPauseButton(sender: AnyObject) {
let playBtn = sender as! UIButton
if toggleState == 1 {
audioPlayer.play()
toggleState = 2
playBtn.setImage(UIImage(named:"pause.png"),forState:UIControlState.Normal)
} else {
audioPlayer.pause()
toggleState = 1
playBtn.setImage(UIImage(named:"play.png"),forState:UIControlState.Normal)
}
}
#IBAction func play(sender: AnyObject) {
audioPlayer.play()
}
#IBAction func pause(sender: AnyObject) {
audioPlayer.pause()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func close(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
audioPlayer.stop()
}
}
And here is what I have tried already:
import UIKit
import Alamofire
import SwiftyJSON
import AVKit
import AVFoundation
import CoreMedia
class test: UIViewController {
var audioPlayer:AVPlayer!
var playerItem:AVPlayerItem!
var timer:NSTimer!
#IBOutlet weak var sermonE: UILabel!
#IBOutlet weak var sermonL: UILabel!
#IBOutlet weak var slider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
//let playerItem:AVPlayerItem!;
let playerURL = "example.com"
let steamingURL:NSURL = NSURL(string:playerURL)!
audioPlayer = AVPlayer(URL: steamingURL)
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateSlider"), userInfo: nil, repeats: true)
}
func updateSlider() {
let item = audioPlayer?.currentItem
let durationInSeconds = CMTimeGetSeconds(item!.duration)
print(durationInSeconds)
}
#IBAction func ChangeAudioTime(sender: AnyObject) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func Play(sender: AnyObject) {
audioPlayer.play()
}
}
I have been searching for days and Apple's docs are very hard to make out.
I even tried
self.player.currentItem.asset.duration
from: How to get Duration from AVPlayer (Not AVAudioPlayer)?
Any help would be much appreciated.
Swift 2.0
loadedTimeRanges The array contains NSValue objects containing a CMTimeRange value
indicating the times ranges for which the player item has media data
readily available. The time ranges returned may be discontinuous.
So I call myplayer.getCurrentTrackDuration every 1 second and noticed that when I'm streaming I got the correct final duration after 3-4 second.
extension AVPlayer {
//run this every 1 second of streaming (or use KVO)
//In Http stream the duration it going to increase and probably finallize near to 7% of the total duration of the song
func getCurrentTrackDuration () -> Float64 {
guard let currentItem = self.currentItem else { return 0.0 }
guard currentItem.loadedTimeRanges.count > 0 else { return 0.0 }
let timeInSecond = CMTimeGetSeconds((currentItem.loadedTimeRanges[0].CMTimeRangeValue).duration);
return timeInSecond >= 0.0 ? timeInSecond : 0.0
}
}

1 Button triggering random sounds (from an array?) in iOS

I've figured out how to trigger a sound when the button is pressed. I'm stuck on triggering a random sound when that same button is pressed. Since the audio player will take a string, I've generated a random number, but don't know how to insert that random number in the player. The code below is really broken so please bear with me there, I'm just stuck.
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var mainButton: UIButton!
var sound1: AVAudioPlayer?
var sound2: AVAudioPlayer?
var sound3: AVAudioPlayer?
var sound4: AVAudioPlayer?
//There are many more sounds, but this is short for the example
var audioPlayer: AVAudioPlayer = AVAudioPlayer()
func setupAudioPlayerWithFile(file: NSString, type: NSString) -> AVAudioPlayer? {
let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
let url = NSURL.fileURLWithPath(path!)
var audioPlayer : AVAudioPlayer?
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
return audioPlayer
}
override func viewDidLoad() {
super.viewDidLoad()
if let sound1 = self.setupAudioPlayerWithFile("sound1", type: "aif")
{self.sound1 = sound1}
if let sound2 = self.setupAudioPlayerWithFile("sound2", type: "aif")
{self.sound2 = sound2}
if let sound3 = self.setupAudioPlayerWithFile("sound3", type: "aif")
{self.sound3 = sound3}
if let sound4 = self.setupAudioPlayerWithFile("sound4", type: "aif")
{self.sound4 = sound4}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func buttonPressed(sender: AnyObject){
let audioArray: NSArray = ["1, 2, 3, 4"]
let range: UInt32 = UInt32(audioArray.count)
number = Int(arc4random_uniform(range))
sound(number)?.play()
}
}
class ViewController: UIViewController {
#IBOutlet weak var mainButton: UIButton!
// PUT SOUNDS AS STRINGS IN ARRAY
var arrayOfSounds = ["sound1", "sound2", "sound3", "sound4"]
var audioPlayer: AVAudioPlayer = AVAudioPlayer()
func setupAudioPlayerWithFile(file: NSString, type: NSString) -> AVAudioPlayer? {
let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
let url = NSURL.fileURLWithPath(path!)
var audioPlayer : AVAudioPlayer?
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
return audioPlayer
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func buttonPressed(sender: AnyObject){
let range: UInt32 = UInt32(arrayOfSounds.count)
number = Int(arc4random_uniform(range))
//FIND OUT WHICH SOUND HERE
let sound = self.setupAudioPlayerWithFile(arrayOfSounds[number], type: "aif")
sound.play()
}
}

Swift runtime error (exc_bad_access) AVAudioRecorder, recordSettings

I have been struggling to change a piece of code for recording audio from swift 1.2 to swift 2. With the help of people here, I made some changes and eventually got rid of all the compiler errors. But now, after I run the code, login into Twitter, and then click on the Record button in the simulator, it crashes and gives me a runtime error. Please see the picture here:
Also, I'm not sure if this is important or not, but I removed "AVFormatIDKey : NSNumber(int: Int32(kAudioFormatAppleLossless))" from the code and commented out "self.audioRecorder.meteringEnabled = true" and "self.audioRecorder.prepareToRecord()" from the code, and it wasn't crashing anymore, but obviously that's not how the code is supposed to run at the very end...
Here is the full version of code. Any thoughts on this?
Thanks a lot for your help
import UIKit
import AVFoundation
class RecordViewController: UIViewController {
required init?(coder aDecoder: NSCoder) {
var baseString : String = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as String
self.audioURL = "sound.m4a"
var pathComponents = [baseString, self.audioURL]
var audioNSURL = NSURL.fileURLWithPathComponents(pathComponents)
var session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch (_) {
}
// session.setCategory(AVAudioSessionCategoryPlayAndRecord, error: nil)
// var recordSettings: [String : AnyObject] = Dictionary()
// recordSettings[AVFormatIDKey] = kAudioFormatMPEG4AAC
// recordSettings[AVFormatIDKey] = NSNumber(unsignedInt: kAudioFormatMPEG4AAC)
// recordSettings[AVSampleRateKey] = 44100.0
// recordSettings[AVNumberOfChannelsKey] = 2
let recordSettings = [
AVSampleRateKey : NSNumber(float: Float(44100.0)),
AVFormatIDKey : NSNumber(int: Int32(kAudioFormatAppleLossless)),
AVNumberOfChannelsKey : NSNumber(int: 1),
AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue)),
AVEncoderBitRateKey : NSNumber(int: Int32(320000))
]
// self.audioRecorder = AVAudioRecorder(URL: audioNSURL, settings: recordSettings, error: nil)
self.audioRecorder = AVAudioRecorder()
print("aaaaa")
do {
self.audioRecorder = try AVAudioRecorder(URL: audioNSURL!, settings: recordSettings)
} catch (_) {
}
self.audioRecorder.meteringEnabled = true
self.audioRecorder.prepareToRecord()
super.init(coder: aDecoder)
}
// required init(coder aDecoder: NSCoder!) {
// super.init(coder : aDecoder)
// self.audioRecorder = AVAudioRecorder()
// }
#IBOutlet weak var recordButton: UIButton!
#IBOutlet weak var playButton: UIButton!
#IBOutlet weak var saveButton: UIBarButtonItem!
var audioRecorder : AVAudioRecorder
var audioURL = ""
override func viewDidLoad() {
super.viewDidLoad()
self.playButton.enabled = false
self.saveButton.enabled = false
// Do any additional setup after loading the view.
}
#IBAction func cancelTapped(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func saveTapped(sender: AnyObject) {
}
#IBAction func recordTapped(sender: AnyObject) {
self.playButton.enabled = true
}
#IBAction func playTapped(sender: AnyObject) {
}
}
I see one forcefully unwrapped optional. Replace your error handling with the following
if let url = audioNSURL {
self.audioRecorder = try? AVAudioRecorder(URL: url, settings: recordSettings)
}
Thank you both Eric and Lukas. I did some further trimming to my whole code and after all I guess I made it work. Now, it compiles without error and also it doesn't do a runtime crash. I'm just posting the final version of my working code so that if anyone else was facing similar issues they can use it.
Thanks again and best to all the awesome guys who contribute here on Stackoverflow.
import UIKit
import AVFoundation
class RecordViewController: UIViewController {
var audioRecorder : AVAudioRecorder?
#IBOutlet weak var recordButton: UIButton!
#IBOutlet weak var playButton: UIButton!
#IBOutlet weak var saveButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
self.playButton.enabled = false
self.saveButton.enabled = false
}
func setRecorder() {
do {
let baseString : String = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).first!
let pathComponents = [baseString, "music.m4a"]
let audioURL = NSURL.fileURLWithPathComponents(pathComponents)
let session = AVAudioSession.sharedInstance()
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
try session.overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker)
try session.setActive(true)
var recordSettings = [String : AnyObject]()
recordSettings[AVFormatIDKey] = Int(kAudioFormatMPEG4AAC)
recordSettings[AVSampleRateKey] = 44100.0
recordSettings[AVNumberOfChannelsKey] = 2
self.audioRecorder = try AVAudioRecorder(URL: audioURL!, settings: recordSettings)
self.audioRecorder!.meteringEnabled = true
self.audioRecorder!.prepareToRecord()
} catch (_) {
}
}
#IBAction func cancelTapped(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func saveTapped(sender: AnyObject) {
}
#IBAction func recordTapped(sender: AnyObject) {
self.playButton.enabled = true
}
#IBAction func playTapped(sender: AnyObject) {
}
}

Xcode 7/Swift 2 Extra argument 'error' in call [duplicate]

I just opened my old project in Xcode 7 beta. The code works perfectly fine in Xcode 6, but now it's showing many error. I don"t know what those are. Can anybody explain why this happened, and how to fix it? Thank you! Here is the Code
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer = AVAudioPlayer()
#IBOutlet weak var firstCardImageView: UIImageView!
#IBOutlet weak var secondCardImageView: UIImageView!
#IBOutlet weak var label: UILabel!
var cardNamesArray:[String] = ["dice1","dice2","dice3","dice4","dice5","dice6"]
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 rollaction(sender: AnyObject) {
updateAction()
}
func updateAction(){
var firstRandomNumber = Int(arc4random_uniform(5))
var firstCardString:String = String(self.cardNamesArray[firstRandomNumber])
var secondRandomNumber = Int(arc4random_uniform(5))
var secondCardString:String = String(self.cardNamesArray[secondRandomNumber])
self.firstCardImageView.image = UIImage(named: firstCardString)
self.secondCardImageView.image = UIImage(named: secondCardString)
var fileLocation = NSBundle.mainBundle().pathForResource("sound", ofType: ".mp3")
var error: NSError? = nil
player = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: fileLocation!), error: &error) //Error: Cannot find an initializer for type 'AVAudioPlayer' that accepts an argument list of type '(contentsOfURL: NSURL, error: inout NSError?)'
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, error: nil) //Error:Extra argument 'error' in call
AVAudioSession.sharedInstance().setActive(true, error: nil) //Error:Extra argument 'error' in call
player.play()
let num = firstRandomNumber + secondRandomNumber + 2
self.label.text = "The sum is \(num)"
}
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent) {
if event.subtype == UIEventSubtype.MotionShake { //Error:Method does not override any method from its superclass
updateAction()
}
}
}
Here's your updateAction() function with Swift 2.0's do/try/catch implementation:
func updateAction(){
var firstRandomNumber = Int(arc4random_uniform(5))
var firstCardString:String = String(self.cardNamesArray[firstRandomNumber])
var secondRandomNumber = Int(arc4random_uniform(5))
var secondCardString:String = String(self.cardNamesArray[secondRandomNumber])
self.firstCardImageView.image = UIImage(named: firstCardString)
self.secondCardImageView.image = UIImage(named: secondCardString)
let fileLocation = NSBundle.mainBundle().pathForResource("sound", ofType: ".mp3")
do {
player = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: fileLocation!))
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
try AVAudioSession.sharedInstance().setActive(true)
}
catch {
print("Something bad happened. Try catching specific errors to narrow things down")
}
player.play()
let num = firstRandomNumber + secondRandomNumber + 2
self.label.text = "The sum is \(num)"
}

Resources