I get an error on the Swift user login screen - swift

I've added screenshots below. I'm delighted to see you. Thank you
user login Screen
Error
override func viewDidLoad() {
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
view.addGestureRecognizer(tap)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func btnGirisYap(_ sender: Any) {
var pass : String!
I assign txtGirisSifre.text as variable "pass"
let arayüzPass = txtGirisSifre.text
var request = URLRequest(url: URL(string: "http://242.253.114.125:7001/WebApplicationo2/login")!)
request.httpMethod = "POST"
let postString = "user=emrekacan"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if error != nil
{
}
else
{
if let urlContent = data
{
do
{
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
if let currencyRate = jsonResult as? NSArray
{
for i in 0..<currencyRate.count
{
if let gelenPass = (currencyRate[i] as? NSDictionary)?["pass"] as? String
{
pass = gelenPass
print(pass)
print(arayüzPass!)
}
}
If the password that is called web service is not empty in this section
if pass != nil {
self.login(pass1: pass , arayüzPass1: arayüzPass!)
}
}
}
catch
{
}
}
}
}
task.resume()
}
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
It gives an error after this section
func login(pass1 : String , arayüzPass1 : String!)
{
"SWRevealViewController" storyboard open
if pass1 == arayüzPass1 {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewController(withIdentifier: "RevealView") as! SWRevealViewController
self.present(resultViewController, animated:true, completion:nil)
}
}
}

Related

AlertController view is not in the window hierarchy

i am a beginner in swift, i was trying to use an UIAlertController but i have got an error and the UiAlertController do not show up and i can see an error in the console that says
2021-06-20 18:16:28.494162+0200 Bicycall[50670:543648] [Presentation] Attempt to present <UIAlertController: 0x7fbaca034e00> on <Bicycall.login: 0x7fbabb01d800> (from <Bicycall.login: 0x7fbabb01d800>) whose view is not in the window hierarchy.
2021-06-20 18:16:28.494339+0200 Bicycall[50670:543648] [Presentation] Attempt to present <UIAlertController: 0x7fbac9862800> on <Bicycall.login: 0x7fbabb01d800> (from <Bicycall.login: 0x7fbabb01d800>) whose view is not in the window hierarchy.
Here what i have tried:
import UIKit
import CoreData
import AVKit
import AVFoundation
import TKSubmitTransition
class login: UIViewController {
#IBOutlet weak var passwordView: UIView!
#IBOutlet weak var emailView: UIView!
var id: Int?
var name: String?
var lastname: String?
var email:String?
var password:String?
var phone:String?
var u = ConnectedUser()
var BR = BaseUrl.baseUrl
var player: AVPlayer?
let videoURL: NSURL = Bundle.main.url(forResource: "Bikers", withExtension: "mp4")! as NSURL
func getTopMostViewController() -> UIViewController? {
var topMostViewController = UIApplication.shared.keyWindow?.rootViewController
while let presentedViewController = topMostViewController?.presentedViewController {
topMostViewController = presentedViewController
}
return topMostViewController
}
func presentTestAlert(_ title: String, _ message: String){
let alert = UIAlertController(title: title , message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"), style: .default, handler: { _ in
NSLog("The \"OK\" alert occured.")
}))
DispatchQueue.main.async {
self.getTopMostViewController()?.present(alert, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.DeleteAllData()
player = AVPlayer(url: videoURL as URL)
player?.actionAtItemEnd = .none
player?.isMuted = true
let playerLayer = AVPlayerLayer(player: player)
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
playerLayer.zPosition = -1
playerLayer.frame = view.frame
view.layer.addSublayer(playerLayer)
player?.play()
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: .main) { [weak self] _ in
self?.player?.seek(to: CMTime.zero)
self?.player?.play()
// Do any additional setup after loading the view.
}
emailView.layer.cornerRadius = 30.0
emailView.layer.borderWidth = 0.5
emailView.layer.borderColor = UIColor.white.cgColor
passwordView.layer.cornerRadius = 30.0
passwordView.layer.borderWidth = 0.5
passwordView.layer.borderColor = UIColor.white.cgColor
}
//widgets
#IBOutlet weak var txtEmail: UITextField!
#IBOutlet weak var txtPassword: UITextField!
//Actions
#IBAction func btnLogin(_ sender: Any){
//get
/*
guard let url = URL(string: "http://localhost:3000/bikes") else {
return
}
let session = URLSession.shared
session.dataTask(with: url) { ( data , response ,error) in
if let response = response {
print(response)
}
if let data = data {
print(data)
do
{
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
}catch{
print(error)
}
}
}.resume()
*/
//post
guard let url = URL(string: BR+"/login") else {
return
}
let bodyparameters = ["email": txtEmail.text, "password": txtPassword.text]
if (txtEmail.text!.isEmpty || txtPassword.text!.isEmpty ){
self.presentTestAlert("Wrong credentials","Email and Password must not be empty")
}else{
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: bodyparameters, options: []) else{
return
}
request.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: request) { (data,response,error) in
let status = (response as! HTTPURLResponse).statusCode
//print(response)
print(status)
if let response = response {
let status = (response as! HTTPURLResponse).statusCode
//print(response)
print(status)
}
if((status) == 200){
self.presentTestAlert("Connection Success", " internet connection")
print(" Connection Successssssssssssssss")
if let data = data {
do {
//let json = try JSONSerialization.jsonObject(with: data, options: [])
// print(json);
print(data)
let user = try JSONDecoder().decode(User.self, from: data)
DispatchQueue.main.async {
self.id = user.user_id
self.name = user.name
self.lastname = user.lastname
self.email = user.email
self.password = user.password
self.phone = user.phone
print(self.id!)
print(self.email!)
if(user.user_id != 0){
self.saveUser()
self.DisplayConnectedUser()
self.performSegue(withIdentifier: "HomeSegue", sender: "nil")
}else{
self.presentTestAlert("Login Failed","Wrong credentials")
}
}
}catch{
print(error)
}
}
}else {
self.presentTestAlert("No Connection", "No internet connection")
print(" Connection Nooooooooooooooooooooooooo")
}
}.resume()
}
}
func DeleteAllData(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let DelAllReqVar = NSBatchDeleteRequest(fetchRequest: NSFetchRequest<NSFetchRequestResult>(entityName: "Users"))
do {
try managedContext.execute(DelAllReqVar)
}
catch {
print(error)
}
}
func saveUser() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
//represente l'ORM
let persistentContainer = appDelegate.persistentContainer
let managedContext = persistentContainer.viewContext
let entityDescription = NSEntityDescription.entity(forEntityName: "Users" , in: managedContext)
let object = NSManagedObject(entity: entityDescription! , insertInto: managedContext )
object.setValue(id! , forKey: "user_id" )
object.setValue(email! , forKey: "email" )
object.setValue(password! , forKey: "password" )
object.setValue(name! , forKey: "name" )
object.setValue(lastname! , forKey: "lastname" )
object.setValue(phone! , forKey: "phone" )
do {
try managedContext.save()
print("INSERT SUCCESSFULLY")
print(id!)
}
catch {
print("INSERT ERROR")
}
}
#IBAction func btnSignup(_ sender: Any) {
performSegue(withIdentifier: "signupSegue", sender: "nil")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
}
func DisplayConnectedUser() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
//represente l'ORM
let persistentContainer = appDelegate.persistentContainer
let managedContext = persistentContainer.viewContext //retourne NSManagedObject toujours
//la requete retourne un NSManagedObject
let request = NSFetchRequest<NSManagedObject>(entityName : "Users")
//execution de la requete
do {
let result = try managedContext.fetch(request)
for item in result {
print(item.value(forKey: "user_id") as! Int )
print(item.value(forKey: "email") as! String)
self.u.user_id = (item.value(forKey: "user_id") as! Int)
self.u.email = (item.value(forKey: "email") as! String)
self.u.password = (item.value(forKey: "password") as! String)
self.u.name = (item.value(forKey: "name") as! String)
self.u.lastname = (item.value(forKey: "lastname") as! String)
self.u.phone = (item.value(forKey: "phone") as! String)
print(self.u.user_id!)
print(self.u.email!)
print(self.u.password!)
print(self.u.name!)
print(self.u.lastname!)
print(self.u.phone!)
}
}
catch {
print("NO DATA FOUND , Error")
}
}
}
What is annoying me is that none of my alerts worked! i read some other answer in stackoverflow but the solutions did not work for me
What i am trying is to make my alerts working good
Any help will be so appreciated
It seems you want to present the alert over the video player (playerLayer) but you are calling your alert over the layer behind the playerLayer, it will give you the error that you're getting.
With reference to Swift 4 Attempt to present ViewController whose view is not in the window hierarchy
Add this function in your code
func getTopMostViewController() -> UIViewController? {
var topMostViewController = UIApplication.shared.keyWindow?.rootViewController
while let presentedViewController = topMostViewController?.presentedViewController {
topMostViewController = presentedViewController
}
return topMostViewController
}
And replace (Line 33)
self.present(alert, animated: true, completion: nil)
with
DispatchQueue.main.async {
getTopMostViewController()?.present(alert, animated: true, completion: nil)
}

