New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not storing references to delegates #1

Closed
hboon opened this Issue Feb 16, 2014 · 4 comments

Comments

Projects
None yet
2 participants
@hboon

hboon commented Feb 16, 2014

Thanks for the great initiative and write up, Jack!

I'm not sure separating delegates out as separate classes is a good way to go since it will undoubtedly require access to several (sub)views and data which are typically accessible from the controller already. I'd normally just use #pragma marks to break them up in ObjC. I'm afraid I'm not proficient enough in Ruby to recommend a better way.

That aside, here's a thing that might be thorny:

Since references to delegates in Cocoa (Touch) classes are often weak references and ditto in RubyMotion, a line like this will often not work:

self.view.delegate = OrganizedViewDelegate.new
@FluffyJack

This comment has been minimized.

Show comment
Hide comment
@FluffyJack

FluffyJack Feb 16, 2014

Collaborator

Of course! I didn't even think about this when I was coming up with the structure... Thank you so much for pointing that out.

As views pass themselves to their delegates most of the time, I don't see too many situations where using an object that isn't the controller should be a problem (though testing this in the wild might just make that problem emerge). What are some scenarios you're concerned about?

I can think of two options at the moment (I really want to make controllers cleaner and smaller), the first being the way I have been doing it up until now, by using a module and including it in the controller, or doing something like

def init
  super
  self.view = ViewWithADelegate.new
  self.view.delegate = self.view_delegate
  self
end

def view_delegate
  @view_delegate ||= TheDelegate.new
end

Any thoughts?

Collaborator

FluffyJack commented Feb 16, 2014

Of course! I didn't even think about this when I was coming up with the structure... Thank you so much for pointing that out.

As views pass themselves to their delegates most of the time, I don't see too many situations where using an object that isn't the controller should be a problem (though testing this in the wild might just make that problem emerge). What are some scenarios you're concerned about?

I can think of two options at the moment (I really want to make controllers cleaner and smaller), the first being the way I have been doing it up until now, by using a module and including it in the controller, or doing something like

def init
  super
  self.view = ViewWithADelegate.new
  self.view.delegate = self.view_delegate
  self
end

def view_delegate
  @view_delegate ||= TheDelegate.new
end

Any thoughts?

@FluffyJack FluffyJack reopened this Feb 16, 2014

@FluffyJack

This comment has been minimized.

Show comment
Hide comment
@FluffyJack

FluffyJack Feb 16, 2014

Collaborator

Actually going to leave this open for further discussion.

Collaborator

FluffyJack commented Feb 16, 2014

Actually going to leave this open for further discussion.

@FluffyJack FluffyJack added bug and removed bug labels Feb 16, 2014

@FluffyJack FluffyJack added this to the v1.0 milestone Feb 16, 2014

@FluffyJack FluffyJack added the bug label Feb 16, 2014

@hboon

This comment has been minimized.

Show comment
Hide comment
@hboon

hboon Feb 19, 2014

A barebones example is a view controller containing a table view. Following the guideline, the table view's dataSource and delegate will be a separate (or quite unlikely, 2 separate) class. The view controller will need to pass the model to the dataSource/delegate(s). If you tap on a cell and the controller needs to do something, the controller itself has to be passed to the table view's delegate.

eg.:

class ViewController
  def some_setup_within_controller
    tv = UITableView.alloc.initWithFrame(bounds)
    tv.delegate = TableViewDelegate.new
    tv.delegate.controller = self
    tv.delegate.model = model
    tv.dataSource = TableViewDataSource.new #might be the same as delegate?
    tv.dataSource.model = model
    #tv.dataSource.controller = self #maybe?
  end
end

class TableViewDelegate
  def tableView(tv, didSelectRowAtIndexPath:indexPath)
    #ask controller to do something with indexPath
    #does TableViewDelegate know about controller or is it another delegate/"interface"?
  end
end

This gets unwieldy quickly once this particular screen (and hence the controller) becomes more complicated, especially with a custom-built view and subviews.

IMHO, the controller is really a good place to coordinate this most of the time and while it tends to grow into a fatter class, breaking it up into delegates might not be good. Since delegates tend to work with each other or have call common code. What can be separated out from the view controller is the view hierarchy. I wrote about this (but for ObjC) sometime ago. On the other hand, this might just be a consequence of the nature of apps I build. They tend to have custom screens, so maybe I'm in the minority :)

I really like how Rubyists are more aggressive with separating concepts though, so hopefully there is a more elegant way of doing this.

hboon commented Feb 19, 2014

A barebones example is a view controller containing a table view. Following the guideline, the table view's dataSource and delegate will be a separate (or quite unlikely, 2 separate) class. The view controller will need to pass the model to the dataSource/delegate(s). If you tap on a cell and the controller needs to do something, the controller itself has to be passed to the table view's delegate.

eg.:

class ViewController
  def some_setup_within_controller
    tv = UITableView.alloc.initWithFrame(bounds)
    tv.delegate = TableViewDelegate.new
    tv.delegate.controller = self
    tv.delegate.model = model
    tv.dataSource = TableViewDataSource.new #might be the same as delegate?
    tv.dataSource.model = model
    #tv.dataSource.controller = self #maybe?
  end
end

class TableViewDelegate
  def tableView(tv, didSelectRowAtIndexPath:indexPath)
    #ask controller to do something with indexPath
    #does TableViewDelegate know about controller or is it another delegate/"interface"?
  end
end

This gets unwieldy quickly once this particular screen (and hence the controller) becomes more complicated, especially with a custom-built view and subviews.

IMHO, the controller is really a good place to coordinate this most of the time and while it tends to grow into a fatter class, breaking it up into delegates might not be good. Since delegates tend to work with each other or have call common code. What can be separated out from the view controller is the view hierarchy. I wrote about this (but for ObjC) sometime ago. On the other hand, this might just be a consequence of the nature of apps I build. They tend to have custom screens, so maybe I'm in the minority :)

I really like how Rubyists are more aggressive with separating concepts though, so hopefully there is a more elegant way of doing this.

@FluffyJack

This comment has been minimized.

Show comment
Hide comment
@FluffyJack

FluffyJack Mar 5, 2014

Collaborator

You're right, while testing out the simple examples, it didn't show the reality of actually having to use the controller in the delegate methods. Back to the drawing board.

Collaborator

FluffyJack commented Mar 5, 2014

You're right, while testing out the simple examples, it didn't show the reality of actually having to use the controller in the delegate methods. Back to the drawing board.

@FluffyJack FluffyJack closed this Aug 7, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment