简体   繁体   中英

iOS TableView with Advertisement elements — IndexPath.row logic

I am looking to add an ad cell at the 0 index as well as at after every three cells thereafter. I was successful to add the first one, but uncertain how to approach this.

Both ads just take a single image.

My current code is as follows:

var adCount = 1
var newsTitleArray : [String] = ["News1"]

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return newsTitleArray.count + adCount
 }
 
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "BannerTableViewCell") as! BannerTableViewCell
        cell.adImageView.image = UIImage(named:"Logo")
        NewsTableView.rowHeight = 50
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "NewsTableViewCell") as! NewsTableViewCell
        cell.newsTitle.text = newsTitleArray[indexPath.row - 1]
        cell.newsSubTitle.text = newsSubTitleArray[indexPath.row - 1]
        cell.newsDate.text = newsDateArray[indexPath.row - 1]
        cell.newsImageView.image = UIImage(named: randomPicArray[indexPath.row - 1])
        cell.selectionStyle = .none
        NewsTableView.rowHeight = 500
        return cell
    }
}

Checking for index to show specific contents is bad practice. Update your data source with types you expect. In this case instead of newsTitleArray use dataSource which contains News & Ads objects.

enum ContentType {
  case news
  case ad
}

struct NewsContent {
 let type: ContentType = .news
 let title: String
 //More if needed 
}

struct AdContent {
 let type: ContentType = .ad
 let title: String
 //More if needed 
}

let dataSource = [AdContent, NewsContent, NewsContent, NewsContent, AdContent, ...]

You can use this framework to create multiple content types. This also simplifies how you are accessing data. Like in numberOfRowsInSection You don't need to do newsContent + ad You can just return dataSource.count . This approach is easy to read & maintain.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataSource.count
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
   let content = dataSource[indexPath.row]
   let height: CGFloat?
   switch content.type {
   case .news:
      height = 500
   case .ad:
      height = 50
   }
   return height ?? 500 // return default
}

Now return/update cell based on content type

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   let content = dataSource[indexPath.row]
   let cell: UITableViewCell?
   switch content.type {
   case .news:
      cell = tableView.dequeueReusableCell(withIdentifier: "NewsTableViewCell") as? NewsTableViewCell
      cell?.newsTitle.text = newsTitleArray[indexPath.row - 1]
      cell?.newsSubTitle.text = newsSubTitleArray[indexPath.row - 1]
      cell?.newsDate.text = newsDateArray[indexPath.row - 1]
      cell?.newsImageView.image = UIImage(named: randomPicArray[indexPath.row - 1])
      cell?.selectionStyle = .none
    case .ad:
      cell = tableView.dequeueReusableCell(withIdentifier: "BannerTableViewCell") as? BannerTableViewCell
      cell?.adImageView.image = UIImage(named:"Logo")
    }

    return cell ?? UITableViewCell()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM