samedi 16 juin 2018

Data passing between Main and Delegate Object without introducing tight coupling?

I am working with delegate, datasource pattern to achieve lean View Controller in iOS, I did separated DataSource and Delegate into separate objects.

This code can be executed in playground

// 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)
    }
}

My question is

How to set the title property of Reminders class from RemindersCalenderDelegate's willDisplay method without creating high coupling in both objects.

This solution is not accepted

// In RemindersCalenderDelegate 
var parentController: Reminders?

func calendar(_ calendar: Calendar, willDisplay year: Int) {
    parentController?.title = "Year: \(year)"
}

Example is taken from: Paul Hudson. “Swift Design Patterns.” Book.

Aucun commentaire:

Enregistrer un commentaire