I wanted to blur the background when the touch id is asked and once the authorization is successfull, the viewcontroller needs to be visible.But this is not happening.The viewcontroller is still blurred even if authorization is successfull.Can anyone help me on how to solve this?
import UIKit
import LocalAuthentication
class TabBarViewController: UITabBarController {
#IBOutlet weak var noteTabBar: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
self.authenticateUser()
self.tabBar.hidden = false
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(false, forKey: "sendModeToggle")
userDefaults.setObject("Avenir-Medium", forKey: "font")
userDefaults.setObject(13, forKey:"fontSize")
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// 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.
}
*/
// MARK: Touch ID Authentication
func authenticateUser()
{
let context = LAContext()
var error: NSError?
let reasonString = "Authentication is needed to access your app! :)"
let blurEffect = UIBlurEffect(style: .Light)
let blurVisualEffectView = UIVisualEffectView(effect: blurEffect)
blurVisualEffectView.frame = view.bounds
self.view.addSubview(blurVisualEffectView)
if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error)
{
context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success, policyError) -> Void in
if success
{
print("Authentication successful! :) ")
blurVisualEffectView.removeFromSuperview()
}
else
{
switch policyError!.code
{
case LAError.SystemCancel.rawValue:
print("Authentication was cancelled by the system.")
/*case LAError.UserCancel.rawValue:
print("Authentication was cancelled by the user.")
*/
case LAError.UserFallback.rawValue:
print("User selected to enter password.")
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.showPasswordAlert()
blurVisualEffectView.removeFromSuperview()
})
default:
print("Authentication failed! :(")
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.showPasswordAlert()
blurVisualEffectView.removeFromSuperview()
})
}
}
})
}
else
{
print(error?.localizedDescription)
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.showPasswordAlert()
})
}
}
}
Since you are removing view in closure, you probably not in main thread. Try to dispatch removing code to main thread:
if success {
print("Authentication successful! :) ")
dispatch_async(dispatch_get_main_queue()) {
blurVisualEffectView.removeFromSuperview()
}
}
Related
I'm assigning a non-nil value of type Data to a non-optional property, which then assigns it to an optional property, which finally instantiates an image with said data. When the optional passes through an if-let clause, it's block executes, throwing an error:
Fatal error: Unexpectedly found nil while unwrapping an Optional value
By no means should stillImageData unwrap nil.
import UIKit
import AVFoundation
import Photos
class ViewController: UIViewController, AVCapturePhotoCaptureDelegate {
var photoOutput: AVCapturePhotoOutput!
var stillImageData: Data!
#IBAction func handleTouch(_ sender: Any) {
let photoSettings = AVCapturePhotoSettings(format: nil)
photoSettings.isAutoStillImageStabilizationEnabled = true
if photoOutput.supportedFlashModes.contains(AVCaptureDevice.FlashMode.auto) {
photoSettings.flashMode = .auto
}
photoOutput.capturePhoto(with: photoSettings, delegate: self)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: // The user has previously granted access to the camera.
self.setupCaptureSession()
case .notDetermined: // The user has not yet been asked for camera access.
AVCaptureDevice.requestAccess(for: .video) { granted in
if granted {
self.setupCaptureSession()
}
}
case .denied: // The user has previously denied access.
return
case .restricted: // The user can't grant access due to restrictions.
return
}
PHPhotoLibrary.requestAuthorization { status in
guard status == .authorized else { return }
// Use PHPhotoLibrary.shared().performChanges(...) to add assets.
}
}
func setupCaptureSession() {
let captureSession = AVCaptureSession()
// Connect inputs and outputs to the session
captureSession.beginConfiguration()
let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera,
for: .video, position: .unspecified)
guard
let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice!),
captureSession.canAddInput(videoDeviceInput)
else { return }
captureSession.addInput(videoDeviceInput)
photoOutput = AVCapturePhotoOutput()
guard captureSession.canAddOutput(photoOutput) else { return }
captureSession.sessionPreset = .photo
captureSession.addOutput(photoOutput)
captureSession.commitConfiguration()
// Display a camera preview
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = view.bounds
previewLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(previewLayer)
// Run the capture session
captureSession.startRunning()
}
// MARK: - Photo capture
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
// guard error != nil else { print("Error capturing photo: \(error!)"); return }
self.stillImageData = photo.fileDataRepresentation()
performSegue(withIdentifier: "showDetail", sender: self)
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
let controller = (segue.destination as! UINavigationController).topViewController as! RootViewController
controller.detailItem = stillImageData
}
}
}
import UIKit
import Photos
class RootViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
func configureView() {
if let stillImageData = detailItem {
imageView.image = UIImage(data: stillImageData)
}
}
var detailItem: Data? {
didSet {
configureView()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func dismissViewController(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
#IBAction func savePhotoToPhotosLibrary(_ sender: Any) {
PHPhotoLibrary.requestAuthorization { status in
guard status == .authorized else { return }
PHPhotoLibrary.shared().performChanges({
// Add the captured photo's file data as the main resource for the Photos asset.
let creationRequest = PHAssetCreationRequest.forAsset()
creationRequest.addResource(with: .photo, data: self.detailItem!, options: nil)
}, completionHandler: { success, error in
if !success { NSLog("error creating asset: \(error!)") }
})
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
If anybody could lend a hand, it'd be greatly appreciated.
1) Why, if stillImageData and detailItem are assigned non-nil values, are they nil, and 2) why is the if-let clause executing its block?
stillImageData and detailItem are not nil, but imageView is nil.
In prepare(for at the moment you execute controller.detailItem = stillImageData the view of the destination controller is not loaded yet, therefore all outlets are not connected. When the outlet is accessed in configureView() the crash occurs.
In this case call configureView() in viewDidLoad
var detailItem: Data?
override func viewDidLoad() {
super.viewDidLoad()
configureView()
}
On the other hand if detailItem is going to be updated multiple times check the outlet
var detailItem: Data? {
didSet {
if imageView != nil { configureView() }
}
}
override func viewDidLoad() {
super.viewDidLoad()
configureView()
}
I hope that this question is not duplicate because I couldn't find any thing similar.
I have two view controllers:
NEWPhoneAuthViewController
NEWVerifyCodeViewController
NEWPhoneAuthViewController Code:
import UIKit
import Firebase
class NEWPhoneAuthViewController: UIViewController {
#IBOutlet weak var phoneTxtField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func submitPressed(_ sender: Any) {
let phoneNumber = phoneTxtField.text!
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil, completion: { (verificationID, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
guard let verificationID = verificationID else { return }
print("Verification ID")
print(verificationID)
let verifyScene = NEWVerifyCodeViewController()
verifyScene.verificationID = verificationID
self.performSegue(withIdentifier: "toCodefromPhoneAuth", sender: nil)
//self.navigationController?.pushViewController(verifyScene, animated: true)
})
}
}
and my NEWVerifyCodeViewController code is:
import UIKit
import Firebase
class NEWVerifyCodeViewController: UIViewController {
#IBOutlet weak var codeTxtField: UITextField!
var verificationID:String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func verifyPressed(_ sender: Any) {
if let verificationCode = codeTxtField.text {
let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID!, verificationCode: verificationCode)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
debugPrint(error.localizedDescription)
}else {
debugPrint("Verified successfully")
print("Navigating to SignUp")
//self.performSegue(withIdentifier: "toSignUpfromCode", sender: nil)
//let newSignUp = NEWSignUp()
//self.navigationController?.pushViewController(newSignUp, animated: true)
//self.performSegue(withIdentifier: "toSignUpFromPhone", sender: nil)
//Once you have verified your phone number kill the firebase session.
//try? Auth.auth().signOut()
}
}
}
}
}
Now the problem is: when I tap on verify button in NEWVerifyCodeViewController the App crashes,
NOTES:
I printed Verification ID and its not NULL.
I printed code that the user receives and its not NULL.
So I'm not sure why that happens, and my console doesn't show any error after the tap except these:
So I made a small tweak that made my project work.
I changed this part in NEWPhoneAuthViewController :
let verifyScene = NEWVerifyCodeViewController()
verifyScene.verificationID = verificationID
to:
first created a global variable called: gVerificationID and set it to:
gVerificationID = verificationID
Thats it, not sure if thats the best practice and not sure why the first code didn't work but this is how I fixed it.
i am using the AVFoundation for the first time, and i have gotten my script working kinda...
I am making a ticket app, witch are scanning a QR code on the tickets and checks the database if its used. (I have hidden my API logins). But as soon as i scans the qr code, my code runs, i get a ticket Valid plottet in the console, but the the viewcontroller dissmisses, and goes back to my login page.
I am using this code, for my login page to show the viewcontroller with the QR code.
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "scanner") as UIViewController
self.present(viewController, animated: false, completion: nil)
And the the viewcontroller with the QR Scanner.
//
// scanner.swift
// GB Billet Scanner
//
// Created by Benjamin Eibye on 26/12/2017.
// Copyright © 2017 GymBilletter.dk. All rights reserved.
//
import UIKit
import AVFoundation
import Alamofire
class scanner: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
#IBOutlet weak var videoPreview: UIView!
#IBOutlet weak var navnLabel: UILabel!
let avCaptureSession = AVCaptureSession()
var returnValue: String = String()
enum error: Error {
case noCameraAvailable
case videoInputInitFail
}
override func viewDidLoad() {
super.viewDidLoad()
// Creating session
do {
try scanQRCode()
} catch {
print("Failed to scan the QR/BarCode")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
avCaptureSession.stopRunning()
if let metadataObject = metadataObjects.first {
let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject;
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
//print(readableObject.stringValue!);
navnLabel.text = "Indlæser billet #\(readableObject.stringValue!)"
let urlEnc = "https://domain?token=\(String(describing: UserDefaults.standard.object(forKey: "token")!))&ticket=\(readableObject.stringValue!)"
Alamofire.request(urlEnc).responseJSON { response in
//print(urlEnc)
//debugPrint(response)
//print(response.result)
if let result = response.result.value {
let JSON = result as! NSDictionary
if JSON["error"] as? Int == 5002 {
print("User not Authendicated")
print(urlEnc)
self.navnLabel.text = "Telefonen er ikke logget ind"
self.avCaptureSession.startRunning()
} else if JSON["error"] as? Int == 5003 {
print("Ticket not Found")
self.navnLabel.text = "Billetten blev ikke fundet"
self.avCaptureSession.startRunning()
} else {
// Billetten eksistere
print("Billet fundet")
if JSON["active"] as! String == "1" {
print("ticket Valid")
self.avCaptureSession.startRunning()
} else {
print("Billetten er blevet brugt")
self.navnLabel.text = "Billetten er blevet brugt \(String(describing: JSON["used_date"]))"
}
}
}
}
}
dismiss(animated: true)
}
func scanQRCode() throws {
guard let avCaptureDevice = AVCaptureDevice.default(for: AVMediaType.video) else {
print("no camera.")
throw error.noCameraAvailable
}
guard let avCaptureInput = try? AVCaptureDeviceInput(device: avCaptureDevice) else {
print("Faild to init camera.")
throw error.videoInputInitFail
}
let avCaptureMetadataOutput = AVCaptureMetadataOutput()
avCaptureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
avCaptureSession.addInput(avCaptureInput)
avCaptureSession.addOutput(avCaptureMetadataOutput)
avCaptureMetadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
let avCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: avCaptureSession)
avCaptureVideoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
avCaptureVideoPreviewLayer.frame = videoPreview.bounds
self.videoPreview.layer.addSublayer(avCaptureVideoPreviewLayer)
avCaptureSession.startRunning()
}
#IBAction func anuller(_ sender: Any) {
navnLabel.text = "Scan billet."
avCaptureSession.startRunning()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
The dismiss(animated: true) at the end of your metadataOutput(...) function is being called regardless of what returned.
I am trying to upload an image in a UIImageView to Dropbox using SwiftyDropbox and Swift 3.0. When I press the button nothing happens after the first print statement. What am I doing wrong.
import UIKit
import SwiftyDropbox
class ViewController: UIViewController {
let client = DropboxClientsManager.authorizedClient
#IBOutlet weak var myPhotoView: UIImageView!
#IBAction func logInAction(_ sender: Any) {
myButtonPressed()
}
#IBAction func sendPhotoAction(_ sender: Any) {
print("Button Pressed")
let fileData = UIImageJPEGRepresentation(myPhotoView.image!, 1.0)
//let compressedJPGImage = UIImage(data: fileData!)
let path = "/"
client?.files.upload(path: path, mode: .overwrite, autorename: true, clientModified: nil, mute: false, input: fileData!).response{ response, error in
if let _ = response { // to enable use: if let metadata = response {
print("OK")
} else {
print("Error at end")
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func myButtonPressed(){
DropboxClientsManager.authorizeFromController(UIApplication.shared, controller: self, openURL: {(url:URL) -> Void in UIApplication.shared.openURL(url)
})
}
}
if your client is nil, then you aren't logged in. Try logging in and doing it again. Otherwise it should work fine.
https://dropbox.github.io/SwiftyDropbox/api-docs/latest/index.html#configure-your-project
Within my main.storyboard I have a UIImage view which is just a generic Facebook Login Button. However, I am confused because using these generic steps
override func viewDidLoad(){
{
super.viewDidLoad()
var imageView = <# imageView #>
let tapGestureRecognizer = UITapGestureRecognizer(target:self, action:Selector("imageTapped:"))
imageView.userInteractionEnabled = true
imageView.addGestureRecognizer(tapGestureRecognizer)
}
func imageTapped(img: AnyObject)
{
// The Action
}
I am a little lost as to what The Action would be in this scenario as I need to link everything through the Facebook SDK.
In your imageTapped
func imageTapped() {
let manager = FBSDKLoginManager()
manager.logInWithReadPermissions(["public_profile"], fromViewController: self, handler: { result, error in
if error != nil {
print("process error")
} else if result.isCancelled {
print("cancelled log in")
} else {
print("logged in")
}
})
}