I'm trying to make "tab" experience. Each tab has width of screen and user can swipe between each of them. Everything is working just fine, except that on tab with index "3" MKMapView is implemented.
When user open app, collection view is initialized to index "1", also cellForIndexAtIndexPath
is called for IndexPath(row: 1, section: 0)
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PageIndentifier, for: indexPath) as! TabCell
if (indexPath.item == 0)
{
cell.SetupNearestView()
NearestView = cell.nearestView
NearestView?.Delegate = self
}
if (indexPath.item == 1)
{
cell.SetupStationsView()
StationsView = cell.stationsView
StationsView?.Delegate = self
}
if (indexPath.item == 2)
{
cell.SetupMapView()
MapView = cell.stationsMapView
}
return cell
}
Issue is that UI is blocked for about second when user swipe from 1 -> 2 then collection view triggers cellForIndexAtIndexPath
is called for IndexPath(row: 2, section: 0)
. I was trying "force" load cell at that index but unfortunatelly, map seems to be initialized just before rendering on screen. Is there any workaround for that?
edit:
TabCell.swift
class TabCell : UICollectionViewCell
{
var nearestView : NearestView?
var stationsView : StationsView?
var stationsMapView : MapView?
override init(frame: CGRect)
{
super.init(frame: frame)
let gradient = CAGradientLayer()
gradient.frame = bounds
gradient.colors = [UIColor.clear, RuntimeResources.Get(color: .VeryDarkBlue).cgColor]
layer.insertSublayer(gradient, at: 0)
}
required init?(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
func SetupNearestView()
{
if (nearestView != nil)
{
return
}
nearestView = NearestView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
addSubview(nearestView!)
addConstraintsWithFormat(format: "H:|[v0]|", views: nearestView!)
addConstraintsWithFormat(format: "V:|[v0]|", views: nearestView!)
}
func SetupMapView()
{
if (stationsMapView != nil)
{
return
}
stationsMapView = MapView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
addSubview(stationsMapView!)
addConstraintsWithFormat(format: "H:|[v0]|", views: stationsMapView!)
addConstraintsWithFormat(format: "V:|[v0]|", views: stationsMapView!)
}
func SetupStationsView()
{
if (stationsView != nil)
{
return
}
stationsView = StationsView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
addSubview(stationsView!)
addConstraintsWithFormat(format: "H:|[v0]|", views: stationsView!)
addConstraintsWithFormat(format: "V:|[v0]|", views: stationsView!)
}
}
MapView.swift
import UIKit
import MapKit
class MapView: MKMapView, MKMapViewDelegate
{
private let infoViewHeight = CGFloat(500)
private let FocusZoomLevel = 0.01
private let ZoomLevel = 0.04
private let centerOfSzczecin = CLLocationCoordinate2D(latitude: 53.433345, longitude: 14.544139)
private var infoViewTopConstraint : NSLayoutConstraint?
lazy var mainStationView : UIView = {
let msv = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.width, height: self.infoViewHeight))
msv.translatesAutoresizingMaskIntoConstraints = false
msv.backgroundColor = RuntimeResources.Get(color: .DarkBlue)
return msv
}()
override init(frame: CGRect)
{
super.init(frame: frame)
delegate = self
// Adding info view
SetupInfoView()
// Setting center of map
let span = MKCoordinateSpanMake(ZoomLevel, ZoomLevel)
let region = MKCoordinateRegion(center: centerOfSzczecin, span: span)
setRegion(region, animated: false)
}
required init?(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
private func SetupInfoView()
{
addSubview(mainStationView)
infoViewTopConstraint = mainStationView.topAnchor.constraint(equalTo: self.bottomAnchor)
infoViewTopConstraint?.isActive = true
mainStationView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
mainStationView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
mainStationView.heightAnchor.constraint(equalToConstant: infoViewHeight).isActive = true
}
}
Since you are not reusing the MapView cell.
Try loading your mapView as a variable outside of your UICollectionViewCell
(In your UIViewController
) and add it as a subView to the cell in collectionView:willDisplayCell:forItemAtIndexPath:
and in collectionView:didEndDisplayingCell:forItemAtIndexPath: you can remove it from the cell.
Simply load all your mapView code outside of your cell and just use the Cell to display the map as a subview that is.