Swift audio playing from url - ios

import AVFoundation
import UIKit
class ViewController: UIViewController {
#IBOutlet var button: UIButton!
var player: AVPlayer?
var playerItem:AVPlayerItem?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func didTapButton(urlRadio: String){
if let player = player, player.isMuted{
//stop playback
}
else{
do {
try AVAudioSession.sharedInstance().setMode(.default)
try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
guard let urlRadio = URL.init(string: "http://live.shtorm.fm:8000/mp3_rushtorm") else {
return
}
let playerItem:AVPlayerItem = AVPlayerItem.init(url: urlRadio)
player = AVAudioPlayer.init(playerItem: playerItem)
}
catch {
print("something went wrong")
}
}
}
}
shows error Exception NSException * "-[RozetkaRadio.ViewController didTapButton]: unrecognized selector sent to instance 0x7ff070f07a50" 0x00006000008c7210 after pressing button in emulator
using storyboard

Your issue is with this line of code. Specifically, the parameter urlRadio.
#IBAction func didTapButton(urlRadio: String){
It looks like you have changed the standard IBAction from what was set in storyboard. You cannot change the parameters in an IBAction as the storyboard no longer recognizes where to send the tap to.
Your IBAction should look something like this
#IBAction func didTapButton(_ sender: Any)
Whenever you see Unrecognized selector sent to instance you should immediately think "Something is not hooked up properly between my storyboard and my ViewController"
One quick way to look is by right clicking your controller scene name on the storyboard. You can see I commented out my SignIn IBAction function. If I wanted to remove it I would have to also remove the connection on the storyboard. You can see the storyboard will let me know by leaving a yellow warning label.

Related

Thread 1: "-[Xylophone.ViewController buttonClicked:]: unrecognized selector sent to instance 0x7ff83a6074e0"

Exception NSException * "-[Xylophone.ViewController buttonClicked:]:
unrecognized selector sent to instance
0x7faa47409400" 0x0000600002148690
I'm trying to make a xylophone app in which the buttons would play different sounds, there are 7 buttons however only the first button doesn't work, all other buttons work. on pressing the first button the app crashes.
Here is the code:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func keyPressed(_ sender: UIButton) {
playSound(soundName: sender.currentTitle!)
}
func playSound(soundName:String) {
let url = Bundle.main.url(forResource: soundName, withExtension: "wav")
player = try! AVAudioPlayer(contentsOf: url!)
player.play()
}
}
what is the issue here?
I faced the same issue and here's how I solved it:
right-click every button you have in Main.storyboard, and check the connection it has in the small menu like this:
When I had more than one connection it gave me this error.

"unrecognized selector sent to instance" when selector is in other file

Here is the problematic ViewController class.
class ViewController: UIViewController {
#IBOutlet weak var photoSelectActionSheet: UIButton!
#IBOutlet weak var selectedImageView: UIImageView!
var imagePicker: UIImagePickerController!
var selectedImage: UIImage? = ni
var iCloud = ICloud() // see below for code of that file
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Must use this system to check each time the view appears.
// This is checked each time so if user goes into settings and come back in same session
// then this will be updated => viewDidLoad is cached and not reloaded each time.
NotificationCenter.default.addObserver(
self,
selector:#selector(ICloud.checkIfUserIsLoggedInIcloud), // PROBLEM IS HERE
name: UIApplication.didBecomeActiveNotification,
object: nil)
}
// more code not shown
}
Problem is in viewWillAppear: the notification center calls a selector that is in an other Model file ICloud.swift:
import UIKit
import CloudKit
class ICloud {
var isLoggedInIcloud: Bool? = nil
var userIcloudId: String? = nil
func getUserIcloudId() {
// Run this only if user is logged into icloud, and we don't have yet its iCloud id.
if isLoggedInIcloud ?? false && userIcloudId == nil {
CKContainer.default().fetchUserRecordID(completionHandler: { (recordId, error) in
if let id = recordId?.recordName {
print("userIcloudId set to: " + id)
self.userIcloudId = id
}
else if let error = error {
print(error.localizedDescription)
}
})
}
}
#objc func checkIfUserIsLoggedInIcloud() {
// Check if user is logged into iCloud
CKContainer.default().accountStatus { accountStatus, error in
if accountStatus == .available {
self.isLoggedInIcloud = true
print("isLoggedInIcloud set to true")
self.getUserIcloudId()
return
}
print("User is not logged into icloud")
}
}
}
I expected "ICloud.checkIfUserIsLoggedInIcloud" passed in selector to work. It doesn't:
2020-07-01 11:46:12.931419+0200 QDog[53348:3422745] -[QDog.ViewController checkIfUserIsLoggedInIcloud]: unrecognized selector sent to instance 0x7fcad5f0c1d0
2020-07-01 11:46:12.938567+0200 QDog[53348:3422745] *** Terminating app due to uncaught exception
If I add back the functions and variables from ICloud.swift directly into the ViewController file and pass to the selector "checkIfUserIsLoggedInIcloud" it WILL WORK properly.
I wanted to put all icloud code into a separate model file for separation of concerns and to make the code more clear.
Question is: why does 'ICloud.checkIfUserIsLoggedInIcloud' passed as selector doesn't work? And how to make this work with ICloud code in its own file, and not in ViewController file?
According to the documentation, the first parameter should be the observer, which in your case you're pointing to self.
In this case, self is your ViewController, which doesn't have the method checkIfUserIsLoggedInIcloud. In order to make it work, as an observer, you need to pass the property iCloud instead of self.

