Skip to content

Commit

Permalink
Merge pull request #395 from ualch9/fix_vc_retain_cycle
Browse files Browse the repository at this point in the history
Fixes view controller retain cycles
  • Loading branch information
aaronbrethorst authored Jun 23, 2021
2 parents 45d2fe6 + 63aa410 commit 3d54807
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ extension AgencyAlertListViewConverters where Self: UIViewController {
func listSections(agencyAlerts: [AgencyAlert]) -> [OBAListViewSection] {
let groupedAlerts = Dictionary(grouping: agencyAlerts, by: { $0.agency?.agency.name ?? "" })
return groupedAlerts.map { group -> OBAListViewSection in
let presentAlertAction: OBAListViewAction<TransitAlertDataListViewModel> = { [weak self] item in self?.presentAlert(item) }
let viewModels: [TransitAlertDataListViewModel] = group.value.map { alert -> TransitAlertDataListViewModel in
let isUnread = application.alertsStore.isAlertUnread(alert)
return TransitAlertDataListViewModel(alert, isUnread: isUnread, forLocale: Locale.current, onSelectAction: presentAlert)
return TransitAlertDataListViewModel(alert, isUnread: isUnread, forLocale: Locale.current, onSelectAction: presentAlertAction)
}

let alerts = viewModels.uniqued.sorted(by: \.title) // remove duplicates
Expand All @@ -45,7 +46,8 @@ extension AgencyAlertListViewConverters where Self: UIViewController {
/// - sectionID: The section ID to use with `OBAListViewSection`. The default value is `service_alerts`.
/// - Returns: An `OBAListViewSection` representing the array of `ServiceAlert`s for use with OBAListView.
func listSection(serviceAlerts: [ServiceAlert], showSectionTitle: Bool, sectionID: String = "service_alerts") -> OBAListViewSection {
let items = serviceAlerts.map { TransitAlertDataListViewModel($0, isUnread: false, forLocale: .current, onSelectAction: presentAlert) }.uniqued
let onSelectAction: OBAListViewAction<TransitAlertDataListViewModel> = { [weak self] item in self?.presentAlert(item) }
let items = serviceAlerts.map { TransitAlertDataListViewModel($0, isUnread: false, forLocale: .current, onSelectAction: onSelectAction) }.uniqued
let title: String?
if showSectionTitle {
if items.count > 1 {
Expand Down
28 changes: 18 additions & 10 deletions OBAKit/Stops/StopViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ public class StopViewController: UIViewController,

registerDefaults()

Timer.scheduledTimer(timeInterval: StopViewController.defaultTimerReloadInterval / 2.0, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
reloadTimer = Timer.scheduledTimer(withTimeInterval: StopViewController.defaultTimerReloadInterval / 2.0, repeats: true) { [weak self] _ in
self?.timerFired()
}

navigationItem.backBarButtonItem = UIBarButtonItem.backButton
}
Expand Down Expand Up @@ -502,15 +504,21 @@ public class StopViewController: UIViewController,
let alarmAvailable = canCreateAlarm(for: arrivalDeparture)
let deepLinkingAvailable = application.features.deepLinking == .running
let highlightTimeOnDisplay = shouldHighlight(arrivalDeparture: arrivalDeparture)

let onSelectAction: OBAListViewAction<ArrivalDepartureItem> = { [unowned self] item in self.didSelectArrivalDepartureItem(item) }
let addAlarmAction: OBAListViewAction<ArrivalDepartureItem> = { [unowned self] item in self.addAlarm(viewModel: item) }
let bookmarkAction: OBAListViewAction<ArrivalDepartureItem> = { [unowned self] item in self.addBookmark(viewModel: item) }
let shareAction: OBAListViewAction<ArrivalDepartureItem> = { [unowned self] item in self.shareTripStatus(viewModel: item) }

return ArrivalDepartureItem(
arrivalDeparture: arrivalDeparture,
isAlarmAvailable: alarmAvailable,
isDeepLinkingAvailable: deepLinkingAvailable,
highlightTimeOnDisplay: highlightTimeOnDisplay,
onSelectAction: didSelectArrivalDepartureItem,
alarmAction: addAlarm,
bookmarkAction: addBookmark,
shareAction: shareTripStatus)
onSelectAction: onSelectAction,
alarmAction: addAlarmAction,
bookmarkAction: bookmarkAction,
shareAction: shareAction)
}

func sectionForGroup(groupRoute: Route?, showSectionHeader: Bool, arrDeps: [ArrivalDeparture]) -> OBAListViewSection {
Expand Down Expand Up @@ -565,22 +573,22 @@ public class StopViewController: UIViewController,
self.performPreviewStopArrival(viewModel)
}

let menuProvider: OBAListViewMenuActions.MenuProvider = { _ in
let menuProvider: OBAListViewMenuActions.MenuProvider = { [unowned self] _ in
var actions = [UIAction]()

if viewModel.isAlarmAvailable {
let alarm = UIAction(title: Strings.addAlarm, image: Icons.addAlarm) { _ in
let alarm = UIAction(title: Strings.addAlarm, image: Icons.addAlarm) { [unowned self] _ in
self.addAlarm(viewModel: viewModel)
}
actions.append(alarm)
}

let addBookmark = UIAction(title: Strings.addBookmark, image: Icons.addBookmark) { _ in
let addBookmark = UIAction(title: Strings.addBookmark, image: Icons.addBookmark) { [unowned self] _ in
self.addBookmark(viewModel: viewModel)
}
actions.append(addBookmark)

let shareTrip = UIAction(title: Strings.shareTrip, image: UIImage(systemName: "square.and.arrow.up")) { _ in
let shareTrip = UIAction(title: Strings.shareTrip, image: UIImage(systemName: "square.and.arrow.up")) { [unowned self] _ in
self.shareTripStatus(viewModel: viewModel)
}
actions.append(shareTrip)
Expand Down Expand Up @@ -734,7 +742,7 @@ public class StopViewController: UIViewController,

// All Service Alerts
if let alerts = stopArrivals?.serviceAlerts, alerts.count > 0 {
let row = OBAListRowView.DefaultViewModel(title: Strings.serviceAlerts, accessoryType: .disclosureIndicator) { _ in
let row = OBAListRowView.DefaultViewModel(title: Strings.serviceAlerts, accessoryType: .disclosureIndicator) { [unowned self] _ in
let controller = ServiceAlertListController(application: self.application, serviceAlerts: alerts)
self.application.viewRouter.navigate(to: controller, from: self)
}
Expand Down
22 changes: 12 additions & 10 deletions OBAKit/Trip/TripFloatingPanelController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ class TripFloatingPanelController: UIViewController,
}

private func serviceAlertsListSection(_ alerts: [ServiceAlert]) -> OBAListViewSection {
let action: OBAListViewAction<TransitAlertDataListViewModel> = { viewModel in
let action: OBAListViewAction<TransitAlertDataListViewModel> = { [unowned self] viewModel in
self.application.viewRouter.navigateTo(alert: viewModel.transitAlert, from: self)
}

Expand All @@ -275,19 +275,21 @@ class TripFloatingPanelController: UIViewController,

private func tripStopListSection(tripDetails: TripDetails, arrivalDeparture: ArrivalDeparture?, showHeader: Bool) -> OBAListViewSection {
var contents: [AnyOBAListViewItem] = []
let selectAdjacentTripAction: OBAListViewAction<AdjacentTripItem> = { [unowned self] item in self.onSelectAdjacentTrip(item) }

// Previous trip, if any.
if let previousTrip = tripDetails.previousTrip {
contents.append(AdjacentTripItem(order: .previous, trip: previousTrip, onSelectAction: onSelectAdjacentTrip).typeErased)
contents.append(AdjacentTripItem(order: .previous, trip: previousTrip, onSelectAction: selectAdjacentTripAction).typeErased)
}

// Stop times
let stopTimes: [AnyOBAListViewItem] = tripDetails.stopTimes.map { TripStopViewModel(stopTime: $0, arrivalDeparture: arrivalDeparture, onSelectAction: onSelectTripStop).typeErased }
let selectTripStopAction: OBAListViewAction<TripStopViewModel> = { [unowned self] item in self.onSelectTripStop(item) }
let stopTimes: [AnyOBAListViewItem] = tripDetails.stopTimes.map { TripStopViewModel(stopTime: $0, arrivalDeparture: arrivalDeparture, onSelectAction: selectTripStopAction).typeErased }
contents.append(contentsOf: stopTimes)

// Next trip, if any.
if let nextTrip = tripDetails.nextTrip {
contents.append(AdjacentTripItem(order: .next, trip: nextTrip, onSelectAction: onSelectAdjacentTrip).typeErased)
contents.append(AdjacentTripItem(order: .next, trip: nextTrip, onSelectAction: selectAdjacentTripAction).typeErased)
}

let title: String? = showHeader ? OBALoc("trip_details_controller.service_alerts_footer", value: "Trip Details", comment: "Service alerts header in the trip details controller.") : nil
Expand All @@ -298,15 +300,15 @@ class TripFloatingPanelController: UIViewController,
private func viewOnMapAction(for viewModel: TripStopViewModel) -> UIAction? {
guard parentTripViewController != nil else { return nil }

return UIAction(title: OBALoc("trip_details_controller.show_on_map", value: "Show on Map", comment: "Button that moves the map to focus on the selected stop"), image: UIImage(systemName: "mappin.circle")) { _ in
return UIAction(title: OBALoc("trip_details_controller.show_on_map", value: "Show on Map", comment: "Button that moves the map to focus on the selected stop"), image: UIImage(systemName: "mappin.circle")) { [unowned self] _ in
self.showOnMap(viewModel)
}
}

private func getWalkingDirections(for viewModel: TripStopViewModel) -> UIMenuElement? {
let appleMapsAction: UIAction?
if let appleMapsURL = AppInterop.appleMapsWalkingDirectionsURL(coordinate: viewModel.stop.coordinate) {
appleMapsAction = UIAction(title: OBALoc("stops_controller.walking_directions_apple", value: "Walking Directions (Apple Maps)", comment: "Button that launches Apple's maps.app with walking directions to this stop")) { _ in
appleMapsAction = UIAction(title: OBALoc("stops_controller.walking_directions_apple", value: "Walking Directions (Apple Maps)", comment: "Button that launches Apple's maps.app with walking directions to this stop")) { [unowned self] _ in
self.application.open(appleMapsURL, options: [:], completionHandler: nil)
}
} else {
Expand All @@ -316,7 +318,7 @@ class TripFloatingPanelController: UIViewController,
let googleMapsAction: UIAction?
#if !targetEnvironment(simulator)
if let googleMapsURL = AppInterop.googleMapsWalkingDirectionsURL(coordinate: viewModel.stop.coordinate) {
googleMapsAction = UIAction(title: OBALoc("stops_controller.walking_directions_google", value: "Walking Directions (Google Maps)", comment: "Button that launches Google Maps with walking directions to this stop")) { _ in
googleMapsAction = UIAction(title: OBALoc("stops_controller.walking_directions_google", value: "Walking Directions (Google Maps)", comment: "Button that launches Google Maps with walking directions to this stop")) { [unowned self] _ in
self.application.open(googleMapsURL, options: [:], completionHandler: nil)
}
} else {
Expand All @@ -336,7 +338,7 @@ class TripFloatingPanelController: UIViewController,
func contextMenu(_ listView: OBAListView, for item: AnyOBAListViewItem) -> OBAListViewMenuActions? {
guard let tripStop = item.as(TripStopViewModel.self) else { return nil }

let menu: OBAListViewMenuActions.MenuProvider = { _ -> UIMenu? in
let menu: OBAListViewMenuActions.MenuProvider = { [unowned self] _ -> UIMenu? in
let menuActions = [
self.viewOnMapAction(for: tripStop),
self.getWalkingDirections(for: tripStop)
Expand All @@ -345,13 +347,13 @@ class TripFloatingPanelController: UIViewController,
return UIMenu(title: tripStop.title, children: menuActions)
}

let previewProvider: OBAListViewMenuActions.PreviewProvider = { () -> UIViewController? in
let previewProvider: OBAListViewMenuActions.PreviewProvider = { [unowned self] () -> UIViewController? in
let stopVC = StopViewController(application: self.application, stopID: tripStop.stop.id)
self.currentPreviewingViewController = stopVC
return stopVC
}

let commitPreviewAction: VoidBlock = {
let commitPreviewAction: VoidBlock = { [unowned self] in
guard let vc = self.currentPreviewingViewController else { return }
(vc as? Previewable)?.exitPreviewMode()
self.application.viewRouter.navigate(to: vc, from: self)
Expand Down

0 comments on commit 3d54807

Please sign in to comment.