first cell in tableview array index out of range error - arrays

I have a tableview in which the first cell is different from all the others (I have two custom cells in the table dequeued With different Identifiers). The codes are as below:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("profileCell") as! SbProfileViewCell
//cell.textArea.text = bio[indexPath.row]
//pictureFile[indexPath.row].getDataInBackgroundWithBlock { (fileData, error) -> Void in
if let pic = UIImage(data: fileData!) {
cell.imageView.image = pic
}
}
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("postCell") as! SbPostsTableViewCell
cell.date.text = dateFormatter.stringFromDate(dates[indexPath.row - 1])
pictureFileOne[indexPath.row - 1].getDataInBackgroundWithBlock { (fileOneData, error) -> Void in
if let downloadedImageOne = UIImage(data: fileOneData!) {
cell.imageArea.image = downloadedImageOne
}
}
cell.textArea.text = text[indexPath.row - 1]
return cell
}
}
i'm getting the array out of index error for the commented lines and i'm also uncertain about whether using [indexPath.row - 1] would yield the effect I want (I want the second cell of the tableview to display the first object in the array), hope i explained everything ok, please help! thanks
EDIT
var dates = [NSDate]()
var autoBio = [String]()
func getPosts() {
let getPostsQuery = PFQuery(className: "allPosts")
getPostsQuery.whereKey("userId", equalTo: userNumber)
getPostsQuery.limit = 15
getPostsQuery.orderByDescending("createdAt")
getPostsQuery.findObjectsInBackgroundWithBlock { (posts, error) -> Void in
if let posts = posts {
self.dates.removeAll(keepCapacity: true)
for post in posts {
self.dates.append(post.createdAt as NSDate!)
}
}
print(self.dates.count)
}
}
func getBio() {
let bioQuery = PFQuery(className: "bios")
bioQuery.whereKey("userId", equalTo: userNumber)
bioQuery.limit = 1
bioQuery.findObjectsInBackgroundWithBlock { (bios, error) -> Void in
if let bios = bios {
self.bio.removeAll(keepCapacity: false)
for bio in bios {
self.bio.append(bio["about"] as! String)
}
}
}
print(self.bio.count)
}
i put getPosts() and getBio() in viewDidLoad. And I tried printing the bio and dates count as the end of these func and they do return a number > 0 so the arrays should be filled. Any idea what's wrong?

You should try using the first cell as Section Header cell...
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCellWithIdentifier("profileCell") as! SbPostsTableViewCell
return cell
}

Related

Ads array in tableview out of index

I have 3 arrays of data. I want to show ads after every 5 user cells in the table.
var nativeAds = [GADNativeAd]()
var item = [NewsElement]()
var filterItem = [NewsElement]()
After displaying 5 cells with ads, the application crashes with an error "Thread 1: Fatal error: Index out of range"
How do I re-add ads to the array or select an array with ads again?
There are smart guys sitting here, please help me. Thank you in advance!
below is my code
extension NewsViewController: GADNativeAdLoaderDelegate {
func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) {
print("\(adLoader) failed with error: \(error.localizedDescription)")
}
func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) {
print("Received native ad: \(nativeAd)")
nativeAds.append(nativeAd)
}
func adLoaderDidFinishLoading(_ adLoader: GADAdLoader) {
newsTblView.reloadData()
}
}
extension NewsViewController: UITableViewDelegate, UITableViewDataSource {
private func dataRow(for indexPath: IndexPath) -> Int? {
let (quotient, remainder) = (indexPath.row + 1).quotientAndRemainder(dividingBy: numAdsToLoad)
if remainder == 0 { return nil }
return quotient * (numAdsToLoad - 1) + remainder - 1
}
private func adRow(for indexPath: IndexPath) -> Int? {
let (quotient, remainder) = (indexPath.row + 1).quotientAndRemainder(dividingBy: numAdsToLoad)
if remainder != 0 { return nil }
return quotient - 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchActive {
return filterItem.count
} else {
return item.count + nativeAds.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let row = dataRow(for: indexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "NewsTableViewCell", for: indexPath) as! NewsTableViewCell
if searchActive {
let items = filterItem[row]
cell.configCell(model: items )
} else {
let items = item[row]
cell.configCell(model: items )
}
cell.selectionStyle = .none
cell.backgroundColor = .clear
return cell
} else if let row = adRow(for: indexPath) {
let nativeAd = nativeAds[row] <-- "Thread 1: Fatal error: Index out of range"
nativeAd.rootViewController = self
let nativeAdCell = tableView.dequeueReusableCell(withIdentifier: "UnifiedNativeAdCell", for: indexPath) as! GADNativeAdViewCell
nativeAdCell.setAdData()
return nativeAdCell
}
fatalError("Did not find data or ad for cell: Should never get here")
}
}