Open with file in swift

When you open url that contain PDF file safari ask you if you want to open it on safari or in iBook.
I want to do the same thing ,
in my project i had a collection view contains videos and photos,
i want the user to chose if he want to open the file on the app or to open it with other media player.
For loading into your own app it depends on which class you're using to display content on the exact code you'd use but for opening in another app you'd normally use a share button. Here is example code that will work if you wire up the #IBAction and #IBOutlet to the same bar button in your UI (and place a file at the fileURL that you specify):
import UIKit
class ViewController: UIViewController {
// UIDocumentInteractionController instance is a class property
var docController:UIDocumentInteractionController!
#IBOutlet weak var shareButton: UIBarButtonItem!
// called when bar button item is pressed
#IBAction func shareDoc(sender: AnyObject) {
// present UIDocumentInteractionController
if let barButton = sender as? UIBarButtonItem {
docController.presentOptionsMenuFromBarButtonItem(barButton, animated: true)
}
else {
print("Wrong button type, check that it is a UIBarButton")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// retrieve URL to file in main bundle
if let fileURL = NSBundle.mainBundle().URLForResource("MyImage", withExtension: "jpg") {
// Instantiate the interaction controller
self.docController = UIDocumentInteractionController(URL: fileURL)
}
else {
shareButton.enabled = false
print("File missing! Button has been disabled")
}
}
}
Notes
A UIDocumentInteractionController is used to enable the sharing of documents between your app and other apps installed on a user's device. It is simple to set up as long as you remember three rules:
Always make the UIDocumentInteractionController instance a class
(type) property. If you only retain a reference to the controller
for the life of the method that is triggered by the button press
your app will crash.
Configure the UIDocumentInteractionController
before the button calling the method is pressed so that there is not
a wait in which the app is waiting for the popover to appear. This is important because while
the presentation of the controller happens asynchronously, the instantiation does not. And you may find that there is a noticeable delay to open the popover if
you throw all the code for instantiation and presentation inside a
single method called on the press of a button. (When testing you might see a delay anyway because the share button is likely going to be pressed almost straightaway but in real world use there should be more time for the controller to prepare itself and so the possibility of lag is less likely.)
The third rule is that you must test this on a real device not in the simulator.
More can be found in my blogpost on the subject.
Edit: Using a UIActivityViewController
Code for using UIActivityViewController instead of UIDocumentInteractionController
import UIKit
class ViewController: UIViewController {
// UIDocumentInteractionController instance is a class property
var activityController: UIActivityViewController!
#IBOutlet weak var shareButton: UIBarButtonItem!
// called when bar button item is pressed
#IBAction func shareStuff(sender: AnyObject) {
if let barButton = sender as? UIBarButtonItem {
self.presentViewController(activityController, animated: true, completion: nil)
let presCon = activityController.popoverPresentationController
presCon?.barButtonItem = barButton
}
else {
print("not a bar button!")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// retrieve URL to file in main bundle
if let img = UIImage(named:"MyImage.jpg") {
// Instantiate the interaction controller
activityController = UIActivityViewController(activityItems: [img], applicationActivities: nil)
}
else {
shareButton.enabled = false
print("file missing!")
}
}
}
You can also add custom activities to the UIActivityViewController and here is code for adding an "Open In..." button to a UIActivityViewController so that you can switch to a UIDocumentInteractionController from a UIActivityViewController.
I did the same code for saving a PDF file from a URL (whether it's a local URL in your device storage, or it's a URL from somewhere on the internet)
Here is the Code for Swift 3 :
#IBOutlet weak var pdfWebView: UIWebView!
#IBOutlet weak var shareBtnItem: UIBarButtonItem!
var pdfURL : URL!
var docController : UIDocumentInteractionController!
then in viewDidLoad()
// retrieve URL to file in main bundle`
let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("YOUR_FILE_NAME.pdf")
//Instantiate the interaction controller`
self.docController = UIDocumentInteractionController(url: fileURL)`
and in your barButtonItem tapped method (which I have called openIn(sender)):
#IBAction func openIn(_ sender: UIBarButtonItem)
{
// present UIDocumentInteractionController`
docController.presentOptionsMenu(from: sender, animated: true)
}
FYI: You need a webView in your storyboard if you wish to show the pdf file as well
Hope this helps.