How to use a stored url from Firebase Database as an image in an UIImageView

I'm new to coding and trying to build an iOS App. I am storing images uploaded by users into my firebase storage and then saving the URL as a string ("https//.....). I am able to get a snapshot to show up in project terminal after I use print(snapshot). It prints, snap (profileImageUrl) https://firebasestorage.... How do I use this snapshot to get the ImageView to show the profile picture most recently saved?
import UIKit
import Firebase
import SDWebImage
class EditProfileViewController: UIViewController {
#IBOutlet weak var ProfileImage: UIImageView!
var selectedImage: UIImage?
var ref:DatabaseReference?
var databaseHandle:DatabaseHandle = 0
var postProfileImage = [String]()
let dbref = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
override func viewDidLoad() {
super.viewDidLoad()
self.ref?.child("users").child(Auth.auth().currentUser!.uid).child("profileImageUrl").observe(.value, with: { (snapshot) in
print(snapshot)
})
ProfileImage.layer.borderWidth = 3.0
ProfileImage.layer.masksToBounds = false
ProfileImage.layer.borderColor = UIColor.white.cgColor
ProfileImage.layer.cornerRadius = ProfileImage.frame.size.width / 2
ProfileImage.clipsToBounds = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(EditProfileViewController.handleSelectProfileImageView))
ProfileImage.addGestureRecognizer(tapGesture)
ProfileImage.isUserInteractionEnabled = true
}
#objc func handleSelectProfileImageView() {
let pickerController = UIImagePickerController()
pickerController.delegate = self
present(pickerController, animated: true, completion: nil)
}
#IBAction func Cancel(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
let user = Auth.auth().currentUser
let fileData = NSData()
#IBAction func DoneButton(_ sender: UIBarButtonItem) {
guard let imageSelected = self.ProfileImage.image else {
print ("Avatar is nil")
return
}
var dict: Dictionary<String, Any> = [
"profileImageUrl": "",
]
guard let imageData = imageSelected.jpegData(compressionQuality: 0.4) else {
return
}
let storageRef = Storage.storage().reference(forURL: "(I have my storage url here")
let imageName = NSUUID().uuidString
let storageProfileRef = storageRef.child("Profile_Images").child(Auth.auth().currentUser!.uid).child("\(imageName).png")
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
storageProfileRef.putData(imageData, metadata: metadata, completion:
{ (StorageMetadata, error) in
if (error != nil) {
return
}
storageProfileRef.downloadURL { (url, error) in
if let metaImageUrl = url?.absoluteString {
dict["profileImageUrl"] = metaImageUrl
Database.database().reference().child("users").child(Auth.auth().currentUser!.uid).updateChildValues(dict, withCompletionBlock: {
(error, ref) in
if error == nil {
print("Done")
}
}
)
}
}
})
dismiss(animated: true, completion: nil)
}
}
extension EditProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
//print("did Finish Picking Media")
if let image = info[UIImagePickerController.InfoKey(rawValue: "UIImagePickerControllerOriginalImage")] as? UIImage{
selectedImage = image
ProfileImage.image = image
}
dismiss(animated: true, completion: nil)
}
}
I could really use some help!
You can add an extension to UIImageView as below:
extension UIImageView {
func load(url: URL, onLoadCompletion: ((_ isImageLoaded: Bool) -> Void)? = nil) {
self.image = nil
DispatchQueue.global().async { [weak self] in
if let data = try? Data(contentsOf: url) {
if let image = UIImage(data: data) {
DispatchQueue.main.async {
self?.image = image
onLoadCompletion?(true)
}
} else {
onLoadCompletion?(false)
}
} else {
onLoadCompletion?(false)
}
}
}
}
Assuming your image view outlet is something like this:
#IBOutlet weak var imageView: UIImageView!
Below is the usage when adding a loader:
if let url = URL(string: "https://firebase-storage-url") {
// show a loader here if needed
imageView.load(url: url) { (imageLoaded) in
if imageLoaded {
// hide loader
} else {
// show a place holder image
// hide loader
}
}
} else {
// show a default image
}
Below is the usage without any extra work and just loading the image:
if let url = URL(string: "https://firebase-storage-url") {
imageView.load(url: url)
}