How to return different array count in tableView numberOfRowsInSection in swift

I have tableView with one cell which contains one label.. i need to display different label text for different category.
for that i have created empty iteamArray and i am trying to append iteamArray for different category using if condition. in the same way i need to return array count in numberOfRowsInSection but here i am unable to check if condition, it only goes out side return if i give return iteamArray.count then it displays all category values if i give return 0 it display nothing in tableview.
if i click water i need to show only water related iteamsArray in tabelview.. but here if i click any category it shows all category related values in tableview.. please help me in the code.
here is my code:
import UIKit
class PaymentTableViewCell: UITableViewCell{
#IBOutlet weak var pamntTypeLabel: UILabel!
}
class AllMakePaymentViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var categoryName: String?
var iteamsArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
allPaymentService()
}
func allPaymentService(){
let urlStr = "https://dev.com/webservices/api.php?rquest"
let url = URL(string: urlStr)
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
guard let respData = data else {
return
}
guard error == nil else {
print("error")
return
}
do{
let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any]
//print("the all make payment json is \(jsonObj)")
let billerdetailsArray = jsonObj["billerdetails"] as! [[String: Any]]
for billerdetail in billerdetailsArray {
self.categoryName = billerdetail["bcategoryname"] as? String
if self.categoryName == "Water"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
print("water arry \(self.iteamsArray.append(bName ?? ""))")
}
if self.categoryName == "Landline Postpaid"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
print("Landline arry \(self.iteamsArray.append(bName ?? ""))")
}
if self.categoryName == "DTH"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
print("DTH arry \(self.iteamsArray.append(bName ?? ""))")
}
if self.categoryName == "Electricity"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
print("Electricity arry \(self.iteamsArray.append(bName ?? ""))")
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch {
print("catch error")
}
}).resume()
}
}
extension AllMakePaymentViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if categoryName == "Water"{
return iteamsArray.count
}
if categoryName == "Landline Postpaid"{
return iteamsArray.count
}
if categoryName == "DTH"{
return iteamsArray.count
}
if categoryName == "Electricity"{
return iteamsArray.count
}
return iteamsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PaymentTableViewCell
cell.pamntTypeLabel.text = iteamsArray[indexPath.row]
self.tableView.separatorStyle = .none
return cell
}
}
Please help me in above code.
This as you embed all the items to the same array here
if self.categoryName == "Water"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
print("water arry \(self.iteamsArray.append(bName ?? ""))")
}
if self.categoryName == "Landline Postpaid"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
print("Landline arry \(self.iteamsArray.append(bName ?? ""))")
}
if self.categoryName == "DTH"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
print("DTH arry \(self.iteamsArray.append(bName ?? ""))")
}
if self.categoryName == "Electricity"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
print("Electricity arry \(self.iteamsArray.append(bName ?? ""))")
}
Even categoryName is different , instead you better need
var iteamsArray = [Category]()
var filteredArray = [Category]()
guard let res = try? JSONDecoder().decode(Root.self,from:data) else { return }
self.iteamsArray = res.billerdetails
struct Root {
let billerdetails:[Category]
}
struct Category {
let bcategoryname,bname:String
}
Then use filteredArray for the table and when you need to change category do
self.filteredArray = itemsArray.filter{ $0.bcategoryname == "Water" }
self.tableView.reloadData()

Fatal error: Array index out of range when appending array

I currently have an array which I am appending options to. They are they displayed in a table with 3 sections. The first 2 sections have 1 row each, but the third section has a variable number of rows depending on what is appended to the array. I essentially take the third component of my initial array (allAlbums[0].markscheme) and break it down to create multiple new items in the array.
However, when I am trying to simulate this, I get a fatal array on 'cell.textData?.text = section[indexPath.row] as! String' and I'm not sure why?
final class CaseViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var titleText: UILabel!
#IBOutlet var tableView: UITableView!
private var allAlbums = [Case]()
let kHeaderSectionTag: Int = 6900;
var expandedSectionHeaderNumber: Int = -1
var expandedSectionHeader: UITableViewHeaderFooterView!
var sectionItems: Array<Any> = []
var sectionNames: Array<Any> = []
var markschemeRows: Array<Any> = []
override func viewDidLoad() {
super.viewDidLoad()
allAlbums = LibraryAPI.shared.getCases()
// Filter the main array to match a single case
allAlbums = allAlbums.filter { $0.title == title}
// Get data to fill in to table
sectionNames = [ "Trainee Information", "Patient Information", "Examiner Information" ];
sectionItems = [ [allAlbums[0].doctor], [allAlbums[0].patient], [allAlbums[0].markscheme]]
let text = allAlbums[0].markscheme
markschemeRows = text.components(separatedBy: " ")
sectionItems.append(contentsOf: markschemeRows)
// Autoresize rows
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 500
// Remove excess row seperators
tableView.tableFooterView = UIView()
tableView.separatorColor = UIColor.clear
titleText.text = title
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.expandedSectionHeaderNumber == section) {
// Header section
let header = self.sectionNames[section] as! String
// If markscheme, create the markscheme format
if (header == "Examiner Information")
{
print(self.markschemeRows.count)
return self.markschemeRows.count
}
else
{
let arrayOfItems = self.sectionItems[section] as! NSArray
print(arrayOfItems.count)
return arrayOfItems.count
}
} else {
return 0;
}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if (self.sectionNames.count != 0) {
return self.sectionNames[section] as? String
}
return ""
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44.0;
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat{
return 0;
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
//recast your view as a UITableViewHeaderFooterView
let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
header.contentView.backgroundColor = UIColor.darkGray
header.textLabel?.textColor = UIColor.white
if let viewWithTag = self.view.viewWithTag(kHeaderSectionTag + section) {
viewWithTag.removeFromSuperview()
}
let headerFrame = self.view.frame.size
let theImageView = UIImageView(frame: CGRect(x: headerFrame.width - 32, y: 13, width: 18, height: 18));
theImageView.image = UIImage(named: "Chevron-Dn-Wht")
theImageView.tag = kHeaderSectionTag + section
header.addSubview(theImageView)
// make headers touchable
header.tag = section
let headerTapGesture = UITapGestureRecognizer()
headerTapGesture.addTarget(self, action: #selector(CaseViewController.sectionHeaderWasTouched(_:)))
header.addGestureRecognizer(headerTapGesture)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
let section = self.sectionItems[indexPath.section] as! NSArray
cell.textLabel?.textColor = UIColor.black
cell.textData?.text = section[indexPath.row] as! String
return cell
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
// MARK: - Expand / Collapse Methods
#objc func sectionHeaderWasTouched(_ sender: UITapGestureRecognizer) {
let headerView = sender.view as! UITableViewHeaderFooterView
let section = headerView.tag
let eImageView = headerView.viewWithTag(kHeaderSectionTag + section) as? UIImageView
if (self.expandedSectionHeaderNumber == -1) {
self.expandedSectionHeaderNumber = section
tableViewExpandSection(section, imageView: eImageView!)
} else {
if (self.expandedSectionHeaderNumber == section) {
tableViewCollapeSection(section, imageView: eImageView!)
} else {
let cImageView = self.view.viewWithTag(kHeaderSectionTag + self.expandedSectionHeaderNumber) as? UIImageView
tableViewCollapeSection(self.expandedSectionHeaderNumber, imageView: cImageView!)
tableViewExpandSection(section, imageView: eImageView!)
}
}
}
func tableViewCollapeSection(_ section: Int, imageView: UIImageView) {
let sectionData = self.sectionItems[section] as! NSArray
self.expandedSectionHeaderNumber = -1;
if (sectionData.count == 0) {
return;
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (0.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
self.tableView!.beginUpdates()
self.tableView!.deleteRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.tableView!.endUpdates()
}
}
func tableViewExpandSection(_ section: Int, imageView: UIImageView) {
let sectionData = self.sectionItems[section] as! NSArray
if (sectionData.count == 0) {
self.expandedSectionHeaderNumber = -1;
return;
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (180.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
// Header section
let header = self.sectionNames[section] as! String
// If markscheme, create the markscheme format
if (header == "Examiner Information")
{
for i in 0 ..< markschemeRows.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
else
{
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
self.expandedSectionHeaderNumber = section
self.tableView!.beginUpdates()
self.tableView!.insertRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.tableView!.endUpdates()
}
}
}
The error is pretty clear.
In numberOfRows you return markschemeRows.count for section 2 which is the number of separated items in this line
markschemeRows = text.components(separatedBy: " ")
Then you must also get the item from markschemeRows rather than from section[indexPath.row] in cellForRow
var markschemeRows = [String]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
let section = self.sectionItems[indexPath.section] as! NSArray
cell.textLabel?.textColor = UIColor.black
if indexPath.section == 2 {
cell.textData?.text = markschemeRows[indexPath.row]
} else {
cell.textData?.text = section[indexPath.row] as! String
}
return cell
}
Your code is quite cumbersome. For example sectionNames and markschemeRows are clearly [String].Why do you declare the arrays as [Any]? This is Swift. Take care of the types. And don't use Foundation collection types like NSArray in Swift at all. Again take care of the types.

My loop to grab number of results within an array in swift is not working

Greetings dear fans and programmers of the Swift language. I have tried to formulate an algorithm number of times an element shows up within an array with a for loop, but it doesn't seem to be working.
My code is as follows:
else if indexPath.section == 1 {
cell = tableView.dequeueReusableCellWithIdentifier("GreenCell", forIndexPath: indexPath)
for item in theModel.userAnswer {
numOfCoincidences[item] = (numOfCoincidences[item] ?? 0) + 1
}
for (numLangs, value) in numOfCoincidences {
txtSummary = "#languages spoken: \(numLangs)"
txtSummary2 = "# of People: \(value)"
}
cell.textLabel?.text = txtSummary
cell.detailTextLabel?.text = txtSummary2
I am trying to display this information in a table Cell but it is not working. I thought that my algorithm was spot on. Any suggestions?
I'm getting the following output: I have a navigation controller in effect where I input data on one screen and it outputs the data on a table. It's a bit of a survey where I prompt the user to enter their name and the number of languages spoken. I'm using an MVC programming methodology.
so in the model, here is the code:
import Foundation
class Model {
var userName = [String]()
var userAnswer = [String]()
var userInfo = [String]()
var name:String
var answer:String
init(){
self.name = ""
self.answer = ""
}
func addUserInfo(name:String, answer:String) -> Void {
userName.append(name)
userAnswer.append(answer)
}
}
In the input screen, I have 2 text boxes that prompt for username and number of languages spoken. So on the output screen, if 2 people speak 4 languages, the output should reflect that, but it's not. If 1 person speaks 3 languages, it should display that and so on. The output is coming out completely incorrectly. Here is the for the data entry code:
import UIKit
class ViewController: UIViewController {
var model = Model()
#IBOutlet var txtName: UITextField!
#IBOutlet var lblStatus: UILabel!
#IBOutlet var txtAnswer: UITextField!
#IBAction func btnAnswer(sender: UIButton) {
model.answer = txtAnswer.text!
model.name = txtName.text!
if ((txtName.text)! == "" || (txtAnswer.text)! == "") {
lblStatus.text = "Name and answer are both required"
}else if model.userName.contains(model.name) {
lblStatus.text = "Answer already recorded for \(model.name)"
} else {
model.addUserInfo(model.name, answer: model.answer)
lblStatus.text = "Ok, \(model.name) answered \(model.answer)"
}
txtAnswer.text = ""
txtName.text = ""
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toReesultsController" {
let vc = segue.destinationViewController as! TableViewController
vc.theModel = self.model
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
The code for the table to display the data inputted from the data entry screen is presented in a table as shown below:
import UIKit
class TableViewController: UITableViewController {
var theModel = Model()
var numOfCoincidences:[String:Int] = [:]
var txtSummary:String = ""
var txtSummary2:String = ""
var greatest:Int = 0
/* override func viewDidLoad() {
for index in 0..<theModel.userName.count {
}
}*/
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return theModel.userAnswer.count
} else if section == 1 {
return theModel.userAnswer.count
} else if section == 2{
return theModel.userAnswer.count
} else {
return 0
}
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Answer Log"
} else if section == 1 {
return "Summary"
} else if section == 2 {
return "Top Answers"
} else {
return nil
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell! = nil
if indexPath.section == 0 {
cell = tableView.dequeueReusableCellWithIdentifier("BlueCell", forIndexPath: indexPath)
cell.textLabel?.text = "\(theModel.userName[indexPath.row]):\(theModel.userAnswer[indexPath.row])"
} else if indexPath.section == 1 {
cell = tableView.dequeueReusableCellWithIdentifier("GreenCell", forIndexPath: indexPath)
for item in theModel.userAnswer {
numOfCoincidences[item] = (numOfCoincidences[item] ?? 0) + 1
}
for (numLangs, value) in numOfCoincidences {
txtSummary = "#languages spoken: \(numLangs)"
txtSummary2 = "# of People: \(value)"
}
cell.textLabel?.text = txtSummary
cell.detailTextLabel?.text = txtSummary2
} else if indexPath.section == 2 {
cell = tableView.dequeueReusableCellWithIdentifier("OrangeCell", forIndexPath: indexPath)
greatest = 0
for index in 0..<theModel.userAnswer.count {
if Int(theModel.userAnswer[index])! > greatest {
greatest = Int(theModel.userAnswer[index])!
}
}
cell.textLabel?.text = "Answer with most votes is \(greatest) languages spoken."
}
return cell
}
}
Based on what you have shared, and making some assumptions on your input this seems to do what you want.
If each item is a dictionary with the keys shown below. Then you would walk through the array and get the number of languages spoken by the person. I chose to define that as a number(Int) since that is what it really is.
This is almost the same as your original code so I have to conclude that your idea was correct, but your implementation was missing something.
Assuming this is your input:
let a = [["name":"carla", "langs" : 3], ["name":"scott", "langs" : 3], ["name":"brad", "langs" : 1], ["name":"cynthia", "langs":2]]
var numOfCoincidences = [Int: Int]()
for item in a {
let numLangs = item["langs"] as! Int
numOfCoincidences[numLangs] = (numOfCoincidences[numLangs] ?? 0) + 1
}
var txtSummary = ""
var txtSummary2 = ""
for (numLangs, value) in numOfCoincidences {
// You should also note that you are overwriting values here.
txtSummary = "#languages spoken: \(numLangs)"
txtSummary2 = "# of People: \(value)"
print(txtSummary)
print(txtSummary2)
}
numOfCoincidences
Output:
// key := number of languages spoken
// value := number of people who speak that many languages
[2: 1, 3: 2, 1: 1]
You do have a problem in your cellForRowAtIndexPath.
After you loop through all the data, you do this:
cell.textLabel?.text = txtSummary
cell.detailTextLabel?.text = txtSummary2
Therefore, every cell is going to have the last values from the loop.

Array index out of range. Swift. Table View

I got a fatal error: Array index out of range. The error comes from let profilePicture = tempProductPictureArray[count] when tempProductPictureArray[count] is nil. I am wondering do I set something wrong on imageArray?
var imageArray = [[PFFile]]()
........
.......
.......
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell:MarketTableViewCell = tableView.dequeueReusableCellWithIdentifier("MarketCell") as! MarketTableViewCell
let tempProductPictureArray = imageArray[indexPath.row]
// tempProductPictureArray.count is something like [nil / PFFile(image), nil / PFFile(image) .....]
if tempProductPictureArray.count != 0 {
var hasImage = false
var count = 0
while hasImage == false {
let profilePicture = tempProductPictureArray[count]
if profilePicture != nil {
profilePicture!.getDataInBackgroundWithBlock { data, error in
if error != nil {
self.appDelegate.displayMyAlertMessage((error?.localizedDescription)!, userVI: self)
} else {
cell.productImage.image = UIImage(data: data!)
}
}
hasImage = true
} else if count == tempProductPictureArray.count {
cell.productImage.image = UIImage(named: "Profile Picture")
} else {
count += 1
}
}
} else {
cell.productImage.image = UIImage(named: "Profile Picture")
}
data source
func refreshResults(){
...
...
...
sameObjectInQuery.findObjectsInBackgroundWithBlock{ (sameObjects: [PFObject]?, error: NSError?) -> Void in
for var i = 0; i <= tempUniqueTitle.count - 1; i++ {
tempProductImage = [PFFile]()
for sameobject in sameObjects! {
if sameobject.objectForKey("detailsImage") != nil {
tempProductImage.append(sameobject.objectForKey("detailsImage") as? PFFile)
} else {
tempProductImage.append(nil)
}
imageArray.append(tempProductImage)
}
....
Trace through your code, assuming that tempProductPictureArray contains one item. tempProductPictureArray.count will be 1 and that item is at offset 0. Presumably, it's a nil optional and you want to skip over it.
Since count is not equal to tempProductPictureArray.count, you add one to count and try to fetch something from the array at that location (offset 1). However, we've said the only element in the array is at offset 0, so...crash.
You need to make sure that count is always less than tempProductPictureArray.count.

Resources