# SumSheet view-SDK for iOS

Open and display `.xlsx` / `.xlsm` workbooks inside your own iOS app, computed
by the same engine and drawn by the same page that ship in SumSheet on the
App Store (version 2026.3.32, build 10). The workbook is opened and
recalculated by a native Rust core (`FastSheetMobileCore.xcframework`); the
grid, charts and ribbon are a `WKWebView` page bundled with the SDK. No
server, no network.

iOS 16+, device (arm64) and simulator slices. The page is the same editor
SumSheet ships. The SDK carries the same release number as the App Store build
and is released together with it.

## What is in the box

| Path | What |
|---|---|
| `FastSheetMobileCore.xcframework/` | the spreadsheet core (device + simulator), C header and module map inside |
| `assets/f1/` | the page: `index.html`, `zagruzka.mobile.js`, `preload.mobile.js`, `main.mobile.js` |
| `assets/sample.xlsx` | a small workbook to prove the integration |
| `bridge/SumSheetBridge.swift` | routes page letters to the core, files, clipboard, pickers (`import FastSheetMobileCore`) |
| `example/EditorWebView.swift` | reference host view: `OpenBook`, boot script, message handler `f1`, load |
| `example/project.yml` | xcodegen spec of the smallest host (what this README was verified with) |
| `VERSION` | version, build, date, checksums |

## Steps 1-2-3

### 1. Add to your app

- Drag `FastSheetMobileCore.xcframework` into the target (Frameworks, Libraries →
  *Do Not Embed*; it is a static framework). Xcode picks up the C header and the
  module map from the xcframework's `Headers/`, so `import FastSheetMobileCore`
  works without a bridging header or `HEADER_SEARCH_PATHS`.
- Add `bridge/SumSheetBridge.swift` to the target.
- Add the `assets/f1` folder as a **folder reference** (blue folder), so the
  page keeps its `f1/…` path inside the app bundle; add `assets/sample.xlsx` as
  a resource.
- Add `example/EditorWebView.swift` to the target. It is self-contained: the
  `OpenBook` value it takes (name + base64), the boot script, the `f1` message
  handler and the bridge wiring.
- The xcframework has arm64 slices only. On an Intel Mac, or if the simulator
  destination is "Rosetta", set `EXCLUDED_ARCHS[sdk=iphonesimulator*] = x86_64`.

With [xcodegen](https://github.com/yonaskolb/XcodeGen) the whole step is
`example/project.yml` (lay the SDK out as the comment at its top says and run
`xcodegen generate`).

### 2. Create the WebView

`example/EditorWebView.swift` is the reference; the essentials:

```swift
let controller = WKUserContentController()
controller.add(coordinator, name: "f1")                 // the bridge door
controller.addUserScript(WKUserScript(source: """
  window.ReactNativeWebView = { postMessage: function (m) {
    window.webkit.messageHandlers.f1.postMessage(m); } };
  window.__F1_КНИГА__ = {"имя": "\(name)", "base64": "\(base64)"};
  window.__F1_MOBILE_BRIDGE_READY__ = true;
  """, injectionTime: .atDocumentStart, forMainFrameOnly: true))
let config = WKWebViewConfiguration(); config.userContentController = controller
let webView = WKWebView(frame: .zero, configuration: config)
let page = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "f1")!
webView.loadFileURL(page, allowingReadAccessTo: page.deletingLastPathComponent())
```

The coordinator hands every message to `SumSheetBridge().handle(text) { reply in … }`
and delivers the reply with `window.__F1_MOBILE_RECEIVE__(reply)`. Keep the
bridge alive as long as the web view lives (it owns the core hosts and frees
them in `deinit`).

### 3. Open a workbook

The page takes the workbook as `{имя, base64}`, so any source works: the
bundled sample (`Bundle.main.url(forResource: "sample", withExtension: "xlsx")`),
a file from the Files picker (`.fileImporter`, security-scoped URL → `Data`),
or a file handed to your app via "Open in…" (`onOpenURL`).

The smallest host is one screen with a button:

```swift
struct RootView: View {
  @State private var book: OpenBook?
  var body: some View {
    if let book {
      EditorWebView(book: book).ignoresSafeArea(edges: .bottom)
    } else {
      Button("Open sample") {
        let url = Bundle.main.url(forResource: "sample", withExtension: "xlsx")!
        book = OpenBook(name: "sample.xlsx", data: try! Data(contentsOf: url))
      }
      .onOpenURL { url in                        // "Open in…" from Files, Mail, …
        let scoped = url.startAccessingSecurityScopedResource()
        defer { if scoped { url.stopAccessingSecurityScopedResource() } }
        if let data = try? Data(contentsOf: url) { book = OpenBook(name: url.lastPathComponent, data: data) }
      }
    }
  }
}
```

To be offered in "Open in…" declare the type in `Info.plist`
(`CFBundleDocumentTypes` with `LSItemContentTypes` =
`org.openxmlformats.spreadsheetml.sheet`; `example/project.yml` has it).

"Save" inside the page writes into the app's Documents directory through the
bridge (`fs.*` kinds); with `UIFileSharingEnabled` the saved workbook is
visible in Files.

## Host contract (what the page expects from you)

Defined in the repository as `apps/desktop-shell/mobile/ДОГОВОР-МОСТА.md`:

- `window.ReactNativeWebView.postMessage(text)` → `webkit.messageHandlers.f1`;
  the page sends `{"id":n,"kind":"<kind>","payload":{…}}`, the bridge answers
  via `window.__F1_MOBILE_RECEIVE__(json)`.
- `window.__F1_КНИГА__` — `{имя, base64}` of the workbook; set before the page runs.
- `window.__F1_MOBILE_BRIDGE_READY__ = true` — the page waits for it before talking to the core.
- UI language follows the device language; the user's choice made in the page
  is kept in the web view's storage.

## Known limits

- iOS 16+; the xcframework carries arm64 device and simulator slices only.
- The core is large (the static library is hundreds of MB; the linked Release
  binary grows by roughly 50 MB, the page adds 35 MB).
- The page is the full editor, not a lightweight viewer.
- Macros (`.xlsm`) open with formulas recalculated; VBA does not run.

## Verified

Empty SwiftUI host built with xcodebuild from `example/project.yml`, this
xcframework, bridge, page and sample, no other code: the sample workbook opened
with grid, ribbon and sheet tabs on the iPhone simulator and on a device (see
the release notes on sumoffice.com/developers for the numbers of this release).

## Terms

Free to evaluate and to build integration prototypes. Licensing for
production use and support: contact us via sumoffice.com.