UIImagePickerController not initiating next function

I'm using Swift 5 and have integrated MessageKit into my app. Here's the expected functionality:
User selects the image via picker
uploadImage function is initiated
Image is uploaded and displayed
What's actually happening:
User selects the image via picker
Nothing happens from there.
I'm not getting a single error message. I've put in print statements to see if it's even entering the uploadImage() function but it's not kicking off. I've change the uipickerimagecontroller code to exact code in other places of my app that is working and even that's not kicking off the function. I know my code isn't pretty but I'm still learning (please don't judge lol). Can anyone help:
Variable setup
private var isSendingPhoto = true {
didSet {
DispatchQueue.main.async {
self.messageInputBar.leftStackViewItems.forEach { item in
item.inputBarAccessoryView?.isUserInteractionEnabled = !self.isSendingPhoto
}
}
}
}
ViewDidLoad
messagesCollectionView.messagesDataSource = self
messagesCollectionView.messagesLayoutDelegate = self
messageInputBar.delegate = self as? InputBarAccessoryViewDelegate
messagesCollectionView.messagesDisplayDelegate = self
title = "MaybeDrinks"
// 1
let cameraItem = InputBarButtonItem(type: .system)
cameraItem.tintColor = .primary
cameraItem.image = #imageLiteral(resourceName: "camera")
// 2
cameraItem.addTarget(
self,
action: #selector(cameraButtonPressed),
for: .primaryActionTriggered
)
cameraItem.setSize(CGSize(width: 60, height: 30), animated: false)
messageInputBar.leftStackView.alignment = .center
messageInputBar.setLeftStackViewWidthConstant(to: 50, animated: false)
messageInputBar.setStackViewItems([cameraItem], forStack: .left, animated: false) // 3
}
private func sendPhoto(_ image: UIImage) {
isSendingPhoto = true
uploadImage(image) { [weak self] url in
guard let `self` = self else {
return
}
self.isSendingPhoto = false
guard let url = url else {
return
}
var message = Message(messageuser: self.sender, image: image)
message.downloadURL = url
self.save(message)
self.messagesCollectionView.scrollToBottom()
}
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
// 1
if let asset = info[.phAsset] as? PHAsset {
let size = CGSize(width: 500, height: 500)
PHImageManager.default().requestImage(
for: asset,
targetSize: size,
contentMode: .aspectFit,
options: nil) { result, info in
print("I'm in image picker")
guard let image = result else {
return
}
self.sendPhoto(image)
}
// 2
} else if let image = info[.originalImage] as? UIImage {
sendPhoto(image)
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
// MARK: - Actions
#objc private func cameraButtonPressed() {
let picker = UIImagePickerController()
picker.delegate = self as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
picker.allowsEditing = true
if UIImagePickerController.isSourceTypeAvailable(.camera) {
picker.sourceType = .camera
} else {
picker.sourceType = .photoLibrary
}
present(picker, animated: true, completion: nil)
}
Upload Image function
private func uploadImage(_ image: UIImage, completion: #escaping (URL?) -> Void) {
print("im in upload")
// STEP 1. Declare URL, Request and Params
let url = URL(string: "https://localhost/messagepost.php")!
// declaring reqeust with further configs
var request = URLRequest(url: url)
// POST - safest method of passing data to the server
request.httpMethod = "POST"
// values to be sent to the server under keys (e.g. ID, TYPE)
let params = ["sender_id": user_id, "uuid": uuid, "sender": me, "recipient_id": rid, "recipient": recipient, "puuid": puuid]
// body
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
// Compressing image and converting image to 'Data' type
guard let scaledImage = image.scaledToSafeUploadSize,
let data = scaledImage.jpegData(compressionQuality: 0.4) else {
return
}
// assigning full body to the request to be sent to the server
request.httpBody = createBodyWithParams(params, filePathKey: "file", imageDataKey: data, boundary: boundary)
print(request.httpBody as Any, "\(puuid).jpg")
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
// error occured
if error != nil {
Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
return
}
do {
// save mode of casting any data
guard let data = data else {
Helper().showAlert(title: "Data Error", message: error!.localizedDescription, in: self)
return
}
// fetching JSON generated by the server - php file
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary
// save method of accessing json constant
guard let parsedJSON = json else {
return
}
// uploaded successfully
if parsedJSON["status"] as! String == "200" {
let newurl = parsedJSON["path"]
print("did you upload", newurl as Any)
print("did you upload", parsedJSON["message"] as Any)
self.isSendingPhoto = true
guard let url = newurl else {
return
}
//uploadImage(image)
var message = Message(messageuser: self.sender, image: image)
message.downloadURL = url as? URL
self.save(message)
self.messagesCollectionView.scrollToBottom()
} else {
// show the error message in AlertView
if parsedJSON["message"] != nil {
let message = parsedJSON["message"] as! String
Helper().showAlert(title: "Error", message: message, in: self)
print("where am i", parsedJSON["message"] as Any)
}
}
} catch {
Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
print("where am i 2")
}
}
}.resume()
let imageName = [UUID().uuidString, String(Date().timeIntervalSince1970)].joined()
}
private func save(_ message: Message) {
self.messagesCollectionView.scrollToBottom()
}
Make sure your view controller declares conformance to both UIImagePickerControllerDelegate and UINavigationControllerDelegate in either the class declaration:
class DirectMessageViewController: MessagesViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
[...]
}
or in one or more extensions:
extension DirectMessageViewController: UIImagePickerControllerDelegate {
[...]
}
extension DirectMessageViewController: UINavigationControllerDelegate {
[...]
}

