UITableViewCell were narrowed when first load - ios

When the cells first appear,they will look like my picture shows.If scroll top then scroll down let them show again,they will be normal.The top three cells is always being normal while the bottom are narrowed.This is my code`
import UIKit
class AllCommentsViewController: UIViewController {
#IBAction func unwindToAllComments(sender: UIStoryboardSegue){
if sender.identifier == "unwindToAllComments"{
}
}
override func awakeFromNib() {
let photo = ZLLPhoto(withoutDataWithObjectId: "55cd717700b0875fb6cc125f")
photo.fetch()
self.photo = photo
}
var photo: ZLLPhoto!
var comments = [ZLLComment]()
#IBAction func commentButtonClicked(sender: UIButton){
performSegueWithIdentifier("comment", sender: nil)
}
private func initialCommentsQuery() -> AVQuery {
let query = ZLLComment.query()
query.whereKey("photo", equalTo: photo)
query.limit = 20
query.orderByDescending("likeCount")
query.addDescendingOrder("createdAt")
query.includeKey("score")
query.includeKey("author")
return query
}
func getFirst(){
initialCommentsQuery().findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
if objects.count != 0 {
let comments = objects as! [ZLLComment]
self.comments = comments
var indexPaths = [NSIndexPath]()
for i in 0..<objects.count{
var indexPath = NSIndexPath(forRow: i, inSection: 2)
indexPaths.append(indexPath)
}
self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .None)
self.tableView.endUpdates()
self.tableView.footer.endRefreshing()
self.tableView.footer = MJRefreshAutoNormalFooter(refreshingTarget: self, refreshingAction: "loadMore")
self.tableView.header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: "refresh")
}
}else{
print(error)
}
self.tableView.footer.endRefreshing()
}
}
func loadMore(){
let last = comments.last!
let query = initialCommentsQuery()
query.whereKey("likeCount", lessThanOrEqualTo: last.likeCount)
query.whereKey("createdAt", lessThan: last.createdAt)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
if objects.count != 0{
var indexPaths = [NSIndexPath]()
for i in 0..<objects.count{
let indexPath = NSIndexPath(forRow: self.comments.count + i, inSection: 2)
indexPaths.append(indexPath)
}
let comments = objects as! [ZLLComment]
self.comments.extend(comments)
self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .None)
self.tableView.endUpdates()
}
}else{
print(error)
}
self.tableView.footer.endRefreshing()
}
}
func refresh(){
let first = comments.first!
let query = initialCommentsQuery()
query.whereKey("likeCount", greaterThanOrEqualTo: first.likeCount)
query.whereKey("createdAt", greaterThan: first.createdAt)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
if objects.count != 0 {
var comments = objects as! [ZLLComment]
comments.extend(self.comments)
self.comments = comments
var indexPaths = [NSIndexPath]()
for i in 0..<objects.count{
var indexPath = NSIndexPath(forRow: i, inSection: 2)
indexPaths.append(indexPath)
}
self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths(indexPaths,
withRowAnimation: UITableViewRowAnimation.None)
self.tableView.endUpdates()
}
}else{
print(error)
}
self.tableView.header.endRefreshing()
}
}
#IBOutlet weak var commentButton: UIButton!
#IBOutlet weak var photoTitle: UILabel!{
didSet{
photoTitle.text = photo.title
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "comment" {
let VC = segue.destinationViewController as! CommentPhotoViewController
VC.photo = photo
}else if segue.identifier == "showUser"{
let VC = segue.destinationViewController as! UserInfoTableViewController
VC.user = sender as! ZLLUser
}
}
#IBAction func likeButtonClicked(sender: UIButton) {
let indexPath = tableView.indexPathForCellContainingView(sender)!
let comment = comments[indexPath.row]
let I = ZLLUser.currentUser()
let cell = tableView.cellForRowAtIndexPath(indexPath) as! CommentCell
if !cell.liked{
I.likeComment(comment, completion: { (error) -> Void in
if error == nil {
comment.incrementKey("likeCount")
cell.likeCount += 1
cell.liked = true
}else{
print(error)
}
})
}else{
I.unlikeComment(comment, completion: { (error) -> Void in
if error == nil{
comment.incrementKey("likeCount", byAmount: -1)
cell.likeCount -= 1
cell.liked = false
}else{
print(error)
}
})
}
}
//XIBload
#IBOutlet weak var tableView: UITableView!
#IBOutlet var titleScoreLabel: UILabel?
#IBOutlet var titleLabel: UILabel?
#IBOutlet var photoCell: UITableViewCell!
override func viewDidLoad() {
NSBundle.mainBundle().loadNibNamed("PhotoCell", owner: self, options: nil)
tableView.footer = MJRefreshAutoNormalFooter(refreshingTarget: self, refreshingAction: "getFirst")
let query = ZLLScore.query()
query.whereKey("photo", equalTo: photo)
query.whereKey("scorer", equalTo: ZLLUser.currentUser())
query.countObjectsInBackgroundWithBlock { (count, error) -> Void in
if error == nil {
if count > 0{
self.commentButton.setImage(UIImage(named: "comments_add_comment")!, forState: UIControlState.Normal)
}
}else{
print(error)
}
}
}
}
extension AllCommentsViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch indexPath.section {
case 0:
let cell = tableView.dequeueReusableCellWithIdentifier("photoCell") as! PhotoCell
cell.loadPhoto2(photo)
return cell
case 1:
tableView
let cell = tableView.dequeueReusableCellWithIdentifier("commentCell", forIndexPath: indexPath) as! CommentCell
cell.loadPhotoInfo(photo)
return cell
default:
let cell = tableView.dequeueReusableCellWithIdentifier("commentCell", forIndexPath: indexPath) as! CommentCell
if indexPath.row == 0{
cell.smallTagImage.image = UIImage(named: "jian")
return cell
}
cell.delegate = self
cell.loadComment(comments[indexPath.row])
return cell
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section{
case 2:
return comments.count
default:
return 1
}
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 1
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
switch section{
case 0:
return 1
default:
return 10
}
}
}
extension AllCommentsViewController: PhotoCellDelegate{
func photoCellDidTapUserField(photoCell: PhotoCell) {
}
func photoCellDidClickShareButton(photoCell: PhotoCell) {
//
let indexPath = tableView.indexPathForCell(photoCell)!
let share = UIAlertController(title: "分享图片", message: "\(photo.title)", preferredStyle: UIAlertControllerStyle.ActionSheet)
let weibo = UIAlertAction(title: "微博", style: UIAlertActionStyle.Default) { (action) -> Void in
if !WeiboSDK.isWeiboAppInstalled(){
ZLLViewModel.showHintWithTitle("未安装微博应用", on: self.view)
return
}
if !ShareSDK.hasAuthorizedWithType(ShareTypeSinaWeibo){
let authorize = UIAlertController(title: "未获取授权", message: "是否要获取授权", preferredStyle: UIAlertControllerStyle.Alert)
let confirm = UIAlertAction(title: "确认", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
ShareSDK.getUserInfoWithType(ShareTypeSinaWeibo, authOptions: nil, result: { (result, userInfo, errorInfo) -> Void in
if !result {
ZLLViewModel.showHintWithTitle("授权失败!", on: self.view)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeSinaWeibo, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
})
})
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
authorize.addAction(confirm)
authorize.addAction(cancel)
self.presentViewController(authorize, animated: true, completion: nil)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeSinaWeibo, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
}
let qZone = UIAlertAction(title: "qq空间", style: UIAlertActionStyle.Default) { (action) -> Void in
//
if !QQApiInterface.isQQInstalled(){
ZLLViewModel.showHintWithTitle("未安装腾讯QQ", on: self.view)
return
}
if !ShareSDK.hasAuthorizedWithType(ShareTypeQQSpace){
let authorize = UIAlertController(title: "未获取授权", message: "是否要获取授权", preferredStyle: UIAlertControllerStyle.Alert)
let confirm = UIAlertAction(title: "确认", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
ShareSDK.getUserInfoWithType(ShareTypeQQSpace, authOptions: nil, result: { (result, userInfo, errorInfo) -> Void in
if !result {
ZLLViewModel.showHintWithTitle("授权失败!", on: self.view)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeQQSpace, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
})
})
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
authorize.addAction(confirm)
authorize.addAction(cancel)
self.presentViewController(authorize, animated: true, completion: nil)
return
}
let image = UIImage(data: self.photo.imageFile.getData())
let data = UIImageJPEGRepresentation(image, 0.1)
let attachment = ShareSDK.imageWithData(data, fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: attachment, title: "c", url: "www.baidu.com", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeQQSpace, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
}
let weixin = UIAlertAction(title: "微信好友", style: UIAlertActionStyle.Default) { (action) -> Void in
if !QQApiInterface.isQQInstalled(){
ZLLViewModel.showHintWithTitle("未安装腾讯QQ", on: self.view)
return
}
if !ShareSDK.hasAuthorizedWithType(ShareTypeQQSpace){
let authorize = UIAlertController(title: "未获取授权", message: "是否要获取授权", preferredStyle: UIAlertControllerStyle.Alert)
let confirm = UIAlertAction(title: "确认", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
ShareSDK.getUserInfoWithType(ShareTypeQQ, authOptions: nil, result: { (result, userInfo, errorInfo) -> Void in
if !result {
ZLLViewModel.showHintWithTitle("授权失败!", on: self.view)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeQQ, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
})
})
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
authorize.addAction(confirm)
authorize.addAction(cancel)
self.presentViewController(authorize, animated: true, completion: nil)
return
}
let image = ShareSDK.imageWithData(self.photo.imageFile.getData(), fileName: "test1", mimeType: "")
let content = ShareSDK.content("a", defaultContent: "b", image: image, title: "c", url: "", description: "d", mediaType: SSPublishContentMediaTypeImage)
ShareSDK.clientShareContent(content, type: ShareTypeQQ, statusBarTips: true, result: { (type, state, shareInfo, errorInfo, end) -> Void in
})
}
let pengyouquan = UIAlertAction(title: "朋友圈", style: UIAlertActionStyle.Default) { (action) -> Void in
}
let cancl = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
share.addAction(weibo)
share.addAction(qZone)
share.addAction(weixin)
share.addAction(pengyouquan)
share.addAction(cancl)
self.presentViewController(share, animated: true, completion: nil)
}
func photoCellDidClickMoreButton(photoCell: PhotoCell) {
let indexPath = tableView.indexPathForCell(photoCell)!
let alertController = UIAlertController(title: "更多", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)
let report = UIAlertAction(title: "举报", style: UIAlertActionStyle.Default) { (alertAction) -> Void in
let confirmReport = UIAlertController(title: "确认举报?", message: nil, preferredStyle: UIAlertControllerStyle.Alert)
let delete = UIAlertAction(title: "确认", style: UIAlertActionStyle.Destructive) { (alertAction) -> Void in
let report = ZLLReport.new()
report.reportedPhoto = self.photo
report.reporter = ZLLUser.currentUser()
let success = report.save()
if success{
ZLLViewModel.showHintWithTitle("举报成功", on: self.view)
}else{
ZLLViewModel.showHintWithTitle("举报失败", on: self.view)
}
}
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
confirmReport.addAction(delete)
confirmReport.addAction(cancel)
self.presentViewController(confirmReport, animated: true, completion: nil)
}
alertController.addAction(report)
if photo.owner.objectId == ZLLUser.currentUser().objectId{
let delete = UIAlertAction(title: "删除图片", style: UIAlertActionStyle.Destructive) { (alertAction) -> Void in
let confirmDelete = UIAlertController(title: "确认删除?", message: nil, preferredStyle: UIAlertControllerStyle.Alert)
let delete = UIAlertAction(title: "确认", style: UIAlertActionStyle.Destructive) { (alertAction) -> Void in
let success = self.photo.delete()
self.photo.deleteInBackgroundWithBlock({ (success, error) -> Void in
if success{
self.performSegueWithIdentifier("deleteComplete", sender: nil)
ZLLViewModel.showHintWithTitle("删除成功", on: self.view)
self.myPopBackButtonClicked(nil)
}else{
print(error)
}
})
}
let cancel = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
confirmDelete.addAction(delete)
confirmDelete.addAction(cancel)
self.presentViewController(confirmDelete, animated: true, completion: nil)
}
alertController.addAction(delete)
}
let cancelAction = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)
alertController.addAction(cancelAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
}
extension AllCommentsViewController: CommentCellProtocol{
func commentCellDidTapAuthorLabel(cell: CommentCell) {
let indexPath = tableView.indexPathForCell(cell)!
let comment = comments[indexPath.row]
let user = comment.author
performSegueWithIdentifier("showUser", sender: user)
}
}`

In Your PhotoCell class, add this snippet code.
override func didMoveToSuperview() {
layoutIfNeeded()
}

Your problem is in the section where you define your tableView.
In your tableView extension, you set the numberOfSectionsInTableView method to return 3 rows, so your code defining the cell dimensions only runs on the first 3 rows.
Try setting your numberOfSections method to the number of rows you want based on the dimensions of your view, it looks to be about 5.

Related

Download URL of firebase storage not working

I'm using the firebase for chat application and I've already stored the images in firebase storage now I want to get the url to fetch the user profile but it's not working even I've tried but nothing is working
Here is the function on line 3rd it generates an error (Value of type 'DatabaseReference' has no member 'downloadURL')
func downloadURL(for path: String, completion: #escaping (Result<URL, Error>) -> Void) {
let refrence = database.child(path)
refrence.downloadURL(completion: { url, error in //here downnloadUrl not working perfectly
guard let url = url, error == nil else {
completion(.failure(StorageErrors.failedToGetDownloadUrl))
return
}
completion(.success(url))
})
}
NetworkingService Class
struct NetworkingService{
static let shared = NetworkingService()
private init(){
}
private let database = Database.database().reference() //creating refrence
public func test(){
database.child("name").setValue(["faheem":true])
}
static func emailForImage(emailAddress: String) -> String{
var safeEmail = emailAddress.replacingOccurrences(of: ".", with: "-")
safeEmail = safeEmail.replacingOccurrences(of: "#", with: "-")
return safeEmail
}
func downloadURL(for path: String, completion: #escaping (Result<URL, Error>) -> Void) {
let refrence = database.child(path)
refrence.downloadURL(completion: { url, error in
guard let url = url, error == nil else {
completion(.failure(StorageErrors.failedToGetDownloadUrl))
return
}
completion(.success(url))
})
}
func userExists(email: String,completion: #escaping((Bool) -> Void)){ //return boolen
var safeEmail = email.replacingOccurrences(of: ".", with: "-")
safeEmail = safeEmail.replacingOccurrences(of: "#", with: "-")
database.child(safeEmail).observeSingleEvent(of: .value) { (snapshot) in
guard let foundEmail = snapshot.value as? String else {
completion(false)
return
}
}
completion(true)
}
func insertUser(user: CUser, completion: #escaping(Result<CUser,Error>) -> Void){
database.child(user.identifier).setValue(user.getDict) { (err, dbRef) in
if err != nil{
completion(.failure(err!))
}else{
completion(.success(user))
}
}
}
}
StoreManager Class
struct StoreManager{
static let shared = StoreManager()
private let storageRefrence = Storage.storage().reference()
func uploadProfilePic(data: Data, fileName: String, completion: #escaping(Result<String,Error>) -> Void){
storageRefrence.child("images/\(fileName)").putData(data,metadata: nil) { (metaData, error) in
guard error == nil else {
completion(.failure(AppError.failedToUpload))
print("faheem ye he error \(error?.localizedDescription)")
return
}
self.storageRefrence.child("images/\(fileName)").downloadURL { (url, error) in
guard let url = url else {
completion(.failure(AppError.failedtoDownloadUrl))
return
}
let urlString = url.absoluteString
print("download url is\(urlString)")
completion(.success(urlString))
}
}
}
}
SignupUserClass
class SignUpUserViewController: UIViewController {
#IBOutlet weak var userProfile: UIImageView!
#IBOutlet weak var lname: UITextField!
#IBOutlet weak var fname: UITextField!
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
var imagePicker = UIImagePickerController() // for imagepicker
private let spinner = JGProgressHUD(style: .dark)
var user:CUser!
override func viewDidLoad() {
super.viewDidLoad()
password.isSecureTextEntry = true
userProfile.layer.masksToBounds = true
userProfile.layer.borderWidth = 2
userProfile.layer.borderColor = UIColor.lightGray.cgColor
userProfile.layer.cornerRadius = userProfile.frame.size.height / 2
// for rounder image
userProfile.isUserInteractionEnabled = true /
let gesture = UITapGestureRecognizer(target: self, action: #selector(userProfileChange)) //photopcker
userProfile.addGestureRecognizer(gesture)
}
#objc private func userProfileChange(){
print("profile pic changed")
getPhoto()
}
private func insertUser(_ user:CUser){
NetworkingService.shared.insertUser(user: user) { (result) in
switch result{
case .success(let user):
print("User inserted: ", user.getDict)
CUser.shared = user
print("sahed Data is fahem\(CUser.shared)")
case .failure(let error):
print("Error: ",error.localizedDescription)
self.showAlert(message: error.localizedDescription)
}
}
}
private func createUser(_ user:CUser){
FirebaseAuth.Auth.auth().createUser(withEmail: user.email, password: user.password) { [weak self] (respomse, error) in
guard let data = respomse else {
print("Error: ",error?.localizedDescription ?? "")
self?.showAlert(message: error?.localizedDescription ?? "")
return
}
self?.insertUser(user)
}
}
private func uploadImage(_ imageData:Data) {
StoreManager.shared.uploadProfilePic(data: imageData, fileName: user.imageName) { (result) in
switch result{
case .success(let url):
self.user.imageURL = url
self.createUser(self.user)
case .failure(let error):
print("Error: ",error.localizedDescription)
self.showAlert(message: error.localizedDescription)
}
}
}
// register User
#IBAction func register(_ sender: UIButton) {
if checkTextFields([email,password,fname,lname]) {
showAlert(message: "Some fields are missing")
}else{
spinner.show(in: self.view)
NetworkingService.shared.userExists(email: email.text!) { (response) in//checking user through email
self.spinner.dismiss()
guard response != nil else { //measn user exists
self.showAlert(message: "user account already exits we verify through email")
return
}
self.user = CUser(firstName: self.fname.text!, lastName: self.lname.text!, email: self.email.text!, password: self.password.text!, imageURL: "")
/*image url is nil becuase we not upload the image here wehn calling the upload image method
then after setting create user method here we only setting the data in user model and url nil*/
if let userImage = self.userProfile.image!.jpegData(compressionQuality: 0.2) {
self.uploadImage(userImage)
}else{
print("Error: Image cannot be compressed")
}
}
}
}
func checkTextFields(_ textfields:[UITextField]) -> Bool{
for textfield in textfields {
return textfield.text?.isEmpty == true ? true: false
}
return true
}
func gotOLogin(){
guard let loginController = self.storyboard?.instantiateViewController(withIdentifier: String(describing: LoginUserViewController.self)) as? LoginUserViewController else {return}
self.navigationController?.pushViewController(loginController, animated: true)
}
func showAlert(title:String = "Error", message:String){
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let ok = UIAlertAction(title: "ok", style:.default, handler: nil)
alertController.addAction(ok)
self.present(alertController, animated: true, completion: nil)
}
}
extension SignUpUserViewController : UIImagePickerControllerDelegate, UINavigationControllerDelegate{
func getPhoto(){
let actionSheet = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
actionSheet.addAction(UIAlertAction(title: "Take Photo", style: .default, handler: {
[weak self] _ in
self?.presentCamera()
}))
actionSheet.addAction(UIAlertAction(title: "Choose Photo", style: .default, handler: { [weak self] _ in
self?.profilePhotoPicker()
}))
present(actionSheet, animated: true, completion: nil)
}
func presentCamera(){ //not allowed in simualtor to capture photo
imagePicker.sourceType = .camera
imagePicker.delegate = self
imagePicker.allowsEditing = true
present(imagePicker, animated: true, completion: nil)
}
func profilePhotoPicker(){
imagePicker.sourceType = .photoLibrary
imagePicker.delegate = self
imagePicker.allowsEditing = true
present(imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { //called when select photo
print(info)
userProfile.image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
imagePicker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
ProfileViewcontroler here is getProfilePic fun i already get all the necessary thing but issue is that in networking class download url is not working
class ProfileViewController: UIViewController {
var logoutUser = ["lgout"]
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var currentUserPic: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName: String(describing: ProfileCell.self), bundle: .main), forCellReuseIdentifier: String(describing: ProfileCell.self))
}
func getProfilePic(){
guard let userEmail = UserDefaults.standard.value(forKey: "useremail") as? String else {
return}
let userEmailForPic = NetworkingService.emailForImage(emailAddress: userEmail)
let fileName = userEmailForPic + "_profile_image_jpg"
let patheStorage = "images/"+fileName//here i want to fetch the pic but in netwroking class downnload url not working
}
}
Firebase Realtime Database and Firebase Storage are separated services. You should be using downloadURL on a storage reference:
func downloadURL(for path: String, completion: #escaping (Result<URL, Error>) -> Void) {
let reference = Storage.storage().reference().child(path)
reference.downloadURL(completion: { url, error in
guard let url = url, error == nil else {
completion(.failure(StorageErrors.failedToGetDownloadUrl))
return
}
completion(.success(url))
})
}

Swift: How to get data from selected cell?

I have a table view with list of users. I want to show guest details from firebase to UIALertController. When I clicked on cells, it give's me the details just for the first user, from the first cell.
Here is my code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)as! userTableViewCell
if cell.isClicked == true {
ref = Database.database().reference().child("userInfo").child(uid!).child("users")
ref.queryOrderedByKey().observe(.value) { (snapshot) in
if snapshot.childrenCount>0{
self.usersList.removeAll()
for users in snapshot.children.allObjects as![DataSnapshot]{
let userObject = users.value as? [String: AnyObject]
let userPhoneNumber = userObject?["PhoneNumber"]
let userEmail = userObject?["Email"]
let user = UserModel(userPhoneNumber: userPhoneNumber as? String, userEmail: userEmail as? String)
let phone = user.userPhoneNumber
let email = user.userEmail
let userInfo = "\(phone!) \n\(email!)"
let alert = UIAlertController(title: "User", message: userInfo, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .default)
alert.addAction(cancelAction)
let callAction = UIAlertAction(title: "Call", style: .default) { (action) in
if let number = guestPhoneNumber {
guard let url = URL(string: "teleprompt://\(number)") else{
return
}
UIApplication.shared.open(url)
}
}
alert.addAction(callAction)
self.present(alert, animated: true, completion: nil)
self.usersList.append(guest)
}
}
}
}
}

