Swift dictionary deletes previous data when appending new data - ios

I have a swift dictionary with custom objects and I use it to fill my UITableview. However, when I fill the dictionary, I realize that it deletes previous data when I append a new data to it. The related code blocks like below:
var dict = Dictionary<ListItem, [ListItem]>()
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.dict.keys.array.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell: CategoryCell! = tableView.dequeueReusableCellWithIdentifier("categoryCell", forIndexPath: indexPath) as? CategoryCell
if(cell == nil)
{
cell = CategoryCell(style: UITableViewCellStyle.Default, reuseIdentifier: "categoryCell")
}
else
{
cell.ClearCurrentCellContext(cell.image, labelTitle: cell.lblCategory, labelDescription: cell.lblDescription)
}
if let ip = indexPath as NSIndexPath?
{
let key = Array(self.dict.keys)[ip.row] as ListItem
cell.SetCell(key, image: cell.image, labelTitle: cell.lblCategory, labelDescription: cell.lblDescription)
}
return cell
}
And I fill the dictionary inside of this block:
Alamofire.request(.POST, WSConstants.WebServiceAddress, parameters: nil)
.responseJSON
{(request, response, JSON, error) in
if let jsonResult: NSDictionary = JSON as? NSDictionary
{
if let categories = jsonResult[WSConstants.CATEGORIES] as? NSDictionary
{
if let wsStatus = categories.valueForKey(WSConstants.WS_STATUS) as? String
{
if(wsStatus == "ok")
{
var mainObj: NSDictionary!
var mainItem: ListItem!
for(var i=0; i<mainJSONArray.count; i++)
{
mainObj = mainJSONArray.objectAtIndex(i) as! NSDictionary
mainItem = ListItem()
mainItem.itemId = mainObj.valueForKey(WSConstants.ID) as! Int
mainItem.itemName = mainObj.valueForKey(WSConstants.TITLE) as! String
mainItem.itemDescription = mainObj.valueForKey(WSConstants.DESCRIPTION) as! String
mainItem.itemIcon = mainObj.valueForKey(WSConstants.ICON) as! String
mainItem.parentId = mainObj.valueForKey(WSConstants.PARENT) as! Int
mainItem.postCount = mainObj.valueForKey(WSConstants.POST_COUNT) as! Int
if let subJSONArray = mainObj.valueForKey(WSConstants.SUB) as? NSArray
{
var midCategoryList: [ListItem]! = [ListItem]()
var subObj: NSDictionary!
var subItem: ListItem!
for(var i=0; i<subJSONArray.count; i++)
{
subObj = subJSONArray.objectAtIndex(i) as! NSDictionary
subItem = ListItem()
subItem.itemId = subObj.valueForKey(WSConstants.ID) as! Int
subItem.itemName = subObj.valueForKey(WSConstants.TITLE) as! String
subItem.itemDescription = subObj.valueForKey(WSConstants.DESCRIPTION) as! String
subItem.itemIcon = subObj.valueForKey(WSConstants.ICON) as! String
subItem.parentId = subObj.valueForKey(WSConstants.PARENT) as! Int
subItem.postCount = subObj.valueForKey(WSConstants.POST_COUNT) as! Int
midCategoryList.append(subItem)
subItem = nil
subObj = nil
}
// The code below line fills the dictionary with key and its values
self.dict[mainItem] = midCategoryList
midCategoryList = nil
}
mainItem = nil
mainObj = nil
}
Utility.ReloadTableViewDataWithAnimations(self.categoryTableView)
}
}
}
}
ListItem class:
class ListItem: Serializable, Hashable, NSCoding
{
var uniqueID: Int = 0
override var hashValue: Int { return uniqueID.hashValue }
var itemId: Int
var itemName: String!
var itemIcon: String!
var itemDescription: String!
var parentId: Int!
var postCount: Int!
var content: String!
override init()
{
self.itemId = 0
self.itemName = ""
self.itemIcon = ""
self.parentId = 0
self.postCount = 0
self.content = ""
self.itemDescription = ""
}
init(itemId: Int, itemName: String!, itemIcon: String!, itemDescription: String!, parentId: Int!, postCount: Int, content: String!, date: String!, url: String!)
{
self.itemId = itemId
self.itemName = itemName
self.itemIcon = itemIcon
self.parentId = parentId
self.postCount = postCount
self.content = content
self.itemDescription = itemDescription
}
deinit
{
}
required init(coder aDecoder: NSCoder)
{
self.itemId = aDecoder.decodeIntegerForKey("itemId") as Int
self.itemName = aDecoder.decodeObjectForKey("itemName") as! String
self.itemIcon = aDecoder.decodeObjectForKey("itemIcon") as! String
self.itemDescription = aDecoder.decodeObjectForKey("itemDescription") as! String
}
func encodeWithCoder(aCoder: NSCoder)
{
aCoder.encodeInteger(self.itemId, forKey: "itemId")
aCoder.encodeObject(self.itemName, forKey: "itemName")
aCoder.encodeObject(self.itemIcon, forKey: "itemIcon")
aCoder.encodeObject(self.itemDescription, forKey: "itemDescription")
}
}
func ==(lhs: ListItem, rhs: ListItem) -> Bool
{
return lhs.uniqueID == rhs.uniqueID
}
Is this a swift bug or I make some mistakes to fill it ?
Thank you for your answers
King regards
Solution:
The reason of the problem is that using == instead of === in ListItem class. Daniel T.'s solution is the right answer. Thank you all.

Without seeing more code, my guess is that the problem lies in your ListItem's == operator. The following code does not exhibit the problem you are describing:
//: Playground - noun: a place where people can play
class ListItem: Hashable {
var itemId: Int = 0
var itemName: String = ""
var itemDescription: String = ""
var itemIcon: String = ""
var parentId: Int = 0
var postCount: Int = 0
var hashValue: Int {
return itemId.hashValue
}
}
func ==(lhs: ListItem, rhs: ListItem) -> Bool {
return lhs === rhs // simple identity
}
var dict = Dictionary<ListItem, [ListItem]>()
let arr = [ListItem(), ListItem()]
dict[ListItem()] = arr
dict[ListItem()] = arr
dict.keys.array.count

Related

Unable to give no. of rows for table view having model class data?

I am having json function below like to get the data from model class and to pass to the table view but the problem is how to give rows count so that in order to pass the data to the table view and here i need to give items model class count to the table view and here I am using table view for pagination so i am appending the data to the list class model can any one help me how to resolve this ?
var listClassModel = [ModelClass]()
func listCategoryDownloadJsonWithURL(listUrl: String) {
let url = URL(string: listUrl)!
print(listUrl)
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil { print(error!); return }
do {
if let jsonObj = try JSONSerialization.jsonObject(with: data!) as? [String:Any] {
self.listClassModel.append(ModelClass(dict: jsonObj as [String : AnyObject]))
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
} catch {
print(error)
}
}
task.resume()
}
struct ModelClass {
var items : [List]
var totalCount : Int
var searchCriteria : SearchCriteria
init(dict:[String:AnyObject]) {
totalCount = dict["total_count"] as! Int
let searchDict = dict["search_criteria"] as? [String:AnyObject]
searchCriteria = SearchCriteria(dict: searchDict!)
let arr = dict["items"] as? [[String:AnyObject]]
var listArr = [List]()
for obj in arr! {
listArr.append(List(dict: obj))
}
items = listArr
}
}
struct List {
let name : String
let sku : Any
let id : Int
let attributeSetId : Int
let price : Int
let status : Int
let visibility : Int
let typeId: String
let createdAt : Any
let updatedAt : Any
var customAttribute = [ListAttribute]()
init(dict : [String:Any]) {
if let customAttribute = dict["custom_attributes"] as? [[String: AnyObject]] {
var result = [ListAttribute]()
for obj in customAttribute {
result.append(ListAttribute(json: obj)!)
}
self.customAttribute = result
} else {
self.customAttribute = [ListAttribute]()
}
self.name = (dict["name"] as? String)!
self.sku = dict["sku"]!
self.id = (dict["id"] as? Int)!
self.attributeSetId = (dict["attribute_set_id"] as? Int)!
self.price = (dict["price"] as? Int)!
self.status = (dict["status"] as? Int)!
self.visibility = (dict["visibility"] as? Int)!
self.typeId = (dict["type_id"] as? String)!
self.createdAt = dict["created_at"]!
self.updatedAt = dict["updated_at"]!
}
}
struct SearchCriteria {
var filterGroup : [FilterGroup]
var sortGroup : [SortGroup]
var pageSize : Int
var pageNumber : Int
init(dict:[String:AnyObject]) {
if let arr = dict["filter_groups"] as? [[String: AnyObject]]{
var filterArr = [FilterGroup]()
for obj in arr {
filterArr.append(FilterGroup(dict: obj))
}
self.filterGroup = filterArr
} else {
self.filterGroup = [FilterGroup]()
}
if let arr = dict["sort_orders"] as? [[String: AnyObject]]{
var filterArr = [SortGroup]()
for obj in arr {
filterArr.append(SortGroup(dict: obj))
}
self.sortGroup = filterArr
} else {
self.sortGroup = [SortGroup]()
}
self.pageSize = dict["page_size"] as! Int
self.pageNumber = dict["current_page"] as! Int
}
}
Below is the code for table view
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let arr = listClassModel[section].items
return arr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "productsCell", for: indexPath) as! productsCell
let arr = listClassModel[indexPath.section].items[indexPath.row]
let images = listCategoryImageArray[indexPath.row]
let urls = NSURL(string: images)
self.tableView.isHidden = false
cell.productImage.hnk_setImageFromURL(urls! as URL)
cell.productName.lineBreakMode = NSLineBreakMode.byWordWrapping
cell.productName.numberOfLines = 2
cell.productName.text = arr.name
cell.productPrice.text = "$\( (arr.price)).00"
cell.buynowButton .addTarget(self, action: #selector(buyNowButton(_:)), for:UIControlEvents.touchUpInside)
cell.cartButton .addTarget(self, action: #selector(cartButton(_:)), for:UIControlEvents.touchUpInside)
return cell
}

Trying to load data from Parse however I keep receiving the error EXC_Brekapoint whenever I try to compile the app

I am currently trying to load data from Parse (which I realize will soon be obselete but I have to stay on it for now) and I have a custom class that is to handle all the data from the backend like so:
import Foundation
import Parse
class FeedContent: PFObject {
#NSManaged var address: String
#NSManaged var content: PFFile
#NSManaged var isVideo: Int
#NSManaged var attendeeObjectId: String
#NSManaged var created: NSDate?
#NSManaged var objId: String
init(address: String, content: PFFile, isVideo: Int, attendeeObjectId: String, created: NSDate?, objId: String) {
super.init()
self.address = address
self.content = content
self.isVideo = isVideo
self.attendeeObjectId = attendeeObjectId
self.created = createdAt
self.objId = objId
}
override init() {
super.init()
}
}
extension FeedContent: PFSubclassing {
class func parseClassName() -> String {
return "FeedContent"
}
override class func initialize() {
var onceToken: dispatch_once_t = 0
dispatch_once(&onceToken) {
self.registerSubclass()
}
}
}
and in my Display View Controller I am creating an array to house these items then calling a function to display the data , like here:
func addPFObjectInFeedContent(object : PFObject) {
let newItem = FeedContent()
newItem.address = (object["address"] as? String)!
newItem.isVideo = (object["isVideo"] as? Int)!
newItem.attendeeObjectId = (object["attendeeObjectId"] as? String)!
//newItem.eventObjectId = (object["eventObjectId"] as? String)!
newItem.content = (object["content"] as? PFFile)!
newItem.created = object.createdAt
newItem.objId = object.objectId!
self.feedContentItems.append(newItem)
}
Here is the array as well:
var feedContentItems = [FeedContent]()
On this line specifically is where the EXC_Breakpoint error occurs:
newItem.isVideo = (object["isVideo"] as? Int)!
so i was curious if anyone had any intimation of what may be happening?
func loadParseFeed() {
let contentQuery = PFQuery(className: "FeedContent")
contentQuery.whereKey("address", equalTo: defaults.objectForKey("newLocation")! as! String)
//contentQuery.whereKey("flagged", notEqualTo: true)
contentQuery.orderByDescending("createdAt")
if blacklist.count != 0 {
for var item = 0; item <= blacklist.count; item += 1 {
contentQuery.whereKey("attendeeObjectId", equalTo: blacklist[item])
}
}
contentQuery.findObjectsInBackgroundWithBlock({ (objects:[PFObject]?,error: NSError?) -> Void in
if error == nil {
if let object = objects as [PFObject]? {
if objects!.count > 0 {
for thing in objects! {
// let newItem = FeedContent()
// newItem.isVideo = (thing["isVideo"] as? Int)!
// newItem.attendeeObjectId = (thing["attendeeObjectId"] as? String)!
// newItem.eventObjectId = (thing["eventObjectId"] as? String)!
// newItem.content = (thing["content"] as? PFFile)!
// newItem.created = thing.createdAt
// newItem.objId = thing.objectId!
// self.feedContentItems.append(newItem)
self.addPFObjectInFeedContent(thing)
}
self.advanceFeed()
// self.overviewTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "advanceFeed", userInfo: nil, repeats: true)
// self.overviewTimer.fire()
}
}
}
})
}

Check For Empty Array From JSON

I am trying to get an array of strings from JSON and I'm trying to figure out how to deal with it if the returned array is empty. In some cases, the returned value is [] and for other cases, the array contains string values. It is crashing because of unexpectedly finding a nil value.
For clarification, the gyms array is passed from another class and everything here works without the code for the images.
Here is my relevant code:
var gyms = [AnyObject]()
var imageArrays = [[String]?]()
In viewDidLoad()
getGymImages()
Methods to get JSON data:
func getGymImages() {
var index = 0
for dictionary in gyms {
let id = dictionary["id"] as! String
let urlString = String("https://gyminyapp.azurewebsites.net/api/GymImage/\(id)")
let url = NSURL(string: urlString)
let data = NSData(contentsOfURL: url!)
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
for imageArray in json as! [AnyObject] {
imageArrays.append((imageArray as? [String])!)
}
} catch {
print("Error")
}
index += 1
}
addImagesToGyms()
}
func addImagesToGyms() {
var index = 0;
for array in imageArrays {
var dictionary = gyms[index] as! [String:AnyObject]
dictionary["images"] = array
gyms[index] = dictionary
index += 1
}
}
In cellForRowAtIndexPath()
let gymImages = dictionary["images"] as! [String]
if gymImages.count > 0 {
let firstImageURL = gymImages[0] as String
cell.cellImageView.sd_setImageWithURL(NSURL(string: firstImageURL))
}
EDIT: I was asked to show more of the file, so here it is.
import UIKit
class GymListTableViewController: UITableViewController {
var gyms = [AnyObject]()
var gymName: String?
var gymAddress: String?
var gymPhoneNumber: String?
var gymWebsite: String?
var gymID: String?
var gymLatitude: String?
var gymLongitude: String?
var maxDistance: Double?
var myLocation: CLLocation?
var milesArray = [Double]()
var imageArrays = [[String]?]()
var segmentedControl: UISegmentedControl?
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Gyms"
tableView.registerNib(UINib(nibName: "GymListTableViewCell", bundle: nil), forCellReuseIdentifier: "gymCell")
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "waypoint_map"), style: .Done, target: self, action: #selector(showMapView))
self.navigationItem.rightBarButtonItem?.tintColor = BarItems.greenTintColor
segmentedControl = UISegmentedControl(items: ["A-Z", "Z-A", "Rating", "Distance"])
segmentedControl?.sizeToFit()
segmentedControl?.selectedSegmentIndex = 0
segmentedControl!.setTitleTextAttributes([NSFontAttributeName: UIFont(name:"Helvetica-Light", size: 15)!],
forState: UIControlState.Normal)
segmentedControl?.addTarget(self, action: #selector(changeSelectedSegmentIndex), forControlEvents: .ValueChanged)
self.navigationItem.titleView = segmentedControl
sortAlphabetically()
let backgroundImage = UIImage(named: "gray_background")
let backgroundImageView = UIImageView(image: backgroundImage)
tableView.backgroundView = backgroundImageView
addDistancesToGyms()
getGymImages()
// geocodeAddresses()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func addDistancesToGyms() {
var index = 0
for distance in milesArray {
var dictionary = gyms[index] as! [String:AnyObject]
dictionary["distance"] = distance
gyms[index] = dictionary
index += 1
}
}
func getGymImages() {
var index = 0
for dictionary in gyms {
let id = dictionary["id"] as! String
let urlString = String("https://gyminyapp.azurewebsites.net/api/GymImage/\(id)")
let url = NSURL(string: urlString)
let data = NSData(contentsOfURL: url!)
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
for imageArray in json as! [AnyObject] {
imageArrays.append((imageArray as? [String])!)
}
} catch {
print("Error")
}
index += 1
}
addImagesToGyms()
}
func addImagesToGyms() {
var index = 0;
for array in imageArrays {
var dictionary = gyms[index] as! [String:AnyObject]
dictionary["images"] = array
gyms[index] = dictionary
index += 1
}
}
func changeSelectedSegmentIndex() {
let segmentTouched = segmentedControl?.selectedSegmentIndex
if segmentTouched == 0 {
sortAlphabetically()
} else if segmentTouched == 1 {
sortReverseAlphabetically()
} else if segmentTouched == 2 {
sortByRatingAscending()
} else {
sortByDistanceAscending()
}
}
func sortAlphabetically() {
gyms.sortInPlace{
(($0 as! Dictionary<String, AnyObject>)["name"] as? String) < (($1 as! Dictionary<String, AnyObject>)["name"] as? String)
}
tableView.reloadData()
}
func sortReverseAlphabetically() {
gyms.sortInPlace{
(($0 as! Dictionary<String, AnyObject>)["name"] as? String) > (($1 as! Dictionary<String, AnyObject>)["name"] as? String)
}
tableView.reloadData()
}
func sortByRatingAscending() {
// TODO: Sort by rating
}
func sortByDistanceAscending() {
gyms.sortInPlace{
(($0 as! Dictionary<String, AnyObject>)["distance"] as? Double) < (($1 as! Dictionary<String, AnyObject>)["distance"] as? Double)
}
tableView.reloadData()
}
func showMapView() {
self.performSegueWithIdentifier("displayMapSegue", sender: self.navigationController)
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return gyms.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 131
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("gymCell", forIndexPath: indexPath) as! GymListTableViewCell
let dictionary = gyms[indexPath.row]
let addressDictionary = dictionary["address"]
let street = addressDictionary!!["streetAddress"] as! String
let city = addressDictionary!!["city"] as! String
let state = addressDictionary!!["state"] as! String
let zipInt = addressDictionary!!["zipCode"] as! Int
let zipCode = String(zipInt)
let addressString = String("\(street) " + "\(city), " + "\(state) " + "\(zipCode)")
cell.backgroundColor = UIColor.clearColor()
cell.gymNameLabel.text = dictionary["name"] as? String
cell.gymAddressLabel.text = addressString
let miles = dictionary["distance"] as! Double
let milesString = String(format: "%.1f miles", miles)
let milesLabelString = milesString
cell.milesLabel.text = milesLabelString
let gymImages = dictionary["images"] as! [String]
if gymImages.count > 0 {
let firstImageURL = gymImages[0] as String
cell.cellImageView.sd_setImageWithURL(NSURL(string: firstImageURL))
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let dictionary = gyms[indexPath.row]
if dictionary["name"] as? String != nil {
self.gymName = dictionary["name"] as? String
}
let cell = tableView.cellForRowAtIndexPath(indexPath) as! GymListTableViewCell
self.gymAddress = cell.gymAddressLabel.text
if dictionary["phone"] as? String != nil {
self.gymPhoneNumber = dictionary["phone"] as? String
}
if dictionary["website"] as? String != nil {
self.gymWebsite = dictionary["website"] as? String
}
if dictionary["id"] as? String != nil {
self.gymID = dictionary["id"] as? String
}
if dictionary["latitude"] as? String != nil {
self.gymLatitude = dictionary["latitude"] as? String
}
if dictionary["longitude"] as? String != nil {
self.gymLongitude = dictionary["longitude"] as? String
}
self.performSegueWithIdentifier("detailFromListSegue", sender: self.navigationController)
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "detailFromListSegue" {
let gymDetailVC = segue.destinationViewController as! DetailTableViewController
if self.gymName != nil {
gymDetailVC.gymName = self.gymName
} else {
gymDetailVC.gymName = nil
}
if self.gymAddress != nil {
gymDetailVC.gymAddress = self.gymAddress
} else {
gymDetailVC.gymAddress = nil
}
if self.gymPhoneNumber != nil {
gymDetailVC.gymPhoneNumber = self.gymPhoneNumber
} else {
gymDetailVC.gymPhoneNumber = nil
}
if self.gymWebsite != nil {
gymDetailVC.gymWebsite = self.gymWebsite
} else {
gymDetailVC.gymWebsite = nil
}
if self.gymID != nil {
gymDetailVC.gymID = self.gymID!
} else {
// gymDetailVC.gymID = nil
}
if self.gymLatitude != nil {
gymDetailVC.gymLatitude = self.gymLatitude!
}
if self.gymLongitude != nil {
gymDetailVC.gymLongitude = self.gymLongitude!
}
}
}
}
numberOfRowsInSection should be returning gymImages.count if it isn't already.
Then as a safeguard you can always do
if indexPath.row < gymImages.count {
}
before accessing the content in cellForRowAtIndexPath

