I'm creating a music app and I'm using an UISlider for the music volume control. the problem is when I press the volume button on the iPhone / iPad UISlider does not change or move. I've been looking for where to get no referrals.
This is the code I use:
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
self.slider.setValue(AVAudioSession.sharedInstance().outputVolume, animated: true)
}
}
#IBAction func volumeControlSlider(_ sender: UISlider) {
slider = (MPVolumeView().subviews.filter { NSStringFromClass($0.classForCoder) == "MPVolumeSlider" }.first as! UISlider)
slider.setValue(sender.value, animated: false)
}
Related
I am creating a small project such that after pressing a button which
will take me to the next view controller using the navigation controller - can i delay the function to execute the navigation controller after some time
i am using this code-
import UIKit
class ViewController: UIViewController
{
#IBAction func enterButtonPressed(_ sender: UIButton)
{
let vc = storyboard?.instantiateViewController(withIdentifier: "ViewController2") as! ViewController2
self.navigationController?.pushViewController(vc, animated: true)
}
override func viewDidLoad()
{
super.viewDidLoad()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
}
Suppose sender.tag holds the duration which is 0 for proceed , 5 or 10
var playTimer:Timer?
//
#IBAction func btnClicked(_ sender:UIButton) {
playTimer?.invalidate()
playTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(sender.tag), repeats: false, block: { (T) in
// play the audio
})
}
Try this one
var timeLimit = 5.0
DispatchQueue.main.asyncAfter(deadline: .now() + timeLimit, execute: {
//Play your audio here
//Audio will play after 5 seconds here
})
I have a UISlider and AvAudioPlayer, currently I am able to set the UISlider to the currentTime of a AvAudioPlayer like so:
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: (#selector(RecordController.updateTimer)), userInfo: nil, repeats: true)
#objc func updateTimer() {
if(audio != nil) {
audioSlider.setValue(Float((self.audio?.currentTime)! / (self.audio?.duration)!), animated: false)
}
}
But how would I set the currentTime of the AVAudioPlayer when changing the value of the UISlider?
#IBAction func audioSliderUpdated(_ sender: Any) {
}
You can use the currentTime property of AVAudioPlayer:
#IBAction func audioSliderUpdated(_ sender: Any) {
if let slider = sender as? UISlider {
self.audio?.currentTime = slider.value
}
}
Use this, slider value changes according to time
#IBAction func slide(_ sender: UISlider) {
self.audio.currentTime = TimeInterval(slider.value)
}
You have to convert your slider value to a new value which based on your media file.
First, you must config your slider values to work in normalized values (from 0.0 to 1.0)
/// call this on viewDidLoad: configDefaults(for: audioSlider)
func configDefaults(for slider: UISlider)
slider.minimumValue = 0.0
slider.maximumValue = 1.0
}
Then you should calculate currentTime from audioSlider.value and duration then set it to the player.currentTime.
#IBAction func audioSliderUpdated(_ sender: Any) {
guard let slider = sender as? UISlider,
let player = audio else {
return
}
player.currentTime = Double(slider.value) * player.duration
}
I need to add Tap Gesture on Navigation Bar or View.
I got the below solution which works perfectly fine.
But removeGestureRecognizer is not removing the gesture and it's breaking the functionality of other back buttons in other view controllers.
How to fix the issue?
var taskTodoOnBar : UITapGestureRecognizer!
override func viewWillAppear(animated: Bool)
{
navigationController?.view.addGestureRecognizer(taskTodoOnBar)
}
override func viewWillDisappear(animated: Bool)
{
navigationController?.view.removeGestureRecognizer(taskTodoOnBar)
}
Or
override func viewWillAppear(animated: Bool)
{
navigationController?.navigationBar.addGestureRecognizer(taskTodoOnBar)
}
override func viewWillDisappear(animated: Bool)
{
navigationController?.navigationBar.removeGestureRecognizer(taskTodoOnBar)
}
When I try to get gestureRecognizers count, It says nil. Then where is the gesture being added ?
override func viewWillDisappear(animated: Bool)
{
print(navigationController!.view.gestureRecognizers!.count)
print(navigationController!.navigationBar.gestureRecognizers!.count)
}
Try using this
Declared gesture as
let tapGesture : UITapGestureRecognizer = UITapGestureRecognizer()
Gesture Handler
#objc func tapHandler(handler: UITapGestureRecognizer){
print("gesture Added")
}
Added in Navigation bar as
override func viewDidLoad()
{
super.viewDidLoad()
tapGesture.numberOfTapsRequired = 1
tapGesture.addTarget(self, action: #selector(VC2.tapHandler(handler:)))
self.navigationController?.view.addGestureRecognizer(tapGesture)
}
Removed as
override func viewWillDisappear(_ animated: Bool) {
for gesture in (navigationController?.view.gestureRecognizers)! {
if gesture == tapGesture {
navigationController?.view.removeGestureRecognizer(tapGesture)
print("removed")
}
}
}
Updated Answer for - gesture count prints nil
console Output :
After help from iOS Geek, I figured out that, gestureRecognizers!.count was 2 in ViewdDidLoad but was nil inside viewWillDisappear.
Then I dug more and discovered that I had written the custom code for my back button.
So in such case, we Should removeGestureRecognizer before popToViewController
So this is for all whom I wish not to make mistake like me while using the custom back button.
func backBarBtnFnc(sender: UIBarButtonItem)
{
navigationController?.navigationBar.removeGestureRecognizer(taskTodoOnBar)
// CodTdo ...
self.navigationController!.popToViewController(VC2, animated: true)
}
I have some ViewCotroller where i tapped a button - some audio file is playing. I want to stop playing audio when change/close this ViewController. How I can do this?
I try add some method to viewWillDisappear and it crashed if I don't tap any button. But if I tapped some button - it will works fine. 🙁
import UIKit
import AVFoundation
class BossViewController: UIViewController {
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//MARK: - Stop sound when we're change/close this viewController
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
audioPlayer.stop()
}
This is how my button is look like:
#IBAction func boss1(_ sender: AnyObject) {
let audioFile = NSURL(fileURLWithPath: Bundle.main.path(forResource: "shamp", ofType: "mp3")!)
do {
audioPlayer = try AVAudioPlayer(contentsOf: audioFile as URL)
audioPlayer.prepareToPlay()
} catch {
print("Problem in getting File")
}
audioPlayer.play()
}
You can check if the audio player is playing, as #SandeepBhandari mentioned, or you can use a Bool variable to keep track whether or not the user tapped the button:
var buttonTapped = false
#IBAction func boss1(_ sender: AnyObject) {
...
buttonTapped = true
}
Then, you can check the variable in your viewWillDisappear(_ animated: Bool) method:
override func viewWillDisappear(_ animated: Bool) {
if buttonTapped {
audioPlayer.stop()
}
}
I created the button with Image on MainStoryBoard. When I press that button it plays audio file.
I would like that button to stay highlighted during the time audio file is playing. When the audio is finished, I want the button to return to its default state.
I discovered that audioPlayerDidFinishPlaying(_:successfully:) is a right way, but can not solve this problem. Is it close to the proper way to do it? If not, how should I?
I'd appreciate any advice that will lead to finding the solution to this problem. Thanks.
let url = Bundle.main.bundleURL.appendingPathComponent("audio1.mp3")
override func viewDidLoad() {
super.viewDidLoad()
}
func play(url: URL) {
do {
try player = AVAudioPlayer(contentsOf:url)
player.play()
} catch {
print(error)
}
}
#IBAction func pushButton1(sender: UIButton) {
play(url: url)
}
On viewDidLoad, you can set default property when it is not playing (eg: I'm keeping background color as white) and while playing, make that button as selected(eg: I'm making it color Green)
Again in audioPlayerDidFinishPlaying when it stops playing audio, make it to default state (green to white again):
#IBOutlet weak var yourButton: UIButton!
let url = Bundle.main.bundleURL.appendingPathComponent("audio1.mp3")
override func viewDidLoad() {
super.viewDidLoad()
self.yourButton.backgroundColor = UIColor.white // default state of button
}
#IBAction func pushButton1(sender: UIButton) {
play(url: url)
}
func play(url: URL) {
do {
try player = AVAudioPlayer(contentsOf:url)
player.play()
self.yourButton.backgroundColor = UIColor.green // playing
}
catch {
print(error)
}
}
func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) {
self.yourButton.backgroundColor = UIColor.white // back to default state
}