- 投稿日:2020-06-28T14:59:36+09:00
スクショ・画面録画されたことを通知する方法
スクリーンショットや画面録画がされたことを通知するには,その
ViewController
の中でoverride func viewWillAppear(_ animated: Bool) { NotificationCenter.default.addObserver(self, selector: #selector(didTakeScreenshot), name: UIApplication.userDidTakeScreenshotNotification, object: nil) NotificationCenter.default.addObserver( self, selector: #selector(didCapturedScreen), name: UIScreen.capturedDidChangeNotification, object: nil ) }
ViewDidLoad()
でも構いません。
didTakeScreenshot
やdidCapturedScreen
自分で決める関数であるので、例えば以下のようにします。@objc func didTakeScreenshot() { print("スクリーンショット") }必要に応じて通知を削除します。
override func viewWillDisappear(_ animated: Bool) { super.viewWillAppear(animated) NotificationCenter.default.removeObserver(self,name: UIApplication.userDidTakeScreenshotNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIScreen.capturedDidChangeNotification, object: nil) }
- 投稿日:2020-06-28T14:49:21+09:00
NotificationCenter.default.removeObserverの大切さを痛感した話
起きたこと
TableViewControllerとNavigationControllerでできているチャットアプリを作成していたところ、トーク画面でスクショすると自動送信されるメッセージが他のトーク画面でスクショしても送信されるバグが発見された。
原因と処理
スクショの監視するObserVerを
ViewDidLoad()
の中に書いていたのですが、NotificationCenter.default.addObserver(self, selector: #selector(didTakeScreenshot), name: UIApplication.userDidTakeScreenshotNotification, object: nil)
NavigationController
画面遷移をしたときに通知を外していないことが原因でした。NotificationCenter.default.removeObserver(self,name: UIApplication.userDidTakeScreenshotNotification, object: nil)を
viewWillDisappear
の中で書くことで期待した処理をすることが出来ました。
- 投稿日:2020-06-28T14:28:29+09:00
複数のTextFieldにそれぞれ文字数の制限をつける
できること
- TextFieldの文字数を取得する
- 複数のTextFieldにそれぞれ異なる条件(①, ②)をつける
- ①,②を満たす時のみボタンを活性にする
ex) TextFieldアには四文字以上、TextFieldイは5文字以上10文字未満の時のみログインボタンが押せるようにする
TextFieldの文字数を取得する
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let textLength = (textField.text! as NSString).replacingCharacters(in: range, with: string).count print("テキストが入力された\(textLength)")//文字数を表示 return true }TextFieldに文字が入力されるたびに呼び出されます。
複数のTextFieldを扱う
複数のTextFieldを扱いたい時には、TextFieldにtagを設定します。
tagを設定することで、上述した
func textField()
の中でTextFieldを一意に定めることができます。//さっきの続き func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let textLength = (textField.text! as NSString).replacingCharacters(in: range, with: string).count switch textField.tag { case 0: print("TextFieldアが押された\(textLength)") case 1: print("TextFieldイが押された\(textLength)") default: break } }TextFieldにそれぞれ異なる条件をつける
TextFieldアには四文字以上、TextFieldイは5文字以上10文字未満の時のみログインボタン(loginButton)が押せるようにするという実装をすることにします。
この時、二つの条件がそれぞれ真である時のみボタンの活性を決める
isEnabled
が真でなければなりません。この時点で真理値が複雑に絡んでいることがわかるので、関数を作ることを試みます。private func checkButton() { if TextFieldABool && TextFieldBBool { loginButton.isEnabled = true loginButton.setTitleColor(UIColor.black, for: .normal) } else { loginButton.isEnabled = false loginButton.setTitleColor(UIColor.gray, for: .normal) } }//二つの真理値がともに真である時のみボタンを活性にして色を白、そうでない時ボタンを非活性にして色を灰色にする。この関数が呼ばれるたび、二つの真理値の状態に基づいた処理が行われます。
//さっきの続き func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let textLength = (textField.text! as NSString).replacingCharacters(in: range, with: string).count switch textField.tag { case 0: print("TextFieldアが押された\(textLength)") if textLength >= 4 { TextFieldABool = true } else { TextFieldABool = false } case 1: print("TextFieldイが押された\(textLength)") if (textLength >= 5) && (textLength < 10) { TextFieldABool = true } else { TextFieldABool = false } default: break } }これで複数のTextFieldにそれぞれ異なる条件を課したときの処理を記述することが出来ました。
ソースコード
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let textLength = (textField.text! as NSString).replacingCharacters(in: range, with: string).count switch textField.tag { case 0: print("TextFieldアが押された\(textLength)") if textLength >= 4 { TextFieldABool = true } else { TextFieldABool = false } case 1: print("TextFieldイが押された\(textLength)") if (textLength >= 5) && (textLength < 10) { TextFieldABool = true } else { TextFieldABool = false } default: break } } private func checkButton() { if TextFieldABool && TextFieldBBool { loginButton.isEnabled = true loginButton.setTitleColor(UIColor.black, for: .normal) } else { loginButton.isEnabled = false loginButton.setTitleColor(UIColor.gray, for: .normal) } }//二つの真理値がともに真である時のみボタンを活性にして色を白、そうでない時ボタンを非活性にして色を灰色にする。