I am using SwiftUI
, UIKit
and external library CalendarKit in my project. The problem is that events don't load while initializing on first load of calendar. When I change date in the in the nav
, update event or create new event everything works fine. Events are reloading and are showed up on screen.
I have few classes in my projects. First is CalendarScreen
which renders the SwiftUI
view, ViewModel of CalendarScreen
which loads data fetched from API. Service which provides repository and Repository class which runs URLRequest. The UIKit
class of DayViewController
where everything is going in:
class CalendarViewController: DayViewController {
convenience init(viewModel: CalendarScreen.ViewModel) {
self.init()
self.viewModel = viewModel
}
var viewModel = CalendarScreen.ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
reloadData()
}
override func reloadData() {
dayView.timelinePagerView.pagingViewController.children.forEach({ (controller) in
if let controller = controller as? TimelineContainerController {
controller.timeline.layoutAttributes = eventsForDate(Date()).map(EventLayoutAttributes.init)
}
})
}
override func eventsForDate(_ date: Date) -> [EventDescriptor] {
return viewModel.fetchCalendarEvents {
var calendarKitEvents = [Event()]
calendarKitEvents = self.viewModel.calendarEvents.compactMap { item in
let event = Event()
event.dateInterval = DateInterval(
start: self.dateTimeFormat.date(from: item.start) ?? Date(),
end: self.dateTimeFormat.date(from: item.end) ?? Date())
event.color = UIColor(InvoiceColor(title: item.title))
event.isAllDay = false
event.text = item.title
return event
}
self.eventsOnCeldanr = calendarKitEvents
}
}
}
And the classes corresponding to my APICall
the main function is func fetchCalendarEvents
which return Events
to my Controller
class Agent {
let session = URLSession.shared
func run<T: Decodable>(_ request: URLRequest) -> AnyPublisher<T, Error> {
return
session
.dataTaskPublisher(for: request)
.decode(type: T.self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}
struct CalendarRepository {
private let agent = Agent()
func getEvents() -> AnyPublisher<[CalendarEvent], Error> {
let urlString = "\(calendarurl)"
let url = URL(string: urlString)!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
return agent.run(request)
}
}
struct CalendarService {
private var calendarRepository = CalendarRepository()
func getEvents() -> AnyPublisher<[CalendarEvent], Error> {
return calendarRepository.getEvents()
}
extension CalendarScreen {
class ViewModel: ObservableObject {
let calendarService = CalendarService()
@Published var calendarEvents: [CalendarEvent]
@Published var events: [Event]
var cancellable: AnyCancellable?
init() {
self.calendarEvents = [CalendarEvent()]
self.events = []
}
func fetchCalendarEvents(_ completion: @escaping () -> Void)
-> [EventDescriptor]
{
cancellable = calendarService.getEvents()
.sink(
receiveCompletion: { _ in },
receiveValue: {
calendarEvents in self.calendarEvents = calendarEvents
NotificationCenter.default.post(name: .onEventLoaded, object: nil)
self.createEvents()
completion()
})
return events
}
func createEvents() {
self.events = self.calendarEvents.compactMap({ (item) in
var event = Event()
event.dateInterval = DateInterval(
start: self.dateTimeFormat.date(from: item.start)!,
end: self.dateTimeFormat.date(from: item.end)!)
event.color = UIColor(InvoiceColor(title: item.title))
event.isAllDay = false
event.text = item.title
return event
})
}
}
}
}
So the problem is when I load view for the first time the reloadDate()
returning empty []
array.
While i try to debug Events
are in variable calendarKitEvents
but without sucessful return
and on first load function ends on reciveCompletion
call instead of reciveValue
call in fetchCalendarEvents
function.