terminating with uncaught exception of type NSException, when I run my code for my camera

When I try to run my camera I get an error message that says following
terminating with uncaught exception of type NSException and "Multiple audio/video AVCaptureInputs are not currently supported"
I have been watching for solutions on stackOverflow but haven't been succesful.
Tried to redirect my outlet my I can't understand where the problem occurs. Therefor I tried to put some breakpoint to find it but didn't manage
let captureSession = AVCaptureSession()
var previewLayer:CALayer!
var captureDevice:AVCaptureDevice!
var takePhoto = false
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
prepareCamera()
}
func prepareCamera() {
captureSession.sessionPreset = AVCaptureSession.Preset.photo
let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices
captureDevice = availableDevices.first
beginSession()
}
func beginSession () {
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice)
captureSession.addInput(captureDeviceInput)
}catch {
print(error.localizedDescription)
}
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
self.previewLayer = previewLayer
self.view.layer.addSublayer(self.previewLayer)
self.previewLayer.frame = self.view.layer.frame
captureSession.startRunning()
let dataOutput = AVCaptureVideoDataOutput()
dataOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString):NSNumber(value:kCVPixelFormatType_32BGRA)] as [String : Any]
dataOutput.alwaysDiscardsLateVideoFrames = true
if captureSession.canAddOutput(dataOutput) {
captureSession.addOutput(dataOutput)
}
captureSession.commitConfiguration()
let queue = DispatchQueue(label: "com.brianadvent.captureQueue")
dataOutput.setSampleBufferDelegate(self, queue: queue)
}
#IBAction func takePhoto(_ sender: Any) {
takePhoto = true
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
if takePhoto {
takePhoto = false
if let image = self.getImageFromSampleBuffer(buffer: sampleBuffer) {
let photoVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoVC") as! Viewcontroller2
photoVC.takenPhoto = image
DispatchQueue.main.async {
self.present(photoVC, animated: true, completion: {
self.stopCaptureSession()
})
}
}
}
}
func getImageFromSampleBuffer (buffer:CMSampleBuffer) -> UIImage? {
if let pixelBuffer = CMSampleBufferGetImageBuffer(buffer) {
let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
let context = CIContext()
let imageRect = CGRect(x: 0, y: 0, width: CVPixelBufferGetWidth(pixelBuffer), height: CVPixelBufferGetHeight(pixelBuffer))
if let image = context.createCGImage(ciImage, from: imageRect) {
return UIImage(cgImage: image, scale: UIScreen.main.scale, orientation: .right)
}
}
return nil
}
func stopCaptureSession () {
self.captureSession.stopRunning()
if let inputs = captureSession.inputs as? [AVCaptureDeviceInput] {
for input in inputs {
self.captureSession.removeInput(input)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
struct Constants {
static let apiKey = "AIzaSyDtaJ5eU24rbnHsG9pb1STOizDJvqcaj5E"
static let bundleId = "com.felibundle"
static let searchEngineId = "016628067786358079133:2gm9usqzouc"
}
#IBAction func pish(_ sender: Any) {
googleSearch(term: "George Bush") { results in
print(results)}
}
func googleSearch(term: String, callback:#escaping ([(title: String, url: String)]?) -> Void) {
let urlString = String(format: "https://cse.google.com/cse?cx=016628067786358079133:2gm9usqzouc", term, Constants.searchEngineId, Constants.apiKey)
let encodedUrl = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
guard let url = URL(string: encodedUrl ?? urlString) else {
print("invalid url \(urlString)")
return
}
let request = NSMutableURLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10)
request.httpMethod = "GET"
request.setValue(Constants.bundleId, forHTTPHeaderField: "X-Ios-Bundle-Identifier")
let session = URLSession.shared
let datatask = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard
error == nil,
let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : Any]
else {
callback(nil)
return
}
guard let items = json?["items"] as? [[String : Any]], items.count > 0 else {
print("no results")
return
}
callback(items.map { ($0["title"] as! String, $0["formattedUrl"] as! String) })
}
datatask.resume()
}
}
Your code runs fine at my end.
However, this kind of error arrives when we try to add multiple input device to the same session. Make sure you are not adding AVCaptureInputs object elsewhere in your project

