我有一个问题。
我在下面的代码中收到错误消息:"无法转换值类型' Node'预期的参数类型' UIViewController' 如何解决这个问题?
文档视图控制器的代码如下:
import UIKit
import WebKit
import AEXML
import STPopup
import Kanna
import DropDownMenuKit
import Toaster
typealias DocumentOpenAction = (_ node: Node) -> ()
class DocumentViewController: BaseViewController {
var currentNode:Node! {
didSet {
if popupController == nil {
navigationItem.titleView = UILabel.forTitleView(withText: currentNode.title)
if titleView != nil {
navigationItem.titleView = titleView
}
} else {
navigationItem.titleView = UILabel.forTitleView(withText: currentNode.title)
}
}
}
//ausgegebene HTML's
var sections:[[String:String]] = []
var changeMarksVisible:Bool? {
didSet {
self.updateChangeMarking()
}
}
var nightModeOn:Bool? {
didSet {
self.updateNightMode()
}
}
var readAccessFolder:URL?
lazy var statusBarHeight: CGFloat = {
let statusBarSize = UIApplication.shared.statusBarFrame.size
return min(statusBarSize.width, statusBarSize.height)
}()
//
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(DocumentViewController.taskGotDeleted(withNotification:)), name: PackageManager.shared.tasksDeletedNotification, object: nil)
contentSizeInPopup = CGSize(width: 600, height: 500)
landscapeContentSizeInPopup = CGSize(width: 600, height: 500)
changeMarksVisible = UserDefaults.standard.bool(forKey: "ChangeMarkings")
nightModeOn = UserDefaults.standard.bool(forKey: "nightTheme")
if popupController == nil {
PackageManager.shared.setCurrentNodeAndAddToHistory(currentNode)
setupNavBar()
// create the drop down menu
createDropDownMenu()
//
jumpToGraphicsViewButton.addTarget(self, action: #selector(DocumentViewController.showGraphicsView), for: .touchUpInside)
jumpToGraphicsViewButtonLeadingConstraint.constant = 8.0
jumpToGraphicsViewButtonWidthConstraint.constant = 48.0
jumpToGraphicsViewButton.isEnabled = false
jumpToGraphicsViewButton.isHidden = false
} else {
setupNavBarForPreview()
//
jumpToGraphicsViewButton.isHidden = true
jumpToGraphicsViewButtonLeadingConstraint.constant = 0.0
jumpToGraphicsViewButtonWidthConstraint.constant = 0.0
}
// webview
setupWebview()
// process html of current node
splitHTML(forCurrentNode: currentNode)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
PackageManager.shared.currentDisplayedModuleNode = currentNode
navigationBarMenu?.container = view
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (ctx) in
self.show3dModelButtonLeadConstraint?.constant = self.view.frame.width - 50
self.show3dModelButton?.updateConstraintsIfNeeded()
self.webview?.scrollView.updateConstraintsIfNeeded()
// If we put this only in -viewDidLayoutSubviews, menu animation is
// messed up when selecting an item
self.updateMenuContentOffsets()
}) { (ctx) in
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
URLCache.shared.removeAllCachedResponses()
}
deinit {
NotificationCenter.default.removeObserver(self)
webview?.scrollView.delegate = nil
}
func showListOfContent(_ sender: AnyObject) {
_ = navigationController?.popViewController(animated: true)
}
}
// MARK: - UI
extension DocumentViewController {
func setupWebview() {
//Content Controller object
let controller = WKUserContentController()
//Add message handler reference
controller.add(self, name: "shoppingcart")
//Create configuration
let configuration = WKWebViewConfiguration()
configuration.userContentController = controller
var f = webViewView.frame
f.origin.y = 0
webview = WKWebView(frame: f, configuration: configuration)
webview?.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
webview?.backgroundColor = .white
webview?.scrollView.bounces = true
webview?.scrollView.delegate = self
webview?.navigationDelegate = self
webview?.uiDelegate = self
webViewView.addSubview(webview!)
webview?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
func setupNavBar() {
//loads nav bar if not presented in popup
settingsButton = UIBarButtonItem(image: UIImage(named: "Settings"), style: .plain, target: self, action: #selector(DocumentViewController.showSettings(_:)))
navigationItem.rightBarButtonItems = [noticeButton,settingsButton]
listOfContentButton = UIBarButtonItem(image: UIImage(named: "List"), style: .plain, target: self, action: #selector(DocumentViewController.showListOfContent(_:)))
shoppingCartButton = UIBarButtonItem(image: UIImage(named: "Checkout"), style: .plain, target: self, action: #selector(DocumentViewController.shoppingCartButtonPressed(_:)))
taskListButton = ZABarButtonItem(image: UIImage(named: "TaskList"), style: .plain, target: self, action: #selector(DocumentViewController.taskListButtonPressed(_:)))
taskListButton.isSelected = PackageManager.shared.nodeIsInTasks(currentNode)
taskListButton.tintColor = taskListButton.isSelected ? navigationController?.navigationBar.tintColor : .lightGray
favoritesButton = ZABarButtonItem(image: UIImage(named: "Star"), style: .plain, target: self, action: #selector(DocumentViewController.favoritesButtonPressed(_:)))
favoritesButton.isSelected = PackageManager.shared.nodeIsInFavorites(currentNode)
let img = favoritesButton.isSelected ? UIImage(named: "StarFilled"): UIImage(named: "Star")
favoritesButton.image = img
backToManualStructure = UIBarButtonItem(image: UIImage(named: "List"), style: .plain, target: self, action: #selector(DocumentViewController.structureButtonPressed(_:)))
var items:[UIBarButtonItem] = [backToManualStructure,shoppingCartButton, favoritesButton]
if currentNode.canBeAddedToTasks() {
items.append(taskListButton)
}
navigationItem.leftBarButtonItems = items
}
func setupNavBarForPreview() {
//loads nav bar if presented in popup
closeButton = UIBarButtonItem(title: NSLocalizedString("Close", tableName: "Localizable", bundle: Bundle.main, value: "", comment: ""), style: .plain, target: self, action: #selector(DocumentViewController.cancel))
navigationItem.leftBarButtonItems = [closeButton]
navigationItem.leftItemsSupplementBackButton = false
openButton = UIBarButtonItem(title: NSLocalizedString("Open in new tab", tableName: "Localizable", bundle: Bundle.main, value: "", comment: ""), style: .plain, target: self, action: #selector(DocumentViewController.openDocument))
navigationItem.rightBarButtonItems = [openButton]
}
}
// MARK: - DropDownMenu
extension DocumentViewController {
func createDropDownMenu() {
// create the drop down menu
let title = prepareNavigationBarMenuTitleView()
prepareNavigationBarMenu(title)
updateMenuContentOffsets()
}
func prepareNavigationBarMenuTitleView() -> String {
// Both title label and image view are fixed horizontally inside title
// view, UIKit is responsible to center title view in the navigation bar.
// We want to ensure the space between title and image remains constant,
// even when title view is moved to remain centered (but never resized).
titleView = DropDownTitleView(frame: CGRect(x: 0, y: 0, width: 150, height: 40))
titleView.addTarget(self,
action: #selector(DocumentViewController.willToggleNavigationBarMenu(_:)),
for: .touchUpInside)
titleView.addTarget(self,
action: #selector(DocumentViewController.didToggleNavigationBarMenu(_:)),
for: .valueChanged)
titleView.titleLabel.textColor = UIColor.black
titleView.title = currentNode.title
navigationItem.titleView = titleView
return titleView.title!
}
func prepareNavigationBarMenu(_ currentChoice: String) {
navigationBarMenu = DropDownMenu(frame: view.bounds)
navigationBarMenu?.delegate = self
var cells:[DropDownMenuCell] = []
for (index, doc) in PackageManager.shared.openNodes.enumerated() {
let cell = DropDownMenuCell()
cell.textLabel!.text = doc.title
cell.tag = index
cell.menuAction = #selector(DocumentViewController.choose(_:))
cell.menuTarget = self
if currentChoice == doc.title {
cell.accessoryType = .checkmark
}
cells.append(cell)
}
navigationBarMenu?.menuCells = cells
// If we set the container to the controller view, the value must be set
// on the hidden content offset (not the visible one)
navigationBarMenu?.visibleContentOffset = (navigationController?.navigationBar.frame.size.height ?? 44.0) + statusBarHeight
// For a simple gray overlay in background
navigationBarMenu?.backgroundView = UIView(frame: view.bounds)
navigationBarMenu?.backgroundView!.backgroundColor = UIColor.black
navigationBarMenu?.backgroundAlpha = 0.7
}
func updateMenuContentOffsets() {
navigationBarMenu?.visibleContentOffset = (navigationController?.navigationBar.frame.size.height ?? 44.0) + statusBarHeight
}
@IBAction func choose(_ sender: AnyObject) {
let cell = (sender as! DropDownMenuCell)
titleView.title = cell.textLabel!.text
let index = cell.tag
let node = PackageManager.shared.openNodes[index]
if node != currentNode {
initalSegment = 0
currentNode = node
setupNavBar()
splitHTML(forCurrentNode: currentNode)
}
if let menu = navigationBarMenu {
didTapInDropDownMenuBackground(menu)
}
}
@IBAction func willToggleNavigationBarMenu(_ sender: DropDownTitleView) {
sender.isUp ? navigationBarMenu?.hide() : navigationBarMenu?.show()
}
@IBAction func didToggleNavigationBarMenu(_ sender: DropDownTitleView) {
}
}
// MARK: - DropDownMenuDelegate
extension DocumentViewController : DropDownMenuDelegate {
func didTapInDropDownMenuBackground(_ menu: DropDownMenu) {
if menu == navigationBarMenu {
titleView.toggleMenu()
}
else {
menu.hide()
}
}
}
// MARK: - data module
extension DocumentViewController {
func splitHTML(forCurrentNode node:Node) {
node.deleteTemporaryHtmls()
if let nodePath = node.path {
let pathComponents = URL(fileURLWithPath: nodePath).pathComponents
if pathComponents.count >= 2 {
let rootFolder = "\(pathComponents[1])"
readAccessFolder = URL(fileURLWithPath: "\(PackageManager.shared.packageFolder)\(rootFolder)")
}
}
// segmented control
segmentedControl.removeAllSegments()
// process html of current node
do {
sections = try node.processHTMLSections()
if sections.count > 0 {
var index = 0
for sec in sections {
segmentedControl.insertSegment(withTitle: sec["title"], at: index, animated: false)
index += 1
}
//
let hasWCN = sections.first(where: { (sec) -> Bool in
return sec["contenttype"] == "safety"
})
if let _ = hasWCN {
} else {
let index = sections.index(where: { (sec) -> Bool in
return sec["contenttype"] == "container"
})
if let i = index {
initalSegment = i
}
}
//
if initalSegment > 5 {
initalSegment = 0
loadHTML(forSection: initalSegment)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
self.show3DModel(self.show3dModelButton as Any)
})
}
else {
if initalSegment > sections.count {
initalSegment = 0
}
loadHTML(forSection: initalSegment)
}
segmentedControl.selectedSegmentIndex = initalSegment
// configure show 3d model button
let button = UIButton(forAutoLayout: ())
button.imageView?.contentMode = .scaleAspectFit
button.imageView?.tintColor = .gray
button.setImage(UIImage(named: "Next"), for: .normal)
button.backgroundColor = UIColor.lightGray.withAlphaComponent(0.3)
button.borderColor = .black
button.borderWidth = 1.0
button.addTarget(self, action: #selector(DocumentViewController.show3DModel(_:)), for: .touchUpInside)
webViewView.addSubview(button)
button.autoAlignAxis(.horizontal, toSameAxisOf: webViewView)
button.autoSetDimension(.height, toSize: 150.0)
button.autoSetDimension(.width, toSize: 50.0)
show3dModelButtonLeadConstraint = button.autoPinEdge(.trailing, to: .trailing, of: webViewView, withOffset: 0)
show3dModelButton = button
// we dont need the button any longer
show3dModelButton?.isHidden = true
}
} catch {
loadPDF()
segmentedControlHeight.constant = 0
segmentedControlMarginTop.constant = 0
segmentedControlMarginBottom.constant = 0
}
if let dmc = node.moduleCode {
dmcLabel.text = dmc
}
if let issno = node.issueNumber {
issnoLabel.text = issno
}
if let issdate = node.issueDate {
issdateLabel.text = DateFormatter.stringFromDate(issdate, format: "yyyy-MM-dd")
}
let edgePan = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(returnToGraphicView))
edgePan.edges = .right
view.addGestureRecognizer(edgePan)
}
func loadHTML(forSection section: Int) {
URLCache.shared.removeAllCachedResponses()
URLCache.shared.diskCapacity = 0
URLCache.shared.memoryCapacity = 0
if section > sections.count {
return
}
if webview?.isLoading == true {
webview?.stopLoading()
}
if let urlString = sections[section]["url"], let contenttype = sections[section]["contenttype"], let readAccessFolder = readAccessFolder {
var url = URL(fileURLWithPath: urlString)
if var components = URLComponents(url: url, resolvingAgainstBaseURL: false), contenttype == "requirements" {
let sc = URLQueryItem(name: "shoppingcart", value: "true")
let domain = URLQueryItem(name: "domain", value: "*")
components.queryItems = [sc, domain]
if let newUrl = components.url {
url = newUrl
}
}
_ = webview?.loadFileURL(url, allowingReadAccessTo: readAccessFolder)
}
}
func loadPDF() {
URLCache.shared.removeAllCachedResponses()
URLCache.shared.diskCapacity = 0
URLCache.shared.memoryCapacity = 0
if webview?.isLoading == true {
webview?.stopLoading()
}
let fileStr = "\(PackageManager.shared.packageFolder)\(currentNode.path ?? "")"
let url = URL(fileURLWithPath: fileStr)
let request = URLRequest(url: url)
if let readAccessFolder = readAccessFolder {
_ = webview?.loadFileURL(url, allowingReadAccessTo: readAccessFolder)
} else {
_ = webview?.load(request)
}
}
}
// MARK: - Illustrations
extension DocumentViewController {
func showFullscreenFigure(with boardNo: String, and components: URLComponents?) {
if let gv = self.storyboard?.instantiateViewController(withIdentifier: "GraphicsViewController") as? GraphicsViewController {
gv.url = URL(fileURLWithPath: "\(PackageManager.shared.packageFolder)\(currentNode.path ?? "").\(boardNo).$tmp.htm")
gv.caption = components?.queryItems?.filter({ (item) in item.name == "caption"}).first?.value
gv.javascript = components?.queryItems?.filter({ (item) in item.name == "javascript"}).first?.value
gv.readAccessFolder = readAccessFolder
graphicsView = gv
}
if popupController != nil {
popupController?.push(graphicsView!, animated: true)
} else {
navigationController?.pushViewController(graphicsView!, animated: true)
}
}
func showGraphicsView() {
if let graphicsView = graphicsView {
if popupController != nil {
popupController?.push(graphicsView, animated: true)
} else {
navigationController?.pushViewController(graphicsView, animated: true)
}
}
}
func returnToGraphicView(_ recognizer: UIScreenEdgePanGestureRecognizer) {
if recognizer.state == .recognized {
showGraphicsView()
}
}
}
// MARK: - Preview
extension DocumentViewController {
func cancel() {
onClose?()
}
func openDocument() {
onOpen?(currentNode)
}
func showPreview(for node:Node) {
let onOpen:DocumentOpenAction = { node in
self.currentNode = node
PackageManager.shared.setCurrentNodeAndAddToHistory(self.currentNode)
self.initalSegment = 0
self.splitHTML(forCurrentNode: self.currentNode)
self.createDropDownMenu()
}
let contentView = self.storyboard?.instantiateViewController(withIdentifier: "DocumentViewController") as! DocumentViewController
contentView.initalSegment = 0
contentView.currentNode = node
//
if popupController != nil {
contentView.onOpen = self.onOpen
contentView.onClose = self.onClose
self.popupController?.push(contentView, animated: true)
} else {
let popup = STPopupController(rootViewController: contentView)
popup.style = .formSheet
popup.hidesCloseButton = false
popup.backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
popup.containerView.layer.cornerRadius = 4
contentView.onOpen = { node in
popup.dismiss(completion: {
onOpen(node)
})
}
contentView.onClose = {
popup.dismiss(completion: {
// we dont need to split the html again for now
// self.splitHTML(forCurrentNode: self.currentNode)
})
}
popup.present(in: self, completion: nil)
}
contentView.navigationItem.titleView = UILabel.forTitleView(withText: node.title)
}
func showProcedureStepCheckboxes() {
if popupController == nil {
self.webview?.evaluateJavaScript("showProcedureStepCheckboxes()", completionHandler: {(result, error) in
guard let err = error else {return}
print(err)
})
}
}
func setLastScrollingPosition() {
if let code = currentNode.contentobjectcode {
webview?.restoreContentOffset(forKey: code)
}
}
}
// MARK: - Settings
extension DocumentViewController {
func showSettings(_ sender: AnyObject) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SetSettingsViewController") as! SetSettingsViewController
vc.modalPresentationStyle = .popover
vc.onChange = {
self.changeMarksVisible = (UserDefaults.standard.bool(forKey: "ChangeMarkings"))
self.nightModeOn = (UserDefaults.standard.bool(forKey: "nightTheme"))
}
if let popover = vc.popoverPresentationController {
popover.barButtonItem = settingsButton
popover.permittedArrowDirections = .any
}
present(vc, animated: true, completion: nil)
}
func updateChangeMarking() {
if (self.changeMarksVisible ?? false) {
self.webview?.evaluateJavaScript("handleChangemarks()", completionHandler: {(result, error) in
})
}
else {
self.webview?.evaluateJavaScript("deleteChangemarks()", completionHandler: {(result, error) in
})
}
}
func updateNightMode() {
let mode = self.nightModeOn ?? false
self.webview?.evaluateJavaScript("s1000d.setNightMode(\(mode))", completionHandler: {(result, error) in
})
}
}
// Mark: - Structure Manual
extension DocumentViewController {
func structureButtonPressed(_ sender: AnyObject) {
PackageManager.shared.structureButtonPressed(currentNode)
if let root = self.parent?.parent as? RootTabBarViewController {
root.selectedIndex = 0
if let navController = root.viewControllers?.first as? UINavigationController, let firstController = navController.viewControllers.first as? ManualsViewController {
PackageManager.shared.strucutreArrayNode.removeLast()
for var i in PackageManager.shared.strucutreArrayNode {
print("\(i.title)")
// get next child node
if let next = i.nextChild() {
i = next
}
if i.type == "document" || i.subnodes.count == 0 {
firstController.showDocumentViewController(for: i)
} else {
firstController.navigationController?.pushViewController(i, animated: false)
}
}
}
}
}
}