Texture/AsyncDisplayKit ASDisplayNode preferredSize's width not working - ios

I am very new to Texture/AsyncDisplayKit. I am able to reproduce the issue with this simple code.
I basically want to show a 10x10 square at the bottom right of the ASCellNode. I am doing this via a ASDisplayNode which is being set as the corner of a ASCornerLayoutSpec. I have set the style.preferredSize of the ASDisplayNode to CGSize(width: 10, height: 10).
For some reason, the width is not working and showing up as 50% of the screen width:
Code:
import UIKit
import AsyncDisplayKit
class ViewController: ASDKViewController<ASDisplayNode>, ASTableDataSource {
var tableNode = ASTableNode()
override init() {
super.init(node: tableNode)
node.automaticallyRelayoutOnSafeAreaChanges = true
node.automaticallyManagesSubnodes = true
tableNode.dataSource = self
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableNode(_ tableNode: ASTableNode, nodeBlockForRowAt indexPath: IndexPath) -> ASCellNodeBlock {
let cellNodeBlock = { () -> ASCellNode in
let cellNode = CellNode()
return cellNode
}
return cellNodeBlock
}
}
class CellNode: ASCellNode {
fileprivate let titleNode = ASTextNode()
fileprivate let savedIconNode = ASDisplayNode()
override init() {
super.init()
self.automaticallyManagesSubnodes = true
titleNode.attributedText = NSAttributedString(string: "This is my title!", attributes: [.font : UIFont.systemFont(ofSize: 20),.foregroundColor:UIColor.white])
savedIconNode.isLayerBacked = true
savedIconNode.backgroundColor = .green
savedIconNode.style.preferredSize = CGSize(width: 10, height: 10)
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let paddingToUse = 15.0;
let contentView = ASInsetLayoutSpec(insets: UIEdgeInsets(top: paddingToUse, left: paddingToUse, bottom: paddingToUse, right: paddingToUse), child: ASStackLayoutSpec(direction: .horizontal, spacing: 5, justifyContent: .spaceBetween, alignItems: .notSet, children: [titleNode]))
let contentViewAndSaveTriangle = ASCornerLayoutSpec(child: contentView, corner: savedIconNode, location: .bottomRight)
return contentViewAndSaveTriangle
}
}

Related

Swift to SwiftUI migration issue

So I am not fully understanding how this needs to be implemented in SwiftUI for it to work properly.
I have the following code:
class RulerView: UIView {
// MARK: - Constants
private struct Constants {
static let labelWidth: CGFloat = 100
static let labelHeight: CGFloat = 20
static let labelMarginTop: CGFloat = 5
static let rulerHeight: CGFloat = 100
}
// MARK: - Properties
override var tintColor: UIColor! {
didSet { _updateStyle().setNeedsDisplay() }
}
internal let unit: Length.Unit
internal let length: CGFloat
private var lineWidth: CGFloat
private var replicatorLayer: CAReplicatorLayer?
private var labels: [UILabel]?
private var lengthUnitWidth: CGFloat {
switch unit {
case .centimeter:
return Length.pixels(fromCentimeter: 1.0)
case .inch:
return Length.pixels(fromInch: 1.0)
}
}
// MARK: - View Life Cycle
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
/*
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
*/
init(unit: Length.Unit, length: CGFloat, lineWidth: CGFloat) {
self.unit = unit
self.length = length
self.lineWidth = lineWidth
super.init(frame: .zero)
let rulerWidth = lengthUnitWidth * length
frame = .init(x: 0, y: 0, width: rulerWidth, height: Constants.rulerHeight)
_setupLabels()
}
override func didMoveToWindow() {
super.didMoveToWindow()
_updateStyle()
}
override func draw(_ rect: CGRect) {
super.draw(rect)
replicatorLayer?.removeFromSuperlayer()
replicatorLayer = CAReplicatorLayer()
if let replicatorLayer = replicatorLayer {
replicatorLayer.instanceCount = Int(ceil(length))
replicatorLayer.instanceTransform = CATransform3DMakeTranslation(lengthUnitWidth, 0, 0)
let unitLayer = LengthUnitLayer(unit: unit, lineWidth: lineWidth, lineColor: tintColor.cgColor, height: frame.height)
unitLayer.frame = CGRect(x: -lineWidth / 2, y: 0, width: unitLayer.bounds.width, height: (bounds.height - Constants.labelHeight - Constants.labelMarginTop))
unitLayer.setNeedsDisplay()
replicatorLayer.addSublayer(unitLayer)
layer.addSublayer(replicatorLayer)
}
labels?.enumerated().forEach { (offset, element) in
element.frame = .init(x: (CGFloat(offset) * lengthUnitWidth - Constants.labelWidth / 2),
y: (bounds.height - Constants.labelHeight),
width: Constants.labelWidth,
height: Constants.labelHeight)
}
}
// MARK: - Setup
#discardableResult
private func _setupLabels() -> Self {
labels?.forEach { $0.removeFromSuperview() }
labels = [UILabel]()
for i in 0...Int(ceil(length)) {
let label = UILabel()
label.text = "\(i)"
label.textAlignment = .center
addSubview(label)
labels?.append(label)
}
return self
}
// MARK: - Layout
#discardableResult
private func _updateStyle() -> Self {
labels?.forEach { $0.textColor = tintColor }
return self
}
}
And I am trying to call it in the ContentView as such:
var viewSize = UIScreen.main.bounds.size
var body: some View {
RulerView(coder: viewSize)
}
But it is not working? Does anyone know how I can resolve this?
The UIView needs to be wrapped into UIViewRepresentable to be used in SwiftUI, like below.
public struct RulerViewRep: UIViewRepresentable {
public func makeUIView(context: Context) -> RulerView {
return RulerView()
}
public func updateUIView(_ uiView: RulerView, context: Context) {
}
}
and then use it
var body: some View {
// by default consumes all space, so UIScreen.main.bounds not needed
RulerView()
}

How to change page control dot size and spacing in swift?

I want customize page control like a image.
I've already search that, but there are only deal scale.
I want change width, height, spacing.
How can I do that?
I tried this
class DefaultPageControl: UIPageControl {
override var currentPage: Int {
didSet {
updateDots()
}
}
func updateDots() {
let currentDot = subviews[currentPage]
subviews.forEach {
$0.frame.size = ($0 == currentDot) ? CGSize(width: 16, height: 4) : CGSize(width: 8, height: 4)
$0.layer.cornerRadius = 2
}
}
}
But how to change distance??
#oddK Can you try with this below answer. It's my assumption.
class DefaultPageControl: UIPageControl {
override var currentPage: Int {
didSet {
updateDots()
}
}
func updateDots() {
let currentDot = subviews[currentPage]
let spacing = 5.0
subviews.forEach {
$0.frame = ($0 == currentDot) ? CGRect(x: 0, y: 0, width: 16, height: 4) : CGRect(x: spacing, y: 0, width: 8, height: 4)
//$0.frame.size = ($0 == currentDot) ? CGSize(width: 16, height: 4) : CGSize(width: 8, height: 4)
$0.layer.cornerRadius = 2
}
}
}
The default UIPageControll is not flexible.
class ExtendedpageControll: UIView{
var numberOfPage: Int
var currentpage : Int = 0{didSet{reloadView()}}
var currentIndicatorColor: UIColor = .black
var indicatorColor: UIColor = UIColor(white: 0.9, alpha: 1)
var circleIndicator: Bool = false
private var dotView = [UIView]()
private let spacing: CGFloat = 6
private lazy var extraWidth: CGFloat = circleIndicator ? 6 : 4
init(numberOfPages: Int,currentPage: Int,isCircular: Bool){
self.numberOfPage = numberOfPages
self.currentpage = currentPage
self.circleIndicator = isCircular
super.init(frame: .zero)
configView()
}
required init?(coder: NSCoder) {fatalError("not implemented")}
private func configView(){
backgroundColor = .clear
(0..<numberOfPage).forEach { _ in
let view = UIView()
addSubview(view)
dotView.append(view)
}
}
private func reloadView(){
dotView.forEach{$0.backgroundColor = indicatorColor}
dotView[currentpage].backgroundColor = currentIndicatorColor
UIView.animate(withDuration: 0.2) {
self.dotView[self.currentpage].frame.origin.x = self.dotView[self.currentpage].frame.origin.x - self.extraWidth
self.dotView[self.currentpage].frame.size.width = self.dotView[self.currentpage].frame.size.width + (self.extraWidth * 2)
}
}
override func layoutSubviews() {
super.layoutSubviews()
for (i,view) in dotView.enumerated(){
view.clipsToBounds = true
view.layer.cornerRadius = bounds.height / 2
let width: CGFloat = circleIndicator ? self.bounds.height : CGFloat(self.bounds.width / CGFloat(self.numberOfPage) - self.spacing) - self.extraWidth
UIView.animate(withDuration: 0.2) {
view.frame = CGRect(x: ((self.bounds.width / CGFloat(self.numberOfPage)) * CGFloat(i)) + self.spacing, y: 0, width: width , height: self.bounds.height)
}
}
reloadView()
}
}
Usage: If you want to link ExtendedpageControll to a View Such as CollectionView Just Do like this: (item is your Datamodel)
class SampleViewController: UIViewController{
let colectionView = UICollectionView()
lazy var pageControll: ExtendedpageControll = {
let pc = ExtendedpageControll(numberOfPages: items.count, currentPage: 0,isCircular: true)
pc.currentIndicatorColor = .black
return pc
}()
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if pageControll.currentpage == indexPath.row {
guard let visible = self.collectionView.visibleCells.first else { return }
guard let index = self.collectionView.indexPath(for: visible)?.row else { return }
pageControll.currentpage = index
}
}
}
inside init, you can set the shape of the indicator to be circular or extended via isCircular.

