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

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

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 execute function after another?

I'm trying to execute loadQuestionToView() after executing loadQuestionsForTests() using defer, but I'm unsuccessful... Can you help me with that?
override func viewDidLoad() {
super.viewDidLoad()
defer {
loadQuestionToView()
}
loadQuestionsForTest(testID: testID)
}
func loadQuestionToView() {
questionLabel.text = self.questions[self.questionIterator].question
}
func loadQuestionsForTest(testID: String) {
let docRef = db.collection(Constants.FStore.collectionTests).document(testID).collection("questions")
docRef.getDocuments { (querySnapshot, error) in
if let e = error {
print(e)
} else {
if let snapshotDocuments = querySnapshot?.documents {
for doc in snapshotDocuments {
let data = doc.data()
let question: Question = Question(question: data["question"] as! String, correctAnswer: data["answerCorrect"] as! String, wrongAnswer1: data["answerWrong1"] as! String, wrongAnswer2: data["answerWrong2"] as! String, wrongAnswer3: data["answerWrong3"] as! String)
self.questions.append(question)
//print(self.questions[self.iterator].question)
}
}
}
}
}
The best way to do is using closure.
If you want learn about closures, here you go: https://docs.swift.org/swift-book/LanguageGuide/Closures.html
override func viewDidLoad() {
super.viewDidLoad()
loadQuestionsForTest(testID: testID) { success in
if success {
questionLabel.text = self.questions[self.questionIterator].questio
} else {
// Whatever you want to do on failure
}
}
}
func loadQuestionsForTest(testID: String, #escaping completion: (Bool) -> Void)) {
let docRef = db.collection(Constants.FStore.collectionTests).document(testID).collection("questions")
docRef.getDocuments { (querySnapshot, error) in
if let e = error {
completion(false)
} else {
if let snapshotDocuments = querySnapshot?.documents {
for doc in snapshotDocuments {
let data = doc.data()
let question: Question = Question(question: data["question"] as! String, correctAnswer: data["answerCorrect"] as! String, wrongAnswer1: data["answerWrong1"] as! String, wrongAnswer2: data["answerWrong2"] as! String, wrongAnswer3: data["answerWrong3"] as! String)
self.questions.append(question)
}
completion(true)
} else {
completion(false)
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
loadQuestionsForTest(testID: testID, completionHandler: { [weak self] result in
// here I call loadQuestionToView when result is true
if result {
self?.loadQuestionToView()
}
})
}
func loadQuestionToView() {
questionLabel.text = self.questions[self.questionIterator].question
}
func loadQuestionsForTest(testID: String, completionHandler: #escaping (Bool) -> Void) {
let docRef = db.collection(Constants.FStore.collectionTests).document(testID).collection("questions")
docRef.getDocuments { (querySnapshot, error) in
if let e = error {
print(e)
} else {
if let snapshotDocuments = querySnapshot?.documents {
for doc in snapshotDocuments {
let data = doc.data()
let question: Question = Question(question: data["question"] as! String, correctAnswer: data["answerCorrect"] as! String, wrongAnswer1: data["answerWrong1"] as! String, wrongAnswer2: data["answerWrong2"] as! String, wrongAnswer3: data["answerWrong3"] as! String)
self.questions.append(question)
//print(self.questions[self.iterator].question)
}
completionHandler(true)
return
}
}
completionHandler(false)
}
}

How to send multiple images to Firebase and retrieve them in the UIImageView in Swift

I have an app that lets users choose multiple images. The problem is that it doesn't upload and save the image to the user in Firebase and retrieve the image.
This is my code:
import UIKit
import Photos
import Firebase
import BSImagePicker
class Downloadimages: UIViewController {
#IBOutlet weak var imgView: UIImageView!
var ref: DatabaseReference?
var SelectedAssets = [PHAsset]()
var PhotoArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
// 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.
}
#IBAction func addImagesClicked(_ sender: Any) {
// create an instance
let vc = BSImagePickerViewController()
//display picture gallery
self.bs_presentImagePickerController(vc, animated: true,
select: { (asset: PHAsset) -> Void in
}, deselect: { (asset: PHAsset) -> Void in
// User deselected an assets.
}, cancel: { (assets: [PHAsset]) -> Void in
// User cancelled. And this where the assets currently selected.
}, finish: { (assets: [PHAsset]) -> Void in
// User finished with these assets
for i in 0..<assets.count
{
self.SelectedAssets.append(assets[i])
}
self.convertAssetToImages()
}, completion: nil)
let image = UIImagePickerController()
image.delegate = self as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
image.sourceType = UIImagePickerControllerSourceType.photoLibrary
image.allowsEditing = false
self.present(image, animated: true)
{
//after its completed
}
}
#objc(imagePickerController:didFinishPickingMediaWithInfo:) func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage
{
imgView.image = image
}
else
{
//error
}
self.dismiss(animated: true, completion: nil)
let storageRef = Storage.storage().reference().child("myImage.png")
if let uploadData = UIImagePNGRepresentation(self.imgView.image!){
storageRef.putData(uploadData, metadata: nil, completion:
{
(metadata, error) in
if error != nil {
print("error")
return
}
print(metadata!)
//how do I put the download URL in the metadata into my database
}
)
}
}
func convertAssetToImages() -> Void {
if SelectedAssets.count != 0{
for i in 0..<SelectedAssets.count{
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
manager.requestImage(for: SelectedAssets[i], targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: option, resultHandler: {(result, info)->Void in
thumbnail = result!
})
let data = UIImageJPEGRepresentation(thumbnail, 0.7)
let newImage = UIImage(data: data!)
self.PhotoArray.append(newImage! as UIImage)
}
self.imgView.animationImages = self.PhotoArray
self.imgView.animationDuration = 3.0
self.imgView.startAnimating()
}
print("complete photo array \(self.PhotoArray)")
}
}
and this is my post code
import Foundation
class Post {
var id:String
var author:UserProfile
var text:String
var createdAt:Date
init(id:String, author:UserProfile,text:String,timestamp:Double) {
self.id = id
self.author = author
self.text = text
self.createdAt = Date(timeIntervalSince1970: timestamp / 1000)
}
static func parse(_ key:String, _ data:[String:Any]) -> Post? {
if let author = data["author"] as? [String:Any],
let uid = author["uid"] as? String,
let username = author["username"] as? String,
let photoURL = author["photoURL"] as? String,
let url = URL(string:photoURL),
let text = data["text"] as? String,
let timestamp = data["timestamp"] as? Double {
let userProfile = UserProfile(uid: uid, username: username, photoURL: url)
return Post(id: key, author: userProfile, text: text, timestamp:timestamp)
}
return nil
}
}
this is my userProfile
import Foundation
class UserProfile {
var uid:String
var username:String
var photoURL:URL
init(uid:String, username:String,photoURL:URL) {
self.uid = uid
self.username = username
self.photoURL = photoURL
}
}
and this is
import Foundation
import Firebase
class UserService {
static var currentUserProfile:UserProfile?
static func observeUserProfile(_ uid:String, completion: #escaping ((_ userProfile:UserProfile?)->())) {
let userRef = Database.database().reference().child("users/profile/\(uid)")
userRef.observe(.value, with: { snapshot in
var userProfile:UserProfile?
if let dict = snapshot.value as? [String:Any],
let username = dict["username"] as? String,
let photoURL = dict["photoURL"] as? String,
let url = URL(string:photoURL) {
userProfile = UserProfile(uid: snapshot.key, username: username, photoURL: url)
}
completion(userProfile)
})
}
}

Incorrect sender name showing in chat using MessageKit

I've integrated MessageKit into my project, I'm using MySQL as my db and PHP for my APIs. I've been able to pull messages from the db and display them; but the name of the sender is replaced with the current user that's logged in. I've printed the sender name and it's correct coming over the app correct, but somehow the displayname is not showing the right one. Here is a screenshot with the code below. I've checked the MessageKit instructions and can't figure out what i'm doing wrong.
Member.swift file
internal struct Message: MessageType {
var sender: SenderType
var senderId: String
var messageId: String
var member: String
var id: String?
var content: String
let sentDate: Date
var messagedata: MessageKind {
if let image = image {
return .photo((image as? MediaItem)!)
} else {
return .text(content)
}
}
var image: UIImage? = nil
var downloadURL: URL? = nil
init(messageuser: Sender, content: String) {
sender = Sender(id: meid, displayName: AppSettings.displayName)
self.senderId = meid
self.messageId = uuid
self.member = me
id = nil
self.content = content
sentDate = Date()
self.image = nil
//self.kind = (content as? MessageKind)!
}
init(messageuser: Sender, image: UIImage) {
sender = Sender(id: meid, displayName: AppSettings.displayName)
self.senderId = meid
self.messageId = uuid
self.member = me
id = nil
self.content = ""
sentDate = Date()
self.image = image
}
}
extension Message: Comparable {
static func == (lhs: Message, rhs: Message) -> Bool {
return lhs.id == rhs.id
}
static func < (lhs: Message, rhs: Message) -> Bool {
return lhs.id == rhs.id
}
var kind: MessageKind {
return .text(content)
}
}
DirectMessageViewController
func loadMessages(offset: Int, limit: Int) {
isLoading = true
let me = user!["username"] as! String
let meid = user!["id"] as! String
let uuid = getmessages["uuid"] as! String
print("tell me what the uuid is", uuid)
let url = URL(string: "https://localhost/message.php")
let body = "username=\(me)&uuid=\(uuid)&recipient_id=\(meid)&limit=\(limit)&offset=\(offset)"
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = body.data(using: String.Encoding.utf8)
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
if error != nil {
Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
return
}
do {
guard let data = data else {
Helper().showAlert(title: "Data Error", message: error!.localizedDescription, in: self)
self.isLoading = false
return
}
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary
guard let parseJSON = json else {
print("Error while parsing")
return
}
guard let posts = parseJSON["messages"] as? [NSDictionary] else {
self.isLoading = false
print("Error while parseJSONing")
return
}
self.hhmessages = posts as! [AnyObject?]
for i in 0 ..< self.hhmessages.count {
let sender = Sender(id: (self.hhmessages[i]?["sender_id"])! as! String, displayName: (self.hhmessages[i]?["sender"])! as! String)
let member = self.hhmessages[i]?["recipient"]
print("who's talking", sender as Any)
let text = self.hhmessages[i]?["messagetext"] as? String
let uuid = self.hhmessages[i]?["uuid"]
let sid = self.hhmessages[i]?["sender_id"]
let message_id = self.hhmessages[i]?["notesid"] as? String
let date = self.hhmessages[i]?["date"] as? Date
let message = Message(messageuser: sender, content: text!)
self.messages.append(message)
self.messageList = self.messages
self.messagesCollectionView.reloadData()
self.messagesCollectionView.scrollToBottom()
}
} catch {
Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
self.isLoading = false
return
}
}
}.resume()
}
}
extension DirectMessageViewController: MessagesDataSource {
func numberOfSections(
in messagesCollectionView: MessagesCollectionView) -> Int {
return messages.count
}
func currentSender() -> SenderType {
return Sender(id: (sender_id as? String)!, displayName: sender.displayName)
}
messageTopLabelAttributedText
func messageTopLabelAttributedText(
for message: MessageType,
at indexPath: IndexPath) -> NSAttributedString? {
return NSAttributedString(
string: message.sender.displayName,
attributes: [.font: UIFont.systemFont(ofSize: 12)])
}
}

