[3]: VEditorNode - GeekTree0101/VEditorKit GitHub Wiki
Case 1: Texture(AsyncDisplayKit)
class VC: ASViewController<VEditorNode> {
init() {
super.init(node: .init(editorRule: Rule(), controlAreaNode: node))
}
Case 2: UIKit
class VC: UIViewController {
lazy var node = VEditorNode.init(editorRule: Rule(), controlAreaNode: node)
override func viewDidLoad() {
super.viewDidLoad()
node.view.snp <--- SnapKit or constraints else
}
}
// MARK: VEditotKit EditorNodeDelegate
public protocol VEditorNodeDelegate: class {
func getRegisterTypingControls() -> [VEditorTypingControlNode]?
func dismissKeyboardNode() -> ASControlNode?
func placeholderCellNode(_ content: VEditorPlaceholderContent,
indexPath: IndexPath) -> VEditorMediaPlaceholderNode?
func contentCellNode(_ content: VEditorContent,
indexPath: IndexPath) -> ASCellNode?
}
- getRegisterTypingControls: You have to return Array of VEditorTypingControlNode subclass or class
VEditorTypingControlNode의 subclass또는 객체의 버튼들을 반환합니다.
- dismissKeyboardNode: Keyboard dismiss controlNode
키보드를 Dismiss하는 버튼을 반환합니다.
- placeholderCellNode: return placeholderNode (VEditorMediaPlaceholderNode subclass)
서버단에서 네트워크콜이 필요한 Content에 대한 Placeholder를 반환합니다. 서버호출 성공 및 실패시 내부적으로 교체 및 삭제됩니다.
- contentCellNode: return content cell object such as attributedString, image, video etc
AttributedString, Image, Video 등등의 Cell을 반환합니다.
extension VC: VEditorNodeDelegate {
func getRegisterTypingControls() -> [VEditorTypingControlNode]? {
return controlAreaNode.typingControlNodes
}
func dismissKeyboardNode() -> ASControlNode? {
return controlAreaNode.dismissNode
}
func placeholderCellNode(_ content: VEditorPlaceholderContent, indexPath: IndexPath) -> VEditorMediaPlaceholderNode? {
guard let xml = EditorRule.XML.init(rawValue: content.xmlTag) else { return nil }
switch xml {
case .article:
guard let url = content.model as? URL else { return nil }
return EditorOpenGraphPlaceholder(xmlTag: EditorRule.XML.opengraph.rawValue,
url: url)
default:
break
}
return nil
}
func contentCellNode(_ content: VEditorContent, indexPath: IndexPath) -> ASCellNode? {
switch content {
case let text as NSAttributedString:
return VEditorTextCellNode(isEdit: isEditMode)
case let imageNode as VImageContent:
return VEditorImageNode(isEdit: isEditMode)
case let videoNode as VVideoContent:
return VEditorVideoNode(isEdit: isEditMode)
case let ogObjectNode as VOpenGraphContent:
return VEditorOpenGraphNode(isEdit: isEditMode)
default:
return nil
}
}
}
placholder example screenshot
public enum MediaAppendScope {
case automatic
case last
case first
case insert(IndexPath)
}
You don't need IndexPath calculate, just put MediaAppendScope
IndexPath를 신경쓰지않고 원하는 MediaAppendScope값만 넣으면 MediaContent가 알아서 정확한 위치에 들어갑니다. More see about media content
- automatic: will append at last or insert onto ActiveTextView cursor location
마지막에 붙거나, ActiveTextView가 있으면 cursor의 location에 삽입됩니다.
- last: append
- first: insert at zero
- insert: Customized IndexPath Insertion
open func fetchNewContent(_ content: VEditorContent,
scope: MeidaAppendScope,
section: Int = 0,
scrollPosition: UITableView.ScrollPosition = .bottom,
animated: Bool = true) {
}
open func fetchNewContents(_ contents: [VEditorContent],
scope: MeidaAppendScope,
section: Int = 0,
scrollPosition: UITableView.ScrollPosition = .bottom,
animated: Bool = true) {
}
You can get first responder UITextView cell
let node = VEditorNode.init(...)
let cell = node.loadActiveTextCellNode()
You can insert url on activeTextView selectedRange
활성화된 텍스트뷰의 선택된 영역에 URL를 삽입합니다.
Will become first responder with resign before TextView
이전에 활성화된 텍스트뷰를 비활성화시키고 자동으로 새로운 텍스트뷰를 활성화시킵니다.
Resign before activeTextNode
활성화된 텍스트뷰를 비활성화시킵니다.
Parse XMLString with render Editor UI
XMLString을 파싱하고 Editor UI를 랜더링합니다.
Synchronize all of contents
에디터에 기록된 모든 속성과 Contents를 동기화합니다.
Building XMLString from Editor Contents with EditorRule. you can make capsuled xmlString with packageTag 에디터의 모든 컨텐츠를 룰에 따라서 XMLString으로 빌드합니다. 또한 packageTag를 정의해서 캡슐화할 수 있습니다.
let node: VEditorNode = ....
// STEP 1: synchronize contents
self.node.synchronizeFetchContents { [weak self] () in
// STEP 2: build XML
guard let output = self?.node.buildXML(packageTag: "content") else {
return
}
let vc = XMLViewController.init(output)
self?.navigationController?.pushViewController(vc, animated: true)
}