I want to set a switch or button to mute on a video background in swift 3+
CODE:
import UIKit
import SwiftVideoBackground
class ViewController: UIViewController {
private let videoBackground = VideoBackground()
override func viewDidLoad() {
super.viewDidLoad()
videoBackground.play(view: view, videoName: "intro", videoType: "mp4", isMuted: false, alpha : 0.25, willLoopVideo : true)
}
}
//Add this method to VideoBackground class
public var isMuted = true {
didSet {
playerLayer.player?.isMuted = isMuted
}
}
//Button action method
#IBAction func mute(_ sender: Any) {
videoBackground.isMuted = true
}
// when app is in background
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
videoBackground.pause() // OR videoBackground.isMuted = true
}
SOLUTION:
SOLUTION:
import UIKit
import SwiftVideoBackground
import AVFoundation
class ViewController: UIViewController {
private let videoBackground = VideoBackground()
#IBAction func `switch`(_ sender: UISwitch) {
if (sender.isOn == true)
{
videoBackground.isMuted = true
}
else
{
videoBackground.isMuted = false
}
}
override func viewDidLoad() {
super.viewDidLoad()
videoBackground.play(view: view, videoName: "intro", videoType: "mp4", isMuted: false, alpha : 0.25, willLoopVideo : true)
}
}
Related
I'll try to change the status bar style inside the view controller because I want to use a different style depending on ViewController, and I try each of these recommendations How to change Status Bar text color in iOS, and I change option inside Info.plist , also not have an effect, what is wrong?
My code:
import SwiftUI
import UIKit
#main
struct TestAppearanceApp: App {
var body: some Scene {
WindowGroup {
WrapperUIVC_Hello().edgesIgnoringSafeArea(.all)
}
}
}
struct WrapperUIVC_Hello: UIViewControllerRepresentable {
func makeUIViewController(context: UIViewControllerRepresentableContext<WrapperUIVC_Hello>) -> some UIViewController {
let controller = ViewController()
controller.modalPresentationStyle = .automatic
return controller
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: UIViewControllerRepresentableContext<WrapperUIVC_Hello>) {
}
}
class ViewController: UIViewController {
lazy var button: UIButton = {
let view = UIButton()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .brown
view.addTarget(self, action: #selector(addInteraction(_:)), for: .touchUpInside)
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
view.addSubview(button)
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
button.widthAnchor.constraint(equalToConstant: 100).isActive = true
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
#objc func addInteraction(_ sender: UIButton) {
let vc = ViewControllerTest()
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override func viewDidAppear(_ animated: Bool) {
setNeedsStatusBarAppearanceUpdate()
}
}
class ViewControllerTest: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
setNeedsStatusBarAppearanceUpdate()
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.dismiss(animated: true)
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .darkContent
}
override func viewDidAppear(_ animated: Bool) {
setNeedsStatusBarAppearanceUpdate()
}
}
First of all, sorry the english.
I have a project in Swift 4.2. One of the Pods is imported and added to a class "Principal View Controller". This Pod has de UIViewController and i cannot add it on the class because it's used on the Pod and Xcode doesn't alow multiple inheritance.
If I remove the Pod from the class the Iboutlets works without problem but the pod is not working ( it's used for side menu ). If i leave the Pod added, the Iboutlets just get nil value.
I track in a debug the code and pass on 2 of the ViewDidLoad and nothing load value on Outlets if Pod is added.
Maybe someone knows the way to fix this?
**I remove some code from classes because it's way more than the 300000 characters that stackoverflow allow...
//
// PrincipalViewController.swift
//
import UIKit
import SwiftyJSON
import JLSlideMenuController
import Alamofire
class PrincipalViewController: JLSlideNavigationController, UIImagePickerControllerDelegate, URLSessionDownloadDelegate, UIGestureRecognizerDelegate {
#IBOutlet weak var scrollViewWeather: UIScrollView!
#IBOutlet var profileImage:UIImageView!
#IBOutlet var parentView: UIView!
#IBOutlet var lblUserName:UILabel!
#IBOutlet var menuButton:UIButton!
var jsonVar:JSON!
var rutasDisponibles : [Ruta]!
var userDefaults = UserDefaults.standard
var viewDayArray = [UIView](repeating: UIView(), count: 7)
var labelDayArray = [UILabel](repeating: UILabel(), count: 7)
var labelTempDayArray = [UILabel](repeating: UILabel(), count: 7)
var ivDayArray = [UIImageView](repeating: UIImageView(), count: 7)
var taskDescargaKmls : URLSessionTask!
var contador = 1
#IBOutlet weak var btMisRutas: UIButton!
#IBOutlet weak var btRutas: UIButton!
#IBOutlet weak var btInfoMunicipio: UIButton!
var jlSlide: JLSlideNavigationController!
lazy var session : Foundation.URLSession = {
let config = URLSessionConfiguration.ephemeral
config.allowsCellularAccess = false
let session = Foundation.URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
return session
}()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
UIApplication.shared.isStatusBarHidden = false
profileImage.layer.borderColor = UIColor.lightGray.cgColor
let lang = UserDefaults.standard.string(forKey: "LANG");
btRutas.setTitle(Languages.translateText("rutas", language: lang!), for: UIControl.State())
btInfoMunicipio.setTitle(Languages.translateText("info_municipio", language: lang!), for: UIControl.State())
btMisRutas.setTitle(Languages.translateText("mis_rutas", language: lang!), for: UIControl.State())
if(!OnlineStatus.isConnectedToNetwork()){
scrollViewWeather.isHidden = true
}
}
#IBAction func sideMenu(_ sender: UIButton) {
if menuIsPresented(){
self.hideMenu(animated: true)
}
else{
self.showMenu(animated: true)
}
}
override func viewDidLoad() {
super.viewDidLoad()
let configuration = URLSessionConfiguration.background(withIdentifier: "com.website.background")
let gesture = UITapGestureRecognizer(target: self, action: #selector(PrincipalViewController.closeMenu(_:)))
gesture.numberOfTapsRequired = 1
gesture.numberOfTouchesRequired = 1
gesture.delegate = self
self.parentView.addGestureRecognizer(gesture)
addSlideMenu("MenuViewController",storyboardName: "Main",distToTop: 0, widthAspectRatio: 0.8, distToBottom: 0,comeFromLeft: true)
}
The pod is JSlideMenuController : https://cocoapods.org/pods/JLSlideMenuController
//
// JLSlideMenuViewController.swift
// Pods
//
// Created by José Lucas Souza das Chagas on 20/03/16.
//
//
import UIKit
public class JLSlideMenuViewController: UIViewController {
public var attachedNavController:JLSlideNavigationController!
//constraints
var sideDist:NSLayoutConstraint!
var distToTopC:NSLayoutConstraint!
var distToBottomC:NSLayoutConstraint!
var widthC:NSLayoutConstraint!
//
/**
TRUE to enable the menu FALSE to disable
The value of this enable or disable the animations and gestures to show and hide the menu
*/
public var enabled:Bool = true{
didSet{
if enabled == false{
attachedNavController.hideMenu(animated: false)
}
}
}
override public func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.view.layoutIfNeeded()
}
override public func didMove(toParent parent: UIViewController?) {
super.didMove(toParent: parent)
//print(parent!.childViewControllers)
}
//public override func canBecomeFirstResponder() -> Bool {
public func canBecomeFirstResponder() -> Bool {
return true
}
override public func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//override public func prefersStatusBarHidden() -> Bool {
public func prefersStatusBarHidden() -> Bool {
return true
}
func removeConstraints(){
self.view.window!.removeConstraint(sideDist)
self.view.window!.removeConstraint(distToTopC)
self.view.window!.removeConstraint(distToBottomC)
self.view.removeConstraint(widthC)
}
/**
Call this method to present modally the correct view controller accordingly to some interaction
with the menu view controller
- parameter VCId: The Id of the view controller to show
- parameter storyboardName: the name of the storyboard where the view controller is
- parameter animated: true to transition with some animation or not
*/
public func presentControllerModally(VCId:String,storyboardName:String,animated:Bool){
let destinyVC = JLSlideNavigationController.loadMenuVC(identifier: VCId, storyboardName: storyboardName)
destinyVC.view.frame = self.attachedNavController.view.frame
self.attachedNavController.hideMenu(animated: false)
let menuSegue = UIStoryboardSegue(identifier: "actualViewToAnother", source: self.attachedNavController,
destination: destinyVC, performHandler: { () -> Void in
DispatchQueue.global(qos: .background).async {
// Background Thread
DispatchQueue.main.async {
// Run UI Updates
self.attachedNavController.topViewController!.present(destinyVC, animated: animated, completion: nil)
}
}
/*
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.attachedNavController.topViewController!.presentViewController(destinyVC, animated: animated, completion: nil)
})
*/
})
//self.prepareForSegue(menuSegue, sender: nil)
self.attachedNavController.topViewController!.prepare(for: menuSegue, sender: nil)
menuSegue.perform()
}
/**
Call this method to show the correct view controller accordingly to some interaction
with the menu view controller
Use this one if the view controller where the menu is right now have some navigation controller
- parameter VCId: The Id of the view controller to show
- parameter storyboardName: the name of the storyboard where the view controller is
- parameter animated: true to transition with some animation or not
*/
public func showController(VCId:String,storyboardName:String,animated:Bool){
let destinyVC = JLSlideNavigationController.loadMenuVC(identifier: VCId, storyboardName: storyboardName)
destinyVC.view.frame = self.attachedNavController.view.frame
self.attachedNavController.hideMenu(animated: false)
let menuSegue = UIStoryboardSegue(identifier: "actualViewToAnother", source: self.attachedNavController,
destination: destinyVC, performHandler: { () -> Void in
self.attachedNavController.pushViewController(destinyVC, animated: animated)
})
//self.prepareForSegue(menuSegue, sender: nil)
self.attachedNavController.prepare(for: menuSegue, sender: nil)
menuSegue.perform()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
//
// JLSlideNavigationController.swift
// Pods
//
// Created by José Lucas Souza das Chagas on 24/04/16.
//
//
import UIKit
open class JLSlideNavigationController: UINavigationController,UINavigationControllerDelegate {
/**
menuVCStoryboardID: The Id of your menu View Controller.
*/
#IBInspectable private(set) var menuVCStoryboardID:String?
/**
the name of the storyboard where your menu View Controller is.
*/
#IBInspectable private(set) var storyboardName:String?
/**
the value of the constraint that indicates the distance between your menu top and this VC top.
*/
#IBInspectable private(set) var distToTop:CGFloat = 0
/**
the value of the constraint that determine your menu Width.
*/
#IBInspectable private(set) var width:CGFloat = 250
/**
the value of the constraint that indicates the distance between your menu bottom and this VC bottom.
*/
#IBInspectable private(set) var distToBottom:CGFloat = 0
/**
the bolean value that indicates if your menu will come from left or from right of the window.
*/
#IBInspectable private(set) var comeFromLeft:Bool = true
/**
A bolean value that indicates to use or not shadow effects
*/
#IBInspectable private(set) var useShadowEffects:Bool = false
private var menuContainerView: UIView?
/**
The instace of your menu View Controller associated to this View Controller
*/
private(set) static var myMenuVC:JLSlideMenuViewController?
public static var panGes:UIPanGestureRecognizer?
public static var screeEdgePanGes:UIScreenEdgePanGestureRecognizer?
/**
Incicates that the pan gesture that were started enabled or not
*/
private var panEnabled:Bool = false
private var lastPanTouch:CGPoint?
override open func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
if let pan = JLSlideNavigationController.panGes{
pan.isEnabled = true
}
if let pan = JLSlideNavigationController.screeEdgePanGes{
pan.isEnabled = true
}
// Do any additional setup after loading the view.
}
open override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let _ = self.view.window{
checkIfShouldAddOrUpdateMenu()
}
print(self.view.window!.gestureRecognizers!.count)
}
open override func viewDidDisappear(_ animated: Bool) {
super.viewDidAppear(animated)
if let pan = JLSlideNavigationController.panGes{
pan.isEnabled = false
}
if let pan = JLSlideNavigationController.screeEdgePanGes{
pan.isEnabled = false
}
}
class func loadMenuVC(identifier:String,storyboardName:String)->UIViewController{
let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
return storyboard.instantiateViewController(withIdentifier: identifier)
}
//MARK: - NavigationController delegate methods
public func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
if let menuView = menuContainerView , let window = self.view.window{
window.bringSubviewToFront(menuView)
}
let subViews = viewController.view.subviews
if let screenEdgeGes = JLSlideNavigationController.screeEdgePanGes{
for subView in subViews{
if let gestures = subView.gestureRecognizers{
for gesture in gestures{
gesture.require(toFail: screenEdgeGes)
}
}
}
}
}
//MARK: - Gestures methods
private func addGestures(){
//Pan
if let window = self.view.window , let pan = JLSlideNavigationController.panGes{
window.removeGestureRecognizer(pan)
}
JLSlideNavigationController.panGes = UIPanGestureRecognizer(target: self, action: #selector(JLSlideNavigationController.panAction(panGes:)))
self.view.window?.addGestureRecognizer(JLSlideNavigationController.panGes!)
//Screen Edge pan
if let window = self.view.window , let pan = JLSlideNavigationController.screeEdgePanGes{
window.removeGestureRecognizer(pan)
}
JLSlideNavigationController.screeEdgePanGes = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(JLSlideNavigationController.screenEdgePanAction(edgePan:)))
if comeFromLeft{
JLSlideNavigationController.screeEdgePanGes!.edges = UIRectEdge.left
}
else{
JLSlideNavigationController.screeEdgePanGes!.edges = UIRectEdge.right
}
self.view.window?.addGestureRecognizer(JLSlideNavigationController.screeEdgePanGes!)
JLSlideNavigationController.panGes!.require(toFail: JLSlideNavigationController.screeEdgePanGes!)
if let screenEdgeGes = JLSlideNavigationController.screeEdgePanGes, let topViewC = topViewController{
let subViews = topViewC.view.subviews
for subView in subViews{
if let gestures = subView.gestureRecognizers{
for gesture in gestures{
gesture.require(toFail: screenEdgeGes)
}
}
}
}
}
#objc public func screenEdgePanAction(edgePan:UIScreenEdgePanGestureRecognizer){
let currenLocation = edgePan.location(in: self.view)
if let menuView = menuContainerView, JLSlideNavigationController.myMenuVC!.enabled{
if edgePan.state == UIGestureRecognizer.State.began{
panEnabled = false
if !menuIsPresented(){
panEnabled = true
lastPanTouch = currenLocation
}
}
else if edgePan.state == UIGestureRecognizer.State.ended{//at the end of pan gesture check if the menu is near to show or hide completelly and then finishes the movement
panEnabled = false
let menuFrame = menuView.frame
if comeFromLeft{
if menuFrame.origin.x <= -menuFrame.size.width/2{
self.hideMenu(animated: true)
}
else if menuFrame.origin.x > -menuFrame.size.width/2{
self.showMenu(animated: true)
}
}
else{
if menuFrame.origin.x >= self.view.frame.width - menuFrame.size.width/2{
self.hideMenu(animated: true)
}
else if menuFrame.origin.x < self.view.frame.width - menuFrame.size.width/2{
self.showMenu(animated: true)
}
}
}
if panEnabled{//if the pan started at a right point continue
menuView.alpha = 1
let xDeslocamento = currenLocation.x - lastPanTouch!.x
lastPanTouch = currenLocation
if comeFromLeft{
if menuView.frame.origin.x + xDeslocamento >= -menuView.frame.width && menuView.frame.origin.x + xDeslocamento <= 0{
menuView.frame.origin = CGPoint(x:menuView.frame.origin.x + xDeslocamento ,y:menuView.frame.origin.y)
}
}
else{
if menuView.frame.origin.x + xDeslocamento >= self.view.frame.width - menuView.frame.width && menuView.frame.origin.x + xDeslocamento <= self.view.frame.width{
menuView.frame.origin = CGPoint(x:menuView.frame.origin.x + xDeslocamento ,y: menuView.frame.origin.y)
}
}
}
}
}
}
I am trying to build an IOS app where the user puts options in to a tableview, then the options appear and the spinning frame spins and stops at a random point.
I have put all the necessary code in ViewWillAppear but for some reason the app doesn't update with the user defaults, only when i close the app and re-open it.
It did actually work at one point but then stopped and i have no idea how to fix it. I am using TTFortuneWheel Pod.
ImageOne
ImageTwo
I will link my GitHub in case anyone wants to have a look at the full code.
https://github.com/jamesnjones/Just.Decide
below is the code for the main screen
import UIKit
import TTFortuneWheel
import AVFoundation
class ViewController: UIViewController, UINavigationControllerDelegate {
#IBOutlet weak var spinningWheel: TTFortuneWheel!
#IBOutlet weak var ResultsLabel: UILabel!
let transition = SlideInTransition()
var slices : [CarnivalWheel] = []
var result: String?
var player: AVAudioPlayer!
var soundIsOn = true
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = self
spinningWheel.initialDrawingOffset = 270.0
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("check")
slices = getSlices()
spinningWheel.slices = slices
spinningWheel.equalSlices = true
spinningWheel.frameStroke.width = 0
spinningWheel.titleRotation = CGFloat.pi
spinningWheel.slices.enumerated().forEach { (pair) in
let slice = pair.element as! CarnivalWheel
let offset = pair.offset
switch offset % 6 {
case 0: slice.style = .blue
case 1: slice.style = .green
case 2: slice.style = .grey
case 3: slice.style = .orange
case 4: slice.style = .purple
default: slice.style = .yellow
}
}
}
private func getSlices() -> [CarnivalWheel] {
PersistenceManager.retrieveSlices { [weak self] result in
guard let self = self else {return}
switch result {
case .success(let slices):
if slices.isEmpty {
print("this is where i will add an alert or sumin")
}else {
self.slices = slices
DispatchQueue.main.async {
self.reloadInputViews()
}
}
case .failure(let error):
print("Edit VC Errror ")
}
}
return slices
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
true
}
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
true
}
#IBAction func rotateButton(_ sender: UIButton) {
if soundIsOn {
playSound(soundName: "spinning")
ResultsLabel.text = ""
let randomNumber = Int.random(in: 0...slices.count - 1)
spinningWheel.startAnimating()
DispatchQueue.main.asyncAfter(deadline: .now() + 0) {
self.spinningWheel.startAnimating(fininshIndex: randomNumber) { (finished) in
self.ResultsLabel.text = self.spinningWheel.slices[randomNumber].title
}
}
} else {
ResultsLabel.text = ""
let randomNumber = Int.random(in: 0...slices.count - 1)
spinningWheel.startAnimating()
DispatchQueue.main.asyncAfter(deadline: .now() + 0) {
self.spinningWheel.startAnimating(fininshIndex: randomNumber) { (finished) in
self.ResultsLabel.text = self.spinningWheel.slices[randomNumber].title
}
}
}
}
Rather than putting it inside of your viewWillAppear put it inside of the viewDidAppear:
override func viewDidAppear(_ animated: Bool) {
<#code#>
}
I have a simple media player and I'm trying to make it change the artwork image as the songs change. With the code I have now it will display the artwork when you hit play but when I hit the next button to skip to the next item it stays the same unless you hit another button.
How can I make the UIImageView image change as the song media item changes?
import UIKit
import MediaPlayer
class ViewController: UIViewController {
#IBOutlet weak var coverImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
createQueue()
}
func showArt(){
coverImageView.image =
myMediaPlayer.nowPlayingItem?.artwork!.image(at: CGSize.init(width: 500, height: 500))
coverImageView.isUserInteractionEnabled = true
}
#IBAction func playButton(_ sender: UIButton) {
togglePlay(on: sender)
showArt()
}
#IBAction func backButton(_ sender: UIButton) {
back()
}
#IBAction func nextButton(_ sender: UIButton) {
skip()
}
}
My other functions are as followed:
import MediaPlayer
let myMediaPlayer = MPMusicPlayerApplicationController.systemMusicPlayer
let playDrake = MPMediaPropertyPredicate(value: "Drake", forProperty: MPMediaItemPropertyArtist, comparisonType: MPMediaPredicateComparison.equalTo)
let myFilterSet: Set<MPMediaPropertyPredicate> = [playDrake]
func createQueue() {
let drakeQuery = MPMediaQuery(filterPredicates: myFilterSet)
myMediaPlayer.setQueue(with: drakeQuery)
}
func skip() {
myMediaPlayer.skipToNextItem()
}
func back() {
if myMediaPlayer.currentPlaybackTime > 0.05 {
myMediaPlayer.skipToPreviousItem()
} else if myMediaPlayer.currentPlaybackTime < 0.05 {
myMediaPlayer.skipToBeginning()
} else {
//do nothing
}
}
func togglePlay(on: UIButton) {
if myMediaPlayer.playbackState.rawValue == 2 || myMediaPlayer.playbackState.rawValue == 0 {
on.setTitle("Pause", for: UIControlState.normal)
myMediaPlayer.play()
} else if myMediaPlayer.playbackState.rawValue == 1{
on.setTitle("Play", for: UIControlState.normal)
myMediaPlayer.pause()
} else {
// do nothing
}
}
Try loading the image asynchronously
DispatchQueue.global(qos: .background).async {
myMediaPlayer.nowPlayingItem?.artwork!.image(at: CGSize.init(width: 500, height: 500))
}
UIViewController needs to hide keyboard inside viewWillDisappear or viewDidDisappear methods. UIViewController stays in memory after disappearing and can be presented again. On first appearance UISearchBar is not firstResponder and keyboard is hidden. But if I pop UIViewController with keyboard shown and then push it again - keyboard is not hidden, however I call:
override func viewDidLoad() {
super.viewDidLoad()
instrumentsTableView.register(UINib(nibName: kDealsFilterInstrumentTableViewCellNib, bundle: nil), forCellReuseIdentifier: kDealsFilterInstrumentTableViewCellReusableId)
instrumentsTableView.dataSource = self
instrumentsTableView.delegate = self
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if presenter.numberOfInstruments != 0 {
instrumentsTableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false)
}
KeyboardManager.shared.unsubscribe()
instrumentsSearchBar.text = ""
presenter.findInstruments(with: "") //just sets settings to default/ reloads data
instrumentsSearchBar.endEditing(true)
instrumentsSearchBar.resignFirstResponder()
view.endEditing(true)
view.resignFirstResponder()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
KeyboardManager.shared.subscribe(self)
}
KeyboardManager - sends notification if keyboard's state has changed, if relevant:
final class KeyboardManager {
private init() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: Notification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: Notification.Name.UIKeyboardWillHide, object: nil)
}
static let shared = KeyboardManager()
#objc private func keyboardWillShow(_ notification: Notification) {
if let keyboardSize = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let height = keyboardSize.cgRectValue.height
keyboardHeight = height
keyboardState = .shown
}
}
#objc private func keyboardWillHide(_ notification: Notification) {
keyboardHeight = 0
keyboardState = .hidden
}
private weak var subscriber: KeyboardManagerDelegate?
func subscribe(_ delegate: KeyboardManagerDelegate) {
subscriber = delegate
}
func unsubscribe() {
subscriber = nil
}
private var keyboardHeight: CGFloat = 0
private var keyboardState: KeyboardState = .hidden {
didSet {
if keyboardState != oldValue {
subscriber?.keyboardDidChange(state: keyboardState, height: keyboardHeight)
}
}
}
}
enum KeyboardState {
case shown
case hidden
}
protocol KeyboardManagerDelegate: class {
func keyboardDidChange(state: KeyboardState, height: CGFloat)
}
I've tried to use this code inside viewWillAppear and viewWillDisappear - but UISearchBar is still firstResponder. If I pop with keyboard being hidden - it stays hidden. What might be the problem?
Screencast:
Sample project with the same issue on bitbucket
For keyboard issue this will work fine,
self.view.endEditing(true)
Write this in viewWillDisappear or viewDidDisappear
I've tried your code: Sample project with the same issue on bitbucket and its working as expected and fine.
Here is that code.
class ViewController: UIViewController {
#IBAction func btnShowSearch(button: UIButton) {
if let search = self.storyboard?.instantiateViewController(withIdentifier: "SeachBarViewController") {
self.navigationController?.pushViewController(search, animated: true)
}
}
}
// SeachBarViewController
class SeachBarViewController: UIViewController {
#IBOutlet var searchBar: UISearchBar!
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
attemptToHidKeyboard()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
attemptToHidKeyboard()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
attemptToHidKeyboard()
}
override func didMove(toParentViewController parent: UIViewController?) {
if parent == nil {
attemptToHidKeyboard()
}
}
override func willMove(toParentViewController parent: UIViewController?) {
if parent == nil {
attemptToHidKeyboard()
}
}
private func attemptToHidKeyboard() {
self.searchBar.resignFirstResponder()
self.searchBar.endEditing(true)
self.view.resignFirstResponder()
self.view.endEditing(true)
}
}
Here is result: