From dd49c439462e02321657788a566efca17190a792 Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Fri, 3 Jan 2020 20:18:30 +0530 Subject: [PATCH] code cleanup --- MVMCoreUI/Molecules/BulletList.swift | 137 ++++++++++++++++++--------- 1 file changed, 94 insertions(+), 43 deletions(-) diff --git a/MVMCoreUI/Molecules/BulletList.swift b/MVMCoreUI/Molecules/BulletList.swift index f680b36a..5cb0dbd4 100644 --- a/MVMCoreUI/Molecules/BulletList.swift +++ b/MVMCoreUI/Molecules/BulletList.swift @@ -11,28 +11,14 @@ import UIKit open class BulletList: Container { var contentView = MVMCoreUICommonViewsUtility.commonView() - var reusableViews: [LeftRightLabelView] = [] + var reusableViews: [LeftLabelRightMoleculeContainer] = [] var bulletChar: String? - /// Restacks the existing items. - func restack() { - //setWithStackItems(items) - } - /// Removes all stack items views from the view. func removeAllItemInViews() { reusableViews.forEach({ $0.removeFromSuperview() }) } - /// The spacing to use between each item in the stack. - var verticalSpacing: CGFloat = 8 { - didSet { - if verticalSpacing != oldValue { - restack() - } - } - } - // MARK: - Inits public override init() { super.init() @@ -77,46 +63,72 @@ open class BulletList: Container { super.updateView(size) directionalLayoutMargins.leading = 0 directionalLayoutMargins.trailing = 0 + reusableViews.forEach({ $0.updateView(size) }) } // MARK: - MVMCoreUIMoleculeViewProtocol public override func reset() { super.reset() backgroundColor = .clear + reusableViews.forEach({ $0.reset() }) } open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - // let previousJSON = self.json + let previousJSON = self.json super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) removeAllItemInViews() + // If the items in the stack are the same, just update previous items instead of re-allocating. + var items: [LeftLabelRightMoleculeContainer]? + if BulletList.name(forReuse: previousJSON, delegateObject: delegateObject) == BulletList.name(forReuse: json, delegateObject: delegateObject) { + items = self.reusableViews + } + self.reusableViews = [] + guard let list = json?.arrayForKey("list") as? [[String: Any]] else { return } bulletChar = json?.optionalStringForKey("bulletChar") - - var views = [LeftLabelRightContainer]() // Adds the molecules and sets the json. for (index, map) in list.enumerated() { - let view = LeftLabelRightContainer() - let moleculeMap = ["left": leftItem(bulletChar ?? String(index + 1)), "right": map] - view.setWithJSON(moleculeMap, delegateObject: delegateObject, additionalData: additionalData) - views.append(view) + if let item = items?[index] { + item.leftText = bulletChar + item.setWithJSON(map, delegateObject: delegateObject, additionalData: nil) + addView(item, lastItem: index == list.count - 1) + } else { + let leftLabel = LeftLabelRightMoleculeContainer() + leftLabel.leftText = bulletChar + leftLabel.setWithJSON(map, delegateObject: delegateObject, additionalData: additionalData) + addView(leftLabel, lastItem: index == list.count - 1) + } } - let lastObj = views.last - MVMCoreUIStackableViewController.populateView(contentView, withUIArray: views) { (obj) -> UIEdgeInsets in - return UIEdgeInsets(top: 0, left: 0, bottom: lastObj?.isEqual(obj) ?? false ? 0 : 16, right: 0) + } + + func addView(_ container: LeftLabelRightMoleculeContainer, lastItem: Bool) { + container.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(container) + let first = reusableViews.first == nil + if first { + pinView(container, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 16) + } else if let previousView = reusableViews.last { + container.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: 16).isActive = true } + pinView(container, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) + pinView(contentView, toView: container, attribute: .trailing, relation: .equal, priority: .required, constant: 0) + if lastItem { + pinView(contentView, toView: container, attribute: .bottom, relation: .equal, priority: .required, constant: 0) + } + reusableViews.append(container) } public class func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { // This will aggregate names of molecules to make an id. guard let molecules = molecule?.optionalArrayForKey("list") else { - return "stack<>" + return "unordered<>" } - var name = "stack<" + var name = "unordered<" for case let item as [AnyHashable: Any] in molecules { - if let molecule = item.optionalDictionaryForKey(KeyMolecule), let moleculeName = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) { + if let moleculeName = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: item)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? item.optionalStringForKey(KeyMoleculeName) { name.append(moleculeName + ",") } } @@ -124,26 +136,36 @@ open class BulletList: Container { return name } + public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + guard let items = json?.optionalArrayForKey("list") else { + return 0 + } + var estimatedHeight: CGFloat = 0 + for case let item as [AnyHashable: AnyHashable] in items { + if let _ = item.optionalStringForKey(KeyMoleculeName) { + let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: item)?.estimatedHeight?(forRow: item, delegateObject: delegateObject) + estimatedHeight += ((height ?? 0) + 16) + } + } + return estimatedHeight + } + public class func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { guard let items = json?.optionalArrayForKey("list") else { return nil } var modules: [String] = [] for case let item as [AnyHashable: AnyHashable] in items { - if let molecule = item.optionalDictionaryForKey(KeyMolecule), let modulesForMolecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.requiredModules?(molecule, delegateObject: delegateObject, error: error) { + if let modulesForMolecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: item)?.requiredModules?(item, delegateObject: delegateObject, error: error) { modules += modulesForMolecule } } return modules.count > 0 ? modules : nil } - - func leftItem(_ string: String) -> [String: Any] { - return ["moleculeName":"label","text":string, "fontStyle":"B2"] - } } -class LeftLabelRightContainer: View { +class LeftLabelRightMoleculeContainer: View { var label = Label.commonLabelB2(true) var rightContainer = MVMCoreUICommonViewsUtility.commonView() @@ -151,6 +173,7 @@ class LeftLabelRightContainer: View { var rightMoleculeName: String? var rightMolecule: View? let containerHelper = ContainerHelper() + var leftText: String? var constraintBtwViews: NSLayoutConstraint? var spaceBtwViews: CGFloat = 8 { @@ -162,6 +185,24 @@ class LeftLabelRightContainer: View { } } + // MARK: - Inits + public override init() { + super.init() + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + + public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.init(frame: CGRect.zero) + setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func setupView() { super.setupView() @@ -173,7 +214,9 @@ class LeftLabelRightContainer: View { addSubview(rightContainer) addSubview(leftContainer) leftContainer.addSubview(label) - NSLayoutConstraint.constraintPinSubview(toSuperview: label) + //NSLayoutConstraint.constraintPinSubview(toSuperview: label) + NSLayoutConstraint.constraintPinSubview(label, pinTop: true, pinBottom: false, pinLeft: true, pinRight: false) + leftContainer.leftAnchor.constraint(greaterThanOrEqualTo: label.rightAnchor).isActive = true NSLayoutConstraint.constraintPinSubview(leftContainer, pinTop: true, pinBottom: false, pinLeft: true, pinRight: false) bottomAnchor.constraint(greaterThanOrEqualTo: leftContainer.bottomAnchor).isActive = true @@ -184,10 +227,10 @@ class LeftLabelRightContainer: View { constraintBtwViews?.isActive = true //TODO: Need to get confirmation on this - leftContainer.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.05, constant: 0).isActive = true + //leftContainer.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.05, constant: 0).isActive = true setContentHuggingPriority(.defaultHigh, for: .vertical) setContentHuggingPriority(.defaultHigh, for: .horizontal) - rightContainer.setContentHuggingPriority(.defaultHigh, for: .vertical) + rightContainer.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) rightContainer.setContentHuggingPriority(.defaultHigh, for: .horizontal) label.setContentHuggingPriority(.defaultHigh, for: .horizontal) @@ -197,23 +240,31 @@ class LeftLabelRightContainer: View { override func updateView(_ size: CGFloat) { super.updateView(size) + rightMolecule?.updateView(size) + label.updateView(size) + } + + override func reset() { + super.reset() + rightMolecule?.reset() } override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) let previousMoleculeName = rightMoleculeName - guard let moleculeJSON = json?.optionalDictionaryForKey("right") else { - removeSubviewsInRightContainer() + removeSubviewsInRightContainer() + guard let moleculeJSON = json, let _ = moleculeJSON.optionalStringForKey(KeyMoleculeName) else { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) return } - Label.setUILabel(label, withJSON: json?.optionalDictionaryForKey("left"), delegate: delegateObject, additionalData: additionalData) + label.text = leftText rightMoleculeName = moleculeJSON.optionalStringForKey(KeyMoleculeName) //For reuse purpose check that allready added molecule is same - if rightMolecule != nil && previousMoleculeName == rightMoleculeName { - rightMolecule?.setWithJSON(json?.optionalDictionaryForKey("right"), delegateObject: delegateObject, additionalData: additionalData) + if let rightMolecule = self.rightMolecule, previousMoleculeName == rightMoleculeName { + rightMolecule.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) + addView(rightMolecule) } else { - removeSubviewsInRightContainer() if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: false) { addView(molecule) }