icloud_storage_plus
Flutter plugin for local iCloud Drive file operations with coordinated iOS and macOS access.
4.0.0
2.9K downloads/mo
#4701 most downloaded on pub.dev
Jason-Holt-Digital/icloud_storage_plus
What this package is like to depend on
Last release 1 months ago
19 Jul 2026
Ships fairly regularly
a new release about every 3 weeks
Nearly every release is documented
notes for 13 of 13 stable releases
Nothing withdrawn
no release was ever pulled
6 months old
13 releases · first in 2026
13 releases in the last 12 months
see the full history below
Release timeline
13 releases · Feb 2026 to Jul 2026Releases
latest 13-
4.0.019 Jul 2026Release notes
Open source →- feat!: release icloud_storage_plus 4.0.0
Harden coordinated Darwin writes and passive document observation, replace legacy APIs with the typed 4.0.0 contract, fix stream lifecycle ownership, and package privacy manifests.\n\nCo-Authored-By: Claude Fable 5 [email protected]
- fix(example): restore iOS minimum version
Co-Authored-By: Claude Fable 5 [email protected]
- docs: update package homepage
Co-Authored-By: Claude Fable 5 [email protected]
- fix: preserve native exception categories and close mapped streams on malformed payloads
Preserve the native-supplied category (e.g. cancelled, initialization)
in decodePlatformException instead of collapsing every unmodeled
category into ICloudUnknownNativeException, so callers can distinguish
intentional cancellation from unknown native failures.Close the transformed event stream after a malformed gather or
document-change payload, matching the transfer-progress stream and the
contract that malformed update payloads fail the stream.Co-authored-by: Codesmith [email protected]
- fix: close mapped streams on channel errors and report transfers once
- close the transformed event stream after a channel error in
_receiveMappedEventStream, matching the transfer-progress stream and
the fail-fast contract (releases the native subscription) - report transfer failures through the progress stream only when a
listener is attached, so uploadFile/downloadFile no longer surface the
same failure on both the stream and the returned Future - rename nativeSecondsNumberToInt to nativeNumToInt (size cast, not seconds)
- add blank lines after 4.0.0 CHANGELOG headings for markdownlint MD022
Co-authored-by: Codesmith [email protected]
- fix: harden macOS/iOS channel unregister, document change, and download cancel
- claim event-channel unregistration atomically with the lifecycle check
so a concurrent listen can no longer have its channel torn down (iOS
and macOS) - emit a conservative .invalidation on macOS when coordinated
presentedItemDidChange inspection fails, so a transient coordination
error no longer silently drops the document-change signal - treat progress-stream cancellation during downloadFile as
progress-monitoring cancellation only; the copy-out is not cancellable,
so let readDocumentAt drive the final result instead of reporting
E_CANCEL while the file is still being written (iOS and macOS), matching
the upload cancel path; remove the now-unused cancellationError helper
Co-authored-by: Codesmith [email protected]
- fix: propagate transfer failures after progress subscription cancel
Co-authored-by: Codesmith [email protected]
- fix: separate cancelOnError from explicit cancel and unblock macOS watcher startup
Co-authored-by: Codesmith [email protected]
- fix(macos): coordinate watched writes and document changes off presenter queue
Co-authored-by: Codesmith [email protected]
- fix: always propagate pluginContract failures from progress-enabled transfers
Co-authored-by: Codesmith [email protected]
- fix(spm): remove nonexistent FlutterFramework package dependency
Co-authored-by: Codesmith [email protected]
- fix: finalize 4.0.0 stream contracts
Co-Authored-By: Claude Fable 5 [email protected]
- fix(example): restore iOS App.framework MinimumOSVersion
Co-authored-by: Codesmith [email protected]
- fix: preserve transfer failures after progress cancellation
Co-Authored-By: Claude Fable 5 [email protected]
- chore(example): keep generated iOS framework plist
Co-Authored-By: Claude Fable 5 [email protected]
- fix: wrap unsupported document-change kinds in typed stream error
Co-authored-by: Codesmith [email protected]
- fix: skip native document watcher start after setup-time cancel
Co-authored-by: Codesmith [email protected]
- style: wrap watcher cancellation assertion
Co-Authored-By: Claude Fable 5 [email protected]
- fix: widen document-change mapping catch to Object
Co-authored-by: Codesmith [email protected]
Co-authored-by: Claude Fable 5 [email protected]
Co-authored-by: Codesmith [email protected]Release notes
Open source →Breaking
- Removed
getDocumentMetadata; usegetItemMetadatafor typed metadata. - Removed the public
PlatformExceptionCodeconstants. Match typedICloudOperationExceptionsubclasses and fields instead of transport codes. - Raw plugin
PlatformExceptionfailures now map to typedICloudOperationExceptionvalues, including details-less native failures and malformed method/event-channel contracts. - Transfer failures now arrive through the progress stream's
onErrorcallback as typed exceptions. RemoveICloudTransferProgressType.error,isError, andevent.exceptionhandling; data events are onlyprogressanddone. - Renamed the
uploadFileanddownloadFilenamed argument and method-channel key fromcloudRelativePathtorelativePath. - Renamed
ICloudDocumentChangeKind.remoteChangeand its native wire value toICloudDocumentChangeKind.invalidation/"invalidation". Treat it as a refresh hint and reread coordinated state. - Removed
ICloudDocumentChangeKind.unknown. Unsupported native wire values now fail the change stream as a plugin-contract violation instead of using a forward-compatibility fallback. - Removed
GatherInvalidEntryandGatherResult.invalidEntries; malformed gather payloads now fail the whole initial call or update stream. - Removed
ICloudStorage.documentsDirectoryanddataDirectory. Use the literalDocuments/path convention for Files app visibility. - Download-status payloads now accept only
null,notDownloaded,downloaded, orcurrent. readInPlaceandreadInPlaceBytesnow return non-nullableStringandUint8Listvalues. Missing items throwICloudItemNotFoundExceptioninstead of returningnull.ICloudStoragePlatform.getItemMetadatanow returnsFuture<ICloudItemMetadata?>; method-channel payloads are decoded exactly once by the default platform implementation.- Every advertised
ICloudOperationExceptionsubtype now has a public constructor accepting normalized failure fields, including dedicated cancellation and initialization exceptions. The rawPlatformExceptionmapper is internal to the method-channel implementation and is no longer part of the public API. onUpdate,onProgress, andonChangecallbacks must attach a stream listener synchronously. Delayed or ignored streams throwInvalidArgumentExceptionbefore native event-channel allocation.- Method and list responses now validate channel types explicitly and map
malformed payloads or missing native plugin implementations to typed
pluginContractexceptions. AllFuture<void>channel operations require a strictlynullsuccess response, including event-channel creation/start, mutations, transfers, and conflict operations.
Fixed
- iOS and macOS existing-file content writes now use ordinary write
coordination (
NSFileCoordinator.WritingOptionsempty) instead of replacement-intent (.forReplacing) coordination. Complete content is still staged outside the container and installed withFileManager.replaceItemAt; unresolved conflict versions remain app-owned. - macOS document observation now uses a passive file-presenter path instead of
NSDocumentreload/revert handling. Non-conflict content callbacks are de-duplicated using the on-disk modification date; conflict callbacks bypass that filter and may repeat while unresolved. - Successful plugin writes to existing watched macOS files refresh every active same-path watcher baseline, so matching queued callbacks are suppressed.
- Canceling a change subscription while native observation is starting now prevents late presenter registration and tears the watcher down exactly once.
- Transfer failures now retain a method-channel fallback; Dart suppresses that duplicate only when an unpaused progress listener accepts the error before cancellation, preventing pause/cancellation races from reporting failed transfers as successful.
- Upload progress no longer turns Apple-owned background iCloud upload lifecycle errors into plugin operation failures after the local copy-in has succeeded.
Documentation
- Clarified that document-change and
gather(onUpdate:)streams are best-effort invalidation/update signals, not real-time or exactly-once change logs. - Clarified that watching a missing future path is unsupported.
-
3.0.024 Jun 2026Release notes
Open source →Major release for the app-owned preserve-both conflict model and the final MYT-1321 publish cutover.
Breaking
- Removed the legacy native conflict auto-resolution contract completely.
ConflictResolver, write-path auto-resolve, and document-observer auto-resolve no longer exist. The plugin never silently marks or deletes losingNSFileVersions. - Consumers must use the explicit version-exposure API
(
enumerateUnresolvedConflictVersions,copyConflictVersion, andmarkConflictResolved) to implement their own conflict policy. The plugin exposes primitives only; apps own preserve-both copy-out and resolution sequencing. - Removed compatibility shims and old readiness/conflict behavior from the public Dart surface. This release has one forward contract rather than dual old/new APIs.
Added
- iOS and macOS expose unresolved
NSFileVersiondescriptors, caller-chosen conflict-version copy-out, and explicit mark-resolved operations over the Dart API. - Per-normalized-path mutation lanes serialize same-path mutations in FIFO order while allowing different paths to proceed concurrently.
AsyncMutex.acquire()now removes a queued waiter immediately when the waiting task is cancelled, preventing cancelled waiters from lingering in a lane until normal FIFO hand-off reaches them.
Changed
- iOS and macOS podspec versions now match the plugin
pubspec.yamlversion. This reconciles the previous podspec2.1.3versus pubspec2.2.0drift before publishing the new major. Package.swiftmanifests remain source-list only, with no semantic version field. The package source lists reference only files that are still present.
- Removed the legacy native conflict auto-resolution contract completely.
-
2.2.026 May 2026Release notes
Open source →Corrective release for the readiness/error-reporting API introduced in
2.0.0. That surface treated normal iCloud Drive lifecycle state as plugin-owned failures; this release removes it and restores the intended local file-operation boundary.Breaking
- Removed the read-side timeout/backoff parameters from
readInPlaceandreadInPlaceBytes. Reads now perform local iCloud Drive file access instead of waiting for Apple metadata to report a fresh remote state. - Removed exported typed exceptions and platform-code constants for plugin-owned iCloud readiness failures. Normal iCloud Drive lifecycle state is no longer a plugin error surface.
- Changed existing-destination
copy()behavior on iOS and macOS: the copy path no longer preflights iCloud download/current/conflict metadata or emits retired readiness errors before replacement. Existing directory destinations are rejected; placeholder, freshness, and conflict lifecycle states are left to Foundation, and any actual replacement failure is surfaced from the local operation.
Changed
- iOS and macOS reads no longer wait for
.currentbefore opening the local document. - iOS and macOS writes no longer run a plugin-owned wait before coordinated replacement. iCloud Drive sync lifecycle remains Apple's responsibility.
- Copy-over-existing-destination now uses the same local-file boundary: it rejects directory replacements, then lets Foundation perform the copy/replace rather than preflighting iCloud download/current metadata.
Removed
- Removed the internal iCloud readiness helper and its synthetic timeout error path.
- Removed the read-side timeout/backoff parameters from
-
2.1.304 May 2026Release notes
Open source →Fixed
- iOS and macOS container operations now route through a shared
UbiquityContainerResolver, includinggather, so transientFileManager.url(forUbiquityContainerIdentifier:)nil responses retry before surfacing a container-access failure. - Container resolution retry delays now preserve
Task.sleepcancellation instead of swallowing it, so cancelled calls stop before issuing an unnecessary second container lookup. - Native iOS and macOS metadata query sessions are retained for their full
query lifetimes, preventing observers from being released before
NSMetadataQuerycompletes. - Native write failures now preserve structured path and native error context for Dart typed exceptions without exposing full local filesystem paths.
- iOS and macOS container operations now route through a shared
-
2.1.223 Apr 2026Release notes
Open source →Fixed
- iOS
readInPlace/readInPlaceBytesnow marshal the post-download continuation back onto the main actor before invokingreadInPlaceDocument/readInPlaceBinaryDocument. The2.1.0async rewrite ofwaitForDownloadCompletioninadvertently removed theDispatchQueue.mainhop that the callback-based waiter guaranteed, lettingUIDocument.open(completionHandler:)be called from the Swift cooperative pool. This restores the1.2.2invariant thatUIDocumentwork runs under the main queue per Apple's completion-handler contract and avoids the_os_object_retain"Resurrection of an object" crash that motivated that fix. - macOS
uploadFile,readInPlace,readInPlaceBytes,writeInPlace,writeInPlaceBytesnow run theirTaskbodies on the main actor. Because the macOSFlutterMethodChannelis registered without a background task queue,FlutterResultmust be invoked on the main thread; the previousTask { [self] in ... }blocks resumed on the cooperative pool afterawait, causingresult(...)to be called off-main in preflight error paths.
Closes the threading concerns raised on #27, #26, and #25.
Full Changelog: 2.1.1...2.1.2
Release notes
Open source →Fixed
- iOS
readInPlaceandreadInPlaceBytesnow marshal the post-materialization continuation back onto the main actor before invokingreadInPlaceDocument/readInPlaceBinaryDocument. The2.1.0async rewrite of the previous readiness helper inadvertently removed theDispatchQueue.mainhop that the callback-based helper guaranteed, lettingUIDocument.open(completionHandler:)be called from the Swift cooperative pool. This restores the1.2.2invariant thatUIDocumentwork runs under the main queue per Apple's completion-handler contract and avoids the_os_object_retain"Resurrection of an object" crash that motivated that fix. - macOS
uploadFile,readInPlace,readInPlaceBytes,writeInPlace, andwriteInPlaceBytesnow run theirTaskbodies on the main actor. Because the macOSFlutterMethodChannelis registered without a background task queue,FlutterResultmust be invoked on the main thread; the previousTask { [self] in ... }blocks resumed on the cooperative pool afterawait, causingresult(...)to be called off-main in preflight error paths.
- iOS
-
2.1.122 Apr 2026Release notes
Open source →Fixed
- Added
WriteEntrypointPreflight.swiftto the explicit iOS pluginPackage.swiftsource list so consumer builds that rely on the plugin's Swift package manifest can compile the2.1.xwrite-path preflight helper. - This is a packaging hotfix only. The Dart API and native write-path behavior
introduced in
2.1.0are unchanged.
- Added
-
2.1.022 Apr 2026Release notes
Open source →Non-breaking behavior upgrade:
writeInPlacebecomes symmetric withreadInPlaceby proactively preparing existing iCloud items before the coordinated replace. Public Dart API unchanged.Added
- Shared
WriteEntrypointPreflighthelpers and foundation tests on iOS and macOS to move write-path container lookup and parent-directory creation off the entry thread before coordinated writes begin. - Typed Dart mapping for native
invalidArgumentwrite failures viaICloudInvalidArgumentException.
Changed
writeInPlaceand the binary / streaming overwrite paths now proactively prepare existing ubiquitous destinations before the coordinated replace.- Inside the coordinator write block, the overwrite path now calls
Apple's canonical conflict-resolution pattern
(
NSFileVersion.unresolvedConflictVersionsOfItem→replaceItem→isResolved = true→removeOtherVersionsOfItem) before invokingreplaceItemAt, symmetric with the existingreadInPlacebehavior. - Pre-flight conflict errors now fire only as last-resort signals when
automatic conflict handling itself fails. Auto-resolution failures surface
with a localized description containing "auto-resolution failed" while still
mapping to
ICloudConflictExceptionon the Dart side. - Internal refactor: unified the four textual copies of
CoordinatedReplaceWriter.swiftinto a single source of truth per platform (iOS and macOS) shared via SPMtarget.sources. - Internal refactor: extracted shared async helpers for readiness handling and unresolved-conflict resolution.
ICloudDocument.resolveConflicts()(iOS) and the equivalent macOS observer both call the shared resolver; the duplicate implementation on iOS has been removed.listContentson iOS and macOS now does less repeated work inside the directory-enumeration loop by reusing the key set, reusing the parent relative path, and skipping hidden files before metadata lookup.- README, package metadata, and publish/package wiring were updated to match the shipped 2.1.x source layout and write-path contract.
Fixed
- iOS and macOS overwrite-path completion handlers now preserve structured native failure details instead of degrading to generic native failures.
- CocoaPods packaging now explicitly includes the shared foundation sources needed by the coordinated overwrite implementation.
- Shared
-
2.0.009 Apr 2026Release notes
Open source →Drop the merged superpowers planning/spec files and top-level planning logs from main so the release branch documentation stays out of the published package history.
Release notes
Open source →Breaking release that hardens the Dart API contract around known-path metadata, typed request/response failures, and coordinated overwrite behavior on iOS and macOS.
BREAKING CHANGES
- Removed the old typed
getMetadata()API in favor ofgetItemMetadata(). - Structured native request/response failures now map to typed
ICloudOperationExceptionsubclasses across the Dart API. getDocumentMetadata()remains the raw metadata escape hatch and preserves rawPlatformExceptionbehavior.
Added
ICloudItemMetadataas the typed known-path metadata model returned bygetItemMetadata().- Typed request/response exception mapping for structured native payloads, including container access, not found, conflict, download-in-progress, item not downloaded, and timeout cases.
Changed
- README, example code, and public Dart doc comments now document the
2.0.0contract explicitly, including the separation betweenICloudItemMetadata,ICloudFile, and rawgetDocumentMetadata()payloads. - Transfer-progress streams continue to emit
PlatformException-based error payloads in2.0.0; only request/response APIs use the new typed exception mapping. - README, changelog, and public Dart doc comments now describe the final iOS and macOS coordinated replacement behavior for existing-destination writes and copies.
- On iOS and macOS, file-write overwrite APIs and
copy()now document separate existing-destination semantics: file writes target files only, whilecopy()preserves file-or-directory copy behavior. - The iOS and macOS coordinated replacement logic now has standalone Foundation-level Swift test seams, with helper XCTest coverage for overwrite and existing-destination copy replacement behavior.
- Repository documentation now points to the hosted DeepWiki site instead of
keeping a checked-in export under
doc/deepwiki/.
Fixed
- iOS and macOS existing-file
writeDocument,writeInPlace, andwriteInPlaceBytesnow stage replacement content outside the ubiquity container and replace the destination through coordinated atomic replacement. - iOS and macOS keep the
1.2.2document-open completion fix that dispatchesUIDocumentcompletion back ontoDispatchQueue.main, avoiding the_os_object_retainresurrection crash from short-lived local queues. - On iOS and macOS, file-write overwrite APIs now reject existing directory destinations instead of replacing them.
- On iOS and macOS, existing ubiquitous-item replacement semantics were tightened in this release.
- iOS and macOS
copy()now keep existing destinations inside coordinated atomic replacement flows instead of removing the destination before copying.
- Removed the old typed
-
1.2.230 Mar 2026Release notes
Open source →Fixed
- iOS and macOS document-open completion no longer uses a local
DispatchQueue. The short-lived queue could be deallocated beforeUIDocument.openWithCompletionHandler:finished retaining it (via the deprecateddispatch_get_current_queuecall in UIKit internals), causing an_os_object_retaincrash with "API MISUSE: Resurrection of an object". Completion is now dispatched onDispatchQueue.main, which is consistent with UIDocument's own completion-handler contract.
- iOS and macOS document-open completion no longer uses a local
-
1.2.127 Mar 2026Release notes
Open source →Changed
- iOS method-channel filesystem work now uses Flutter's background task queue
when that queue is available. Container lookup, iCloud path preflight, and
UIDocumentinitialization stay coordinated but no longer block the UI thread during in-place reads and writes on supported runtimes.
Fixed
- iOS and macOS metadata query update handling no longer depends on
DispatchQueue.main.syncfor event-channel state checks, reducing deadlock risk when iCloud change notifications arrive while other native work is in flight. - Event stream state on iOS and macOS is now synchronized for cross-queue access, which avoids races between cancellation, progress delivery, and metadata updates.
- iOS download watchdog startup now schedules its initial timeout on the main run loop even when the method channel handler starts on a background task queue, preventing stalled in-place reads from hanging indefinitely.
- iOS and macOS download completion/cancellation paths now use a synchronized
single-fire completion gate, preventing double
FlutterResultdelivery when cancellation races with native completion.
- iOS method-channel filesystem work now uses Flutter's background task queue
when that queue is available. Container lookup, iCloud path preflight, and
-
1.2.009 Mar 2026Release notes
Open source →Added
listContents()API for immediately-consistent container listings usingFileManager.contentsOfDirectorywith URL resource values. Unlikegather()(which reads the Spotlight metadata index),listContents()reflects filesystem mutations (rename, delete, copy) immediately.ContainerItemmodel withrelativePath,downloadStatus,isDownloading,isUploaded,isUploading,hasUnresolvedConflicts,isDirectory, and a convenienceisDownloadedgetter.- iCloud placeholder file resolution: both iOS (
.originalName.icloudstubs) and macOS Sonoma+ (APFS dataless files) are handled transparently —listContentsreturns the real filename and accurate download status. - Hidden file filtering:
listContentssuppresses system files (.DS_Store,.Trash, etc.) by filtering entries whose resolved name starts with..
Changed
ICloudFiledartdoc now cross-referencesContainerItemand explains the eventual-consistency distinction.GatherResultdartdoc expanded to describeinvalidEntriespurpose.- Fixed typo in
InvalidArgumentExceptiondoc comment ("ued" → "used"). - README expanded with
listContentsdocumentation,gathervslistContentscomparison table, iCloud placeholder files section, andContainerItemmodel reference.
-
1.1.114 Feb 2026Release notes
Open source →Fixed
- GitHub Actions automated publishing trigger for tags like
1.2.3(novprefix). - Remove example ephemeral LLDB helper files that were causing
dart pub publishvalidation warnings.
- GitHub Actions automated publishing trigger for tags like
-
1.0.004 Feb 2026Release notes
Open source →Major API update with path-based transfers for large files, coordinated in-place read/write APIs for small files, and a documentation overhaul.
BREAKING CHANGES
Transfer API: file-path based for large files
Byte-based transfer APIs have been removed in favor of file-path methods. Large file content is no longer sent over platform channels.
Removed:
upload(),download(), and related byte/JSON helpers.New:
uploadFile()anddownloadFile()using local paths pluscloudRelativePath.Migration:
- Write data to a local file in Dart.
- Call
uploadFile(localPath, cloudRelativePath). - To read, call
downloadFile(cloudRelativePath, localPath)and read the local file in Dart.
gather() now returns GatherResult
gather()now returns aGatherResultcontaining:files: parsedICloudFileentriesinvalidEntries: entries that could not be parsed (helps debug malformed metadata payloads)
ICloudFile metadata shape and nullability
ICloudFilenow:- includes
isDirectory: bool(directories are returned by metadata APIs) - may return
nullfor some fields when iCloud metadata is unavailable or the entry represents a directory (for examplesizeInBytes)
Directory detection behavior
documentExists()andgetMetadata()return true/non-null for both files and directories. Filter directories explicitly if your code expects only files.Platform requirements updated
Minimum deployment targets match Flutter 3.10+:
- iOS: 13.0
- macOS: 10.15
Internal channel name change
The native method channel name is
icloud_storage_plus(wasicloud_storage).Linting package change
Dev linting moved to
very_good_analysis.Added
- File-path transfer methods:
uploadFile()(local → iCloud container)downloadFile()(iCloud container → local)
- Coordinated in-place access for small files:
readInPlace()/writeInPlace()(String, UTF-8)readInPlaceBytes()/writeInPlaceBytes()(Uint8List)- Former optional read readiness tuning parameters were available in this release and have since been removed.
- Convenience
rename()API (implemented in Dart viamove()). - Additional iCloud sync-state fields on
ICloudFile:downloadStatus,isDownloadingisUploading,isUploadedhasUnresolvedConflicts
- New public error code constants:
PlatformExceptionCode.initializationError(E_INIT)
- Documentation overhaul:
- README updated to match the real API surface and semantics
- DeepWiki badge added to the README
- DeepWiki exported into
doc/for GitHub navigation - Added
scripts/fix_deepwiki_links.pyto keep exported docs linkable - Old
doc/research/plans removed (replaced by short notes underdoc/notes/)
Changed
- Structural operations (
delete,move,copy) use coordinated file URL operations (NSFileCoordinator) rather than relying on metadata queries. - Existence and metadata (
documentExists,getDocumentMetadata) use direct filesystem checks (FileManager / URL resource values) rather than metadata queries. documentExists()is a filesystem existence check; it does not force a download. Usegather()for a remote-aware view of container contents.- Transfer progress streams deliver failures as
ICloudTransferProgressType.errordata events (not streamonError).
Fixed
gather()now verifies the event channel handler exists before registering query observers (prevents leaked observers on early-return).getDocumentMetadata()now serializes download status keys as strings (.rawValue) for correct transport to Dart.- Dart relative-path validation accepts trailing slashes so directory paths from
metadata can be reused directly in operations like
delete(),move(),rename(), etc. uploadFile()/downloadFile()rejectcloudRelativePathvalues that end with/(directory-style paths).- macOS streaming writes use
.saveOperationfor existing files to avoid unintended “Save As” behavior.
Migration Guide (2.x → 1.0.0)
- Replace byte-based reads/writes with local files +
uploadFile()/downloadFile(). - For small JSON/text stored in iCloud Drive, consider switching to in-place
access (
readInPlace/writeInPlace) for “transparent sync”. - Update call sites to handle directories via
ICloudFile.isDirectoryand add null checks for optional metadata fields. - If you use transfer progress, attach a listener immediately inside
onProgress(streams are listener-driven and may miss early events). - Run
flutter analyzeto address anyvery_good_analysislint findings.