我正在使用委托,数据源模式来实现iOS中的精简视图控制器,我将DataSource和Delegate分离为单独的对象。
此代码可以在游乐场中执行
// Calender Delegate
protocol CalenderDelegate: class{
func calender(_ calender: Calender, willDisplay year:Int)
func calender(_ calender: Calender, didSelect date: Date)
func calenderShouldChange(_ calender: Calender) -> Bool
}
// Calender DataSource
protocol CalenderDataSource{
func calender(_ calender: Calender, eventsFor date: Date) -> [String]
func calender(_ calender: Calender, add event: String, to date: Date)
}
// Calander Object
class Calender{
weak var delegate: CalenderDelegate?
var dataSource: CalenderDataSource?
var selectedDate: Date = Date()
var currentYear: Int = 2018
func changeDate(to date: Date){
self.selectedDate = date
delegate?.calender(self, didSelect: date)
if let items = dataSource?.calender(self, eventsFor: date){
print("Events for \(date) are")
items.forEach{print($0)}
}
else{
print("This is a rest day not event hurrrhhhhaaa!")
}
}
func changeYear(to year: Int) {
if delegate?.calenderShouldChange(self) ?? true{
delegate?.calender(self, willDisplay: year)
self.currentYear = year
print(year)
}
}
func add(event: String){
dataSource?.calender(self, add: event, to: selectedDate)
}
}
// Datasource
class RemindersCalenderDataSource: CalenderDataSource{
func calender(_ calender: Calender, eventsFor date: Date) -> [String] {
return ["Event 1","Event 2","Event 3","Event 4","Event 4"]
}
func calender(_ calender: Calender, add event: String, to date: Date) {
print("Events for date are \(event) \(date).")
}
}
protocol ReminderPresenting {
func yearChanged(to year: Int)
}
// Delegate
class RemindersCalenderDelegate: CalenderDelegate{
var parentController: ReminderPresenting?
func calender(_ calender: Calender, willDisplay year: Int) {
self.parentController?.yearChanged(to: year)
// self.title = "Year: \(year)"
}
func calender(_ calender: Calender, didSelect date: Date) {
print("You selected date \(date)")
}
func calenderShouldChange(_ calender: Calender) -> Bool {
return true
}
}
//Gernal Object like ViewController
class Reminders: ReminderPresenting{
var title = "Year: 2200"
var calender = Calender()
init() {
calender.delegate = RemindersCalenderDelegate()
calender.dataSource = RemindersCalenderDataSource()
}
func yearChanged(to year: Int) {
self.title = "Year: \(year)"
print(self.title)
}
}
我的问题是
如何从RemindersCalenderDelegate的willDisplay方法设置Reminders类的title属性,而不在两个对象中创建高耦合。
不接受此解决方案
// In RemindersCalenderDelegate
var parentController: Reminders?
func calendar(_ calendar: Calendar, willDisplay year: Int) {
parentController?.title = "Year: \(year)"
}
示例来自:Paul Hudson。 “Swift设计模式。”书。
答案 0 :(得分:1)
因此,如果您想在没有紧耦合的情况下引入单向通信,您可以使用闭包以通用方式传回信息,并让消费者控制将数据绑定到其本地控件。
通过你所拥有的,我认为这是正确的关系。如果它有助于保持代码整洁,您还可以键入回调类型。
class RemindersCalenderDelegate: CalenderDelegate{
let yearSelectionCallback: (Int) -> ()
init(yearSelectionCallback: (Int) -> ()) {
self.yearSelectionCallback = yearSelectioncallback
}
func calender(_ calender: Calender, willDisplay year: Int) {
yearSelectionCallback(year)
}
func calender(_ calender: Calender, didSelect date: Date) {
print("You selected date \(date)")
}
func calenderShouldChange(_ calender: Calender) -> Bool {
return true
}
}
class Reminders: ReminderPresenting{
var title = "Year: 2200"
var calender = Calender()
init() {
calender.delegate = RemindersCalenderDelegate(yearChangedCallback: {
[weak self]
year in
self?.yearChanged(to: year)
})
calender.dataSource = RemindersCalenderDataSource()
}
func yearChanged(to year: Int) {
self.title = "Year: \(year)"
print(self.title)
}
}
当然,请记住这会让RemindersCalendarDelegate不了解ReminderPresenting,但无法帮助ReminderPresenting实施者了解RemindersCalendarDelegate的实现。
为避免这种情况,也许可以考虑采用工厂模式,他们唯一的工作就是了解这些联轴器!这将允许ReminderPresenting和RemindersCalendar度过生活,无需知道另一个存在。