user3746428
user3746428

Reputation: 11175

UIScrollView in UITableViewCell in Swift

I am trying to add a UIScrollView() into one of my table's cells. I am having difficulties figuring out in what methods to put the code for the scroll view.

I have a scroll view elsewhere in my app, and this is the code I used transferred across to my UITableView() view as I guessed it should be:

var page = Int()
var pageViews: [UIImageView?] = []
var sixPlusImages = [
    UIImage(named: "Glance 5.5"),
    UIImage(named: "Currencies 5.5"),
    UIImage(named: "Swipe 5.5"),
    UIImage(named: "Format 5.5"),
    UIImage(named: "Search 5.5")
]

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell:AppImagesTableViewCell = self.appTableView.dequeueReusableCellWithIdentifier("appImages", forIndexPath: indexPath) as! AppImagesTableViewCell

    return cell
}

func loadPage(page: Int) {
    let cell = appTableView.cellForRowAtIndexPath(NSIndexPath(index: 0))

    if page < 0 || page >= pageViews.count {
        return
    }

    if let pageView = pageViews[page] {
        return
    } else {
        var imageFrame = CGRect(x: (cell.scrollView.bounds.width * CGFloat(page)) + 5, y: 0, width: (cell.scrollView.bounds.width) - 10, height: 40)

        let imageView = UIImageView()
        imageView.contentMode = .ScaleAspectFit
        imageView.frame = imageFrame
        imageView.image = sixPlusImages[page]
        cell.scrollView.addSubview(imageView)
    }

    pageViews[page] = imageView
}

func purgePage(page: Int) {
    if page < 0 || page >= sixPlusImages.count {
        return
    }

    if let pageView = pageViews[page] {
        pageView.removeFromSuperview()
        pageViews[page] = nil
    }
}

func loadVisiblePages() {
    let pageWidth = cell.scrollView.frame.size.width
    page = Int(floor((cell.scrollView.contentOffset.x * 2.0 + pageWidth) / (pageWidth * 2.0)))

    pageControl.currentPage = page

    let firstPage = page - 1
    let lastPage = page + 1

    for var index = 0; index < firstPage; ++index {
        purgePage(index)
    }

    for index in firstPage...lastPage {
        loadPage(index)
    }

    for var index = lastPage+1; index < sixPlusImages.count; ++index {
        purgePage(index)
    }
}

func scrollViewDidScroll(scrollView: UIScrollView) {
    loadVisiblePages()
}

Obviously, there are quite a few issues with it. I don't seem to be able to access the scrollView that I have as an outlet in the cell class, which is causing some issues.

Can anyone give me some guidance? There aren't any Swift examples online that I could see.

Thanks.

Upvotes: 1

Views: 8727

Answers (1)

Victor Sigler
Victor Sigler

Reputation: 23449

I notice that you are using part of the code proposed in the tutorials in UIScrollView Tutorial: Getting Started to make a slide show using an UIScrollView.

You can use an UIScrollView inside you custom UITableViewCell without any problem, first of all you have to declare your @IBOutlet inside the CustomTableViewCell.

The class CustomTableViewCell must be implement the protocol UIScrollViewDelegate to be notified it about changes in the UIScrollView, you must implement the functions to handle the UIScrollView inside it. Let's take a look in the following example:

CustomTableViewCell to handle the UIScrollView

class CustomTableViewCell: UITableViewCell, UIScrollViewDelegate {


   @IBOutlet weak var scrollView: UIScrollView!

   var pageImages: [UIImage] = []
   var pageViews: [UIImageView?] = []


   override func awakeFromNib() {
      super.awakeFromNib()        

      // 1
      pageImages = [UIImage(named: "photo1.jpg")!,
         UIImage(named: "photo2.jpg")!,
         UIImage(named: "photo3.jpg")!]            

      let pageCount = pageImages.count       

      // 3
      for _ in 0..<pageCount {
          pageViews.append(nil)
      }

      // 4
      let pagesScrollViewSize = scrollView.frame.size
      scrollView.contentSize = CGSize(width: pagesScrollViewSize.width * CGFloat(pageImages.count),
        height: pagesScrollViewSize.height)

      // 5
      loadVisiblePages()        
  }

  func loadPage(page: Int) {
       if page < 0 || page >= pageImages.count {
          // If it's outside the range of what you have to display, then do nothing
          return
       }

       // 1
       if let pageView = pageViews[page] {
          // Do nothing. The view is already loaded.
       } else {
          // 2
          var frame = scrollView.bounds
          frame.origin.x = frame.size.width * CGFloat(page)
          frame.origin.y = 0.0

          // 3
          let newPageView = UIImageView(image: pageImages[page])
          newPageView.contentMode = .ScaleAspectFit
          newPageView.frame = frame
          scrollView.addSubview(newPageView)

          // 4
          pageViews[page] = newPageView
       }
   }

   func loadVisiblePages() {
      // First, determine which page is currently visible
      let pageWidth = scrollView.frame.size.width
      let page = Int(floor((scrollView.contentOffset.x * 2.0 + pageWidth) / (pageWidth * 2.0)))

      // Work out which pages you want to load
      let firstPage = page - 1
      let lastPage = page + 1

      // Purge anything before the first page
      for var index = 0; index < firstPage; ++index {
         purgePage(index)
      }

      // Load pages in our range
      for index in firstPage...lastPage {
         loadPage(index)
      }

      // Purge anything after the last page
      for var index = lastPage+1; index < pageImages.count; ++index {
         purgePage(index)
      }
   }

   func scrollViewDidScroll(scrollView: UIScrollView) {
      // Load the pages that are now on screen
      loadVisiblePages()
   }

   func purgePage(page: Int) {
       if page < 0 || page >= pageImages.count {
          // If it's outside the range of what you have to display, then do nothing
         return
       }

       // Remove a page from the scroll view and reset the container array
       if let pageView = pageViews[page] {
          pageView.removeFromSuperview()
          pageViews[page] = nil
       }
   }

   override func setSelected(selected: Bool, animated: Bool) {
      super.setSelected(selected, animated: animated)

      // Configure the view for the selected state
   }
}

Then in your cellForRowAtIndexPath in your UITableViewController or ViewController the only thing you need is the following code:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomTableViewCell        

    return cell
}

The above code it's only for example, you must consider the constraints for the UIScrollView, enable the Paging Enabled, etc.

I hope this help you.

Upvotes: 2

Related Questions