FaceBook Image Upload In API in iOS swift

I am new in iOS . i am trying to convert image or image url into png,or jpg format and failed .plz help me in this matter
#IBAction func FBSignInAct(sender: AnyObject) {
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager .logInWithReadPermissions(["email"], fromViewController: self, handler: { (result, error) -> Void in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult = result
if result.isCancelled {
return
}
if(fbloginresult.grantedPermissions.contains("email"))
{
self.getFBUserData()
}
}
})
}
func getFBUserData(){
if((FBSDKAccessToken.currentAccessToken()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).startWithCompletionHandler({ (connection, result, error) -> Void in
if (error == nil){
print(result)
let url = NSURL(string: result["picture"]!!["data"]!!["url"]!! as! String)
let email:String = result["email"] as! String
let id:String = result["id"] as! String
let name:String = result["name"] as! String
self.signUpFBControl(email , fbID: id , name: name , profile_PicUrl: url!)
}
})
}
}
func signUpFBControl(email:String,fbID:String,name:String,profile_PicUrl:NSURL)
{
let data = NSData(contentsOfURL: profile_PicUrl)
let profilePic : UIImage = UIImage(data: data!)!
let image:NSData = UIImageJPEGRepresentation(profilePic,1)!
let strBase64:String = image.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
print(strBase64)
let dataDecoded:NSData = NSData(base64EncodedString: strBase64, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)!
print( dataDecoded)
Alamofire.request(.POST, "\(SERVERURL)fb_login", parameters: ["email": email,"fbid": fbID,"name": name ,"profile_pic": image,"user_type":"business" ]).responseJSON { response in
let json = JSON(data: response.data!)
if json["msg"].string == "User Details" {
let data = json["user_details"][0]
print(data)
LoginValue.sharedInstance.setUserLoginInfo(data)
self.reachNextViewController()
} else {
self.alertView("Sign Up Failed", message: json["error_description"].string!, button: "Close", destructive: false,secondButton: "")
}
print(json["error_description"])
}
}
error says
The profile pic must be a file of type: jpeg, jpg, png.