跳到主要内容

iOS 设备上的移动集成

可以使用 WKWebView 组件将文档编辑器嵌入到 iOS 应用程序中。完整的演示项目已发布于 GitHub。

基于 ONLYOFFICE 测试样本的集成​

本示例展示如何将 ONLYOFFICE 移动编辑器与测试或 DMS 样本集成。

iOS 测试样本集成示意图

打开 ONLYOFFICE 编辑器​

  1. 下载并安装ONLYOFFICE 文档企业版或开发者版。

  2. 从 GitHub 下载 iOS 移动演示示例。

  3. 使用 Xcode 打开 EditorWebViewDemo.xcodeproj 项目,修改代码以适应您的DMS系统。

  4. 在 EditorWebViewDemo.xcconfig 配置文件中设置 DOCUMENT_SERVER_EXAMPLE_URL 属性值为 ONLYOFFICE 文档示例页面的地址:

    DOCUMENT_SERVER_EXAMPLE_URL = documentserver

    其中 documentserver 为安装 ONLYOFFICE 文档的服务器名称。

    提示

    还没有文档服务器?注册一个免费的 ONLYOFFICE 云,并使用实例的公共 IP 地址或公共 DNS 名称作为 documentserver。这些信息可以在云控制台的实例部分找到。

    若已指定 DOCUMENT_SERVER_EXAMPLE_URL,则加载 DMS 主页。否则将出现错误提示:

    private func load() {
    if Env.documentServerExampleUrl.replacingOccurrences(of: "https://", with: "").isEmpty {
    showAlert(title: "Error", message: "You must specify the document server example page address for \"DOCUMENT_SERVER_EXAMPLE_URL\" value in configuration file.")
    return
    }

    guard let url = URL(string: Env.documentServerExampleUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "") else {
    return
    }

    webView.load(URLRequest(url: url))
    }
    iOS error iOS managing
  5. 使用 DocumentServerViewController 控制器在 iOS 设备上正确打开编辑器。在该控制器中,定义一个通过 WKWebView 组件打开文档的函数。首先,请求一个绝对 URL 并检查其是否包含 "/editor?" 字符串。如果包含,则在链接中添加一个额外的查询参数(移动平台类型):

    private var openDocumentMarker = "/editor?"
    private var additionalQueryParameters = ["type": "mobile"]

    func webView(_ webView: WKWebView,
    decidePolicyFor navigationAction:
    WKNavigationAction,
    decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
    {
    guard let urlString = navigationAction.request.url?.absoluteString else {
    decisionHandler(.cancel)
    return
    }

    if urlString.contains(openDocumentMarker),
    let redirectUrl = navigationAction.request.url?.appendingQueryParameters(additionalQueryParameters)
    {
    decisionHandler(.cancel)
    navigator.navigate(to: .documentServerEditor(url: redirectUrl))
    } else {
    reloadItem.isEnabled = true
    backItem.isEnabled = webView.canGoBack
    forwardItem.isEnabled = webView.canGoForward

    title = navigationAction.request.url?.host ?? ""

    decisionHandler(.allow)
    }

    }
  6. 在 DocumentServerViewController 控制器中,创建文档管理系统主页上可用的导航操作。例如,在我们的测试示例中,这些操作通过界面元素重新加载、返回和前进按钮来实现。

  7. 为了便于与编辑器进行交互,定义 Activity Indicator 和 Progress View UI 组件。

    DocumentServerViewController 的完整代码可以在此处找到。

    Activity indicator Progress view Buttons
  8. 要在移动设备上通过 WKWebView 组件显示 ONLYOFFICE 编辑器并开始处理文档,请在 DocumentServerEditorViewController 控制器中设置 WKWebView 并布局,如下所示:

    private lazy var webViewConfiguration: WKWebViewConfiguration = {
    let preferences = WKPreferences()
    let dropSharedWorkersScript = WKUserScript(
    source: "delete window.SharedWorker;",
    injectionTime: WKUserScriptInjectionTime.atDocumentStart,
    forMainFrameOnly: false
    )
    preferences.javaScriptEnabled = true
    $0.userContentController.addUserScript(dropSharedWorkersScript)
    $0.preferences = preferences
    return $0
    }(WKWebViewConfiguration())

    private func configureView() {
    webView = WKWebView(frame: .zero, configuration: webViewConfiguration)

    view.addSubview(webView)
    webView.translatesAutoresizingMaskIntoConstraints = false

    webView.navigationDelegate = self
    webView.uiDelegate = self

    if let webViewSuperview = webView.superview {
    webView.topAnchor.constraint(equalTo: webViewSuperview.topAnchor).isActive = true
    webView.leadingAnchor.constraint(equalTo: webViewSuperview.leadingAnchor).isActive = true
    webView.bottomAnchor.constraint(equalTo: webViewSuperview.bottomAnchor).isActive = true
    webView.trailingAnchor.constraint(equalTo: webViewSuperview.trailingAnchor).isActive = true
    }
    }
  9. 在 Xcode 工具栏中,选择一个构建方案和一个运行应用程序的设备。之后,选择产品 -> 运行,或点击项目工具栏中的运行按钮来构建并运行你的代码。

  10. 在应用程序的主页面上,选择 Using DocumentServer 选项,以展示将 ONLYOFFICE 移动网页编辑器与 ONLYOFFICE 测试或 DMS 示例集成的示例。

关闭 ONLYOFFICE 编辑器​

使用 DocumentServerEditorViewController 控制器退出编辑器。当用户导航回 DMS 主页 URL 时,控制器会拦截导航并返回到上一个页面:

func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
{
guard let urlString = navigationAction.request.url?.absoluteString else {
decisionHandler(.cancel)
return
}

if urlString == Env.documentServerExampleUrl {
decisionHandler(.cancel)
navigationController?.popViewController(animated: true)
} else {
decisionHandler(.allow)
}
}
Go back

DocumentServerEditorViewController 的完整代码可以在此处找到。

基于 ONLYOFFICE 文档 API 的集成​

此示例展示如何使用 WKWebView 打开 ONLYOFFICE 编辑器,并通过 API 文档和配置示例中描述的编辑器配置来实现。

通过 api 的 iOS 集成

打开 ONLYOFFICE 编辑器​

  1. 下载并安装 ONLYOFFICE 文档企业版或开发者版。

  2. 从 GitHub 下载 iOS 移动演示示例。

  3. 使用 Xcode 打开 EditorWebViewDemo.xcodeproj 项目,修改代码以适应您的 DMS 系统。

  4. 创建一个空的 .html 文件。演示项目中的 editor.html 资源被用作模板。

  5. 添加如下所示的 <div> 元素:

    <div id="placeholder"></div>
  6. 指定您网站上将使用的 ONLYOFFICE 文档链接及 JavaScript API:

    <script type="text/javascript" src="https://documentserver/web-apps/apps/api/documents/api.js"></script>

    其中 documentserver 是安装了 ONLYOFFICE 文档的服务器的名称。

    提示

    还没有文档服务器?注册一个免费的 ONLYOFFICE 云,并使用实例的公共 IP 地址或公共 DNS 名称作为 documentserver。这些信息可以在云控制台的实例部分找到。

  7. 添加初始化文档编辑器的脚本,用于 <div> 元素,并配置您要打开的文档。定义通过 window.webkit.messageHandlers 将事件转发到原生代码的事件处理函数,并将它们传递给编辑器配置:

    <script type="text/javascript">

    var handler = window.webkit.messageHandlers;

    var onAppReady = function() {
    handler.onAppReady.postMessage({});
    };

    var onDownloadAs = function(event) {
    handler.onDownloadAs.postMessage({fileType: event.data.fileType, url: event.data.url});
    };

    // ... other event handlers ...

    window.docEditor = new DocsAPI.DocEditor("placeholder",
    {
    {external_config},
    "type": "mobile",
    "events": {
    "onAppReady": onAppReady,
    "onDocumentReady": onDocumentReady,
    "onDownloadAs": onDownloadAs,
    "onError": onError,
    "onInfo": onInfo,
    "onRequestClose": onRequestClose,
    "onRequestInsertImage": onRequestInsertImage,
    "onRequestUsers": onRequestUsers,
    "onWarning": onWarning,
    }
    });

    </script>
  8. 要开始在移动设备上处理文档,请通过 WKWebView 组件显示 ONLYOFFICE 编辑器。为此,指定 EditorViewController 控制器。请求 editor.html 文件的 URL,获取其内容,将占位符值替换为 samples.plist 文件中的实际配置(其中所有示例配置均根据 API 文档 Try 页面进行分类),使用 JWT 令牌签名配置,并注入文档服务器 URL:

    private func load() {
    guard let url = Bundle.main.url(forResource: "editor", withExtension: "html") else {
    return
    }

    var html = ""

    do {
    html = try String(contentsOf: url)
    } catch {
    print(error)
    }

    var config = config?
    .replacingOccurrences(of: "{KEY}", with: UUID().uuidString)
    .replacingOccurrences(of: "{DOC_URL_PATH}", with: Env.documentServerFilesUrl)
    .replacingOccurrences(of: "{CALLBACK_URL}", with: Env.editorCallbackUrl)
    .toDictionary() ?? [:]

    config["token"] = JWT.encode(claims: config, algorithm: .hs256(Env.documentServerJwtSecret.data(using: .utf8)!))

    let jsonString = (config.jsonString(prettify: true) ?? "")
    .dropLast()
    .dropFirst()

    html = html
    .replacingOccurrences(of: "{document_server_url}", with: Env.documentServerUrl)
    .replacingOccurrences(of: "{external_config}", with: jsonString)

    webView.loadHTMLString(html, baseURL: nil)
    }
    Editor samples

    EditorViewController 完整代码可在此处找到。

  9. 在 Xcode 工具栏中,选择一个构建方案和一个运行应用程序的设备。然后,选择产品 -> 运行,或点击项目工具栏中的运行按钮来构建并运行你的代码。

  10. 在应用程序的主屏幕上,选择使用 API 配置选项,以展示如何使用 API 文档和配置示例中描述的编辑器配置来打开 ONLYOFFICE 移动网页编辑器。

  11. 在下一页中,选择一个配置示例,以在 WKWebView 组件中打开生成的 HTML。

处理文档​

要处理文档(打开、下载、插入图片、提及其他用户等),请使用 API 文档及其事件和方法:

  1. 为了跟踪事件并调用适当的方法,通过 EditorEventsHandler 控制器在原生代码中处理 ONLYOFFICE 编辑器的事件,然后将它们委托给 EditorViewController:

    var delegate: EditorEventsDelegate?

    convenience init(configuration: WKWebViewConfiguration) {
    self.init()

    configuration.userContentController.add(self, name: EditorEvent.onDownloadAs.rawValue)
    }

    extension EditorEventsHandler: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController,
    didReceive message: WKScriptMessage)
    {
    let event = EditorEvent(rawValue: message.name)

    switch event {
    case .onDownloadAs:
    guard
    let json = message.body as? [String: Any],
    let fileType = json["fileType"] as? String,
    let url = json["url"] as? String
    else { return }

    delegate?.onDownloadAs(fileType: fileType, url: url)
    }
    }
    }

    以 onDownloadAs 事件为例。在 WKWebView 配置期间,通过调用 configuration.userContentController.add(self, name: messageName) 将一个对象注册为特定消息的处理程序。获取事件参数(文件类型和 URL),并将事件处理委托给 EditorViewController:

    func onDownloadAs(fileType: String, url: String) {
    print("⚡ ONLYOFFICE Document Editor create file: \(url)")
    }
  2. 定义 callMethod 函数以从原生代码调用 API 方法。该函数可以接受字符串、布尔值或对象作为参数。它将方法名称及其参数添加到 JavaScript 代码字符串中,然后使用 evaluateJavaScript 方法在 WKWebView 组件中执行 JavaScript:

    private func callMethod(function: String, arg: Bool) {
    let javascript = "window.docEditor.\(function)(\(arg))"
    webView.evaluateJavaScript(javascript, completionHandler: nil)
    }

    private func callMethod(function: String, arg: String) {
    let javascript = "window.docEditor.\(function)(\"\(arg)\")"
    webView.evaluateJavaScript(javascript, completionHandler: nil)
    }

    private func callMethod(function: String, arg: [String: Any]) {
    guard
    let json = try? JSONSerialization.data(withJSONObject: arg, options: []),
    let jsonString = String(data: json, encoding: .utf8)
    else {
    return
    }

    let javascript = "window.docEditor.\(function)(\(jsonString))"
    webView.evaluateJavaScript(javascript, completionHandler: nil)
    }

    EditorEventsHandler 完整代码可在此处找到。

  3. 要显示下载和打印文档的结果,可以使用 PreviewController 控制器。该控制器基于 QLPreviewController。通过文档的 URL 下载文档,并将 dataSource 和 delegate 属性设置为 QLPreviewController:

    func present(url: URL, in parent: UIViewController, complation: @escaping (() -> Void)) {
    download(url: url) { fileUrl in
    DispatchQueue.main.async {
    guard let fileUrl = fileUrl else {
    complation()
    return
    }

    self.fileUrl = fileUrl

    let quickLookController = QLPreviewController()
    quickLookController.dataSource = self
    quickLookController.delegate = self

    if QLPreviewController.canPreview(fileUrl as QLPreviewItem) {
    quickLookController.currentPreviewItemIndex = 0
    parent.present(quickLookController, animated: true, completion: nil)
    }
    complation()
    }
    }
    }

    PreviewController 完整代码可在此处找到。