-
Notifications
You must be signed in to change notification settings - Fork 1.7k
User defaults #6907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
User defaults #6907
Conversation
* Initial commit for CustomModel class. * Initial commit for CustomModel class. * API scaffolding for CustomModel and ModelDownloader classes * API scaffolding for CustomModel and ModelDownloader classes * Delete ModelDownloadConditions.swift * Changed Swift structs to NSObject subclasses for objc visibility * Design for a Swift-first SDK * Design for a Swift-first SDK * Design for a Swift-first SDK * Updated design w/ errors and download progress handler * Style compliance * Refactor Test folder structure * Refactor Test folder structure * Fix pod lint errors * Fix pod lint errors * Add xcscheme for SwiftPM builds. * Disable catalyst temporarily, re-enable issue #6790 * Better classification of download errors * Documentation comments for custom model * Refactor errors for model downloading Co-authored-by: Ryan Wilson <[email protected]>
* Restores ML Pods after M77. * Remove deprecated sendLogsWithServiceName (#6437) * Remove deprecated pods from Firebase.h and Firebase.podspec (#6438) * Remove the FCM Direct Channel API from Messaging (#6430) * Remove unnecessary Core private headers (#6439) * Update SPM docs to current version (#6524) * Update podspecs to min iOS 10 (#6517) * Merging the 6.33.0 release into master (#6523) * Update versions for Release 6.33.0 * SPM M80(6.33.0) Analytics update (#6490) Co-authored-by: Paul Beusterien <[email protected]> * Merge 6.33 SPM fixes back to master (#6530) * SPM M80(6.33.0) Analytics update (#6490) * Remove unnecessary analytics public header copy (#6498) * Fix SPM analytics warning introduced yesterday (#6504) * Fix SPM version (#6527) * Import Spec tests (#6525) * Import Spec tests * Init * Add recovery specs * Update FSTSyncEngineTestDriver.mm * Add release candidate prerelease workflow. (#6487) This also update cocoapods source to cocoapods repo since cdn is failed to connect. * Move internal Crashlytics changes to Github (#6535) Move *most* internal Crashlytics changes to Github * GDTCORFlatFileStorageTest size limit tests: use timeout proportional to the number of events (#6537) * IID: repo-relative headers (#6539) * Use Xcode 12 in CI instead of the beta (#6542) * SwiftPM for FCM (#6541) * Fix a rare RC crash (#6556) * Refactoring archive testing to a single yml file. (#6510) * Refactoring archive testing to a single yml file. This reduces the duplication in each of the workflow files. This also will make archive testing with SwiftPM more straightforward. * Prefixed with 'pod' name * Commenting out to run archive testing on PR for now. * Put array on single line The yml won't be parsed unless the `pod` array is on a single line. * Fix to run on PRs to the yml itself. * Fix naming of AppDistro * Remove schemes. * Update versions automation (#6550) * Remove iOS 10.0 check since minimum support in Messaging is already 10.0 (#6559) * Add Performance podspec (#6526) * Integrate Firestore with Firebase platform logging (#6507) The sample user agent string I'm getting in XCode is `apple-platform/ios apple-sdk/17E8258 fire-fst/1.17.1 fire-ios/6.10.2 swift/true xcode/11E503a`. * Change lastFetchTime to be readonly (#6567) * Change lastFetchTime to be readonly * Add changelog * GDTCORDirectorySizeTracker: fix NSURL constructor (#6580) * GDTCORDirectorySizeTracker: replace optional NSURL constructor with non-optional. * GDTCORDirectorySizeTracker tests for the issue * ./scripts/style.sh * changelog * Upload Symbols 3.4 with performance improvements (#6583) * Stop requiring pods to be static frameworks (#6557) * Always send the user agent regardless of the heartbeat value (#6592) Any non-zero heartbeat value is immediately reset to zero upon retrieval. Thus, should the network request containing the heartbeat value and the user agent string fail, the previous logic would prevent us from sending the user agent string until the next day (when the heartbeat once again returns a non-zero value). Until this is resolved, always send the user agent string, regardless of the heartbeat value. The associated increase in bandwidth usage is minor (~1.2% in _total_ traffic from running the full suite of Firestore integration tests, which represent the worst-case scenario because they recreate the streams much more often than a typical application). * Make all GoogleUtilities APIs public (#6588) * Make FirestoreException a type defined by Firestore/core (#6589) Move FirestoreInternalError to firebase::firestore to match FirestoreException in Android. When importing this into google3, we'll have to delete the Android-specific version of this type. * Update CHANGELOG for Firestore v1.19.0 (#6601) * Remove deprecated method in ABT public header (#6602) * Remove deprecated method, implementation * Replace call to deprecated method in RC, fix tests * Update changelogs * Add InstanceID deprecation warning (#6585) * Firebase 7 Firebase.podspec versions (#6604) * Add a changelog entry for Firestore platform logging (#6603) * 6.34.0 CHANGELOG update (#6611) * Migrate FIRLoggerServices strings from Core to clients (#6608) * Add static-framework testing to CI (#6599) * FIS: Additional FIRInstallationsItem validation (#6570) * FIS API tests for no FID in response * FIRInstallationsIDControllerTests: test names * FIRInstallationsIDControllerTests: corrupted storage tests * FIRInstallationsItem validation * Fix FIRInstallationsItem.IIDDefaultToken copy * Improve error description. * FIRInstallationsItem validation error * FIRInstallationsItem validation tests * ./scripts/style.sh * FIRInstallationsIDController: validate stored installation * FIRInstallationsAPIService installation validation * Changelog * Update versions for Release 6.34.0 * 6.34.0 updates for SwiftPM (#6614) * M81 FIS cherry pick of #6570 (#6616) * FIS: Additional FIRInstallationsItem validation (#6570) * FIS API tests for no FID in response * FIRInstallationsIDControllerTests: test names * FIRInstallationsIDControllerTests: corrupted storage tests * FIRInstallationsItem validation * Fix FIRInstallationsItem.IIDDefaultToken copy * Improve error description. * FIRInstallationsItem validation error * FIRInstallationsItem validation tests * ./scripts/style.sh * FIRInstallationsIDController: validate stored installation * FIRInstallationsAPIService installation validation * Changelog * Update versions * patch version * release manifest * Add link to App Distribution docs page (#6620) * Add link to App Distribution docs page * Remove trailing whitespaace * FIS IID tests shouldn't use repo-relative imports * Clean up usage of deprecated methods in unit tests (#6618) * Clean up usage of deprecated methods in unit tests * Add back second namespace tests * Remove test for setDefaults:namespace: * Remove deprecated auth APIs (#6607) * Remove deprecated APIs from public header. * Remove deprecated API implementations. * Also remove deprecated APIs from FIRUser. * Update unit tests. * Update sample app. * Update changelog. * Use MIMEType for image download extension if not present in resource URL (#6591) * ZipBuilder Firebase 7 updates (#6629) * Change numberValue to be nonnull (#6623) * Change numberValue to be nonnull * Add changelog * Add auth emulator support to public API. (#6624) * Add auth emulator support to public API. * Update changelog. * FIS: don't log anything on success validation (#6635) (#6636) * Remove the `FirebaseOptions()` bare initializer. (#6633) * Remove the `FirebaseOptions()` bare initializer. This was unintentionally surfaced from the ObjC header and should be removed. Note: although the existing initializer doesn't work, this is still a breaking change. * Style * Changelog update. * Remove deprecated elements of FIAM API (#6617) * Remove deprecated FIAM API * Remove call to deprecated method * Fix imports * Modify view controllers to use dummy test subclasses for message objects * Add bridging header, include it in test app * Add CHANGELOG entry * Revert "Add CHANGELOG entry" This reverts commit 55c0bbc. * Add CHANGELOG entry * Swift formatting * Add LLC to copyright notice * Revert "Fix imports" This reverts commit 55fdbbd. * FIS: disable IID migration tests by default (#6619) * FIS: disable IID migration tests by default * remove redundant env variable * Fix merge errors * Merge FLoC SDK into master branch. (#6466) * Create Segmentation SDK structure for source and unit tests. (#3214) * Create Segmentation SDK structure for source and unit tests. * Review changes: Remove unnecessary files in test folder. Add md-floc-master to CI * Rename Segmentation directory to FirebaseSegmentation directory. Update podspec to include search header path. * Add core support with interop for Segmentation SDK. (#3430) * Add core support with interop for Segmentation SDK. Also update headers to be under sources folder. * Review fixes. * Minor changes. * Fix style. * Fix style. * Style changes. * Fix whitespace in travis.yml * Fix style. * Travis CI is stuck..try updating the travis.yml * Undo travis.yml change. * Working drop of Segmentation SDK along with test app and unit tests. (#4574) * Working drop of Segmentation SDK along with sample app and unit tests. * Update if_changed.sh to include FirebaseSegmentation. * Complete NS_ASSUME_NON_NULL_START with NS_ASSUME_NON_NULL_END in header file. * Fix unit tests. * Fix style. * Fixes after running XCode's static analyzer. * Fix style. * fix style. * 'pod lib lint' fixes. * Fix analyzer errors. * Address review comments. * Minor changes for review comments. * Address review comments. * Address review comments. * stop mocking in tear down method for tests. * Minor update to sample app project. * Fix trailing whitespace in Podfile. * Add set -x to check.sh * update segmetation dependency version * migrate FloC SDK to depend on FIS SDK directly * format floc * format * using customized FIRapp * remove test plist file * refactor to capture weakself * format * replace partial mock with class mock * minor refactoring * use subscript to manipulate dictionary instance * fix import error * minor refoctoring, addressing comments * address comments * fix configurations * format Co-authored-by: dmandar <[email protected]> Co-authored-by: ChaoqunCHEN <[email protected]> * Remove deprecated RC APIs (#6637) * Remove deprecated method declarations and implementations * Fix broken dangerfile (#6642) * GDT: Move GDTCORAssert.h to internal headers (#6638) * Move GDTCORAssert.h to internal headers * Fix import * Update check_imports check (#6640) * Stop using CocoaPods private headers (#6572) * Add check for unauthenticated error and sign out in fetchNewLatestRelease (#6648) * Add check for unauthenticated error and sign out in fetchNewRelase method * Update CHANGELOG * Add check for Tester sign in before calling fetch * One Firebase version (#6634) * Update Symbol Collision Test for Firebase 7 (#6656) * Fix ZipBuilder crash and warning (#6653) * Public Version API (#6651) * Bump nanopb to fix Xcode 12 warning (#6659) * Fix breakage from #6651 (#6660) * GDT: move some headers from public to internal (#6643) * Move extra public headers to Internal and fix imports * Cleanup * Use relative paths in internal headers * Fix imports in internal headers * ./scripts/style.sh * Fix GDTTestApp * Fix test app * Use real uploader for watchOS test app * comma * Update the sample project link. (#6661) * Simplify FirebaseCore imports (#6664) * Call fetchAndActivate completion handler on main thread (#6665) * Call fetchAndActivate completion handler on main thread * Add changelog * Update changelog to use issue number * Missing Foundation import (#6670) * Remove duplicate section for instructions. (#6668) * FirebaseInstallations import added to Firebase.h (#4908) * FirebaseInstallations import added to Firebase.h * Add Installations to Firebase.podspec * UI_USER_INTERFACE_IDIOM() was deprecated in iOS 14 (#6576) * Update FirebaseAnalytics to the latest version from the release branch. (#6675) * Remove deprecated -[FIRInstanceID appInstanceID:] (#6677) * Remove deprecated -[FIRInstanceID appInstanceID:] * changelog * typo fix * Messaging token refresh delegate should be able to return null token (#6647) * Cherry-pick two 6.34.0 commits to master (#6688) * Update changelogs (#6649) * Speedup SwiftPM (#6687) Co-authored-by: Morgan Chen <[email protected]> * Fix a google3 build error (#6689) * Fix an issue notification is not received during app first install (#6669) * FIS: require projectID and valid API Key format (#6678) * FIRInstallations validation: remove GCMSenderID fallback for missing projectID * FIRInstallationsIDController: remove GCMSenderID fallback for missing projectID * Add API Key validation * Changelog * changelog * Constant for API key lenght * array] -> alloc] init] * typo * message * ./scripts/style.sh * Fix dummy API key in integration tests * Update dummy API Keys to match the expected format * debug test quickstart with no xcpretty * fix debug * Use debug QS repo branch * print debug * Add missing allowed characters `-`, `_` * Nicer dummy API Keys * Comment * Revert "Use debug QS repo branch" This reverts commit 69739dd. * Revert "fix debug" This reverts commit 84fcbc7. * Revert "debug test quickstart with no xcpretty" This reverts commit 1fa21ed. * C API for Firebase Version (#6690) * Fix retain cycle build issue (#6693) * Provide version for FDL 1P builds (#6679) * Fix tvOS storage issues. (#6658) * Fix tvOS storage issues. On tvOS devices, the ApplicationSupport directory cannot be used. Unfortunately this doesn't come up in simulator testing, only on device. This hasn't been fully tested on device but given that any writes to the ApplicationSupport directory fail on tvOS, this change can't break much. Fixes #6612 @defagos can you please give this a test? * Fixed changed dir name for RC * Fixed test naming, too. * Fix the documentation comment for GoogleUtilities. * Updated changelog. * Review feedback * Fixed CHANGELOG location. (#6698) * Fix CI/regression - update for change FCM API (#6699) * Support paths with + in List API (#6700) * Update API documentation referencing removed methods (#6667) * Update API documentation to remove references to removed methods * Add changelog * Address comments * Merge release-6.34.0 branch after patch (#6701) * Update versions for Release 6.34.0 * 6.34.0 updates for SwiftPM (#6614) * M81 FIS cherry pick of #6570 (#6616) * FIS: Additional FIRInstallationsItem validation (#6570) * FIS API tests for no FID in response * FIRInstallationsIDControllerTests: test names * FIRInstallationsIDControllerTests: corrupted storage tests * FIRInstallationsItem validation * Fix FIRInstallationsItem.IIDDefaultToken copy * Improve error description. * FIRInstallationsItem validation error * FIRInstallationsItem validation tests * ./scripts/style.sh * FIRInstallationsIDController: validate stored installation * FIRInstallationsAPIService installation validation * Changelog * Update versions * patch version * release manifest * FIS: don't log anything on success validation (#6635) * Update changelogs (#6649) * GoogleDataTransport: deprecated API conditions (#6697) * GoogleDataTransport: deprecated API conditions * Version bump * use `TARGET_OS_IOS` * changelog * changelog * style * Fix merge Co-authored-by: Ryan Wilson <[email protected]> Co-authored-by: Paul Beusterien <[email protected]> Co-authored-by: Morgan Chen <[email protected]> * Refactor GULSwizzledObject to ARC to unblock SwiftPM support (#5862) * Refactor GULSwizzledObject to ARC to unblock SwiftPM transition. * run ./scripts/style.sh * Assert a single swizzler per swizzled object. * testMultiSwizzling: fix iOS 10 tests * Changelog * Cleanup * Address floc review comments (#6691) * Address floc review comments * Fix style * fix bad synthesize * Remove segmentation constants from core * fix style * Allow Generic OAuth for Facebook and Apple when using the auth emulator. (#6702) * Update NOTICES now that several FirebaseML pods are deleted (#6709) * Log warning instead of failing SDK when discovering dangling target. (#6685) * Log warning instead of failing SDK when discovering dangling target. * Add unit test * Delete old test. * Initial SPM building for watchOS (#6705) * Update testing account since the previous one is disabled for GHA. (#6652) * Update the version of analytics to the latest released one. (#6562) * Disable deprecation warning (#6512) * Remove the `FIR` prefix from notification constants. (#6645) * Remove the `FIR` prefix from notification constants. * Enable Firebase 7 path in quickstart test Co-authored-by: Paul Beusterien <[email protected]> * Change instances of 'dimiss' to 'dismiss' (#6708) * Use completion handler when updating experiments after activation (#6711) * Use completion handler when updating experiments after activation * Fix Travis * Add changelog * Fix whitespace * Nonnull initializers * Firebase user agent: additional fields for platform logging (#6429) * Move firebase user agent logic to a separate class. * FIRAppTest: prefix some tests with the tested method names * FIRAppTest: user agent new fields tests * New user agent field added. * Headers * API docs * ./scripts/style.sh * nullability fix * Move environment info methods to GoogleUtilities * GULAppEnvironmentUtilTest * GULAppEnvironmentUtil swift tests * FirebaseApp user agent swift flag test * ./scripts/style.sh * Cleanup CoreDiagnostics * Nullable device model * FIRCoreDiagnosticsTest fix * Merge fixes * Fix import * rename * Cleanup GUL imports (since all headers are public now) * Don't allow logger version deallocation (#6719) * s/withMaxResults/maxResults (#6714) * Remove support for setting timestampsInSnapshotsEnabled (#6622) Snapshots will now always include `FIRTimestamp` values. Use `[FIRTimestamp dateValue]` to convert to `NSDate` if required. `timestampsInSnapshotsEnabled` was deprecated in Firebase 5.16.0 (January 22, 2019) and has defaulted to true since then. Projects that have not enabled `timestampsInSnapshotsEnabled` have logged a warning since Firebase 4.12.0 (April 10, 2018). * FIS API docs: use term "installation auth token" consistently. (#6014) * FIS API docs: use term "Installation auth token" consistently. * Changelog * Capitalize * Use lowercase * SHA1 usage explanation * missed upper case * a -> an * Minor RC cleanup (#6722) * Cleanup developer mode variables * Fix README link * Use fully qualified namespace in test to avoid errors * Fix whitespace * Re-enable quickstart testing for FirebaseUI apps (#6725) * Update GDT version for M82 (#6729) * Update versions for Release 7.0.0 * ios version fixes * Delete Test dependency * Add manual trigger and update catching branch version. (#6732) * One version release process (#6724) * Missing iid handler checking cause crash (#6737) * Fix spelling in header name (#6738) * Travis GoogleUtilities : skip Swift tests when --use-libraries (#6735) * Travis GoogleUtilities : skip Swift tests when --use-libraries * Temporary enable cron tests for PRs to check * Revert temp change * Add update-tags release process (#6739) * Firebase zip contents from FirebaseManifest instead of textproto (#6747) * Add Carthage JSON manifests to git repo (#6742) * Address #6747 review comments (#6749) * CocoaPods CI update (#6751) * CocoaPods CI update * CocoaPods CI update * Restore cron after test success * FIS docs: whitelist -> allowlist (#6757) * FIS docs: whitelist -> allowlist * Changelog * Changelog fix * Revert accidently added GUL change * GoogleUtilities: NSURLSession promise extension (#6753) * GoogleUtilities: NSURLSession promise extension * Imports fix * Changelog * API and API docs * style * Changelog fix * Finish port of update-versions.py (#6758) * Finish port of update-versions.py * comments * more comment * Prevent test build errors under Xcode 12.1 (#6760) Xcode 12 changed the XCTest assertions to be macros that no longer implicitly depended on `self`. It seems as if Xcode 12.1 has made -Wunused-lambda-capture part of our default warnings and this breaks Objective-C++ code that lambda captures `self` only for its implicit use with the XCTest macros. This isn't common, so just suppress the warning by forcing `self` to appear used regardless of whether XCTest assertions reference `self` or not. * Exclude FirebaseSegmentation in testing (#6736) * Some Release tooling cleanup (#6761) * Only run schedule actions on the main repo (#6770) * Rename ReleaseTooling (#6772) * Address two comments from last week's PRs (#6774) * Source updates for ReleaseTooling rename (#6773) * Fix a memory leak introduced in #6418 (#6778) The root of the issue is that when serializing a singular filter, it is being treated as a unary filter before it is definitively established whether it is a unary filter or a field filter. The leak is caused by always serializing the unary filter's field path field for equality and non-equality filters -- if the filter's value turns out not to be NaN or null, the serialization code switches the filter's type to a field filter without clearing the partially-initialized unary filter. `pb_release` would not free the `unary_filter.field.field_path` member variable because it would consider the object not to be a unary filter. Also a small refactoring to make the function easier to digest. * Fix typo to fix zip cron (#6784) * Fix cron logic for forks (#6785) * Crashlytics update run script to quote all arguments passed (#6789) * Adjust Storage Timeouts to GTM's retry interval (#6791) * Add custom domain support to callable functions (#6787) * Update to CocoaPods 1.10.0 (#6795) * Restore zip cron test (#6798) * Fixed broken callback to AppDelegate (#6800) Fixed broken callback to AppDelegate after retrieving a dynamic link during fresh app start. The AppDelegate call was broken in PR : #6517 Reverting to the old implementation of dynamic link passing to App delegate with changes to remove iOS 9 checks. Using new "openURL" method instead of the deprecated one. Clean up in the sample app pod file. * Merge release-7.0 branch to master (#6797) * Update cron tests for new Swift product names (#6804) * Stop failing on warnings (#6807) * Merge SPM updates back to master to fix CI (#6809) * Add support for other Firebase products to integrate with Remote Config. (#6692) * Update zip builder to handle xcframeworks from binary pods (#6815) * Readme and Roadmap updates (#6816) * Fix typo on publish command (#6831) * Update SPM instructions for 7.0 (#6832) * Fix publish order - RemoteConfig is a dependency of Performance (#6834) * Post-release 7.0 merge to master (#6836) * Firebase user agent: add iOS on mac platform (#6799) * Firebase user agent: add iOS on mac platform * Older Xcode compatibility * Fix check iOS version * changelog * Carthage updates for 7.0.0 (#6833) * Adding test to make sure pending dynamic link is getting passed to App delegate method. (#6819) Adding unit test to make sure the pending dynamic link is getting delivered to specific method in App delegate. * Remove Component version from issue template (#6838) * Run integration tests against the emulator by default. (#6852) Remove support for running against Hexa, which we haven't done in years. Integration tests will now assume a local emulator by default. Once imported into google3, this will make it significantly easier to run integration tests against cls from third-parties because this will be able to use the emulator we're already running rather than requiring us to build hexa again. * Fix cache for check workflow (#6853) * clarify error when logging settings failures (#6847) Added additional logging when settings requests fail with a 404 status to help customers debug onboarding issues. * Update Firestore macOS build for Xcode 12 (#6859) * Remove usages of "whitelist" in Firestore. (#6846) Fixes #6755. * Allocate global objects so that their destructors don't run. (#6849) Fixes #6844. * Fix minor style issues uncovered during auditing (#6851) * Remove explicit MobileCoreServices from podspecs (#6858) * Change the Crashlytics version constant to read from FIRCore instead of from a build flag. (#6712) * Get rid of an additional import of FIRVersion that I missed deleting (#6867) * Merge #6860 to master (#6868) * Fix warning introduced with Xcode 12 (#6865) * GDTCCTUploader: lazy initialize url session, use ephemeral session (#6870) * GDTCCTUploader: lazy initialize url session, use ephemeral session * Changelog * typo * Update to Firebase 7.0 and add Installations dependency * Fix lint errors Co-authored-by: Paul Beusterien <[email protected]> Co-authored-by: Chen Liang <[email protected]> Co-authored-by: Maksym Malyhin <[email protected]> Co-authored-by: Sebastian Schmidt <[email protected]> Co-authored-by: Gran <[email protected]> Co-authored-by: Tejas Deshpande <[email protected]> Co-authored-by: Ryan Wilson <[email protected]> Co-authored-by: Konstantin Varlamov <[email protected]> Co-authored-by: karenyz <[email protected]> Co-authored-by: Sam Edson <[email protected]> Co-authored-by: Gil <[email protected]> Co-authored-by: christibbs <[email protected]> Co-authored-by: Alex Singer <[email protected]> Co-authored-by: Rosalyn Tan <[email protected]> Co-authored-by: akiva <[email protected]> Co-authored-by: Di Wu <[email protected]> Co-authored-by: dmandar <[email protected]> Co-authored-by: ChaoqunCHEN <[email protected]> Co-authored-by: Morgan Chen <[email protected]> Co-authored-by: Cleo Schneider <[email protected]> Co-authored-by: Yuchen Shi <[email protected]> Co-authored-by: Daisuke TONOSAKI <[email protected]> Co-authored-by: wu-hui <[email protected]> Co-authored-by: Jim Hays <[email protected]> Co-authored-by: Sam Stern <[email protected]> Co-authored-by: Eldhose M Babu <[email protected]> Co-authored-by: vic-flair <[email protected]> Co-authored-by: Adam Duke <[email protected]>
Generated by 🚫 Danger |
return value ?? defaultValue | ||
} | ||
set { | ||
guard let optional = newValue as Optional?, optional != nil else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I'm checking here is if newValue
is nil - is this the right way to do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if something like the following will work:
if let newValue = newValue else {
storage.setValue(newValue, forKey: key)
} else {
storage.removeObject(forKey: key)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will work. I was playing around in a playground and remember seeing something like this before and came up with a different (somewhat messy?) solution:
private protocol OptionalProtocol: ExpressibleByNilLiteral {
var isNil: Bool { get }
}
extension Optional: OptionalProtocol {
public var isNil: Bool {
switch self {
case .some(_): return false
case .none: return true
}
}
}
This is just saying that there's a protocol that nil
"conforms" to and Optional does as well, then the check can be against the protocol:
if let opt = newValue as? OptionalProtocol, opt.isNil {
// Value is nil, remove it.
} else {
// Value is not nil.
}
Does that make sense? It's not the nicest but it works as far as I can tell :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, I updated the code to look more like this.
defaults: .getTestInstance() | ||
) | ||
modelInfoRetriever.modelInfo = ModelInfo(app: testApp, name: testModelName) | ||
// XCTAssertEqual(modelInfoRetriever.modelInfo?.downloadURL, "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured this line would work, given that getTestInstance()
wipes out user defaults, but it fails. What am I missing?
…ebase-ios-sdk into ml-model-downloader
5f5c31a
to
e0c24a4
Compare
e0c24a4
to
09c28fd
Compare
/// Get model info from server. | ||
func downloadModelInfo(completion: @escaping (DownloadError?) -> Void) { | ||
/// Get FIS token. | ||
installations.authToken { [weak self] tokenResult, error in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
|
||
/// Property initializer for user defaults. Value is always read from or written to a named user defaults store. | ||
@propertyWrapper struct UserDefaultsBacked<Value> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this to a new file since it could be used elsewhere. Could also eventually be pulled out into a common utility for other products as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return value ?? defaultValue | ||
} | ||
set { | ||
guard let optional = newValue as Optional?, optional != nil else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will work. I was playing around in a playground and remember seeing something like this before and came up with a different (somewhat messy?) solution:
private protocol OptionalProtocol: ExpressibleByNilLiteral {
var isNil: Bool { get }
}
extension Optional: OptionalProtocol {
public var isNil: Bool {
switch self {
case .some(_): return false
case .none: return true
}
}
}
This is just saying that there's a protocol that nil
"conforms" to and Optional does as well, then the check can be against the protocol:
if let opt = newValue as? OptionalProtocol, opt.isNil {
// Value is nil, remove it.
} else {
// Value is not nil.
}
Does that make sense? It's not the nicest but it works as far as I can tell :P
/// Get FIS token. | ||
installations.authToken { [weak self] tokenResult, error in | ||
guard let result = tokenResult | ||
else { completion(.internalError(description: ModelInfoRetriever.tokenErrorDescription)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: completion(...)
on a new line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return | ||
} | ||
/// Get model info fetch URL with appropriate HTTP headers. | ||
guard let request = self?.getModelInfoFetchURLRequest(token: result.authToken) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to have a separate guard
to unwrap self
at the beginning of the handler?
|
||
/// Local model not modified. | ||
if httpResponse.statusCode == 304 { | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why completion is not called in this case? Could you add a comment please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, I fixed it. The error handling needs to be fleshed out in a future PR.
return | ||
} | ||
|
||
self?.saveModelInfo(data: data, modelHash: modelHash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we unwrap self
at the beginning of the handler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return | ||
} | ||
/// Download model info. | ||
let dataTask = URLSession.shared.dataTask(with: request) { [weak self] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: will it be more readable if we move sending the request to a separate method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. I've added a TODO for myself to do this in a future PR, since this one is primarily about user defaults and FIS.
} | ||
|
||
guard let modelHash = httpResponse | ||
.allHeaderFields[ModelInfoRetriever.etagHTTPHeader] as? String else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Standard caching headers like ETag are usually handled transparently by NSURLSession. I wonder what's the reason of additional manual handling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use ETag to extract the model hash returned by the server for the model object.
return | ||
} | ||
|
||
guard httpResponse.statusCode == 200 || httpResponse.statusCode == 304 else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It may be better to express this using switch
with pattern matching, e.g.:
switch httpResponse.statusCode {
case 100..<300:
// Handle success codes
break
case 304:
return
default:
...
}
In this case it will be easier to spot handled and unhandled cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return value ?? defaultValue | ||
} | ||
set { | ||
guard let optional = newValue as Optional?, optional != nil else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if something like the following will work:
if let newValue = newValue else {
storage.setValue(newValue, forKey: key)
} else {
storage.removeObject(forKey: key)
}
extension UserDefaults { | ||
static var firebaseMLDefaults: UserDefaults { | ||
let suiteName = "com.google.firebase.ml" | ||
let defaults = UserDefaults(suiteName: suiteName)! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please avoid using force unwrap in the production code unless it is 100% safe or required as it potentially leads to unexpected obfuscated crashes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into this and it seems like UserDefaults will only fail when you pass it a reserved (therefore invalid) suiteName. So technically this should work 100% of the time, but I've added a TODO here to look into this more and add a test in a future PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my experience, we should rely only on the public API definition as the implementation details may change without a notice, so I'm pretty convinced we should handle nullability gracefully here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I've added a TODO to handle this in a future PR.
} | ||
|
||
/// For testing: returns a new cleared instance of user defaults. | ||
static func getTestInstance() -> UserDefaults { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would try to avoid adding test code to production version. Can it be defined in tests instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly LGTM for an intermediate PR, but a couple things to be addressed here or later on.
var defaults: UserDefaults | ||
|
||
/// Download URL for the model file, as returned by server. | ||
@UserDefaultsBacked var downloadURL: String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I enjoy seeing how a property wrapper can extend functionality of a simple class, it looks really cool. From the other side I'm a bit worried of the fact that the struct that looks like a simple data object actually has a very significant side effect and modifies a shared global state (user defaults). As it is a value type, a new copy of the model will be created each time the model is modified but all of these copies will actually modify the same user defaults affecting other copies violating the value type semantic.
Do you think I'm missing anything? If not then I think there are a couple ways to proceed:
- accept the controversy of a data object modifying the global shared state in favour the convenience. In this case the model should be redefined as a class to fix conflict between the value type semantic and actual model behaviour
- separate the model persistence logic and make
ModelInfo
a plain data value type.
I think we may address it in a followup PR just to keep moving. If you decide to do so please add a TODO for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a TODO, and for now ModelInfo is a class.
/// Extension to handle fetching model info from server. | ||
extension ModelInfoRetriever { | ||
/// HTTP request headers. | ||
static let fisTokenHTTPHeader: String = "x-goog-firebase-installations-auth" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the String
type declaration is redundant when assigned with the literal here and below. It should be just:
static let fisTokenHTTPHeader = "x-goog-firebase-installations-auth"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
components.scheme = "https" | ||
components.host = "firebaseml.googleapis.com" | ||
components.path = "/v1beta2/projects/\(projectID)/models/\(modelName):download" | ||
return components.url! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No force unwrap should be used in production code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a TODO to handle this in a future PR.
|
||
/// Download model info. | ||
// TODO: Consider moving request to a separate method | ||
let dataTask = URLSession.shared.dataTask(with: request) { [weak self] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I am not mistaken URLSession.shared
caches request and response into an unencrypted database in the app sandbox, which for some cases may be considered a security vulnerability when request contains data like FIS token API key, etc. You may find more details in b/158644295.
Could you please add a TODO to reconsider using the shared URL session for the follow up PRs.
extension UserDefaults { | ||
static var firebaseMLDefaults: UserDefaults { | ||
let suiteName = "com.google.firebase.ml" | ||
let defaults = UserDefaults(suiteName: suiteName)! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my experience, we should rely only on the public API definition as the implementation details may change without a notice, so I'm pretty convinced we should handle nullability gracefully here.
] | ||
), | ||
|
||
.target( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks problematic and looks to be causing CI failure
Hey there! So you want to contribute to a Firebase SDK?
Before you file this pull request, please read these guidelines:
Discussion
If not, go file an issue about this before creating a pull request to discuss.
Testing
API Changes
us make Firebase APIs better, please propose your change in a feature request so that we
can discuss it together.