I'm trying to find tutorials or examples on how to load a tableView or collectionView for continuous scrolling.
For example, I have a database of over 1000 entries but I only want to fetch a 100 at a time. Then when the scroll reaches the bottom it automatically loads the next 100, and so on...
Does anyone know of any tutorials or examples?
I'm coding using swift 2 but any objective-C examples would be fine as I can usually figure out the translation.
I have created a test app to try it out. It fetches 20 records starting from zero.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var personTable: UITableView!
var people = []
var startIndex:Int = 0;
override func viewDidLoad() {
super.viewDidLoad()
self.personTable.delegate = self
self.personTable.dataSource = self
fetchData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.people.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("personCell") as! TableViewCell
cell.usernameLabel.text = people[indexPath.row]["username"] as? String
return cell
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == people.count - 1{
self.startIndex += 20
fetchData()
}
}
func fetchData(){
let post = PostService()
let data = ["startIndex":String(self.startIndex),"limit":"20"]
let url = "http://**********/index.php?action=fetchPersonList"
post.post(data, url: url) { (succeeded, msg) -> () in
if succeeded{
if msg as! String != "<null>"{
self.people = msg as! NSArray
self.personTable.reloadData()
}
}
}
}
}
it works when the last cell is reached and reloads the data but doesn't stop until all the rows have been downloaded which is when it throws an error as there is no more data.
I'm not sure where to go from here.
I've looked for the last couple of hours online to try and find examples but either i'm not using the right search terms or there aren't that many out there.
After several hours of experimenting with this (that I was hoping to avoid by finding a tutorial which wasn't to be.) I eventually found a method that works.
This is the code that works for me.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var personTable: UITableView!
var people = [NSDictionary]()
var page = 0
var holdPage = false;
override func viewDidLoad() {
super.viewDidLoad()
self.personTable.delegate = self
self.personTable.dataSource = self
fetchData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.people.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("personCell") as! TableViewCell
cell.usernameLabel.text = people[indexPath.row]["username"] as? String
return cell
}
func scrollViewDidScroll(scrollView: UIScrollView) {
let actualPosition:CGFloat = scrollView.contentOffset.y;
let contentHeight:CGFloat = scrollView.contentSize.height
let viewHeight:CGFloat = scrollView.frame.height
if (actualPosition + viewHeight >= contentHeight && self.holdPage == false && self.page < 3) {
self.holdPage = true //this is used to stop this if statement from running more than once.
self.page++
self.fetchData()
}
}
func fetchData(){
let post = PostService()
let startIndex = self.page * 20
let data = ["startIndex":String(startIndex),"limit":"20"]
let url = "http://*********/index.php?action=fetchPersonList"
post.post(data, url: url) { (succeeded, msg) -> () in
if succeeded{
if let data = msg as? [NSDictionary]{
self.people = self.people + data
self.holdPage = false
self.personTable.reloadData()
}
}
}
}
}
I had to use the holdPage variable as I found that when the scroll reached the end it loaded several pages in one go.
The only drawback to this method is that it keeps adding rows to the people array as you scroll down making it bigger each time. I was initially looking to remove the rows that were no longer in view but that was proving to be very complex.
Unless someone can show me a good example?
Related
So I recently asked a question regarding firebase - but have refactored my code quite a bit as I wanted all of my firebase methods to be done in the same place. I am having the following issue after the refactor...
Data from my firebase database is not populating my tableview. I'm not too sure why this would be, as it was working fine before I moved the method to a separate file from my table view(for cleaner code). All I did was move the method that populates the array to a separate file, return an array and then reload the tableview after calling the method. Below is the code in question:
In my FireBaseMethods class
//-------------- POPULATE TABLE ARRAY -----------------//
public func populateConsumableTableArray() -> [Consumable]{
var tableArray = [Consumable]()
//let the object populate itself.
ref.child("Consumables").observe(.childAdded, with: { snapshot in
let dataChange = snapshot.value as? [String:AnyObject]
let aRequest = Consumable(aDict: dataChange!)
tableArray.append(aRequest)
})
return tableArray
}
In my ListOfConsumablesViewController table view class
class ListOfConsumablesViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
private var methods:MethodsForController = MethodsForController()
private var fireBaseMethods:FireBaseMethods = FireBaseMethods()
private var consumableArray = [Consumable]()
let picker = UIImagePickerController()
#IBOutlet weak var consumableTable: UITableView!
//-------------------- VIEW DID LOAD -----------------------//
override func viewDidLoad() {
super.viewDidLoad()
//Trying to populate the table view here...
consumableArray = fireBaseMethods.populateConsumableTableArray()
consumableTable.reloadData()
self.consumableTable.dataSource = self
self.consumableTable.delegate = self
}
...
//---------------------- FUNCTIONS FOR TABLE VIEW CELLS & TABLE ----------------------//
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(consumableArray.count)
return consumableArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "consumableCell", for: indexPath) as! ConsumablesCell
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.backgroundColor = UIColor.white
cell.adapterType.text = consumableArray[indexPath.row].getType()
cell.count.text = String(consumableArray[indexPath.row].getCount())
if Int(consumableArray[indexPath.row].getCount()) ?? 0 <= 0{
cell.count.textColor = UIColor.red
}else{
cell.count.textColor = UIColor.black
}
cell.sku.text = consumableArray[indexPath.row].getSku()
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 90
}
}
As shown below, nothing populates in the table view... I'm assuming it's something to do with the method being in a separate file, but I'm not really sure why that would be?
Simple implementation of a completion handler
//-------------- POPULATE TABLE ARRAY -----------------//
public func populateConsumableTableArray(completion: #escaping (Consumable) -> Void) {
//let the object populate itself.
ref.child("Consumables").observe(.childAdded, with: { snapshot in
guard let dataChange = snapshot.value as? [String:AnyObject] else { return }
let aRequest = Consumable(aDict: dataChange)
completion(aRequest)
})
}
override func viewDidLoad() {
super.viewDidLoad()
self.consumableTable.dataSource = self
self.consumableTable.delegate = self
//Trying to populate the table view here...
fireBaseMethods.populateConsumableTableArray { [unowned self] consumable in
self.tableArray.append(consumable)
DispatchQueue.main.async {
self.consumableTable.reloadData()
}
}
}
In my current project I'm trying to fetch news from a REST-Endpoint and I wanna refresh the UITableView once the network request is finished. So I call reloadData() but unfortunately cellForRowAtIndexPath isn't called however numberOfRowsInSection gets called and returns the correct number of items.
Following my code stripped down to the relevant parts:
class NewsTableViewController: UIViewController {
private var newsItems: Array<NewsItem>!
private var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
newsItems = []
addDummyItem()
prepareTableView()
getNews()
}
func addDummyItem(){
let newsItem = NewsItem()
newsItem.dateString = "12th May"
newsItem.title = "Lorem ipsum"
newsItem.imgUrl = "URL"
newsItem.url = "URL"
newsItem.message = "Lorem ipsum dolor sit amet"
self.newsItems.append(newsItem)
}
func getNews(){
let url = NSURL(string: "http://someurl.com/news")
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) { data, response, error in
guard data != nil && error == nil else {
print(error)
return
}
guard let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200 else {
print("status code not 200; \(response)")
return
}
let json = String(data:data!, encoding: NSISOLatin1StringEncoding)
let arr: AnyObject? = json?.parseJSONString
for item in arr as! Array<AnyObject>{
let newsItem = NewsItem()
newsItem.dateString = (item["dateString"] as AnyObject? as? String) ?? ""
newsItem.title = (item["title"] as AnyObject? as? String) ?? ""
newsItem.imgUrl = (item["imgUrl"] as AnyObject? as? String) ?? ""
newsItem.url = (item["url"] as AnyObject? as? String) ?? ""
newsItem.message = (item["message"] as AnyObject? as? String) ?? ""
self.newsItems.append(newsItem)
}
print("Network request finished - call reloadData()")
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
task.resume()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
automaticallyAdjustsScrollViewInsets = false
}
private func prepareTableView() {
tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
tableView.separatorColor = UIColor.clearColor()
}
}
extension NewsTableViewController : UITableViewDataSource{
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("Item count: ", newsItems.count)
return newsItems.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("cellForRowAtIndexPath called with indexPathRow: ", indexPath.row)
let cell = tableView.dequeueReusableCellWithIdentifier("ImageCardViewCell") as! NewsImageCardViewCell
let item: NewsItem = newsItems[indexPath.row]
getImageCardView(item.url, btnDate: item.dateString, textTitle: item.title, textDetail: item.message, imageCardView: cell.imageCardView, imageName: "news_1", indexPath: indexPath)
return cell
}
}
extension NewsTableViewController : UITableViewDelegate{
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
As you can see: The UITableView is correctly setup by setting the dataSource and delegate to my class. The reloadData() method is called on the main thread. Following the log-output:
Item count: 1
cellForRowAtIndexPath called with indexPathRow: 0
Network request finished - call reloadData()
Item count: 72
Note: At first there's one dummy item my array just to show you that cellForRowAtIndexPath is indeed called but only one time. After triggering reloadData() on numberOfRowsInSection is called but not the cellForRowAtIndexPath method.
I know that there're a lot of similar issues like this and I've checked them all for possible solutions but none were working. I appreciate any help.
Edit
Please note that the dummy view which is added before the network request is visible. So the UITableViews' height is not 0.
Edit #2
Thanks to everyone for your answers. I've found the issue. I've instantiated the ViewController via the Storyboard but I missed to set an IBOutlet. Due that the bounds of my UITableView were 0,0,0,0.
That because your table view did not add to your window, If the table view is not visible, the UIKit will not deal with UI related methods. It's kind of Apple's lazy load.
Change your prepareTableView function as below:
private func prepareTableView() {
tableView = UITableView(frame: self.view.bounds, style: .Plain)
tableView.dataSource = self
tableView.delegate = self
tableView.separatorColor = UIColor.clearColor()
self.view.addSubview(tableView)
}
Check Following :
1 numberOfRowsInSection see the Number of return value
2 if step1 is called and return right value still not calling cellForRowAtIndexPath that means your table view height is less then height of cell or table view height is 0 , print tableview bounds and also check superview of tableview has clips to bounds to TRUE
tableview datasource method cellForRowAtIndexPath is depending on numberOfRowsInSection . So it may be possiblity that you having zero item in newsItems
I have been trying to create an app that gets a website data through a function ( func obtainData) and display some of the data on a tableView.
I have figured out the part on how to get the data from the website then make it as an array so I can use indexpath.row but I have not able to find out the way to pass on the data I'm getting to display it on a tableView.
Any ideas!
Thanks
Below is the code I wrote.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var recommendation = ""
var recommendationArray = ""
var delExtraTextArray = [String]()
var urlRecommendationArrayStart = [String]()
var urlRecommendationArrayEnd = [String]()
var RecommendationStart = [String]()
var RecommendationEnd = [String]()
// need the var below to make the recommendations as an array to be used in a table view as indexpath.row
var cellNumber = [String]()
var cellTitle = [String]()
var cellDetails = [String]()
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
obtainData()
tableView.delegate = self
tableView.dataSource = self
}
func obtainData () {
var url = NSURL (string: "http://www.choosingwisely.org/societies/american-college-of-obstetricians-and-gynecologists")
if url != nil {
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if error == nil {
// to get all of the url content and covert them into string
var urlContent = NSString(data: data!, encoding: NSUTF8StringEncoding) as NSString!
// to get to a specific contect seperated by a string
self.urlRecommendationArrayStart = (urlContent?.componentsSeparatedByString("<ol class=\"society-ol\">"))!
if self.urlRecommendationArrayStart.count > 0 {
self.urlRecommendationArrayEnd = self.urlRecommendationArrayStart[1].componentsSeparatedByString("</ol>")
// print(self.urlRecommendationArrayEnd)
// to check if there is any extra not needed text at the end of the recommnedations in the source page
self.delExtraTextArray = self.urlRecommendationArrayEnd[0].componentsSeparatedByString("<p><a")
if self.delExtraTextArray.count > 0 {
self.recommendationArray self.delExtraTextArray[0] as! String
self.obtainRecommendationTitle()
} else {
self.recommendationArray = self.urlRecommendationArrayEnd[0] as! String
self.obtainRecommendationTitle()
// print("method 2 worked")
}
} else {
self.textView.text = "Sorry, couldn't get the recommendation at this point. Please make sure to download the updated version of the app"
}
} else {
self.textView.text = "Please check connection then try again"
}
})
task.resume()
} else {
self.textView.text = "Please check connection then try again"
}
}
// to get the title of each recommendation
func obtainRecommendationTitle() -> Array<String> {
for var i = 2; i < urlRecommendationArrayEnd[0].componentsSeparatedByString("<p>").count - delExtraTextArray.count ; i = i + 4 {
self.RecommendationStart = self.delExtraTextArray[0].componentsSeparatedByString("<p>")
self.RecommendationEnd = RecommendationStart[i].componentsSeparatedByString("</p>")
self.recommendationArray = self.RecommendationEnd[0] as! String
self.cellTitle.append(recommendationArray)
}
return cellTitle
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellTitle.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
cell.textLabel?.text = cellTitle [indexPath.row]
return cell
}
You would pass it via the cellForRowAtIndexPath delegate method. This question is too open ended for a firm answer, but following along any half-decent online UITableView tutorial should do the trick.
A quick glance at this one appears to hit the basics: https://www.weheartswift.com/how-to-make-a-simple-table-view-with-ios-8-and-swift/
I think what you need is to configure the contents of the table view cell with the data you want. Based on this assumption, you can use something like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("PUT_YOUR_CELL_IDENTIFIER_HERE") as? UITableViewCell {
let stuff = yourArray[indexPath.row]
stuff.some_property_you_want = the_value_you_want
return cell
} else {
return UITableViewCell()
}
}
If you show some code or explain your problem a little better, you will get a better support from the people here on Stack Overflow.
EDIT (based on your edit):
Are you using a normal cell?
The cell has the text field to put the string you want?
Did you define the cell's identifier, "cell", in the storyboard?
Did you connect the tableView outlet to the tableView itself?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell {
print("ENTERED HERE!")
let myCellText = cellTitle[indexPath.row]
//what is the result of this print?
print("TEXT TO ADD: \(myCellText)")
//(...)
cell.textLabel?.text = myCellText
return cell
} else {
return UITableViewCell()
}
}
What is the result of these prints?
So, I am trying to do something that I think is fairly simple, yet this is causing me no end of pain.
Essentially I have a ViewController, and from here you can open another ViewController which again you can load another ViewController from. In this last ViewController you can select a row which will add some data to NSUserdefaults (Using a class that I built to handle this data)
This all works fine, and the data is added. Now when I go back to my first ViewController whence the journey began, using viewWillAppear I ask it to get the data from NSUserdefaults and then refresh the data in a table that is in this view.
let jsonData = JSON(NSUserDefaults.standardUserDefaults().objectForKey("set")!)
self.tracks = jsonData.arrayObject!
print(self.tracks)
self.tblSongs.reloadData()
Now this never seems to work when there is just 1 row in the array, however if there is more than 1 row, then everything works fine and the table is visible with the required amount of data.
The Print does indeed show the data that is stored, and I can see the single row that is stored but is not showing up in the table.
Has anyone had anything similar or any idea what I can do to solve this?
I have tried using a delegate, NSNotificationCenter, and performing spells but everything returns the same result.
Many thanks in advance for your help
*Disclaimer I am new to native iOS and Swift being a JS Developer and previously using Titanium
EDIT: I have logged numberOfRowsInSection and this returns 1 as expected, but cellForRowAtIndexPath does not get fired
EDIT 2: Here is the cellForRowAtIndexPath code, this isn't fired even though there is 1 item in the array and numberOfRowsInSection says 1. This does work fine if you re-launch the app
EDIT 3: Here is the entire Class
import Foundation
import UIKit
class Main: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var viewNoTracks: UIView!
#IBOutlet weak var viewTracksNoSet: UIView!
#IBOutlet weak var btnPlay: UIButton!
#IBOutlet weak var tblSongs: UITableView!
#IBOutlet weak var lblStatus: UILabel!
#IBOutlet weak var btnSubmitSet: UIButton!
var tracks = []
let setMgr = SetManager()
override func viewDidLoad() {
super.viewDidLoad()
let bgColor: UIColor = UIColor.whiteColor()
self.btnSubmitSet.layer.borderColor = bgColor.CGColor
self.btnSubmitSet.layer.borderWidth = 1
self.tblSongs.delegate = self
self.tblSongs.dataSource = self
if self.setMgr.getCurrentSetCount() > 0 {
self.viewTracksNoSet.hidden = false
self.viewNoTracks.hidden = true
self.updateData()
} else {
self.viewTracksNoSet.hidden = true
self.viewNoTracks.hidden = false
}
self.checkSetStatus()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
dispatch_async(dispatch_get_main_queue()) {
if self.setMgr.getCurrentSetCount() > 0 {
self.viewTracksNoSet.hidden = false
self.viewNoTracks.hidden = true
self.updateData()
} else {
self.viewTracksNoSet.hidden = true
self.viewNoTracks.hidden = false
}
self.checkSetStatus()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func openPlay(sender: AnyObject){
self.performSegueWithIdentifier("segueChoonSelector", sender: nil)
}
#IBAction func unwindToMain(segue: UIStoryboardSegue){
}
#IBAction func submitSet(sender: AnyObject){
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CellMainSong", forIndexPath: indexPath) as! CellMainSong
let row = self.tracks[indexPath.row]
var artist = row["artist"] as! String
artist = artist.stringByReplacingOccurrencesOfString("&", withString: "&", options: NSStringCompareOptions.LiteralSearch, range: nil)
var song = row["song"] as! String
song = song.stringByReplacingOccurrencesOfString("&", withString: "&", options: NSStringCompareOptions.LiteralSearch, range: nil)
var genre = row["genre"] as! String
genre = genre.stringByReplacingOccurrencesOfString("&", withString: "&", options: NSStringCompareOptions.LiteralSearch, range: nil)
print(artist)
cell.lblDetails.text = artist + " - " + song + " - " + genre
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tracks.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 50
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
let row = self.tracks[indexPath.row]
let tid = row["tid"] as! String
self.setMgr.removeFromSet(tid)
self.updateData()
}
}
func UITableView_Auto_Height()
{
if(self.tblSongs.contentSize.height < self.tblSongs.frame.height){
var frame: CGRect = self.tblSongs.frame;
frame.size.height = self.tblSongs.contentSize.height;
self.tblSongs.frame = frame;
}
}
func setSetLabelOrButton(){
if self.setMgr.getCurrentSetCount() < 3 {
let currCountInt: Int = self.setMgr.getCurrentSetCount()
let tracksLeft = 3 - currCountInt
let currentCount = String(tracksLeft)
self.btnSubmitSet.hidden = true
self.lblStatus.hidden = false
if currentCount == "1" {
self.viewTracksNoSet.hidden = false
self.viewNoTracks.hidden = true
self.lblStatus.text = "Hey DJ, you are " + currentCount + " track away from rocking the dancefloor"
} else if currentCount == "3" {
self.viewTracksNoSet.hidden = true
self.viewNoTracks.hidden = false
} else {
self.lblStatus.text = "Hey DJ, you are " + currentCount + " tracks away from rocking the dancefloor"
}
} else if self.setMgr.getCurrentSetCount() == 3 {
self.lblStatus.hidden = true
self.btnSubmitSet.hidden = false
}
}
func updateData(){
let jsonData = JSON(NSUserDefaults.standardUserDefaults().objectForKey("set")!)
self.tracks = jsonData.arrayObject!
print(self.tracks)
self.tblSongs.reloadData()
self.performSelectorOnMainThread(Selector("updateTableData"), withObject: self.tblSongs, waitUntilDone: false)
self.setSetLabelOrButton()
self.UITableView_Auto_Height()
}
func updateTableData(){
self.tblSongs.reloadData()
}
func checkSetStatus(){
let setStatus = SetStatus()
setStatus.getSetStatus { (resp) -> Void in
//print(resp)
}
}
}
Didn't get the reason Bt just log what value does "numberOfSections" in tableview returns. It may not be the reason but just try
I found out the issue. Turns out that self.UITableView_Auto_Height() was being called before the data had been loaded, causing the table to render at 0 height. Although interestingly it still wasn't firing the cellForRowAtIndex, so perhaps an issue with the lifecycle in this case
I am trying to use the MVC model in my app. This is the first time I am using it as I am just learning iOS programming. There are several things you need to know to help me. First: I have a model called Home.swift inside this model I have an array and a function. "Home.swift":
class Home: NSObject {
var content: [String] = [
"Apple",
"Door",
"Evil",
"Error",
]
func homeDisplayContent() -> String {
for var i = 0; i < 12; i++ {
return content[i]
}
}
}
Do I need an init in here, if so how would I implement it? Secondly, I have a View for my tableView. I don't think anything is wrong with my view. But just in case inside here I have my "HomeCell.swift":
var homes: Home! {
didSet{
contentLabel.text = homes.homeContent()
}
}
Lastly I have my view controller, "HomePageViewController.swift":
var homes: [Home]!
#IBOutlet weak var homeTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.homeTableView.delegate = self
self.homeTableView.dataSource = self
homes = [Home()]
self.homeTableView.reloadData()
// Do any additional setup after loading the view.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("homeCell", forIndexPath: indexPath) as? HomeCell
cell!.homes = homes[indexPath.row]
return cell!
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.homes.count
}
What I want to do is be able to grab each index inside my array inside the Home.swift (My model) and present them in their own individual cells. I believe I need to create an array of Home objects but I am not sure how to go about doing this. Sorry for the block of text and for poor formatting (cannot for the life of me fix the first block of code) but I am really lost and have looked around on google and stackoverflow for awhile trying to figure out my problem with no luck. Thanks in advance!
You are hard-coding the values in contents array. So you need to use the values from that array. There is no need to create multiple Home object in this case. You want something like:
Home.swift
class Home : NSObject
{
var content: [String] = [
"Apple",
"Door",
"Evil",
"Error",
]
func homeDisplayContent(atIndex : Int) -> String
{
return content[atIndex]
}
}
HomePageViewController.swift
var home = Home()
#IBOutlet weak var homeTableView: UITableView!
override func viewDidLoad()
{
super.viewDidLoad()
self.homeTableView.delegate = self
self.homeTableView.dataSource = self
self.homeTableView.reloadData()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("homeCell", forIndexPath: indexPath) as! HomeCell
cell.contentLabel.text = home.homeDisplayContent(indexPath.row)
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.home.contents.count
}