Compare commits

..

No commits in common. "2.6.0" and "master" have entirely different histories.

338 changed files with 7741 additions and 16428 deletions

View File

@ -39,7 +39,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
0ABF8340F735722CEE937FA3 /* libPods-PNObject_Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PNObject_Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 0ABF8340F735722CEE937FA3 /* libPods-PNObject_Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PNObject_Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
116AF818F8117B91EF290C9A /* Pods-PNObject_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PNObject_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PNObject_Example/Pods-PNObject_Example.release.xcconfig"; sourceTree = "<group>"; }; 116AF818F8117B91EF290C9A /* Pods-PNObject_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PNObject_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PNObject_Example/Pods-PNObject_Example.release.xcconfig"; sourceTree = "<group>"; };
2661CEE1F223361CD1DACC25 /* PNObject.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PNObject.podspec; path = ../PNObject.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 2661CEE1F223361CD1DACC25 /* PNObject.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PNObject.podspec; path = ../PNObject.podspec; sourceTree = "<group>"; };
3E392C278361604C1602CAF0 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; }; 3E392C278361604C1602CAF0 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
6003F58A195388D20070C39A /* PNObject_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PNObject_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F58A195388D20070C39A /* PNObject_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PNObject_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@ -210,6 +210,7 @@
6003F586195388D20070C39A /* Sources */, 6003F586195388D20070C39A /* Sources */,
6003F587195388D20070C39A /* Frameworks */, 6003F587195388D20070C39A /* Frameworks */,
6003F588195388D20070C39A /* Resources */, 6003F588195388D20070C39A /* Resources */,
C40CC8D7B1996A567BE82827 /* [CP] Embed Pods Frameworks */,
614EA73ED5E0ED0F8684468C /* [CP] Copy Pods Resources */, 614EA73ED5E0ED0F8684468C /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
@ -229,6 +230,8 @@
6003F5AA195388D20070C39A /* Sources */, 6003F5AA195388D20070C39A /* Sources */,
6003F5AB195388D20070C39A /* Frameworks */, 6003F5AB195388D20070C39A /* Frameworks */,
6003F5AC195388D20070C39A /* Resources */, 6003F5AC195388D20070C39A /* Resources */,
746A765B48FD98342716D81F /* [CP] Embed Pods Frameworks */,
21411FBE0FE21EC75B6AB1E3 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
@ -304,6 +307,21 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
21411FBE0FE21EC75B6AB1E3 /* [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-PNObject_Tests/Pods-PNObject_Tests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3FF38AA7E586B22171D1A118 /* [CP] Check Pods Manifest.lock */ = { 3FF38AA7E586B22171D1A118 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -333,13 +351,43 @@
); );
name = "[CP] Copy Pods Resources"; name = "[CP] Copy Pods Resources";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FacebookSDKStrings.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PNObject_Example/Pods-PNObject_Example-resources.sh\"\n"; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PNObject_Example/Pods-PNObject_Example-resources.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
746A765B48FD98342716D81F /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PNObject_Tests/Pods-PNObject_Tests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
C40CC8D7B1996A567BE82827 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PNObject_Example/Pods-PNObject_Example-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
E4CE079F616C61EA34D08B8B /* [CP] Check Pods Manifest.lock */ = { E4CE079F616C61EA34D08B8B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;

View File

@ -1,8 +0,0 @@
<?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>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -25,6 +25,7 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ {
[FBSDKSettings setAppID:@"213761522305123"]; [FBSDKSettings setAppID:@"213761522305123"];
[[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions]; [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];
@ -33,23 +34,21 @@
// Override point for customization after application launch. // Override point for customization after application launch.
[PNObjectConfig initSharedInstanceForEnvironments:@{EnvironmentDevelopment : @{BaseUrl:@"http://pnobject.local/",EndpointPath:@"api/v1/"}, [PNObjectConfig initSharedInstanceForEnvironments:@{EnvironmentDevelopment : @{BaseUrl:@"http://pnobject.local/",EndpointPath:@"api/v1/"},
EnvironmentStage : @{BaseUrl:@"https://pnobject.stage.it/",EndpointPath:@"api/v1/"}, EnvironmentStage : @{BaseUrl:@"http://pnobject.stage.it/",EndpointPath:@"api/v1/"},
EnvironmentProduction : @{BaseUrl:@"http://pnobject.prod.it/",EndpointPath:@"api/v1/"}, EnvironmentProduction : @{BaseUrl:@"http://pnobject.prod.it/",EndpointPath:@"api/v1/"},
} andUserSubclass:[PNUser class]]; } userSubclass:[PNUser class] withOauthMode:OAuthModeClientCredential];
/** Can user special char %@ to autoset EndpointPath to Oauth endpointPath */ [[PNObjectConfig sharedInstance] setClientID:@"xxxxxxxxx" clientSecret:@"xxxxxxxxxxxx" forEnv:EnvironmentStage];
[[PNObjectConfig sharedInstance] setClientID:@"******" clientSecret:@"******" oAuthEndpointAction:@"%@oauth-token" oauthMode:OAuthModeClientCredential refreshTokenEnabled:NO forEnv:EnvironmentStage]; [[PNObjectConfig sharedInstance] setClientID:@"xxxxxxxxx" clientSecret:@"xxxxxxxxxxxx" forEnv:EnvironmentProduction];
[[PNObjectConfig sharedInstance] setClientID:@"******" clientSecret:@"******" oAuthEndpointAction:@"%@oauth-token" oauthMode:OAuthModePassword refreshTokenEnabled:NO forEnv:EnvironmentStage];
[[PNObjectConfig sharedInstance] setOauthUserName:@"admin" oauthPassword:@"admin" forEnv:EnvironmentStage];
[[PNObjectConfig sharedInstance] setEnvironment:EnvironmentStage]; [[PNObjectConfig sharedInstance] setEnvironment:EnvironmentStage];
//[[PNObjectConfig sharedInstance] setHTTPHeaderValue:@"XMLHttpRequest" forKey:@"X-Request-With"];
NSLogDebug(@"%@",[[PNObjectConfig sharedInstance] baseUrl]); NSLogDebug(@"%@",[[PNObjectConfig sharedInstance] baseUrl]);
NSLogDebug(@"%@",[[PNObjectConfig sharedInstance] endPointPath]); NSLogDebug(@"%@",[[PNObjectConfig sharedInstance] endPointPath]);
NSLogDebug(@"%@",[[PNObjectConfig sharedInstance] endPointUrl]); NSLogDebug(@"%@",[[PNObjectConfig sharedInstance] endPointUrl]);
[[PNObjectConfig sharedInstance] loadManagersWithCredentials];
PNObjViewController *viewController = [[PNObjViewController alloc] init]; PNObjViewController *viewController = [[PNObjViewController alloc] init];

View File

@ -93,21 +93,11 @@
} }
- (void) refreshTokenAction { - (void) refreshTokenAction {
[[PNObjectConfig sharedInstance] refreshTokenForClientCredentialWithBlockSuccess:^(BOOL refreshSuccess) { [[PNObjectConfig sharedInstance] refreshTokenForClientCredential];
[PNUser loginCurrentUserWithUsername:@"test" password:@"test" withBlockSuccess:^(PNUser * _Nullable responseObject) {
NSLog(@"success");
} failure:^(NSError * _Nonnull error) {
NSLog(@"%@",error);
}];
} failure:^(NSError * _Nonnull error) {
}];
} }
- (void) cancelTokenAction { - (void) cancelTokenAction {
[[PNObjectConfig sharedInstance] resetAllTokens]; [[PNObjectConfig sharedInstance] resetToken];
} }
- (void) apiCallAction { - (void) apiCallAction {

View File

@ -1,13 +1,13 @@
platform :ios, '9.0' platform :ios, '9.0'
target 'PNObject_Example' do target 'PNObject_Example' do
pod 'PNObject', :path => '../' pod 'PNObject', :path => '../'
pod 'PureLayout' pod 'PureLayout'
target 'PNObject_Tests' do target 'PNObject_Tests' do
inherit! :search_paths inherit! :search_paths
pod 'Specta' pod 'Specta'
pod 'Expecta' pod 'Expecta'
end end
end end

View File

@ -1,18 +1,18 @@
PODS: PODS:
- AFNetworking (3.2.1): - AFNetworking (3.1.0):
- AFNetworking/NSURLSession (= 3.2.1) - AFNetworking/NSURLSession (= 3.1.0)
- AFNetworking/Reachability (= 3.2.1) - AFNetworking/Reachability (= 3.1.0)
- AFNetworking/Security (= 3.2.1) - AFNetworking/Security (= 3.1.0)
- AFNetworking/Serialization (= 3.2.1) - AFNetworking/Serialization (= 3.1.0)
- AFNetworking/UIKit (= 3.2.1) - AFNetworking/UIKit (= 3.1.0)
- AFNetworking/NSURLSession (3.2.1): - AFNetworking/NSURLSession (3.1.0):
- AFNetworking/Reachability - AFNetworking/Reachability
- AFNetworking/Security - AFNetworking/Security
- AFNetworking/Serialization - AFNetworking/Serialization
- AFNetworking/Reachability (3.2.1) - AFNetworking/Reachability (3.1.0)
- AFNetworking/Security (3.2.1) - AFNetworking/Security (3.1.0)
- AFNetworking/Serialization (3.2.1) - AFNetworking/Serialization (3.1.0)
- AFNetworking/UIKit (3.2.1): - AFNetworking/UIKit (3.1.0):
- AFNetworking/NSURLSession - AFNetworking/NSURLSession
- Bolts (1.9.0): - Bolts (1.9.0):
- Bolts/AppLinks (= 1.9.0) - Bolts/AppLinks (= 1.9.0)
@ -26,19 +26,19 @@ PODS:
- DJLocalization/Core (= 1.2.2) - DJLocalization/Core (= 1.2.2)
- DJLocalization/Core (1.2.2) - DJLocalization/Core (1.2.2)
- Expecta (1.0.6) - Expecta (1.0.6)
- FBSDKCoreKit (4.37.0): - FBSDKCoreKit (4.29.0):
- Bolts (~> 1.7) - Bolts (~> 1.7)
- FBSDKLoginKit (4.37.0): - FBSDKLoginKit (4.29.0):
- FBSDKCoreKit
- FBSDKShareKit (4.29.0):
- FBSDKCoreKit - FBSDKCoreKit
- FBSDKShareKit (4.37.0):
- FBSDKCoreKit (~> 4.37.0)
- NSDataAES (0.2.2) - NSDataAES (0.2.2)
- NSDate_Utils (1.1.0): - NSDate_Utils (1.1.0):
- DJLocalization - DJLocalization
- NSString-Helper (1.2.0) - NSString-Helper (1.0.5)
- nv-ios-http-status (0.0.1) - nv-ios-http-status (0.0.1)
- PEAR-FileManager-iOS (1.3.1) - PEAR-FileManager-iOS (1.3.1)
- PNObject (2.6.0): - PNObject (1.3.4):
- AFNetworking - AFNetworking
- CodFis-Helper - CodFis-Helper
- DDDKeychainWrapper - DDDKeychainWrapper
@ -54,11 +54,11 @@ PODS:
- RZDataBinding - RZDataBinding
- StrongestPasswordValidator - StrongestPasswordValidator
- UIDevice-Utils - UIDevice-Utils
- PureLayout (3.1.2) - PureLayout (3.0.2)
- RZDataBinding (2.1.1) - RZDataBinding (2.1.0)
- Specta (1.0.7) - Specta (1.0.7)
- StrongestPasswordValidator (0.1.2) - StrongestPasswordValidator (0.1.2)
- UIDevice-Utils (1.0.9) - UIDevice-Utils (1.0.0)
DEPENDENCIES: DEPENDENCIES:
- Expecta - Expecta
@ -66,54 +66,32 @@ DEPENDENCIES:
- PureLayout - PureLayout
- Specta - Specta
SPEC REPOS:
https://github.com/cocoapods/specs.git:
- AFNetworking
- Bolts
- CodFis-Helper
- DDDKeychainWrapper
- DJLocalization
- Expecta
- FBSDKCoreKit
- FBSDKLoginKit
- FBSDKShareKit
- NSDataAES
- NSDate_Utils
- NSString-Helper
- nv-ios-http-status
- PEAR-FileManager-iOS
- PureLayout
- RZDataBinding
- Specta
- StrongestPasswordValidator
- UIDevice-Utils
EXTERNAL SOURCES: EXTERNAL SOURCES:
PNObject: PNObject:
:path: "../" :path: ../
SPEC CHECKSUMS: SPEC CHECKSUMS:
AFNetworking: b6f891fdfaed196b46c7a83cf209e09697b94057 AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67
Bolts: ac6567323eac61e203f6a9763667d0f711be34c8 Bolts: ac6567323eac61e203f6a9763667d0f711be34c8
CodFis-Helper: 28be4c74d7202542459d72354f59b1215871de87 CodFis-Helper: 28be4c74d7202542459d72354f59b1215871de87
DDDKeychainWrapper: e681a4daba6448786fa83b4941f58102a33b1897 DDDKeychainWrapper: e681a4daba6448786fa83b4941f58102a33b1897
DJLocalization: 0c84029af375647d4104a42ae36be87194c46c47 DJLocalization: 0c84029af375647d4104a42ae36be87194c46c47
Expecta: 3b6bd90a64b9a1dcb0b70aa0e10a7f8f631667d5 Expecta: 3b6bd90a64b9a1dcb0b70aa0e10a7f8f631667d5
FBSDKCoreKit: fe5f3474499a81963e11e3f3a5c753d0a95ca2b4 FBSDKCoreKit: 6f139173dc63a1deaff4430a55f2fe5bb222d2af
FBSDKLoginKit: 2f7249686d1e30ce8a5ef5400eedf50b3e3df332 FBSDKLoginKit: 56a057ca6822535ea0faa25f57a7c41edb697fd4
FBSDKShareKit: 52e0083222c38e930eb6878007478326599195c3 FBSDKShareKit: 18a2cd118aef11dd657fe7e8b64bae5c719088b2
NSDataAES: 967ea3337476a80e9838a533c25d570a06855ed0 NSDataAES: 967ea3337476a80e9838a533c25d570a06855ed0
NSDate_Utils: c858a89da6e204ecf53aca48dbccb4da4d25bc9e NSDate_Utils: c858a89da6e204ecf53aca48dbccb4da4d25bc9e
NSString-Helper: 1c259caa6c845e79e0bb45ee25e34f95d86d2317 NSString-Helper: 459e1b6a62b3bf7db10f01b0d102548608e945c4
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3 PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
PNObject: d92d660eb43b9385e7148e42598b8a7d3a785834 PNObject: 8dc560680a7a48060ed309b019ca4fc41505cc07
PureLayout: 4634d0b61e3b5021166e8ec7c18e9e0ca0720c8b PureLayout: 4d550abe49a94f24c2808b9b95db9131685fe4cd
RZDataBinding: 289e2fbdce8b9585afef69def83425c5d380ffbd RZDataBinding: 6981e90ddaae2f5e02028323b1043f8c31013109
Specta: 3e1bd89c3517421982dc4d1c992503e48bd5fe66 Specta: 3e1bd89c3517421982dc4d1c992503e48bd5fe66
StrongestPasswordValidator: 921e42615bdf353513c6f925bffd4fc29865dbd7 StrongestPasswordValidator: 921e42615bdf353513c6f925bffd4fc29865dbd7
UIDevice-Utils: 6ba44475416a1e823f214a8ed26fc9a0761db096 UIDevice-Utils: ff37bd042127117572d6ce4c5ff074f4f54ab5ed
PODFILE CHECKSUM: eec9c921f7aee591fd1fdea1fd3e5a191b74a436 PODFILE CHECKSUM: fcd5d1cf3426c7c9c5b3e5edcd4b8e5402ee7f2e
COCOAPODS: 1.5.3 COCOAPODS: 1.3.1

View File

@ -1,37 +0,0 @@
// AFCompatibilityMacros.h
// Copyright (c) 20112016 Alamofire Software Foundation ( http://alamofire.org/ )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef AFCompatibilityMacros_h
#define AFCompatibilityMacros_h
#ifdef API_UNAVAILABLE
#define AF_API_UNAVAILABLE(x) API_UNAVAILABLE(x)
#else
#define AF_API_UNAVAILABLE(x)
#endif // API_UNAVAILABLE
#if __has_warning("-Wunguarded-availability-new")
#define AF_CAN_USE_AT_AVAILABLE 1
#else
#define AF_CAN_USE_AT_AVAILABLE 0
#endif
#endif /* AFCompatibilityMacros_h */

View File

@ -44,7 +44,7 @@
## Methods to Override ## Methods to Override
To change the behavior of all data task operation construction, which is also used in the `GET` / `POST` / et al. convenience methods, override `dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:`. To change the behavior of all data task operation construction, which is also used in the `GET` / `POST` / et al. convenience methods, override `dataTaskWithRequest:completionHandler:`.
## Serialization ## Serialization
@ -94,15 +94,6 @@ NS_ASSUME_NONNULL_BEGIN
*/ */
@property (nonatomic, strong) AFHTTPResponseSerializer <AFURLResponseSerialization> * responseSerializer; @property (nonatomic, strong) AFHTTPResponseSerializer <AFURLResponseSerialization> * responseSerializer;
///-------------------------------
/// @name Managing Security Policy
///-------------------------------
/**
The security policy used by created session to evaluate server trust for secure connections. `AFURLSessionManager` uses the `defaultPolicy` unless otherwise specified. A security policy configured with `AFSSLPinningModePublicKey` or `AFSSLPinningModeCertificate` can only be applied on a session manager initialized with a secure base URL (i.e. https). Applying a security policy with pinning enabled on an insecure session manager throws an `Invalid Security Policy` exception.
*/
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;
///--------------------- ///---------------------
/// @name Initialization /// @name Initialization
///--------------------- ///---------------------

View File

@ -98,23 +98,6 @@
[super setResponseSerializer:responseSerializer]; [super setResponseSerializer:responseSerializer];
} }
@dynamic securityPolicy;
- (void)setSecurityPolicy:(AFSecurityPolicy *)securityPolicy {
if (securityPolicy.SSLPinningMode != AFSSLPinningModeNone && ![self.baseURL.scheme isEqualToString:@"https"]) {
NSString *pinningMode = @"Unknown Pinning Mode";
switch (securityPolicy.SSLPinningMode) {
case AFSSLPinningModeNone: pinningMode = @"AFSSLPinningModeNone"; break;
case AFSSLPinningModeCertificate: pinningMode = @"AFSSLPinningModeCertificate"; break;
case AFSSLPinningModePublicKey: pinningMode = @"AFSSLPinningModePublicKey"; break;
}
NSString *reason = [NSString stringWithFormat:@"A security policy configured with `%@` can only be applied on a manager with a secure base URL (i.e. https)", pinningMode];
@throw [NSException exceptionWithName:@"Invalid Security Policy" reason:reason userInfo:nil];
}
[super setSecurityPolicy:securityPolicy];
}
#pragma mark - #pragma mark -
- (NSURLSessionDataTask *)GET:(NSString *)URLString - (NSURLSessionDataTask *)GET:(NSString *)URLString
@ -203,9 +186,12 @@
NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
if (serializationError) { if (serializationError) {
if (failure) { if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError); failure(nil, serializationError);
}); });
#pragma clang diagnostic pop
} }
return nil; return nil;
@ -276,9 +262,12 @@
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
if (serializationError) { if (serializationError) {
if (failure) { if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError); failure(nil, serializationError);
}); });
#pragma clang diagnostic pop
} }
return nil; return nil;

View File

@ -107,16 +107,6 @@ NS_ASSUME_NONNULL_BEGIN
*/ */
- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER;
/**
* Unavailable initializer
*/
+ (instancetype)new NS_UNAVAILABLE;
/**
* Unavailable initializer
*/
- (instancetype)init NS_UNAVAILABLE;
///-------------------------------------------------- ///--------------------------------------------------
/// @name Starting & Stopping Reachability Monitoring /// @name Starting & Stopping Reachability Monitoring
///-------------------------------------------------- ///--------------------------------------------------

View File

@ -170,11 +170,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
return self; return self;
} }
- (instancetype)init - (instancetype)init NS_UNAVAILABLE
{ {
@throw [NSException exceptionWithName:NSGenericException
reason:@"`-init` unavailable. Use `-initWithReachability:` instead"
userInfo:nil];
return nil; return nil;
} }

View File

@ -51,6 +51,8 @@ static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) {
static id AFPublicKeyForCertificate(NSData *certificate) { static id AFPublicKeyForCertificate(NSData *certificate) {
id allowedPublicKey = nil; id allowedPublicKey = nil;
SecCertificateRef allowedCertificate; SecCertificateRef allowedCertificate;
SecCertificateRef allowedCertificates[1];
CFArrayRef tempCertificates = nil;
SecPolicyRef policy = nil; SecPolicyRef policy = nil;
SecTrustRef allowedTrust = nil; SecTrustRef allowedTrust = nil;
SecTrustResultType result; SecTrustResultType result;
@ -58,8 +60,11 @@ static id AFPublicKeyForCertificate(NSData *certificate) {
allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate); allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate);
__Require_Quiet(allowedCertificate != NULL, _out); __Require_Quiet(allowedCertificate != NULL, _out);
allowedCertificates[0] = allowedCertificate;
tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL);
policy = SecPolicyCreateBasicX509(); policy = SecPolicyCreateBasicX509();
__Require_noErr_Quiet(SecTrustCreateWithCertificates(allowedCertificate, policy, &allowedTrust), _out); __Require_noErr_Quiet(SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust), _out);
__Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out); __Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out);
allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust); allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust);
@ -73,6 +78,10 @@ _out:
CFRelease(policy); CFRelease(policy);
} }
if (tempCertificates) {
CFRelease(tempCertificates);
}
if (allowedCertificate) { if (allowedCertificate) {
CFRelease(allowedCertificate); CFRelease(allowedCertificate);
} }

View File

@ -60,7 +60,10 @@ NSString * AFPercentEscapedStringFromString(NSString *string) {
NSMutableString *escaped = @"".mutableCopy; NSMutableString *escaped = @"".mutableCopy;
while (index < string.length) { while (index < string.length) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wgnu"
NSUInteger length = MIN(string.length - index, batchSize); NSUInteger length = MIN(string.length - index, batchSize);
#pragma GCC diagnostic pop
NSRange range = NSMakeRange(index, length); NSRange range = NSMakeRange(index, length);
// To avoid breaking up character sequences such as 👴🏻👮🏽 // To avoid breaking up character sequences such as 👴🏻👮🏽
@ -186,7 +189,6 @@ static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerOb
@interface AFHTTPRequestSerializer () @interface AFHTTPRequestSerializer ()
@property (readwrite, nonatomic, strong) NSMutableSet *mutableObservedChangedKeyPaths; @property (readwrite, nonatomic, strong) NSMutableSet *mutableObservedChangedKeyPaths;
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableHTTPRequestHeaders; @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableHTTPRequestHeaders;
@property (readwrite, nonatomic, strong) dispatch_queue_t requestHeaderModificationQueue;
@property (readwrite, nonatomic, assign) AFHTTPRequestQueryStringSerializationStyle queryStringSerializationStyle; @property (readwrite, nonatomic, assign) AFHTTPRequestQueryStringSerializationStyle queryStringSerializationStyle;
@property (readwrite, nonatomic, copy) AFQueryStringSerializationBlock queryStringSerialization; @property (readwrite, nonatomic, copy) AFQueryStringSerializationBlock queryStringSerialization;
@end @end
@ -206,7 +208,6 @@ static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerOb
self.stringEncoding = NSUTF8StringEncoding; self.stringEncoding = NSUTF8StringEncoding;
self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary]; self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary];
self.requestHeaderModificationQueue = dispatch_queue_create("requestHeaderModificationQueue", DISPATCH_QUEUE_CONCURRENT);
// Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4 // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
NSMutableArray *acceptLanguagesComponents = [NSMutableArray array]; NSMutableArray *acceptLanguagesComponents = [NSMutableArray array];
@ -218,6 +219,8 @@ static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerOb
[self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"]; [self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"];
NSString *userAgent = nil; NSString *userAgent = nil;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
#if TARGET_OS_IOS #if TARGET_OS_IOS
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
@ -227,6 +230,7 @@ static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerOb
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]; userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
#endif #endif
#pragma clang diagnostic pop
if (userAgent) { if (userAgent) {
if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) { if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) {
NSMutableString *mutableUserAgent = [userAgent mutableCopy]; NSMutableString *mutableUserAgent = [userAgent mutableCopy];
@ -302,27 +306,17 @@ static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerOb
#pragma mark - #pragma mark -
- (NSDictionary *)HTTPRequestHeaders { - (NSDictionary *)HTTPRequestHeaders {
NSDictionary __block *value; return [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders];
dispatch_sync(self.requestHeaderModificationQueue, ^{
value = [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders];
});
return value;
} }
- (void)setValue:(NSString *)value - (void)setValue:(NSString *)value
forHTTPHeaderField:(NSString *)field forHTTPHeaderField:(NSString *)field
{ {
dispatch_barrier_async(self.requestHeaderModificationQueue, ^{ [self.mutableHTTPRequestHeaders setValue:value forKey:field];
[self.mutableHTTPRequestHeaders setValue:value forKey:field];
});
} }
- (NSString *)valueForHTTPHeaderField:(NSString *)field { - (NSString *)valueForHTTPHeaderField:(NSString *)field {
NSString __block *value; return [self.mutableHTTPRequestHeaders valueForKey:field];
dispatch_sync(self.requestHeaderModificationQueue, ^{
value = [self.mutableHTTPRequestHeaders valueForKey:field];
});
return value;
} }
- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username - (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username
@ -334,9 +328,7 @@ forHTTPHeaderField:(NSString *)field
} }
- (void)clearAuthorizationHeader { - (void)clearAuthorizationHeader {
dispatch_barrier_async(self.requestHeaderModificationQueue, ^{ [self.mutableHTTPRequestHeaders removeObjectForKey:@"Authorization"];
[self.mutableHTTPRequestHeaders removeObjectForKey:@"Authorization"];
});
} }
#pragma mark - #pragma mark -
@ -568,9 +560,7 @@ forHTTPHeaderField:(NSString *)field
} }
- (void)encodeWithCoder:(NSCoder *)coder { - (void)encodeWithCoder:(NSCoder *)coder {
dispatch_sync(self.requestHeaderModificationQueue, ^{ [coder encodeObject:self.mutableHTTPRequestHeaders forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))];
[coder encodeObject:self.mutableHTTPRequestHeaders forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))];
});
[coder encodeInteger:self.queryStringSerializationStyle forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))]; [coder encodeInteger:self.queryStringSerializationStyle forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))];
} }
@ -578,9 +568,7 @@ forHTTPHeaderField:(NSString *)field
- (instancetype)copyWithZone:(NSZone *)zone { - (instancetype)copyWithZone:(NSZone *)zone {
AFHTTPRequestSerializer *serializer = [[[self class] allocWithZone:zone] init]; AFHTTPRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
dispatch_sync(self.requestHeaderModificationQueue, ^{ serializer.mutableHTTPRequestHeaders = [self.mutableHTTPRequestHeaders mutableCopyWithZone:zone];
serializer.mutableHTTPRequestHeaders = [self.mutableHTTPRequestHeaders mutableCopyWithZone:zone];
});
serializer.queryStringSerializationStyle = self.queryStringSerializationStyle; serializer.queryStringSerializationStyle = self.queryStringSerializationStyle;
serializer.queryStringSerialization = self.queryStringSerialization; serializer.queryStringSerialization = self.queryStringSerialization;
@ -679,11 +667,6 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
return self; return self;
} }
- (void)setRequest:(NSMutableURLRequest *)request
{
_request = [request mutableCopy];
}
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL - (BOOL)appendPartWithFileURL:(NSURL *)fileURL
name:(NSString *)name name:(NSString *)name
error:(NSError * __autoreleasing *)error error:(NSError * __autoreleasing *)error
@ -852,11 +835,14 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
@end @end
@implementation AFMultipartBodyStream @implementation AFMultipartBodyStream
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wimplicit-atomic-properties"
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1100) #if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1100)
@synthesize delegate; @synthesize delegate;
#endif #endif
@synthesize streamStatus; @synthesize streamStatus;
@synthesize streamError; @synthesize streamError;
#pragma clang diagnostic pop
- (instancetype)initWithStringEncoding:(NSStringEncoding)encoding { - (instancetype)initWithStringEncoding:(NSStringEncoding)encoding {
self = [super init]; self = [super init];
@ -902,6 +888,8 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
NSInteger totalNumberOfBytesRead = 0; NSInteger totalNumberOfBytesRead = 0;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
while ((NSUInteger)totalNumberOfBytesRead < MIN(length, self.numberOfBytesInPacket)) { while ((NSUInteger)totalNumberOfBytesRead < MIN(length, self.numberOfBytesInPacket)) {
if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) { if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) {
if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) { if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) {
@ -922,6 +910,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
} }
} }
} }
#pragma clang diagnostic pop
return totalNumberOfBytesRead; return totalNumberOfBytesRead;
} }
@ -1102,6 +1091,8 @@ typedef enum {
return YES; return YES;
} }
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcovered-switch-default"
switch (self.inputStream.streamStatus) { switch (self.inputStream.streamStatus) {
case NSStreamStatusNotOpen: case NSStreamStatusNotOpen:
case NSStreamStatusOpening: case NSStreamStatusOpening:
@ -1115,6 +1106,7 @@ typedef enum {
default: default:
return NO; return NO;
} }
#pragma clang diagnostic pop
} }
- (NSInteger)read:(uint8_t *)buffer - (NSInteger)read:(uint8_t *)buffer
@ -1159,8 +1151,11 @@ typedef enum {
intoBuffer:(uint8_t *)buffer intoBuffer:(uint8_t *)buffer
maxLength:(NSUInteger)length maxLength:(NSUInteger)length
{ {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
NSRange range = NSMakeRange((NSUInteger)_phaseReadOffset, MIN([data length] - ((NSUInteger)_phaseReadOffset), length)); NSRange range = NSMakeRange((NSUInteger)_phaseReadOffset, MIN([data length] - ((NSUInteger)_phaseReadOffset), length));
[data getBytes:buffer range:range]; [data getBytes:buffer range:range];
#pragma clang diagnostic pop
_phaseReadOffset += range.length; _phaseReadOffset += range.length;
@ -1179,6 +1174,8 @@ typedef enum {
return YES; return YES;
} }
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcovered-switch-default"
switch (_phase) { switch (_phase) {
case AFEncapsulationBoundaryPhase: case AFEncapsulationBoundaryPhase:
_phase = AFHeaderPhase; _phase = AFHeaderPhase;
@ -1198,6 +1195,7 @@ typedef enum {
break; break;
} }
_phaseReadOffset = 0; _phaseReadOffset = 0;
#pragma clang diagnostic pop
return YES; return YES;
} }
@ -1259,21 +1257,7 @@ typedef enum {
[mutableRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [mutableRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
} }
if (![NSJSONSerialization isValidJSONObject:parameters]) { [mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
if (error) {
NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedStringFromTable(@"The `parameters` argument is not valid JSON.", @"AFNetworking", nil)};
*error = [[NSError alloc] initWithDomain:AFURLRequestSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo];
}
return nil;
}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error];
if (!jsonData) {
return nil;
}
[mutableRequest setHTTPBody:jsonData];
} }
return mutableRequest; return mutableRequest;
@ -1352,13 +1336,7 @@ typedef enum {
[mutableRequest setValue:@"application/x-plist" forHTTPHeaderField:@"Content-Type"]; [mutableRequest setValue:@"application/x-plist" forHTTPHeaderField:@"Content-Type"];
} }
NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:parameters format:self.format options:self.writeOptions error:error]; [mutableRequest setHTTPBody:[NSPropertyListSerialization dataWithPropertyList:parameters format:self.format options:self.writeOptions error:error]];
if (!plistData) {
return nil;
}
[mutableRequest setHTTPBody:plistData];
} }
return mutableRequest; return mutableRequest;

View File

@ -57,7 +57,10 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init; - (instancetype)init;
@property (nonatomic, assign) NSStringEncoding stringEncoding DEPRECATED_MSG_ATTRIBUTE("The string encoding is never used. AFHTTPResponseSerializer only validates status codes and content types but does not try to decode the received data in any way."); /**
The string encoding used to serialize data received from the server, when no string encoding is specified by the response. `NSUTF8StringEncoding` by default.
*/
@property (nonatomic, assign) NSStringEncoding stringEncoding;
/** /**
Creates and returns a serializer with default configuration. Creates and returns a serializer with default configuration.
@ -108,8 +111,6 @@ NS_ASSUME_NONNULL_BEGIN
- `application/json` - `application/json`
- `text/json` - `text/json`
- `text/javascript` - `text/javascript`
In RFC 7159 - Section 8.1, it states that JSON text is required to be encoded in UTF-8, UTF-16, or UTF-32, and the default encoding is UTF-8. NSJSONSerialization provides support for all the encodings listed in the specification, and recommends UTF-8 for efficiency. Using an unsupported encoding will result in serialization error. See the `NSJSONSerialization` documentation for more details.
*/ */
@interface AFJSONResponseSerializer : AFHTTPResponseSerializer @interface AFJSONResponseSerializer : AFHTTPResponseSerializer
@ -165,7 +166,7 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init; - (instancetype)init;
/** /**
Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSXMLDocument` documentation section "Input and Output Options". `0` by default. Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default.
*/ */
@property (nonatomic, assign) NSUInteger options; @property (nonatomic, assign) NSUInteger options;

View File

@ -97,6 +97,8 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO
return nil; return nil;
} }
self.stringEncoding = NSUTF8StringEncoding;
self.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)]; self.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
self.acceptableContentTypes = nil; self.acceptableContentTypes = nil;
@ -240,28 +242,23 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO
} }
} }
id responseObject = nil;
NSError *serializationError = nil;
// Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization. // Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization.
// See https://github.com/rails/rails/issues/1742 // See https://github.com/rails/rails/issues/1742
BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]]; BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]];
if (data.length > 0 && !isSpace) {
if (data.length == 0 || isSpace) { responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
} else {
return nil; return nil;
} }
NSError *serializationError = nil; if (self.removesKeysWithNullValues && responseObject) {
responseObject = AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
id responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
if (!responseObject)
{
if (error) {
*error = AFErrorWithUnderlyingError(serializationError, *error);
}
return nil;
} }
if (self.removesKeysWithNullValues) { if (error) {
return AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions); *error = AFErrorWithUnderlyingError(serializationError, *error);
} }
return responseObject; return responseObject;
@ -291,7 +288,7 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO
#pragma mark - NSCopying #pragma mark - NSCopying
- (instancetype)copyWithZone:(NSZone *)zone { - (instancetype)copyWithZone:(NSZone *)zone {
AFJSONResponseSerializer *serializer = [super copyWithZone:zone]; AFJSONResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
serializer.readingOptions = self.readingOptions; serializer.readingOptions = self.readingOptions;
serializer.removesKeysWithNullValues = self.removesKeysWithNullValues; serializer.removesKeysWithNullValues = self.removesKeysWithNullValues;
@ -381,12 +378,8 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO
NSError *serializationError = nil; NSError *serializationError = nil;
NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data options:self.options error:&serializationError]; NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data options:self.options error:&serializationError];
if (!document) if (error) {
{ *error = AFErrorWithUnderlyingError(serializationError, *error);
if (error) {
*error = AFErrorWithUnderlyingError(serializationError, *error);
}
return nil;
} }
return document; return document;
@ -414,7 +407,7 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO
#pragma mark - NSCopying #pragma mark - NSCopying
- (instancetype)copyWithZone:(NSZone *)zone { - (instancetype)copyWithZone:(NSZone *)zone {
AFXMLDocumentResponseSerializer *serializer = [super copyWithZone:zone]; AFXMLDocumentResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
serializer.options = self.options; serializer.options = self.options;
return serializer; return serializer;
@ -465,20 +458,15 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO
} }
} }
if (!data) { id responseObject;
return nil;
}
NSError *serializationError = nil; NSError *serializationError = nil;
id responseObject = [NSPropertyListSerialization propertyListWithData:data options:self.readOptions format:NULL error:&serializationError]; if (data) {
responseObject = [NSPropertyListSerialization propertyListWithData:data options:self.readOptions format:NULL error:&serializationError];
}
if (!responseObject) if (error) {
{ *error = AFErrorWithUnderlyingError(serializationError, *error);
if (error) {
*error = AFErrorWithUnderlyingError(serializationError, *error);
}
return nil;
} }
return responseObject; return responseObject;
@ -508,7 +496,7 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO
#pragma mark - NSCopying #pragma mark - NSCopying
- (instancetype)copyWithZone:(NSZone *)zone { - (instancetype)copyWithZone:(NSZone *)zone {
AFPropertyListResponseSerializer *serializer = [super copyWithZone:zone]; AFPropertyListResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
serializer.format = self.format; serializer.format = self.format;
serializer.readOptions = self.readOptions; serializer.readOptions = self.readOptions;
@ -734,7 +722,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
#pragma mark - NSCopying #pragma mark - NSCopying
- (instancetype)copyWithZone:(NSZone *)zone { - (instancetype)copyWithZone:(NSZone *)zone {
AFImageResponseSerializer *serializer = [super copyWithZone:zone]; AFImageResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
serializer.imageScale = self.imageScale; serializer.imageScale = self.imageScale;
@ -808,7 +796,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
#pragma mark - NSCopying #pragma mark - NSCopying
- (instancetype)copyWithZone:(NSZone *)zone { - (instancetype)copyWithZone:(NSZone *)zone {
AFCompoundResponseSerializer *serializer = [super copyWithZone:zone]; AFCompoundResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
serializer.responseSerializers = self.responseSerializers; serializer.responseSerializers = self.responseSerializers;
return serializer; return serializer;

View File

@ -25,7 +25,6 @@
#import "AFURLResponseSerialization.h" #import "AFURLResponseSerialization.h"
#import "AFURLRequestSerialization.h" #import "AFURLRequestSerialization.h"
#import "AFSecurityPolicy.h" #import "AFSecurityPolicy.h"
#import "AFCompatibilityMacros.h"
#if !TARGET_OS_WATCH #if !TARGET_OS_WATCH
#import "AFNetworkReachabilityManager.h" #import "AFNetworkReachabilityManager.h"
#endif #endif
@ -209,7 +208,7 @@ NS_ASSUME_NONNULL_BEGIN
@param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
*/ */
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler DEPRECATED_ATTRIBUTE; completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;
/** /**
Creates an `NSURLSessionDataTask` with the specified request. Creates an `NSURLSessionDataTask` with the specified request.
@ -355,7 +354,7 @@ NS_ASSUME_NONNULL_BEGIN
@param block A block object to be executed when an HTTP request is attempting to perform a redirection to a different URL. The block returns the request to be made for the redirection, and takes four arguments: the session, the task, the redirection response, and the request corresponding to the redirection response. @param block A block object to be executed when an HTTP request is attempting to perform a redirection to a different URL. The block returns the request to be made for the redirection, and takes four arguments: the session, the task, the redirection response, and the request corresponding to the redirection response.
*/ */
- (void)setTaskWillPerformHTTPRedirectionBlock:(nullable NSURLRequest * _Nullable (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block; - (void)setTaskWillPerformHTTPRedirectionBlock:(nullable NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block;
/** /**
Sets a block to be executed when a session task has received a request specific authentication challenge, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didReceiveChallenge:completionHandler:`. Sets a block to be executed when a session task has received a request specific authentication challenge, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didReceiveChallenge:completionHandler:`.
@ -415,7 +414,7 @@ NS_ASSUME_NONNULL_BEGIN
@param block A block object to be executed once all messages enqueued for a session have been delivered. The block has no return value and takes a single argument: the session. @param block A block object to be executed once all messages enqueued for a session have been delivered. The block has no return value and takes a single argument: the session.
*/ */
- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block AF_API_UNAVAILABLE(macos); - (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block;
///----------------------------------------------- ///-----------------------------------------------
/// @name Setting Download Task Delegate Callbacks /// @name Setting Download Task Delegate Callbacks

View File

@ -85,6 +85,8 @@ static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking
static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3; static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3;
static void * AFTaskStateChangedContext = &AFTaskStateChangedContext;
typedef void (^AFURLSessionDidBecomeInvalidBlock)(NSURLSession *session, NSError *error); typedef void (^AFURLSessionDidBecomeInvalidBlock)(NSURLSession *session, NSError *error);
typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential); typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential);
@ -112,7 +114,6 @@ typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id re
#pragma mark - #pragma mark -
@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate> @interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
- (instancetype)initWithTask:(NSURLSessionTask *)task;
@property (nonatomic, weak) AFURLSessionManager *manager; @property (nonatomic, weak) AFURLSessionManager *manager;
@property (nonatomic, strong) NSMutableData *mutableData; @property (nonatomic, strong) NSMutableData *mutableData;
@property (nonatomic, strong) NSProgress *uploadProgress; @property (nonatomic, strong) NSProgress *uploadProgress;
@ -126,56 +127,113 @@ typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id re
@implementation AFURLSessionManagerTaskDelegate @implementation AFURLSessionManagerTaskDelegate
- (instancetype)initWithTask:(NSURLSessionTask *)task { - (instancetype)init {
self = [super init]; self = [super init];
if (!self) { if (!self) {
return nil; return nil;
} }
_mutableData = [NSMutableData data]; self.mutableData = [NSMutableData data];
_uploadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil]; self.uploadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
_downloadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil]; self.uploadProgress.totalUnitCount = NSURLSessionTransferSizeUnknown;
__weak __typeof__(task) weakTask = task; self.downloadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
for (NSProgress *progress in @[ _uploadProgress, _downloadProgress ]) self.downloadProgress.totalUnitCount = NSURLSessionTransferSizeUnknown;
{
progress.totalUnitCount = NSURLSessionTransferSizeUnknown;
progress.cancellable = YES;
progress.cancellationHandler = ^{
[weakTask cancel];
};
progress.pausable = YES;
progress.pausingHandler = ^{
[weakTask suspend];
};
#if AF_CAN_USE_AT_AVAILABLE
if (@available(iOS 9, macOS 10.11, *))
#else
if ([progress respondsToSelector:@selector(setResumingHandler:)])
#endif
{
progress.resumingHandler = ^{
[weakTask resume];
};
}
[progress addObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
options:NSKeyValueObservingOptionNew
context:NULL];
}
return self; return self;
} }
- (void)dealloc {
[self.downloadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
[self.uploadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
}
#pragma mark - NSProgress Tracking #pragma mark - NSProgress Tracking
- (void)setupProgressForTask:(NSURLSessionTask *)task {
__weak __typeof__(task) weakTask = task;
self.uploadProgress.totalUnitCount = task.countOfBytesExpectedToSend;
self.downloadProgress.totalUnitCount = task.countOfBytesExpectedToReceive;
[self.uploadProgress setCancellable:YES];
[self.uploadProgress setCancellationHandler:^{
__typeof__(weakTask) strongTask = weakTask;
[strongTask cancel];
}];
[self.uploadProgress setPausable:YES];
[self.uploadProgress setPausingHandler:^{
__typeof__(weakTask) strongTask = weakTask;
[strongTask suspend];
}];
if ([self.uploadProgress respondsToSelector:@selector(setResumingHandler:)]) {
[self.uploadProgress setResumingHandler:^{
__typeof__(weakTask) strongTask = weakTask;
[strongTask resume];
}];
}
[self.downloadProgress setCancellable:YES];
[self.downloadProgress setCancellationHandler:^{
__typeof__(weakTask) strongTask = weakTask;
[strongTask cancel];
}];
[self.downloadProgress setPausable:YES];
[self.downloadProgress setPausingHandler:^{
__typeof__(weakTask) strongTask = weakTask;
[strongTask suspend];
}];
if ([self.downloadProgress respondsToSelector:@selector(setResumingHandler:)]) {
[self.downloadProgress setResumingHandler:^{
__typeof__(weakTask) strongTask = weakTask;
[strongTask resume];
}];
}
[task addObserver:self
forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))
options:NSKeyValueObservingOptionNew
context:NULL];
[task addObserver:self
forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))
options:NSKeyValueObservingOptionNew
context:NULL];
[task addObserver:self
forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))
options:NSKeyValueObservingOptionNew
context:NULL];
[task addObserver:self
forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToSend))
options:NSKeyValueObservingOptionNew
context:NULL];
[self.downloadProgress addObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
options:NSKeyValueObservingOptionNew
context:NULL];
[self.uploadProgress addObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
options:NSKeyValueObservingOptionNew
context:NULL];
}
- (void)cleanUpProgressForTask:(NSURLSessionTask *)task {
[task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))];
[task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))];
[task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))];
[task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToSend))];
[self.downloadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
[self.uploadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if ([object isEqual:self.downloadProgress]) { if ([object isKindOfClass:[NSURLSessionTask class]] || [object isKindOfClass:[NSURLSessionDownloadTask class]]) {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) {
self.downloadProgress.completedUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))]) {
self.downloadProgress.totalUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) {
self.uploadProgress.completedUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesExpectedToSend))]) {
self.uploadProgress.totalUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
}
}
else if ([object isEqual:self.downloadProgress]) {
if (self.downloadProgressBlock) { if (self.downloadProgressBlock) {
self.downloadProgressBlock(object); self.downloadProgressBlock(object);
} }
@ -193,6 +251,8 @@ typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id re
task:(NSURLSessionTask *)task task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error didCompleteWithError:(NSError *)error
{ {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
__strong AFURLSessionManager *manager = self.manager; __strong AFURLSessionManager *manager = self.manager;
__block id responseObject = nil; __block id responseObject = nil;
@ -254,60 +314,33 @@ didCompleteWithError:(NSError *)error
}); });
}); });
} }
#pragma clang diagnostic pop
} }
#pragma mark - NSURLSessionDataDelegate #pragma mark - NSURLSessionDataTaskDelegate
- (void)URLSession:(__unused NSURLSession *)session - (void)URLSession:(__unused NSURLSession *)session
dataTask:(__unused NSURLSessionDataTask *)dataTask dataTask:(__unused NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data didReceiveData:(NSData *)data
{ {
self.downloadProgress.totalUnitCount = dataTask.countOfBytesExpectedToReceive;
self.downloadProgress.completedUnitCount = dataTask.countOfBytesReceived;
[self.mutableData appendData:data]; [self.mutableData appendData:data];
} }
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task #pragma mark - NSURLSessionDownloadTaskDelegate
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
self.uploadProgress.totalUnitCount = task.countOfBytesExpectedToSend;
self.uploadProgress.completedUnitCount = task.countOfBytesSent;
}
#pragma mark - NSURLSessionDownloadDelegate
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
self.downloadProgress.totalUnitCount = totalBytesExpectedToWrite;
self.downloadProgress.completedUnitCount = totalBytesWritten;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
self.downloadProgress.totalUnitCount = expectedTotalBytes;
self.downloadProgress.completedUnitCount = fileOffset;
}
- (void)URLSession:(NSURLSession *)session - (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location didFinishDownloadingToURL:(NSURL *)location
{ {
NSError *fileManagerError = nil;
self.downloadFileURL = nil; self.downloadFileURL = nil;
if (self.downloadTaskDidFinishDownloading) { if (self.downloadTaskDidFinishDownloading) {
self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location); self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
if (self.downloadFileURL) { if (self.downloadFileURL) {
NSError *fileManagerError = nil; [[NSFileManager defaultManager] moveItemAtURL:location toURL:self.downloadFileURL error:&fileManagerError];
if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:self.downloadFileURL error:&fileManagerError]) { if (fileManagerError) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:fileManagerError.userInfo]; [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:fileManagerError.userInfo];
} }
} }
@ -454,7 +487,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
@property (readwrite, nonatomic, strong) NSLock *lock; @property (readwrite, nonatomic, strong) NSLock *lock;
@property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid; @property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
@property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge; @property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession AF_API_UNAVAILABLE(macos); @property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession;
@property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection; @property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge; @property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge;
@property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream; @property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
@ -575,6 +608,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
[self.lock lock]; [self.lock lock];
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate; self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
[delegate setupProgressForTask:task];
[self addNotificationObserverForTask:task]; [self addNotificationObserverForTask:task];
[self.lock unlock]; [self.lock unlock];
} }
@ -584,7 +618,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{ {
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask]; AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
delegate.manager = self; delegate.manager = self;
delegate.completionHandler = completionHandler; delegate.completionHandler = completionHandler;
@ -599,7 +633,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{ {
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:uploadTask]; AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
delegate.manager = self; delegate.manager = self;
delegate.completionHandler = completionHandler; delegate.completionHandler = completionHandler;
@ -615,7 +649,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{ {
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:downloadTask]; AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
delegate.manager = self; delegate.manager = self;
delegate.completionHandler = completionHandler; delegate.completionHandler = completionHandler;
@ -635,7 +669,9 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
- (void)removeDelegateForTask:(NSURLSessionTask *)task { - (void)removeDelegateForTask:(NSURLSessionTask *)task {
NSParameterAssert(task); NSParameterAssert(task);
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
[self.lock lock]; [self.lock lock];
[delegate cleanUpProgressForTask:task];
[self removeNotificationObserverForTask:task]; [self removeNotificationObserverForTask:task];
[self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)]; [self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)];
[self.lock unlock]; [self.lock unlock];
@ -684,11 +720,13 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
#pragma mark - #pragma mark -
- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks { - (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks {
if (cancelPendingTasks) { dispatch_async(dispatch_get_main_queue(), ^{
[self.session invalidateAndCancel]; if (cancelPendingTasks) {
} else { [self.session invalidateAndCancel];
[self.session finishTasksAndInvalidate]; } else {
} [self.session finishTasksAndInvalidate];
}
});
} }
#pragma mark - #pragma mark -
@ -743,21 +781,16 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
__block NSURLSessionUploadTask *uploadTask = nil; __block NSURLSessionUploadTask *uploadTask = nil;
url_session_manager_create_task_safely(^{ url_session_manager_create_task_safely(^{
uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL]; uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
// uploadTask may be nil on iOS7 because uploadTaskWithRequest:fromFile: may return nil despite being documented as nonnull (https://devforums.apple.com/message/926113#926113)
if (!uploadTask && self.attemptsToRecreateUploadTasksForBackgroundSessions && self.session.configuration.identifier) {
for (NSUInteger attempts = 0; !uploadTask && attempts < AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask; attempts++) {
uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
}
}
}); });
if (uploadTask) { if (!uploadTask && self.attemptsToRecreateUploadTasksForBackgroundSessions && self.session.configuration.identifier) {
[self addDelegateForUploadTask:uploadTask for (NSUInteger attempts = 0; !uploadTask && attempts < AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask; attempts++) {
progress:uploadProgressBlock uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
completionHandler:completionHandler]; }
} }
[self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];
return uploadTask; return uploadTask;
} }
@ -841,11 +874,9 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
self.sessionDidReceiveAuthenticationChallenge = block; self.sessionDidReceiveAuthenticationChallenge = block;
} }
#if !TARGET_OS_OSX
- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block { - (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block {
self.didFinishEventsForBackgroundURLSession = block; self.didFinishEventsForBackgroundURLSession = block;
} }
#endif
#pragma mark - #pragma mark -
@ -914,12 +945,9 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi
return self.dataTaskDidReceiveResponse != nil; return self.dataTaskDidReceiveResponse != nil;
} else if (selector == @selector(URLSession:dataTask:willCacheResponse:completionHandler:)) { } else if (selector == @selector(URLSession:dataTask:willCacheResponse:completionHandler:)) {
return self.dataTaskWillCacheResponse != nil; return self.dataTaskWillCacheResponse != nil;
} } else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) {
#if !TARGET_OS_OSX
else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) {
return self.didFinishEventsForBackgroundURLSession != nil; return self.didFinishEventsForBackgroundURLSession != nil;
} }
#endif
return [[self class] instancesRespondToSelector:selector]; return [[self class] instancesRespondToSelector:selector];
} }
@ -1046,12 +1074,6 @@ totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
} }
} }
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
if (delegate) {
[delegate URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend];
}
if (self.taskDidSendBodyData) { if (self.taskDidSendBodyData) {
self.taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalUnitCount); self.taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalUnitCount);
} }
@ -1137,7 +1159,6 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
} }
} }
#if !TARGET_OS_OSX
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
if (self.didFinishEventsForBackgroundURLSession) { if (self.didFinishEventsForBackgroundURLSession) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
@ -1145,7 +1166,6 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
}); });
} }
} }
#endif
#pragma mark - NSURLSessionDownloadDelegate #pragma mark - NSURLSessionDownloadDelegate
@ -1159,8 +1179,8 @@ didFinishDownloadingToURL:(NSURL *)location
if (fileURL) { if (fileURL) {
delegate.downloadFileURL = fileURL; delegate.downloadFileURL = fileURL;
NSError *error = nil; NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error];
if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error]) { if (error) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo]; [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo];
} }
@ -1179,13 +1199,6 @@ didFinishDownloadingToURL:(NSURL *)location
totalBytesWritten:(int64_t)totalBytesWritten totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{ {
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didWriteData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite];
}
if (self.downloadTaskDidWriteData) { if (self.downloadTaskDidWriteData) {
self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
} }
@ -1196,13 +1209,6 @@ totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
didResumeAtOffset:(int64_t)fileOffset didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes expectedTotalBytes:(int64_t)expectedTotalBytes
{ {
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didResumeAtOffset:fileOffset expectedTotalBytes:expectedTotalBytes];
}
if (self.downloadTaskDidResume) { if (self.downloadTaskDidResume) {
self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes); self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes);
} }

View File

@ -1,4 +1,4 @@
Copyright (c) 2011-2016 Alamofire Software Foundation (http://alamofire.org/) Copyright (c) 20112016 Alamofire Software Foundation (http://alamofire.org/)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -9,7 +9,7 @@
[![Platform](https://img.shields.io/cocoapods/p/AFNetworking.svg?style=flat)](http://cocoadocs.org/docsets/AFNetworking) [![Platform](https://img.shields.io/cocoapods/p/AFNetworking.svg?style=flat)](http://cocoadocs.org/docsets/AFNetworking)
[![Twitter](https://img.shields.io/badge/twitter-@AFNetworking-blue.svg?style=flat)](http://twitter.com/AFNetworking) [![Twitter](https://img.shields.io/badge/twitter-@AFNetworking-blue.svg?style=flat)](http://twitter.com/AFNetworking)
AFNetworking is a delightful networking library for iOS, macOS, watchOS, and tvOS. It's built on top of the [Foundation URL Loading System](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html), extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use. AFNetworking is a delightful networking library for iOS and Mac OS X. It's built on top of the [Foundation URL Loading System](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html), extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use.
Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac. Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac.
@ -51,9 +51,7 @@ To integrate AFNetworking into your Xcode project using CocoaPods, specify it in
source 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0' platform :ios, '8.0'
target 'TargetName' do
pod 'AFNetworking', '~> 3.0' pod 'AFNetworking', '~> 3.0'
end
``` ```
Then, run the following command: Then, run the following command:
@ -83,7 +81,7 @@ Run `carthage` to build the framework and drag the built `AFNetworking.framework
## Requirements ## Requirements
| AFNetworking Version | Minimum iOS Target | Minimum macOS Target | Minimum watchOS Target | Minimum tvOS Target | Notes | | AFNetworking Version | Minimum iOS Target | Minimum OS X Target | Minimum watchOS Target | Minimum tvOS Target | Notes |
|:--------------------:|:---------------------------:|:----------------------------:|:----------------------------:|:----------------------------:|:-------------------------------------------------------------------------:| |:--------------------:|:---------------------------:|:----------------------------:|:----------------------------:|:----------------------------:|:-------------------------------------------------------------------------:|
| 3.x | iOS 7 | OS X 10.9 | watchOS 2.0 | tvOS 9.0 | Xcode 7+ is required. `NSURLConnectionOperation` support has been removed. | | 3.x | iOS 7 | OS X 10.9 | watchOS 2.0 | tvOS 9.0 | Xcode 7+ is required. `NSURLConnectionOperation` support has been removed. |
| 2.6 -> 2.6.3 | iOS 7 | OS X 10.9 | watchOS 2.0 | n/a | Xcode 7+ is required. | | 2.6 -> 2.6.3 | iOS 7 | OS X 10.9 | watchOS 2.0 | n/a | Xcode 7+ is required. |
@ -91,7 +89,7 @@ Run `carthage` to build the framework and drag the built `AFNetworking.framework
| 1.x | iOS 5 | Mac OS X 10.7 | n/a | n/a | | 1.x | iOS 5 | Mac OS X 10.7 | n/a | n/a |
| 0.10.x | iOS 4 | Mac OS X 10.6 | n/a | n/a | | 0.10.x | iOS 4 | Mac OS X 10.6 | n/a | n/a |
(macOS projects must support [64-bit with modern Cocoa runtime](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html)). (OS X projects must support [64-bit with modern Cocoa runtime](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html)).
> Programming in Swift? Try [Alamofire](https://github.com/Alamofire/Alamofire) for a more conventional set of APIs. > Programming in Swift? Try [Alamofire](https://github.com/Alamofire/Alamofire) for a more conventional set of APIs.
@ -112,7 +110,7 @@ Run `carthage` to build the framework and drag the built `AFNetworking.framework
- `AFHTTPResponseSerializer` - `AFHTTPResponseSerializer`
- `AFJSONResponseSerializer` - `AFJSONResponseSerializer`
- `AFXMLParserResponseSerializer` - `AFXMLParserResponseSerializer`
- `AFXMLDocumentResponseSerializer` _(macOS)_ - `AFXMLDocumentResponseSerializer` _(Mac OS X)_
- `AFPropertyListResponseSerializer` - `AFPropertyListResponseSerializer`
- `AFImageResponseSerializer` - `AFImageResponseSerializer`
- `AFCompoundResponseSerializer` - `AFCompoundResponseSerializer`
@ -319,4 +317,4 @@ If you believe you have identified a security vulnerability with AFNetworking, y
## License ## License
AFNetworking is released under the MIT license. See [LICENSE](https://github.com/AFNetworking/AFNetworking/blob/master/LICENSE) for details. AFNetworking is released under the MIT license. See LICENSE for details.

View File

@ -72,17 +72,6 @@ NS_ASSUME_NONNULL_BEGIN
*/ */
@protocol AFImageRequestCache <AFImageCache> @protocol AFImageRequestCache <AFImageCache>
/**
Asks if the image should be cached using an identifier created from the request and additional identifier.
@param image The image to be cached.
@param request The unique URL request identifing the image asset.
@param identifier The additional identifier to apply to the URL request to identify the image.
@return A BOOL indicating whether or not the image should be added to the cache. YES will cache, NO will prevent caching.
*/
- (BOOL)shouldCacheImage:(UIImage *)image forRequest:(NSURLRequest *)request withAdditionalIdentifier:(nullable NSString *)identifier;
/** /**
Adds the image to the cache using an identifier created from the request and additional identifier. Adds the image to the cache using an identifier created from the request and additional identifier.

View File

@ -196,10 +196,6 @@
return key; return key;
} }
- (BOOL)shouldCacheImage:(UIImage *)image forRequest:(NSURLRequest *)request withAdditionalIdentifier:(nullable NSString *)identifier {
return YES;
}
@end @end
#endif #endif

View File

@ -81,11 +81,6 @@ typedef NS_ENUM(NSInteger, AFImageDownloadPrioritization) {
*/ */
+ (NSURLCache *)defaultURLCache; + (NSURLCache *)defaultURLCache;
/**
The default `NSURLSessionConfiguration` with common usage parameter values.
*/
+ (NSURLSessionConfiguration *)defaultURLSessionConfiguration;
/** /**
Default initializer Default initializer
@ -93,15 +88,6 @@ typedef NS_ENUM(NSInteger, AFImageDownloadPrioritization) {
*/ */
- (instancetype)init; - (instancetype)init;
/**
Initializer with specific `URLSessionConfiguration`
@param configuration The `NSURLSessionConfiguration` to be be used
@return An instance of `AFImageDownloader` initialized with default values and custom `NSURLSessionConfiguration`
*/
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration;
/** /**
Initializes the `AFImageDownloader` instance with the given session manager, download prioritization, maximum active download count and image cache. Initializes the `AFImageDownloader` instance with the given session manager, download prioritization, maximum active download count and image cache.

View File

@ -106,20 +106,10 @@
@end @end
@implementation AFImageDownloader @implementation AFImageDownloader
+ (NSURLCache *)defaultURLCache { + (NSURLCache *)defaultURLCache {
// It's been discovered that a crash will occur on certain versions
// of iOS if you customize the cache.
//
// More info can be found here: https://devforums.apple.com/message/1102182#1102182
//
// When iOS 7 support is dropped, this should be modified to use
// NSProcessInfo methods instead.
if ([[[UIDevice currentDevice] systemVersion] compare:@"8.2" options:NSNumericSearch] == NSOrderedAscending) {
return [NSURLCache sharedURLCache];
}
return [[NSURLCache alloc] initWithMemoryCapacity:20 * 1024 * 1024 return [[NSURLCache alloc] initWithMemoryCapacity:20 * 1024 * 1024
diskCapacity:150 * 1024 * 1024 diskCapacity:150 * 1024 * 1024
diskPath:@"com.alamofire.imagedownloader"]; diskPath:@"com.alamofire.imagedownloader"];
@ -143,11 +133,7 @@
- (instancetype)init { - (instancetype)init {
NSURLSessionConfiguration *defaultConfiguration = [self.class defaultURLSessionConfiguration]; NSURLSessionConfiguration *defaultConfiguration = [self.class defaultURLSessionConfiguration];
return [self initWithSessionConfiguration:defaultConfiguration]; AFHTTPSessionManager *sessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:defaultConfiguration];
}
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
AFHTTPSessionManager *sessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];
sessionManager.responseSerializer = [AFImageResponseSerializer serializer]; sessionManager.responseSerializer = [AFImageResponseSerializer serializer];
return [self initWithSessionManager:sessionManager return [self initWithSessionManager:sessionManager
@ -249,12 +235,10 @@
createdTask = [self.sessionManager createdTask = [self.sessionManager
dataTaskWithRequest:request dataTaskWithRequest:request
uploadProgress:nil
downloadProgress:nil
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
dispatch_async(self.responseQueue, ^{ dispatch_async(self.responseQueue, ^{
__strong __typeof__(weakSelf) strongSelf = weakSelf; __strong __typeof__(weakSelf) strongSelf = weakSelf;
AFImageDownloaderMergedTask *mergedTask = strongSelf.mergedTasks[URLIdentifier]; AFImageDownloaderMergedTask *mergedTask = self.mergedTasks[URLIdentifier];
if ([mergedTask.identifier isEqual:mergedTaskIdentifier]) { if ([mergedTask.identifier isEqual:mergedTaskIdentifier]) {
mergedTask = [strongSelf safelyRemoveMergedTaskWithURLIdentifier:URLIdentifier]; mergedTask = [strongSelf safelyRemoveMergedTaskWithURLIdentifier:URLIdentifier];
if (error) { if (error) {
@ -266,9 +250,7 @@
} }
} }
} else { } else {
if ([strongSelf.imageCache shouldCacheImage:responseObject forRequest:request withAdditionalIdentifier:nil]) { [strongSelf.imageCache addImage:responseObject forRequest:request withAdditionalIdentifier:nil];
[strongSelf.imageCache addImage:responseObject forRequest:request withAdditionalIdentifier:nil];
}
for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) { for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) {
if (handler.successBlock) { if (handler.successBlock) {

View File

@ -147,7 +147,10 @@ typedef void (^AFNetworkActivityActionBlock)(BOOL networkActivityIndicatorVisibl
- (void)decrementActivityCount { - (void)decrementActivityCount {
[self willChangeValueForKey:@"activityCount"]; [self willChangeValueForKey:@"activityCount"];
@synchronized(self) { @synchronized(self) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
_activityCount = MAX(_activityCount - 1, 0); _activityCount = MAX(_activityCount - 1, 0);
#pragma clang diagnostic pop
} }
[self didChangeValueForKey:@"activityCount"]; [self didChangeValueForKey:@"activityCount"];
@ -191,9 +194,8 @@ typedef void (^AFNetworkActivityActionBlock)(BOOL networkActivityIndicatorVisibl
[self startCompletionDelayTimer]; [self startCompletionDelayTimer];
break; break;
} }
[self didChangeValueForKey:@"currentState"];
} }
[self didChangeValueForKey:@"currentState"];
} }
} }

View File

@ -71,12 +71,16 @@
if (task) { if (task) {
if (task.state != NSURLSessionTaskStateCompleted) { if (task.state != NSURLSessionTaskStateCompleted) {
UIActivityIndicatorView *activityIndicatorView = self.activityIndicatorView;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreceiver-is-weak"
#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak"
if (task.state == NSURLSessionTaskStateRunning) { if (task.state == NSURLSessionTaskStateRunning) {
[activityIndicatorView startAnimating]; [self.activityIndicatorView startAnimating];
} else { } else {
[activityIndicatorView stopAnimating]; [self.activityIndicatorView stopAnimating];
} }
#pragma clang diagnostic pop
[notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task];
[notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task];
@ -89,13 +93,19 @@
- (void)af_startAnimating { - (void)af_startAnimating {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreceiver-is-weak"
[self.activityIndicatorView startAnimating]; [self.activityIndicatorView startAnimating];
#pragma clang diagnostic pop
}); });
} }
- (void)af_stopAnimating { - (void)af_stopAnimating {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreceiver-is-weak"
[self.activityIndicatorView stopAnimating]; [self.activityIndicatorView stopAnimating];
#pragma clang diagnostic pop
}); });
} }

View File

@ -103,7 +103,10 @@ static const char * af_backgroundImageDownloadReceiptKeyForState(UIControlState
+ (AFImageDownloader *)sharedImageDownloader { + (AFImageDownloader *)sharedImageDownloader {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
return objc_getAssociatedObject(self, @selector(sharedImageDownloader)) ?: [AFImageDownloader defaultInstance]; return objc_getAssociatedObject(self, @selector(sharedImageDownloader)) ?: [AFImageDownloader defaultInstance];
#pragma clang diagnostic pop
} }
+ (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader { + (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader {

View File

@ -48,7 +48,11 @@
@implementation UIImageView (AFNetworking) @implementation UIImageView (AFNetworking)
+ (AFImageDownloader *)sharedImageDownloader { + (AFImageDownloader *)sharedImageDownloader {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
return objc_getAssociatedObject(self, @selector(sharedImageDownloader)) ?: [AFImageDownloader defaultInstance]; return objc_getAssociatedObject(self, @selector(sharedImageDownloader)) ?: [AFImageDownloader defaultInstance];
#pragma clang diagnostic pop
} }
+ (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader { + (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader {
@ -77,11 +81,8 @@
{ {
if ([urlRequest URL] == nil) { if ([urlRequest URL] == nil) {
[self cancelImageDownloadTask];
self.image = placeholderImage; self.image = placeholderImage;
if (failure) {
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil];
failure(urlRequest, nil, error);
}
return; return;
} }

View File

@ -55,10 +55,6 @@ static void * AFTaskCountOfBytesReceivedContext = &AFTaskCountOfBytesReceivedCon
- (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task - (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task
animated:(BOOL)animated animated:(BOOL)animated
{ {
if (task.state == NSURLSessionTaskStateCompleted) {
return;
}
[task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesSentContext]; [task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesSentContext];
[task addObserver:self forKeyPath:@"countOfBytesSent" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesSentContext]; [task addObserver:self forKeyPath:@"countOfBytesSent" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesSentContext];
@ -68,10 +64,6 @@ static void * AFTaskCountOfBytesReceivedContext = &AFTaskCountOfBytesReceivedCon
- (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task - (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task
animated:(BOOL)animated animated:(BOOL)animated
{ {
if (task.state == NSURLSessionTaskStateCompleted) {
return;
}
[task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext]; [task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext];
[task addObserver:self forKeyPath:@"countOfBytesReceived" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext]; [task addObserver:self forKeyPath:@"countOfBytesReceived" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext];

View File

@ -71,16 +71,19 @@
[notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil];
if (task) { if (task) {
UIRefreshControl *refreshControl = self.refreshControl; #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreceiver-is-weak"
#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak"
if (task.state == NSURLSessionTaskStateRunning) { if (task.state == NSURLSessionTaskStateRunning) {
[refreshControl beginRefreshing]; [self.refreshControl beginRefreshing];
[notificationCenter addObserver:self selector:@selector(af_beginRefreshing) name:AFNetworkingTaskDidResumeNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_beginRefreshing) name:AFNetworkingTaskDidResumeNotification object:task];
[notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidCompleteNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidCompleteNotification object:task];
[notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidSuspendNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidSuspendNotification object:task];
} else { } else {
[refreshControl endRefreshing]; [self.refreshControl endRefreshing];
} }
#pragma clang diagnostic pop
} }
} }
@ -88,13 +91,19 @@
- (void)af_beginRefreshing { - (void)af_beginRefreshing {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreceiver-is-weak"
[self.refreshControl beginRefreshing]; [self.refreshControl beginRefreshing];
#pragma clang diagnostic pop
}); });
} }
- (void)af_endRefreshing { - (void)af_endRefreshing {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreceiver-is-weak"
[self.refreshControl endRefreshing]; [self.refreshControl endRefreshing];
#pragma clang diagnostic pop
}); });
} }

View File

@ -58,7 +58,10 @@
_af_defaultHTTPSessionManager.responseSerializer = [AFHTTPResponseSerializer serializer]; _af_defaultHTTPSessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];
}); });
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
return objc_getAssociatedObject(self, @selector(sessionManager)) ?: _af_defaultHTTPSessionManager; return objc_getAssociatedObject(self, @selector(sessionManager)) ?: _af_defaultHTTPSessionManager;
#pragma clang diagnostic pop
} }
- (void)setSessionManager:(AFHTTPSessionManager *)sessionManager { - (void)setSessionManager:(AFHTTPSessionManager *)sessionManager {
@ -72,7 +75,10 @@
_af_defaultResponseSerializer = [AFHTTPResponseSerializer serializer]; _af_defaultResponseSerializer = [AFHTTPResponseSerializer serializer];
}); });
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
return objc_getAssociatedObject(self, @selector(responseSerializer)) ?: _af_defaultResponseSerializer; return objc_getAssociatedObject(self, @selector(responseSerializer)) ?: _af_defaultResponseSerializer;
#pragma clang diagnostic pop
} }
- (void)setResponseSerializer:(AFHTTPResponseSerializer<AFURLResponseSerialization> *)responseSerializer { - (void)setResponseSerializer:(AFHTTPResponseSerializer<AFURLResponseSerialization> *)responseSerializer {
@ -119,28 +125,27 @@
self.af_URLSessionTask = nil; self.af_URLSessionTask = nil;
__weak __typeof(self)weakSelf = self; __weak __typeof(self)weakSelf = self;
__block NSURLSessionDataTask *dataTask; NSURLSessionDataTask *dataTask;
dataTask = [self.sessionManager dataTask = [self.sessionManager
dataTaskWithRequest:request GET:request.URL.absoluteString
uploadProgress:nil parameters:nil
downloadProgress:nil progress:nil
completionHandler:^(NSURLResponse * _Nonnull response, id _Nonnull responseObject, NSError * _Nullable error) { success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
__strong __typeof(weakSelf) strongSelf = weakSelf; __strong __typeof(weakSelf) strongSelf = weakSelf;
if (error) { if (success) {
if (failure) { success((NSHTTPURLResponse *)task.response, responseObject);
failure(error); }
} [strongSelf loadData:responseObject MIMEType:MIMEType textEncodingName:textEncodingName baseURL:[task.currentRequest URL]];
} else {
if (success) {
success((NSHTTPURLResponse *)response, responseObject);
}
[strongSelf loadData:responseObject MIMEType:MIMEType textEncodingName:textEncodingName baseURL:[dataTask.currentRequest URL]];
if ([strongSelf.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { if ([strongSelf.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[strongSelf.delegate webViewDidFinishLoad:strongSelf]; [strongSelf.delegate webViewDidFinishLoad:strongSelf];
} }
} }
}]; failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
self.af_URLSessionTask = dataTask; self.af_URLSessionTask = dataTask;
if (progress != nil) { if (progress != nil) {
*progress = [self.sessionManager downloadProgressForTask:dataTask]; *progress = [self.sessionManager downloadProgressForTask:dataTask];

View File

@ -60,12 +60,6 @@ FBSDK_EXTERN NSString *const FBSDKAccessTokenChangeOldKey;
*/ */
FBSDK_EXTERN NSString *const FBSDKAccessTokenChangeNewKey; FBSDK_EXTERN NSString *const FBSDKAccessTokenChangeNewKey;
/*
A key in the notification's userInfo that will be set
if and only if the token has expired.
*/
FBSDK_EXTERN NSString *const FBSDKAccessTokenDidExpire;
/** /**
Represents an immutable access token for using Facebook services. Represents an immutable access token for using Facebook services.
@ -77,11 +71,6 @@ FBSDK_EXTERN NSString *const FBSDKAccessTokenDidExpire;
*/ */
@property (readonly, copy, nonatomic) NSString *appID; @property (readonly, copy, nonatomic) NSString *appID;
/**
Returns the expiration date for data access
*/
@property (readonly, copy, nonatomic) NSDate *dataAccessExpirationDate;
/** /**
Returns the known declined permissions. Returns the known declined permissions.
*/ */
@ -112,56 +101,20 @@ FBSDK_EXTERN NSString *const FBSDKAccessTokenDidExpire;
*/ */
@property (readonly, copy, nonatomic) NSString *userID; @property (readonly, copy, nonatomic) NSString *userID;
/**
Returns whether the access token is expired by checking its expirationDate property
*/
@property (readonly, assign, nonatomic, getter = isExpired) BOOL expired;
/**
Returns whether user data access is still active for the given access token
*/
@property (readonly, assign, nonatomic, getter = isDataAccessExpired) BOOL dataAccessExpired;
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE;
/**
Initializes a new instance.
@param tokenString the opaque token string.
@param permissions the granted permissions. Note this is converted to NSSet and is only
an NSArray for the convenience of literal syntax.
@param declinedPermissions the declined permissions. Note this is converted to NSSet and is only
an NSArray for the convenience of literal syntax.
@param appID the app ID.
@param userID the user ID.
@param expirationDate the optional expiration date (defaults to distantFuture).
@param refreshDate the optional date the token was last refreshed (defaults to today).
This initializer should only be used for advanced apps that
manage tokens explicitly. Typical login flows only need to use `FBSDKLoginManager`
along with `+currentAccessToken`.
*/
- (instancetype)initWithTokenString:(NSString *)tokenString
permissions:(NSArray *)permissions
declinedPermissions:(NSArray *)declinedPermissions
appID:(NSString *)appID
userID:(NSString *)userID
expirationDate:(NSDate *)expirationDate
refreshDate:(NSDate *)refreshDate;
/** /**
Initializes a new instance. Initializes a new instance.
@param tokenString the opaque token string. - Parameter tokenString: the opaque token string.
@param permissions the granted permissions. Note this is converted to NSSet and is only - Parameter permissions: the granted permissions. Note this is converted to NSSet and is only
an NSArray for the convenience of literal syntax. an NSArray for the convenience of literal syntax.
@param declinedPermissions the declined permissions. Note this is converted to NSSet and is only - Parameter declinedPermissions: the declined permissions. Note this is converted to NSSet and is only
an NSArray for the convenience of literal syntax. an NSArray for the convenience of literal syntax.
@param appID the app ID. - Parameter appID: the app ID.
@param userID the user ID. - Parameter userID: the user ID.
@param expirationDate the optional expiration date (defaults to distantFuture). - Parameter expirationDate: the optional expiration date (defaults to distantFuture).
@param refreshDate the optional date the token was last refreshed (defaults to today). - Parameter refreshDate: the optional date the token was last refreshed (defaults to today).
@param dataAccessExpirationDate the date which data access will expire for the given user
(defaults to distantFuture).
This initializer should only be used for advanced apps that This initializer should only be used for advanced apps that
manage tokens explicitly. Typical login flows only need to use `FBSDKLoginManager` manage tokens explicitly. Typical login flows only need to use `FBSDKLoginManager`
@ -174,19 +127,18 @@ FBSDK_EXTERN NSString *const FBSDKAccessTokenDidExpire;
userID:(NSString *)userID userID:(NSString *)userID
expirationDate:(NSDate *)expirationDate expirationDate:(NSDate *)expirationDate
refreshDate:(NSDate *)refreshDate refreshDate:(NSDate *)refreshDate
dataAccessExpirationDate:(NSDate *)dataAccessExpirationDate
NS_DESIGNATED_INITIALIZER; NS_DESIGNATED_INITIALIZER;
/** /**
Convenience getter to determine if a permission has been granted Convenience getter to determine if a permission has been granted
@param permission The permission to check. - Parameter permission: The permission to check.
*/ */
- (BOOL)hasGranted:(NSString *)permission; - (BOOL)hasGranted:(NSString *)permission;
/** /**
Compares the receiver to another FBSDKAccessToken Compares the receiver to another FBSDKAccessToken
@param token The other token - Parameter token: The other token
@return YES if the receiver's values are equal to the other token's values; otherwise NO - Returns: YES if the receiver's values are equal to the other token's values; otherwise NO
*/ */
- (BOOL)isEqualToAccessToken:(FBSDKAccessToken *)token; - (BOOL)isEqualToAccessToken:(FBSDKAccessToken *)token;
@ -198,15 +150,9 @@ NS_DESIGNATED_INITIALIZER;
*/ */
+ (FBSDKAccessToken *)currentAccessToken; + (FBSDKAccessToken *)currentAccessToken;
/**
Returns YES if currentAccessToken is not nil AND currentAccessToken is not expired
*/
+ (BOOL)currentAccessTokenIsActive;
/** /**
Sets the "global" access token that represents the currently logged in user. Sets the "global" access token that represents the currently logged in user.
@param token The access token to set. - Parameter token: The access token to set.
This will broadcast a notification and save the token to the app keychain. This will broadcast a notification and save the token to the app keychain.
*/ */
@ -215,7 +161,7 @@ NS_DESIGNATED_INITIALIZER;
/** /**
Refresh the current access token's permission state and extend the token's expiration date, Refresh the current access token's permission state and extend the token's expiration date,
if possible. if possible.
@param completionHandler an optional callback handler that can surface any errors related to permission refreshing. - Parameter completionHandler: an optional callback handler that can surface any errors related to permission refreshing.
On a successful refresh, the currentAccessToken will be updated so you typically only need to On a successful refresh, the currentAccessToken will be updated so you typically only need to
observe the `FBSDKAccessTokenDidChangeNotification` notification. observe the `FBSDKAccessTokenDidChangeNotification` notification.

View File

@ -27,7 +27,6 @@ NSString *const FBSDKAccessTokenDidChangeNotification = @"com.facebook.sdk.FBSDK
NSString *const FBSDKAccessTokenDidChangeUserID = @"FBSDKAccessTokenDidChangeUserID"; NSString *const FBSDKAccessTokenDidChangeUserID = @"FBSDKAccessTokenDidChangeUserID";
NSString *const FBSDKAccessTokenChangeNewKey = @"FBSDKAccessToken"; NSString *const FBSDKAccessTokenChangeNewKey = @"FBSDKAccessToken";
NSString *const FBSDKAccessTokenChangeOldKey = @"FBSDKAccessTokenOld"; NSString *const FBSDKAccessTokenChangeOldKey = @"FBSDKAccessTokenOld";
NSString *const FBSDKAccessTokenDidExpire = @"FBSDKAccessTokenDidExpire";
static FBSDKAccessToken *g_currentAccessToken; static FBSDKAccessToken *g_currentAccessToken;
@ -38,8 +37,6 @@ static FBSDKAccessToken *g_currentAccessToken;
#define FBSDK_ACCESSTOKEN_USERID_KEY @"userID" #define FBSDK_ACCESSTOKEN_USERID_KEY @"userID"
#define FBSDK_ACCESSTOKEN_REFRESHDATE_KEY @"refreshDate" #define FBSDK_ACCESSTOKEN_REFRESHDATE_KEY @"refreshDate"
#define FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY @"expirationDate" #define FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY @"expirationDate"
#define FBSDK_ACCESSTOKEN_DATA_EXPIRATIONDATE_KEY @"dataAccessExpirationDate"
@implementation FBSDKAccessToken @implementation FBSDKAccessToken
@ -55,25 +52,6 @@ static FBSDKAccessToken *g_currentAccessToken;
userID:(NSString *)userID userID:(NSString *)userID
expirationDate:(NSDate *)expirationDate expirationDate:(NSDate *)expirationDate
refreshDate:(NSDate *)refreshDate refreshDate:(NSDate *)refreshDate
{
return [self initWithTokenString:tokenString
permissions:permissions
declinedPermissions:declinedPermissions
appID:appID
userID:userID
expirationDate:expirationDate
refreshDate:refreshDate
dataAccessExpirationDate:[NSDate distantFuture]];
}
- (instancetype)initWithTokenString:(NSString *)tokenString
permissions:(NSArray *)permissions
declinedPermissions:(NSArray *)declinedPermissions
appID:(NSString *)appID
userID:(NSString *)userID
expirationDate:(NSDate *)expirationDate
refreshDate:(NSDate *)refreshDate
dataAccessExpirationDate:(NSDate *)dataAccessExpirationDate
{ {
if ((self = [super init])) { if ((self = [super init])) {
_tokenString = [tokenString copy]; _tokenString = [tokenString copy];
@ -83,7 +61,6 @@ static FBSDKAccessToken *g_currentAccessToken;
_userID = [userID copy]; _userID = [userID copy];
_expirationDate = [expirationDate copy] ?: [NSDate distantFuture]; _expirationDate = [expirationDate copy] ?: [NSDate distantFuture];
_refreshDate = [refreshDate copy] ?: [NSDate date]; _refreshDate = [refreshDate copy] ?: [NSDate date];
_dataAccessExpirationDate = [dataAccessExpirationDate copy] ?: [NSDate distantFuture];
} }
return self; return self;
} }
@ -91,17 +68,6 @@ static FBSDKAccessToken *g_currentAccessToken;
- (BOOL)hasGranted:(NSString *)permission - (BOOL)hasGranted:(NSString *)permission
{ {
return [self.permissions containsObject:permission]; return [self.permissions containsObject:permission];
}
- (BOOL)isDataAccessExpired
{
return [self.dataAccessExpirationDate compare:NSDate.date] == NSOrderedAscending;
}
- (BOOL)isExpired
{
return [self.expirationDate compare:NSDate.date] == NSOrderedAscending;
} }
+ (FBSDKAccessToken *)currentAccessToken + (FBSDKAccessToken *)currentAccessToken
@ -115,8 +81,7 @@ static FBSDKAccessToken *g_currentAccessToken;
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[FBSDKInternalUtility dictionary:userInfo setObject:token forKey:FBSDKAccessTokenChangeNewKey]; [FBSDKInternalUtility dictionary:userInfo setObject:token forKey:FBSDKAccessTokenChangeNewKey];
[FBSDKInternalUtility dictionary:userInfo setObject:g_currentAccessToken forKey:FBSDKAccessTokenChangeOldKey]; [FBSDKInternalUtility dictionary:userInfo setObject:g_currentAccessToken forKey:FBSDKAccessTokenChangeOldKey];
// We set this flag also when the current Access Token was not valid, since there might be legacy code relying on it if (![g_currentAccessToken.userID isEqualToString:token.userID]) {
if (![g_currentAccessToken.userID isEqualToString:token.userID] || ![self currentAccessTokenIsActive]) {
userInfo[FBSDKAccessTokenDidChangeUserID] = @YES; userInfo[FBSDKAccessTokenDidChangeUserID] = @YES;
} }
@ -135,12 +100,6 @@ static FBSDKAccessToken *g_currentAccessToken;
} }
} }
+ (BOOL)currentAccessTokenIsActive
{
FBSDKAccessToken *currentAccessToken = [self currentAccessToken];
return currentAccessToken != nil && !currentAccessToken.isExpired;
}
+ (void)refreshCurrentAccessToken:(FBSDKGraphRequestHandler)completionHandler + (void)refreshCurrentAccessToken:(FBSDKGraphRequestHandler)completionHandler
{ {
if ([FBSDKAccessToken currentAccessToken]) { if ([FBSDKAccessToken currentAccessToken]) {
@ -165,8 +124,7 @@ static FBSDKAccessToken *g_currentAccessToken;
[self.appID hash], [self.appID hash],
[self.userID hash], [self.userID hash],
[self.refreshDate hash], [self.refreshDate hash],
[self.expirationDate hash], [self.expirationDate hash]
[self.dataAccessExpirationDate hash]
}; };
return [FBSDKMath hashWithIntegerArray:subhashes count:sizeof(subhashes) / sizeof(subhashes[0])]; return [FBSDKMath hashWithIntegerArray:subhashes count:sizeof(subhashes) / sizeof(subhashes[0])];
} }
@ -191,8 +149,7 @@ static FBSDKAccessToken *g_currentAccessToken;
[FBSDKInternalUtility object:self.appID isEqualToObject:token.appID] && [FBSDKInternalUtility object:self.appID isEqualToObject:token.appID] &&
[FBSDKInternalUtility object:self.userID isEqualToObject:token.userID] && [FBSDKInternalUtility object:self.userID isEqualToObject:token.userID] &&
[FBSDKInternalUtility object:self.refreshDate isEqualToObject:token.refreshDate] && [FBSDKInternalUtility object:self.refreshDate isEqualToObject:token.refreshDate] &&
[FBSDKInternalUtility object:self.expirationDate isEqualToObject:token.expirationDate] && [FBSDKInternalUtility object:self.expirationDate isEqualToObject:token.expirationDate] );
[FBSDKInternalUtility object:self.dataAccessExpirationDate isEqualToObject:token.dataAccessExpirationDate] );
} }
#pragma mark - NSCopying #pragma mark - NSCopying
@ -219,7 +176,6 @@ static FBSDKAccessToken *g_currentAccessToken;
NSString *userID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_ACCESSTOKEN_USERID_KEY]; NSString *userID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_ACCESSTOKEN_USERID_KEY];
NSDate *refreshDate = [decoder decodeObjectOfClass:[NSDate class] forKey:FBSDK_ACCESSTOKEN_REFRESHDATE_KEY]; NSDate *refreshDate = [decoder decodeObjectOfClass:[NSDate class] forKey:FBSDK_ACCESSTOKEN_REFRESHDATE_KEY];
NSDate *expirationDate = [decoder decodeObjectOfClass:[NSDate class] forKey:FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY]; NSDate *expirationDate = [decoder decodeObjectOfClass:[NSDate class] forKey:FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY];
NSDate *dataAccessExpirationDate = [decoder decodeObjectOfClass:[NSDate class] forKey:FBSDK_ACCESSTOKEN_DATA_EXPIRATIONDATE_KEY];
return [self initWithTokenString:tokenString return [self initWithTokenString:tokenString
permissions:[permissions allObjects] permissions:[permissions allObjects]
@ -227,8 +183,7 @@ static FBSDKAccessToken *g_currentAccessToken;
appID:appID appID:appID
userID:userID userID:userID
expirationDate:expirationDate expirationDate:expirationDate
refreshDate:refreshDate refreshDate:refreshDate];
dataAccessExpirationDate:dataAccessExpirationDate];
} }
- (void)encodeWithCoder:(NSCoder *)encoder - (void)encodeWithCoder:(NSCoder *)encoder
@ -240,7 +195,6 @@ static FBSDKAccessToken *g_currentAccessToken;
[encoder encodeObject:self.userID forKey:FBSDK_ACCESSTOKEN_USERID_KEY]; [encoder encodeObject:self.userID forKey:FBSDK_ACCESSTOKEN_USERID_KEY];
[encoder encodeObject:self.expirationDate forKey:FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY]; [encoder encodeObject:self.expirationDate forKey:FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY];
[encoder encodeObject:self.refreshDate forKey:FBSDK_ACCESSTOKEN_REFRESHDATE_KEY]; [encoder encodeObject:self.refreshDate forKey:FBSDK_ACCESSTOKEN_REFRESHDATE_KEY];
[encoder encodeObject:self.dataAccessExpirationDate forKey:FBSDK_ACCESSTOKEN_DATA_EXPIRATIONDATE_KEY];
} }
@end @end

View File

@ -18,10 +18,6 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#if !TARGET_OS_TV
#import <WebKit/WebKit.h>
#endif
#import <FBSDKCoreKit/FBSDKGraphRequestConnection.h> #import <FBSDKCoreKit/FBSDKGraphRequestConnection.h>
#import "FBSDKMacros.h" #import "FBSDKMacros.h"
@ -55,45 +51,6 @@ typedef NS_ENUM(NSUInteger, FBSDKAppEventsFlushBehavior)
}; };
/**
NS_ENUM(NSUInteger, FBSDKProductAvailability)
Specifies product availability for Product Catalog product item update
*/
typedef NS_ENUM(NSUInteger, FBSDKProductAvailability)
{
/**
* Item ships immediately
*/
FBSDKProductAvailabilityInStock = 0,
/**
* No plan to restock
*/
FBSDKProductAvailabilityOutOfStock,
/**
* Available in future
*/
FBSDKProductAvailabilityPreOrder,
/**
* Ships in 1-2 weeks
*/
FBSDKProductAvailabilityAvailableForOrder,
/**
* Discontinued
*/
FBSDKProductAvailabilityDiscontinued,
};
/**
NS_ENUM(NSUInteger, FBSDKProductCondition)
Specifies product condition for Product Catalog product item update
*/
typedef NS_ENUM(NSUInteger, FBSDKProductCondition)
{
FBSDKProductConditionNew = 0,
FBSDKProductConditionRefurbished,
FBSDKProductConditionUsed,
};
/** /**
@methodgroup Predefined event names for logging events common to many apps. Logging occurs through the `logEvent` family of methods on `FBSDKAppEvents`. @methodgroup Predefined event names for logging events common to many apps. Logging occurs through the `logEvent` family of methods on `FBSDKAppEvents`.
Common event parameters are provided in the `FBSDKAppEventsParameterNames*` constants. Common event parameters are provided in the `FBSDKAppEventsParameterNames*` constants.
@ -135,36 +92,6 @@ FBSDK_EXTERN NSString *const FBSDKAppEventNameUnlockedAchievement;
/** Log this event when a user has viewed a form of content in the app. */ /** Log this event when a user has viewed a form of content in the app. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameViewedContent; FBSDK_EXTERN NSString *const FBSDKAppEventNameViewedContent;
/** A telephone/SMS, email, chat or other type of contact between a customer and your business. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameContact;
/** The customization of products through a configuration tool or other application your business owns. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameCustomizeProduct;
/** The donation of funds to your organization or cause. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameDonate;
/** When a person finds one of your locations via web or application, with an intention to visit (example: find product at a local store). */
FBSDK_EXTERN NSString *const FBSDKAppEventNameFindLocation;
/** The booking of an appointment to visit one of your locations. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameSchedule;
/** The start of a free trial of a product or service you offer (example: trial subscription). */
FBSDK_EXTERN NSString *const FBSDKAppEventNameStartTrial;
/** The submission of an application for a product, service or program you offer (example: credit card, educational program or job).. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameSubmitApplication;
/** The start of a paid subscription for a product or service you offer. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameSubscribe;
/** Log this event when the user views an ad. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameAdImpression;
/** Log this event when the user clicks an ad. */
FBSDK_EXTERN NSString *const FBSDKAppEventNameAdClick;
/** /**
@methodgroup Predefined event name parameters for common additional information to accompany events logged through the `logEvent` family @methodgroup Predefined event name parameters for common additional information to accompany events logged through the `logEvent` family
of methods on `FBSDKAppEvents`. Common event names are provided in the `FBAppEventName*` constants. of methods on `FBSDKAppEvents`. Common event names are provided in the `FBAppEventName*` constants.
@ -222,14 +149,6 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterValueYes;
/** No-valued parameter value to be used with parameter keys that need a Yes/No value */ /** No-valued parameter value to be used with parameter keys that need a Yes/No value */
FBSDK_EXTERN NSString *const FBSDKAppEventParameterValueNo; FBSDK_EXTERN NSString *const FBSDKAppEventParameterValueNo;
/** Parameter key used to specify the type of ad in an FBSDKAppEventNameAdImpression
* or FBSDKAppEventNameAdClick event.
* E.g. "banner", "interstitial", "rewarded_video", "native" */
FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameAdType;
/** Parameter key used to specify the unique ID for all events within a subscription
* in an FBSDKAppEventNameSubscribe or FBSDKAppEventNameStartTrial event. */
FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
/** /**
@ -290,7 +209,7 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Log an event with just an eventName. Log an event with just an eventName.
@param eventName The name of the event to record. Limitations on number of events and name length - Parameter eventName: The name of the event to record. Limitations on number of events and name length
are given in the `FBSDKAppEvents` documentation. are given in the `FBSDKAppEvents` documentation.
*/ */
@ -300,10 +219,10 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Log an event with an eventName and a numeric value to be aggregated with other events of this name. Log an event with an eventName and a numeric value to be aggregated with other events of this name.
@param eventName The name of the event to record. Limitations on number of events and name length - Parameter eventName: The name of the event to record. Limitations on number of events and name length
are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants. are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants.
@param valueToSum Amount to be aggregated into all events of this eventName, and App Insights will report - Parameter valueToSum: Amount to be aggregated into all events of this eventName, and App Insights will report
the cumulative and average value of this amount. the cumulative and average value of this amount.
*/ */
+ (void)logEvent:(NSString *)eventName + (void)logEvent:(NSString *)eventName
@ -315,10 +234,10 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Log an event with an eventName and a set of key/value pairs in the parameters dictionary. Log an event with an eventName and a set of key/value pairs in the parameters dictionary.
Parameter limitations are described above. Parameter limitations are described above.
@param eventName The name of the event to record. Limitations on number of events and name construction - Parameter eventName: The name of the event to record. Limitations on number of events and name construction
are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants. are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants.
@param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must - Parameter parameters: Arbitrary parameter dictionary of characteristics. The keys to this dictionary must
be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
are provided in `FBSDKAppEventParameterName*` constants. are provided in `FBSDKAppEventParameterName*` constants.
@ -331,13 +250,13 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Log an event with an eventName, a numeric value to be aggregated with other events of this name, Log an event with an eventName, a numeric value to be aggregated with other events of this name,
and a set of key/value pairs in the parameters dictionary. and a set of key/value pairs in the parameters dictionary.
@param eventName The name of the event to record. Limitations on number of events and name construction - Parameter eventName: The name of the event to record. Limitations on number of events and name construction
are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants. are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants.
@param valueToSum Amount to be aggregated into all events of this eventName, and App Insights will report - Parameter valueToSum: Amount to be aggregated into all events of this eventName, and App Insights will report
the cumulative and average value of this amount. the cumulative and average value of this amount.
@param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must - Parameter parameters: Arbitrary parameter dictionary of characteristics. The keys to this dictionary must
be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
are provided in `FBSDKAppEventParameterName*` constants. are provided in `FBSDKAppEventParameterName*` constants.
@ -354,19 +273,19 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
and a set of key/value pairs in the parameters dictionary. Providing session lets the developer and a set of key/value pairs in the parameters dictionary. Providing session lets the developer
target a particular <FBSession>. If nil is provided, then `[FBSession activeSession]` will be used. target a particular <FBSession>. If nil is provided, then `[FBSession activeSession]` will be used.
@param eventName The name of the event to record. Limitations on number of events and name construction - Parameter eventName: The name of the event to record. Limitations on number of events and name construction
are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants. are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants.
@param valueToSum Amount to be aggregated into all events of this eventName, and App Insights will report - Parameter valueToSum: Amount to be aggregated into all events of this eventName, and App Insights will report
the cumulative and average value of this amount. Note that this is an NSNumber, and a value of `nil` denotes the cumulative and average value of this amount. Note that this is an NSNumber, and a value of `nil` denotes
that this event doesn't have a value associated with it for summation. that this event doesn't have a value associated with it for summation.
@param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must - Parameter parameters: Arbitrary parameter dictionary of characteristics. The keys to this dictionary must
be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
are provided in `FBSDKAppEventParameterName*` constants. are provided in `FBSDKAppEventParameterName*` constants.
@param accessToken The optional access token to log the event as. - Parameter accessToken: The optional access token to log the event as.
*/ */
+ (void)logEvent:(NSString *)eventName + (void)logEvent:(NSString *)eventName
valueToSum:(NSNumber *)valueToSum valueToSum:(NSNumber *)valueToSum
@ -381,10 +300,10 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Log a purchase of the specified amount, in the specified currency. Log a purchase of the specified amount, in the specified currency.
@param purchaseAmount Purchase amount to be logged, as expressed in the specified currency. This value - Parameter purchaseAmount: Purchase amount to be logged, as expressed in the specified currency. This value
will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346). will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346).
@param currency Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for - Parameter currency: Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for
specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>. specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>.
@ -400,13 +319,13 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Log a purchase of the specified amount, in the specified currency, also providing a set of Log a purchase of the specified amount, in the specified currency, also providing a set of
additional characteristics describing the purchase. additional characteristics describing the purchase.
@param purchaseAmount Purchase amount to be logged, as expressed in the specified currency.This value - Parameter purchaseAmount: Purchase amount to be logged, as expressed in the specified currency.This value
will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346). will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346).
@param currency Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for - Parameter currency: Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for
specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>. specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>.
@param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must - Parameter parameters: Arbitrary parameter dictionary of characteristics. The keys to this dictionary must
be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
are provided in `FBSDKAppEventParameterName*` constants. are provided in `FBSDKAppEventParameterName*` constants.
@ -425,18 +344,18 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Log a purchase of the specified amount, in the specified currency, also providing a set of Log a purchase of the specified amount, in the specified currency, also providing a set of
additional characteristics describing the purchase, as well as an <FBSession> to log to. additional characteristics describing the purchase, as well as an <FBSession> to log to.
@param purchaseAmount Purchase amount to be logged, as expressed in the specified currency.This value - Parameter purchaseAmount: Purchase amount to be logged, as expressed in the specified currency.This value
will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346). will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346).
@param currency Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for - Parameter currency: Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for
specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>. specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>.
@param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must - Parameter parameters: Arbitrary parameter dictionary of characteristics. The keys to this dictionary must
be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
are provided in `FBSDKAppEventParameterName*` constants. are provided in `FBSDKAppEventParameterName*` constants.
@param accessToken The optional access token to log the event as. - Parameter accessToken: The optional access token to log the event as.
This event immediately triggers a flush of the `FBSDKAppEvents` event queue, unless the `flushBehavior` is set This event immediately triggers a flush of the `FBSDKAppEvents` event queue, unless the `flushBehavior` is set
@ -456,58 +375,18 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
/** /**
Log an app event that tracks that the application was open via Push Notification. Log an app event that tracks that the application was open via Push Notification.
@param payload Notification payload received via `UIApplicationDelegate`. - Parameter payload: Notification payload received via `UIApplicationDelegate`.
*/ */
+ (void)logPushNotificationOpen:(NSDictionary *)payload; + (void)logPushNotificationOpen:(NSDictionary *)payload;
/** /**
Log an app event that tracks that a custom action was taken from a push notification. Log an app event that tracks that a custom action was taken from a push notification.
@param payload Notification payload received via `UIApplicationDelegate`. - Parameter payload: Notification payload received via `UIApplicationDelegate`.
@param action Name of the action that was taken. - Parameter action: Name of the action that was taken.
*/ */
+ (void)logPushNotificationOpen:(NSDictionary *)payload action:(NSString *)action; + (void)logPushNotificationOpen:(NSDictionary *)payload action:(NSString *)action;
/**
Uploads product catalog product item as an app event
@param itemID Unique ID for the item. Can be a variant for a product.
Max size is 100.
@param availability If item is in stock. Accepted values are:
in stock - Item ships immediately
out of stock - No plan to restock
preorder - Available in future
available for order - Ships in 1-2 weeks
discontinued - Discontinued
@param condition Product condition: new, refurbished or used.
@param description Short text describing product. Max size is 5000.
@param imageLink Link to item image used in ad.
@param link Link to merchant's site where someone can buy the item.
@param title Title of item.
@param priceAmount Amount of purchase, in the currency specified by the 'currency'
parameter. This value will be rounded to the thousandths place
(e.g., 12.34567 becomes 12.346).
@param currency Currency used to specify the amount.
E.g. "USD", "EUR", "GBP". See ISO-4217 for specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>
@param gtin Global Trade Item Number including UPC, EAN, JAN and ISBN
@param mpn Unique manufacture ID for product
@param brand Name of the brand
Note: Either gtin, mpn or brand is required.
@param parameters Optional fields for deep link specification.
*/
+ (void)logProductItem:(NSString *)itemID
availability:(FBSDKProductAvailability)availability
condition:(FBSDKProductCondition)condition
description:(NSString *)description
imageLink:(NSString *)imageLink
link:(NSString *)link
title:(NSString *)title
priceAmount:(double)priceAmount
currency:(NSString *)currency
gtin:(NSString *)gtin
mpn:(NSString *)mpn
brand:(NSString *)brand
parameters:(NSDictionary *)parameters;
/** /**
Notifies the events system that the app has launched and, when appropriate, logs an "activated app" event. Notifies the events system that the app has launched and, when appropriate, logs an "activated app" event.
@ -540,7 +419,7 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Sets and sends a device token from `NSData` representation that you get from `UIApplicationDelegate.-application:didRegisterForRemoteNotificationsWithDeviceToken:`. Sets and sends a device token from `NSData` representation that you get from `UIApplicationDelegate.-application:didRegisterForRemoteNotificationsWithDeviceToken:`.
@param deviceToken Device token data. - Parameter deviceToken: Device token data.
*/ */
+ (void)setPushNotificationsDeviceToken:(NSData *)deviceToken; + (void)setPushNotificationsDeviceToken:(NSData *)deviceToken;
@ -558,7 +437,7 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Set the current event flushing behavior specifying when events are sent back to Facebook servers. Set the current event flushing behavior specifying when events are sent back to Facebook servers.
@param flushBehavior The desired `FBSDKAppEventsFlushBehavior` to be used. - Parameter flushBehavior: The desired `FBSDKAppEventsFlushBehavior` to be used.
*/ */
+ (void)setFlushBehavior:(FBSDKAppEventsFlushBehavior)flushBehavior; + (void)setFlushBehavior:(FBSDKAppEventsFlushBehavior)flushBehavior;
@ -575,7 +454,7 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
This should be set before any other calls are made to `FBSDKAppEvents`. Thus, you should set it in your application This should be set before any other calls are made to `FBSDKAppEvents`. Thus, you should set it in your application
delegate's `application:didFinishLaunchingWithOptions:` delegate. delegate's `application:didFinishLaunchingWithOptions:` delegate.
@param appID The Facebook App ID to be used for App Event logging. - Parameter appID: The Facebook App ID to be used for App Event logging.
*/ */
+ (void)setLoggingOverrideAppID:(NSString *)appID; + (void)setLoggingOverrideAppID:(NSString *)appID;
@ -583,7 +462,7 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Get the 'override' App ID for App Event logging. Get the 'override' App ID for App Event logging.
@see setLoggingOverrideAppID: - See:setLoggingOverrideAppID:
*/ */
+ (NSString *)loggingOverrideAppID; + (NSString *)loggingOverrideAppID;
@ -600,7 +479,7 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
Callers will send this ID back to their own servers, collect up a set to create a Facebook Custom Audience with, Callers will send this ID back to their own servers, collect up a set to create a Facebook Custom Audience with,
and then use the resultant Custom Audience to target ads. and then use the resultant Custom Audience to target ads.
@param accessToken The access token to use to establish the user's identity for users logged into Facebook through this app. - Parameter accessToken: The access token to use to establish the user's identity for users logged into Facebook through this app.
If `nil`, then the `[FBSDKAccessToken currentAccessToken]` is used. If `nil`, then the `[FBSDKAccessToken currentAccessToken]` is used.
@ -627,96 +506,18 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameOrderID;
*/ */
+ (void)setUserID:(NSString *)userID; + (void)setUserID:(NSString *)userID;
/*
Clears the custom user ID to associate with all app events.
*/
+ (void)clearUserID;
/* /*
Returns the set custom user ID. Returns the set custom user ID.
*/ */
+ (NSString *)userID; + (NSString *)userID;
/*
Sets custom user data to associate with all app events. All user data are hashed
and used to match Facebook user from this instance of an application.
The user data will be persisted between application instances.
@param userData user data to identify the user. User data should be formated as
a NSDictionary of data type name and value.
Supported data types and names are:
Email: em
First Name: fn
Last Name: ln
Phone: ph
Date of Birth: db
Gender: ge
City: ct
State: st
Zip: zp
Country: country
*/
+ (void)setUserData:(NSDictionary *)userData
DEPRECATED_MSG_ATTRIBUTE("Renamed `setUserEmail:firstName: ...`");
/*
Sets custom user data to associate with all app events. All user data are hashed
and used to match Facebook user from this instance of an application.
The user data will be persisted between application instances.
@param email user's email
@param firstName user's first name
@param lastName user's last name
@param phone user's phone
@param dateOfBirth user's date of birth
@param gender user's gender
@param city user's city
@param state user's state
@param zip user's zip
@param country user's country
*/
+ (void)setUserEmail:(nullable NSString *)email
firstName:(nullable NSString *)firstName
lastName:(nullable NSString *)lastName
phone:(nullable NSString *)phone
dateOfBirth:(nullable NSString *)dateOfBirth
gender:(nullable NSString *)gender
city:(nullable NSString *)city
state:(nullable NSString *)state
zip:(nullable NSString *)zip
country:(nullable NSString *)country;
/*
Returns the set user data else nil
*/
+ (NSString *)getUserData;
/*
Clears the current user data
*/
+ (void)clearUserData;
/* /*
Sends a request to update the properties for the current user, set by `setUserID:` Sends a request to update the properties for the current user, set by `setUserID:`
You must call `FBSDKAppEvents setUserID:` before making this call. You must call `FBSDKAppEvents setUserID:` before making this call.
@param properties the custom user properties - Parameter properties: the custom user properties
@param handler the optional completion handler - Parameter handler: the optional completion handler
*/ */
+ (void)updateUserProperties:(NSDictionary *)properties handler:(FBSDKGraphRequestHandler)handler; + (void)updateUserProperties:(NSDictionary *)properties handler:(FBSDKGraphRequestHandler)handler;
#if !TARGET_OS_TV
/*
Intended to be used as part of a hybrid webapp.
If you call this method, the FB SDK will inject a new JavaScript object into your webview.
If the FB Pixel is used within the webview, and references the app ID of this app,
then it will detect the presence of this injected JavaScript object
and pass Pixel events back to the FB SDK for logging using the AppEvents framework.
@param webView The webview to augment with the additional JavaScript behaviour
*/
+ (void)augmentHybridWKWebView:(WKWebView *)webView;
#endif
@end @end

View File

@ -26,7 +26,6 @@
#import "FBSDKAppEventsStateManager.h" #import "FBSDKAppEventsStateManager.h"
#import "FBSDKAppEventsUtility.h" #import "FBSDKAppEventsUtility.h"
#import "FBSDKConstants.h" #import "FBSDKConstants.h"
#import "FBSDKDynamicFrameworkLoader.h"
#import "FBSDKError.h" #import "FBSDKError.h"
#import "FBSDKGraphRequest+Internal.h" #import "FBSDKGraphRequest+Internal.h"
#import "FBSDKInternalUtility.h" #import "FBSDKInternalUtility.h"
@ -37,12 +36,6 @@
#import "FBSDKSettings.h" #import "FBSDKSettings.h"
#import "FBSDKTimeSpentData.h" #import "FBSDKTimeSpentData.h"
#import "FBSDKUtility.h" #import "FBSDKUtility.h"
#import "FBSDKUserDataStore.h"
#if !TARGET_OS_TV
#import "FBSDKEventBindingManager.h"
#import "FBSDKHybridAppEventsScriptMessageHandler.h"
#endif
// //
// Public event names // Public event names
@ -54,23 +47,13 @@ NSString *const FBSDKAppEventNameViewedContent = @"fb_mobile_content_v
NSString *const FBSDKAppEventNameSearched = @"fb_mobile_search"; NSString *const FBSDKAppEventNameSearched = @"fb_mobile_search";
NSString *const FBSDKAppEventNameRated = @"fb_mobile_rate"; NSString *const FBSDKAppEventNameRated = @"fb_mobile_rate";
NSString *const FBSDKAppEventNameCompletedTutorial = @"fb_mobile_tutorial_completion"; NSString *const FBSDKAppEventNameCompletedTutorial = @"fb_mobile_tutorial_completion";
NSString *const FBSDKAppEventNameContact = @"Contact"; NSString *const FBSDKAppEventParameterLaunchSource = @"fb_mobile_launch_source";
NSString *const FBSDKAppEventNameCustomizeProduct = @"CustomizeProduct";
NSString *const FBSDKAppEventNameDonate = @"Donate";
NSString *const FBSDKAppEventNameFindLocation = @"FindLocation";
NSString *const FBSDKAppEventNameSchedule = @"Schedule";
NSString *const FBSDKAppEventNameStartTrial = @"StartTrial";
NSString *const FBSDKAppEventNameSubmitApplication = @"SubmitApplication";
NSString *const FBSDKAppEventNameSubscribe = @"Subscribe";
NSString *const FBSDKAppEventNameAdImpression = @"AdImpression";
NSString *const FBSDKAppEventNameAdClick = @"AdClick";
// Ecommerce related // Ecommerce related
NSString *const FBSDKAppEventNameAddedToCart = @"fb_mobile_add_to_cart"; NSString *const FBSDKAppEventNameAddedToCart = @"fb_mobile_add_to_cart";
NSString *const FBSDKAppEventNameAddedToWishlist = @"fb_mobile_add_to_wishlist"; NSString *const FBSDKAppEventNameAddedToWishlist = @"fb_mobile_add_to_wishlist";
NSString *const FBSDKAppEventNameInitiatedCheckout = @"fb_mobile_initiated_checkout"; NSString *const FBSDKAppEventNameInitiatedCheckout = @"fb_mobile_initiated_checkout";
NSString *const FBSDKAppEventNameAddedPaymentInfo = @"fb_mobile_add_payment_info"; NSString *const FBSDKAppEventNameAddedPaymentInfo = @"fb_mobile_add_payment_info";
NSString *const FBSDKAppEventNameProductCatalogUpdate = @"fb_mobile_catalog_update";
// Gaming related // Gaming related
NSString *const FBSDKAppEventNameAchievedLevel = @"fb_mobile_level_achieved"; NSString *const FBSDKAppEventNameAchievedLevel = @"fb_mobile_level_achieved";
@ -93,9 +76,6 @@ NSString *const FBSDKAppEventParameterNamePaymentInfoAvailable = @"fb_payment_
NSString *const FBSDKAppEventParameterNameNumItems = @"fb_num_items"; NSString *const FBSDKAppEventParameterNameNumItems = @"fb_num_items";
NSString *const FBSDKAppEventParameterNameLevel = @"fb_level"; NSString *const FBSDKAppEventParameterNameLevel = @"fb_level";
NSString *const FBSDKAppEventParameterNameDescription = @"fb_description"; NSString *const FBSDKAppEventParameterNameDescription = @"fb_description";
NSString *const FBSDKAppEventParameterLaunchSource = @"fb_mobile_launch_source";
NSString *const FBSDKAppEventParameterNameAdType = @"ad_type";
NSString *const FBSDKAppEventParameterNameOrderID = @"fb_order_id";
// //
// Public event parameter values // Public event parameter values
@ -142,7 +122,6 @@ NSString *const FBSDKAppEventNameFBSDKLikeButtonImpression = @"fb_like_bu
NSString *const FBSDKAppEventNameFBSDKLoginButtonImpression = @"fb_login_button_impression"; NSString *const FBSDKAppEventNameFBSDKLoginButtonImpression = @"fb_login_button_impression";
NSString *const FBSDKAppEventNameFBSDKSendButtonImpression = @"fb_send_button_impression"; NSString *const FBSDKAppEventNameFBSDKSendButtonImpression = @"fb_send_button_impression";
NSString *const FBSDKAppEventNameFBSDKShareButtonImpression = @"fb_share_button_impression"; NSString *const FBSDKAppEventNameFBSDKShareButtonImpression = @"fb_share_button_impression";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonImpression = @"fb_live_streaming_button_impression";
NSString *const FBSDKAppEventNameFBSDKSmartLoginService = @"fb_smart_login_service"; NSString *const FBSDKAppEventNameFBSDKSmartLoginService = @"fb_smart_login_service";
@ -150,7 +129,6 @@ NSString *const FBSDKAppEventNameFBSDKLikeButtonDidTap = @"fb_like_button_did_t
NSString *const FBSDKAppEventNameFBSDKLoginButtonDidTap = @"fb_login_button_did_tap"; NSString *const FBSDKAppEventNameFBSDKLoginButtonDidTap = @"fb_login_button_did_tap";
NSString *const FBSDKAppEventNameFBSDKSendButtonDidTap = @"fb_send_button_did_tap"; NSString *const FBSDKAppEventNameFBSDKSendButtonDidTap = @"fb_send_button_did_tap";
NSString *const FBSDKAppEventNameFBSDKShareButtonDidTap = @"fb_share_button_did_tap"; NSString *const FBSDKAppEventNameFBSDKShareButtonDidTap = @"fb_share_button_did_tap";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonDidTap = @"fb_live_streaming_button_did_tap";
NSString *const FBSDKAppEventNameFBSDKLikeControlDidDisable = @"fb_like_control_did_disable"; NSString *const FBSDKAppEventNameFBSDKLikeControlDidDisable = @"fb_like_control_did_disable";
NSString *const FBSDKAppEventNameFBSDKLikeControlDidLike = @"fb_like_control_did_like"; NSString *const FBSDKAppEventNameFBSDKLikeControlDidLike = @"fb_like_control_did_like";
@ -171,16 +149,6 @@ NSString *const FBSDKAppEventNameFBSDKEventAppInviteShareDialogShow = @"fb_app
NSString *const FBSDKAppEventNameFBSessionFASLoginDialogResult = @"fb_mobile_login_fas_dialog_result"; NSString *const FBSDKAppEventNameFBSessionFASLoginDialogResult = @"fb_mobile_login_fas_dialog_result";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingStart = @"fb_sdk_live_streaming_start";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingStop = @"fb_sdk_live_streaming_stop";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingPause = @"fb_sdk_live_streaming_pause";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingResume = @"fb_sdk_live_streaming_resume";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingError = @"fb_sdk_live_streaming_error";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingUpdateStatus = @"fb_sdk_live_streaming_update_status";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingVideoID = @"fb_sdk_live_streaming_video_id";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingMic = @"fb_sdk_live_streaming_mic";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingCamera = @"fb_sdk_live_streaming_camera";
// Event Parameters internal to this file // Event Parameters internal to this file
NSString *const FBSDKAppEventParameterDialogOutcome = @"fb_dialog_outcome"; NSString *const FBSDKAppEventParameterDialogOutcome = @"fb_dialog_outcome";
NSString *const FBSDKAppEventParameterDialogErrorMessage = @"fb_dialog_outcome_error_message"; NSString *const FBSDKAppEventParameterDialogErrorMessage = @"fb_dialog_outcome_error_message";
@ -194,26 +162,6 @@ NSString *const FBSDKAppEventParameterLogTime = @"_logTime";
NSString *const FBSDKAppEventParameterEventName = @"_eventName"; NSString *const FBSDKAppEventParameterEventName = @"_eventName";
NSString *const FBSDKAppEventParameterImplicitlyLogged = @"_implicitlyLogged"; NSString *const FBSDKAppEventParameterImplicitlyLogged = @"_implicitlyLogged";
NSString *const FBSDKAppEventParameterLiveStreamingPrevStatus = @"live_streaming_prev_status";
NSString *const FBSDKAppEventParameterLiveStreamingStatus = @"live_streaming_status";
NSString *const FBSDKAppEventParameterLiveStreamingError = @"live_streaming_error";
NSString *const FBSDKAppEventParameterLiveStreamingVideoID = @"live_streaming_video_id";
NSString *const FBSDKAppEventParameterLiveStreamingMicEnabled = @"live_streaming_mic_enabled";
NSString *const FBSDKAppEventParameterLiveStreamingCameraEnabled = @"live_streaming_camera_enabled";
NSString *const FBSDKAppEventParameterProductItemID = @"fb_product_item_id";
NSString *const FBSDKAppEventParameterProductAvailability = @"fb_product_availability";
NSString *const FBSDKAppEventParameterProductCondition = @"fb_product_condition";
NSString *const FBSDKAppEventParameterProductDescription = @"fb_product_description";
NSString *const FBSDKAppEventParameterProductImageLink = @"fb_product_image_link";
NSString *const FBSDKAppEventParameterProductLink = @"fb_product_link";
NSString *const FBSDKAppEventParameterProductTitle = @"fb_product_title";
NSString *const FBSDKAppEventParameterProductGTIN = @"fb_product_gtin";
NSString *const FBSDKAppEventParameterProductMPN = @"fb_product_mpn";
NSString *const FBSDKAppEventParameterProductBrand = @"fb_product_brand";
NSString *const FBSDKAppEventParameterProductPriceAmount = @"fb_product_price_amount";
NSString *const FBSDKAppEventParameterProductPriceCurrency = @"fb_product_price_currency";
// Event parameter values internal to this file // Event parameter values internal to this file
NSString *const FBSDKAppEventsDialogOutcomeValue_Completed = @"Completed"; NSString *const FBSDKAppEventsDialogOutcomeValue_Completed = @"Completed";
NSString *const FBSDKAppEventsDialogOutcomeValue_Cancelled = @"Cancelled"; NSString *const FBSDKAppEventsDialogOutcomeValue_Cancelled = @"Cancelled";
@ -257,18 +205,9 @@ static NSString *const FBSDKAppEventParameterPushAction = @"fb_push_action";
static NSString *const FBSDKAppEventsPushPayloadKey = @"fb_push_payload"; static NSString *const FBSDKAppEventsPushPayloadKey = @"fb_push_payload";
static NSString *const FBSDKAppEventsPushPayloadCampaignKey = @"campaign"; static NSString *const FBSDKAppEventsPushPayloadCampaignKey = @"campaign";
//
// Augmentation of web browser constants
//
NSString *const FBSDKAppEventsWKWebViewMessagesPixelIDKey = @"pixelID";
NSString *const FBSDKAppEventsWKWebViewMessagesHandlerKey = @"fbmqHandler";
NSString *const FBSDKAppEventsWKWebViewMessagesEventKey = @"event";
NSString *const FBSDKAppEventsWKWebViewMessagesParamsKey = @"params";
NSString *const FBSDKAPPEventsWKWebViewMessagesProtocolKey = @"fbmq-0.1";
#define NUM_LOG_EVENTS_TO_TRY_TO_FLUSH_AFTER 100 #define NUM_LOG_EVENTS_TO_TRY_TO_FLUSH_AFTER 100
#define FLUSH_PERIOD_IN_SECONDS 15 #define FLUSH_PERIOD_IN_SECONDS 15
#define APP_SUPPORTS_ATTRIBUTION_ID_RECHECK_PERIOD 60 * 60 * 24
#define USER_ID_USER_DEFAULTS_KEY @"com.facebook.sdk.appevents.userid" #define USER_ID_USER_DEFAULTS_KEY @"com.facebook.sdk.appevents.userid"
static NSString *g_overrideAppID = nil; static NSString *g_overrideAppID = nil;
@ -281,18 +220,15 @@ static NSString *g_overrideAppID = nil;
@property (nonatomic, copy) NSString *pushNotificationsDeviceTokenString; @property (nonatomic, copy) NSString *pushNotificationsDeviceTokenString;
@property (nonatomic, strong) dispatch_source_t flushTimer;
@end @end
@implementation FBSDKAppEvents @implementation FBSDKAppEvents
{ {
BOOL _explicitEventsLoggedYet; BOOL _explicitEventsLoggedYet;
NSTimer *_flushTimer;
NSTimer *_attributionIDRecheckTimer;
FBSDKServerConfiguration *_serverConfiguration; FBSDKServerConfiguration *_serverConfiguration;
FBSDKAppEventsState *_appEventsState; FBSDKAppEventsState *_appEventsState;
#if !TARGET_OS_TV
FBSDKEventBindingManager *_eventBindingManager;
#endif
NSString *_userID; NSString *_userID;
} }
@ -310,12 +246,35 @@ static NSString *g_overrideAppID = nil;
self = [super init]; self = [super init];
if (self) { if (self) {
_flushBehavior = FBSDKAppEventsFlushBehaviorAuto; _flushBehavior = FBSDKAppEventsFlushBehaviorAuto;
_flushTimer = [NSTimer timerWithTimeInterval:FLUSH_PERIOD_IN_SECONDS
target:self
selector:@selector(flushTimerFired:)
userInfo:nil
repeats:YES];
_attributionIDRecheckTimer = [NSTimer timerWithTimeInterval:APP_SUPPORTS_ATTRIBUTION_ID_RECHECK_PERIOD
target:self
selector:@selector(appSettingsFetchStateResetTimerFired:)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:_flushTimer forMode:NSDefaultRunLoopMode];
[[NSRunLoop mainRunLoop] addTimer:_attributionIDRecheckTimer forMode:NSDefaultRunLoopMode];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(applicationMovingFromActiveStateOrTerminating)
name:UIApplicationWillResignActiveNotification
object:NULL];
typeof(self) __weak weakSelf = self; [[NSNotificationCenter defaultCenter]
self.flushTimer = [FBSDKUtility startGCDTimerWithInterval:FLUSH_PERIOD_IN_SECONDS addObserver:self
block:^{ selector:@selector(applicationMovingFromActiveStateOrTerminating)
[weakSelf flushTimerFired:nil]; name:UIApplicationWillTerminateNotification
}]; object:NULL];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(applicationDidBecomeActive)
name:UIApplicationDidBecomeActiveNotification
object:NULL];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
_userID = [defaults stringForKey:USER_ID_USER_DEFAULTS_KEY]; _userID = [defaults stringForKey:USER_ID_USER_DEFAULTS_KEY];
@ -324,30 +283,13 @@ static NSString *g_overrideAppID = nil;
return self; return self;
} }
- (void)registerNotifications {
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(applicationMovingFromActiveStateOrTerminating)
name:UIApplicationWillResignActiveNotification
object:NULL];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(applicationMovingFromActiveStateOrTerminating)
name:UIApplicationWillTerminateNotification
object:NULL];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(applicationDidBecomeActive)
name:UIApplicationDidBecomeActiveNotification
object:NULL];
}
- (void)dealloc - (void)dealloc
{ {
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
[FBSDKUtility stopGCDTimer:self.flushTimer]; // technically these timers retain self so there's a cycle but
// we're a singleton anyway.
[_flushTimer invalidate];
[_attributionIDRecheckTimer invalidate];
} }
#pragma mark - Public Methods #pragma mark - Public Methods
@ -472,109 +414,6 @@ static NSString *g_overrideAppID = nil;
[self logEvent:FBSDKAppEventNamePushOpened parameters:parameters]; [self logEvent:FBSDKAppEventNamePushOpened parameters:parameters];
} }
/*
* Uploads product catalog product item as an app event
*/
+ (void)logProductItem:(NSString *)itemID
availability:(FBSDKProductAvailability)availability
condition:(FBSDKProductCondition)condition
description:(NSString *)description
imageLink:(NSString *)imageLink
link:(NSString *)link
title:(NSString *)title
priceAmount:(double)priceAmount
currency:(NSString *)currency
gtin:(NSString *)gtin
mpn:(NSString *)mpn
brand:(NSString *)brand
parameters:(NSDictionary *)parameters {
if (itemID == nil) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"itemID cannot be null"];
return;
} else if (description == nil) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"description cannot be null"];
return;
} else if (imageLink == nil) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"imageLink cannot be null"];
return;
} else if (link == nil) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"link cannot be null"];
return;
} else if (title == nil) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"title cannot be null"];
return;
} else if (currency == nil) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"currency cannot be null"];
return;
} else if (gtin == nil && mpn == nil && brand == nil) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"Either gtin, mpn or brand is required"];
return;
}
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
if (nil != parameters) {
[dict setValuesForKeysWithDictionary:parameters];
}
[dict setObject:itemID forKey:FBSDKAppEventParameterProductItemID];
NSString *avail = nil;
switch (availability) {
case FBSDKProductAvailabilityInStock:
avail = @"IN_STOCK"; break;
case FBSDKProductAvailabilityOutOfStock:
avail = @"OUT_OF_STOCK"; break;
case FBSDKProductAvailabilityPreOrder:
avail = @"PREORDER"; break;
case FBSDKProductAvailabilityAvailableForOrder:
avail = @"AVALIABLE_FOR_ORDER"; break;
case FBSDKProductAvailabilityDiscontinued:
avail = @"DISCONTINUED"; break;
}
if (avail) {
[dict setObject:avail forKey:FBSDKAppEventParameterProductAvailability];
}
NSString *cond = nil;
switch (condition) {
case FBSDKProductConditionNew:
cond = @"NEW"; break;
case FBSDKProductConditionRefurbished:
cond = @"REFURBISHED"; break;
case FBSDKProductConditionUsed:
cond = @"USED"; break;
}
if (cond) {
[dict setObject:cond forKey:FBSDKAppEventParameterProductCondition];
}
[dict setObject:description forKey:FBSDKAppEventParameterProductDescription];
[dict setObject:imageLink forKey:FBSDKAppEventParameterProductImageLink];
[dict setObject:link forKey:FBSDKAppEventParameterProductLink];
[dict setObject:title forKey:FBSDKAppEventParameterProductTitle];
[dict setObject:[NSString stringWithFormat:@"%.3lf", priceAmount] forKey:FBSDKAppEventParameterProductPriceAmount];
[dict setObject:currency forKey:FBSDKAppEventParameterProductPriceCurrency];
if (gtin) {
[dict setObject:gtin forKey:FBSDKAppEventParameterProductGTIN];
}
if (mpn) {
[dict setObject:mpn forKey:FBSDKAppEventParameterProductMPN];
}
if (brand) {
[dict setObject:brand forKey:FBSDKAppEventParameterProductBrand];
}
[FBSDKAppEvents logEvent:FBSDKAppEventNameProductCatalogUpdate
parameters:dict];
}
+ (void)activateApp + (void)activateApp
{ {
[FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass(self)]; [FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass(self)];
@ -589,7 +428,6 @@ static NSString *g_overrideAppID = nil;
// when appropriate, result in logging an "activated app" and "deactivated app" (for the // when appropriate, result in logging an "activated app" and "deactivated app" (for the
// previous session) App Event. // previous session) App Event.
[FBSDKTimeSpentData restore:YES]; [FBSDKTimeSpentData restore:YES];
[FBSDKUserDataStore initStore];
} }
+ (void)setPushNotificationsDeviceToken:(NSData *)deviceToken + (void)setPushNotificationsDeviceToken:(NSData *)deviceToken
@ -653,63 +491,11 @@ static NSString *g_overrideAppID = nil;
[defaults synchronize]; [defaults synchronize];
} }
+ (void)clearUserID
{
[self setUserID:nil];
}
+ (NSString *)userID + (NSString *)userID
{ {
return [[self class] singleton]->_userID; return [[self class] singleton]->_userID;
} }
+ (void)setUserData:(NSDictionary*)userData
{
[FBSDKUserDataStore setUserDataAndHash:userData];
}
+ (void)setUserEmail:(nullable NSString *)email
firstName:(nullable NSString *)firstName
lastName:(nullable NSString *)lastName
phone:(nullable NSString *)phone
dateOfBirth:(nullable NSString *)dateOfBirth
gender:(nullable NSString *)gender
city:(nullable NSString *)city
state:(nullable NSString *)state
zip:(nullable NSString *)zip
country:(nullable NSString *)country
{
[FBSDKUserDataStore setUserDataAndHash:email
firstName:firstName
lastName:lastName
phone:phone
dateOfBirth:dateOfBirth
gender:gender
city:city
state:state
zip:zip
country:country];
}
+ (NSString*)getUserData
{
return [FBSDKUserDataStore getHashedUserData];
}
+ (void)clearUserData
{
[FBSDKUserDataStore setUserDataAndHash:nil
firstName:nil
lastName:nil
phone:nil
dateOfBirth:nil
gender:nil
city:nil
state:nil
zip:nil
country:nil];
}
+ (void)updateUserProperties:(NSDictionary *)properties handler:(FBSDKGraphRequestHandler)handler + (void)updateUserProperties:(NSDictionary *)properties handler:(FBSDKGraphRequestHandler)handler
{ {
NSString *userID = [[self class] userID]; NSString *userID = [[self class] userID];
@ -756,35 +542,6 @@ static NSString *g_overrideAppID = nil;
[request startWithCompletionHandler:handler]; [request startWithCompletionHandler:handler];
} }
#if !TARGET_OS_TV
+ (void)augmentHybridWKWebView:(WKWebView *)webView {
// Ensure we can instantiate WebKit before trying this
Class WKWebViewClass = fbsdkdfl_WKWebViewClass();
if (WKWebViewClass != nil && [webView isKindOfClass:WKWebViewClass]) {
Class WKUserScriptClass = fbsdkdfl_WKUserScriptClass();
if (WKUserScriptClass != nil) {
WKUserContentController *controller = webView.configuration.userContentController;
FBSDKHybridAppEventsScriptMessageHandler *scriptHandler = [[FBSDKHybridAppEventsScriptMessageHandler alloc] init];
[controller addScriptMessageHandler:scriptHandler name:FBSDKAppEventsWKWebViewMessagesHandlerKey];
NSString *js = [NSString stringWithFormat:@"window.fbmq_%@={'sendEvent': function(pixel_id,event_name,custom_data){var msg={\"%@\":pixel_id, \"%@\":event_name,\"%@\":custom_data};window.webkit.messageHandlers[\"%@\"].postMessage(msg);}, 'getProtocol':function(){return \"%@\";}}",
[[self singleton] appID],
FBSDKAppEventsWKWebViewMessagesPixelIDKey,
FBSDKAppEventsWKWebViewMessagesEventKey,
FBSDKAppEventsWKWebViewMessagesParamsKey,
FBSDKAppEventsWKWebViewMessagesHandlerKey,
FBSDKAPPEventsWKWebViewMessagesProtocolKey
];
[controller addUserScript:[[WKUserScriptClass alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]];
}
}
else {
[FBSDKAppEventsUtility logAndNotify:@"You must call augmentHybridWKWebView with WebKit linked to your project and a WKWebView instance"];
}
}
#endif
#pragma mark - Internal Methods #pragma mark - Internal Methods
+ (void)logImplicitEvent:(NSString *)eventName + (void)logImplicitEvent:(NSString *)eventName
@ -837,10 +594,6 @@ static NSString *g_overrideAppID = nil;
- (void)publishInstall - (void)publishInstall
{ {
NSString *appID = [self appID]; NSString *appID = [self appID];
if ([appID length] == 0) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors logEntry:@"Missing [FBSDKAppEvents appID] for [FBSDKAppEvents publishInstall:]"];
return;
}
NSString *lastAttributionPingString = [NSString stringWithFormat:@"com.facebook.sdk:lastAttributionPing%@", appID]; NSString *lastAttributionPingString = [NSString stringWithFormat:@"com.facebook.sdk:lastAttributionPing%@", appID];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:lastAttributionPingString]) { if ([defaults objectForKey:lastAttributionPingString]) {
@ -849,7 +602,7 @@ static NSString *g_overrideAppID = nil;
[self fetchServerConfiguration:^{ [self fetchServerConfiguration:^{
NSDictionary *params = [FBSDKAppEventsUtility activityParametersDictionaryForEvent:@"MOBILE_APP_INSTALL" NSDictionary *params = [FBSDKAppEventsUtility activityParametersDictionaryForEvent:@"MOBILE_APP_INSTALL"
implicitEventsOnly:NO implicitEventsOnly:NO
shouldAccessAdvertisingID:self->_serverConfiguration.isAdvertisingIDEnabled]; shouldAccessAdvertisingID:_serverConfiguration.isAdvertisingIDEnabled];
NSString *path = [NSString stringWithFormat:@"%@/activities", appID]; NSString *path = [NSString stringWithFormat:@"%@/activities", appID];
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:path FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:path
parameters:params parameters:params
@ -867,38 +620,27 @@ static NSString *g_overrideAppID = nil;
}]; }];
} }
#if !TARGET_OS_TV
- (void)enableCodelessEvents {
if (_serverConfiguration.isCodelessEventsEnabled) {
if (!_eventBindingManager) {
_eventBindingManager = [[FBSDKEventBindingManager alloc] init];
[_eventBindingManager start];
}
[_eventBindingManager updateBindings:[FBSDKEventBindingManager
parseArray:_serverConfiguration.eventBindings]];
}
}
#endif
// app events can use a server configuration up to 24 hours old to minimize network traffic. // app events can use a server configuration up to 24 hours old to minimize network traffic.
- (void)fetchServerConfiguration:(void (^)(void))callback - (void)fetchServerConfiguration:(void (^)(void))callback
{ {
[FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *error) { if (_serverConfiguration == nil) {
self->_serverConfiguration = serverConfiguration; [FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *error) {
_serverConfiguration = serverConfiguration;
if (self->_serverConfiguration.implicitPurchaseLoggingEnabled) { if (_serverConfiguration.implicitPurchaseLoggingEnabled) {
[FBSDKPaymentObserver startObservingTransactions]; [FBSDKPaymentObserver startObservingTransactions];
} else { } else {
[FBSDKPaymentObserver stopObservingTransactions]; [FBSDKPaymentObserver stopObservingTransactions];
} }
#if !TARGET_OS_TV if (callback) {
[self enableCodelessEvents]; callback();
#endif }
if (callback) { }];
callback(); return;
} }
}]; if (callback) {
callback();
}
} }
- (void)instanceLogEvent:(NSString *)eventName - (void)instanceLogEvent:(NSString *)eventName
@ -1041,21 +783,15 @@ static NSString *g_overrideAppID = nil;
- (void)flushOnMainQueue:(FBSDKAppEventsState *)appEventsState - (void)flushOnMainQueue:(FBSDKAppEventsState *)appEventsState
forReason:(FBSDKAppEventsFlushReason)reason forReason:(FBSDKAppEventsFlushReason)reason
{ {
if (appEventsState.events.count == 0) { if (appEventsState.events.count == 0) {
return; return;
} }
if ([appEventsState.appID length] == 0) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors logEntry:@"Missing [FBSDKAppEvents appEventsState.appID] for [FBSDKAppEvents flushOnMainQueue:]"];
return;
}
[FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])]; [FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])];
[self fetchServerConfiguration:^(void) { [self fetchServerConfiguration:^(void) {
NSString *receipt_data = [appEventsState extractReceiptData]; NSString *receipt_data = [appEventsState extractReceiptData];
NSString *encodedEvents = [appEventsState JSONStringForEvents:self->_serverConfiguration.implicitLoggingEnabled]; NSString *JSONString = [appEventsState JSONStringForEvents:_serverConfiguration.implicitLoggingEnabled];
NSData *encodedEvents = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
if (!encodedEvents) { if (!encodedEvents) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
logEntry:@"FBSDKAppEvents: Flushing skipped - no events after removing implicitly logged ones.\n"]; logEntry:@"FBSDKAppEvents: Flushing skipped - no events after removing implicitly logged ones.\n"];
@ -1064,13 +800,13 @@ static NSString *g_overrideAppID = nil;
NSMutableDictionary *postParameters = [FBSDKAppEventsUtility NSMutableDictionary *postParameters = [FBSDKAppEventsUtility
activityParametersDictionaryForEvent:@"CUSTOM_APP_EVENTS" activityParametersDictionaryForEvent:@"CUSTOM_APP_EVENTS"
implicitEventsOnly:appEventsState.areAllEventsImplicit implicitEventsOnly:appEventsState.areAllEventsImplicit
shouldAccessAdvertisingID:self->_serverConfiguration.advertisingIDEnabled]; shouldAccessAdvertisingID:_serverConfiguration.advertisingIDEnabled];
NSInteger length = [receipt_data length]; NSInteger length = [receipt_data length];
if (length > 0) { if (length > 0) {
postParameters[@"receipt_data"] = receipt_data; postParameters[@"receipt_data"] = receipt_data;
} }
postParameters[@"custom_events"] = encodedEvents; postParameters[@"custom_events_file"] = encodedEvents;
if (appEventsState.numSkipped > 0) { if (appEventsState.numSkipped > 0) {
postParameters[@"num_skipped_events"] = [NSString stringWithFormat:@"%lu", (unsigned long)appEventsState.numSkipped]; postParameters[@"num_skipped_events"] = [NSString stringWithFormat:@"%lu", (unsigned long)appEventsState.numSkipped];
} }
@ -1097,7 +833,6 @@ static NSString *g_overrideAppID = nil;
prettyPrintedJsonEvents]; prettyPrintedJsonEvents];
} }
[FBSDKAppEventsUtility logAndNotify:[NSString stringWithFormat:@"param %@", postParameters]];
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:[NSString stringWithFormat:@"%@/activities", appEventsState.appID] FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:[NSString stringWithFormat:@"%@/activities", appEventsState.appID]
parameters:postParameters parameters:postParameters
tokenString:appEventsState.tokenString tokenString:appEventsState.tokenString
@ -1131,8 +866,7 @@ static NSString *g_overrideAppID = nil;
// We interpret a 400 coming back from FBRequestConnection as a server error due to improper data being // We interpret a 400 coming back from FBRequestConnection as a server error due to improper data being
// sent down. Otherwise we assume no connectivity, or another condition where we could treat it as no connectivity. // sent down. Otherwise we assume no connectivity, or another condition where we could treat it as no connectivity.
// Adding 404 as having wrong/missing appID results in 404 and that is not a connectivity issue flushResult = errorCode == 400 ? FlushResultServerError : FlushResultNoConnectivity;
flushResult = (errorCode == 400 || errorCode == 404) ? FlushResultServerError : FlushResultNoConnectivity;
} }
if (flushResult == FlushResultServerError) { if (flushResult == FlushResultServerError) {
@ -1180,6 +914,11 @@ static NSString *g_overrideAppID = nil;
} }
} }
- (void)appSettingsFetchStateResetTimerFired:(id)arg
{
_serverConfiguration = nil;
}
- (void)applicationDidBecomeActive - (void)applicationDidBecomeActive
{ {
[FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])]; [FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])];

View File

@ -1,63 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import "FBSDKAppLinkTarget.h"
NS_ASSUME_NONNULL_BEGIN
/*! The version of the App Link protocol that this library supports */
FOUNDATION_EXPORT NSString *const FBSDKAppLinkVersion;
/*!
Contains App Link metadata relevant for navigation on this device
derived from the HTML at a given URL.
*/
@interface FBSDKAppLink : NSObject
/*!
Creates a FBSDKAppLink with the given list of FBSDKAppLinkTargets and target URL.
Generally, this will only be used by implementers of the FBSDKAppLinkResolving protocol,
as these implementers will produce App Link metadata for a given URL.
@param sourceURL the URL from which this App Link is derived
@param targets an ordered list of FBSDKAppLinkTargets for this platform derived
from App Link metadata.
@param webURL the fallback web URL, if any, for the app link.
*/
+ (instancetype)appLinkWithSourceURL:(NSURL *)sourceURL
targets:(NSArray<FBSDKAppLinkTarget *> *)targets
webURL:(nullable NSURL *)webURL;
/*! The URL from which this FBSDKAppLink was derived */
@property (nonatomic, strong, readonly) NSURL *sourceURL;
/*!
The ordered list of targets applicable to this platform that will be used
for navigation.
*/
@property (nonatomic, copy, readonly) NSArray<FBSDKAppLinkTarget *> *targets;
/*! The fallback web URL to use if no targets are installed on this device. */
@property (nonatomic, strong, readonly, nullable) NSURL *webURL;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,70 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKAppLink_Internal.h"
NSString *const FBSDKAppLinkDataParameterName = @"al_applink_data";
NSString *const FBSDKAppLinkTargetKeyName = @"target_url";
NSString *const FBSDKAppLinkUserAgentKeyName = @"user_agent";
NSString *const FBSDKAppLinkExtrasKeyName = @"extras";
NSString *const FBSDKAppLinkRefererAppLink = @"referer_app_link";
NSString *const FBSDKAppLinkRefererAppName = @"app_name";
NSString *const FBSDKAppLinkRefererUrl = @"url";
NSString *const FBSDKAppLinkVersionKeyName = @"version";
NSString *const FBSDKAppLinkVersion = @"1.0";
@interface FBSDKAppLink ()
@property (nonatomic, strong, readwrite) NSURL *sourceURL;
@property (nonatomic, copy, readwrite) NSArray<FBSDKAppLinkTarget *> *targets;
@property (nonatomic, strong, readwrite) NSURL *webURL;
@property (nonatomic, assign, readwrite, getter=isBackToReferrer) BOOL backToReferrer;
@end
@implementation FBSDKAppLink
+ (instancetype)appLinkWithSourceURL:(NSURL *)sourceURL
targets:(NSArray<FBSDKAppLinkTarget *> *)targets
webURL:(NSURL *)webURL
isBackToReferrer:(BOOL)isBackToReferrer {
FBSDKAppLink *link = [[self alloc] initWithIsBackToReferrer:isBackToReferrer];
link.sourceURL = sourceURL;
link.targets = [targets copy];
link.webURL = webURL;
return link;
}
+ (instancetype)appLinkWithSourceURL:(NSURL *)sourceURL
targets:(NSArray<FBSDKAppLinkTarget *> *)targets
webURL:(NSURL *)webURL {
return [self appLinkWithSourceURL:sourceURL
targets:targets
webURL:webURL
isBackToReferrer:NO];
}
- (FBSDKAppLink *)initWithIsBackToReferrer:(BOOL)backToReferrer {
if ((self = [super init])) {
_backToReferrer = backToReferrer;
}
return self;
}
@end

View File

@ -1,137 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import "FBSDKAppLink.h"
#import "FBSDKAppLinkResolving.h"
NS_ASSUME_NONNULL_BEGIN
/*!
The result of calling navigate on a FBSDKAppLinkNavigation
*/
typedef NS_ENUM(NSInteger, FBSDKAppLinkNavigationType) {
/*! Indicates that the navigation failed and no app was opened */
FBSDKAppLinkNavigationTypeFailure,
/*! Indicates that the navigation succeeded by opening the URL in the browser */
FBSDKAppLinkNavigationTypeBrowser,
/*! Indicates that the navigation succeeded by opening the URL in an app on the device */
FBSDKAppLinkNavigationTypeApp
};
/**
Describes the callback for appLinkFromURLInBackground.
@param navType the FBSDKAppLink representing the deferred App Link
@param error the error during the request, if any
*/
typedef void (^FBSDKAppLinkNavigationHandler)(FBSDKAppLinkNavigationType navType, NSError * _Nullable error);
/*!
Represents a pending request to navigate to an App Link. Most developers will
simply use navigateToURLInBackground: to open a URL, but developers can build
custom requests with additional navigation and app data attached to them by
creating FBSDKAppLinkNavigations themselves.
*/
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension")
@interface FBSDKAppLinkNavigation : NSObject
/*!
The extras for the AppLinkNavigation. This will generally contain application-specific
data that should be passed along with the request, such as advertiser or affiliate IDs or
other such metadata relevant on this device.
*/
@property (nonatomic, copy, readonly) NSDictionary<NSString *, id> *extras;
/*!
The al_applink_data for the AppLinkNavigation. This will generally contain data common to
navigation attempts such as back-links, user agents, and other information that may be used
in routing and handling an App Link request.
*/
@property (nonatomic, copy, readonly) NSDictionary<NSString *, id> *appLinkData;
/*! The AppLink to navigate to */
@property (nonatomic, strong, readonly) FBSDKAppLink *appLink;
/*! Creates an AppLinkNavigation with the given link, extras, and App Link data */
+ (instancetype)navigationWithAppLink:(FBSDKAppLink *)appLink
extras:(NSDictionary<NSString *, id> *)extras
appLinkData:(NSDictionary<NSString *, id> *)appLinkData;
/*!
Creates an NSDictionary with the correct format for iOS callback URLs,
to be used as 'appLinkData' argument in the call to navigationWithAppLink:extras:appLinkData:
*/
+ (NSDictionary<NSString *, NSDictionary<NSString *, NSString *> *> *)callbackAppLinkDataForAppWithName:(NSString *)appName
url:(NSString *)url;
/*! Performs the navigation */
- (FBSDKAppLinkNavigationType)navigate:(NSError *__autoreleasing *)error;
/*! Returns a FBSDKAppLink for the given URL */
+ (void)resolveAppLink:(NSURL *)destination handler:(FBSDKAppLinkFromURLHandler)handler;
/*! Returns a FBSDKAppLink for the given URL using the given App Link resolution strategy */
+ (void)resolveAppLink:(NSURL *)destination
resolver:(id<FBSDKAppLinkResolving>)resolver
handler:(FBSDKAppLinkFromURLHandler)handler;
/*! Navigates to a FBSDKAppLink and returns whether it opened in-app or in-browser */
+ (FBSDKAppLinkNavigationType)navigateToAppLink:(FBSDKAppLink *)link error:(NSError *__autoreleasing *)error;
/*!
Returns a FBSDKAppLinkNavigationType based on a FBSDKAppLink.
It's essentially a no-side-effect version of navigateToAppLink:error:,
allowing apps to determine flow based on the link type (e.g. open an
internal web view instead of going straight to the browser for regular links.)
*/
+ (FBSDKAppLinkNavigationType)navigationTypeForLink:(FBSDKAppLink *)link;
/*!
Return navigation type for current instance.
No-side-effect version of navigate:
*/
- (FBSDKAppLinkNavigationType)navigationType;
/*! Navigates to a URL (an asynchronous action) and returns a FBSDKNavigationType */
+ (void)navigateToURL:(NSURL *)destination handler:(FBSDKAppLinkNavigationHandler)handler;
/*!
Navigates to a URL (an asynchronous action) using the given App Link resolution
strategy and returns a FBSDKNavigationType
*/
+ (void)navigateToURL:(NSURL *)destination
resolver:(id<FBSDKAppLinkResolving>)resolver
handler:(FBSDKAppLinkNavigationHandler)handler;
/*!
Gets the default resolver to be used for App Link resolution. If the developer has not set one explicitly,
a basic, built-in resolver will be used.
*/
+ (id<FBSDKAppLinkResolving>)defaultResolver;
/*!
Sets the default resolver to be used for App Link resolution. Setting this to nil will revert the
default resolver to the basic, built-in resolver provided by FBSDK.
*/
+ (void)setDefaultResolver:(id<FBSDKAppLinkResolving>)resolver;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,302 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKAppLinkNavigation.h"
#import "FBSDKAppLinkTarget.h"
#import "FBSDKAppLink_Internal.h"
#import "FBSDKMeasurementEvent_Internal.h"
#import "FBSDKSettings.h"
#import "FBSDKWebViewAppLinkResolver.h"
FOUNDATION_EXPORT NSString *const FBSDKAppLinkDataParameterName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkTargetKeyName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkUserAgentKeyName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkExtrasKeyName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkVersionKeyName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkRefererAppLink;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkRefererAppName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkRefererUrl;
static id<FBSDKAppLinkResolving> defaultResolver;
@interface FBSDKAppLinkNavigation ()
@property (nonatomic, copy, readwrite) NSDictionary<NSString *, id> *extras;
@property (nonatomic, copy, readwrite) NSDictionary<NSString *, id> *appLinkData;
@property (nonatomic, strong, readwrite) FBSDKAppLink *appLink;
@end
@implementation FBSDKAppLinkNavigation
+ (instancetype)navigationWithAppLink:(FBSDKAppLink *)appLink
extras:(NSDictionary<NSString *, id> *)extras
appLinkData:(NSDictionary<NSString *, id> *)appLinkData {
FBSDKAppLinkNavigation *navigation = [[self alloc] init];
navigation.appLink = appLink;
navigation.extras = extras;
navigation.appLinkData = appLinkData;
return navigation;
}
+ (NSDictionary<NSString *, NSDictionary<NSString *, NSString *> *> *)callbackAppLinkDataForAppWithName:(NSString *)appName
url:(NSString *)url {
return @{FBSDKAppLinkRefererAppLink: @{FBSDKAppLinkRefererAppName: appName, FBSDKAppLinkRefererUrl: url}};
}
- (NSString *)stringByEscapingQueryString:(NSString *)string {
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0 || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_9
return [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
#else
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)string,
NULL,
(CFStringRef) @":/?#[]@!$&'()*+,;=",
kCFStringEncodingUTF8));
#endif
}
- (NSURL *)appLinkURLWithTargetURL:(NSURL *)targetUrl error:(NSError **)error {
NSMutableDictionary<NSString *, id> *appLinkData =
[NSMutableDictionary dictionaryWithDictionary:self.appLinkData ?: @{}];
// Add applink protocol data
if (!appLinkData[FBSDKAppLinkUserAgentKeyName]) {
appLinkData[FBSDKAppLinkUserAgentKeyName] = [NSString stringWithFormat:@"FBSDK %@", FBSDKSettings.sdkVersion];
}
if (!appLinkData[FBSDKAppLinkVersionKeyName]) {
appLinkData[FBSDKAppLinkVersionKeyName] = FBSDKAppLinkVersion;
}
if (self.appLink.sourceURL.absoluteString) {
appLinkData[FBSDKAppLinkTargetKeyName] = self.appLink.sourceURL.absoluteString;
}
appLinkData[FBSDKAppLinkExtrasKeyName] = self.extras ?: @{};
// JSON-ify the applink data
NSError *jsonError = nil;
NSData *jsonBlob = [NSJSONSerialization dataWithJSONObject:appLinkData options:0 error:&jsonError];
if (!jsonError) {
NSString *jsonString = [[NSString alloc] initWithData:jsonBlob encoding:NSUTF8StringEncoding];
NSString *encoded = [self stringByEscapingQueryString:jsonString];
NSString *endUrlString = [NSString stringWithFormat:@"%@%@%@=%@",
[targetUrl absoluteString],
targetUrl.query ? @"&" : @"?",
FBSDKAppLinkDataParameterName,
encoded];
return [NSURL URLWithString:endUrlString];
} else {
if (error) {
*error = jsonError;
}
// If there was an error encoding the app link data, fail hard.
return nil;
}
}
- (FBSDKAppLinkNavigationType)navigate:(NSError **)error {
NSURL *openedURL = nil;
NSError *encodingError = nil;
FBSDKAppLinkNavigationType retType = FBSDKAppLinkNavigationTypeFailure;
// Find the first eligible/launchable target in the FBSDKAppLink.
for (FBSDKAppLinkTarget *target in self.appLink.targets) {
NSURL *appLinkAppURL = [self appLinkURLWithTargetURL:target.URL error:&encodingError];
if (encodingError || !appLinkAppURL) {
if (error) {
*error = encodingError;
}
} else if ([[UIApplication sharedApplication] openURL:appLinkAppURL]) {
retType = FBSDKAppLinkNavigationTypeApp;
openedURL = appLinkAppURL;
break;
}
}
if (!openedURL && self.appLink.webURL) {
// Fall back to opening the url in the browser if available.
NSURL *appLinkBrowserURL = [self appLinkURLWithTargetURL:self.appLink.webURL error:&encodingError];
if (encodingError || !appLinkBrowserURL) {
// If there was an error encoding the app link data, fail hard.
if (error) {
*error = encodingError;
}
} else if ([[UIApplication sharedApplication] openURL:appLinkBrowserURL]) {
// This was a browser navigation.
retType = FBSDKAppLinkNavigationTypeBrowser;
openedURL = appLinkBrowserURL;
}
}
[self postAppLinkNavigateEventNotificationWithTargetURL:openedURL
error:error ? *error : nil
type:retType];
return retType;
}
- (void)postAppLinkNavigateEventNotificationWithTargetURL:(NSURL *)outputURL error:(NSError *)error type:(FBSDKAppLinkNavigationType)type {
NSString *const EVENT_YES_VAL = @"1";
NSString *const EVENT_NO_VAL = @"0";
NSMutableDictionary<NSString *, id> *logData =
[[NSMutableDictionary alloc] init];
NSString *outputURLScheme = [outputURL scheme];
NSString *outputURLString = [outputURL absoluteString];
if (outputURLScheme) {
logData[@"outputURLScheme"] = outputURLScheme;
}
if (outputURLString) {
logData[@"outputURL"] = outputURLString;
}
NSString *sourceURLString = [self.appLink.sourceURL absoluteString];
NSString *sourceURLHost = [self.appLink.sourceURL host];
NSString *sourceURLScheme = [self.appLink.sourceURL scheme];
if (sourceURLString) {
logData[@"sourceURL"] = sourceURLString;
}
if (sourceURLHost) {
logData[@"sourceHost"] = sourceURLHost;
}
if (sourceURLScheme) {
logData[@"sourceScheme"] = sourceURLScheme;
}
if ([error localizedDescription]) {
logData[@"error"] = [error localizedDescription];
}
NSString *success = nil; //no
NSString *linkType = nil; // unknown;
switch (type) {
case FBSDKAppLinkNavigationTypeFailure:
success = EVENT_NO_VAL;
linkType = @"fail";
break;
case FBSDKAppLinkNavigationTypeBrowser:
success = EVENT_YES_VAL;
linkType = @"web";
break;
case FBSDKAppLinkNavigationTypeApp:
success = EVENT_YES_VAL;
linkType = @"app";
break;
default:
break;
}
if (success) {
logData[@"success"] = success;
}
if (linkType) {
logData[@"type"] = linkType;
}
if ([self.appLink isBackToReferrer]) {
[FBSDKMeasurementEvent postNotificationForEventName:FBSDKAppLinkNavigateBackToReferrerEventName args:logData];
} else {
[FBSDKMeasurementEvent postNotificationForEventName:FBSDKAppLinkNavigateOutEventName args:logData];
}
}
+ (void)resolveAppLink:(NSURL *)destination
resolver:(id<FBSDKAppLinkResolving>)resolver
handler:(FBSDKAppLinkFromURLHandler)handler {
[resolver appLinkFromURL:destination handler:handler];
}
+ (void)resolveAppLink:(NSURL *)destination handler:(FBSDKAppLinkFromURLHandler)handler {
[self resolveAppLink:destination resolver:[self defaultResolver] handler:handler];
}
+ (void)navigateToURL:(NSURL *)destination handler:(FBSDKAppLinkNavigationHandler)handler {
[self navigateToURL:destination resolver:[self defaultResolver] handler:handler];
}
+ (void)navigateToURL:(NSURL *)destination
resolver:(id<FBSDKAppLinkResolving>)resolver
handler:(FBSDKAppLinkNavigationHandler)handler {
dispatch_async(dispatch_get_main_queue(), ^{
[self resolveAppLink:destination
resolver:resolver
handler:^(FBSDKAppLink * _Nullable appLink, NSError * _Nullable error) {
if (error) {
handler(FBSDKAppLinkNavigationTypeFailure, error);
return;
}
NSError *navigateError = nil;
FBSDKAppLinkNavigationType result = [self navigateToAppLink:appLink error:&navigateError];
handler(result, navigateError);
}];
});
}
+ (FBSDKAppLinkNavigationType)navigateToAppLink:(FBSDKAppLink *)link error:(NSError **)error {
return [[FBSDKAppLinkNavigation navigationWithAppLink:link
extras:@{}
appLinkData:@{}] navigate:error];
}
+ (FBSDKAppLinkNavigationType)navigationTypeForLink:(FBSDKAppLink *)link {
return [[self navigationWithAppLink:link extras:@{} appLinkData:@{}] navigationType];
}
- (FBSDKAppLinkNavigationType)navigationType {
FBSDKAppLinkTarget *eligibleTarget = nil;
for (FBSDKAppLinkTarget *target in self.appLink.targets) {
if ([[UIApplication sharedApplication] canOpenURL:target.URL]) {
eligibleTarget = target;
break;
}
}
if (eligibleTarget != nil) {
NSURL *appLinkURL = [self appLinkURLWithTargetURL:eligibleTarget.URL error:nil];
if (appLinkURL != nil) {
return FBSDKAppLinkNavigationTypeApp;
} else {
return FBSDKAppLinkNavigationTypeFailure;
}
}
if (self.appLink.webURL != nil) {
NSURL *appLinkURL = [self appLinkURLWithTargetURL:eligibleTarget.URL error:nil];
if (appLinkURL != nil) {
return FBSDKAppLinkNavigationTypeBrowser;
} else {
return FBSDKAppLinkNavigationTypeFailure;
}
}
return FBSDKAppLinkNavigationTypeFailure;
}
+ (id<FBSDKAppLinkResolving>)defaultResolver {
if (defaultResolver) {
return defaultResolver;
}
return [FBSDKWebViewAppLinkResolver sharedInstance];
}
+ (void)setDefaultResolver:(id<FBSDKAppLinkResolving>)resolver {
defaultResolver = resolver;
}
@end

View File

@ -18,15 +18,12 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "FBSDKAppLinkResolving.h"
@class BFTask; @class BFTask;
// Check if Bolts.framework is available for import // Check if Bolts.framework is available for import
#if __has_include(<Bolts/BFAppLinkResolving.h>) #if __has_include(<Bolts/BFAppLinkResolving.h>)
// Import it if it's available // Import it if it's available
#import <Bolts/BFAppLinkResolving.h> # import <Bolts/BFAppLinkResolving.h>
#else #else
// Otherwise - redeclare BFAppLinkResolving protocol to resolve the problem of missing symbols // Otherwise - redeclare BFAppLinkResolving protocol to resolve the problem of missing symbols
// Please note: Bolts.framework is still required for AppLink resolving to work, // Please note: Bolts.framework is still required for AppLink resolving to work,
@ -37,17 +34,15 @@
App Links that may include pre-fetching, caching, or querying for App Link App Links that may include pre-fetching, caching, or querying for App Link
data from an index provided by a service provider. data from an index provided by a service provider.
*/ */
DEPRECATED_MSG_ATTRIBUTE("Use `FBSDKAppLinkResolving`")
@protocol BFAppLinkResolving <NSObject> @protocol BFAppLinkResolving <NSObject>
/** /**
Asynchronously resolves App Link data for a given URL. Asynchronously resolves App Link data for a given URL.
@param url The URL to resolve into an App Link. - Parameter url: The URL to resolve into an App Link.
@return A BFTask that will return a BFAppLink for the given URL. - Returns: A BFTask that will return a BFAppLink for the given URL.
*/ */
- (BFTask *)appLinkFromURLInBackground:(NSURL *)url - (BFTask *)appLinkFromURLInBackground:(NSURL *)url;
DEPRECATED_MSG_ATTRIBUTE("Use `appLinkFromURL:handler:`");
@end @end
@ -64,40 +59,20 @@ DEPRECATED_MSG_ATTRIBUTE("Use `appLinkFromURL:handler:`");
Usage of this type requires a client token. See `[FBSDKSettings setClientToken:]` and linking Usage of this type requires a client token. See `[FBSDKSettings setClientToken:]` and linking
Bolts.framework Bolts.framework
*/ */
#pragma clang diagnostic push @interface FBSDKAppLinkResolver : NSObject<BFAppLinkResolving>
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@interface FBSDKAppLinkResolver : NSObject<FBSDKAppLinkResolving, BFAppLinkResolving>
#pragma clang diagnostic pop
/** /**
Asynchronously resolves App Link data for multiple URLs. Asynchronously resolves App Link data for multiple URLs.
@param urls An array of NSURLs to resolve into App Links. - Parameter urls: An array of NSURLs to resolve into App Links.
@return A BFTask that will return dictionary mapping input NSURLs to their - Returns: A BFTask that will return dictionary mapping input NSURLs to their
corresponding BFAppLink. corresponding BFAppLink.
You should set the client token before making this call. See `[FBSDKSettings setClientToken:]` You should set the client token before making this call. See `[FBSDKSettings setClientToken:]`
*/ */
- (BFTask *)appLinksFromURLsInBackground:(NSArray<NSURL *> *)urls - (BFTask *)appLinksFromURLsInBackground:(NSArray *)urls;
DEPRECATED_MSG_ATTRIBUTE("Use `appLinkFromURLs:handler:`");
/**
Asynchronously resolves App Link data for a given URL.
@param url The URL to resolve into an App Link.
@return A BFTask that will return a BFAppLink for the given URL.
*/
- (BFTask *)appLinkFromURLInBackground:(NSURL *)url
DEPRECATED_MSG_ATTRIBUTE("Use `appLinkFromURL:handler:`");
/**
Asynchronously resolves App Link data for a given array of URLs.
@param urls The URLs to resolve into an App Link.
@param handler The completion block that will return an App Link for the given URL.
*/
- (void)appLinksFromURLs:(NSArray<NSURL *> *)urls handler:(FBSDKAppLinksFromURLArrayHandler)handler
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension");
/** /**
Allocates and initializes a new instance of FBSDKAppLinkResolver. Allocates and initializes a new instance of FBSDKAppLinkResolver.

View File

@ -26,7 +26,6 @@
#import <Bolts/BFTaskCompletionSource.h> #import <Bolts/BFTaskCompletionSource.h>
#import "FBSDKAccessToken.h" #import "FBSDKAccessToken.h"
#import "FBSDKAppLink.h"
#import "FBSDKGraphRequest+Internal.h" #import "FBSDKGraphRequest+Internal.h"
#import "FBSDKGraphRequestConnection.h" #import "FBSDKGraphRequestConnection.h"
#import "FBSDKInternalUtility.h" #import "FBSDKInternalUtility.h"
@ -46,8 +45,7 @@ static NSString *const kAppLinksKey = @"app_links";
@interface FBSDKAppLinkResolver () @interface FBSDKAppLinkResolver ()
@property (nonatomic, strong) NSMutableDictionary<NSURL *, BFAppLink *> *cachedBFAppLinks; @property (nonatomic, strong) NSMutableDictionary *cachedLinks;
@property (nonatomic, strong) NSMutableDictionary<NSURL *, FBSDKAppLink *> *cachedFBSDKAppLinks;
@property (nonatomic, assign) UIUserInterfaceIdiom userInterfaceIdiom; @property (nonatomic, assign) UIUserInterfaceIdiom userInterfaceIdiom;
@end @end
@ -69,133 +67,29 @@ static Class g_BFTaskClass;
} }
} }
- (instancetype)initWithUserInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - (id)initWithUserInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
{ {
if (self = [super init]) { if (self = [super init]) {
self.cachedBFAppLinks = [NSMutableDictionary dictionary]; self.cachedLinks = [NSMutableDictionary dictionary];
self.cachedFBSDKAppLinks = [NSMutableDictionary dictionary];
self.userInterfaceIdiom = userInterfaceIdiom; self.userInterfaceIdiom = userInterfaceIdiom;
} }
return self; return self;
} }
- (void)appLinkFromURL:(NSURL *)url handler:(FBSDKAppLinkFromURLHandler)handler
{
[self appLinksFromURLs:@[url] handler:^(NSDictionary<NSURL *, FBSDKAppLink *> *urls, NSError * _Nullable error) {
handler(urls[url], error);
}];
}
- (void)appLinksFromURLs:(NSArray<NSURL *> *)urls handler:(FBSDKAppLinksFromURLArrayHandler)handler
{
if (![FBSDKSettings clientToken] && ![FBSDKAccessToken currentAccessToken]) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"A user access token or clientToken is required to use FBAppLinkResolver"];
}
NSMutableDictionary<NSURL *, FBSDKAppLink *> *appLinks = [NSMutableDictionary dictionary];
NSMutableArray<NSURL *> *toFind = [NSMutableArray array];
NSMutableArray<NSString *> *toFindStrings = [NSMutableArray array];
@synchronized (self.cachedFBSDKAppLinks) {
for (NSURL *url in urls) {
if (self.cachedFBSDKAppLinks[url]) {
appLinks[url] = self.cachedFBSDKAppLinks[url];
} else {
[toFind addObject:url];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSString *toFindString = [url.absoluteString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
#pragma clang diagnostic pop
if (toFindString) {
[toFindStrings addObject:toFindString];
}
}
}
}
if (toFind.count == 0) {
// All of the URLs have already been found.
handler(_cachedFBSDKAppLinks, nil);
}
NSMutableArray<NSString *> *fields = [NSMutableArray arrayWithObject:kIOSKey];
NSString *idiomSpecificField = nil;
switch (self.userInterfaceIdiom) {
case UIUserInterfaceIdiomPad:
idiomSpecificField = kIPadKey;
break;
case UIUserInterfaceIdiomPhone:
idiomSpecificField = kIPhoneKey;
break;
default:
break;
}
if (idiomSpecificField) {
[fields addObject:idiomSpecificField];
}
NSString *path = [NSString stringWithFormat:@"?fields=%@.fields(%@)&ids=%@",
kAppLinksKey,
[fields componentsJoinedByString:@","],
[toFindStrings componentsJoinedByString:@","]];
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:path
parameters:nil
flags:FBSDKGraphRequestFlagDoNotInvalidateTokenOnError | FBSDKGraphRequestFlagDisableErrorRecovery];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (error) {
handler(@{}, error);
return;
}
for (NSURL *url in toFind) {
id nestedObject = [[result objectForKey:url.absoluteString] objectForKey:kAppLinksKey];
NSMutableArray *rawTargets = [NSMutableArray array];
if (idiomSpecificField) {
[rawTargets addObjectsFromArray:[nestedObject objectForKey:idiomSpecificField]];
}
[rawTargets addObjectsFromArray:[nestedObject objectForKey:kIOSKey]];
NSMutableArray<FBSDKAppLinkTarget *> *targets = [NSMutableArray arrayWithCapacity:rawTargets.count];
for (id rawTarget in rawTargets) {
[targets addObject:[FBSDKAppLinkTarget appLinkTargetWithURL:[NSURL URLWithString:[rawTarget objectForKey:kURLKey]]
appStoreId:[rawTarget objectForKey:kIOSAppStoreIdKey]
appName:[rawTarget objectForKey:kIOSAppNameKey]]];
}
id webTarget = [nestedObject objectForKey:kWebKey];
NSString *webFallbackString = [webTarget objectForKey:kURLKey];
NSURL *fallbackUrl = webFallbackString ? [NSURL URLWithString:webFallbackString] : url;
NSNumber *shouldFallback = [webTarget objectForKey:kShouldFallbackKey];
if (shouldFallback && !shouldFallback.boolValue) {
fallbackUrl = nil;
}
FBSDKAppLink *link = [FBSDKAppLink appLinkWithSourceURL:url
targets:targets
webURL:fallbackUrl];
@synchronized (self.cachedFBSDKAppLinks) {
self.cachedFBSDKAppLinks[url] = link;
}
appLinks[url] = link;
}
handler(appLinks, nil);
}];
}
- (BFTask *)appLinksFromURLsInBackground:(NSArray *)urls - (BFTask *)appLinksFromURLsInBackground:(NSArray *)urls
{ {
if (![FBSDKSettings clientToken] && ![FBSDKAccessToken currentAccessToken]) { if (![FBSDKSettings clientToken] && ![FBSDKAccessToken currentAccessToken]) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"A user access token or clientToken is required to use FBAppLinkResolver"]; logEntry:@"A user access token or clientToken is required to use FBAppLinkResolver"];
} }
NSMutableDictionary<NSURL *, BFAppLink *> *appLinks = [NSMutableDictionary dictionary]; NSMutableDictionary *appLinks = [NSMutableDictionary dictionary];
NSMutableArray<NSURL *> *toFind = [NSMutableArray array]; NSMutableArray *toFind = [NSMutableArray array];
NSMutableArray<NSString *> *toFindStrings = [NSMutableArray array]; NSMutableArray *toFindStrings = [NSMutableArray array];
@synchronized (self.cachedBFAppLinks) { @synchronized (self.cachedLinks) {
for (NSURL *url in urls) { for (NSURL *url in urls) {
if (self.cachedBFAppLinks[url]) { if (self.cachedLinks[url]) {
appLinks[url] = self.cachedBFAppLinks[url]; appLinks[url] = self.cachedLinks[url];
} else { } else {
[toFind addObject:url]; [toFind addObject:url];
#pragma clang diagnostic push #pragma clang diagnostic push
@ -209,7 +103,7 @@ static Class g_BFTaskClass;
// All of the URLs have already been found. // All of the URLs have already been found.
return [g_BFTaskClass taskWithResult:appLinks]; return [g_BFTaskClass taskWithResult:appLinks];
} }
NSMutableArray<NSString *> *fields = [NSMutableArray arrayWithObject:kIOSKey]; NSMutableArray *fields = [NSMutableArray arrayWithObject:kIOSKey];
NSString *idiomSpecificField = nil; NSString *idiomSpecificField = nil;
@ -247,7 +141,7 @@ static Class g_BFTaskClass;
} }
[rawTargets addObjectsFromArray:[nestedObject objectForKey:kIOSKey]]; [rawTargets addObjectsFromArray:[nestedObject objectForKey:kIOSKey]];
NSMutableArray<BFAppLinkTarget *> *targets = [NSMutableArray arrayWithCapacity:rawTargets.count]; NSMutableArray *targets = [NSMutableArray arrayWithCapacity:rawTargets.count];
for (id rawTarget in rawTargets) { for (id rawTarget in rawTargets) {
[targets addObject:[g_BFAppLinkTargetClass appLinkTargetWithURL:[NSURL URLWithString:[rawTarget objectForKey:kURLKey]] [targets addObject:[g_BFAppLinkTargetClass appLinkTargetWithURL:[NSURL URLWithString:[rawTarget objectForKey:kURLKey]]
appStoreId:[rawTarget objectForKey:kIOSAppStoreIdKey] appStoreId:[rawTarget objectForKey:kIOSAppStoreIdKey]
@ -266,8 +160,8 @@ static Class g_BFTaskClass;
BFAppLink *link = [g_BFAppLinkClass appLinkWithSourceURL:url BFAppLink *link = [g_BFAppLinkClass appLinkWithSourceURL:url
targets:targets targets:targets
webURL:fallbackUrl]; webURL:fallbackUrl];
@synchronized (self.cachedBFAppLinks) { @synchronized (self.cachedLinks) {
self.cachedBFAppLinks[url] = link; self.cachedLinks[url] = link;
} }
appLinks[url] = link; appLinks[url] = link;
} }
@ -276,8 +170,6 @@ static Class g_BFTaskClass;
return tcs.task; return tcs.task;
} }
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (BFTask *)appLinkFromURLInBackground:(NSURL *)url - (BFTask *)appLinkFromURLInBackground:(NSURL *)url
{ {
// Implement in terms of appLinksFromURLsInBackground // Implement in terms of appLinksFromURLsInBackground
@ -286,7 +178,6 @@ static Class g_BFTaskClass;
return task.result[url]; return task.result[url];
}]; }];
} }
#pragma clang diagnostic pop
+ (id)resolver + (id)resolver
{ {

View File

@ -1,60 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class FBSDKAppLink;
/**
Describes the callback for appLinkFromURLInBackground.
@param appLink the FBSDKAppLink representing the deferred App Link
@param error the error during the request, if any
*/
typedef void (^FBSDKAppLinkFromURLHandler)(FBSDKAppLink * _Nullable appLink, NSError * _Nullable error);
/**
Describes the callback for appLinkFromURLInBackground.
@param appLinks the FBSDKAppLinks representing the deferred App Links
@param error the error during the request, if any
*/
typedef void (^FBSDKAppLinksFromURLArrayHandler)(NSDictionary<NSURL *, FBSDKAppLink *> * appLinks,
NSError * _Nullable error);
/*!
Implement this protocol to provide an alternate strategy for resolving
App Links that may include pre-fetching, caching, or querying for App Link
data from an index provided by a service provider.
*/
@protocol FBSDKAppLinkResolving <NSObject>
/**
Asynchronously resolves App Link data for a given URL.
@param url The URL to resolve into an App Link.
@param handler The completion block that will return an App Link for the given URL.
*/
- (void)appLinkFromURL:(NSURL *)url handler:(FBSDKAppLinkFromURLHandler)handler
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension");
@end
NS_ASSUME_NONNULL_END

View File

@ -1,100 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "FBSDKAppLinkReturnToRefererView.h"
NS_ASSUME_NONNULL_BEGIN
@class FBSDKAppLink;
@class FBSDKAppLinkReturnToRefererController;
/*!
Protocol that a class can implement in order to be notified when the user has navigated back
to the referer of an App Link.
*/
@protocol FBSDKAppLinkReturnToRefererControllerDelegate <NSObject>
@optional
/*! Called when the user has tapped to navigate, but before the navigation has been performed. */
- (void)returnToRefererController:(FBSDKAppLinkReturnToRefererController *)controller
willNavigateToAppLink:(FBSDKAppLink *)appLink;
/*! Called after the navigation has been attempted, with an indication of whether the referer
app link was successfully opened. */
- (void)returnToRefererController:(FBSDKAppLinkReturnToRefererController *)controller
didNavigateToAppLink:(FBSDKAppLink *)url
type:(FBSDKAppLinkNavigationType)type;
@end
/*!
A controller class that implements default behavior for a FBSDKAppLinkReturnToRefererView, including
the ability to display the view above the navigation bar for navigation-based apps.
*/
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension")
@interface FBSDKAppLinkReturnToRefererController : NSObject <FBSDKAppLinkReturnToRefererViewDelegate>
/*!
The delegate that will be notified when the user navigates back to the referer.
*/
@property (nonatomic, weak, nullable) id<FBSDKAppLinkReturnToRefererControllerDelegate> delegate;
/*!
The FBSDKAppLinkReturnToRefererView this controller is controlling.
*/
@property (nonatomic, strong) FBSDKAppLinkReturnToRefererView *view;
/*!
Initializes a controller suitable for controlling a FBSDKAppLinkReturnToRefererView that is to be displayed
contained within another UIView (i.e., not displayed above the navigation bar).
*/
- (instancetype)init NS_DESIGNATED_INITIALIZER;
/*!
Initializes a controller suitable for controlling a FBSDKAppLinkReturnToRefererView that is to be displayed
displayed above the navigation bar.
*/
- (instancetype)initForDisplayAboveNavController:(UINavigationController *)navController;
/*!
Removes the view entirely from the navigation controller it is currently displayed in.
*/
- (void)removeFromNavController;
/*!
Shows the FBSDKAppLinkReturnToRefererView with the specified referer information. If nil or missing data,
the view will not be displayed. */
- (void)showViewForRefererAppLink:(FBSDKAppLink *)refererAppLink;
/*!
Shows the FBSDKAppLinkReturnToRefererView with referer information extracted from the specified URL.
If nil or missing referer App Link data, the view will not be displayed. */
- (void)showViewForRefererURL:(NSURL *)url;
/*!
Closes the view, possibly animating it.
*/
- (void)closeViewAnimated:(BOOL)animated;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,238 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKAppLinkReturnToRefererController.h"
#import "FBSDKAppLink.h"
#import "FBSDKAppLinkReturnToRefererView_Internal.h"
#import "FBSDKURL_Internal.h"
static const CFTimeInterval kFBSDKViewAnimationDuration = 0.25f;
@implementation FBSDKAppLinkReturnToRefererController {
UINavigationController *_navigationController;
FBSDKAppLinkReturnToRefererView *_view;
}
#pragma mark - Object lifecycle
- (instancetype)init {
return [super init];
}
- (instancetype)initForDisplayAboveNavController:(UINavigationController *)navController {
self = [self init];
if (self) {
_navigationController = navController;
if (_navigationController != nil) {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(statusBarFrameWillChange:)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
[nc addObserver:self
selector:@selector(statusBarFrameDidChange:)
name:UIApplicationDidChangeStatusBarFrameNotification
object:nil];
[nc addObserver:self
selector:@selector(orientationDidChange:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
}
return self;
}
- (void)dealloc {
_view.delegate = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Public API
- (FBSDKAppLinkReturnToRefererView *)view {
if (!_view) {
self.view = [[FBSDKAppLinkReturnToRefererView alloc] initWithFrame:CGRectZero];
if (_navigationController) {
[_navigationController.view addSubview:_view];
}
}
return _view;
}
- (void)setView:(FBSDKAppLinkReturnToRefererView *)view {
if (_view != view) {
_view.delegate = nil;
}
_view = view;
_view.delegate = self;
if (_navigationController) {
_view.includeStatusBarInSize = FBSDKIncludeStatusBarInSizeAlways;
}
}
- (void)showViewForRefererAppLink:(FBSDKAppLink *)refererAppLink {
self.view.refererAppLink = refererAppLink;
[_view sizeToFit];
if (_navigationController) {
if (!_view.closed) {
dispatch_async(dispatch_get_main_queue(), ^{
[self moveNavigationBar];
});
}
}
}
- (void)showViewForRefererURL:(NSURL *)url {
FBSDKAppLink *appLink = [FBSDKURL URLForRenderBackToReferrerBarURL:url].appLinkReferer;
[self showViewForRefererAppLink:appLink];
}
- (void)removeFromNavController {
if (_navigationController) {
[_view removeFromSuperview];
_navigationController = nil;
}
}
#pragma mark - FBSDKAppLinkReturnToRefererViewDelegate
- (void)returnToRefererViewDidTapInsideCloseButton:(FBSDKAppLinkReturnToRefererView *)view {
[self closeViewAnimated:YES explicitlyClosed:YES];
}
- (void)returnToRefererViewDidTapInsideLink:(FBSDKAppLinkReturnToRefererView *)view
link:(FBSDKAppLink *)link {
[self openRefererAppLink:link];
[self closeViewAnimated:NO explicitlyClosed:NO];
}
#pragma mark - Private
- (void)statusBarFrameWillChange:(NSNotification *)notification {
NSValue *rectValue = [[notification userInfo] valueForKey:UIApplicationStatusBarFrameUserInfoKey];
CGRect newFrame;
[rectValue getValue:&newFrame];
if (_navigationController && !_view.closed) {
if (CGRectGetHeight(newFrame) == 40) {
UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState;
[UIView animateWithDuration:kFBSDKViewAnimationDuration delay:0.0 options:options animations:^{
self->_view.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self->_view.bounds), 0.0);
} completion:nil];
}
}
}
- (void)statusBarFrameDidChange:(NSNotification *)notification {
NSValue *rectValue = [[notification userInfo] valueForKey:UIApplicationStatusBarFrameUserInfoKey];
CGRect newFrame;
[rectValue getValue:&newFrame];
if (_navigationController && !_view.closed) {
if (CGRectGetHeight(newFrame) == 40) {
UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState;
[UIView animateWithDuration:kFBSDKViewAnimationDuration delay:0.0 options:options animations:^{
[self->_view sizeToFit];
[self moveNavigationBar];
} completion:nil];
}
}
}
- (void)orientationDidChange:(NSNotificationCenter *)notification {
if (_navigationController && !_view.closed && CGRectGetHeight(_view.bounds) > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
[self moveNavigationBar];
});
}
}
- (void)moveNavigationBar {
if (_view.closed || !_view.refererAppLink) {
return;
}
[self updateNavigationBarY:CGRectGetHeight(_view.bounds)];
}
- (void)updateNavigationBarY:(CGFloat)y {
UINavigationBar *navigationBar = _navigationController.navigationBar;
CGRect navigationBarFrame = navigationBar.frame;
CGFloat oldContainerViewY = CGRectGetMaxY(navigationBarFrame);
navigationBarFrame.origin.y = y;
navigationBar.frame = navigationBarFrame;
CGFloat dy = CGRectGetMaxY(navigationBarFrame) - oldContainerViewY;
UIView *containerView = _navigationController.visibleViewController.view.superview;
containerView.frame = UIEdgeInsetsInsetRect(containerView.frame, UIEdgeInsetsMake(dy, 0.0, 0.0, 0.0));
}
- (void)closeViewAnimated:(BOOL)animated {
[self closeViewAnimated:animated explicitlyClosed:YES];
}
- (void)closeViewAnimated:(BOOL)animated explicitlyClosed:(BOOL)explicitlyClosed {
void (^closer)(void) = ^{
if (self->_navigationController) {
[self updateNavigationBarY:self->_view.statusBarHeight];
}
CGRect frame = self->_view.frame;
frame.size.height = 0.0;
self->_view.frame = frame;
};
if (animated) {
[UIView animateWithDuration:kFBSDKViewAnimationDuration animations:^{
closer();
} completion:^(BOOL finished) {
if (explicitlyClosed) {
self->_view.closed = YES;
}
}];
} else {
closer();
if (explicitlyClosed) {
self->_view.closed = YES;
}
}
}
- (void)openRefererAppLink:(FBSDKAppLink *)refererAppLink {
if (refererAppLink) {
id<FBSDKAppLinkReturnToRefererControllerDelegate> delegate = _delegate;
if ([delegate respondsToSelector:@selector(returnToRefererController:willNavigateToAppLink:)]) {
[delegate returnToRefererController:self willNavigateToAppLink:refererAppLink];
}
NSError *error = nil;
FBSDKAppLinkNavigationType type = [FBSDKAppLinkNavigation navigateToAppLink:refererAppLink error:&error];
if ([delegate respondsToSelector:@selector(returnToRefererController:didNavigateToAppLink:type:)]) {
[delegate returnToRefererController:self didNavigateToAppLink:refererAppLink type:type];
}
}
}
@end

View File

@ -1,90 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "FBSDKAppLinkNavigation.h"
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, FBSDKIncludeStatusBarInSize) {
FBSDKIncludeStatusBarInSizeNever,
FBSDKIncludeStatusBarInSizeIOS7AndLater,
FBSDKIncludeStatusBarInSizeAlways,
};
@class FBSDKAppLinkReturnToRefererView;
@class FBSDKURL;
/*!
Protocol that a class can implement in order to be notified when the user has navigated back
to the referer of an App Link.
*/
@protocol FBSDKAppLinkReturnToRefererViewDelegate <NSObject>
/*!
Called when the user has tapped inside the close button.
*/
- (void)returnToRefererViewDidTapInsideCloseButton:(FBSDKAppLinkReturnToRefererView *)view;
/*!
Called when the user has tapped inside the App Link portion of the view.
*/
- (void)returnToRefererViewDidTapInsideLink:(FBSDKAppLinkReturnToRefererView *)view
link:(FBSDKAppLink *)link;
@end
/*!
Provides a UIView that displays a button allowing users to navigate back to the
application that launched the App Link currently being handled, if the App Link
contained referer data. The user can also close the view by clicking a close button
rather than navigating away. If the view is provided an App Link that does not contain
referer data, it will have zero size and no UI will be displayed.
*/
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension")
@interface FBSDKAppLinkReturnToRefererView : UIView
/*!
The delegate that will be notified when the user navigates back to the referer.
*/
@property (nonatomic, weak, nullable) id<FBSDKAppLinkReturnToRefererViewDelegate> delegate;
/*!
The color of the text label and close button.
*/
@property (nonatomic, strong) UIColor *textColor;
@property (nonatomic, strong) FBSDKAppLink *refererAppLink;
/*!
Indicates whether to extend the size of the view to include the current status bar
size, for use in scenarios where the view might extend under the status bar on iOS 7 and
above; this property has no effect on earlier versions of iOS.
*/
@property (nonatomic, assign) FBSDKIncludeStatusBarInSize includeStatusBarInSize;
/*!
Indicates whether the user has closed the view by clicking the close button.
*/
@property (nonatomic, assign) BOOL closed;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,275 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKAppLinkReturnToRefererView.h"
#import "FBSDKAppLink.h"
#import "FBSDKAppLinkTarget.h"
static const CGFloat FBSDKMarginX = 8.5f;
static const CGFloat FBSDKMarginY = 8.5f;
static NSString *const FBSDKRefererAppLink = @"referer_app_link";
static NSString *const FBSDKRefererAppName = @"app_name";
static NSString *const FBSDKRefererUrl = @"url";
static const CGFloat FBSDKCloseButtonWidth = 12.0;
static const CGFloat FBSDKCloseButtonHeight = 12.0;
@interface FBSDKAppLinkReturnToRefererView ()
@property (nonatomic, strong) UILabel *labelView;
@property (nonatomic, strong) UIButton *closeButton;
@property (nonatomic, strong) UITapGestureRecognizer *insideTapGestureRecognizer;
@end
@implementation FBSDKAppLinkReturnToRefererView {
BOOL _explicitlyHidden;
}
#pragma mark - Initialization
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
[self sizeToFit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
// Initialization code
_includeStatusBarInSize = FBSDKIncludeStatusBarInSizeIOS7AndLater;
// iOS 7 system blue color
self.backgroundColor = [UIColor colorWithRed:0.0f green:122.0f / 255.0f blue:1.0f alpha:1.0f];
self.textColor = [UIColor whiteColor];
self.clipsToBounds = YES;
[self initViews];
}
- (void)initViews {
if (!_labelView && !_closeButton) {
_closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
_closeButton.backgroundColor = [UIColor clearColor];
_closeButton.userInteractionEnabled = YES;
_closeButton.clipsToBounds = YES;
_closeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
_closeButton.contentMode = UIViewContentModeCenter;
[_closeButton addTarget:self action:@selector(closeButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_closeButton];
_labelView = [[UILabel alloc] initWithFrame:CGRectZero];
_labelView.font = [UIFont systemFontOfSize:[UIFont smallSystemFontSize]];
_labelView.textColor = [UIColor whiteColor];
_labelView.backgroundColor = [UIColor clearColor];
#ifdef __IPHONE_6_0
_labelView.textAlignment = NSTextAlignmentCenter;
#else
_labelView.textAlignment = UITextAlignmentCenter;
#endif
_labelView.clipsToBounds = YES;
[self updateLabelText];
[self addSubview:_labelView];
_insideTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapInside:)];
_labelView.userInteractionEnabled = YES;
[_labelView addGestureRecognizer:_insideTapGestureRecognizer];
[self updateColors];
}
}
#pragma mark - Layout
- (CGSize)intrinsicContentSize {
CGSize size = self.bounds.size;
if (_closed || !self.hasRefererData) {
size.height = 0.0;
} else {
CGSize labelSize = [_labelView sizeThatFits:size];
size = CGSizeMake(size.width, labelSize.height + 2 * FBSDKMarginY + self.statusBarHeight);
}
return size;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect bounds = self.bounds;
_labelView.preferredMaxLayoutWidth = _labelView.bounds.size.width;
CGSize labelSize = [_labelView sizeThatFits:bounds.size];
_labelView.frame = CGRectMake(FBSDKMarginX,
CGRectGetMaxY(bounds) - labelSize.height - 1.5f * FBSDKMarginY,
CGRectGetMaxX(bounds) - FBSDKCloseButtonWidth - 3 * FBSDKMarginX,
labelSize.height + FBSDKMarginY);
_closeButton.frame = CGRectMake(CGRectGetMaxX(bounds) - FBSDKCloseButtonWidth - 2 * FBSDKMarginX,
_labelView.center.y - FBSDKCloseButtonHeight / 2.0f - FBSDKMarginY,
FBSDKCloseButtonWidth + 2 * FBSDKMarginX,
FBSDKCloseButtonHeight + 2 * FBSDKMarginY);
}
- (CGSize)sizeThatFits:(CGSize)size {
if (_closed || !self.hasRefererData) {
size = CGSizeMake(size.width, 0.0);
} else {
CGSize labelSize = [_labelView sizeThatFits:size];
size = CGSizeMake(size.width, labelSize.height + 2 * FBSDKMarginY + self.statusBarHeight);
}
return size;
}
- (CGFloat)statusBarHeight {
UIApplication *application = [UIApplication sharedApplication];
BOOL include;
switch (_includeStatusBarInSize) {
case FBSDKIncludeStatusBarInSizeAlways:
include = YES;
break;
case FBSDKIncludeStatusBarInSizeIOS7AndLater: {
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
include = (systemVersion >= 7.0);
break;
}
case FBSDKIncludeStatusBarInSizeNever:
include = NO;
break;
}
if (include && !application.statusBarHidden) {
BOOL landscape = UIInterfaceOrientationIsLandscape(application.statusBarOrientation);
CGRect statusBarFrame = application.statusBarFrame;
return landscape ? CGRectGetWidth(statusBarFrame) : CGRectGetHeight(statusBarFrame);
}
return 0;
}
#pragma mark - Public API
- (void)setIncludeStatusBarInSize:(FBSDKIncludeStatusBarInSize)includeStatusBarInSize {
_includeStatusBarInSize = includeStatusBarInSize;
[self setNeedsLayout];
[self invalidateIntrinsicContentSize];
}
- (void)setTextColor:(UIColor *)textColor {
_textColor = textColor;
[self updateColors];
}
- (void)setRefererAppLink:(FBSDKAppLink *)refererAppLink {
_refererAppLink = refererAppLink;
[self updateLabelText];
[self updateHidden];
[self invalidateIntrinsicContentSize];
}
- (void)setClosed:(BOOL)closed {
if (_closed != closed) {
_closed = closed;
[self updateHidden];
[self invalidateIntrinsicContentSize];
}
}
- (void)setHidden:(BOOL)hidden {
_explicitlyHidden = hidden;
[self updateHidden];
}
#pragma mark - Private
- (void)updateLabelText {
NSString *appName = (_refererAppLink && _refererAppLink.targets[0]) ? [_refererAppLink.targets[0] appName] : nil;
_labelView.text = [self localizedLabelForReferer:appName];
}
- (void)updateColors {
UIImage *closeButtonImage = [self drawCloseButtonImageWithColor:_textColor];
_labelView.textColor = _textColor;
[_closeButton setImage:closeButtonImage forState:UIControlStateNormal];
}
- (UIImage *)drawCloseButtonImageWithColor:(UIColor *)color {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(FBSDKCloseButtonWidth, FBSDKCloseButtonHeight), NO, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [color CGColor]);
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextSetLineWidth(context, 1.25f);
CGFloat inset = 0.5f;
CGContextMoveToPoint(context, inset, inset);
CGContextAddLineToPoint(context, FBSDKCloseButtonWidth - inset, FBSDKCloseButtonHeight - inset);
CGContextStrokePath(context);
CGContextMoveToPoint(context, FBSDKCloseButtonWidth - inset, inset);
CGContextAddLineToPoint(context, inset, FBSDKCloseButtonHeight - inset);
CGContextStrokePath(context);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
- (NSString *)localizedLabelForReferer:(NSString *)refererName {
if (!refererName) {
return nil;
}
NSString *format = NSLocalizedString(@"Touch to return to %1$@", @"Format for the string to return to a calling app.");
return [NSString stringWithFormat:format, refererName];
}
- (BOOL)hasRefererData {
return _refererAppLink && _refererAppLink.targets[0];
}
- (void)closeButtonTapped:(id)sender {
[_delegate returnToRefererViewDidTapInsideCloseButton:self];
}
- (void)onTapInside:(UIGestureRecognizer *)sender {
[_delegate returnToRefererViewDidTapInsideLink:self link:_refererAppLink];
}
- (void)updateHidden {
[super setHidden:_explicitlyHidden || _closed || !self.hasRefererData];
}
@end

View File

@ -1,45 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/*!
Represents a target defined in App Link metadata, consisting of at least
a URL, and optionally an App Store ID and name.
*/
@interface FBSDKAppLinkTarget : NSObject
/*! Creates a FBSDKAppLinkTarget with the given app site and target URL. */
+ (instancetype)appLinkTargetWithURL:(NSURL *)url
appStoreId:(nullable NSString *)appStoreId
appName:(NSString *)appName;
/*! The URL prefix for this app link target */
@property (nonatomic, strong, readonly) NSURL *URL;
/*! The app ID for the app store */
@property (nonatomic, copy, readonly, nullable) NSString *appStoreId;
/*! The name of the app */
@property (nonatomic, copy, readonly) NSString *appName;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,41 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKAppLinkTarget.h"
@interface FBSDKAppLinkTarget ()
@property (nonatomic, strong, readwrite) NSURL *URL;
@property (nonatomic, copy, readwrite) NSString *appStoreId;
@property (nonatomic, copy, readwrite) NSString *appName;
@end
@implementation FBSDKAppLinkTarget
+ (instancetype)appLinkTargetWithURL:(NSURL *)url
appStoreId:(NSString *)appStoreId
appName:(NSString *)appName {
FBSDKAppLinkTarget *target = [[self alloc] init];
target.URL = url;
target.appStoreId = appStoreId;
target.appName = appName;
return target;
}
@end

View File

@ -20,8 +20,8 @@
/** /**
Describes the callback for fetchDeferredAppLink. Describes the callback for fetchDeferredAppLink.
@param url the url representing the deferred App Link - Parameter url: the url representing the deferred App Link
@param error the error during the request, if any - Parameter error: the error during the request, if any
The url may also have a fb_click_time_utc query parameter that The url may also have a fb_click_time_utc query parameter that
@ -32,7 +32,7 @@ typedef void (^FBSDKDeferredAppLinkHandler)(NSURL *url, NSError *error);
/** /**
Describes the callback for fetchOrganicDeferredAppLink. Describes the callback for fetchOrganicDeferredAppLink.
@param url the url representing the deferred App Link - Parameter url: the url representing the deferred App Link
*/ */
typedef void (^FBSDKDeferredAppInviteHandler)(NSURL *url); typedef void (^FBSDKDeferredAppInviteHandler)(NSURL *url);
@ -49,7 +49,7 @@ typedef void (^FBSDKDeferredAppInviteHandler)(NSURL *url);
data (this will only return a valid URL once, and future calls will result in a nil URL data (this will only return a valid URL once, and future calls will result in a nil URL
value in the callback). value in the callback).
@param handler the handler to be invoked if there is deferred App Link data - Parameter handler: the handler to be invoked if there is deferred App Link data
The handler may contain an NSError instance to capture any errors. In the The handler may contain an NSError instance to capture any errors. In the
@ -63,7 +63,7 @@ typedef void (^FBSDKDeferredAppInviteHandler)(NSURL *url);
/** /**
@warning This method is no longer available and will always return NO. - Warning:This method is no longer available and will always return NO.
*/ */
+ (BOOL)fetchDeferredAppInvite:(FBSDKDeferredAppInviteHandler)handler + (BOOL)fetchDeferredAppInvite:(FBSDKDeferredAppInviteHandler)handler
__attribute__((deprecated("This method is no longer available.")));; __attribute__((deprecated("This method is no longer available.")));;
@ -75,9 +75,9 @@ __attribute__((deprecated("This method is no longer available.")));;
Note: This throws an exception if Bolts.framework is not linked. Add '[BFURL class]' in intialize method Note: This throws an exception if Bolts.framework is not linked. Add '[BFURL class]' in intialize method
of your AppDelegate. of your AppDelegate.
@param url App Link url that was passed to the app. - Parameter url: App Link url that was passed to the app.
@return Promotion code string. - Returns: Promotion code string.
Call this method to fetch App Invite Promotion Code from applink if present. Call this method to fetch App Invite Promotion Code from applink if present.

View File

@ -41,15 +41,15 @@
of the AppDelegate for your app. It should be invoked for the proper processing of responses during interaction of the AppDelegate for your app. It should be invoked for the proper processing of responses during interaction
with the native Facebook app or Safari as part of SSO authorization flow or Facebook dialogs. with the native Facebook app or Safari as part of SSO authorization flow or Facebook dialogs.
@param application The application as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. - Parameter application: The application as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:].
@param url The URL as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. - Parameter url: The URL as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:].
@param sourceApplication The sourceApplication as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. - Parameter sourceApplication: The sourceApplication as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:].
@param annotation The annotation as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. - Parameter annotation: The annotation as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:].
@return YES if the url was intended for the Facebook SDK, NO if not. - Returns: YES if the url was intended for the Facebook SDK, NO if not.
*/ */
- (BOOL)application:(UIApplication *)application - (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url openURL:(NSURL *)url
@ -62,13 +62,13 @@
of the AppDelegate for your app. It should be invoked for the proper processing of responses during interaction of the AppDelegate for your app. It should be invoked for the proper processing of responses during interaction
with the native Facebook app or Safari as part of SSO authorization flow or Facebook dialogs. with the native Facebook app or Safari as part of SSO authorization flow or Facebook dialogs.
@param application The application as passed to [UIApplicationDelegate application:openURL:options:]. - Parameter application: The application as passed to [UIApplicationDelegate application:openURL:options:].
@param url The URL as passed to [UIApplicationDelegate application:openURL:options:]. - Parameter url: The URL as passed to [UIApplicationDelegate application:openURL:options:].
@param options The options dictionary as passed to [UIApplicationDelegate application:openURL:options:]. - Parameter options: The options dictionary as passed to [UIApplicationDelegate application:openURL:options:].
@return YES if the url was intended for the Facebook SDK, NO if not. - Returns: YES if the url was intended for the Facebook SDK, NO if not.
*/ */
- (BOOL)application:(UIApplication *)application - (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url openURL:(NSURL *)url
@ -81,11 +81,11 @@
As part of SDK initialization basic auto logging of app events will occur, this can be As part of SDK initialization basic auto logging of app events will occur, this can be
controlled via 'FacebookAutoLogAppEventsEnabled' key in the project info plist file. controlled via 'FacebookAutoLogAppEventsEnabled' key in the project info plist file.
@param application The application as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. - Parameter application: The application as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
@param launchOptions The launchOptions as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. - Parameter launchOptions: The launchOptions as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
@return YES if the url was intended for the Facebook SDK, NO if not. - Returns: YES if the url was intended for the Facebook SDK, NO if not.
*/ */
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

View File

@ -55,14 +55,13 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
FBSDKBridgeAPIRequest *_pendingRequest; FBSDKBridgeAPIRequest *_pendingRequest;
FBSDKBridgeAPICallbackBlock _pendingRequestCompletionBlock; FBSDKBridgeAPICallbackBlock _pendingRequestCompletionBlock;
id<FBSDKURLOpening> _pendingURLOpen; id<FBSDKURLOpening> _pendingURLOpen;
#ifdef __IPHONE_11_0
SFAuthenticationSession *_authenticationSession NS_AVAILABLE_IOS(11_0); SFAuthenticationSession *_authenticationSession NS_AVAILABLE_IOS(11_0);
SFAuthenticationCompletionHandler _authenticationSessionCompletionHandler NS_AVAILABLE_IOS(11_0); #endif
#endif #endif
BOOL _expectingBackground; BOOL _expectingBackground;
BOOL _isRequestingSFAuthenticationSession;
UIViewController *_safariViewController; UIViewController *_safariViewController;
BOOL _isDismissingSafariViewController; BOOL _isDismissingSafariViewController;
BOOL _isAppLaunched;
} }
#pragma mark - Class Methods #pragma mark - Class Methods
@ -81,9 +80,6 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
+ (void)initializeWithLaunchData:(NSNotification *)note + (void)initializeWithLaunchData:(NSNotification *)note
{ {
NSDictionary *launchData = note.userInfo; NSDictionary *launchData = note.userInfo;
[[self sharedInstance] application:[UIApplication sharedApplication] didFinishLaunchingWithOptions:launchData];
#if !TARGET_OS_TV #if !TARGET_OS_TV
// Register Listener for Bolts measurement events // Register Listener for Bolts measurement events
[FBSDKBoltsMeasurementEventListener defaultListener]; [FBSDKBoltsMeasurementEventListener defaultListener];
@ -118,8 +114,6 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [defaultCenter addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
[defaultCenter addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; [defaultCenter addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
[[FBSDKAppEvents singleton] registerNotifications];
} }
return self; return self;
} }
@ -164,12 +158,12 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
id<FBSDKURLOpening> pendingURLOpen = _pendingURLOpen; id<FBSDKURLOpening> pendingURLOpen = _pendingURLOpen;
void (^completePendingOpenURLBlock)(void) = ^{ void (^completePendingOpenURLBlock)(void) = ^{
self->_pendingURLOpen = nil; _pendingURLOpen = nil;
[pendingURLOpen application:application [pendingURLOpen application:application
openURL:url openURL:url
sourceApplication:sourceApplication sourceApplication:sourceApplication
annotation:annotation]; annotation:annotation];
self->_isDismissingSafariViewController = NO; _isDismissingSafariViewController = NO;
}; };
// if they completed a SFVC flow, dismiss it. // if they completed a SFVC flow, dismiss it.
if (_safariViewController) { if (_safariViewController) {
@ -178,12 +172,12 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
completion:completePendingOpenURLBlock]; completion:completePendingOpenURLBlock];
_safariViewController = nil; _safariViewController = nil;
} else { } else {
if (@available(iOS 11.0, *)) { #ifdef __IPHONE_11_0
if (_authenticationSession != nil) { if (_authenticationSession != nil) {
[_authenticationSession cancel]; [_authenticationSession cancel];
_authenticationSession = nil; _authenticationSession = nil;
}
} }
#endif
completePendingOpenURLBlock(); completePendingOpenURLBlock();
} }
if ([pendingURLOpen canOpenURL:url if ([pendingURLOpen canOpenURL:url
@ -203,19 +197,12 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ {
if (_isAppLaunched) {
return NO;
}
_isAppLaunched = YES;
FBSDKAccessToken *cachedToken = [[FBSDKSettings accessTokenCache] fetchAccessToken]; FBSDKAccessToken *cachedToken = [[FBSDKSettings accessTokenCache] fetchAccessToken];
[FBSDKAccessToken setCurrentAccessToken:cachedToken]; [FBSDKAccessToken setCurrentAccessToken:cachedToken];
// fetch app settings // fetch app settings
[FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:NULL]; [FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:NULL];
if ([[FBSDKSettings autoLogAppEventsEnabled] boolValue]) { [self _logSDKInitialize];
[self _logSDKInitialize];
}
#if !TARGET_OS_TV #if !TARGET_OS_TV
FBSDKProfile *cachedProfile = [FBSDKProfile fetchCachedProfile]; FBSDKProfile *cachedProfile = [FBSDKProfile fetchCachedProfile];
[FBSDKProfile setCurrentProfile:cachedProfile]; [FBSDKProfile setCurrentProfile:cachedProfile];
@ -241,7 +228,6 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
- (void)applicationDidEnterBackground:(NSNotification *)notification - (void)applicationDidEnterBackground:(NSNotification *)notification
{ {
_isRequestingSFAuthenticationSession = NO;
_active = NO; _active = NO;
_expectingBackground = NO; _expectingBackground = NO;
} }
@ -255,14 +241,11 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
// _expectingBackground can be YES if the caller started doing work (like login) // _expectingBackground can be YES if the caller started doing work (like login)
// within the app delegate's lifecycle like openURL, in which case there // within the app delegate's lifecycle like openURL, in which case there
// might have been a "didBecomeActive" event pending that we want to ignore. // might have been a "didBecomeActive" event pending that we want to ignore.
BOOL notExpectingBackground = !_expectingBackground && !_safariViewController && !_isDismissingSafariViewController && !_isRequestingSFAuthenticationSession; BOOL notExpectingBackground = !_expectingBackground && !_safariViewController && !_isDismissingSafariViewController;
#if !TARGET_OS_TV #if !TARGET_OS_TV
if (@available(iOS 11.0, *)) { #ifdef __IPHONE_11_0
if (notExpectingBackground && _authenticationSessionCompletionHandler != nil) { notExpectingBackground = notExpectingBackground && !_authenticationSession;
_authenticationSessionCompletionHandler(nil, nil); #endif
}
notExpectingBackground = notExpectingBackground && !_authenticationSession;
}
#endif #endif
if (notExpectingBackground) { if (notExpectingBackground) {
_active = YES; _active = YES;
@ -328,8 +311,8 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
_pendingRequestCompletionBlock = [completionBlock copy]; _pendingRequestCompletionBlock = [completionBlock copy];
void (^handler)(BOOL, NSError *) = ^(BOOL openedURL, NSError *anError) { void (^handler)(BOOL, NSError *) = ^(BOOL openedURL, NSError *anError) {
if (!openedURL) { if (!openedURL) {
self->_pendingRequest = nil; _pendingRequest = nil;
self->_pendingRequestCompletionBlock = nil; _pendingRequestCompletionBlock = nil;
NSError *openedURLError; NSError *openedURLError;
if ([request.scheme hasPrefix:@"http"]) { if ([request.scheme hasPrefix:@"http"]) {
openedURLError = [FBSDKError errorWithCode:FBSDKBrowserUnavailableErrorCode openedURLError = [FBSDKError errorWithCode:FBSDKBrowserUnavailableErrorCode
@ -364,35 +347,22 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
_expectingBackground = NO; _expectingBackground = NO;
_pendingURLOpen = sender; _pendingURLOpen = sender;
if (@available(iOS 11.0, *)) { #ifdef __IPHONE_11_0
if ([sender isAuthenticationURL:url]) { if ([sender isAuthenticationURL:url]) {
Class SFAuthenticationSessionClass = fbsdkdfl_SFAuthenticationSessionClass(); Class SFAuthenticationSessionClass = fbsdkdfl_SFAuthenticationSessionClass();
if (SFAuthenticationSessionClass != nil) { if (SFAuthenticationSessionClass != nil) {
if (_authenticationSession != nil) { _authenticationSession = [[SFAuthenticationSessionClass alloc] initWithURL:url callbackURLScheme:[FBSDKInternalUtility appURLScheme] completionHandler:^ (NSURL *aURL, NSError *error) {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors handler(error == nil, error);
formatString:@"There is already a request for authenticated session. Cancelling active SFAuthenticationSession before starting the new one.", nil]; if (error == nil) {
[_authenticationSession cancel]; [self application:[UIApplication sharedApplication] openURL:aURL sourceApplication:@"com.apple" annotation:nil];
} }
__weak typeof(self) weakSelf = self; _authenticationSession = nil;
_authenticationSessionCompletionHandler = ^ (NSURL *aURL, NSError *error) { }];
typeof(self) strongSelf = weakSelf; [_authenticationSession start];
strongSelf->_isRequestingSFAuthenticationSession = NO; return;
handler(error == nil, error);
if (error == nil) {
[strongSelf application:[UIApplication sharedApplication] openURL:aURL sourceApplication:@"com.apple" annotation:nil];
}
strongSelf->_authenticationSession = nil;
strongSelf->_authenticationSessionCompletionHandler = nil;
};
_authenticationSession = [[SFAuthenticationSessionClass alloc] initWithURL:url
callbackURLScheme:[FBSDKInternalUtility appURLScheme]
completionHandler:_authenticationSessionCompletionHandler];
_isRequestingSFAuthenticationSession = YES;
[_authenticationSession start];
return;
}
} }
} }
#endif
// trying to dynamically load SFSafariViewController class // trying to dynamically load SFSafariViewController class
// so for the cases when it is available we can send users through Safari View Controller flow // so for the cases when it is available we can send users through Safari View Controller flow
@ -417,11 +387,11 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
// Wait until the transition is finished before presenting SafariVC to avoid a blank screen. // Wait until the transition is finished before presenting SafariVC to avoid a blank screen.
[parent.transitionCoordinator animateAlongsideTransition:NULL completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { [parent.transitionCoordinator animateAlongsideTransition:NULL completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Note SFVC init must occur inside block to avoid blank screen. // Note SFVC init must occur inside block to avoid blank screen.
self->_safariViewController = [[SFSafariViewControllerClass alloc] initWithURL:url]; _safariViewController = [[SFSafariViewControllerClass alloc] initWithURL:url];
// Disable dismissing with edge pan gesture // Disable dismissing with edge pan gesture
self->_safariViewController.modalPresentationStyle = UIModalPresentationOverFullScreen; _safariViewController.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self->_safariViewController performSelector:@selector(setDelegate:) withObject:self]; [_safariViewController performSelector:@selector(setDelegate:) withObject:self];
[container displayChildController:self->_safariViewController]; [container displayChildController:_safariViewController];
[parent presentViewController:container animated:YES completion:nil]; [parent presentViewController:container animated:YES completion:nil];
}]; }];
} else { } else {
@ -539,9 +509,6 @@ static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
if (objc_lookUpClass("FBSDKTVInterfaceFactory.m") != nil) { if (objc_lookUpClass("FBSDKTVInterfaceFactory.m") != nil) {
[params setObject:@1 forKey:@"tv_lib_included"]; [params setObject:@1 forKey:@"tv_lib_included"];
} }
if (objc_lookUpClass("FBSDKAutoLog") != nil) {
[params setObject:@1 forKey:@"marketing_lib_included"];
}
[FBSDKAppEvents logEvent:@"fb_sdk_initialize" parameters:params]; [FBSDKAppEvents logEvent:@"fb_sdk_initialize" parameters:params];
} }

View File

@ -111,7 +111,7 @@ typedef NS_ENUM(NSInteger, FBSDKErrorCode)
/** /**
@warning use FBSDKBrowserUnavailableErrorCode instead - Warning:use FBSDKBrowserUnavailableErrorCode instead
*/ */
FBSDKBrowswerUnavailableErrorCode __attribute__ ((deprecated("use FBSDKBrowserUnavailableErrorCode instead"))) = FBSDKBrowserUnavailableErrorCode, FBSDKBrowswerUnavailableErrorCode __attribute__ ((deprecated("use FBSDKBrowserUnavailableErrorCode instead"))) = FBSDKBrowserUnavailableErrorCode,
}; };
@ -207,11 +207,11 @@ FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorParsedJSONResponseKey;
/** /**
attempt the recovery attempt the recovery
@param error the error - Parameter error: the error
@param recoveryOptionIndex the selected option index - Parameter recoveryOptionIndex: the selected option index
@param delegate the delegate - Parameter delegate: the delegate
@param didRecoverSelector the callback selector, see discussion. - Parameter didRecoverSelector: the callback selector, see discussion.
@param contextInfo context info to pass back to callback selector, see discussion. - Parameter contextInfo: context info to pass back to callback selector, see discussion.
Given that an error alert has been presented document-modally to the user, and the user has chosen one of the error's recovery options, attempt recovery from the error, and send the selected message to the specified delegate. The option index is an index into the error's array of localized recovery options. The method selected by didRecoverSelector must have the same signature as: Given that an error alert has been presented document-modally to the user, and the user has chosen one of the error's recovery options, attempt recovery from the error, and send the selected message to the specified delegate. The option index is an index into the error's array of localized recovery options. The method selected by didRecoverSelector must have the same signature as:

View File

@ -27,7 +27,7 @@
/** /**
Implemented by NSObject as a convenience to copyWithZone:. Implemented by NSObject as a convenience to copyWithZone:.
@return A copy of the receiver. - Returns: A copy of the receiver.
*/ */
- (id)copy; - (id)copy;

View File

@ -33,25 +33,16 @@
#import <FBSDKCoreKit/FBSDKUtility.h> #import <FBSDKCoreKit/FBSDKUtility.h>
#if !TARGET_OS_TV #if !TARGET_OS_TV
#import <FBSDKCoreKit/FBSDKAppLink.h>
#import <FBSDKCoreKit/FBSDKAppLinkNavigation.h>
#import <FBSDKCoreKit/FBSDKAppLinkResolver.h> #import <FBSDKCoreKit/FBSDKAppLinkResolver.h>
#import <FBSDKCoreKit/FBSDKAppLinkResolving.h>
#import <FBSDKCoreKit/FBSDKAppLinkReturnToRefererController.h>
#import <FBSDKCoreKit/FBSDKAppLinkReturnToRefererView.h>
#import <FBSDKCoreKit/FBSDKAppLinkTarget.h>
#import <FBSDKCoreKit/FBSDKAppLinkUtility.h> #import <FBSDKCoreKit/FBSDKAppLinkUtility.h>
#import <FBSDKCoreKit/FBSDKGraphErrorRecoveryProcessor.h> #import <FBSDKCoreKit/FBSDKGraphErrorRecoveryProcessor.h>
#import <FBSDKCoreKit/FBSDKMeasurementEvent.h>
#import <FBSDKCoreKit/FBSDKMutableCopying.h> #import <FBSDKCoreKit/FBSDKMutableCopying.h>
#import <FBSDKCoreKit/FBSDKProfile.h> #import <FBSDKCoreKit/FBSDKProfile.h>
#import <FBSDKCoreKit/FBSDKProfilePictureView.h> #import <FBSDKCoreKit/FBSDKProfilePictureView.h>
#import <FBSDKCoreKit/FBSDKURL.h>
#import <FBSDKCoreKit/FBSDKWebViewAppLinkResolver.h>
#else #else
#import <FBSDKCoreKit/FBSDKDeviceButton.h> #import <FBSDKCoreKit/FBSDKDeviceButton.h>
#import <FBSDKCoreKit/FBSDKDeviceViewControllerBase.h> #import <FBSDKCoreKit/FBSDKDeviceViewControllerBase.h>
#endif #endif
#define FBSDK_VERSION_STRING @"4.37.0" #define FBSDK_VERSION_STRING @"4.29.0"
#define FBSDK_TARGET_PLATFORM_VERSION @"v3.1" #define FBSDK_TARGET_PLATFORM_VERSION @"v2.11"

View File

@ -30,17 +30,17 @@
/** /**
Indicates the error recovery has been attempted. Indicates the error recovery has been attempted.
@param processor the processor instance. - Parameter processor: the processor instance.
@param didRecover YES if the recovery was successful. - Parameter didRecover: YES if the recovery was successful.
@param error the error that that was attempted to be recovered from. - Parameter error: the error that that was attempted to be recovered from.
*/ */
- (void)processorDidAttemptRecovery:(FBSDKGraphErrorRecoveryProcessor *)processor didRecover:(BOOL)didRecover error:(NSError *)error; - (void)processorDidAttemptRecovery:(FBSDKGraphErrorRecoveryProcessor *)processor didRecover:(BOOL)didRecover error:(NSError *)error;
@optional @optional
/** /**
Indicates the processor is about to process the error. Indicates the processor is about to process the error.
@param processor the processor instance. - Parameter processor: the processor instance.
@param error the error is about to be processed. - Parameter error: the error is about to be processed.
return NO if the processor should not process the error. For example, return NO if the processor should not process the error. For example,
if you want to prevent alerts of localized messages but otherwise perform retries and recoveries, if you want to prevent alerts of localized messages but otherwise perform retries and recoveries,
@ -83,16 +83,16 @@
/** /**
Attempts to process the error, return YES if the error can be processed. Attempts to process the error, return YES if the error can be processed.
@param error the error to process. - Parameter error: the error to process.
@param request the related request that may be reissued. - Parameter request: the related request that may be reissued.
@param delegate the delegate that will be retained until recovery is complete. - Parameter delegate: the delegate that will be retained until recovery is complete.
*/ */
- (BOOL)processError:(NSError *)error request:(FBSDKGraphRequest *)request delegate:(id<FBSDKGraphErrorRecoveryProcessorDelegate>) delegate; - (BOOL)processError:(NSError *)error request:(FBSDKGraphRequest *)request delegate:(id<FBSDKGraphErrorRecoveryProcessorDelegate>) delegate;
/** /**
The callback for FBSDKErrorRecoveryAttempting The callback for FBSDKErrorRecoveryAttempting
@param didRecover if the recovery succeeded - Parameter didRecover: if the recovery succeeded
@param contextInfo unused - Parameter contextInfo: unused
*/ */
- (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo; - (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo;

View File

@ -67,9 +67,9 @@
// the block returns YES if recovery UI is started (meaning we wait for the alertviewdelegate to resume control flow). // the block returns YES if recovery UI is started (meaning we wait for the alertviewdelegate to resume control flow).
BOOL (^standardRecoveryWork)(void) = ^BOOL{ BOOL (^standardRecoveryWork)(void) = ^BOOL{
NSArray *recoveryOptionsTitles = error.userInfo[NSLocalizedRecoveryOptionsErrorKey]; NSArray *recoveryOptionsTitles = error.userInfo[NSLocalizedRecoveryOptionsErrorKey];
if (recoveryOptionsTitles.count > 0 && self->_recoveryAttempter) { if (recoveryOptionsTitles.count > 0 && _recoveryAttempter) {
NSString *recoverySuggestion = error.userInfo[NSLocalizedRecoverySuggestionErrorKey]; NSString *recoverySuggestion = error.userInfo[NSLocalizedRecoverySuggestionErrorKey];
self->_error = error; _error = error;
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[self displayAlertWithRecoverySuggestion:recoverySuggestion recoveryOptionsTitles:recoveryOptionsTitles]; [self displayAlertWithRecoverySuggestion:recoverySuggestion recoveryOptionsTitles:recoveryOptionsTitles];
}); });
@ -90,7 +90,7 @@
[self.delegate processorDidAttemptRecovery:self didRecover:YES error:nil]; [self.delegate processorDidAttemptRecovery:self didRecover:YES error:nil];
self.delegate = nil; self.delegate = nil;
} else if (!standardRecoveryWork()) { } else if (!standardRecoveryWork()) {
[self.delegate processorDidAttemptRecovery:self didRecover:NO error:self->_error]; [self.delegate processorDidAttemptRecovery:self didRecover:NO error:_error];
}; };
}); });
}]; }];
@ -133,7 +133,7 @@
UIAlertAction *option = [UIAlertAction actionWithTitle:title UIAlertAction *option = [UIAlertAction actionWithTitle:title
style:UIAlertActionStyleDefault style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) { handler:^(UIAlertAction * _Nonnull action) {
[self->_recoveryAttempter attemptRecoveryFromError:self->_error [_recoveryAttempter attemptRecoveryFromError:_error
optionIndex:i optionIndex:i
delegate:self delegate:self
didRecoverSelector:@selector(didPresentErrorWithRecovery:contextInfo:) didRecoverSelector:@selector(didPresentErrorWithRecovery:contextInfo:)
@ -170,7 +170,7 @@
UIAlertAction *OKAction = [UIAlertAction actionWithTitle:localizedOK UIAlertAction *OKAction = [UIAlertAction actionWithTitle:localizedOK
style:UIAlertActionStyleCancel style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) { handler:^(UIAlertAction * _Nonnull action) {
[self->_recoveryAttempter attemptRecoveryFromError:self->_error [_recoveryAttempter attemptRecoveryFromError:_error
optionIndex:0 optionIndex:0
delegate:self delegate:self
didRecoverSelector:@selector(didPresentErrorWithRecovery:contextInfo:) didRecoverSelector:@selector(didPresentErrorWithRecovery:contextInfo:)

View File

@ -39,23 +39,23 @@
By default, FBSDKGraphRequest will attempt to recover any errors returned from By default, FBSDKGraphRequest will attempt to recover any errors returned from
Facebook. You can disable this via `disableErrorRecovery:`. Facebook. You can disable this via `disableErrorRecovery:`.
@see FBSDKGraphErrorRecoveryProcessor - See:FBSDKGraphErrorRecoveryProcessor
*/ */
@interface FBSDKGraphRequest : NSObject @interface FBSDKGraphRequest : NSObject
/** /**
Initializes a new instance that use use `[FBSDKAccessToken currentAccessToken]`. Initializes a new instance that use use `[FBSDKAccessToken currentAccessToken]`.
@param graphPath the graph path (e.g., @"me"). - Parameter graphPath: the graph path (e.g., @"me").
@param parameters the optional parameters dictionary. - Parameter parameters: the optional parameters dictionary.
*/ */
- (instancetype)initWithGraphPath:(NSString *)graphPath - (instancetype)initWithGraphPath:(NSString *)graphPath
parameters:(NSDictionary *)parameters; parameters:(NSDictionary *)parameters;
/** /**
Initializes a new instance that use use `[FBSDKAccessToken currentAccessToken]`. Initializes a new instance that use use `[FBSDKAccessToken currentAccessToken]`.
@param graphPath the graph path (e.g., @"me"). - Parameter graphPath: the graph path (e.g., @"me").
@param parameters the optional parameters dictionary. - Parameter parameters: the optional parameters dictionary.
@param HTTPMethod the optional HTTP method. nil defaults to @"GET". - Parameter HTTPMethod: the optional HTTP method. nil defaults to @"GET".
*/ */
- (instancetype)initWithGraphPath:(NSString *)graphPath - (instancetype)initWithGraphPath:(NSString *)graphPath
parameters:(NSDictionary *)parameters parameters:(NSDictionary *)parameters
@ -63,11 +63,11 @@
/** /**
Initializes a new instance. Initializes a new instance.
@param graphPath the graph path (e.g., @"me"). - Parameter graphPath: the graph path (e.g., @"me").
@param parameters the optional parameters dictionary. - Parameter parameters: the optional parameters dictionary.
@param tokenString the token string to use. Specifying nil will cause no token to be used. - Parameter tokenString: the token string to use. Specifying nil will cause no token to be used.
@param version the optional Graph API version (e.g., @"v2.0"). nil defaults to `[FBSDKSettings graphAPIVersion]`. - Parameter version: the optional Graph API version (e.g., @"v2.0"). nil defaults to `[FBSDKSettings graphAPIVersion]`.
@param HTTPMethod the optional HTTP method (e.g., @"POST"). nil defaults to @"GET". - Parameter HTTPMethod: the optional HTTP method (e.g., @"POST"). nil defaults to @"GET".
*/ */
- (instancetype)initWithGraphPath:(NSString *)graphPath - (instancetype)initWithGraphPath:(NSString *)graphPath
parameters:(NSDictionary *)parameters parameters:(NSDictionary *)parameters
@ -103,7 +103,7 @@ NS_DESIGNATED_INITIALIZER;
/** /**
If set, disables the automatic error recovery mechanism. If set, disables the automatic error recovery mechanism.
@param disable whether to disable the automatic error recovery mechanism - Parameter disable: whether to disable the automatic error recovery mechanism
By default, non-batched FBSDKGraphRequest instances will automatically try to recover By default, non-batched FBSDKGraphRequest instances will automatically try to recover
from errors by constructing a `FBSDKGraphErrorRecoveryProcessor` instance that from errors by constructing a `FBSDKGraphErrorRecoveryProcessor` instance that
@ -116,7 +116,7 @@ NS_DESIGNATED_INITIALIZER;
/** /**
Starts a connection to the Graph API. Starts a connection to the Graph API.
@param handler The handler block to call when the request completes. - Parameter handler: The handler block to call when the request completes.
*/ */
- (FBSDKGraphRequestConnection *)startWithCompletionHandler:(FBSDKGraphRequestHandler)handler; - (FBSDKGraphRequestConnection *)startWithCompletionHandler:(FBSDKGraphRequestHandler)handler;

View File

@ -30,7 +30,6 @@
// constants // constants
static NSString *const kGetHTTPMethod = @"GET"; static NSString *const kGetHTTPMethod = @"GET";
static NSString *const kPostHTTPMethod = @"POST";
@interface FBSDKGraphRequest() @interface FBSDKGraphRequest()
@property (nonatomic, assign) FBSDKGraphRequestFlags flags; @property (nonatomic, assign) FBSDKGraphRequestFlags flags;
@ -145,23 +144,12 @@ static NSString *const kPostHTTPMethod = @"POST";
+ (NSString *)serializeURL:(NSString *)baseUrl + (NSString *)serializeURL:(NSString *)baseUrl
params:(NSDictionary *)params params:(NSDictionary *)params
httpMethod:(NSString *)httpMethod { httpMethod:(NSString *)httpMethod {
return [self serializeURL:baseUrl params:params httpMethod:httpMethod forBatch:NO];
}
+ (NSString *)serializeURL:(NSString *)baseUrl
params:(NSDictionary *)params
httpMethod:(NSString *)httpMethod
forBatch:(BOOL)forBatch {
params = [self preprocessParams: params]; params = [self preprocessParams: params];
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations" #pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSURL *parsedURL = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSURL *parsedURL = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
#pragma clang pop #pragma clang pop
if ([httpMethod isEqualToString:kPostHTTPMethod] && !forBatch) {
return baseUrl;
}
NSString *queryPrefix = parsedURL.query ? @"&" : @"?"; NSString *queryPrefix = parsedURL.query ? @"&" : @"?";
NSString *query = [FBSDKInternalUtility queryStringWithDictionary:params error:NULL invalidObjectHandler:^id(id object, BOOL *stop) { NSString *query = [FBSDKInternalUtility queryStringWithDictionary:params error:NULL invalidObjectHandler:^id(id object, BOOL *stop) {

View File

@ -34,13 +34,13 @@
Pass a block of this type when calling addRequest. This will be called once Pass a block of this type when calling addRequest. This will be called once
the request completes. The call occurs on the UI thread. the request completes. The call occurs on the UI thread.
@param connection The `FBSDKGraphRequestConnection` that sent the request. - Parameter connection: The `FBSDKGraphRequestConnection` that sent the request.
@param result The result of the request. This is a translation of - Parameter result: The result of the request. This is a translation of
JSON data to `NSDictionary` and `NSArray` objects. This JSON data to `NSDictionary` and `NSArray` objects. This
is nil if there was an error. is nil if there was an error.
@param error The `NSError` representing any error that occurred. - Parameter error: The `NSError` representing any error that occurred.
*/ */
typedef void (^FBSDKGraphRequestHandler)(FBSDKGraphRequestConnection *connection, typedef void (^FBSDKGraphRequestHandler)(FBSDKGraphRequestConnection *connection,
@ -68,7 +68,7 @@ typedef void (^FBSDKGraphRequestHandler)(FBSDKGraphRequestConnection *connection
start, the object returned from the convenience method has already begun loading and this method start, the object returned from the convenience method has already begun loading and this method
will not be called when the delegate is set. will not be called when the delegate is set.
@param connection The request connection that is starting a network request - Parameter connection: The request connection that is starting a network request
*/ */
- (void)requestConnectionWillBeginLoading:(FBSDKGraphRequestConnection *)connection; - (void)requestConnectionWillBeginLoading:(FBSDKGraphRequestConnection *)connection;
@ -86,7 +86,7 @@ typedef void (^FBSDKGraphRequestHandler)(FBSDKGraphRequestConnection *connection
This method is invoked after the completion handler for each <FBSDKGraphRequest>. This method is invoked after the completion handler for each <FBSDKGraphRequest>.
@param connection The request connection that successfully completed a network request - Parameter connection: The request connection that successfully completed a network request
*/ */
- (void)requestConnectionDidFinishLoading:(FBSDKGraphRequestConnection *)connection; - (void)requestConnectionDidFinishLoading:(FBSDKGraphRequestConnection *)connection;
@ -101,8 +101,8 @@ typedef void (^FBSDKGraphRequestHandler)(FBSDKGraphRequestConnection *connection
argument specifies why the network connection failed. The `NSError` object passed to the argument specifies why the network connection failed. The `NSError` object passed to the
FBSDKGraphRequestHandler block may contain additional information. FBSDKGraphRequestHandler block may contain additional information.
@param connection The request connection that successfully completed a network request - Parameter connection: The request connection that successfully completed a network request
@param error The `NSError` representing the network error that occurred, if any. May be nil - Parameter error: The `NSError` representing the network error that occurred, if any. May be nil
in some circumstances. Consult the `NSError` for the <FBSDKGraphRequest> for reliable in some circumstances. Consult the `NSError` for the <FBSDKGraphRequest> for reliable
failure information. failure information.
*/ */
@ -120,10 +120,10 @@ typedef void (^FBSDKGraphRequestHandler)(FBSDKGraphRequestConnection *connection
Like `NSURLConnection`, the values may change in unexpected ways if data needs to be resent. Like `NSURLConnection`, the values may change in unexpected ways if data needs to be resent.
@param connection The request connection transmitting data to a remote host - Parameter connection: The request connection transmitting data to a remote host
@param bytesWritten The number of bytes sent in the last transmission - Parameter bytesWritten: The number of bytes sent in the last transmission
@param totalBytesWritten The total number of bytes sent to the remote host - Parameter totalBytesWritten: The total number of bytes sent to the remote host
@param totalBytesExpectedToWrite The total number of bytes expected to send to the remote host - Parameter totalBytesExpectedToWrite: The total number of bytes expected to send to the remote host
*/ */
- (void)requestConnection:(FBSDKGraphRequestConnection *)connection - (void)requestConnection:(FBSDKGraphRequestConnection *)connection
didSendBodyData:(NSInteger)bytesWritten didSendBodyData:(NSInteger)bytesWritten
@ -177,7 +177,7 @@ totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
This method sets the default timeout on all FBSDKGraphRequestConnection instances. Defaults to 60 seconds. This method sets the default timeout on all FBSDKGraphRequestConnection instances. Defaults to 60 seconds.
@param defaultConnectionTimeout The timeout interval. - Parameter defaultConnectionTimeout: The timeout interval.
*/ */
+ (void)setDefaultConnectionTimeout:(NSTimeInterval)defaultConnectionTimeout; + (void)setDefaultConnectionTimeout:(NSTimeInterval)defaultConnectionTimeout;
@ -190,8 +190,8 @@ totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
This method adds an <FBSDKGraphRequest> object to this connection. This method adds an <FBSDKGraphRequest> object to this connection.
@param request A request to be included in the round-trip when start is called. - Parameter request: A request to be included in the round-trip when start is called.
@param handler A handler to call back when the round-trip completes or times out. - Parameter handler: A handler to call back when the round-trip completes or times out.
@ -206,12 +206,12 @@ totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
This method adds an <FBSDKGraphRequest> object to this connection. This method adds an <FBSDKGraphRequest> object to this connection.
@param request A request to be included in the round-trip when start is called. - Parameter request: A request to be included in the round-trip when start is called.
@param handler A handler to call back when the round-trip completes or times out. - Parameter handler: A handler to call back when the round-trip completes or times out.
The handler will be invoked on the main thread. The handler will be invoked on the main thread.
@param name An optional name for this request. This can be used to feed - Parameter name: An optional name for this request. This can be used to feed
the results of one request to the input of another <FBSDKGraphRequest> in the same the results of one request to the input of another <FBSDKGraphRequest> in the same
`FBSDKGraphRequestConnection` as described in `FBSDKGraphRequestConnection` as described in
[Graph API Batch Requests]( https://developers.facebook.com/docs/reference/api/batch/ ). [Graph API Batch Requests]( https://developers.facebook.com/docs/reference/api/batch/ ).
@ -231,11 +231,11 @@ totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
This method adds an <FBSDKGraphRequest> object to this connection. This method adds an <FBSDKGraphRequest> object to this connection.
@param request A request to be included in the round-trip when start is called. - Parameter request: A request to be included in the round-trip when start is called.
@param handler A handler to call back when the round-trip completes or times out. - Parameter handler: A handler to call back when the round-trip completes or times out.
@param batchParameters The optional dictionary of parameters to include for this request - Parameter batchParameters: The optional dictionary of parameters to include for this request
as described in [Graph API Batch Requests]( https://developers.facebook.com/docs/reference/api/batch/ ). as described in [Graph API Batch Requests]( https://developers.facebook.com/docs/reference/api/batch/ ).
Examples include "depends_on", "name", or "omit_response_on_success". Examples include "depends_on", "name", or "omit_response_on_success".
@ -285,7 +285,7 @@ totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
/** /**
Determines the operation queue that is used to call methods on the connection's delegate. Determines the operation queue that is used to call methods on the connection's delegate.
@param queue The operation queue to use when calling delegate methods. - Parameter queue: The operation queue to use when calling delegate methods.
By default, a connection is scheduled on the current thread in the default mode when it is created. By default, a connection is scheduled on the current thread in the default mode when it is created.
You cannot reschedule a connection after it has started. You cannot reschedule a connection after it has started.
@ -305,7 +305,7 @@ totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
for applications. If you want to override the version part while using batch requests on the connection, call for applications. If you want to override the version part while using batch requests on the connection, call
this method to set the version for the batch request. this method to set the version for the batch request.
@param version This is a string in the form @"v2.0" which will be used for the version part of an API path - Parameter version: This is a string in the form @"v2.0" which will be used for the version part of an API path
*/ */
- (void)overrideVersionPartWith:(NSString *)version; - (void)overrideVersionPartWith:(NSString *)version;

View File

@ -60,27 +60,6 @@ static NSTimeInterval g_defaultTimeout = 60.0;
static FBSDKErrorConfiguration *g_errorConfiguration; static FBSDKErrorConfiguration *g_errorConfiguration;
#if !TARGET_OS_TV
static FBSDKAccessToken *_CreateExpiredAccessToken(FBSDKAccessToken *accessToken)
{
if (accessToken == nil) {
return nil;
}
if (accessToken.isExpired) {
return accessToken;
}
NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:-1];
return [[FBSDKAccessToken alloc] initWithTokenString:accessToken.tokenString
permissions:accessToken.permissions.allObjects
declinedPermissions:accessToken.declinedPermissions.allObjects
appID:accessToken.appID
userID:accessToken.userID
expirationDate:expirationDate
refreshDate:expirationDate
dataAccessExpirationDate:expirationDate];
}
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// FBSDKGraphRequestConnectionState // FBSDKGraphRequestConnectionState
@ -464,7 +443,7 @@ NSURLSessionDataDelegate
NSUInteger bodyLength = [[body data] length] / 1024; NSUInteger bodyLength = [[body data] length] / 1024;
[request setValue:[FBSDKGraphRequestConnection userAgent] forHTTPHeaderField:@"User-Agent"]; [request setValue:[FBSDKGraphRequestConnection userAgent] forHTTPHeaderField:@"User-Agent"];
[request setValue:[body mimeContentType] forHTTPHeaderField:@"Content-Type"]; [request setValue:[FBSDKGraphRequestBody mimeContentType] forHTTPHeaderField:@"Content-Type"];
[request setHTTPShouldHandleCookies:NO]; [request setHTTPShouldHandleCookies:NO];
[self logRequest:request bodyLength:bodyLength bodyLogger:bodyLogger attachmentLogger:attachmentLogger]; [self logRequest:request bodyLength:bodyLength bodyLogger:bodyLogger attachmentLogger:attachmentLogger];
@ -516,8 +495,7 @@ NSURLSessionDataDelegate
NSString *url = [FBSDKGraphRequest serializeURL:baseURL NSString *url = [FBSDKGraphRequest serializeURL:baseURL
params:request.parameters params:request.parameters
httpMethod:request.HTTPMethod httpMethod:request.HTTPMethod];
forBatch:forBatch];
return url; return url;
} }
@ -680,7 +658,7 @@ NSURLSessionDataDelegate
error:(NSError **)error error:(NSError **)error
{ {
id parsed = nil; id parsed = nil;
if (!(*error) && [utf8 isKindOfClass:[NSString class]]) { if (!(*error)) {
parsed = [FBSDKInternalUtility objectForJSONString:utf8 error:error]; parsed = [FBSDKInternalUtility objectForJSONString:utf8 error:error];
// if we fail parse we attempt a re-parse of a modified input to support results in the form "foo=bar", "true", etc. // if we fail parse we attempt a re-parse of a modified input to support results in the form "foo=bar", "true", etc.
// which is shouldn't be necessary since Graph API v2.1. // which is shouldn't be necessary since Graph API v2.1.
@ -727,9 +705,9 @@ NSURLSessionDataDelegate
#if !TARGET_OS_TV #if !TARGET_OS_TV
if (resultError && ![metadata.request isGraphErrorRecoveryDisabled] && isSingleRequestToRecover) { if (resultError && ![metadata.request isGraphErrorRecoveryDisabled] && isSingleRequestToRecover) {
self->_recoveringRequestMetadata = metadata; _recoveringRequestMetadata = metadata;
self->_errorRecoveryProcessor = [[FBSDKGraphErrorRecoveryProcessor alloc] init]; _errorRecoveryProcessor = [[FBSDKGraphErrorRecoveryProcessor alloc] init];
if ([self->_errorRecoveryProcessor processError:resultError request:metadata.request delegate:self]) { if ([_errorRecoveryProcessor processError:resultError request:metadata.request delegate:self]) {
return; return;
} }
} }
@ -754,24 +732,18 @@ NSURLSessionDataDelegate
} }
[metadata invokeCompletionHandlerForConnection:self withResults:body error:error]; [metadata invokeCompletionHandlerForConnection:self withResults:body error:error];
if (--self->_expectingResults == 0) { if (--_expectingResults == 0) {
if (canNotifyDelegate && [self->_delegate respondsToSelector:@selector(requestConnectionDidFinishLoading:)]) { if (canNotifyDelegate && [_delegate respondsToSelector:@selector(requestConnectionDidFinishLoading:)]) {
[self->_delegate requestConnectionDidFinishLoading:self]; [_delegate requestConnectionDidFinishLoading:self];
} }
} }
}; };
#if !TARGET_OS_TV #if !TARGET_OS_TV
void (^clearToken)(NSInteger) = ^(NSInteger errorSubcode){ void (^clearToken)(void) = ^{
if (metadata.request.flags & FBSDKGraphRequestFlagDoNotInvalidateTokenOnError) { if (!(metadata.request.flags & FBSDKGraphRequestFlagDoNotInvalidateTokenOnError)) {
return;
}
if (errorSubcode == 493) {
[FBSDKAccessToken setCurrentAccessToken:_CreateExpiredAccessToken([FBSDKAccessToken currentAccessToken])];
} else {
[FBSDKAccessToken setCurrentAccessToken:nil]; [FBSDKAccessToken setCurrentAccessToken:nil];
} }
}; };
FBSDKSystemAccountStoreAdapter *adapter = [FBSDKSystemAccountStoreAdapter sharedInstance]; FBSDKSystemAccountStoreAdapter *adapter = [FBSDKSystemAccountStoreAdapter sharedInstance];
@ -794,20 +766,20 @@ NSURLSessionDataDelegate
adapter.forceBlockingRenew = YES; adapter.forceBlockingRenew = YES;
} else { } else {
[adapter renewSystemAuthorization:^(ACAccountCredentialRenewResult result, NSError *renewError) { [adapter renewSystemAuthorization:^(ACAccountCredentialRenewResult result, NSError *renewError) {
NSOperationQueue *queue = self->_delegateQueue ?: [NSOperationQueue mainQueue]; NSOperationQueue *queue = _delegateQueue ?: [NSOperationQueue mainQueue];
[queue addOperationWithBlock:^{ [queue addOperationWithBlock:^{
clearToken(errorSubcode); clearToken();
finishAndInvokeCompletionHandler(); finishAndInvokeCompletionHandler();
}]; }];
}]; }];
return; return;
} }
} }
clearToken(errorSubcode); clearToken();
} else if (errorCode >= 200 && errorCode < 300) { } else if (errorCode >= 200 && errorCode < 300) {
// permission error // permission error
[adapter renewSystemAuthorization:^(ACAccountCredentialRenewResult result, NSError *renewError) { [adapter renewSystemAuthorization:^(ACAccountCredentialRenewResult result, NSError *renewError) {
NSOperationQueue *queue = self->_delegateQueue ?: [NSOperationQueue mainQueue]; NSOperationQueue *queue = _delegateQueue ?: [NSOperationQueue mainQueue];
[queue addOperationWithBlock:finishAndInvokeCompletionHandler]; [queue addOperationWithBlock:finishAndInvokeCompletionHandler];
}]; }];
return; return;
@ -1029,8 +1001,8 @@ totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
FBSDKGraphRequestMetadata *retryMetadata = [[FBSDKGraphRequestMetadata alloc] initWithRequest:retryRequest completionHandler:_recoveringRequestMetadata.completionHandler batchParameters:_recoveringRequestMetadata.batchParameters]; FBSDKGraphRequestMetadata *retryMetadata = [[FBSDKGraphRequestMetadata alloc] initWithRequest:retryRequest completionHandler:_recoveringRequestMetadata.completionHandler batchParameters:_recoveringRequestMetadata.batchParameters];
[retryRequest startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *retriedError) { [retryRequest startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *retriedError) {
[self processResultBody:result error:retriedError metadata:retryMetadata canNotifyDelegate:YES]; [self processResultBody:result error:retriedError metadata:retryMetadata canNotifyDelegate:YES];
self->_errorRecoveryProcessor = nil; _errorRecoveryProcessor = nil;
self->_recoveringRequestMetadata = nil; _recoveringRequestMetadata = nil;
}]; }];
} else { } else {
[self processResultBody:nil error:error metadata:_recoveringRequestMetadata canNotifyDelegate:YES]; [self processResultBody:nil error:error metadata:_recoveringRequestMetadata canNotifyDelegate:YES];

View File

@ -25,9 +25,9 @@
/** /**
Initializes the receiver with the attachment data and metadata. Initializes the receiver with the attachment data and metadata.
@param data The attachment data (retained, not copied) - Parameter data: The attachment data (retained, not copied)
@param filename The filename for the attachment - Parameter filename: The filename for the attachment
@param contentType The content type for the attachment - Parameter contentType: The content type for the attachment
*/ */
- (instancetype)initWithData:(NSData *)data - (instancetype)initWithData:(NSData *)data
filename:(NSString *)filename filename:(NSString *)filename

View File

@ -1,57 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/*! The name of the notification posted by FBSDKMeasurementEvent */
FOUNDATION_EXPORT NSString *const FBSDKMeasurementEventNotificationName;
/*! Defines keys in the userInfo object for the notification named FBSDKMeasurementEventNotificationName */
/*! The string field for the name of the event */
FOUNDATION_EXPORT NSString *const FBSDKMeasurementEventNameKey;
/*! The dictionary field for the arguments of the event */
FOUNDATION_EXPORT NSString *const FBSDKMeasurementEventArgsKey;
/*! Events raised by FBSDKMeasurementEvent for Applink */
/*!
The name of the event posted when [FBSDKURL URLWithURL:] is called successfully. This represents the successful parsing of an app link URL.
*/
FOUNDATION_EXPORT NSString *const FBSDKAppLinkParseEventName;
/*!
The name of the event posted when [FBSDKURL URLWithInboundURL:] is called successfully.
This represents parsing an inbound app link URL from a different application
*/
FOUNDATION_EXPORT NSString *const FBSDKAppLinkNavigateInEventName;
/*! The event raised when the user navigates from your app to other apps */
FOUNDATION_EXPORT NSString *const FBSDKAppLinkNavigateOutEventName;
/*!
The event raised when the user navigates out from your app and back to the referrer app.
e.g when the user leaves your app after tapping the back-to-referrer navigation bar
*/
FOUNDATION_EXPORT NSString *const FBSDKAppLinkNavigateBackToReferrerEventName;
@interface FBSDKMeasurementEvent : NSObject
@end
NS_ASSUME_NONNULL_END

View File

@ -1,68 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKMeasurementEvent_Internal.h"
NSString *const FBSDKMeasurementEventNotificationName = @"com.facebook.facebook-objc-sdk.measurement_event";
NSString *const FBSDKMeasurementEventNameKey = @"event_name";
NSString *const FBSDKMeasurementEventArgsKey = @"event_args";
/* app Link Event raised by this FBSDKURL */
NSString *const FBSDKAppLinkParseEventName = @"al_link_parse";
NSString *const FBSDKAppLinkNavigateInEventName = @"al_nav_in";
/*! AppLink events raised in this class */
NSString *const FBSDKAppLinkNavigateOutEventName = @"al_nav_out";
NSString *const FBSDKAppLinkNavigateBackToReferrerEventName = @"al_ref_back_out";
@implementation FBSDKMeasurementEvent {
NSString *_name;
NSDictionary<NSString *, id> *_args;
}
- (void)postNotification {
if (!_name) {
NSLog(@"Warning: Missing event name when logging FBSDK measurement event. \n"
" Ignoring this event in logging.");
return;
}
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
NSDictionary<NSString *, id> *userInfo = @{FBSDKMeasurementEventNameKey : _name,
FBSDKMeasurementEventArgsKey : _args};
[center postNotificationName:FBSDKMeasurementEventNotificationName
object:self
userInfo:userInfo];
}
- (instancetype)initEventWithName:(NSString *)name
args:(NSDictionary<NSString *, id> *)args {
if ((self = [super init])) {
_name = name;
_args = args ? args : @{};
}
return self;
}
+ (void)postNotificationForEventName:(NSString *)name
args:(NSDictionary<NSString *, id> *)args {
[[[self alloc] initEventWithName:name args:args] postNotification];
}
@end

View File

@ -29,7 +29,7 @@
/** /**
Implemented by NSObject as a convenience to mutableCopyWithZone:. Implemented by NSObject as a convenience to mutableCopyWithZone:.
@return A mutable copy of the receiver. - Returns: A mutable copy of the receiver.
*/ */
- (id)mutableCopy; - (id)mutableCopy;

View File

@ -56,13 +56,13 @@ FBSDK_EXTERN NSString *const FBSDKProfileChangeNewKey;
/** /**
initializes a new instance. initializes a new instance.
@param userID the user ID - Parameter userID: the user ID
@param firstName the user's first name - Parameter firstName: the user's first name
@param middleName the user's middle name - Parameter middleName: the user's middle name
@param lastName the user's last name - Parameter lastName: the user's last name
@param name the user's complete name - Parameter name: the user's complete name
@param linkURL the link for this profile - Parameter linkURL: the link for this profile
@param refreshDate the optional date this profile was fetched. Defaults to [NSDate date]. - Parameter refreshDate: the optional date this profile was fetched. Defaults to [NSDate date].
*/ */
- (instancetype)initWithUserID:(NSString *)userID - (instancetype)initWithUserID:(NSString *)userID
firstName:(NSString *)firstName firstName:(NSString *)firstName
@ -112,7 +112,7 @@ FBSDK_EXTERN NSString *const FBSDKProfileChangeNewKey;
/** /**
Sets the current instance and posts the appropriate notification if the profile parameter is different Sets the current instance and posts the appropriate notification if the profile parameter is different
than the receiver. than the receiver.
@param profile the profile to set - Parameter profile: the profile to set
This persists the profile to NSUserDefaults. This persists the profile to NSUserDefaults.
*/ */
@ -120,7 +120,7 @@ FBSDK_EXTERN NSString *const FBSDKProfileChangeNewKey;
/** /**
Indicates if `currentProfile` will automatically observe `FBSDKAccessTokenDidChangeNotification` notifications Indicates if `currentProfile` will automatically observe `FBSDKAccessTokenDidChangeNotification` notifications
@param enable YES is observing - Parameter enable: YES is observing
If observing, this class will issue a graph request for public profile data when the current token's userID If observing, this class will issue a graph request for public profile data when the current token's userID
differs from the current profile. You can observe `FBSDKProfileDidChangeNotification` for when the profile is updated. differs from the current profile. You can observe `FBSDKProfileDidChangeNotification` for when the profile is updated.
@ -132,7 +132,7 @@ FBSDK_EXTERN NSString *const FBSDKProfileChangeNewKey;
/** /**
Loads the current profile and passes it to the completion block. Loads the current profile and passes it to the completion block.
@param completion The block to be executed once the profile is loaded - Parameter completion: The block to be executed once the profile is loaded
If the profile is already loaded, this method will call the completion block synchronously, otherwise it If the profile is already loaded, this method will call the completion block synchronously, otherwise it
will begin a graph request to update `currentProfile` and then call the completion block when finished. will begin a graph request to update `currentProfile` and then call the completion block when finished.
@ -141,26 +141,26 @@ FBSDK_EXTERN NSString *const FBSDKProfileChangeNewKey;
/** /**
A convenience method for returning a complete `NSURL` for retrieving the user's profile image. A convenience method for returning a complete `NSURL` for retrieving the user's profile image.
@param mode The picture mode - Parameter mode: The picture mode
@param size The height and width. This will be rounded to integer precision. - Parameter size: The height and width. This will be rounded to integer precision.
*/ */
- (NSURL *)imageURLForPictureMode:(FBSDKProfilePictureMode)mode size:(CGSize)size; - (NSURL *)imageURLForPictureMode:(FBSDKProfilePictureMode)mode size:(CGSize)size;
/** /**
A convenience method for returning a Graph API path for retrieving the user's profile image. A convenience method for returning a Graph API path for retrieving the user's profile image.
@warning use `imageURLForPictureMode:size:` instead - Warning:use `imageURLForPictureMode:size:` instead
You can pass this to a `FBSDKGraphRequest` instance to download the image. You can pass this to a `FBSDKGraphRequest` instance to download the image.
@param mode The picture mode - Parameter mode: The picture mode
@param size The height and width. This will be rounded to integer precision. - Parameter size: The height and width. This will be rounded to integer precision.
*/ */
- (NSString *)imagePathForPictureMode:(FBSDKProfilePictureMode)mode size:(CGSize)size - (NSString *)imagePathForPictureMode:(FBSDKProfilePictureMode)mode size:(CGSize)size
__attribute__ ((deprecated("use imageURLForPictureMode:size: instead"))); __attribute__ ((deprecated("use imageURLForPictureMode:size: instead")));
/** /**
Returns YES if the profile is equivalent to the receiver. Returns YES if the profile is equivalent to the receiver.
@param profile the profile to compare to. - Parameter profile: the profile to compare to.
*/ */
- (BOOL)isEqualToProfile:(FBSDKProfile *)profile; - (BOOL)isEqualToProfile:(FBSDKProfile *)profile;
@end @end

View File

@ -67,7 +67,7 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
/** /**
Set the Facebook App ID to be used by the SDK. Set the Facebook App ID to be used by the SDK.
@param appID The Facebook App ID to be used by the SDK. - Parameter appID: The Facebook App ID to be used by the SDK.
*/ */
+ (void)setAppID:(NSString *)appID; + (void)setAppID:(NSString *)appID;
@ -80,7 +80,7 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
/** /**
Set the app url scheme suffix used by the SDK. Set the app url scheme suffix used by the SDK.
@param appURLSchemeSuffix The url scheme suffix to be used by the SDK. - Parameter appURLSchemeSuffix: The url scheme suffix to be used by the SDK.
*/ */
+ (void)setAppURLSchemeSuffix:(NSString *)appURLSchemeSuffix; + (void)setAppURLSchemeSuffix:(NSString *)appURLSchemeSuffix;
@ -95,14 +95,14 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
Sets the Client Token for the Facebook App. Sets the Client Token for the Facebook App.
This is needed for certain API calls when made anonymously, without a user-based access token. This is needed for certain API calls when made anonymously, without a user-based access token.
@param clientToken The Facebook App's "client token", which, for a given appid can be found in the Security - Parameter clientToken: The Facebook App's "client token", which, for a given appid can be found in the Security
section of the Advanced tab of the Facebook App settings found at <https://developers.facebook.com/apps/[your-app-id]> section of the Advanced tab of the Facebook App settings found at <https://developers.facebook.com/apps/[your-app-id]>
*/ */
+ (void)setClientToken:(NSString *)clientToken; + (void)setClientToken:(NSString *)clientToken;
/** /**
A convenient way to toggle error recovery for all FBSDKGraphRequest instances created after this is set. A convenient way to toggle error recovery for all FBSDKGraphRequest instances created after this is set.
@param disableGraphErrorRecovery YES or NO. - Parameter disableGraphErrorRecovery: YES or NO.
*/ */
+ (void)setGraphErrorRecoveryDisabled:(BOOL)disableGraphErrorRecovery; + (void)setGraphErrorRecoveryDisabled:(BOOL)disableGraphErrorRecovery;
@ -118,7 +118,7 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
This should match the Display Name that has been set for the app with the corresponding Facebook App ID, This should match the Display Name that has been set for the app with the corresponding Facebook App ID,
in the Facebook App Dashboard. in the Facebook App Dashboard.
@param displayName The Facebook Display Name to be used by the SDK. - Parameter displayName: The Facebook Display Name to be used by the SDK.
*/ */
+ (void)setDisplayName:(NSString *)displayName; + (void)setDisplayName:(NSString *)displayName;
@ -134,7 +134,7 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
This can be used to change the Facebook domain (e.g. @"beta") so that requests will be sent to This can be used to change the Facebook domain (e.g. @"beta") so that requests will be sent to
graph.beta.facebook.com graph.beta.facebook.com
@param facebookDomainPart The domain part to be inserted into facebook.com. - Parameter facebookDomainPart: The domain part to be inserted into facebook.com.
*/ */
+ (void)setFacebookDomainPart:(NSString *)facebookDomainPart; + (void)setFacebookDomainPart:(NSString *)facebookDomainPart;
@ -143,14 +143,14 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
If not explicitly set, the default is 0.9. If not explicitly set, the default is 0.9.
@see [UIImageJPEGRepresentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIImageJPEGRepresentation) */ - See:[UIImageJPEGRepresentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIImageJPEGRepresentation) */
+ (CGFloat)JPEGCompressionQuality; + (CGFloat)JPEGCompressionQuality;
/** /**
Set the quality of JPEG images sent to Facebook from the SDK. Set the quality of JPEG images sent to Facebook from the SDK.
@param JPEGCompressionQuality The quality for JPEG images, expressed as a value from 0.0 to 1.0. - Parameter JPEGCompressionQuality: The quality for JPEG images, expressed as a value from 0.0 to 1.0.
@see [UIImageJPEGRepresentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIImageJPEGRepresentation) */ - See:[UIImageJPEGRepresentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIImageJPEGRepresentation) */
+ (void)setJPEGCompressionQuality:(CGFloat)JPEGCompressionQuality; + (void)setJPEGCompressionQuality:(CGFloat)JPEGCompressionQuality;
/** /**
@ -161,22 +161,10 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
/** /**
Set the flag which controls the auto logging of basic app events, such as activateApp and deactivateApp. Set the flag which controls the auto logging of basic app events, such as activateApp and deactivateApp.
@param AutoLogAppEventsEnabled Flag value, expressed as a value from 0 - false or 1 - true. - Parameter AutoLogAppEventsEnabled: Flag value, expressed as a value from 0 - false or 1 - true.
*/ */
+ (void)setAutoLogAppEventsEnabled:(NSNumber *)AutoLogAppEventsEnabled; + (void)setAutoLogAppEventsEnabled:(NSNumber *)AutoLogAppEventsEnabled;
/**
Flag which controls the fb_codeless_debug logging event
If not explicitly set, the default is 1 - true
*/
+ (NSNumber *)codelessDebugLogEnabled;
/**
Set the flag which controls the fb_codeless_debug logging event
@param CodelessDebugLogEnabled Flag value, expressed as a value from 0 - false or 1 - true.
*/
+ (void)setCodelessDebugLogEnabled:(NSNumber *)CodelessDebugLogEnabled;
/** /**
Gets whether data such as that generated through FBSDKAppEvents and sent to Facebook should be restricted from being used for other than analytics and conversions. Defaults to NO. This value is stored on the device and persists across app launches. Gets whether data such as that generated through FBSDKAppEvents and sent to Facebook should be restricted from being used for other than analytics and conversions. Defaults to NO. This value is stored on the device and persists across app launches.
*/ */
@ -185,7 +173,7 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
/** /**
Sets whether data such as that generated through FBSDKAppEvents and sent to Facebook should be restricted from being used for other than analytics and conversions. Defaults to NO. This value is stored on the device and persists across app launches. Sets whether data such as that generated through FBSDKAppEvents and sent to Facebook should be restricted from being used for other than analytics and conversions. Defaults to NO. This value is stored on the device and persists across app launches.
@param limitEventAndDataUsage The desired value. - Parameter limitEventAndDataUsage: The desired value.
*/ */
+ (void)setLimitEventAndDataUsage:(BOOL)limitEventAndDataUsage; + (void)setLimitEventAndDataUsage:(BOOL)limitEventAndDataUsage;
@ -203,7 +191,7 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
Set the current Facebook SDK logging behavior. This should consist of strings defined as Set the current Facebook SDK logging behavior. This should consist of strings defined as
constants with FBSDKLoggingBehavior*. constants with FBSDKLoggingBehavior*.
@param loggingBehavior A set of strings indicating what information should be logged. If nil is provided, the logging - Parameter loggingBehavior: A set of strings indicating what information should be logged. If nil is provided, the logging
behavior is reset to the default set of enabled behaviors. Set to an empty set in order to disable all logging. behavior is reset to the default set of enabled behaviors. Set to an empty set in order to disable all logging.
@ -214,21 +202,21 @@ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors;
/** /**
Enable a particular Facebook SDK logging behavior. Enable a particular Facebook SDK logging behavior.
@param loggingBehavior The LoggingBehavior to enable. This should be a string defined as a constant with FBSDKLoggingBehavior*. - Parameter loggingBehavior: The LoggingBehavior to enable. This should be a string defined as a constant with FBSDKLoggingBehavior*.
*/ */
+ (void)enableLoggingBehavior:(NSString *)loggingBehavior; + (void)enableLoggingBehavior:(NSString *)loggingBehavior;
/** /**
Disable a particular Facebook SDK logging behavior. Disable a particular Facebook SDK logging behavior.
@param loggingBehavior The LoggingBehavior to disable. This should be a string defined as a constant with FBSDKLoggingBehavior*. - Parameter loggingBehavior: The LoggingBehavior to disable. This should be a string defined as a constant with FBSDKLoggingBehavior*.
*/ */
+ (void)disableLoggingBehavior:(NSString *)loggingBehavior; + (void)disableLoggingBehavior:(NSString *)loggingBehavior;
/** /**
Set the user defaults key used by legacy token caches. Set the user defaults key used by legacy token caches.
@param tokenInformationKeyName the key used by legacy token caches. - Parameter tokenInformationKeyName: the key used by legacy token caches.
Use this only if you customized FBSessionTokenCachingStrategy in v3.x of Use this only if you customized FBSessionTokenCachingStrategy in v3.x of

View File

@ -19,7 +19,6 @@
#import "FBSDKSettings+Internal.h" #import "FBSDKSettings+Internal.h"
#import "FBSDKAccessTokenCache.h" #import "FBSDKAccessTokenCache.h"
#import "FBSDKAccessTokenExpirer.h"
#import "FBSDKCoreKit.h" #import "FBSDKCoreKit.h"
#define FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL(TYPE, PLIST_KEY, GETTER, SETTER, DEFAULT_VALUE) \ #define FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL(TYPE, PLIST_KEY, GETTER, SETTER, DEFAULT_VALUE) \
@ -53,7 +52,6 @@ static NSString *const FBSDKSettingsLimitEventAndDataUsage = @"com.facebook.sdk:
static BOOL g_disableErrorRecovery; static BOOL g_disableErrorRecovery;
static NSString *g_userAgentSuffix; static NSString *g_userAgentSuffix;
static NSString *g_defaultGraphAPIVersion; static NSString *g_defaultGraphAPIVersion;
static FBSDKAccessTokenExpirer *g_accessTokenExpirer;
@implementation FBSDKSettings @implementation FBSDKSettings
@ -61,7 +59,6 @@ static FBSDKAccessTokenExpirer *g_accessTokenExpirer;
{ {
if (self == [FBSDKSettings class]) { if (self == [FBSDKSettings class]) {
g_tokenCache = [[FBSDKAccessTokenCache alloc] init]; g_tokenCache = [[FBSDKAccessTokenCache alloc] init];
g_accessTokenExpirer = [[FBSDKAccessTokenExpirer alloc] init];
} }
} }
@ -75,8 +72,6 @@ FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL(NSString, FacebookDomainPart, fac
FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL(NSNumber, FacebookJpegCompressionQuality, _JPEGCompressionQualityNumber, _setJPEGCompressionQualityNumber, @0.9); FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL(NSNumber, FacebookJpegCompressionQuality, _JPEGCompressionQualityNumber, _setJPEGCompressionQualityNumber, @0.9);
FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL(NSNumber, FacebookAutoLogAppEventsEnabled, autoLogAppEventsEnabled, FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL(NSNumber, FacebookAutoLogAppEventsEnabled, autoLogAppEventsEnabled,
setAutoLogAppEventsEnabled, @1); setAutoLogAppEventsEnabled, @1);
FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL(NSNumber, FacebookCodelessDebugLogEnabled, codelessDebugLogEnabled,
setCodelessDebugLogEnabled, @0);
+ (void)setGraphErrorRecoveryDisabled:(BOOL)disableGraphErrorRecovery { + (void)setGraphErrorRecoveryDisabled:(BOOL)disableGraphErrorRecovery {
g_disableErrorRecovery = disableGraphErrorRecovery; g_disableErrorRecovery = disableGraphErrorRecovery;

View File

@ -50,20 +50,20 @@ typedef void (^FBSDKTestUsersManagerRemoveTestAccountHandler)(NSError *error) ;
/** /**
construct or return the shared instance construct or return the shared instance
@param appID the Facebook app id - Parameter appID: the Facebook app id
@param appSecret the Facebook app secret - Parameter appSecret: the Facebook app secret
*/ */
+ (instancetype)sharedInstanceForAppID:(NSString *)appID appSecret:(NSString *)appSecret; + (instancetype)sharedInstanceForAppID:(NSString *)appID appSecret:(NSString *)appSecret;
/** /**
retrieve FBSDKAccessToken instances for test accounts with the specific permissions. retrieve FBSDKAccessToken instances for test accounts with the specific permissions.
@param arraysOfPermissions an array of permissions sets, such as @[ [NSSet setWithObject:@"email"], [NSSet setWithObject:@"user_birthday"]] - Parameter arraysOfPermissions: an array of permissions sets, such as @[ [NSSet setWithObject:@"email"], [NSSet setWithObject:@"user_birthday"]]
if you needed two test accounts with email and birthday permissions, respectively. You can pass in empty nested sets if you needed two test accounts with email and birthday permissions, respectively. You can pass in empty nested sets
if you need two arbitrary test accounts. For convenience, passing nil is treated as @[ [NSSet set] ] if you need two arbitrary test accounts. For convenience, passing nil is treated as @[ [NSSet set] ]
for fetching a single test user. for fetching a single test user.
@param createIfNotFound if YES, new test accounts are created if no test accounts existed that fit the permissions - Parameter createIfNotFound: if YES, new test accounts are created if no test accounts existed that fit the permissions
requirement requirement
@param handler the callback to invoke which will return an array of `FBAccessTokenData` instances or an `NSError`. - Parameter handler: the callback to invoke which will return an array of `FBAccessTokenData` instances or an `NSError`.
If param `createIfNotFound` is NO, the array may contain `[NSNull null]` instances. If param `createIfNotFound` is NO, the array may contain `[NSNull null]` instances.
@ -77,24 +77,24 @@ typedef void (^FBSDKTestUsersManagerRemoveTestAccountHandler)(NSError *error) ;
/** /**
add a test account with the specified permissions add a test account with the specified permissions
@param permissions the set of permissions, e.g., [NSSet setWithObjects:@"email", @"user_friends"] - Parameter permissions: the set of permissions, e.g., [NSSet setWithObjects:@"email", @"user_friends"]
@param handler the callback handler - Parameter handler: the callback handler
*/ */
- (void)addTestAccountWithPermissions:(NSSet *)permissions - (void)addTestAccountWithPermissions:(NSSet *)permissions
completionHandler:(FBSDKTestUsersManagerRetrieveTestAccountTokensHandler)handler; completionHandler:(FBSDKTestUsersManagerRetrieveTestAccountTokensHandler)handler;
/** /**
remove a test account for the given user id remove a test account for the given user id
@param userId the user id - Parameter userId: the user id
@param handler the callback handler - Parameter handler: the callback handler
*/ */
- (void)removeTestAccount:(NSString *)userId completionHandler:(FBSDKTestUsersManagerRemoveTestAccountHandler)handler; - (void)removeTestAccount:(NSString *)userId completionHandler:(FBSDKTestUsersManagerRemoveTestAccountHandler)handler;
/** /**
Make two test users friends with each other. Make two test users friends with each other.
@param first the token of the first user - Parameter first: the token of the first user
@param second the token of the second user - Parameter second: the token of the second user
@param callback the callback handler - Parameter callback: the callback handler
*/ */
- (void)makeFriendsWithFirst:(FBSDKAccessToken *)first second:(FBSDKAccessToken *)second callback:(void (^)(NSError *))callback; - (void)makeFriendsWithFirst:(FBSDKAccessToken *)first second:(FBSDKAccessToken *)second callback:(void (^)(NSError *))callback;

View File

@ -149,7 +149,7 @@ static NSMutableDictionary *gInstancesDictionary;
NSMutableDictionary *accountData = [NSMutableDictionary dictionaryWithCapacity:2]; NSMutableDictionary *accountData = [NSMutableDictionary dictionaryWithCapacity:2];
accountData[kAccountsDictionaryPermissionsKey] = [NSSet setWithSet:permissions]; accountData[kAccountsDictionaryPermissionsKey] = [NSSet setWithSet:permissions];
accountData[kAccountsDictionaryTokenKey] = result[@"access_token"]; accountData[kAccountsDictionaryTokenKey] = result[@"access_token"];
self->_accounts[result[@"id"]] = accountData; _accounts[result[@"id"]] = accountData;
if (handler) { if (handler) {
FBSDKAccessToken *token = [self tokenDataForTokenString:accountData[kAccountsDictionaryTokenKey] FBSDKAccessToken *token = [self tokenDataForTokenString:accountData[kAccountsDictionaryTokenKey]
@ -216,8 +216,7 @@ static NSMutableDictionary *gInstancesDictionary;
appID:_appID appID:_appID
userID:userId userID:userId
expirationDate:nil expirationDate:nil
refreshDate:nil refreshDate:nil];
dataAccessExpirationDate:nil];
} }
- (NSArray *)userIdAndTokenOfExistingAccountWithPermissions:(NSSet *)permissions skip:(NSSet *)setToSkip { - (NSArray *)userIdAndTokenOfExistingAccountWithPermissions:(NSSet *)permissions skip:(NSSet *)setToSkip {
@ -265,15 +264,15 @@ static NSMutableDictionary *gInstancesDictionary;
handler(error); handler(error);
} }
// on errors, clear out accounts since it may be in a bad state // on errors, clear out accounts since it may be in a bad state
[self->_accounts removeAllObjects]; [_accounts removeAllObjects];
return; return;
} else { } else {
for (NSDictionary *account in result[@"data"]) { for (NSDictionary *account in result[@"data"]) {
NSString *userId = account[@"id"]; NSString *userId = account[@"id"];
NSString *token = account[@"access_token"]; NSString *token = account[@"access_token"];
if (userId && token) { if (userId && token) {
self->_accounts[userId] = [NSMutableDictionary dictionaryWithCapacity:2]; _accounts[userId] = [NSMutableDictionary dictionaryWithCapacity:2];
self->_accounts[userId][kAccountsDictionaryTokenKey] = token; _accounts[userId][kAccountsDictionaryTokenKey] = token;
expectedTestAccounts++; expectedTestAccounts++;
[permissionConnection addRequest:[[FBSDKGraphRequest alloc] initWithGraphPath:[NSString stringWithFormat:@"%@?fields=permissions", userId] [permissionConnection addRequest:[[FBSDKGraphRequest alloc] initWithGraphPath:[NSString stringWithFormat:@"%@?fields=permissions", userId]
parameters:nil parameters:nil
@ -281,7 +280,7 @@ static NSMutableDictionary *gInstancesDictionary;
version:nil version:nil
HTTPMethod:nil] HTTPMethod:nil]
completionHandler:^(FBSDKGraphRequestConnection *innerConnection2, id innerResult, NSError *innerError) { completionHandler:^(FBSDKGraphRequestConnection *innerConnection2, id innerResult, NSError *innerError) {
if (self->_accounts.count == 0) { if (_accounts.count == 0) {
// indicates an earlier error that was already passed to handler, so just short circuit. // indicates an earlier error that was already passed to handler, so just short circuit.
return; return;
} }
@ -289,7 +288,7 @@ static NSMutableDictionary *gInstancesDictionary;
if (handler) { if (handler) {
handler(innerError); handler(innerError);
} }
[self->_accounts removeAllObjects]; [_accounts removeAllObjects];
return; return;
} else { } else {
NSMutableSet *grantedPermissions = [NSMutableSet set]; NSMutableSet *grantedPermissions = [NSMutableSet set];
@ -299,7 +298,7 @@ static NSMutableDictionary *gInstancesDictionary;
[grantedPermissions addObject:obj[@"permission"]]; [grantedPermissions addObject:obj[@"permission"]];
} }
}]; }];
self->_accounts[userId][kAccountsDictionaryPermissionsKey] = grantedPermissions; _accounts[userId][kAccountsDictionaryPermissionsKey] = grantedPermissions;
} }
expectedTestAccounts--; expectedTestAccounts--;
if (!expectedTestAccounts) { if (!expectedTestAccounts) {

View File

@ -1,87 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class FBSDKAppLink;
/*!
Provides a set of utilities for working with NSURLs, such as parsing of query parameters
and handling for App Link requests.
*/
@interface FBSDKURL : NSObject
/*!
Creates a link target from a raw URL.
On success, this posts the FBSDKAppLinkParseEventName measurement event. If you are constructing the FBSDKURL within your application delegate's
application:openURL:sourceApplication:annotation:, you should instead use URLWithInboundURL:sourceApplication:
to support better FBSDKMeasurementEvent notifications
@param url The instance of `NSURL` to create FBSDKURL from.
*/
+ (FBSDKURL *)URLWithURL:(NSURL *)url;
/*!
Creates a link target from a raw URL received from an external application. This is typically called from the app delegate's
application:openURL:sourceApplication:annotation: and will post the FBSDKAppLinkNavigateInEventName measurement event.
@param url The instance of `NSURL` to create FBSDKURL from.
@param sourceApplication the bundle ID of the app that is requesting your app to open the URL. The same sourceApplication in application:openURL:sourceApplication:annotation:
*/
+ (FBSDKURL *)URLWithInboundURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication;
/*!
Gets the target URL. If the link is an App Link, this is the target of the App Link.
Otherwise, it is the url that created the target.
*/
@property (nonatomic, strong, readonly) NSURL *targetURL;
/*!
Gets the query parameters for the target, parsed into an NSDictionary.
*/
@property (nonatomic, strong, readonly) NSDictionary<NSString *, id> *targetQueryParameters;
/*!
If this link target is an App Link, this is the data found in al_applink_data.
Otherwise, it is nil.
*/
@property (nonatomic, strong, readonly) NSDictionary<NSString *, id> *appLinkData;
/*!
If this link target is an App Link, this is the data found in extras.
*/
@property (nonatomic, strong, readonly) NSDictionary<NSString *, id> *appLinkExtras;
/*!
The App Link indicating how to navigate back to the referer app, if any.
*/
@property (nonatomic, strong, readonly) FBSDKAppLink *appLinkReferer;
/*!
The URL that was used to create this FBSDKURL.
*/
@property (nonatomic, strong, readonly) NSURL *inputURL;
/*!
The query parameters of the inputURL, parsed into an NSDictionary.
*/
@property (nonatomic, strong, readonly) NSDictionary<NSString *, id> *inputQueryParameters;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,152 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKURL_Internal.h"
#import "FBSDKAppLinkTarget.h"
#import "FBSDKAppLink_Internal.h"
#import "FBSDKMeasurementEvent_Internal.h"
@implementation FBSDKURL
- (instancetype)initWithURL:(NSURL *)url forOpenInboundURL:(BOOL)forOpenURLEvent sourceApplication:(NSString *)sourceApplication forRenderBackToReferrerBar:(BOOL)forRenderBackToReferrerBar {
self = [super init];
if (!self) return nil;
_inputURL = url;
_targetURL = url;
// Parse the query string parameters for the base URL
NSDictionary<NSString *, id> *baseQuery = [FBSDKURL queryParametersForURL:url];
_inputQueryParameters = baseQuery;
_targetQueryParameters = baseQuery;
// Check for applink_data
NSString *appLinkDataString = baseQuery[FBSDKAppLinkDataParameterName];
if (appLinkDataString) {
// Try to parse the JSON
NSError *error = nil;
NSDictionary<NSString *, id> *applinkData =
[NSJSONSerialization JSONObjectWithData:[appLinkDataString dataUsingEncoding:NSUTF8StringEncoding]
options:0
error:&error];
if (!error && [applinkData isKindOfClass:[NSDictionary class]]) {
// If the version is not specified, assume it is 1.
NSString *version = applinkData[FBSDKAppLinkVersionKeyName] ?: @"1.0";
NSString *target = applinkData[FBSDKAppLinkTargetKeyName];
if ([version isKindOfClass:[NSString class]] &&
[version isEqual:FBSDKAppLinkVersion]) {
// There's applink data! The target should actually be the applink target.
_appLinkData = applinkData;
id applinkExtras = applinkData[FBSDKAppLinkExtrasKeyName];
if (applinkExtras && [applinkExtras isKindOfClass:[NSDictionary class]]) {
_appLinkExtras = applinkExtras;
}
_targetURL = ([target isKindOfClass:[NSString class]] ? [NSURL URLWithString:target] : url);
_targetQueryParameters = [FBSDKURL queryParametersForURL:_targetURL];
NSDictionary<NSString *, id> *refererAppLink = _appLinkData[FBSDKAppLinkRefererAppLink];
NSString *refererURLString = refererAppLink[FBSDKAppLinkRefererUrl];
NSString *refererAppName = refererAppLink[FBSDKAppLinkRefererAppName];
if (refererURLString && refererAppName) {
FBSDKAppLinkTarget *appLinkTarget = [FBSDKAppLinkTarget appLinkTargetWithURL:[NSURL URLWithString:refererURLString]
appStoreId:nil
appName:refererAppName];
_appLinkReferer = [FBSDKAppLink appLinkWithSourceURL:[NSURL URLWithString:refererURLString]
targets:@[ appLinkTarget ]
webURL:nil
isBackToReferrer:YES];
}
// Raise Measurement Event
NSString *const EVENT_YES_VAL = @"1";
NSString *const EVENT_NO_VAL = @"0";
NSMutableDictionary<NSString *, id> *logData = [[NSMutableDictionary alloc] init];
logData[@"version"] = version;
if (refererURLString) {
logData[@"refererURL"] = refererURLString;
}
if (refererAppName) {
logData[@"refererAppName"] = refererAppName;
}
if (sourceApplication) {
logData[@"sourceApplication"] = sourceApplication;
}
if ([_targetURL absoluteString]) {
logData[@"targetURL"] = [_targetURL absoluteString];
}
if ([_inputURL absoluteString]) {
logData[@"inputURL"] = [_inputURL absoluteString];
}
if ([_inputURL scheme]) {
logData[@"inputURLScheme"] = [_inputURL scheme];
}
logData[@"forRenderBackToReferrerBar"] = forRenderBackToReferrerBar ? EVENT_YES_VAL : EVENT_NO_VAL;
logData[@"forOpenUrl"] = forOpenURLEvent ? EVENT_YES_VAL : EVENT_NO_VAL;
[FBSDKMeasurementEvent postNotificationForEventName:FBSDKAppLinkParseEventName args:logData];
if (forOpenURLEvent) {
[FBSDKMeasurementEvent postNotificationForEventName:FBSDKAppLinkNavigateInEventName args:logData];
}
}
}
}
return self;
}
+ (FBSDKURL *)URLWithURL:(NSURL *)url {
return [[FBSDKURL alloc] initWithURL:url forOpenInboundURL:NO sourceApplication:nil forRenderBackToReferrerBar:NO];
}
+ (FBSDKURL *)URLWithInboundURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication {
return [[FBSDKURL alloc] initWithURL:url forOpenInboundURL:YES sourceApplication:sourceApplication forRenderBackToReferrerBar:NO];
}
+ (FBSDKURL *)URLForRenderBackToReferrerBarURL:(NSURL *)url {
return [[FBSDKURL alloc] initWithURL:url forOpenInboundURL:NO sourceApplication:nil forRenderBackToReferrerBar:YES];
}
+ (NSString *)decodeURLString:(NSString *)string {
return (NSString *)CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapes(NULL,
(CFStringRef)string,
CFSTR("")));
}
+ (NSDictionary<NSString *, id> *)queryParametersForURL:(NSURL *)url {
NSMutableDictionary<NSString *, id> *parameters = [NSMutableDictionary dictionary];
NSString *query = url.query;
if ([query isEqualToString:@""]) {
return @{};
}
NSArray<NSString *> *queryComponents = [query componentsSeparatedByString:@"&"];
for (NSString *component in queryComponents) {
NSRange equalsLocation = [component rangeOfString:@"="];
if (equalsLocation.location == NSNotFound) {
// There's no equals, so associate the key with NSNull
parameters[[self decodeURLString:component]] = [NSNull null];
} else {
NSString *key = [self decodeURLString:[component substringToIndex:equalsLocation.location]];
NSString *value = [self decodeURLString:[component substringFromIndex:equalsLocation.location + 1]];
parameters[key] = value;
}
}
return [NSDictionary dictionaryWithDictionary:parameters];
}
@end

View File

@ -25,52 +25,31 @@
/** /**
Parses a query string into a dictionary. Parses a query string into a dictionary.
@param queryString The query string value. - Parameter queryString: The query string value.
@return A dictionary with the key/value pairs. - Returns: A dictionary with the key/value pairs.
*/ */
+ (NSDictionary *)dictionaryWithQueryString:(NSString *)queryString; + (NSDictionary *)dictionaryWithQueryString:(NSString *)queryString;
/** /**
Constructs a query string from a dictionary. Constructs a query string from a dictionary.
@param dictionary The dictionary with key/value pairs for the query string. - Parameter dictionary: The dictionary with key/value pairs for the query string.
@param errorRef If an error occurs, upon return contains an NSError object that describes the problem. - Parameter errorRef: If an error occurs, upon return contains an NSError object that describes the problem.
@return Query string representation of the parameters. - Returns: Query string representation of the parameters.
*/ */
+ (NSString *)queryStringWithDictionary:(NSDictionary *)dictionary error:(NSError *__autoreleasing *)errorRef; + (NSString *)queryStringWithDictionary:(NSDictionary *)dictionary error:(NSError *__autoreleasing *)errorRef;
/** /**
Decodes a value from an URL. Decodes a value from an URL.
@param value The value to decode. - Parameter value: The value to decode.
@return The decoded value. - Returns: The decoded value.
*/ */
+ (NSString *)URLDecode:(NSString *)value; + (NSString *)URLDecode:(NSString *)value;
/** /**
Encodes a value for an URL. Encodes a value for an URL.
@param value The value to encode. - Parameter value: The value to encode.
@return The encoded value. - Returns: The encoded value.
*/ */
+ (NSString *)URLEncode:(NSString *)value; + (NSString *)URLEncode:(NSString *)value;
/**
Creates a timer using Grand Central Dispatch.
@param interval The interval to fire the timer, in seconds.
@param block The code block to execute when timer is fired.
@return The dispatch handle.
*/
+ (dispatch_source_t)startGCDTimerWithInterval:(double)interval block:(dispatch_block_t)block;
/**
Stop a timer that was started by startGCDTimerWithInterval.
@param timer The dispatch handle received from startGCDTimerWithInterval.
*/
+ (void)stopGCDTimer:(dispatch_source_t)timer;
/**
Get SHA256 hased string of NSString/NSData
@param input The data that needs to be hashed, it could be NSString or NSData.
*/
+ (NSString *)SHA256Hash:(NSObject *)input;
@end @end

View File

@ -18,8 +18,6 @@
#import "FBSDKUtility.h" #import "FBSDKUtility.h"
#import <CommonCrypto/CommonDigest.h>
#import "FBSDKInternalUtility.h" #import "FBSDKInternalUtility.h"
#import "FBSDKMacros.h" #import "FBSDKMacros.h"
@ -83,56 +81,6 @@
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop
+ (dispatch_source_t)startGCDTimerWithInterval:(double)interval block:(dispatch_block_t)block
{
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, // source type
0, // handle
0, // mask
dispatch_get_main_queue()); // queue
dispatch_source_set_timer(timer, // dispatch source
dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), // start
interval * NSEC_PER_SEC, // interval
0 * NSEC_PER_SEC); // leeway
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
return timer;
}
+ (void)stopGCDTimer:(dispatch_source_t)timer
{
if (timer) {
dispatch_source_cancel(timer);
}
}
+ (NSString *)SHA256Hash:(NSObject *)input
{
NSData *data = nil;
if ([input isKindOfClass:[NSString class]]) {
data = [(NSString *)input dataUsingEncoding:NSUTF8StringEncoding];
} else if ([input isKindOfClass:[NSData class]]) {
data = (NSData *)input;
}
if (!data) {
return nil;
}
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
NSMutableString *encryptedStuff = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[encryptedStuff appendFormat:@"%02x", digest[i]];
}
return encryptedStuff;
}
- (instancetype)init - (instancetype)init
{ {
FBSDK_NO_DESIGNATED_INITIALIZER(); FBSDK_NO_DESIGNATED_INITIALIZER();

View File

@ -1,38 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import "FBSDKAppLinkResolving.h"
NS_ASSUME_NONNULL_BEGIN
/*!
A reference implementation for an App Link resolver that uses a hidden UIWebView
to parse the HTML containing App Link metadata.
*/
@interface FBSDKWebViewAppLinkResolver : NSObject <FBSDKAppLinkResolving>
/*!
Gets the instance of a FBSDKWebViewAppLinkResolver.
*/
+ (instancetype)sharedInstance;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,308 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKWebViewAppLinkResolver.h"
#import <UIKit/UIKit.h>
#import "FBSDKAppLink.h"
#import "FBSDKAppLinkTarget.h"
/**
Describes the callback for appLinkFromURLInBackground.
@param result the results from following redirects
@param error the error during the request, if any
*/
typedef void (^FBSDKURLFollowRedirectsHandler)(NSDictionary<NSString *, id> *result, NSError * _Nullable error);
// Defines JavaScript to extract app link tags from HTML content
static NSString *const FBSDKWebViewAppLinkResolverTagExtractionJavaScript = @""
"(function() {"
" var metaTags = document.getElementsByTagName('meta');"
" var results = [];"
" for (var i = 0; i < metaTags.length; i++) {"
" var property = metaTags[i].getAttribute('property');"
" if (property && property.substring(0, 'al:'.length) === 'al:') {"
" var tag = { \"property\": metaTags[i].getAttribute('property') };"
" if (metaTags[i].hasAttribute('content')) {"
" tag['content'] = metaTags[i].getAttribute('content');"
" }"
" results.push(tag);"
" }"
" }"
" return JSON.stringify(results);"
"})()";
static NSString *const FBSDKWebViewAppLinkResolverIOSURLKey = @"url";
static NSString *const FBSDKWebViewAppLinkResolverIOSAppStoreIdKey = @"app_store_id";
static NSString *const FBSDKWebViewAppLinkResolverIOSAppNameKey = @"app_name";
static NSString *const FBSDKWebViewAppLinkResolverDictionaryValueKey = @"_value";
static NSString *const FBSDKWebViewAppLinkResolverPreferHeader = @"Prefer-Html-Meta-Tags";
static NSString *const FBSDKWebViewAppLinkResolverMetaTagPrefix = @"al";
static NSString *const FBSDKWebViewAppLinkResolverWebKey = @"web";
static NSString *const FBSDKWebViewAppLinkResolverIOSKey = @"ios";
static NSString *const FBSDKWebViewAppLinkResolverIPhoneKey = @"iphone";
static NSString *const FBSDKWebViewAppLinkResolverIPadKey = @"ipad";
static NSString *const FBSDKWebViewAppLinkResolverWebURLKey = @"url";
static NSString *const FBSDKWebViewAppLinkResolverShouldFallbackKey = @"should_fallback";
@interface FBSDKWebViewAppLinkResolverWebViewDelegate : NSObject <UIWebViewDelegate>
@property (nonatomic, copy) void (^didFinishLoad)(UIWebView *webView);
@property (nonatomic, copy) void (^didFailLoadWithError)(UIWebView *webView, NSError *error);
@property (nonatomic, assign) BOOL hasLoaded;
@end
@implementation FBSDKWebViewAppLinkResolverWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if (self.didFinishLoad) {
self.didFinishLoad(webView);
}
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
if (self.didFailLoadWithError) {
self.didFailLoadWithError(webView, error);
}
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (self.hasLoaded) {
// Consider loading a second resource to be "success", since it indicates an inner frame
// or redirect is happening. We can run the tag extraction script at this point.
self.didFinishLoad(webView);
return NO;
}
self.hasLoaded = YES;
return YES;
}
@end
@implementation FBSDKWebViewAppLinkResolver
+ (instancetype)sharedInstance {
static id instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (void)followRedirects:(NSURL *)url handler:(FBSDKURLFollowRedirectsHandler)handler
{
// This task will be resolved with either the redirect NSURL
// or a dictionary with the response data to be returned.
void (^completion)(NSURLResponse *response, NSData *data, NSError *error) = ^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
handler(nil, error);
return;
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
// NSURLConnection usually follows redirects automatically, but the
// documentation is unclear what the default is. This helps it along.
if (httpResponse.statusCode >= 300 && httpResponse.statusCode < 400) {
NSString *redirectString = httpResponse.allHeaderFields[@"Location"];
NSURL *redirectURL = [NSURL URLWithString:redirectString];
[self followRedirects:redirectURL handler:handler];
return;
}
}
handler(@{ @"response" : response, @"data" : data }, nil);
};
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:FBSDKWebViewAppLinkResolverMetaTagPrefix forHTTPHeaderField:FBSDKWebViewAppLinkResolverPreferHeader];
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0 || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_9
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
completion(response, data, error);
}] resume];
#else
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:completion];
#endif
}
- (void)appLinkFromURL:(NSURL *)url handler:(FBSDKAppLinkFromURLHandler)handler
{
dispatch_async(dispatch_get_main_queue(), ^{
[self followRedirects:url handler:^(NSDictionary<NSString *,id> *result, NSError * _Nullable error) {
if (error) {
handler(nil, error);
return;
}
NSData *responseData = result[@"data"];
NSHTTPURLResponse *response = result[@"response"];
UIWebView *webView = [[UIWebView alloc] init];
FBSDKWebViewAppLinkResolverWebViewDelegate *listener = [[FBSDKWebViewAppLinkResolverWebViewDelegate alloc] init];
__block FBSDKWebViewAppLinkResolverWebViewDelegate *retainedListener = listener;
listener.didFinishLoad = ^(UIWebView *view) {
if (retainedListener) {
NSDictionary<NSString *, id> *ogData = [self getALDataFromLoadedPage:view];
[view removeFromSuperview];
view.delegate = nil;
retainedListener = nil;
handler([self appLinkFromALData:ogData destination:url], nil);
}
};
listener.didFailLoadWithError = ^(UIWebView* view, NSError *loadError) {
if (retainedListener) {
[view removeFromSuperview];
view.delegate = nil;
retainedListener = nil;
handler(nil, loadError);
}
};
webView.delegate = listener;
webView.hidden = YES;
[webView loadData:responseData
MIMEType:response.MIMEType
textEncodingName:response.textEncodingName
baseURL:response.URL];
UIWindow *window = [UIApplication sharedApplication].windows.firstObject;
[window addSubview:webView];
}];
});
}
/*
Builds up a data structure filled with the app link data from the meta tags on a page.
The structure of this object is a dictionary where each key holds an array of app link
data dictionaries. Values are stored in a key called "_value".
*/
- (NSDictionary<NSString *, id> *)parseALData:(NSArray<NSDictionary<NSString *, id> *> *)dataArray {
NSMutableDictionary<NSString *, id> *al = [NSMutableDictionary dictionary];
for (NSDictionary<NSString *, id> *tag in dataArray) {
NSString *name = tag[@"property"];
if (![name isKindOfClass:[NSString class]]) {
continue;
}
NSArray<NSString *> *nameComponents = [name componentsSeparatedByString:@":"];
if (![nameComponents[0] isEqualToString:FBSDKWebViewAppLinkResolverMetaTagPrefix]) {
continue;
}
NSMutableDictionary<NSString *, id> *root = al;
for (NSUInteger i = 1; i < nameComponents.count; i++) {
NSMutableArray<NSMutableDictionary<NSString *, id> *> *children = root[nameComponents[i]];
if (!children) {
children = [NSMutableArray array];
root[nameComponents[i]] = children;
}
NSMutableDictionary<NSString *, id> *child = children.lastObject;
if (!child || i == nameComponents.count - 1) {
child = [NSMutableDictionary dictionary];
[children addObject:child];
}
root = child;
}
if (tag[@"content"]) {
root[FBSDKWebViewAppLinkResolverDictionaryValueKey] = tag[@"content"];
}
}
return al;
}
- (NSDictionary<NSString *, id> *)getALDataFromLoadedPage:(UIWebView *)webView {
// Run some JavaScript in the webview to fetch the meta tags.
NSString *jsonString = [webView stringByEvaluatingJavaScriptFromString:FBSDKWebViewAppLinkResolverTagExtractionJavaScript];
NSError *error = nil;
NSArray<NSDictionary<NSString *, id> *> *arr =
[NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]
options:0
error:&error];
return [self parseALData:arr];
}
/*
Converts app link data into a FBSDKAppLink containing the targets relevant for this platform.
*/
- (FBSDKAppLink *)appLinkFromALData:(NSDictionary<NSString *, id> *)appLinkDict destination:(NSURL *)destination {
NSMutableArray<FBSDKAppLinkTarget *> *linkTargets = [NSMutableArray array];
NSArray *platformData = nil;
const UIUserInterfaceIdiom idiom = UI_USER_INTERFACE_IDIOM();
if (idiom == UIUserInterfaceIdiomPad) {
platformData = @[ appLinkDict[FBSDKWebViewAppLinkResolverIPadKey] ?: @{},
appLinkDict[FBSDKWebViewAppLinkResolverIOSKey] ?: @{} ];
} else if (idiom == UIUserInterfaceIdiomPhone) {
platformData = @[ appLinkDict[FBSDKWebViewAppLinkResolverIPhoneKey] ?: @{},
appLinkDict[FBSDKWebViewAppLinkResolverIOSKey] ?: @{} ];
} else {
// Future-proofing. Other User Interface idioms should only hit ios.
platformData = @[ appLinkDict[FBSDKWebViewAppLinkResolverIOSKey] ?: @{} ];
}
for (NSArray<NSDictionary *> *platformObjects in platformData) {
for (NSDictionary<NSString *, NSArray *> *platformDict in platformObjects) {
// The schema requires a single url/app store id/app name,
// but we could find multiple of them. We'll make a best effort
// to interpret this data.
NSArray<NSDictionary<NSString *, id> *> *urls = platformDict[FBSDKWebViewAppLinkResolverIOSURLKey];
NSArray<NSDictionary<NSString *, id> *> *appStoreIds = platformDict[FBSDKWebViewAppLinkResolverIOSAppStoreIdKey];
NSArray<NSDictionary<NSString *, id> *> *appNames = platformDict[FBSDKWebViewAppLinkResolverIOSAppNameKey];
NSUInteger maxCount = MAX(urls.count, MAX(appStoreIds.count, appNames.count));
for (NSUInteger i = 0; i < maxCount; i++) {
NSString *urlString = urls[i][FBSDKWebViewAppLinkResolverDictionaryValueKey];
NSURL *url = urlString ? [NSURL URLWithString:urlString] : nil;
NSString *appStoreId = appStoreIds[i][FBSDKWebViewAppLinkResolverDictionaryValueKey];
NSString *appName = appNames[i][FBSDKWebViewAppLinkResolverDictionaryValueKey];
FBSDKAppLinkTarget *target = [FBSDKAppLinkTarget appLinkTargetWithURL:url
appStoreId:appStoreId
appName:appName];
[linkTargets addObject:target];
}
}
}
NSDictionary<NSString *, id> *webDict = appLinkDict[FBSDKWebViewAppLinkResolverWebKey][0];
NSString *webUrlString = webDict[FBSDKWebViewAppLinkResolverWebURLKey][0][FBSDKWebViewAppLinkResolverDictionaryValueKey];
NSString *shouldFallbackString = webDict[FBSDKWebViewAppLinkResolverShouldFallbackKey][0][FBSDKWebViewAppLinkResolverDictionaryValueKey];
NSURL *webUrl = destination;
if (shouldFallbackString &&
[@[ @"no", @"false", @"0" ] containsObject:[shouldFallbackString lowercaseString]]) {
webUrl = nil;
}
if (webUrl && webUrlString) {
webUrl = [NSURL URLWithString:webUrlString];
}
return [FBSDKAppLink appLinkWithSourceURL:destination
targets:linkTargets
webURL:webUrl];
}
@end

View File

@ -1,48 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef FBSDKCodelessMacros_h
#define FBSDKCodelessMacros_h
// keys for event binding path compoenent
#define CODELESS_MAPPING_METHOD_KEY @"method"
#define CODELESS_MAPPING_EVENT_NAME_KEY @"event_name"
#define CODELESS_MAPPING_EVENT_TYPE_KEY @"event_type"
#define CODELESS_MAPPING_APP_VERSION_KEY @"app_version"
#define CODELESS_MAPPING_PATH_KEY @"path"
#define CODELESS_MAPPING_PATH_TYPE_KEY @"path_type"
#define CODELESS_MAPPING_CLASS_NAME_KEY @"class_name"
#define CODELESS_MAPPING_MATCH_BITMASK_KEY @"match_bitmask"
#define CODELESS_MAPPING_ID_KEY @"id"
#define CODELESS_MAPPING_INDEX_KEY @"index"
#define CODELESS_MAPPING_SECTION_KEY @"section"
#define CODELESS_MAPPING_ROW_KEY @"row"
#define CODELESS_MAPPING_TEXT_KEY @"text"
#define CODELESS_MAPPING_TAG_KEY @"tag"
#define CODELESS_MAPPING_DESC_KEY @"description"
#define CODELESS_MAPPING_HINT_KEY @"hint"
#define CODELESS_MAPPING_PARAMETERS_KEY @"parameters"
#define CODELESS_MAPPING_PARAMETER_NAME_KEY @"name"
#define CODELESS_MAPPING_PARAMETER_VALUE_KEY @"value"
#define CODELESS_MAPPING_PARENT_CLASS_NAME @".."
#define CODELESS_MAPPING_CURRENT_CLASS_NAME @"."
#define ReactNativeClassRCTView @"RCTView"
#define ReactNativeClassRCTRootView @"RCTRootView"
#endif /* FBSDKCodelessMacros_h */

View File

@ -1,30 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
@interface FBSDKCodelessParameterComponent : NSObject
@property (nonatomic, copy, readonly) NSString *name;
@property (nonatomic, copy, readonly) NSString *value;
@property (nonatomic, readonly) NSArray *path;
@property (nonatomic, copy, readonly) NSString *pathType;
- (instancetype)initWithJSON:(NSDictionary *)dict;
@end

View File

@ -1,45 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKCodelessParameterComponent.h"
#import "FBSDKCodelessMacros.h"
#import "FBSDKCodelessPathComponent.h"
@implementation FBSDKCodelessParameterComponent
- (instancetype)initWithJSON:(NSDictionary *)dict {
if (self = [super init]) {
_name = [[dict objectForKey:CODELESS_MAPPING_PARAMETER_NAME_KEY] copy];
_value = [[dict objectForKey:CODELESS_MAPPING_PARAMETER_VALUE_KEY] copy];
_pathType = [[dict objectForKey:CODELESS_MAPPING_PATH_TYPE_KEY] copy];
NSArray *ary = [dict objectForKey:CODELESS_MAPPING_PATH_KEY];
NSMutableArray *mut = [NSMutableArray array];
for (NSDictionary *info in ary) {
FBSDKCodelessPathComponent *component = [[FBSDKCodelessPathComponent alloc]
initWithJSON:info];
[mut addObject:component];
}
_path = [mut copy];
}
return self;
}
@end

View File

@ -1,44 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
typedef NS_OPTIONS(int, FBSDKCodelessMatchBitmaskField)
{
FBSDKCodelessMatchBitmaskFieldID = 1,
FBSDKCodelessMatchBitmaskFieldText = 1 << 1,
FBSDKCodelessMatchBitmaskFieldTag = 1 << 2,
FBSDKCodelessMatchBitmaskFieldDescription = 1 << 3,
FBSDKCodelessMatchBitmaskFieldHint = 1 << 4
};
@interface FBSDKCodelessPathComponent : NSObject
@property (nonatomic, copy, readonly) NSString *className;
@property (nonatomic, copy, readonly) NSString *text;
@property (nonatomic, copy, readonly) NSString *hint;
@property (nonatomic, copy, readonly) NSString *desc; // description
@property (nonatomic, readonly) int index;
@property (nonatomic, readonly) int tag;
@property (nonatomic, readonly) int section;
@property (nonatomic, readonly) int row;
@property (nonatomic, readonly) int matchBitmask;
- (instancetype)initWithJSON:(NSDictionary*)dict;
@end

View File

@ -1,58 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKCodelessPathComponent.h"
#import "FBSDKCodelessMacros.h"
@implementation FBSDKCodelessPathComponent
- (instancetype)initWithJSON:(NSDictionary *)dict {
if (self = [super init]) {
_className = [[dict objectForKey:CODELESS_MAPPING_CLASS_NAME_KEY] copy];
_text = [[dict objectForKey:CODELESS_MAPPING_TEXT_KEY] copy];
_hint = [[dict objectForKey:CODELESS_MAPPING_HINT_KEY] copy];
_desc = [[dict objectForKey:CODELESS_MAPPING_DESC_KEY] copy];
if ([dict objectForKey:CODELESS_MAPPING_INDEX_KEY]) {
_index = [[dict objectForKey:CODELESS_MAPPING_INDEX_KEY] intValue];
} else {
_index = -1;
}
if ([dict objectForKey:CODELESS_MAPPING_SECTION_KEY]) {
_section = [[dict objectForKey:CODELESS_MAPPING_SECTION_KEY] intValue];
} else {
_section = -1;
}
if ([dict objectForKey:CODELESS_MAPPING_ROW_KEY]) {
_row = [[dict objectForKey:CODELESS_MAPPING_ROW_KEY] intValue];
} else {
_row = -1;
}
_tag = [[dict objectForKey:CODELESS_MAPPING_TAG_KEY] intValue];
_matchBitmask = [[dict objectForKey:CODELESS_MAPPING_MATCH_BITMASK_KEY] intValue];
}
return self;
}
@end

View File

@ -1,37 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface FBSDKEventBinding : NSObject
@property (nonatomic, copy, readonly) NSString *eventName;
@property (nonatomic, copy, readonly) NSString *eventType;
@property (nonatomic, copy, readonly) NSString *appVersion;
@property (nonatomic, readonly) NSArray *path;
@property (nonatomic, copy, readonly) NSString *pathType;
@property (nonatomic, readonly) NSArray *parameters;
+ (BOOL)isViewMatchPath:(UIView *)view path:(NSArray *)path;
+ (BOOL)isPath:(NSArray *)path matchViewPath:(NSArray *)viewPath;
- (FBSDKEventBinding *)initWithJSON:(NSDictionary *)dict;
- (void)trackEvent:(id)sender;
@end

View File

@ -1,276 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKEventBinding.h"
#import <FBSDKCoreKit/FBSDKAppEvents.h>
#import "FBSDKAppEventsUtility.h"
#import "FBSDKCodelessMacros.h"
#import "FBSDKCodelessParameterComponent.h"
#import "FBSDKCodelessPathComponent.h"
#import "FBSDKSwizzler.h"
#import "FBSDKViewHierarchy.h"
#define CODELESS_PATH_TYPE_ABSOLUTE @"absolute"
#define CODELESS_PATH_TYPE_RELATIVE @"relative"
#define CODELESS_CODELESS_EVENT_KEY @"_is_fb_codeless"
#define PARAMETER_NAME_PRICE @"_valueToSum"
@implementation FBSDKEventBinding
- (FBSDKEventBinding *)initWithJSON:(NSDictionary *)dict
{
if ((self = [super init])) {
_eventName = [[dict objectForKey:CODELESS_MAPPING_EVENT_NAME_KEY] copy];
_eventType = [[dict objectForKey:CODELESS_MAPPING_EVENT_TYPE_KEY] copy];
_appVersion = [[dict objectForKey:CODELESS_MAPPING_APP_VERSION_KEY] copy];
_pathType = [[dict objectForKey:CODELESS_MAPPING_PATH_TYPE_KEY] copy];
NSArray *pathComponents = [dict objectForKey:CODELESS_MAPPING_PATH_KEY];
NSMutableArray *mut = [NSMutableArray array];
for (NSDictionary *info in pathComponents) {
FBSDKCodelessPathComponent *component = [[FBSDKCodelessPathComponent alloc]
initWithJSON:info];
[mut addObject:component];
}
_path = [mut copy];
NSArray *parameters = [dict objectForKey:CODELESS_MAPPING_PARAMETERS_KEY];
mut = [NSMutableArray array];
for (NSDictionary *info in parameters) {
FBSDKCodelessParameterComponent *component = [[FBSDKCodelessParameterComponent alloc]
initWithJSON:info];
[mut addObject:component];
}
_parameters = [mut copy];
}
return self;
}
- (void)trackEvent:(id)sender
{
UIView *sourceView = [sender isKindOfClass:[UIView class]] ? (UIView *)sender : nil;
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:@"1" forKey:CODELESS_CODELESS_EVENT_KEY];
for (FBSDKCodelessParameterComponent *component in self.parameters) {
NSString *text = component.value;
if (!text || text.length == 0) {
text = [FBSDKEventBinding findParameterOfPath:component.path
pathType:component.pathType
sourceView:sourceView];
}
if (text) {
if ([component.name isEqualToString:PARAMETER_NAME_PRICE]) {
NSNumber *value = [FBSDKAppEventsUtility getNumberValue:text];
[params setObject:value forKey:component.name];
} else {
[params setObject:text forKey:component.name];
}
}
}
[FBSDKAppEvents logEvent:_eventName parameters:[params copy]];
}
+ (BOOL)matchAnyView:(NSArray *)views
pathComponent:(FBSDKCodelessPathComponent *)component
{
for (NSObject *view in views) {
if ([self match:view pathComponent:component]) {
return YES;
}
}
return NO;
}
+ (BOOL)match:(NSObject *)view
pathComponent:(FBSDKCodelessPathComponent *)component
{
NSString *className = NSStringFromClass([view class]);
if (![className isEqualToString:component.className]) {
return NO;
}
if (component.index >= 0) {
NSObject *parent = [FBSDKViewHierarchy getParent:view];
if (parent) {
NSArray *children = [FBSDKViewHierarchy getChildren:[FBSDKViewHierarchy getParent:view]];
NSUInteger index = [children indexOfObject:view];
if (index == NSNotFound || index != component.index) {
return NO;
}
} else {
if (0 != component.index) {
return NO;
}
}
}
if ((component.matchBitmask & FBSDKCodelessMatchBitmaskFieldText) > 0) {
NSString *text = [FBSDKViewHierarchy getText:view];
BOOL match = ((text.length == 0 && component.text.length == 0)
|| [text isEqualToString:component.text]);
if (!match) {
return NO;
}
}
if ((component.matchBitmask & FBSDKCodelessMatchBitmaskFieldTag) > 0
&& [view isKindOfClass:[UIView class]]
&& component.tag != ((UIView *)view).tag) {
return NO;
}
if ((component.matchBitmask & FBSDKCodelessMatchBitmaskFieldHint) > 0) {
NSString *hint = [FBSDKViewHierarchy getHint:view];
BOOL match = ((hint.length == 0 && component.hint.length == 0)
|| [hint isEqualToString:component.hint]);
if (!match) {
return NO;
}
}
return YES;
}
+ (BOOL)isViewMatchPath:(UIView *)view path:(NSArray *)path
{
NSArray *viewPath = [FBSDKViewHierarchy getPath:view];
BOOL isMatch = [self isPath:path matchViewPath:viewPath];
return isMatch;
}
+ (BOOL)isPath:(NSArray *)path matchViewPath:(NSArray *)viewPath {
for (NSInteger i = 0; i < MIN(path.count, viewPath.count); i++) {
NSInteger idxPath = path.count - i - 1;
NSInteger idxViewPath = viewPath.count - i - 1;
FBSDKCodelessPathComponent *pathComponent = [path objectAtIndex:idxPath];
FBSDKCodelessPathComponent *viewPathComponent = [viewPath objectAtIndex:idxViewPath];
if (![pathComponent.className isEqualToString:viewPathComponent.className]) {
return NO;
}
if (pathComponent.index >= 0
&& pathComponent.index != viewPathComponent.index) {
return NO;
}
if ((pathComponent.matchBitmask & FBSDKCodelessMatchBitmaskFieldText) > 0) {
NSString *text = viewPathComponent.text;
BOOL match = ((text.length == 0 && pathComponent.text.length == 0)
|| [text isEqualToString:pathComponent.text]);
if (!match) {
return NO;
}
}
if ((pathComponent.matchBitmask & FBSDKCodelessMatchBitmaskFieldTag) > 0
&& pathComponent.tag != viewPathComponent.tag) {
return NO;
}
if ((pathComponent.matchBitmask & FBSDKCodelessMatchBitmaskFieldHint) > 0) {
NSString *hint = viewPathComponent.hint;
BOOL match = ((hint.length == 0 && pathComponent.hint.length == 0)
|| [hint isEqualToString:pathComponent.hint]);
if (!match) {
return NO;
}
}
}
return YES;
}
+ (NSObject *)findViewByPath:(NSArray *)path parent:(NSObject *)parent level:(int)level {
if (level >= path.count) {
return nil;
}
FBSDKCodelessPathComponent *pathComponent = [path objectAtIndex:level];
// If found parent, skip to next level
if ([pathComponent.className isEqualToString:CODELESS_MAPPING_PARENT_CLASS_NAME]) {
NSObject *nextParent = [FBSDKViewHierarchy getParent:parent];
return [FBSDKEventBinding findViewByPath:path parent:nextParent level:level + 1];
} else if ([pathComponent.className isEqualToString:CODELESS_MAPPING_CURRENT_CLASS_NAME]) {
return parent;
}
NSArray *children;
if (parent) {
children = [FBSDKViewHierarchy getChildren:parent];
} else {
UIWindow *window = [UIApplication sharedApplication].delegate.window;
if (window) {
children = @[window];
} else {
return nil;
}
}
if (path.count - 1 == level) {
int index = pathComponent.index;
if (index >= 0) {
NSObject *child = index < children.count ? [children objectAtIndex:index] : nil;
if ([self match:child pathComponent:pathComponent]) {
return child;
}
} else {
for (NSObject *child in children) {
if ([self match:child pathComponent:pathComponent]) {
return child;
}
}
}
} else {
for (NSObject *child in children) {
NSObject *result = [self findViewByPath:path parent:child level:level + 1];
if (result) {
return result;
}
}
}
return nil;
}
// MARK: - find event parameters via relative path
+ (NSString *)findParameterOfPath:(NSArray *)path
pathType:(NSString *)pathType
sourceView:(UIView *)sourceView {
if (0 == path.count) {
return nil;
}
UIView *rootView = sourceView;
if (![pathType isEqualToString:CODELESS_PATH_TYPE_RELATIVE]) {
rootView = nil;
}
NSObject *foundObj = [self findViewByPath:path parent:rootView level:0];
return [FBSDKViewHierarchy getText:foundObj];
}
@end

View File

@ -1,28 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
@interface FBSDKEventBindingManager : NSObject
- (FBSDKEventBindingManager*)initWithJSON:(NSDictionary*)dict;
- (void)start;
- (void)updateBindings:(NSArray *)bindings;
+ (NSArray *)parseArray:(NSArray *)array;
@end

View File

@ -1,380 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKEventBindingManager.h"
#import <UIKit/UIKit.h>
#import "FBSDKCodelessMacros.h"
#import "FBSDKCodelessPathComponent.h"
#import "FBSDKEventBinding.h"
#import "FBSDKSwizzler.h"
#import "FBSDKTypeUtility.h"
#import "FBSDKViewHierarchy.h"
#define ReactNativeEventNameKey @"eventName"
#define ReactNativeViewTagKey @"viewTag"
#define ReactNativeTouchEndEventName @"touchEnd"
#define ReactNativeClassRCTTextView @"RCTTextView"
#define ReactNativeClassRCTImageView @"RCTImageVIew"
#define ReactNativeClassRCTEventDispatcher @"RCTEventDispatcher"
#define ReactNativeClassRCTTouchEvent @"RCTTouchEvent"
static void fb_dispatch_on_main_thread(dispatch_block_t block) {
dispatch_async(dispatch_get_main_queue(), block);
}
static void fb_dispatch_on_default_thread(dispatch_block_t block) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
}
@interface FBSDKEventBindingManager ()
{
BOOL isStarted;
NSMutableDictionary *reactBindings;
NSSet *validClasses;
BOOL hasReactNative;
NSArray *eventBindings;
}
@end
@implementation FBSDKEventBindingManager
- (id)init {
self = [super init];
if (self) {
isStarted = false;
hasReactNative = NO;
reactBindings = [NSMutableDictionary dictionary];
NSMutableSet *classes = [NSMutableSet set];
[classes addObject:[UIControl class]];
[classes addObject:[UITableView class]];
[classes addObject:[UICollectionView class]];
// ReactNative
Class classRCTRootView = NSClassFromString(ReactNativeClassRCTRootView);
if (classRCTRootView != nil) {
hasReactNative = YES;
Class classRCTView = NSClassFromString(ReactNativeClassRCTView);
Class classRCTTextView = NSClassFromString(ReactNativeClassRCTTextView);
Class classRCTImageView = NSClassFromString(ReactNativeClassRCTImageView);
if (classRCTView) {
[classes addObject:classRCTView];
}
if (classRCTTextView) {
[classes addObject:classRCTTextView];
}
if (classRCTImageView) {
[classes addObject:classRCTImageView];
}
}
validClasses = [NSSet setWithSet:classes];
}
return self;
}
+ (NSArray *)parseArray:(NSArray *)array {
NSMutableArray *result = [NSMutableArray array];
for (NSDictionary *json in array) {
FBSDKEventBinding *binding = [[FBSDKEventBinding alloc] initWithJSON:json];
[result addObject:binding];
}
return [result copy];
}
- (FBSDKEventBindingManager*)initWithJSON:(NSDictionary*)dict
{
if ((self = [super init])) {
NSArray *eventBindingsDict = [FBSDKTypeUtility arrayValue:dict[@"event_bindings"]];
NSMutableArray *bindings = [NSMutableArray array];
for (NSDictionary *d in eventBindingsDict) {
FBSDKEventBinding *e = [[FBSDKEventBinding alloc] initWithJSON:d];
[bindings addObject:e];
}
eventBindings = [bindings copy];
}
return self;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
- (void)start
{
if (isStarted) {
return;
}
isStarted = true;
void (^blockToSuperview)(id view) = ^(id view) {
[self matchView:view delegate:nil];
};
void (^blockToWindow)(id view) = ^(id view) {
[self matchView:view delegate:nil];
};
[FBSDKSwizzler swizzleSelector:@selector(didMoveToSuperview)
onClass:[UIControl class]
withBlock:blockToSuperview named:@"map_control"];
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
onClass:[UIControl class]
withBlock:blockToWindow named:@"map_control"];
// ReactNative
if (hasReactNative) { // If app is built via ReactNative
Class classRCTView = NSClassFromString(ReactNativeClassRCTView);
Class classRCTTextView = NSClassFromString(ReactNativeClassRCTTextView);
Class classRCTImageView = NSClassFromString(ReactNativeClassRCTImageView);
Class classRCTEventDispatcher = NSClassFromString(ReactNativeClassRCTEventDispatcher);
// All react-native views would be added tp RCTRootView, so no need to check didMoveToWindow
[FBSDKSwizzler swizzleSelector:@selector(didMoveToSuperview)
onClass:classRCTView
withBlock:blockToSuperview
named:@"match_react_native"];
[FBSDKSwizzler swizzleSelector:@selector(didMoveToSuperview)
onClass:classRCTTextView
withBlock:blockToSuperview
named:@"match_react_native"];
[FBSDKSwizzler swizzleSelector:@selector(didMoveToSuperview)
onClass:classRCTImageView
withBlock:blockToSuperview
named:@"match_react_native"];
[FBSDKSwizzler swizzleSelector:@selector(dispatchEvent:) onClass:classRCTEventDispatcher withBlock:^(id dispatcher, SEL command, id event){
if ([event isKindOfClass:NSClassFromString(ReactNativeClassRCTTouchEvent)]) {
@try {
NSString *eventName = [event valueForKeyPath:ReactNativeEventNameKey];
NSNumber *viewTag = [event valueForKeyPath:ReactNativeViewTagKey];
if ([eventName isEqualToString:ReactNativeTouchEndEventName]
&& nil != viewTag) {
FBSDKEventBinding *eventBinding = [self->reactBindings objectForKey:viewTag];
if (eventBinding) {
[eventBinding trackEvent:nil];
}
}
}
@catch(NSException *exception) {
// Catch exception here to prevent LytroKit from crashing app
}
}
} named:@"dispatch_rn_event"];
}
// UITableView
void (^tableViewBlock)(UITableView *tableView,
SEL cmd,
id<UITableViewDelegate> delegate) =
^(UITableView *tableView, SEL cmd, id<UITableViewDelegate> delegate) {
if (!delegate) {
return;
}
[self matchView:tableView delegate:delegate];
};
[FBSDKSwizzler swizzleSelector:@selector(setDelegate:)
onClass:[UITableView class]
withBlock:tableViewBlock
named:@"match_table_view"];
// UICollectionView
void (^collectionViewBlock)(UICollectionView *collectionView,
SEL cmd,
id<UICollectionViewDelegate> delegate) =
^(UICollectionView *collectionView, SEL cmd, id<UICollectionViewDelegate> delegate) {
if (nil == delegate) {
return;
}
[self matchView:collectionView delegate:delegate];
};
[FBSDKSwizzler swizzleSelector:@selector(setDelegate:)
onClass:[UICollectionView class]
withBlock:collectionViewBlock
named:@"handle_collection_view"];
}
- (void)rematchBindings {
if (0 == eventBindings.count) {
return;
}
NSArray *windows = [UIApplication sharedApplication].windows;
for (UIWindow *window in windows) {
[self matchSubviewsIn:window];
}
}
- (void)matchSubviewsIn:(UIView *)view {
if (!view) {
return;
}
for (UIView *subview in view.subviews) {
BOOL isValidClass = NO;
for (Class cls in validClasses) {
if ([subview isKindOfClass:cls]) {
isValidClass = YES;
break;
}
}
if (isValidClass) {
if ([subview isKindOfClass:[UITableView class]]) {
UITableView *tableView = (UITableView *)subview;
if (tableView.delegate) {
[self matchView:subview delegate:tableView.delegate];
}
} else if ([subview isKindOfClass:[UICollectionView class]]) {
UICollectionView *collectionView = (UICollectionView *)subview;
if (collectionView.delegate) {
[self matchView:subview delegate:collectionView.delegate];
}
} else {
[self matchView:subview delegate:nil];
}
}
if (![subview isKindOfClass:[UIControl class]]) {
[self matchSubviewsIn:subview];
}
}
}
// check if the view is matched to any event
- (void)matchView:(UIView *)view delegate:(id)delegate {
if (0 == eventBindings.count) {
return;
}
fb_dispatch_on_main_thread(^{
NSArray *path = [FBSDKViewHierarchy getPath:view];
fb_dispatch_on_default_thread(^{
if ([view isKindOfClass:[UIControl class]]) {
UIControl *control = (UIControl *)view;
for (FBSDKEventBinding *binding in self->eventBindings) {
if ([FBSDKEventBinding isPath:binding.path matchViewPath:path]) {
fb_dispatch_on_main_thread(^{
[control addTarget:binding
action:@selector(trackEvent:)
forControlEvents:UIControlEventTouchUpInside];
});
break;
}
}
} else if (self->hasReactNative
&& [view respondsToSelector:@selector(reactTag)]) {
NSNumber *reactTag = [view performSelector:@selector(reactTag)];
for (FBSDKEventBinding *binding in self->eventBindings) {
if ([FBSDKEventBinding isPath:binding.path matchViewPath:path]) {
fb_dispatch_on_main_thread(^{
if (reactTag && [reactTag isKindOfClass:[NSNumber class]]) {
[self->reactBindings setObject:binding forKey:reactTag];
}
});
break;
}
}
} else if ([view isKindOfClass:[UITableView class]]
&& [delegate conformsToProtocol:@protocol(UITableViewDelegate)]) {
fb_dispatch_on_default_thread(^{
NSMutableSet *matchedBindings = [NSMutableSet set];
for (FBSDKEventBinding *binding in self->eventBindings) {
if (binding.path.count > 1) {
NSArray *shortPath = [binding.path
subarrayWithRange:NSMakeRange(0, binding.path.count - 1)];
if ([FBSDKEventBinding isPath:shortPath matchViewPath:path]) {
[matchedBindings addObject:binding];
}
}
}
if (matchedBindings.count > 0) {
NSArray *bindings = [matchedBindings allObjects];
void (^block)(id, SEL, id, id) = ^(id target, SEL command, UITableView *tableView, NSIndexPath *indexPath) {
fb_dispatch_on_main_thread(^{
for (FBSDKEventBinding *binding in bindings) {
FBSDKCodelessPathComponent *component = binding.path.lastObject;
if ((component.section == -1 || component.section == indexPath.section)
&& (component.row == -1 || component.row == indexPath.row)) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[binding trackEvent:cell];
}
}
});
};
[FBSDKSwizzler swizzleSelector:@selector(tableView:didSelectRowAtIndexPath:)
onClass:[delegate class]
withBlock:block
named:@"handle_table_view"];
}
});
} else if ([view isKindOfClass:[UICollectionView class]]
&& [delegate conformsToProtocol:@protocol(UICollectionViewDelegate)]) {
fb_dispatch_on_default_thread(^{
NSMutableSet *matchedBindings = [NSMutableSet set];
for (FBSDKEventBinding *binding in self->eventBindings) {
if (binding.path.count > 1) {
NSArray *shortPath = [binding.path
subarrayWithRange:NSMakeRange(0, binding.path.count - 1)];
if ([FBSDKEventBinding isPath:shortPath matchViewPath:path]) {
[matchedBindings addObject:binding];
}
}
}
if (matchedBindings.count > 0) {
NSArray *bindings = [matchedBindings allObjects];
void (^block)(id, SEL, id, id) = ^(id target, SEL command, UICollectionView *collectionView, NSIndexPath *indexPath) {
fb_dispatch_on_main_thread(^{
for (FBSDKEventBinding *binding in bindings) {
FBSDKCodelessPathComponent *component = binding.path.lastObject;
if ((component.section == -1 || component.section == indexPath.section)
&& (component.row == -1 || component.row == indexPath.row)) {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[binding trackEvent:cell];
}
}
});
};
[FBSDKSwizzler swizzleSelector:@selector(collectionView:didSelectItemAtIndexPath:)
onClass:[delegate class]
withBlock:block
named:@"handle_collection_view"];
}
});
}
});
});
}
#pragma clang diagnostic pop
- (void)updateBindings:(NSArray *)bindings {
eventBindings = bindings;
[reactBindings removeAllObjects];
fb_dispatch_on_main_thread(^{
[self rematchBindings];
});
}
@end

View File

@ -1,33 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface FBSDKViewHierarchy : NSObject
+ (NSObject *)getParent:(NSObject *)obj;
+ (NSArray *)getChildren:(NSObject *)obj;
+ (NSArray *)getPath:(NSObject *)obj;
+ (NSString *)getText:(NSObject *)obj;
+ (NSString *)getHint:(NSObject *)obj;
+ (UITableView *)getParentTableView:(UIView *)cell;
+ (UICollectionView *)getParentCollectionView:(UIView *)cell;
@end

View File

@ -1,394 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKViewHierarchy.h"
#import <objc/runtime.h>
#import <QuartzCore/QuartzCore.h>
#import "FBSDKCodelessMacros.h"
#import "FBSDKCodelessPathComponent.h"
#import "FBSDKCoreKit+Internal.h"
#define MAX_VIEW_HIERARCHY_LEVEL 35
@implementation FBSDKViewHierarchy
+ (NSArray*)getChildren:(NSObject*)obj {
if ([obj isKindOfClass:[UIControl class]]) {
return nil;
}
NSMutableArray *children = [NSMutableArray array];
// children of window should be viewcontroller
if ([obj isKindOfClass:[UIWindow class]]) {
UIViewController *rootVC = ((UIWindow *)obj).rootViewController;
NSArray *subviews = [(UIWindow *)obj subviews];
for (UIView *child in subviews) {
if (child != rootVC.view) {
UIViewController *vc = [FBSDKViewHierarchy getParentViewController:child];
if (vc != nil && vc.view == child) {
[children addObject:vc];
} else {
[children addObject:child];
}
} else {
if (rootVC) {
[children addObject:rootVC];
}
}
}
} else if ([obj isKindOfClass:[UIView class]]) {
NSArray *subviews = [[(UIView *)obj subviews] copy];
for (UIView *child in subviews) {
UIViewController *vc = [FBSDKViewHierarchy getParentViewController:child];
if (vc && vc.view == child) {
[children addObject:vc];
} else {
[children addObject:child];
}
}
} else if ([obj isKindOfClass:[UINavigationController class]]) {
UIViewController *vc = [(UINavigationController*)obj visibleViewController];
UIViewController *tc = [(UINavigationController*)obj topViewController];
NSArray *nextChildren = [FBSDKViewHierarchy getChildren:((UIViewController*)obj).view];
for (NSObject *child in nextChildren) {
if (tc && [self isView:child superViewOfView:tc.view]) {
[children addObject:tc];
} else if (vc && [self isView:child superViewOfView:vc.view]) {
[children addObject:vc];
} else {
if (child != vc.view && child != tc.view) {
[children addObject:child];
} else {
if (vc && child == vc.view) {
[children addObject:vc];
} else if (tc && child == tc.view) {
[children addObject:tc];
}
}
}
}
if (vc && ![children containsObject:vc]) {
[children addObject:vc];
}
} else if ([obj isKindOfClass:[UITabBarController class]]) {
UIViewController *vc = [(UITabBarController *)obj selectedViewController];
NSArray *nextChildren = [FBSDKViewHierarchy getChildren:((UIViewController*)obj).view];
for (NSObject *child in nextChildren) {
if (vc && [self isView:child superViewOfView:vc.view]) {
[children addObject:vc];
} else {
if (vc && child == vc.view) {
[children addObject:vc];
} else {
[children addObject:child];
}
}
}
if (vc && ![children containsObject:vc]) {
[children addObject:vc];
}
} else if ([obj isKindOfClass:[UIViewController class]]) {
UIViewController *vc = (UIViewController *)obj;
if (vc.isViewLoaded) {
NSArray *nextChildren = [FBSDKViewHierarchy getChildren:vc.view];
if (nextChildren.count > 0) {
[children addObjectsFromArray:nextChildren];
}
}
for (NSObject *child in [vc childViewControllers]) {
[children addObject:child];
}
UIViewController *presentedVC = vc.presentedViewController;
if (presentedVC) {
[children addObject:presentedVC];
}
}
return children;
}
+ (NSObject *)getParent:(NSObject *)obj
{
if ([obj isKindOfClass:[UIView class]]) {
UIView *superview = [(UIView *)obj superview];
UIViewController *superviewViewController = [FBSDKViewHierarchy
getParentViewController:superview];
if (superviewViewController && superviewViewController.view == superview) {
return superviewViewController;
}
if (superview && superview != obj) {
return superview;
}
}
else if ([obj isKindOfClass:[UIViewController class]]) {
UIViewController *vc = (UIViewController *)obj;
UIViewController *parentVC = [vc parentViewController];
UIViewController *presentingVC = [vc presentingViewController];
UINavigationController *nav = [vc navigationController];
UITabBarController *tab = [vc tabBarController];
if (nav) {
return nav;
}
if (tab) {
return tab;
}
if (parentVC) {
return parentVC;
}
if (presentingVC && [presentingVC presentedViewController] == vc) {
return presentingVC;
}
// Return parent of view of UIViewController
NSObject *viewParent = [FBSDKViewHierarchy getParent:vc.view];
if (viewParent) {
return viewParent;
}
}
return nil;
}
+ (NSArray *)getPath:(NSObject *)obj {
return [FBSDKViewHierarchy getPath:obj limit:MAX_VIEW_HIERARCHY_LEVEL];
}
+ (NSArray *)getPath:(NSObject *)obj limit:(int)limit {
if (!obj || limit <= 0) {
return nil;
}
NSMutableArray *path;
NSObject *parent = [FBSDKViewHierarchy getParent:obj];
if (parent) {
NSArray *parentPath = [FBSDKViewHierarchy getPath:parent limit:limit - 1];
path = [NSMutableArray arrayWithArray:parentPath];
} else {
path = [NSMutableArray array];
}
NSMutableDictionary *componentInfo = [NSMutableDictionary dictionary];
[componentInfo setObject:NSStringFromClass([obj class])
forKey:CODELESS_MAPPING_CLASS_NAME_KEY];
NSString *text = [FBSDKViewHierarchy getText:obj];
if (text) {
[componentInfo setObject:text forKey:CODELESS_MAPPING_TEXT_KEY];
}
if (parent != nil) {
NSArray *children = [FBSDKViewHierarchy getChildren:parent];
NSUInteger index = [children indexOfObject:obj];
if (index != NSNotFound) {
[componentInfo setObject:@(index)
forKey:CODELESS_MAPPING_INDEX_KEY];
}
} else {
[componentInfo setObject:@0 forKey:CODELESS_MAPPING_INDEX_KEY];
}
if ([obj isKindOfClass:[UIView class]]) {
[componentInfo setObject:@(((UIView *)obj).tag)
forKey:CODELESS_MAPPING_TAG_KEY];
// Handle UITableViewCell & UICollectionViewCell
if ([obj isKindOfClass:[UITableViewCell class]]) {
UITableView *tableView = [FBSDKViewHierarchy getParentTableView:(UIView *)obj];
NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)obj];
if (indexPath) {
[componentInfo setObject:@(indexPath.section)
forKey:CODELESS_MAPPING_SECTION_KEY];
[componentInfo setObject:@(indexPath.row)
forKey:CODELESS_MAPPING_ROW_KEY];
}
} else if ([obj isKindOfClass:[UICollectionViewCell class]]) {
UICollectionView *collectionView = [FBSDKViewHierarchy getParentCollectionView:(UIView *)obj];
NSIndexPath *indexPath = [collectionView indexPathForCell:(UICollectionViewCell *)obj];
if (indexPath) {
[componentInfo setObject:@(indexPath.section)
forKey:CODELESS_MAPPING_SECTION_KEY];
[componentInfo setObject:@(indexPath.row)
forKey:CODELESS_MAPPING_ROW_KEY];
}
} else if ([obj isKindOfClass:[UITextField class]]) {
NSString *hint = [FBSDKViewHierarchy getHint:obj];
if (hint) {
[componentInfo setObject:hint forKey:CODELESS_MAPPING_HINT_KEY];
}
}
} else if ([obj isKindOfClass:[UINavigationController class]]) {
NSString *hint = [FBSDKViewHierarchy getHint:obj];
if (hint) {
[componentInfo setObject:hint forKey:CODELESS_MAPPING_HINT_KEY];
}
}
FBSDKCodelessPathComponent *pathComponent = [[FBSDKCodelessPathComponent alloc]
initWithJSON:componentInfo];
[path addObject:pathComponent];
return [NSArray arrayWithArray:path];
}
+ (NSString *)getText:(NSObject *)obj {
NSString *text = nil;
if ([obj isKindOfClass:[UIButton class]]) {
text = [(UIButton *)obj currentTitle];
} else if ([obj isKindOfClass:[UITextView class]] ||
[obj isKindOfClass:[UITextField class]] ||
[obj isKindOfClass:[UILabel class]]) {
text = [(UILabel *)obj text];
} else if ([obj isKindOfClass:[UIPickerView class]]) {
UIPickerView *picker = (UIPickerView *)obj;
NSInteger sections = [picker numberOfComponents];
NSMutableArray *titles = [NSMutableArray array];
for (NSInteger i = 0; i < sections; i++) {
NSInteger row = [picker selectedRowInComponent:i];
NSString *title;
if ([picker.delegate
respondsToSelector:@selector(pickerView:titleForRow:forComponent:)]) {
title = [picker.delegate pickerView:picker titleForRow:row forComponent:i];
} else if ([picker.delegate
respondsToSelector:@selector(pickerView:attributedTitleForRow:forComponent:)]) {
title = [[picker.delegate
pickerView:picker
attributedTitleForRow:row forComponent:i] string];
}
[titles addObject:title ?: @""];
}
if (titles.count > 0) {
text = [FBSDKInternalUtility JSONStringForObject:titles
error:NULL
invalidObjectHandler:NULL];
}
} else if ([obj isKindOfClass:[UIDatePicker class]]) {
UIDatePicker *picker = (UIDatePicker *)obj;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ssZ"];
text = [formatter stringFromDate:picker.date];
} else if ([obj isKindOfClass:NSClassFromString(@"RCTTextView")]) {
NSTextStorage *textStorage = [FBSDKAppEventsUtility getVariable:@"_textStorage"
fromInstance:obj];
if (textStorage) {
text = [textStorage string];
}
} else if ([obj isKindOfClass:NSClassFromString(@"RCTBaseTextInputView")]) {
NSAttributedString *attributedText = [FBSDKAppEventsUtility getVariable:@"attributedText"
fromInstance:obj];
text = [attributedText string];
}
if ([obj conformsToProtocol:@protocol(UITextInput)]) {
id<UITextInput> input = (id<UITextInput>)obj;
if ([input isSecureTextEntry]) {
text = nil;
} else {
switch (input.keyboardType) {
case UIKeyboardTypePhonePad:
case UIKeyboardTypeEmailAddress:
text = nil;
break;
default: break;
}
}
}
return text.length > 0 ? text : nil;
}
+ (NSString *)getHint:(NSObject *)obj {
NSString *hint = nil;
if ([obj isKindOfClass:[UITextField class]]) {
hint = [(UITextField *)obj placeholder];
} else if ([obj isKindOfClass:[UINavigationController class]]) {
UIViewController *top = [(UINavigationController *)obj topViewController];
if (top) {
hint = NSStringFromClass([top class]);
}
}
return hint.length > 0 ? hint : nil;
}
+ (BOOL)isView:(NSObject *)obj1 superViewOfView:(UIView *)obj2 {
if (![obj1 isKindOfClass:[UIView class]]
|| ![obj2 isKindOfClass:[UIView class]]) {
return NO;
}
UIView *view1 = (UIView *)obj1;
UIView *view2 = (UIView *)obj2;
UIView *superview = view2;
while (superview) {
superview = [superview superview];
if (superview == view1) {
return YES;
}
}
return NO;
}
+ (UIViewController *)getParentViewController:(UIView *)view {
UIResponder *parentResponder = view;
while (parentResponder) {
parentResponder = [parentResponder nextResponder];
if ([parentResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)parentResponder;
}
}
return nil;
}
+ (UITableView *)getParentTableView:(UIView *)cell {
UIView *superview = cell.superview;
while (superview) {
if ([superview isKindOfClass:[UITableView class]]) {
return (UITableView *)superview;
}
superview = [superview superview];
}
return nil;
}
+ (UICollectionView *)getParentCollectionView:(UIView *)cell {
UIView *superview = cell.superview;
while (superview) {
if ([superview isKindOfClass:[UICollectionView class]]) {
return (UICollectionView *)superview;
}
superview = [superview superview];
}
return nil;
}
@end

View File

@ -94,17 +94,6 @@ FBSDK_EXTERN NSString *const FBSDKAppEventNameFBDialogsWebLoginCompleted;
/** Use to log the result of the App Switch OS AlertView. Only available on OS >= iOS10 */ /** Use to log the result of the App Switch OS AlertView. Only available on OS >= iOS10 */
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSessionFASLoginDialogResult; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSessionFASLoginDialogResult;
/** Use to log the live streaming events from sdk */
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingStart;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingStop;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingPause;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingResume;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingError;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingUpdateStatus;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingVideoID;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingMic;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingCamera;
/** Use to log the results of a share dialog */ /** Use to log the results of a share dialog */
FBSDK_EXTERN NSString *const FBSDLAppEventNameFBSDKEventShareDialogResult; FBSDK_EXTERN NSString *const FBSDLAppEventNameFBSDKEventShareDialogResult;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKEventMessengerShareDialogResult; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKEventMessengerShareDialogResult;
@ -123,14 +112,6 @@ FBSDK_EXTERN NSString *const FBSDKAppEventParameterDialogShareContentPageID;
FBSDK_EXTERN NSString *const FBSDKAppEventParameterShareTrayActivityName; FBSDK_EXTERN NSString *const FBSDKAppEventParameterShareTrayActivityName;
FBSDK_EXTERN NSString *const FBSDKAppEventParameterShareTrayResult; FBSDK_EXTERN NSString *const FBSDKAppEventParameterShareTrayResult;
/*! Use to log parameters for live streaming*/
FBSDK_EXTERN NSString *const FBSDKAppEventParameterLiveStreamingPrevStatus;
FBSDK_EXTERN NSString *const FBSDKAppEventParameterLiveStreamingStatus;
FBSDK_EXTERN NSString *const FBSDKAppEventParameterLiveStreamingError;
FBSDK_EXTERN NSString *const FBSDKAppEventParameterLiveStreamingVideoID;
FBSDK_EXTERN NSString *const FBSDKAppEventParameterLiveStreamingMicEnabled;
FBSDK_EXTERN NSString *const FBSDKAppEventParameterLiveStreamingCameraEnabled;
// Internally known event parameter values // Internally known event parameter values
FBSDK_EXTERN NSString *const FBSDKAppEventsDialogOutcomeValue_Completed; FBSDK_EXTERN NSString *const FBSDKAppEventsDialogOutcomeValue_Completed;
@ -166,7 +147,6 @@ FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLikeButtonImpression;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLoginButtonImpression; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLoginButtonImpression;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKSendButtonImpression; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKSendButtonImpression;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKShareButtonImpression; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKShareButtonImpression;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonImpression;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKSmartLoginService; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKSmartLoginService;
@ -174,7 +154,6 @@ FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLikeButtonDidTap;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLoginButtonDidTap; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLoginButtonDidTap;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKSendButtonDidTap; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKSendButtonDidTap;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKShareButtonDidTap; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKShareButtonDidTap;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonDidTap;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLikeControlDidDisable; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLikeControlDidDisable;
FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLikeControlDidLike; FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLikeControlDidLike;
@ -188,16 +167,6 @@ FBSDK_EXTERN NSString *const FBSDKAppEventNameFBSDKLikeControlNetworkUnavailable
FBSDK_EXTERN NSString *const FBSDKAppEventParameterDialogErrorMessage; FBSDK_EXTERN NSString *const FBSDKAppEventParameterDialogErrorMessage;
FBSDK_EXTERN NSString *const FBSDKAppEventParameterLogTime; FBSDK_EXTERN NSString *const FBSDKAppEventParameterLogTime;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesHandlerKey;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesActionKey;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesEventKey;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesParamsKey;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackKey;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackCustomKey;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackSingleKey;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackSingleCustomKey;
FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesPixelIDKey;
@interface FBSDKAppEvents (Internal) @interface FBSDKAppEvents (Internal)
+ (void)logImplicitEvent:(NSString *)eventName + (void)logImplicitEvent:(NSString *)eventName
@ -207,6 +176,5 @@ FBSDK_EXTERN NSString *const FBSDKAppEventsWKWebViewMessagesPixelIDKey;
+ (FBSDKAppEvents *)singleton; + (FBSDKAppEvents *)singleton;
- (void)flushForReason:(FBSDKAppEventsFlushReason)flushReason; - (void)flushForReason:(FBSDKAppEventsFlushReason)flushReason;
- (void)registerNotifications;
@end @end

View File

@ -118,7 +118,7 @@
_numSkipped++; _numSkipped++;
} else { } else {
[_mutableEvents addObject:@{ [_mutableEvents addObject:@{
@"event" : [eventDictionary mutableCopy], @"event" : eventDictionary,
FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY : @(isImplicit) FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY : @(isImplicit)
}]; }];
} }

View File

@ -1,24 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
@interface FBSDKAppEventsUninstall : NSObject
@end

View File

@ -1,118 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKAppEventsUninstall.h"
#import <objc/runtime.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#import "FBSDKAppEventsUtility.h"
#import "FBSDKGraphRequest.h"
#import "FBSDKLogger.h"
#import "FBSDKServerConfigurationManager.h"
#import "FBSDKSettings.h"
#import "FBSDKSwizzler.h"
#define UNINSTALL_TRACKING_DEVICE_ID_KEY @"device_id"
#define UNINSTALL_TRACKING_PLATFORM_KEY @"platform"
#define UNINSTALL_TRACKING_DEVICE_TOKEN_KEY @"device_token"
#define UNINSTALL_TRACKING_TOKEN_ENDPOINT @"app_push_device_token"
@implementation FBSDKAppEventsUninstall
+ (void)load
{
[FBSDKAppEventsUninstall installSwizzler];
}
+ (NSString *)stringWithDeviceToken:(NSData *)deviceToken {
const char *data = [deviceToken bytes];
NSMutableString *token = [NSMutableString string];
for (NSUInteger i = 0; i < [deviceToken length]; i++) {
[token appendFormat:@"%02.2hhX", data[i]];
}
return [token copy];
}
+ (void)installSwizzler
{
Class cls = [[UIApplication sharedApplication].delegate class];
SEL selector = @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:);
BOOL hasMethod = class_getInstanceMethod(cls, selector) != nil;
void (^block)(id) = ^(NSData *deviceToken) {
NSString *tokenString = [self stringWithDeviceToken:deviceToken];
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorInformational
logEntry:[NSString stringWithFormat:@"Register token from Swizzling: %@", tokenString]];
// try upload token immediately after receiving it from swizzling
[self updateAndUploadToken:tokenString];
};
if (!hasMethod)
{
void (^registerBlock)(id, id, id) = ^(id _, id __, NSData *deviceToken)
{
block(deviceToken);
};
IMP imp = imp_implementationWithBlock(registerBlock);
struct objc_method_description desc = protocol_getMethodDescription(@protocol(UIApplicationDelegate),
selector, NO, YES);
const char *types = desc.types;
class_addMethod(cls, selector, imp, types);
} else
{
void (^registerBlock)(id, SEL, id, id) = ^(id _, SEL __, id ___, NSData *deviceToken)
{
block(deviceToken);
};
[FBSDKSwizzler swizzleSelector:selector
onClass:cls
withBlock:registerBlock
named:@"map_control"];
}
}
// Token is updated when (changed OR not uploaded)
// Token is uploaded when enabled AND (changed OR not uploaded)
+ (void)updateAndUploadToken:(NSString *)tokenString
{
if (!tokenString) {
return;
}
[FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *error) {
if (serverConfiguration.uninstallTrackingEnabled) {
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
initWithGraphPath:[NSString stringWithFormat:@"%@/%@",
[FBSDKSettings appID], UNINSTALL_TRACKING_TOKEN_ENDPOINT]
parameters:@{
UNINSTALL_TRACKING_DEVICE_TOKEN_KEY: tokenString,
UNINSTALL_TRACKING_PLATFORM_KEY: @"ios",
// advertiserID could be 0s if user select limit ad tracking
UNINSTALL_TRACKING_DEVICE_ID_KEY: [FBSDKAppEventsUtility advertiserID]?:@""
}
HTTPMethod:@"POST"];
[request startWithCompletionHandler:nil];
}
}];
}
@end

View File

@ -53,7 +53,5 @@ typedef NS_ENUM(NSUInteger, FBSDKAppEventsFlushReason)
+ (NSString *)tokenStringToUseFor:(FBSDKAccessToken *)token; + (NSString *)tokenStringToUseFor:(FBSDKAccessToken *)token;
+ (long)unixTimeNow; + (long)unixTimeNow;
+ (BOOL)validateIdentifier:(NSString *)identifier; + (BOOL)validateIdentifier:(NSString *)identifier;
+ (id)getVariable:(NSString *)variableName fromInstance:(NSObject *)instance;
+ (NSNumber *)getNumberValue:(NSString *)text;
@end @end

View File

@ -18,8 +18,6 @@
#import "FBSDKAppEventsUtility.h" #import "FBSDKAppEventsUtility.h"
#import <objc/runtime.h>
#import <AdSupport/AdSupport.h> #import <AdSupport/AdSupport.h>
#import "FBSDKAccessToken.h" #import "FBSDKAccessToken.h"
@ -68,10 +66,6 @@
if (userID) { if (userID) {
parameters[@"app_user_id"] = userID; parameters[@"app_user_id"] = userID;
} }
NSString *userData = [FBSDKAppEvents getUserData];
if (userData){
parameters[@"ud"] = userData;
}
[FBSDKAppEventsDeviceInfo extendDictionaryWithDeviceInfo:parameters]; [FBSDKAppEventsDeviceInfo extendDictionaryWithDeviceInfo:parameters];
@ -340,49 +334,6 @@ restOfStringCharacterSet:(NSCharacterSet *)restOfStringCharacterSet
return (long)round([[NSDate date] timeIntervalSince1970]); return (long)round([[NSDate date] timeIntervalSince1970]);
} }
+ (id)getVariable:(NSString *)variableName fromInstance:(NSObject *)instance {
Ivar ivar = class_getInstanceVariable([instance class], [variableName UTF8String]);
if (ivar != NULL) {
const char *encoding = ivar_getTypeEncoding(ivar);
if (encoding != NULL && encoding[0] == '@') {
return object_getIvar(instance, ivar);
}
}
return nil;
}
+ (NSNumber *)getNumberValue:(NSString *)text {
NSNumber *value = @0;
NSLocale *locale = [NSLocale currentLocale];
NSString *ds = [locale objectForKey:NSLocaleDecimalSeparator] ?: @".";
NSString *gs = [locale objectForKey:NSLocaleGroupingSeparator] ?: @",";
NSString *separators = [ds stringByAppendingString:gs];
NSString *regex = [NSString stringWithFormat:@"[+-]?([0-9]+[%1$@]?)?[%1$@]?([0-9]+[%1$@]?)+", separators];
NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex
options:0
error:nil];
NSTextCheckingResult *match = [re firstMatchInString:text
options:0
range:NSMakeRange(0, text.length)];
if (match) {
NSString *validText = [text substringWithRange:match.range];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.locale = locale;
formatter.numberStyle = NSNumberFormatterDecimalStyle;
value = [formatter numberFromString:validText];
if (nil == value) {
value = @([validText floatValue]);
}
}
return value;
}
- (instancetype)init - (instancetype)init
{ {
FBSDK_NO_DESIGNATED_INITIALIZER(); FBSDK_NO_DESIGNATED_INITIALIZER();

View File

@ -1,26 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#if !TARGET_OS_TV
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
@interface FBSDKHybridAppEventsScriptMessageHandler : NSObject <WKScriptMessageHandler>
@end
#endif

View File

@ -1,62 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKHybridAppEventsScriptMessageHandler.h"
#import <FBSDKCoreKit/FBSDKAppEvents.h>
#import "FBSDKAppEvents+Internal.h"
NSString *const FBSDKAppEventsWKWebViewMessagesPixelReferralParamKey = @"_fb_pixel_referral_id";
@class WKUserContentController;
@implementation FBSDKHybridAppEventsScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:FBSDKAppEventsWKWebViewMessagesHandlerKey]) {
NSString *event = message.body[FBSDKAppEventsWKWebViewMessagesEventKey];
if ([event length] > 0) {
NSString *stringedParams = message.body[FBSDKAppEventsWKWebViewMessagesParamsKey];
NSMutableDictionary <NSObject *, NSObject *> *params = nil;
NSError *jsonParseError = nil;
if ([stringedParams isKindOfClass:[NSString class]]) {
params = [NSJSONSerialization JSONObjectWithData:[stringedParams dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error:&jsonParseError
];
}
NSString *pixelID = message.body[FBSDKAppEventsWKWebViewMessagesPixelIDKey];
if (pixelID == nil) {
[FBSDKAppEventsUtility logAndNotify:@"Can't bridge an event without a referral Pixel ID. Check your webview Pixel configuration."];
return;
}
if (jsonParseError != nil || ![params isKindOfClass:[NSDictionary class]] || params == nil) {
[FBSDKAppEventsUtility logAndNotify:@"Could not find parameters for your Pixel request. Check your webview Pixel configuration."];
params = [[NSMutableDictionary alloc] initWithObjectsAndKeys:pixelID, FBSDKAppEventsWKWebViewMessagesPixelReferralParamKey, nil];
}
else {
[params setObject:pixelID forKey: FBSDKAppEventsWKWebViewMessagesPixelReferralParamKey];
}
[FBSDKAppEvents logEvent:event parameters:params];
}
}
}
@end

View File

@ -27,12 +27,8 @@
static NSString *const FBSDKAppEventParameterImplicitlyLoggedPurchase = @"_implicitlyLogged"; static NSString *const FBSDKAppEventParameterImplicitlyLoggedPurchase = @"_implicitlyLogged";
static NSString *const FBSDKAppEventNamePurchaseFailed = @"fb_mobile_purchase_failed"; static NSString *const FBSDKAppEventNamePurchaseFailed = @"fb_mobile_purchase_failed";
static NSString *const FBSDKAppEventNamePurchaseRestored = @"fb_mobile_purchase_restored";
static NSString *const FBSDKAppEventParameterNameInAppPurchaseType = @"fb_iap_product_type";
static NSString *const FBSDKAppEventParameterNameProductTitle = @"fb_content_title"; static NSString *const FBSDKAppEventParameterNameProductTitle = @"fb_content_title";
static NSString *const FBSDKAppEventParameterNameTransactionID = @"fb_transaction_id"; static NSString *const FBSDKAppEventParameterNameTransactionID = @"fb_transaction_id";
static NSString *const FBSDKAppEventParameterNameTransactionDate = @"fb_transaction_date";
static NSString *const FBSDKAppEventParameterNameSubscriptionPeriod = @"fb_iap_subs_period";
static int const FBSDKMaxParameterValueLength = 100; static int const FBSDKMaxParameterValueLength = 100;
static NSMutableArray *g_pendingRequestors; static NSMutableArray *g_pendingRequestors;
@ -114,10 +110,10 @@ static NSMutableArray *g_pendingRequestors;
case SKPaymentTransactionStatePurchasing: case SKPaymentTransactionStatePurchasing:
case SKPaymentTransactionStatePurchased: case SKPaymentTransactionStatePurchased:
case SKPaymentTransactionStateFailed: case SKPaymentTransactionStateFailed:
case SKPaymentTransactionStateRestored:
[self handleTransaction:transaction]; [self handleTransaction:transaction];
break; break;
case SKPaymentTransactionStateDeferred: case SKPaymentTransactionStateDeferred:
case SKPaymentTransactionStateRestored:
break; break;
} }
} }
@ -192,9 +188,6 @@ static NSMutableArray *g_pendingRequestors;
{ {
NSString *eventName = nil; NSString *eventName = nil;
NSString *transactionID = nil; NSString *transactionID = nil;
NSString *transactionDate = nil;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ssZ"];
switch (self.transaction.transactionState) { switch (self.transaction.transactionState) {
case SKPaymentTransactionStatePurchasing: case SKPaymentTransactionStatePurchasing:
eventName = FBSDKAppEventNameInitiatedCheckout; eventName = FBSDKAppEventNameInitiatedCheckout;
@ -202,16 +195,12 @@ static NSMutableArray *g_pendingRequestors;
case SKPaymentTransactionStatePurchased: case SKPaymentTransactionStatePurchased:
eventName = FBSDKAppEventNamePurchased; eventName = FBSDKAppEventNamePurchased;
transactionID = self.transaction.transactionIdentifier; transactionID = self.transaction.transactionIdentifier;
transactionDate = [formatter stringFromDate:self.transaction.transactionDate];
break; break;
case SKPaymentTransactionStateFailed: case SKPaymentTransactionStateFailed:
eventName = FBSDKAppEventNamePurchaseFailed; eventName = FBSDKAppEventNamePurchaseFailed;
break; break;
case SKPaymentTransactionStateRestored:
eventName = FBSDKAppEventNamePurchaseRestored;
transactionDate = [formatter stringFromDate:self.transaction.transactionDate];
break;
case SKPaymentTransactionStateDeferred: case SKPaymentTransactionStateDeferred:
case SKPaymentTransactionStateRestored:
return; return;
} }
if (!eventName) { if (!eventName) {
@ -224,7 +213,6 @@ static NSMutableArray *g_pendingRequestors;
NSMutableDictionary *eventParameters = [NSMutableDictionary dictionaryWithDictionary: @{ NSMutableDictionary *eventParameters = [NSMutableDictionary dictionaryWithDictionary: @{
FBSDKAppEventParameterNameContentID: payment.productIdentifier ?: @"", FBSDKAppEventParameterNameContentID: payment.productIdentifier ?: @"",
FBSDKAppEventParameterNameNumItems: @(payment.quantity), FBSDKAppEventParameterNameNumItems: @(payment.quantity),
FBSDKAppEventParameterNameTransactionDate: transactionDate ?: @"",
}]; }];
double totalAmount = 0; double totalAmount = 0;
if (product) { if (product) {
@ -235,29 +223,6 @@ static NSMutableArray *g_pendingRequestors;
FBSDKAppEventParameterNameProductTitle: [self getTruncatedString:product.localizedTitle], FBSDKAppEventParameterNameProductTitle: [self getTruncatedString:product.localizedTitle],
FBSDKAppEventParameterNameDescription: [self getTruncatedString:product.localizedDescription], FBSDKAppEventParameterNameDescription: [self getTruncatedString:product.localizedDescription],
}]; }];
#if !TARGET_OS_TV
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_2
if (@available(iOS 11.2, *)) {
BOOL isSubscription = (product.subscriptionPeriod != nil) && ((unsigned long)product.subscriptionPeriod.numberOfUnits > 0);
if (isSubscription) {
// subs inapp
SKProductSubscriptionPeriod *period = product.subscriptionPeriod;
NSString *unit = nil;
switch (period.unit) {
case SKProductPeriodUnitDay: unit = @"D"; break;
case SKProductPeriodUnitWeek: unit = @"W"; break;
case SKProductPeriodUnitMonth: unit = @"M"; break;
case SKProductPeriodUnitYear: unit = @"Y"; break;
}
NSString *p = [NSString stringWithFormat:@"P%lu%@", (unsigned long)period.numberOfUnits, unit];
[eventParameters setObject:p forKey:FBSDKAppEventParameterNameSubscriptionPeriod];
[eventParameters setObject:@"subs" forKey:FBSDKAppEventParameterNameInAppPurchaseType];
} else {
[eventParameters setObject:@"inapp" forKey:FBSDKAppEventParameterNameInAppPurchaseType];
}
}
#endif
#endif
if (transactionID) { if (transactionID) {
[eventParameters setObject:transactionID forKey:FBSDKAppEventParameterNameTransactionID]; [eventParameters setObject:transactionID forKey:FBSDKAppEventParameterNameTransactionID];
} }
@ -314,7 +279,7 @@ static NSMutableArray *g_pendingRequestors;
} }
} }
[eventParameters setObject:@"1" forKey:FBSDKAppEventParameterImplicitlyLoggedPurchase]; [eventParameters setObject:@"1"forKey:FBSDKAppEventParameterImplicitlyLoggedPurchase];
[FBSDKAppEvents logEvent:eventName [FBSDKAppEvents logEvent:eventName
valueToSum:valueToSum valueToSum:valueToSum
parameters:eventParameters]; parameters:eventParameters];

View File

@ -1,42 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <FBSDKCoreKit/FBSDKMacros.h>
@interface FBSDKUserDataStore : NSObject
+ (void)initStore;
+ (void)setUserDataAndHash:(NSDictionary *)ud;
+ (void)setUserDataAndHash:(nullable NSString *)email
firstName:(nullable NSString *)firstName
lastName:(nullable NSString *)lastName
phone:(nullable NSString *)phone
dateOfBirth:(nullable NSString *)dateOfBirth
gender:(nullable NSString *)gender
city:(nullable NSString *)city
state:(nullable NSString *)state
zip:(nullable NSString *)zip
country:(nullable NSString *)country;
+ (NSString *) getHashedUserData;
@end

View File

@ -1,216 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKUserDataStore.h"
#import <FBSDKSettings.h>
#import "FBSDKAppEventsUtility.h"
#import "FBSDKLogger.h"
#import "FBSDKUtility.h"
#define USER_DATA_KEY @"com.facebook.appevents.UserDataStore.userData"
static NSString *const FBSDKEmail = @"em";
static NSString *const FBSDKFirstName = @"fn";
static NSString *const FBSDKLastName = @"ln";
static NSString *const FBSDKPhone = @"ph";
static NSString *const FBSDKDateOfBirth = @"db";
static NSString *const FBSDKGender = @"ge";
static NSString *const FBSDKCity = @"ct";
static NSString *const FBSDKState = @"st";
static NSString *const FBSDKZip = @"zp";
static NSString *const FBSDKCountry = @"country";
static NSString *hashedUserData;
static volatile bool initialized = false;
@implementation FBSDKUserDataStore
+ (void)initStore
{
if (initialized){
return;
}
[FBSDKUserDataStore initAndWait];
}
+ (void)initAndWait
{
if (initialized){
return;
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
hashedUserData = [defaults stringForKey:USER_DATA_KEY];
initialized = true;
}
+ (void)setUserDataAndHash:(NSDictionary *)ud
{
if (!initialized){
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"initStore should have been called before calling setUserData"];
[FBSDKUserDataStore initAndWait];
}
hashedUserData = [FBSDKUserDataStore hashUserData:ud];
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:(hashedUserData) forKey:(USER_DATA_KEY)];
}
+ (void)setUserDataAndHash:(nullable NSString *)email
firstName:(nullable NSString *)firstName
lastName:(nullable NSString *)lastName
phone:(nullable NSString *)phone
dateOfBirth:(nullable NSString *)dateOfBirth
gender:(nullable NSString *)gender
city:(nullable NSString *)city
state:(nullable NSString *)state
zip:(nullable NSString *)zip
country:(nullable NSString *)country
{
if (!initialized){
[FBSDKUserDataStore initAndWait];
}
NSMutableDictionary *ud = [[NSMutableDictionary alloc] init];
if (email != nil) {
ud[FBSDKEmail] = email;
}
if (firstName != nil) {
ud[FBSDKFirstName] = firstName;
}
if (lastName != nil) {
ud[FBSDKLastName] = lastName;
}
if (phone != nil) {
ud[FBSDKPhone] = phone;
}
if (dateOfBirth != nil) {
ud[FBSDKDateOfBirth] = dateOfBirth;
}
if (gender != nil) {
ud[FBSDKGender] = gender;
}
if (city != nil) {
ud[FBSDKCity] = city;
}
if (state != nil) {
ud[FBSDKState] = state;
}
if (zip != nil) {
ud[FBSDKZip] = zip;
}
if (country != nil) {
ud[FBSDKCountry] = country;
}
hashedUserData = [FBSDKUserDataStore hashUserData:ud];
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:(hashedUserData) forKey:(USER_DATA_KEY)];
}
+ (NSString *)getHashedUserData
{
if (!initialized){
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
logEntry:@"initStore should have been called before calling setUserID"];
[FBSDKUserDataStore initAndWait];
}
return hashedUserData;
}
+ (NSString *)hashUserData:(NSDictionary *)ud
{
if (ud == nil){
return nil;
}
NSMutableDictionary *encryptUserData = [NSMutableDictionary dictionaryWithCapacity:[ud count]];
for (NSString *key in ud){
NSString *const value = ud[key];
if ([FBSDKUserDataStore maybeSHA256Hashed:value]){
encryptUserData[key] = value;
} else {
NSString *const normalizedValue = [FBSDKUserDataStore normalizeData:key data:value];
NSString *const encryptedValue = [FBSDKUserDataStore encryptData:normalizedValue];
if (encryptedValue != nil){
encryptUserData[key] = encryptedValue;
}
}
}
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:encryptUserData
options:0
error:&error];
if (jsonData){
return [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
} else {
[FBSDKAppEventsUtility logAndNotify:[NSString stringWithFormat:@"invalid json object: %@", error]];
return nil;
}
}
+ (NSString *)encryptData:(NSString *)data
{
if (data == nil || [data length] == 0){
return nil;
}
return [FBSDKUtility SHA256Hash:data];
}
+ (NSString *)normalizeData:(NSString *)type data:(NSString *)data{
NSString *normalizedData = @"";
if ([type isEqualToString:FBSDKEmail] || [type isEqualToString:FBSDKFirstName]
|| [type isEqualToString:FBSDKLastName] || [type isEqualToString:FBSDKCity]
|| [type isEqualToString:FBSDKState] || [type isEqualToString:FBSDKCountry]) {
normalizedData = [data stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
normalizedData = [normalizedData lowercaseString];
} else if ([type isEqualToString:FBSDKPhone]){
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^0-9]"
options:NSRegularExpressionCaseInsensitive
error:&error
];
normalizedData = [regex stringByReplacingMatchesInString:data
options:0
range:NSMakeRange(0, [data length])
withTemplate:@""
];
} else if ([type isEqualToString:FBSDKGender]){
NSString *temp = [data stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
temp = [temp lowercaseString];
normalizedData = [temp length] > 0 ? [temp substringToIndex:1]: @"";
}
return normalizedData;
}
+ (BOOL)maybeSHA256Hashed:(NSString *)data
{
NSRange range = [data rangeOfString:@"[A-Fa-f0-9]{64}" options:NSRegularExpressionSearch];
return ([data length] == 64) && (range.location != NSNotFound);
}
@end

View File

@ -22,29 +22,29 @@
/** /**
Decodes a base-64 encoded string. Decodes a base-64 encoded string.
@param string The base-64 encoded string. - Parameter string: The base-64 encoded string.
@return NSData containing the decoded bytes. - Returns: NSData containing the decoded bytes.
*/ */
+ (NSData *)decodeAsData:(NSString *)string; + (NSData *)decodeAsData:(NSString *)string;
/** /**
Decodes a base-64 encoded string into a string. Decodes a base-64 encoded string into a string.
@param string The base-64 encoded string. - Parameter string: The base-64 encoded string.
@return NSString with the decoded UTF-8 value. - Returns: NSString with the decoded UTF-8 value.
*/ */
+ (NSString *)decodeAsString:(NSString *)string; + (NSString *)decodeAsString:(NSString *)string;
/** /**
Encodes data into a string. Encodes data into a string.
@param data The data to be encoded. - Parameter data: The data to be encoded.
@return The base-64 encoded string. - Returns: The base-64 encoded string.
*/ */
+ (NSString *)encodeData:(NSData *)data; + (NSString *)encodeData:(NSData *)data;
/** /**
Encodes string into a base-64 representation. Encodes string into a base-64 representation.
@param string The string to be encoded. - Parameter string: The string to be encoded.
@return The base-64 encoded string. - Returns: The base-64 encoded string.
*/ */
+ (NSString *)encodeString:(NSString *)string; + (NSString *)encodeString:(NSString *)string;

View File

@ -290,7 +290,7 @@ static const struct
if ([invalidObject isKindOfClass:[NSData class]]) { if ([invalidObject isKindOfClass:[NSData class]]) {
NSData *data = (NSData *)invalidObject; NSData *data = (NSData *)invalidObject;
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
if (didAddToPasteboard || !enablePasteboard || !self->_pasteboard || (data.length < self->_dataLengthThreshold)) { if (didAddToPasteboard || !enablePasteboard || !_pasteboard || (data.length < _dataLengthThreshold)) {
dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.isBase64] = @YES; dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.isBase64] = @YES;
dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.tag] = dataTag; dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.tag] = dataTag;
[FBSDKInternalUtility dictionary:dictionary [FBSDKInternalUtility dictionary:dictionary
@ -299,18 +299,18 @@ static const struct
} else { } else {
dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.isPasteboard] = @YES; dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.isPasteboard] = @YES;
dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.tag] = dataTag; dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.tag] = dataTag;
dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.value] = self->_pasteboard.name; dictionary[FBSDKBridgeAPIProtocolNativeV1DataKeys.value] = _pasteboard.name;
[self->_pasteboard setData:data forPasteboardType:FBSDKBridgeAPIProtocolNativeV1DataPasteboardKey]; [_pasteboard setData:data forPasteboardType:FBSDKBridgeAPIProtocolNativeV1DataPasteboardKey];
// this version of the protocol only supports a single item on the pasteboard, so if when we add an item, make // this version of the protocol only supports a single item on the pasteboard, so if when we add an item, make
// sure we don't add another item // sure we don't add another item
didAddToPasteboard = YES; didAddToPasteboard = YES;
// if we are adding this to the general pasteboard, then we want to remove it when we are done with the share. // if we are adding this to the general pasteboard, then we want to remove it when we are done with the share.
// the Facebook app will not clear the value with this version of the protocol, so we should do it when the app // the Facebook app will not clear the value with this version of the protocol, so we should do it when the app
// becomes active again // becomes active again
NSString *pasteboardName = self->_pasteboard.name; NSString *pasteboardName = _pasteboard.name;
if ([pasteboardName isEqualToString:UIPasteboardNameGeneral] || if ([pasteboardName isEqualToString:UIPasteboardNameGeneral] ||
[pasteboardName isEqualToString:UIPasteboardNameFind]) { [pasteboardName isEqualToString:UIPasteboardNameFind]) {
[[self class] clearData:data fromPasteboardOnApplicationDidBecomeActive:self->_pasteboard]; [[self class] clearData:data fromPasteboardOnApplicationDidBecomeActive:_pasteboard];
} }
} }
return dictionary; return dictionary;

View File

@ -1,25 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKAppLinkReturnToRefererView.h"
@interface FBSDKAppLinkReturnToRefererView (Internal)
- (CGFloat)statusBarHeight;
@end

View File

@ -1,40 +0,0 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKAppLink.h"
FOUNDATION_EXPORT NSString *const FBSDKAppLinkDataParameterName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkTargetKeyName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkUserAgentKeyName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkExtrasKeyName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkVersionKeyName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkRefererAppLink;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkRefererAppName;
FOUNDATION_EXPORT NSString *const FBSDKAppLinkRefererUrl;
@interface FBSDKAppLink (Internal)
+ (instancetype)appLinkWithSourceURL:(NSURL *)sourceURL
targets:(NSArray<FBSDKAppLinkTarget *> *)targets
webURL:(NSURL *)webURL
isBackToReferrer:(BOOL)isBackToReferrer;
/*! return if this AppLink is to go back to referrer. */
@property (nonatomic, assign, readonly, getter=isBackToReferrer) BOOL backToReferrer;
@end

Some files were not shown because too many files have changed in this diff Show More