This commit is contained in:
Pfeil, Scott Robert 2019-05-24 11:56:07 -04:00
parent b03fa77dfd
commit 699aa94d0a
5 changed files with 92 additions and 29 deletions

View File

@ -63,6 +63,10 @@ import UIKit
primaryButton?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
public static func estimatedHeight(forRow json: [AnyHashable : Any]?) -> CGFloat {
return 40
}
// MARK: - Constraining
func setupButton() {
if let primaryButton = primaryButton, !subviews.contains(primaryButton) {

View File

@ -27,7 +27,7 @@
- (UIStackViewAlignment)moleculeAlignment;
// For the molecule list to load more efficiently.
+ (CGFloat)estimatedHeightForRow;
+ (CGFloat)estimatedHeightForRow:(nullable NSDictionary *)json;
@end

View File

@ -91,6 +91,15 @@ import UIKit
}
}
public static func estimatedHeight(forRow json: [AnyHashable : Any]?) -> CGFloat {
guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule),
let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON, delegateObject: nil),
let estimatedHeightFor = theClass.estimatedHeight else {
return 0
}
return estimatedHeightFor(moleculeJSON)
}
// MARK: - Arrow
/// Adds the standard mvm style caret to the accessory view
public func addCaretViewAccessory() {

View File

@ -15,7 +15,7 @@
@interface MVMCoreUIMoleculeMappingObject : NSObject
/// Maps molecule name to class.
@property (nullable, strong, nonatomic) NSMutableDictionary <NSString *, Class> *moleculeMapping;
@property (nonnull, strong, nonatomic) NSMutableDictionary <NSString *, Class> *moleculeMapping;
/// Returns the shared instance
+ (nullable instancetype)sharedMappingObject;

View File

@ -9,10 +9,15 @@
import UIKit
open class MoleculeListTemplate: ThreeLayerTableViewController {
var molecules: [(molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)]?
open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error)
if shouldFinish, let firstError = modulesNeeded().errors?.first {
guard shouldFinish else {
return shouldFinish
}
if let firstError = setup()?.first {
// Don't continue if there was an error loading needed modules.
error.pointee = firstError
shouldFinish = false
@ -38,48 +43,49 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
open override func newDataBuildScreen() {
super.newDataBuildScreen()
_ = setupMoleculeList()
registerWithTable()
}
// MARK: - table
open override func registerWithTable() {
super.registerWithTable()
guard let molecules = loadObject?.pageJSON?.arrayForKey(KeyMolecules) else {
guard let molecules = molecules else {
return
}
for case let map as Dictionary<AnyHashable, Any> in molecules {
if let molecule = getMoleculeInfo(with: map), let moleculeToRegister = molecule.name {
tableView?.register(molecule.class, forCellReuseIdentifier: moleculeToRegister)
for molecule in molecules {
if let moleculeInfo = getMoleculeInfo(with: molecule), let moleculeToRegister = moleculeInfo.name {
tableView?.register(moleculeInfo.class, forCellReuseIdentifier: moleculeToRegister)
}
}
}
open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
guard let map = loadObject?.pageJSON?.optionalDictionaryWithChainOfKeysOrIndexes([KeyMolecules,indexPath.row]),
let molecule = getMoleculeInfo(with: map),
let estimatedHeightForRow = molecule.class.estimatedHeightForRow else {
guard let molecule = molecules?[indexPath.row],
let moleculeInfo = getMoleculeInfo(with: molecule),
let estimatedHeight = moleculeInfo.class.estimatedHeight else {
return 0
}
return estimatedHeightForRow()
return estimatedHeight(molecule.molecule)
}
open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return loadObject?.pageJSON?.arrayForKey(KeyMolecules).count ?? 0
return molecules?.count ?? 0
}
open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let delegate = delegateObject() as? MVMCoreUIDelegateObject
guard let map = loadObject?.pageJSON?.optionalDictionaryWithChainOfKeysOrIndexes([KeyMolecules,indexPath.row]),
let moleculeJSON = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: map, delegateObject: delegate)?.molecule,
let moleculeName = moleculeJSON.optionalStringForKey(KeyMoleculeName),
guard let molecule = molecules?[indexPath.row],
let moleculeInfo = getMoleculeInfo(with: molecule),
let moleculeName = moleculeInfo.name,
let cell = tableView.dequeueReusableCell(withIdentifier: moleculeName) else {
return UITableViewCell()
}
let delegate = delegateObject() as? MVMCoreUIDelegateObject
if let protocolCell = cell as? MoleculeListCellProtocol {
protocolCell.setSeparatorWithJSON?(loadObject?.pageJSON?.optionalDictionaryForKey("separator"), delegateObject: delegate, additionalData: nil, indexPath: indexPath)
}
if let protocolCell = cell as? MVMCoreUIMoleculeViewProtocol {
protocolCell.setWithJSON(moleculeJSON, delegateObject: delegate, additionalData: nil)
protocolCell.setWithJSON(molecule.molecule, delegateObject: delegate, additionalData: nil)
protocolCell.updateView(tableView.bounds.width)
}
return cell
@ -101,34 +107,78 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
open override func modulesToListenFor() -> [Any]? {
// Get all of the molecules that need modules.
return modulesNeeded().modules
return modulesNeeded()
}
// MARK: - Module Molecule Handling
/// Returns the (name, class) of the molecule for the given map.
func getMoleculeInfo(with map: [AnyHashable: Any]?) -> (name: String?, class: AnyClass)? {
guard let map = map, let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: map, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) else {
func getMoleculeInfo(with molecule: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)) -> (name: String?, class: AnyClass)? {
guard let map = molecule.molecule, let moleculeName = map.optionalStringForKey(KeyMoleculeName), let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? AnyClass else {
return nil
}
if let moleculeClass = moleculeClass as? MoleculeListCellProtocol.Type, let moleculeName = moleculeClass.moleculeName {
return (moleculeName(map, loadObject), moleculeClass)
} else {
return (map.optionalStringForKey(KeyMoleculeName), moleculeClass)
return (moleculeName, moleculeClass)
}
}
func modulesNeeded() -> (modules: [String]?, errors: [MVMCoreErrorObject]?) {
var modules: [String]? = []
var errors: [MVMCoreErrorObject]? = []
/// Sets up the molecule list and ensures no errors loading all content.
func setupMoleculeList() -> [MVMCoreErrorObject]? {
var errors: [MVMCoreErrorObject] = []
let delegate = delegateObject() as? MVMCoreUIDelegateObject
let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleNames: &modules, errors: &errors)
let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleNames: &modules, errors: &errors)
var moleculeList: [(molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)] = []
if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] {
for molecule in molecules {
let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, moduleNames: &modules, errors: &errors)
if let object = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: molecule, delegateObject: delegate) {
if let error = object.error {
errors.append(error)
} else {
moleculeList.append(object)
}
}
}
}
return (modules?.count ?? 0 > 0 ? modules : nil, errors?.count ?? 0 > 0 ? errors : nil)
molecules = moleculeList
return errors.count > 0 ? errors : nil
}
/// Sets up the header, footer, molecule list and ensures no errors loading all content.
func setup() -> [MVMCoreErrorObject]? {
var errors: [MVMCoreErrorObject] = []
let delegate = delegateObject() as? MVMCoreUIDelegateObject
MoleculeListTemplate.addToErrorList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate), errors: &errors)
MoleculeListTemplate.addToErrorList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate), errors: &errors)
if let newErrors = setupMoleculeList() {
errors.append(contentsOf: newErrors)
}
return errors.count > 0 ? errors : nil
}
static func addToErrorList(with moleculeObject: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)?, errors: inout [MVMCoreErrorObject]) {
if let error = moleculeObject?.error {
errors.append(error)
}
}
static func addToModuleList(with moleculeObject: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)?, moduleNames: inout [String]) {
if let moduleName = moleculeObject?.moduleName {
moduleNames.append(moduleName)
}
}
/// Gets a list of required modules
func modulesNeeded() -> [String]? {
var modules: [String] = []
let delegate = delegateObject() as? MVMCoreUIDelegateObject
MoleculeListTemplate.addToModuleList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate), moduleNames: &modules)
MoleculeListTemplate.addToModuleList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate), moduleNames: &modules)
if let molecules = molecules {
for molecule in molecules {
MoleculeListTemplate.addToModuleList(with: molecule, moduleNames: &modules)
}
}
return (modules.count > 0 ? modules : nil)
}
}