cancel button using MBProgressView

I am trying to use cancel button with the MBProgressView. I am getting the error "cannot convert value of type '()' to expected argument type 'Selector'"
hud.button.addTarget(hud.progressObject, action: cancelButton(), for: .touchUpInside)
I have also tried doing this:
hud.button.addTarget(hud.progressObject, action: #selector(cancelButton), for: .touchUpInside)
and I got the error "Argument of #selector cannot refer to local function 'cancelButton()'".
Can anyone explain to me what am i doing wrong?
cancelButton should be in viewDidLoad or at least I need to find a way to access what's inside viewDidload, because I need to use hud and snapshot.progress to cancel the download:
override func viewDidLoad() {
super.viewDidLoad()
let appdelegate = UIApplication.shared.delegate as! AppDelegate
appdelegate.orintation = UIInterfaceOrientationMask.allButUpsideDown
if book?.bookPath != book?.bookPath {
print("HERE \(book?.bookPath)")
loadReader(filePaht: (book?.bookPath)!)
} else {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let strName = book?.id
let filePath = "\(documentsPath)/"+strName!+".pdf"
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
loadReader(filePaht: filePath)
return;
}
print("DOWNLOAD #1")
let reference = FIRStorage.storage().reference(forURL: (self.book?.bookURL)!)
let downloadTask = reference.data(withMaxSize: 50 * 1024 * 1024) { (data, error) -> Void in
if (error != nil) {
} else {
if ((try! data?.write(to: URL.init(fileURLWithPath: filePath, isDirectory: false))) != nil) {
self.db.upDate(id: (self.book?.id)!, bookPath: filePath)
self.loadReader(filePaht: filePath)
}
}
}
downloadTask.observe(.resume) { (snapshot) -> Void in
// Download resumed, also fires when the download starts
}
downloadTask.observe(.pause) { (snapshot) -> Void in
// Download paused
}
downloadTask.observe(.progress) { (snapshot) -> Void in
DispatchQueue.global(qos: .default).async(execute: {() -> Void in
self.showHUDWithCancel("Downloading")
DispatchQueue.main.async(execute: {() -> Void in
})
})
self.hud.progressObject = snapshot.progress
}
downloadTask.observe(.success) { (snapshot) -> Void in
// Download completed successfully
print("Download Success")
SwiftLoader.hide()
}
downloadTask.observe(.failure) { (snapshot) -> Void in
//Download failed
print("Download failed")
}
}
}
func showHUDWithCancel(_ aMessage: String) {
self.hud = MBProgressHUD.showAdded(to: self.view, animated: true)
self.hud.mode = MBProgressHUDMode.annularDeterminate
self.hud.label.text = aMessage
self.hud.detailsLabel.text = "Tap to cancel"
let tap = UITapGestureRecognizer(target: self, action: #selector(cancelButton))
self.hud.addGestureRecognizer(tap)
}
func cancelButton() {
self.hud.hide(animated: true)
self.hud.progressObject?.cancel()
print("cancel button is working")
}
This is the Cancel Button function
func cancelButton() {
MBProgressHUD.hide(for: view, animated: true)
snapshot.progress?.pause()
}
Try this -
Call below showHUDWithCancel from where you want to add hud with Cancel.
class ViewController: UIViewController {
var hud = MBProgressHUD()
override func viewDidLoad() {
super.viewDidLoad()
}
func showHUDWithCancel(_ aMessage: String) {
self.hud = MBProgressHUD.showAdded(to: self.view, animated: true)
self.hud.label.text = aMessage
self.hud.detailsLabel.text = "Tap to cancel"
let tap = UITapGestureRecognizer(target: self, action: #selector(cancelButton))
self.hud.addGestureRecognizer(tap)
}
func cancelButton() {
self.hud.hide(animated: true)
// do your other stuff here.
}
}
Add this code within your viewDidLoad it will work.
override func viewDidLoad() {
super.viewDidLoad()
let appdelegate = UIApplication.shared.delegate as! AppDelegate
appdelegate.orintation = UIInterfaceOrientationMask.allButUpsideDown
if book?.bookPath != book?.bookPath {
print("HERE \(book?.bookPath)")
loadReader(filePaht: (book?.bookPath)!)
} else {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let strName = book?.id
let filePath = "\(documentsPath)/"+strName!+".pdf"
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
loadReader(filePaht: filePath)
return;
}
print("DOWNLOAD #1")
let reference = FIRStorage.storage().reference(forURL: (self.book?.bookURL)!)
downloadTask = reference.data(withMaxSize: 50 * 1024 * 1024) { (data, error) -> Void in
if (error != nil) {
} else {
if ((try! data?.write(to: URL.init(fileURLWithPath: filePath, isDirectory: false))) != nil) {
self.db.upDate(id: (self.book?.id)!, bookPath: filePath)
self.loadReader(filePaht: filePath)
}
}
}
downloadTask.observe(.resume) { (snapshot) -> Void in
// Download resumed, also fires when the download starts
}
downloadTask.observe(.pause) { (snapshot) -> Void in
// Download paused
}
downloadTask.observe(.progress) { (snapshot) -> Void in OperationQueue.main.addOperation {
OperationQueue.main.addOperation {
self.hud.progressObject = snapshot.progress
self.showHUDWithCancel("Downloading")
}
}
}
downloadTask.observe(.success) { (snapshot) -> Void in OperationQueue.main.addOperation {
// Download completed successfully
print("Download Success")
OperationQueue.main.addOperation {
SwiftLoader.hide()
}
}
}
downloadTask.observe(.failure) { (snapshot) -> Void in OperationQueue.main.addOperation {
//Download failed
print("Download failed")
OperationQueue.main.addOperation {
_ = self.navigationController?.popViewController(animated: false)
}
}
}
}
}
Move definition of downloadTask outside of the viewDidLoad method scope into the class itself. This way you'll be able to access task directly, not via snapshot passed in observers, or progress attached to either downloadTask or progressHUD. Doing so you could access task from any method of your view controller including cancelButton():
task.pause()
instead of
snapshot.progress?.pause()
Final code could look like:
class ViewController: UIViewController {
var downloadTask: FIRStorageDownloadTask!
...
override func viewDidLoad() {
super.viewDidLoad()
...
let reference = FIRStorage.storage().reference(forURL: (self.book?.bookURL)!)
downloadTask = reference...
...
}
}
NOTICE: For those of you who use the latest version of MBProgressView, the button documentation has been changed:
/**
* A button that is placed below the labels. Visible only if a target / action is added and a title is assigned..
*/
So, the creation should look something like the following:
class Tools {
static func popLoadingDialog(viewParent: UIView,
label: String,
cancelTarget: Any? = nil,
cancelSelector: Selector? = nil) -> MBProgressHUD {
let loadingNotification = MBProgressHUD.showAdded(to: viewParent, animated: true)
loadingNotification.mode = MBProgressHUDMode.indeterminate
loadingNotification.label.text = label
if(cancelSelector != nil) {
loadingNotification.button.setTitle("Cancel", for: .normal)
loadingNotification.button.addTarget(cancelTarget, action: cancelSelector!, for: .touchUpInside)
}
return loadingNotification
}
}
and call it:
loadingIndicator = Tools.createLoadingDialog(viewParent: view,
label: "Please wait...",
cancelTarget: self,
cancelSelector: #selector(onCancelClick))
loadingIndicator?.show(animated: true)
}
#objc func onCancelClick(){
// do something when the user click on cancel...
}