Tableview numberOfRowsInSection returns duplicate .count number? - ios

This might be a really stupid question, but i can't seem to find the answer anywhere.
Below is a small part code of a tableview and an empty dictionary.
// MARK: - Object2
struct Object2: Codable {
let id: Int
let url: String
let displayname: String
let media: [Media2]
}
// MARK: - Media2
struct Media2: Codable {
let id, prodno: Int
let webpath: String
let slot: Int
let type, extdata: String
let ctime, xsize, ysize, mediasetid: Int
let alt, title: String
let generation: Int
let created, changed: String
}
var sokresultat2 = [Object2]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(sokresultat2.count)
return sokresultat2.count
}
The "numberOfRowsInSection" func is checking the .count of the variable "sokresultat2", and it always prints out double zero, just like this:
0
0
Isn't it supposed to print out only 1 zero?
I've played around with the code, but it always prints out a duplicate of the amount, why is this? I'm simply curious to how this works.
Thanks!

Related

Swift 4 Remove JSON zero value and It's key name from tableView array

My task is I am trying to get keys and values from JSON response and load into tableView. Its like a billing UI left side list of fee names and right side It's prices. Keys pricenames and Values It prices
Here, my problem is I am receiving zero prices for some pricenames, If I received zero value I dont show that value and relevant key name in tableView.
If I load directly JSON to TableView list of price name first letter should be capital but JSON response only small providing. So, I decided to show static names(we don't add new name) and JSON price value. I would like to learn which is best solution for my problem and how to fix this?
// JSON Struct
struct Item : Codable {
var name : String
var price : String
init(name: String, price: String) {
self.name = name
self.price = price
}
}
// Array Declarations
var billing_array = [Item]()
// JSON Parsing
if let results = result["result"] as? [String: AnyObject] {
self.billing_array.append(results)
}
// TableView Delegation
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.billing_array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
let item = billing_array[indexPath.row]
cell.product_name.text = item.name
cell.product_price.text = item.price
return cell
}

Custom Swift 2 Struct - Cannot subscript a value of type [ILT] on pushControllerWithName()

I am trying to pass my custom struct ILT through pushControllerWithName() so I can pass it to the next screen in my watchOS 2 app. ILTList is an array of ILT types, and the pushControllerWithName() is happening when the user taps on a row in the table, which has its' rows fed from ILTList.
ILTList is initialised with var ILTList = [ILT](), and the ILT struct is as follows:
struct ILT {
let homeworkID: Int
let title: String
let subject: String
let teacher: String
let teacherCode: String
let studentID: Int
let description: String
let due: Double
let status: String
let hasAttachments: Bool
}
And this is where the tap occurs:
override func table(table: WKInterfaceTable, didSelectRowAtIndex rowIndex: Int) {
print(ILTList[rowIndex])
let context:AnyObject = ILTList[rowIndex]
self.pushControllerWithName("showILT", context: context)
}
With this code I get
Cannot subscript a value of type '[ILT]'
When I change context:AnyObject to just context or context:ILT, it says:
Cannot convert value of type 'ILT' to expected argument type
'AnyObject'?
What am I missing here?
For people who really want to use pushControllerWithName(), I formed the following solution by converting my ILT variable type to a Dictionary.
override func table(table: WKInterfaceTable, didSelectRowAtIndex rowIndex: Int) {
// construct the dictionary
let context = [
"title":ILTList[rowIndex].title,
"subject":ILTList[rowIndex].subject,
"teacher":ILTList[rowIndex].teacher
]
self.pushControllerWithName("showILT", context: context)
}
That's a weird error message. I think the problem might be that pushControllerWithName:context: takes a context of type AnyObject?, and structs can't be passed for that type. A dictionary works because it is a class-type object.

Array has append, but no value inside

I've declared a String array in my Swift file.
var postTitleArray : [String] = []
In my viewDidLoad method, I've append values into my array...
RestApiManager.sharedInstance.makeGetRequest("/development/vw_posts?filter=parent_term_id%20%3D%20%22%5B82%5D%22", onCompletion: { json in
for result in json["record"].arrayValue
{
let postTitle = result["post_title"].stringValue
print(postTitle)
self.postTitleArray.append(postTitle)
}
})
Other than that, I've use the count of array into the numberOfRowsInSection to set the rows number of my tableView...
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.postTitleArray.count
}
However, the numberOfRowsInSection has return 0, why could it happened, I've assigned value into my postTitleArray, anyone can help me take a look on this? Appreciated...
Your API call is likely not finished before numberOfRowsInSection is called.
Try calling reloadData on your UITableView instance after you have populated your postTitleArray. (I'm assuming here you have a reference to your UITableView and it's called tableView)
RestApiManager.sharedInstance.makeGetRequest("/development/vw_posts?filter=parent_term_id%20%3D%20%22%5B82%5D%22", onCompletion: { json in
for result in json["record"].arrayValue
{
let postTitle = result["post_title"].stringValue
print(postTitle)
self.postTitleArray.append(postTitle)
}
self.tableView.reloadData()
})
You should check :
if let postTitle = result["post_title"]?.stringValue{
self.postTitleArray.append(postTitle)
self.tableView.reloadData()
}

Swift 2 Unable to remove optional binding

I am new in Swift and don't have much more idea on optional (! , ?). I tried to fetch data from plist, create Model and show to UITableView. Table data shows perfectly, but it shows with Optional() binding. I tried change ! to ? but unable to unwrap. Could you please, guide me to solve this problem.
Here is my code & output -
var fileName : String?
var dataArray : Array<SHQuesAns>?
For fetch data from pList -
func loadTableView(){
dataArray = SHDataAccess.init(fname: fileName).arrayFromPlist()
self.questionTableView.dataSource = self
self.questionTableView.delegate=self
self.questionTableView.reloadData()
}
SHDataAccess class -
import UIKit
var fileName : String!
class SHDataAccess: NSObject {
init(fname:String?) {
super.init()
fileName = fname
}
func arrayFromPlist() -> Array <SHQuesAns>?{
let dataPlists = NSMutableArray(contentsOfFile:NSBundle.mainBundle().pathForResource(fileName, ofType: "plist")!)
var dataObj : Array <SHQuesAns>? = Array()
for data in dataPlists! {
dataObj?.append(SHQuesAns.init(_dic: data as! NSDictionary))
}
return dataObj
}
}
And UITableView delegates -
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray == nil ? 0 : dataArray!.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let aCell = self.questionTableView.dequeueReusableCellWithIdentifier("qcell",forIndexPath: indexPath) as! SHQuestionCell
let q : SHQuesAns = dataArray![indexPath.row]
aCell.lblQuestion.text = "\(q.question)"
return aCell
}
Here is the output -
This will remove that Optional() text:
if let q = q.question as? String {
aCell.lblQuestion.text = "\(q.question!)"
} else {
aCell.lblQuestion.text = ""
}
The key is to unwrap the string contained in the question object so that when it is assigned to the text of the label, the Optional() part will not be included.
I’ve added support for the nil case if the question string is not defined.
You might also consider not making your dataObj array optional? what purpose does it serve to be optional? Seems to me that if you need to add items to the array then you know it should exist and since you've initialized it it will always exist but then may be empty. Instead just make it implicitly unwrapped and then return nil if there's no data, then the objects of the array won't all be optional.
if you have a default in mind that you would want the optional string to fall back to, a simple fix would be something like:
"\(q.question ?? "")"
which will default to an empty string if q.question is nil
also: be careful of all of your force unwraps. it might make more sense to have some guard statements or if let unwraps.
and swift array's can be written like so: var dataArray : [SHQuesAns]?
but there aren't many situations where you need to differentiate between a nil array and an empty array so you can just do var dataArray = [SHQuesAns]() and save yourself the need to unwrap

Appending to an Int to a collection of type [Int] gives 'not identical' error

Here's the code.
class Stack {
var size: Int = 0
var items: [Int] = []
func push(element: Int) {
items += element // Error - '[Int]' is not identical to 'UInt8'
}
func pop() -> Int {
return items.removeLast()
}
}
Everything is explicitly typed. How does the interpreter decide that my element is of UInt8 type?
The meaning of + has changed. You can use it only with two arrays. So you can say:
items += [element]
However, I recommend using append instead.

Resources