AlertController view is not in the window hierarchy - swift

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)
}

Related

CCavenue Payment Gateway with WKWebView - iOS (as UiWebview is deprecated since 2020 by apple)

Post December 2020, apple does not allow UiWebView support. ccavenue, being popular payment gateway in India, still have not updated their sdk from official website.
Here is the the complete code, to be replaced for UiWebView issue.
class CCWebViewController: BaseViewController, WKNavigationDelegate {
var mywebview: WKWebView!
var request: NSMutableURLRequest?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupWebView()
notification = NotificationCenter.default.addObserver(forName: .UIApplicationWillEnterForeground, object: nil, queue: .main) {
[unowned self] notification in
self.checkResponseUrl()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if !isHere {
isHere = true
self.gettingRsaKey(){
(success, object) -> () in
DispatchQueue.main.sync {
if success {
self.encyptCardDetails(data: object as! Data)
}
else{
self.displayAlert(msg: object as! String)
}
}
}
}
}
override func viewDidAppear(_ animated: Bool) {
LoadingOverlay.shared.showOverlay(view: self.view)
}
private func setupWebView(){
//setup webview
let config = WKWebViewConfiguration()
self.mywebview = WKWebView(frame: CGRect.init(x: self.view.bounds.origin.x, y: self.view.bounds.origin.y, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height), configuration: config)
mywebview.navigationDelegate = self
self.view.addSubview(mywebview)
}
private func gettingRsaKey(completion: #escaping (_ success: Bool, _ object: AnyObject?) -> ()){
DispatchQueue.main.async {
self.rsaKeyDataStr = "access_code=\(self.accessCode)&order_id=\(self.orderId)"
let requestData = self.rsaKeyDataStr.data(using: String.Encoding.utf8)
guard let urlFromString = URL(string: self.rsaKeyUrl) else{
return
}
var urlRequest = URLRequest(url: urlFromString)
urlRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
urlRequest.httpMethod = "POST"
urlRequest.httpBody = requestData
let session = URLSession(configuration: URLSessionConfiguration.default)
print("session",session)
session.dataTask(with: urlRequest as URLRequest) {
(data, response, error) -> Void in
if let response = response as? HTTPURLResponse, 200...299 ~= response.statusCode{
guard let responseData = data else{
print("No value for data")
completion(false, "Not proper data for RSA Key" as AnyObject?)
return
}
print("data :: ",responseData)
completion(true, responseData as AnyObject?)
}
else{
completion(false, "Unable to generate RSA Key please check" as AnyObject?) }
}.resume()
}
}
private func encyptCardDetails(data: Data){
guard let rsaKeytemp = String(bytes: data, encoding: String.Encoding.ascii) else{
print("No value for rsaKeyTemp")
return
}
rsaKey = rsaKeytemp
rsaKey = self.rsaKey.trimmingCharacters(in: CharacterSet.newlines)
rsaKey = "-----BEGIN PUBLIC KEY-----\n\(self.rsaKey)\n-----END PUBLIC KEY-----\n"
print("rsaKey :: ",rsaKey)
let myRequestString = "amount=\(amount)&currency=\(currency)"
do{
let encodedData = try RSAUtils.encryptWithRSAPublicKey(str: myRequestString, pubkeyBase64: rsaKey)
var encodedStr = encodedData?.base64EncodedString(options: [])
let validCharSet = CharacterSet(charactersIn: "!*'();:#&=+$,/?%#[]").inverted
encodedStr = encodedStr?.addingPercentEncoding(withAllowedCharacters: validCharSet)
CCWebViewController.statusCode = 0
//Preparing for webview call
if CCWebViewController.statusCode == 0{
CCWebViewController.statusCode = 1
let urlAsString = "https://secure.ccavenue.com/transaction/initTrans"
let encryptedStr = "merchant_id=\(merchantId)&order_id=\(orderId)&redirect_url=\(redirectUrl)&cancel_url=\(cancelUrl)&enc_val=\(encodedStr!)&access_code=\(accessCode)&billing_name=\(billingName)&billing_address=\(billingAddress)&billing_city=\(billingCity)&billing_state=\(billingState)&billing_country=\(billingCountry)&billing_tel=\(billingMobile)&billing_zip=\(pincode)&billing_email=\(billingEmail)&merchant_param1=\(notes)&billing_country=\(billingCountry)&merchant_param2=\(notes)&merchant_param3=\(notes)&merchant_param4=\(notes)&delivery_country=\(billingCountry)&delivery_cust_notes=\(notes)"
let myRequestData = encryptedStr.data(using: String.Encoding.utf8)
request = NSMutableURLRequest(url: URL(string: urlAsString)! as URL, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 30)
request?.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
request?.setValue(urlAsString, forHTTPHeaderField: "Referer")
request?.httpMethod = "POST"
request?.httpBody = myRequestData
self.mywebview.load(request! as URLRequest)
}
else{
print("Unable to create requestURL")
displayAlert(msg: "Unable to create requestURL")
}
}
catch let err {
print(err)
}
}
func displayAlert(msg: String){
let alert: UIAlertController = UIAlertController(title: "ERROR", message: msg, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
LoadingOverlay.shared.hideOverlayView()
self.dismiss(animated: true, completion: nil)
}
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
}
//MARK: WebviewDelegate Methods
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
self.showToast(type: 0, message: "Error", timeToDisplay: 2)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print(String(describing: webView.url))
LoadingOverlay.shared.hideOverlayView()
webView.evaluateJavaScript("document.documentElement.outerHTML", completionHandler: { result, error in
if let datHtml = result as? String {
print(datHtml)
// parse datHtml here
let string = webView.url!.absoluteString
if(string.contains(self.redirectUrl))
{
print(self.mywebview.isLoading)
let html = datHtml
print("html :: ",html)
var transStatus = "Not Known"
if(html.contains("tracking_id"))
{
if(html.contains("Success"))
{
transStatus = "Transaction Successful"
let controller: CCResultViewController = CCResultViewController()
controller.transStatus = transStatus
controller.isSucceed = true
self.present(controller, animated: true, completion: nil)
}
else if(html.contains("Aborted"))
{
transStatus = "Transaction Cancelled"
let controller: CCResultViewController = CCResultViewController()
controller.transStatus = transStatus
controller.isSucceed = false
self.present(controller, animated: true, completion: nil)
}
else
{
transStatus = "Transaction Failed"
let controller: CCResultViewController = CCResultViewController()
controller.transStatus = transStatus
controller.isSucceed = false
self.present(controller, animated: true, completion: nil)
}
}
else{
print("html does not contain any related data")
self.displayAlert(msg: "html does not contain any related data for this transaction.")
}
}
}
} )
}
}

Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread in swift

