UIIMagePickerController not working properly with Swift 3 - uiimagepickercontroller

I'm getting crazy with this.
While migrating a simple UIIMagePicker implementation I have everything working properly , no issues, no warning.
Running on both simulator and device the PickerController just don't take into consideration the new image and won't apply to the UImageView.
This is my code:
#IBOutlet weak var profilePictureImageView: UIImageView!
let picker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
}
//Opening Camera to take a new picture
#IBAction func takeNewPictureButtonDidTouch(_ sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.camera
picker.cameraCaptureMode = .photo
picker.modalPresentationStyle = .fullScreen
present(picker,animated: true,completion: nil)
} else {
noCamera()
}
}
//Opening the library to select an existing picture
#IBAction func openPicturesLibraryButtonDidTouch(_ sender: AnyObject) {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
picker.modalPresentationStyle = .popover
present(picker, animated: true, completion: nil)
}
//MARK: - Delegates
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : AnyObject])
{
var chosenImage = UIImage()
chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage //2
profilePictureImageView.contentMode = .scaleAspectFill //3
profilePictureImageView.image = chosenImage //4
dismiss(animated:true, completion: nil) //5
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
func noCamera(){
let alertVC = UIAlertController(
title: "No Camera",
message: "Sorry, this device has no camera",
preferredStyle: .alert)
let okAction = UIAlertAction(
title: "OK",
style:.default,
handler: nil)
alertVC.addAction(okAction)
present(
alertVC,
animated: true,
completion: nil)
}
}

set delegate to self in viewdidload

Related

How to update share button coding to work on iOS 13

My code for the share button works well on all versions below iOS 13, How do I modify the coding to work on iOS 13 for both IPad and IPhone?
class CatseyeViewController: BaseViewController{
#IBOutlet weak var sliderImage: UIImageView!
#IBAction func share(_ sender: UIButton) {
let activityController = UIActivityViewController(activityItems:
[self.sliderImage.image as Any], applicationActivities: nil)
self.present(activityController, animated:true, completion: nil)
if let popOver = activityController.popoverPresentationController {
popOver.sourceView = self.view
}
}
}
In order to update the share sheet to work on iOS 13, create an IF/ELSE statement to detect first for iOS 13 versus all other versions.
class CatseyeViewController: BaseViewController{
#IBOutlet weak var sliderImage: UIImageView!
#IBAction func share(_ sender: UIButton) {
let version = OperatingSystemVersion(majorVersion: 13, minorVersion: 0, patchVersion: 0)
if ProcessInfo.processInfo.isOperatingSystemAtLeast(version) {
/* runNewCode()*/
let items = [self.sliderImage.image]
let ac = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil)
UIApplication.shared.windows.first?.rootViewController?.present(ac, animated: true, completion: nil)
if UIDevice.current.userInterfaceIdiom == .pad {
ac.popoverPresentationController?.sourceView = UIApplication.shared.windows.first
ac.popoverPresentationController?.sourceRect = CGRect(
x: UIScreen.main.bounds.width / 2.1,
y: UIScreen.main.bounds.height / 2.3,
width: 200, height: 200)
}
}
else
{
/* runOriginalCode() that works for earlier IOS*/
let activityController = UIActivityViewController(activityItems: [self.sliderImage.image as Any], applicationActivities: nil)
self.present(activityController, animated:true, completion: nil)
if let popOver = activityController.popoverPresentationController {
popOver.sourceView = self.view
}
}//end of else statement
}//end of share function
}//end of controller

Cant Create Accout (Upload Image Swift)

After importing Firebase to my Project which i want to Create for iOS (Swift)
I tried to create a user, with ProfileImage and Username.
When i tap "Create Account" i get an error message it says "Error signing up".
This is the Error Message in the Terminal
2018-07-20 23:15:50.764062+0200 Collect App[3341:120860] [discovery] errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled}
I will paste my code here.
//
// SignUpViewController.swift
import Foundation
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage
class SignUpViewController: UIViewController {
#IBOutlet weak var userNameTextField: UITextField!
#IBOutlet weak var userEmailTextField: UITextField!
#IBOutlet weak var userPasswordTextField: UITextField!
#IBOutlet weak var confirmuserPasswordTextField: UITextField!
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var dismissButton: UIButton!
#IBAction func tapToChangeProfileButton(_ sender: Any) {
}
#IBAction func handleDismissButton(_ sender: Any) {
self.dismiss(animated: false, completion: nil)
}
var imagePicker:UIImagePickerController!
private var authUser : User? {
return Auth.auth().currentUser
}
public func sendVerificationMail() {
if self.authUser != nil && !self.authUser!.isEmailVerified {
self.authUser!.sendEmailVerification(completion: { (error) in
// Notify the user that the mail has sent or couldn't because of an error.
})
}
else {
// Either the user is not available, or the user is already verified.
}
}
override func viewDidLoad() {
super.viewDidLoad()
let imageTap = UITapGestureRecognizer(target: self, action: #selector(openImagePicker))
profileImageView.isUserInteractionEnabled = true
profileImageView.addGestureRecognizer(imageTap)
profileImageView.layer.cornerRadius = profileImageView.bounds.height / 2
profileImageView.clipsToBounds = true
//tapToChangeProfileButton.addTarget(self, action: #selector(openImagePicker), for: .touchUpInside)
imagePicker = UIImagePickerController()
imagePicker.allowsEditing = true
imagePicker.sourceType = .photoLibrary
imagePicker.delegate = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#objc func openImagePicker(_ sender:Any) {
// Open Image Picker
self.present(imagePicker, animated: true, completion: nil)
}
#IBAction func CreateAccount(_ sender: Any) {
guard let username = userNameTextField.text else { return }
guard let email = userEmailTextField.text else { return }
guard let pass = userPasswordTextField.text else { return }
guard let image = profileImageView.image else { return }
Auth.auth().createUser(withEmail: email, password: pass) { user, error in
if error == nil && user != nil {
print("User created!")
// 1. Upload the profile image to Firebase Storage
self.uploadProfileImage(image) { url in
if url != nil {
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.displayName = username
changeRequest?.photoURL = url
changeRequest?.commitChanges { error in
if error == nil {
print("User display name changed!")
self.saveProfile(username: username, profileImageURL: url!) { success in
if success {
self.dismiss(animated: true, completion: nil)
} else {
self.resetForm()
}
}
} else {
print("Error: \(error!.localizedDescription)")
self.resetForm()
}
}
} else {
self.resetForm()
}
}
} else {
self.resetForm()
}
}
}
func resetForm() {
let alert = UIAlertController(title: "Error signing up", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
func uploadProfileImage(_ image:UIImage, completion: #escaping ((_ url:URL?)->())) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let storageRef = Storage.storage().reference().child("user/\(uid)")
// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")
// Fetch the download URL
starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors
} else {
// Get the download URL for 'images/stars.jpg'
}
}
}
func saveProfile(username:String, profileImageURL:URL, completion: #escaping ((_ success:Bool)->())) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let databaseRef = Database.database().reference().child("users/profile/\(uid)")
let userObject = [
"username": username,
"photoURL": profileImageURL.absoluteString
] as [String:Any]
databaseRef.setValue(userObject) { error, ref in
completion(error == nil)
}
}
#IBAction func AlreadyaccountButtonTapped(_ sender: Any) {
print("Already account Button Tapped")
let LoginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
self.present(LoginViewController, animated: true)
}
//EmailVerificationViewController
#IBAction func ResendEmailVerificationTapped(_ sender: Any) {
self.sendVerificationMail()
}
#IBAction func LoginButtonTapped(_ sender: Any) {
print("Login Button Tapped")
let LoginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
self.present(LoginViewController, animated: true)
}
func displayMessage(userMessage:String) -> Void {
DispatchQueue.main.async
{
let alertController = UIAlertController(title: "Alert", message: userMessage, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in
// Code in this block will trigger when OK button tapped.
print("Ok button tapped")
DispatchQueue.main.async
{
self.dismiss(animated: true, completion: nil)
}
}
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion:nil)
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
}
}
extension SignUpViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
self.profileImageView.image = pickedImage
}
picker.dismiss(animated: true, completion: nil)
}
}
Thanks for your time !
Now the New Code with another i error that i mentioned in the Comment
#IBAction func CreateAccount(_ sender: Any) {
guard let username = userNameTextField.text else { return }
guard let image = profileImageView.image else { return }
Auth.auth().createUser(withEmail: self.userEmailTextField.text!, password: self.userPasswordTextField.text!) { user, error in
if error == nil && user != nil {
print("User created!")
// 1. Upload the profile image to Firebase Storage
self.uploadProfileImage(image, uid: user.uid) { url in
if url != nil {
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.displayName = username
changeRequest?.photoURL = url
changeRequest?.commitChanges { error in
if error == nil {
print("User display name changed!")
self.saveProfile(username: username, profileImageURL: url!) { success in
if success {
self.dismiss(animated: true, completion: nil)
} else {
self.resetForm()
}
}
} else {
print("Error: \(error!.localizedDescription)")
self.resetForm()
}
}
} else {
self.resetForm()
}
}
} else {
self.resetForm()
}
}
}
func resetForm() {
let alert = UIAlertController(title: "Error signing up", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
func uploadProfileImage(_ image:UIImage, uid:String, completion: #escaping ((_ url:URL?)->())) {
let storageRef = Storage.storage().reference().child("user/\(uid)")
// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")
// Fetch the download URL
starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors
} else {
// Get the download URL for 'images/stars.jpg'
}
}
}
You are getting that error because your url is nil.
It is nil because you are creating the user, upon successful creation self.uploadProfileImage(image) is called in order to get the image url of the current user but the user is not logged in.
A solution would be:
Sign in the user and upon success then call uploadProfileImage.

Value of type 'AuthDataResult' has no member 'uid'

I am a noob trying to create a social app through Youtube videos, and I am following instructions of this video.
https://youtu.be/GrRggN41VF0
At around 3 mins. of the video you'll see the code.
Here's the code I have.
import UIKit
import Firebase
import SwiftKeychainWrapper
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var userImgView: UIImageView!
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
override func viewDidLoad() {
emailField.delegate = self
passwordField.delegate = self
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
if let _ = KeychainWrapper.standard.string(forKey: "uid") {
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == emailField {
passwordField.becomeFirstResponder()
} else if textField == passwordField {
textField.resignFirstResponder()
}
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func signInPressed(_ sender: Any) {
if let email = emailField.text, let password = passwordField.text {
Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
if error != nil {
// Create Account
} else {
if let userID = user?.uid {
KeychainWrapper.standard.set((userID), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
}
}
}
}
Screenshot of the error
What am I doing wrong here and how do I fix this?
Try using:
if let user = Auth.auth().currentUser, let uid = user?.uid {
KeychainWrapper.standard.set((uid), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
Try using with the guard statement to unwrap optionals safely. Give it a try!
guard let uid = user?.uid else { return }
KeychainWrapper.standard.set((uid), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
or
guard let uid = Auth.auth().currentUser?.uid else { return }
KeychainWrapper.standard.set((uid), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
I hope this helps you..

Why incoming message can't show in the left side of the screen?

I got some error when I send photo message.
I'm a beginner with swift language. I want to create undergraduate project about chat app. I need some help to fix this problem. Everything had worked smoothly till now but I am facing a small bug that is when I receive an image then it don't appears on the left side of the screen both incoming and outgoing images appear on the right side of the screen.
import UIKit
import JSQMessagesViewController
import MobileCoreServices
import AVKit
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth
import SDWebImage
class ChatViewController: JSQMessagesViewController {
var messages = [JSQMessage]()
var avatarDict = [String: JSQMessagesAvatarImage]()
var messageRef = FIRDatabase.database().reference().child("messages")
override func viewDidLoad() {
super.viewDidLoad()
if let currentUser = FIRAuth.auth()?.currentUser
{
self.senderId = currentUser.uid
if currentUser.isAnonymous == true
{
self.senderDisplayName = "anonymous"
} else
{
self.senderDisplayName = "\(currentUser.displayName!)"
}
}
observeMessages()
}
func observeUsers(_ id: String)
{
FIRDatabase.database().reference().child("users").child(id).observe(.value, with: {
snapshot in
if let dict = snapshot.value as? [String: AnyObject]
{
let avatarUrl = dict["profileUrl"] as! String
self.setupAvatar(avatarUrl, messageId: id)
}
})
}
func setupAvatar(_ url: String, messageId: String)
{
if url != "" {
let fileUrl = URL(string: url)
let data = try? Data(contentsOf: fileUrl!)
let image = UIImage(data: data!)
let userImg = JSQMessagesAvatarImageFactory.avatarImage(with: image, diameter: 30)
self.avatarDict[messageId] = userImg
self.collectionView.reloadData()
} else {
avatarDict[messageId] = JSQMessagesAvatarImageFactory.avatarImage(with: UIImage(named: "profileImage"), diameter: 30)
collectionView.reloadData()
}
}
func observeMessages() {
messageRef.observe(.childAdded, with: { 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
self.observeUsers(senderId)
switch mediaType {
case "TEXT":
let text = dict["text"] as! String
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, text: text))
case "PHOTO":
let photo = JSQPhotoMediaItem(image: nil)
let fileUrl = dict["fileUrl"] as! String
let downloader = SDWebImageDownloader.shared()
downloader.downloadImage(with: URL(string: fileUrl)!, options: [], progress: nil, completed: { (image, data, error, finished) in
DispatchQueue.main.async(execute: {
photo?.image = image
self.collectionView.reloadData()
})
})
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photo))
if self.senderId == senderId {
photo?.appliesMediaViewMaskAsOutgoing = true
} else {
photo?.appliesMediaViewMaskAsOutgoing = false
}
case "VIDEO":
let fileUrl = dict["fileUrl"] as! String
let video = URL(string: fileUrl)!
let videoItem = JSQVideoMediaItem(fileURL: video, isReadyToPlay: true)
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: videoItem))
if self.senderId == senderId {
videoItem?.appliesMediaViewMaskAsOutgoing = true
} else {
videoItem?.appliesMediaViewMaskAsOutgoing = false
}
default:
print("unknown data type")
}
self.collectionView.reloadData()
}
})
}
override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!) {
let newMessage = messageRef.childByAutoId()
let messageData = ["text": text, "senderId": senderId, "senderName": senderDisplayName, "MediaType": "TEXT"]
newMessage.setValue(messageData)
self.finishSendingMessage()
}
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.present(sheet, animated: true, completion: nil)
}
func getMediaFrom(_ type: CFString) {
print(type)
let mediaPicker = UIImagePickerController()
mediaPicker.delegate = self
mediaPicker.mediaTypes = [type as String]
self.present(mediaPicker, animated: true, completion: nil)
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageDataForItemAt indexPath: IndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAt indexPath: IndexPath!) -> JSQMessageBubbleImageDataSource! {
let message = messages[indexPath.item]
let bubbleFactory = JSQMessagesBubbleImageFactory()
if message.senderId == self.senderId {
return bubbleFactory!.outgoingMessagesBubbleImage(with: .black)
} else {
return bubbleFactory!.incomingMessagesBubbleImage(with: .blue)
}
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! {
let message = messages[indexPath.item]
return avatarDict[message.senderId]
//return JSQMessagesAvatarImageFactory.avatarImageWithImage(UIImage(named: "profileImage"), diameter: 30)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("number of item:\(messages.count)")
return messages.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell
return cell
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAt indexPath: IndexPath!) {
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.present(playerViewController, animated: true, completion: nil)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func logoutDidTapped(_ sender: AnyObject) {
do {
try FIRAuth.auth()?.signOut()
} catch let error {
print(error)
}
// Create a main storyboard instance
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// From main storyboard instantiate a View controller
let LogInVC = storyboard.instantiateViewController(withIdentifier: "LogInVC") as! LogInViewController
// Get the app delegate
let appDelegate = UIApplication.shared.delegate as! AppDelegate
// Set LogIn View Controller as root view controller
appDelegate.window?.rootViewController = LogInVC
}
func sendMedia(_ picture: UIImage?, video: URL?) {
print(picture)
print(FIRStorage.storage().reference())
if let picture = picture {
let filePath = "\(FIRAuth.auth()!.currentUser)/\(Date.timeIntervalSinceReferenceDate)"
print(filePath)
let data = UIImageJPEGRepresentation(picture, 0.1)
let metadata = FIRStorageMetadata()
metadata.contentType = "image/jpg"
FIRStorage.storage().reference().child(filePath).put(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)/\(Date.timeIntervalSinceReferenceDate)"
print(filePath)
let data = try? Data(contentsOf: video)
let metadata = FIRStorageMetadata()
metadata.contentType = "video/mp4"
FIRStorage.storage().reference().child(filePath).put(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)
}
}
}
}
extension ChatViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("did finish picking")
// get the image
print(info)
if let picture = info[UIImagePickerControllerOriginalImage] as? UIImage {
sendMedia(picture, video: nil)
}
else if let video = info[UIImagePickerControllerMediaURL] as? URL {
sendMedia(nil, video: video)
}
self.dismiss(animated: true, completion: nil)
collectionView.reloadData()
}
}
You just need to understand what is going on in your code , as i am looking into your code you are reloading collectionview before the JSQPhotoMediaItem or JSQVideoMediaItem objects are completely configured and added these MediaItem into your message array, so make sure you have completely configured your JSQPhotoMediaItem and JSQVideoMediaItem objects and only after that you add these object to your message array.
you can add this into your switch case condition
case "PHOTO":
let photo = JSQPhotoMediaItem(image: nil)
let fileUrl = dict["fileUrl"] as! String
let downloader = SDWebImageDownloader.shared()
downloader.downloadImage(with: URL(string: fileUrl)!, options: [], progress: nil, completed: { (image, data, error, finished) in
DispatchQueue.main.async(execute: {
photo?.image = image // you have image in your media object
if self.senderId == senderId {
photo?.appliesMediaViewMaskAsOutgoing = true
} else {
photo?.appliesMediaViewMaskAsOutgoing = false
}
// you just configured media object by using appliesMediaViewMaskAsOutgoing
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photo))
// successfully added object into your message array now you should reload collectionview
self.collectionView.reloadData()
})
})
//same goes for your video condition
But still i would recommend you to follow each step one by one.
Follow these steps for adding A JSQPhotoMediaItem object
make a JSQPhotoMediaItem Object like
let photoItem = JSQPhotoMediaItem(image: UIImage(named: <your Image Object>))
make sure you have downloaded your image from server and successfully have your image object ready to add in the JSQPhotoMediaItem Object (as you are downloading it from firebase) first get the image then add it to your JSQPhotoMediaItem
now you have to tell your message type( outgoing or incoming ) so add appliesMediaViewMaskAsOutgoing property to according to you need so this would be in your code
if self.senderId == senderId {
photoItem?.appliesMediaViewMaskAsOutgoing = true
} else {
photoItem?.appliesMediaViewMaskAsOutgoing = false
}
now this is the final step for appending this object to your array
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photoItem))
now reload collectionView as you have successfully configured your media item ( JSQPhotoMediaItem )
self.collectionView.reloadData()
same goes for the JSQVideoMediaItem objects.

How to get the key of a value in Firebase?

I'm using Swift 3
I have this social network like twitter and im trying to retrive the user's following list but i'm having some troubles, my idea is to get them so i can use them to then do a for loop and retrive the Posts or Tweets, so something like this
self.databaseRef.child("following").child((self.loggedInUser?.uid)!).observeSingleEvent(of: .value) { (snapshot:FIRDataSnapshot) in
for child in snapshot.children {
self.databaseRef.child("Jalas").child((child as AnyObject).key!).observe(.childAdded, with: { (snapshot:FIRDataSnapshot) in
if (snapshot.value as? NSDictionary != nil)
{
self.Jalas.append(snapshot.value as! NSDictionary)
}
}){(error) in
print(error.localizedDescription)
}
}
self.homeTableView.beginUpdates()
self.homeTableView.insertRows(at: [IndexPath(row:0,section:0)], with: UITableViewRowAnimation.automatic)
self.homeTableView.endUpdates()
self.aivLoading.stopAnimating()
}
and in number of rows in section i'm returning self.Jalas.count but this does nothing. and it throws me an error.
"attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update"
this is my database.
Jalas = Posts
{
"Jalas" : {
"dEXaVLDOSPfJa3zTyUNqAEtVuMR2" : {
"-KbHUnL-RveUQa3MPSWp" : {
"latitud" : "21.111401000574",
"longitud" : "-89.6112191677094",
"text" : "Fiesta en la Anahuac!!! ",
"timestamp" : "1485295269.30773",
"ubicacionN" : "Universidad Anáhuac Mayab"
},
"-KbI1azr6uFel-5uTZOD" : {
"latitud" : "Optional(21.018988764483463)",
"longitud" : "Optional(-89.614319546492695)",
"text" : "Hola chicos",
"timestamp" : "1485304393.77929",
"ubicacionN" : "Calle 53-A 341"
},
"-KbNQWxjQhc0Ce_ZQbq9" : {
"latitud" : "Optional(21.019219877217914)",
"longitud" : "Optional(-89.614173537203683)",
"text" : "Hola",
"timestamp" : "1485394812.83039",
"ubicacionN" : "Calle 53 341"
}
},
"mt0fzirhMhazIcy90MRWuRpTfmE2" : {
"-KbQOWfUnzY1JiS61J6-" : {
"latitud" : "Optional(21.111502615883129)",
"longitud" : "Optional(-89.611767497121221)",
"text" : "Hola chicos!",
"timestamp" : "1485444619.10931",
"ubicacionN" : "Carretera Mérida-Progreso 96"
}
}
},
"follower" : {
"dEXaVLDOSPfJa3zTyUNqAEtVuMR2" : {
"mt0fzirhMhazIcy90MRWuRpTfmE2" : true
},
"mt0fzirhMhazIcy90MRWuRpTfmE2" : {
"dEXaVLDOSPfJa3zTyUNqAEtVuMR2" : true
}
},
"following" : {
"dEXaVLDOSPfJa3zTyUNqAEtVuMR2" : {
"mt0fzirhMhazIcy90MRWuRpTfmE2" : true
},
"mt0fzirhMhazIcy90MRWuRpTfmE2" : {
"dEXaVLDOSPfJa3zTyUNqAEtVuMR2" : true
}
},
"handles" : {
"jcadmin" : "mt0fzirhMhazIcy90MRWuRpTfmE2",
"jcbest" : "dEXaVLDOSPfJa3zTyUNqAEtVuMR2"
},
"user_profiles" : {
"dEXaVLDOSPfJa3zTyUNqAEtVuMR2" : {
"about" : "Hola Mundo",
"handle" : "jcbest",
"name" : "Juan Carlos Estevez Rodriguez",
"profile_pic" : "https://firebasestorage.googleapis.com/v0/b/jalo-267da.appspot.com/o/user_profiles%2FOptional(%22dEXaVLDOSPfJa3zTyUNqAEtVuMR2%22)%2Fprofile_pic?alt=media&token=bfc3c516-7849-472c-b7cd-9668965a5dbe"
},
"mt0fzirhMhazIcy90MRWuRpTfmE2" : {
"about" : "Hola chicos",
"handle" : "jcadmin",
"name" : "Juan Carlos",
"profile_pic" : "https://firebasestorage.googleapis.com/v0/b/jalo-267da.appspot.com/o/user_profiles%2FOptional(%22mt0fzirhMhazIcy90MRWuRpTfmE2%22)%2Fprofile_pic?alt=media&token=b741b6c1-0bc5-446d-a1e5-159b21e770d2"
}
}
}
This is my entire code.
//
// HomeViewController.swift
// Twitter Clone
//
// Created by Juan Carlos Estevez on 15/12/16.
// Copyright © 2016 JC&C. All rights reserved.
//
import UIKit
import FirebaseDatabase
import FirebaseAuth
import SDWebImage
import ReadMoreTextView
class HomeViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UIScrollViewDelegate {
var databaseRef = FIRDatabase.database().reference()
var loggedInUser:AnyObject?
var loggedInUserData:NSDictionary?
var listFollowing = [NSDictionary?]()
var listFollowers = [NSDictionary?]()//store all the followers
#IBOutlet weak var aivLoading: UIActivityIndicatorView!
#IBOutlet weak var homeTableView: UITableView!
var defaultImageViewHeightConstraint:CGFloat = 77.0
var Jalas = [NSDictionary]()
override func viewDidLoad() {
super.viewDidLoad()
self.homeTableView.separatorStyle = .none
//self.homeTableView.backgroundView?.backgroundColor = UIColor.init(red: 247, green: 247, blue: 247, alpha: 1)
UITabBar.appearance().tintColor = UIColor.orange
navigationController?.navigationBar.barTintColor = UIColor.orange
Evento.sharedInstance.titulo = ""
Evento.sharedInstance.UbicacionN = nil
self.loggedInUser = FIRAuth.auth()?.currentUser
self.databaseRef.child("following").child((self.loggedInUser?.uid)!).observeSingleEvent(of: .value) { (snapshot:FIRDataSnapshot) in
for child in snapshot.children {
self.databaseRef.child("Jalas").child((child as AnyObject).key!).observeSingleEvent(of: .value) { (snapshot:FIRDataSnapshot) in
//if (snapshot.value as? NSDictionary != nil)
//{
self.Jalas.append(snapshot.value as! NSDictionary)
//}
}
}
//self.homeTableView.beginUpdates()
self.homeTableView.insertRows(at: [IndexPath(row:0,section:0)], with: UITableViewRowAnimation.automatic)
//self.homeTableView.endUpdates()
self.aivLoading.stopAnimating()
}
/*
//get the logged in users details
self.databaseRef.child("user_profiles").child(self.loggedInUser!.uid).observeSingleEvent(of: .value) { (snapshot:FIRDataSnapshot) in
//store the logged in users details into the variable
self.logdInUserData = snapshot.value as? NSDictionary
// print(self.loggedInUserData)
//get all the Jalas that are made by the user
self.databaseRef.child("Jalas").child(self.loggedInUser!.uid).observe(.childAdded, with: { (snapshot:FIRDataSnapshot) in
//self.Jalas.append(snapshot.value as! NSDictionary)
self.homeTableView.insertRows(at: [IndexPath(row:0,section:0)], with: UITableViewRowAnimation.automatic)
self.aivLoading.stopAnimating()
}){(error) in
print(error.localizedDescription)
}
}
*/
//when the user has no posts, stop animating the aiv after 5 seconds
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(stopAnimating), userInfo: nil, repeats: false)
self.homeTableView.rowHeight = UITableViewAutomaticDimension
self.homeTableView.estimatedRowHeight = 140
/*
self.databaseRef.child("following").child(self.loggedInUser!.uid).observe(.childAdded, with: { (snapshot) in
let snapshot = snapshot.value as? NSDictionary
self.listFollowing.append(snapshot)
print(self.listFollowing)
}) { (error) in
print(error.localizedDescription)
}
self.databaseRef.child("followers").child(self.loggedInUser!.uid).observe(.childAdded, with: { (snapshot) in
let snapshot = snapshot.value as? NSDictionary
self.listFollowers.append(snapshot)
print(self.listFollowers)
}) { (error) in
print(error.localizedDescription)
}
*/
}
#IBAction func NewJalo(_ sender: Any) {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let welcomeViewController: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "new")
self.present(welcomeViewController, animated: true, completion: nil)
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UITabBar.appearance().tintColor = UIColor.orange
return true
}
open func stopAnimating()
{
self.aivLoading.stopAnimating()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.Jalas.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.separatorStyle = .none
var ubicacion = ""
let cell: HomeViewTableViewCell = tableView.dequeueReusableCell(withIdentifier: "HomeViewTableViewCell", for: indexPath) as! HomeViewTableViewCell
cell.contentView.backgroundColor = UIColor.clear
let JaloPost = Jalas[(self.Jalas.count-1) - (indexPath.row)]["text"] as! String
var HG = 105
let CHAR = JaloPost.characters.count
if (CHAR > 30)
{
let CH = ((CHAR/30) * 15)
HG += CH
}
if(Jalas[(self.Jalas.count-1) - (indexPath.row)]["picture"] != nil)
{
HG += 77
}
let whiteRoundedView : UIView = UIView(frame: CGRect(x: 10, y: 8, width: Int(self.view.frame.size.width - 20), height: HG))
whiteRoundedView.layer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.9])
whiteRoundedView.layer.masksToBounds = false
whiteRoundedView.layer.cornerRadius = 2.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1, height: 1)
whiteRoundedView.layer.shadowOpacity = 0.2
cell.contentView.addSubview(whiteRoundedView)
cell.contentView.sendSubview(toBack: whiteRoundedView)
let imageTap = UITapGestureRecognizer(target: self, action: #selector(self.didTapMediaInTweet(_:)))
cell.tweetImage.addGestureRecognizer(imageTap)
if(Jalas[(self.Jalas.count-1) - (indexPath.row)]["ubicacionN"] != nil)
{
ubicacion = (Jalas[(self.Jalas.count-1) - (indexPath.row)]["ubicacionN"] as? String)!
}
if(Jalas[(self.Jalas.count-1) - (indexPath.row)]["picture"] != nil)
{
cell.tweetImage.isHidden = false
cell.imageViewHeightConstraint.constant = defaultImageViewHeightConstraint
let picture = Jalas[(self.Jalas.count-1) - (indexPath.row)]["picture"] as! String
let url = URL(string:picture)
cell.tweetImage.layer.cornerRadius = 10
cell.tweetImage.layer.borderWidth = 3
cell.tweetImage.layer.borderColor = UIColor.clear.cgColor
cell.tweetImage!.sd_setImage(with: url, placeholderImage: UIImage(named:"twitter")!)
}
else
{
cell.tweetImage.isHidden = true
cell.imageViewHeightConstraint.constant = 0
}
if (self.loggedInUserData!["profile_pic"] == nil)
{
cell.configure(nil,name:self.loggedInUserData!["name"] as! String,handle:self.loggedInUserData!["handle"] as! String,tweet:JaloPost, ubi: ubicacion)
}else
{
cell.configure(self.loggedInUserData!["profile_pic"]! as? String,name:self.loggedInUserData!["name"] as! String,handle:self.loggedInUserData!["handle"] as! String,tweet:JaloPost, ubi: ubicacion)
}
return cell
}
func didTapMediaInTweet(_ sender:UITapGestureRecognizer)
{
let imageView = sender.view as! UIImageView
let newImageView = UIImageView(image: imageView.image)
newImageView.frame = self.view.frame
newImageView.backgroundColor = UIColor.black
newImageView.contentMode = .scaleAspectFit
newImageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target:self,action:#selector(self.dismissFullScreenImage))
newImageView.addGestureRecognizer(tap)
self.view.addSubview(newImageView)
}
func dismissFullScreenImage(_ sender:UITapGestureRecognizer)
{
sender.view?.removeFromSuperview()
}
/*
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "findUserSegue")
{
var showFollowingTableViewController = segue.destination as! FollowUsersTableViewController
showFollowingTableViewController.loggedInUser = self.loggedInUser as? FIRUser
// showFollowingTableViewController.followData = self.followData
}
else if(segue.identifier == "showFollowersTableViewController")
{
var showFollowersTableViewController = segue.destination as! ShowFollowersTableViewController
showFollowersTableViewController.user = self.loggedInUser as? FIRUser
}
}
*/
}
And this is my Table View Cell code.
//
// HomeViewTableViewCell.swift
// Jalo
//
// Created by Juan Carlos Estevez Rodriguez on 24/08/16.
// Copyright © 2016 JC&C. All rights reserved.
//
import UIKit
open class HomeViewTableViewCell: UITableViewCell {
#IBOutlet weak var profilePic: UIImageView!
#IBOutlet weak var name: UILabel!
#IBOutlet weak var handle: UILabel!
#IBOutlet weak var tweet: UITextView!
#IBOutlet weak var tweetImage: UIImageView!
#IBOutlet weak var ubic: UILabel!
#IBOutlet weak var imageViewHeightConstraint: NSLayoutConstraint!
override open func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
open func configure(_ profilePic:String?,name:String,handle:String,tweet:String, ubi:String)
{
self.tweet.text = tweet
self.handle.text = "#"+handle
self.name.text = name
self.ubic.text = ubi
if((profilePic) != nil)
{
let imageData = try? Data(contentsOf: URL(string:profilePic!)!)
self.profilePic.image = UIImage(data:imageData!)
}
else
{
self.profilePic.image = UIImage(named:"twitter")
}
}
}
This
self.homeTableView.beginUpdates()
self.homeTableView.insertRows(at: [IndexPath(row:0,section:0)], with: UITableViewRowAnimation.automatic)
self.homeTableView.endUpdates()
Segment is what's most likely causing your problem. Won't be sure until you edit your question and add the exact error.
When you use .insertRows() in a UITableView, you need to make sure that the count in numberOfRows inSection method also changes accordingly. What you have here is just a mismatch between the number of rows returned by the delegate method and the actual number of rows. Make sure that when you use .insertRows() you return the new expected number of rows in the delegate method!

Resources