Downloading too many items in table view from Firebase

When I post from a different device, the tableview I on the current device keeps the items that were previously there and then downloads the items again including the new post, can anyone help me to make it so that it only displays one of each item?
I think the issue is in my downloadFromFirebase().
Here is my code:
class DisplayVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var captionField: RoundTextField!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var myMainImg: roundImage!
var imageSelected = false
static var imageCache: NSCache<NSString,UIImage> = NSCache()
var posts = [Post]() // array for the posts
var imagePicker: UIImagePickerController!
#IBAction func addImageTapped(_ sender: Any) {
present(imagePicker, animated: true, completion: nil)
}
#IBAction func logoutPressed(_ sender: Any) {
//remove keychain and sign out of firebase
let keychainResult = KeychainWrapper.standard.removeObject(forKey: KEY_UID)
print("AA: ID removed from keychain: \(keychainResult)")
try! FIRAuth.auth()?.signOut()
performSegue(withIdentifier: "goToSignIn", sender: nil)
}
#IBAction func postBtnTapped(_ sender: Any) {
//does this exist? or is it null? if condition is not true then it is executed
guard let caption = captionField.text, caption != "" else {
let alert = UIAlertController(title: "Bad Caption", message: "Caption must be entered", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
guard let img = myMainImg.image, imageSelected == true else {
let alert = UIAlertController(title: "Bad Image", message: "Image must be choosen", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
if let imgData = UIImageJPEGRepresentation(img, 0.2){
let imgUid = NSUUID().uuidString
let metadata = FIRStorageMetadata()
metadata.contentType = "image/jpeg"
DataService.ds.REF_POST_IMAGES.child(imgUid).put(imgData, metadata: metadata, completion: { (metadata, error) in
if error != nil{
print("unable to upload image to Firebase storage")
}else{
print("GREAT SUCESS FOR IMAGE ON STORAGE")
let downloadURL = metadata?.downloadURL()?.absoluteString
if let url = downloadURL{
self.postToFireBase(imageURL: url)
}
}
})
}
}
func postToFireBase(imageURL: String){
let post: Dictionary<String, AnyObject> = ["caption": captionField.text as AnyObject,"imageURL":imageURL as AnyObject, "likes":0 as AnyObject,"userName": userName as AnyObject]
let firebasePost = DataService.ds.REF_POSTS.childByAutoId()
firebasePost.setValue(post)
captionField.text = ""
imageSelected = false
myMainImg.image = UIImage(named: "add-image")
posts.removeAll()
tableView.reloadData()
}
//cannot use the view did load for the guard method!
override func viewDidAppear(_ animated: Bool) {
}
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
tableView.delegate = self
tableView.dataSource = self
imagePicker = UIImagePickerController()
imagePicker.allowsEditing = true
imagePicker.delegate = self
posts.removeAll()
self.downloadFromFirebase()
}
func downloadFromFirebase(){
//"POSTS" Listener, initialize listener and it will work constantly
DataService.ds.REF_POSTS.observe(.value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot]{
for snap in snapshot{
print("SNAP: \(snap)") // make free objects by parsing the JSON
if let postDict = snap.value as? Dictionary<String, AnyObject>{
let key = snap.key
let post = Post(postKey: key, postData: postDict)
self.posts.append(post) //stick the post in the posts Array
}
}
}
self.tableView.reloadData()
})
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count //number of total posts
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = posts[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell{
if let img = DisplayVC.imageCache.object(forKey: post.imageURL as NSString){
cell.configureCell(post: post, image: img)
return cell
}else{
cell.configureCell(post: post, image: nil)
return cell
}
}else{
return PostCell()
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerEditedImage] as? UIImage{
myMainImg.image = image
}else{
print("AA: Valid image wasn't selected")
}
imagePicker.dismiss(animated: true, completion: nil)
imageSelected = true
}
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
}
Try this:
Include after
let post = Post(postKey: key, postData: postDict)
the following:
if !posts.contains(post) {
self.post.append(post)
}
Let me know if it works!

How to download image from asynchronously in swift

Hi I am developing a app using swift2.2 am getting a data from a server and am passing it to the collection view.am getting more images from the server i cant pass it very quickly it consumes so much of time so i need to to pass that quickly as much as possible.
code in my view controller:
func jsonParsingFromURL() {
self.view.makeToastActivity(.Center)
if Reachability.isConnectedToNetwork() == true {
Alamofire.request(.POST, "http://something.com=\(appDelCityname)&fromLimit=0&toLimit=20", parameters: nil, encoding: .URL, headers: nil).response {
(req, res, data, error) - > Void in
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print(dataString)
let json = JSON(data: data!)
let jsonData = json["ad_count"].int
if jsonData == 0 {
let alert = UIAlertController(title: "sorry!", message: "No Ads availabe", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
} else {
self.startParsing(data!)
}
}
} else {
let alert = UIAlertController(title: "No Internet Connection", message: "make sure your device is connected to the internet", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
func startParsing(data: NSData) {
let json = JSON(data: data)
let mainArr = json["subcategory"].array!
for item in mainArr {
self.fetchImage = item["images"].stringValue
self.fetchPrice = item["originalprice"].stringValue
self.fetchTitle = item["adtitle"].stringValue
self.fetchCityname = item["districtname"].stringValue
let takefirstImg = self.fetchImage.componentsSeparatedByString(",")
let firstimgofStr = takefirstImg[0]
dispatch_async(dispatch_get_main_queue(), {
() - > Void in
let URL_API_HOST2: String = "https://www.something.com"
let url = NSURL(string: URL_API_HOST2 + firstimgofStr)
let data = NSData(contentsOfURL: url!)
let imageyy = UIImage(data: data!)
self.priceArr.append(self.fetchPrice)
self.cityArr.append(self.fetchCityname)
self.adtitleArr.append(self.fetchTitle)
print("something = \(firstimgofStr)")
print("check image = \(self.fetchTitle)")
self.imageDict.append(imageyy!)
self.view.hideToastActivity()
})
self.refresh()
}
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) - > Int {
return imageDict.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) - > UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("FilterCell", forIndexPath: indexPath) as!SecondTableViewCell
cell.FifTitle.text = adtitleArr[indexPath.item]
cell.FifAddress.text = cityArr[indexPath.item]
cell.Fifprice.text = priceArr[indexPath.item]
dispatch_async(dispatch_get_main_queue(), {
cell.Fifimage.image = self.imageDict[indexPath.item]
})
// cell.Fifimage.sd_setImageWithURL(NSURL(string: URL_API_HOST2 + (firstImage as String)))
return cell
}
func collectionView(collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) - > CGSize {
return imageDict[indexPath.item].size
}
I am having the library of SDWebImage but which will allow only url type but i have to use UIImage value to calculate the size of image to get Pinterest style view.according to my method it works well but when i get more value from the server it makes very late to display so help me to work with this process am struggling from the morning.

Why is my firebase database not waiting to update values

So I am really new to threading and I've been reading up on it all day. For some reason though the data isn't loading before other code executes
Basically I need all the values that have a key ["whatever"] to be filled into an array, which works in other places because I don't need to load it first. So i have checked and double checked the keys that I am updating do exist and the keys I am extracting do exist maybe not the values yet but the keys do.
The problem is the code goes to fast to through the method. How would I make the main thread wait untill my firebase has loaded the data I have tried it below but it does not seem to be working
here is my code
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let alertController = UIAlertController(title: "Accept Bet", message: "Match the bet of " + amountBets[indexPath.row], preferredStyle: .alert)
let okButton = UIAlertAction(title: "No", style: .default, handler: { (action) -> Void in
print("Ok button tapped")
})
let yesButton = UIAlertAction(title: "Yes", style: .default, handler: { (action) -> Void in
// let them know to wait a second or the bet won't go through
var waitController = UIAlertController(title: "Please Wait", message: "You must wait for the bet to go through", preferredStyle: .alert)
self.present(waitController, animated: true, completion: nil)
//take away that bitches money
self.takeAwayMoney(self.amountBets[indexPath.row], completion: { (result: Bool?) in
guard let boolResult = result else {
return
}
if boolResult == true {
self.updateBet(indexPath.row, completion: {(result: String?) in
guard let resultRecieved = result else {
return
}
print(self.opposingUserNames)
//let delayInSeconds = 7.0 // 1
//DispatchQueue.main.asyncAfter(deadline: .now() + delayInSeconds) { // 2
self.dismiss(animated: true, completion: nil)
let successController = UIAlertController(title: "Success", message: "You have made a bet with " + self.opposingUserNames!, preferredStyle: .alert)
let okButt = UIAlertAction(title: "Ok", style: .default, handler: nil)
successController.addAction(okButt)
self.present(successController, animated: true, completion: nil)
//lastly delete the opposing UserName
print(self.opposingUserNames)
self.amountBets.remove(at: indexPath.row)
self.tableView.reloadData()
print("Second")
print(self.opposingUserNames)
//}
})
} else {
return
}
})
//then delete that cell and do another pop up that says successful
// check if value is yes or no in the database
})
alertController.addAction(okButton)
alertController.addAction(yesButton)
present(alertController, animated: true, completion: nil)
}
The below function updates the values OpposingUsername and show
func updateBet(_ index: Int, completion: #escaping (_ something: String?) -> Void) {
let userID = FIRAuth.auth()?.currentUser?.uid
datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
// ...
self.datRef.child("Bets").observe(.childAdded, with: { snapshot in
//
// this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P
guard let dict = snapshot.value as? [String: AnyHashable] else {
print("failed to get dictionary from Bets.\(self.userName)")
return
}
let values = ["OpposingUsername": self.userName,"Show": "no"]
self.datRef.child("Bets").child(self.tieBetToUser[index]).updateChildValues(values)
// now get the opposing username which is just the Username registered to that specific bet
self.datRef.child("Bets").child(self.tieBetToUser[index]).observe(.childAdded, with: { snapshot in
guard let dict2 = snapshot.value as? [String: AnyHashable] else {
return
}
let userNameOfOtherPlayer = dict2["Username"] as? String
self.opposingUserNames = userNameOfOtherPlayer!
completion(self.opposingUserNames)
})
})
}) { (error) in
print(error.localizedDescription)
}
}
ok so with this updated code it cuts out the logic errors I had earlier, but now the app hangs on my waitAlertViewController. Not sure why. it does updated the bet in the firebase database so I know its working and running that code but its like never completing it all. sorry bibscy I see what you mean now
completion handlers are pretty powerful once you understand them better
//Notice that I made `result: String?` optional, it may or may not have a value.
func getOpoosingUserNames(_ username: String,_ index: Int, completion: #escaping (_ result: String?) -> Void ) {
let userID = FIRAuth.auth()?.currentUser?.uid
datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let username = value?["username"] as? String ?? ""
self.userName = username
// ...
self.datRef.child("Bets").observe(.childAdded, with: { snapshot in
//
// this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P
let betId = snapshot.key as String
guard let dict = snapshot.value as? [String: AnyHashable] else {
print("failed to get dictionary from Bets.\(self.userName)")
return
}
if let show = dict["Show"] as? String {
let opposingUser = dict["OpposingUsername"] as? String
self.opposingUserNames.append(opposingUser!)
}
completion(opposingUserNames)
})
}) { (error) in
print(error.localizedDescription)
}
}
//update the be
func updateBet(_ index: Int, completion: #escaping (_ something: [String]?) -> Void) {
let userID = FIRAuth.auth()?.currentUser?.uid
datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
// ...
self.datRef.child("Bets").observe(.childAdded, with: { snapshot in
//
// this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P
guard let dict = snapshot.value as? [String: AnyHashable] else {
print("failed to get dictionary from Bets.\(self.userName)")
return
}
let values = ["OpposingUsername": self.userName,"Show": "no"]
//store the values received from Firebase in let valueOfUpdate and pass this
// constant to your completion handler completion(valueOfUpdate) so that you can use this value in func
//tableView(_ tableView:_, didSelectRowAt indexPath:_)
let valueOfUpdate = self.datRef.child("Bets").child(self.tieBetToUser[index]).updateChildValues(values)
completion(valueOfUpdate)
}) { (error) in
print(error.localizedDescription)
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let alertController = UIAlertController(title: "Accept Bet", message: "Match the bet of " + amountBets[indexPath.row], preferredStyle: .alert)
let okButton = UIAlertAction(title: "No", style: .default, handler: { (action) -> Void in
print("Ok button tapped")
})
let yesButton = UIAlertAction(title: "Yes", style: .default, handler: { (action) -> Void in
//take away that bitches money
self.takeAwayMoney(self.amountBets[indexPath.row])
//then delete that cell and do another pop up that says successful
// check if value is yes or no in the database
self.updateBet(indexPath.row, completion: {(result: String) in
guard let resultReceivedInupdateBet = result, else {
print("result of updateBet() is \(result)")
}
print("If you see this print, database was updated")
//calling this method with the indexPath.row clicked by the user
self.getOpoosingUserNames(self.userName, indexPath.row, completion: { (result: [String]) in
guard let resultReceivedIngetOpoosingUserNames = result{
print("result of getOpoosingUserNames is \(result)")
}
print("If you see this print, you received a value from db after calling getOpoosingUserNames and that value is in \(result) ")
//result is not nil, resultReceivedIngetOpoosingUserNames has the same value as result.
}//end of self.getOpoosingUserNames
self.checkForNo(indexPath.row)
self.amountBets.remove(at: indexPath.row)
self.tableView.reloadData()
print(self.opposingUserNames)
let successController = UIAlertController(title: "Success", message: "You have made a bet with " + self.opposingUserNames[indexPath.row], preferredStyle: .alert)
let okButt = UIAlertAction(title: "Ok", style: .default, handler: nil)
successController.addAction(okButt)
self.present(successController, animated: true, completion: nil)
//lastly delete the opposing UserName
self.opposingUserNames.remove(at: indexPath.row)
})
alertController.addAction(okButton)
alertController.addAction(yesButton)
present(alertController, animated: true, completion: nil)
}

Resources