I have given DispatchQueue.main.async {} where it necessary but when i give break point from dataTask here it says
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.'
Cannot be called with asCopy = NO on non-main thread.
class EventsViewController: UIViewController {
#IBOutlet weak var backBtn: UIButton!
var eventsListArray = [AnyObject]()
var eventType: String?
var eventList : EventsModel? = nil
#IBOutlet weak var eventsTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
getAllEventsList()
}
func getAllEventsList() {
DispatchQueue.main.async {
let deviceId: String = (UIDevice.current.identifierForVendor?.uuidString)!
let personalId: String = UserDefaults.standard.string(forKey: "regUserID") ?? ""//KeychainWrapper.standard.string(forKey: "USERID") ?? ""
let headers = ["deviceid": deviceId,"userType": "personal","key": personalId]
DispatchQueue.main.async {
let string = Constants.GLOBAL_URL + "/get/allevents"
var urlComponents = URLComponents(string: string)
let eventStatus = self.eventType
let requestEventType = URLQueryItem(name: "eventstatus", value: eventStatus)
urlComponents?.queryItems = [requestEventType]
let urlStr = urlComponents?.url
let request = NSMutableURLRequest(url: urlStr!, cachePolicy: .useProtocolCachePolicy,timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers as! [String : String]
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if error == nil {
let httpResponse = response as? HTTPURLResponse
if httpResponse!.statusCode == 200 {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! [String :AnyObject]
print("publish event \(jsonObject)")
self.eventList = EventsModel.init(fromDictionary: jsonObject)
DispatchQueue.main.async {
if self.eventList?.events.count != 0 {
DispatchQueue.main.async {
self.eventsTableView.reloadData()
}
}
else {
DispatchQueue.main.async {
Constants.showAlertView(alertViewTitle: "", Message: "No Events \(self.eventType)", on: self)
self.eventList?.events.removeAll()
self.eventsTableView.reloadData()
}
}
}
} catch { print(error.localizedDescription) }
} else {
Constants.showAlertView(alertViewTitle: "", Message: "Something went wrong, Please try again", on: self)
}
}
})
dataTask.resume()
}
}
}
}
You've probably missed a few spots where you're trying to present an alert when errors are thrown. Why don't you just enter the main queue right after the data request is complete.
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
DispatchQueue.main.async {
if error == nil {
//...
}
}
})

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

I get an error on the Swift user login screen

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)
}
}
}

My chat data is successfully inserted into firebase, but I cannot fetch the data into designated chat rooms

I am currently following zero2launches chat application, and I also watched/completed their other tutorials on YouTube. While I started the chat application, I thought about changing the chat portion from a tableViewController to JSQMessageViewController. In that effort, I can post the data to firebase, but it won't show up in the individual chat rooms.
Here is the code:
var roomId: String!
var messages = [JSQMessage]()
func observeMessage() {
messageRef.observeEventType(.ChildAdded, withBlock: { snapshot in
//print(snapshot.value)
if let dict = snapshot.value as? [String: AnyObject] {
let mediaType = dict["MediaType"] as! String
let senderId = dict["senderId"] as! String
let senderName = dict["senderName"] as! String
switch mediaType {
case "TEXT":
let text = dict["text"] as? String
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, text: text))
case "PHOTO":
let fileUrl = dict["fileUrl"] as! String
let url = NSURL(string: fileUrl)
let data = NSData(contentsOfURL: url!)
let picture = UIImage(data: data!)
let photo = JSQPhotoMediaItem(image: picture)
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photo))
case "VIDEO":
let fileUrl = dict["fileUrl"] as! String
let video = NSURL(string: fileUrl)
let videoItem = JSQVideoMediaItem(fileURL: video, isReadyToPlay: true)
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: videoItem))
default:
print("unknow data type")
}
if mediaType == "TEXT" {
let text = dict["text"] as? String
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, text: text))
}else if mediaType == "PHOTO" {
let fileUrl = dict["fileUrl"] as! String
let url = NSURL(string: fileUrl)
let data = NSData(contentsOfURL: url!)
let picture = UIImage(data: data!)
let photo = JSQPhotoMediaItem(image: picture)
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photo))
}else if mediaType == "VIDEO" {
let fileUrl = dict["fileUrl"] as! String
let video = NSURL(string: fileUrl)
let videoItem = JSQVideoMediaItem(fileURL: video, isReadyToPlay: true)
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: videoItem))
}
print(dict)
let text = dict["text"] as? String
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, text: text))
self.collectionView.reloadData()
}
})
}
override func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: NSDate!) {
let newMessage = messageRef.childByAutoId()
let messageData = ["text": text, "senderId": senderId, "senderName": senderDisplayName, "MediaType": "TEXT"]
newMessage.setValue(messageData)
}
override func didPressAccessoryButton(sender: UIButton!) {
print("didPressAccessoryButton")
let sheet = UIAlertController(title: "Media Messages", message: "Please select a media", preferredStyle: UIAlertControllerStyle.ActionSheet)
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (alert:UIAlertAction) in
}
let photoLibrary = UIAlertAction(title: "Photo Library", style: UIAlertActionStyle.Default) { (alert: UIAlertAction) in
self.getMediaFrom(kUTTypeImage)
}
let videoLibrary = UIAlertAction(title: "Video Library", style: UIAlertActionStyle.Default) { (alert: UIAlertAction) in
self.getMediaFrom(kUTTypeMovie)
}
sheet.addAction(photoLibrary)
sheet.addAction(videoLibrary)
sheet.addAction(cancel)
self.presentViewController(sheet, animated: true, completion: nil)
}
func getMediaFrom(type: CFString) {
print(type)
let mediaPicker = UIImagePickerController()
mediaPicker.delegate = self
mediaPicker.mediaTypes = [type as String]
self.presentViewController(mediaPicker, animated: true, completion: nil)
}
override func collectionView(collectionView: JSQMessagesCollectionView!, messageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
override func collectionView(collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageBubbleImageDataSource! {
let bubbleFactory = JSQMessagesBubbleImageFactory()
return bubbleFactory.outgoingMessagesBubbleImageWithColor(.blackColor())
}
override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
return nil
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("number of item:\(messages.count)" )
return messages.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! JSQMessagesCollectionViewCell
return cell
}
override func collectionView(collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAtIndexPath indexPath: NSIndexPath!) {
print("didTapMessageBubbleAtIndexPath: \(indexPath.item)")
let message = messages[indexPath.item]
if message.isMediaMessage {
if let mediaItem = message.media as? JSQVideoMediaItem {
let player = AVPlayer(URL: mediaItem.fileURL)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.presentViewController(playerViewController, animated: true, completion: nil)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func sendMedia(picture: UIImage?, video: NSURL?) {
print(picture)
FIRStorage.storage().reference()
if let picture = picture {
let filePath = "\(FIRAuth.auth()?.currentUser!)\(NSDate.timeIntervalSinceReferenceDate())"
print(filePath)
let data = UIImageJPEGRepresentation(picture, 0.1)
let metadata = FIRStorageMetadata()
metadata.contentType = "image/jpg"
FIRStorage.storage().reference().child(filePath).putData(data!, metadata: metadata) { (metadata, error) in
if error != nil {
print(error?.localizedDescription)
return
}
let fileUrl = metadata!.downloadURLs![0].absoluteString
let newMessage = self.messageRef.childByAutoId()
let messageData = ["fileUrl": fileUrl, "senderId": self.senderId, "senderName": self.senderDisplayName, "MediaType": "PHOTO"]
newMessage.setValue(messageData)
}
}else if let video = video {
let filePath = "\(FIRAuth.auth()?.currentUser!)\(NSDate.timeIntervalSinceReferenceDate())"
print(filePath)
let data = NSData(contentsOfURL: video)
let metadata = FIRStorageMetadata()
metadata.contentType = "video/mp4"
FIRStorage.storage().reference().child(filePath).putData(data!, metadata: metadata) { (metadata, error) in
if error != nil {
print(error?.localizedDescription)
return
}
let fileUrl = metadata!.downloadURLs![0].absoluteString
let newMessage = self.messageRef.childByAutoId()
let messageData = ["fileUrl": fileUrl, "senderId": self.senderId, "senderName": self.senderDisplayName, "MediaType": "VIDEO"]
newMessage.setValue(messageData)
}
}
}
}
Here is my existing message database functions
let roofRef = FIRDatabase.database().reference()
class DataService {
static let dataService = DataService()
private var _BASE_REF = roofRef
private var _ROOM_REF = roofRef.child("captions")
private var _MESSAGE_REF = roofRef.child("messages")
private var _PEOPLE_REF = roofRef.child("people")
var currentUser: FIRUser? {
return FIRAuth.auth()!.currentUser!
}
var BASE_REF: FIRDatabaseReference {
return _BASE_REF
}
var ROOM_REF: FIRDatabaseReference {
return _ROOM_REF
}
var MESSAGE_REF: FIRDatabaseReference {
return _MESSAGE_REF
}
var PEOPLE_REF: FIRDatabaseReference {
return _PEOPLE_REF
}
var storageRef: FIRStorageReference {
return FIRStorage.storage().reference()
}
var fileUrl: String!
func CreateNewPost(user: FIRUser, caption: String, data: NSData) {
let filePath = "\(user.uid)/\(Int(NSDate.timeIntervalSinceReferenceDate()))"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
storageRef.child(filePath).putData(data, metadata: metaData, completion: { (metadata, error) in
if let error = error{
print("Error uploarding: \(error.description)")
return
}
self.fileUrl = metadata!.downloadURLs![0].absoluteString
if let user = FIRAuth.auth()?.currentUser {
let idCaption = self.BASE_REF.child("captions").childByAutoId()
idCaption.setValue(["caption": caption, "thumbnailURLFromStorage": self.storageRef.child(metadata!.path!).description, "filelUrl": self.fileUrl])
}
})
}
func SignUp(username: String, email: String, password: String, data: NSData) {
FIRAuth.auth()?.createUserWithEmail(email, password: password, completion: { (user, error) in
if let error = error {
print(error.localizedDescription)
return
}
let changeRequest = user?.profileChangeRequest()
changeRequest?.displayName = username
changeRequest?.commitChangesWithCompletion({ (error) in
if let error = error {
print(error.localizedDescription)
return
}
})
let filePath = "profileImage/\(user!.uid)"
let metadata = FIRStorageMetadata()
metadata.contentType = "image/jpeg"
self.storageRef.child(filePath).putData(data, metadata: metadata, completion: { (metadata, error) in
if let error = error {
print("\(error.description)")
return
}
self.fileUrl = metadata?.downloadURLs![0].absoluteString
let changeRequestPhoto = user!.profileChangeRequest()
changeRequestPhoto.photoURL = NSURL(string: self.fileUrl)
changeRequestPhoto.commitChangesWithCompletion({ (error) in
if let error = error {
print(error.localizedDescription)
return
}else{
print("profile updated")
}
})
self.PEOPLE_REF.child((user?.uid)!).setValue(["username": username, "email": email, "profileImage": self.storageRef.child((metadata?.path)!).description])
ProgressHUD.showSuccess("Succeeded.")
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.login()
})
})
}
//implement login func
func login(email: String, password: String) {
FIRAuth.auth()?.signInWithEmail(email, password: password, completion: { (user, error) in
if let error = error {
print(error.localizedDescription)
return
}
ProgressHUD.showSuccess("Succeeded")
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.login()
})
}
// Update profile
func SaveProfile(username: String, email: String, data: NSData) {
let user = FIRAuth.auth()?.currentUser!
let filePath = "\(user!.uid)/\(Int(NSDate.timeIntervalSinceReferenceDate()))"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
self.storageRef.child(filePath).putData(data, metadata: metaData) { (metaData, error) in
if let error = error {
print("Error uploading: \(error.description)")
return
}
self.fileUrl = metaData!.downloadURLs![0].absoluteString
let changeRequestProfile = user?.profileChangeRequest()
changeRequestProfile?.photoURL = NSURL(string: self.fileUrl)
changeRequestProfile?.displayName = username
changeRequestProfile?.commitChangesWithCompletion({ (error) in
if let error = error {
print(error.localizedDescription)
ProgressHUD.showError("NetWork error")
}else{
}
})
if let user = user {
user.updateEmail(email, completion: { (error) in
if let error = error {
print(error.description)
}else{
print("email update")
}
})
}
ProgressHUD.showSuccess("Saved")
}
}
func CreateNewMessage(userId: String, roomId: String, textMessage: String) {
let idMessage = roofRef.child("messages").childByAutoId()
DataService.dataService.MESSAGE_REF.child(idMessage.key).setValue(["message": textMessage, "senderId": userId])
DataService.dataService.ROOM_REF.child(roomId).child("messages").child(idMessage.key).setValue(true)
}
func fetchMessageFromServer(roomId: String, callback: (FIRDataSnapshot) -> ()) {
DataService.dataService.ROOM_REF.child(roomId).child("messages").observeEventType(.ChildAdded, withBlock: {snapshot -> Void in
DataService.dataService.MESSAGE_REF.child(snapshot.key).observeEventType(.Value, withBlock: {
snap -> Void in
callback(snap)
})
})
}