Skip to content

Add Swift bindings and sample apps#834

Open
tsvvladimir wants to merge 4 commits into
brainflow-dev:masterfrom
tsvvladimir:feature-swift-bindings
Open

Add Swift bindings and sample apps#834
tsvvladimir wants to merge 4 commits into
brainflow-dev:masterfrom
tsvvladimir:feature-swift-bindings

Conversation

@tsvvladimir
Copy link
Copy Markdown

@tsvvladimir tsvvladimir commented May 18, 2026

Summary

  • Add a Swift Package Manager package with Swift bindings for BoardShim, DataFilter, MLModel, BrainFlow params, errors, enums, and runtime native-library loading.
  • Add Swift tests and examples modeled after existing BrainFlow binding examples, including synthetic board data, markers, file IO, downsampling, transforms, filtering, denoising, band powers, ICA, and MLModel prediction.
  • Add Swift CLI, macOS SwiftUI demo, iOS/macOS sample app assets under swift_package/examples/apps, App Store readiness notes, docs, and macOS CI coverage for Swift build/test/CLI/examples.

Verification

  • python3 tools/build.py --clear-build-dir --num-jobs 4 --no-synchroni --no-bluetooth --no-ble --no-tests --cmake-osx-architectures arm64
  • env BRAINFLOW_LIB_DIR=../installed/lib swift build
  • env BRAINFLOW_LIB_DIR=../installed/lib swift test
  • all Swift example products with env BRAINFLOW_LIB_DIR=../installed/lib swift run <example>
  • env BRAINFLOW_LIB_DIR=../installed/lib swift run brainflow-swift-cli
  • xcodebuild -quiet -project swift_package/examples/apps/ios/BrainFlowiOSDemo/BrainFlowiOSDemo.xcodeproj -scheme BrainFlowiOSDemo -configuration Debug -destination id=22FB561A-9754-45E2-92CF-D16F1F84FAC4 -derivedDataPath /private/tmp/brainflow-ios-derived-review build
  • iOS simulator autorun on iPhone 17 Pro reported Rows: 32, Samples: 533 and rendered EEG plot
  • make html SPHINXBUILD=/private/tmp/brainflow-docs-venv-20260518/bin/sphinx-build
  • git diff --check
  • macOS SwiftUI demo launched with synthetic board and reported Rows: 32, Samples: 521

Notes

  • Swift package loading uses dlopen and does not vendor native binaries; native BrainFlow libraries must be built separately and placed in BRAINFLOW_LIB_DIR, system library paths, installed/lib, or an app bundle resource/framework directory.
  • iOS/App Store runtime support requires target-specific BrainFlow native libraries or XCFrameworks embedded and signed in the app bundle.
  • App Store submission still needs production bundle IDs, signing/provisioning, screenshots, icons, and App Store Connect records.

Copy link
Copy Markdown
Member

@Andrey1994 Andrey1994 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrote some comments, but looks good overall, main concern is about packaging

if: (matrix.os == 'macos-14')
run: |
cd $GITHUB_WORKSPACE/swift_package
BRAINFLOW_LIB_DIR=$GITHUB_WORKSPACE/installed/lib swift run brainflow-swift-cli
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add all examples to CI as in brainflow dosc https://brainflow.readthedocs.io/en/stable/Examples.html#python

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c030c76. I added all documented Swift examples as SwiftPM executable products and added a macOS CI step that runs them all with BRAINFLOW_LIB_DIR=$GITHUB_WORKSPACE/installed/lib swift run <example>.

Comment thread docs/requirements.txt Outdated
@@ -1,4 +1,9 @@
sphinx==4.0.2
sphinxcontrib-applehelp==1.0.2
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it needed? doesnt look relevant to the binding


stopStream()
readData()
let rows = rowCount
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for demo app for ias lets add a plot for eeg channels, also keep it under swift_package folder, dont add it to the root folder.
So folder structure will be like:

  • swift_package
    - brainflow
    - examples


private func startStream() {
do {
let board = try BoardShim(board_id: BoardIds.SYNTHETIC_BOARD)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it possible to use non synthetic board, devices we care about are Muse boards(no BLED dongle but native BLE boards should work)

@@ -0,0 +1,44 @@
# BrainFlow iOS Demo

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dont create folders like samples in the root folder. Instructions to build and use the binding should be in Docs

import BrainFlow

let data = Array(0..<256).map { sin(Double($0) / 10.0) }
let psd = try DataFilter.get_psd(data: data, start_pos: 0, end_pos: data.count, sampling_rate: 250, window: WindowOperations.HANNING.rawValue)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dont use synathetic data like this, get it from synthetic board instead. Check how code samples referenced from docs are structured and make it the same way for consistency. Update docs to include swift binding code samples

@@ -0,0 +1,13 @@
import BrainFlow

var data = Array(0..<256).map { sin(Double($0) / 10.0) }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here and for all other examples

@@ -0,0 +1,5 @@
import BrainFlow

let data = Array(0..<256).map(Double.init)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

init(names: [String]) throws {
var errors = [String]()
for path in Self.candidatePaths(for: names) {
if let handle = dlopen(path, Self.openFlags) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its good, I like dlopen approach like in other bindings, but how does packaging work? native libs should be installed and compiled separately? Did you find a way to add them to the package like we do in jar and whl? How will it work for ios and publishing to appstore?

Copy link
Copy Markdown
Member

Addressed the review feedback in c030c76:

  • Removed the unrelated docs/requirements.txt dependency additions.
  • Moved iOS/macOS sample app files from root samples/ into swift_package/examples/apps/... and updated docs accordingly.
  • Added all documented Swift examples as SwiftPM executable products and added a macOS CI step to run them all.
  • Reworked Swift signal-processing examples to read real data from BoardShim synthetic board instead of local generated arrays.
  • Added shared Swift example support for synthetic-board reads.
  • Updated docs to include Swift example run instructions and native-library packaging behavior.
  • Expanded the iOS demo with Muse/native BLE board selection fields and a live EEG channel plot from BrainFlow data.
  • Clarified iOS/App Store packaging: Swift package does not vendor native binaries; apps must embed/sign target-specific libBoardController, libDataHandler, and libMLModule libraries or XCFrameworks.

Local verification:

  • env BRAINFLOW_LIB_DIR=../installed/lib swift build
  • env BRAINFLOW_LIB_DIR=../installed/lib swift test
  • all Swift example products via swift run
  • env BRAINFLOW_LIB_DIR=../installed/lib swift run brainflow-swift-cli
  • iOS Xcode simulator build and autorun on iPhone 17 Pro simulator, showing 32 rows / 533 samples and EEG plot
  • docs build with make html SPHINXBUILD=/private/tmp/brainflow-docs-venv-20260518/bin/sphinx-build
  • git diff --check

@tsvvladimir
Copy link
Copy Markdown
Author

Clarification: the previous review-response comment was accidentally posted through a GitHub connector authenticated as Andrey1994. This follow-up is posted from tsvvladimir. The branch and commits are from tsvvladimir; the review fixes are in c030c762 on feature-swift-bindings. Summary: Swift examples were added to CI, app samples were moved under swift_package/examples/apps, synthetic generated arrays were replaced with synthetic-board reads, the iOS demo now has Muse/native BLE options plus an EEG plot, unrelated docs dependency changes were removed, and packaging/App Store notes were clarified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants