I am getting some data from server using Alamofire like this :
func getNewestFeed(order:String , page:Int) {
Alamofire.request("https://blahblah.com/api/front/\(page)/\(order)", method: .post, parameters: ["foo":"bar"], encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: { respone in
if respone.response?.statusCode == 200 {
let result = respone.result.value as! [String:Any]
self.newestArray = result["records"] as! [Any]
self.tableView.reloadData()
} else {
//Show error
let alertController = UIAlertController(title: "Error", message: "", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
OperationQueue.main.addOperation { self.present(alertController, animated: true, completion: nil) }
}
})
}
by default server gives me page 1, now I need to add more data too self.newestArray to load more contents. So here is the code :
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let lastElement = newestArray.count - 1
if indexPath.row == lastElement {
//add more data
}
}
Now I am trying to add result to self.newestArray , like this :
let result = respone.result.value as! [String:Any]
self.newestArray.append(result["records"] as! [Any])
self.tableView.reloadData()
but crashes with this error :
Could not cast value of type 'Swift.Array' (0x109c3c828) to
'Swift.Dictionary' (0x109c3c798).
How should I addd more array to self.newestArray and show it again in table view ?
append(_:) is used to add a single element to the end of the array.
There is append(contentsOf:) if you want to add a collection of items:
self.newestArray.append(contentsOf: result["records"] as! [Any])
Related
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)
}
}
}
}
}
My requirement : I will be having a list of chat details in a table view.On top of table view ,there will be a search functionality using text field.based on unique id of user, search should get done.if there is no chat with the unique id, which the user entered,then it has to redirect to another screen which is called chatcreatepage. when ever we are searching chat, we will be using an api called FIND API and in that FIND API there is a chat dictionary,if it is null,then create chat will get called.If that chat dictionary is not nil then need to display that chat details in chat list table view. When the chat list page is loading then ,we will be calling Chat list Api.when we are searching the chat by entering the unique id in textfield,we will be getting the corresponding details of that entered unique id & that unique id details we have to show in the table view.
This is the task and i have done till the chat list showing in the table.I am really not aware of this search result showing after calling the FIND API.If anyone helps me to solve it, would be really great.Thank in advance.I am providing the code below.
import UIKit
import Alamofire
import SwiftyJSON
import SDWebImage
class ChatlistViewController: UIViewController{
var pro = [[String:Any]]()
var dict:[String:Any]!
var idd = ""
var id = ""
var chatt:Dictionary = [String:Any]()
var searchActive : Bool = false
var filtered:[String] = []
var data:[String] = []
#IBOutlet weak var search-text: UITextField!
#IBOutlet weak var chatlisttable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
apical()
}
func apical(){
let acce:String = UserDefaults.standard.string(forKey: "access-tokenn")!
print(acce)
let headers:HTTPHeaders = ["Authorization":"Bearer \(acce)","Content-Type":"application/X-Access-Token"]
Alamofire.request(Constants.Chatlist, method: .get, encoding: URLEncoding.default, headers: headers).responseJSON { response in
switch response.result {
case .success:
print(response)
if response.result.value != nil{
var maindictionary = NSDictionary()
maindictionary = response.result.value as! NSDictionary
print(maindictionary)
var userdata = NSDictionary()
userdata = maindictionary.value(forKey: "data") as! NSDictionary
var productsdetails = [[String:Any]]()
productsdetails = userdata.value(forKey: "chat") as! [[String:Any]]
self.pro = productsdetails
print(self.pro)
self.chatlisttable.reloadData()
}else{
let Alertcontroller = UIAlertController(title: "Alert", message: "No data found ", preferredStyle: .alert)
let CancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
Alertcontroller.addAction(CancelAction)
self.present(Alertcontroller, animated: true, completion: nil)
}
break
case .failure(let error):
print(error)
}
}
}
func searchapicall(){
idd = searchtext.text!
let acce:String = UserDefaults.standard.string(forKey: "access-tokenn")!
print(acce)
let headers:HTTPHeaders = ["Authorization":"Bearer \(acce)","Content-Type":"application/X-Access-Token"]
print((Constants.Chatlistsearch)+(idd))
Alamofire.request((Constants.Chatlistsearch+idd), method: .get, encoding: URLEncoding.default, headers: headers).responseJSON { response in
switch response.result {
case .success:
//print(response)
if response.result.value != nil{
var maindictionary = NSDictionary()
maindictionary = response.result.value as! NSDictionary
var chat:Dictionary = maindictionary.value(forKey: "data") as! [String:Any]
var chattt:Dictionary = chat["chat"] as! [String:Any]
if (chattt != nil) {
print("Find Action")
self.chatt = chat["user"] as! [String:Any]
print(self.chatt)
//var uniqued:String = self.chatt["unique_id"] as! String
}else{
let viewc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ChatViewController") as? ChatViewController
self.navigationController?.pushViewController(viewc!, animated: true)
}
}else{
let Alertcontroller = UIAlertController(title: "Alert", message: "No data found on this unique id", preferredStyle: .alert)
let CancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
Alertcontroller.addAction(CancelAction)
self.present(Alertcontroller, animated: true, completion: nil)
}
break
case .failure(let error):
print(error)
}
}
}
}
extension ChatlistViewController: UITextFieldDelegate{
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.searchapicall()
return true
}
}
extension ChatlistViewController: UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (searchActive == false){
return self.pro.count
}else{
return 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = chatlisttable.dequeueReusableCell(withIdentifier: "ChatlistTableViewCell", for: indexPath) as! ChatlistTableViewCell
if (searchActive == false){
dict = pro[indexPath.row]
var recepient = dict["recipient"] as! [String:Any]
print(recepient)
var name = recepient["name"] as! String
print(name)
id = recepient["unique_id"] as! String
print(id)
var image = recepient["avatar"] as! String
print(image)
cell.namelbl.text = name
cell.idlbl.text = id
cell.imageView!.sd_setImage(with: URL(string:image), placeholderImage: UIImage(named: "Mahi.png"))
}else{
cell.namelbl.text = chatt["name"] as! String
cell.idlbl.text = chatt["unique_id"] as! String
}
return cell
self.chatlisttable.reloadData()
}
}
//Response format
{
"success": 1,
"status": 200,
"data": {
"user": {
"id": 3,
"unique_id": "10002",
"name": "nani",
"avatar": "https://www.planetzoom.co.in/storage/user/avatar/AkgcUFF3QIejMhZuLF4OXnSFHjxNAOo4FuXV3Mgi.jpeg"
},
"chat": null
}
}
You have to use UISearchBar and in call your api in delegate method of searchbar func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String).
For reference use this https://guides.codepath.com/ios/Search-Bar-Guide
i tried to do swipe to delete on table view cell, but after swiping that cell several times then only it is getting deleted. how to make it work smoothly(in one attempt swipe and delete)? my code is here :
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
var bId = Helper.businessId as String
let param = ["id" : bId] as! [String : AnyObject]
if editingStyle == .delete{
print(Helper.memId)
print("Deleted")
var myDictionary = self.List[indexPath.row] as! NSDictionary
var bId : String!
if myDictionary.allKeys.count>0
{
bId = myDictionary["id"] as! String
}
var bb = bId as String
if editingStyle == .delete{
print(Helper.memId)
print("Deleted")
Alamofire.request("http://api.noattabeta.com/api/v1/user/current/memberships/\(bb)", method: .delete, headers: ["Authorization":Helper.token]).responseString
{response in
print("In Response")
switch response.result {
case .success:
DispatchQueue.main.async {
let myAlert = UIAlertController(title:"Alert", message: "Do You want to delete",preferredStyle:UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title:"Ok",style:UIAlertActionStyle.default,handler:{ (action: UIAlertAction!) in
self.tableView.reloadData()
})
myAlert.addAction(okAction)
let cancelAction = UIAlertAction(title:"Cancel",style:UIAlertActionStyle.default,handler:{ (action: UIAlertAction!) in
self.tableView.reloadData()
})
myAlert.addAction(okAction)
myAlert.addAction(cancelAction)
self.present(myAlert, animated: true, completion: nil)
}
case .failure(let error):
print(error)
}}}
First I wanted to point out that you're presenting the alert in the wrong place. You make a delete call on the API after it success you're asking if he or she want's to confirm. you have to ask it before you call delete
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
var bId = Helper.businessId as String
let param = ["id" : bId] as! [String : AnyObject]
if editingStyle == .delete{
print(Helper.memId)
print("Deleted")
var myDictionary = self.List[indexPath.row] as! NSDictionary
var bId : String!
if myDictionary.allKeys.count>0
{
bId = myDictionary["id"] as! String
}
var bb = bId as String
if editingStyle == .delete{
print(Helper.memId)
print("Deleted")
let myAlert = UIAlertController(title:"Alert", message: "Do You want to delete",preferredStyle:UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title:"Ok",style:UIAlertActionStyle.default,handler:{ (action: UIAlertAction!) in
// here you can call the delete if user accepts
Alamofire.request("http://api.noattabeta.com/api/v1/user/current/memberships/\(bb)", method: .delete, headers: ["Authorization":Helper.token]).responseString
{response in
print("In Response")
switch response.result {
case .success:
DispatchQueue.main.async {
// remove from your local array e.g
self.dataModel.remove(at: indexPath.row)
// Delete the row before you reload the tableView
self.tableView.deleteRows(at: [indexPath], with: .automatic)
// Now reload your tableView
self.tableView.reloadData()
}
case .failure(let error):
print(error)
})
myAlert.addAction(okAction)
let cancelAction = UIAlertAction(title:"Cancel",style:UIAlertActionStyle.default,handler:{ (action: UIAlertAction!) in
self.tableView.reloadData()
})
myAlert.addAction(okAction)
myAlert.addAction(cancelAction)
self.present(myAlert, animated: true, completion: nil)
}
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.
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)
}