On Tap of UILabel (gesture recogniser) finding nil in tableview prototype cell for one cell and its working fine for another two cells

I am trying to implement UITapGestureRecognizer, Idea is that on tap of label I will get a pop up displaying the number to make call and it should come up with pop up alert saying call or cancel!!
Code I've written worked for me in 3 to 4 places but I am stuck at one point
In this screen I have a tableview with prototype cells grouped type here, please check this Image:
Link For Image
Third Cell
Now If I am Tapping 065668982 I have canOpenURL: failed for URL: "telprompt://065668982" - error: "This app is not allowed to query for scheme telprompt" which actually works on iPhone not on simulator and it pulls to call which is working fine.
Second Cell
If I am Tapping 065454858 I have canOpenURL: failed for URL: "telprompt://065668982" - error: "This app is not allowed to query for scheme telprompt" which actually works on iPhone not on simulator and it pulls to call which is working fine.
first Cell
But for first one it never works and end up with fatal error: unexpectedly found nil while unwrapping an Optional value
NOTE : I am Getting phone Number from an API and append the data in view controller to UITableViewCell.
I Hope I make sense, Thanks in advance for any help also if I am not clear please comment below
Here is my code:
import UIKit
import Foundation
class XyzTableViewCell: UITableViewCell
{
#IBOutlet weak var phoneNumber: UILabel!
var touchContact : String = ""
var myCell: MyCellData! {
didSet {
self.updateUI()
}
}
func updateUI()
{
touchContact = vicarCell.phone_no
//Tap Gesture
tapGestureAddonView()
}
//MARK:- Tap to Call and Open Email
func tapGestureAddonView(){
let contacttap = UITapGestureRecognizer(target: self, action:("contactTapped"))
contacttap.numberOfTapsRequired = 1
phoneNumber!.userInteractionEnabled = true
phoneNumber!.addGestureRecognizer(contacttap)
}
func contactTapped() {
// do something cool here
print("contactTapped")
print(touchContact)
dispatch_async(dispatch_get_main_queue())
{
if UIApplication.sharedApplication().canOpenURL(NSURL(string: "telprompt://\(self.touchContact)")!){
UIApplication.sharedApplication().openURL(NSURL(string: "telprompt://\(self.touchContact)")!)
}
else{
//showAlert("Info",message: "Your device could not called" ,owner: self)
}
}
}
The issues: 1) you should add gesture only once 2) you should check NSURL for nil. Let me assume that you use storyboard and improve your code a bit
class XyzTableViewCell: UITableViewCell
{
#IBOutlet weak var phoneNumber: UILabel!
var touchContact : String = ""
var myCell: MyCellData! {didSet {self.updateUI()}}
func updateUI() {
touchContact = myCell.phone_no // did you mean myCell instead vicarCell?
}
override func awakeFromNib() {
super.awakeFromNib()
tapGestureAddonView()
}
func tapGestureAddonView(){
let contacttap = UITapGestureRecognizer(target: self, action: #selector(contactTapped))
contacttap.numberOfTapsRequired = 1
phoneNumber!.userInteractionEnabled = true
phoneNumber!.addGestureRecognizer(contacttap)
}
func contactTapped() {
print("contactTapped")
print(touchContact)
if touchContact.isEmpty {return}
guard let url = NSURL(string: "telprompt://\(touchContact)") else {
print("url string invalid")
return
}
dispatch_async(dispatch_get_main_queue())
{
if UIApplication.sharedApplication().canOpenURL(url){
UIApplication.sharedApplication().openURL(url)
} else{
//showAlert("Info",message: "Your device could not called" ,owner: self)
}
}
}
}

SIGABRT error in swift 2

I recently updated my app to Swift 2, and had one error, which I solved thanks to you guys.
And now, I have a second error, which is at runtime, when I press the one button to play a sound. It is a signal SIGABRT error.
Here is the error message I get in the debug console:
2016-01-25 09:16:09.019 WarningShot1.0.0[291:19030] -[WarningShot1_0_0.ViewController playMySound:]: unrecognized selector sent to instance 0x135547d30
2016-01-25 09:16:09.021 WarningShot1.0.0[291:19030] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[WarningShot1_0_0.ViewController playMySound:]: unrecognized selector sent to instance 0x135547d30'
*** First throw call stack:
(0x182835900 0x181ea3f80 0x18283c61c 0x1828395b8 0x18273d68c 0x18755fe50 0x18755fdcc 0x187547a88 0x18755f6e4 0x18755f314 0x187557e30 0x1875284cc 0x187526794 0x1827ecefc 0x1827ec990 0x1827ea690 0x182719680 0x183c28088 0x187590d90 0x10005e2e0 0x1822ba8b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
Also, this is the part of the code where it throws this error, in the second line, where the class is declared:
import UIKit
#UIApplicationMain
-> class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
What is happening here? What am I missing / misnaming? What do I need to change in my code to get ot running again. This app is ridiculously simple, and worked for months under the last version of Swift. Why is it now giving me errors?
Thank you for your help.
Here is the code for my ViewController.swift file:
import UIKit
import AVFoundation
import CoreMotion
class ViewController: UIViewController {
var myPlayer = AVAudioPlayer()
var mySound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("RemSound_01", ofType: "wav")!)
func initYourSound() {
do {
try myPlayer = AVAudioPlayer(contentsOfURL: mySound, fileTypeHint: nil)
myPlayer.prepareToPlay()
// myPlayer.volume = 1.0 // < for setting initial volume, still not perfected.
} catch {
// handle error
}
var motionManager = CMMotionManager()
var currentMaxAccelY : Double = 0.0
func viewDidLoad() {
super.viewDidLoad()
initYourSound()
// Do any additional setup after loading the view, typically from a nib.
//set motion manager properties
motionManager.accelerometerUpdateInterval = 0.17
//start recording data
// motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler: {
// (accelerometerData: CMAccelerometerData!,error:NSError!) -> Void in
// self.outputAccelerationData(accelerometerData.acceleration)
// if(error != nil) {
// print("\(error)")
// }
// })
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue()!, withHandler: {
(accelerometerData,error) in outputAccelerationData(accelerometerData!.acceleration)
if(error != nil) {
print("\(error)", terminator: "")
}
})
}
//func outputAccelerationData(acceleration : CMAcceleration){
// accY?.text = "\(acceleration.y).2fg"
//if fabs(acceleration.y) > fabs(currentMaxAccelY)
//{
// currentMaxAccelY = acceleration.y
//}
// maxAccY?.text = "\(currentMaxAccelY) .2f"
//}
func outputAccelerationData(acceleration : CMAcceleration){
if fabs(acceleration.y) >= 1.25 {
myPlayer.play()
}
}
func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func playMySound(sender: AnyObject) {
myPlayer.play()
}
// self.resetMaxValues()
// #IBOutlet var accY: UILabel!
// #IBOutlet var maxAccY: UILabel!
// #IBAction func resetMaxValues() {
// currentMaxAccelY = 0
// }
}
}
"unrecognized selector sent to instance" means that there is a mismatch between the action-name in "addTarget()" and the name of the function you want to call. Probably something with the parameters of the function.. It's hard to say without seeing any code.
action: Selector("playMySound:")
would expect to find a function:
func playMySound(sender: AnyObject?) {};
To easier track what's happening, you might add a symbolic breakpoint for all exceptions. You do that in Xcode on the "exceptions" tab (left part of the window) and when an exception is thrown, Xcode stops like usual and you might look up the stack trace. If the call is synchronous, you should easily find and see your mistake.
EDIT: Oh well, you seem to have done the user interface using a XIB file. The mistake could be, you wired the button's action in the XIB file to the view controller. If you later change the method's signature (parameter, name, etc.), UIKit can't find the method. Open the XIB and fix your error. ;-)

Resources