diff options
25 files changed, 938 insertions, 394 deletions
diff --git a/.travis.yml b/.travis.yml index 042fab1..7c1c0b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ before_install: - bundle exec pod install --project-directory=Example --repo-update - bundle exec pod install --project-directory=Firestore/Example --no-repo-update - brew install clang-format + - brew install swiftformat - brew install cmake - brew install go # Somehow the build for Abseil requires this. - echo "$TRAVIS_COMMIT_RANGE" diff --git a/Example/tvOSSample/tvOSSample/AppDelegate.swift b/Example/tvOSSample/tvOSSample/AppDelegate.swift index 9a0d052..723a3c4 100644 --- a/Example/tvOSSample/tvOSSample/AppDelegate.swift +++ b/Example/tvOSSample/tvOSSample/AppDelegate.swift @@ -17,7 +17,6 @@ import FirebaseCore @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { @@ -26,4 +25,3 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } } - diff --git a/Example/tvOSSample/tvOSSample/AuthLoginViewController.swift b/Example/tvOSSample/tvOSSample/AuthLoginViewController.swift index dcf72d4..65e0316 100644 --- a/Example/tvOSSample/tvOSSample/AuthLoginViewController.swift +++ b/Example/tvOSSample/tvOSSample/AuthLoginViewController.swift @@ -16,25 +16,14 @@ import UIKit import FirebaseAuth class AuthLoginViewController: UIViewController { + override func viewDidLoad() { + super.viewDidLoad() - override func viewDidLoad() { - super.viewDidLoad() + // Do any additional setup after loading the view. + } - // Do any additional setup after loading the view. - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destinationViewController. - // Pass the selected object to the new view controller. - } - */ + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } } diff --git a/Example/tvOSSample/tvOSSample/AuthViewController.swift b/Example/tvOSSample/tvOSSample/AuthViewController.swift index 72351d3..56276ed 100644 --- a/Example/tvOSSample/tvOSSample/AuthViewController.swift +++ b/Example/tvOSSample/tvOSSample/AuthViewController.swift @@ -20,13 +20,13 @@ class AuthViewController: UIViewController { // MARK: - User Interface /// A stackview containing all of the buttons to providers (Email, OAuth, etc). - @IBOutlet weak var providers: UIStackView! + @IBOutlet var providers: UIStackView! /// A stackview containing a signed in label and sign out button. - @IBOutlet weak var signedIn: UIStackView! + @IBOutlet var signedIn: UIStackView! /// A label to display the status for the signed in user. - @IBOutlet weak var signInStatus: UILabel! + @IBOutlet var signInStatus: UILabel! // MARK: - User Actions diff --git a/Example/tvOSSample/tvOSSample/DatabaseViewController.swift b/Example/tvOSSample/tvOSSample/DatabaseViewController.swift index 712c48f..2b710fa 100644 --- a/Example/tvOSSample/tvOSSample/DatabaseViewController.swift +++ b/Example/tvOSSample/tvOSSample/DatabaseViewController.swift @@ -30,7 +30,7 @@ class DatabaseViewController: UIViewController { // MARK: - Interface /// Label to display the current value. - @IBOutlet weak var currentValue: UILabel! + @IBOutlet var currentValue: UILabel! // MARK: - User Actions @@ -65,7 +65,7 @@ class DatabaseViewController: UIViewController { // Observe the current value, and update the UI every time it changes. let ref = Database.database().reference(withPath: Constants.databasePath) - ref.observe(.value) { [weak self] (snapshot) in + ref.observe(.value) { [weak self] snapshot in guard let value = snapshot.value as? Int else { print("Error grabbing value from Snapshot!") return diff --git a/Example/tvOSSample/tvOSSample/EmailLoginViewController.swift b/Example/tvOSSample/tvOSSample/EmailLoginViewController.swift index 60dfc43..9bea765 100644 --- a/Example/tvOSSample/tvOSSample/EmailLoginViewController.swift +++ b/Example/tvOSSample/tvOSSample/EmailLoginViewController.swift @@ -19,6 +19,7 @@ protocol EmailLoginDelegate { func emailLogin(_ controller: EmailLoginViewController, signedInAs user: User) func emailLogin(_ controller: EmailLoginViewController, failedWithError error: Error) } + class EmailLoginViewController: UIViewController { // MARK: - Public Properties @@ -27,15 +28,15 @@ class EmailLoginViewController: UIViewController { // MARK: - User Interface - @IBOutlet private weak var emailAddress: UITextField! - @IBOutlet private weak var password: UITextField! + @IBOutlet private var emailAddress: UITextField! + @IBOutlet private var password: UITextField! // MARK: - User Actions @IBAction func logInButtonHit(_ sender: UIButton) { guard let (email, password) = validatedInputs() else { return } - Auth.auth().signIn(withEmail: email, password: password) { [unowned self] (user, error) in + Auth.auth().signIn(withEmail: email, password: password) { [unowned self] user, error in guard let user = user else { print("Error signing in: \(error!)") self.delegate?.emailLogin(self, failedWithError: error!) @@ -50,7 +51,7 @@ class EmailLoginViewController: UIViewController { @IBAction func signUpButtonHit(_ sender: UIButton) { guard let (email, password) = validatedInputs() else { return } - Auth.auth().createUser(withEmail: email, password: password) { [unowned self] (user, error) in + Auth.auth().createUser(withEmail: email, password: password) { [unowned self] user, error in guard let user = user else { print("Error signing up: \(error!)") self.delegate?.emailLogin(self, failedWithError: error!) diff --git a/Example/tvOSSample/tvOSSample/StorageViewController.swift b/Example/tvOSSample/tvOSSample/StorageViewController.swift index 4416649..2e91d92 100644 --- a/Example/tvOSSample/tvOSSample/StorageViewController.swift +++ b/Example/tvOSSample/tvOSSample/StorageViewController.swift @@ -31,7 +31,7 @@ class StorageViewController: UIViewController { case failed(String) /// Equatable support for UIState. - static func ==(lhs: StorageViewController.UIState, rhs: StorageViewController.UIState) -> Bool { + static func == (lhs: StorageViewController.UIState, rhs: StorageViewController.UIState) -> Bool { switch (lhs, rhs) { case (.cleared, .cleared): return true case (.downloading, .downloading): return true @@ -52,16 +52,16 @@ class StorageViewController: UIViewController { // MARK: Interface /// Image view to display the downloaded image. - @IBOutlet weak var imageView: UIImageView! + @IBOutlet var imageView: UIImageView! /// The download button. - @IBOutlet weak var downloadButton: UIButton! + @IBOutlet var downloadButton: UIButton! /// The clear button. - @IBOutlet weak var clearButton: UIButton! + @IBOutlet var clearButton: UIButton! /// A visual representation of the state. - @IBOutlet weak var stateLabel: UILabel! + @IBOutlet var stateLabel: UILabel! // MARK: - User Actions @@ -72,7 +72,7 @@ class StorageViewController: UIViewController { let storage = Storage.storage() let ref = storage.reference(withPath: Constants.downloadPath) // TODO: Show progress bar here using proper API. - let task = ref.getData(maxSize: Constants.maxSize) { [unowned self] (data, error) in + let task = ref.getData(maxSize: Constants.maxSize) { [unowned self] data, error in guard let data = data else { self.state = .failed("Error downloading: \(error!.localizedDescription)") return @@ -114,7 +114,7 @@ class StorageViewController: UIViewController { stateLabel.text = "State: Downloading..." // Download complete, ensure the download button is still off and enable the clear button. - case (_, .downloaded(let image)): + case let (_, .downloaded(image)): imageView.image = image stateLabel.text = "State: Image downloaded!" @@ -124,7 +124,7 @@ class StorageViewController: UIViewController { stateLabel.text = "State: Pending download" // An error occurred. - case (_, .failed(let error)): + case let (_, .failed(error)): stateLabel.text = "State: \(error)" // For now, as the default, throw a fatal error because it's an unexpected state. This will diff --git a/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.m b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.m index 4a0120b..a44a340 100644 --- a/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.m +++ b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.m @@ -166,11 +166,11 @@ NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?%@"; FIRAuthURLCallbackMatcher callbackMatcher = ^BOOL(NSURL *_Nullable callbackURL) { return [self isVerifyAppURL:callbackURL eventID:eventID]; }; - [_auth.authURLPresenter presentURL:reCAPTCHAURL - UIDelegate:UIDelegate - callbackMatcher:callbackMatcher - completion:^(NSURL *_Nullable callbackURL, - NSError *_Nullable error) { + [self->_auth.authURLPresenter presentURL:reCAPTCHAURL + UIDelegate:UIDelegate + callbackMatcher:callbackMatcher + completion:^(NSURL *_Nullable callbackURL, + NSError *_Nullable error) { if (error) { callBackOnMainThread(nil, error); return; @@ -185,7 +185,8 @@ NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?%@"; [[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber appCredential:nil reCAPTCHAToken:reCAPTCHAToken - requestConfiguration:_auth.requestConfiguration]; + requestConfiguration: + self->_auth.requestConfiguration]; [FIRAuthBackend sendVerificationCode:request callback:^(FIRSendVerificationCodeResponse *_Nullable response, NSError *_Nullable error) { @@ -361,14 +362,15 @@ NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?%@"; [[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber appCredential:appCredential reCAPTCHAToken:nil - requestConfiguration:_auth.requestConfiguration]; + requestConfiguration: + self->_auth.requestConfiguration]; [FIRAuthBackend sendVerificationCode:request callback:^(FIRSendVerificationCodeResponse *_Nullable response, NSError *_Nullable error) { if (error) { if (error.code == FIRAuthErrorCodeInvalidAppCredential) { if (retryOnInvalidAppCredential) { - [_auth.appCredentialManager clearCredential]; + [self->_auth.appCredentialManager clearCredential]; [self verifyClientAndSendVerificationCodeToPhoneNumber:phoneNumber retryOnInvalidAppCredential:NO callback:callback]; @@ -404,7 +406,7 @@ NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?%@"; FIRVerifyClientRequest *request = [[FIRVerifyClientRequest alloc] initWithAppToken:token.string isSandbox:token.type == FIRAuthAPNSTokenTypeSandbox - requestConfiguration:_auth.requestConfiguration]; + requestConfiguration:self->_auth.requestConfiguration]; [FIRAuthBackend verifyClient:request callback:^(FIRVerifyClientResponse *_Nullable response, NSError *_Nullable error) { if (error) { @@ -412,7 +414,7 @@ NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?%@"; return; } NSTimeInterval timeout = [response.suggestedTimeOutDate timeIntervalSinceNow]; - [_auth.appCredentialManager + [self->_auth.appCredentialManager didStartVerificationWithReceipt:response.receipt timeout:timeout callback:^(FIRAuthAppCredential *credential) { @@ -442,8 +444,8 @@ NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?%@"; return; } NSString *bundleID = [NSBundle mainBundle].bundleIdentifier; - NSString *clienID = _auth.app.options.clientID; - NSString *apiKey = _auth.requestConfiguration.APIKey; + NSString *clienID = self->_auth.app.options.clientID; + NSString *apiKey = self->_auth.requestConfiguration.APIKey; NSMutableDictionary *urlArguments = [[NSMutableDictionary alloc] initWithDictionary: @{ @"apiKey" : apiKey, @"authType" : kAuthTypeVerifyApp, @@ -452,8 +454,8 @@ NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?%@"; @"v" : [FIRAuthBackend authUserAgent], @"eventId" : eventID, }]; - if (_auth.requestConfiguration.languageCode) { - urlArguments[@"hl"] = _auth.requestConfiguration.languageCode; + if (self->_auth.requestConfiguration.languageCode) { + urlArguments[@"hl"] = self->_auth.requestConfiguration.languageCode; } NSString *argumentsString = [urlArguments gtm_httpArgumentsString]; NSString *URLString = diff --git a/Firebase/Auth/Source/FIRAuth.m b/Firebase/Auth/Source/FIRAuth.m index ebca6c8..0f3705f 100644 --- a/Firebase/Auth/Source/FIRAuth.m +++ b/Firebase/Auth/Source/FIRAuth.m @@ -436,7 +436,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; NSError *error; if ([strongSelf getUser:&user error:&error]) { [strongSelf updateCurrentUser:user byForce:NO savingToDisk:NO error:&error]; - _lastNotifiedUserToken = user.rawAccessToken; + self->_lastNotifiedUserToken = user.rawAccessToken; } else { FIRLogError(kFIRLoggerAuth, @"I-AUT000001", @"Error loading saved user when starting up: %@", error); @@ -486,7 +486,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; - (FIRUser *)currentUser { __block FIRUser *result; dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - result = _currentUser; + result = self->_currentUser; }); return result; } @@ -497,7 +497,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; FIRCreateAuthURIRequest *request = [[FIRCreateAuthURIRequest alloc] initWithIdentifier:email continueURI:@"http://www.google.com/" - requestConfiguration:_requestConfiguration]; + requestConfiguration:self->_requestConfiguration]; [FIRAuthBackend createAuthURI:request callback:^(FIRCreateAuthURIResponse *_Nullable response, NSError *_Nullable error) { if (completion) { @@ -743,14 +743,14 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; dispatch_async(FIRAuthGlobalWorkQueue(), ^{ FIRAuthDataResultCallback decoratedCallback = [self signInFlowAuthDataResultCallbackByDecoratingCallback:completion]; - if (_currentUser.anonymous) { + if (self->_currentUser.anonymous) { FIRAdditionalUserInfo *additionalUserInfo = [[FIRAdditionalUserInfo alloc] initWithProviderID:nil profile:nil username:nil isNewUser:NO]; FIRAuthDataResult *authDataResult = - [[FIRAuthDataResult alloc] initWithUser:_currentUser + [[FIRAuthDataResult alloc] initWithUser:self->_currentUser additionalUserInfo:additionalUserInfo]; decoratedCallback(authDataResult, nil); return; @@ -784,8 +784,8 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; dispatch_async(FIRAuthGlobalWorkQueue(), ^{ FIRAuthResultCallback decoratedCallback = [self signInFlowAuthResultCallbackByDecoratingCallback:completion]; - if (_currentUser.anonymous) { - decoratedCallback(_currentUser, nil); + if (self->_currentUser.anonymous) { + decoratedCallback(self->_currentUser, nil); return; } [self internalSignInAnonymouslyWithCompletion:^(FIRSignUpNewUserResponse *_Nullable response, @@ -889,7 +889,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; FIRResetPasswordRequest *request = [[FIRResetPasswordRequest alloc] initWithOobCode:code newPassword:newPassword - requestConfiguration:_requestConfiguration]; + requestConfiguration:self->_requestConfiguration]; [FIRAuthBackend resetPassword:request callback:^(FIRResetPasswordResponse *_Nullable response, NSError *_Nullable error) { if (completion) { @@ -910,7 +910,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; FIRResetPasswordRequest *request = [[FIRResetPasswordRequest alloc] initWithOobCode:code newPassword:nil - requestConfiguration:_requestConfiguration]; + requestConfiguration:self->_requestConfiguration]; [FIRAuthBackend resetPassword:request callback:^(FIRResetPasswordResponse *_Nullable response, NSError *_Nullable error) { if (completion) { @@ -951,7 +951,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; - (void)applyActionCode:(NSString *)code completion:(FIRApplyActionCodeCallback)completion { dispatch_async(FIRAuthGlobalWorkQueue(), ^ { FIRSetAccountInfoRequest *request = - [[FIRSetAccountInfoRequest alloc] initWithRequestConfiguration:_requestConfiguration]; + [[FIRSetAccountInfoRequest alloc] initWithRequestConfiguration:self->_requestConfiguration]; request.OOBCode = code; [FIRAuthBackend setAccountInfo:request callback:^(FIRSetAccountInfoResponse *_Nullable response, NSError *_Nullable error) { @@ -999,7 +999,8 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; FIRGetOOBConfirmationCodeRequest *request = [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:email actionCodeSettings:actionCodeSettings - requestConfiguration:_requestConfiguration]; + requestConfiguration:self->_requestConfiguration + ]; [FIRAuthBackend getOOBConfirmationCode:request callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response, NSError *_Nullable error) { @@ -1015,7 +1016,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; - (BOOL)signOut:(NSError *_Nullable __autoreleasing *_Nullable)error { __block BOOL result = YES; dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - if (!_currentUser) { + if (!self->_currentUser) { return; } result = [self updateCurrentUser:nil byForce:NO savingToDisk:YES error:error]; @@ -1068,7 +1069,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; [_listenerHandles addObject:handle]; } dispatch_async(dispatch_get_main_queue(), ^{ - listener(self, self.currentUser); + listener(self, self->_currentUser); }); return handle; } @@ -1082,7 +1083,8 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; - (void)useAppLanguage { dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - _requestConfiguration.languageCode = [NSBundle mainBundle].preferredLocalizations.firstObject; + self->_requestConfiguration.languageCode = + [NSBundle mainBundle].preferredLocalizations.firstObject; }); } @@ -1092,17 +1094,17 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; - (void)setLanguageCode:(nullable NSString *)languageCode { dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - _requestConfiguration.languageCode = [languageCode copy]; + self->_requestConfiguration.languageCode = [languageCode copy]; }); } - (NSString *)additionalFrameworkMarker { - return _requestConfiguration.additionalFrameworkMarker; + return self->_requestConfiguration.additionalFrameworkMarker; } - (void)setAdditionalFrameworkMarker:(NSString *)additionalFrameworkMarker { dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - _requestConfiguration.additionalFrameworkMarker = [additionalFrameworkMarker copy]; + self->_requestConfiguration.additionalFrameworkMarker = [additionalFrameworkMarker copy]; }); } @@ -1110,7 +1112,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; - (NSData *)APNSToken { __block NSData *result = nil; dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - result = _tokenManager.token.data; + result = self->_tokenManager.token.data; }); return result; } @@ -1121,20 +1123,20 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; - (void)setAPNSToken:(NSData *)token type:(FIRAuthAPNSTokenType)type { dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - _tokenManager.token = [[FIRAuthAPNSToken alloc] initWithData:token type:type]; + self->_tokenManager.token = [[FIRAuthAPNSToken alloc] initWithData:token type:type]; }); } - (void)handleAPNSTokenError:(NSError *)error { dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - [_tokenManager cancelWithError:error]; + [self->_tokenManager cancelWithError:error]; }); } - (BOOL)canHandleNotification:(NSDictionary *)userInfo { __block BOOL result = NO; dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - result = [_notificationManager canHandleNotification:userInfo]; + result = [self->_notificationManager canHandleNotification:userInfo]; }); return result; } @@ -1142,7 +1144,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; - (BOOL)canHandleURL:(NSURL *)URL { __block BOOL result = NO; dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - result = [_authURLPresenter canHandleURL:URL]; + result = [self->_authURLPresenter canHandleURL:URL]; }); return result; } diff --git a/Firebase/Auth/Source/FIRAuthAPNSTokenManager.m b/Firebase/Auth/Source/FIRAuthAPNSTokenManager.m index 215a391..2b39aef 100644 --- a/Firebase/Auth/Source/FIRAuthAPNSTokenManager.m +++ b/Firebase/Auth/Source/FIRAuthAPNSTokenManager.m @@ -68,13 +68,13 @@ static const NSTimeInterval kLegacyRegistrationTimeout = 30; _pendingCallbacks = [[NSMutableArray<FIRAuthAPNSTokenCallback> alloc] initWithObjects:callback, nil]; dispatch_async(dispatch_get_main_queue(), ^{ - if ([_application respondsToSelector:@selector(registerForRemoteNotifications)]) { - [_application registerForRemoteNotifications]; + if ([self->_application respondsToSelector:@selector(registerForRemoteNotifications)]) { + [self->_application registerForRemoteNotifications]; } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" #if TARGET_OS_IOS - [_application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert]; + [self->_application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert]; #endif // TARGET_OS_IOS #pragma clang diagnostic pop } @@ -83,7 +83,7 @@ static const NSTimeInterval kLegacyRegistrationTimeout = 30; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_timeout * NSEC_PER_SEC)), FIRAuthGlobalWorkQueue(), ^{ // Only cancel if the pending callbacks remain the same, i.e., not triggered yet. - if (applicableCallbacks == _pendingCallbacks) { + if (applicableCallbacks == self->_pendingCallbacks) { [self callBackWithToken:nil error:nil]; } }); diff --git a/Firebase/Auth/Source/FIRAuthNotificationManager.m b/Firebase/Auth/Source/FIRAuthNotificationManager.m index b1dd34c..624de10 100644 --- a/Firebase/Auth/Source/FIRAuthNotificationManager.m +++ b/Firebase/Auth/Source/FIRAuthNotificationManager.m @@ -104,14 +104,14 @@ static const NSTimeInterval kProbingTimeout = 1; kNotificationProberKey : @"This fake notification should be forwarded to Firebase Auth." } }; - if ([_application.delegate respondsToSelector: + if ([self->_application.delegate respondsToSelector: @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)]) { - [_application.delegate application:_application + [self->_application.delegate application:self->_application didReceiveRemoteNotification:proberNotification fetchCompletionHandler:^(UIBackgroundFetchResult result) {}]; - } else if ([_application.delegate respondsToSelector: + } else if ([self->_application.delegate respondsToSelector: @selector(application:didReceiveRemoteNotification:)]) { - [_application.delegate application:_application + [self->_application.delegate application:self->_application didReceiveRemoteNotification:proberNotification]; } else { FIRLogWarning(kFIRLoggerAuth, @"I-AUT000015", diff --git a/Firebase/Auth/Source/FIRAuthSerialTaskQueue.m b/Firebase/Auth/Source/FIRAuthSerialTaskQueue.m index 3be0f54..edceeec 100644 --- a/Firebase/Auth/Source/FIRAuthSerialTaskQueue.m +++ b/Firebase/Auth/Source/FIRAuthSerialTaskQueue.m @@ -37,14 +37,14 @@ - (void)enqueueTask:(FIRAuthSerialTask)task { // This dispatch queue will run tasks serially in FIFO order, as long as it's not suspended. - dispatch_async(_dispatchQueue, ^{ + dispatch_async(self->_dispatchQueue, ^{ // But as soon as a task is started, stop other tasks from running until the task calls it's // completion handler, which allows the queue to resume processing of tasks. This allows the // task to perform other asyncronous actions on other dispatch queues and "get back to us" when // all of their sub-tasks are complete. - dispatch_suspend(_dispatchQueue); + dispatch_suspend(self->_dispatchQueue); task(^{ - dispatch_resume(_dispatchQueue); + dispatch_resume(self->_dispatchQueue); }); }); } diff --git a/Firebase/Auth/Source/FIRAuthURLPresenter.m b/Firebase/Auth/Source/FIRAuthURLPresenter.m index 5526a85..d8e3593 100644 --- a/Firebase/Auth/Source/FIRAuthURLPresenter.m +++ b/Firebase/Auth/Source/FIRAuthURLPresenter.m @@ -81,17 +81,19 @@ NS_ASSUME_NONNULL_BEGIN _callbackMatcher = callbackMatcher; _completion = completion; dispatch_async(dispatch_get_main_queue(), ^() { - _UIDelegate = UIDelegate ?: [FIRAuthDefaultUIDelegate defaultUIDelegate]; + self->_UIDelegate = UIDelegate ?: [FIRAuthDefaultUIDelegate defaultUIDelegate]; if ([SFSafariViewController class]) { - _safariViewController = [[SFSafariViewController alloc] initWithURL:URL]; - _safariViewController.delegate = self; - [_UIDelegate presentViewController:_safariViewController animated:YES completion:nil]; + self->_safariViewController = [[SFSafariViewController alloc] initWithURL:URL]; + self->_safariViewController.delegate = self; + [self->_UIDelegate presentViewController:self->_safariViewController + animated:YES + completion:nil]; return; } else { - _webViewController = [[FIRAuthWebViewController alloc] initWithURL:URL delegate:self]; + self->_webViewController = [[FIRAuthWebViewController alloc] initWithURL:URL delegate:self]; UINavigationController *navController = - [[UINavigationController alloc] initWithRootViewController:_webViewController]; - [_UIDelegate presentViewController:navController animated:YES completion:nil]; + [[UINavigationController alloc] initWithRootViewController:self->_webViewController]; + [self->_UIDelegate presentViewController:navController animated:YES completion:nil]; } }); } @@ -108,8 +110,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)safariViewControllerDidFinish:(SFSafariViewController *)controller { dispatch_async(FIRAuthGlobalWorkQueue(), ^() { - if (controller == _safariViewController) { - _safariViewController = nil; + if (controller == self->_safariViewController) { + self->_safariViewController = nil; //TODO:Ensure that the SFSafariViewController is actually removed from the screen before //invoking finishPresentationWithURL:error: [self finishPresentationWithURL:nil @@ -123,7 +125,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)webViewController:(FIRAuthWebViewController *)webViewController canHandleURL:(NSURL *)URL { __block BOOL result = NO; dispatch_sync(FIRAuthGlobalWorkQueue(), ^() { - if (webViewController == _webViewController) { + if (webViewController == self->_webViewController) { result = [self canHandleURL:URL]; } }); @@ -132,7 +134,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)webViewControllerDidCancel:(FIRAuthWebViewController *)webViewController { dispatch_async(FIRAuthGlobalWorkQueue(), ^() { - if (webViewController == _webViewController) { + if (webViewController == self->_webViewController) { [self finishPresentationWithURL:nil error:[FIRAuthErrorUtils webContextCancelledErrorWithMessage:nil]]; } @@ -142,7 +144,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)webViewController:(FIRAuthWebViewController *)webViewController didFailWithError:(NSError *)error { dispatch_async(FIRAuthGlobalWorkQueue(), ^() { - if (webViewController == _webViewController) { + if (webViewController == self->_webViewController) { [self finishPresentationWithURL:nil error:error]; } }); @@ -163,7 +165,7 @@ NS_ASSUME_NONNULL_BEGIN FIRAuthURLPresentationCompletion completion = _completion; _completion = nil; void (^finishBlock)(void) = ^() { - _isPresenting = NO; + self->_isPresenting = NO; completion(URL, error); }; SFSafariViewController *safariViewController = _safariViewController; diff --git a/Firebase/Auth/Source/FIRSecureTokenService.m b/Firebase/Auth/Source/FIRSecureTokenService.m index 8e37a05..69434ff 100644 --- a/Firebase/Auth/Source/FIRSecureTokenService.m +++ b/Firebase/Auth/Source/FIRSecureTokenService.m @@ -107,7 +107,7 @@ static const NSTimeInterval kFiveMinutes = 5 * 60; [_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock complete) { if (!forceRefresh && [self hasValidAccessToken]) { complete(); - callback(_accessToken, nil, NO); + callback(self->_accessToken, nil, NO); } else { [self requestAccessToken:^(NSString *_Nullable token, NSError *_Nullable error, @@ -184,14 +184,15 @@ static const NSTimeInterval kFiveMinutes = 5 * 60; NSError *_Nullable error) { BOOL tokenUpdated = NO; NSString *newAccessToken = response.accessToken; - if (newAccessToken.length && ![newAccessToken isEqualToString:_accessToken]) { - _accessToken = [newAccessToken copy]; - _accessTokenExpirationDate = response.approximateExpirationDate; + if (newAccessToken.length && ![newAccessToken isEqualToString:self->_accessToken]) { + self->_accessToken = [newAccessToken copy]; + self->_accessTokenExpirationDate = response.approximateExpirationDate; tokenUpdated = YES; } NSString *newRefreshToken = response.refreshToken; - if (newRefreshToken.length && ![newRefreshToken isEqualToString:_refreshToken]) { - _refreshToken = [newRefreshToken copy]; + if (newRefreshToken.length && + ![newRefreshToken isEqualToString:self->_refreshToken]) { + self->_refreshToken = [newRefreshToken copy]; tokenUpdated = YES; } callback(newAccessToken, error, tokenUpdated); diff --git a/Firebase/Auth/Source/FIRUser.m b/Firebase/Auth/Source/FIRUser.m index 6af263d..a77db75 100644 --- a/Firebase/Auth/Source/FIRUser.m +++ b/Firebase/Auth/Source/FIRUser.m @@ -383,7 +383,7 @@ static void callInMainThreadWithAuthDataResultAndError( } FIRGetAccountInfoRequest *getAccountInfoRequest = [[FIRGetAccountInfoRequest alloc] initWithAccessToken:accessToken - requestConfiguration:_auth.requestConfiguration]; + requestConfiguration:self->_auth.requestConfiguration]; [FIRAuthBackend getAccountInfo:getAccountInfoRequest callback:^(FIRGetAccountInfoResponse *_Nullable response, NSError *_Nullable error) { @@ -451,7 +451,7 @@ static void callInMainThreadWithAuthDataResultAndError( callback(error); return; } - FIRAuthRequestConfiguration *configuration = _auth.requestConfiguration; + FIRAuthRequestConfiguration *configuration = self->_auth.requestConfiguration; // Mutate setAccountInfoRequest in block: FIRSetAccountInfoRequest *setAccountInfoRequest = [[FIRSetAccountInfoRequest alloc] initWithRequestConfiguration:configuration]; @@ -513,7 +513,7 @@ static void callInMainThreadWithAuthDataResultAndError( callback(error); return; } - _tokenService = tokenService; + self->_tokenService = tokenService; if (![self updateKeychain:&error]) { callback(error); return; @@ -558,11 +558,11 @@ static void callInMainThreadWithAuthDataResultAndError( return; } if (email) { - _email = email; + self->_email = email; } - if (_email && password) { - _anonymous = NO; - _hasEmailPasswordCredential = YES; + if (self->_email && password) { + self->_anonymous = NO; + self->_hasEmailPasswordCredential = YES; if (!hadEmailPasswordCredential) { // The list of providers need to be updated for the newly added email-password provider. [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, @@ -571,7 +571,7 @@ static void callInMainThreadWithAuthDataResultAndError( callback(error); return; } - FIRAuthRequestConfiguration *requestConfiguration = _auth.requestConfiguration; + FIRAuthRequestConfiguration *requestConfiguration = self->_auth.requestConfiguration; FIRGetAccountInfoRequest *getAccountInfoRequest = [[FIRGetAccountInfoRequest alloc] initWithAccessToken:accessToken requestConfiguration:requestConfiguration]; @@ -646,7 +646,7 @@ static void callInMainThreadWithAuthDataResultAndError( initWithVerificationID:phoneAuthCredential.verificationID verificationCode:phoneAuthCredential.verificationCode operation:operation - requestConfiguration:_auth.requestConfiguration]; + requestConfiguration:self->_auth.requestConfiguration]; request.accessToken = accessToken; [FIRAuthBackend verifyPhoneNumber:request callback:^(FIRVerifyPhoneNumberResponse *_Nullable response, @@ -664,7 +664,7 @@ static void callInMainThreadWithAuthDataResultAndError( completion(error); return; } - _anonymous = NO; + self->_anonymous = NO; if (![self updateKeychain:&error]) { completion(error); return; @@ -737,10 +737,11 @@ static void callInMainThreadWithAuthDataResultAndError( reauthenticateAndRetrieveDataWithCredential:(FIRAuthCredential *) credential completion:(nullable FIRAuthDataResultCallback) completion { dispatch_async(FIRAuthGlobalWorkQueue(), ^{ - [_auth internalSignInAndRetrieveDataWithCredential:credential - isReauthentication:YES - callback:^(FIRAuthDataResult *_Nullable authResult, - NSError *_Nullable error) { + [self->_auth internalSignInAndRetrieveDataWithCredential:credential + isReauthentication:YES + callback:^(FIRAuthDataResult *_Nullable + authResult, + NSError *_Nullable error) { if (error) { // If "user not found" error returned by backend, translate to user mismatch error which is // more accurate. @@ -750,7 +751,7 @@ static void callInMainThreadWithAuthDataResultAndError( callInMainThreadWithAuthDataResultAndError(completion, authResult, error); return; } - if (![authResult.user.uid isEqual:[_auth getUID]]) { + if (![authResult.user.uid isEqual:[self->_auth getUID]]) { callInMainThreadWithAuthDataResultAndError(completion, authResult, [FIRAuthErrorUtils userMismatchError]); return; @@ -766,7 +767,7 @@ static void callInMainThreadWithAuthDataResultAndError( - (nullable NSString *)refreshToken { __block NSString *result; dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - result = _tokenService.refreshToken; + result = self->_tokenService.refreshToken; }); return result; } @@ -842,7 +843,7 @@ static void callInMainThreadWithAuthDataResultAndError( - (void)linkAndRetrieveDataWithCredential:(FIRAuthCredential *)credential completion:(nullable FIRAuthDataResultCallback)completion { dispatch_async(FIRAuthGlobalWorkQueue(), ^{ - if (_providerData[credential.provider]) { + if (self->_providerData[credential.provider]) { callInMainThreadWithAuthDataResultAndError(completion, nil, [FIRAuthErrorUtils providerAlreadyLinkedError]); @@ -851,7 +852,7 @@ static void callInMainThreadWithAuthDataResultAndError( FIRAuthDataResult *result = [[FIRAuthDataResult alloc] initWithUser:self additionalUserInfo:nil]; if ([credential isKindOfClass:[FIREmailPasswordAuthCredential class]]) { - if (_hasEmailPasswordCredential) { + if (self->_hasEmailPasswordCredential) { callInMainThreadWithAuthDataResultAndError(completion, nil, [FIRAuthErrorUtils providerAlreadyLinkedError]); @@ -887,7 +888,7 @@ static void callInMainThreadWithAuthDataResultAndError( } #endif - [_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock _Nonnull complete) { + [self->_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock _Nonnull complete) { CallbackWithAuthDataResultAndError completeWithError = ^(FIRAuthDataResult *result, NSError *error) { complete(); @@ -899,7 +900,7 @@ static void callInMainThreadWithAuthDataResultAndError( completeWithError(nil, error); return; } - FIRAuthRequestConfiguration *requestConfiguration = _auth.requestConfiguration; + FIRAuthRequestConfiguration *requestConfiguration = self->_auth.requestConfiguration; FIRVerifyAssertionRequest *request = [[FIRVerifyAssertionRequest alloc] initWithProviderID:credential.provider requestConfiguration:requestConfiguration]; @@ -917,7 +918,7 @@ static void callInMainThreadWithAuthDataResultAndError( FIRAuthDataResult *result = [[FIRAuthDataResult alloc] initWithUser:self additionalUserInfo:additionalUserInfo]; // Update the new token and refresh user info again. - _tokenService = [[FIRSecureTokenService alloc] + self->_tokenService = [[FIRSecureTokenService alloc] initWithRequestConfiguration:requestConfiguration accessToken:response.IDToken accessTokenExpirationDate:response.approximateExpirationDate @@ -939,7 +940,7 @@ static void callInMainThreadWithAuthDataResultAndError( completeWithError(nil, error); return; } - _anonymous = NO; + self->_anonymous = NO; [self updateWithGetAccountInfoResponse:response]; if (![self updateKeychain:&error]) { completeWithError(nil, error); @@ -967,19 +968,19 @@ static void callInMainThreadWithAuthDataResultAndError( completeAndCallbackWithError(error); return; } - FIRAuthRequestConfiguration *requestConfiguration = _auth.requestConfiguration; + FIRAuthRequestConfiguration *requestConfiguration = self->_auth.requestConfiguration; FIRSetAccountInfoRequest *setAccountInfoRequest = [[FIRSetAccountInfoRequest alloc] initWithRequestConfiguration:requestConfiguration]; setAccountInfoRequest.accessToken = accessToken; BOOL isEmailPasswordProvider = [provider isEqualToString:FIREmailAuthProviderID]; if (isEmailPasswordProvider) { - if (!_hasEmailPasswordCredential) { + if (!self->_hasEmailPasswordCredential) { completeAndCallbackWithError([FIRAuthErrorUtils noSuchProviderError]); return; } setAccountInfoRequest.deleteAttributes = @[ FIRSetAccountInfoUserAttributePassword ]; } else { - if (!_providerData[provider]) { + if (!self->_providerData[provider]) { completeAndCallbackWithError([FIRAuthErrorUtils noSuchProviderError]); return; } @@ -994,19 +995,19 @@ static void callInMainThreadWithAuthDataResultAndError( return; } if (isEmailPasswordProvider) { - _hasEmailPasswordCredential = NO; + self->_hasEmailPasswordCredential = NO; } else { // We can't just use the provider info objects in FIRSetAcccountInfoResponse because they // don't have localID and email fields. Remove the specific provider manually. - NSMutableDictionary *mutableProviderData = [_providerData mutableCopy]; + NSMutableDictionary *mutableProviderData = [self->_providerData mutableCopy]; [mutableProviderData removeObjectForKey:provider]; - _providerData = [mutableProviderData copy]; + self->_providerData = [mutableProviderData copy]; #if TARGET_OS_IOS // After successfully unlinking a phone auth provider, remove the phone number from the // cached user info. if ([provider isEqualToString:FIRPhoneAuthProviderID]) { - _phoneNumber = nil; + self->_phoneNumber = nil; } #endif } @@ -1060,7 +1061,7 @@ static void callInMainThreadWithAuthDataResultAndError( callInMainThreadWithError(completion, error); return; } - FIRAuthRequestConfiguration *configuration = _auth.requestConfiguration; + FIRAuthRequestConfiguration *configuration = self->_auth.requestConfiguration; FIRGetOOBConfirmationCodeRequest *request = [FIRGetOOBConfirmationCodeRequest verifyEmailRequestWithAccessToken:accessToken actionCodeSettings:actionCodeSettings @@ -1085,15 +1086,15 @@ static void callInMainThreadWithAuthDataResultAndError( return; } FIRDeleteAccountRequest *deleteUserRequest = - [[FIRDeleteAccountRequest alloc] initWitLocalID:_userID + [[FIRDeleteAccountRequest alloc] initWitLocalID:self->_userID accessToken:accessToken - requestConfiguration:_auth.requestConfiguration]; + requestConfiguration:self->_auth.requestConfiguration]; [FIRAuthBackend deleteAccount:deleteUserRequest callback:^(NSError *_Nullable error) { if (error) { callInMainThreadWithError(completion, error); return; } - if (![_auth signOutByForceWithUserID:_userID error:&error]) { + if (![self->_auth signOutByForceWithUserID:self->_userID error:&error]) { callInMainThreadWithError(completion, error); return; } @@ -1167,14 +1168,14 @@ static void callInMainThreadWithAuthDataResultAndError( - (void)setDisplayName:(nullable NSString *)displayName { dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - if (_consumed) { + if (self->_consumed) { [NSException raise:NSInternalInconsistencyException format:@"%@", @"Invalid call to setDisplayName: after commitChangesWithCallback:."]; return; } - _displayNameSet = YES; - _displayName = [displayName copy]; + self->_displayNameSet = YES; + self->_displayName = [displayName copy]; }); } @@ -1184,14 +1185,14 @@ static void callInMainThreadWithAuthDataResultAndError( - (void)setPhotoURL:(nullable NSURL *)photoURL { dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - if (_consumed) { + if (self->_consumed) { [NSException raise:NSInternalInconsistencyException format:@"%@", @"Invalid call to setPhotoURL: after commitChangesWithCallback:."]; return; } - _photoURLSet = YES; - _photoURL = [photoURL copy]; + self->_photoURLSet = YES; + self->_photoURL = [photoURL copy]; }); } @@ -1204,24 +1205,24 @@ static void callInMainThreadWithAuthDataResultAndError( - (void)commitChangesWithCompletion:(nullable FIRUserProfileChangeCallback)completion { dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ - if (_consumed) { + if (self->_consumed) { [NSException raise:NSInternalInconsistencyException format:@"%@", @"commitChangesWithCallback: should only be called once."]; return; } - _consumed = YES; + self->_consumed = YES; // Return fast if there is nothing to update: if (![self hasUpdates]) { callInMainThreadWithError(completion, nil); return; } - NSString *displayName = [_displayName copy]; - BOOL displayNameWasSet = _displayNameSet; - NSURL *photoURL = [_photoURL copy]; - BOOL photoURLWasSet = _photoURLSet; - [_user executeUserUpdateWithChanges:^(FIRGetAccountInfoResponseUser *user, - FIRSetAccountInfoRequest *request) { + NSString *displayName = [self->_displayName copy]; + BOOL displayNameWasSet = self->_displayNameSet; + NSURL *photoURL = [self->_photoURL copy]; + BOOL photoURLWasSet = self->_photoURLSet; + [self->_user executeUserUpdateWithChanges:^(FIRGetAccountInfoResponseUser *user, + FIRSetAccountInfoRequest *request) { if (photoURLWasSet) { request.photoURL = photoURL; } @@ -1235,12 +1236,12 @@ static void callInMainThreadWithAuthDataResultAndError( return; } if (displayNameWasSet) { - [_user setDisplayName:displayName]; + [self->_user setDisplayName:displayName]; } if (photoURLWasSet) { - [_user setPhotoURL:photoURL]; + [self->_user setPhotoURL:photoURL]; } - if (![_user updateKeychain:&error]) { + if (![self->_user updateKeychain:&error]) { callInMainThreadWithError(completion, error); return; } diff --git a/FirebaseFirestoreSwift.podspec b/FirebaseFirestoreSwift.podspec new file mode 100644 index 0000000..6843070 --- /dev/null +++ b/FirebaseFirestoreSwift.podspec @@ -0,0 +1,37 @@ +# +# Be sure to run `pod lib lint FirebaseFirestoreSwift.podspec' to ensure this is a +# valid spec before submitting. +# + +Pod::Spec.new do |s| + s.name = 'FirebaseFirestoreSwift' + s.version = '0.1' + s.summary = 'Google Cloud Firestore for iOS Swift Extensions' + + s.description = <<-DESC +Google Cloud Firestore is a NoSQL document database built for automatic scaling, high performance, and ease of application development. + DESC + + s.homepage = 'https://developers.google.com/' + s.license = { :type => 'Apache', :file => 'LICENSE' } + s.authors = 'Google, Inc.' + + s.source = { + :git => 'https://github.com/Firebase/firebase-ios-sdk.git', + :tag => s.version.to_s + } + + s.swift_version = '4.0' + s.ios.deployment_target = '8.0' + + s.cocoapods_version = '>= 1.4.0' + s.static_framework = true + s.prefix_header_file = false + + s.requires_arc = true + s.source_files = [ + 'Firestore/Swift/Source/**/*.swift', + ] + + s.dependency 'FirebaseFirestore', ">= 0.10.0" +end diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index 6287462..92b4b7b 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -13,9 +13,10 @@ buildPhases = ( ); dependencies = ( - DE0761FA1F2FEE7E003233AF /* PBXTargetDependency */, DE29E7FA1F2174DD00909613 /* PBXTargetDependency */, + 54C9EDFF2040E41900A969CD /* PBXTargetDependency */, DE29E7FC1F2174DD00909613 /* PBXTargetDependency */, + DE0761FA1F2FEE7E003233AF /* PBXTargetDependency */, ); name = AllTests; productName = AllTests; @@ -106,6 +107,7 @@ 5492E0C82021557E00B64F25 /* FSTDatastoreTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0C22021557E00B64F25 /* FSTDatastoreTests.mm */; }; 5492E0C92021557E00B64F25 /* FSTRemoteEventTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0C32021557E00B64F25 /* FSTRemoteEventTests.mm */; }; 5492E0CA2021557E00B64F25 /* FSTWatchChangeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0C52021557E00B64F25 /* FSTWatchChangeTests.mm */; }; + 5495EB032040E90200EBA509 /* CodableGeoPointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5495EB022040E90200EBA509 /* CodableGeoPointTests.swift */; }; 54C2294F1FECABAE007D065B /* log_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54C2294E1FECABAE007D065B /* log_test.cc */; }; 54DA12A61F315EE100DD57A1 /* collection_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA129C1F315EE100DD57A1 /* collection_spec_test.json */; }; 54DA12A71F315EE100DD57A1 /* existence_filter_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA129D1F315EE100DD57A1 /* existence_filter_spec_test.json */; }; @@ -169,10 +171,25 @@ DE2EF0861F3D0B6E003D0CDC /* FSTImmutableSortedDictionary+Testing.m in Sources */ = {isa = PBXBuildFile; fileRef = DE2EF0801F3D0B6E003D0CDC /* FSTImmutableSortedDictionary+Testing.m */; }; DE2EF0871F3D0B6E003D0CDC /* FSTImmutableSortedSet+Testing.m in Sources */ = {isa = PBXBuildFile; fileRef = DE2EF0821F3D0B6E003D0CDC /* FSTImmutableSortedSet+Testing.m */; }; DE2EF0881F3D0B6E003D0CDC /* FSTTreeSortedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE2EF0841F3D0B6E003D0CDC /* FSTTreeSortedDictionaryTests.m */; }; + DEF43C59D90C3CF3CA34DDF4 /* Pods_Firestore_Example_Firestore_SwiftTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 245812330F6A31632BB4B623 /* Pods_Firestore_Example_Firestore_SwiftTests_iOS.framework */; }; F104BBD69BC3F0796E3A77C1 /* Pods_Firestore_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69F6A10DBD6187489481CD76 /* Pods_Firestore_Tests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 54C9EDF62040E16300A969CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6003F582195388D10070C39A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6003F589195388D20070C39A; + remoteInfo = Firestore_Example; + }; + 54C9EDFE2040E41900A969CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6003F582195388D10070C39A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 54C9EDF02040E16300A969CD; + remoteInfo = Firestore_SwiftTests_iOS; + }; 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6003F582195388D10070C39A /* Project object */; @@ -213,8 +230,10 @@ /* Begin PBXFileReference section */ 04DF37A117F88A9891379ED6 /* Pods-Firestore_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Tests/Pods-Firestore_Tests.release.xcconfig"; sourceTree = "<group>"; }; 12F4357299652983A615F886 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; }; + 245812330F6A31632BB4B623 /* Pods_Firestore_Example_Firestore_SwiftTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_Firestore_SwiftTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 32AD40BF6B0E849B07FFD05E /* Pods_SwiftBuildTest.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftBuildTest.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B843E4A1F3930A400548890 /* remote_store_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = remote_store_spec_test.json; sourceTree = "<group>"; }; + 3F422FFBDA6E79396E2FB594 /* Pods-Firestore_Example-Firestore_SwiftTests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example-Firestore_SwiftTests_iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example-Firestore_SwiftTests_iOS/Pods-Firestore_Example-Firestore_SwiftTests_iOS.debug.xcconfig"; sourceTree = "<group>"; }; 42491D7DC8C8CD245CC22B93 /* Pods-SwiftBuildTest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftBuildTest.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftBuildTest/Pods-SwiftBuildTest.debug.xcconfig"; sourceTree = "<group>"; }; 4EBC5F5ABE1FD097EFE5E224 /* Pods-Firestore_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example/Pods-Firestore_Example.release.xcconfig"; sourceTree = "<group>"; }; 5436F32320008FAD006E51E3 /* string_printf_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_printf_test.cc; path = ../../core/test/firebase/firestore/util/string_printf_test.cc; sourceTree = "<group>"; }; @@ -304,7 +323,10 @@ 5492E0C32021557E00B64F25 /* FSTRemoteEventTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTRemoteEventTests.mm; sourceTree = "<group>"; }; 5492E0C42021557E00B64F25 /* FSTWatchChange+Testing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FSTWatchChange+Testing.h"; sourceTree = "<group>"; }; 5492E0C52021557E00B64F25 /* FSTWatchChangeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTWatchChangeTests.mm; sourceTree = "<group>"; }; + 5495EB022040E90200EBA509 /* CodableGeoPointTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodableGeoPointTests.swift; sourceTree = "<group>"; }; 54C2294E1FECABAE007D065B /* log_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = log_test.cc; path = ../../core/test/firebase/firestore/util/log_test.cc; sourceTree = "<group>"; }; + 54C9EDF12040E16300A969CD /* Firestore_SwiftTests_iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Firestore_SwiftTests_iOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 54C9EDF52040E16300A969CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 54DA129C1F315EE100DD57A1 /* collection_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = collection_spec_test.json; sourceTree = "<group>"; }; 54DA129D1F315EE100DD57A1 /* existence_filter_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = existence_filter_spec_test.json; sourceTree = "<group>"; }; 54DA129E1F315EE100DD57A1 /* limbo_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = limbo_spec_test.json; sourceTree = "<group>"; }; @@ -366,6 +388,7 @@ B65D34A7203C99090076A5E1 /* FIRTimestampTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRTimestampTest.m; sourceTree = "<group>"; }; B686F2AD2023DDB20028D6BE /* field_path_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = field_path_test.cc; sourceTree = "<group>"; }; B686F2B02024FFD70028D6BE /* resource_path_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resource_path_test.cc; sourceTree = "<group>"; }; + C1D89E5405935366C88CC3E5 /* Pods-Firestore_Example-Firestore_SwiftTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example-Firestore_SwiftTests_iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example-Firestore_SwiftTests_iOS/Pods-Firestore_Example-Firestore_SwiftTests_iOS.release.xcconfig"; sourceTree = "<group>"; }; CE00BABB5A3AAB44A4C209E2 /* Pods-Firestore_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Tests/Pods-Firestore_Tests.debug.xcconfig"; sourceTree = "<group>"; }; D3CC3DC5338DCAF43A211155 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; }; DB17FEDFB80770611A935A60 /* Pods-Firestore_IntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_IntegrationTests/Pods-Firestore_IntegrationTests.release.xcconfig"; sourceTree = "<group>"; }; @@ -389,6 +412,14 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 54C9EDEE2040E16300A969CD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DEF43C59D90C3CF3CA34DDF4 /* Pods_Firestore_Example_Firestore_SwiftTests_iOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 6003F587195388D20070C39A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -474,6 +505,24 @@ name = GoogleTests; sourceTree = "<group>"; }; + 5495EB012040E90200EBA509 /* Codable */ = { + isa = PBXGroup; + children = ( + 5495EB022040E90200EBA509 /* CodableGeoPointTests.swift */, + ); + path = Codable; + sourceTree = "<group>"; + }; + 54C9EDF22040E16300A969CD /* SwiftTests */ = { + isa = PBXGroup; + children = ( + 5495EB012040E90200EBA509 /* Codable */, + 54C9EDF52040E16300A969CD /* Info.plist */, + ); + name = SwiftTests; + path = ../Swift/Tests; + sourceTree = "<group>"; + }; 54EB764B202277970088B8F3 /* immutable */ = { isa = PBXGroup; children = ( @@ -489,6 +538,7 @@ 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 6003F593195388D20070C39A /* Example for Firestore */, 6003F5B5195388D20070C39A /* Tests */, + 54C9EDF22040E16300A969CD /* SwiftTests */, DE0761E51F2FE611003233AF /* SwiftBuildTest */, 6003F58C195388D20070C39A /* Frameworks */, 6003F58B195388D20070C39A /* Products */, @@ -503,6 +553,7 @@ 6003F5AE195388D20070C39A /* Firestore_Tests.xctest */, DE03B2E91F2149D600A30B9C /* Firestore_IntegrationTests.xctest */, DE0761E41F2FE611003233AF /* SwiftBuildTest.app */, + 54C9EDF12040E16300A969CD /* Firestore_SwiftTests_iOS.xctest */, ); name = Products; sourceTree = "<group>"; @@ -518,6 +569,7 @@ 69F6A10DBD6187489481CD76 /* Pods_Firestore_Tests.framework */, B2FA635DF5D116A67A7441CD /* Pods_Firestore_IntegrationTests.framework */, 32AD40BF6B0E849B07FFD05E /* Pods_SwiftBuildTest.framework */, + 245812330F6A31632BB4B623 /* Pods_Firestore_Example_Firestore_SwiftTests_iOS.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -596,6 +648,8 @@ 04DF37A117F88A9891379ED6 /* Pods-Firestore_Tests.release.xcconfig */, 42491D7DC8C8CD245CC22B93 /* Pods-SwiftBuildTest.debug.xcconfig */, F23325524BEAF8D24F78AC88 /* Pods-SwiftBuildTest.release.xcconfig */, + 3F422FFBDA6E79396E2FB594 /* Pods-Firestore_Example-Firestore_SwiftTests_iOS.debug.xcconfig */, + C1D89E5405935366C88CC3E5 /* Pods-Firestore_Example-Firestore_SwiftTests_iOS.release.xcconfig */, ); name = Pods; sourceTree = "<group>"; @@ -839,6 +893,27 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 54C9EDF02040E16300A969CD /* Firestore_SwiftTests_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 54C9EDFA2040E16300A969CD /* Build configuration list for PBXNativeTarget "Firestore_SwiftTests_iOS" */; + buildPhases = ( + 6FB7F3A6D6ADAC64E4972A29 /* [CP] Check Pods Manifest.lock */, + 54C9EDED2040E16300A969CD /* Sources */, + 54C9EDEE2040E16300A969CD /* Frameworks */, + 54C9EDEF2040E16300A969CD /* Resources */, + 9E2D564AC55ADE2D52B7E951 /* [CP] Embed Pods Frameworks */, + A650E34A01FE620F7B26F5FF /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 54C9EDF72040E16300A969CD /* PBXTargetDependency */, + ); + name = Firestore_SwiftTests_iOS; + productName = Firestore_SwiftTests_iOS; + productReference = 54C9EDF12040E16300A969CD /* Firestore_SwiftTests_iOS.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 6003F589195388D20070C39A /* Firestore_Example */ = { isa = PBXNativeTarget; buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "Firestore_Example" */; @@ -928,10 +1003,15 @@ isa = PBXProject; attributes = { CLASSPREFIX = FIR; - LastSwiftUpdateCheck = 0830; + LastSwiftUpdateCheck = 0920; LastUpgradeCheck = 0720; ORGANIZATIONNAME = Google; TargetAttributes = { + 54C9EDF02040E16300A969CD = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + TestTargetID = 6003F589195388D20070C39A; + }; 6003F5AD195388D20070C39A = { DevelopmentTeam = EQHXZ8M8AV; TestTargetID = 6003F589195388D20070C39A; @@ -965,6 +1045,7 @@ targets = ( 6003F589195388D20070C39A /* Firestore_Example */, 6003F5AD195388D20070C39A /* Firestore_Tests */, + 54C9EDF02040E16300A969CD /* Firestore_SwiftTests_iOS */, DE03B2941F2149D600A30B9C /* Firestore_IntegrationTests */, DE29E7F51F2174B000909613 /* AllTests */, DE0761E31F2FE611003233AF /* SwiftBuildTest */, @@ -973,6 +1054,13 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 54C9EDEF2040E16300A969CD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 6003F588195388D20070C39A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1071,6 +1159,24 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftBuildTest/Pods-SwiftBuildTest-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + 6FB7F3A6D6ADAC64E4972A29 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Firestore_Example-Firestore_SwiftTests_iOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 7C5123A9C345ECE100DA21BD /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1143,6 +1249,57 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 9E2D564AC55ADE2D52B7E951 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-Firestore_Example-Firestore_SwiftTests_iOS/Pods-Firestore_Example-Firestore_SwiftTests_iOS-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/BoringSSL/openssl.framework", + "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", + "${BUILT_PRODUCTS_DIR}/GoogleToolboxForMac-f0850809/GoogleToolboxForMac.framework", + "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework", + "${BUILT_PRODUCTS_DIR}/gRPC/GRPCClient.framework", + "${BUILT_PRODUCTS_DIR}/gRPC-Core/grpc.framework", + "${BUILT_PRODUCTS_DIR}/gRPC-ProtoRPC/ProtoRPC.framework", + "${BUILT_PRODUCTS_DIR}/gRPC-RxLibrary/RxLibrary.framework", + "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework", + "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/openssl.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleToolboxForMac.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Protobuf.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GRPCClient.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/grpc.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ProtoRPC.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxLibrary.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Firestore_Example-Firestore_SwiftTests_iOS/Pods-Firestore_Example-Firestore_SwiftTests_iOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + A650E34A01FE620F7B26F5FF /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Firestore_Example-Firestore_SwiftTests_iOS/Pods-Firestore_Example-Firestore_SwiftTests_iOS-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; AB3F19DA92555D3399DB07CE /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1271,6 +1428,14 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 54C9EDED2040E16300A969CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5495EB032040E90200EBA509 /* CodableGeoPointTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 6003F586195388D20070C39A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1417,6 +1582,16 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 54C9EDF72040E16300A969CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6003F589195388D20070C39A /* Firestore_Example */; + targetProxy = 54C9EDF62040E16300A969CD /* PBXContainerItemProxy */; + }; + 54C9EDFF2040E41900A969CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 54C9EDF02040E16300A969CD /* Firestore_SwiftTests_iOS */; + targetProxy = 54C9EDFE2040E41900A969CD /* PBXContainerItemProxy */; + }; 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 6003F589195388D20070C39A /* Firestore_Example */; @@ -1472,6 +1647,84 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 54C9EDF82040E16300A969CD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3F422FFBDA6E79396E2FB594 /* Pods-Firestore_Example-Firestore_SwiftTests_iOS.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = ../Swift/Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.google.Firestore-SwiftTests-iOS"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Firestore_Example.app/Firestore_Example"; + }; + name = Debug; + }; + 54C9EDF92040E16300A969CD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C1D89E5405935366C88CC3E5 /* Pods-Firestore_Example-Firestore_SwiftTests_iOS.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = ../Swift/Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.google.Firestore-SwiftTests-iOS"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Firestore_Example.app/Firestore_Example"; + }; + name = Release; + }; 6003F5BD195388D20070C39A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1808,6 +2061,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 54C9EDFA2040E16300A969CD /* Build configuration list for PBXNativeTarget "Firestore_SwiftTests_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 54C9EDF82040E16300A969CD /* Debug */, + 54C9EDF92040E16300A969CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 6003F585195388D10070C39A /* Build configuration list for PBXProject "Firestore" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme index aacb70e..6cf00a9 100644 --- a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme +++ b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme @@ -20,6 +20,20 @@ ReferencedContainer = "container:Firestore.xcodeproj"> </BuildableReference> </BuildActionEntry> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "NO" + buildForProfiling = "NO" + buildForArchiving = "NO" + buildForAnalyzing = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "54C9EDF02040E16300A969CD" + BuildableName = "Firestore_SwiftTests_iOS.xctest" + BlueprintName = "Firestore_SwiftTests_iOS" + ReferencedContainer = "container:Firestore.xcodeproj"> + </BuildableReference> + </BuildActionEntry> </BuildActionEntries> </BuildAction> <TestAction @@ -49,6 +63,16 @@ ReferencedContainer = "container:Firestore.xcodeproj"> </BuildableReference> </TestableReference> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "54C9EDF02040E16300A969CD" + BuildableName = "Firestore_SwiftTests_iOS.xctest" + BlueprintName = "Firestore_SwiftTests_iOS" + ReferencedContainer = "container:Firestore.xcodeproj"> + </BuildableReference> + </TestableReference> </Testables> <MacroExpansion> <BuildableReference diff --git a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Tests.xcscheme b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Tests.xcscheme index 846b772..6f79458 100644 --- a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Tests.xcscheme +++ b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_Tests.xcscheme @@ -20,6 +20,20 @@ ReferencedContainer = "container:Firestore.xcodeproj"> </BuildableReference> </BuildActionEntry> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "54C9EDF02040E16300A969CD" + BuildableName = "Firestore_SwiftTests_iOS.xctest" + BlueprintName = "Firestore_SwiftTests_iOS" + ReferencedContainer = "container:Firestore.xcodeproj"> + </BuildableReference> + </BuildActionEntry> </BuildActionEntries> </BuildAction> <TestAction @@ -39,7 +53,26 @@ ReferencedContainer = "container:Firestore.xcodeproj"> </BuildableReference> </TestableReference> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "54C9EDF02040E16300A969CD" + BuildableName = "Firestore_SwiftTests_iOS.xctest" + BlueprintName = "Firestore_SwiftTests_iOS" + ReferencedContainer = "container:Firestore.xcodeproj"> + </BuildableReference> + </TestableReference> </Testables> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "6003F5AD195388D20070C39A" + BuildableName = "Firestore_Tests.xctest" + BlueprintName = "Firestore_Tests" + ReferencedContainer = "container:Firestore.xcodeproj"> + </BuildableReference> + </MacroExpansion> <AdditionalOptions> </AdditionalOptions> </TestAction> @@ -72,6 +105,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "6003F5AD195388D20070C39A" + BuildableName = "Firestore_Tests.xctest" + BlueprintName = "Firestore_Tests" + ReferencedContainer = "container:Firestore.xcodeproj"> + </BuildableReference> + </MacroExpansion> </ProfileAction> <AnalyzeAction buildConfiguration = "Debug"> diff --git a/Firestore/Example/Podfile b/Firestore/Example/Podfile index 5fa6a95..2c38cd9 100644 --- a/Firestore/Example/Podfile +++ b/Firestore/Example/Podfile @@ -28,6 +28,11 @@ target 'Firestore_Example' do pod 'OCMock' end + + target 'Firestore_SwiftTests_iOS' do + pod 'FirebaseFirestore', :path => '../../' + pod 'FirebaseFirestoreSwift', :path => '../../' + end end target 'SwiftBuildTest' do diff --git a/Firestore/Example/SwiftBuildTest/main.swift b/Firestore/Example/SwiftBuildTest/main.swift index 260735b..cd2462b 100644 --- a/Firestore/Example/SwiftBuildTest/main.swift +++ b/Firestore/Example/SwiftBuildTest/main.swift @@ -19,223 +19,215 @@ import Foundation import FirebaseFirestore func main() { - let db = initializeDb(); + let db = initializeDb() - let (collectionRef, documentRef) = makeRefs(database: db); + let (collectionRef, documentRef) = makeRefs(database: db) - let query = makeQuery(collection: collectionRef); + let query = makeQuery(collection: collectionRef) - writeDocument(at: documentRef); + writeDocument(at: documentRef) - writeDocuments(at: documentRef, database: db); + writeDocuments(at: documentRef, database: db) - addDocument(to: collectionRef); + addDocument(to: collectionRef) - readDocument(at: documentRef); + readDocument(at: documentRef) - readDocuments(matching: query); + readDocuments(matching: query) - listenToDocument(at: documentRef); + listenToDocument(at: documentRef) - listenToDocuments(matching: query); + listenToDocuments(matching: query) - enableDisableNetwork(database: db); + enableDisableNetwork(database: db) - types(); + types() } func initializeDb() -> Firestore { + // Initialize with ProjectID. + let firestore = Firestore.firestore() - // Initialize with ProjectID. - let firestore = Firestore.firestore() + // Apply settings + let settings = FirestoreSettings() + settings.host = "localhost" + settings.isPersistenceEnabled = true + firestore.settings = settings - // Apply settings - let settings = FirestoreSettings() - settings.host = "localhost" - settings.isPersistenceEnabled = true - firestore.settings = settings - - return firestore; + return firestore } func makeRefs(database db: Firestore) -> (CollectionReference, DocumentReference) { + var collectionRef = db.collection("my-collection") - var collectionRef = db.collection("my-collection") - - var documentRef: DocumentReference; - documentRef = collectionRef.document("my-doc") - // or - documentRef = db.document("my-collection/my-doc") + var documentRef: DocumentReference + documentRef = collectionRef.document("my-doc") + // or + documentRef = db.document("my-collection/my-doc") - // deeper collection (my-collection/my-doc/some/deep/collection) - collectionRef = documentRef.collection("some/deep/collection") + // deeper collection (my-collection/my-doc/some/deep/collection) + collectionRef = documentRef.collection("some/deep/collection") - // parent doc (my-collection/my-doc/some/deep) - documentRef = collectionRef.parent! + // parent doc (my-collection/my-doc/some/deep) + documentRef = collectionRef.parent! - // print paths. - print("Collection: \(collectionRef.path), document: \(documentRef.path)") + // print paths. + print("Collection: \(collectionRef.path), document: \(documentRef.path)") - return (collectionRef, documentRef); + return (collectionRef, documentRef) } func makeQuery(collection collectionRef: CollectionReference) -> Query { - - let query = collectionRef.whereField(FieldPath(["name"]), isEqualTo: "Fred") - .whereField("age", isGreaterThanOrEqualTo: 24) - .whereField(FieldPath.documentID(), isEqualTo: "fred") - .order(by: FieldPath(["age"])) - .order(by: "name", descending: true) - .limit(to: 10) - - return query; + let query = collectionRef.whereField(FieldPath(["name"]), isEqualTo: "Fred") + .whereField("age", isGreaterThanOrEqualTo: 24) + .whereField(FieldPath.documentID(), isEqualTo: "fred") + .order(by: FieldPath(["age"])) + .order(by: "name", descending: true) + .limit(to: 10) + + return query } func writeDocument(at docRef: DocumentReference) { - - let setData = [ - "foo": 42, - "bar": [ - "baz": "Hello world!" - ] - ] as [String : Any]; - - let updateData = [ - "bar.baz": 42, - FieldPath(["foobar"]) : 42 - ] as [AnyHashable : Any]; - - docRef.setData(setData) - - // Completion callback (via trailing closure syntax). - docRef.setData(setData) { error in - if let error = error { - print("Uh oh! \(error)") - return - } - - print("Set complete!") + let setData = [ + "foo": 42, + "bar": [ + "baz": "Hello world!", + ], + ] as [String: Any] + + let updateData = [ + "bar.baz": 42, + FieldPath(["foobar"]): 42, + ] as [AnyHashable: Any] + + docRef.setData(setData) + + // Completion callback (via trailing closure syntax). + docRef.setData(setData) { error in + if let error = error { + print("Uh oh! \(error)") + return } - // SetOptions - docRef.setData(setData, options:SetOptions.merge()) + print("Set complete!") + } - docRef.updateData(updateData) - docRef.delete(); + // SetOptions + docRef.setData(setData, options: SetOptions.merge()) - docRef.delete() { error in - if let error = error { - print("Uh oh! \(error)") - return - } + docRef.updateData(updateData) + docRef.delete() - print("Set complete!") + docRef.delete { error in + if let error = error { + print("Uh oh! \(error)") + return } + + print("Set complete!") + } } func enableDisableNetwork(database db: Firestore) { - // closure syntax - db.disableNetwork(completion: { (error) in - if let e = error { - print("Uh oh! \(e)") - return - } - }) - // trailing block syntax - db.enableNetwork { (error) in - if let e = error { - print("Uh oh! \(e)") - return - } + // closure syntax + db.disableNetwork(completion: { error in + if let e = error { + print("Uh oh! \(e)") + return } + }) + // trailing block syntax + db.enableNetwork { error in + if let e = error { + print("Uh oh! \(e)") + return + } + } } func writeDocuments(at docRef: DocumentReference, database db: Firestore) { - var batch: WriteBatch; + var batch: WriteBatch - batch = db.batch(); - batch.setData(["a" : "b"], forDocument:docRef); - batch.setData(["c" : "d"], forDocument:docRef); + batch = db.batch() + batch.setData(["a": "b"], forDocument: docRef) + batch.setData(["c": "d"], forDocument: docRef) // commit without completion callback. - batch.commit(); - print("Batch write without completion complete!"); + batch.commit() + print("Batch write without completion complete!") - batch = db.batch(); - batch.setData(["a" : "b"], forDocument:docRef); - batch.setData(["c" : "d"], forDocument:docRef); + batch = db.batch() + batch.setData(["a": "b"], forDocument: docRef) + batch.setData(["c": "d"], forDocument: docRef) // commit with completion callback via trailing closure syntax. - batch.commit() { error in + batch.commit { error in if let error = error { - print("Uh oh! \(error)"); - return; + print("Uh oh! \(error)") + return } - print("Batch write callback complete!"); + print("Batch write callback complete!") } - print("Batch write with completion complete!"); + print("Batch write with completion complete!") } func addDocument(to collectionRef: CollectionReference) { - - collectionRef.addDocument(data: ["foo": 42]); - //or - collectionRef.document().setData(["foo": 42]); + collectionRef.addDocument(data: ["foo": 42]) + // or + collectionRef.document().setData(["foo": 42]) } func readDocument(at docRef: DocumentReference) { - - // Trailing closure syntax. - docRef.getDocument() { document, error in - if let document = document { - // Note that both document and document.data() is nullable. - if let data = document.data() { - print("Read document: \(data)") - } - if let data = document.data(with:SnapshotOptions.serverTimestampBehavior(.estimate)) { - print("Read document: \(data)") - } - if let foo = document.get("foo") { - print("Field: \(foo)") - } - if let foo = document.get("foo", options: SnapshotOptions.serverTimestampBehavior(.previous)) { - print("Field: \(foo)") - } - // Fields can also be read via subscript notation. - if let foo = document["foo"] { - print("Field: \(foo)") - } - } else { - // TODO(mikelehen): There may be a better way to do this, but it at least demonstrates - // the swift error domain / enum codes are renamed appropriately. - if let errorCode = error.flatMap({ - ($0._domain == FirestoreErrorDomain) ? FirestoreErrorCode (rawValue: $0._code) : nil - }) { - switch errorCode { - case .unavailable: - print("Can't read document due to being offline!") - case _: - print("Failed to read.") - } - } else { - print("Unknown error!") - } + // Trailing closure syntax. + docRef.getDocument { document, error in + if let document = document { + // Note that both document and document.data() is nullable. + if let data = document.data() { + print("Read document: \(data)") + } + if let data = document.data(with: SnapshotOptions.serverTimestampBehavior(.estimate)) { + print("Read document: \(data)") + } + if let foo = document.get("foo") { + print("Field: \(foo)") + } + if let foo = document.get("foo", options: SnapshotOptions.serverTimestampBehavior(.previous)) { + print("Field: \(foo)") + } + // Fields can also be read via subscript notation. + if let foo = document["foo"] { + print("Field: \(foo)") + } + } else { + // TODO(mikelehen): There may be a better way to do this, but it at least demonstrates + // the swift error domain / enum codes are renamed appropriately. + if let errorCode = error.flatMap({ + ($0._domain == FirestoreErrorDomain) ? FirestoreErrorCode(rawValue: $0._code) : nil + }) { + switch errorCode { + case .unavailable: + print("Can't read document due to being offline!") + case _: + print("Failed to read.") } - + } else { + print("Unknown error!") + } } + } } func readDocuments(matching query: Query) { - query.getDocuments() { querySnapshot, error in - // TODO(mikelehen): Figure out how to make "for..in" syntax work - // directly on documentSet. - for document in querySnapshot!.documents { - print(document.data()) - } + query.getDocuments { querySnapshot, error in + // TODO(mikelehen): Figure out how to make "for..in" syntax work + // directly on documentSet. + for document in querySnapshot!.documents { + print(document.data()) } + } } func listenToDocument(at docRef: DocumentReference) { - - let listener = docRef.addSnapshotListener() { document, error in + let listener = docRef.addSnapshotListener { document, error in if let error = error { print("Uh oh! Listen canceled: \(error)") return @@ -243,8 +235,8 @@ func listenToDocument(at docRef: DocumentReference) { if let document = document { // Note that document.data() is nullable. - if let data : [String:Any] = document.data() { - print("Current document: \(data)"); + if let data: [String: Any] = document.data() { + print("Current document: \(data)") } if document.metadata.isFromCache { print("From Cache") @@ -255,100 +247,98 @@ func listenToDocument(at docRef: DocumentReference) { } // Unsubscribe. - listener.remove(); + listener.remove() } func listenToDocuments(matching query: Query) { + let listener = query.addSnapshotListener { snap, error in + if let error = error { + print("Uh oh! Listen canceled: \(error)") + return + } - let listener = query.addSnapshotListener() { snap, error in - if let error = error { - print("Uh oh! Listen canceled: \(error)") - return - } - - if let snap = snap { - print("NEW SNAPSHOT (empty=\(snap.isEmpty) count=\(snap.count)") + if let snap = snap { + print("NEW SNAPSHOT (empty=\(snap.isEmpty) count=\(snap.count)") - // TODO(mikelehen): Figure out how to make "for..in" syntax work - // directly on documentSet. - for document in snap.documents { - // Note that document.data() is not nullable. - let data : [String:Any] = document.data() - print("Doc: ", data) - } - } + // TODO(mikelehen): Figure out how to make "for..in" syntax work + // directly on documentSet. + for document in snap.documents { + // Note that document.data() is not nullable. + let data: [String: Any] = document.data() + print("Doc: ", data) + } } + } - // Unsubscribe - listener.remove(); + // Unsubscribe + listener.remove() } func listenToQueryDiffs(onQuery query: Query) { - - let listener = query.addSnapshotListener() { snap, error in - if let snap = snap { - for change in snap.documentChanges { - switch (change.type) { - case .added: - print("New document: \(change.document.data())") - case .modified: - print("Modified document: \(change.document.data())") - case .removed: - print("Removed document: \(change.document.data())") - } - } + let listener = query.addSnapshotListener { snap, error in + if let snap = snap { + for change in snap.documentChanges { + switch change.type { + case .added: + print("New document: \(change.document.data())") + case .modified: + print("Modified document: \(change.document.data())") + case .removed: + print("Removed document: \(change.document.data())") } + } } + } - // Unsubscribe - listener.remove(); + // Unsubscribe + listener.remove() } func transactions() { - let db = Firestore.firestore() - - let collectionRef = db.collection("cities") - let accA = collectionRef.document("accountA") - let accB = collectionRef.document("accountB") - let amount = 20.0 - - db.runTransaction({ (transaction, errorPointer) -> Any? in - do { - let balanceA = try transaction.getDocument(accA)["balance"] as! Double - let balanceB = try transaction.getDocument(accB)["balance"] as! Double - - if balanceA < amount { - errorPointer?.pointee = NSError(domain: "Foo", code: 123, userInfo: nil) - return nil - } - transaction.updateData(["balance": balanceA - amount], forDocument:accA) - transaction.updateData(["balance": balanceB + amount], forDocument:accB) - } catch let error as NSError { - print("Uh oh! \(error)") - } - return 0 - }) { (result, error) in - // handle result. + let db = Firestore.firestore() + + let collectionRef = db.collection("cities") + let accA = collectionRef.document("accountA") + let accB = collectionRef.document("accountB") + let amount = 20.0 + + db.runTransaction({ (transaction, errorPointer) -> Any? in + do { + let balanceA = try transaction.getDocument(accA)["balance"] as! Double + let balanceB = try transaction.getDocument(accB)["balance"] as! Double + + if balanceA < amount { + errorPointer?.pointee = NSError(domain: "Foo", code: 123, userInfo: nil) + return nil + } + transaction.updateData(["balance": balanceA - amount], forDocument: accA) + transaction.updateData(["balance": balanceB + amount], forDocument: accB) + } catch let error as NSError { + print("Uh oh! \(error)") } + return 0 + }) { result, error in + // handle result. + } } func types() { - let _: CollectionReference; - let _: DocumentChange; - let _: DocumentListenOptions; - let _: DocumentReference; - let _: DocumentSnapshot; - let _: FieldPath; - let _: FieldValue; - let _: Firestore; - let _: FirestoreSettings; - let _: GeoPoint; - let _: ListenerRegistration; - let _: QueryListenOptions; - let _: Query; - let _: QuerySnapshot; - let _: SetOptions; - let _: SnapshotMetadata; - let _: Transaction; - let _: WriteBatch; + let _: CollectionReference + let _: DocumentChange + let _: DocumentListenOptions + let _: DocumentReference + let _: DocumentSnapshot + let _: FieldPath + let _: FieldValue + let _: Firestore + let _: FirestoreSettings + let _: GeoPoint + let _: ListenerRegistration + let _: QueryListenOptions + let _: Query + let _: QuerySnapshot + let _: SetOptions + let _: SnapshotMetadata + let _: Transaction + let _: WriteBatch } diff --git a/Firestore/Swift/Source/Codable/CodableGeoPoint.swift b/Firestore/Swift/Source/Codable/CodableGeoPoint.swift new file mode 100644 index 0000000..fa56340 --- /dev/null +++ b/Firestore/Swift/Source/Codable/CodableGeoPoint.swift @@ -0,0 +1,62 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import FirebaseFirestore + +/** + * A protocol describing the encodable properties of a GeoPoint. + * + * Note: this protocol exists as a workaround for the Swift compiler: if the GeoPoint class was + * extended directly to conform to Codable, the methods implementing the protcol would be need to be + * marked required but that can't be done in an extension. Declaring the extension on the protocol + * sidesteps this issue. + */ +fileprivate protocol CodableGeoPoint: Codable { + var latitude: Double { get } + var longitude: Double { get } + + init(latitude: Double, longitude: Double) +} + +/** The keys in a GeoPoint. Must match the properties of CodableGeoPoint. */ +fileprivate enum GeoPointKeys: String, CodingKey { + case latitude + case longitude +} + +/** + * An extension of GeoPoint that implements the behavior of the Codable protocol. + * + * Note: this is implemented manually here because the Swift compiler can't synthesize these methods + * when declaring an extension to conform to Codable. + */ +extension CodableGeoPoint { + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: GeoPointKeys.self) + let latitude = try container.decode(Double.self, forKey: .latitude) + let longitude = try container.decode(Double.self, forKey: .longitude) + self.init(latitude: latitude, longitude: longitude) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: GeoPointKeys.self) + try container.encode(latitude, forKey: .latitude) + try container.encode(longitude, forKey: .longitude) + } +} + +/** Extends GeoPoint to conform to Codable. */ +extension GeoPoint: CodableGeoPoint {} diff --git a/Firestore/Swift/Tests/Codable/CodableGeoPointTests.swift b/Firestore/Swift/Tests/Codable/CodableGeoPointTests.swift new file mode 100644 index 0000000..6b1dce4 --- /dev/null +++ b/Firestore/Swift/Tests/Codable/CodableGeoPointTests.swift @@ -0,0 +1,49 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import FirebaseFirestore +import FirebaseFirestoreSwift +import Foundation +import XCTest + +class CodableGeoPointTests: XCTestCase { + func testGeoPointEncodes() { + let geoPoint = GeoPoint(latitude: 37.77493, longitude: -122.41942) + + let jsonData = try! JSONEncoder().encode(geoPoint) + let json = String(data: jsonData, encoding: .utf8)! + + // The ordering of attributes in the JSON output is not guaranteed, nor is the rounding of + // the values so just verify that each required property is present and that the value + // starts as expected. + XCTAssert(json.contains("\"latitude\":37.")) + XCTAssert(json.contains("\"longitude\":-122.")) + } + + func testGeoPointDecodes() { + let json = """ + { + "latitude": 37.77493, + "longitude": -122.41942 + } + """ + let jsonData: Data = json.data(using: .utf8)! + + let geoPoint = try! JSONDecoder().decode(GeoPoint.self, from: jsonData) + XCTAssertEqual(37.77493, geoPoint.latitude, accuracy: 0.0001) + XCTAssertEqual(-122.41942, geoPoint.longitude, accuracy: 0.0001) + } +} diff --git a/Firestore/Swift/Tests/Info.plist b/Firestore/Swift/Tests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/Firestore/Swift/Tests/Info.plist @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleVersion</key> + <string>1</string> +</dict> +</plist> diff --git a/scripts/style.sh b/scripts/style.sh index b4c495d..e2f8207 100755 --- a/scripts/style.sh +++ b/scripts/style.sh @@ -21,19 +21,61 @@ # Commonly # ./scripts/style.sh master -if [[ $(clang-format --version) != **"version 6"** ]]; then +system=$(uname -s) + +if [[ $(clang-format --version) != *"version 6"* ]]; then echo "Please upgrade to clang-format version 6." echo "If it's installed via homebrew you can run: brew upgrade clang-format" exit 1 fi -if [[ $# -gt 0 && "$1" = "test-only" ]]; then +if [[ "$system" == "Darwin" ]]; then + version=$(swiftformat --version) + version="${version/*version /}" + # Allow an older swiftformat because travis isn't running High Sierra yet + # and the formula hasn't been updated in a while on Sierra :-/. + if [[ "$version" != "0.32.0" && "$version" != "0.33"* ]]; then + echo "Please upgrade to swiftformat 0.33.3" + echo "If it's installed via homebrew you can run: brew upgrade swiftformat" + exit 1 + fi +fi + +# Joins the given arguments with the separator given as the first argument. +function join() { + local IFS="$1" + shift + echo "$*" +} + +clang_options=(-style=file) + +# Rules to disable in swiftformat: +swift_disable=( + # sortedImports is broken, sorting into the middle of the copyright notice. + sortedImports + + # Too many of our swift files have simplistic examples. While technically + # it's correct to remove the unused argument labels, it makes our examples + # look wrong. + unusedArguments +) + +swift_options=( + # Mimic Objective-C style. + --indent 2 + + --disable $(join , "${swift_disable[@]}") +) + +if [[ $# -gt 0 && "$1" == "test-only" ]]; then test_only=true - options="-output-replacements-xml" + clang_options+=(-output-replacements-xml) + swift_options+=(--dryrun) shift else test_only=false - options="-i" + clang_options+=(-i) fi files=$( @@ -54,6 +96,8 @@ files=$( # Build outputs \%/Pods/% d \%^./build/% d +\%^./Debug/% d +\%^./Release/% d # Sources controlled outside this tree \%/third_party/% d @@ -73,19 +117,29 @@ files=$( \%\.pb\.% d # Format C-ish sources only -\%\.(h|m|mm|cc)$% p +\%\.(h|m|mm|cc|swift)$% p ' ) + needs_formatting=false for f in $files; do - clang-format -style=file $options $f | grep "<replacement " > /dev/null - if [[ "$test_only" = true && $? -ne 1 ]]; then + if [[ "${f: -6}" == '.swift' ]]; then + if [[ "$system" == 'Darwin' ]]; then + swiftformat "${swift_options[@]}" "$f" 2> /dev/null | grep 'would have updated' > /dev/null + else + false + fi + else + clang-format "${clang_options[@]}" "$f" | grep "<replacement " > /dev/null + fi + + if [[ "$test_only" == true && $? -ne 1 ]]; then echo "$f needs formatting." needs_formatting=true fi done -if [[ "$needs_formatting" = true ]]; then +if [[ "$needs_formatting" == true ]]; then echo "Proposed commit is not style compliant." echo "Run scripts/style.sh and git add the result." exit 1 |