jamonholmgren / ProMotion

ProMotion is a RubyMotion gem that makes iPhone development less like Objective-C and more like Ruby.
MIT License
1.26k stars 147 forks source link

Trying to use PM::Table::Searchable with NSFetchResultsController and Core Data #506

Closed matthewsinclair closed 9 years ago

matthewsinclair commented 10 years ago

I've finally gotten around to attempt to use some of the PM goodness with CoreData, CDQ and NSFetchResultsControllers, which I have used extensively throughout my app.

To warm up to the main game, I'm trying to get the PM::Table::Searchable module to work, but I'm having some very odd screen refresh problems. No matter what I do, when I tap into the search box, it "moves" about 44 pixels up the page, and ends up going underneath the nav bar.

The search bar renders perfectly on presentation, it's just when I tap in it to type something in that it flies up the page.

I have looked everywhere for what might be causing, and there's a few StackOverflow posts that suggest overriding setVisible, but that is not working in my case.

Here's my hacked version of PM::Table::Searchable:

module Searchable

  def table_view
    self.tableView
  end

  def make_searchable(params={})
    params = set_searchable_param_defaults(params)

    @search_bar = create_search_bar(params)

    if params[:search_bar] && params[:search_bar][:placeholder]
      @search_bar.placeholder = params[:search_bar][:placeholder]
    end

    @table_search_display_controller = TCSearchDisplayController.alloc.initWithSearchBar(@search_bar, contentsController: params[:content_controller])
    @table_search_display_controller.delegate = params[:delegate]
    @table_search_display_controller.searchResultsDataSource = params[:data_source]
    @table_search_display_controller.searchResultsDelegate = params[:search_results_delegate]

    self.table_view.tableHeaderView = @search_bar
  end
  alias :makeSearchable :make_searchable

  def set_searchable_param_defaults(params)
    params[:content_controller] ||= params[:contentController]
    params[:data_source] ||= params[:searchResultsDataSource]
    params[:search_results_delegate] ||= params[:searchResultsDelegate]

    params[:frame] ||= CGRectMake(0, 0, 320, 44) # TODO: Don't hardcode this...
    params[:content_controller] ||= self
    params[:delegate] ||= self
    params[:data_source] ||= self
    params[:search_results_delegate] ||= self
    params
  end

  def create_search_bar(params)
    search_bar = UISearchBar.alloc.initWithFrame(params[:frame])
    search_bar.autoresizingMask = UIViewAutoresizingFlexibleWidth
    search_bar
  end

  def search_field=(sf)
    @search_field = sf
  end
  def search_field
    @search_field
  end
  def search_text=(st)
    @search_text = st
  end
  def search_text
    @search_text
  end

  def search_predicate
    if search_field && search_text
      args             = [search_text]
      search_predicate = NSPredicate.predicateWithFormat(
        "#{search_field} CONTAINS[cd] %@",
        argumentArray: args
      )
    else
      search_predicate = nil
    end
  end

  # UISearchDisplayController

  def searchDisplayController(controller, shouldReloadTableForSearchString: search_text)
    T::Log.debug "#{self.class}: searchable: #{search_text}"
    self.search_text = search_text
    true
  end

  def searchDisplayControllerWillBeginSearch(controller)
    self.table_view.setScrollEnabled false
  end

  def searchDisplayControllerWillEndSearch(controller)
    self.table_view.setScrollEnabled true
    self.search_text = nil
    self.table_view.reloadData
  end

end # module Searchable

What I want to do is get it all working first, then I will try to integrate it back into PM when I migrate to PM2.0. For the moment, I'm just calling make_searchable when the view appears.

This class TCSearchDisplayController is just an empty subclass UISearchDisplayController that I was experimenting with. It is empty at the moment.

For the record, what I am trying to head towards is to use a NSCompoundPredicate to perform the search. I'm already using a predicate to filter the CDQ entities, and what I want to do is to add a search_predicate when the user types something in the search box. From what I know, that should work. The problem is, at the moment, I can't get the search box to display properly so that I can type in it.

Curiously, hacking the search box's frame works momentarily, but then it just flies back up the page again before it settles down.

Any ideas would be most helpful.

PS: Please ignore the crappy state that this is in, I'm just trying to get it working and then I will clean it up for a possible PR.

jamonholmgren commented 10 years ago

Hi Matt,

I'm pretty unavailable this weekend, but hopefully will get some time to devote to it next week. Keep us updated as you bang your head against this. :-)

matthewsinclair commented 10 years ago

No probs. I've parked it for now. I'll get back to it later in the week. Thanks.

matthewsinclair commented 10 years ago

@jamonholmgren I wonder if this might be an issue with MotionKit? I'm using MK to layout an outer view, which has the table view controller as an inner view. Could that affect the way that the search bar is displayed? Might @colinta have some tips?

colinta commented 10 years ago

Hmm, wow that's interesting... well MotionKit isn't going to do anything odd to your views, but it is possible that the hierarchy you've got there is "unexpected" by Apple.

If you can whip up a sample project I'll try and take a look - it might be Monday or Tuesday before I have a chance, though.

matthewsinclair commented 10 years ago

@colinta Ok, I'll see what I can do. It might be later this week before I can get back to this.

markrickert commented 9 years ago

Closing. searchable is close to being fully functional in the new redpotion DataTableScreen

jamonholmgren commented 9 years ago

:+1: Can't wait!