formatitgn and commenting
This commit is contained in:
parent
f9ce6e9f0f
commit
ecba5863ff
@ -8,7 +8,12 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class ScrollingViewController: ViewController {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var dismissKeyboardTapGesture: UITapGestureRecognizer?
|
||||
@IBOutlet public var scrollView: UIScrollView!
|
||||
public var contentView: UIView?
|
||||
@ -17,6 +22,10 @@ open class ScrollingViewController: ViewController {
|
||||
private var keyboardIsShowing = false
|
||||
private var preKeyboardContentInset: UIEdgeInsets?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(with scrollView: UIScrollView) {
|
||||
self.scrollView = scrollView
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
@ -30,7 +39,10 @@ open class ScrollingViewController: ViewController {
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
}
|
||||
|
||||
// MARK: - View Life Cycle
|
||||
//--------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
@ -53,7 +65,10 @@ open class ScrollingViewController: ViewController {
|
||||
registerForKeyboardNotifications()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keyboard Handling
|
||||
//--------------------------------------------------
|
||||
|
||||
open func registerForKeyboardNotifications() {
|
||||
if !keyboardNotificationsAdded {
|
||||
keyboardNotificationsAdded = true
|
||||
@ -96,7 +111,9 @@ open class ScrollingViewController: ViewController {
|
||||
|
||||
open func rectToScrollToWhenKeyboardPopsUp() -> CGRect? {
|
||||
guard let field = selectedField,
|
||||
let parent = selectedField?.superview else { return nil }
|
||||
let parent = selectedField?.superview
|
||||
else { return nil }
|
||||
|
||||
return scrollView.convert(field.frame, from: parent)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,10 @@
|
||||
import UIKit
|
||||
|
||||
@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
@objc public var pageType: String?
|
||||
@objc public var loadObject: MVMCoreLoadObject?
|
||||
public var pageModel: MVMControllerModelProtocol?
|
||||
@ -39,10 +43,15 @@ import UIKit
|
||||
return !MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Response handling
|
||||
//--------------------------------------------------
|
||||
|
||||
open func observeForResponseJSONUpdates() {
|
||||
guard !observingForResponses,
|
||||
(pagesToListenFor()?.count ?? 0 > 0 || modulesToListenFor()?.count ?? 0 > 0) else { return }
|
||||
(pagesToListenFor()?.count ?? 0 > 0 || modulesToListenFor()?.count ?? 0 > 0)
|
||||
else { return }
|
||||
|
||||
observingForResponses = true
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(responseJSONUpdated(notification:)), name: NSNotification.Name(rawValue: NotificationResponseLoaded), object: nil)
|
||||
}
|
||||
@ -69,7 +78,9 @@ import UIKit
|
||||
let pageType = pagesToListenFor()?.first(where: { (pageTypeListened) -> Bool in
|
||||
guard let page = pagesLoaded.optionalDictionaryForKey(pageTypeListened),
|
||||
let pageType = page.optionalStringForKey(KeyPageType),
|
||||
pageType == pageTypeListened else { return false }
|
||||
pageType == pageTypeListened
|
||||
else { return false }
|
||||
|
||||
return true
|
||||
}) {
|
||||
newData = true
|
||||
@ -90,6 +101,7 @@ import UIKit
|
||||
}
|
||||
|
||||
guard newData else { return }
|
||||
|
||||
do {
|
||||
try parsePageJSON()
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
@ -134,8 +146,10 @@ import UIKit
|
||||
switch (registryError) {
|
||||
case .decoderErrorModelNotMapped(let identifier, let codingKey, let codingPath) where identifier != nil && codingKey != nil && codingPath != nil:
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Error parsing template: Model identifier \"\(identifier!)\" is not mapped for \"\(codingKey!.stringValue)\" @ \(codingPath!.map { return $0.stringValue })")
|
||||
|
||||
case .decoderErrorObjectNotPresent(let codingKey, codingPath: let codingPath):
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Error parsing template: Required model \"\(codingKey.stringValue)\" was not found @ \(codingPath.map { return $0.stringValue })")
|
||||
|
||||
default:
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Error parsing template: Registry error: \(registryError)")
|
||||
}
|
||||
@ -144,24 +158,29 @@ import UIKit
|
||||
switch (decodingError) {
|
||||
case .keyNotFound(let codingKey, let context):
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Error parsing template: Key \(codingKey.stringValue) was not found @ \(context.codingPath.map { return $0.stringValue })")
|
||||
|
||||
case .valueNotFound(_, let context):
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Error parsing template: Value not found @ \(context.codingPath.map { return $0.stringValue })")
|
||||
|
||||
case .typeMismatch(_, let context):
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Error parsing template: Type mismatch @ \(context.codingPath.map { return $0.stringValue })")
|
||||
|
||||
case .dataCorrupted(let context):
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Error parsing template: Data corrupted @ \(context.codingPath.map { return $0.stringValue })")
|
||||
|
||||
@unknown default:
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Error parsing template: \(parsingError)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open func parsePageJSON() throws {
|
||||
}
|
||||
open func parsePageJSON() throws { }
|
||||
|
||||
open class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
|
||||
guard let pageType = loadObject?.pageType, var modulesRequired = MVMCoreUIViewControllerMappingObject.shared()?.modulesRequired(forPageType: pageType),
|
||||
!modulesRequired.isEmpty else { return true }
|
||||
guard let pageType = loadObject?.pageType,
|
||||
var modulesRequired = MVMCoreUIViewControllerMappingObject.shared()?.modulesRequired(forPageType: pageType),
|
||||
!modulesRequired.isEmpty
|
||||
else { return true }
|
||||
|
||||
guard let loadedModules = loadObject?.modulesJSON else { return false }
|
||||
|
||||
@ -210,7 +229,9 @@ import UIKit
|
||||
setNavigationItem()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Navigation Item (Move to model base)
|
||||
//--------------------------------------------------
|
||||
|
||||
open func getNavigationModel() -> NavigationItemModelProtocol? {
|
||||
// TODO: remove legacy. Temporary, convert legacy to navigation model.
|
||||
@ -224,7 +245,8 @@ import UIKit
|
||||
/// Sets the navigation item for this view controller.
|
||||
open func setNavigationItem() {
|
||||
guard let navigationItemModel = getNavigationModel(),
|
||||
let navigationController = navigationController else { return }
|
||||
let navigationController = navigationController
|
||||
else { return }
|
||||
|
||||
// We additionally want our left items
|
||||
navigationItem.leftItemsSupplementBackButton = true
|
||||
@ -268,18 +290,16 @@ import UIKit
|
||||
|
||||
// Eventually will be moved to separate button in navigation item model
|
||||
open func isOverridingRightButton() -> Bool {
|
||||
guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink") else {
|
||||
return false
|
||||
}
|
||||
guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink")
|
||||
else { return false }
|
||||
MVMCoreActionHandler.shared()?.handleAction(with: rightPanelLink, additionalData: nil, delegateObject: delegateObject())
|
||||
return true
|
||||
}
|
||||
|
||||
// Eventually will be moved to separate button in navigation item model
|
||||
open func isOverridingLeftButton() -> Bool {
|
||||
guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink") else {
|
||||
return false
|
||||
}
|
||||
guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink")
|
||||
else { return false }
|
||||
MVMCoreActionHandler.shared()?.handleAction(with: leftPanelLink, additionalData: nil, delegateObject: delegateObject())
|
||||
return true
|
||||
}
|
||||
@ -287,11 +307,15 @@ import UIKit
|
||||
// Eventually will be moved to Model
|
||||
open func bottomProgress() -> Float? {
|
||||
guard let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent),
|
||||
let progress = Float(progressString) else { return nil }
|
||||
return (progress / Float(100))
|
||||
}
|
||||
let progress = Float(progressString)
|
||||
else { return nil }
|
||||
|
||||
return progress / Float(100)
|
||||
}
|
||||
//--------------------------------------------------
|
||||
// MARK: - TabBar
|
||||
//--------------------------------------------------
|
||||
|
||||
open func updateTabBar() {
|
||||
guard MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() == self,
|
||||
let tabModel = pageModel as? TabPageModelProtocol else { return }
|
||||
@ -302,7 +326,9 @@ import UIKit
|
||||
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!tabModel.tabBarHidden)
|
||||
}
|
||||
|
||||
// MARK: - View lifecycle
|
||||
//--------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Called only once in viewDidLoad
|
||||
open func initialLoad() {
|
||||
@ -401,18 +427,22 @@ import UIKit
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
|
||||
// Updates the detail view width
|
||||
coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
|
||||
}) { (UIViewControllerTransitionCoordinatorContext) in
|
||||
coordinator.animate(alongsideTransition: { UIViewControllerTransitionCoordinatorContext in
|
||||
}) { UIViewControllerTransitionCoordinatorContext in
|
||||
self.view.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
||||
pageShown()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreLoadDelegateProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
// TODO: Move this function out of here after architecture cleanup.
|
||||
open func loadFinished(_ loadObject: MVMCoreLoadObject?, loadedViewController: (UIViewController & MVMCoreViewControllerProtocol)?, error: MVMCoreErrorObject?) {
|
||||
|
||||
@ -434,7 +464,10 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreActionDelegateProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) {
|
||||
formValidator?.addFormParams(requestParameters: requestParameters)
|
||||
requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType")
|
||||
@ -445,7 +478,10 @@ import UIKit
|
||||
MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: self, actionInformation: actionInformation, additionalData: additionalData)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeDelegateProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? {
|
||||
guard let name = name else { return nil }
|
||||
return loadObject?.modulesJSON?.optionalDictionaryForKey(name)
|
||||
@ -456,6 +492,7 @@ import UIKit
|
||||
let moleculeName = moduleJSON.optionalStringForKey("moleculeName"),
|
||||
let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self)
|
||||
else { return nil }
|
||||
|
||||
do {
|
||||
return try modelType.decode(jsonDict: moduleJSON) as? MoleculeModelProtocol
|
||||
} catch {
|
||||
@ -471,14 +508,19 @@ import UIKit
|
||||
open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {}
|
||||
open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreUIDetailViewProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
// Reset the navigation state.
|
||||
public func splitViewDidReset() {
|
||||
setNavigationBar()
|
||||
}
|
||||
|
||||
// MARK: - UITextFieldDelegate (Check if this is still needed)
|
||||
//--------------------------------------------------
|
||||
// MARK: - UITextFieldDelegate
|
||||
//--------------------------------------------------
|
||||
|
||||
// To Remove TextFields Bug: Keyboard is not dismissing after reaching textfield max length limit
|
||||
open func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
textField.resignFirstResponder()
|
||||
@ -490,9 +532,13 @@ import UIKit
|
||||
|
||||
// TODO: Make this into a protocol
|
||||
if UIAccessibility.isVoiceOverRunning {
|
||||
if let toolBar = textField.inputAccessoryView as? UIToolbar, let _ = toolBar.items?.last, let pickerView = textField.inputView as? UIPickerView {
|
||||
if let toolBar = textField.inputAccessoryView as? UIToolbar,
|
||||
let _ = toolBar.items?.last,
|
||||
let pickerView = textField.inputView as? UIPickerView {
|
||||
|
||||
view.accessibilityElements = [pickerView, toolBar]
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
UIAccessibility.post(notification: .layoutChanged, argument: textField.inputView)
|
||||
}
|
||||
@ -500,11 +546,13 @@ import UIKit
|
||||
}
|
||||
|
||||
open func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
|
||||
|
||||
if textField === selectedField {
|
||||
if UIAccessibility.isVoiceOverRunning {
|
||||
view.accessibilityElements = nil
|
||||
UIAccessibility.post(notification: .layoutChanged, argument: textField)
|
||||
}
|
||||
|
||||
selectedField = nil
|
||||
}
|
||||
}
|
||||
@ -513,7 +561,10 @@ import UIKit
|
||||
selectedField?.resignFirstResponder()
|
||||
}
|
||||
|
||||
// MARK: - UITextViewDelegate (Check if this is still needed)
|
||||
//--------------------------------------------------
|
||||
// MARK: - UITextViewDelegate
|
||||
//--------------------------------------------------
|
||||
|
||||
open func textViewDidBeginEditing(_ textView: UITextView) {
|
||||
selectedField = textView
|
||||
}
|
||||
@ -524,8 +575,11 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Behavior Execution
|
||||
//--------------------------------------------------
|
||||
|
||||
func executeBehaviors<T>(_ behaviorBlock:(_ behavior:T)->Void) {
|
||||
pageModel?.behaviors?.compactMap({ $0 as? T }).forEach({ behaviorBlock($0) })
|
||||
pageModel?.behaviors?.compactMap({ $0 as? T }).forEach { behaviorBlock($0) }
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user