Search code examples
rubymotion

how can I add another textlabel and buttons to a cell in a tableView in rubymotion?


I use the following methods to create a cell and populate data in it(adapted from the tweets app example) Now I want to add a new label displaying the selected event date and a button that will perform another action. Here comes the 2 methods:

def self.cellForEvent(event, inTableView:tableView)
    cell = tableView.dequeueReusableCellWithIdentifier(EventCell::CellId) || EventCell.alloc.initWithStyle(UITableViewCellStyleDefault, reuseIdentifier:CellId)
    cell.fillWithEvent(event, inTableView:tableView)
    cell.accessoryType =  UITableViewCellAccessoryDetailDisclosureButton
    cell
end

Populate data into the cell

def fillWithEvent(event, inTableView:tableView)
    self.textLabel.text = event.name
    puts event.image
    unless event.image
      self.imageView.image = nil
      Dispatch::Queue.concurrent.async do
        event_image_data = NSData.alloc.initWithContentsOfURL(NSURL.URLWithString(event.image_url))
        if event_image_data
          event.image = UIImage.alloc.initWithData(event_image_data)
          Dispatch::Queue.main.sync do
            self.imageView.image = event.image
            tableView.delegate.reloadRowForEvent(event)
          end
        end
      end
    else
      self.imageView.image = event.image
    end
  end

Solution

  • railsdog's recommendation is not without merit. You could make a @reference to the cell you want to edit, and make changes to it later. But this is kind of dangerous - lots of pitfalls: What happens it the cell is moved off screen? Reused elsewhere? Tricky.

    Instead, I would recommend adding some of the fillWithEvent:inTableView code into the cellForEvent method, that way you can call tableView.reloadRowsAtIndexPaths:withRowAnimation: and that method will be called. This moves the complications I mentioned above onto the back of the Cocoa framework, and that's a good thing :-)

    The downside is that you'll need to keep the indexPath handy (or calculatable), and always keep in mind that the event associated with the cell is transient, because the cells are reused. Your code above doesn't seem to keep a reference to event, which is a good thing!

    # in fetchImageForEvent:tableView:
    # ...
    event.image = UIImage.alloc.initWithData(event_image_data)
    Dispatch::Queue.main.sync do
      # instead of this:
      # self.imageView.image = event.image
    
      # tell the tableView to reload.  unfortunately, we don't have the index
      # path.  not sure how you're calculating it, but if you've got a list of
      # events, this should be easy.
      # I'm just assuming section 0, row 1 here.
      path = NSIndexPath.indexPathWithIndex(0).indexPathByAddingIndex(1)
      tableView.reloadRowsAtIndexPaths([path], withRowAnimation:UITableViewRowAnimationAutomatic)
    end