-
Notifications
You must be signed in to change notification settings - Fork 348
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
[WIP] Custom event views support #274
base: master
Are you sure you want to change the base?
Conversation
…) and DefaultEventView (current implementation of EventView)
Hi, thanks a lot for your pull request! Highly appreciate! So, before going further with development, I'd like to clarify a use-case that you'd like to solve. Could you please share design mockups of how the end result should look like? That would make our discussion more concrete and grounded in the reality. As for your pull request, here are few issues that need to be addressed:
From my understanding, you'd like to have a custom EventView with buttons and be able to react to those button events. I suggest modifying the API the following way: DayViewThis method registers the func registerEventViewClass(_ eventViewClass: EventView.Type) // Should be a subclass of EventView dayView.registerEventViewClass(MyCustomEventView.self) DayViewDelegateThis method will be called just after the
In your example, to connect the button with some other target you'll need to implement something similar to this: func dayView(_ dayView: DayView, didUpdateEventView eventView: EventView) {
if let myEventView = eventView as? MyCustomClass {
myEventView.button.addTarget(self, action: #selector(buttonDidPress:), for: .touchUpInside)
}
} What do you think of this approach?It won't work if you need to use 2 or more different kinds of EventView. But if that's the case, I could think of slightly modifying this architecture. The goal is to keep the API clean, simple and extensible. |
Thanks for the quick response. I compared mine and your approach to the implementation of this feature and they are very similar:
However, we see the last point in different ways. Way to provide a custom EventViewI want the I do not fully understand why we need to implement I find that registering views can be useful in views with a large scrolling area. And such a situation may arise if, for example, there is an opportunity to enlarge Now I'm not sure that registering views is the right thing to do. Moreover, we can return different Place to register viewsAnd why should we register views in In addition, we have another problem - we need to give the opportunity to create different event views for the Your API for decoupling modules
Could you tell us more about this API? |
Sorry for brevity of my reply, on mobile.
Also, the change could be put in place without introduction of new protocols, that would keep the library simple. |
And although my approach suggests a new protocol, it removes the task of creating a custom view instance from I will present the implementation of my approach a little later, as soon as I fix the bugs. |
+ It is possible to have several types of EventViews in one timeline
@richardtop Here's a sketch of how I see support for custom views. Key points:
private func generateEventsForDate(_ date: Date) -> [EventDescriptor] {
// ...
let event: EventDescriptor
if (Bool.random()) {
event = Event()
} else {
event = MyEvent()
}
// ...
}
func timelineView(_ timeloneView: TimelineView, viewFor event: EventDescriptor) -> EventView {
if (event is MyEvent) {
return MyEventView()
} else {
return DefaultEventView()
}
}
override open func updateWithDescriptor(event: EventDescriptor) {
super.updateWithDescriptor(event: event)
subviews[2].backgroundColor = event.color // for example
} |
@@ -5,13 +5,13 @@ import UIKit | |||
public protocol EventDescriptor: AnyObject { | |||
var startDate: Date {get set} | |||
var endDate: Date {get set} | |||
var isAllDay: Bool {get} | |||
var text: String {get} | |||
var isAllDay: Bool {get set} // TODO: should we return this to read-only? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, these properties should be read-only, as the CalendarKit doesn't modify them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But in this case, we cannot use EventDescriptor
as a generic type for custom descriptors. I find it quite convenient:
var event: EventDescriptor
if (Bool.random()) {
event = Event()
} else {
event = MyEvent()
}
// imposible with read-only properties
event.text = info.reduce("", {$0 + $1 + "\n"})
event.color = colors[Int(arc4random_uniform(UInt32(colors.count)))]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but that's not a requirement by the library.
You're free to create own, stricter protocol requirement and use it. Meanwhile, it would inherit from EventDescriptor
, so it would be perfectly compatible.
Hi, commenting on your thoughts:
That's the point, event creation and configuration is left for the CalendarKit. The client just provides the appropriate
This is currently supported. In your case, having 2 completely different event types could be managed with having multiple What I suggest would work best here is to add a parameter to the
and then, use that information to create the event in the Timeline. The default descriptor ( Also, with the proposed approach it's possible to add any information thru the
What if there is 3 kinds of descriptors? Or even 5? Then we'll need to add an if-else statement for all of them. Clearly, this information ( Please, let me know, if the approach I propose is clear, as well as the limitations of using a custom protocol just to provide a type. |
@richardtop Thx for you comment.
I believe that by this step we artificially limit the flexibility of the CalendarKit. A situation may arise when the logic of initializing a custom event view may differ from the usual call of the constructor and setting the frame. I believe that obliging the
This nice because any event can be fully described only using the descriptor subclass. I'm glad that this has already been implemented.
I have not tested more than two types of views, because this is not a priority for my organization. If possible, I will take the time to do this testing. But I'm not sure if I have time to do this.
The descriptor should store information about the event, not a view-type of the event! Because in this case we establish a strong relation between the model layer and the view layer, and this is a wrong approach at the root. If you are so confused about the if-else expression chain, how about using a factory to create custom views? We also have two other problems:
|
This was because String(reflecting:) was returning an invalid object class name (it included the word "optional"). Now I have to forcibly expand the optional field, but I'm not sure if this is a good solution
I ran into a bug in my typed queue that poses too complex questions for me:
In order for the I have a suspicion that the Now I cannot answer these two questions. I will be very grateful if you can help me with them |
No, it's just a general philosophy of the library. I'd prefer to keep it simple. If you need something more complex, then I recommend just forking the library and making changes in your fork.
It's clear that having more than 2 views would make implementing interface for the CK support cumbersome. Instead of containing every piece of the logic in an individual To me it seems that your project requires a highly customized solution, so it's best to fork the library and use it as it is.
It's fine, CalendarKit doesn't follow MVC strictly.
Please, implement this feature either the way I suggested or just fork the library if this approach doesn't fit your project.
It's a known issue: #113 |
This is in order to figure out which event has been selected / pressed:
I think, it's most likely due to the lifecycle issues. E.g. |
Btw, feel free to email me at [email protected] or reach via Telegram https://t.me/richardtop to discuss this feature more in detail. |
This is the first draft of the planned feature. I created a WIP pull request as you asked in #175. So @richardtop please give me a feedback while I implementing this feature.