add the values according to appending the values - ios

How to add the values according to appending the values in swift3.
this is my datasource:-
class QM_ChartDataSourceModel: NSObject {
var dataListArray:Array<QM_CartModel>? = []
init(array :Array<[String:Any]>?) {
super.init()
var newArray:Array<[String:Any]> = []
if array == nil{
newArray = self.getJsonDataStored22()
}
else{
newArray = array!
}
var datalist:Array<QM_CartModel> = []
for dict in newArray{
let model = QM_CartModel(dictionary: dict)
datalist.append(model!)
}
self.dataListArray = datalist
}
}
typealias dummyDataSource22 = QM_ChartDataSourceModel
extension dummyDataSource22{
func getJsonDataStored22() ->Array<Dictionary<String,String>>{
let jsonArray = [["id":"311","name":"Dosa Fest","price":"QR 40","quantity":"3"],["id":"312","name":"Organic Vegan Fest","price":"QR 40","quantity":"2"],["id":"313","name":"Food Of Life Time","price":"QR 56","quantity":"7"],["id":"314","name":"Tea Time","price":"QR 88","quantity":"1"],["id":"315","name":"Dosa Fest","price":"QR 13","quantity":"6"],["id":"316","name":"Organic Vegan Fest","price":"QR 4","quantity":"8"],["id":"317","name":"Food Of Life Time","price":"QR 90","quantity":"3"],["id":"318","name":"Tea Time","price":"QR 66","quantity":"2"],["id":"319","name":"Dosa Fest","price":"QR 81","quantity":"6"],["id":"320","name":"Organic Vegan Fest","price":"QR 49","quantity":"2"]] as Array<Dictionary<String,String>>
return jsonArray
}
}
in tableviewcell:
func setEventData(carts:QM_CartModel)
{
self.name.text = carts.cartname
self.price.text = carts.cartsum
self.itemQuantityStepper.value = 1
setItemQuantity(quantity)
print(self.price.text)
let value = carts.cartsum
let x: Int? = Int(value!)
print(x)
let add = x!
print(add)
let theIntegerValue1 :Int = add
let theStringValue1 :String = String(theIntegerValue1)
self.price.text = theStringValue1
}
my model:-
class QM_CartModel: NSObject {
var cartname :String!
var cartprice:String!
var cartquantity:String!
var carttotalprice:String!
var carttotal:String!
var cartQR:String!
var cartvalue:String!
var cartsum:String?
var cartid:String!
init?(dictionary :JSONDictionary) {
guard let name = dictionary["name"] as? String else {
return
}
if let quantity = dictionary["quantity"] as? String{
let price = dictionary["price"] as? String
let id = dictionary["id"] as? String
self.cartid = id
self.cartprice = price
self.cartquantity = quantity
let fullNameArr = price?.components(separatedBy: " ")
let QR = fullNameArr?[0]
let value = fullNameArr?[1]
self.cartQR = QR
self.cartvalue = value
let x: Int? = Int(value!)
print(x)
let y:Int? = Int(quantity)
print(y)
let sum = x! * y!
print(sum)
let sum1 = String(describing: sum)
cartsum = sum1
}
my viewmodel:-
class QM_ChartViewModel: NSObject {
var datasourceModel:QM_ChartDataSourceModel
var insertedArray:QM_CartModel?
var filteredListArray:Array<QM_CartModel>? = []
var totalListArray:Array<QM_CartModel>? = []
init(withdatasource newDatasourceModel: QM_ChartDataSourceModel) {
datasourceModel = newDatasourceModel
print(datasourceModel.dataListArray)
}
func datafordisplay(atindex indexPath: IndexPath) -> QM_CartModel{
return datasourceModel.dataListArray![indexPath.row]
}
func numberOfRowsInSection(section:Int) -> Int {
return datasourceModel.dataListArray!.count
}
func delete(atIndex indexPath: IndexPath) {
datasourceModel.dataListArray!.remove(at: indexPath.row)
}
func search(idsearch :String?) {
filteredListArray = datasourceModel.dataListArray?.filter{($0.cartid?.range(of: idsearch!, options: .caseInsensitive) != nil)}
print(filteredListArray)
}
func searchindex(objectatindex index: Int) -> QM_CartModel {
return self.filteredListArray![index]
}
func total()
{ totalListArray = datasourceModel.dataListArray?.filter{($0.cartsum != nil)}
print(totalListArray)
}
func add(){
datasourceModel.dataListArray?.append(insertedArray!)
print(datasourceModel.dataListArray)
print(insertedArray?.offerAddName)
print(insertedArray?.offerprice)
self.datasourceModel.dataListArray = datasourceModel.dataListArray
print(insertedArray?.cartsum)
}
func addquantity(quantity:Int)
{
// datasourceModel.dataListArray?.filter{ $0.cartid! == cartaddedid! }.first?.qty = quantity as NSNumber?
}
}
in viewcontroller my code as below:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return chartViewModel.numberOfRowsInSection(section: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "cell"
var cell: QM_ChartCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? QM_ChartCell
if cell == nil {
tableView.register(UINib(nibName: "QM_ChartCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? QM_ChartCell
}
cell.setEventData(carts: chartViewModel.datafordisplay(atindex: indexPath))
print(cell.numbers)
see here can see the total.So that way i need to display the total
this is my code ...here i getting the values model.cartsum.So this value is appending in var number:[String] = []
.But here i need-as values are appending ,here i need to add the number.So first value is 1 and second value is 2 then i need to add this values.And if next number is 3 then i need to get sum = 6.
How to get

You need to calculate all the cart stuff just after you get it either from service or from local. You don't need to do calculation in cellForRowAtIndex: method because it should be done once.
I assume this is your data structure as mentioned in question.
let jsonArray = [["id":"311","name":"Dosa Fest","price":"QR 40","quantity":"3"],
["id":"312","name":"Organic Vegan Fest","price":"QR 40","quantity":"2"],
["id":"313","name":"Food Of Life Time","price":"QR 56","quantity":"7"],
["id":"314","name":"Tea Time","price":"QR 88","quantity":"1"],
["id":"315","name":"Dosa Fest","price":"QR 13","quantity":"6"],
["id":"316","name":"Organic Vegan Fest","price":"QR 4","quantity":"8"],
["id":"317","name":"Food Of Life Time","price":"QR 90","quantity":"3"],
["id":"318","name":"Tea Time","price":"QR 66","quantity":"2"],
["id":"319","name":"Dosa Fest","price":"QR 81","quantity":"6"],
["id":"320","name":"Organic Vegan Fest","price":"QR 49","quantity":"2"]]
Here is how to calculate the total of the cart. As per your data considering price is in Int
var total = 0
for item in jsonArray {
/// Will check if quantity is available in dictionary and convertible into an Int else will be 0
let quantity = Int(item["quantity"] ?? "0") ?? 0
/// Will check price key exists in the dictionary
if let priceStr = item["price"] {
/// Will fetch the last components and check if it is convertible into an Int else 0
let price = Int(priceStr.components(separatedBy: " ").last ?? "0") ?? 0
/// Multiply price with quantity and add into total
total += price * quantity
}
}
print(total)
Output: 1776
Another way:
let total = jsonArray.map { (item) -> Int in
let quantity = Int(item["quantity"] ?? "0") ?? 0
let price = Int(item["price"]?.components(separatedBy: " ").last ?? "0") ?? 0
return quantity * price
}.reduce(0, +)
print(total)

Please try this code if you have array of Int
var arrayOfInt = [2,3,4,5,4,7,2]
let reducedNumberSum = arrayOfInt.reduce(0,+)
print(reducedNumberSum)
Answer: 27
In your code
let model = chartViewModel.datafordisplay(atindex: indexPath)
Please describe more so we can answer according your problem.

Related

Force casts should be avoided

I am getting "Force cast violation : Force casts should be avoided warning"
on my code :
daysCombinedFinal = daysCombined[0] as! [Any?]
The screenshot is attached below:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "location", for: indexPath) as? TravelShopCustomCell {
if !isFirstTime && self.nameArray.count != 0 {
var daysCombined = [Any]()
var daysCombinedFinal = [Any?]()
daysCombined = [self.combinedArray[0]]
daysCombinedFinal = daysCombined[0] as? [Any?] ?? []
let str = daysCombinedFinal.flatMap { $0 as? String }.joined(separator:" ")
var startAMCombined = [Any]()
var startAMCombinedFinal = [Any?]()
startAMCombined = [self.combinedStartAMArray[0]]
startAMCombinedFinal = startAMCombined[0] as? [Any?] ?? []
var endPMCombined = [Any]()
var endPMCombinedFinal = [Any?]()
endPMCombined = [self.combinedEndPMArray[0]]
endPMCombinedFinal = endPMCombined[0] as? [Any?] ?? []
cell.operatingDaysLabel.text = str
let isAMEqual = checkArrayStatus(testArray: [startAMCombinedFinal as Any])
let isPMEqual = checkArrayStatus(testArray: [endPMCombinedFinal as Any])
if isAMEqual && isPMEqual {
self.mergedArray = arrayMerger(array1: startAMCombinedFinal, array2: endPMCombinedFinal)
}
let startTimeString = self.mergedArray[0] as? String
let endTimeString = self.mergedArray[1] as? String
cell.operatingTimeLabel.text = startTimeString! + " - " + endTimeString!
return cell
} else if isFirstTime && self.nameArray.count != 0 {
var daysCombined = [Any]()
var daysCombinedFinal = [Any?]()
daysCombined = [self.combinedArray[indexPath.row]]
daysCombinedFinal = daysCombined[0] as! [Any?]
let str = daysCombinedFinal.flatMap { $0 as? String }.joined(separator:" ")
var startAMCombined = [Any]()
var startAMCombinedFinal = [Any?]()
startAMCombined = [self.combinedStartAMArray[indexPath.row]]
startAMCombinedFinal = startAMCombined[0] as! [Any?]
var endPMCombined = [Any]()
var endPMCombinedFinal = [Any?]()
endPMCombined = [self.combinedEndPMArray[indexPath.row]]
endPMCombinedFinal = endPMCombined[0] as! [Any?]
cell.operatingDaysLabel.text = str
let isAMEqual = checkArrayStatus(testArray: [startAMCombinedFinal as Any])
let isPMEqual = checkArrayStatus(testArray: [endPMCombinedFinal as Any])
if isAMEqual && isPMEqual {
self.mergedArray = arrayMerger(array1: startAMCombinedFinal, array2: endPMCombinedFinal)
}
let startTimeString = self.mergedArray[0] as? String
let endTimeString = self.mergedArray[1] as? String
cell.operatingTimeLabel.text = startTimeString! + " - " + endTimeString!
return cell
}
return cell
} else {
fatalError("Dequeueing SomeCell failed")
}
}
The array declaration is:
var dateArray = [Any]()
var endAmTimeArray = [Any]()
var endPmTimeArray = [Any]()
var startAmTimeArray = [Any]()
var startPmTimeArray = [Any]()
var combinedArray = [Any]()
var combinedStartAMArray = [Any]()
var combinedEndPMArray = [Any]()
var mergedArray = [Any?]()
Your problem has relation with concept of 'optional' & 'unwrapper'. Here is brief about both and difference between them: How to understand ! and ? in swift?
? (Optional) indicates your variable may contain a nil value while ! (unwrapper) indicates your variable must have a memory (or value) when it is used (tried to get a value from it) at runtime.
In your case, you are trying to get value from array using index number. Now type of elements of your array is 'Any'
So, there may be any kind of value/information contained by element of array. It will result into app crash, if you try to force unwrap a value of element, when it won't return a value or value with type that you're casting with unwrapper.
Here is basic tutorial in detail, by Apple Developer Committee.
This warning is indicating you, that your app may crash on force unwrapping optional value.
As a solution you should use ? (optional) with if-let block, to avoid force unwrapping and safe execution of your code, like:
if let daysC = daysCombined[0] as? [Any] {
daysCombinedFinal = daysC
}
Share your full source code, to get better solution of your query as you have not shared declaration of your array in your question. Because I've confusion about optional array [Any?] elements. Swift not allows array elements as optional.
Update : By considering elements of all arrays as 'Dictionary < String : Any >', forced unwraps from array assignments are removed here.
var daysCombined = [Any]()
var daysCombinedFinal = [Any?]()
daysCombined = [self.combinedArray[indexPath.row]]
// Update 1
// if combinedArray is an array of array
if let arrayElement = daysCombined[0] as? [Any] {
daysCombinedFinal = arrayElement
}
let str = daysCombinedFinal.flatMap { $0 as? String }.joined(separator:" ")
var startAMCombined = [Any]()
var startAMCombinedFinal = [Any?]()
startAMCombined = [self.combinedStartAMArray[indexPath.row]]
// Update 2
if let arrayElement = startAMCombined[0] as? [Any] {
startAMCombinedFinal = arrayElement
}
var endPMCombined = [Any]()
var endPMCombinedFinal = [Any?]()
endPMCombined = [self.combinedEndPMArray[indexPath.row]]
// Update 3
if let arrayElement = endPMCombined[0] as? [Any] {
endPMCombinedFinal = arrayElement
}
cell.operatingDaysLabel.text = str

Get users messages from firebase

When Users have a conversation, I want the conversations to be displayed in a tableViewController. For example, if User1 sends 10 messages to User2, then I should have one cell in my TableView that displays the last message sent in User1 - User2 conversation. Again, if User1 sends User3 4 messages then User1 should have two tableView cells and User2 and User3 should only have 1 message.
My database looks like this:
messages
hx1DXeMFRU
-KkVUFuhv7xsYVhnjldV
ReceiverId: "hx1DX1hW5JZMSmDjwQRUYo3i5Yt2"
senderId: "eMFRUhfmckTq9cRWNnwIc9mqxxv1"
text:"hey"
convoId: hx1DXeMFRU
timestamp: 1495193736.860723
-KkVUJG8VPOijCvzMKRf
ReceiverId: "eMFRUhfmckTq9cRWNnwIc9mqxxv1"
senderId: "hx1DX1hW5JZMSmDjwQRUYo3i5Yt2"
text:"Hey how are you?"
convoId: hx1DXeMFRU
timestamp: 1495193699.448048
I am using the below function to retrieve all messages and view them in a messagesViewController. However, when I try to append the conversation between two unique users, it instead appends all of the messages into one cell. So in my specific example, I should have two cells, one for User1 communicating with User2 and User1 communicating with User3.
import UIKit
import Firebase
import FirebaseStorage
import FirebaseAuth
import FBSDKCoreKit
import FBSDKLoginKit
import FirebaseDatabase
import JSQMessagesViewController
class MessagesTableViewController: UITableViewController {
var databaseRef = FIRDatabase.database().reference()
var loggedInUser = FIRAuth.auth()?.currentUser
var loggedInUserUid = FIRAuth.auth()?.currentUser?.uid
var dictDetails: [String:AnyObject]?
var messages = NSMutableArray()
var messagesArray = [String]()
var convoId: String?
var receiverData: AnyObject?
let storage = FIRStorage.storage()
var senderId = FIRAuth.auth()?.currentUser?.uid
#IBOutlet var MessageTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.barTintColor = UIColor(red:0.23, green:0.73, blue:1.00, alpha:1.0)
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
self.navigationItem.title = "Messages"
self.navigationItem.rightBarButtonItem?.tintColor = UIColor.white
self.navigationItem.leftBarButtonItem?.tintColor = UIColor.white
loadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadData()
{
let uidToFind = loggedInUserUid as String!
FIRDatabase.database().reference().child("messages")
.queryOrdered(byChild: "ReceiverId")
.queryEqual(toValue: uidToFind).queryLimited(toLast: 1)
.observe(.childAdded, with: { snapshot in
let msgDict = snapshot.value as! [String: Any]
let msg = msgDict["ReceiverId"] as! String
self.messages = []
self.messages.append(msg)
self.MessageTableView.reloadData()
})
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if messages.count > 0 {
tableView.backgroundView = .none;
tableView.separatorStyle = .singleLine
return self.messages.count
}
else{
let noDataLabel: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
noDataLabel.text = "No Messages"
noDataLabel.textColor = UIColor.lightGray
noDataLabel.textAlignment = .center
tableView.backgroundView = noDataLabel
tableView.separatorStyle = .none
return 0
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as! MessageTableViewCell
//Configure the cell
print(messages[indexPath.row])
let message = self.messages[indexPath.row] as! [String: AnyObject]
if let seconds = message["timestamp"] as? Double {
let timeStampDate = NSDate(timeIntervalSince1970: seconds)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
cell.Time.text = dateFormatter.string(from: timeStampDate as Date)
}
cell.Message.text = message["text"] as? String
if let imageName = message["ReceiverId"] as? String {
let ref = FIRDatabase.database().reference().child("posts").child(imageName)
ref.observeSingleEvent(of: .value, with: { (snapshot)
in
if let dictionary = snapshot.value as? [String: AnyObject]{
for post in dictionary {
let messages = post.value as! [String: AnyObject]
for (id, value) in messages {
cell.SellerName.text = messages["username"] as? String
if (messages["uid"] as? String) != nil {
let uidPoster = messages["uid"] as? String
let imageRef = FIRStorage.storage().reference().child((uidPoster)!+"/profile_pic.jpg")
imageRef.data(withMaxSize: 25 * 1024 * 1024, completion: { (data, error) -> Void in
if error == nil {
let image = UIImage(data: data!)
cell.UserPic.image = image
cell.UserPic.layer.cornerRadius = 30
cell.UserPic.clipsToBounds = true
}else {
}})}
self.messages.add(value)
}}}})}
return cell
}
}
The problem with the code in the question is this
queryEqual(toValue: "senderId")
That query is going to query the messages/ReceiverId nodes that have a value of "senderId" (literally the string senderId). It needs to query for the actual uid instead.
func loadData()
{
let uidToFind = "hx1DX1hW5JZMSmDjwQRUYo3i5Yt2"
FIRDatabase.database().reference().child("messages")
.queryOrdered(byChild: "ReceiverId")
.queryEqual(toValue: uidToFind)
.observe(.childAdded, with: { snapshot in
let msgDict = snapshot.value as! [String: Any]
let msg = msgDict["ReceiverId"] as! String
self.messages = []
self.messages.append(msg)
self.MessageTableView.reloadData()
})
}
I will stress that while this code works, it's iterating over all of the child nodes matching ReceiverId = uid, loading them one at a time and leaving an observer for any new child nodes added afterwards.
This is a good thing as it allows you to populate an array with multiple values as well as attaching a listener for new values.
However, if you are really only interested in the most recent post, a better direction would be to use queryLimitedToLast(1) which will only return the last node that matches the query.
Something like
var messages = [String]()
func loadData()
{
let uidToFind = "hx1DX1hW5JZMSmDjwQRUYo3i5Yt2"
FIRDatabase.database().reference().child("messages")
.queryOrdered(byChild: "ReceiverId")
.queryEqual(toValue: uidToFind)
.queryLimited(toLast: 1)
.observe(.childAdded, with: { snapshot in
let msgDict = snapshot.value as! [String: Any]
let msg = msgDict["ReceiverId"] as! String
self.messages = []
self.messages.append(msg)
//self.MessageTableView.reloadData()
print(self.messages) //this will print the last msg and any new msgs
})
}

How to iterate through Dictionary of Dictionary Values in UITableViewCell?

This is my first post and I hope its a great question because iv been stuck on this for days. (Literally searched every related question and found nothing that I could add up for a solution.)
Basically I'm building a pure Swift application. My problem is that I cant figure out how to place each dictionary values into each UITableCell that is created.
Also the JSON response from the GET creates a NSCFDictionary type.
UITableViewCell Properties
UILabel - Holds the Offer "name"
UI Label #2 - Holds Offer "description"
UIImage - Holds the Offer "thumb_url"
So basically I need to store each offer object's (name, description, thumb_url) in every UITableViewCell that the ViewController creates.
GET Request
import UIKit
class freeIAPCell: UITableViewCell {
#IBOutlet weak var aName: UILabel!
#IBOutlet weak var aDescription: UILabel!
#IBOutlet weak var aImage: UIImageView!
}
class FreeIAPViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// Everbadge Request
var apiURL = "apiurlhere"
var parsedArray: [[String:String]] = []
func queryEB() {
// Query DB Here
// Store the API url in a NSURL Object
let nsURL = NSURL(string: apiURL)
let request = NSMutableURLRequest(URL: nsURL!)
request.HTTPMethod = "GET"
// Execute HTTP Request
let task = NSURLSession.sharedSession().dataTaskWithURL(nsURL!) {
data, response, error in
if error != nil {
print("Error = \(error)")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) as! NSDictionary
print(json.isKindOfClass(NSDictionary)) // true
let data = json.objectForKey("data") as! NSDictionary
//print(data)
let m = data.objectForKey("offers") as! NSArray
print(m)
print(m.valueForKeyPath("name"))
self.parsedArray = m as! [[String : String]]
} catch {
print("THERE WAS AN ERROR PARSING JSON FOR EVERBADGE")
}
}
task.resume()
}
override func viewDidLoad() {
super.viewDidLoad()
queryEB()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
}
// MARK: UITableView method implementation
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("freeAppCell", forIndexPath: indexPath) as! freeIAPCell
let obj = parsedArray[indexPath.row] // fatal error: Index out of range
cell.aName.text = obj["name"]
return cell
}
}
API Request Data Structure (print(m))
(
{
"name" = "Mate";
id = 23941;
description = "10-20 word description goes here"
"url" = "google.com
"ver" = "0.12"
price = "0.17"
"public_name" = "Good Ole Mate"
"thumb_url" = "http://google.com/mate.jpg
};
{
"name" = "Mate";
id = 23941;
description = "10-20 word description goes here"
"url" = "google.com
"ver" = "0.12"
price = "0.17"
"public_name" = "Good Ole Mate"
"thumb_url" = "http://google.com/mate.jpg
};
{
"name" = "Mate";
id = 23941;
description = "10-20 word description goes here"
"url" = "google.com
"ver" = "0.12"
price = "0.17"
"public_name" = "Good Ole Mate"
"thumb_url" = "http://google.com/mate.jpg
};
{
"name" = "Mate";
id = 23941;
description = "10-20 word description goes here"
"url" = "google.com
"ver" = "0.12"
price = "0.17"
"public_name" = "Good Ole Mate"
"thumb_url" = "http://google.com/mate.jpg
};
{
"name" = "Mate";
id = 23941;
description = "10-20 word description goes here"
"url" = "google.com
"ver" = "0.12"
price = "0.17"
"public_name" = "Good Ole Mate"
"thumb_url" = "http://google.com/mate.jpg
};
);
First create public arrays for your 3 items...
var nameArray = [String]()
var descriptionArray = [String]()
var thumbnailArray = [String]()
Then loop through your json parse like this....
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) as! NSDictionary
if responseString != nil
{
let items: AnyObject! = responseString["items"] as AnyObject!
if items != nil
{
// Loop through all search results and keep just the necessary data.
for var i=0; i<items.count; ++i
{
if let names = items[i]["name"] as? NSDictionary
{
let name = names as! String
self.nameArray.append(name)
}
if let descriptions = items[i]["description"] as? NSDictionary
{
let description = descriptions as! String
self.descriptionArray.append(description)
}
if let thumbnails = items[i]["thumb_url"] as? NSDictionary
{
let thumbnail = thumbnails as! String
self.thumbnailArray.append(thumbnail)
}
}
}
self.resultsTableView.reloadData()
Create an OfferTableViewCell Class with a nameLabel:UILabel, descriptionLabel:UILabel, and thumbnailImage:UIImage. Finally in your cellForRowAtIndexPath.....
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("offer", forIndexPath: indexPath) as! OfferTableViewCell
cell.nameLabel.text = self.nameArray[indexPath.row]
cell.descriptionLabel.text = self.descriptionArray[indexPath.row]
let url = NSURL(string: self.thumbnailArray[indexPath.row])
let data = NSData(contentsOfURL: url!)
cell.thumbnailImage.image = UIImage(data: data!)
return cell
}

How to sort A - z in table view swift 2.0

i have one table view, which will dipslay the json data from one url.Its all working fine. What i need is?. in my table view i have one lable called "name label ".Which will display the name in my table view.
And i have one menu option with one button name called" sort data A - z ".When i click that, my table view data should reload with sorting the date from A-z alphabets order ( My name title ).
This is my button action :
#IBAction func sortByAZBtnPress(sender: AnyObject) {
}
My viewcontroller.swift
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var RightMenu: UIView!
#IBOutlet weak var tableView: UITableView! // UITable view declaration
#IBOutlet weak var Resultcount: UILabel! // count label
var arrDict :NSMutableArray=[] // array to store the value from json
let cellSpacingHeight: CGFloat = 5 // cell spacing from each cell in table view
override func viewDidLoad() {
super.viewDidLoad()
self.jsonParsingFromURL() // call the json method
let nib = UINib(nibName:"customCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell")
RightMenu.layer.borderWidth = 1
}
// web services method
func jsonParsingFromURL () {
let url = NSURL(string: "http://sampleUrl.com”)
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: url!)
let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
// print("done, error: \(error)")
if error == nil
{
dispatch_async(dispatch_get_main_queue()){
self.arrDict=(try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSMutableArray
//print(self.arrDict)
if (self.arrDict.count>0)
{
self.Resultcount.text = "\(self.arrDict.count) Results"
self.tableView.reloadData()
}}
// arrDict.addObject((dict.valueForKey("xxxx")
}
}
dataTask.resume()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.arrDict.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
// calling each cell based on tap and users ( premium / non premium )
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:customCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! customCell
cell.vendorName.text=arrDict[indexPath.section] .valueForKey("name") as? String
cell.vendorAddress.text=arrDict[indexPath.section] .valueForKey("address") as? String
return cell
}
// MARK:
// MARK: Sort Method
#IBAction func sortByRevBtnPress(sender: AnyObject) {
self.indicator.startAnimating()
self.indicator.hidden = false
RightMenu.hidden = true
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(1 * NSEC_PER_SEC)), dispatch_get_main_queue()){
self.indicator.stopAnimating()
self.indicator.hidden = true
};
self.tableView.reloadData()
}
#IBAction func sortByAZBtnPress(sender: AnyObject) {
}
}
Please help me out. I am not getting clear idea to do that...Thanks
Updated :
(
{
ad = 0;
address = "900 York Mills Rd, Toronto, ON M3B 3H2, Canada";
"category_id" = 1;
latitude = "43.7563";
longitude = "-79.3495";
name = "Honeybee Restaurant";
phone = 9876543210;
rating = "5.0";
},
{
ad = 1;
address = "1677 Wilson Ave, Toronto, ON M3L 1A5, Canada";
"category_id" = 1;
latitude = "43.7194";
longitude = "-79.5153";
name = "Maki My Way";
phone = 9875463254;
rating = "4.0";
},
{
ad = 1;
address = "75 Bremner Blvd, Toronto, ON M5J 0A1, Canada";
"category_id" = 1;
latitude = "43.6429";
longitude = "-79.3814";
name = "Blow Fish Restaurant";
phone = 9873245610;
rating = "5.0";
},
{
ad = 0;
address = "4150 Yonge St, Toronto, ON M2P 2C6, Canada";
"category_id" = 1;
latitude = "43.747";
longitude = "-79.4079";
name = "SaigonFlower Restaurant";
phone = 7892345621;
rating = "3.0";
},
{
ad = 1;
address = "604 King St W, Toronto, ON M5V 1M6, Canada";
"category_id" = 1;
latitude = "43.6445";
longitude = "-79.4004";
name = "Sushi Gen";
phone = 7456321065;
rating = "2.0";
},
)
Assuming that your array is an array of dictionaries and your dictionary has a "Name" key you can do this. Change the code if your dict has different keys that contains the name.
#IBAction func sortByAZBtnPress(sender: AnyObject) {
arrDict.sortUsingComparator { (dict1, dict2) -> NSComparisonResult in
if let name1 = dict1["name"] as? String, name2 = dict2["name"] as? String {
return name1.compare(name2)
}
return .OrderedAscending
}
self.tableView.reloadData()
}
For order by rating (High to low) you can use this.
arrDict.sortUsingComparator { (dict1, dict2) -> NSComparisonResult in
if let name1 = dict1["rating"] as? String, name2 = dict2["rating"] as? String {
return name2.compare(name1)
}
return .OrderedAscending
}
For sorting of the tableview you should sort youre dataSource firstly and than reload tableview.
In you're case:
Firstly sort by A to z:
arrDict
For sorting use functional programming:
arrDict = arrDict.sort({ $0.name > $1.name })
Secondly reload tableview by:
self.tableView.reloadData()
sort arrDict using below code then self.tableView.reloadData():
sortedArray = [anArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];

How to filter an array of JSON objects to be used in a table view?

I'm getting JSON data from an API and parsing that data in objects, which are then simply stored in an array of objects. The objects themselves contain data about articles from a newspaper. However, I need to filter that data. Some of the objects I'm getting from my JSON actually have no article content because they are pictures and not articles (i.e. some of the "nodes" from the API's JSON have content that I don't want to see in my table view).
In my JSON-parsing function, I've tried to make it so that the parsed object will only get added to the array of parsed objects if the character count of the "articleContent" variable is above 40. Here is what it looked like.
if issueElement.articleContent.characters.count > 40 {
self.currentIssueObjects.addObject(issueElement)
}
However, this simply does not work. I get the typical "unexpectedly found nil while unwrapping an Optional value" error message (I don't get a specific line for the error). How can I make this work ? I'm essentially trying to prevent the array from having objects with empty articleContent, because then that screws up my table view (empty cells, duplicates, etc...).
Here is my cellForRowAtIndexPath code, and my JSON-parsing code:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell {
let row = indexPath.row
guard let cell = tableView.dequeueReusableCellWithIdentifier(CurrentIssueArticlesTableCellIdentifier, forIndexPath: indexPath) as? CurrentIssueArticlesTableViewCell else {
print ("error: currentIssueTableView cell is not of class CurrentIssueArticlesTableViewCell, we will use EditorialsTableViewCell instead")
return tableView.dequeueReusableCellWithIdentifier(CurrentIssueArticlesTableCellIdentifier, forIndexPath: indexPath) as! EditorialsTableViewCell
}
let currentIssueObject = currentIssueObjects.objectAtIndex(indexPath.row) as! IssueElement
let title = currentIssueObject.title ?? ""
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(currentIssueObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject) ?? "Date unknown"
if let author = currentIssueObject.author {
cell.currentIssueArticlesAuthorLabel!.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cell.currentIssueArticlesAuthorLabel!.text = author
}
let issueNumber = currentIssueObject.issueNumber ?? ""
let volumeNumber = currentIssueObject.volumeNumber ?? ""
let articleContent = currentIssueObject.articleContent ?? ""
let nodeID = currentIssueObject.nodeID ?? 0
cell.currentIssueArticlesHeadlineLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
cell.currentIssueArticlesHeadlineLabel.text = title
cell.currentIssueArticlesPublishDateLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cell.currentIssueArticlesPublishDateLabel.text = timeStampDateString
if row == 0 {
cell.userInteractionEnabled = false
let imageURL = (currentIssueObjects.objectAtIndex(row) as! IssueElement).imageURL
cell.currentIssueArticlesHeadlineLabel.textColor = UIColor.clearColor()
cell.currentIssueArticlesAuthorLabel.textColor = UIColor.clearColor()
cell.currentIssueArticlesPublishDateLabel.textColor = UIColor.clearColor()
cell.request?.cancel()
if let image = self.imageCache.objectForKey(imageURL!) as? UIImage {
cell.currentIssueArticlesBackgroundImageView.image = image
} else {
cell.currentIssueArticlesBackgroundImageView.image = UIImage(named: "reveal Image")
cell.request = Alamofire.request(.GET, imageURL!).responseImage() { response in
if response.result.error == nil && response.result.value != nil {
self.imageCache.setObject(response.result.value!, forKey: response.request!.URLString)
cell.currentIssueArticlesBackgroundImageView.image = response.result.value
} else {
}
}
}
cell.currentIssueArticlesBackgroundImageView.hidden = false
}
else {
cell.currentIssueArticlesBackgroundImageView.hidden = true
}
return cell
}
JSON-parsing code:
func populateCurrentIssue() {
if populatingCurrentIssue {
return
}
populatingCurrentIssue = true
self.cellLoadingIndicator.backgroundColor = goldenWordsYellow
self.cellLoadingIndicator.startAnimating()
Alamofire.request(GWNetworking.Router.Issue).responseJSON() { response in
if let JSON = response.result.value {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
var nodeIDArray : [Int]
if (JSON .isKindOfClass(NSDictionary)) {
for node in JSON as! Dictionary<String, AnyObject> {
let nodeIDValue = node.0
var lastItem : Int = 0
self.nodeIDArray.addObject(nodeIDValue)
if let issueElement : IssueElement = IssueElement(title: "Could not retrieve title", nodeID: 0, timeStamp: 0, imageURL: "init", author: "Author not found", issueNumber: "Issue # error", volumeNumber: "Volume # error", articleContent: "Could not retrieve article content", coverImageInteger: "init", coverImage: UIImage()) {
issueElement.title = node.1["title"] as! String
issueElement.nodeID = Int(nodeIDValue)!
let timeStampString = node.1["revision_timestamp"] as! String
issueElement.timeStamp = Int(timeStampString)!
issueElement.imageURL = String(node.1["image_url"])
if let author = node.1["author"] as? String {
issueElement.author = author
}
if let issueNumber = node.1["issue_int"] as? String {
issueElement.issueNumber = issueNumber
}
if let volumeNumber = node.1["volume_int"] as? String {
issueElement.volumeNumber = volumeNumber
}
if let articleContent = node.1["html_content"] as? String {
issueElement.articleContent = articleContent
}
issueElement.coverImageInteger = String(node.1["cover_image"]) // addition specific to the Current Issue View Controller
lastItem = self.currentIssueObjects.count
print(issueElement.nodeID)
if issueElement.articleContent.characters.count > 40 {
self.currentIssueObjects.addObject(issueElement)
print(issueElement.nodeID)
}
// Sorting with decreasing timestamp from top to bottom.
let timestampSortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: false)
self.currentIssueObjects.sortUsingDescriptors([timestampSortDescriptor])
// Placing the object with coverImage
let coverImageSortDescriptor = NSSortDescriptor(key: "coverImageInteger", ascending: false)
self.currentIssueObjects.sortUsingDescriptors([coverImageSortDescriptor])
let indexPaths = (lastItem..<self.currentIssueObjects.count).map {
NSIndexPath(forItem: $0, inSection: 0) }
}
}
}
dispatch_async(dispatch_get_main_queue()) {
self.currentIssueTableView.reloadData()
self.cellLoadingIndicator.stopAnimating()
self.cellLoadingIndicator.hidesWhenStopped = true
}
}
}
self.populatingCurrentIssue = false
}
}

Resources