iOS应用中Readium与Sony URMS SDK的集成及同步问题咨询
Hey there! I’ve worked on a few ebook projects integrating Readium and user sync systems before, so let me break this down for you step by step.
First, let’s cover the basic usage since you already have R2Shared.framework and R2Streamer.framework integrated.
1. Initialize Core Components
Start by setting up the core Readium classes when your app launches—these handle book loading and management:
import R2Shared import R2Streamer class BookService { private let streamer = Streamer() private let library = Library() static let shared = BookService() func setupReadium() { // Register the streamer with the library to handle book parsing library.register(streamer: streamer) } }
Call BookService.shared.setupReadium() in your AppDelegate or SceneDelegate during initialization.
2. Load an Ebook
Use the Streamer to load local or remote ebook files (EPUB, PDF, etc.). Here’s an async example for loading a local file:
func loadBook(from fileURL: URL) async throws -> Publication? { let result = try await streamer.open( url: fileURL, allowUserInteraction: true, sender: nil ) switch result { case .success(let publication): // Add the loaded book to the library for management library.addPublication(publication) return publication case .cancelled, .failure(let error): print("Failed to load book: \(error.localizedDescription)") return nil } }
3. Display the Reader
To show the ebook content, you’ll likely need the R2Navigator framework (if you haven’t added it yet, grab it from the Readium repo). Here’s how to push a reader view controller:
// Assuming you have a reference to a UINavigationController if let publication = loadedPublication { let readerVC = EPUBNavigatorViewController(publication: publication, locator: nil) navigationController?.pushViewController(readerVC, animated: true) }
The key to syncing is bridging Readium’s reading data (progress, bookmarks, annotations) with URMS’s user data system. Here’s a practical approach:
1. Track Reading Progress
Readium’s navigator sends notifications when the user’s reading location changes. Listen for these to capture progress:
// In your reader view controller override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(readingProgressUpdated(_:)), name: .r2NavigatorLocationChanged, object: nil ) } @objc private func readingProgressUpdated(_ notification: Notification) { guard let locator = notification.userInfo?["locator"] as? Locator else { return } // Sync this locator data to URMS syncProgressToURMS(locator: locator) }
2. Sync Progress to URMS
Convert Readium’s Locator (which contains chapter path, progress percentage, etc.) into a format URMS accepts, then call URMS’s sync API:
private func syncProgressToURMS(locator: Locator) { // Get current user ID from URMS guard let userId = URMSUserManager.shared.currentUserId() else { return } // Extract key data from Locator let bookId = locator.publicationId // Unique ID for the book let progress = locator.progression ?? 0.0 // 0-1 float representing read progress let chapterPath = locator.href // Path to the current chapter in the ebook // Call URMS's sync method (adjust based on URMS's actual API) URMSReadingSyncManager.shared.syncReadingProgress( userId: userId, bookId: bookId, progress: progress, chapterPath: chapterPath ) { success, error in if let error = error { print("Progress sync failed: \(error)") } } }
3. Restore Progress from URMS
When the user reopens a book, fetch their last saved progress from URMS and jump to that location:
func restoreLastProgress(for publication: Publication) { guard let userId = URMSUserManager.shared.currentUserId(), let bookId = publication.metadata.identifier else { return } URMSReadingSyncManager.shared.getLastReadingProgress( userId: userId, bookId: bookId ) { [weak self] progressData, error in guard let progressData = progressData else { return } // Convert URMS data back to a Readium Locator let locator = Locator( href: progressData.chapterPath, type: "application/xhtml+xml", progression: progressData.progress ) // Jump to the saved location in the reader if let navigator = self?.navigatorViewController as? EPUBNavigatorViewController { navigator.go(to: locator, animated: true) } } }
4. Sync Bookmarks & Annotations
For bookmarks/highlights, use Readium’s AnnotationManager to track changes and sync with URMS:
// In your reader setup let annotationManager = publication.annotationManager // Listen for annotation changes annotationManager.observeAnnotations { [weak self] change in switch change { case .added(let annotations): annotations.forEach { self?.syncAnnotationToURMS(annotation: $0) } case .removed(let annotations): annotations.forEach { self?.deleteAnnotationFromURMS(annotationId: $0.id) } } }
Convert Readium’s Annotation objects to URMS’s annotation format, then sync additions/deletions similarly to progress.
- Double-check that all required Readium frameworks are linked in your project’s Build Phases > Link Binary With Libraries
- If you hit issues with book loading, enable Readium’s debug logs by setting
R2EnableLogging = truein your Info.plist - Test offline sync: cache progress locally first, then sync to URMS when the network is available
- Make sure URMS and Readium use the same book identifier (e.g., ISBN or custom UUID) to avoid mismatches
内容的提问来源于stack exchange,提问作者Sptibo

