when click button I added face id recognition and if true, need to navigate another page. But not working. application crashed. After few minutes navigate to the next page and back button not working.
#IBAction func myProfile(_ sender: Any) {
// self.performSegue(withIdentifier: "MyProfile", sender: nil)
let context:LAContext = LAContext()
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil){
context.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Need to access with your finger print", reply: {(wasCorrect, error) in
if wasCorrect{
print("correct")
self.performSegue(withIdentifier: "MyProfile", sender: nil)
}else{
print("incorrect")
}
})
}else{
print("finger print doesn't support touch id")
}
}
Error message is:
[Animation] +[UIView setAnimationsEnabled:] being called from a
background thread. Performing any operation from a background thread
on UIView or a subclass is not supported and may result in unexpected
and insidious behavior.
Callback of evaluatePolicy runs in a background queue so do
DisptachQueue.main.async {
self.performSegue(withIdentifier: "MyProfile", sender: nil)
}
Related
I am trying to jump to a second view controller after I have authorized a user's TouchID. I am able to validate that the TouchID is working but I am having an issue of jumping to a second viewController.
I have created a SecondViewController and a Segue with the Identifier "dispenseScreen". However, whenever I try to jump to the second screen my program crashes.
#IBAction func touchID(_ sender: Any)
{
let context:LAContext = LAContext()
//Removes Enter Password during failed TouchID
context.localizedFallbackTitle = ""
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
{
context.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: "We require your TouchID", reply: { (wasCorrect, error) in
self.isBiometryReady()
if wasCorrect {
self.performSegue(withIdentifier: "dispenseScreen", sender: self)
print("Correct")
}
else {
print("Incorrect")
}
})
} else {
//Enter phone password if too many login attempts
//Add message alerting user that TouchID is not enabled
}
}
There are no semantic errors in my code but I am receiving a threading error when I try to go to the second view controller.
You're trying to do the segue in the callback from evaluatePolicy. For anything involving UI, you need to make sure you're on the main thread: (wasCorrect, error) in DispatchQueue.main.async { ... }
I am a beginner in iOS development. I have a problem when I move the screen. I clicked the button on the story board, then drag it with the right mouse, and then clicked on the view controller that I wanted to move. However, the navigation back button is not visible when the button is pressed. What's the reason?
Main.storyboard
Cell phone
Move when the lower right yellow button is pressed.
Move when the lower right yellow button is pressed. My right button is not 'Bar Button Item' but just a button. The reason is that 'Bar Button' is not what I want.
************************ Edited Start ************************************
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goAgreeScreen" {
performSegue(withIdentifier: "goAgreeScreen", sender: self) // get Error
} else if segue.identifier == "otherScreen" {
}
}
Error is Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee5677ff8)
************************ Edited end ************************************
*******************Edited Two *******************************************
Move Main Screen Button
#IBAction func Onclick(_ sender: Any) {
AVCaptureDevice.requestAccess(for: AVMediaType.video) { response in
if response {
print(response , ": granted")
let center = UNUserNotificationCenter.current()
// Request permission to display alerts and play sounds.
center.requestAuthorization(options: [.alert, .sound])
{ (granted, error) in
if granted {
print(granted, ": is granted")
DispatchQueue.main.async { self.moveScreen()}
} else {
print(granted, ": is not granted")
DispatchQueue.main.async { self.moveScreen()}
}
}
} else {
print(response , ": not granted")
let center = UNUserNotificationCenter.current()
// Request permission to display alerts and play sounds.
center.requestAuthorization(options: [.alert, .sound])
{ (granted, error) in
if error == nil {
if granted == true {
print(granted, ": is granted")
DispatchQueue.main.async { self.moveScreen()}
}
else {
print(granted, ": is not granted")
DispatchQueue.main.async { self.moveScreen()}
}
} else {
print(error as Any)
}
}
}
}
}
*******************Edited Two end *****************************************
Are you presenting the ViewController programmatically? It seems that the navigation bar is not shown.
Maybe you have to present if in a IBAction. Create it connecting a button. Set the identifier to the segue (on the Storyboard) and call it with:
performSegue(withIdentifier: "myIdentifier", sender: self)
I think that you don't need any code for your situation. Here is a Quick-Start example from Apple which is very clear.
https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/ImplementNavigation.html#//apple_ref/doc/uid/TP40015214-CH16-SW1
I have written the following code where after the user logs in with touch id or face id it should go to the next view controller.
#IBAction func logInButton(_ sender: Any) {
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
context.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Account") { (correct, error) in
if correct {
print("Logged In....")
self.performSegue(withIdentifier: "SecondView", sender: self)
} else {
print("Not Logged in....")
}
}
} else {
print("No Support for Biometrics")
}
}
I'm able to print the Logged in and Not Logged in message. But after user gets authenticated that is after Logged In message is printed I get the following message in console for "performSegue"
019-03-21 19:37:18.473350-0400 Login v1[7596:2446134] [Animation] +[UIView setAnimationsEnabled:] being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior. trace=(
0 UIKitCore 0x00000001d6ac7710 + 136
1 libdispatch.dylib 0x000000010159cdc8 _dispatch_client_callout + 16
2 libdispatch.dylib 0x000000010159ee28 _dispatch_once_callout + 84
and much more. I have connected my second view controller and made is display as "Present Modally". not sure where I am going wrong.
As the message states, any operations that affect the UI must be performed on the main thread.
The callback from context.evaluatePolicy is being invoked on some other thread.
All you need to do is dispatch the performSegue on thee main thread:
#IBAction func logInButton(_ sender: Any) {
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
context.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Account") { (correct, error) in
if correct {
print("Logged In....")
DispatchQueue.main.async {
self.performSegue(withIdentifier: "SecondView", sender: self)
}
} else {
print("Not Logged in....")
}
}
} else {
print("No Support for Biometrics")
}
}
This happens when i am saving a video, I am also trying to segue to another view controller. I am not sure why the app crashes here
func finalExportCompletion(_ session: AVAssetExportSession) {
PhotoManager().saveVideoToUserLibrary(fileUrl: session.outputURL!) { (success, error) in
if success {
ProgressHUD.showSuccess("Video Saved", interaction: true)
self.finalVideo = session.outputURL!
//FileManager.default.clearTmpDirectory()
self.clipsCollectionView.reloadData()
} else {
ProgressHUD.show(error?.localizedDescription)
}
self.performSegue(withIdentifier: "toPostVideoViewController", sender: nil)
}
}
Your crash is issued to modifications in UI while your are in background thread, as said your crash log, and #rmaddy in his comment, THREAD 8 is a background thread, your need execute all your UI actions in Thread 1 which is the "Main Thread" you have to modify your code like this
func finalExportCompletion(_ session: AVAssetExportSession) {
PhotoManager().saveVideoToUserLibrary(fileUrl: session.outputURL!) { (success, error) in
DispatchQueue.main.async{
if success {
ProgressHUD.showSuccess("Video Saved", interaction: true)
self.finalVideo = session.outputURL!
//FileManager.default.clearTmpDirectory()
self.clipsCollectionView.reloadData()
} else {
ProgressHUD.show(error?.localizedDescription)
}
//I don't know if you anyway want to go to "toPostVideoViewController" this you need to do it also in main thread
self.performSegue(withIdentifier: "toPostVideoViewController", sender: nil)
}
}
}
I'm using Facebook login in my app and I'm not able to go to next view after login completed.
i.e. TabBarController its shows an above stated error. I am doing custom login from a button. Here is my code of how I am doing login.
#IBAction func fbLoginBtn(sender: AnyObject) {
facebookLogin.logInWithReadPermissions(["email","user_friends","user_posts"],fromViewController: self, handler: { (response:FBSDKLoginManagerLoginResult!, error: NSError!) in
if error != nil {
print(error.localizedDescription)
print("Facebook login failed")
} else {
let accessToken = response.token.tokenString
print(accessToken)
print("Successfully login.\(accessToken)")
self.performSegueWithIdentifier("showMain", sender: self)
}
})
}
After login I'm performing segue to go to next view i.e. TabBarController. If anyone can help please help me. Thank you.