我可以使用一些建筑建议。我现在遇到了几次以下问题而且我从来没有找到一种真正优雅的方法来解决它。
问题,尽可能在最高级别描述:我有一个父类,希望充当多个孩子的代理(都使用相同的协议),但是孩子们呼叫父母的方法,父母不再知道哪个孩子正在进行呼叫。
我想使用松散耦合(委托/协议或通知)而不是直接调用。我不需要多个处理程序,因此通知看起来可能有点过分。
为了说明问题,让我尝试一个超简化的例子:
我从父视图控制器(和相应的视图)开始。我创建了三个子视图,并将它们中的每一个插入到父视图中。我想在用户触摸其中一个孩子时通知父视图控制器。有几个选项可以通知父母:
定义协议。父实现协议并将其自身设置为每个子代的委托。当用户触摸子视图时,其视图控制器会调用其委托(父级)。在这种情况下,通知父母一个视图被触摸,但它不知道哪一个。不够好。
与#1相同,但定义协议中的方法也传递某种标识符。当孩子告诉其代表它被触摸时,它也会传递指向自身的指针。这样,父母就知道确切地触摸了哪个视图。对象传递自身的引用似乎很奇怪。
使用NSNotifications。父级为三个子节点中的每一个定义一个单独的方法,然后为这三个子节点中的每一个订阅“viewWasTouched”通知作为通知发送方。孩子们不需要将自己附加到用户词典,但他们确实需要发送带有指针的通知作为范围。
与#4相同,但不是使用单独的方法,父母可以使用带有切换案例或其他分支的方法以及通知的发件人来确定要采用的路径。
创建多个中间人类,充当子视图的委托,然后使用指向子项的指针或其他一些区分因子调用父项上的方法。这种方法似乎不具备可扩展性。
这些方法中的任何一种都被认为是最佳做法吗?我不能肯定地说,但感觉我错过了一些更明显/更优雅的东西。
答案 0 :(得分:5)
您的#2是代表的标准Cocoa模式。委托协议的每条消息都将对象作为第一个参数。例如,在UITableViewDelegate
中,您可以找到以下方法:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
当表视图将此消息发送给其委托时,它将自身(表视图)作为第一个参数发送。如果委托对象是多个表视图的委托,它可以使用第一个参数来确定哪个表视图发送了消息。
当没有其他参数时,该消息仍将对象作为参数,如此UITableViewDataSource
方法:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
你会在Cocoa Touch框架中找到这种模式; UIPickerViewDelegate
,UIImagePickerControllerDelegate
和UINavigationControllerDelegate
只是几个例子。
除非你有令人信服的理由,否则你应该遵循标准模式。遵循惯例将使其他人(以及将来的您)更容易理解您的代码。