Dribble Api returning wrong data

Hi guys so recently there has been a bug of getting data from Dribble..
My Dribbble client IOS shows shots on the main screen and if you click on a collectionView Cell it takes you to the detail of the shot..
And i am getting Dribble Data through its api with this method.
The Code for the getShots Method
class func getShots(url: String, callback:(([Shot]) -> Void)){
var shots = [Shot]()
let url = url + "&access_token=" + Config.ACCESS_TOKEN
HttpService.getJSON(url){ (jsonData) -> Void in
for shotData in jsonData {
let shot = Shot(data: shotData as! NSDictionary)
shots.append(shot)
}
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0), { () -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
callback(shots)
})
})
}
}
The Code for the getJSON method..
class HttpService {
class func getJSON(url: String, callback:((NSArray) -> Void)) {
let nsURL = NSURL(string: url)!
Alamofire.request(.GET, nsURL).response { (request, response, data, error) -> Void in
if error != nil{
print("error")
}
if data != nil {
let jsonData = (try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSArray
callback(jsonData)
}
}
}
}
This code is above which loads The Shot JSON Data successfully..
So when i debug it on the self.shots = shots line it returns something like this..
The log when debugging on the self.shots = shots line
It all works fine.. and the code for the class of Detail of a Shot...
I have been using dynamic tableView to show the Shot Detail
The code in ShotDetail the code where the label are allocated their text.. basically The TableView Data Source Method..
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 2
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if section == 0 {
return 9
} else {
return comments.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 0 {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! vlcTableViewCell
// Configure the cell
// the views . likes. and the comment Count label are allocated
cell.viewsCount.text = "\(shot.viewsCount)"
cell.likesCount.text = "\(shot.likesCount)"
cell.commentCount.text = "\(shot.commentCount)"
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! descCell
// Configure the Cell
// the text for the labels
cell.usernameLabel.text = "\(shot.user.username)"
cell.descriptionLabel.text = "\(shot.description)"
cell.profileImageView.sd_setImageWithURL(NSURL(string: shot.user.avatarUrl), placeholderImage: UIImage(named: "2"))
return cell
} else if indexPath.row == 2 {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell4", forIndexPath: indexPath) as! teamCell
if shot.team == nil{
cell.teamNameLabel.text = "Team"
} else {
cell.teamNameLabel.text = "\(shot.team.name)"
}
return cell
} else if indexPath.row == 4 {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell5", forIndexPath: indexPath) as! reboundShotsCount
cell.reboundCountLabel.text = "\(shot.reboundCount)"
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell10", forIndexPath: indexPath) as! CommentCell
let comment = comments[indexPath.row]
cell.nameLabel.text = comment.user.name
cell.commentLabel.text = comment.body
cell.avatarImageView.alpha = 0.0
cell.avatarImageView.sd_setImageWithURL(NSURL(string: comment.user.avatarUrl), placeholderImage: UIImage(named: "2"), completed: { (image, error, cacheType, url) -> Void in
cell.avatarImageView.alpha = 1.0
// Animate the imageView after the image is loaded
cell.animationView.layer.cornerRadius = 25
cell.animationView.delay = 0
cell.animationView.duration = 0.5
cell.animationView.type = "popAlpha"
cell.animationView.startCanvasAnimation()
})
cell.dateLabel.text = comment.date
return cell
}
}
and the Code for the Shot Class.. From where i get all the data to set to the labels
import Foundation
class Shot: DribbbleBase {
var imageUrl : String!
var htmlUrl : String!
var commentsUrl : String!
var bucketsUrl : String!
var likesUrl : String!
var attachmentUrl : String!
var reboundUrl : String!
var title : String!
var date : String!
var description : String!
var commentCount : Int!
var viewsCount : Int!
var likesCount : Int!
var bucketsCount : Int!
var attachmentsCount : Int!
var reboundCount : Int!
var imageUrll : String!
var teamUrl : String!
var user : User!
var team : Team!
override init(data: NSDictionary) {
super.init(data: data)
self.commentCount = data["comments_count"] as! Int
self.likesCount = data["likes_count"] as! Int
self.viewsCount = data["views_count"] as! Int
self.bucketsCount = data["buckets_count"] as! Int
self.attachmentsCount = data["attachments_count"] as! Int
self.reboundCount = data["rebounds_count"] as! Int
self.commentsUrl = Utils.getStringFromJSON(data, key: "comments_url")
self.bucketsUrl = Utils.getStringFromJSON(data, key: "buckets_url")
self.likesUrl = Utils.getStringFromJSON(data, key: "likes_url")
self.title = Utils.getStringFromJSON(data, key: "title")
self.attachmentUrl = Utils.getStringFromJSON(data, key: "attachments_url")
self.reboundUrl = Utils.getStringFromJSON(data, key: "rebounds_url")
self.teamUrl = Utils.getStringFromJSON(data, key: "teams_url")
let dateInfo = Utils.getStringFromJSON(data, key: "created_at")
self.date = Utils.formatDate(dateInfo)
let desc = Utils.getStringFromJSON(data, key: "description")
self.description = Utils.stripHTML(desc)
let images = data["images"] as! NSDictionary
self.imageUrl = Utils.getStringFromJSON(images, key: "normal")
self.imageUrll = Utils.getStringFromJSON(images, key: "hidpi")
let tags = data["tags"] as! NSArray
if let userData = data["user"] as? NSDictionary {
self.user = User(data: userData)
}
if let teamData = data["team"] as? NSDictionary {
self.team = Team(data: teamData)
}
}
}
Now the problem occurs when i tap on the cell to go to the next cell.
before that if i debug in the Shot class..
The data looks like this
The Log Which shows the data returned
and now whenever i click on the cell. to go to the detail. the data returns only 7 value for the exact thing which in the first was returning all the values needed..
the code i am using to push the data in PopularShotsCollectionViewController is this.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "1"){
let selectedItems = collectionView!.indexPathsForSelectedItems()
if let sItem = selectedItems as [NSIndexPath]!{
let shot = shots[sItem[0].row]
let controller = segue.destinationViewController as! ShotDetail
controller.shot = shot
}
}
}
But the log only returns 7 value in that..
https://www.dropbox.com/s/4vkgg7a3f44fg35/Screen%20Shot%202016-03-28%20at%2014.40.23.png?dl=0
I have put the link in a code block as i cant post more than 2 links.
Any help will be really appreciated..
Thanks
Aryan
let shot = shots[sItem[0].row] Might be the issue. You're passing the same index to the DetailVC. You could save an array of the selected shots then pass it to shot variable in your DetailVC (If the shot variable is an array of shots)
var selectedIndex = NSIndexPath()
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedIndex = indexPath
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "1"){
let selectedItems = collectionView!.indexPathsForSelectedItems()
let selectedShots = shots[selectedIndex.row]
let controller = segue.destinationViewController as! ShotDetail
controller.shot = selectedShots
}
}
}

Unable to put JSON array of dictionaries into class object for my UITableView cell

I have some JSON I'm iterating through (it contains an array of dictionaries) and add to an array of custom objects I made in order to work with the data and add fields to my UITableView cell.
I'm creating an array of my custom objects at the top of the page:
var warehouseItems: [Inventory] = [];
In my viewDidLoad() I have the following:
let urlString = "myUrl.php";
let session = NSURLSession.sharedSession();
let url = NSURL(string: urlString)!;
session.dataTaskWithURL(url) { (data: NSData?, response:NSURLResponse?, error: NSError?) -> Void in
if let responseData = data {
do {
let json = try NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.AllowFragments) as! Dictionary<String, AnyObject>;
//print(json);
if let inventoryDictionary = json["inventory"] as? [Dictionary<String, AnyObject>] {
//print(inventoryDictionary);
for anItem in inventoryDictionary {
if let id = anItem["id"] as? Int, let item = anItem["item"] as? String, let description = anItem["description"] as? String, let quantityOnHand = anItem["quantityOnHand"] as? Int, let supplierId = anItem["supplier_id"] as? Int, let supplierName = anItem["supplierName"] as? String {
let item = Inventory(id: id, item: item, description: description, quantityOnHand: quantityOnHand, supplierId: supplierId, supplierName: supplierName);
self.warehouseItems.append(item);
}
}
print(self.warehouseItems); //This just prints 'Warehouse.Inventory' for every item I have
}
} catch {
print("Could not serialize");
}
}
}.resume()
For some reason it doesn't add the item to the Inventory object. My tableView is blank. It only works when I manually add a string to the cell, so I know my tableView is wired up properly.
When I print(self.warehouseItems) it just shows Warehouse.Inventory 6 times (current number of items my JSON is returning) in the output. In fact if I print(inventoryDictionary) I get the following:
[["item": Item 1, "supplierName": Supplier 1, "quantityOnHand": 42, "id": 1, "supplier_id": 1, "description": Description],
["item": Item 2, "supplierName": Supplier 1, "quantityOnHand": 1001, "id": 2, "supplier_id": 1, "description": Description], ... and so on
Here's my tableview protocol where I'm trying to assign the object's properties to my row:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return warehouseItems.count; //Make sure to set count of array from json
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as UITableViewCell;
let row = indexPath.row;
cell.textLabel!.text = warehouseItems[row].item;
cell.detailTextLabel!.text = warehouseItems[row].description;
return cell;
}
In case you need it, here's my custom Inventory object class:
class Inventory {
private var _id, _quantityOnHand: Int!;
private var _item, _description: String!;
private var _supplierId: Int?;
private var _supplierName: String?;
var id: Int {
get {
return _id;
}
}
var item: String {
get {
return _item;
}
}
var description: String {
get {
return _description;
}
}
var quantityOnHand: Int {
get {
return _quantityOnHand;
}
}
var supplierId: Int {
get {
return _supplierId!;
}
}
var supplierName: String {
get {
return _supplierName!;
}
}
init(id: Int, item: String, description: String, quantityOnHand: Int, supplierId: Int, supplierName: String) {
_id = id;
_item = item;
_description = description;
_quantityOnHand = quantityOnHand;
_supplierId = supplierId;
_supplierName = supplierName;
}
My head is spinning since I switched to swift, especially all the optionals and unwrapping.

Resources