2-way scrolling Table in iOS

I am an android application developer and new to iOS programming and my very first challenge is to build a 2-way scrolling table in iOS. I am getting many solutions with UICollectionView inside UITableView. But in my case rows will scroll together, not independent of each other. There are more than 15 columns and 100+ rows with text data in the table.
I have achieved the same in Android by using a ListView inside a HorizontalScrollView. But yet to find any solution in iOS. Any help is greatly appreciated.
EDIT: I have added a couple of screens of the android app where the table is scrolled horizontally.
So you want this:
You should use a UICollectionView. You can't use UICollectionViewFlowLayout (the only layout that's provided in the public SDK) because it is designed to only scroll in one direction, so you need to implement a custom UICollectionViewLayout subclass that arranges the elements to scroll in both directions if needed.
For full details on building a custom UICollectionViewLayout subclass, you should watch these: videos from WWDC 2012:
Session 205: Introducing Collection Views
Session 219: Advanced Collection Views and Building Custom Layouts
Anyway, I'll just dump an example implementation of GridLayout here for you to start with. For each IndexPath, I use the section as the row number and the item as the column number.
class GridLayout: UICollectionViewLayout {
var cellHeight: CGFloat = 22
var cellWidths: [CGFloat] = [] {
didSet {
precondition(cellWidths.filter({ $0 <= 0 }).isEmpty)
invalidateCache()
}
}
override var collectionViewContentSize: CGSize {
return CGSize(width: totalWidth, height: totalHeight)
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// When bouncing, rect's origin can have a negative x or y, which is bad.
let newRect = rect.intersection(CGRect(x: 0, y: 0, width: totalWidth, height: totalHeight))
var poses = [UICollectionViewLayoutAttributes]()
let rows = rowsOverlapping(newRect)
let columns = columnsOverlapping(newRect)
for row in rows {
for column in columns {
let indexPath = IndexPath(item: column, section: row)
poses.append(pose(forCellAt: indexPath))
}
}
return poses
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return pose(forCellAt: indexPath)
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return false
}
private struct CellSpan {
var minX: CGFloat
var maxX: CGFloat
}
private struct Cache {
var cellSpans: [CellSpan]
var totalWidth: CGFloat
}
private var _cache: Cache? = nil
private var cache: Cache {
if let cache = _cache { return cache }
var spans = [CellSpan]()
var x: CGFloat = 0
for width in cellWidths {
spans.append(CellSpan(minX: x, maxX: x + width))
x += width
}
let cache = Cache(cellSpans: spans, totalWidth: x)
_cache = cache
return cache
}
private var totalWidth: CGFloat { return cache.totalWidth }
private var cellSpans: [CellSpan] { return cache.cellSpans }
private var totalHeight: CGFloat {
return cellHeight * CGFloat(collectionView?.numberOfSections ?? 0)
}
private func invalidateCache() {
_cache = nil
invalidateLayout()
}
private func rowsOverlapping(_ rect: CGRect) -> Range<Int> {
let startRow = Int(floor(rect.minY / cellHeight))
let endRow = Int(ceil(rect.maxY / cellHeight))
return startRow ..< endRow
}
private func columnsOverlapping(_ rect: CGRect) -> Range<Int> {
let minX = rect.minX
let maxX = rect.maxX
if let start = cellSpans.firstIndex(where: { $0.maxX >= minX }), let end = cellSpans.lastIndex(where: { $0.minX <= maxX }) {
return start ..< end + 1
} else {
return 0 ..< 0
}
}
private func pose(forCellAt indexPath: IndexPath) -> UICollectionViewLayoutAttributes {
let pose = UICollectionViewLayoutAttributes(forCellWith: indexPath)
let row = indexPath.section
let column = indexPath.item
pose.frame = CGRect(x: cellSpans[column].minX, y: CGFloat(row) * cellHeight, width: cellWidths[column], height: cellHeight)
return pose
}
}
To draw the separating lines, I added hairline views to each cell's background:
class GridCell: UICollectionViewCell {
static var reuseIdentifier: String { return "cell" }
override init(frame: CGRect) {
super.init(frame: frame)
label.frame = bounds.insetBy(dx: 2, dy: 2)
label.autoresizingMask = [.flexibleWidth, .flexibleHeight]
contentView.addSubview(label)
let backgroundView = UIView(frame: CGRect(origin: .zero, size: frame.size))
backgroundView.backgroundColor = .white
self.backgroundView = backgroundView
rightSeparator.backgroundColor = .gray
backgroundView.addSubview(rightSeparator)
bottomSeparator.backgroundColor = .gray
backgroundView.addSubview(bottomSeparator)
}
func setRecord(_ record: String) {
label.text = record
}
override func layoutSubviews() {
super.layoutSubviews()
let thickness = 1 / (window?.screen.scale ?? 1)
let size = bounds.size
rightSeparator.frame = CGRect(x: size.width - thickness, y: 0, width: thickness, height: size.height)
bottomSeparator.frame = CGRect(x: 0, y: size.height - thickness, width: size.width, height: thickness)
}
private let label = UILabel()
private let rightSeparator = UIView()
private let bottomSeparator = UIView()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Here's my demo view controller:
class ViewController: UIViewController {
var records: [[String]] = (0 ..< 20).map { row in
(0 ..< 6).map {
column in
"Row \(row) column \(column)"
}
}
var cellWidths: [CGFloat] = [ 180, 200, 180, 160, 200, 200 ]
override func viewDidLoad() {
super.viewDidLoad()
let layout = GridLayout()
layout.cellHeight = 44
layout.cellWidths = cellWidths
let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.isDirectionalLockEnabled = true
collectionView.backgroundColor = UIColor(white: 0.95, alpha: 1)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.register(GridCell.self, forCellWithReuseIdentifier: GridCell.reuseIdentifier)
collectionView.dataSource = self
view.addSubview(collectionView)
}
}
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return records.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return records[section].count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: GridCell.reuseIdentifier, for: indexPath) as! GridCell
cell.setRecord(records[indexPath.section][indexPath.item])
return cell
}
}

iOS - IGListKit - implement self sizing cell with UIImageView

I am trying to implement IGListKit based CollectionView. It has 1 UILabel and 1 UIImageView.
Checked official examples too but couldn't manage to make it self sizing.
This is Cell class. In this class tried to add the code which is given in the official repository. The function I've used is preferredLayoutAttributesFitting:
import UIKit
import Stevia
class MainControllerCell: UICollectionViewCell {
lazy var userNameLabel: UILabel = {
let lbl = UILabel()
lbl.numberOfLines = 1
lbl.translatesAutoresizingMaskIntoConstraints = false
return lbl
}()
lazy var photoImageView: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.backgroundColor = .white
contentView.sv(
userNameLabel,
photoImageView
)
}
override func layoutSubviews() {
contentView.layout(
8,
|-8-userNameLabel.height(20)-8-|,
8,
|-0-photoImageView-0-|,
8
)
}
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
setNeedsLayout()
layoutIfNeeded()
let size = contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
var newFrame = layoutAttributes.frame
// note: don't change the width
newFrame.size.height = ceil(size.height)
layoutAttributes.frame = newFrame
return layoutAttributes
}
}
This is SectionController:
import IGListKit
class MainSectionController: ListSectionController {
private var post: Post!
override init() {
super.init()
inset = UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)
minimumLineSpacing = 10
minimumInteritemSpacing = 10
}
override func numberOfItems() -> Int {
return 1
}
override func sizeForItem(at index: Int) -> CGSize {
let width = collectionContext!.containerSize.width
return CGSize(width: width, height: 75) // width / post.photo.getImageRatio() + 44
}
override func cellForItem(at index: Int) -> UICollectionViewCell {
let userName = post.userName
let photo = post.photo
let cell: UICollectionViewCell
guard let mainCollectionViewCell = collectionContext?.dequeueReusableCell(of: MainControllerCell.self,
for: self,
at: index) as? MainControllerCell else { fatalError() }
mainCollectionViewCell.userName = userName
mainCollectionViewCell.photoImageView.image = photo
cell = mainCollectionViewCell
return cell
}
override func didUpdate(to object: Any) {
self.post = object as? Post
}
}
And lastly Controller:
import UIKit
import IGListKit
class MainController: UIViewController, ListAdapterDataSource {
lazy var adapter: ListAdapter = {
let updater = ListAdapterUpdater()
return ListAdapter(updater: updater, viewController: self)
}()
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .white
return collectionView
}()
var posts: [Post] = []
override func viewDidLoad() {
super.viewDidLoad()
posts = [Post(timeStamp: 0, userName: "onur", photoUrl: "xxx", photo: UIImage(named: "cat")!),
Post(timeStamp: 1, userName: "onur", photoUrl: "xxx", photo: UIImage(named: "iPhoneMP")!),
Post(timeStamp: 2, userName: "onur", photoUrl: "xxx", photo: UIImage(named: "placeholder")!),
Post(timeStamp: 3, userName: "onur", photoUrl: "xxx", photo: UIImage(named: "random")!)]
adapter.collectionView = collectionView
adapter.dataSource = self
view.addSubview(collectionView)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.frame = view.bounds
adapter.performUpdates(animated: false, completion: nil)
}
// MARK: ListAdapterDataSource
func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
return posts
}
func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
return MainSectionController()
}
func emptyView(for listAdapter: ListAdapter) -> UIView? {
return nil
}
}
What I am trying to implemet is making a Instagram like layout but less complicated. I won't add new views or anything.
In the preferredLayoutAttributesFitting method, I am getting the original image size. Not the scaled image's size.
The official examples are made with just labels. Before trying to implement this project I tried with just labels and constant sized UIImageView for profile photo. It is working good with it.
Not sure if the problem is with SteviaLayout?
Thanks in advance.

Preloading MKMapView in collection view

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.

Resources