pod install facebook sdk
This commit is contained in:
parent
d89924d5a2
commit
58a8d5f8ce
@ -45,6 +45,6 @@ pod 'FirebaseCrashlytics'
|
|||||||
pod 'Firebase/AnalyticsWithoutAdIdSupport'
|
pod 'Firebase/AnalyticsWithoutAdIdSupport'
|
||||||
pod 'FirebaseAuth'
|
pod 'FirebaseAuth'
|
||||||
pod 'FirebaseFirestore'
|
pod 'FirebaseFirestore'
|
||||||
|
pod 'FacebookCore'
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -823,6 +823,14 @@ PODS:
|
|||||||
- BoringSSL-GRPC/Interface (= 0.0.32)
|
- BoringSSL-GRPC/Interface (= 0.0.32)
|
||||||
- BoringSSL-GRPC/Interface (0.0.32)
|
- BoringSSL-GRPC/Interface (0.0.32)
|
||||||
- DeviceKit (5.2.2)
|
- DeviceKit (5.2.2)
|
||||||
|
- FacebookCore (0.9.0):
|
||||||
|
- FBSDKCoreKit (~> 5.0)
|
||||||
|
- FBSDKCoreKit (5.15.1):
|
||||||
|
- FBSDKCoreKit/Basics (= 5.15.1)
|
||||||
|
- FBSDKCoreKit/Core (= 5.15.1)
|
||||||
|
- FBSDKCoreKit/Basics (5.15.1)
|
||||||
|
- FBSDKCoreKit/Core (5.15.1):
|
||||||
|
- FBSDKCoreKit/Basics
|
||||||
- Firebase/AnalyticsWithoutAdIdSupport (10.23.0):
|
- Firebase/AnalyticsWithoutAdIdSupport (10.23.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseAnalytics/WithoutAdIdSupport (~> 10.23.0)
|
- FirebaseAnalytics/WithoutAdIdSupport (~> 10.23.0)
|
||||||
@ -1038,6 +1046,7 @@ PODS:
|
|||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Alamofire
|
- Alamofire
|
||||||
- DeviceKit
|
- DeviceKit
|
||||||
|
- FacebookCore
|
||||||
- Firebase/AnalyticsWithoutAdIdSupport
|
- Firebase/AnalyticsWithoutAdIdSupport
|
||||||
- FirebaseAuth
|
- FirebaseAuth
|
||||||
- FirebaseCrashlytics
|
- FirebaseCrashlytics
|
||||||
@ -1053,6 +1062,8 @@ SPEC REPOS:
|
|||||||
- Alamofire
|
- Alamofire
|
||||||
- BoringSSL-GRPC
|
- BoringSSL-GRPC
|
||||||
- DeviceKit
|
- DeviceKit
|
||||||
|
- FacebookCore
|
||||||
|
- FBSDKCoreKit
|
||||||
- Firebase
|
- Firebase
|
||||||
- FirebaseAnalytics
|
- FirebaseAnalytics
|
||||||
- FirebaseAppCheckInterop
|
- FirebaseAppCheckInterop
|
||||||
@ -1089,6 +1100,8 @@ SPEC CHECKSUMS:
|
|||||||
Alamofire: 3ca42e259043ee0dc5c0cdd76c4bc568b8e42af7
|
Alamofire: 3ca42e259043ee0dc5c0cdd76c4bc568b8e42af7
|
||||||
BoringSSL-GRPC: 1e2348957acdbcad360b80a264a90799984b2ba6
|
BoringSSL-GRPC: 1e2348957acdbcad360b80a264a90799984b2ba6
|
||||||
DeviceKit: e36aaf2a0d142ef0b4fac2007649a4414af234be
|
DeviceKit: e36aaf2a0d142ef0b4fac2007649a4414af234be
|
||||||
|
FacebookCore: ba86524b66cfa86d0f8e65d08faa8504a9f732dd
|
||||||
|
FBSDKCoreKit: 1d5acf7c9d7a2f92bb1a242dc60cae5b7adb91df
|
||||||
Firebase: 333ec7c6b12fa09c77b5162cda6b862102211d50
|
Firebase: 333ec7c6b12fa09c77b5162cda6b862102211d50
|
||||||
FirebaseAnalytics: 45f6e2e5ef8ccbb90be73ae983c3b20fa78837f7
|
FirebaseAnalytics: 45f6e2e5ef8ccbb90be73ae983c3b20fa78837f7
|
||||||
FirebaseAppCheckInterop: a1955ce8c30f38f87e7d091630e871e91154d65d
|
FirebaseAppCheckInterop: a1955ce8c30f38f87e7d091630e871e91154d65d
|
||||||
@ -1120,6 +1133,6 @@ SPEC CHECKSUMS:
|
|||||||
SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6
|
SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6
|
||||||
TZImagePickerController: f1c9f1cae6ac0e30b31aaa9698f9bf4a7cf5b84f
|
TZImagePickerController: f1c9f1cae6ac0e30b31aaa9698f9bf4a7cf5b84f
|
||||||
|
|
||||||
PODFILE CHECKSUM: 3d5feb483f1e0625e790607cb3a94eeb8fca4d45
|
PODFILE CHECKSUM: 348e68c1ad5662db981acd0c0690ba09e3436445
|
||||||
|
|
||||||
COCOAPODS: 1.15.2
|
COCOAPODS: 1.15.2
|
||||||
|
|||||||
865
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/FBSDKAppEvents.h
generated
Normal file
865
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/FBSDKAppEvents.h
generated
Normal file
@ -0,0 +1,865 @@
|
|||||||
|
// 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>
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#import <WebKit/WebKit.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUCK
|
||||||
|
#import <FBSDKCoreKit/FBSDKGraphRequestConnection.h>
|
||||||
|
#else
|
||||||
|
#import "FBSDKGraphRequestConnection.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@class FBSDKAccessToken;
|
||||||
|
@class FBSDKGraphRequest;
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||||
|
|
||||||
|
/** NSNotificationCenter name indicating a result of a failed log flush attempt. The posted object will be an NSError instance. */
|
||||||
|
FOUNDATION_EXPORT NSNotificationName const FBSDKAppEventsLoggingResultNotification
|
||||||
|
NS_SWIFT_NAME(AppEventsLoggingResult);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/** NSNotificationCenter name indicating a result of a failed log flush attempt. The posted object will be an NSError instance. */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsLoggingResultNotification
|
||||||
|
NS_SWIFT_NAME(AppEventsLoggingResultNotification);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** optional plist key ("FacebookLoggingOverrideAppID") for setting `loggingOverrideAppID` */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsOverrideAppIDBundleKey
|
||||||
|
NS_SWIFT_NAME(AppEventsOverrideAppIDBundleKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
NS_ENUM (NSUInteger, FBSDKAppEventsFlushBehavior)
|
||||||
|
|
||||||
|
Specifies when `FBSDKAppEvents` sends log events to the server.
|
||||||
|
|
||||||
|
*/
|
||||||
|
typedef NS_ENUM(NSUInteger, FBSDKAppEventsFlushBehavior)
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Flush automatically: periodically (once a minute or every 100 logged events) and always at app reactivation. */
|
||||||
|
FBSDKAppEventsFlushBehaviorAuto = 0,
|
||||||
|
|
||||||
|
/** Only flush when the `flush` method is called. When an app is moved to background/terminated, the
|
||||||
|
events are persisted and re-established at activation, but they will only be written with an
|
||||||
|
explicit call to `flush`. */
|
||||||
|
FBSDKAppEventsFlushBehaviorExplicitOnly,
|
||||||
|
} NS_SWIFT_NAME(AppEvents.FlushBehavior);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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_SWIFT_NAME(AppEvents.ProductAvailability);
|
||||||
|
|
||||||
|
/**
|
||||||
|
NS_ENUM(NSUInteger, FBSDKProductCondition)
|
||||||
|
Specifies product condition for Product Catalog product item update
|
||||||
|
*/
|
||||||
|
typedef NS_ENUM(NSUInteger, FBSDKProductCondition)
|
||||||
|
{
|
||||||
|
FBSDKProductConditionNew = 0,
|
||||||
|
FBSDKProductConditionRefurbished,
|
||||||
|
FBSDKProductConditionUsed,
|
||||||
|
} NS_SWIFT_NAME(AppEvents.ProductCondition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// typedef for FBSDKAppEventName
|
||||||
|
typedef NSString *const FBSDKAppEventName NS_TYPED_EXTENSIBLE_ENUM NS_SWIFT_NAME(AppEvents.Name);
|
||||||
|
|
||||||
|
/** Log this event when the user has achieved a level in the app. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameAchievedLevel;
|
||||||
|
|
||||||
|
/** Log this event when the user has entered their payment info. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameAddedPaymentInfo;
|
||||||
|
|
||||||
|
/** Log this event when the user has added an item to their cart. The valueToSum passed to logEvent should be the item's price. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameAddedToCart;
|
||||||
|
|
||||||
|
/** Log this event when the user has added an item to their wishlist. The valueToSum passed to logEvent should be the item's price. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameAddedToWishlist;
|
||||||
|
|
||||||
|
/** Log this event when a user has completed registration with the app. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameCompletedRegistration;
|
||||||
|
|
||||||
|
/** Log this event when the user has completed a tutorial in the app. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameCompletedTutorial;
|
||||||
|
|
||||||
|
/** Log this event when the user has entered the checkout process. The valueToSum passed to logEvent should be the total price in the cart. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameInitiatedCheckout;
|
||||||
|
|
||||||
|
/** Log this event when the user has completed a transaction. The valueToSum passed to logEvent should be the total price of the transaction. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNamePurchased;
|
||||||
|
|
||||||
|
/** Log this event when the user has rated an item in the app. The valueToSum passed to logEvent should be the numeric rating. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameRated;
|
||||||
|
|
||||||
|
/** Log this event when a user has performed a search within the app. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameSearched;
|
||||||
|
|
||||||
|
/** Log this event when the user has spent app credits. The valueToSum passed to logEvent should be the number of credits spent. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameSpentCredits;
|
||||||
|
|
||||||
|
/** Log this event when the user has unlocked an achievement in the app. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameUnlockedAchievement;
|
||||||
|
|
||||||
|
/** Log this event when a user has viewed a form of content in the app. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameViewedContent;
|
||||||
|
|
||||||
|
/** A telephone/SMS, email, chat or other type of contact between a customer and your business. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameContact;
|
||||||
|
|
||||||
|
/** The customization of products through a configuration tool or other application your business owns. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameCustomizeProduct;
|
||||||
|
|
||||||
|
/** The donation of funds to your organization or cause. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName 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). */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameFindLocation;
|
||||||
|
|
||||||
|
/** The booking of an appointment to visit one of your locations. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameSchedule;
|
||||||
|
|
||||||
|
/** The subsequent subscriptions after the start of a paid subscription for a product or service you offer. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameSubscriptionHeartbeat __attribute((deprecated("This attribute is no longer used.")));
|
||||||
|
|
||||||
|
/** The start of a free trial of a product or service you offer (example: trial subscription). */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameStartTrial;
|
||||||
|
|
||||||
|
/** The submission of an application for a product, service or program you offer (example: credit card, educational program or job). */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameSubmitApplication;
|
||||||
|
|
||||||
|
/** The start of a paid subscription for a product or service you offer. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameSubscribe;
|
||||||
|
|
||||||
|
/** Log this event when the user views an ad. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameAdImpression;
|
||||||
|
|
||||||
|
/** Log this event when the user clicks an ad. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventName FBSDKAppEventNameAdClick;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// typedef for FBSDKAppEventParameterName
|
||||||
|
typedef NSString *const FBSDKAppEventParameterName NS_TYPED_EXTENSIBLE_ENUM NS_SWIFT_NAME(AppEvents.ParameterName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter key used to specify data for the one or more pieces of content being logged about.
|
||||||
|
* Data should be a JSON encoded string.
|
||||||
|
* Example:
|
||||||
|
* "[{\"id\": \"1234\", \"quantity\": 2, \"item_price\": 5.99}, {\"id\": \"5678\", \"quantity\": 1, \"item_price\": 9.99}]"
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameContent;
|
||||||
|
|
||||||
|
/** Parameter key used to specify an ID for the specific piece of content being logged about. Could be an EAN, article identifier, etc., depending on the nature of the app. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameContentID;
|
||||||
|
|
||||||
|
/** Parameter key used to specify a generic content type/family for the logged event, e.g. "music", "photo", "video". Options to use will vary based upon what the app is all about. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameContentType;
|
||||||
|
|
||||||
|
/** Parameter key used to specify currency used with logged event. E.g. "USD", "EUR", "GBP". See ISO-4217 for specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameCurrency;
|
||||||
|
|
||||||
|
/** Parameter key used to specify a description appropriate to the event being logged. E.g., the name of the achievement unlocked in the `FBAppEventNameAchievementUnlocked` event. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameDescription;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the level achieved in a `FBAppEventNameAchieved` event. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameLevel;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the maximum rating available for the `FBAppEventNameRate` event. E.g., "5" or "10". */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameMaxRatingValue;
|
||||||
|
|
||||||
|
/** Parameter key used to specify how many items are being processed for an `FBAppEventNameInitiatedCheckout` or `FBAppEventNamePurchased` event. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameNumItems;
|
||||||
|
|
||||||
|
/** Parameter key used to specify whether payment info is available for the `FBAppEventNameInitiatedCheckout` event. `FBSDKAppEventParameterValueYes` and `FBSDKAppEventParameterValueNo` are good canonical values to use for this parameter. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNamePaymentInfoAvailable;
|
||||||
|
|
||||||
|
/** Parameter key used to specify method user has used to register for the app, e.g., "Facebook", "email", "Twitter", etc */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameRegistrationMethod;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the string provided by the user for a search operation. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameSearchString;
|
||||||
|
|
||||||
|
/** Parameter key used to specify whether the activity being logged about was successful or not. `FBSDKAppEventParameterValueYes` and `FBSDKAppEventParameterValueNo` are good canonical values to use for this parameter. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameSuccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@methodgroup Predefined event name parameters for common additional information to accompany events logged through the `logProductItem` method on `FBSDKAppEvents`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// typedef for FBSDKAppEventParameterProduct
|
||||||
|
typedef NSString *const FBSDKAppEventParameterProduct NS_TYPED_EXTENSIBLE_ENUM NS_SWIFT_NAME(AppEvents.ParameterProduct);
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's category. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductCategory;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's custom label 0. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductCustomLabel0;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's custom label 1. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductCustomLabel1;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's custom label 2. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductCustomLabel2;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's custom label 3. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductCustomLabel3;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's custom label 4. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductCustomLabel4;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app URL for iOS. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIOSUrl;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app ID for iOS App Store. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIOSAppStoreID;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app name for iOS. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIOSAppName;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app URL for iPhone. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIPhoneUrl;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app ID for iPhone App Store. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIPhoneAppStoreID;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app name for iPhone. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIPhoneAppName;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app URL for iPad. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIPadUrl;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app ID for iPad App Store. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIPadAppStoreID;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app name for iPad. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkIPadAppName;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app URL for Android. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkAndroidUrl;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink fully-qualified package name for intent generation. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkAndroidPackage;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app name for Android. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkAndroidAppName;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app URL for Windows Phone. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkWindowsPhoneUrl;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app ID, as a GUID, for App Store. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkWindowsPhoneAppID;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the product item's AppLink app name for Windows Phone. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterProduct FBSDKAppEventParameterProductAppLinkWindowsPhoneAppName;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@methodgroup Predefined values to assign to event parameters that accompany events logged through the `logEvent` family
|
||||||
|
of methods on `FBSDKAppEvents`. Common event parameters are provided in the `FBSDKAppEventParameterName*` constants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// typedef for FBSDKAppEventParameterValue
|
||||||
|
typedef NSString *const FBSDKAppEventParameterValue NS_TYPED_EXTENSIBLE_ENUM NS_SWIFT_NAME(AppEvents.ParameterValue);
|
||||||
|
|
||||||
|
/** Yes-valued parameter value to be used with parameter keys that need a Yes/No value */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterValue FBSDKAppEventParameterValueYes;
|
||||||
|
|
||||||
|
/** No-valued parameter value to be used with parameter keys that need a Yes/No value */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterValue FBSDKAppEventParameterValueNo;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the type of ad in an FBSDKAppEventNameAdImpression
|
||||||
|
* or FBSDKAppEventNameAdClick event.
|
||||||
|
* E.g. "banner", "interstitial", "rewarded_video", "native" */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameAdType;
|
||||||
|
|
||||||
|
/** Parameter key used to specify the unique ID for all events within a subscription
|
||||||
|
* in an FBSDKAppEventNameSubscribe or FBSDKAppEventNameStartTrial event. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventParameterName FBSDKAppEventParameterNameOrderID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@methodgroup Predefined values to assign to user data store
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// typedef for FBSDKAppEventUserDataType
|
||||||
|
typedef NSString *const FBSDKAppEventUserDataType NS_TYPED_EXTENSIBLE_ENUM NS_SWIFT_NAME(AppEvents.UserDataType);
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's email. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventEmail;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's first name. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventFirstName;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's last name. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventLastName;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's phone. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventPhone;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's date of birth. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventDateOfBirth;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's gender. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventGender;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's city. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventCity;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's state. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventState;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's zip. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventZip;
|
||||||
|
|
||||||
|
/** Parameter key used to specify user's country. */
|
||||||
|
FOUNDATION_EXPORT FBSDKAppEventUserDataType FBSDKAppEventCountry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
|
||||||
|
Client-side event logging for specialized application analytics available through Facebook App Insights
|
||||||
|
and for use with Facebook Ads conversion tracking and optimization.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The `FBSDKAppEvents` static class has a few related roles:
|
||||||
|
|
||||||
|
+ Logging predefined and application-defined events to Facebook App Insights with a
|
||||||
|
numeric value to sum across a large number of events, and an optional set of key/value
|
||||||
|
parameters that define "segments" for this event (e.g., 'purchaserStatus' : 'frequent', or
|
||||||
|
'gamerLevel' : 'intermediate')
|
||||||
|
|
||||||
|
+ Logging events to later be used for ads optimization around lifetime value.
|
||||||
|
|
||||||
|
+ Methods that control the way in which events are flushed out to the Facebook servers.
|
||||||
|
|
||||||
|
Here are some important characteristics of the logging mechanism provided by `FBSDKAppEvents`:
|
||||||
|
|
||||||
|
+ Events are not sent immediately when logged. They're cached and flushed out to the Facebook servers
|
||||||
|
in a number of situations:
|
||||||
|
- when an event count threshold is passed (currently 100 logged events).
|
||||||
|
- when a time threshold is passed (currently 15 seconds).
|
||||||
|
- when an app has gone to background and is then brought back to the foreground.
|
||||||
|
|
||||||
|
+ Events will be accumulated when the app is in a disconnected state, and sent when the connection is
|
||||||
|
restored and one of the above 'flush' conditions are met.
|
||||||
|
|
||||||
|
+ The `FBSDKAppEvents` class is thread-safe in that events may be logged from any of the app's threads.
|
||||||
|
|
||||||
|
+ The developer can set the `flushBehavior` on `FBSDKAppEvents` to force the flushing of events to only
|
||||||
|
occur on an explicit call to the `flush` method.
|
||||||
|
|
||||||
|
+ The developer can turn on console debug output for event logging and flushing to the server by using
|
||||||
|
the `FBSDKLoggingBehaviorAppEvents` value in `[FBSettings setLoggingBehavior:]`.
|
||||||
|
|
||||||
|
Some things to note when logging events:
|
||||||
|
|
||||||
|
+ There is a limit on the number of unique event names an app can use, on the order of 1000.
|
||||||
|
+ There is a limit to the number of unique parameter names in the provided parameters that can
|
||||||
|
be used per event, on the order of 25. This is not just for an individual call, but for all
|
||||||
|
invocations for that eventName.
|
||||||
|
+ Event names and parameter names (the keys in the NSDictionary) must be between 2 and 40 characters, and
|
||||||
|
must consist of alphanumeric characters, _, -, or spaces.
|
||||||
|
+ The length of each parameter value can be no more than on the order of 100 characters.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(AppEvents)
|
||||||
|
@interface FBSDKAppEvents : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control over event batching/flushing
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
The current event flushing behavior specifying when events are sent back to Facebook servers.
|
||||||
|
*/
|
||||||
|
@property (class, nonatomic, assign) FBSDKAppEventsFlushBehavior flushBehavior;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set the 'override' App ID for App Event logging.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
In some cases, apps want to use one Facebook App ID for login and social presence and another
|
||||||
|
for App Event logging. (An example is if multiple apps from the same company share an app ID for login, but
|
||||||
|
want distinct logging.) By default, this value is `nil`, and defers to the `FBSDKAppEventsOverrideAppIDBundleKey`
|
||||||
|
plist value. If that's not set, it defaults to `[FBSDKSettings appID]`.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
@property (class, nonatomic, copy, nullable) NSString *loggingOverrideAppID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The custom user ID to associate with all app events.
|
||||||
|
|
||||||
|
The userID is persisted until it is cleared by passing nil.
|
||||||
|
*/
|
||||||
|
@property (class, nonatomic, copy, nullable) NSString *userID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic event logging
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Log an event with just an eventName.
|
||||||
|
|
||||||
|
@param eventName The name of the event to record. Limitations on number of events and name length
|
||||||
|
are given in the `FBSDKAppEvents` documentation.
|
||||||
|
|
||||||
|
*/
|
||||||
|
+ (void)logEvent:(FBSDKAppEventName)eventName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
the cumulative and average value of this amount.
|
||||||
|
*/
|
||||||
|
+ (void)logEvent:(FBSDKAppEventName)eventName
|
||||||
|
valueToSum:(double)valueToSum;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Log an event with an eventName and a set of key/value pairs in the parameters dictionary.
|
||||||
|
Parameter limitations are described above.
|
||||||
|
|
||||||
|
@param 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.
|
||||||
|
|
||||||
|
@param 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
|
||||||
|
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
|
||||||
|
are provided in `FBSDKAppEventParameterName*` constants.
|
||||||
|
*/
|
||||||
|
+ (void)logEvent:(FBSDKAppEventName)eventName
|
||||||
|
parameters:(NSDictionary<FBSDKAppEventParameterName, id> *)parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param 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.
|
||||||
|
|
||||||
|
@param valueToSum Amount to be aggregated into all events of this eventName, and App Insights will report
|
||||||
|
the cumulative and average value of this amount.
|
||||||
|
|
||||||
|
@param 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
|
||||||
|
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
|
||||||
|
are provided in `FBSDKAppEventParameterName*` constants.
|
||||||
|
|
||||||
|
*/
|
||||||
|
+ (void)logEvent:(FBSDKAppEventName)eventName
|
||||||
|
valueToSum:(double)valueToSum
|
||||||
|
parameters:(NSDictionary<FBSDKAppEventParameterName, id> *)parameters;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
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. Providing session lets the developer
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param 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
|
||||||
|
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
|
||||||
|
are provided in `FBSDKAppEventParameterName*` constants.
|
||||||
|
|
||||||
|
@param accessToken The optional access token to log the event as.
|
||||||
|
*/
|
||||||
|
+ (void)logEvent:(FBSDKAppEventName)eventName
|
||||||
|
valueToSum:(nullable NSNumber *)valueToSum
|
||||||
|
parameters:(NSDictionary<FBSDKAppEventParameterName, id> *)parameters
|
||||||
|
accessToken:(nullable FBSDKAccessToken *)accessToken;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Purchase logging
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
specific values. One reference for these is <http://en.wikipedia.org/wiki/ISO_4217>.
|
||||||
|
|
||||||
|
|
||||||
|
This event immediately triggers a flush of the `FBSDKAppEvents` event queue, unless the `flushBehavior` is set
|
||||||
|
to `FBSDKAppEventsFlushBehaviorExplicitOnly`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
+ (void)logPurchase:(double)purchaseAmount
|
||||||
|
currency:(NSString *)currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Log a purchase of the specified amount, in the specified currency, also providing a set of
|
||||||
|
additional characteristics describing the purchase.
|
||||||
|
|
||||||
|
@param 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).
|
||||||
|
|
||||||
|
@param 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>.
|
||||||
|
|
||||||
|
@param 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
|
||||||
|
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
|
||||||
|
are provided in `FBSDKAppEventParameterName*` constants.
|
||||||
|
|
||||||
|
|
||||||
|
This event immediately triggers a flush of the `FBSDKAppEvents` event queue, unless the `flushBehavior` is set
|
||||||
|
to `FBSDKAppEventsFlushBehaviorExplicitOnly`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
+ (void)logPurchase:(double)purchaseAmount
|
||||||
|
currency:(NSString *)currency
|
||||||
|
parameters:(NSDictionary<NSString *, id> *)parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param 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).
|
||||||
|
|
||||||
|
@param 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>.
|
||||||
|
|
||||||
|
@param 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
|
||||||
|
parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names
|
||||||
|
are provided in `FBSDKAppEventParameterName*` constants.
|
||||||
|
|
||||||
|
@param 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
|
||||||
|
to `FBSDKAppEventsFlushBehaviorExplicitOnly`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
+ (void)logPurchase:(double)purchaseAmount
|
||||||
|
currency:(NSString *)currency
|
||||||
|
parameters:(NSDictionary<NSString *, id> *)parameters
|
||||||
|
accessToken:(nullable FBSDKAccessToken *)accessToken;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Push Notifications Logging
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Log an app event that tracks that the application was open via Push Notification.
|
||||||
|
|
||||||
|
@param payload Notification payload received via `UIApplicationDelegate`.
|
||||||
|
*/
|
||||||
|
+ (void)logPushNotificationOpen:(NSDictionary *)payload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Log an app event that tracks that a custom action was taken from a push notification.
|
||||||
|
|
||||||
|
@param payload Notification payload received via `UIApplicationDelegate`.
|
||||||
|
@param action Name of the action that was taken.
|
||||||
|
*/
|
||||||
|
+ (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:(nullable NSString *)gtin
|
||||||
|
mpn:(nullable NSString *)mpn
|
||||||
|
brand:(nullable NSString *)brand
|
||||||
|
parameters:(nullable NSDictionary<NSString *, id> *)parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Notifies the events system that the app has launched and, when appropriate, logs an "activated app" event.
|
||||||
|
This function is called automatically from FBSDKApplicationDelegate applicationDidBecomeActive, unless
|
||||||
|
one overrides 'FacebookAutoLogAppEventsEnabled' key to false in the project info plist file.
|
||||||
|
In case 'FacebookAutoLogAppEventsEnabled' is set to false, then it should typically be placed in the
|
||||||
|
app delegates' `applicationDidBecomeActive:` method.
|
||||||
|
|
||||||
|
This method also takes care of logging the event indicating the first time this app has been launched, which, among other things, is used to
|
||||||
|
track user acquisition and app install ads conversions.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
`activateApp` will not log an event on every app launch, since launches happen every time the app is backgrounded and then foregrounded.
|
||||||
|
"activated app" events will be logged when the app has not been active for more than 60 seconds. This method also causes a "deactivated app"
|
||||||
|
event to be logged when sessions are "completed", and these events are logged with the session length, with an indication of how much
|
||||||
|
time has elapsed between sessions, and with the number of background/foreground interruptions that session had. This data
|
||||||
|
is all visible in your app's App Events Insights.
|
||||||
|
*/
|
||||||
|
+ (void)activateApp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Push Notifications Registration and Uninstall Tracking
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets and sends device token to register the current application for push notifications.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Sets and sends a device token from `NSData` representation that you get from `UIApplicationDelegate.-application:didRegisterForRemoteNotificationsWithDeviceToken:`.
|
||||||
|
|
||||||
|
@param deviceToken Device token data.
|
||||||
|
*/
|
||||||
|
+ (void)setPushNotificationsDeviceToken:(NSData *)deviceToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets and sends device token string to register the current application for push notifications.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Sets and sends a device token string
|
||||||
|
|
||||||
|
@param deviceTokenString Device token string.
|
||||||
|
*/
|
||||||
|
+ (void)setPushNotificationsDeviceTokenString:(NSString *)deviceTokenString
|
||||||
|
NS_SWIFT_NAME(setPushNotificationsDeviceToken(_:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Explicitly kick off flushing of events to Facebook. This is an asynchronous method, but it does initiate an immediate
|
||||||
|
kick off. Server failures will be reported through the NotificationCenter with notification ID `FBSDKAppEventsLoggingResultNotification`.
|
||||||
|
*/
|
||||||
|
+ (void)flush;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a request representing the Graph API call to retrieve a Custom Audience "third party ID" for the app's Facebook user.
|
||||||
|
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.
|
||||||
|
|
||||||
|
The JSON in the request's response will include an "custom_audience_third_party_id" key/value pair, with the value being the ID retrieved.
|
||||||
|
This ID is an encrypted encoding of the Facebook user's ID and the invoking Facebook app ID.
|
||||||
|
Multiple calls with the same user will return different IDs, thus these IDs cannot be used to correlate behavior
|
||||||
|
across devices or applications, and are only meaningful when sent back to Facebook for creating Custom Audiences.
|
||||||
|
|
||||||
|
The ID retrieved represents the Facebook user identified in the following way: if the specified access token is valid,
|
||||||
|
the ID will represent the user associated with that token; otherwise the ID will represent the user logged into the
|
||||||
|
native Facebook app on the device. If there is no native Facebook app, no one is logged into it, or the user has opted out
|
||||||
|
at the iOS level from ad tracking, then a `nil` ID will be returned.
|
||||||
|
|
||||||
|
This method returns `nil` if either the user has opted-out (via iOS) from Ad Tracking, the app itself has limited event usage
|
||||||
|
via the `[FBSDKSettings limitEventAndDataUsage]` flag, or a specific Facebook user cannot be identified.
|
||||||
|
|
||||||
|
@param 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.
|
||||||
|
*/
|
||||||
|
+ (nullable FBSDKGraphRequest *)requestForCustomAudienceThirdPartyIDWithAccessToken:(nullable FBSDKAccessToken *)accessToken;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Clears the custom user ID to associate with all app events.
|
||||||
|
*/
|
||||||
|
+ (void)clearUserID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
NS_SWIFT_NAME(setUser(email:firstName:lastName:phone:dateOfBirth:gender:city:state:zip:country:));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns the set user data else nil
|
||||||
|
*/
|
||||||
|
+ (nullable NSString *)getUserData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Clears the current user data
|
||||||
|
*/
|
||||||
|
+ (void)clearUserData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 data data
|
||||||
|
@param type data type, e.g. FBSDKAppEventEmail, FBSDKAppEventPhone
|
||||||
|
*/
|
||||||
|
+ (void)setUserData:(nullable NSString *)data
|
||||||
|
forType:(FBSDKAppEventUserDataType)type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Clears the current user data of certain type
|
||||||
|
*/
|
||||||
|
+ (void)clearUserDataForType:(FBSDKAppEventUserDataType)type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sends a request to update the properties for the current user, set by `setUserID:`
|
||||||
|
|
||||||
|
You must call `FBSDKAppEvents setUserID:` before making this call.
|
||||||
|
@param properties the custom user properties
|
||||||
|
@param handler the optional completion handler
|
||||||
|
*/
|
||||||
|
+ (void)updateUserProperties:(NSDictionary<NSString *, id> *)properties handler:(nullable FBSDKGraphRequestBlock)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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unity helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Set if the Unity is already initialized
|
||||||
|
|
||||||
|
@param isUnityInit whether Unity is initialized.
|
||||||
|
|
||||||
|
*/
|
||||||
|
+ (void)setIsUnityInit:(BOOL)isUnityInit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Send event binding to Unity
|
||||||
|
*/
|
||||||
|
+ (void)sendEventBindingsToUnity;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
1487
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/FBSDKAppEvents.m
generated
Normal file
1487
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/FBSDKAppEvents.m
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,35 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface FBSDKMetadataIndexer : NSObject
|
||||||
|
|
||||||
|
+ (void)enable;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
329
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/AAM/FBSDKMetadataIndexer.m
generated
Normal file
329
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/AAM/FBSDKMetadataIndexer.m
generated
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKMetadataIndexer.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
#import <sys/sysctl.h>
|
||||||
|
#import <sys/utsname.h>
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKCoreKit+Internal.h"
|
||||||
|
|
||||||
|
static const int FBSDKMetadataIndexerMaxTextLength = 100;
|
||||||
|
static const int FBSDKMetadataIndexerMaxIndicatorLength = 100;
|
||||||
|
static const int FBSDKMetadataIndexerMaxValue = 5;
|
||||||
|
|
||||||
|
static NSString * const FIELD_K = @"k";
|
||||||
|
static NSString * const FIELD_V = @"v";
|
||||||
|
static NSString * const FIELD_K_DELIMITER = @",";
|
||||||
|
|
||||||
|
FBSDKAppEventUserDataType FBSDKAppEventRule1 = @"r1";
|
||||||
|
FBSDKAppEventUserDataType FBSDKAppEventRule2 = @"r2";
|
||||||
|
|
||||||
|
static NSArray<FBSDKAppEventUserDataType> *FBSDKMetadataIndexerKeys;
|
||||||
|
static NSMutableDictionary<NSString *, NSDictionary<NSString *, NSString *> *> *_rules;
|
||||||
|
static NSMutableDictionary<NSString *, NSMutableArray<NSString *> *> *_store;
|
||||||
|
static dispatch_queue_t serialQueue;
|
||||||
|
|
||||||
|
@implementation FBSDKMetadataIndexer
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
FBSDKMetadataIndexerKeys = @[FBSDKAppEventRule1, FBSDKAppEventRule2];
|
||||||
|
serialQueue = dispatch_queue_create("com.facebook.appevents.MetadataIndexer", DISPATCH_QUEUE_SERIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)enable
|
||||||
|
{
|
||||||
|
if (FBSDKAdvertisingTrackingAllowed != [FBSDKAppEventsUtility advertisingTrackingStatus]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *error) {
|
||||||
|
if (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[FBSDKMetadataIndexer setupWithRules:serverConfiguration.AAMRules];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setupWithRules:(NSDictionary<NSString *, id> * _Nullable)rules
|
||||||
|
{
|
||||||
|
if (0 == rules.count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
[FBSDKMetadataIndexer constructRules:rules];
|
||||||
|
[FBSDKMetadataIndexer initStore];
|
||||||
|
|
||||||
|
BOOL isEnabled = NO;
|
||||||
|
for (NSString *key in FBSDKMetadataIndexerKeys) {
|
||||||
|
BOOL isRuleEnabled = (nil != [_rules objectForKey:key]);
|
||||||
|
if (isRuleEnabled) {
|
||||||
|
isEnabled = YES;
|
||||||
|
}
|
||||||
|
if (!isRuleEnabled) {
|
||||||
|
[_store removeObjectForKey:key];
|
||||||
|
[FBSDKUserDataStore setHashData:nil forType:key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEnabled) {
|
||||||
|
[FBSDKMetadataIndexer setupMetadataIndexing];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)initStore
|
||||||
|
{
|
||||||
|
_store = [[NSMutableDictionary alloc] init];
|
||||||
|
for (NSString *key in FBSDKMetadataIndexerKeys) {
|
||||||
|
NSString *data = [FBSDKUserDataStore getHashedDataForType:key];
|
||||||
|
if (data.length > 0) {
|
||||||
|
_store[key] = [NSMutableArray arrayWithArray:[data componentsSeparatedByString:FIELD_K_DELIMITER]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NSString *key in FBSDKMetadataIndexerKeys) {
|
||||||
|
if (!_store[key]) {
|
||||||
|
_store[key] = [[NSMutableArray alloc] init];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)constructRules:(NSDictionary<NSString *, id> * _Nullable)rules
|
||||||
|
{
|
||||||
|
if (!_rules) {
|
||||||
|
_rules = [[NSMutableDictionary alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NSString *key in rules) {
|
||||||
|
NSDictionary<NSString *, NSString *> *value = [FBSDKTypeUtility dictionaryValue:rules[key]];
|
||||||
|
if (value && value[FIELD_K].length > 0 && value[FIELD_V].length > 0) {
|
||||||
|
_rules[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setupMetadataIndexing
|
||||||
|
{
|
||||||
|
void (^block)(UIView *) = ^(UIView *view) {
|
||||||
|
// Indexing when the view is removed from window and conforms to UITextInput, and skip UIFieldEditor, which is an internval view of UITextField
|
||||||
|
if (![view window] && ![NSStringFromClass([view class]) isEqualToString:@"UIFieldEditor"] && [view conformsToProtocol:@protocol(UITextInput)]) {
|
||||||
|
NSString *text = [FBSDKViewHierarchy getText:view];
|
||||||
|
NSString *placeholder = [FBSDKViewHierarchy getHint:view];
|
||||||
|
BOOL secureTextEntry = [self checkSecureTextEntry:view];
|
||||||
|
NSArray<NSString *> *labels = [self getLabelsOfView:view];
|
||||||
|
UIKeyboardType keyboardType = [self getKeyboardType:view];
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
|
||||||
|
[self getMetadataWithText:[self normalizedValue:text]
|
||||||
|
placeholder:[self normalizeField:placeholder]
|
||||||
|
labels:labels
|
||||||
|
secureTextEntry:secureTextEntry
|
||||||
|
inputType:keyboardType];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow) onClass:[UIView class] withBlock:block named:@"metadataIndexingUIView"];
|
||||||
|
|
||||||
|
// iOS 12: UITextField implements didMoveToWindow without calling parent implementation
|
||||||
|
if (@available(iOS 12, *)) {
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow) onClass:[UITextField class] withBlock:block named:@"metadataIndexingUITextField"];
|
||||||
|
} else {
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow) onClass:[UIControl class] withBlock:block named:@"metadataIndexingUIControl"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<UIView *> *)getSiblingViewsOfView:(UIView *)view
|
||||||
|
{
|
||||||
|
NSObject *parent = [FBSDKViewHierarchy getParent:view];
|
||||||
|
if (parent) {
|
||||||
|
NSArray<id> *views = [FBSDKViewHierarchy getChildren:parent];
|
||||||
|
if (views) {
|
||||||
|
NSMutableArray<id> *siblings = [NSMutableArray arrayWithArray:views];
|
||||||
|
[siblings removeObject:view];
|
||||||
|
return [siblings copy];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSString *> *)getLabelsOfView:(UIView *)view
|
||||||
|
{
|
||||||
|
NSMutableArray<NSString *> *labels = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
NSString *placeholder = [self normalizeField:[FBSDKViewHierarchy getHint:view]];
|
||||||
|
if (placeholder) {
|
||||||
|
[labels addObject:placeholder];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSArray<id> *siblingViews = [self getSiblingViewsOfView:view];
|
||||||
|
for (id sibling in siblingViews) {
|
||||||
|
if ([sibling isKindOfClass:[UILabel class]]) {
|
||||||
|
NSString *text = [self normalizeField:[FBSDKViewHierarchy getText:sibling]];
|
||||||
|
if (text) {
|
||||||
|
[labels addObject:text];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [labels copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)checkSecureTextEntry:(UIView *)view
|
||||||
|
{
|
||||||
|
if ([view isKindOfClass:[UITextField class]]) {
|
||||||
|
return ((UITextField *)view).secureTextEntry;
|
||||||
|
}
|
||||||
|
if ([view isKindOfClass:[UITextView class]]) {
|
||||||
|
return ((UITextView *)view).secureTextEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (UIKeyboardType)getKeyboardType:(UIView *)view
|
||||||
|
{
|
||||||
|
if ([view isKindOfClass:[UITextField class]]) {
|
||||||
|
return ((UITextField *)view).keyboardType;
|
||||||
|
}
|
||||||
|
if ([view isKindOfClass:[UITextView class]]) {
|
||||||
|
return ((UITextView *)view).keyboardType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UIKeyboardTypeDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)getMetadataWithText:(NSString *)text
|
||||||
|
placeholder:(NSString *)placeholder
|
||||||
|
labels:(NSArray<NSString *> *)labels
|
||||||
|
secureTextEntry:(BOOL)secureTextEntry
|
||||||
|
inputType:(UIKeyboardType)inputType
|
||||||
|
{
|
||||||
|
if (secureTextEntry ||
|
||||||
|
[placeholder containsString:@"password"] ||
|
||||||
|
text.length == 0 ||
|
||||||
|
text.length > FBSDKMetadataIndexerMaxTextLength ||
|
||||||
|
placeholder.length >= FBSDKMetadataIndexerMaxIndicatorLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NSString *key in _rules) {
|
||||||
|
NSDictionary<NSString *, NSString *> *rule = _rules[key];
|
||||||
|
BOOL isRuleKMatched = [self checkMetadataHint:placeholder matchRuleK:rule[FIELD_K]]
|
||||||
|
|| [self checkMetadataLabels:labels matchRuleK:rule[FIELD_K]];
|
||||||
|
BOOL isRuleVMatched = [self checkMetadataText:text matchRuleV:rule[FIELD_V]];
|
||||||
|
if (isRuleKMatched && isRuleVMatched) {
|
||||||
|
[FBSDKMetadataIndexer checkAndAppendData:text forKey:key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Helper Methods
|
||||||
|
|
||||||
|
+ (void)checkAndAppendData:(NSString *)data
|
||||||
|
forKey:(NSString *)key
|
||||||
|
{
|
||||||
|
NSString *hashData = [FBSDKUtility SHA256Hash:data];
|
||||||
|
dispatch_async(serialQueue, ^{
|
||||||
|
if (hashData.length == 0 || [_store[key] containsObject:hashData]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_store[key].count >= FBSDKMetadataIndexerMaxValue) {
|
||||||
|
[_store[key] removeObjectAtIndex:0];
|
||||||
|
}
|
||||||
|
[_store[key] addObject:hashData];
|
||||||
|
[FBSDKUserDataStore setHashData:[_store[key] componentsJoinedByString:@","]
|
||||||
|
forType:key];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)checkMetadataLabels:(NSArray<NSString *> *)labels
|
||||||
|
matchRuleK:(NSString *)ruleK
|
||||||
|
{
|
||||||
|
for (NSString *label in labels) {
|
||||||
|
if ([self checkMetadataHint:label matchRuleK:ruleK]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)checkMetadataHint:(NSString *)hint
|
||||||
|
matchRuleK:(NSString *)ruleK
|
||||||
|
{
|
||||||
|
if (hint.length > 0 && ruleK) {
|
||||||
|
NSArray<NSString *> *items = [ruleK componentsSeparatedByString:@","];
|
||||||
|
for (NSString *item in items) {
|
||||||
|
if ([hint containsString:item]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)checkMetadataText:(NSString *)text
|
||||||
|
matchRuleV:(NSString *)ruleV
|
||||||
|
{
|
||||||
|
if (text.length > 0 && ruleV) {
|
||||||
|
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:ruleV
|
||||||
|
options:NSRegularExpressionCaseInsensitive
|
||||||
|
error:nil];
|
||||||
|
NSUInteger matches = [regex numberOfMatchesInString:text options:0 range:NSMakeRange(0, text.length)];
|
||||||
|
|
||||||
|
NSString *prunedText = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"+- ()."]] componentsJoinedByString:@""];
|
||||||
|
NSUInteger prunedMatches = [regex numberOfMatchesInString:prunedText options:0 range:NSMakeRange(0, prunedText.length)];
|
||||||
|
|
||||||
|
return matches > 0 || prunedMatches > 0;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)normalizeField:(NSString *)field
|
||||||
|
{
|
||||||
|
if (!field) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[_-]|\\s"
|
||||||
|
options:NSRegularExpressionCaseInsensitive
|
||||||
|
error:nil];
|
||||||
|
return [regex stringByReplacingMatchesInString:field
|
||||||
|
options:0
|
||||||
|
range:NSMakeRange(0, field.length)
|
||||||
|
withTemplate:@""].lowercaseString;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)normalizedValue:(NSString *)value
|
||||||
|
{
|
||||||
|
if (!value) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]].lowercaseString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef void(^FBSDKCodelessSettingLoadBlock)(BOOL isCodelessSetupEnabled, NSError *_Nullable error);
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(CodelessIndexer)
|
||||||
|
@interface FBSDKCodelessIndexer : NSObject
|
||||||
|
|
||||||
|
@property (class, nonatomic, copy, readonly) NSString *extInfo;
|
||||||
|
|
||||||
|
+ (void)enable;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,414 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKCodelessIndexer.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
#import <sys/sysctl.h>
|
||||||
|
#import <sys/utsname.h>
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKCoreKit+Internal.h"
|
||||||
|
#import "FBSDKGraphRequest.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
|
||||||
|
@implementation FBSDKCodelessIndexer
|
||||||
|
|
||||||
|
static BOOL _isCodelessIndexing;
|
||||||
|
static BOOL _isCheckingSession;
|
||||||
|
static BOOL _isCodelessIndexingEnabled;
|
||||||
|
static BOOL _isGestureSet;
|
||||||
|
|
||||||
|
static NSMutableDictionary<NSString *, id> *_codelessSetting;
|
||||||
|
static const NSTimeInterval kTimeout = 4.0;
|
||||||
|
|
||||||
|
static NSString *_deviceSessionID;
|
||||||
|
static NSTimer *_appIndexingTimer;
|
||||||
|
static NSString *_lastTreeHash;
|
||||||
|
|
||||||
|
+ (void)enable
|
||||||
|
{
|
||||||
|
if (_isGestureSet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if TARGET_OS_SIMULATOR
|
||||||
|
[self setupGesture];
|
||||||
|
#else
|
||||||
|
[self loadCodelessSettingWithCompletionBlock:^(BOOL isCodelessSetupEnabled, NSError *error) {
|
||||||
|
if (isCodelessSetupEnabled) {
|
||||||
|
[self setupGesture];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT call this function, it is only called once in the load function
|
||||||
|
+ (void)loadCodelessSettingWithCompletionBlock:(FBSDKCodelessSettingLoadBlock)completionBlock
|
||||||
|
{
|
||||||
|
NSString *appID = [FBSDKSettings appID];
|
||||||
|
if (appID == nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *serverConfigurationLoadingError) {
|
||||||
|
if (!serverConfiguration.codelessEventsEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the defaults
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSString *defaultKey = [NSString stringWithFormat:CODELESS_SETTING_KEY, appID];
|
||||||
|
NSData *data = [defaults objectForKey:defaultKey];
|
||||||
|
if ([data isKindOfClass:[NSData class]]) {
|
||||||
|
NSMutableDictionary<NSString *, id> *codelessSetting = [NSKeyedUnarchiver unarchiveObjectWithData:data];
|
||||||
|
if (codelessSetting) {
|
||||||
|
_codelessSetting = codelessSetting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_codelessSetting) {
|
||||||
|
_codelessSetting = [[NSMutableDictionary alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![self _codelessSetupTimestampIsValid:[_codelessSetting objectForKey:CODELESS_SETTING_TIMESTAMP_KEY]]) {
|
||||||
|
FBSDKGraphRequest *request = [self requestToLoadCodelessSetup:appID];
|
||||||
|
if (request == nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FBSDKGraphRequestConnection *requestConnection = [[FBSDKGraphRequestConnection alloc] init];
|
||||||
|
requestConnection.timeout = kTimeout;
|
||||||
|
[requestConnection addRequest:request completionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *codelessLoadingError) {
|
||||||
|
if (codelessLoadingError) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDictionary<NSString *, id> *resultDictionary = [FBSDKTypeUtility dictionaryValue:result];
|
||||||
|
if (resultDictionary) {
|
||||||
|
BOOL isCodelessSetupEnabled = [FBSDKTypeUtility boolValue:resultDictionary[CODELESS_SETUP_ENABLED_FIELD]];
|
||||||
|
[_codelessSetting setObject:@(isCodelessSetupEnabled) forKey:CODELESS_SETUP_ENABLED_KEY];
|
||||||
|
[_codelessSetting setObject:[NSDate date] forKey:CODELESS_SETTING_TIMESTAMP_KEY];
|
||||||
|
// update the cached copy in user defaults
|
||||||
|
[defaults setObject:[NSKeyedArchiver archivedDataWithRootObject:_codelessSetting] forKey:defaultKey];
|
||||||
|
completionBlock(isCodelessSetupEnabled, codelessLoadingError);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
[requestConnection start];
|
||||||
|
} else {
|
||||||
|
completionBlock([FBSDKTypeUtility boolValue:[_codelessSetting objectForKey:CODELESS_SETUP_ENABLED_KEY]], nil);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (FBSDKGraphRequest *)requestToLoadCodelessSetup:(NSString *)appID
|
||||||
|
{
|
||||||
|
NSString *advertiserID = [FBSDKAppEventsUtility advertiserID];
|
||||||
|
if (!advertiserID) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDictionary<NSString *, NSString *> *parameters = @{
|
||||||
|
@"fields": CODELESS_SETUP_ENABLED_FIELD,
|
||||||
|
@"advertiser_id": advertiserID
|
||||||
|
};
|
||||||
|
|
||||||
|
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:appID
|
||||||
|
parameters:parameters
|
||||||
|
tokenString:nil
|
||||||
|
HTTPMethod:nil
|
||||||
|
flags:FBSDKGraphRequestFlagSkipClientToken | FBSDKGraphRequestFlagDisableErrorRecovery];
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)_codelessSetupTimestampIsValid:(NSDate *)timestamp
|
||||||
|
{
|
||||||
|
return (timestamp != nil && [[NSDate date] timeIntervalSinceDate:timestamp] < CODELESS_SETTING_CACHE_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setupGesture
|
||||||
|
{
|
||||||
|
_isGestureSet = YES;
|
||||||
|
[UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
|
||||||
|
Class class = [UIApplication class];
|
||||||
|
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(motionBegan:withEvent:) onClass:class withBlock:^{
|
||||||
|
if ([FBSDKServerConfigurationManager cachedServerConfiguration].isCodelessEventsEnabled) {
|
||||||
|
[self checkCodelessIndexingSession];
|
||||||
|
}
|
||||||
|
} named:@"motionBegan"];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)checkCodelessIndexingSession
|
||||||
|
{
|
||||||
|
if (_isCheckingSession) return;
|
||||||
|
|
||||||
|
_isCheckingSession = YES;
|
||||||
|
NSDictionary *parameters = @{
|
||||||
|
CODELESS_INDEXING_SESSION_ID_KEY: [self currentSessionDeviceID],
|
||||||
|
CODELESS_INDEXING_EXT_INFO_KEY: [self extInfo]
|
||||||
|
};
|
||||||
|
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
|
||||||
|
initWithGraphPath:[NSString stringWithFormat:@"%@/%@",
|
||||||
|
[FBSDKSettings appID], CODELESS_INDEXING_SESSION_ENDPOINT]
|
||||||
|
parameters:parameters
|
||||||
|
HTTPMethod:FBSDKHTTPMethodPOST];
|
||||||
|
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
|
||||||
|
_isCheckingSession = NO;
|
||||||
|
if ([result isKindOfClass:[NSDictionary class]]) {
|
||||||
|
_isCodelessIndexingEnabled = [((NSDictionary *)result)[CODELESS_INDEXING_STATUS_KEY] boolValue];
|
||||||
|
if (_isCodelessIndexingEnabled) {
|
||||||
|
_lastTreeHash = nil;
|
||||||
|
if (!_appIndexingTimer) {
|
||||||
|
_appIndexingTimer = [NSTimer timerWithTimeInterval:CODELESS_INDEXING_UPLOAD_INTERVAL_IN_SECONDS
|
||||||
|
target:self
|
||||||
|
selector:@selector(startIndexing)
|
||||||
|
userInfo:nil
|
||||||
|
repeats:YES];
|
||||||
|
|
||||||
|
[[NSRunLoop mainRunLoop] addTimer:_appIndexingTimer forMode:NSDefaultRunLoopMode];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_deviceSessionID = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)currentSessionDeviceID
|
||||||
|
{
|
||||||
|
if (!_deviceSessionID) {
|
||||||
|
_deviceSessionID = [NSUUID UUID].UUIDString;
|
||||||
|
}
|
||||||
|
return _deviceSessionID;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)extInfo
|
||||||
|
{
|
||||||
|
struct utsname systemInfo;
|
||||||
|
uname(&systemInfo);
|
||||||
|
NSString *machine = @(systemInfo.machine);
|
||||||
|
NSString *advertiserID = [FBSDKAppEventsUtility advertiserID] ?: @"";
|
||||||
|
machine = machine ?: @"";
|
||||||
|
NSString *debugStatus = [FBSDKAppEventsUtility isDebugBuild] ? @"1" : @"0";
|
||||||
|
#if TARGET_IPHONE_SIMULATOR
|
||||||
|
NSString *isSimulator = @"1";
|
||||||
|
#else
|
||||||
|
NSString *isSimulator = @"0";
|
||||||
|
#endif
|
||||||
|
NSLocale *locale = [NSLocale currentLocale];
|
||||||
|
NSString *languageCode = [locale objectForKey:NSLocaleLanguageCode];
|
||||||
|
NSString *countryCode = [locale objectForKey:NSLocaleCountryCode];
|
||||||
|
NSString *localeString = locale.localeIdentifier;
|
||||||
|
if (languageCode && countryCode) {
|
||||||
|
localeString = [NSString stringWithFormat:@"%@_%@", languageCode, countryCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *extinfo = [FBSDKBasicUtility JSONStringForObject:@[machine,
|
||||||
|
advertiserID,
|
||||||
|
debugStatus,
|
||||||
|
isSimulator,
|
||||||
|
localeString]
|
||||||
|
error:NULL
|
||||||
|
invalidObjectHandler:NULL];
|
||||||
|
|
||||||
|
return extinfo ?: @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)startIndexing {
|
||||||
|
if (!_isCodelessIndexingEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UIApplicationStateActive != [UIApplication sharedApplication].applicationState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If userAgentSuffix begins with Unity, trigger unity code to upload view hierarchy
|
||||||
|
NSString *userAgentSuffix = [FBSDKSettings userAgentSuffix];
|
||||||
|
if (userAgentSuffix != nil && [userAgentSuffix hasPrefix:@"Unity"]) {
|
||||||
|
Class FBUnityUtility = objc_lookUpClass("FBUnityUtility");
|
||||||
|
SEL selector = NSSelectorFromString(@"triggerUploadViewHierarchy");
|
||||||
|
if (FBUnityUtility && selector && [FBUnityUtility respondsToSelector:selector]) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||||
|
[FBUnityUtility performSelector:selector];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
[self uploadIndexing];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)uploadIndexing
|
||||||
|
{
|
||||||
|
if (_isCodelessIndexing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *tree = [FBSDKCodelessIndexer currentViewTree];
|
||||||
|
|
||||||
|
[self uploadIndexing:tree];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)uploadIndexing:(NSString *)tree
|
||||||
|
{
|
||||||
|
if (_isCodelessIndexing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *currentTreeHash = [FBSDKUtility SHA256Hash:tree];
|
||||||
|
if (_lastTreeHash && [_lastTreeHash isEqualToString:currentTreeHash]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastTreeHash = currentTreeHash;
|
||||||
|
|
||||||
|
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||||
|
NSString *version = [mainBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||||
|
|
||||||
|
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
|
||||||
|
initWithGraphPath:[NSString stringWithFormat:@"%@/%@",
|
||||||
|
[FBSDKSettings appID], CODELESS_INDEXING_ENDPOINT]
|
||||||
|
parameters:@{
|
||||||
|
CODELESS_INDEXING_TREE_KEY: tree,
|
||||||
|
CODELESS_INDEXING_APP_VERSION_KEY: version ?: @"",
|
||||||
|
CODELESS_INDEXING_PLATFORM_KEY: @"iOS",
|
||||||
|
CODELESS_INDEXING_SESSION_ID_KEY: [self currentSessionDeviceID]
|
||||||
|
}
|
||||||
|
HTTPMethod:FBSDKHTTPMethodPOST];
|
||||||
|
_isCodelessIndexing = YES;
|
||||||
|
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
|
||||||
|
_isCodelessIndexing = NO;
|
||||||
|
if ([result isKindOfClass:[NSDictionary class]]) {
|
||||||
|
_isCodelessIndexingEnabled = [result[CODELESS_INDEXING_STATUS_KEY] boolValue];
|
||||||
|
if (!_isCodelessIndexingEnabled) {
|
||||||
|
_deviceSessionID = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)currentViewTree
|
||||||
|
{
|
||||||
|
NSMutableArray *trees = [NSMutableArray array];
|
||||||
|
|
||||||
|
NSArray *windows = [UIApplication sharedApplication].windows;
|
||||||
|
for (UIWindow *window in windows) {
|
||||||
|
NSDictionary *tree = [FBSDKCodelessIndexer recursiveCaptureTree:window];
|
||||||
|
if (tree) {
|
||||||
|
if (window.isKeyWindow) {
|
||||||
|
[trees insertObject:tree atIndex:0];
|
||||||
|
} else {
|
||||||
|
[trees addObject:tree];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == trees.count) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSArray *viewTrees = [trees reverseObjectEnumerator].allObjects;
|
||||||
|
|
||||||
|
NSData *data = UIImageJPEGRepresentation([FBSDKCodelessIndexer screenshot], 0.5);
|
||||||
|
NSString *screenshot = [data base64EncodedStringWithOptions:0];
|
||||||
|
|
||||||
|
NSMutableDictionary *treeInfo = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
treeInfo[@"view"] = viewTrees;
|
||||||
|
treeInfo[@"screenshot"] = screenshot ?: @"";
|
||||||
|
|
||||||
|
NSString *tree = nil;
|
||||||
|
data = [NSJSONSerialization dataWithJSONObject:treeInfo options:0 error:nil];
|
||||||
|
if (data) {
|
||||||
|
tree = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, id> *)recursiveCaptureTree:(NSObject *)obj
|
||||||
|
{
|
||||||
|
if (!obj) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableDictionary *result = [FBSDKViewHierarchy getDetailAttributesOf:obj];
|
||||||
|
|
||||||
|
NSArray *children = [FBSDKViewHierarchy getChildren:obj];
|
||||||
|
NSMutableArray *childrenTrees = [NSMutableArray array];
|
||||||
|
for (NSObject *child in children) {
|
||||||
|
NSDictionary *objTree = [self recursiveCaptureTree:child];
|
||||||
|
[childrenTrees addObject:objTree];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childrenTrees.count > 0) {
|
||||||
|
[result setValue:[childrenTrees copy] forKey:VIEW_HIERARCHY_CHILD_VIEWS_KEY];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [result copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (UIImage *)screenshot {
|
||||||
|
UIWindow *window = [UIApplication sharedApplication].delegate.window;
|
||||||
|
|
||||||
|
UIGraphicsBeginImageContext(window.bounds.size);
|
||||||
|
[window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
|
||||||
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, NSNumber *> *)dimensionOf:(NSObject *)obj
|
||||||
|
{
|
||||||
|
UIView *view = nil;
|
||||||
|
|
||||||
|
if ([obj isKindOfClass:[UIView class]]) {
|
||||||
|
view = (UIView *)obj;
|
||||||
|
} else if ([obj isKindOfClass:[UIViewController class]]) {
|
||||||
|
view = ((UIViewController *)obj).view;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGRect frame = view.frame;
|
||||||
|
CGPoint offset = CGPointZero;
|
||||||
|
|
||||||
|
if ([view isKindOfClass:[UIScrollView class]])
|
||||||
|
offset = ((UIScrollView *)view).contentOffset;
|
||||||
|
|
||||||
|
return @{
|
||||||
|
CODELESS_VIEW_TREE_TOP_KEY: @((int)frame.origin.y),
|
||||||
|
CODELESS_VIEW_TREE_LEFT_KEY: @((int)frame.origin.x),
|
||||||
|
CODELESS_VIEW_TREE_WIDTH_KEY: @((int)frame.size.width),
|
||||||
|
CODELESS_VIEW_TREE_HEIGHT_KEY: @((int)frame.size.height),
|
||||||
|
CODELESS_VIEW_TREE_OFFSET_X_KEY: @((int)offset.x),
|
||||||
|
CODELESS_VIEW_TREE_OFFSET_Y_KEY: @((int)offset.y),
|
||||||
|
CODELESS_VIEW_TREE_VISIBILITY_KEY: view.isHidden ? @4 : @0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(CodelessParameterComponent)
|
||||||
|
@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
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKCodelessParameterComponent.h"
|
||||||
|
|
||||||
|
#import "FBSDKCodelessPathComponent.h"
|
||||||
|
#import "FBSDKViewHierarchyMacros.h"
|
||||||
|
|
||||||
|
@implementation FBSDKCodelessParameterComponent
|
||||||
|
|
||||||
|
- (instancetype)initWithJSON:(NSDictionary *)dict {
|
||||||
|
if (self = [super init]) {
|
||||||
|
_name = [dict[CODELESS_MAPPING_PARAMETER_NAME_KEY] copy];
|
||||||
|
_value = [dict[CODELESS_MAPPING_PARAMETER_VALUE_KEY] copy];
|
||||||
|
_pathType = [dict[CODELESS_MAPPING_PATH_TYPE_KEY] copy];
|
||||||
|
|
||||||
|
NSArray *ary = dict[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
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
typedef NS_OPTIONS(int, FBSDKCodelessMatchBitmaskField)
|
||||||
|
{
|
||||||
|
FBSDKCodelessMatchBitmaskFieldID = 1,
|
||||||
|
FBSDKCodelessMatchBitmaskFieldText = 1 << 1,
|
||||||
|
FBSDKCodelessMatchBitmaskFieldTag = 1 << 2,
|
||||||
|
FBSDKCodelessMatchBitmaskFieldDescription = 1 << 3,
|
||||||
|
FBSDKCodelessMatchBitmaskFieldHint = 1 << 4
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(CodelessPathComponent)
|
||||||
|
@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
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKCodelessPathComponent.h"
|
||||||
|
|
||||||
|
#import "FBSDKViewHierarchyMacros.h"
|
||||||
|
|
||||||
|
@implementation FBSDKCodelessPathComponent
|
||||||
|
|
||||||
|
- (instancetype)initWithJSON:(NSDictionary *)dict {
|
||||||
|
if (self = [super init]) {
|
||||||
|
_className = [dict[CODELESS_MAPPING_CLASS_NAME_KEY] copy];
|
||||||
|
_text = [dict[CODELESS_MAPPING_TEXT_KEY] copy];
|
||||||
|
_hint = [dict[CODELESS_MAPPING_HINT_KEY] copy];
|
||||||
|
_desc = [dict[CODELESS_MAPPING_DESC_KEY] copy];
|
||||||
|
|
||||||
|
|
||||||
|
if (dict[CODELESS_MAPPING_INDEX_KEY]) {
|
||||||
|
_index = [dict[CODELESS_MAPPING_INDEX_KEY] intValue];
|
||||||
|
} else {
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict[CODELESS_MAPPING_SECTION_KEY]) {
|
||||||
|
_section = [dict[CODELESS_MAPPING_SECTION_KEY] intValue];
|
||||||
|
} else {
|
||||||
|
_section = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict[CODELESS_MAPPING_ROW_KEY]) {
|
||||||
|
_row = [dict[CODELESS_MAPPING_ROW_KEY] intValue];
|
||||||
|
} else {
|
||||||
|
_row = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tag = [dict[CODELESS_MAPPING_TAG_KEY] intValue];
|
||||||
|
_matchBitmask = [dict[CODELESS_MAPPING_MATCH_BITMASK_KEY] intValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(EventBinding)
|
||||||
|
@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
|
||||||
|
|
||||||
|
#endif
|
||||||
282
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/Codeless/FBSDKEventBinding.m
generated
Normal file
282
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/Codeless/FBSDKEventBinding.m
generated
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKEventBinding.h"
|
||||||
|
|
||||||
|
#import "FBSDKAppEvents.h"
|
||||||
|
#import "FBSDKAppEventsUtility.h"
|
||||||
|
#import "FBSDKCodelessParameterComponent.h"
|
||||||
|
#import "FBSDKCodelessPathComponent.h"
|
||||||
|
#import "FBSDKSwizzler.h"
|
||||||
|
#import "FBSDKUtility.h"
|
||||||
|
#import "FBSDKViewHierarchy.h"
|
||||||
|
#import "FBSDKViewHierarchyMacros.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[CODELESS_MAPPING_EVENT_NAME_KEY] copy];
|
||||||
|
_eventType = [dict[CODELESS_MAPPING_EVENT_TYPE_KEY] copy];
|
||||||
|
_appVersion = [dict[CODELESS_MAPPING_APP_VERSION_KEY] copy];
|
||||||
|
_pathType = [dict[CODELESS_MAPPING_PATH_TYPE_KEY] copy];
|
||||||
|
|
||||||
|
NSArray *pathComponents = dict[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[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[CODELESS_CODELESS_EVENT_KEY] = @"1";
|
||||||
|
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[component.name] = value;
|
||||||
|
} else {
|
||||||
|
params[component.name] = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[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[idxPath];
|
||||||
|
FBSDKCodelessPathComponent *viewPathComponent = viewPath[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]
|
||||||
|
|| [[FBSDKUtility SHA256Hash: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]
|
||||||
|
|| [[FBSDKUtility SHA256Hash: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[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[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
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(EventBindingManager)
|
||||||
|
@interface FBSDKEventBindingManager : NSObject
|
||||||
|
|
||||||
|
- (FBSDKEventBindingManager*)initWithJSON:(NSDictionary*)dict;
|
||||||
|
- (void)updateBindings:(NSArray *)bindings;
|
||||||
|
+ (NSArray *)parseArray:(NSArray *)array;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,397 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKEventBindingManager.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKCodelessPathComponent.h"
|
||||||
|
#import "FBSDKEventBinding.h"
|
||||||
|
#import "FBSDKSwizzler.h"
|
||||||
|
#import "FBSDKTypeUtility.h"
|
||||||
|
#import "FBSDKViewHierarchy.h"
|
||||||
|
#import "FBSDKViewHierarchyMacros.h"
|
||||||
|
|
||||||
|
#define ReactNativeTargetKey @"target"
|
||||||
|
#define ReactNativeTouchEndEventName @"touchEnd"
|
||||||
|
|
||||||
|
#define ReactNativeClassRCTTextView "RCTTextView"
|
||||||
|
#define ReactNativeClassRCTImageView "RCTImageVIew"
|
||||||
|
#define ReactNativeClassRCTTouchEvent "RCTTouchEvent"
|
||||||
|
#define ReactNativeClassRCTTouchHandler "RCTTouchHandler"
|
||||||
|
|
||||||
|
@interface FBSDKEventBindingManager ()
|
||||||
|
{
|
||||||
|
BOOL isStarted;
|
||||||
|
NSMutableDictionary *reactBindings;
|
||||||
|
NSSet *validClasses;
|
||||||
|
BOOL hasReactNative;
|
||||||
|
NSArray *eventBindings;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKEventBindingManager
|
||||||
|
|
||||||
|
- (id)init {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
isStarted = NO;
|
||||||
|
hasReactNative = NO;
|
||||||
|
reactBindings = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
NSMutableSet *classes = [NSMutableSet set];
|
||||||
|
[classes addObject:[UIControl class]];
|
||||||
|
[classes addObject:[UITableView class]];
|
||||||
|
[classes addObject:[UICollectionView class]];
|
||||||
|
// ReactNative
|
||||||
|
Class classRCTRootView = objc_lookUpClass(ReactNativeClassRCTRootView);
|
||||||
|
if (classRCTRootView != nil) {
|
||||||
|
hasReactNative = YES;
|
||||||
|
Class classRCTView = objc_lookUpClass(ReactNativeClassRCTView);
|
||||||
|
Class classRCTTextView = objc_lookUpClass(ReactNativeClassRCTTextView);
|
||||||
|
Class classRCTImageView = objc_lookUpClass(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == eventBindings.count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isStarted = YES;
|
||||||
|
|
||||||
|
void (^blockToWindow)(id view) = ^(id view) {
|
||||||
|
[self matchView:view delegate:nil];
|
||||||
|
};
|
||||||
|
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
|
||||||
|
onClass:[UIControl class]
|
||||||
|
withBlock:blockToWindow named:@"map_control"];
|
||||||
|
|
||||||
|
// ReactNative
|
||||||
|
if (hasReactNative) { // If app is built via ReactNative
|
||||||
|
Class classRCTView = objc_lookUpClass(ReactNativeClassRCTView);
|
||||||
|
Class classRCTTextView = objc_lookUpClass(ReactNativeClassRCTTextView);
|
||||||
|
Class classRCTImageView = objc_lookUpClass(ReactNativeClassRCTImageView);
|
||||||
|
Class classRCTTouchHandler = objc_lookUpClass(ReactNativeClassRCTTouchHandler);
|
||||||
|
|
||||||
|
// All react-native views would be added tp RCTRootView, so no need to check didMoveToWindow
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
|
||||||
|
onClass:classRCTView
|
||||||
|
withBlock:blockToWindow
|
||||||
|
named:@"match_react_native"];
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
|
||||||
|
onClass:classRCTTextView
|
||||||
|
withBlock:blockToWindow
|
||||||
|
named:@"match_react_native"];
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
|
||||||
|
onClass:classRCTImageView
|
||||||
|
withBlock:blockToWindow
|
||||||
|
named:@"match_react_native"];
|
||||||
|
|
||||||
|
// RCTTouchHandler handles with touch events, like touchEnd and uses RCTEventDispather to dispatch events, so we can check _updateAndDispatchTouches to fire events
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(_updateAndDispatchTouches:eventName:) onClass:classRCTTouchHandler withBlock:^(id touchHandler, SEL command, id touches, id eventName){
|
||||||
|
if ([touches isKindOfClass:[NSSet class]] && [eventName isKindOfClass:[NSString class]]) {
|
||||||
|
@try {
|
||||||
|
NSString *reactEventName = (NSString *)eventName;
|
||||||
|
NSSet<UITouch *> *reactTouches = (NSSet<UITouch *> *)touches;
|
||||||
|
if ([reactEventName isEqualToString:ReactNativeTouchEndEventName]) {
|
||||||
|
for (UITouch *touch in reactTouches) {
|
||||||
|
UIView *targetView = ((UITouch *)touch).view.superview;
|
||||||
|
NSNumber *reactTag = nil;
|
||||||
|
// Find the closest React-managed touchable view like RCTTouchHandler
|
||||||
|
while(targetView) {
|
||||||
|
reactTag = [FBSDKViewHierarchy getViewReactTag:targetView];
|
||||||
|
if (reactTag != nil && targetView.userInteractionEnabled) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
targetView = targetView.superview;
|
||||||
|
}
|
||||||
|
FBSDKEventBinding *eventBinding = self->reactBindings[reactTag];
|
||||||
|
if (reactTag != nil && eventBinding != nil) {
|
||||||
|
[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(^{
|
||||||
|
if (![view window]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)]) {
|
||||||
|
for (FBSDKEventBinding *binding in self->eventBindings) {
|
||||||
|
if ([FBSDKEventBinding isPath:binding.path matchViewPath:path]) {
|
||||||
|
fb_dispatch_on_main_thread(^{
|
||||||
|
if (view) {
|
||||||
|
NSNumber *reactTag = [FBSDKViewHierarchy getViewReactTag:view];
|
||||||
|
if (reactTag != nil) {
|
||||||
|
self->reactBindings[reactTag] = binding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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];
|
||||||
|
if (!isStarted) {
|
||||||
|
[self start];
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_dispatch_on_main_thread(^{
|
||||||
|
[self rematchBindings];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
@interface FBSDKEventDeactivationManager : NSObject
|
||||||
|
|
||||||
|
+ (void)enable;
|
||||||
|
+ (void)updateDeactivatedEvents:(nullable NSDictionary<NSString *, id> *)events;
|
||||||
|
+ (void)processEvents:(NSMutableArray<NSDictionary<NSString *, id> *> *)events;
|
||||||
|
+ (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||||
|
eventName:(NSString *)eventName;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
// 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 "FBSDKEventDeactivationManager.h"
|
||||||
|
|
||||||
|
static NSString *const DEPRECATED_PARAM_KEY = @"deprecated_param";
|
||||||
|
static NSString *const DEPRECATED_EVENT_KEY = @"is_deprecated_event";
|
||||||
|
|
||||||
|
@interface FBSDKDeactivatedEvent : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, readonly, copy) NSString *eventName;
|
||||||
|
@property (nonatomic, readonly, copy, nullable) NSSet<NSString *> *deactivatedParams;
|
||||||
|
|
||||||
|
-(instancetype)initWithEventName:(NSString *)eventName
|
||||||
|
deactivatedParams:(NSSet<NSString *> *)deactivatedParams;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKDeactivatedEvent
|
||||||
|
|
||||||
|
-(instancetype)initWithEventName:(NSString *)eventName
|
||||||
|
deactivatedParams:(NSSet<NSString *> *)deactivatedParams
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_eventName = eventName;
|
||||||
|
_deactivatedParams = deactivatedParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKEventDeactivationManager
|
||||||
|
|
||||||
|
static BOOL isEventDeactivationEnabled = NO;
|
||||||
|
|
||||||
|
static NSMutableSet<NSString *> *_deactivatedEvents;
|
||||||
|
static NSMutableArray<FBSDKDeactivatedEvent *> *_eventsWithDeactivatedParams;
|
||||||
|
|
||||||
|
+ (void)enable
|
||||||
|
{
|
||||||
|
isEventDeactivationEnabled = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)updateDeactivatedEvents:(nullable NSDictionary<NSString *, id> *)events
|
||||||
|
{
|
||||||
|
if (!isEventDeactivationEnabled || events.count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[_deactivatedEvents removeAllObjects];
|
||||||
|
[_eventsWithDeactivatedParams removeAllObjects];
|
||||||
|
NSMutableArray<FBSDKDeactivatedEvent *> *deactivatedParamsArray = [NSMutableArray array];
|
||||||
|
NSMutableSet<NSString *> *deactivatedEventSet = [NSMutableSet set];
|
||||||
|
for (NSString *eventName in events.allKeys) {
|
||||||
|
NSDictionary<NSString *, id> *eventInfo = events[eventName];
|
||||||
|
if (!eventInfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (eventInfo[DEPRECATED_EVENT_KEY]) {
|
||||||
|
[deactivatedEventSet addObject:eventName];
|
||||||
|
}
|
||||||
|
if (eventInfo[DEPRECATED_PARAM_KEY]) {
|
||||||
|
FBSDKDeactivatedEvent *eventWithDeactivatedParams = [[FBSDKDeactivatedEvent alloc] initWithEventName:eventName
|
||||||
|
deactivatedParams:[NSSet setWithArray:eventInfo[DEPRECATED_PARAM_KEY]]];
|
||||||
|
[deactivatedParamsArray addObject:eventWithDeactivatedParams];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_deactivatedEvents = deactivatedEventSet;
|
||||||
|
_eventsWithDeactivatedParams = deactivatedParamsArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)processEvents:(NSMutableArray<NSDictionary<NSString *, id> *> *)events
|
||||||
|
{
|
||||||
|
if (!isEventDeactivationEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSArray<NSDictionary<NSString *, id> *> *eventArray = [events copy];
|
||||||
|
for (NSDictionary<NSString *, NSDictionary<NSString *, id> *> *event in eventArray) {
|
||||||
|
if ([_deactivatedEvents containsObject:event[@"event"][@"_eventName"]]) {
|
||||||
|
[events removeObject:event];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||||
|
eventName:(NSString *)eventName
|
||||||
|
{
|
||||||
|
if (!isEventDeactivationEnabled || parameters.count == 0 || _eventsWithDeactivatedParams.count == 0) {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
NSMutableDictionary<NSString *, id> *params = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||||
|
for (NSString *key in [parameters keyEnumerator]) {
|
||||||
|
for (FBSDKDeactivatedEvent *event in _eventsWithDeactivatedParams) {
|
||||||
|
if ([event.eventName isEqualToString:eventName] && [event.deactivatedParams containsObject:key]) {
|
||||||
|
[params removeObjectForKey:key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [params copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
245
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEvents+Internal.h
generated
Normal file
245
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEvents+Internal.h
generated
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
// 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 SWIFT_PACKAGE
|
||||||
|
#import "FBSDKAppEvents.h"
|
||||||
|
#else
|
||||||
|
#import <FBSDKCoreKit/FBSDKAppEvents.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#import "FBSDKAppEventsUtility.h"
|
||||||
|
|
||||||
|
@class FBSDKGraphRequest;
|
||||||
|
|
||||||
|
// Internally known event names
|
||||||
|
|
||||||
|
/** Use to log that the share dialog was launched */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameShareSheetLaunch;
|
||||||
|
|
||||||
|
/** Use to log that the share dialog was dismissed */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameShareSheetDismiss;
|
||||||
|
|
||||||
|
/** Use to log that the permissions UI was launched */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNamePermissionsUILaunch;
|
||||||
|
|
||||||
|
/** Use to log that the permissions UI was dismissed */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNamePermissionsUIDismiss;
|
||||||
|
|
||||||
|
/** Use to log that the login view was used */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameLoginViewUsage;
|
||||||
|
|
||||||
|
/** Use to log that the share tray launched. */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameShareTrayDidLaunch;
|
||||||
|
|
||||||
|
/** Use to log that the person selected a sharing target. */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameShareTrayDidSelectActivity;
|
||||||
|
|
||||||
|
// Internally known event parameters
|
||||||
|
|
||||||
|
/** String parameter specifying the outcome of a dialog invocation */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterDialogOutcome;
|
||||||
|
|
||||||
|
/** Parameter key used to specify which application launches this application. */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLaunchSource;
|
||||||
|
|
||||||
|
/** Use to log the result of a call to FBDialogs presentShareDialogWithParams: */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentShareDialog;
|
||||||
|
|
||||||
|
/** Use to log the result of a call to FBDialogs presentShareDialogWithOpenGraphActionParams: */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentShareDialogOG;
|
||||||
|
|
||||||
|
/** Use to log the result of a call to FBDialogs presentLikeDialogWithLikeParams: */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentLikeDialogOG;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentShareDialogPhoto;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentMessageDialog;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentMessageDialogPhoto;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentMessageDialogOG;
|
||||||
|
|
||||||
|
/** Use to log the start of an auth request that cannot be fulfilled by the token cache */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSessionAuthStart;
|
||||||
|
|
||||||
|
/** Use to log the end of an auth request that was not fulfilled by the token cache */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSessionAuthEnd;
|
||||||
|
|
||||||
|
/** Use to log the start of a specific auth method as part of an auth request */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSessionAuthMethodStart;
|
||||||
|
|
||||||
|
/** Use to log the end of the last tried auth method as part of an auth request */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSessionAuthMethodEnd;
|
||||||
|
|
||||||
|
/** Use to log the timestamp for the transition to the Facebook native login dialog */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsNativeLoginDialogStart;
|
||||||
|
|
||||||
|
/** Use to log the timestamp for the transition back to the app after the Facebook native login dialog */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsNativeLoginDialogEnd;
|
||||||
|
|
||||||
|
/** Use to log the e2e timestamp metrics for web login */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsWebLoginCompleted;
|
||||||
|
|
||||||
|
/** Use to log the result of the App Switch OS AlertView. Only available on OS >= iOS10 */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSessionFASLoginDialogResult;
|
||||||
|
|
||||||
|
/** Use to log the live streaming events from sdk */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingStart;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingStop;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingPause;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingResume;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingError;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingUpdateStatus;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingVideoID;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingMic;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingCamera;
|
||||||
|
|
||||||
|
/** Use to log the results of a share dialog */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKEventShareDialogResult;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKEventMessengerShareDialogResult;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKEventAppInviteShareDialogResult;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKEventShareDialogShow;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKEventMessengerShareDialogShow;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKEventAppInviteShareDialogShow;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterDialogMode;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterDialogShareContentType;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterDialogShareContentUUID;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterDialogShareContentPageID;
|
||||||
|
|
||||||
|
/** Use to log parameters for share tray use */
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterShareTrayActivityName;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterShareTrayResult;
|
||||||
|
|
||||||
|
/** Use to log parameters for live streaming*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingPrevStatus;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingStatus;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingError;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingVideoID;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingMicEnabled;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingCameraEnabled;
|
||||||
|
|
||||||
|
// Internally known event parameter values
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogOutcomeValue_Completed;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogOutcomeValue_Cancelled;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogOutcomeValue_Failed;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypeOpenGraph;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypeStatus;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypePhoto;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypeVideo;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypeCamera;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypeMessengerGenericTemplate;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypeMessengerMediaTemplate;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypeMessengerOpenGraphMusicTemplate;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareContentTypeUnknown;
|
||||||
|
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareModeAutomatic;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareModeBrowser;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareModeNative;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareModeShareSheet;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareModeWeb;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareModeFeedBrowser;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareModeFeedWeb;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogShareModeUnknown;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsNativeLoginDialogStartTime;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsNativeLoginDialogEndTime;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWebLoginE2E;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeButtonImpression;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLoginButtonImpression;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKSendButtonImpression;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKShareButtonImpression;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonImpression;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKSmartLoginService;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeButtonDidTap;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLoginButtonDidTap;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKSendButtonDidTap;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKShareButtonDidTap;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonDidTap;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeControlDidDisable;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeControlDidLike;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeControlDidPresentDialog;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeControlDidTap;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeControlDidUnlike;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeControlError;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeControlImpression;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeControlNetworkUnavailable;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterDialogErrorMessage;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLogTime;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesHandlerKey;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesActionKey;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesEventKey;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesParamsKey;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackKey;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackCustomKey;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackSingleKey;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackSingleCustomKey;
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelIDKey;
|
||||||
|
|
||||||
|
@interface FBSDKAppEvents (Internal)
|
||||||
|
|
||||||
|
@property (class, nonatomic, strong, readonly) FBSDKAppEvents *singleton;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
+ (void)resetSingleton;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ (void)logInternalEvent:(FBSDKAppEventName)eventName
|
||||||
|
isImplicitlyLogged:(BOOL)isImplicitlyLogged;
|
||||||
|
|
||||||
|
+ (void)logInternalEvent:(FBSDKAppEventName)eventName
|
||||||
|
valueToSum:(double)valueToSum
|
||||||
|
isImplicitlyLogged:(BOOL)isImplicitlyLogged;
|
||||||
|
|
||||||
|
+ (void)logInternalEvent:(FBSDKAppEventName)eventName
|
||||||
|
parameters:(NSDictionary *)parameters
|
||||||
|
isImplicitlyLogged:(BOOL)isImplicitlyLogged;
|
||||||
|
|
||||||
|
+ (void)logInternalEvent:(FBSDKAppEventName)eventName
|
||||||
|
parameters:(NSDictionary *)parameters
|
||||||
|
isImplicitlyLogged:(BOOL)isImplicitlyLogged
|
||||||
|
accessToken:(FBSDKAccessToken *)accessToken;
|
||||||
|
|
||||||
|
+ (void)logInternalEvent:(FBSDKAppEventName)eventName
|
||||||
|
valueToSum:(double)valueToSum
|
||||||
|
parameters:(NSDictionary *)parameters
|
||||||
|
isImplicitlyLogged:(BOOL)isImplicitlyLogged;
|
||||||
|
|
||||||
|
+ (void)logInternalEvent:(NSString *)eventName
|
||||||
|
valueToSum:(NSNumber *)valueToSum
|
||||||
|
parameters:(NSDictionary *)parameters
|
||||||
|
isImplicitlyLogged:(BOOL)isImplicitlyLogged
|
||||||
|
accessToken:(FBSDKAccessToken *)accessToken;
|
||||||
|
|
||||||
|
+ (void)logImplicitEvent:(NSString *)eventName
|
||||||
|
valueToSum:(NSNumber *)valueToSum
|
||||||
|
parameters:(NSDictionary *)parameters
|
||||||
|
accessToken:(FBSDKAccessToken *)accessToken;
|
||||||
|
|
||||||
|
- (void)flushForReason:(FBSDKAppEventsFlushReason)flushReason;
|
||||||
|
- (void)registerNotifications;
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
// 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_SWIFT_NAME(AppEventsDeviceInfo)
|
||||||
|
@interface FBSDKAppEventsDeviceInfo : NSObject
|
||||||
|
|
||||||
|
+ (void)extendDictionaryWithDeviceInfo:(NSMutableDictionary *)dictionary;
|
||||||
|
|
||||||
|
@end
|
||||||
279
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsDeviceInfo.m
generated
Normal file
279
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsDeviceInfo.m
generated
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
// 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 "FBSDKAppEventsDeviceInfo.h"
|
||||||
|
|
||||||
|
#import <sys/sysctl.h>
|
||||||
|
#import <sys/utsname.h>
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#import <CoreTelephony/CTCarrier.h>
|
||||||
|
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKAppEvents+Internal.h"
|
||||||
|
#import "FBSDKDynamicFrameworkLoader.h"
|
||||||
|
#import "FBSDKInternalUtility.h"
|
||||||
|
#import "FBSDKUtility.h"
|
||||||
|
|
||||||
|
#define FB_ARRAY_COUNT(x) sizeof(x) / sizeof(x[0])
|
||||||
|
|
||||||
|
static const u_int FB_GROUP1_RECHECK_DURATION = 30 * 60; // seconds
|
||||||
|
|
||||||
|
// Apple reports storage in binary gigabytes (1024^3) in their About menus, etc.
|
||||||
|
static const u_int FB_GIGABYTE = 1024 * 1024 * 1024; // bytes
|
||||||
|
|
||||||
|
@implementation FBSDKAppEventsDeviceInfo
|
||||||
|
{
|
||||||
|
// Ephemeral data, may change during the lifetime of an app. We collect them in different
|
||||||
|
// 'group' frequencies - group1 may gets collected once every 30 minutes.
|
||||||
|
|
||||||
|
// group1
|
||||||
|
NSString *_carrierName;
|
||||||
|
NSString *_timeZoneAbbrev;
|
||||||
|
unsigned long long _remainingDiskSpaceGB;
|
||||||
|
NSString *_timeZoneName;
|
||||||
|
|
||||||
|
// Persistent data, but we maintain it to make rebuilding the device info as fast as possible.
|
||||||
|
NSString *_bundleIdentifier;
|
||||||
|
NSString *_longVersion;
|
||||||
|
NSString *_shortVersion;
|
||||||
|
NSString *_sysVersion;
|
||||||
|
NSString *_machine;
|
||||||
|
NSString *_language;
|
||||||
|
unsigned long long _totalDiskSpaceGB;
|
||||||
|
unsigned long long _coreCount;
|
||||||
|
CGFloat _width;
|
||||||
|
CGFloat _height;
|
||||||
|
CGFloat _density;
|
||||||
|
|
||||||
|
// Other state
|
||||||
|
long _lastGroup1CheckTime;
|
||||||
|
BOOL _isEncodingDirty;
|
||||||
|
NSString *_encodedDeviceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Public Methods
|
||||||
|
|
||||||
|
+ (void)extendDictionaryWithDeviceInfo:(NSMutableDictionary *)dictionary
|
||||||
|
{
|
||||||
|
dictionary[@"extinfo"] = [[self sharedDeviceInfo] encodedDeviceInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Internal Methods
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
if (self == [FBSDKAppEventsDeviceInfo class]) {
|
||||||
|
[[self sharedDeviceInfo] _collectPersistentData];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (instancetype)sharedDeviceInfo
|
||||||
|
{
|
||||||
|
static FBSDKAppEventsDeviceInfo *_sharedDeviceInfo = nil;
|
||||||
|
if (_sharedDeviceInfo == nil) {
|
||||||
|
_sharedDeviceInfo = [[FBSDKAppEventsDeviceInfo alloc] init];
|
||||||
|
}
|
||||||
|
return _sharedDeviceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_isEncodingDirty = YES;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)encodedDeviceInfo
|
||||||
|
{
|
||||||
|
@synchronized (self) {
|
||||||
|
|
||||||
|
BOOL isGroup1Expired = [self _isGroup1Expired];
|
||||||
|
BOOL isEncodingExpired = isGroup1Expired; // Can || other groups in if we add them
|
||||||
|
|
||||||
|
// As long as group1 hasn't expired, we can just return the last generated value
|
||||||
|
if (_encodedDeviceInfo && !isEncodingExpired) {
|
||||||
|
return _encodedDeviceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGroup1Expired) {
|
||||||
|
[self _collectGroup1Data];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isEncodingDirty) {
|
||||||
|
self.encodedDeviceInfo = [self _generateEncoding];
|
||||||
|
_isEncodingDirty = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _encodedDeviceInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setEncodedDeviceInfo:(NSString *)encodedDeviceInfo
|
||||||
|
{
|
||||||
|
@synchronized (self) {
|
||||||
|
if (![_encodedDeviceInfo isEqualToString:encodedDeviceInfo]) {
|
||||||
|
_encodedDeviceInfo = [encodedDeviceInfo copy];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This data need only be collected once.
|
||||||
|
- (void)_collectPersistentData
|
||||||
|
{
|
||||||
|
// Bundle stuff
|
||||||
|
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||||
|
_bundleIdentifier = mainBundle.bundleIdentifier;
|
||||||
|
_longVersion = [mainBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||||
|
_shortVersion = [mainBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||||
|
|
||||||
|
// Locale stuff
|
||||||
|
_language = [NSLocale currentLocale].localeIdentifier;
|
||||||
|
|
||||||
|
// Device stuff
|
||||||
|
UIDevice *device = [UIDevice currentDevice];
|
||||||
|
_sysVersion = device.systemVersion;
|
||||||
|
_coreCount = [FBSDKAppEventsDeviceInfo _coreCount];
|
||||||
|
|
||||||
|
UIScreen *sc = [UIScreen mainScreen];
|
||||||
|
CGRect sr = sc.bounds;
|
||||||
|
_width = sr.size.width;
|
||||||
|
_height = sr.size.height;
|
||||||
|
_density = sc.scale;
|
||||||
|
|
||||||
|
struct utsname systemInfo;
|
||||||
|
uname(&systemInfo);
|
||||||
|
_machine = @(systemInfo.machine);
|
||||||
|
|
||||||
|
// Disk space stuff
|
||||||
|
float totalDiskSpace = [FBSDKAppEventsDeviceInfo _getTotalDiskSpace].floatValue;
|
||||||
|
_totalDiskSpaceGB = (unsigned long long)round(totalDiskSpace / FB_GIGABYTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)_isGroup1Expired
|
||||||
|
{
|
||||||
|
return ([FBSDKAppEventsUtility unixTimeNow] - _lastGroup1CheckTime) > FB_GROUP1_RECHECK_DURATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This data is collected only once every GROUP1_RECHECK_DURATION.
|
||||||
|
- (void)_collectGroup1Data
|
||||||
|
{
|
||||||
|
// Carrier
|
||||||
|
NSString *newCarrierName = [FBSDKAppEventsDeviceInfo _getCarrier];
|
||||||
|
if (![newCarrierName isEqualToString:_carrierName]) {
|
||||||
|
_carrierName = newCarrierName;
|
||||||
|
_isEncodingDirty = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time zone
|
||||||
|
NSTimeZone *timeZone = [NSTimeZone systemTimeZone];
|
||||||
|
NSString *timeZoneName = timeZone.name;
|
||||||
|
if (![timeZoneName isEqualToString:_timeZoneName]) {
|
||||||
|
_timeZoneName = timeZoneName;
|
||||||
|
_timeZoneAbbrev = timeZone.abbreviation;
|
||||||
|
_isEncodingDirty = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remaining disk space
|
||||||
|
float remainingDiskSpace = [FBSDKAppEventsDeviceInfo _getRemainingDiskSpace].floatValue;
|
||||||
|
unsigned long long newRemainingDiskSpaceGB = (unsigned long long)round(remainingDiskSpace / FB_GIGABYTE);
|
||||||
|
if (_remainingDiskSpaceGB != newRemainingDiskSpaceGB) {
|
||||||
|
_remainingDiskSpaceGB = newRemainingDiskSpaceGB;
|
||||||
|
_isEncodingDirty = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastGroup1CheckTime = [FBSDKAppEventsUtility unixTimeNow];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)_generateEncoding
|
||||||
|
{
|
||||||
|
// Keep a bit of precision on density as it's the most likely to become non-integer.
|
||||||
|
NSString *densityString = _density ? [NSString stringWithFormat:@"%.02f", _density] : @"";
|
||||||
|
|
||||||
|
NSArray *arr = @[
|
||||||
|
@"i2", // version - starts with 'i' for iOS, we'll use 'a' for Android
|
||||||
|
_bundleIdentifier ?: @"",
|
||||||
|
_longVersion ?: @"",
|
||||||
|
_shortVersion ?: @"",
|
||||||
|
_sysVersion ?: @"",
|
||||||
|
_machine ?: @"",
|
||||||
|
_language ?: @"",
|
||||||
|
_timeZoneAbbrev ?: @"",
|
||||||
|
_carrierName ?: @"",
|
||||||
|
_width ? @((unsigned long)_width) : @"",
|
||||||
|
_height ? @((unsigned long)_height) : @"",
|
||||||
|
densityString,
|
||||||
|
@(_coreCount) ?: @"",
|
||||||
|
@(_totalDiskSpaceGB) ?: @"",
|
||||||
|
@(_remainingDiskSpaceGB) ?: @"",
|
||||||
|
_timeZoneName ?: @""
|
||||||
|
];
|
||||||
|
|
||||||
|
return [FBSDKBasicUtility JSONStringForObject:arr error:NULL invalidObjectHandler:NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Helper Methods
|
||||||
|
|
||||||
|
+ (NSNumber *)_getTotalDiskSpace
|
||||||
|
{
|
||||||
|
NSDictionary *attrs = [[[NSFileManager alloc] init] attributesOfFileSystemForPath:NSHomeDirectory()
|
||||||
|
error:nil];
|
||||||
|
return attrs[NSFileSystemSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSNumber *)_getRemainingDiskSpace
|
||||||
|
{
|
||||||
|
NSDictionary *attrs = [[[NSFileManager alloc] init] attributesOfFileSystemForPath:NSHomeDirectory()
|
||||||
|
error:nil];
|
||||||
|
return attrs[NSFileSystemFreeSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (uint)_coreCount
|
||||||
|
{
|
||||||
|
return [FBSDKAppEventsDeviceInfo _readSysCtlUInt:CTL_HW type:HW_AVAILCPU];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (uint)_readSysCtlUInt:(int)ctl type:(int)type
|
||||||
|
{
|
||||||
|
int mib[2] = {ctl, type};
|
||||||
|
uint value;
|
||||||
|
size_t size = sizeof value;
|
||||||
|
if (0 != sysctl(mib, FB_ARRAY_COUNT(mib), &value, &size, NULL, 0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)_getCarrier
|
||||||
|
{
|
||||||
|
#if TARGET_OS_TV || TARGET_IPHONE_SIMULATOR
|
||||||
|
return @"NoCarrier";
|
||||||
|
#else
|
||||||
|
// Dynamically load class for this so calling app doesn't need to link framework in.
|
||||||
|
CTTelephonyNetworkInfo *networkInfo = [[fbsdkdfl_CTTelephonyNetworkInfoClass() alloc] init];
|
||||||
|
CTCarrier *carrier = networkInfo.subscriberCellularProvider;
|
||||||
|
return carrier.carrierName ?: @"NoCarrier";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
42
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsState.h
generated
Normal file
42
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsState.h
generated
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// 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>
|
||||||
|
|
||||||
|
// this type is not thread safe.
|
||||||
|
NS_SWIFT_NAME(AppEventsState)
|
||||||
|
@interface FBSDKAppEventsState : NSObject<NSCopying, NSSecureCoding>
|
||||||
|
|
||||||
|
@property (nonatomic, readonly, copy) NSArray *events;
|
||||||
|
@property (nonatomic, readonly, assign) NSUInteger numSkipped;
|
||||||
|
@property (nonatomic, readonly, copy) NSString *tokenString;
|
||||||
|
@property (nonatomic, readonly, copy) NSString *appID;
|
||||||
|
@property (nonatomic, readonly, getter=areAllEventsImplicit) BOOL allEventsImplicit;
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
- (instancetype)initWithToken:(NSString *)tokenString appID:(NSString *)appID NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
- (void)addEvent:(NSDictionary *)eventDictionary isImplicit:(BOOL)isImplicit;
|
||||||
|
- (void)addEventsFromAppEventState:(FBSDKAppEventsState *)appEventsState;
|
||||||
|
- (BOOL)isCompatibleWithAppEventsState:(FBSDKAppEventsState *)appEventsState;
|
||||||
|
- (BOOL)isCompatibleWithTokenString:(NSString *)tokenString appID:(NSString *)appID;
|
||||||
|
- (NSString *)JSONStringForEvents:(BOOL)includeImplicitEvents;
|
||||||
|
- (NSString *)extractReceiptData;
|
||||||
|
|
||||||
|
@end
|
||||||
185
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsState.m
generated
Normal file
185
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsState.m
generated
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
// 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 "FBSDKAppEventsState.h"
|
||||||
|
|
||||||
|
#import "FBSDKBasicUtility.h"
|
||||||
|
#import "FBSDKEventDeactivationManager.h"
|
||||||
|
#import "FBSDKRestrictiveDataFilterManager.h"
|
||||||
|
|
||||||
|
#define FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY @"isImplicit"
|
||||||
|
|
||||||
|
#define FBSDK_APPEVENTSSTATE_MAX_EVENTS 1000
|
||||||
|
|
||||||
|
#define FBSDK_APPEVENTSSTATE_APPID_KEY @"appID"
|
||||||
|
#define FBSDK_APPEVENTSSTATE_EVENTS_KEY @"events"
|
||||||
|
#define FBSDK_APPEVENTSSTATE_NUMSKIPPED_KEY @"numSkipped"
|
||||||
|
#define FBSDK_APPEVENTSSTATE_TOKENSTRING_KEY @"tokenString"
|
||||||
|
#define FBSDK_APPEVENTSTATE_RECEIPTDATA_KEY @"receipt_data"
|
||||||
|
#define FBSDK_APPEVENTSTATE_RECEIPTID_KEY @"receipt_id"
|
||||||
|
|
||||||
|
@implementation FBSDKAppEventsState
|
||||||
|
{
|
||||||
|
NSMutableArray *_mutableEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithToken:(NSString *)tokenString appID:(NSString *)appID
|
||||||
|
{
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_tokenString = [tokenString copy];
|
||||||
|
_appID = [appID copy];
|
||||||
|
_mutableEvents = [NSMutableArray array];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)copyWithZone:(NSZone *)zone
|
||||||
|
{
|
||||||
|
FBSDKAppEventsState *copy = [[FBSDKAppEventsState allocWithZone:zone] initWithToken:_tokenString appID:_appID];
|
||||||
|
if (copy) {
|
||||||
|
[copy->_mutableEvents addObjectsFromArray:_mutableEvents];
|
||||||
|
copy->_numSkipped = _numSkipped;
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSCoding
|
||||||
|
|
||||||
|
+ (BOOL)supportsSecureCoding
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithCoder:(NSCoder *)decoder
|
||||||
|
{
|
||||||
|
NSString *appID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_APPEVENTSSTATE_APPID_KEY];
|
||||||
|
NSString *tokenString = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_APPEVENTSSTATE_TOKENSTRING_KEY];
|
||||||
|
NSArray *events = [decoder decodeObjectOfClass:[NSArray class] forKey:FBSDK_APPEVENTSSTATE_EVENTS_KEY];
|
||||||
|
NSUInteger numSkipped = [[decoder decodeObjectOfClass:[NSNumber class] forKey:FBSDK_APPEVENTSSTATE_NUMSKIPPED_KEY] unsignedIntegerValue];
|
||||||
|
|
||||||
|
if ((self = [self initWithToken:tokenString appID:appID])) {
|
||||||
|
_mutableEvents = [NSMutableArray arrayWithArray:events];
|
||||||
|
_numSkipped = numSkipped;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||||
|
{
|
||||||
|
[encoder encodeObject:_appID forKey:FBSDK_APPEVENTSSTATE_APPID_KEY];
|
||||||
|
[encoder encodeObject:_tokenString forKey:FBSDK_APPEVENTSSTATE_TOKENSTRING_KEY];
|
||||||
|
[encoder encodeObject:@(_numSkipped) forKey:FBSDK_APPEVENTSSTATE_NUMSKIPPED_KEY];
|
||||||
|
[encoder encodeObject:_mutableEvents forKey:FBSDK_APPEVENTSSTATE_EVENTS_KEY];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Implementation
|
||||||
|
|
||||||
|
- (NSArray *)events
|
||||||
|
{
|
||||||
|
return [_mutableEvents copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addEventsFromAppEventState:(FBSDKAppEventsState *)appEventsState
|
||||||
|
{
|
||||||
|
NSArray *toAdd = appEventsState->_mutableEvents;
|
||||||
|
NSInteger excess = _mutableEvents.count + toAdd.count - FBSDK_APPEVENTSSTATE_MAX_EVENTS;
|
||||||
|
if (excess > 0) {
|
||||||
|
NSInteger range = FBSDK_APPEVENTSSTATE_MAX_EVENTS - _mutableEvents.count;
|
||||||
|
toAdd = [toAdd subarrayWithRange:NSMakeRange(0, range)];
|
||||||
|
_numSkipped += excess;
|
||||||
|
}
|
||||||
|
|
||||||
|
[_mutableEvents addObjectsFromArray:toAdd];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addEvent:(NSDictionary *)eventDictionary
|
||||||
|
isImplicit:(BOOL)isImplicit {
|
||||||
|
if (_mutableEvents.count >= FBSDK_APPEVENTSSTATE_MAX_EVENTS) {
|
||||||
|
_numSkipped++;
|
||||||
|
} else {
|
||||||
|
[_mutableEvents addObject:@{
|
||||||
|
@"event" : [eventDictionary mutableCopy],
|
||||||
|
FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY : @(isImplicit)
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)extractReceiptData {
|
||||||
|
NSMutableString *receipts_string = [NSMutableString string];
|
||||||
|
NSInteger transactionId = 1;
|
||||||
|
for (NSMutableDictionary* events in _mutableEvents) {
|
||||||
|
NSMutableDictionary *event = events[@"event"];
|
||||||
|
|
||||||
|
NSString* receipt = event[@"receipt_data"];
|
||||||
|
// Add receipt id as the identifier for receipt data in event parameter.
|
||||||
|
// Receipt data will be sent as post parameter rather than the event parameter
|
||||||
|
if (receipt) {
|
||||||
|
NSString* idKey = [NSString stringWithFormat:@"receipt_%ld", (long)transactionId];
|
||||||
|
event[FBSDK_APPEVENTSTATE_RECEIPTID_KEY] = idKey;
|
||||||
|
NSString* receiptWithId = [NSString stringWithFormat:@"%@::%@;;;", idKey, receipt];
|
||||||
|
[receipts_string appendString:receiptWithId];
|
||||||
|
transactionId++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return receipts_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)areAllEventsImplicit
|
||||||
|
{
|
||||||
|
for (NSDictionary *event in _mutableEvents) {
|
||||||
|
if (![[event valueForKey:FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY] boolValue]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isCompatibleWithAppEventsState:(FBSDKAppEventsState *)appEventsState
|
||||||
|
{
|
||||||
|
return ([self isCompatibleWithTokenString:appEventsState.tokenString appID:appEventsState.appID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isCompatibleWithTokenString:(NSString *)tokenString appID:(NSString *)appID
|
||||||
|
{
|
||||||
|
// token strings can be nil (e.g., no user token) but appIDs should not.
|
||||||
|
BOOL tokenCompatible = ([self.tokenString isEqualToString:tokenString] ||
|
||||||
|
(self.tokenString == nil && tokenString == nil));
|
||||||
|
return (tokenCompatible &&
|
||||||
|
[self.appID isEqualToString:appID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)JSONStringForEvents:(BOOL)includeImplicitEvents
|
||||||
|
{
|
||||||
|
[FBSDKEventDeactivationManager processEvents:_mutableEvents];
|
||||||
|
|
||||||
|
NSMutableArray *events = [[NSMutableArray alloc] initWithCapacity:_mutableEvents.count];
|
||||||
|
for (NSDictionary *eventAndImplicitFlag in _mutableEvents) {
|
||||||
|
if (!includeImplicitEvents && [eventAndImplicitFlag[FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY] boolValue]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NSMutableDictionary *event = eventAndImplicitFlag[@"event"];
|
||||||
|
NSAssert(event != nil, @"event cannot be nil");
|
||||||
|
[event removeObjectForKey:FBSDK_APPEVENTSTATE_RECEIPTDATA_KEY];
|
||||||
|
|
||||||
|
[events addObject:event];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [FBSDKBasicUtility JSONStringForObject:events error:NULL invalidObjectHandler:NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
// 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>
|
||||||
|
|
||||||
|
@class FBSDKAppEventsState;
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(AppEventsStateManager)
|
||||||
|
@interface FBSDKAppEventsStateManager : NSObject
|
||||||
|
|
||||||
|
+ (void)clearPersistedAppEventsStates;
|
||||||
|
|
||||||
|
// reads all saved event states, appends the param, and writes them all.
|
||||||
|
+ (void)persistAppEventsData:(FBSDKAppEventsState *)appEventsState;
|
||||||
|
|
||||||
|
// returns the array of saved app event states and deletes them.
|
||||||
|
+ (NSArray *)retrievePersistedAppEventsStates;
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
// 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 "FBSDKAppEventsStateManager.h"
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "FBSDKAppEventsState.h"
|
||||||
|
#import "FBSDKAppEventsUtility.h"
|
||||||
|
#import "FBSDKInternalUtility.h"
|
||||||
|
#import "FBSDKLogger.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
|
||||||
|
// A quick optimization to allow returning empty array if we know there are no persisted events.
|
||||||
|
static BOOL g_canSkipDiskCheck = NO;
|
||||||
|
|
||||||
|
@implementation FBSDKAppEventsStateManager
|
||||||
|
|
||||||
|
+ (void)clearPersistedAppEventsStates
|
||||||
|
{
|
||||||
|
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||||
|
logEntry:@"FBSDKAppEvents Persist: Clearing"];
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:[[self class] filePath]
|
||||||
|
error:NULL];
|
||||||
|
g_canSkipDiskCheck = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)persistAppEventsData:(FBSDKAppEventsState *)appEventsState
|
||||||
|
{
|
||||||
|
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||||
|
formatString:@"FBSDKAppEvents Persist: Writing %lu events", (unsigned long)appEventsState.events.count];
|
||||||
|
|
||||||
|
if (!appEventsState.events.count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSMutableArray *existingEvents = [NSMutableArray arrayWithArray:[[self class] retrievePersistedAppEventsStates]];
|
||||||
|
[existingEvents addObject:appEventsState];
|
||||||
|
|
||||||
|
[NSKeyedArchiver archiveRootObject:existingEvents toFile:[[self class] filePath]];
|
||||||
|
g_canSkipDiskCheck = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray *)retrievePersistedAppEventsStates
|
||||||
|
{
|
||||||
|
NSMutableArray *eventsStates = [NSMutableArray array];
|
||||||
|
if (!g_canSkipDiskCheck) {
|
||||||
|
[eventsStates addObjectsFromArray:[NSKeyedUnarchiver unarchiveObjectWithFile:[[self class] filePath]]];
|
||||||
|
|
||||||
|
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||||
|
formatString:@"FBSDKAppEvents Persist: Read %lu event states. First state has %lu events",
|
||||||
|
(unsigned long)eventsStates.count,
|
||||||
|
(unsigned long)(eventsStates.count > 0 ? ((FBSDKAppEventsState *)eventsStates[0]).events.count : 0)];
|
||||||
|
[[self class] clearPersistedAppEventsStates];
|
||||||
|
}
|
||||||
|
return eventsStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private Helpers
|
||||||
|
|
||||||
|
+ (NSString *)filePath
|
||||||
|
{
|
||||||
|
return [FBSDKBasicUtility persistenceFilePath:@"com-facebook-sdk-AppEventsPersistedEvents.json"];
|
||||||
|
}
|
||||||
|
@end
|
||||||
66
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsUtility.h
generated
Normal file
66
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsUtility.h
generated
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// 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>
|
||||||
|
|
||||||
|
@class FBSDKAccessToken;
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, FBSDKAdvertisingTrackingStatus)
|
||||||
|
{
|
||||||
|
FBSDKAdvertisingTrackingAllowed,
|
||||||
|
FBSDKAdvertisingTrackingDisallowed,
|
||||||
|
FBSDKAdvertisingTrackingUnspecified
|
||||||
|
} NS_SWIFT_NAME(AppEventsUtility.AdvertisingTrackingStatus);
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, FBSDKAppEventsFlushReason)
|
||||||
|
{
|
||||||
|
FBSDKAppEventsFlushReasonExplicit,
|
||||||
|
FBSDKAppEventsFlushReasonTimer,
|
||||||
|
FBSDKAppEventsFlushReasonSessionChange,
|
||||||
|
FBSDKAppEventsFlushReasonPersistedEvents,
|
||||||
|
FBSDKAppEventsFlushReasonEventThreshold,
|
||||||
|
FBSDKAppEventsFlushReasonEagerlyFlushingEvent
|
||||||
|
} NS_SWIFT_NAME(AppEventsUtility.FlushReason);
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(AppEventsUtility)
|
||||||
|
@interface FBSDKAppEventsUtility : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
@property (class, nonatomic, copy, readonly) NSString *advertiserID;
|
||||||
|
@property (class, nonatomic, assign, readonly) FBSDKAdvertisingTrackingStatus advertisingTrackingStatus;
|
||||||
|
@property (class, nonatomic, strong, readonly) NSString *attributionID;
|
||||||
|
@property (class, nonatomic, assign, readonly) long unixTimeNow;
|
||||||
|
@property (class, nonatomic, assign, readonly) BOOL isDebugBuild;
|
||||||
|
|
||||||
|
+ (NSMutableDictionary *)activityParametersDictionaryForEvent:(NSString *)eventCategory
|
||||||
|
implicitEventsOnly:(BOOL)implicitEventsOnly
|
||||||
|
shouldAccessAdvertisingID:(BOOL)shouldAccessAdvertisingID;
|
||||||
|
|
||||||
|
+ (void)ensureOnMainThread:(NSString *)methodName className:(NSString *)className;
|
||||||
|
+ (NSString *)flushReasonToString:(FBSDKAppEventsFlushReason)flushReason;
|
||||||
|
+ (void)logAndNotify:(NSString *)msg allowLogAsDeveloperError:(BOOL)allowLogAsDeveloperError;
|
||||||
|
+ (void)logAndNotify:(NSString *)msg;
|
||||||
|
+ (NSString *)tokenStringToUseFor:(FBSDKAccessToken *)token;
|
||||||
|
+ (BOOL)validateIdentifier:(NSString *)identifier;
|
||||||
|
+ (id)getVariable:(NSString *)variableName fromInstance:(NSObject *)instance;
|
||||||
|
+ (NSNumber *)getNumberValue:(NSString *)text;
|
||||||
|
+ (BOOL)isSensitiveUserData:(NSString *)text;
|
||||||
|
|
||||||
|
@end
|
||||||
430
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsUtility.m
generated
Normal file
430
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsUtility.m
generated
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
// 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 "FBSDKAppEventsUtility.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
#import <AdSupport/AdSupport.h>
|
||||||
|
|
||||||
|
#import "FBSDKAccessToken.h"
|
||||||
|
#import "FBSDKAppEvents.h"
|
||||||
|
#import "FBSDKAppEventsDeviceInfo.h"
|
||||||
|
#import "FBSDKConstants.h"
|
||||||
|
#import "FBSDKDynamicFrameworkLoader.h"
|
||||||
|
#import "FBSDKError.h"
|
||||||
|
#import "FBSDKInternalUtility.h"
|
||||||
|
#import "FBSDKLogger.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
#import "FBSDKTimeSpentData.h"
|
||||||
|
|
||||||
|
#define FBSDK_APPEVENTSUTILITY_ANONYMOUSIDFILENAME @"com-facebook-sdk-PersistedAnonymousID.json"
|
||||||
|
#define FBSDK_APPEVENTSUTILITY_ANONYMOUSID_KEY @"anon_id"
|
||||||
|
#define FBSDK_APPEVENTSUTILITY_MAX_IDENTIFIER_LENGTH 40
|
||||||
|
|
||||||
|
@implementation FBSDKAppEventsUtility
|
||||||
|
|
||||||
|
+ (NSMutableDictionary *)activityParametersDictionaryForEvent:(NSString *)eventCategory
|
||||||
|
implicitEventsOnly:(BOOL)implicitEventsOnly
|
||||||
|
shouldAccessAdvertisingID:(BOOL)shouldAccessAdvertisingID {
|
||||||
|
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||||||
|
parameters[@"event"] = eventCategory;
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
|
||||||
|
NSString *attributionID = [[self class] attributionID]; // Only present on iOS 6 and below.
|
||||||
|
[FBSDKBasicUtility dictionary:parameters setObject:attributionID forKey:@"attribution"];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!implicitEventsOnly && shouldAccessAdvertisingID) {
|
||||||
|
NSString *advertiserID = [[self class] advertiserID];
|
||||||
|
[FBSDKBasicUtility dictionary:parameters setObject:advertiserID forKey:@"advertiser_id"];
|
||||||
|
}
|
||||||
|
|
||||||
|
parameters[FBSDK_APPEVENTSUTILITY_ANONYMOUSID_KEY] = [FBSDKBasicUtility anonymousID];
|
||||||
|
|
||||||
|
FBSDKAdvertisingTrackingStatus advertisingTrackingStatus = [[self class] advertisingTrackingStatus];
|
||||||
|
if (advertisingTrackingStatus != FBSDKAdvertisingTrackingUnspecified) {
|
||||||
|
BOOL allowed = (advertisingTrackingStatus == FBSDKAdvertisingTrackingAllowed);
|
||||||
|
parameters[@"advertiser_tracking_enabled"] = @(allowed).stringValue;
|
||||||
|
}
|
||||||
|
if (advertisingTrackingStatus == FBSDKAdvertisingTrackingAllowed) {
|
||||||
|
NSString *userData = [FBSDKAppEvents getUserData];
|
||||||
|
if (userData){
|
||||||
|
parameters[@"ud"] = userData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parameters[@"application_tracking_enabled"] = @(!FBSDKSettings.limitEventAndDataUsage).stringValue;
|
||||||
|
|
||||||
|
NSString *userID = [FBSDKAppEvents userID];
|
||||||
|
if (userID) {
|
||||||
|
parameters[@"app_user_id"] = userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
[FBSDKAppEventsDeviceInfo extendDictionaryWithDeviceInfo:parameters];
|
||||||
|
|
||||||
|
static dispatch_once_t fetchBundleOnce;
|
||||||
|
static NSMutableArray *urlSchemes;
|
||||||
|
|
||||||
|
dispatch_once(&fetchBundleOnce, ^{
|
||||||
|
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||||
|
urlSchemes = [[NSMutableArray alloc] init];
|
||||||
|
for (NSDictionary<NSString *, id> *fields in [mainBundle objectForInfoDictionaryKey:@"CFBundleURLTypes"]) {
|
||||||
|
NSArray<NSString *> *schemesForType = fields[@"CFBundleURLSchemes"];
|
||||||
|
if (schemesForType) {
|
||||||
|
[urlSchemes addObjectsFromArray:schemesForType];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (urlSchemes.count > 0) {
|
||||||
|
parameters[@"url_schemes"] = [FBSDKBasicUtility JSONStringForObject:urlSchemes error:NULL invalidObjectHandler:NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)advertiserID
|
||||||
|
{
|
||||||
|
if (!FBSDKSettings.isAdvertiserIDCollectionEnabled) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *result = nil;
|
||||||
|
|
||||||
|
Class ASIdentifierManagerClass = fbsdkdfl_ASIdentifierManagerClass();
|
||||||
|
if ([ASIdentifierManagerClass class]) {
|
||||||
|
ASIdentifierManager *manager = [ASIdentifierManagerClass sharedManager];
|
||||||
|
result = manager.advertisingIdentifier.UUIDString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (FBSDKAdvertisingTrackingStatus)advertisingTrackingStatus
|
||||||
|
{
|
||||||
|
static dispatch_once_t fetchAdvertisingTrackingStatusOnce;
|
||||||
|
static FBSDKAdvertisingTrackingStatus status;
|
||||||
|
|
||||||
|
dispatch_once(&fetchAdvertisingTrackingStatusOnce, ^{
|
||||||
|
status = FBSDKAdvertisingTrackingUnspecified;
|
||||||
|
Class ASIdentifierManagerClass = fbsdkdfl_ASIdentifierManagerClass();
|
||||||
|
if ([ASIdentifierManagerClass class]) {
|
||||||
|
ASIdentifierManager *manager = [ASIdentifierManagerClass sharedManager];
|
||||||
|
if (manager) {
|
||||||
|
status = manager.advertisingTrackingEnabled ? FBSDKAdvertisingTrackingAllowed : FBSDKAdvertisingTrackingDisallowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)attributionID
|
||||||
|
{
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
return nil;
|
||||||
|
#else
|
||||||
|
return [UIPasteboard pasteboardWithName:@"fb_app_attribution" create:NO].string;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Internal, for testing
|
||||||
|
|
||||||
|
+ (void)clearLibraryFiles
|
||||||
|
{
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:[[self class] persistenceFilePath:FBSDK_APPEVENTSUTILITY_ANONYMOUSIDFILENAME]
|
||||||
|
error:NULL];
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:[[self class] persistenceFilePath:FBSDKTimeSpentFilename]
|
||||||
|
error:NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)ensureOnMainThread:(NSString *)methodName className:(NSString *)className
|
||||||
|
{
|
||||||
|
FBSDKConditionalLog([NSThread isMainThread],
|
||||||
|
FBSDKLoggingBehaviorDeveloperErrors,
|
||||||
|
@"*** <%@, %@> is not called on the main thread. This can lead to errors.",
|
||||||
|
methodName,
|
||||||
|
className);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)flushReasonToString:(FBSDKAppEventsFlushReason)flushReason
|
||||||
|
{
|
||||||
|
NSString *result = @"Unknown";
|
||||||
|
switch (flushReason) {
|
||||||
|
case FBSDKAppEventsFlushReasonExplicit:
|
||||||
|
result = @"Explicit";
|
||||||
|
break;
|
||||||
|
case FBSDKAppEventsFlushReasonTimer:
|
||||||
|
result = @"Timer";
|
||||||
|
break;
|
||||||
|
case FBSDKAppEventsFlushReasonSessionChange:
|
||||||
|
result = @"SessionChange";
|
||||||
|
break;
|
||||||
|
case FBSDKAppEventsFlushReasonPersistedEvents:
|
||||||
|
result = @"PersistedEvents";
|
||||||
|
break;
|
||||||
|
case FBSDKAppEventsFlushReasonEventThreshold:
|
||||||
|
result = @"EventCountThreshold";
|
||||||
|
break;
|
||||||
|
case FBSDKAppEventsFlushReasonEagerlyFlushingEvent:
|
||||||
|
result = @"EagerlyFlushingEvent";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)logAndNotify:(NSString *)msg
|
||||||
|
{
|
||||||
|
[[self class] logAndNotify:msg allowLogAsDeveloperError:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)logAndNotify:(NSString *)msg allowLogAsDeveloperError:(BOOL)allowLogAsDeveloperError
|
||||||
|
{
|
||||||
|
NSString *behaviorToLog = FBSDKLoggingBehaviorAppEvents;
|
||||||
|
if (allowLogAsDeveloperError) {
|
||||||
|
if ([FBSDKSettings.loggingBehaviors containsObject:FBSDKLoggingBehaviorDeveloperErrors]) {
|
||||||
|
// Rather than log twice, prefer 'DeveloperErrors' if it's set over AppEvents.
|
||||||
|
behaviorToLog = FBSDKLoggingBehaviorDeveloperErrors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[FBSDKLogger singleShotLogEntry:behaviorToLog logEntry:msg];
|
||||||
|
NSError *error = [FBSDKError errorWithCode:FBSDKErrorAppEventsFlush message:msg];
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:FBSDKAppEventsLoggingResultNotification object:error];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)matchString:(NSString *)string
|
||||||
|
firstCharacterSet:(NSCharacterSet *)firstCharacterSet
|
||||||
|
restOfStringCharacterSet:(NSCharacterSet *)restOfStringCharacterSet
|
||||||
|
{
|
||||||
|
if (string.length == 0) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
for (NSUInteger i = 0; i < string.length; i++) {
|
||||||
|
const unichar c = [string characterAtIndex:i];
|
||||||
|
if (i == 0) {
|
||||||
|
if (![firstCharacterSet characterIsMember:c]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (![restOfStringCharacterSet characterIsMember:c]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)regexValidateIdentifier:(NSString *)identifier
|
||||||
|
{
|
||||||
|
static NSCharacterSet *firstCharacterSet;
|
||||||
|
static NSCharacterSet *restOfStringCharacterSet;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
static NSMutableSet *cachedIdentifiers;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
NSMutableCharacterSet *mutableSet = [NSMutableCharacterSet alphanumericCharacterSet];
|
||||||
|
[mutableSet addCharactersInString:@"_"];
|
||||||
|
firstCharacterSet = [mutableSet copy];
|
||||||
|
|
||||||
|
[mutableSet addCharactersInString:@"- "];
|
||||||
|
restOfStringCharacterSet = [mutableSet copy];
|
||||||
|
cachedIdentifiers = [[NSMutableSet alloc] init];
|
||||||
|
});
|
||||||
|
|
||||||
|
@synchronized(self) {
|
||||||
|
if (![cachedIdentifiers containsObject:identifier]) {
|
||||||
|
if ([self matchString:identifier
|
||||||
|
firstCharacterSet:firstCharacterSet
|
||||||
|
restOfStringCharacterSet:restOfStringCharacterSet]) {
|
||||||
|
[cachedIdentifiers addObject:identifier];
|
||||||
|
} else {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)validateIdentifier:(NSString *)identifier
|
||||||
|
{
|
||||||
|
if (identifier == nil || identifier.length == 0 || identifier.length > FBSDK_APPEVENTSUTILITY_MAX_IDENTIFIER_LENGTH || ![[self class] regexValidateIdentifier:identifier]) {
|
||||||
|
[[self class] logAndNotify:[NSString stringWithFormat:@"Invalid identifier: '%@'. Must be between 1 and %d characters, and must be contain only alphanumerics, _, - or spaces, starting with alphanumeric or _.",
|
||||||
|
identifier, FBSDK_APPEVENTSUTILITY_MAX_IDENTIFIER_LENGTH]];
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a candidate token (which may be nil), find the real token to string to use.
|
||||||
|
// Precedence: 1) provided token, 2) current token, 3) app | client token, 4) fully anonymous session.
|
||||||
|
+ (NSString *)tokenStringToUseFor:(FBSDKAccessToken *)token
|
||||||
|
{
|
||||||
|
if (!token) {
|
||||||
|
token = [FBSDKAccessToken currentAccessToken];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *appID = [FBSDKAppEvents loggingOverrideAppID] ?: token.appID ?: [FBSDKSettings appID];
|
||||||
|
NSString *tokenString = token.tokenString;
|
||||||
|
if (!tokenString || ![appID isEqualToString:token.appID]) {
|
||||||
|
// If there's an logging override app id present, then we don't want to use the client token since the client token
|
||||||
|
// is intended to match up with the primary app id (and AppEvents doesn't require a client token).
|
||||||
|
NSString *clientTokenString = [FBSDKSettings clientToken];
|
||||||
|
if (clientTokenString && appID && [appID isEqualToString:token.appID]){
|
||||||
|
tokenString = [NSString stringWithFormat:@"%@|%@", appID, clientTokenString];
|
||||||
|
} else if (appID) {
|
||||||
|
tokenString = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tokenString;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (long)unixTimeNow
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isDebugBuild {
|
||||||
|
#if TARGET_IPHONE_SIMULATOR
|
||||||
|
return YES;
|
||||||
|
#else
|
||||||
|
BOOL isDevelopment = NO;
|
||||||
|
|
||||||
|
// There is no provisioning profile in AppStore Apps.
|
||||||
|
@try
|
||||||
|
{
|
||||||
|
NSData *data = [NSData dataWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"embedded" ofType:@"mobileprovision"]];
|
||||||
|
if (data) {
|
||||||
|
const char *bytes = [data bytes];
|
||||||
|
NSMutableString *profile = [[NSMutableString alloc] initWithCapacity:data.length];
|
||||||
|
for (NSUInteger i = 0; i < data.length; i++) {
|
||||||
|
[profile appendFormat:@"%c", bytes[i]];
|
||||||
|
}
|
||||||
|
// Look for debug value, if detected we're in a development build.
|
||||||
|
NSString *cleared = [[profile componentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet] componentsJoinedByString:@""];
|
||||||
|
isDevelopment = ([cleared rangeOfString:@"<key>get-task-allow</key><true/>"].length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isDevelopment;
|
||||||
|
}
|
||||||
|
@catch(NSException *exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isSensitiveUserData:(NSString *)text
|
||||||
|
{
|
||||||
|
if (0 == text.length) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [self isEmailAddress:text] || [self isCreditCardNumber:text];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isCreditCardNumber:(NSString *)text
|
||||||
|
{
|
||||||
|
text = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet.decimalDigitCharacterSet invertedSet]] componentsJoinedByString:@""];
|
||||||
|
|
||||||
|
if (text.doubleValue == 0) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.length < 9 || text.length > 21) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *chars = [text cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
if (NULL == chars) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL isOdd = YES;
|
||||||
|
int oddSum = 0;
|
||||||
|
int evenSum = 0;
|
||||||
|
|
||||||
|
for (int i = (int)text.length - 1; i >= 0; i--) {
|
||||||
|
int digit = chars[i] - '0';
|
||||||
|
|
||||||
|
if (isOdd)
|
||||||
|
oddSum += digit;
|
||||||
|
else
|
||||||
|
evenSum += digit / 5 + (2 * digit) % 10;
|
||||||
|
|
||||||
|
isOdd = !isOdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((oddSum + evenSum) % 10 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isEmailAddress:(NSString *)text
|
||||||
|
{
|
||||||
|
NSString *pattern = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
|
||||||
|
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
NSUInteger matches = [regex numberOfMatchesInString:text options:0 range:NSMakeRange(0, [text length])];
|
||||||
|
return matches > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <WebKit/WebKit.h>
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(HybridAppEventsScriptMessageHandler)
|
||||||
|
@interface FBSDKHybridAppEventsScriptMessageHandler : NSObject <WKScriptMessageHandler>
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKHybridAppEventsScriptMessageHandler.h"
|
||||||
|
|
||||||
|
#if SWIFT_PACKAGE
|
||||||
|
#import "FBSDKAppEvents.h"
|
||||||
|
#else
|
||||||
|
#import <FBSDKCoreKit/FBSDKAppEvents.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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 <NSString *, id> *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[FBSDKAppEventsWKWebViewMessagesPixelReferralParamKey] = pixelID;
|
||||||
|
}
|
||||||
|
[FBSDKAppEvents logInternalEvent:event
|
||||||
|
parameters:params
|
||||||
|
isImplicitlyLogged:NO];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
26
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentObserver.h
generated
Normal file
26
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentObserver.h
generated
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// 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>
|
||||||
|
|
||||||
|
// Class to encapsulate implicit logging of purchase events
|
||||||
|
NS_SWIFT_NAME(PaymentObserver)
|
||||||
|
@interface FBSDKPaymentObserver : NSObject
|
||||||
|
+ (void)startObservingTransactions;
|
||||||
|
+ (void)stopObservingTransactions;
|
||||||
|
@end
|
||||||
547
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentObserver.m
generated
Normal file
547
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentObserver.m
generated
Normal file
@ -0,0 +1,547 @@
|
|||||||
|
// 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 "FBSDKPaymentObserver.h"
|
||||||
|
|
||||||
|
#import <StoreKit/StoreKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKCoreKit+Internal.h"
|
||||||
|
|
||||||
|
#import "FBSDKAppEvents+Internal.h"
|
||||||
|
#import "FBSDKDynamicFrameworkLoader.h"
|
||||||
|
#import "FBSDKLogger.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
|
||||||
|
static NSString *const FBSDKPaymentObserverOriginalTransactionKey = @"com.facebook.appevents.PaymentObserver.originalTransaction";
|
||||||
|
static NSString *const FBSDKPaymentObserverDelimiter = @",";
|
||||||
|
|
||||||
|
static NSString *const FBSDKAppEventParameterImplicitlyLoggedPurchase = @"_implicitlyLogged";
|
||||||
|
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 FBSDKAppEventParameterNameOriginalTransactionID = @"fb_original_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 NSString *const FBSDKAppEventParameterNameIsStartTrial = @"fb_iap_is_start_trial";
|
||||||
|
static NSString *const FBSDKAppEventParameterNameHasFreeTrial = @"fb_iap_has_free_trial";
|
||||||
|
static NSString *const FBSDKAppEventParameterNameTrialPeriod = @"fb_iap_trial_period";
|
||||||
|
static NSString *const FBSDKAppEventParameterNameTrialPrice = @"fb_iap_trial_price";
|
||||||
|
static int const FBSDKMaxParameterValueLength = 100;
|
||||||
|
static NSMutableArray *g_pendingRequestors;
|
||||||
|
|
||||||
|
static NSString *const FBSDKGateKeeperAppEventsIfAutoLogSubs = @"app_events_if_auto_log_subs";
|
||||||
|
|
||||||
|
@interface FBSDKPaymentProductRequestor : NSObject<SKProductsRequestDelegate>
|
||||||
|
|
||||||
|
@property (nonatomic, retain) SKPaymentTransaction *transaction;
|
||||||
|
|
||||||
|
- (instancetype)initWithTransaction:(SKPaymentTransaction*)transaction;
|
||||||
|
- (void)resolveProducts;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface FBSDKPaymentObserver() <SKPaymentTransactionObserver>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKPaymentObserver
|
||||||
|
{
|
||||||
|
BOOL _observingTransactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)startObservingTransactions
|
||||||
|
{
|
||||||
|
[[self singleton] startObservingTransactions];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)stopObservingTransactions
|
||||||
|
{
|
||||||
|
[[self singleton] stopObservingTransactions];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Internal Methods
|
||||||
|
|
||||||
|
+ (FBSDKPaymentObserver *)singleton
|
||||||
|
{
|
||||||
|
static dispatch_once_t pred;
|
||||||
|
static FBSDKPaymentObserver *shared = nil;
|
||||||
|
|
||||||
|
dispatch_once(&pred, ^{
|
||||||
|
shared = [[FBSDKPaymentObserver alloc] init];
|
||||||
|
});
|
||||||
|
return shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_observingTransactions = NO;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startObservingTransactions
|
||||||
|
{
|
||||||
|
@synchronized (self) {
|
||||||
|
if (!_observingTransactions) {
|
||||||
|
[(SKPaymentQueue *)[fbsdkdfl_SKPaymentQueueClass() defaultQueue] addTransactionObserver:self];
|
||||||
|
_observingTransactions = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopObservingTransactions
|
||||||
|
{
|
||||||
|
@synchronized (self) {
|
||||||
|
if (_observingTransactions) {
|
||||||
|
[(SKPaymentQueue *)[fbsdkdfl_SKPaymentQueueClass() defaultQueue] removeTransactionObserver:self];
|
||||||
|
_observingTransactions = NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
|
||||||
|
{
|
||||||
|
for (SKPaymentTransaction *transaction in transactions) {
|
||||||
|
switch (transaction.transactionState) {
|
||||||
|
case SKPaymentTransactionStatePurchasing:
|
||||||
|
case SKPaymentTransactionStatePurchased:
|
||||||
|
case SKPaymentTransactionStateFailed:
|
||||||
|
case SKPaymentTransactionStateRestored:
|
||||||
|
[self handleTransaction:transaction];
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateDeferred:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)handleTransaction:(SKPaymentTransaction *)transaction
|
||||||
|
{
|
||||||
|
FBSDKPaymentProductRequestor *productRequest = [[FBSDKPaymentProductRequestor alloc] initWithTransaction:transaction];
|
||||||
|
[productRequest resolveProducts];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface FBSDKPaymentProductRequestor()
|
||||||
|
@property (nonatomic, retain) SKProductsRequest *productRequest;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKPaymentProductRequestor
|
||||||
|
{
|
||||||
|
NSMutableSet<NSString *> *_originalTransactionSet;
|
||||||
|
NSSet<NSString *> *_eventsWithReceipt;
|
||||||
|
NSDateFormatter *_formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
if ([self class] == [FBSDKPaymentProductRequestor class]) {
|
||||||
|
g_pendingRequestors = [[NSMutableArray alloc] init];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithTransaction:(SKPaymentTransaction*)transaction
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_transaction = transaction;
|
||||||
|
_formatter = [[NSDateFormatter alloc] init];
|
||||||
|
_formatter.dateFormat = @"yyyy-MM-dd HH:mm:ssZ";
|
||||||
|
NSString *data = [[NSUserDefaults standardUserDefaults] stringForKey:FBSDKPaymentObserverOriginalTransactionKey];
|
||||||
|
_eventsWithReceipt = [NSSet setWithArray:@[FBSDKAppEventNamePurchased, FBSDKAppEventNameSubscribe,
|
||||||
|
FBSDKAppEventNameStartTrial]];
|
||||||
|
if (data) {
|
||||||
|
_originalTransactionSet = [NSMutableSet setWithArray:[data componentsSeparatedByString:FBSDKPaymentObserverDelimiter]];
|
||||||
|
} else {
|
||||||
|
_originalTransactionSet = [[NSMutableSet alloc] init];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setProductRequest:(SKProductsRequest *)productRequest
|
||||||
|
{
|
||||||
|
if (productRequest != _productRequest) {
|
||||||
|
if (_productRequest) {
|
||||||
|
_productRequest.delegate = nil;
|
||||||
|
}
|
||||||
|
_productRequest = productRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)resolveProducts
|
||||||
|
{
|
||||||
|
NSString *productId = self.transaction.payment.productIdentifier;
|
||||||
|
NSSet *productIdentifiers = [NSSet setWithObjects:productId, nil];
|
||||||
|
self.productRequest = [[fbsdkdfl_SKProductsRequestClass() alloc] initWithProductIdentifiers:productIdentifiers];
|
||||||
|
self.productRequest.delegate = self;
|
||||||
|
@synchronized(g_pendingRequestors) {
|
||||||
|
[g_pendingRequestors addObject:self];
|
||||||
|
}
|
||||||
|
[self.productRequest start];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)getTruncatedString:(NSString *)inputString
|
||||||
|
{
|
||||||
|
if (!inputString) {
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputString.length <= FBSDKMaxParameterValueLength ? inputString : [inputString substringToIndex:FBSDKMaxParameterValueLength];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logTransactionEvent:(SKProduct *)product
|
||||||
|
{
|
||||||
|
if ([self isSubscription:product] &&
|
||||||
|
[FBSDKGateKeeperManager boolForKey:FBSDKGateKeeperAppEventsIfAutoLogSubs
|
||||||
|
defaultValue:NO]) {
|
||||||
|
[self logImplicitSubscribeTransaction:self.transaction ofProduct:product];
|
||||||
|
} else {
|
||||||
|
[self logImplicitPurchaseTransaction:self.transaction ofProduct:product];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isSubscription:(SKProduct *)product
|
||||||
|
{
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||||
|
if (@available(iOS 11.2, *)) {
|
||||||
|
return (product.subscriptionPeriod != nil) && ((unsigned long)product.subscriptionPeriod.numberOfUnits > 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableDictionary<NSString *, id> *)getEventParametersOfProduct:(SKProduct *)product
|
||||||
|
withTransaction:(SKPaymentTransaction *)transaction
|
||||||
|
{
|
||||||
|
NSString *transactionID = nil;
|
||||||
|
NSString *transactionDate = nil;
|
||||||
|
switch (transaction.transactionState) {
|
||||||
|
case SKPaymentTransactionStatePurchasing:
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStatePurchased:
|
||||||
|
transactionID = self.transaction.transactionIdentifier;
|
||||||
|
transactionDate = [_formatter stringFromDate:self.transaction.transactionDate];
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateFailed:
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateRestored:
|
||||||
|
transactionDate = [_formatter stringFromDate:self.transaction.transactionDate];
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
SKPayment *payment = transaction.payment;
|
||||||
|
NSMutableDictionary *eventParameters = [NSMutableDictionary dictionaryWithDictionary: @{
|
||||||
|
FBSDKAppEventParameterNameContentID: payment.productIdentifier ?: @"",
|
||||||
|
FBSDKAppEventParameterNameNumItems: @(payment.quantity),
|
||||||
|
FBSDKAppEventParameterNameTransactionDate: transactionDate ?: @"",
|
||||||
|
}];
|
||||||
|
if (product) {
|
||||||
|
[eventParameters addEntriesFromDictionary: @{
|
||||||
|
FBSDKAppEventParameterNameCurrency: [product.priceLocale objectForKey:NSLocaleCurrencyCode],
|
||||||
|
FBSDKAppEventParameterNameNumItems: @(payment.quantity),
|
||||||
|
FBSDKAppEventParameterNameProductTitle: [self getTruncatedString:product.localizedTitle],
|
||||||
|
FBSDKAppEventParameterNameDescription: [self getTruncatedString:product.localizedDescription],
|
||||||
|
}];
|
||||||
|
if (transactionID) {
|
||||||
|
eventParameters[FBSDKAppEventParameterNameTransactionID] = transactionID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||||
|
if (@available(iOS 11.2, *)) {
|
||||||
|
if ([self isSubscription:product]) {
|
||||||
|
// subs inapp
|
||||||
|
eventParameters[FBSDKAppEventParameterNameSubscriptionPeriod] = [self durationOfSubscriptionPeriod:product.subscriptionPeriod];
|
||||||
|
eventParameters[FBSDKAppEventParameterNameInAppPurchaseType] = @"subs";
|
||||||
|
eventParameters[FBSDKAppEventParameterNameIsStartTrial] = [self isStartTrial:transaction ofProduct:product] ? @"1" : @"0";
|
||||||
|
// trial information for subs
|
||||||
|
SKProductDiscount *discount = product.introductoryPrice;
|
||||||
|
if (discount) {
|
||||||
|
if (discount.paymentMode == SKProductDiscountPaymentModeFreeTrial) {
|
||||||
|
eventParameters[FBSDKAppEventParameterNameHasFreeTrial] = @"1";
|
||||||
|
} else {
|
||||||
|
eventParameters[FBSDKAppEventParameterNameHasFreeTrial] = @"0";
|
||||||
|
}
|
||||||
|
eventParameters[FBSDKAppEventParameterNameTrialPeriod] = [self durationOfSubscriptionPeriod:discount.subscriptionPeriod];
|
||||||
|
eventParameters[FBSDKAppEventParameterNameTrialPrice] = discount.price;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eventParameters[FBSDKAppEventParameterNameInAppPurchaseType] = @"inapp";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return eventParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)appendOriginalTransactionID:(NSString *)transactionID
|
||||||
|
{
|
||||||
|
if (!transactionID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[_originalTransactionSet addObject:transactionID];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:[[_originalTransactionSet allObjects] componentsJoinedByString:FBSDKPaymentObserverDelimiter]
|
||||||
|
forKey:FBSDKPaymentObserverOriginalTransactionKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)clearOriginalTransactionID:(NSString *)transactionID
|
||||||
|
{
|
||||||
|
if (!transactionID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[_originalTransactionSet removeObject:transactionID];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:[[_originalTransactionSet allObjects] componentsJoinedByString:FBSDKPaymentObserverDelimiter]
|
||||||
|
forKey:FBSDKPaymentObserverOriginalTransactionKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isStartTrial:(SKPaymentTransaction *)transaction
|
||||||
|
ofProduct:(SKProduct *)product
|
||||||
|
{
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_4
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_12_1
|
||||||
|
// promotional offer starting from iOS 12.2
|
||||||
|
if (@available(iOS 12.2, *)) {
|
||||||
|
SKPaymentDiscount *paymentDiscount = transaction.payment.paymentDiscount;
|
||||||
|
if (paymentDiscount) {
|
||||||
|
NSArray<SKProductDiscount *> *discounts = product.discounts;
|
||||||
|
for (SKProductDiscount *discount in discounts) {
|
||||||
|
if (discount.paymentMode == SKProductDiscountPaymentModeFreeTrial &&
|
||||||
|
[paymentDiscount.identifier isEqualToString:discount.identifier]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
// introductory offer starting from iOS 11.2
|
||||||
|
if (@available(iOS 11.2, *)) {
|
||||||
|
if (product.introductoryPrice &&
|
||||||
|
product.introductoryPrice.paymentMode == SKProductDiscountPaymentModeFreeTrial) {
|
||||||
|
NSString *originalTransactionID = transaction.originalTransaction.transactionIdentifier;
|
||||||
|
// only consider the very first trial transaction as start trial
|
||||||
|
if (!originalTransactionID) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasStartTrial:(SKProduct *)product
|
||||||
|
{
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_4
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_12_1
|
||||||
|
// promotional offer starting from iOS 12.2
|
||||||
|
if (@available(iOS 12.2, *)) {
|
||||||
|
NSArray<SKProductDiscount *> *discounts = product.discounts;
|
||||||
|
for (SKProductDiscount *discount in discounts) {
|
||||||
|
if (discount.paymentMode == SKProductDiscountPaymentModeFreeTrial) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
// introductory offer starting from iOS 11.2
|
||||||
|
if (@available(iOS 11.2, *)) {
|
||||||
|
if (product.introductoryPrice && (product.introductoryPrice.paymentMode == SKProductDiscountPaymentModeFreeTrial)) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)durationOfSubscriptionPeriod:(id)subcriptionPeriod
|
||||||
|
{
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||||
|
if (@available(iOS 11.2, *)) {
|
||||||
|
if (subcriptionPeriod && [subcriptionPeriod isKindOfClass:[SKProductSubscriptionPeriod class]]) {
|
||||||
|
SKProductSubscriptionPeriod *period = (SKProductSubscriptionPeriod *)subcriptionPeriod;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return [NSString stringWithFormat:@"P%lu%@", (unsigned long)period.numberOfUnits, unit];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
|
||||||
|
{
|
||||||
|
NSArray* products = response.products;
|
||||||
|
NSArray* invalidProductIdentifiers = response.invalidProductIdentifiers;
|
||||||
|
if (products.count + invalidProductIdentifiers.count != 1) {
|
||||||
|
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||||
|
formatString:@"FBSDKPaymentObserver: Expect to resolve one product per request"];
|
||||||
|
}
|
||||||
|
SKProduct *product = nil;
|
||||||
|
if (products.count) {
|
||||||
|
product = products[0];
|
||||||
|
}
|
||||||
|
[self logTransactionEvent:product];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)requestDidFinish:(SKRequest *)request
|
||||||
|
{
|
||||||
|
[self cleanUp];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
|
||||||
|
{
|
||||||
|
[self logTransactionEvent:nil];
|
||||||
|
[self cleanUp];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cleanUp
|
||||||
|
{
|
||||||
|
@synchronized(g_pendingRequestors) {
|
||||||
|
[g_pendingRequestors removeObject:self];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logImplicitSubscribeTransaction:(SKPaymentTransaction *)transaction
|
||||||
|
ofProduct:(SKProduct *)product
|
||||||
|
{
|
||||||
|
NSString *eventName = nil;
|
||||||
|
NSString *originalTransactionID = transaction.originalTransaction.transactionIdentifier;
|
||||||
|
switch (transaction.transactionState) {
|
||||||
|
case SKPaymentTransactionStatePurchasing:
|
||||||
|
eventName = @"SubscriptionInitiatedCheckout";
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStatePurchased:
|
||||||
|
if ([self isStartTrial:transaction ofProduct:product]) {
|
||||||
|
eventName = FBSDKAppEventNameStartTrial;
|
||||||
|
[self clearOriginalTransactionID:originalTransactionID];
|
||||||
|
} else {
|
||||||
|
if (originalTransactionID && [_originalTransactionSet containsObject:originalTransactionID]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eventName = FBSDKAppEventNameSubscribe;
|
||||||
|
[self appendOriginalTransactionID:(originalTransactionID ?: transaction.transactionIdentifier)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateFailed:
|
||||||
|
eventName = @"SubscriptionFailed";
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateRestored:
|
||||||
|
eventName = @"SubscriptionRestore";
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateDeferred:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double totalAmount = 0;
|
||||||
|
if (product) {
|
||||||
|
totalAmount = transaction.payment.quantity * product.price.doubleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self logImplicitTransactionEvent:eventName
|
||||||
|
valueToSum:totalAmount
|
||||||
|
parameters:[self getEventParametersOfProduct:product withTransaction:transaction]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logImplicitPurchaseTransaction:(SKPaymentTransaction *)transaction
|
||||||
|
ofProduct:(SKProduct *)product
|
||||||
|
{
|
||||||
|
NSString *eventName = nil;
|
||||||
|
switch (transaction.transactionState) {
|
||||||
|
case SKPaymentTransactionStatePurchasing:
|
||||||
|
eventName = FBSDKAppEventNameInitiatedCheckout;
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStatePurchased:
|
||||||
|
eventName = FBSDKAppEventNamePurchased;
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateFailed:
|
||||||
|
eventName = FBSDKAppEventNamePurchaseFailed;
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateRestored:
|
||||||
|
eventName = FBSDKAppEventNamePurchaseRestored;
|
||||||
|
break;
|
||||||
|
case SKPaymentTransactionStateDeferred:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double totalAmount = 0;
|
||||||
|
if (product) {
|
||||||
|
totalAmount = transaction.payment.quantity * product.price.doubleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self logImplicitTransactionEvent:eventName
|
||||||
|
valueToSum:totalAmount
|
||||||
|
parameters:[self getEventParametersOfProduct:product withTransaction:transaction]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logImplicitTransactionEvent:(NSString *)eventName
|
||||||
|
valueToSum:(double)valueToSum
|
||||||
|
parameters:(NSDictionary<NSString *, id> *)parameters
|
||||||
|
{
|
||||||
|
NSMutableDictionary *eventParameters = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||||
|
|
||||||
|
if ([_eventsWithReceipt containsObject:eventName]) {
|
||||||
|
NSData* receipt = [self fetchDeviceReceipt];
|
||||||
|
if (receipt) {
|
||||||
|
NSString *base64encodedReceipt = [receipt base64EncodedStringWithOptions:0];
|
||||||
|
eventParameters[@"receipt_data"] = base64encodedReceipt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventParameters[FBSDKAppEventParameterImplicitlyLoggedPurchase] = @"1";
|
||||||
|
[FBSDKAppEvents logEvent:eventName
|
||||||
|
valueToSum:valueToSum
|
||||||
|
parameters:eventParameters];
|
||||||
|
|
||||||
|
// Unless the behavior is set to only allow explicit flushing, we go ahead and flush, since purchase events
|
||||||
|
// are relatively rare and relatively high value and worth getting across on wire right away.
|
||||||
|
if ([FBSDKAppEvents flushBehavior] != FBSDKAppEventsFlushBehaviorExplicitOnly) {
|
||||||
|
[[FBSDKAppEvents singleton] flushForReason:FBSDKAppEventsFlushReasonEagerlyFlushingEvent];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the current receipt for this application.
|
||||||
|
- (NSData*)fetchDeviceReceipt
|
||||||
|
{
|
||||||
|
NSURL *receiptURL = [NSBundle bundleForClass:[self class]].appStoreReceiptURL;
|
||||||
|
NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
|
||||||
|
return receipt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
35
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKTimeSpentData.h
generated
Normal file
35
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKTimeSpentData.h
generated
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 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>
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKTimeSpentFilename;
|
||||||
|
|
||||||
|
// Class to encapsulate persisting of time spent data collected by [FBSDKAppEvents activateApp]. The activate app App Event is
|
||||||
|
// logged when restore: is called with sufficient time since the last deactivation.
|
||||||
|
NS_SWIFT_NAME(TimeSpentData)
|
||||||
|
@interface FBSDKTimeSpentData : NSObject
|
||||||
|
|
||||||
|
+ (void)suspend;
|
||||||
|
+ (void)restore:(BOOL)calledFromActivateApp;
|
||||||
|
|
||||||
|
+ (void)setSourceApplication:(NSString *)sourceApplication openURL:(NSURL *)url;
|
||||||
|
+ (void)setSourceApplication:(NSString *)sourceApplication isFromAppLink:(BOOL)isFromAppLink;
|
||||||
|
+ (void)registerAutoResetSourceApplication;
|
||||||
|
|
||||||
|
@end
|
||||||
319
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKTimeSpentData.m
generated
Normal file
319
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKTimeSpentData.m
generated
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
// 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 "FBSDKTimeSpentData.h"
|
||||||
|
|
||||||
|
#import "FBSDKAppEvents+Internal.h"
|
||||||
|
#import "FBSDKAppEventsUtility.h"
|
||||||
|
#import "FBSDKInternalUtility.h"
|
||||||
|
#import "FBSDKLogger.h"
|
||||||
|
#import "FBSDKServerConfiguration.h"
|
||||||
|
#import "FBSDKServerConfigurationManager.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Filename and keys for session length
|
||||||
|
NSString *const FBSDKTimeSpentFilename = @"com-facebook-sdk-AppEventsTimeSpent.json";
|
||||||
|
static NSString *const FBSDKTimeSpentPersistKeySessionSecondsSpent = @"secondsSpentInCurrentSession";
|
||||||
|
static NSString *const FBSDKTimeSpentPersistKeySessionNumInterruptions = @"numInterruptions";
|
||||||
|
static NSString *const FBSDKTimeSpentPersistKeyLastSuspendTime = @"lastSuspendTime";
|
||||||
|
static NSString *const FBSDKTimeSpentPersistKeySessionID = @"sessionID";
|
||||||
|
|
||||||
|
static NSString *const FBSDKAppEventNameActivatedApp = @"fb_mobile_activate_app";
|
||||||
|
static NSString *const FBSDKAppEventNameDeactivatedApp = @"fb_mobile_deactivate_app";
|
||||||
|
static NSString *const FBSDKAppEventParameterNameSessionInterruptions = @"fb_mobile_app_interruptions";
|
||||||
|
static NSString *const FBSDKAppEventParameterNameTimeBetweenSessions = @"fb_mobile_time_between_sessions";
|
||||||
|
static NSString *const FBSDKAppEventParameterNameSessionID = @"_session_id";
|
||||||
|
|
||||||
|
|
||||||
|
static const int SECS_PER_MIN = 60;
|
||||||
|
static const int SECS_PER_HOUR = 60 * SECS_PER_MIN;
|
||||||
|
static const int SECS_PER_DAY = 24 * SECS_PER_HOUR;
|
||||||
|
|
||||||
|
static NSString *g_sourceApplication;
|
||||||
|
static BOOL g_isOpenedFromAppLink;
|
||||||
|
|
||||||
|
// Will be translated and displayed in App Insights. Need to maintain same number and value of quanta on the server.
|
||||||
|
static const long INACTIVE_SECONDS_QUANTA[] =
|
||||||
|
{
|
||||||
|
5 * SECS_PER_MIN,
|
||||||
|
15 * SECS_PER_MIN,
|
||||||
|
30 * SECS_PER_MIN,
|
||||||
|
1 * SECS_PER_HOUR,
|
||||||
|
6 * SECS_PER_HOUR,
|
||||||
|
12 * SECS_PER_HOUR,
|
||||||
|
1 * SECS_PER_DAY,
|
||||||
|
2 * SECS_PER_DAY,
|
||||||
|
3 * SECS_PER_DAY,
|
||||||
|
7 * SECS_PER_DAY,
|
||||||
|
14 * SECS_PER_DAY,
|
||||||
|
21 * SECS_PER_DAY,
|
||||||
|
28 * SECS_PER_DAY,
|
||||||
|
60 * SECS_PER_DAY,
|
||||||
|
90 * SECS_PER_DAY,
|
||||||
|
120 * SECS_PER_DAY,
|
||||||
|
150 * SECS_PER_DAY,
|
||||||
|
180 * SECS_PER_DAY,
|
||||||
|
365 * SECS_PER_DAY,
|
||||||
|
LONG_MAX, // keep as LONG_MAX to guarantee loop will terminate
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class encapsulates the notion of an app 'session' - the length of time that the user has
|
||||||
|
* spent in the app that can be considered a single usage of the app. Apps may be frequently interrupted
|
||||||
|
* do to other device activity, like a text message, so this class allows those interruptions to be smoothed
|
||||||
|
* out and the time actually spent in the app excluding this interruption time to be accumulated. Also,
|
||||||
|
* once a certain amount of time has gone by where the app is not in the foreground, we consider the
|
||||||
|
* session to be complete, and a new session beginning. When this occurs, we log a 'deactivate app' event
|
||||||
|
* with the duration of the previous session as the 'value' of this event, along with the number of
|
||||||
|
* interruptions from that previous session as an event parameter.
|
||||||
|
*/
|
||||||
|
@implementation FBSDKTimeSpentData
|
||||||
|
{
|
||||||
|
BOOL _isCurrentlyLoaded;
|
||||||
|
BOOL _shouldLogActivateEvent;
|
||||||
|
BOOL _shouldLogDeactivateEvent;
|
||||||
|
long _secondsSpentInCurrentSession;
|
||||||
|
long _timeSinceLastSuspend;
|
||||||
|
int _numInterruptionsInCurrentSession;
|
||||||
|
long _lastRestoreTime;
|
||||||
|
long _lastSuspendTime;
|
||||||
|
NSString *_sessionID;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Public methods
|
||||||
|
//
|
||||||
|
|
||||||
|
+ (void)suspend
|
||||||
|
{
|
||||||
|
[self.singleton instanceSuspend];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)restore:(BOOL)calledFromActivateApp
|
||||||
|
{
|
||||||
|
[self.singleton instanceRestore:calledFromActivateApp];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Internal methods
|
||||||
|
//
|
||||||
|
+ (FBSDKTimeSpentData *)singleton
|
||||||
|
{
|
||||||
|
static dispatch_once_t pred;
|
||||||
|
static FBSDKTimeSpentData *shared = nil;
|
||||||
|
|
||||||
|
dispatch_once(&pred, ^{
|
||||||
|
shared = [[FBSDKTimeSpentData alloc] init];
|
||||||
|
});
|
||||||
|
return shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate and persist time spent data for this instance of the app activation.
|
||||||
|
- (void)instanceSuspend
|
||||||
|
{
|
||||||
|
|
||||||
|
[FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])];
|
||||||
|
if (!_isCurrentlyLoaded) {
|
||||||
|
FBSDKConditionalLog(YES, FBSDKLoggingBehaviorInformational, @"[FBSDKTimeSpentData suspend] invoked without corresponding restore");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long now = [FBSDKAppEventsUtility unixTimeNow];
|
||||||
|
long timeSinceRestore = now - _lastRestoreTime;
|
||||||
|
|
||||||
|
// Can happen if the clock on the device is changed
|
||||||
|
if (timeSinceRestore < 0) {
|
||||||
|
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||||
|
formatString:@"Clock skew detected"];
|
||||||
|
timeSinceRestore = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_secondsSpentInCurrentSession += timeSinceRestore;
|
||||||
|
|
||||||
|
NSDictionary *timeSpentData =
|
||||||
|
@{
|
||||||
|
FBSDKTimeSpentPersistKeySessionSecondsSpent : @(_secondsSpentInCurrentSession),
|
||||||
|
FBSDKTimeSpentPersistKeySessionNumInterruptions : @(_numInterruptionsInCurrentSession),
|
||||||
|
FBSDKTimeSpentPersistKeyLastSuspendTime : @(now),
|
||||||
|
FBSDKTimeSpentPersistKeySessionID : _sessionID,
|
||||||
|
};
|
||||||
|
|
||||||
|
NSString *content = [FBSDKBasicUtility JSONStringForObject:timeSpentData error:NULL invalidObjectHandler:NULL];
|
||||||
|
|
||||||
|
[content writeToFile:[FBSDKBasicUtility persistenceFilePath:FBSDKTimeSpentFilename]
|
||||||
|
atomically:YES
|
||||||
|
encoding:NSASCIIStringEncoding
|
||||||
|
error:nil];
|
||||||
|
|
||||||
|
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||||
|
formatString:@"FBSDKTimeSpentData Persist: %@", content];
|
||||||
|
|
||||||
|
_isCurrentlyLoaded = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Called during activation - either through an explicit 'activateApp' call or implicitly when the app is foregrounded.
|
||||||
|
// In both cases, we restore the persisted event data. In the case of the activateApp, we log an 'app activated'
|
||||||
|
// event if there's been enough time between the last deactivation and now.
|
||||||
|
- (void)instanceRestore:(BOOL)calledFromActivateApp
|
||||||
|
{
|
||||||
|
|
||||||
|
[FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])];
|
||||||
|
|
||||||
|
// It's possible to call this multiple times during the time the app is in the foreground. If this is the case,
|
||||||
|
// just restore persisted data the first time.
|
||||||
|
if (!_isCurrentlyLoaded) {
|
||||||
|
|
||||||
|
NSString *content =
|
||||||
|
[[NSString alloc] initWithContentsOfFile:[FBSDKBasicUtility persistenceFilePath:FBSDKTimeSpentFilename]
|
||||||
|
usedEncoding:nil
|
||||||
|
error:nil];
|
||||||
|
|
||||||
|
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||||
|
formatString:@"FBSDKTimeSpentData Restore: %@", content];
|
||||||
|
|
||||||
|
long now = [FBSDKAppEventsUtility unixTimeNow];
|
||||||
|
if (!content) {
|
||||||
|
|
||||||
|
// Nothing persisted, so this is the first launch.
|
||||||
|
_sessionID = [NSUUID UUID].UUIDString;
|
||||||
|
_secondsSpentInCurrentSession = 0;
|
||||||
|
_numInterruptionsInCurrentSession = 0;
|
||||||
|
_lastSuspendTime = 0;
|
||||||
|
|
||||||
|
// We want to log the app activation event on the first launch, but not the deactivate event
|
||||||
|
_shouldLogActivateEvent = YES;
|
||||||
|
_shouldLogDeactivateEvent = NO;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
NSDictionary<id, id> *results = [FBSDKBasicUtility objectForJSONString:content error:NULL];
|
||||||
|
|
||||||
|
_lastSuspendTime = [results[FBSDKTimeSpentPersistKeyLastSuspendTime] longValue];
|
||||||
|
|
||||||
|
_timeSinceLastSuspend = now - _lastSuspendTime;
|
||||||
|
_secondsSpentInCurrentSession = [results[FBSDKTimeSpentPersistKeySessionSecondsSpent] intValue];
|
||||||
|
_sessionID = results[FBSDKTimeSpentPersistKeySessionID] ? : [NSUUID UUID].UUIDString;
|
||||||
|
_numInterruptionsInCurrentSession = [results[FBSDKTimeSpentPersistKeySessionNumInterruptions] intValue];
|
||||||
|
_shouldLogActivateEvent = (_timeSinceLastSuspend > [FBSDKServerConfigurationManager cachedServerConfiguration].sessionTimoutInterval);
|
||||||
|
|
||||||
|
// Other than the first launch, we always log the last session's deactivate with this session's activate.
|
||||||
|
_shouldLogDeactivateEvent = _shouldLogActivateEvent;
|
||||||
|
|
||||||
|
if (!_shouldLogDeactivateEvent) {
|
||||||
|
// If we're not logging, then the time we spent deactivated is considered another interruption. But cap it
|
||||||
|
// so errant or test uses doesn't blow out the cardinality on the backend processing
|
||||||
|
_numInterruptionsInCurrentSession = MIN(_numInterruptionsInCurrentSession + 1, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastRestoreTime = now;
|
||||||
|
_isCurrentlyLoaded = YES;
|
||||||
|
|
||||||
|
if (calledFromActivateApp) {
|
||||||
|
// It's important to log deactivate first to reset sessionID
|
||||||
|
if (_shouldLogDeactivateEvent) {
|
||||||
|
[FBSDKAppEvents logEvent:FBSDKAppEventNameDeactivatedApp
|
||||||
|
valueToSum:_secondsSpentInCurrentSession
|
||||||
|
parameters:[self appEventsParametersForDeactivate]];
|
||||||
|
|
||||||
|
// We've logged the session stats, now reset.
|
||||||
|
_secondsSpentInCurrentSession = 0;
|
||||||
|
_numInterruptionsInCurrentSession = 0;
|
||||||
|
_sessionID = [NSUUID UUID].UUIDString;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_shouldLogActivateEvent) {
|
||||||
|
[FBSDKAppEvents logEvent:FBSDKAppEventNameActivatedApp
|
||||||
|
parameters:[self appEventsParametersForActivate]];
|
||||||
|
// Unless the behavior is set to only allow explicit flushing, we go ahead and flush. App launch
|
||||||
|
// events are critical to Analytics so we don't want to lose them.
|
||||||
|
if ([FBSDKAppEvents flushBehavior] != FBSDKAppEventsFlushBehaviorExplicitOnly) {
|
||||||
|
[[FBSDKAppEvents singleton] flushForReason:FBSDKAppEventsFlushReasonEagerlyFlushingEvent];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)appEventsParametersForActivate
|
||||||
|
{
|
||||||
|
return @{
|
||||||
|
FBSDKAppEventParameterLaunchSource: [[self class] getSourceApplication],
|
||||||
|
FBSDKAppEventParameterNameSessionID: _sessionID,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)appEventsParametersForDeactivate
|
||||||
|
{
|
||||||
|
int quantaIndex = 0;
|
||||||
|
while (_timeSinceLastSuspend > INACTIVE_SECONDS_QUANTA[quantaIndex]) {
|
||||||
|
quantaIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableDictionary *params = [@{ FBSDKAppEventParameterNameSessionInterruptions : @(_numInterruptionsInCurrentSession),
|
||||||
|
FBSDKAppEventParameterNameTimeBetweenSessions : [NSString stringWithFormat:@"session_quanta_%d", quantaIndex],
|
||||||
|
FBSDKAppEventParameterLaunchSource: [[self class] getSourceApplication],
|
||||||
|
FBSDKAppEventParameterNameSessionID : _sessionID ?: @"",
|
||||||
|
} mutableCopy];
|
||||||
|
if (_lastSuspendTime) {
|
||||||
|
params[FBSDKAppEventParameterLogTime] = @(_lastSuspendTime);
|
||||||
|
}
|
||||||
|
return [params copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setSourceApplication:(NSString *)sourceApplication openURL:(NSURL *)url
|
||||||
|
{
|
||||||
|
[self setSourceApplication:sourceApplication
|
||||||
|
isFromAppLink:[FBSDKInternalUtility dictionaryFromFBURL:url][@"al_applink_data"] != nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setSourceApplication:(NSString *)sourceApplication isFromAppLink:(BOOL)isFromAppLink
|
||||||
|
{
|
||||||
|
g_isOpenedFromAppLink = isFromAppLink;
|
||||||
|
g_sourceApplication = sourceApplication;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getSourceApplication
|
||||||
|
{
|
||||||
|
NSString *openType = @"Unclassified";
|
||||||
|
if (g_isOpenedFromAppLink) {
|
||||||
|
openType = @"AppLink";
|
||||||
|
}
|
||||||
|
return (g_sourceApplication ?
|
||||||
|
[NSString stringWithFormat:@"%@(%@)", openType, g_sourceApplication]
|
||||||
|
: openType);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)resetSourceApplication
|
||||||
|
{
|
||||||
|
g_sourceApplication = nil;
|
||||||
|
g_isOpenedFromAppLink = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)registerAutoResetSourceApplication
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(resetSourceApplication)
|
||||||
|
name:UIApplicationDidEnterBackgroundNotification
|
||||||
|
object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
48
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKUserDataStore.h
generated
Normal file
48
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKUserDataStore.h
generated
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// 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 "FBSDKAppEvents+Internal.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(UserDataStore)
|
||||||
|
@interface FBSDKUserDataStore : NSObject
|
||||||
|
|
||||||
|
+ (void)setAndHashUserEmail:(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;
|
||||||
|
+ (void)setAndHashData:(nullable NSString *)data
|
||||||
|
forType:(FBSDKAppEventUserDataType)type;
|
||||||
|
+ (void)setHashData:(nullable NSString *)hashData
|
||||||
|
forType:(FBSDKAppEventUserDataType)type;
|
||||||
|
+ (nullable NSString *)getHashedData;
|
||||||
|
+ (nullable NSString *)getHashedDataForType:(FBSDKAppEventUserDataType)type;
|
||||||
|
+ (void)clearDataForType:(FBSDKAppEventUserDataType)type;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
199
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKUserDataStore.m
generated
Normal file
199
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKUserDataStore.m
generated
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
// 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 "FBSDKAppEventsUtility.h"
|
||||||
|
#import "FBSDKLogger.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
#import "FBSDKUtility.h"
|
||||||
|
|
||||||
|
static NSString *const FBSDKUserDataKey = @"com.facebook.appevents.UserDataStore.userData";
|
||||||
|
|
||||||
|
static NSMutableDictionary<NSString *, NSString *> *hashedUserData;
|
||||||
|
static dispatch_queue_t serialQueue;
|
||||||
|
|
||||||
|
@implementation FBSDKUserDataStore
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
serialQueue = dispatch_queue_create("com.facebook.appevents.UserDataStore", DISPATCH_QUEUE_SERIAL);
|
||||||
|
NSString *userData = [[NSUserDefaults standardUserDefaults] stringForKey:FBSDKUserDataKey];
|
||||||
|
if (userData) {
|
||||||
|
hashedUserData = (NSMutableDictionary<NSString *, NSString *> *)[NSJSONSerialization JSONObjectWithData:[userData dataUsingEncoding:NSUTF8StringEncoding]
|
||||||
|
options:NSJSONReadingMutableContainers
|
||||||
|
error:nil];
|
||||||
|
}
|
||||||
|
if (!hashedUserData) {
|
||||||
|
hashedUserData = [[NSMutableDictionary alloc] init];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setAndHashUserEmail:(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
|
||||||
|
{
|
||||||
|
NSMutableDictionary *ud = [[NSMutableDictionary alloc] init];
|
||||||
|
if (email) {
|
||||||
|
ud[FBSDKAppEventEmail] = [FBSDKUserDataStore encryptData:email type:FBSDKAppEventEmail];
|
||||||
|
}
|
||||||
|
if (firstName) {
|
||||||
|
ud[FBSDKAppEventFirstName] = [FBSDKUserDataStore encryptData:firstName type:FBSDKAppEventFirstName];
|
||||||
|
}
|
||||||
|
if (lastName) {
|
||||||
|
ud[FBSDKAppEventLastName] = [FBSDKUserDataStore encryptData:lastName type:FBSDKAppEventLastName];
|
||||||
|
}
|
||||||
|
if (phone) {
|
||||||
|
ud[FBSDKAppEventPhone] = [FBSDKUserDataStore encryptData:phone type:FBSDKAppEventPhone];
|
||||||
|
}
|
||||||
|
if (dateOfBirth) {
|
||||||
|
ud[FBSDKAppEventDateOfBirth] = [FBSDKUserDataStore encryptData:dateOfBirth type:FBSDKAppEventDateOfBirth];
|
||||||
|
}
|
||||||
|
if (gender) {
|
||||||
|
ud[FBSDKAppEventGender] = [FBSDKUserDataStore encryptData:gender type:FBSDKAppEventGender];
|
||||||
|
}
|
||||||
|
if (city) {
|
||||||
|
ud[FBSDKAppEventCity] = [FBSDKUserDataStore encryptData:city type:FBSDKAppEventCity];
|
||||||
|
}
|
||||||
|
if (state) {
|
||||||
|
ud[FBSDKAppEventState] = [FBSDKUserDataStore encryptData:state type:FBSDKAppEventState];
|
||||||
|
}
|
||||||
|
if (zip) {
|
||||||
|
ud[FBSDKAppEventZip] = [FBSDKUserDataStore encryptData:zip type:FBSDKAppEventZip];
|
||||||
|
}
|
||||||
|
if (country) {
|
||||||
|
ud[FBSDKAppEventCountry] = [FBSDKUserDataStore encryptData:country type:FBSDKAppEventCountry];
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch_async(serialQueue, ^{
|
||||||
|
hashedUserData = [ud mutableCopy];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:[FBSDKUserDataStore stringByHashedData:hashedUserData]
|
||||||
|
forKey:FBSDKUserDataKey];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setAndHashData:(nullable NSString *)data
|
||||||
|
forType:(FBSDKAppEventUserDataType)type
|
||||||
|
{
|
||||||
|
[FBSDKUserDataStore setHashData:[FBSDKUserDataStore encryptData:data type:type]
|
||||||
|
forType:type];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setHashData:(nullable NSString *)hashData
|
||||||
|
forType:(FBSDKAppEventUserDataType)type
|
||||||
|
{
|
||||||
|
dispatch_async(serialQueue, ^{
|
||||||
|
if (!hashData) {
|
||||||
|
[hashedUserData removeObjectForKey:type];
|
||||||
|
} else {
|
||||||
|
hashedUserData[type] = hashData;
|
||||||
|
}
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:[FBSDKUserDataStore stringByHashedData:hashedUserData]
|
||||||
|
forKey:FBSDKUserDataKey];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)clearDataForType:(FBSDKAppEventUserDataType)type
|
||||||
|
{
|
||||||
|
[FBSDKUserDataStore setAndHashData:nil forType:type];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getHashedData
|
||||||
|
{
|
||||||
|
__block NSString *hashedUserDataString;
|
||||||
|
dispatch_sync(serialQueue, ^{
|
||||||
|
hashedUserDataString = [FBSDKUserDataStore stringByHashedData:hashedUserData];
|
||||||
|
});
|
||||||
|
return hashedUserDataString;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getHashedDataForType:(FBSDKAppEventUserDataType)type
|
||||||
|
{
|
||||||
|
__block NSString *hashedData;
|
||||||
|
dispatch_sync(serialQueue, ^{
|
||||||
|
hashedData = [hashedUserData objectForKey:type];
|
||||||
|
});
|
||||||
|
return hashedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)stringByHashedData:(id)hashedData
|
||||||
|
{
|
||||||
|
NSError *error;
|
||||||
|
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:hashedData
|
||||||
|
options:0
|
||||||
|
error:&error];
|
||||||
|
if (jsonData) {
|
||||||
|
return [[NSString alloc] initWithData:jsonData
|
||||||
|
encoding:NSUTF8StringEncoding];
|
||||||
|
} else {
|
||||||
|
[FBSDKAppEventsUtility logAndNotify:[NSString stringWithFormat:@"Invalid json object: %@", error]];
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)encryptData:(NSString *)data
|
||||||
|
type:(FBSDKAppEventUserDataType)type
|
||||||
|
{
|
||||||
|
if (data.length == 0 || [FBSDKUserDataStore maybeSHA256Hashed:data]) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
return [FBSDKUtility SHA256Hash:[FBSDKUserDataStore normalizeData:data type:type]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)normalizeData:(NSString *)data
|
||||||
|
type:(FBSDKAppEventUserDataType)type
|
||||||
|
{
|
||||||
|
NSString *normalizedData = @"";
|
||||||
|
NSSet<FBSDKAppEventUserDataType> *set = [NSSet setWithArray:
|
||||||
|
@[FBSDKAppEventEmail, FBSDKAppEventFirstName, FBSDKAppEventLastName, FBSDKAppEventCity, FBSDKAppEventState, FBSDKAppEventCountry]];
|
||||||
|
if ([set containsObject:type]) {
|
||||||
|
normalizedData = [data stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||||
|
normalizedData = normalizedData.lowercaseString;
|
||||||
|
} else if ([type isEqualToString:FBSDKAppEventPhone]) {
|
||||||
|
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:FBSDKAppEventGender]) {
|
||||||
|
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
|
||||||
35
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelManager.h
generated
Normal file
35
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelManager.h
generated
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
typedef void (^FBSDKDownloadCompletionBlock)(BOOL success);
|
||||||
|
|
||||||
|
@interface FBSDKModelManager : NSObject
|
||||||
|
|
||||||
|
+ (void)enable;
|
||||||
|
+ (nullable NSDictionary *)getRules;
|
||||||
|
+ (nullable NSString *)getWeightsPath:(NSString *_Nonnull)useCaseKey;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
233
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelManager.m
generated
Normal file
233
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelManager.m
generated
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKModelManager.h"
|
||||||
|
|
||||||
|
#import "FBSDKAddressFilterManager.h"
|
||||||
|
#import "FBSDKAddressInferencer.h"
|
||||||
|
#import "FBSDKEventInferencer.h"
|
||||||
|
#import "FBSDKFeatureExtractor.h"
|
||||||
|
#import "FBSDKFeatureManager.h"
|
||||||
|
#import "FBSDKGraphRequest.h"
|
||||||
|
#import "FBSDKGraphRequestConnection.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
#import "FBSDKSuggestedEventsIndexer.h"
|
||||||
|
#import "FBSDKTypeUtility.h"
|
||||||
|
#import "FBSDKViewHierarchyMacros.h"
|
||||||
|
|
||||||
|
#define FBSDK_ML_MODEL_PATH @"models"
|
||||||
|
|
||||||
|
static NSString *const MODEL_INFO_KEY= @"com.facebook.sdk:FBSDKModelInfo";
|
||||||
|
static NSString *const ASSET_URI_KEY = @"asset_uri";
|
||||||
|
static NSString *const RULES_URI_KEY = @"rules_uri";
|
||||||
|
static NSString *const THRESHOLDS_KEY = @"thresholds";
|
||||||
|
static NSString *const USE_CASE_KEY = @"use_case";
|
||||||
|
static NSString *const VERSION_ID_KEY = @"version_id";
|
||||||
|
static NSString *const MODEL_DATA_KEY = @"data";
|
||||||
|
static NSString *const ADDRESS_FILTERING_KEY = @"DATA_DETECTION_ADDRESS";
|
||||||
|
|
||||||
|
static NSString *_directoryPath;
|
||||||
|
static NSMutableDictionary<NSString *, id> *_modelInfo;
|
||||||
|
|
||||||
|
@implementation FBSDKModelManager
|
||||||
|
|
||||||
|
+ (void)enable
|
||||||
|
{
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
NSString *languageCode = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode];
|
||||||
|
// If the languageCode could not be fetched successfully, it's regarded as "en" by default.
|
||||||
|
if (languageCode && ![languageCode isEqualToString:@"en"]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *dirPath = [NSTemporaryDirectory() stringByAppendingPathComponent:FBSDK_ML_MODEL_PATH];
|
||||||
|
if (![[NSFileManager defaultManager] fileExistsAtPath:dirPath]) {
|
||||||
|
[[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:NO attributes:NULL error:NULL];
|
||||||
|
}
|
||||||
|
_directoryPath = dirPath;
|
||||||
|
|
||||||
|
// fetch api
|
||||||
|
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
|
||||||
|
initWithGraphPath:[NSString stringWithFormat:@"%@/model_asset", [FBSDKSettings appID]]];
|
||||||
|
|
||||||
|
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
|
||||||
|
if (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id> *resultDictionary = [FBSDKTypeUtility dictionaryValue:result];
|
||||||
|
NSDictionary<NSString *, id> *modelInfo = [self convertToDictionary:resultDictionary[MODEL_DATA_KEY]];
|
||||||
|
if (!modelInfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// update cache
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:modelInfo forKey:MODEL_INFO_KEY];
|
||||||
|
|
||||||
|
[FBSDKFeatureManager checkFeature:FBSDKFeatureSuggestedEvents completionBlock:^(BOOL enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
[self getModelAndRules:SUGGEST_EVENT_KEY handler:^(BOOL success){
|
||||||
|
if (success) {
|
||||||
|
[FBSDKEventInferencer loadWeights];
|
||||||
|
[FBSDKFeatureExtractor loadRules];
|
||||||
|
[FBSDKSuggestedEventsIndexer enable];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
[FBSDKFeatureManager checkFeature:FBSDKFeaturePIIFiltering completionBlock:^(BOOL enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
[self getModelAndRules:ADDRESS_FILTERING_KEY handler:^(BOOL success){
|
||||||
|
if (success) {
|
||||||
|
[FBSDKAddressInferencer loadWeights];
|
||||||
|
[FBSDKAddressInferencer initializeDenseFeature];
|
||||||
|
[FBSDKAddressFilterManager enable];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)getModelAndRules:(NSString *)useCaseKey
|
||||||
|
handler:(FBSDKDownloadCompletionBlock)handler
|
||||||
|
{
|
||||||
|
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||||
|
dispatch_group_t group = dispatch_group_create();
|
||||||
|
_modelInfo = [[NSUserDefaults standardUserDefaults] objectForKey:MODEL_INFO_KEY];
|
||||||
|
if (!_modelInfo || !_directoryPath) {
|
||||||
|
if (handler) {
|
||||||
|
handler(NO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id> *model = [_modelInfo objectForKey:useCaseKey];
|
||||||
|
|
||||||
|
if (!model) {
|
||||||
|
if (handler) {
|
||||||
|
handler(NO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear old model files
|
||||||
|
NSArray<NSString *> *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:_directoryPath error:nil];
|
||||||
|
NSString *prefixWithVersion = [NSString stringWithFormat:@"%@_%@", useCaseKey, model[VERSION_ID_KEY]];
|
||||||
|
|
||||||
|
for (NSString *file in files) {
|
||||||
|
if ([file hasPrefix:useCaseKey] && ![file hasPrefix:prefixWithVersion]) {
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:[_directoryPath stringByAppendingPathComponent:file] error:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// download model asset
|
||||||
|
NSString *assetUrlString = [model objectForKey:ASSET_URI_KEY];
|
||||||
|
NSString *assetFilePath;
|
||||||
|
if (assetUrlString.length > 0) {
|
||||||
|
assetFilePath = [_directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.weights", useCaseKey, model[VERSION_ID_KEY]]];
|
||||||
|
[self download:assetUrlString filePath:assetFilePath queue:queue group:group];
|
||||||
|
}
|
||||||
|
|
||||||
|
// download rules
|
||||||
|
NSString *rulesUrlString = [model objectForKey:RULES_URI_KEY];
|
||||||
|
NSString *rulesFilePath;
|
||||||
|
// rules are optional and rulesUrlString may be empty
|
||||||
|
if (rulesUrlString.length > 0) {
|
||||||
|
rulesFilePath = [_directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.rules", useCaseKey, model[VERSION_ID_KEY]]];
|
||||||
|
[self download:rulesUrlString filePath:rulesFilePath queue:queue group:group];
|
||||||
|
}
|
||||||
|
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
|
||||||
|
if (handler) {
|
||||||
|
if ([[NSFileManager defaultManager] fileExistsAtPath:assetFilePath] && (!rulesUrlString || (rulesUrlString && [[NSFileManager defaultManager] fileExistsAtPath:rulesFilePath]))) {
|
||||||
|
handler(YES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handler(NO);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)download:(NSString *)urlString
|
||||||
|
filePath:(NSString *)filePath
|
||||||
|
queue:(dispatch_queue_t)queue
|
||||||
|
group:(dispatch_group_t)group
|
||||||
|
{
|
||||||
|
if (!filePath || [[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch_group_async(group, queue, ^{
|
||||||
|
NSURL *url = [NSURL URLWithString:urlString];
|
||||||
|
NSData *urlData = [NSData dataWithContentsOfURL:url];
|
||||||
|
if (urlData) {
|
||||||
|
[urlData writeToFile:filePath atomically:YES];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (nullable NSMutableDictionary<NSString *, id> *)convertToDictionary:(NSArray<NSDictionary<NSString *, id> *> *)models
|
||||||
|
{
|
||||||
|
if ([models count] == 0) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSMutableDictionary<NSString *, id> *modelInfo = [NSMutableDictionary dictionary];
|
||||||
|
for (NSDictionary<NSString *, id> *model in models) {
|
||||||
|
if (model[USE_CASE_KEY]) {
|
||||||
|
[modelInfo addEntriesFromDictionary:@{model[USE_CASE_KEY]:model}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modelInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (nullable NSDictionary *)getRules
|
||||||
|
{
|
||||||
|
NSDictionary<NSString *, id> *cachedModelInfo = [[NSUserDefaults standardUserDefaults] objectForKey:MODEL_INFO_KEY];
|
||||||
|
if (!cachedModelInfo) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id> *model = [cachedModelInfo objectForKey:SUGGEST_EVENT_KEY];
|
||||||
|
if (model && model[VERSION_ID_KEY]) {
|
||||||
|
NSString *filePath = [_directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.rules", SUGGEST_EVENT_KEY, model[VERSION_ID_KEY]]];
|
||||||
|
if (filePath) {
|
||||||
|
NSData *ruelsData = [NSData dataWithContentsOfFile:filePath];
|
||||||
|
NSDictionary *rules = [NSJSONSerialization JSONObjectWithData:ruelsData options:0 error:nil];
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (nullable NSString *)getWeightsPath:(NSString *_Nonnull)useCaseKey
|
||||||
|
{
|
||||||
|
NSDictionary<NSString *, id> *cachedModelInfo = [[NSUserDefaults standardUserDefaults] objectForKey:MODEL_INFO_KEY];
|
||||||
|
if (!cachedModelInfo || !_directoryPath) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id> *model = [cachedModelInfo objectForKey:useCaseKey];
|
||||||
|
if (model && model[VERSION_ID_KEY]) {
|
||||||
|
return [_directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.weights", useCaseKey, model[VERSION_ID_KEY]]];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
310
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelRuntime.hpp
generated
Normal file
310
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelRuntime.hpp
generated
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#import <Accelerate/Accelerate.h>
|
||||||
|
|
||||||
|
#include "FBSDKStandaloneModel.hpp"
|
||||||
|
|
||||||
|
#define SEQ_LEN 128
|
||||||
|
#define ALPHABET_SIZE 256
|
||||||
|
#define EMBEDDING_SIZE 64
|
||||||
|
#define DENSE_FEATURE_LEN 30
|
||||||
|
|
||||||
|
const int CONV_BLOCKS[3][3] = {{32, 2, SEQ_LEN - 1}, {32, 3, SEQ_LEN - 2}, {32, 5, SEQ_LEN - 4}};
|
||||||
|
|
||||||
|
namespace mat1 {
|
||||||
|
static void relu(float *data, int len) {
|
||||||
|
float min = 0;
|
||||||
|
float max = FLT_MAX;
|
||||||
|
vDSP_vclip(data, 1, &min, &max, data, 1, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void concatenate(float *dst, float *a, float *b, int a_len, int b_len) {
|
||||||
|
memcpy(dst, a, a_len * sizeof(float));
|
||||||
|
memcpy(dst + a_len, b, b_len * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void softmax(float *data, int n) {
|
||||||
|
int i = 0;
|
||||||
|
float max = FLT_MIN;
|
||||||
|
float sum = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (data[i] > max) {
|
||||||
|
max = data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++){
|
||||||
|
data[i] = expf(data[i] - max);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++){
|
||||||
|
sum += data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++){
|
||||||
|
data[i] = data[i] / sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static float* embedding(int *a, float *b, int n_examples, int seq_length, int embedding_size) {
|
||||||
|
int i,j,k,val;
|
||||||
|
float* res = (float *)malloc(sizeof(float) * (n_examples * seq_length * embedding_size));
|
||||||
|
for (i = 0; i < n_examples; i++) {
|
||||||
|
for (j = 0; j < seq_length; j++) {
|
||||||
|
val = a[i * seq_length + j];
|
||||||
|
for (k = 0; k < embedding_size; k++) {
|
||||||
|
res[(embedding_size * seq_length) * i + embedding_size * j + k] = b[val * embedding_size + k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
a shape: n_examples, in_vector_size
|
||||||
|
b shape: n_examples, out_vector_size
|
||||||
|
c shape: out_vector_size
|
||||||
|
return shape: n_examples, out_vector_size
|
||||||
|
*/
|
||||||
|
static float* dense(float *a, float *b, float *c, int n_examples, int in_vector_size, int out_vector_size) {
|
||||||
|
int i,j;
|
||||||
|
float *m_res = (float *)malloc(sizeof(float) * (n_examples * out_vector_size));
|
||||||
|
vDSP_mmul(a, 1, b, 1, m_res, 1, n_examples, out_vector_size, in_vector_size);
|
||||||
|
for (i = 0; i < n_examples; i++) {
|
||||||
|
for (j = 0; j < out_vector_size; j++) {
|
||||||
|
m_res[i * out_vector_size + j] += c[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
x shape: n_examples, seq_len, input_size
|
||||||
|
w shape: kernel_size, input_size, output_size
|
||||||
|
return shape: n_examples, seq_len - kernel_size + 1, output_size
|
||||||
|
*/
|
||||||
|
static float* conv1D(float *x, float *w, int n_examples, int seq_len, int input_size, int kernel_size, int output_size) {
|
||||||
|
int n, o, i, k, m;
|
||||||
|
float sum;
|
||||||
|
float *res = (float *)malloc(sizeof(float) * (n_examples * (seq_len - kernel_size + 1) * output_size));
|
||||||
|
float *temp_x = (float *)malloc(sizeof(float) * (kernel_size * input_size));
|
||||||
|
float *temp_w = (float *)malloc(sizeof(float) * (kernel_size * input_size));
|
||||||
|
for (n = 0; n < n_examples; n++){
|
||||||
|
for (o = 0; o < output_size; o++){
|
||||||
|
for (i = 0; i < seq_len - kernel_size + 1; i++) {
|
||||||
|
sum = 0;
|
||||||
|
for (m = 0; m < kernel_size; m++) {
|
||||||
|
for (k = 0; k < input_size; k++) {
|
||||||
|
temp_x[m * input_size + k] = x[n * (seq_len * input_size) + (m + i) * input_size + k];
|
||||||
|
temp_w[m * input_size + k] = w[(m * input_size + k) * output_size + o];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vDSP_dotpr(temp_x, 1, temp_w, 1, &sum, kernel_size * input_size);
|
||||||
|
res[(n * (output_size * (seq_len - kernel_size + 1)) + i * output_size + o)] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(temp_x);
|
||||||
|
free(temp_w);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
input shape: n_examples, len, n_channel
|
||||||
|
return shape: n_examples, len - pool_size + 1, n_channel
|
||||||
|
*/
|
||||||
|
static float* maxPool1D(float *input, int n_examples, int input_len, int n_channel, int pool_size) {
|
||||||
|
int res_len = input_len - pool_size + 1;
|
||||||
|
float* res = (float *)calloc(n_examples * res_len * n_channel, sizeof(float));
|
||||||
|
|
||||||
|
for (int n = 0; n < n_examples; n++) {
|
||||||
|
for (int c = 0; c < n_channel; c++) {
|
||||||
|
for (int i = 0; i < res_len; i++) {
|
||||||
|
for (int r = i; r < i + pool_size; r++) {
|
||||||
|
int res_pos = n * (n_channel * res_len) + i * n_channel + c;
|
||||||
|
int input_pos = n * (n_channel * input_len) + r * n_channel + c;
|
||||||
|
if (r == i) {
|
||||||
|
res[res_pos] = input[input_pos];
|
||||||
|
} else {
|
||||||
|
res[res_pos] = fmax(res[res_pos], input[input_pos]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int* vectorize(const char *texts, int str_len, int max_len) {
|
||||||
|
int *res = (int *)malloc(sizeof(int) * max_len);
|
||||||
|
for (int i = 0; i < max_len; i++) {
|
||||||
|
if (i < str_len){
|
||||||
|
res[i] = static_cast<unsigned char>(texts[i]);
|
||||||
|
} else {
|
||||||
|
res[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
input shape: m, n
|
||||||
|
return shape: n, m
|
||||||
|
*/
|
||||||
|
static float* transpose2D(float *input, int m, int n) {
|
||||||
|
float *transposed = (float *)malloc(sizeof(float) * m * n);
|
||||||
|
for (int i = 0; i < m; i++){
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
transposed[j * m + i] = input[i * n + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transposed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
input shape: m, n, p
|
||||||
|
return shape: p, n, m
|
||||||
|
*/
|
||||||
|
static float* transpose3D(float *input, int64_t m, int n, int p) {
|
||||||
|
float *transposed = (float *)malloc((size_t)(sizeof(float) * m * n * p));
|
||||||
|
for (int i = 0; i < m; i++){
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
for (int k = 0; k < p; k++) {
|
||||||
|
transposed[k * m * n + j * m + i] = input[i * n * p + j * p + k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transposed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float* add(float *a, float *b, int m, int n, int p) {
|
||||||
|
for(int i = 0; i < m * n; i++){
|
||||||
|
for(int j = 0; j < p; j++){
|
||||||
|
a[i * p + j] += b[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float* predictOnText(const char *texts, std::unordered_map<std::string, mat::MTensor>& weights, float *df) {
|
||||||
|
int *x;
|
||||||
|
float *embed_x;
|
||||||
|
float *dense1_x;
|
||||||
|
float *dense2_x;
|
||||||
|
float *dense3_x;
|
||||||
|
float *c1;
|
||||||
|
float *c2;
|
||||||
|
float *c3;
|
||||||
|
float *ca;
|
||||||
|
float *cb;
|
||||||
|
float *cc;
|
||||||
|
|
||||||
|
mat::MTensor& embed_t = weights.at("embed.weight");
|
||||||
|
mat::MTensor& conv1w_t = weights.at("convs.0.weight"); // (32, 64, 2)
|
||||||
|
mat::MTensor& conv2w_t = weights.at("convs.1.weight");
|
||||||
|
mat::MTensor& conv3w_t = weights.at("convs.2.weight");
|
||||||
|
mat::MTensor& conv1b_t = weights.at("convs.0.bias");
|
||||||
|
mat::MTensor& conv2b_t = weights.at("convs.1.bias");
|
||||||
|
mat::MTensor& conv3b_t = weights.at("convs.2.bias");
|
||||||
|
mat::MTensor& fc1w_t = weights.at("fc1.weight"); // (128, 126)
|
||||||
|
mat::MTensor& fc1b_t = weights.at("fc1.bias"); // 128
|
||||||
|
mat::MTensor& fc2w_t = weights.at("fc2.weight"); // (64, 128)
|
||||||
|
mat::MTensor& fc2b_t = weights.at("fc2.bias"); // 64
|
||||||
|
mat::MTensor& fc3w_t = weights.at("fc3.weight"); // (2, 64) or (4, 64)
|
||||||
|
mat::MTensor& fc3b_t = weights.at("fc3.bias"); // 2 or 4
|
||||||
|
|
||||||
|
float *embed_weight = embed_t.data<float>();
|
||||||
|
float *convs_0_weight = transpose3D(conv1w_t.data<float>(), (int)conv1w_t.size(0), (int)conv1w_t.size(1), (int)conv1w_t.size(2)); // (2, 64, 32)
|
||||||
|
float *convs_1_weight = transpose3D(conv2w_t.data<float>(), (int)conv2w_t.size(0), (int)conv2w_t.size(1), (int)conv2w_t.size(2));
|
||||||
|
float *convs_2_weight = transpose3D(conv3w_t.data<float>(), (int)conv3w_t.size(0), (int)conv3w_t.size(1), (int)conv3w_t.size(2));
|
||||||
|
float *convs_0_bias = conv1b_t.data<float>();
|
||||||
|
float *convs_1_bias = conv2b_t.data<float>();
|
||||||
|
float *convs_2_bias = conv3b_t.data<float>();
|
||||||
|
float *fc1_weight = transpose2D(fc1w_t.data<float>(), (int)fc1w_t.size(0), (int)fc1w_t.size(1));
|
||||||
|
float *fc2_weight = transpose2D(fc2w_t.data<float>(), (int)fc2w_t.size(0), (int)fc2w_t.size(1));
|
||||||
|
float *fc3_weight = transpose2D(fc3w_t.data<float>(), (int)fc3w_t.size(0), (int)fc3w_t.size(1));
|
||||||
|
float *fc1_bias = fc1b_t.data<float>();
|
||||||
|
float *fc2_bias = fc2b_t.data<float>();
|
||||||
|
float *fc3_bias = fc3b_t.data<float>();
|
||||||
|
|
||||||
|
// vectorize text
|
||||||
|
x = vectorize(texts, (int)strlen(texts), SEQ_LEN);
|
||||||
|
|
||||||
|
// embedding
|
||||||
|
embed_x = embedding(x, embed_weight, 1, SEQ_LEN, EMBEDDING_SIZE); // (1, 128, 64)
|
||||||
|
free(x);
|
||||||
|
|
||||||
|
// conv1D
|
||||||
|
c1 = conv1D(embed_x, convs_0_weight, 1, SEQ_LEN, EMBEDDING_SIZE, (int)conv1w_t.size(2), (int)conv1w_t.size(0)); // (1, 127, 32) CONV_BLOCKS[0][1], CONV_BLOCKS[0][0]
|
||||||
|
c2 = conv1D(embed_x, convs_1_weight, 1, SEQ_LEN, EMBEDDING_SIZE, (int)conv2w_t.size(2), (int)conv2w_t.size(0)); // (1, 126, 32)
|
||||||
|
c3 = conv1D(embed_x, convs_2_weight, 1, SEQ_LEN, EMBEDDING_SIZE, (int)conv3w_t.size(2), (int)conv3w_t.size(0)); // (1, 124, 32)
|
||||||
|
free(embed_x);
|
||||||
|
|
||||||
|
// add bias
|
||||||
|
add(c1, convs_0_bias, 1, (int)(SEQ_LEN - conv1w_t.size(2) + 1), (int)conv1w_t.size(0));
|
||||||
|
add(c2, convs_1_bias, 1, (int)(SEQ_LEN - conv2w_t.size(2) + 1), (int)conv2w_t.size(0));
|
||||||
|
add(c3, convs_2_bias, 1, (int)(SEQ_LEN - conv3w_t.size(2) + 1), (int)conv3w_t.size(0));
|
||||||
|
|
||||||
|
// relu
|
||||||
|
relu(c1, (int)(SEQ_LEN - conv1w_t.size(2) + 1) * (int)conv1w_t.size(0));
|
||||||
|
relu(c2, (int)(SEQ_LEN - conv2w_t.size(2) + 1) * (int)conv2w_t.size(0));
|
||||||
|
relu(c3, (int)(SEQ_LEN - conv3w_t.size(2) + 1) * (int)conv3w_t.size(0));
|
||||||
|
|
||||||
|
// max pooling
|
||||||
|
ca = maxPool1D(c1, 1, (int)(SEQ_LEN - conv1w_t.size(2) + 1), (int)conv1w_t.size(0), (int)(SEQ_LEN - conv1w_t.size(2) + 1)); // (1, 1, 32)
|
||||||
|
cb = maxPool1D(c2, 1, (int)(SEQ_LEN - conv2w_t.size(2) + 1), (int)conv2w_t.size(0), (int)(SEQ_LEN - conv2w_t.size(2) + 1)); // (1, 1, 32)
|
||||||
|
cc = maxPool1D(c3, 1, (int)(SEQ_LEN - conv3w_t.size(2) + 1), (int)conv3w_t.size(0), (int)(SEQ_LEN - conv3w_t.size(2) + 1)); // (1, 1, 32)
|
||||||
|
free(c1);
|
||||||
|
free(c2);
|
||||||
|
free(c3);
|
||||||
|
|
||||||
|
// concatenate
|
||||||
|
float *concat = (float *)malloc((size_t)(sizeof(float) * (conv1w_t.size(0) + conv2w_t.size(0) + conv3w_t.size(0) + 30)));
|
||||||
|
concatenate(concat, ca, cb, (int)conv1w_t.size(0), (int)conv2w_t.size(0));
|
||||||
|
concatenate(concat + conv1w_t.size(0) + conv2w_t.size(0), cc, df, (int)conv3w_t.size(0), 30);
|
||||||
|
free(ca);
|
||||||
|
free(cb);
|
||||||
|
free(cc);
|
||||||
|
|
||||||
|
// dense + relu
|
||||||
|
dense1_x = dense(concat, fc1_weight, fc1_bias, 1, (int)fc1w_t.size(1), (int)fc1w_t.size(0));
|
||||||
|
free(concat);
|
||||||
|
relu(dense1_x, (int)fc1b_t.size(0));
|
||||||
|
dense2_x = dense(dense1_x, fc2_weight, fc2_bias, 1, (int)fc2w_t.size(1), (int)fc2w_t.size(0));
|
||||||
|
relu(dense2_x, (int)fc2b_t.size(0));
|
||||||
|
free(dense1_x);
|
||||||
|
dense3_x = dense(dense2_x, fc3_weight, fc3_bias, 1, (int)fc3w_t.size(1), (int)fc3w_t.size(0));
|
||||||
|
free(dense2_x);
|
||||||
|
softmax(dense3_x, (int)fc3b_t.size(0));
|
||||||
|
return dense3_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
31
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelUtility.h
generated
Normal file
31
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelUtility.h
generated
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface FBSDKModelUtility : NSObject
|
||||||
|
|
||||||
|
+ (NSString *)normalizeText:(NSString *)text;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
38
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelUtility.m
generated
Normal file
38
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKModelUtility.m
generated
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "FBSDKModelUtility.h"
|
||||||
|
|
||||||
|
@implementation FBSDKModelUtility : NSObject
|
||||||
|
|
||||||
|
+ (NSString *)normalizeText:(NSString *)text
|
||||||
|
{
|
||||||
|
NSMutableArray *tokens = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] mutableCopy];
|
||||||
|
[tokens removeObject:@""];
|
||||||
|
return [tokens componentsJoinedByString: @" "];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
152
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKStandaloneModel.hpp
generated
Normal file
152
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/ML/FBSDKStandaloneModel.hpp
generated
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#import <Accelerate/Accelerate.h>
|
||||||
|
|
||||||
|
// minimal aten implementation
|
||||||
|
#define MAT_ALWAYS_INLINE inline __attribute__((always_inline))
|
||||||
|
namespace mat {
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
class MTensorAccessor {
|
||||||
|
public:
|
||||||
|
MAT_ALWAYS_INLINE
|
||||||
|
MTensorAccessor(T* data, const int64_t* sizes, const int64_t* strides)
|
||||||
|
: data_(data), sizes_(sizes), strides_(strides) {}
|
||||||
|
|
||||||
|
MAT_ALWAYS_INLINE MTensorAccessor<T, N - 1> operator[](int64_t i) {
|
||||||
|
return MTensorAccessor<T, N - 1>(
|
||||||
|
this->data_ + this->strides_[0] * i,
|
||||||
|
this->sizes_ + 1,
|
||||||
|
this->strides_ + 1);
|
||||||
|
}
|
||||||
|
T* data_;
|
||||||
|
private:
|
||||||
|
const int64_t* sizes_;
|
||||||
|
const int64_t* strides_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class MTensorAccessor<T, 1> {
|
||||||
|
public:
|
||||||
|
MAT_ALWAYS_INLINE
|
||||||
|
MTensorAccessor(T* data, const int64_t* sizes, const int64_t* strides)
|
||||||
|
: data_(data), sizes_(sizes), strides_(strides) {}
|
||||||
|
|
||||||
|
MAT_ALWAYS_INLINE T& operator[](int64_t i) {
|
||||||
|
// assume stride==1 in innermost dimension.
|
||||||
|
// DCHECK_EQ(strides_[0], 1);
|
||||||
|
return this->data_[i];
|
||||||
|
}
|
||||||
|
T* data_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int64_t* sizes_;
|
||||||
|
const int64_t* strides_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void* MAllocateMemory(size_t nbytes) {
|
||||||
|
void* ptr = nullptr;
|
||||||
|
assert(nbytes > 0);
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
ptr = memalign(64, nbytes);
|
||||||
|
#else
|
||||||
|
const int ret = posix_memalign(&ptr, 64, nbytes);
|
||||||
|
(void)ret;
|
||||||
|
assert(ret == 0);
|
||||||
|
#endif
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MFreeMemory(void* ptr) {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MCheckPtr(void* ptr) {
|
||||||
|
if (ptr) {
|
||||||
|
MFreeMemory(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MTensor {
|
||||||
|
public:
|
||||||
|
MTensor(){};
|
||||||
|
MTensor(const std::vector<int64_t>& sizes) {
|
||||||
|
auto strides = std::vector<int64_t>(sizes.size());
|
||||||
|
strides[strides.size() - 1] = 1;
|
||||||
|
for (auto i = static_cast<int32_t>(strides.size()) - 2; i >= 0; --i) {
|
||||||
|
strides[i] = strides[i + 1] * sizes[i + 1];
|
||||||
|
}
|
||||||
|
strides_ = strides;
|
||||||
|
sizes_ = sizes;
|
||||||
|
// assume float32 storage.
|
||||||
|
size_t nbytes = sizeof(float);
|
||||||
|
for (auto size : sizes) {
|
||||||
|
nbytes *= size;
|
||||||
|
}
|
||||||
|
storage_ = std::shared_ptr<void>(MAllocateMemory(nbytes), MCheckPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t size(int dim) {
|
||||||
|
return sizes_[dim];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<int64_t>& sizes() const {
|
||||||
|
return sizes_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<int64_t>& strides() const {
|
||||||
|
return strides_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* data() {
|
||||||
|
return static_cast<T*>(storage_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
MTensorAccessor<T, N> accessor() {
|
||||||
|
return MTensorAccessor<T, N>(data<T>(), sizes().data(), strides().data());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<int64_t> sizes_;
|
||||||
|
std::vector<int64_t> strides_;
|
||||||
|
std::shared_ptr<void> storage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static MTensor mempty(const std::vector<int64_t>& sizes) {
|
||||||
|
return MTensor(sizes);
|
||||||
|
}
|
||||||
|
} // namespace mat
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface FBSDKAddressFilterManager : NSObject
|
||||||
|
|
||||||
|
+ (void)enable;
|
||||||
|
+ (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKAddressFilterManager.h"
|
||||||
|
|
||||||
|
#import "FBSDKAddressInferencer.h"
|
||||||
|
#import "FBSDKBasicUtility.h"
|
||||||
|
#import "FBSDKGateKeeperManager.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
#import "FBSDKTypeUtility.h"
|
||||||
|
|
||||||
|
static BOOL isAddressFilterEnabled = NO;
|
||||||
|
static BOOL isSampleEnabled = NO;
|
||||||
|
|
||||||
|
@implementation FBSDKAddressFilterManager
|
||||||
|
|
||||||
|
+ (void)enable
|
||||||
|
{
|
||||||
|
isAddressFilterEnabled = YES;
|
||||||
|
isSampleEnabled = [FBSDKGateKeeperManager boolForKey:@"FBSDKFeatureAddressDetectionSample" defaultValue:false];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||||
|
{
|
||||||
|
if (!isAddressFilterEnabled || parameters.count == 0) {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
NSMutableDictionary<NSString *, id> *params = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||||
|
NSMutableDictionary<NSString *, id> *addressParams = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
for (NSString *key in [parameters keyEnumerator]) {
|
||||||
|
NSString *valueString =[FBSDKTypeUtility stringValue:parameters[key]];
|
||||||
|
BOOL shouldFilter = [FBSDKAddressInferencer shouldFilterParam:valueString];
|
||||||
|
if (shouldFilter) {
|
||||||
|
[addressParams setObject:isSampleEnabled ? valueString : @"" forKey:key];
|
||||||
|
[params removeObjectForKey:key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ([addressParams count] > 0) {
|
||||||
|
NSString *addressParamsJSONString = [FBSDKBasicUtility JSONStringForObject:addressParams
|
||||||
|
error:NULL
|
||||||
|
invalidObjectHandler:NULL];
|
||||||
|
[FBSDKBasicUtility dictionary:params setObject:addressParamsJSONString forKey:@"_onDeviceParams"];
|
||||||
|
}
|
||||||
|
return [params copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface FBSDKAddressInferencer : NSObject
|
||||||
|
|
||||||
|
+ (void)initializeDenseFeature;
|
||||||
|
+ (void)loadWeights;
|
||||||
|
+ (BOOL)shouldFilterParam:(nullable NSString *)param;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,213 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKAddressInferencer.h"
|
||||||
|
|
||||||
|
#import "FBSDKModelManager.h"
|
||||||
|
#import "FBSDKModelRuntime.hpp"
|
||||||
|
#import "FBSDKModelUtility.h"
|
||||||
|
#import "FBSDKStandaloneModel.hpp"
|
||||||
|
|
||||||
|
#include<stdexcept>
|
||||||
|
|
||||||
|
static NSString *const MODEL_INFO_KEY= @"com.facebook.sdk:FBSDKModelInfo";
|
||||||
|
static NSString *const THRESHOLDS_KEY = @"thresholds";
|
||||||
|
static NSString *const DATA_DETECTION_ADDRESS_KEY = @"DATA_DETECTION_ADDRESS";
|
||||||
|
static NSDictionary<NSString *, NSArray *> *const WEIGHTS_INFO = @{@"embed.weight" : @[@(256), @(64)],
|
||||||
|
@"convs.0.weight" : @[@(32), @(64), @(2)],
|
||||||
|
@"convs.0.bias" : @[@(32)],
|
||||||
|
@"convs.1.weight" : @[@(32), @(64), @(3)],
|
||||||
|
@"convs.1.bias" : @[@(32)],
|
||||||
|
@"convs.2.weight" : @[@(32), @(64), @(5)],
|
||||||
|
@"convs.2.bias" : @[@(32)],
|
||||||
|
@"fc1.weight": @[@(128), @(126)],
|
||||||
|
@"fc1.bias": @[@(128)],
|
||||||
|
@"fc2.weight": @[@(64), @(128)],
|
||||||
|
@"fc2.bias": @[@(64)],
|
||||||
|
@"fc3.weight": @[@(2), @(64)],
|
||||||
|
@"fc3.bias": @[@(2)]};
|
||||||
|
|
||||||
|
static NSDictionary<NSString *, NSString *> *const WEIGHTS_KEYS = @{@"embedding.weight": @"embed.weight",
|
||||||
|
@"dense1.weight": @"fc1.weight",
|
||||||
|
@"dense2.weight": @"fc2.weight",
|
||||||
|
@"dense3.weight": @"fc3.weight",
|
||||||
|
@"dense1.bias": @"fc1.bias",
|
||||||
|
@"dense2.bias": @"fc2.bias",
|
||||||
|
@"dense3.bias": @"fc3.bias"};
|
||||||
|
|
||||||
|
@implementation FBSDKAddressInferencer : NSObject
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, mat::MTensor> _weights;
|
||||||
|
static std::vector<float> _denseFeature;
|
||||||
|
|
||||||
|
+ (void)initializeDenseFeature
|
||||||
|
{
|
||||||
|
std::vector<float> dense_feature(30);
|
||||||
|
std::fill(dense_feature.begin(), dense_feature.end(), 0);
|
||||||
|
_denseFeature = dense_feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)loadWeights
|
||||||
|
{
|
||||||
|
NSString *path = [FBSDKModelManager getWeightsPath:DATA_DETECTION_ADDRESS_KEY];
|
||||||
|
if (!path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSData *latestData = [NSData dataWithContentsOfFile:path
|
||||||
|
options:NSDataReadingMappedIfSafe
|
||||||
|
error:nil];
|
||||||
|
if (!latestData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::unordered_map<std::string, mat::MTensor> weights = [self loadWeights:latestData];
|
||||||
|
if ([self validateWeights:weights]) {
|
||||||
|
_weights = weights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (bool)validateWeights: (std::unordered_map<std::string, mat::MTensor>) weights
|
||||||
|
{
|
||||||
|
if (WEIGHTS_INFO.count != weights.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (NSString *key in WEIGHTS_INFO) {
|
||||||
|
if (weights.count(std::string([key UTF8String])) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mat::MTensor tensor = weights[std::string([key UTF8String])];
|
||||||
|
const std::vector<int64_t>& actualSize = tensor.sizes();
|
||||||
|
NSArray *expectedSize = WEIGHTS_INFO[key];
|
||||||
|
if (actualSize.size() != expectedSize.count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < expectedSize.count; i++) {
|
||||||
|
if((int)actualSize[i] != (int)[expectedSize[i] intValue]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (std::unordered_map<std::string, mat::MTensor>)loadWeights:(NSData *)weightsData{
|
||||||
|
std::unordered_map<std::string, mat::MTensor> weights;
|
||||||
|
|
||||||
|
const void *data = weightsData.bytes;
|
||||||
|
NSUInteger totalLength = weightsData.length;
|
||||||
|
|
||||||
|
int totalFloats = 0;
|
||||||
|
if (weightsData.length < 4) {
|
||||||
|
// Make sure data length is valid
|
||||||
|
return weights;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
int length;
|
||||||
|
memcpy(&length, data, 4);
|
||||||
|
if (length + 4 > totalLength) {
|
||||||
|
// Make sure data length is valid
|
||||||
|
return weights;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *json = (char *)data + 4;
|
||||||
|
NSDictionary<NSString *, id> *info = [NSJSONSerialization JSONObjectWithData:[NSData dataWithBytes:json length:length]
|
||||||
|
options:0
|
||||||
|
error:nil];
|
||||||
|
NSArray<NSString *> *keys = [[info allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString *key1, NSString *key2) {
|
||||||
|
return [key1 compare:key2];
|
||||||
|
}];
|
||||||
|
|
||||||
|
float *floats = (float *)(json + length);
|
||||||
|
for (NSString *key in keys) {
|
||||||
|
NSString *finalKey = key;
|
||||||
|
NSString *mapping = [WEIGHTS_KEYS objectForKey:key];
|
||||||
|
if (mapping) {
|
||||||
|
finalKey = mapping;
|
||||||
|
}
|
||||||
|
std::string s_name([finalKey UTF8String]);
|
||||||
|
|
||||||
|
std::vector<int64_t> v_shape;
|
||||||
|
NSArray<NSString *> *shape = [info objectForKey:key];
|
||||||
|
int count = 1;
|
||||||
|
for (NSNumber *_s in shape) {
|
||||||
|
int i = [_s intValue];
|
||||||
|
v_shape.push_back(i);
|
||||||
|
count *= i;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalFloats += count;
|
||||||
|
|
||||||
|
if ((4 + length + totalFloats * 4) > totalLength) {
|
||||||
|
// Make sure data length is valid
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mat::MTensor tensor = mat::mempty(v_shape);
|
||||||
|
float *tensor_data = tensor.data<float>();
|
||||||
|
memcpy(tensor_data, floats, sizeof(float) * count);
|
||||||
|
floats += count;
|
||||||
|
|
||||||
|
weights[s_name] = tensor;
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {}
|
||||||
|
|
||||||
|
return weights;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)shouldFilterParam:(nullable NSString *)param
|
||||||
|
{
|
||||||
|
if (!param || _weights.size() == 0 || _denseFeature.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *text = [FBSDKModelUtility normalizeText:param];
|
||||||
|
const char *bytes = [text UTF8String];
|
||||||
|
if ((int)strlen(bytes) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
float *predictedRaw;
|
||||||
|
NSMutableDictionary<NSString *, id> *modelInfo = [[NSUserDefaults standardUserDefaults] objectForKey:MODEL_INFO_KEY];
|
||||||
|
if (!modelInfo) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id> * addressModelInfo = [modelInfo objectForKey:DATA_DETECTION_ADDRESS_KEY];
|
||||||
|
if (!addressModelInfo) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NSMutableArray *thresholds = [addressModelInfo objectForKey:THRESHOLDS_KEY];
|
||||||
|
float threshold = [thresholds[0] floatValue];
|
||||||
|
try {
|
||||||
|
predictedRaw = mat1::predictOnText(bytes, _weights, &_denseFeature[0]);
|
||||||
|
if (!predictedRaw[1]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return predictedRaw[1] >= threshold;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
@interface FBSDKRestrictiveDataFilterManager : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
+ (void)enable;
|
||||||
|
+ (void)updateFilters:(nullable NSDictionary<NSString *, id> *)restrictiveParams;
|
||||||
|
+ (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||||
|
eventName:(NSString *)eventName;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@ -0,0 +1,146 @@
|
|||||||
|
// 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 "FBSDKRestrictiveDataFilterManager.h"
|
||||||
|
|
||||||
|
#import "FBSDKBasicUtility.h"
|
||||||
|
#import "FBSDKTypeUtility.h"
|
||||||
|
|
||||||
|
static NSString *const RESTRICTIVE_PARAM_KEY = @"restrictive_param";
|
||||||
|
|
||||||
|
@interface FBSDKRestrictiveEventFilter : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, readonly, copy) NSString *eventName;
|
||||||
|
@property (nonatomic, readonly, copy) NSDictionary<NSString *, id> *restrictiveParams;
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
-(instancetype)initWithEventName:(NSString *)eventName
|
||||||
|
restrictiveParams:(NSDictionary<NSString *, id> *)restrictiveParams;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKRestrictiveEventFilter
|
||||||
|
|
||||||
|
-(instancetype)initWithEventName:(NSString *)eventName
|
||||||
|
restrictiveParams:(NSDictionary<NSString *, id> *)restrictiveParams
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_eventName = eventName;
|
||||||
|
_restrictiveParams = restrictiveParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKRestrictiveDataFilterManager
|
||||||
|
|
||||||
|
static BOOL isRestrictiveEventFilterEnabled = NO;
|
||||||
|
|
||||||
|
static NSMutableArray<FBSDKRestrictiveEventFilter *> *_params;
|
||||||
|
|
||||||
|
+ (void)updateFilters:(nullable NSDictionary<NSString *, id> *)restrictiveParams
|
||||||
|
{
|
||||||
|
if (!isRestrictiveEventFilterEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (restrictiveParams.count > 0) {
|
||||||
|
[_params removeAllObjects];
|
||||||
|
NSMutableArray<FBSDKRestrictiveEventFilter *> *eventFilterArray = [NSMutableArray array];
|
||||||
|
for (NSString *eventName in restrictiveParams.allKeys) {
|
||||||
|
NSDictionary<NSString *, id> *eventInfo = restrictiveParams[eventName];
|
||||||
|
if (!eventInfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (eventInfo[RESTRICTIVE_PARAM_KEY]) {
|
||||||
|
FBSDKRestrictiveEventFilter *restrictiveEventFilter = [[FBSDKRestrictiveEventFilter alloc] initWithEventName:eventName
|
||||||
|
restrictiveParams:eventInfo[RESTRICTIVE_PARAM_KEY]];
|
||||||
|
[eventFilterArray addObject:restrictiveEventFilter];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_params = eventFilterArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (nullable NSString *)getMatchedDataTypeWithEventName:(NSString *)eventName
|
||||||
|
paramKey:(NSString *)paramKey
|
||||||
|
{
|
||||||
|
// match by params in custom events with event name
|
||||||
|
for (FBSDKRestrictiveEventFilter *filter in _params) {
|
||||||
|
if ([filter.eventName isEqualToString:eventName]) {
|
||||||
|
NSString *type = [FBSDKTypeUtility stringValue:filter.restrictiveParams[paramKey]];
|
||||||
|
if (type) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *,id> *)processParameters:(NSDictionary<NSString *,id> *)parameters
|
||||||
|
eventName:(NSString *)eventName
|
||||||
|
{
|
||||||
|
if (!isRestrictiveEventFilterEnabled) {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
if (parameters) {
|
||||||
|
NSMutableDictionary<NSString *, id> *params = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||||
|
NSMutableDictionary<NSString *, NSString *> *restrictedParams = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
for (NSString *key in [parameters keyEnumerator]) {
|
||||||
|
NSString *type = [FBSDKRestrictiveDataFilterManager getMatchedDataTypeWithEventName:eventName
|
||||||
|
paramKey:key];
|
||||||
|
if (type) {
|
||||||
|
[restrictedParams setObject:type forKey:key];
|
||||||
|
[params removeObjectForKey:key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([[restrictedParams allKeys] count] > 0) {
|
||||||
|
NSString *restrictedParamsJSONString = [FBSDKBasicUtility JSONStringForObject:restrictedParams
|
||||||
|
error:NULL
|
||||||
|
invalidObjectHandler:NULL];
|
||||||
|
[FBSDKBasicUtility dictionary:params setObject:restrictedParamsJSONString forKey:@"_restrictedParams"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [params copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)enable
|
||||||
|
{
|
||||||
|
isRestrictiveEventFilterEnabled = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Helper functions
|
||||||
|
|
||||||
|
+ (BOOL)isMatchedWithPattern:(NSString *)pattern
|
||||||
|
text:(NSString *)text
|
||||||
|
{
|
||||||
|
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
NSUInteger matches = [regex numberOfMatchesInString:text options:0 range:NSMakeRange(0, text.length)];
|
||||||
|
return matches > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface FBSDKEventInferencer : NSObject
|
||||||
|
|
||||||
|
+ (void)loadWeights;
|
||||||
|
+ (NSDictionary<NSString *, NSString *> *)predict:(NSString *)buttonText
|
||||||
|
viewTree:(NSMutableDictionary<NSString *, id> *)viewTree
|
||||||
|
withLog:(BOOL)isPrint;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,227 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKEventInferencer.h"
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "FBSDKFeatureExtractor.h"
|
||||||
|
#import "FBSDKModelManager.h"
|
||||||
|
#import "FBSDKModelRuntime.hpp"
|
||||||
|
#import "FBSDKModelUtility.h"
|
||||||
|
#import "FBSDKViewHierarchyMacros.h"
|
||||||
|
|
||||||
|
#include<stdexcept>
|
||||||
|
|
||||||
|
static NSString *const MODEL_INFO_KEY= @"com.facebook.sdk:FBSDKModelInfo";
|
||||||
|
static NSString *const THRESHOLDS_KEY = @"thresholds";
|
||||||
|
static NSString *const SUGGESTED_EVENT[4] = {@"fb_mobile_add_to_cart", @"fb_mobile_complete_registration", @"other", @"fb_mobile_purchase"};
|
||||||
|
static NSDictionary<NSString *, NSString *> *const DEFAULT_PREDICTION = @{SUGGEST_EVENT_KEY: SUGGESTED_EVENTS_OTHER};
|
||||||
|
static NSDictionary<NSString *, NSArray *> *const WEIGHTS_INFO = @{@"embed.weight" : @[@(256), @(64)],
|
||||||
|
@"convs.0.weight" : @[@(32), @(64), @(2)],
|
||||||
|
@"convs.0.bias" : @[@(32)],
|
||||||
|
@"convs.1.weight" : @[@(32), @(64), @(3)],
|
||||||
|
@"convs.1.bias" : @[@(32)],
|
||||||
|
@"convs.2.weight" : @[@(32), @(64), @(5)],
|
||||||
|
@"convs.2.bias" : @[@(32)],
|
||||||
|
@"fc1.weight": @[@(128), @(126)],
|
||||||
|
@"fc1.bias": @[@(128)],
|
||||||
|
@"fc2.weight": @[@(64), @(128)],
|
||||||
|
@"fc2.bias": @[@(64)],
|
||||||
|
@"fc3.weight": @[@(4), @(64)],
|
||||||
|
@"fc3.bias": @[@(4)]};
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, mat::MTensor> _weights;
|
||||||
|
|
||||||
|
@implementation FBSDKEventInferencer : NSObject
|
||||||
|
|
||||||
|
+ (void)loadWeights
|
||||||
|
{
|
||||||
|
NSString *path = [FBSDKModelManager getWeightsPath:SUGGEST_EVENT_KEY];
|
||||||
|
if (!path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSData *latestData = [NSData dataWithContentsOfFile:path
|
||||||
|
options:NSDataReadingMappedIfSafe
|
||||||
|
error:nil];
|
||||||
|
if (!latestData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::unordered_map<std::string, mat::MTensor> weights = [self loadWeights:latestData];
|
||||||
|
if ([self validateWeights:weights]) {
|
||||||
|
_weights = weights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (bool)validateWeights: (std::unordered_map<std::string, mat::MTensor>) weights
|
||||||
|
{
|
||||||
|
if (WEIGHTS_INFO.count != weights.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (NSString *key in WEIGHTS_INFO) {
|
||||||
|
if (weights.count(std::string([key UTF8String])) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mat::MTensor tensor = weights[std::string([key UTF8String])];
|
||||||
|
const std::vector<int64_t>& actualSize = tensor.sizes();
|
||||||
|
NSArray *expectedSize = WEIGHTS_INFO[key];
|
||||||
|
if (actualSize.size() != expectedSize.count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < expectedSize.count; i++) {
|
||||||
|
if((int)actualSize[i] != (int)[expectedSize[i] intValue]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (std::unordered_map<std::string, mat::MTensor>)loadWeights:(NSData *)weightsData{
|
||||||
|
std::unordered_map<std::string, mat::MTensor> weights;
|
||||||
|
try {
|
||||||
|
const void *data = weightsData.bytes;
|
||||||
|
NSUInteger totalLength = weightsData.length;
|
||||||
|
|
||||||
|
int totalFloats = 0;
|
||||||
|
if (weightsData.length < 4) {
|
||||||
|
// Make sure data length is valid
|
||||||
|
return weights;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length;
|
||||||
|
memcpy(&length, data, 4);
|
||||||
|
if (length + 4 > totalLength) {
|
||||||
|
// Make sure data length is valid
|
||||||
|
return weights;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *json = (char *)data + 4;
|
||||||
|
NSDictionary<NSString *, id> *info = [NSJSONSerialization JSONObjectWithData:[NSData dataWithBytes:json length:length]
|
||||||
|
options:0
|
||||||
|
error:nil];
|
||||||
|
NSArray<NSString *> *keys = [[info allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString *key1, NSString *key2) {
|
||||||
|
return [key1 compare:key2];
|
||||||
|
}];
|
||||||
|
|
||||||
|
float *floats = (float *)(json + length);
|
||||||
|
for (NSString *key in keys) {
|
||||||
|
std::string s_name([key UTF8String]);
|
||||||
|
|
||||||
|
std::vector<int64_t> v_shape;
|
||||||
|
NSArray<NSString *> *shape = [info objectForKey:key];
|
||||||
|
int count = 1;
|
||||||
|
for (NSNumber *_s in shape) {
|
||||||
|
int i = [_s intValue];
|
||||||
|
v_shape.push_back(i);
|
||||||
|
count *= i;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalFloats += count;
|
||||||
|
|
||||||
|
if ((4 + length + totalFloats * 4) > totalLength) {
|
||||||
|
// Make sure data length is valid
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mat::MTensor tensor = mat::mempty(v_shape);
|
||||||
|
float *tensor_data = tensor.data<float>();
|
||||||
|
memcpy(tensor_data, floats, sizeof(float) * count);
|
||||||
|
floats += count;
|
||||||
|
|
||||||
|
weights[s_name] = tensor;
|
||||||
|
}
|
||||||
|
} catch(const std::exception &e) {}
|
||||||
|
|
||||||
|
return weights;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, NSString *> *)predict:(NSString *)buttonText
|
||||||
|
viewTree:(NSMutableDictionary *)viewTree
|
||||||
|
withLog:(BOOL)isPrint
|
||||||
|
{
|
||||||
|
if (buttonText.length == 0 || _weights.size() == 0) {
|
||||||
|
return DEFAULT_PREDICTION;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Get bytes tensor
|
||||||
|
NSString *textFeature = [FBSDKModelUtility normalizeText:[FBSDKFeatureExtractor getTextFeature:buttonText withScreenName:viewTree[@"screenname"]]];
|
||||||
|
if (textFeature.length == 0) {
|
||||||
|
return DEFAULT_PREDICTION;
|
||||||
|
}
|
||||||
|
const char *bytes = [textFeature UTF8String];
|
||||||
|
if ((int)strlen(bytes) == 0) {
|
||||||
|
return DEFAULT_PREDICTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get dense tensor
|
||||||
|
std::vector<int64_t> dense_tensor_shape;
|
||||||
|
dense_tensor_shape.push_back(1);
|
||||||
|
dense_tensor_shape.push_back(30);
|
||||||
|
mat::MTensor dense_tensor = mat::mempty(dense_tensor_shape);
|
||||||
|
float *dense_tensor_data = dense_tensor.data<float>();
|
||||||
|
float *dense_data = [FBSDKFeatureExtractor getDenseFeatures:viewTree];
|
||||||
|
if (!dense_data) {
|
||||||
|
return DEFAULT_PREDICTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableDictionary<NSString *, NSString *> *result = [[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
|
// Get dense feature string
|
||||||
|
NSMutableArray *denseDataArray = [NSMutableArray array];
|
||||||
|
for (int i=0; i < 30; i++) {
|
||||||
|
[denseDataArray addObject:[NSNumber numberWithFloat: dense_data[i]]];
|
||||||
|
}
|
||||||
|
[result setObject:[denseDataArray componentsJoinedByString:@","] forKey:DENSE_FEATURE_KEY];
|
||||||
|
|
||||||
|
memcpy(dense_tensor_data, dense_data, sizeof(float) * 30);
|
||||||
|
free(dense_data);
|
||||||
|
float *res = mat1::predictOnText(bytes, _weights, dense_tensor_data);
|
||||||
|
NSMutableDictionary<NSString *, id> *modelInfo = [[NSUserDefaults standardUserDefaults] objectForKey:MODEL_INFO_KEY];
|
||||||
|
if (!modelInfo) {
|
||||||
|
return DEFAULT_PREDICTION;
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id> * suggestedEventModelInfo = [modelInfo objectForKey:SUGGEST_EVENT_KEY];
|
||||||
|
if (!suggestedEventModelInfo) {
|
||||||
|
return DEFAULT_PREDICTION;
|
||||||
|
}
|
||||||
|
NSMutableArray *thresholds = [suggestedEventModelInfo objectForKey:THRESHOLDS_KEY];
|
||||||
|
if (thresholds.count < 4) {
|
||||||
|
return DEFAULT_PREDICTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < thresholds.count; i++){
|
||||||
|
if ((float)res[i] >= (float)[thresholds[i] floatValue]) {
|
||||||
|
[result setObject:SUGGESTED_EVENT[i] forKey:SUGGEST_EVENT_KEY];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {}
|
||||||
|
return DEFAULT_PREDICTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface FBSDKFeatureExtractor : NSObject
|
||||||
|
|
||||||
|
+ (void)loadRules;
|
||||||
|
+ (NSString *)getTextFeature:(NSString *)text
|
||||||
|
withScreenName:(NSString *)screenName;
|
||||||
|
+ (float *)getDenseFeatures:(NSDictionary *)viewHierarchy;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,345 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKFeatureExtractor.h"
|
||||||
|
|
||||||
|
#import "FBSDKCoreKit+Internal.h"
|
||||||
|
#import "FBSDKModelManager.h"
|
||||||
|
|
||||||
|
#define REGEX_CR_PASSWORD_FIELD @"password"
|
||||||
|
#define REGEX_CR_HAS_CONFIRM_PASSWORD_FIELD @"(?i)(confirm.*password)|(password.*(confirmation|confirm)|confirmation)"
|
||||||
|
#define REGEX_CR_HAS_LOG_IN_KEYWORDS @"(?i)(sign in)|login|signIn"
|
||||||
|
#define REGEX_CR_HAS_SIGN_ON_KEYWORDS @"(?i)(sign.*(up|now)|registration|" \
|
||||||
|
@"register|(create|apply).*(profile|account)|open.*account|" \
|
||||||
|
@"account.*(open|creation|application)|enroll|join.*now)"
|
||||||
|
#define REGEX_ADD_TO_CART_BUTTON_TEXT @"(?i)add to(\\s|\\Z)|update(\\s|\\Z)|cart"
|
||||||
|
#define REGEX_ADD_TO_CART_PAGE_TITLE @"(?i)add to(\\s|\\Z)|update(\\s|\\Z)|cart|shop|buy"
|
||||||
|
|
||||||
|
static NSDictionary *_languageInfo;
|
||||||
|
static NSDictionary *_eventInfo;
|
||||||
|
static NSDictionary *_textTypeInfo;
|
||||||
|
static NSDictionary *_rules;
|
||||||
|
|
||||||
|
void sum(float *val0, float *val1);
|
||||||
|
|
||||||
|
@implementation FBSDKFeatureExtractor
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
_languageInfo = @{
|
||||||
|
@"ENGLISH" : @"1",
|
||||||
|
@"GERMAN" : @"2",
|
||||||
|
@"SPANISH" : @"3",
|
||||||
|
@"JAPANESE" : @"4"
|
||||||
|
};
|
||||||
|
_eventInfo = @{
|
||||||
|
@"VIEW_CONTENT" : @"0",
|
||||||
|
@"SEARCH" : @"1",
|
||||||
|
@"ADD_TO_CART" : @"2",
|
||||||
|
@"ADD_TO_WISHLIST" : @"3",
|
||||||
|
@"INITIATE_CHECKOUT" : @"4",
|
||||||
|
@"ADD_PAYMENT_INFO" : @"5",
|
||||||
|
@"PURCHASE" : @"6",
|
||||||
|
@"LEAD" : @"7",
|
||||||
|
@"COMPLETE_REGISTRATION" : @"8"
|
||||||
|
};
|
||||||
|
_textTypeInfo = @{
|
||||||
|
@"BUTTON_TEXT": @"1",
|
||||||
|
@"PAGE_TITLE": @"2",
|
||||||
|
@"RESOLVED_DOCUMENT_LINK": @"3",
|
||||||
|
@"BUTTON_ID": @"4"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)loadRules
|
||||||
|
{
|
||||||
|
_rules = [FBSDKModelManager getRules];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getTextFeature:(NSString *)text
|
||||||
|
withScreenName:(NSString *)screenName
|
||||||
|
{
|
||||||
|
// use "|" and "," to separate different text based on the rule of how text processed during training
|
||||||
|
NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleNameKey];
|
||||||
|
return [[NSString stringWithFormat:@"%@ | %@, %@", appName, screenName, text] lowercaseString];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (float *)getDenseFeatures:(NSDictionary *)viewHierarchy
|
||||||
|
{
|
||||||
|
if (!_rules) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSMutableArray<NSMutableDictionary<NSString *, id> *> *viewTree = [viewHierarchy[VIEW_HIERARCHY_VIEW_KEY] mutableCopy];
|
||||||
|
NSString *screenName = viewHierarchy[VIEW_HIERARCHY_SCREEN_NAME_KEY];
|
||||||
|
NSMutableArray<NSMutableDictionary<NSString *, id> *> *siblings = [NSMutableArray array];
|
||||||
|
|
||||||
|
[self pruneTree:[viewTree[0] mutableCopy] siblings:siblings];
|
||||||
|
|
||||||
|
float *result = [self parseFeatures:viewTree[0]];
|
||||||
|
|
||||||
|
NSMutableDictionary<NSString *, id> *interactedNode;
|
||||||
|
for (NSMutableDictionary<NSString *, id> *node in siblings) {
|
||||||
|
if ([[node objectForKey:VIEW_HIERARCHY_IS_INTERACTED_KEY] boolValue]) {
|
||||||
|
interactedNode = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *viewTreeString = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:viewTree options:0 error:nil] encoding:NSUTF8StringEncoding];
|
||||||
|
|
||||||
|
float *nonparseResult = [self nonparseFeatures:interactedNode siblings:siblings screenname:screenName viewTreeString:viewTreeString];
|
||||||
|
sum(result, nonparseResult);
|
||||||
|
free(nonparseResult);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Helper functions
|
||||||
|
+ (BOOL)pruneTree:(NSMutableDictionary *)node siblings:(NSMutableArray *)siblings
|
||||||
|
{
|
||||||
|
// If it's interacted, don't prune away the children and just return.
|
||||||
|
BOOL isInteracted = [[node objectForKey:VIEW_HIERARCHY_IS_INTERACTED_KEY] boolValue];
|
||||||
|
if (isInteracted) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableArray<NSMutableDictionary<NSString *, id> *> *newChildren = [NSMutableArray array];
|
||||||
|
// If a child is interacted, we're at the right level and we want to grab everything
|
||||||
|
BOOL isChildInteracted = NO;
|
||||||
|
BOOL isDescendantInteracted = NO;
|
||||||
|
|
||||||
|
NSMutableArray<NSMutableDictionary<NSString *, id> *> *childviews = [node objectForKey:VIEW_HIERARCHY_CHILD_VIEWS_KEY];
|
||||||
|
for (NSMutableDictionary<NSString *, id> *child in childviews) {
|
||||||
|
if ([child[VIEW_HIERARCHY_IS_INTERACTED_KEY] boolValue]) {
|
||||||
|
isChildInteracted = YES;
|
||||||
|
isDescendantInteracted = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isChildInteracted) {
|
||||||
|
[siblings addObjectsFromArray:childviews];
|
||||||
|
} else {
|
||||||
|
for (NSMutableDictionary<NSString *, id> *c in childviews) {
|
||||||
|
NSMutableDictionary<NSString *, id> *child = [c mutableCopy];
|
||||||
|
if ([self pruneTree:child siblings:siblings]) {
|
||||||
|
isDescendantInteracted = YES;
|
||||||
|
[newChildren addObject:child];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node[VIEW_HIERARCHY_CHILD_VIEWS_KEY] = newChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isDescendantInteracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (float *)nonparseFeatures:(NSMutableDictionary *)node
|
||||||
|
siblings:(NSMutableArray *)siblings
|
||||||
|
screenname:(NSString *)screenname
|
||||||
|
viewTreeString:(NSString *)viewTreeString
|
||||||
|
{
|
||||||
|
float *densefeat = (float *)calloc(30, sizeof(float));
|
||||||
|
|
||||||
|
densefeat[3] = MAX((float)siblings.count - 1, 0);
|
||||||
|
|
||||||
|
densefeat[9] = [siblings filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
|
||||||
|
return [self isButton:evaluatedObject];
|
||||||
|
}]].count;
|
||||||
|
if ([self isButton:node]) {
|
||||||
|
densefeat[9] -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
densefeat[13] = -1;
|
||||||
|
densefeat[14] = -1;
|
||||||
|
|
||||||
|
NSString *pageTitle = screenname ?: @"";
|
||||||
|
NSString *formFieldsJSON = viewTreeString;
|
||||||
|
NSString *buttonID = @"";
|
||||||
|
NSString *buttonText = @"";
|
||||||
|
|
||||||
|
if ([self isButton:node]) {
|
||||||
|
NSMutableString *buttonTextString = [NSMutableString string];
|
||||||
|
NSMutableString *buttonHintString = [NSMutableString string];
|
||||||
|
[self update:node text:buttonTextString hint:buttonHintString];
|
||||||
|
buttonText = (NSString *)buttonTextString;
|
||||||
|
buttonID = (NSString *)buttonHintString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regex features
|
||||||
|
densefeat[15] = [self regexMatch:@"ENGLISH" event:@"COMPLETE_REGISTRATION" textType:@"BUTTON_TEXT" matchText:buttonText];
|
||||||
|
densefeat[16] = [self regexMatch:@"ENGLISH" event:@"COMPLETE_REGISTRATION" textType:@"PAGE_TITLE" matchText:pageTitle];
|
||||||
|
densefeat[17] = [self regexMatch:@"ENGLISH" event:@"COMPLETE_REGISTRATION" textType:@"BUTTON_ID" matchText:buttonID];
|
||||||
|
|
||||||
|
densefeat[18] = [formFieldsJSON containsString:REGEX_CR_PASSWORD_FIELD] ? 1.0 : 0.0;
|
||||||
|
|
||||||
|
densefeat[19] = [self regextMatch:REGEX_CR_HAS_CONFIRM_PASSWORD_FIELD text:formFieldsJSON];
|
||||||
|
densefeat[20] = [self regextMatch:REGEX_CR_HAS_LOG_IN_KEYWORDS text:formFieldsJSON];
|
||||||
|
densefeat[21] = [self regextMatch:REGEX_CR_HAS_SIGN_ON_KEYWORDS text:formFieldsJSON];
|
||||||
|
|
||||||
|
// Purchase specific features
|
||||||
|
densefeat[22] = [self regexMatch:@"ENGLISH" event:@"PURCHASE" textType:@"BUTTON_TEXT" matchText:buttonText];
|
||||||
|
densefeat[24] = [self regexMatch:@"ENGLISH" event:@"PURCHASE" textType:@"PAGE_TITLE" matchText:pageTitle];
|
||||||
|
|
||||||
|
// AddToCart specific features
|
||||||
|
densefeat[25] = [self regextMatch:REGEX_ADD_TO_CART_BUTTON_TEXT text:buttonText];
|
||||||
|
densefeat[27] = [self regextMatch:REGEX_ADD_TO_CART_PAGE_TITLE text:pageTitle];
|
||||||
|
|
||||||
|
// Lead specific features
|
||||||
|
densefeat[28] = [self regexMatch:@"ENGLISH" event:@"LEAD" textType:@"BUTTON_TEXT" matchText:buttonText];
|
||||||
|
densefeat[29] = [self regexMatch:@"ENGLISH" event:@"LEAD" textType:@"PAGE_TITLE" matchText:pageTitle];
|
||||||
|
|
||||||
|
return densefeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (float *)parseFeatures:(NSMutableDictionary *)node
|
||||||
|
{
|
||||||
|
float *densefeat = (float *)calloc(30, sizeof(float));
|
||||||
|
|
||||||
|
NSString *text = [node[VIEW_HIERARCHY_TEXT_KEY] lowercaseString] ?: @"";
|
||||||
|
NSString *hint = [node[VIEW_HIERARCHY_HINT_KEY] lowercaseString] ?: @"";
|
||||||
|
NSString *className = [node[VIEW_HIERARCHY_CLASS_NAME_KEY] lowercaseString] ?: @"";
|
||||||
|
|
||||||
|
if ([self foundIndicators:[@"$,amount,price,total" componentsSeparatedByString:@","]
|
||||||
|
inValues:@[text, hint]]) {
|
||||||
|
densefeat[0] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([self foundIndicators:[@"password,pwd" componentsSeparatedByString:@","]
|
||||||
|
inValues:@[text, hint]]) {
|
||||||
|
densefeat[1] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([self foundIndicators:[@"phone,tel" componentsSeparatedByString:@","]
|
||||||
|
inValues:@[text, hint]]) {
|
||||||
|
densefeat[2] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([self foundIndicators:@[@"search"]
|
||||||
|
inValues:@[text, hint]]) {
|
||||||
|
densefeat[4] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input field with general text
|
||||||
|
if ([className containsString:@"text"] && [className containsString:@"edit"]) {
|
||||||
|
densefeat[5] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input field with number or phone
|
||||||
|
if (([className containsString:@"num"] || [className containsString:@"phone"]) && [className containsString:@"edit"]) {
|
||||||
|
densefeat[6] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([hint containsString:@"email"] || [text containsString:@"@"]) {
|
||||||
|
densefeat[7] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Box
|
||||||
|
if ([className containsString:@"checkbox"]) {
|
||||||
|
densefeat[8] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([self foundIndicators:[@"complete,confirm,done,submit" componentsSeparatedByString:@","]
|
||||||
|
inValues:@[text]]) {
|
||||||
|
densefeat[10] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
densefeat[11] = 0.0;
|
||||||
|
|
||||||
|
// Radio Button
|
||||||
|
if ([className containsString:@"radio"] && [className containsString:@"button"]) {
|
||||||
|
densefeat[12] += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableArray<NSMutableDictionary<NSString *, id> *> *childviews = node[VIEW_HIERARCHY_CHILD_VIEWS_KEY];
|
||||||
|
|
||||||
|
for (int i = 0; i < childviews.count; i++) {
|
||||||
|
sum(densefeat, [self parseFeatures:childviews[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return densefeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sum(float *val0, float *val1) {
|
||||||
|
for (int i = 0; i < 30; i++) {
|
||||||
|
val0[i] += val1[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isButton:(NSDictionary *)node
|
||||||
|
{
|
||||||
|
int classtypebitmask = [[node objectForKey:VIEW_HIERARCHY_CLASS_TYPE_BITMASK_KEY] intValue];
|
||||||
|
return (classtypebitmask & FBCodelessClassBitmaskUIButton) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)update:(NSDictionary *)node
|
||||||
|
text:(NSMutableString *)buttonTextString
|
||||||
|
hint:(NSMutableString *)buttonHintString
|
||||||
|
{
|
||||||
|
NSString *text = [node[VIEW_HIERARCHY_TEXT_KEY] lowercaseString];
|
||||||
|
NSString *hint = [node[VIEW_HIERARCHY_HINT_KEY] lowercaseString];
|
||||||
|
|
||||||
|
if (text.length > 0) {
|
||||||
|
[buttonTextString appendFormat:@"%@ ", text];
|
||||||
|
}
|
||||||
|
if (hint.length > 0) {
|
||||||
|
[buttonHintString appendFormat:@"%@ ", hint];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableArray<NSMutableDictionary<NSString *, id> *> *childviews = node[VIEW_HIERARCHY_CHILD_VIEWS_KEY];
|
||||||
|
for (NSMutableDictionary<NSString *, id> *child in childviews) {
|
||||||
|
[self update:child text:buttonTextString hint:buttonHintString];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)foundIndicators:(NSArray *)indicators inValues:(NSArray *)values
|
||||||
|
{
|
||||||
|
for (NSString *indicator in indicators) {
|
||||||
|
for (NSString *value in values) {
|
||||||
|
if ([value containsString:indicator]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (float)regextMatch:(NSString *)pattern text:(NSString *)text
|
||||||
|
{
|
||||||
|
NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
|
||||||
|
NSRange range = NSMakeRange(0, text.length);
|
||||||
|
NSArray<NSTextCheckingResult *> *matched = [re matchesInString:text options:0 range:range];
|
||||||
|
return matched.count > 0 ? 1.0 : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (float)regexMatch:(NSString *)language
|
||||||
|
event:(NSString *)event
|
||||||
|
textType:(NSString *)textType
|
||||||
|
matchText:(NSString *)matchText
|
||||||
|
{
|
||||||
|
NSString *pattern = _rules[@"rulesForLanguage"][_languageInfo[language]]
|
||||||
|
[@"rulesForEvent"][_eventInfo[event]]
|
||||||
|
[@"positiveRules"][_textTypeInfo[textType]];
|
||||||
|
return [self regextMatch:pattern text:matchText];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface FBSDKSuggestedEventsIndexer : NSObject
|
||||||
|
|
||||||
|
+ (void)enable;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,271 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKSuggestedEventsIndexer.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
#import <sys/sysctl.h>
|
||||||
|
#import <sys/utsname.h>
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKCoreKit+Internal.h"
|
||||||
|
#import "FBSDKEventInferencer.h"
|
||||||
|
|
||||||
|
NSString * const OptInEvents = @"production_events";
|
||||||
|
NSString * const UnconfirmedEvents = @"eligible_for_prediction_events";
|
||||||
|
|
||||||
|
static NSMutableArray<NSMutableDictionary<NSString *, id> *> *_viewTrees;
|
||||||
|
static NSMutableSet<NSString *> *_optInEvents;
|
||||||
|
static NSMutableSet<NSString *> *_unconfirmedEvents;
|
||||||
|
|
||||||
|
@implementation FBSDKSuggestedEventsIndexer
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
_viewTrees = [NSMutableArray array];
|
||||||
|
_optInEvents = [NSMutableSet set];
|
||||||
|
_unconfirmedEvents = [NSMutableSet set];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)enable
|
||||||
|
{
|
||||||
|
[FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *error) {
|
||||||
|
if (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDictionary<NSString *, id> *suggestedEventsSetting = serverConfiguration.suggestedEventsSetting;
|
||||||
|
if ([suggestedEventsSetting isKindOfClass:[NSNull class]] || !suggestedEventsSetting[OptInEvents] || !suggestedEventsSetting[UnconfirmedEvents]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[_optInEvents addObjectsFromArray:suggestedEventsSetting[OptInEvents]];
|
||||||
|
[_unconfirmedEvents addObjectsFromArray:suggestedEventsSetting[UnconfirmedEvents]];
|
||||||
|
|
||||||
|
[FBSDKSuggestedEventsIndexer setup];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setup
|
||||||
|
{
|
||||||
|
// won't do the model prediction when there is no opt-in event and unconfirmed event
|
||||||
|
if (_optInEvents.count == 0 && _unconfirmedEvents.count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
|
||||||
|
// swizzle UIButton
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow) onClass:[UIButton class] withBlock:^(UIButton *button) {
|
||||||
|
if (button.window) {
|
||||||
|
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchDown];
|
||||||
|
}
|
||||||
|
} named:@"suggested_events"];
|
||||||
|
|
||||||
|
// UITableView
|
||||||
|
void (^tableViewBlock)(UITableView *tableView,
|
||||||
|
SEL cmd,
|
||||||
|
id<UITableViewDelegate> delegate) =
|
||||||
|
^(UITableView *tableView, SEL cmd, id<UITableViewDelegate> delegate) {
|
||||||
|
[self handleView:tableView withDelegate:delegate];
|
||||||
|
};
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(setDelegate:)
|
||||||
|
onClass:[UITableView class]
|
||||||
|
withBlock:tableViewBlock
|
||||||
|
named:@"suggested_events"];
|
||||||
|
|
||||||
|
// UICollectionView
|
||||||
|
void (^collectionViewBlock)(UICollectionView *collectionView,
|
||||||
|
SEL cmd,
|
||||||
|
id<UICollectionViewDelegate> delegate) =
|
||||||
|
^(UICollectionView *collectionView, SEL cmd, id<UICollectionViewDelegate> delegate) {
|
||||||
|
[self handleView:collectionView withDelegate:delegate];
|
||||||
|
};
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(setDelegate:)
|
||||||
|
onClass:[UICollectionView class]
|
||||||
|
withBlock:collectionViewBlock
|
||||||
|
named:@"suggested_events"];
|
||||||
|
|
||||||
|
fb_dispatch_on_main_thread(^{
|
||||||
|
[self rematchBindings];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)rematchBindings {
|
||||||
|
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) {
|
||||||
|
|
||||||
|
if ([subview isKindOfClass:[UITableView class]]) {
|
||||||
|
UITableView *tableView = (UITableView *)subview;
|
||||||
|
[self handleView:tableView withDelegate:tableView.delegate];
|
||||||
|
} else if ([subview isKindOfClass:[UICollectionView class]]) {
|
||||||
|
UICollectionView *collectionView = (UICollectionView *)subview;
|
||||||
|
[self handleView:collectionView withDelegate:collectionView.delegate];
|
||||||
|
} else if ([subview isKindOfClass:[UIButton class]]) {
|
||||||
|
[(UIButton *)subview addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchDown];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![subview isKindOfClass:[UIControl class]]) {
|
||||||
|
[self matchSubviewsIn:subview];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)buttonClicked:(UIButton *)button
|
||||||
|
{
|
||||||
|
[self predictEvent:button withText:[FBSDKViewHierarchy getText:button]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)handleView:(UIView *)view withDelegate:(id)delegate
|
||||||
|
{
|
||||||
|
if (!delegate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([view isKindOfClass:[UITableView class]]
|
||||||
|
&& [delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {
|
||||||
|
void (^block)(id, SEL, id, id) = ^(id target, SEL command, UITableView *tableView, NSIndexPath *indexPath) {
|
||||||
|
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
||||||
|
[self predictEvent:cell withText:[self getTextFromContentView:[cell contentView]]];
|
||||||
|
};
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(tableView:didSelectRowAtIndexPath:)
|
||||||
|
onClass:[delegate class]
|
||||||
|
withBlock:block
|
||||||
|
named:@"suggested_events"];
|
||||||
|
} else if ([view isKindOfClass:[UICollectionView class]]
|
||||||
|
&& [delegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]) {
|
||||||
|
void (^block)(id, SEL, id, id) = ^(id target, SEL command, UICollectionView *collectionView, NSIndexPath *indexPath) {
|
||||||
|
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
|
||||||
|
[self predictEvent:cell withText:[self getTextFromContentView:[cell contentView]]];
|
||||||
|
};
|
||||||
|
[FBSDKSwizzler swizzleSelector:@selector(collectionView:didSelectItemAtIndexPath:)
|
||||||
|
onClass:[delegate class]
|
||||||
|
withBlock:block
|
||||||
|
named:@"suggested_events"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)predictEvent:(NSObject *)obj withText:(NSString *)text
|
||||||
|
{
|
||||||
|
if (text.length > 100 || text.length == 0 || [FBSDKAppEventsUtility isSensitiveUserData: text]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableArray<NSDictionary<NSString *, id> *> *trees = [NSMutableArray array];
|
||||||
|
|
||||||
|
fb_dispatch_on_main_thread(^{
|
||||||
|
NSArray<UIWindow *> *windows = [UIApplication sharedApplication].windows;
|
||||||
|
for (UIWindow *window in windows) {
|
||||||
|
NSDictionary<NSString *, id> *tree = [FBSDKViewHierarchy recursiveCaptureTree:window withObject:obj];
|
||||||
|
if (tree) {
|
||||||
|
if (window.isKeyWindow) {
|
||||||
|
[trees insertObject:tree atIndex:0];
|
||||||
|
} else {
|
||||||
|
[trees addObject:tree];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NSMutableDictionary<NSString *, id> *treeInfo = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
NSString *screenName = nil;
|
||||||
|
UIViewController *topMostViewController = [FBSDKInternalUtility topMostViewController];
|
||||||
|
if (topMostViewController) {
|
||||||
|
screenName = NSStringFromClass([topMostViewController class]);
|
||||||
|
}
|
||||||
|
|
||||||
|
treeInfo[VIEW_HIERARCHY_VIEW_KEY] = trees;
|
||||||
|
treeInfo[VIEW_HIERARCHY_SCREEN_NAME_KEY] = screenName ?: @"";
|
||||||
|
|
||||||
|
[_viewTrees addObject:treeInfo];
|
||||||
|
|
||||||
|
NSDictionary<NSString *, id> *viewTree = [_viewTrees lastObject];
|
||||||
|
|
||||||
|
fb_dispatch_on_default_thread(^{
|
||||||
|
NSDictionary<NSString *, NSString *> *result = [FBSDKEventInferencer predict:text viewTree:[viewTree mutableCopy] withLog:YES];
|
||||||
|
NSString *event = result[SUGGEST_EVENT_KEY];
|
||||||
|
if (!event || [event isEqualToString:SUGGESTED_EVENTS_OTHER]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ([_optInEvents containsObject:event]) {
|
||||||
|
[FBSDKAppEvents logEvent:event
|
||||||
|
parameters:@{@"_is_suggested_event": @"1",
|
||||||
|
@"_button_text": text
|
||||||
|
}];
|
||||||
|
} else if ([_unconfirmedEvents containsObject:event]) {
|
||||||
|
// Only send back not confirmed events to advertisers
|
||||||
|
[self logSuggestedEvent:event withText:text withDenseFeature:result[DENSE_FEATURE_KEY] ?: @""];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Helper Methods
|
||||||
|
|
||||||
|
+ (NSString *)getTextFromContentView:(UIView *)contentView
|
||||||
|
{
|
||||||
|
NSMutableArray<NSString *> *textArray = [NSMutableArray array];
|
||||||
|
for (UIView *subView in [contentView subviews]) {
|
||||||
|
NSString *label = [FBSDKViewHierarchy getText:subView];
|
||||||
|
if (label.length > 0) {
|
||||||
|
[textArray addObject:label];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [textArray componentsJoinedByString:@" "];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)logSuggestedEvent:(NSString *)event withText:(NSString *)text withDenseFeature:(NSString *)denseFeature
|
||||||
|
{
|
||||||
|
NSString *metadata = [FBSDKBasicUtility JSONStringForObject:@{@"button_text": text,
|
||||||
|
@"dense": denseFeature,
|
||||||
|
}
|
||||||
|
error:nil
|
||||||
|
invalidObjectHandler:nil];
|
||||||
|
if (!metadata) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
|
||||||
|
initWithGraphPath:[NSString stringWithFormat:@"%@/suggested_events", [FBSDKSettings appID]]
|
||||||
|
parameters: @{@"event_name": event,
|
||||||
|
@"metadata": metadata,
|
||||||
|
}
|
||||||
|
HTTPMethod:FBSDKHTTPMethodPOST];
|
||||||
|
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {}];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, FBCodelessClassBitmask) {
|
||||||
|
/** Indicates that the class is subclass of UIControl */
|
||||||
|
FBCodelessClassBitmaskUIControl = 1 << 3,
|
||||||
|
/** Indicates that the class is subclass of UIControl */
|
||||||
|
FBCodelessClassBitmaskUIButton = 1 << 4,
|
||||||
|
/** Indicates that the class is ReactNative Button */
|
||||||
|
FBCodelessClassBitmaskReactNativeButton = 1 << 6,
|
||||||
|
/** Indicates that the class is UITableViewCell */
|
||||||
|
FBCodelessClassBitmaskUITableViewCell = 1 << 7,
|
||||||
|
/** Indicates that the class is UICollectionViewCell */
|
||||||
|
FBCodelessClassBitmaskUICollectionViewCell = 1 << 8,
|
||||||
|
/** Indicates that the class is UILabel */
|
||||||
|
FBCodelessClassBitmaskLabel = 1 << 10,
|
||||||
|
/** Indicates that the class is UITextView or UITextField*/
|
||||||
|
FBCodelessClassBitmaskInput = 1 << 11,
|
||||||
|
/** Indicates that the class is UIPicker*/
|
||||||
|
FBCodelessClassBitmaskPicker = 1 << 12,
|
||||||
|
/** Indicates that the class is UISwitch*/
|
||||||
|
FBCodelessClassBitmaskSwitch = 1 << 13,
|
||||||
|
/** Indicates that the class is UIViewController*/
|
||||||
|
FBCodelessClassBitmaskUIViewController = 1 << 17,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void fb_dispatch_on_main_thread(dispatch_block_t block);
|
||||||
|
extern void fb_dispatch_on_default_thread(dispatch_block_t block);
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(ViewHierarchy)
|
||||||
|
@interface FBSDKViewHierarchy : NSObject
|
||||||
|
|
||||||
|
+ (NSObject *)getParent:(NSObject *)obj;
|
||||||
|
+ (NSArray<NSObject *> *)getChildren:(NSObject *)obj;
|
||||||
|
+ (NSArray<NSObject *> *)getPath:(NSObject *)obj;
|
||||||
|
+ (NSMutableDictionary<NSString *, id> *)getDetailAttributesOf:(NSObject *)obj;
|
||||||
|
|
||||||
|
+ (NSString *)getText:(NSObject *)obj;
|
||||||
|
+ (NSString *)getHint:(NSObject *)obj;
|
||||||
|
+ (NSIndexPath *)getIndexPath:(NSObject *)obj;
|
||||||
|
+ (NSUInteger)getClassBitmask:(NSObject *)obj;
|
||||||
|
+ (UITableView *)getParentTableView:(UIView *)cell;
|
||||||
|
+ (UICollectionView *)getParentCollectionView:(UIView *)cell;
|
||||||
|
+ (NSInteger)getTag:(NSObject *)obj;
|
||||||
|
+ (NSNumber *)getViewReactTag:(UIView *)view;
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, id> *)recursiveCaptureTree:(NSObject *)obj withObject:(NSObject *)interact;
|
||||||
|
|
||||||
|
+ (BOOL)isUserInputView:(NSObject *)obj;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,662 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKViewHierarchy.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
|
#import "FBSDKCodelessPathComponent.h"
|
||||||
|
#import "FBSDKCoreKit+Internal.h"
|
||||||
|
#import "FBSDKViewHierarchyMacros.h"
|
||||||
|
|
||||||
|
#define MAX_VIEW_HIERARCHY_LEVEL 35
|
||||||
|
|
||||||
|
void fb_dispatch_on_main_thread(dispatch_block_t block) {
|
||||||
|
if (block != nil) {
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
block();
|
||||||
|
} else {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fb_dispatch_on_default_thread(dispatch_block_t block) {
|
||||||
|
if (block != nil) {
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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<UIView *> *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<UIView *> *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];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDictionary *componentInfo = [FBSDKViewHierarchy getAttributesOf:obj parent:parent];
|
||||||
|
|
||||||
|
FBSDKCodelessPathComponent *pathComponent = [[FBSDKCodelessPathComponent alloc]
|
||||||
|
initWithJSON:componentInfo];
|
||||||
|
[path addObject:pathComponent];
|
||||||
|
|
||||||
|
return [NSArray arrayWithArray:path];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, id> *)getAttributesOf:(NSObject *)obj parent:(NSObject *)parent
|
||||||
|
{
|
||||||
|
NSMutableDictionary *componentInfo = [NSMutableDictionary dictionary];
|
||||||
|
componentInfo[CODELESS_MAPPING_CLASS_NAME_KEY] = NSStringFromClass([obj class]);
|
||||||
|
|
||||||
|
if (![FBSDKViewHierarchy isUserInputView:obj]) {
|
||||||
|
NSString *text = [FBSDKViewHierarchy getText:obj];
|
||||||
|
if (text) {
|
||||||
|
componentInfo[CODELESS_MAPPING_TEXT_KEY] = text;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
componentInfo[CODELESS_MAPPING_TEXT_KEY] = @"";
|
||||||
|
componentInfo[CODELESS_MAPPING_IS_USER_INPUT_KEY] = @YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *hint = [FBSDKViewHierarchy getHint:obj];
|
||||||
|
if (hint) {
|
||||||
|
componentInfo[CODELESS_MAPPING_HINT_KEY] = hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSIndexPath *indexPath = [FBSDKViewHierarchy getIndexPath:obj];
|
||||||
|
if (indexPath) {
|
||||||
|
componentInfo[CODELESS_MAPPING_SECTION_KEY] = @(indexPath.section);
|
||||||
|
componentInfo[CODELESS_MAPPING_ROW_KEY] = @(indexPath.row);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent != nil) {
|
||||||
|
NSArray *children = [FBSDKViewHierarchy getChildren:parent];
|
||||||
|
NSUInteger index = [children indexOfObject:obj];
|
||||||
|
if (index != NSNotFound) {
|
||||||
|
componentInfo[CODELESS_MAPPING_INDEX_KEY] = @(index);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
componentInfo[CODELESS_MAPPING_INDEX_KEY] = @0;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentInfo[CODELESS_VIEW_TREE_TAG_KEY] = @([FBSDKViewHierarchy getTag:obj]);
|
||||||
|
|
||||||
|
return [componentInfo copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableDictionary<NSString *, id> *)getDetailAttributesOf:(NSObject *)obj
|
||||||
|
{
|
||||||
|
return [self getDetailAttributesOf:obj withHash:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableDictionary<NSString *, id> *)getDetailAttributesOf:(NSObject *)obj withHash:(BOOL)hash
|
||||||
|
{
|
||||||
|
if (!obj) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSObject *parent = [FBSDKViewHierarchy getParent:obj];
|
||||||
|
|
||||||
|
NSDictionary *simpleAttributes = [FBSDKViewHierarchy getAttributesOf:obj parent:parent];
|
||||||
|
|
||||||
|
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:simpleAttributes];
|
||||||
|
|
||||||
|
NSString *className = NSStringFromClass([obj class]);
|
||||||
|
result[VIEW_HIERARCHY_CLASS_NAME_KEY] = className;
|
||||||
|
|
||||||
|
NSUInteger classBitmask = [FBSDKViewHierarchy getClassBitmask:obj];
|
||||||
|
result[VIEW_HIERARCHY_CLASS_TYPE_BITMASK_KEY] = [NSString stringWithFormat:@"%lu", (unsigned long)classBitmask];
|
||||||
|
|
||||||
|
if ([obj isKindOfClass:[UIControl class]]) {
|
||||||
|
// Get actions of UIControl
|
||||||
|
UIControl *control = (UIControl *)obj;
|
||||||
|
NSMutableSet *actions = [NSMutableSet set];
|
||||||
|
NSSet *targets = control.allTargets;
|
||||||
|
for (NSObject *target in targets) {
|
||||||
|
NSArray *ary = [control actionsForTarget:target forControlEvent:0];
|
||||||
|
if (ary.count > 0) {
|
||||||
|
[actions addObjectsFromArray:ary];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (targets.count > 0) {
|
||||||
|
result[CODELESS_VIEW_TREE_ACTIONS_KEY] = actions.allObjects;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result[CODELESS_VIEW_TREE_DIMENSION_KEY] = [FBSDKViewHierarchy getDimensionOf:obj];
|
||||||
|
|
||||||
|
NSDictionary<NSString *, id> *textStyle = [FBSDKViewHierarchy getTextStyle:obj];
|
||||||
|
if (textStyle) {
|
||||||
|
result[CODELESS_VIEW_TREE_TEXT_STYLE_KEY] = textStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash) {
|
||||||
|
// hash text and hint
|
||||||
|
result[VIEW_HIERARCHY_TEXT_KEY] = [FBSDKUtility SHA256Hash:result[VIEW_HIERARCHY_TEXT_KEY]];
|
||||||
|
result[VIEW_HIERARCHY_HINT_KEY] = [FBSDKUtility SHA256Hash:result[VIEW_HIERARCHY_HINT_KEY]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSIndexPath *)getIndexPath:(NSObject *)obj
|
||||||
|
{
|
||||||
|
NSIndexPath *indexPath = nil;
|
||||||
|
|
||||||
|
if ([obj isKindOfClass:[UITableViewCell class]]) {
|
||||||
|
UITableView *tableView = [FBSDKViewHierarchy getParentTableView:(UIView *)obj];
|
||||||
|
indexPath = [tableView indexPathForCell:(UITableViewCell *)obj];
|
||||||
|
} else if ([obj isKindOfClass:[UICollectionViewCell class]]) {
|
||||||
|
UICollectionView *collectionView = [FBSDKViewHierarchy getParentCollectionView:(UIView *)obj];
|
||||||
|
indexPath = [collectionView indexPathForCell:(UICollectionViewCell *)obj];
|
||||||
|
}
|
||||||
|
|
||||||
|
return indexPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (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 = [FBSDKBasicUtility JSONStringForObject:titles
|
||||||
|
error:NULL
|
||||||
|
invalidObjectHandler:NULL];
|
||||||
|
}
|
||||||
|
} else if ([obj isKindOfClass:[UIDatePicker class]]) {
|
||||||
|
UIDatePicker *picker = (UIDatePicker *)obj;
|
||||||
|
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
||||||
|
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ssZ";
|
||||||
|
text = [formatter stringFromDate:picker.date];
|
||||||
|
} else if ([obj isKindOfClass:objc_lookUpClass("RCTTextView")]) {
|
||||||
|
NSTextStorage *textStorage = [FBSDKAppEventsUtility getVariable:@"_textStorage"
|
||||||
|
fromInstance:obj];
|
||||||
|
if (textStorage) {
|
||||||
|
text = textStorage.string;
|
||||||
|
}
|
||||||
|
} else if ([obj isKindOfClass:objc_lookUpClass("RCTBaseTextInputView")]) {
|
||||||
|
NSAttributedString *attributedText = [FBSDKAppEventsUtility getVariable:@"attributedText"
|
||||||
|
fromInstance:obj];
|
||||||
|
text = attributedText.string;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.length > 0 ? text : nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, id> *)getTextStyle:(NSObject *)obj
|
||||||
|
{
|
||||||
|
UIFont *font = nil;
|
||||||
|
if ([obj isKindOfClass:[UIButton class]]) {
|
||||||
|
font = ((UIButton *)obj).titleLabel.font;
|
||||||
|
} else if ([obj isKindOfClass:[UILabel class]]) {
|
||||||
|
font = ((UILabel *)obj).font;
|
||||||
|
} else if ([obj isKindOfClass:[UITextField class]]) {
|
||||||
|
font = ((UITextField *)obj).font;
|
||||||
|
} else if ([obj isKindOfClass:[UITextView class]]) {
|
||||||
|
font = ((UITextView *)obj).font;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (font) {
|
||||||
|
UIFontDescriptorSymbolicTraits traits = font.fontDescriptor.symbolicTraits;
|
||||||
|
BOOL isBold = (traits & UIFontDescriptorTraitBold) != 0;
|
||||||
|
BOOL isItalic = (traits & UIFontDescriptorTraitItalic) != 0;
|
||||||
|
CGFloat fontSize = font.pointSize;
|
||||||
|
|
||||||
|
return @{
|
||||||
|
CODELESS_VIEW_TREE_TEXT_IS_BOLD_KEY: @(isBold),
|
||||||
|
CODELESS_VIEW_TREE_TEXT_IS_ITALIC_KEY: @(isItalic),
|
||||||
|
CODELESS_VIEW_TREE_TEXT_SIZE_KEY: @(fontSize)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSUInteger)getClassBitmask:(NSObject *)obj
|
||||||
|
{
|
||||||
|
NSUInteger bitmask = 0;
|
||||||
|
|
||||||
|
if ([obj isKindOfClass:[UIView class]]) {
|
||||||
|
if ([obj isKindOfClass:[UIControl class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskUIControl;
|
||||||
|
if ([obj isKindOfClass:[UIButton class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskUIButton;
|
||||||
|
} else if ([obj isKindOfClass:[UISwitch class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskSwitch;
|
||||||
|
}else if ([obj isKindOfClass:[UIDatePicker class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskPicker;
|
||||||
|
}
|
||||||
|
} else if ([obj isKindOfClass:[UITableViewCell class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskUITableViewCell;
|
||||||
|
} else if ([obj isKindOfClass:[UICollectionViewCell class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskUICollectionViewCell;
|
||||||
|
} else if ([obj isKindOfClass:[UIPickerView class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskPicker;
|
||||||
|
} else if ([obj isKindOfClass:[UILabel class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([FBSDKViewHierarchy isRCTButton:((UIView *)obj)]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskReactNativeButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check selector of UITextInput protocol instead of checking conformsToProtocol
|
||||||
|
if ([obj respondsToSelector:@selector(textInRange:)]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskInput;
|
||||||
|
}
|
||||||
|
} else if ([obj isKindOfClass:[UIViewController class]]) {
|
||||||
|
bitmask |= FBCodelessClassBitmaskUIViewController;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isUserInputView:(NSObject *)obj
|
||||||
|
{
|
||||||
|
if (obj && [obj conformsToProtocol:@protocol(UITextInput)]) {
|
||||||
|
id<UITextInput> input = (id<UITextInput>)obj;
|
||||||
|
if ([input respondsToSelector:@selector(isSecureTextEntry)]
|
||||||
|
&& input.secureTextEntry) {
|
||||||
|
return YES;
|
||||||
|
} else {
|
||||||
|
if ([input respondsToSelector:@selector(keyboardType)]) {
|
||||||
|
switch (input.keyboardType) {
|
||||||
|
case UIKeyboardTypePhonePad:
|
||||||
|
case UIKeyboardTypeEmailAddress:
|
||||||
|
return YES;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *text = [FBSDKViewHierarchy getText:obj];
|
||||||
|
return text && [FBSDKAppEventsUtility isSensitiveUserData:text];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, id> *)recursiveCaptureTree:(NSObject *)obj withObject:(NSObject *)interact
|
||||||
|
{
|
||||||
|
if (!obj) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableDictionary<NSString *, id> *result = [FBSDKViewHierarchy getDetailAttributesOf:obj withHash:NO];
|
||||||
|
|
||||||
|
NSArray<NSObject *> *children = [FBSDKViewHierarchy getChildren:obj];
|
||||||
|
NSMutableArray<NSDictionary<NSString *, id> *> *childrenTrees = [NSMutableArray array];
|
||||||
|
for (NSObject *child in children) {
|
||||||
|
NSDictionary<NSString *, id> *objTree = [self recursiveCaptureTree:child withObject:interact];
|
||||||
|
[childrenTrees addObject:objTree];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childrenTrees.count > 0) {
|
||||||
|
[result setObject:[childrenTrees copy] forKey:VIEW_HIERARCHY_CHILD_VIEWS_KEY];
|
||||||
|
}
|
||||||
|
if (obj == interact) {
|
||||||
|
[result setObject:[NSNumber numberWithBool:YES] forKey:VIEW_HIERARCHY_IS_INTERACTED_KEY];
|
||||||
|
}
|
||||||
|
return [result copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||||
|
+ (BOOL)isRCTButton:(UIView *)view
|
||||||
|
{
|
||||||
|
if (view == nil) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class classRCTView = objc_lookUpClass(ReactNativeClassRCTView);
|
||||||
|
if (classRCTView && [view isKindOfClass:classRCTView] &&
|
||||||
|
[view respondsToSelector:@selector(reactTagAtPoint:)] &&
|
||||||
|
[view respondsToSelector:@selector(reactTag)] &&
|
||||||
|
view.userInteractionEnabled) {
|
||||||
|
// We check all its subviews locations and the view is clickable if there exists one that mathces reactTagAtPoint
|
||||||
|
for (UIView *subview in view.subviews) {
|
||||||
|
if (subview && ![subview isKindOfClass:classRCTView]) {
|
||||||
|
NSNumber *reactTag = [view performSelector:@selector(reactTagAtPoint:)
|
||||||
|
withObject:[NSValue valueWithCGPoint:subview.frame.origin]];
|
||||||
|
NSNumber *subviewReactTag = [FBSDKViewHierarchy getViewReactTag:subview];
|
||||||
|
if (reactTag != nil && subviewReactTag != nil && [reactTag isEqualToNumber:subviewReactTag]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSNumber *)getViewReactTag:(UIView *)view
|
||||||
|
{
|
||||||
|
if (view != nil && [view respondsToSelector:@selector(reactTag)]) {
|
||||||
|
NSNumber *reactTag = [view performSelector:@selector(reactTag)];
|
||||||
|
if (reactTag != nil && [reactTag isKindOfClass:[NSNumber class]]) {
|
||||||
|
return reactTag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
+ (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSInteger)getTag:(NSObject *)obj
|
||||||
|
{
|
||||||
|
if ([obj isKindOfClass:[UIView class]]) {
|
||||||
|
return ((UIView *)obj).tag;
|
||||||
|
} else if ([obj isKindOfClass:[UIViewController class]]) {
|
||||||
|
return ((UIViewController *)obj).view.tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, NSNumber *> *)getDimensionOf:(NSObject *)obj
|
||||||
|
{
|
||||||
|
UIView *view = nil;
|
||||||
|
|
||||||
|
if ([obj isKindOfClass:[UIView class]]) {
|
||||||
|
view = (UIView *)obj;
|
||||||
|
} else if ([obj isKindOfClass:[UIViewController class]]) {
|
||||||
|
view = ((UIViewController *)obj).view;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGRect frame = view.frame;
|
||||||
|
CGPoint offset = CGPointZero;
|
||||||
|
|
||||||
|
if ([view isKindOfClass:[UIScrollView class]])
|
||||||
|
offset = ((UIScrollView *)view).contentOffset;
|
||||||
|
|
||||||
|
return @{
|
||||||
|
CODELESS_VIEW_TREE_TOP_KEY: @((int)frame.origin.y),
|
||||||
|
CODELESS_VIEW_TREE_LEFT_KEY: @((int)frame.origin.x),
|
||||||
|
CODELESS_VIEW_TREE_WIDTH_KEY: @((int)frame.size.width),
|
||||||
|
CODELESS_VIEW_TREE_HEIGHT_KEY: @((int)frame.size.height),
|
||||||
|
CODELESS_VIEW_TREE_OFFSET_X_KEY: @((int)offset.x),
|
||||||
|
CODELESS_VIEW_TREE_OFFSET_Y_KEY: @((int)offset.y),
|
||||||
|
CODELESS_VIEW_TREE_VISIBILITY_KEY: view.isHidden ? @4 : @0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
// 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 FBSDKViewHierarchyMacros_h
|
||||||
|
#define FBSDKViewHierarchyMacros_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_IS_USER_INPUT_KEY @"is_user_input"
|
||||||
|
#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"
|
||||||
|
|
||||||
|
#define CODELESS_INDEXING_UPLOAD_INTERVAL_IN_SECONDS 1
|
||||||
|
#define CODELESS_INDEXING_STATUS_KEY @"is_app_indexing_enabled"
|
||||||
|
#define CODELESS_INDEXING_SESSION_ID_KEY @"device_session_id"
|
||||||
|
#define CODELESS_INDEXING_APP_VERSION_KEY @"app_version"
|
||||||
|
#define CODELESS_INDEXING_SDK_VERSION_KEY @"sdk_version"
|
||||||
|
#define CODELESS_INDEXING_PLATFORM_KEY @"platform"
|
||||||
|
#define CODELESS_INDEXING_TREE_KEY @"tree"
|
||||||
|
#define CODELESS_INDEXING_SCREENSHOT_KEY @"screenshot"
|
||||||
|
#define CODELESS_INDEXING_EXT_INFO_KEY @"extinfo"
|
||||||
|
|
||||||
|
#define CODELESS_INDEXING_ENDPOINT @"app_indexing"
|
||||||
|
#define CODELESS_INDEXING_SESSION_ENDPOINT @"app_indexing_session"
|
||||||
|
|
||||||
|
#define CODELESS_SETUP_ENABLED_FIELD @"auto_event_setup_enabled"
|
||||||
|
#define CODELESS_SETUP_ENABLED_KEY @"codeless_setup_enabled"
|
||||||
|
#define CODELESS_SETTING_KEY @"com.facebook.sdk:codelessSetting%@"
|
||||||
|
#define CODELESS_SETTING_TIMESTAMP_KEY @"codeless_setting_timestamp"
|
||||||
|
#define CODELESS_SETTING_CACHE_TIMEOUT (7 * 24 * 60 * 60)
|
||||||
|
|
||||||
|
// keys for view tree
|
||||||
|
#define CODELESS_VIEW_TREE_DESC_KEY @"description"
|
||||||
|
#define CODELESS_VIEW_TREE_DIMENSION_KEY @"dimension"
|
||||||
|
#define CODELESS_VIEW_TREE_TAG_KEY @"tag"
|
||||||
|
#define CODELESS_VIEW_TREE_ACTIONS_KEY @"actions"
|
||||||
|
|
||||||
|
#define CODELESS_VIEW_TREE_TOP_KEY @"top"
|
||||||
|
#define CODELESS_VIEW_TREE_LEFT_KEY @"left"
|
||||||
|
#define CODELESS_VIEW_TREE_WIDTH_KEY @"width"
|
||||||
|
#define CODELESS_VIEW_TREE_HEIGHT_KEY @"height"
|
||||||
|
#define CODELESS_VIEW_TREE_OFFSET_X_KEY @"scrollx"
|
||||||
|
#define CODELESS_VIEW_TREE_OFFSET_Y_KEY @"scrolly"
|
||||||
|
#define CODELESS_VIEW_TREE_VISIBILITY_KEY @"visibility"
|
||||||
|
|
||||||
|
#define CODELESS_VIEW_TREE_TEXT_STYLE_KEY @"text_style"
|
||||||
|
#define CODELESS_VIEW_TREE_TEXT_IS_BOLD_KEY @"is_bold"
|
||||||
|
#define CODELESS_VIEW_TREE_TEXT_IS_ITALIC_KEY @"is_italic"
|
||||||
|
#define CODELESS_VIEW_TREE_TEXT_SIZE_KEY @"font_size"
|
||||||
|
|
||||||
|
// keys for view hierarchy
|
||||||
|
#define VIEW_HIERARCHY_CHILD_VIEWS_KEY @"childviews"
|
||||||
|
#define VIEW_HIERARCHY_CLASS_NAME_KEY @"classname"
|
||||||
|
#define VIEW_HIERARCHY_CLASS_TYPE_BITMASK_KEY @"classtypebitmask"
|
||||||
|
#define VIEW_HIERARCHY_HINT_KEY @"hint"
|
||||||
|
#define VIEW_HIERARCHY_IS_INTERACTED_KEY @"is_interacted"
|
||||||
|
#define VIEW_HIERARCHY_SCREEN_NAME_KEY @"screenname"
|
||||||
|
#define VIEW_HIERARCHY_TEXT_KEY @"text"
|
||||||
|
#define VIEW_HIERARCHY_VIEW_KEY @"view"
|
||||||
|
|
||||||
|
// keys for suggested events
|
||||||
|
#define DENSE_FEATURE_KEY @"DENSE_FEATURE"
|
||||||
|
#define SUGGEST_EVENT_KEY @"SUGGEST_EVENT"
|
||||||
|
#define SUGGESTED_EVENTS_OTHER @"other"
|
||||||
|
|
||||||
|
#endif /* FBSDKCodelessMacros_h */
|
||||||
75
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLink.h
generated
Normal file
75
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLink.h
generated
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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
|
||||||
|
NS_SWIFT_NAME(AppLinkVersion);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Contains App Link metadata relevant for navigation on this device
|
||||||
|
derived from the HTML at a given URL.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(AppLink)
|
||||||
|
@interface FBSDKAppLink : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
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:(nullable NSURL *)sourceURL
|
||||||
|
targets:(NSArray<FBSDKAppLinkTarget *> *)targets
|
||||||
|
webURL:(nullable NSURL *)webURL
|
||||||
|
NS_SWIFT_NAME(init(sourceURL:targets:webURL:));
|
||||||
|
|
||||||
|
/** The URL from which this FBSDKAppLink was derived */
|
||||||
|
@property (nonatomic, strong, readonly, nullable) 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
|
||||||
|
|
||||||
|
#endif
|
||||||
76
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLink.m
generated
Normal file
76
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLink.m
generated
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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) NSURL *sourceURL;
|
||||||
|
@property (nonatomic, copy) NSArray<FBSDKAppLinkTarget *> *targets;
|
||||||
|
@property (nonatomic, strong) NSURL *webURL;
|
||||||
|
|
||||||
|
@property (nonatomic, assign, 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
|
||||||
|
|
||||||
|
#endif
|
||||||
147
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkNavigation.h
generated
Normal file
147
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkNavigation.h
generated
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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
|
||||||
|
} NS_SWIFT_NAME(AppLinkNavigation.Type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 (^FBSDKAppLinkNavigationBlock)(FBSDKAppLinkNavigationType navType, NSError * _Nullable error)
|
||||||
|
NS_SWIFT_NAME(AppLinkNavigationBlock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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")
|
||||||
|
NS_SWIFT_NAME(AppLinkNavigation)
|
||||||
|
@interface FBSDKAppLinkNavigation : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The default resolver to be used for App Link resolution. If the developer has not set one explicitly,
|
||||||
|
a basic, built-in FBSDKWebViewAppLinkResolver will be used.
|
||||||
|
*/
|
||||||
|
@property (class, nonatomic, strong) id<FBSDKAppLinkResolving> defaultResolver
|
||||||
|
NS_SWIFT_NAME(default);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return navigation type for current instance.
|
||||||
|
No-side-effect version of navigate:
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly) FBSDKAppLinkNavigationType navigationType;
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
NS_SWIFT_NAME(init(appLink:extras: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
|
||||||
|
NS_SWIFT_NAME(callbackAppLinkData(forApp:url:));
|
||||||
|
|
||||||
|
/** Performs the navigation */
|
||||||
|
- (FBSDKAppLinkNavigationType)navigate:(NSError **)error
|
||||||
|
__attribute__((swift_error(nonnull_error)));
|
||||||
|
|
||||||
|
/** Returns a FBSDKAppLink for the given URL */
|
||||||
|
+ (void)resolveAppLink:(NSURL *)destination handler:(FBSDKAppLinkBlock)handler;
|
||||||
|
|
||||||
|
/** Returns a FBSDKAppLink for the given URL using the given App Link resolution strategy */
|
||||||
|
+ (void)resolveAppLink:(NSURL *)destination
|
||||||
|
resolver:(id<FBSDKAppLinkResolving>)resolver
|
||||||
|
handler:(FBSDKAppLinkBlock)handler;
|
||||||
|
|
||||||
|
/** Navigates to a FBSDKAppLink and returns whether it opened in-app or in-browser */
|
||||||
|
+ (FBSDKAppLinkNavigationType)navigateToAppLink:(FBSDKAppLink *)link error:(NSError **)error
|
||||||
|
__attribute__((swift_error(nonnull_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;
|
||||||
|
|
||||||
|
/** Navigates to a URL (an asynchronous action) and returns a FBSDKNavigationType */
|
||||||
|
+ (void)navigateToURL:(NSURL *)destination handler:(FBSDKAppLinkNavigationBlock)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:(FBSDKAppLinkNavigationBlock)handler;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
300
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkNavigation.m
generated
Normal file
300
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkNavigation.m
generated
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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) NSDictionary<NSString *, id> *extras;
|
||||||
|
@property (nonatomic, copy) NSDictionary<NSString *, id> *appLinkData;
|
||||||
|
@property (nonatomic, strong) 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 {
|
||||||
|
return [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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.backToReferrer) {
|
||||||
|
[FBSDKMeasurementEvent postNotificationForEventName:FBSDKAppLinkNavigateBackToReferrerEventName args:logData];
|
||||||
|
} else {
|
||||||
|
[FBSDKMeasurementEvent postNotificationForEventName:FBSDKAppLinkNavigateOutEventName args:logData];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)resolveAppLink:(NSURL *)destination
|
||||||
|
resolver:(id<FBSDKAppLinkResolving>)resolver
|
||||||
|
handler:(FBSDKAppLinkBlock)handler {
|
||||||
|
[resolver appLinkFromURL:destination handler:handler];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)resolveAppLink:(NSURL *)destination handler:(FBSDKAppLinkBlock)handler {
|
||||||
|
[self resolveAppLink:destination resolver:[self defaultResolver] handler:handler];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)navigateToURL:(NSURL *)destination handler:(FBSDKAppLinkNavigationBlock)handler {
|
||||||
|
[self navigateToURL:destination resolver:[self defaultResolver] handler:handler];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)navigateToURL:(NSURL *)destination
|
||||||
|
resolver:(id<FBSDKAppLinkResolving>)resolver
|
||||||
|
handler:(FBSDKAppLinkNavigationBlock)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
|
||||||
|
|
||||||
|
#endif
|
||||||
72
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkResolver.h
generated
Normal file
72
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkResolver.h
generated
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "FBSDKAppLinkResolving.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 (^FBSDKAppLinksBlock)(NSDictionary<NSURL *, FBSDKAppLink *> * appLinks,
|
||||||
|
NSError * _Nullable error)
|
||||||
|
NS_SWIFT_NAME(AppLinksBlock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Provides an implementation of the FBSDKAppLinkResolving protocol that uses the Facebook App Link
|
||||||
|
Index API to resolve App Links given a URL. It also provides an additional helper method that can resolve
|
||||||
|
multiple App Links in a single call.
|
||||||
|
|
||||||
|
Usage of this type requires a client token. See `[FBSDKSettings setClientToken:]`
|
||||||
|
*/
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(AppLinkResolver)
|
||||||
|
@interface FBSDKAppLinkResolver : NSObject<FBSDKAppLinkResolving>
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
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:(FBSDKAppLinksBlock)handler
|
||||||
|
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension");
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocates and initializes a new instance of FBSDKAppLinkResolver.
|
||||||
|
*/
|
||||||
|
+ (instancetype)resolver
|
||||||
|
NS_SWIFT_NAME(init());
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
180
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkResolver.m
generated
Normal file
180
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkResolver.m
generated
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKAppLinkResolver.h"
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKAccessToken.h"
|
||||||
|
#import "FBSDKAppLink.h"
|
||||||
|
#import "FBSDKAppLinkTarget.h"
|
||||||
|
#import "FBSDKGraphRequest+Internal.h"
|
||||||
|
#import "FBSDKGraphRequestConnection.h"
|
||||||
|
#import "FBSDKInternalUtility.h"
|
||||||
|
#import "FBSDKLogger.h"
|
||||||
|
#import "FBSDKSettings+Internal.h"
|
||||||
|
#import "FBSDKUtility.h"
|
||||||
|
|
||||||
|
static NSString *const kURLKey = @"url";
|
||||||
|
static NSString *const kIOSAppStoreIdKey = @"app_store_id";
|
||||||
|
static NSString *const kIOSAppNameKey = @"app_name";
|
||||||
|
static NSString *const kWebKey = @"web";
|
||||||
|
static NSString *const kIOSKey = @"ios";
|
||||||
|
static NSString *const kIPhoneKey = @"iphone";
|
||||||
|
static NSString *const kIPadKey = @"ipad";
|
||||||
|
static NSString *const kShouldFallbackKey = @"should_fallback";
|
||||||
|
static NSString *const kAppLinksKey = @"app_links";
|
||||||
|
|
||||||
|
@interface FBSDKAppLinkResolver ()
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSMutableDictionary<NSURL *, FBSDKAppLink *> *cachedFBSDKAppLinks;
|
||||||
|
@property (nonatomic, assign) UIUserInterfaceIdiom userInterfaceIdiom;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKAppLinkResolver
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
if (self == [FBSDKAppLinkResolver class]) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithUserInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
self.cachedFBSDKAppLinks = [NSMutableDictionary dictionary];
|
||||||
|
self.userInterfaceIdiom = userInterfaceIdiom;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)appLinkFromURL:(NSURL *)url handler:(FBSDKAppLinkBlock)handler
|
||||||
|
{
|
||||||
|
[self appLinksFromURLs:@[url] handler:^(NSDictionary<NSURL *, FBSDKAppLink *> *urls, NSError * _Nullable error) {
|
||||||
|
handler(urls[url], error);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)appLinksFromURLs:(NSArray<NSURL *> *)urls handler:(FBSDKAppLinksBlock)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[url.absoluteString][kAppLinksKey];
|
||||||
|
NSMutableArray *rawTargets = [NSMutableArray array];
|
||||||
|
if (idiomSpecificField) {
|
||||||
|
[rawTargets addObjectsFromArray:nestedObject[idiomSpecificField]];
|
||||||
|
}
|
||||||
|
[rawTargets addObjectsFromArray:nestedObject[kIOSKey]];
|
||||||
|
|
||||||
|
NSMutableArray<FBSDKAppLinkTarget *> *targets = [NSMutableArray arrayWithCapacity:rawTargets.count];
|
||||||
|
for (id rawTarget in rawTargets) {
|
||||||
|
[targets addObject:[FBSDKAppLinkTarget appLinkTargetWithURL:[NSURL URLWithString:rawTarget[kURLKey]]
|
||||||
|
appStoreId:rawTarget[kIOSAppStoreIdKey]
|
||||||
|
appName:rawTarget[kIOSAppNameKey]]];
|
||||||
|
}
|
||||||
|
|
||||||
|
id webTarget = nestedObject[kWebKey];
|
||||||
|
NSString *webFallbackString = webTarget[kURLKey];
|
||||||
|
NSURL *fallbackUrl = webFallbackString ? [NSURL URLWithString:webFallbackString] : url;
|
||||||
|
|
||||||
|
NSNumber *shouldFallback = webTarget[kShouldFallbackKey];
|
||||||
|
if (shouldFallback != nil && !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);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (instancetype)resolver
|
||||||
|
{
|
||||||
|
return [[self alloc] initWithUserInterfaceIdiom:UI_USER_INTERFACE_IDIOM()];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
60
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkResolving.h
generated
Normal file
60
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkResolving.h
generated
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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 (^FBSDKAppLinkBlock)(FBSDKAppLink * _Nullable appLink, NSError * _Nullable error)
|
||||||
|
NS_SWIFT_NAME(AppLinkBlock);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(AppLinkResolving)
|
||||||
|
@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:(FBSDKAppLinkBlock)handler
|
||||||
|
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension");
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
114
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkReturnToRefererController.h
generated
Normal file
114
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkReturnToRefererController.h
generated
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(AppLinkReturnToRefererControllerDelegate)
|
||||||
|
@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
|
||||||
|
NS_SWIFT_NAME(return(to:willNavigateTo:));
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
NS_SWIFT_NAME(return(to:didNavigateTo: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")
|
||||||
|
NS_SWIFT_NAME(AppLinkReturnToRefererController)
|
||||||
|
@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.
|
||||||
|
|
||||||
|
@param navController The Navigation Controller for display above
|
||||||
|
*/
|
||||||
|
- (instancetype)initForDisplayAboveNavController:(UINavigationController *)navController
|
||||||
|
NS_SWIFT_NAME(init(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
|
||||||
|
NS_SWIFT_NAME(showView(forReferer:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
NS_SWIFT_NAME(showView(forReferer:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Closes the view, possibly animating it.
|
||||||
|
*/
|
||||||
|
- (void)closeViewAnimated:(BOOL)animated;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
244
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkReturnToRefererController.m
generated
Normal file
244
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkReturnToRefererController.m
generated
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#endif
|
||||||
99
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkReturnToRefererView.h
generated
Normal file
99
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkReturnToRefererView.h
generated
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKAppLinkNavigation.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, FBSDKIncludeStatusBarInSize) {
|
||||||
|
FBSDKIncludeStatusBarInSizeNever,
|
||||||
|
FBSDKIncludeStatusBarInSizeAlways,
|
||||||
|
} NS_SWIFT_NAME(FBAppLinkReturnToRefererView.StatusBarSizeInclude);
|
||||||
|
|
||||||
|
@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.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(AppLinkReturnToRefererViewDelegate)
|
||||||
|
@protocol FBSDKAppLinkReturnToRefererViewDelegate <NSObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Called when the user has tapped inside the close button.
|
||||||
|
*/
|
||||||
|
- (void)returnToRefererViewDidTapInsideCloseButton:(FBSDKAppLinkReturnToRefererView *)view
|
||||||
|
NS_SWIFT_NAME(returnToRefererViewDidTapInsideCloseButton(_:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Called when the user has tapped inside the App Link portion of the view.
|
||||||
|
*/
|
||||||
|
- (void)returnToRefererViewDidTapInsideLink:(FBSDKAppLinkReturnToRefererView *)view
|
||||||
|
link:(FBSDKAppLink *)link
|
||||||
|
NS_SWIFT_NAME(returnToRefererView(_:didTapInside:));
|
||||||
|
|
||||||
|
@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")
|
||||||
|
NS_SWIFT_NAME(FBAppLinkReturnToRefererView)
|
||||||
|
@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
|
||||||
|
NS_SWIFT_NAME(statusBarSizeInclude);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Indicates whether the user has closed the view by clicking the close button.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign, getter=isClosed) BOOL closed;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
272
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkReturnToRefererView.m
generated
Normal file
272
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkReturnToRefererView.m
generated
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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 = FBSDKIncludeStatusBarInSizeAlways;
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
_labelView.textAlignment = NSTextAlignmentCenter;
|
||||||
|
_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 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.hidden = _explicitlyHidden || _closed || !self.hasRefererData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
56
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkTarget.h
generated
Normal file
56
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkTarget.h
generated
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#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.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(AppLinkTarget)
|
||||||
|
@interface FBSDKAppLinkTarget : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
/** Creates a FBSDKAppLinkTarget with the given app site and target URL. */
|
||||||
|
+ (instancetype)appLinkTargetWithURL:(nullable NSURL *)url
|
||||||
|
appStoreId:(nullable NSString *)appStoreId
|
||||||
|
appName:(NSString *)appName
|
||||||
|
NS_SWIFT_NAME(init(url:appStoreId:appName:));
|
||||||
|
|
||||||
|
/** The URL prefix for this app link target */
|
||||||
|
@property (nonatomic, strong, readonly, nullable) 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
|
||||||
|
|
||||||
|
#endif
|
||||||
47
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkTarget.m
generated
Normal file
47
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkTarget.m
generated
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKAppLinkTarget.h"
|
||||||
|
|
||||||
|
@interface FBSDKAppLinkTarget ()
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSURL *URL;
|
||||||
|
@property (nonatomic, copy) NSString *appStoreId;
|
||||||
|
@property (nonatomic, copy) 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
|
||||||
|
|
||||||
|
#endif
|
||||||
93
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkUtility.h
generated
Normal file
93
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkUtility.h
generated
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
Describes the callback for fetchDeferredAppLink.
|
||||||
|
@param url the url representing the deferred App Link
|
||||||
|
@param error the error during the request, if any
|
||||||
|
|
||||||
|
|
||||||
|
The url may also have a fb_click_time_utc query parameter that
|
||||||
|
represents when the click occurred that caused the deferred App Link to be created.
|
||||||
|
*/
|
||||||
|
typedef void (^FBSDKURLBlock)(NSURL *_Nullable url, NSError *_Nullable error)
|
||||||
|
NS_SWIFT_NAME(URLBlock);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Class containing App Links related utility methods.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(AppLinkUtility)
|
||||||
|
@interface FBSDKAppLinkUtility : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call this method from the main thread to fetch deferred applink data if you use Mobile App
|
||||||
|
Engagement Ads (https://developers.facebook.com/docs/ads-for-apps/mobile-app-ads-engagement).
|
||||||
|
This may require a network round trip. If successful, the handler is invoked with the link
|
||||||
|
data (this will only return a valid URL once, and future calls will result in a nil URL
|
||||||
|
value in the callback).
|
||||||
|
|
||||||
|
@param 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
|
||||||
|
common case where there simply was no app link data, the NSError instance will be nil.
|
||||||
|
|
||||||
|
This method should only be called from a location that occurs after any launching URL has
|
||||||
|
been processed (e.g., you should call this method from your application delegate's
|
||||||
|
applicationDidBecomeActive:).
|
||||||
|
*/
|
||||||
|
+ (void)fetchDeferredAppLink:(nullable FBSDKURLBlock)handler;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Call this method to fetch promotion code from the url, if it's present.
|
||||||
|
|
||||||
|
@param url App Link url that was passed to the app.
|
||||||
|
|
||||||
|
@return Promotion code string.
|
||||||
|
|
||||||
|
|
||||||
|
Call this method to fetch App Invite Promotion Code from applink if present.
|
||||||
|
This can be used to fetch the promotion code that was associated with the invite when it
|
||||||
|
was created. This method should be called with the url from the openURL method.
|
||||||
|
*/
|
||||||
|
+ (nullable NSString *)appInvitePromotionCodeFromURL:(NSURL *)url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check whether the scheme is defined in the app's URL schemes.
|
||||||
|
@param scheme the scheme of App Link URL
|
||||||
|
@return YES if the scheme is defined, otherwise NO.
|
||||||
|
*/
|
||||||
|
+ (BOOL)isMatchURLScheme:(NSString *)scheme;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
125
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkUtility.m
generated
Normal file
125
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkUtility.m
generated
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKAppLinkUtility.h"
|
||||||
|
|
||||||
|
#import "FBSDKAppEventsUtility.h"
|
||||||
|
#import "FBSDKGraphRequest.h"
|
||||||
|
#import "FBSDKInternalUtility.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
#import "FBSDKURL.h"
|
||||||
|
#import "FBSDKUtility.h"
|
||||||
|
|
||||||
|
static NSString *const FBSDKLastDeferredAppLink = @"com.facebook.sdk:lastDeferredAppLink%@";
|
||||||
|
static NSString *const FBSDKDeferredAppLinkEvent = @"DEFERRED_APP_LINK";
|
||||||
|
|
||||||
|
@implementation FBSDKAppLinkUtility {}
|
||||||
|
|
||||||
|
+ (void)fetchDeferredAppLink:(FBSDKURLBlock)handler
|
||||||
|
{
|
||||||
|
NSAssert([NSThread isMainThread], @"FBSDKAppLink fetchDeferredAppLink: must be invoked from main thread.");
|
||||||
|
|
||||||
|
NSString *appID = [FBSDKSettings appID];
|
||||||
|
|
||||||
|
// Deferred app links are only currently used for engagement ads, thus we consider the app to be an advertising one.
|
||||||
|
// If this is considered for organic, non-ads scenarios, we'll need to retrieve the FBAppEventsUtility.shouldAccessAdvertisingID
|
||||||
|
// before we make this call.
|
||||||
|
NSMutableDictionary *deferredAppLinkParameters =
|
||||||
|
[FBSDKAppEventsUtility activityParametersDictionaryForEvent:FBSDKDeferredAppLinkEvent
|
||||||
|
implicitEventsOnly:NO
|
||||||
|
shouldAccessAdvertisingID:YES];
|
||||||
|
|
||||||
|
FBSDKGraphRequest *deferredAppLinkRequest = [[FBSDKGraphRequest alloc] initWithGraphPath:[NSString stringWithFormat:@"%@/activities", appID, nil]
|
||||||
|
parameters:deferredAppLinkParameters
|
||||||
|
tokenString:nil
|
||||||
|
version:nil
|
||||||
|
HTTPMethod:FBSDKHTTPMethodPOST];
|
||||||
|
|
||||||
|
[deferredAppLinkRequest startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
|
||||||
|
id result,
|
||||||
|
NSError *error) {
|
||||||
|
NSURL *applinkURL = nil;
|
||||||
|
if (!error) {
|
||||||
|
NSString *appLinkString = result[@"applink_url"];
|
||||||
|
if (appLinkString) {
|
||||||
|
applinkURL = [NSURL URLWithString:appLinkString];
|
||||||
|
|
||||||
|
NSString *createTimeUtc = result[@"click_time"];
|
||||||
|
if (createTimeUtc) {
|
||||||
|
// append/translate the create_time_utc so it can be used by clients
|
||||||
|
NSString *modifiedURLString = [applinkURL.absoluteString
|
||||||
|
stringByAppendingFormat:@"%@fb_click_time_utc=%@",
|
||||||
|
(applinkURL.query) ? @"&" : @"?" ,
|
||||||
|
createTimeUtc];
|
||||||
|
applinkURL = [NSURL URLWithString:modifiedURLString];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
handler(applinkURL, error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)appInvitePromotionCodeFromURL:(NSURL *)url
|
||||||
|
{
|
||||||
|
FBSDKURL *parsedUrl = [FBSDKURL URLWithURL:url];
|
||||||
|
NSDictionary *extras = parsedUrl.appLinkExtras;
|
||||||
|
if (extras) {
|
||||||
|
NSString *deeplinkContextString = extras[@"deeplink_context"];
|
||||||
|
|
||||||
|
// Parse deeplinkContext and extract promo code
|
||||||
|
if (deeplinkContextString.length > 0) {
|
||||||
|
NSError *error = nil;
|
||||||
|
NSDictionary<id, id> *deeplinkContextData = [FBSDKBasicUtility objectForJSONString:deeplinkContextString error:&error];
|
||||||
|
if (!error && [deeplinkContextData isKindOfClass:[NSDictionary class]]) {
|
||||||
|
return deeplinkContextData[@"promo_code"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isMatchURLScheme:(NSString *)scheme
|
||||||
|
{
|
||||||
|
if (!scheme) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
for(NSDictionary *urlType in [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"])
|
||||||
|
{
|
||||||
|
for(NSString *urlScheme in urlType[@"CFBundleURLSchemes"]) {
|
||||||
|
if([urlScheme caseInsensitiveCompare:scheme] == NSOrderedSame) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
46
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKWebViewAppLinkResolver.h
generated
Normal file
46
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKWebViewAppLinkResolver.h
generated
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "FBSDKAppLinkResolving.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
A reference implementation for an App Link resolver that uses a hidden WKWebView
|
||||||
|
to parse the HTML containing App Link metadata.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(WebViewAppLinkResolver)
|
||||||
|
@interface FBSDKWebViewAppLinkResolver : NSObject <FBSDKAppLinkResolving>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gets the instance of a FBSDKWebViewAppLinkResolver.
|
||||||
|
*/
|
||||||
|
@property (class, nonatomic, readonly, strong) FBSDKWebViewAppLinkResolver *sharedInstance
|
||||||
|
NS_SWIFT_NAME(shared);
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
325
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKWebViewAppLinkResolver.m
generated
Normal file
325
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKWebViewAppLinkResolver.m
generated
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKWebViewAppLinkResolver.h"
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <WebKit/WebKit.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 (^FBSDKURLFollowRedirectsBlock)(NSDictionary<NSString *, id> *result, NSError * _Nullable error)
|
||||||
|
NS_SWIFT_NAME(URLFollowRedirectsBlock);
|
||||||
|
|
||||||
|
// 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 <WKNavigationDelegate>
|
||||||
|
|
||||||
|
@property (nonatomic, copy) void (^didFinishLoad)(WKWebView *webView);
|
||||||
|
@property (nonatomic, copy) void (^didFailLoadWithError)(WKWebView *webView, NSError *error);
|
||||||
|
@property (nonatomic, assign) BOOL hasLoaded;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKWebViewAppLinkResolverWebViewDelegate
|
||||||
|
|
||||||
|
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
|
||||||
|
{
|
||||||
|
if (self.didFinishLoad) {
|
||||||
|
self.didFinishLoad(webView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
|
||||||
|
{
|
||||||
|
if (self.didFailLoadWithError) {
|
||||||
|
self.didFailLoadWithError(webView, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
|
||||||
|
{
|
||||||
|
if (self.hasLoaded) {
|
||||||
|
self.didFinishLoad(webView);
|
||||||
|
decisionHandler(WKNavigationActionPolicyCancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.hasLoaded = YES;
|
||||||
|
decisionHandler(WKNavigationActionPolicyAllow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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:(FBSDKURLFollowRedirectsBlock)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];
|
||||||
|
|
||||||
|
NSURLSession *session = [NSURLSession sharedSession];
|
||||||
|
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
||||||
|
completion(response, data, error);
|
||||||
|
}] resume];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)appLinkFromURL:(NSURL *)url handler:(FBSDKAppLinkBlock)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"];
|
||||||
|
|
||||||
|
WKWebView *webView = [[WKWebView alloc] init];
|
||||||
|
|
||||||
|
FBSDKWebViewAppLinkResolverWebViewDelegate *listener = [[FBSDKWebViewAppLinkResolverWebViewDelegate alloc] init];
|
||||||
|
__block FBSDKWebViewAppLinkResolverWebViewDelegate *retainedListener = listener;
|
||||||
|
listener.didFinishLoad = ^(WKWebView *view) {
|
||||||
|
if (retainedListener) {
|
||||||
|
[self getALDataFromLoadedPage:view handler:^(NSDictionary<NSString *,id> *ogData) {
|
||||||
|
[view removeFromSuperview];
|
||||||
|
view.navigationDelegate = nil;
|
||||||
|
retainedListener = nil;
|
||||||
|
handler([self appLinkFromALData:ogData destination:url], nil);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
listener.didFailLoadWithError = ^(WKWebView *view, NSError *loadError) {
|
||||||
|
if (retainedListener) {
|
||||||
|
[view removeFromSuperview];
|
||||||
|
view.navigationDelegate = nil;
|
||||||
|
retainedListener = nil;
|
||||||
|
handler(nil, loadError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
webView.navigationDelegate = listener;
|
||||||
|
webView.hidden = YES;
|
||||||
|
if (@available(iOS 9.0, *)) {
|
||||||
|
[webView loadData:responseData
|
||||||
|
MIMEType:response.MIMEType
|
||||||
|
characterEncodingName:response.textEncodingName
|
||||||
|
baseURL:response.URL];
|
||||||
|
} else {
|
||||||
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
||||||
|
[request setValue:FBSDKWebViewAppLinkResolverMetaTagPrefix forHTTPHeaderField:FBSDKWebViewAppLinkResolverPreferHeader];
|
||||||
|
[webView loadRequest:request];
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getALDataFromLoadedPage:(WKWebView *)webView
|
||||||
|
handler:(void (^)(NSDictionary<NSString *, id> *))handler
|
||||||
|
{
|
||||||
|
// Run some JavaScript in the webview to fetch the meta tags.
|
||||||
|
[webView evaluateJavaScript:FBSDKWebViewAppLinkResolverTagExtractionJavaScript
|
||||||
|
completionHandler:^(id _Nullable evaluateResult, NSError * _Nullable error) {
|
||||||
|
NSString *jsonString = [evaluateResult isKindOfClass:[NSString class]] ? evaluateResult : nil;
|
||||||
|
error = nil;
|
||||||
|
NSArray<NSDictionary<NSString *, id> *> *arr =
|
||||||
|
[NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]
|
||||||
|
options:0
|
||||||
|
error:&error];
|
||||||
|
handler([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
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(MeasurementEventListener)
|
||||||
|
@interface FBSDKMeasurementEventListener : NSObject
|
||||||
|
|
||||||
|
@property (class, nonatomic, strong, readonly) FBSDKMeasurementEventListener *defaultListener
|
||||||
|
NS_SWIFT_NAME(default);
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKMeasurementEventListener.h"
|
||||||
|
|
||||||
|
#import "FBSDKAppEvents+Internal.h"
|
||||||
|
#import "FBSDKTimeSpentData.h"
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||||
|
|
||||||
|
static NSNotificationName const FBSDKMeasurementEventNotification = @"com.facebook.facebook-objc-sdk.measurement_event";
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static NSString *const FBSDKMeasurementEventNotification = @"com.facebook.facebook-objc-sdk.measurement_event";
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static NSString *const FBSDKMeasurementEventName = @"event_name";
|
||||||
|
static NSString *const FBSDKMeasurementEventArgs = @"event_args";
|
||||||
|
static NSString *const FBSDKMeasurementEventPrefix = @"bf_";
|
||||||
|
|
||||||
|
@implementation FBSDKMeasurementEventListener
|
||||||
|
|
||||||
|
+ (instancetype)defaultListener
|
||||||
|
{
|
||||||
|
static dispatch_once_t dispatchOnceLocker = 0;
|
||||||
|
static FBSDKMeasurementEventListener *defaultListener = nil;
|
||||||
|
dispatch_once(&dispatchOnceLocker, ^{
|
||||||
|
defaultListener = [[self alloc] init];
|
||||||
|
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||||
|
[center addObserver:defaultListener
|
||||||
|
selector:@selector(logFBAppEventForNotification:)
|
||||||
|
name:FBSDKMeasurementEventNotification
|
||||||
|
object:nil];
|
||||||
|
});
|
||||||
|
return defaultListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logFBAppEventForNotification:(NSNotification *)note
|
||||||
|
{
|
||||||
|
// when catch al_nav_in event, we set source application for FBAppEvents.
|
||||||
|
if ([note.userInfo[FBSDKMeasurementEventName] isEqualToString:@"al_nav_in"]) {
|
||||||
|
NSString *sourceApplication = note.userInfo[FBSDKMeasurementEventArgs][@"sourceApplication"];
|
||||||
|
if (sourceApplication) {
|
||||||
|
[FBSDKTimeSpentData setSourceApplication:sourceApplication isFromAppLink:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id> *eventArgs = note.userInfo[FBSDKMeasurementEventArgs];
|
||||||
|
NSMutableDictionary<NSString *, id> *logData = [[NSMutableDictionary alloc] init];
|
||||||
|
for (NSString *key in eventArgs.allKeys) {
|
||||||
|
NSError *error = nil;
|
||||||
|
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^0-9a-zA-Z _-]" options:0 error:&error];
|
||||||
|
NSString *safeKey = [regex stringByReplacingMatchesInString:key
|
||||||
|
options:0
|
||||||
|
range:NSMakeRange(0, key.length)
|
||||||
|
withTemplate:@"-"];
|
||||||
|
safeKey = [safeKey stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" -"]];
|
||||||
|
logData[safeKey] = eventArgs[key];
|
||||||
|
}
|
||||||
|
[FBSDKAppEvents logInternalEvent:[FBSDKMeasurementEventPrefix stringByAppendingString:note.userInfo[FBSDKMeasurementEventName]]
|
||||||
|
parameters:logData
|
||||||
|
isImplicitlyLogged:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
35
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKCrashHandler.h
generated
Normal file
35
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKCrashHandler.h
generated
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 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 "FBSDKCrashObserving.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface FBSDKCrashHandler : NSObject
|
||||||
|
|
||||||
|
+ (void)disable;
|
||||||
|
+ (void)addObserver:(id<FBSDKCrashObserving>)observer;
|
||||||
|
+ (void)removeObserver:(id<FBSDKCrashObserving>)observer;
|
||||||
|
+ (void)clearCrashReportFiles;
|
||||||
|
+ (NSString *)getFBSDKVersion;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
347
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKCrashHandler.m
generated
Normal file
347
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKCrashHandler.m
generated
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
// 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 "FBSDKCrashHandler.h"
|
||||||
|
|
||||||
|
#import <sys/utsname.h>
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKLibAnalyzer.h"
|
||||||
|
|
||||||
|
#define FBSDK_MAX_CRASH_LOGS 5
|
||||||
|
#define FBSDK_CRASH_PATH_NAME @"instrument"
|
||||||
|
#ifndef FBSDK_VERSION_STRING
|
||||||
|
#define FBSDK_VERSION_STRING @"5.15.1"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static NSUncaughtExceptionHandler *previousExceptionHandler = NULL;
|
||||||
|
static NSString *mappingTableIdentifier = NULL;
|
||||||
|
static NSString *directoryPath;
|
||||||
|
|
||||||
|
NSString *const kFBSDKAppVersion = @"app_version";
|
||||||
|
NSString *const kFBSDKCallstack = @"callstack";
|
||||||
|
NSString *const kFBSDKCrashReason = @"reason";
|
||||||
|
NSString *const kFBSDKCrashTimestamp = @"timestamp";
|
||||||
|
NSString *const kFBSDKDeviceModel = @"device_model";
|
||||||
|
NSString *const kFBSDKDeviceOSVersion = @"device_os_version";
|
||||||
|
|
||||||
|
NSString *const kFBSDKMapingTable = @"mapping_table";
|
||||||
|
NSString *const kFBSDKMappingTableIdentifier = @"mapping_table_identifier";
|
||||||
|
|
||||||
|
@implementation FBSDKCrashHandler
|
||||||
|
|
||||||
|
static NSHashTable<id<FBSDKCrashObserving>> *_observers;
|
||||||
|
static NSArray<NSDictionary<NSString *, id> *> *_processedCrashLogs;
|
||||||
|
static BOOL _isTurnedOff;
|
||||||
|
|
||||||
|
# pragma mark - Class Methods
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
NSString *dirPath = [NSTemporaryDirectory() stringByAppendingPathComponent:FBSDK_CRASH_PATH_NAME];
|
||||||
|
if (![[NSFileManager defaultManager] fileExistsAtPath:dirPath]) {
|
||||||
|
[[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:NO attributes:NULL error:NULL];
|
||||||
|
}
|
||||||
|
directoryPath = dirPath;
|
||||||
|
NSString *identifier = [[NSUUID UUID] UUIDString];
|
||||||
|
mappingTableIdentifier = [identifier stringByReplacingOccurrencesOfString:@"-" withString:@""];
|
||||||
|
_observers = [[NSHashTable alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)sendCrashLogs
|
||||||
|
{
|
||||||
|
NSArray<id<FBSDKCrashObserving>> *observers = [_observers copy];
|
||||||
|
for (id<FBSDKCrashObserving> observer in observers) {
|
||||||
|
if (observer && [observer respondsToSelector:@selector(didReceiveCrashLogs:)]) {
|
||||||
|
NSArray<NSDictionary<NSString *, id> *> *filteredCrashLogs = [self filterCrashLogs:observer.prefixes];
|
||||||
|
[observer didReceiveCrashLogs:filteredCrashLogs];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSDictionary<NSString *, id> *> *)filterCrashLogs:(NSArray<NSString *> *)prefixList
|
||||||
|
{
|
||||||
|
NSMutableArray<NSDictionary<NSString *, id> *> *crashLogs = [NSMutableArray array];
|
||||||
|
for (NSDictionary<NSString *, id> *crashLog in _processedCrashLogs) {
|
||||||
|
NSArray<NSString *> *callstack = crashLog[kFBSDKCallstack];
|
||||||
|
if ([self callstack:callstack containsPrefix:prefixList]) {
|
||||||
|
[crashLogs addObject:crashLog];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crashLogs;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)callstack:(NSArray<NSString *> *)callstack
|
||||||
|
containsPrefix:(NSArray<NSString *> *)prefixList
|
||||||
|
{
|
||||||
|
NSString *callStackString = [callstack componentsJoinedByString:@""];
|
||||||
|
for (NSString *prefix in prefixList) {
|
||||||
|
if ([callStackString containsString:prefix]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)disable
|
||||||
|
{
|
||||||
|
_isTurnedOff = YES;
|
||||||
|
[FBSDKCrashHandler uninstallExceptionsHandler];
|
||||||
|
_observers = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)addObserver:(id<FBSDKCrashObserving>)observer
|
||||||
|
{
|
||||||
|
if (_isTurnedOff || ![self isSafeToGenerateMapping]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static dispatch_once_t onceToken = 0;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
[FBSDKCrashHandler installExceptionsHandler];
|
||||||
|
_processedCrashLogs = [self getProcessedCrashLogs];
|
||||||
|
});
|
||||||
|
if (![_observers containsObject:observer]) {
|
||||||
|
[_observers addObject:observer];
|
||||||
|
[self generateMethodMapping:observer];
|
||||||
|
[self sendCrashLogs];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)removeObserver:(id<FBSDKCrashObserving>)observer
|
||||||
|
{
|
||||||
|
if ([_observers containsObject:observer]) {
|
||||||
|
[_observers removeObject:observer];
|
||||||
|
if (_observers.count == 0) {
|
||||||
|
[FBSDKCrashHandler uninstallExceptionsHandler];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# pragma mark handler function
|
||||||
|
|
||||||
|
+ (void)installExceptionsHandler
|
||||||
|
{
|
||||||
|
NSUncaughtExceptionHandler *currentHandler = NSGetUncaughtExceptionHandler();
|
||||||
|
|
||||||
|
if (currentHandler != FBSDKExceptionHandler) {
|
||||||
|
previousExceptionHandler = currentHandler;
|
||||||
|
NSSetUncaughtExceptionHandler(&FBSDKExceptionHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)uninstallExceptionsHandler
|
||||||
|
{
|
||||||
|
NSSetUncaughtExceptionHandler(previousExceptionHandler);
|
||||||
|
previousExceptionHandler = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FBSDKExceptionHandler(NSException *exception)
|
||||||
|
{
|
||||||
|
[FBSDKCrashHandler saveException:exception];
|
||||||
|
if (previousExceptionHandler) {
|
||||||
|
previousExceptionHandler(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Storage
|
||||||
|
|
||||||
|
+ (void)saveException:(NSException *)exception
|
||||||
|
{
|
||||||
|
if (exception.callStackSymbols && exception.name) {
|
||||||
|
NSArray<NSString *> *stackSymbols = [NSArray arrayWithArray:exception.callStackSymbols];
|
||||||
|
[self saveCrashLog:@{
|
||||||
|
kFBSDKCallstack : stackSymbols,
|
||||||
|
kFBSDKCrashReason : exception.name,
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)saveSignal:(int)signal withCallStack:(NSArray<NSString *> *)callStack
|
||||||
|
{
|
||||||
|
if (callStack) {
|
||||||
|
NSString *signalDescription = [NSString stringWithCString:strsignal(signal) encoding:NSUTF8StringEncoding] ?: [NSString stringWithFormat:@"SIGNUM(%i)", signal];
|
||||||
|
[self saveCrashLog:@{
|
||||||
|
kFBSDKCallstack : callStack,
|
||||||
|
kFBSDKCrashReason : signalDescription,
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSDictionary<NSString *, id> *> *)getProcessedCrashLogs
|
||||||
|
{
|
||||||
|
NSArray<NSDictionary<NSString *, id> *> *crashLogs = [self loadCrashLogs];
|
||||||
|
if (0 == crashLogs.count) {
|
||||||
|
[self clearCrashReportFiles];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSMutableArray<NSDictionary<NSString *, id> *> *processedCrashLogs = [NSMutableArray array];
|
||||||
|
|
||||||
|
for (NSDictionary<NSString *, id> *crashLog in crashLogs) {
|
||||||
|
NSArray<NSString *> *callstack = crashLog[kFBSDKCallstack];
|
||||||
|
NSData *data = [self loadLibData:crashLog];
|
||||||
|
if (!data) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id> *methodMapping = [NSJSONSerialization JSONObjectWithData:data
|
||||||
|
options:kNilOptions
|
||||||
|
error:nil];
|
||||||
|
NSArray<NSString *> *symbolicatedCallstack = [FBSDKLibAnalyzer symbolicateCallstack:callstack methodMapping:methodMapping];
|
||||||
|
NSMutableDictionary<NSString *, id> *symbolicatedCrashLog = [NSMutableDictionary dictionaryWithDictionary:crashLog];
|
||||||
|
if (symbolicatedCallstack) {
|
||||||
|
[symbolicatedCrashLog setObject:symbolicatedCallstack forKey:kFBSDKCallstack];
|
||||||
|
[symbolicatedCrashLog removeObjectForKey:kFBSDKMappingTableIdentifier];
|
||||||
|
[processedCrashLogs addObject:symbolicatedCrashLog];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return processedCrashLogs;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSDictionary<NSString *, id> *> *)loadCrashLogs
|
||||||
|
{
|
||||||
|
NSArray<NSString *> *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:NULL];
|
||||||
|
NSArray<NSString *> *fileNames = [[self getCrashLogFileNames:files] sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2){
|
||||||
|
return [obj2 compare:obj1];
|
||||||
|
}];
|
||||||
|
NSMutableArray<NSDictionary<NSString *, id> *> *crashLogArray = [NSMutableArray array];
|
||||||
|
|
||||||
|
for (NSUInteger i = 0; i < MIN(fileNames.count, FBSDK_MAX_CRASH_LOGS); i++) {
|
||||||
|
NSData *data = [self loadCrashLog:fileNames[i]];
|
||||||
|
if (!data) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, id>* crashLog = [NSJSONSerialization JSONObjectWithData:data
|
||||||
|
options:kNilOptions
|
||||||
|
error:nil];
|
||||||
|
if (crashLog) {
|
||||||
|
[crashLogArray addObject:crashLog];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [crashLogArray copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (nullable NSData *)loadCrashLog:(NSString *)fileName
|
||||||
|
{
|
||||||
|
return [NSData dataWithContentsOfFile:[directoryPath stringByAppendingPathComponent:fileName] options:NSDataReadingMappedIfSafe error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)clearCrashReportFiles
|
||||||
|
{
|
||||||
|
NSArray<NSString *> *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:nil];
|
||||||
|
|
||||||
|
for (NSUInteger i = 0; i < files.count; i++) {
|
||||||
|
// remove all crash related files except for the current mapping table
|
||||||
|
if ([files[i] hasPrefix:@"crash_"] && ![files[i] containsString:mappingTableIdentifier]) {
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:[directoryPath stringByAppendingPathComponent:files[i]] error:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSString *> *)getCrashLogFileNames:(NSArray<NSString *> *)files
|
||||||
|
{
|
||||||
|
NSMutableArray<NSString *> *fileNames = [NSMutableArray array];
|
||||||
|
|
||||||
|
for (NSString *fileName in files) {
|
||||||
|
if ([fileName hasPrefix:@"crash_log_"] && [fileName hasSuffix:@".json"]) {
|
||||||
|
[fileNames addObject:fileName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)saveCrashLog:(NSDictionary<NSString *, id> *)crashLog
|
||||||
|
{
|
||||||
|
NSMutableDictionary<NSString *, id> *completeCrashLog = [NSMutableDictionary dictionaryWithDictionary:crashLog];
|
||||||
|
NSString *currentTimestamp = [NSString stringWithFormat:@"%.0lf", [[NSDate date] timeIntervalSince1970]];
|
||||||
|
|
||||||
|
[completeCrashLog setObject:currentTimestamp forKey:kFBSDKCrashTimestamp];
|
||||||
|
[completeCrashLog setObject:mappingTableIdentifier forKey:kFBSDKMappingTableIdentifier];
|
||||||
|
|
||||||
|
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||||
|
NSString *version = [mainBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||||
|
NSString *build = [mainBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||||
|
[completeCrashLog setObject:[NSString stringWithFormat:@"%@(%@)", version, build] forKey:kFBSDKAppVersion];
|
||||||
|
|
||||||
|
struct utsname systemInfo;
|
||||||
|
uname(&systemInfo);
|
||||||
|
[completeCrashLog setObject:@(systemInfo.machine) forKey:kFBSDKDeviceModel];
|
||||||
|
|
||||||
|
[completeCrashLog setObject:[UIDevice currentDevice].systemVersion forKey:kFBSDKDeviceOSVersion];
|
||||||
|
|
||||||
|
NSData *data = [NSJSONSerialization dataWithJSONObject:completeCrashLog options:0 error:nil];
|
||||||
|
|
||||||
|
[data writeToFile:[self getPathToCrashFile:currentTimestamp]
|
||||||
|
atomically:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)generateMethodMapping:(id<FBSDKCrashObserving>)observer
|
||||||
|
{
|
||||||
|
if (observer.prefixes.count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:mappingTableIdentifier forKey:kFBSDKMappingTableIdentifier];
|
||||||
|
NSDictionary<NSString *, NSString *> *methodMapping = [FBSDKLibAnalyzer getMethodsTable:observer.prefixes
|
||||||
|
frameworks:observer.frameworks];
|
||||||
|
if (methodMapping.count > 0){
|
||||||
|
NSData *data = [NSJSONSerialization dataWithJSONObject:methodMapping options:0 error:nil];
|
||||||
|
[data writeToFile:[self getPathToLibDataFile:mappingTableIdentifier]
|
||||||
|
atomically:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (nullable NSData *)loadLibData:(NSDictionary<NSString *, id> *)crashLog
|
||||||
|
{
|
||||||
|
NSString *identifier = [crashLog objectForKey:kFBSDKMappingTableIdentifier];
|
||||||
|
return [NSData dataWithContentsOfFile:[self getPathToLibDataFile:identifier] options:NSDataReadingMappedIfSafe error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getPathToCrashFile:(NSString *)timestamp
|
||||||
|
{
|
||||||
|
return [directoryPath stringByAppendingPathComponent:
|
||||||
|
[NSString stringWithFormat:@"crash_log_%@.json", timestamp]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getPathToLibDataFile:(NSString *)identifier
|
||||||
|
{
|
||||||
|
return [directoryPath stringByAppendingPathComponent:
|
||||||
|
[NSString stringWithFormat:@"crash_lib_data_%@.json", identifier]];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isSafeToGenerateMapping
|
||||||
|
{
|
||||||
|
#if TARGET_OS_SIMULATOR
|
||||||
|
return YES;
|
||||||
|
#else
|
||||||
|
NSString *identifier = [[NSUserDefaults standardUserDefaults] objectForKey:kFBSDKMappingTableIdentifier];
|
||||||
|
//first app start
|
||||||
|
if (!identifier) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [[NSFileManager defaultManager] fileExistsAtPath:[self getPathToLibDataFile:identifier]];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getFBSDKVersion
|
||||||
|
{
|
||||||
|
return FBSDK_VERSION_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
34
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKCrashObserving.h
generated
Normal file
34
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKCrashObserving.h
generated
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
@protocol FBSDKCrashObserving <NSObject>
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSArray<NSString *> *prefixes;
|
||||||
|
@property (nonatomic, copy, nullable) NSArray<NSString *> *frameworks;
|
||||||
|
|
||||||
|
@optional
|
||||||
|
|
||||||
|
- (void)didReceiveCrashLogs:(NSArray<NSDictionary<NSString *, id> *> *)crashLogs;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
32
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKLibAnalyzer.h
generated
Normal file
32
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKLibAnalyzer.h
generated
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
@interface FBSDKLibAnalyzer : NSObject
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, NSString *> *)getMethodsTable:(NSArray<NSString *> *)prefixes
|
||||||
|
frameworks:(NSArray<NSString *> * _Nullable)frameworks;
|
||||||
|
+ (nullable NSArray<NSString *> *)symbolicateCallstack:(NSArray<NSString *> *)callstack
|
||||||
|
methodMapping:(NSDictionary<NSString *,id> *)methodMapping;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
227
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKLibAnalyzer.m
generated
Normal file
227
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Instrument/FBSDKLibAnalyzer.m
generated
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
// 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 "FBSDKLibAnalyzer.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
@implementation FBSDKLibAnalyzer
|
||||||
|
|
||||||
|
static NSMutableDictionary<NSString *, NSString *> *_methodMapping;
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
_methodMapping = [NSMutableDictionary dictionary];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, NSString *> *)getMethodsTable:(NSArray<NSString *> *)prefixes
|
||||||
|
frameworks:(NSArray<NSString *> *)frameworks
|
||||||
|
{
|
||||||
|
NSArray<NSString *> *allClasses = [self getClassNames:prefixes frameworks:frameworks];
|
||||||
|
for (NSString *className in allClasses) {
|
||||||
|
Class class = NSClassFromString(className);
|
||||||
|
if (class) {
|
||||||
|
[self addClass:class isClassMethod:NO];
|
||||||
|
[self addClass:object_getClass(class) isClassMethod:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@synchronized (_methodMapping) {
|
||||||
|
return [_methodMapping copy];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - private methods
|
||||||
|
|
||||||
|
+ (NSArray<NSString *> *)getClassNames:(NSArray<NSString *> *)prefixes
|
||||||
|
frameworks:(NSArray<NSString *> *)frameworks
|
||||||
|
{
|
||||||
|
NSMutableArray<NSString *> *classNames = [NSMutableArray new];
|
||||||
|
// from main bundle
|
||||||
|
[classNames addObjectsFromArray:[self getClassesFrom:[[NSBundle mainBundle] executablePath]
|
||||||
|
prefixes:prefixes]];
|
||||||
|
// from dynamic libraries
|
||||||
|
if (frameworks.count > 0) {
|
||||||
|
unsigned int count = 0;
|
||||||
|
const char **images = objc_copyImageNames(&count);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
NSString *image = [NSString stringWithUTF8String:images[i]];
|
||||||
|
for (NSString *framework in frameworks) {
|
||||||
|
if ([image containsString:framework]) {
|
||||||
|
[classNames addObjectsFromArray:[self getClassesFrom:image
|
||||||
|
prefixes:nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(images);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [classNames copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSString *> *)getClassesFrom:(NSString *)image
|
||||||
|
prefixes:(NSArray<NSString *> *)prefixes
|
||||||
|
{
|
||||||
|
NSMutableArray<NSString *> *classNames = [NSMutableArray array];
|
||||||
|
unsigned int count = 0;
|
||||||
|
const char **classes = objc_copyClassNamesForImage([image UTF8String], &count);
|
||||||
|
for (unsigned int i = 0; i < count; i++){
|
||||||
|
NSString *className = [NSString stringWithUTF8String:classes[i]];
|
||||||
|
if (prefixes.count > 0) {
|
||||||
|
for (NSString *prefix in prefixes) {
|
||||||
|
if ([className hasPrefix:prefix]) {
|
||||||
|
[classNames addObject:className];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
[classNames addObject:className];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(classes);
|
||||||
|
return [classNames copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)addClass:(Class)class
|
||||||
|
isClassMethod:(BOOL)isClassMethod
|
||||||
|
{
|
||||||
|
unsigned int methodsCount = 0;
|
||||||
|
Method *methods = class_copyMethodList(class, &methodsCount);
|
||||||
|
|
||||||
|
NSString *methodType = isClassMethod ? @"+" : @"-";
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < methodsCount; i++) {
|
||||||
|
Method method = methods[i];
|
||||||
|
|
||||||
|
if (method) {
|
||||||
|
SEL selector = method_getName(method);
|
||||||
|
|
||||||
|
IMP methodImplementation = class_getMethodImplementation(class, selector);
|
||||||
|
NSString *methodAddress = [NSString stringWithFormat:@"0x%010lx", (unsigned long)methodImplementation];
|
||||||
|
NSString *methodName = [NSString stringWithFormat:@"%@[%@ %@]",
|
||||||
|
methodType,
|
||||||
|
NSStringFromClass(class),
|
||||||
|
NSStringFromSelector(selector)];
|
||||||
|
|
||||||
|
if (methodAddress && methodName) {
|
||||||
|
@synchronized (_methodMapping) {
|
||||||
|
[_methodMapping setObject:methodName forKey:methodAddress];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSString *> *)symbolicateCallstack:(NSArray<NSString *> *)callstack
|
||||||
|
methodMapping:(NSDictionary<NSString *,id> *)methodMapping
|
||||||
|
{
|
||||||
|
if (!callstack || !methodMapping) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSArray<NSString *> *sortedAllAddress = [methodMapping.allKeys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
|
||||||
|
return [obj1 compare:obj2];
|
||||||
|
}];
|
||||||
|
|
||||||
|
BOOL containsFBSDKFunction = NO;
|
||||||
|
NSInteger nonSDKMethodCount = 0;
|
||||||
|
NSMutableArray<NSString *> *symbolicatedCallstack = [NSMutableArray array];
|
||||||
|
|
||||||
|
for (NSUInteger i = 0; i < callstack.count; i++){
|
||||||
|
NSString *rawAddress = [self getAddress:callstack[i]];
|
||||||
|
NSString *addressString = [NSString stringWithFormat:@"0x%@",[rawAddress substringWithRange:NSMakeRange(rawAddress.length - 10, 10)]];
|
||||||
|
NSString *methodAddress = [self searchMethod:addressString sortedAllAddress:sortedAllAddress];
|
||||||
|
|
||||||
|
if (methodAddress) {
|
||||||
|
containsFBSDKFunction = YES;
|
||||||
|
nonSDKMethodCount == 0 ?: [symbolicatedCallstack addObject:[NSString stringWithFormat:@"(%ld DEV METHODS)", (long)nonSDKMethodCount]];
|
||||||
|
nonSDKMethodCount = 0;
|
||||||
|
NSString *methodName = [methodMapping objectForKey:methodAddress];
|
||||||
|
|
||||||
|
// filter out cxx_destruct
|
||||||
|
if ([methodName containsString:@".cxx_destruct"]) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
[symbolicatedCallstack addObject:[NSString stringWithFormat:@"%@%@", methodName, [self getOffset:addressString secondString:methodAddress]]];
|
||||||
|
} else {
|
||||||
|
nonSDKMethodCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nonSDKMethodCount == 0 ?: [symbolicatedCallstack addObject:[NSString stringWithFormat:@"(%ld DEV METHODS)", (long)nonSDKMethodCount]];
|
||||||
|
|
||||||
|
return containsFBSDKFunction ? symbolicatedCallstack : nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getAddress:(NSString *)callstackEntry
|
||||||
|
{
|
||||||
|
NSArray<NSString *> *components = [callstackEntry componentsSeparatedByString:@" "];
|
||||||
|
for (NSString *component in components) {
|
||||||
|
if ([component containsString:@"0x"]) {
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getOffset:(NSString *)firstString
|
||||||
|
secondString:(NSString *)secondString
|
||||||
|
{
|
||||||
|
if (!firstString || !secondString) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
unsigned long long first = 0, second = 0;
|
||||||
|
NSScanner *scanner = [NSScanner scannerWithString:firstString];
|
||||||
|
[scanner scanHexLongLong:&first];
|
||||||
|
|
||||||
|
scanner = [NSScanner scannerWithString:secondString];
|
||||||
|
[scanner scanHexLongLong:&second];
|
||||||
|
|
||||||
|
unsigned long long difference = first - second;
|
||||||
|
return [NSString stringWithFormat:@"+%llu", difference];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)searchMethod:(NSString *)address
|
||||||
|
sortedAllAddress:(NSArray<NSString *> *)sortedAllAddress
|
||||||
|
{
|
||||||
|
if (0 == sortedAllAddress.count) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSString *lowestAddress = sortedAllAddress[0];
|
||||||
|
NSString *highestAddress = sortedAllAddress[sortedAllAddress.count - 1];
|
||||||
|
|
||||||
|
if ([address compare:lowestAddress] == NSOrderedAscending || [address compare:highestAddress] == NSOrderedDescending) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([address compare:lowestAddress] == NSOrderedSame) {
|
||||||
|
return lowestAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([address compare:highestAddress] == NSOrderedSame) {
|
||||||
|
return highestAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSUInteger index = [sortedAllAddress indexOfObject:address
|
||||||
|
inSortedRange:NSMakeRange(0, sortedAllAddress.count - 1)
|
||||||
|
options:NSBinarySearchingInsertionIndex
|
||||||
|
usingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
|
||||||
|
return [obj1 compare:obj2];
|
||||||
|
}];
|
||||||
|
return sortedAllAddress[index - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
135
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKBasicUtility.h
generated
Normal file
135
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKBasicUtility.h
generated
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
Describes the callback for appLinkFromURLInBackground.
|
||||||
|
@param object the FBSDKAppLink representing the deferred App Link
|
||||||
|
@param stop the error during the request, if any
|
||||||
|
|
||||||
|
*/
|
||||||
|
typedef id _Nullable (^FBSDKInvalidObjectHandler)(id object, BOOL *stop)
|
||||||
|
NS_SWIFT_NAME(InvalidObjectHandler);
|
||||||
|
|
||||||
|
@interface FBSDKBasicUtility : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts an object into a JSON string.
|
||||||
|
@param object The object to convert to JSON.
|
||||||
|
@param errorRef If an error occurs, upon return contains an NSError object that describes the problem.
|
||||||
|
@param invalidObjectHandler Handles objects that are invalid, returning a replacement value or nil to ignore.
|
||||||
|
@return A JSON string or nil if the object cannot be converted to JSON.
|
||||||
|
*/
|
||||||
|
+ (nullable NSString *)JSONStringForObject:(id)object
|
||||||
|
error:(NSError *__autoreleasing *)errorRef
|
||||||
|
invalidObjectHandler:(nullable FBSDKInvalidObjectHandler)invalidObjectHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets an object for a key in a dictionary if it is not nil.
|
||||||
|
@param dictionary The dictionary to set the value for.
|
||||||
|
@param object The value to set.
|
||||||
|
@param key The key to set the value for.
|
||||||
|
*/
|
||||||
|
+ (void)dictionary:(NSMutableDictionary<NSString *, id> *)dictionary
|
||||||
|
setObject:(nullable id)object
|
||||||
|
forKey:(nullable id<NSCopying>)key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets an object for a key in a dictionary if it is not nil.
|
||||||
|
@param dictionary The dictionary to set the value for.
|
||||||
|
@param object The value to set after serializing to JSON.
|
||||||
|
@param key The key to set the value for.
|
||||||
|
@param errorRef If an error occurs, upon return contains an NSError object that describes the problem.
|
||||||
|
@return NO if an error occurred while serializing the object, otherwise YES.
|
||||||
|
*/
|
||||||
|
+ (BOOL)dictionary:(NSMutableDictionary<id, id> *)dictionary
|
||||||
|
setJSONStringForObject:(id)object
|
||||||
|
forKey:(id<NSCopying>)key
|
||||||
|
error:(NSError *__autoreleasing *)errorRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Adds an object to an array if it is not nil.
|
||||||
|
@param array The array to add the object to.
|
||||||
|
@param object The object to add to the array.
|
||||||
|
*/
|
||||||
|
+ (void)array:(NSMutableArray *)array addObject:(nullable id)object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts a JSON string into an object
|
||||||
|
@param string The JSON string to convert.
|
||||||
|
@param errorRef If an error occurs, upon return contains an NSError object that describes the problem.
|
||||||
|
@return An NSDictionary, NSArray, NSString or NSNumber containing the object representation, or nil if the string
|
||||||
|
cannot be converted.
|
||||||
|
*/
|
||||||
|
+ (nullable id)objectForJSONString:(NSString *)string error:(NSError *__autoreleasing *)errorRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Constructs a query string from a dictionary.
|
||||||
|
@param 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.
|
||||||
|
@param invalidObjectHandler Handles objects that are invalid, returning a replacement value or nil to ignore.
|
||||||
|
@return Query string representation of the parameters.
|
||||||
|
*/
|
||||||
|
+ (NSString *)queryStringWithDictionary:(NSDictionary<NSString *, id> *)dictionary
|
||||||
|
error:(NSError *__autoreleasing *)errorRef
|
||||||
|
invalidObjectHandler:(nullable FBSDKInvalidObjectHandler)invalidObjectHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts simple value types to the string equivalent for serializing to a request query or body.
|
||||||
|
@param value The value to be converted.
|
||||||
|
@return The value that may have been converted if able (otherwise the input param).
|
||||||
|
*/
|
||||||
|
+ (id)convertRequestValue:(id)value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Encodes a value for an URL.
|
||||||
|
@param value The value to encode.
|
||||||
|
@return The encoded value.
|
||||||
|
*/
|
||||||
|
+ (NSString *)URLEncode:(NSString *)value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parses a query string into a dictionary.
|
||||||
|
@param queryString The query string value.
|
||||||
|
@return A dictionary with the key/value pairs.
|
||||||
|
*/
|
||||||
|
+ (NSDictionary<NSString *, NSString *> *)dictionaryWithQueryString:(NSString *)queryString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Decodes a value from an URL.
|
||||||
|
@param value The value to decode.
|
||||||
|
@return The decoded value.
|
||||||
|
*/
|
||||||
|
+ (NSString *)URLDecode:(NSString *)value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gzip data with default compression level if possible.
|
||||||
|
@param data The raw data.
|
||||||
|
@return nil if unable to gzip the data, otherwise gzipped data.
|
||||||
|
*/
|
||||||
|
+ (nullable NSData *)gzip:(NSData *)data;
|
||||||
|
|
||||||
|
+ (NSString *)anonymousID;
|
||||||
|
+ (NSString *)persistenceFilePath:(NSString *)filename;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
341
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKBasicUtility.m
generated
Normal file
341
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKBasicUtility.m
generated
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
// 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 "FBSDKBasicUtility.h"
|
||||||
|
|
||||||
|
#import <zlib.h>
|
||||||
|
|
||||||
|
#import "FBSDKTypeUtility.h"
|
||||||
|
|
||||||
|
#define kChunkSize 1024
|
||||||
|
|
||||||
|
static NSString *const FBSDK_BASICUTILITY_ANONYMOUSIDFILENAME = @"com-facebook-sdk-PersistedAnonymousID.json";
|
||||||
|
static NSString *const FBSDK_BASICUTILITY_ANONYMOUSID_KEY = @"anon_id";
|
||||||
|
|
||||||
|
@protocol BASIC_FBSDKError
|
||||||
|
|
||||||
|
+ (NSError *)invalidArgumentErrorWithName:(NSString *)name value:(id)value message:(NSString *)message;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FBSDKBasicUtility
|
||||||
|
|
||||||
|
+ (NSString *)JSONStringForObject:(id)object
|
||||||
|
error:(NSError *__autoreleasing *)errorRef
|
||||||
|
invalidObjectHandler:(FBSDKInvalidObjectHandler)invalidObjectHandler
|
||||||
|
{
|
||||||
|
if (invalidObjectHandler || ![NSJSONSerialization isValidJSONObject:object]) {
|
||||||
|
object = [self _convertObjectToJSONObject:object invalidObjectHandler:invalidObjectHandler stop:NULL];
|
||||||
|
if (![NSJSONSerialization isValidJSONObject:object]) {
|
||||||
|
if (errorRef != NULL) {
|
||||||
|
Class FBSDKErrorClass = NSClassFromString(@"FBSDKError");
|
||||||
|
if ([FBSDKErrorClass respondsToSelector:@selector(invalidArgumentErrorWithName:value:message:)]) {
|
||||||
|
*errorRef = [FBSDKErrorClass invalidArgumentErrorWithName:@"object"
|
||||||
|
value:object
|
||||||
|
message:@"Invalid object for JSON serialization."];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NSData *data = [NSJSONSerialization dataWithJSONObject:object options:0 error:errorRef];
|
||||||
|
if (!data) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)dictionary:(NSMutableDictionary<NSString *, id> *)dictionary
|
||||||
|
setJSONStringForObject:(id)object
|
||||||
|
forKey:(id<NSCopying>)key
|
||||||
|
error:(NSError *__autoreleasing *)errorRef
|
||||||
|
{
|
||||||
|
if (!object || !key) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
NSString *JSONString = [self JSONStringForObject:object error:errorRef invalidObjectHandler:NULL];
|
||||||
|
if (!JSONString) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
[self dictionary:dictionary setObject:JSONString forKey:key];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id)_convertObjectToJSONObject:(id)object
|
||||||
|
invalidObjectHandler:(FBSDKInvalidObjectHandler)invalidObjectHandler
|
||||||
|
stop:(BOOL *)stopRef
|
||||||
|
{
|
||||||
|
__block BOOL stop = NO;
|
||||||
|
if ([object isKindOfClass:[NSString class]] || [object isKindOfClass:[NSNumber class]]) {
|
||||||
|
// good to go, keep the object
|
||||||
|
} else if ([object isKindOfClass:[NSURL class]]) {
|
||||||
|
object = ((NSURL *)object).absoluteString;
|
||||||
|
} else if ([object isKindOfClass:[NSDictionary class]]) {
|
||||||
|
NSMutableDictionary<NSString *, id> *dictionary = [[NSMutableDictionary alloc] init];
|
||||||
|
[(NSDictionary<id, id> *)object enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *dictionaryStop) {
|
||||||
|
[self dictionary:dictionary
|
||||||
|
setObject:[self _convertObjectToJSONObject:obj invalidObjectHandler:invalidObjectHandler stop:&stop]
|
||||||
|
forKey:[FBSDKTypeUtility stringValue:key]];
|
||||||
|
if (stop) {
|
||||||
|
*dictionaryStop = YES;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
object = dictionary;
|
||||||
|
} else if ([object isKindOfClass:[NSArray class]]) {
|
||||||
|
NSMutableArray<id> *array = [[NSMutableArray alloc] init];
|
||||||
|
for (id obj in (NSArray *)object) {
|
||||||
|
id convertedObj = [self _convertObjectToJSONObject:obj invalidObjectHandler:invalidObjectHandler stop:&stop];
|
||||||
|
[self array:array addObject:convertedObj];
|
||||||
|
if (stop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
object = array;
|
||||||
|
} else {
|
||||||
|
object = invalidObjectHandler(object, stopRef);
|
||||||
|
}
|
||||||
|
if (stopRef != NULL) {
|
||||||
|
*stopRef = stop;
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)dictionary:(NSMutableDictionary<NSString *, id> *)dictionary setObject:(id)object forKey:(id<NSCopying>)key
|
||||||
|
{
|
||||||
|
if (object && key) {
|
||||||
|
dictionary[key] = object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)array:(NSMutableArray *)array addObject:(id)object
|
||||||
|
{
|
||||||
|
if (object) {
|
||||||
|
[array addObject:object];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id)objectForJSONString:(NSString *)string error:(NSError *__autoreleasing *)errorRef
|
||||||
|
{
|
||||||
|
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
if (!data) {
|
||||||
|
if (errorRef != NULL) {
|
||||||
|
*errorRef = nil;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:errorRef];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)queryStringWithDictionary:(NSDictionary<id, id> *)dictionary
|
||||||
|
error:(NSError *__autoreleasing *)errorRef
|
||||||
|
invalidObjectHandler:(FBSDKInvalidObjectHandler)invalidObjectHandler
|
||||||
|
{
|
||||||
|
NSMutableString *queryString = [[NSMutableString alloc] init];
|
||||||
|
__block BOOL hasParameters = NO;
|
||||||
|
if (dictionary) {
|
||||||
|
NSMutableArray<NSString *> *keys = [dictionary.allKeys mutableCopy];
|
||||||
|
// remove non-string keys, as they are not valid
|
||||||
|
[keys filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary<id, id> *bindings) {
|
||||||
|
return [evaluatedObject isKindOfClass:[NSString class]];
|
||||||
|
}]];
|
||||||
|
// sort the keys so that the query string order is deterministic
|
||||||
|
[keys sortUsingSelector:@selector(compare:)];
|
||||||
|
BOOL stop = NO;
|
||||||
|
for (NSString *key in keys) {
|
||||||
|
id value = [self convertRequestValue:dictionary[key]];
|
||||||
|
if ([value isKindOfClass:[NSString class]]) {
|
||||||
|
value = [self URLEncode:value];
|
||||||
|
}
|
||||||
|
if (invalidObjectHandler && ![value isKindOfClass:[NSString class]]) {
|
||||||
|
value = invalidObjectHandler(value, &stop);
|
||||||
|
if (stop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
if (hasParameters) {
|
||||||
|
[queryString appendString:@"&"];
|
||||||
|
}
|
||||||
|
[queryString appendFormat:@"%@=%@", key, value];
|
||||||
|
hasParameters = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorRef != NULL) {
|
||||||
|
*errorRef = nil;
|
||||||
|
}
|
||||||
|
return (queryString.length ? [queryString copy] : nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id)convertRequestValue:(id)value
|
||||||
|
{
|
||||||
|
if ([value isKindOfClass:[NSNumber class]]) {
|
||||||
|
value = ((NSNumber *)value).stringValue;
|
||||||
|
} else if ([value isKindOfClass:[NSURL class]]) {
|
||||||
|
value = ((NSURL *)value).absoluteString;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
+ (NSString *)URLEncode:(NSString *)value
|
||||||
|
{
|
||||||
|
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
|
||||||
|
(CFStringRef)value,
|
||||||
|
NULL, // characters to leave unescaped
|
||||||
|
CFSTR(":!*();@/&?+$,='"),
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
+ (NSDictionary<NSString *, NSString *> *)dictionaryWithQueryString:(NSString *)queryString
|
||||||
|
{
|
||||||
|
NSMutableDictionary<NSString *, NSString *> *result = [[NSMutableDictionary alloc] init];
|
||||||
|
NSArray<NSString *> *parts = [queryString componentsSeparatedByString:@"&"];
|
||||||
|
|
||||||
|
for (NSString *part in parts) {
|
||||||
|
if (part.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSRange index = [part rangeOfString:@"="];
|
||||||
|
NSString *key;
|
||||||
|
NSString *value;
|
||||||
|
|
||||||
|
if (index.location == NSNotFound) {
|
||||||
|
key = part;
|
||||||
|
value = @"";
|
||||||
|
} else {
|
||||||
|
key = [part substringToIndex:index.location];
|
||||||
|
value = [part substringFromIndex:index.location + index.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
key = [self URLDecode:key];
|
||||||
|
value = [self URLDecode:value];
|
||||||
|
if (key && value) {
|
||||||
|
result[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)URLDecode:(NSString *)value
|
||||||
|
{
|
||||||
|
value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "];
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSData *)gzip:(NSData *)data
|
||||||
|
{
|
||||||
|
const void *bytes = data.bytes;
|
||||||
|
const NSUInteger length = data.length;
|
||||||
|
|
||||||
|
if (!bytes || !length) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__LP64__) && __LP64__
|
||||||
|
if (length > UINT_MAX) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// initialze stream
|
||||||
|
z_stream stream;
|
||||||
|
bzero(&stream, sizeof(z_stream));
|
||||||
|
|
||||||
|
if (deflateInit2(&stream, -1, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
stream.avail_in = (uint)length;
|
||||||
|
stream.next_in = (Bytef *)bytes;
|
||||||
|
|
||||||
|
int retCode;
|
||||||
|
NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)];
|
||||||
|
unsigned char output[kChunkSize];
|
||||||
|
do {
|
||||||
|
stream.avail_out = kChunkSize;
|
||||||
|
stream.next_out = output;
|
||||||
|
retCode = deflate(&stream, Z_FINISH);
|
||||||
|
if (retCode != Z_OK && retCode != Z_STREAM_END) {
|
||||||
|
deflateEnd(&stream);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
unsigned size = kChunkSize - stream.avail_out;
|
||||||
|
if (size > 0) {
|
||||||
|
[result appendBytes:output length:size];
|
||||||
|
}
|
||||||
|
} while (retCode == Z_OK);
|
||||||
|
|
||||||
|
deflateEnd(&stream);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)anonymousID
|
||||||
|
{
|
||||||
|
// Grab previously written anonymous ID and, if none have been generated, create and
|
||||||
|
// persist a new one which will remain associated with this app.
|
||||||
|
NSString *result = [[self class] retrievePersistedAnonymousID];
|
||||||
|
if (!result) {
|
||||||
|
// Generate a new anonymous ID. Create as a UUID, but then prepend the fairly
|
||||||
|
// arbitrary 'XZ' to the front so it's easily distinguishable from IDFA's which
|
||||||
|
// will only contain hex.
|
||||||
|
result = [NSString stringWithFormat:@"XZ%@", [NSUUID UUID].UUIDString];
|
||||||
|
|
||||||
|
[self persistAnonymousID:result];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)retrievePersistedAnonymousID
|
||||||
|
{
|
||||||
|
NSString *file = [[self class] persistenceFilePath:FBSDK_BASICUTILITY_ANONYMOUSIDFILENAME];
|
||||||
|
NSString *content = [[NSString alloc] initWithContentsOfFile:file
|
||||||
|
encoding:NSASCIIStringEncoding
|
||||||
|
error:nil];
|
||||||
|
NSDictionary<NSString *, id> *results = [FBSDKBasicUtility objectForJSONString:content error:NULL];
|
||||||
|
return results[FBSDK_BASICUTILITY_ANONYMOUSID_KEY];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)persistenceFilePath:(NSString *)filename
|
||||||
|
{
|
||||||
|
NSSearchPathDirectory directory = NSLibraryDirectory;
|
||||||
|
NSArray<NSString *> *paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES);
|
||||||
|
NSString *docDirectory = paths[0];
|
||||||
|
return [docDirectory stringByAppendingPathComponent:filename];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)persistAnonymousID:(NSString *)anonymousID
|
||||||
|
{
|
||||||
|
NSDictionary<NSString *, NSString *> *data = @{ FBSDK_BASICUTILITY_ANONYMOUSID_KEY : anonymousID };
|
||||||
|
NSString *content = [self JSONStringForObject:data error:NULL invalidObjectHandler:NULL];
|
||||||
|
|
||||||
|
[content writeToFile:[[self class] persistenceFilePath:FBSDK_BASICUTILITY_ANONYMOUSIDFILENAME]
|
||||||
|
atomically:YES
|
||||||
|
encoding:NSASCIIStringEncoding
|
||||||
|
error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
37
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKTypeUtility.h
generated
Normal file
37
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKTypeUtility.h
generated
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 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_SWIFT_NAME(TypeUtility)
|
||||||
|
@interface FBSDKTypeUtility : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
+ (NSArray *)arrayValue:(id)object;
|
||||||
|
+ (BOOL)boolValue:(id)object;
|
||||||
|
+ (NSDictionary *)dictionaryValue:(id)object;
|
||||||
|
+ (NSInteger)integerValue:(id)object;
|
||||||
|
+ (id)objectValue:(id)object;
|
||||||
|
+ (NSString *)stringValue:(id)object;
|
||||||
|
+ (NSTimeInterval)timeIntervalValue:(id)object;
|
||||||
|
+ (NSUInteger)unsignedIntegerValue:(id)object;
|
||||||
|
+ (NSURL *)URLValue:(id)object;
|
||||||
|
|
||||||
|
@end
|
||||||
121
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKTypeUtility.m
generated
Normal file
121
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKTypeUtility.m
generated
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
// 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 "FBSDKTypeUtility.h"
|
||||||
|
|
||||||
|
@implementation FBSDKTypeUtility
|
||||||
|
|
||||||
|
#pragma mark - Class Methods
|
||||||
|
|
||||||
|
+ (NSArray *)arrayValue:(id)object
|
||||||
|
{
|
||||||
|
return (NSArray *)[self _objectValue:object ofClass:[NSArray class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)boolValue:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[NSNumber class]]) {
|
||||||
|
// @0 or @NO returns NO, otherwise YES
|
||||||
|
return ((NSNumber *)object).boolValue;
|
||||||
|
} else if ([object isKindOfClass:[NSString class]]) {
|
||||||
|
// Returns YES on encountering one of "Y", "y", "T", "t", or a digit 1-9, otherwise NO
|
||||||
|
return ((NSString *)object).boolValue;
|
||||||
|
} else {
|
||||||
|
return ([self objectValue:object] != nil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary *)dictionaryValue:(id)object
|
||||||
|
{
|
||||||
|
return (NSDictionary *)[self _objectValue:object ofClass:[NSDictionary class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSInteger)integerValue:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[NSNumber class]]) {
|
||||||
|
return ((NSNumber *)object).integerValue;
|
||||||
|
} else if ([object isKindOfClass:[NSString class]]) {
|
||||||
|
return ((NSString *)object).integerValue;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id)objectValue:(id)object
|
||||||
|
{
|
||||||
|
return ([object isKindOfClass:[NSNull class]] ? nil : object);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)stringValue:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[NSString class]]) {
|
||||||
|
return (NSString *)object;
|
||||||
|
} else if ([object isKindOfClass:[NSNumber class]]) {
|
||||||
|
return ((NSNumber *)object).stringValue;
|
||||||
|
} else if ([object isKindOfClass:[NSURL class]]) {
|
||||||
|
return ((NSURL *)object).absoluteString;
|
||||||
|
} else {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSTimeInterval)timeIntervalValue:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[NSNumber class]]) {
|
||||||
|
return ((NSNumber *)object).doubleValue;
|
||||||
|
} else if ([object isKindOfClass:[NSString class]]) {
|
||||||
|
return ((NSString *)object).doubleValue;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSUInteger)unsignedIntegerValue:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[NSNumber class]]) {
|
||||||
|
return ((NSNumber *)object).unsignedIntegerValue;
|
||||||
|
} else {
|
||||||
|
// there is no direct support for strings containing unsigned values > NSIntegerMax - not worth writing ourselves
|
||||||
|
// right now, so just cap unsigned values at NSIntegerMax until we have a need for larger
|
||||||
|
NSInteger integerValue = [self integerValue:object];
|
||||||
|
if (integerValue < 0) {
|
||||||
|
integerValue = 0;
|
||||||
|
}
|
||||||
|
return (NSUInteger)integerValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSURL *)URLValue:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[NSURL class]]) {
|
||||||
|
return (NSURL *)object;
|
||||||
|
} else if ([object isKindOfClass:[NSString class]]) {
|
||||||
|
return [NSURL URLWithString:(NSString *)object];
|
||||||
|
} else {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Helper Methods
|
||||||
|
|
||||||
|
+ (id)_objectValue:(id)object ofClass:(Class)expectedClass
|
||||||
|
{
|
||||||
|
return ([object isKindOfClass:expectedClass] ? object : nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
45
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKURLSession.h
generated
Normal file
45
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKURLSession.h
generated
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// 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 "FBSDKURLSessionTask.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface FBSDKURLSession : NSObject
|
||||||
|
|
||||||
|
@property (atomic, strong, nullable) NSURLSession *session;
|
||||||
|
@property (nonatomic, weak, nullable) id<NSURLSessionDataDelegate> delegate;
|
||||||
|
@property (nonatomic, retain, nullable) NSOperationQueue *delegateQueue;
|
||||||
|
|
||||||
|
- (instancetype)initWithDelegate:(id<NSURLSessionDataDelegate>)delegate
|
||||||
|
delegateQueue:(NSOperationQueue *)delegateQueue;
|
||||||
|
|
||||||
|
- (void)executeURLRequest:(NSURLRequest *)request
|
||||||
|
completionHandler:(FBSDKURLSessionTaskBlock)handler;
|
||||||
|
|
||||||
|
- (void)updateSessionWithBlock:(dispatch_block_t)block;
|
||||||
|
|
||||||
|
- (void)invalidateAndCancel;
|
||||||
|
|
||||||
|
- (BOOL)valid;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
71
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKURLSession.m
generated
Normal file
71
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKURLSession.m
generated
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// 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 "FBSDKURLSession.h"
|
||||||
|
|
||||||
|
#import "FBSDKBasicUtility.h"
|
||||||
|
#import "FBSDKURLSessionTask.h"
|
||||||
|
|
||||||
|
@implementation FBSDKURLSession
|
||||||
|
|
||||||
|
- (instancetype)initWithDelegate:(id<NSURLSessionDataDelegate>)delegate
|
||||||
|
delegateQueue:(NSOperationQueue *)queue
|
||||||
|
{
|
||||||
|
if ((self = [super init])) {
|
||||||
|
self.delegate = delegate;
|
||||||
|
self.delegateQueue = queue;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)executeURLRequest:(NSURLRequest *)request
|
||||||
|
completionHandler:(FBSDKURLSessionTaskBlock)handler
|
||||||
|
{
|
||||||
|
if (!self.valid) {
|
||||||
|
[self updateSessionWithBlock:^{
|
||||||
|
FBSDKURLSessionTask *task = [[FBSDKURLSessionTask alloc] initWithRequest:request fromSession:self.session completionHandler:handler];
|
||||||
|
[task start];
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
FBSDKURLSessionTask *task = [[FBSDKURLSessionTask alloc] initWithRequest:request fromSession:self.session completionHandler:handler];
|
||||||
|
[task start];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateSessionWithBlock:(dispatch_block_t)block
|
||||||
|
{
|
||||||
|
if (!self.valid) {
|
||||||
|
self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
|
||||||
|
delegate:_delegate
|
||||||
|
delegateQueue:_delegateQueue];
|
||||||
|
}
|
||||||
|
block();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)invalidateAndCancel
|
||||||
|
{
|
||||||
|
[self.session invalidateAndCancel];
|
||||||
|
self.session = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)valid
|
||||||
|
{
|
||||||
|
return self.session != nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
45
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKURLSessionTask.h
generated
Normal file
45
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKURLSessionTask.h
generated
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// 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 void (^FBSDKURLSessionTaskBlock)(NSData *responseData,
|
||||||
|
NSURLResponse *response,
|
||||||
|
NSError *error)
|
||||||
|
NS_SWIFT_NAME(URLSessionTaskBlock);
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(URLSessionTask)
|
||||||
|
@interface FBSDKURLSessionTask : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSURLSessionTask *task;
|
||||||
|
@property (atomic, readonly) NSURLSessionTaskState state;
|
||||||
|
@property (nonatomic, strong, readonly) NSDate *requestStartDate;
|
||||||
|
@property (nonatomic, copy) FBSDKURLSessionTaskBlock handler;
|
||||||
|
@property (nonatomic, assign) uint64_t requestStartTime;
|
||||||
|
@property (nonatomic, assign) NSUInteger loggerSerialNumber;
|
||||||
|
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
- (instancetype)initWithRequest:(NSURLRequest *)request
|
||||||
|
fromSession:(NSURLSession *)session
|
||||||
|
completionHandler:(FBSDKURLSessionTaskBlock)handler;
|
||||||
|
|
||||||
|
- (void)start;
|
||||||
|
- (void)cancel;
|
||||||
|
|
||||||
|
@end
|
||||||
60
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKURLSessionTask.m
generated
Normal file
60
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/Basics/Internal/FBSDKURLSessionTask.m
generated
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// 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 "FBSDKURLSessionTask.h"
|
||||||
|
|
||||||
|
@implementation FBSDKURLSessionTask
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_requestStartDate = [NSDate date];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithRequest:(NSURLRequest *)request
|
||||||
|
fromSession:(NSURLSession *)session
|
||||||
|
completionHandler:(FBSDKURLSessionTaskBlock)handler
|
||||||
|
{
|
||||||
|
if ((self = [self init])) {
|
||||||
|
self.requestStartTime = (uint64_t)([self.requestStartDate timeIntervalSince1970] * 1000);
|
||||||
|
self.task = [session dataTaskWithRequest:request completionHandler:handler];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURLSessionTaskState)state
|
||||||
|
{
|
||||||
|
return self.task.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Task State
|
||||||
|
|
||||||
|
- (void)start
|
||||||
|
{
|
||||||
|
[self.task resume];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cancel
|
||||||
|
{
|
||||||
|
[self.task cancel];
|
||||||
|
self.handler = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
274
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKAccessToken.h
generated
Normal file
274
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKAccessToken.h
generated
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
// 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 "FBSDKCopying.h"
|
||||||
|
|
||||||
|
#ifdef BUCK
|
||||||
|
#import <FBSDKCoreKit/FBSDKGraphRequestConnection.h>
|
||||||
|
#else
|
||||||
|
#import "FBSDKGraphRequestConnection.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification indicating that the `currentAccessToken` has changed.
|
||||||
|
|
||||||
|
the userInfo dictionary of the notification will contain keys
|
||||||
|
`FBSDKAccessTokenChangeOldKey` and
|
||||||
|
`FBSDKAccessTokenChangeNewKey`.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSNotificationName const FBSDKAccessTokenDidChangeNotification
|
||||||
|
NS_SWIFT_NAME(AccessTokenDidChange);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification indicating that the `currentAccessToken` has changed.
|
||||||
|
|
||||||
|
the userInfo dictionary of the notification will contain keys
|
||||||
|
`FBSDKAccessTokenChangeOldKey` and
|
||||||
|
`FBSDKAccessTokenChangeNewKey`.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAccessTokenDidChangeNotification
|
||||||
|
NS_SWIFT_NAME(AccessTokenDidChangeNotification);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
A key in the notification's userInfo that will be set
|
||||||
|
if and only if the user ID changed between the old and new tokens.
|
||||||
|
|
||||||
|
Token refreshes can occur automatically with the SDK
|
||||||
|
which do not change the user. If you're only interested in user
|
||||||
|
changes (such as logging out), you should check for the existence
|
||||||
|
of this key. The value is a NSNumber with a boolValue.
|
||||||
|
|
||||||
|
On a fresh start of the app where the SDK reads in the cached value
|
||||||
|
of an access token, this key will also exist since the access token
|
||||||
|
is moving from a null state (no user) to a non-null state (user).
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAccessTokenDidChangeUserIDKey
|
||||||
|
NS_SWIFT_NAME(AccessTokenDidChangeUserIDKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
key in notification's userInfo object for getting the old token.
|
||||||
|
|
||||||
|
If there was no old token, the key will not be present.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAccessTokenChangeOldKey
|
||||||
|
NS_SWIFT_NAME(AccessTokenChangeOldKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
key in notification's userInfo object for getting the new token.
|
||||||
|
|
||||||
|
If there is no new token, the key will not be present.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAccessTokenChangeNewKey
|
||||||
|
NS_SWIFT_NAME(AccessTokenChangeNewKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
A key in the notification's userInfo that will be set
|
||||||
|
if and only if the token has expired.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKAccessTokenDidExpireKey
|
||||||
|
NS_SWIFT_NAME(AccessTokenDidExpireKey);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Represents an immutable access token for using Facebook services.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(AccessToken)
|
||||||
|
@interface FBSDKAccessToken : NSObject<FBSDKCopying, NSSecureCoding>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The "global" access token that represents the currently logged in user.
|
||||||
|
|
||||||
|
The `currentAccessToken` is a convenient representation of the token of the
|
||||||
|
current user and is used by other SDK components (like `FBSDKLoginManager`).
|
||||||
|
*/
|
||||||
|
@property (class, nonatomic, copy, nullable) FBSDKAccessToken *currentAccessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns YES if currentAccessToken is not nil AND currentAccessToken is not expired
|
||||||
|
|
||||||
|
*/
|
||||||
|
@property (class, nonatomic, assign, readonly, getter=isCurrentAccessTokenActive) BOOL currentAccessTokenIsActive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the app ID.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSString *appID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the expiration date for data access
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSDate *dataAccessExpirationDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the known declined permissions.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSSet<NSString *> *declinedPermissions
|
||||||
|
NS_REFINED_FOR_SWIFT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the known declined permissions.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSSet<NSString *> *expiredPermissions
|
||||||
|
NS_REFINED_FOR_SWIFT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the expiration date.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSDate *expirationDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the known granted permissions.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSSet<NSString *> *permissions
|
||||||
|
NS_REFINED_FOR_SWIFT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the date the token was last refreshed.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSDate *refreshDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the opaque token string.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSString *tokenString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the user ID.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSString *userID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The graph domain where this access token is valid.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, readonly) NSString *graphDomain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
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)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 expiredPermissions the expired 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).
|
||||||
|
@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
|
||||||
|
manage tokens explicitly. Typical login flows only need to use `FBSDKLoginManager`
|
||||||
|
along with `+currentAccessToken`.
|
||||||
|
*/
|
||||||
|
- (instancetype)initWithTokenString:(NSString *)tokenString
|
||||||
|
permissions:(NSArray<NSString *> *)permissions
|
||||||
|
declinedPermissions:(NSArray<NSString *> *)declinedPermissions
|
||||||
|
expiredPermissions:(NSArray<NSString *> *)expiredPermissions
|
||||||
|
appID:(NSString *)appID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
expirationDate:(nullable NSDate *)expirationDate
|
||||||
|
refreshDate:(nullable NSDate *)refreshDate
|
||||||
|
dataAccessExpirationDate:(nullable NSDate *)dataAccessExpirationDate
|
||||||
|
NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convenience initializer.
|
||||||
|
@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 expiredPermissions the expired 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).
|
||||||
|
@param dataAccessExpirationDate the date which data access will expire for the given user
|
||||||
|
(defaults to distantFuture).
|
||||||
|
@param graphDomain the domain this access token can be used in.
|
||||||
|
|
||||||
|
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<NSString *> *)permissions
|
||||||
|
declinedPermissions:(NSArray<NSString *> *)declinedPermissions
|
||||||
|
expiredPermissions:(NSArray<NSString *> *)expiredPermissions
|
||||||
|
appID:(NSString *)appID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
expirationDate:(nullable NSDate *)expirationDate
|
||||||
|
refreshDate:(nullable NSDate *)refreshDate
|
||||||
|
dataAccessExpirationDate:(nullable NSDate *)dataAccessExpirationDate
|
||||||
|
graphDomain:(nullable NSString *)graphDomain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convenience getter to determine if a permission has been granted
|
||||||
|
@param permission The permission to check.
|
||||||
|
*/
|
||||||
|
- (BOOL)hasGranted:(NSString *)permission
|
||||||
|
NS_SWIFT_NAME(hasGranted(permission:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
Compares the receiver to another FBSDKAccessToken
|
||||||
|
@param token The other token
|
||||||
|
@return YES if the receiver's values are equal to the other token's values; otherwise NO
|
||||||
|
*/
|
||||||
|
- (BOOL)isEqualToAccessToken:(FBSDKAccessToken *)token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Refresh the current access token's permission state and extend the token's expiration date,
|
||||||
|
if possible.
|
||||||
|
@param 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
|
||||||
|
observe the `FBSDKAccessTokenDidChangeNotification` notification.
|
||||||
|
|
||||||
|
If a token is already expired, it cannot be refreshed.
|
||||||
|
*/
|
||||||
|
+ (void)refreshCurrentAccessToken:(nullable FBSDKGraphRequestBlock)completionHandler;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
277
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKAccessToken.m
generated
Normal file
277
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKAccessToken.m
generated
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
// 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 "FBSDKAccessToken.h"
|
||||||
|
|
||||||
|
#import "FBSDKGraphRequestPiggybackManager.h"
|
||||||
|
#import "FBSDKInternalUtility.h"
|
||||||
|
#import "FBSDKMath.h"
|
||||||
|
#import "FBSDKSettings+Internal.h"
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||||
|
|
||||||
|
NSNotificationName const FBSDKAccessTokenDidChangeNotification = @"com.facebook.sdk.FBSDKAccessTokenData.FBSDKAccessTokenDidChangeNotification";
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
NSString *const FBSDKAccessTokenDidChangeNotification = @"com.facebook.sdk.FBSDKAccessTokenData.FBSDKAccessTokenDidChangeNotification";
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NSString *const FBSDKAccessTokenDidChangeUserIDKey = @"FBSDKAccessTokenDidChangeUserIDKey";
|
||||||
|
NSString *const FBSDKAccessTokenChangeNewKey = @"FBSDKAccessToken";
|
||||||
|
NSString *const FBSDKAccessTokenChangeOldKey = @"FBSDKAccessTokenOld";
|
||||||
|
NSString *const FBSDKAccessTokenDidExpireKey = @"FBSDKAccessTokenDidExpireKey";
|
||||||
|
|
||||||
|
static FBSDKAccessToken *g_currentAccessToken;
|
||||||
|
|
||||||
|
#define FBSDK_ACCESSTOKEN_TOKENSTRING_KEY @"tokenString"
|
||||||
|
#define FBSDK_ACCESSTOKEN_PERMISSIONS_KEY @"permissions"
|
||||||
|
#define FBSDK_ACCESSTOKEN_DECLINEDPERMISSIONS_KEY @"declinedPermissions"
|
||||||
|
#define FBSDK_ACCESSTOKEN_EXPIREDPERMISSIONS_KEY @"expiredPermissions"
|
||||||
|
#define FBSDK_ACCESSTOKEN_APPID_KEY @"appID"
|
||||||
|
#define FBSDK_ACCESSTOKEN_USERID_KEY @"userID"
|
||||||
|
#define FBSDK_ACCESSTOKEN_REFRESHDATE_KEY @"refreshDate"
|
||||||
|
#define FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY @"expirationDate"
|
||||||
|
#define FBSDK_ACCESSTOKEN_DATA_EXPIRATIONDATE_KEY @"dataAccessExpirationDate"
|
||||||
|
#define FBSDK_ACCESSTOKEN_GRAPH_DOMAIN_KEY @"graphDomain"
|
||||||
|
|
||||||
|
@implementation FBSDKAccessToken
|
||||||
|
|
||||||
|
- (instancetype)initWithTokenString:(NSString *)tokenString
|
||||||
|
permissions:(NSArray *)permissions
|
||||||
|
declinedPermissions:(NSArray *)declinedPermissions
|
||||||
|
expiredPermissions:(NSArray *)expiredPermissions
|
||||||
|
appID:(NSString *)appID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
expirationDate:(NSDate *)expirationDate
|
||||||
|
refreshDate:(NSDate *)refreshDate
|
||||||
|
dataAccessExpirationDate:(NSDate *)dataAccessExpirationDate
|
||||||
|
{
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_tokenString = [tokenString copy];
|
||||||
|
_permissions = [NSSet setWithArray:permissions];
|
||||||
|
_declinedPermissions = [NSSet setWithArray:declinedPermissions];
|
||||||
|
_expiredPermissions = [NSSet setWithArray:expiredPermissions];
|
||||||
|
_appID = [appID copy];
|
||||||
|
_userID = [userID copy];
|
||||||
|
_expirationDate = [expirationDate copy] ?: [NSDate distantFuture];
|
||||||
|
_refreshDate = [refreshDate copy] ?: [NSDate date];
|
||||||
|
_dataAccessExpirationDate = [dataAccessExpirationDate copy] ?: [NSDate distantFuture];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithTokenString:(NSString *)tokenString
|
||||||
|
permissions:(NSArray<NSString *> *)permissions
|
||||||
|
declinedPermissions:(NSArray<NSString *> *)declinedPermissions
|
||||||
|
expiredPermissions:(NSArray<NSString *> *)expiredPermissions
|
||||||
|
appID:(NSString *)appID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
expirationDate:(NSDate *)expirationDate
|
||||||
|
refreshDate:(NSDate *)refreshDate
|
||||||
|
dataAccessExpirationDate:(NSDate *)dataAccessExpirationDate
|
||||||
|
graphDomain:(NSString *)graphDomain
|
||||||
|
{
|
||||||
|
FBSDKAccessToken *accessToken =
|
||||||
|
[self
|
||||||
|
initWithTokenString:tokenString
|
||||||
|
permissions:permissions
|
||||||
|
declinedPermissions:declinedPermissions
|
||||||
|
expiredPermissions:expiredPermissions
|
||||||
|
appID:appID
|
||||||
|
userID:userID
|
||||||
|
expirationDate:expirationDate
|
||||||
|
refreshDate:refreshDate
|
||||||
|
dataAccessExpirationDate:dataAccessExpirationDate];
|
||||||
|
|
||||||
|
if (accessToken != nil) {
|
||||||
|
accessToken->_graphDomain = [graphDomain copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasGranted:(NSString *)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
|
||||||
|
{
|
||||||
|
return g_currentAccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setCurrentAccessToken:(FBSDKAccessToken *)token
|
||||||
|
{
|
||||||
|
if (token != g_currentAccessToken) {
|
||||||
|
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
||||||
|
[FBSDKBasicUtility dictionary:userInfo setObject:token forKey:FBSDKAccessTokenChangeNewKey];
|
||||||
|
[FBSDKBasicUtility 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] || !self.isCurrentAccessTokenActive) {
|
||||||
|
userInfo[FBSDKAccessTokenDidChangeUserIDKey] = @YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_currentAccessToken = token;
|
||||||
|
|
||||||
|
// Only need to keep current session in web view for the case when token is current
|
||||||
|
// When token is abandoned cookies must to be cleaned up immediately
|
||||||
|
if (token == nil) {
|
||||||
|
[FBSDKInternalUtility deleteFacebookCookies];
|
||||||
|
}
|
||||||
|
|
||||||
|
[FBSDKSettings accessTokenCache].accessToken = token;
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:FBSDKAccessTokenDidChangeNotification
|
||||||
|
object:[self class]
|
||||||
|
userInfo:userInfo];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isCurrentAccessTokenActive
|
||||||
|
{
|
||||||
|
FBSDKAccessToken *currentAccessToken = [self currentAccessToken];
|
||||||
|
return currentAccessToken != nil && !currentAccessToken.isExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)refreshCurrentAccessToken:(FBSDKGraphRequestBlock)completionHandler
|
||||||
|
{
|
||||||
|
if ([FBSDKAccessToken currentAccessToken]) {
|
||||||
|
FBSDKGraphRequestConnection *connection = [[FBSDKGraphRequestConnection alloc] init];
|
||||||
|
[FBSDKGraphRequestPiggybackManager addRefreshPiggyback:connection permissionHandler:completionHandler];
|
||||||
|
[connection start];
|
||||||
|
} else if (completionHandler) {
|
||||||
|
completionHandler(nil, nil, [FBSDKError
|
||||||
|
errorWithCode:FBSDKErrorAccessTokenRequired
|
||||||
|
message:@"No current access token to refresh"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Equality
|
||||||
|
|
||||||
|
- (NSUInteger)hash
|
||||||
|
{
|
||||||
|
NSUInteger subhashes[] = {
|
||||||
|
self.tokenString.hash,
|
||||||
|
self.permissions.hash,
|
||||||
|
self.declinedPermissions.hash,
|
||||||
|
self.expiredPermissions.hash,
|
||||||
|
self.appID.hash,
|
||||||
|
self.userID.hash,
|
||||||
|
self.refreshDate.hash,
|
||||||
|
self.expirationDate.hash,
|
||||||
|
self.dataAccessExpirationDate.hash,
|
||||||
|
self.graphDomain.hash
|
||||||
|
};
|
||||||
|
return [FBSDKMath hashWithIntegerArray:subhashes count:sizeof(subhashes) / sizeof(subhashes[0])];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqual:(id)object
|
||||||
|
{
|
||||||
|
if (self == object) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
if (![object isKindOfClass:[FBSDKAccessToken class]]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return [self isEqualToAccessToken:(FBSDKAccessToken *)object];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqualToAccessToken:(FBSDKAccessToken *)token
|
||||||
|
{
|
||||||
|
return (token &&
|
||||||
|
[FBSDKInternalUtility object:self.tokenString isEqualToObject:token.tokenString] &&
|
||||||
|
[FBSDKInternalUtility object:self.permissions isEqualToObject:token.permissions] &&
|
||||||
|
[FBSDKInternalUtility object:self.declinedPermissions isEqualToObject:token.declinedPermissions] &&
|
||||||
|
[FBSDKInternalUtility object:self.expiredPermissions isEqualToObject:token.expiredPermissions] &&
|
||||||
|
[FBSDKInternalUtility object:self.appID isEqualToObject:token.appID] &&
|
||||||
|
[FBSDKInternalUtility object:self.userID isEqualToObject:token.userID] &&
|
||||||
|
[FBSDKInternalUtility object:self.refreshDate isEqualToObject:token.refreshDate] &&
|
||||||
|
[FBSDKInternalUtility object:self.expirationDate isEqualToObject:token.expirationDate] &&
|
||||||
|
[FBSDKInternalUtility object:self.dataAccessExpirationDate isEqualToObject:token.dataAccessExpirationDate] &&
|
||||||
|
[FBSDKInternalUtility object:self.graphDomain isEqualToObject:token.graphDomain]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSCopying
|
||||||
|
|
||||||
|
- (id)copyWithZone:(NSZone *)zone
|
||||||
|
{
|
||||||
|
// we're immutable.
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark NSCoding
|
||||||
|
|
||||||
|
+ (BOOL)supportsSecureCoding
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||||
|
{
|
||||||
|
NSString *appID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_ACCESSTOKEN_APPID_KEY];
|
||||||
|
NSSet *declinedPermissions = [decoder decodeObjectOfClass:[NSSet class] forKey:FBSDK_ACCESSTOKEN_DECLINEDPERMISSIONS_KEY];
|
||||||
|
NSSet *expiredPermissions = [decoder decodeObjectOfClass:[NSSet class] forKey:FBSDK_ACCESSTOKEN_EXPIREDPERMISSIONS_KEY];
|
||||||
|
NSSet *permissions = [decoder decodeObjectOfClass:[NSSet class] forKey:FBSDK_ACCESSTOKEN_PERMISSIONS_KEY];
|
||||||
|
NSString *tokenString = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_ACCESSTOKEN_TOKENSTRING_KEY];
|
||||||
|
NSString *userID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_ACCESSTOKEN_USERID_KEY];
|
||||||
|
NSDate *refreshDate = [decoder decodeObjectOfClass:[NSDate class] forKey:FBSDK_ACCESSTOKEN_REFRESHDATE_KEY];
|
||||||
|
NSDate *expirationDate = [decoder decodeObjectOfClass:[NSDate class] forKey:FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY];
|
||||||
|
NSDate *dataAccessExpirationDate = [decoder decodeObjectOfClass:[NSDate class] forKey:FBSDK_ACCESSTOKEN_DATA_EXPIRATIONDATE_KEY];
|
||||||
|
NSString *graphDomain = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_ACCESSTOKEN_GRAPH_DOMAIN_KEY];
|
||||||
|
|
||||||
|
return
|
||||||
|
[self
|
||||||
|
initWithTokenString:tokenString
|
||||||
|
permissions:permissions.allObjects
|
||||||
|
declinedPermissions:declinedPermissions.allObjects
|
||||||
|
expiredPermissions:expiredPermissions.allObjects
|
||||||
|
appID:appID
|
||||||
|
userID:userID
|
||||||
|
expirationDate:expirationDate
|
||||||
|
refreshDate:refreshDate
|
||||||
|
dataAccessExpirationDate:dataAccessExpirationDate
|
||||||
|
graphDomain:graphDomain];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||||
|
{
|
||||||
|
[encoder encodeObject:self.appID forKey:FBSDK_ACCESSTOKEN_APPID_KEY];
|
||||||
|
[encoder encodeObject:self.declinedPermissions forKey:FBSDK_ACCESSTOKEN_DECLINEDPERMISSIONS_KEY];
|
||||||
|
[encoder encodeObject:self.expiredPermissions forKey:FBSDK_ACCESSTOKEN_EXPIREDPERMISSIONS_KEY];
|
||||||
|
[encoder encodeObject:self.permissions forKey:FBSDK_ACCESSTOKEN_PERMISSIONS_KEY];
|
||||||
|
[encoder encodeObject:self.tokenString forKey:FBSDK_ACCESSTOKEN_TOKENSTRING_KEY];
|
||||||
|
[encoder encodeObject:self.userID forKey:FBSDK_ACCESSTOKEN_USERID_KEY];
|
||||||
|
[encoder encodeObject:self.expirationDate forKey:FBSDK_ACCESSTOKEN_EXPIRATIONDATE_KEY];
|
||||||
|
[encoder encodeObject:self.refreshDate forKey:FBSDK_ACCESSTOKEN_REFRESHDATE_KEY];
|
||||||
|
[encoder encodeObject:self.dataAccessExpirationDate forKey:FBSDK_ACCESSTOKEN_DATA_EXPIRATIONDATE_KEY];
|
||||||
|
[encoder encodeObject:self.graphDomain forKey:FBSDK_ACCESSTOKEN_GRAPH_DOMAIN_KEY];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
112
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKApplicationDelegate.h
generated
Normal file
112
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKApplicationDelegate.h
generated
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// 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 <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
The FBSDKApplicationDelegate is designed to post process the results from Facebook Login
|
||||||
|
or Facebook Dialogs (or any action that requires switching over to the native Facebook
|
||||||
|
app or Safari).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The methods in this class are designed to mirror those in UIApplicationDelegate, and you
|
||||||
|
should call them in the respective methods in your AppDelegate implementation.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(ApplicationDelegate)
|
||||||
|
@interface FBSDKApplicationDelegate : NSObject
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
+ (instancetype)new NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gets the singleton instance.
|
||||||
|
*/
|
||||||
|
@property (class, nonatomic, readonly, strong) FBSDKApplicationDelegate *sharedInstance
|
||||||
|
NS_SWIFT_NAME(shared);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call this method from the [UIApplicationDelegate application:openURL:sourceApplication:annotation:] method
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param application The application as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:].
|
||||||
|
|
||||||
|
@param url The URL as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:].
|
||||||
|
|
||||||
|
@param sourceApplication The sourceApplication as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:].
|
||||||
|
|
||||||
|
@param 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.
|
||||||
|
*/
|
||||||
|
- (BOOL)application:(UIApplication *)application
|
||||||
|
openURL:(NSURL *)url
|
||||||
|
sourceApplication:(nullable NSString *)sourceApplication
|
||||||
|
annotation:(nullable id)annotation;
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_9_0
|
||||||
|
/**
|
||||||
|
Call this method from the [UIApplicationDelegate application:openURL:options:] method
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param application The application as passed to [UIApplicationDelegate application:openURL:options:].
|
||||||
|
|
||||||
|
@param url The URL as passed to [UIApplicationDelegate application:openURL:options:].
|
||||||
|
|
||||||
|
@param 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.
|
||||||
|
*/
|
||||||
|
- (BOOL)application:(UIApplication *)application
|
||||||
|
openURL:(NSURL *)url
|
||||||
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call this method from the [UIApplicationDelegate application:didFinishLaunchingWithOptions:] method
|
||||||
|
of the AppDelegate for your app. It should be invoked for the proper use of the Facebook SDK.
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param application The application as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
|
||||||
|
|
||||||
|
@param launchOptions The launchOptions as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
|
||||||
|
|
||||||
|
@return YES if the url was intended for the Facebook SDK, NO if not.
|
||||||
|
*/
|
||||||
|
- (BOOL)application:(UIApplication *)application
|
||||||
|
didFinishLaunchingWithOptions:(nullable NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call this method to manually initialize SDK.
|
||||||
|
As we initialize SDK automatically, this should only be called when auto initialization is disabled, this can be
|
||||||
|
controlled via 'FacebookAutoInitEnabled' key in the project info plist file.
|
||||||
|
|
||||||
|
@param launchOptions The launchOptions as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
|
||||||
|
Could be nil if you don't call this function from [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
|
||||||
|
*/
|
||||||
|
+ (void)initializeSDK:(nullable NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
428
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKApplicationDelegate.m
generated
Normal file
428
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKApplicationDelegate.m
generated
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
// 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 "FBSDKApplicationDelegate.h"
|
||||||
|
#import "FBSDKApplicationDelegate+Internal.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
#import "FBSDKAppEvents+Internal.h"
|
||||||
|
#import "FBSDKConstants.h"
|
||||||
|
#import "FBSDKDynamicFrameworkLoader.h"
|
||||||
|
#import "FBSDKError.h"
|
||||||
|
#import "FBSDKEventDeactivationManager.h"
|
||||||
|
#import "FBSDKFeatureManager.h"
|
||||||
|
#import "FBSDKGateKeeperManager.h"
|
||||||
|
#import "FBSDKInstrumentManager.h"
|
||||||
|
#import "FBSDKInternalUtility.h"
|
||||||
|
#import "FBSDKLogger.h"
|
||||||
|
#import "FBSDKServerConfiguration.h"
|
||||||
|
#import "FBSDKServerConfigurationManager.h"
|
||||||
|
#import "FBSDKSettings+Internal.h"
|
||||||
|
#import "FBSDKTimeSpentData.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#import "FBSDKMeasurementEventListener.h"
|
||||||
|
#import "FBSDKContainerViewController.h"
|
||||||
|
#import "FBSDKProfile+Internal.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||||
|
|
||||||
|
NSNotificationName const FBSDKApplicationDidBecomeActiveNotification = @"com.facebook.sdk.FBSDKApplicationDidBecomeActiveNotification";
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
NSString *const FBSDKApplicationDidBecomeActiveNotification = @"com.facebook.sdk.FBSDKApplicationDidBecomeActiveNotification";
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static NSString *const FBSDKAppLinkInboundEvent = @"fb_al_inbound";
|
||||||
|
static NSString *const FBSDKKitsBitmaskKey = @"com.facebook.sdk.kits.bitmask";
|
||||||
|
static BOOL g_isSDKInitialized = NO;
|
||||||
|
static UIApplicationState _applicationState;
|
||||||
|
|
||||||
|
@implementation FBSDKApplicationDelegate
|
||||||
|
{
|
||||||
|
NSHashTable<id<FBSDKApplicationObserving>> *_applicationObservers;
|
||||||
|
BOOL _isAppLaunched;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Class Methods
|
||||||
|
|
||||||
|
+ (void)load
|
||||||
|
{
|
||||||
|
if ([FBSDKSettings isAutoInitEnabled]) {
|
||||||
|
// when the app becomes active by any means, kick off the initialization.
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(initializeWithLaunchData:)
|
||||||
|
name:UIApplicationDidFinishLaunchingNotification
|
||||||
|
object:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize SDK listeners
|
||||||
|
// Don't call this function in any place else. It should only be called when the class is loaded.
|
||||||
|
+ (void)initializeWithLaunchData:(NSNotification *)note
|
||||||
|
{
|
||||||
|
[self initializeSDK:note.userInfo];
|
||||||
|
// Remove the observer
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||||
|
name:UIApplicationDidFinishLaunchingNotification
|
||||||
|
object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)initializeSDK:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions
|
||||||
|
{
|
||||||
|
if (g_isSDKInitialized) {
|
||||||
|
// Do nothing if initialized already
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_isSDKInitialized = YES;
|
||||||
|
|
||||||
|
FBSDKApplicationDelegate *delegate = [self sharedInstance];
|
||||||
|
|
||||||
|
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
|
||||||
|
[defaultCenter addObserver:delegate selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
|
||||||
|
[defaultCenter addObserver:delegate selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||||
|
|
||||||
|
[[FBSDKAppEvents singleton] registerNotifications];
|
||||||
|
|
||||||
|
[delegate application:[UIApplication sharedApplication] didFinishLaunchingWithOptions:launchOptions];
|
||||||
|
|
||||||
|
[FBSDKFeatureManager checkFeature:FBSDKFeatureInstrument completionBlock:^(BOOL enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
[FBSDKInstrumentManager enable];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
[FBSDKFeatureManager checkFeature:FBSDKFeatureRestrictiveDataFiltering completionBlock:^(BOOL enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
[FBSDKRestrictiveDataFilterManager enable];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
[FBSDKFeatureManager checkFeature:FBSDKFeatureEventDeactivation completionBlock:^(BOOL enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
[FBSDKEventDeactivationManager enable];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
// Register Listener for App Link measurement events
|
||||||
|
[FBSDKMeasurementEventListener defaultListener];
|
||||||
|
[delegate _logIfAutoAppLinkEnabled];
|
||||||
|
#endif
|
||||||
|
// Set the SourceApplication for time spent data. This is not going to update the value if the app has already launched.
|
||||||
|
[FBSDKTimeSpentData setSourceApplication:launchOptions[UIApplicationLaunchOptionsSourceApplicationKey]
|
||||||
|
openURL:launchOptions[UIApplicationLaunchOptionsURLKey]];
|
||||||
|
// Register on UIApplicationDidEnterBackgroundNotification events to reset source application data when app backgrounds.
|
||||||
|
[FBSDKTimeSpentData registerAutoResetSourceApplication];
|
||||||
|
|
||||||
|
[FBSDKInternalUtility validateFacebookReservedURLSchemes];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (FBSDKApplicationDelegate *)sharedInstance
|
||||||
|
{
|
||||||
|
static FBSDKApplicationDelegate *_sharedInstance;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
_sharedInstance = [[self alloc] init];
|
||||||
|
});
|
||||||
|
return _sharedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Object Lifecycle
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if ((self = [super init]) != nil) {
|
||||||
|
_applicationObservers = [[NSHashTable alloc] init];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - UIApplicationDelegate
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_9_0
|
||||||
|
- (BOOL)application:(UIApplication *)application
|
||||||
|
openURL:(NSURL *)url
|
||||||
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
|
||||||
|
{
|
||||||
|
if (@available(iOS 9.0, *)) {
|
||||||
|
return [self application:application
|
||||||
|
openURL:url
|
||||||
|
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
|
||||||
|
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- (BOOL)application:(UIApplication *)application
|
||||||
|
openURL:(NSURL *)url
|
||||||
|
sourceApplication:(NSString *)sourceApplication
|
||||||
|
annotation:(id)annotation
|
||||||
|
{
|
||||||
|
if (sourceApplication != nil && ![sourceApplication isKindOfClass:[NSString class]]) {
|
||||||
|
@throw [NSException exceptionWithName:NSInvalidArgumentException
|
||||||
|
reason:@"Expected 'sourceApplication' to be NSString. Please verify you are passing in 'sourceApplication' from your app delegate (not the UIApplication* parameter). If your app delegate implements iOS 9's application:openURL:options:, you should pass in options[UIApplicationOpenURLOptionsSourceApplicationKey]. "
|
||||||
|
userInfo:nil];
|
||||||
|
}
|
||||||
|
[FBSDKTimeSpentData setSourceApplication:sourceApplication openURL:url];
|
||||||
|
|
||||||
|
BOOL handled = NO;
|
||||||
|
NSArray<id<FBSDKApplicationObserving>> *observers = [_applicationObservers allObjects];
|
||||||
|
for (id<FBSDKApplicationObserving> observer in observers) {
|
||||||
|
if ([observer respondsToSelector:@selector(application:openURL:sourceApplication:annotation:)]) {
|
||||||
|
if ([observer application:application
|
||||||
|
openURL:url
|
||||||
|
sourceApplication:sourceApplication
|
||||||
|
annotation:annotation]) {
|
||||||
|
handled = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self _logIfAppLinkEvent:url];
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||||
|
{
|
||||||
|
if ([self isAppLaunched]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isAppLaunched = YES;
|
||||||
|
FBSDKAccessToken *cachedToken = [FBSDKSettings accessTokenCache].accessToken;
|
||||||
|
[FBSDKAccessToken setCurrentAccessToken:cachedToken];
|
||||||
|
// fetch app settings
|
||||||
|
[FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:NULL];
|
||||||
|
|
||||||
|
if (FBSDKSettings.isAutoLogAppEventsEnabled) {
|
||||||
|
[self _logSDKInitialize];
|
||||||
|
}
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
FBSDKProfile *cachedProfile = [FBSDKProfile fetchCachedProfile];
|
||||||
|
[FBSDKProfile setCurrentProfile:cachedProfile];
|
||||||
|
#endif
|
||||||
|
NSArray<id<FBSDKApplicationObserving>> *observers = [_applicationObservers allObjects];
|
||||||
|
BOOL handled = NO;
|
||||||
|
for (id<FBSDKApplicationObserving> observer in observers) {
|
||||||
|
if ([observer respondsToSelector:@selector(application:didFinishLaunchingWithOptions:)]) {
|
||||||
|
if ([observer application:application didFinishLaunchingWithOptions:launchOptions]) {
|
||||||
|
handled = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidEnterBackground:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
_applicationState = UIApplicationStateBackground;
|
||||||
|
NSArray<id<FBSDKApplicationObserving>> *observers = [_applicationObservers allObjects];
|
||||||
|
for (id<FBSDKApplicationObserving> observer in observers) {
|
||||||
|
if ([observer respondsToSelector:@selector(applicationDidEnterBackground:)]) {
|
||||||
|
[observer applicationDidEnterBackground:notification.object];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidBecomeActive:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
_applicationState = UIApplicationStateActive;
|
||||||
|
// Auto log basic events in case autoLogAppEventsEnabled is set
|
||||||
|
if (FBSDKSettings.isAutoLogAppEventsEnabled) {
|
||||||
|
[FBSDKAppEvents activateApp];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSArray<id<FBSDKApplicationObserving>> *observers = [_applicationObservers copy];
|
||||||
|
for (id<FBSDKApplicationObserving> observer in observers) {
|
||||||
|
if ([observer respondsToSelector:@selector(applicationDidBecomeActive:)]) {
|
||||||
|
[observer applicationDidBecomeActive:notification.object];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Internal Methods
|
||||||
|
|
||||||
|
#pragma mark - FBSDKApplicationObserving
|
||||||
|
|
||||||
|
- (void)addObserver:(id<FBSDKApplicationObserving>)observer
|
||||||
|
{
|
||||||
|
if (![_applicationObservers containsObject:observer]) {
|
||||||
|
[_applicationObservers addObject:observer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeObserver:(id<FBSDKApplicationObserving>)observer
|
||||||
|
{
|
||||||
|
if ([_applicationObservers containsObject:observer]) {
|
||||||
|
[_applicationObservers removeObject:observer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (UIApplicationState)applicationState
|
||||||
|
{
|
||||||
|
return _applicationState;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Helper Methods
|
||||||
|
|
||||||
|
- (void)_logIfAppLinkEvent:(NSURL *)url
|
||||||
|
{
|
||||||
|
if (!url) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSDictionary<NSString *, NSString *> *params = [FBSDKBasicUtility dictionaryWithQueryString:url.query];
|
||||||
|
NSString *applinkDataString = params[@"al_applink_data"];
|
||||||
|
if (!applinkDataString) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDictionary<id, id> *applinkData = [FBSDKBasicUtility objectForJSONString:applinkDataString error:NULL];
|
||||||
|
if (!applinkData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *targetURLString = applinkData[@"target_url"];
|
||||||
|
NSURL *targetURL = [targetURLString isKindOfClass:[NSString class]] ? [NSURL URLWithString:targetURLString] : nil;
|
||||||
|
|
||||||
|
NSMutableDictionary *logData = [[NSMutableDictionary alloc] init];
|
||||||
|
[FBSDKBasicUtility dictionary:logData setObject:targetURL.absoluteString forKey:@"targetURL"];
|
||||||
|
[FBSDKBasicUtility dictionary:logData setObject:targetURL.host forKey:@"targetURLHost"];
|
||||||
|
|
||||||
|
NSDictionary *refererData = applinkData[@"referer_data"];
|
||||||
|
if (refererData) {
|
||||||
|
[FBSDKBasicUtility dictionary:logData setObject:refererData[@"target_url"] forKey:@"referralTargetURL"];
|
||||||
|
[FBSDKBasicUtility dictionary:logData setObject:refererData[@"url"] forKey:@"referralURL"];
|
||||||
|
[FBSDKBasicUtility dictionary:logData setObject:refererData[@"app_name"] forKey:@"referralAppName"];
|
||||||
|
}
|
||||||
|
[FBSDKBasicUtility dictionary:logData setObject:url.absoluteString forKey:@"inputURL"];
|
||||||
|
[FBSDKBasicUtility dictionary:logData setObject:url.scheme forKey:@"inputURLScheme"];
|
||||||
|
|
||||||
|
[FBSDKAppEvents logInternalEvent:FBSDKAppLinkInboundEvent
|
||||||
|
parameters:logData
|
||||||
|
isImplicitlyLogged:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_logSDKInitialize
|
||||||
|
{
|
||||||
|
NSDictionary *metaInfo = [NSDictionary dictionaryWithObjects:@[@"login_lib_included",
|
||||||
|
@"marketing_lib_included",
|
||||||
|
@"messenger_lib_included",
|
||||||
|
@"places_lib_included",
|
||||||
|
@"share_lib_included",
|
||||||
|
@"tv_lib_included"]
|
||||||
|
forKeys:@[@"FBSDKLoginManager",
|
||||||
|
@"FBSDKAutoLog",
|
||||||
|
@"FBSDKMessengerButton",
|
||||||
|
@"FBSDKPlacesManager",
|
||||||
|
@"FBSDKShareDialog",
|
||||||
|
@"FBSDKTVInterfaceFactory"]];
|
||||||
|
|
||||||
|
NSInteger bitmask = 0;
|
||||||
|
NSInteger bit = 0;
|
||||||
|
NSMutableDictionary<NSString *, NSNumber *> *params = NSMutableDictionary.new;
|
||||||
|
params[@"core_lib_included"] = @1;
|
||||||
|
for (NSString *className in metaInfo.allKeys) {
|
||||||
|
NSString *keyName = [metaInfo objectForKey:className];
|
||||||
|
if (objc_lookUpClass([className UTF8String])) {
|
||||||
|
params[keyName] = @1;
|
||||||
|
bitmask |= 1 << bit;
|
||||||
|
}
|
||||||
|
bit++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tracking if the consuming Application is using Swift
|
||||||
|
id delegate = [UIApplication sharedApplication].delegate;
|
||||||
|
NSString const *className = NSStringFromClass([delegate class]);
|
||||||
|
if ([className componentsSeparatedByString:@"."].count > 1) {
|
||||||
|
params[@"is_using_swift"] = @YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
void (^checkViewForSwift)(void) = ^void ()
|
||||||
|
{
|
||||||
|
// Additional check to see if the consuming application perhaps was
|
||||||
|
// originally an objc project but is now using Swift
|
||||||
|
UIViewController *topMostViewController = [FBSDKInternalUtility topMostViewController];
|
||||||
|
NSString const *vcClassName = NSStringFromClass([topMostViewController class]);
|
||||||
|
if ([vcClassName componentsSeparatedByString:@"."].count > 1) {
|
||||||
|
params[@"is_using_swift"] = @YES;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
checkViewForSwift();
|
||||||
|
} else {
|
||||||
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||||
|
checkViewForSwift();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
NSInteger existingBitmask = [[NSUserDefaults standardUserDefaults] integerForKey:FBSDKKitsBitmaskKey];
|
||||||
|
if (existingBitmask != bitmask) {
|
||||||
|
[[NSUserDefaults standardUserDefaults] setInteger:bitmask forKey:FBSDKKitsBitmaskKey];
|
||||||
|
[FBSDKAppEvents logInternalEvent:@"fb_sdk_initialize"
|
||||||
|
parameters:params
|
||||||
|
isImplicitlyLogged:NO];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_logIfAutoAppLinkEnabled
|
||||||
|
{
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
NSNumber *enabled = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FBSDKAutoAppLinkEnabled"];
|
||||||
|
if (enabled.boolValue) {
|
||||||
|
NSMutableDictionary<NSString *, NSString *> *params = [[NSMutableDictionary alloc] init];
|
||||||
|
if (![FBSDKAppLinkUtility isMatchURLScheme:[NSString stringWithFormat:@"fb%@", [FBSDKSettings appID]]]) {
|
||||||
|
NSString *warning = @"You haven't set the Auto App Link URL scheme: fb<YOUR APP ID>";
|
||||||
|
params[@"SchemeWarning"] = warning;
|
||||||
|
NSLog(@"%@", warning);
|
||||||
|
}
|
||||||
|
[FBSDKAppEvents logInternalEvent:@"fb_auto_applink" parameters:params isImplicitlyLogged:YES];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isSDKInitialized
|
||||||
|
{
|
||||||
|
return [FBSDKSettings isAutoInitEnabled] || g_isSDKInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapping this makes it mockable and enables testability
|
||||||
|
- (BOOL)isAppLaunched {
|
||||||
|
return _isAppLaunched;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
31
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKButton.h
generated
Normal file
31
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKButton.h
generated
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 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 <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/**
|
||||||
|
A base class for common SDK buttons.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(FBButton)
|
||||||
|
@interface FBSDKButton : UIButton
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
465
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKButton.m
generated
Normal file
465
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKButton.m
generated
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
// 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 "FBSDKButton.h"
|
||||||
|
#import "FBSDKButton+Subclass.h"
|
||||||
|
|
||||||
|
#import "FBSDKAccessToken.h"
|
||||||
|
#import "FBSDKAppEvents+Internal.h"
|
||||||
|
#import "FBSDKAppEvents.h"
|
||||||
|
#import "FBSDKApplicationDelegate+Internal.h"
|
||||||
|
#import "FBSDKLogo.h"
|
||||||
|
#import "FBSDKUIUtility.h"
|
||||||
|
#import "FBSDKViewImpressionTracker.h"
|
||||||
|
|
||||||
|
#define HEIGHT_TO_FONT_SIZE 0.47
|
||||||
|
#define HEIGHT_TO_MARGIN 0.27
|
||||||
|
#define HEIGHT_TO_PADDING 0.23
|
||||||
|
#define HEIGHT_TO_TEXT_PADDING_CORRECTION 0.08
|
||||||
|
|
||||||
|
@implementation FBSDKButton
|
||||||
|
{
|
||||||
|
BOOL _skipIntrinsicContentSizing;
|
||||||
|
BOOL _isExplicitlyDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Object Lifecycle
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
|
{
|
||||||
|
if ((self = [super initWithFrame:frame])) {
|
||||||
|
_skipIntrinsicContentSizing = YES;
|
||||||
|
[self configureButton];
|
||||||
|
_skipIntrinsicContentSizing = NO;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)awakeFromNib
|
||||||
|
{
|
||||||
|
[super awakeFromNib];
|
||||||
|
_skipIntrinsicContentSizing = YES;
|
||||||
|
[self configureButton];
|
||||||
|
_skipIntrinsicContentSizing = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Properties
|
||||||
|
|
||||||
|
- (void)setEnabled:(BOOL)enabled
|
||||||
|
{
|
||||||
|
_isExplicitlyDisabled = !enabled;
|
||||||
|
[self checkImplicitlyDisabled];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Layout
|
||||||
|
|
||||||
|
- (CGRect)imageRectForContentRect:(CGRect)contentRect
|
||||||
|
{
|
||||||
|
if (self.hidden || CGRectIsEmpty(self.bounds)) {
|
||||||
|
return CGRectZero;
|
||||||
|
}
|
||||||
|
CGRect imageRect = UIEdgeInsetsInsetRect(contentRect, self.imageEdgeInsets);
|
||||||
|
CGFloat margin = [self _marginForHeight:[self _heightForContentRect:contentRect]];
|
||||||
|
imageRect = CGRectInset(imageRect, margin, margin);
|
||||||
|
imageRect.size.width = CGRectGetHeight(imageRect);
|
||||||
|
return imageRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)intrinsicContentSize
|
||||||
|
{
|
||||||
|
if (_skipIntrinsicContentSizing) {
|
||||||
|
return CGSizeZero;
|
||||||
|
}
|
||||||
|
_skipIntrinsicContentSizing = YES;
|
||||||
|
CGSize size = [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||||
|
_skipIntrinsicContentSizing = NO;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)layoutSubviews
|
||||||
|
{
|
||||||
|
// automatic impression tracking if the button conforms to FBSDKButtonImpressionTracking
|
||||||
|
if ([self conformsToProtocol:@protocol(FBSDKButtonImpressionTracking)]) {
|
||||||
|
NSString *eventName = ((id<FBSDKButtonImpressionTracking>)self).impressionTrackingEventName;
|
||||||
|
NSString *identifier = ((id<FBSDKButtonImpressionTracking>)self).impressionTrackingIdentifier;
|
||||||
|
NSDictionary<NSString *, id> *parameters = ((id<FBSDKButtonImpressionTracking>)self).analyticsParameters;
|
||||||
|
if (eventName && identifier) {
|
||||||
|
FBSDKViewImpressionTracker *impressionTracker = [FBSDKViewImpressionTracker impressionTrackerWithEventName:eventName];
|
||||||
|
[impressionTracker logImpressionWithIdentifier:identifier parameters:parameters];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[super layoutSubviews];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)sizeThatFits:(CGSize)size
|
||||||
|
{
|
||||||
|
if (self.hidden) {
|
||||||
|
return CGSizeZero;
|
||||||
|
}
|
||||||
|
CGSize normalSize = [self sizeThatFits:size title:[self titleForState:UIControlStateNormal]];
|
||||||
|
CGSize selectedSize = [self sizeThatFits:size title:[self titleForState:UIControlStateSelected]];
|
||||||
|
return CGSizeMake(MAX(normalSize.width, selectedSize.width), MAX(normalSize.height, selectedSize.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sizeToFit
|
||||||
|
{
|
||||||
|
CGRect bounds = self.bounds;
|
||||||
|
bounds.size = [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||||
|
self.bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGRect)titleRectForContentRect:(CGRect)contentRect
|
||||||
|
{
|
||||||
|
if (self.hidden || CGRectIsEmpty(self.bounds)) {
|
||||||
|
return CGRectZero;
|
||||||
|
}
|
||||||
|
CGRect imageRect = [self imageRectForContentRect:contentRect];
|
||||||
|
CGFloat height = [self _heightForContentRect:contentRect];
|
||||||
|
CGFloat padding = [self _paddingForHeight:height];
|
||||||
|
CGFloat titleX = CGRectGetMaxX(imageRect) + padding;
|
||||||
|
CGRect titleRect = CGRectMake(titleX, 0.0, CGRectGetWidth(contentRect) - titleX, CGRectGetHeight(contentRect));
|
||||||
|
|
||||||
|
UIEdgeInsets titleEdgeInsets = UIEdgeInsetsZero;
|
||||||
|
if (!self.layer.needsLayout) {
|
||||||
|
UILabel *titleLabel = self.titleLabel;
|
||||||
|
if (titleLabel.textAlignment == NSTextAlignmentCenter) {
|
||||||
|
// if the text is centered, we need to adjust the frame for the titleLabel based on the size of the text in order
|
||||||
|
// to keep the text centered in the button without adding extra blank space to the right when unnecessary
|
||||||
|
// 1. the text fits centered within the button without colliding with the image (imagePaddingWidth)
|
||||||
|
// 2. the text would run into the image, so adjust the insets to effectively left align it (textPaddingWidth)
|
||||||
|
CGSize titleSize = FBSDKTextSize(titleLabel.text,
|
||||||
|
titleLabel.font,
|
||||||
|
titleRect.size,
|
||||||
|
titleLabel.lineBreakMode);
|
||||||
|
CGFloat titlePaddingWidth = (CGRectGetWidth(titleRect) - titleSize.width) / 2;
|
||||||
|
CGFloat imagePaddingWidth = titleX / 2;
|
||||||
|
CGFloat inset = MIN(titlePaddingWidth, imagePaddingWidth);
|
||||||
|
titleEdgeInsets.left -= inset;
|
||||||
|
titleEdgeInsets.right += inset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UIEdgeInsetsInsetRect(titleRect, titleEdgeInsets);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Subclass Methods
|
||||||
|
|
||||||
|
- (void)logTapEventWithEventName:(NSString *)eventName parameters:(NSDictionary *)parameters
|
||||||
|
{
|
||||||
|
[FBSDKAppEvents logInternalEvent:eventName
|
||||||
|
parameters:parameters
|
||||||
|
isImplicitlyLogged:YES
|
||||||
|
accessToken:[FBSDKAccessToken currentAccessToken]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)checkImplicitlyDisabled
|
||||||
|
{
|
||||||
|
BOOL enabled = !_isExplicitlyDisabled && !self.implicitlyDisabled;
|
||||||
|
BOOL currentEnabled = self.enabled;
|
||||||
|
super.enabled = enabled;
|
||||||
|
if (currentEnabled != enabled) {
|
||||||
|
[self invalidateIntrinsicContentSize];
|
||||||
|
[self setNeedsLayout];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)configureButton
|
||||||
|
{
|
||||||
|
[self configureWithIcon:[self defaultIcon]
|
||||||
|
title:nil
|
||||||
|
backgroundColor:[self defaultBackgroundColor]
|
||||||
|
highlightedColor:[self defaultHighlightedColor]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)configureWithIcon:(FBSDKIcon *)icon
|
||||||
|
title:(NSString *)title
|
||||||
|
backgroundColor:(UIColor *)backgroundColor
|
||||||
|
highlightedColor:(UIColor *)highlightedColor
|
||||||
|
{
|
||||||
|
[self _configureWithIcon:icon
|
||||||
|
title:title
|
||||||
|
backgroundColor:backgroundColor
|
||||||
|
highlightedColor:highlightedColor
|
||||||
|
selectedTitle:nil
|
||||||
|
selectedIcon:nil
|
||||||
|
selectedColor:nil
|
||||||
|
selectedHighlightedColor:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)configureWithIcon:(FBSDKIcon *)icon
|
||||||
|
title:(NSString *)title
|
||||||
|
backgroundColor:(UIColor *)backgroundColor
|
||||||
|
highlightedColor:(UIColor *)highlightedColor
|
||||||
|
selectedTitle:(NSString *)selectedTitle
|
||||||
|
selectedIcon:(FBSDKIcon *)selectedIcon
|
||||||
|
selectedColor:(UIColor *)selectedColor
|
||||||
|
selectedHighlightedColor:(UIColor *)selectedHighlightedColor
|
||||||
|
{
|
||||||
|
[self _configureWithIcon:icon
|
||||||
|
title:title
|
||||||
|
backgroundColor:backgroundColor
|
||||||
|
highlightedColor:highlightedColor
|
||||||
|
selectedTitle:selectedTitle
|
||||||
|
selectedIcon:selectedIcon
|
||||||
|
selectedColor:selectedColor
|
||||||
|
selectedHighlightedColor:selectedHighlightedColor];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIColor *)defaultBackgroundColor
|
||||||
|
{
|
||||||
|
return [UIColor colorWithRed:24.0/255.0 green:119.0/255.0 blue:242.0/255.0 alpha:1.0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIColor *)defaultDisabledColor
|
||||||
|
{
|
||||||
|
return [UIColor colorWithRed:189.0/255.0 green:193.0/255.0 blue:201.0/255.0 alpha:1.0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIFont *)defaultFont
|
||||||
|
{
|
||||||
|
return [UIFont systemFontOfSize:14];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIColor *)defaultHighlightedColor
|
||||||
|
{
|
||||||
|
return [UIColor colorWithRed:21.0/255.0 green:105.0/255.0 blue:214.0/255.0 alpha:1.0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (FBSDKIcon *)defaultIcon
|
||||||
|
{
|
||||||
|
return [[FBSDKLogo alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIColor *)defaultSelectedColor
|
||||||
|
{
|
||||||
|
return [self defaultBackgroundColor];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIColor *)highlightedContentColor
|
||||||
|
{
|
||||||
|
return [UIColor colorWithRed:218.0/255.0 green:221.0/255.0 blue:226.0/255.0 alpha:1.0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isImplicitlyDisabled
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)sizeThatFits:(CGSize)size title:(NSString *)title
|
||||||
|
{
|
||||||
|
UIFont *font = self.titleLabel.font;
|
||||||
|
CGFloat height = [self _heightForFont:font];
|
||||||
|
|
||||||
|
UIEdgeInsets contentEdgeInsets = self.contentEdgeInsets;
|
||||||
|
|
||||||
|
CGSize constrainedContentSize = FBSDKEdgeInsetsInsetSize(size, contentEdgeInsets);
|
||||||
|
|
||||||
|
CGSize titleSize = FBSDKTextSize(title, font, constrainedContentSize, self.titleLabel.lineBreakMode);
|
||||||
|
|
||||||
|
CGFloat padding = [self _paddingForHeight:height];
|
||||||
|
CGFloat textPaddingCorrection = [self _textPaddingCorrectionForHeight:height];
|
||||||
|
CGSize contentSize = CGSizeMake(height + padding + titleSize.width - textPaddingCorrection, height);
|
||||||
|
return FBSDKEdgeInsetsOutsetSize(contentSize, contentEdgeInsets);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Helper Methods
|
||||||
|
|
||||||
|
- (void)_applicationDidBecomeActiveNotification:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
[self checkImplicitlyDisabled];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImage *)_backgroundImageWithColor:(UIColor *)color cornerRadius:(CGFloat)cornerRadius scale:(CGFloat)scale
|
||||||
|
{
|
||||||
|
CGFloat size = 1.0 + 2 * cornerRadius;
|
||||||
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size, size), NO, scale);
|
||||||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||||
|
CGContextSetFillColorWithColor(context, color.CGColor);
|
||||||
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
|
CGPathMoveToPoint(path, NULL, cornerRadius + 1.0, 0.0);
|
||||||
|
CGPathAddArcToPoint(path, NULL, size, 0.0, size, cornerRadius, cornerRadius);
|
||||||
|
CGPathAddLineToPoint(path, NULL, size, cornerRadius + 1.0);
|
||||||
|
CGPathAddArcToPoint(path, NULL, size, size, cornerRadius + 1.0, size, cornerRadius);
|
||||||
|
CGPathAddLineToPoint(path, NULL, cornerRadius, size);
|
||||||
|
CGPathAddArcToPoint(path, NULL, 0.0, size, 0.0, cornerRadius + 1.0, cornerRadius);
|
||||||
|
CGPathAddLineToPoint(path, NULL, 0.0, cornerRadius);
|
||||||
|
CGPathAddArcToPoint(path, NULL, 0.0, 0.0, cornerRadius, 0.0, cornerRadius);
|
||||||
|
CGPathCloseSubpath(path);
|
||||||
|
CGContextAddPath(context, path);
|
||||||
|
CGPathRelease(path);
|
||||||
|
CGContextFillPath(context);
|
||||||
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
return [image resizableImageWithCapInsets:UIEdgeInsetsMake(cornerRadius, cornerRadius, cornerRadius, cornerRadius)
|
||||||
|
resizingMode:UIImageResizingModeStretch];
|
||||||
|
#else
|
||||||
|
return [image stretchableImageWithLeftCapWidth:cornerRadius topCapHeight:cornerRadius];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_configureWithIcon:(FBSDKIcon *)icon
|
||||||
|
title:(NSString *)title
|
||||||
|
backgroundColor:(UIColor *)backgroundColor
|
||||||
|
highlightedColor:(UIColor *)highlightedColor
|
||||||
|
selectedTitle:(NSString *)selectedTitle
|
||||||
|
selectedIcon:(FBSDKIcon *)selectedIcon
|
||||||
|
selectedColor:(UIColor *)selectedColor
|
||||||
|
selectedHighlightedColor:(UIColor *)selectedHighlightedColor
|
||||||
|
{
|
||||||
|
[self checkImplicitlyDisabled];
|
||||||
|
|
||||||
|
if (!icon) {
|
||||||
|
icon = [self defaultIcon];
|
||||||
|
}
|
||||||
|
if (!selectedIcon) {
|
||||||
|
selectedIcon = [self defaultIcon];
|
||||||
|
}
|
||||||
|
if (!backgroundColor) {
|
||||||
|
backgroundColor = [self defaultBackgroundColor];
|
||||||
|
}
|
||||||
|
if (!highlightedColor) {
|
||||||
|
highlightedColor = [self defaultHighlightedColor];
|
||||||
|
}
|
||||||
|
if (!selectedColor) {
|
||||||
|
selectedColor = [self defaultSelectedColor];
|
||||||
|
}
|
||||||
|
if (!selectedHighlightedColor) {
|
||||||
|
selectedHighlightedColor = highlightedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.adjustsImageWhenDisabled = NO;
|
||||||
|
self.adjustsImageWhenHighlighted = NO;
|
||||||
|
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
|
||||||
|
self.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
|
||||||
|
self.tintColor = [UIColor whiteColor];
|
||||||
|
|
||||||
|
BOOL forceSizeToFit = CGRectIsEmpty(self.bounds);
|
||||||
|
|
||||||
|
CGFloat scale = [UIScreen mainScreen].scale;
|
||||||
|
UIImage *backgroundImage;
|
||||||
|
|
||||||
|
backgroundImage = [self _backgroundImageWithColor:backgroundColor cornerRadius:3.0 scale:scale];
|
||||||
|
[self setBackgroundImage:backgroundImage forState:UIControlStateNormal];
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
[self setBackgroundImage:backgroundImage forState:UIControlStateFocused];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
backgroundImage = [self _backgroundImageWithColor:highlightedColor cornerRadius:3.0 scale:scale];
|
||||||
|
[self setBackgroundImage:backgroundImage forState:UIControlStateHighlighted];
|
||||||
|
|
||||||
|
backgroundImage = [self _backgroundImageWithColor:[self defaultDisabledColor] cornerRadius:3.0 scale:scale];
|
||||||
|
[self setBackgroundImage:backgroundImage forState:UIControlStateDisabled];
|
||||||
|
|
||||||
|
if (selectedColor) {
|
||||||
|
backgroundImage = [self _backgroundImageWithColor:selectedColor cornerRadius:3.0 scale:scale];
|
||||||
|
[self setBackgroundImage:backgroundImage forState:UIControlStateSelected];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedHighlightedColor) {
|
||||||
|
backgroundImage = [self _backgroundImageWithColor:selectedHighlightedColor cornerRadius:3.0 scale:scale];
|
||||||
|
[self setBackgroundImage:backgroundImage forState:UIControlStateSelected | UIControlStateHighlighted];
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
[self setBackgroundImage:backgroundImage forState:UIControlStateSelected | UIControlStateFocused];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||||
|
[self setTitleColor:[self highlightedContentColor] forState: UIControlStateHighlighted | UIControlStateSelected];
|
||||||
|
|
||||||
|
[self setTitle:title forState:UIControlStateNormal];
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
[self setTitle:title forState:UIControlStateFocused];
|
||||||
|
#endif
|
||||||
|
if (selectedTitle) {
|
||||||
|
[self setTitle:selectedTitle forState:UIControlStateSelected];
|
||||||
|
[self setTitle:selectedTitle forState:UIControlStateSelected | UIControlStateHighlighted];
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
[self setTitle:selectedTitle forState:UIControlStateSelected | UIControlStateFocused];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
UILabel *titleLabel = self.titleLabel;
|
||||||
|
titleLabel.lineBreakMode = NSLineBreakByClipping;
|
||||||
|
UIFont *font = [self defaultFont];
|
||||||
|
titleLabel.font = font;
|
||||||
|
|
||||||
|
CGSize imageSize = CGSizeMake(font.pointSize, font.pointSize);
|
||||||
|
UIImage *image = [icon imageWithSize:imageSize];
|
||||||
|
image = [image resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeStretch];
|
||||||
|
[self setImage:image forState:UIControlStateNormal];
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
[self setImage:image forState:UIControlStateFocused];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (selectedIcon) {
|
||||||
|
UIImage *selectedImage = [selectedIcon imageWithSize:imageSize];
|
||||||
|
selectedImage = [selectedImage resizableImageWithCapInsets:UIEdgeInsetsZero
|
||||||
|
resizingMode:UIImageResizingModeStretch];
|
||||||
|
[self setImage:selectedImage forState:UIControlStateSelected];
|
||||||
|
[self setImage:selectedImage forState:UIControlStateSelected | UIControlStateHighlighted];
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
[self setImage:selectedImage forState:UIControlStateSelected | UIControlStateFocused];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forceSizeToFit) {
|
||||||
|
[self sizeToFit];
|
||||||
|
}
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(_applicationDidBecomeActiveNotification:)
|
||||||
|
name:FBSDKApplicationDidBecomeActiveNotification
|
||||||
|
object:[FBSDKApplicationDelegate sharedInstance]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)_fontSizeForHeight:(CGFloat)height
|
||||||
|
{
|
||||||
|
return floorf(height * HEIGHT_TO_FONT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)_heightForContentRect:(CGRect)contentRect
|
||||||
|
{
|
||||||
|
UIEdgeInsets contentEdgeInsets = self.contentEdgeInsets;
|
||||||
|
return contentEdgeInsets.top + CGRectGetHeight(contentRect) + contentEdgeInsets.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)_heightForFont:(UIFont *)font
|
||||||
|
{
|
||||||
|
return floorf(font.pointSize / (1 - 2 * HEIGHT_TO_MARGIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)_marginForHeight:(CGFloat)height
|
||||||
|
{
|
||||||
|
return floorf(height * HEIGHT_TO_MARGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)_paddingForHeight:(CGFloat)height
|
||||||
|
{
|
||||||
|
return roundf(height * HEIGHT_TO_PADDING) - [self _textPaddingCorrectionForHeight:height];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)_textPaddingCorrectionForHeight:(CGFloat)height
|
||||||
|
{
|
||||||
|
return floorf(height * HEIGHT_TO_TEXT_PADDING_CORRECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
375
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKConstants.h
generated
Normal file
375
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKConstants.h
generated
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||||
|
|
||||||
|
/**
|
||||||
|
The error domain for all errors from FBSDKCoreKit.
|
||||||
|
|
||||||
|
Error codes from the SDK in the range 0-99 are reserved for this domain.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorDomain const FBSDKErrorDomain
|
||||||
|
NS_SWIFT_NAME(ErrorDomain);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/**
|
||||||
|
The error domain for all errors from FBSDKCoreKit.
|
||||||
|
|
||||||
|
Error codes from the SDK in the range 0-99 are reserved for this domain.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKErrorDomain
|
||||||
|
NS_SWIFT_NAME(ErrorDomain);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0
|
||||||
|
|
||||||
|
/*
|
||||||
|
@methodgroup error userInfo keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key for the invalid collection for errors with FBSDKErrorInvalidArgument.
|
||||||
|
|
||||||
|
If the invalid argument is a collection, the collection can be found with this key and the individual
|
||||||
|
invalid item can be found with FBSDKErrorArgumentValueKey.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKErrorArgumentCollectionKey
|
||||||
|
NS_SWIFT_NAME(ErrorArgumentCollectionKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key for the invalid argument name for errors with FBSDKErrorInvalidArgument.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKErrorArgumentNameKey
|
||||||
|
NS_SWIFT_NAME(ErrorArgumentNameKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key for the invalid argument value for errors with FBSDKErrorInvalidArgument.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKErrorArgumentValueKey
|
||||||
|
NS_SWIFT_NAME(ErrorArgumentValueKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key for the message for developers in NSErrors that originate from the SDK.
|
||||||
|
|
||||||
|
The developer message will not be localized and is not intended to be presented within the app.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKErrorDeveloperMessageKey
|
||||||
|
NS_SWIFT_NAME(ErrorDeveloperMessageKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key describing a localized description that can be presented to the user.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKErrorLocalizedDescriptionKey
|
||||||
|
NS_SWIFT_NAME(ErrorLocalizedDescriptionKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key describing a localized title that can be presented to the user, used with `FBSDKLocalizedErrorDescriptionKey`.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKErrorLocalizedTitleKey
|
||||||
|
NS_SWIFT_NAME(ErrorLocalizedTitleKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@methodgroup FBSDKGraphRequest error userInfo keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key describing the error category, for error recovery purposes.
|
||||||
|
|
||||||
|
See `FBSDKGraphErrorRecoveryProcessor` and `[FBSDKGraphRequest disableErrorRecovery]`.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKGraphRequestErrorKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The userInfo key for the Graph API error code.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKGraphRequestErrorGraphErrorCodeKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorGraphErrorCodeKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The userInfo key for the Graph API error subcode.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKGraphRequestErrorGraphErrorSubcodeKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorGraphErrorSubcodeKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The userInfo key for the HTTP status code.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKGraphRequestErrorHTTPStatusCodeKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorHTTPStatusCodeKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The userInfo key for the raw JSON response.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSErrorUserInfoKey const FBSDKGraphRequestErrorParsedJSONResponseKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorParsedJSONResponseKey);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
@methodgroup error userInfo keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key for the invalid collection for errors with FBSDKErrorInvalidArgument.
|
||||||
|
|
||||||
|
If the invalid argument is a collection, the collection can be found with this key and the individual
|
||||||
|
invalid item can be found with FBSDKErrorArgumentValueKey.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKErrorArgumentCollectionKey
|
||||||
|
NS_SWIFT_NAME(ErrorArgumentCollectionKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key for the invalid argument name for errors with FBSDKErrorInvalidArgument.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKErrorArgumentNameKey
|
||||||
|
NS_SWIFT_NAME(ErrorArgumentNameKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key for the invalid argument value for errors with FBSDKErrorInvalidArgument.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKErrorArgumentValueKey
|
||||||
|
NS_SWIFT_NAME(ErrorArgumentValueKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key for the message for developers in NSErrors that originate from the SDK.
|
||||||
|
|
||||||
|
The developer message will not be localized and is not intended to be presented within the app.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKErrorDeveloperMessageKey
|
||||||
|
NS_SWIFT_NAME(ErrorDeveloperMessageKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key describing a localized description that can be presented to the user.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKErrorLocalizedDescriptionKey
|
||||||
|
NS_SWIFT_NAME(ErrorLocalizedDescriptionKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key describing a localized title that can be presented to the user, used with `FBSDKLocalizedErrorDescriptionKey`.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKErrorLocalizedTitleKey
|
||||||
|
NS_SWIFT_NAME(ErrorLocalizedTitleKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@methodgroup FBSDKGraphRequest error userInfo keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
The userInfo key describing the error category, for error recovery purposes.
|
||||||
|
|
||||||
|
See `FBSDKGraphErrorRecoveryProcessor` and `[FBSDKGraphRequest disableErrorRecovery]`.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKGraphRequestErrorKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The userInfo key for the Graph API error code.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKGraphRequestErrorGraphErrorCodeKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorGraphErrorCodeKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The userInfo key for the Graph API error subcode.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKGraphRequestErrorGraphErrorSubcodeKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorGraphErrorSubcodeKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The userInfo key for the HTTP status code.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKGraphRequestErrorHTTPStatusCodeKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorHTTPStatusCodeKey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The userInfo key for the raw JSON response.
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const FBSDKGraphRequestErrorParsedJSONResponseKey
|
||||||
|
NS_SWIFT_NAME(GraphRequestErrorParsedJSONResponseKey);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
@methodgroup Common Code Block typedefs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Success Block
|
||||||
|
*/
|
||||||
|
typedef void (^FBSDKCodeBlock)(void)
|
||||||
|
NS_SWIFT_NAME(CodeBlock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Error Block
|
||||||
|
*/
|
||||||
|
typedef void (^FBSDKErrorBlock)(NSError *_Nullable error)
|
||||||
|
NS_SWIFT_NAME(ErrorBlock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Success Block
|
||||||
|
*/
|
||||||
|
typedef void (^FBSDKSuccessBlock)(BOOL success, NSError *_Nullable error)
|
||||||
|
NS_SWIFT_NAME(SuccessBlock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@methodgroup Enums
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NS_ERROR_ENUM
|
||||||
|
#define NS_ERROR_ENUM(_domain, _name) \
|
||||||
|
enum _name: NSInteger _name; \
|
||||||
|
enum __attribute__((ns_error_domain(_domain))) _name: NSInteger
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
FBSDKCoreError
|
||||||
|
Error codes for FBSDKErrorDomain.
|
||||||
|
*/
|
||||||
|
typedef NS_ERROR_ENUM(FBSDKErrorDomain, FBSDKCoreError)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
Reserved.
|
||||||
|
*/
|
||||||
|
FBSDKErrorReserved = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
The error code for errors from invalid encryption on incoming encryption URLs.
|
||||||
|
*/
|
||||||
|
FBSDKErrorEncryption,
|
||||||
|
|
||||||
|
/**
|
||||||
|
The error code for errors from invalid arguments to SDK methods.
|
||||||
|
*/
|
||||||
|
FBSDKErrorInvalidArgument,
|
||||||
|
|
||||||
|
/**
|
||||||
|
The error code for unknown errors.
|
||||||
|
*/
|
||||||
|
FBSDKErrorUnknown,
|
||||||
|
|
||||||
|
/**
|
||||||
|
A request failed due to a network error. Use NSUnderlyingErrorKey to retrieve
|
||||||
|
the error object from the NSURLSession for more information.
|
||||||
|
*/
|
||||||
|
FBSDKErrorNetwork,
|
||||||
|
|
||||||
|
/**
|
||||||
|
The error code for errors encountered during an App Events flush.
|
||||||
|
*/
|
||||||
|
FBSDKErrorAppEventsFlush,
|
||||||
|
|
||||||
|
/**
|
||||||
|
An endpoint that returns a binary response was used with FBSDKGraphRequestConnection.
|
||||||
|
|
||||||
|
Endpoints that return image/jpg, etc. should be accessed using NSURLRequest
|
||||||
|
*/
|
||||||
|
FBSDKErrorGraphRequestNonTextMimeTypeReturned,
|
||||||
|
|
||||||
|
/**
|
||||||
|
The operation failed because the server returned an unexpected response.
|
||||||
|
|
||||||
|
You can get this error if you are not using the most recent SDK, or you are accessing a version of the
|
||||||
|
Graph API incompatible with the current SDK.
|
||||||
|
*/
|
||||||
|
FBSDKErrorGraphRequestProtocolMismatch,
|
||||||
|
|
||||||
|
/**
|
||||||
|
The Graph API returned an error.
|
||||||
|
|
||||||
|
See below for useful userInfo keys (beginning with FBSDKGraphRequestError*)
|
||||||
|
*/
|
||||||
|
FBSDKErrorGraphRequestGraphAPI,
|
||||||
|
|
||||||
|
/**
|
||||||
|
The specified dialog configuration is not available.
|
||||||
|
|
||||||
|
This error may signify that the configuration for the dialogs has not yet been downloaded from the server
|
||||||
|
or that the dialog is unavailable. Subsequent attempts to use the dialog may succeed as the configuration is loaded.
|
||||||
|
*/
|
||||||
|
FBSDKErrorDialogUnavailable,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Indicates an operation failed because a required access token was not found.
|
||||||
|
*/
|
||||||
|
FBSDKErrorAccessTokenRequired,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Indicates an app switch (typically for a dialog) failed because the destination app is out of date.
|
||||||
|
*/
|
||||||
|
FBSDKErrorAppVersionUnsupported,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Indicates an app switch to the browser (typically for a dialog) failed.
|
||||||
|
*/
|
||||||
|
FBSDKErrorBrowserUnavailable,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Indicates that a bridge api interaction was interrupted.
|
||||||
|
*/
|
||||||
|
FBSDKErrorBridgeAPIInterruption,
|
||||||
|
} NS_SWIFT_NAME(CoreError);
|
||||||
|
|
||||||
|
/**
|
||||||
|
FBSDKGraphRequestError
|
||||||
|
Describes the category of Facebook error. See `FBSDKGraphRequestErrorKey`.
|
||||||
|
*/
|
||||||
|
typedef NS_ENUM(NSUInteger, FBSDKGraphRequestError)
|
||||||
|
{
|
||||||
|
/** The default error category that is not known to be recoverable. Check `FBSDKLocalizedErrorDescriptionKey` for a user facing message. */
|
||||||
|
FBSDKGraphRequestErrorOther = 0,
|
||||||
|
/** Indicates the error is temporary (such as server throttling). While a recoveryAttempter will be provided with the error instance, the attempt is guaranteed to succeed so you can simply retry the operation if you do not want to present an alert. */
|
||||||
|
FBSDKGraphRequestErrorTransient = 1,
|
||||||
|
/** Indicates the error can be recovered (such as requiring a login). A recoveryAttempter will be provided with the error instance that can take UI action. */
|
||||||
|
FBSDKGraphRequestErrorRecoverable = 2
|
||||||
|
} NS_SWIFT_NAME(GraphRequestError);
|
||||||
|
|
||||||
|
/**
|
||||||
|
a formal protocol very similar to the informal protocol NSErrorRecoveryAttempting
|
||||||
|
*/
|
||||||
|
NS_SWIFT_UNAVAILABLE("")
|
||||||
|
@protocol FBSDKErrorRecoveryAttempting<NSObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
attempt the recovery
|
||||||
|
@param error the error
|
||||||
|
@param recoveryOptionIndex the selected option index
|
||||||
|
@param delegate the delegate
|
||||||
|
@param didRecoverSelector the callback selector, see discussion.
|
||||||
|
@param 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:
|
||||||
|
|
||||||
|
- (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo;
|
||||||
|
|
||||||
|
The value passed for didRecover must be YES if error recovery was completely successful, NO otherwise.
|
||||||
|
*/
|
||||||
|
- (void)attemptRecoveryFromError:(NSError *)error
|
||||||
|
optionIndex:(NSUInteger)recoveryOptionIndex
|
||||||
|
delegate:(nullable id)delegate
|
||||||
|
didRecoverSelector:(SEL)didRecoverSelector
|
||||||
|
contextInfo:(nullable void *)contextInfo;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
64
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKConstants.m
generated
Normal file
64
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKConstants.m
generated
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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 "FBSDKConstants.h"
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||||
|
|
||||||
|
NSErrorDomain const FBSDKErrorDomain = @"com.facebook.sdk.core";
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
NSString *const FBSDKErrorDomain = @"com.facebook.sdk.core";
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||||
|
|
||||||
|
NSErrorUserInfoKey const FBSDKErrorArgumentCollectionKey = @"com.facebook.sdk:FBSDKErrorArgumentCollectionKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKErrorArgumentNameKey = @"com.facebook.sdk:FBSDKErrorArgumentNameKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKErrorArgumentValueKey = @"com.facebook.sdk:FBSDKErrorArgumentValueKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKErrorDeveloperMessageKey = @"com.facebook.sdk:FBSDKErrorDeveloperMessageKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKErrorLocalizedDescriptionKey = @"com.facebook.sdk:FBSDKErrorLocalizedDescriptionKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKErrorLocalizedTitleKey = @"com.facebook.sdk:FBSDKErrorLocalizedErrorTitleKey";
|
||||||
|
|
||||||
|
NSErrorUserInfoKey const FBSDKGraphRequestErrorKey = @"com.facebook.sdk:FBSDKGraphRequestErrorKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKGraphRequestErrorCategoryKey = @"com.facebook.sdk:FBSDKGraphRequestErrorCategoryKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKGraphRequestErrorGraphErrorCodeKey = @"com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorCodeKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKGraphRequestErrorGraphErrorSubcodeKey = @"com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorSubcodeKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKGraphRequestErrorHTTPStatusCodeKey = @"com.facebook.sdk:FBSDKGraphRequestErrorHTTPStatusCodeKey";
|
||||||
|
NSErrorUserInfoKey const FBSDKGraphRequestErrorParsedJSONResponseKey = @"com.facebook.sdk:FBSDKGraphRequestErrorParsedJSONResponseKey";
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
NSString *const FBSDKErrorArgumentCollectionKey = @"com.facebook.sdk:FBSDKErrorArgumentCollectionKey";
|
||||||
|
NSString *const FBSDKErrorArgumentNameKey = @"com.facebook.sdk:FBSDKErrorArgumentNameKey";
|
||||||
|
NSString *const FBSDKErrorArgumentValueKey = @"com.facebook.sdk:FBSDKErrorArgumentValueKey";
|
||||||
|
NSString *const FBSDKErrorDeveloperMessageKey = @"com.facebook.sdk:FBSDKErrorDeveloperMessageKey";
|
||||||
|
NSString *const FBSDKErrorLocalizedDescriptionKey = @"com.facebook.sdk:FBSDKErrorLocalizedDescriptionKey";
|
||||||
|
NSString *const FBSDKErrorLocalizedTitleKey = @"com.facebook.sdk:FBSDKErrorLocalizedErrorTitleKey";
|
||||||
|
|
||||||
|
NSString *const FBSDKGraphRequestErrorKey = @"com.facebook.sdk:FBSDKGraphRequestErrorCategoryKey";
|
||||||
|
NSString *const FBSDKGraphRequestErrorCategoryKey = @"com.facebook.sdk:FBSDKGraphRequestErrorCategoryKey";
|
||||||
|
NSString *const FBSDKGraphRequestErrorGraphErrorCodeKey = @"com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorCodeKey";
|
||||||
|
NSString *const FBSDKGraphRequestErrorGraphErrorSubcodeKey = @"com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorSubcodeKey";
|
||||||
|
NSString *const FBSDKGraphRequestErrorHTTPStatusCodeKey = @"com.facebook.sdk:FBSDKGraphRequestErrorHTTPStatusCodeKey";
|
||||||
|
NSString *const FBSDKGraphRequestErrorParsedJSONResponseKey = @"com.facebook.sdk:FBSDKGraphRequestErrorParsedJSONResponseKey";
|
||||||
|
|
||||||
|
#endif
|
||||||
39
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKCopying.h
generated
Normal file
39
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKCopying.h
generated
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
Extension protocol for NSCopying that adds the copy method, which is implemented on NSObject.
|
||||||
|
|
||||||
|
NSObject<NSCopying> implicitly conforms to this protocol.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(Copying)
|
||||||
|
@protocol FBSDKCopying <NSCopying, NSObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Implemented by NSObject as a convenience to copyWithZone:.
|
||||||
|
@return A copy of the receiver.
|
||||||
|
*/
|
||||||
|
- (id)copy;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
96
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit.h
generated
Normal file
96
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit.h
generated
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// 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 <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#ifdef BUCK
|
||||||
|
|
||||||
|
#import <FBSDKCoreKit/FBSDKAccessToken.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKAppEvents.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKApplicationDelegate.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKButton.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKConstants.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKCopying.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKGraphRequest.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKGraphRequestConnection.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKGraphRequestDataAttachment.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKSettings.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKTestUsersManager.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKUtility.h>
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#import <FBSDKCoreKit/FBSDKAppLink.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKAppLinkNavigation.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/FBSDKGraphErrorRecoveryProcessor.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKMeasurementEvent.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKMutableCopying.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKProfile.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKProfilePictureView.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKURL.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKWebViewAppLinkResolver.h>
|
||||||
|
#else
|
||||||
|
#import <FBSDKCoreKit/FBSDKDeviceButton.h>
|
||||||
|
#import <FBSDKCoreKit/FBSDKDeviceViewControllerBase.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#import "FBSDKAccessToken.h"
|
||||||
|
#import "FBSDKAppEvents.h"
|
||||||
|
#import "FBSDKApplicationDelegate.h"
|
||||||
|
#import "FBSDKButton.h"
|
||||||
|
#import "FBSDKConstants.h"
|
||||||
|
#import "FBSDKCopying.h"
|
||||||
|
#import "FBSDKGraphRequest.h"
|
||||||
|
#import "FBSDKGraphRequestConnection.h"
|
||||||
|
#import "FBSDKGraphRequestDataAttachment.h"
|
||||||
|
#import "FBSDKSettings.h"
|
||||||
|
#import "FBSDKTestUsersManager.h"
|
||||||
|
#import "FBSDKUtility.h"
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
#import "FBSDKAppLink.h"
|
||||||
|
#import "FBSDKAppLinkNavigation.h"
|
||||||
|
#import "FBSDKAppLinkResolver.h"
|
||||||
|
#import "FBSDKAppLinkResolving.h"
|
||||||
|
#import "FBSDKAppLinkReturnToRefererController.h"
|
||||||
|
#import "FBSDKAppLinkReturnToRefererView.h"
|
||||||
|
#import "FBSDKAppLinkTarget.h"
|
||||||
|
#import "FBSDKAppLinkUtility.h"
|
||||||
|
#import "FBSDKGraphErrorRecoveryProcessor.h"
|
||||||
|
#import "FBSDKMeasurementEvent.h"
|
||||||
|
#import "FBSDKMutableCopying.h"
|
||||||
|
#import "FBSDKProfile.h"
|
||||||
|
#import "FBSDKProfilePictureView.h"
|
||||||
|
#import "FBSDKURL.h"
|
||||||
|
#import "FBSDKWebViewAppLinkResolver.h"
|
||||||
|
#else
|
||||||
|
#import "FBSDKDeviceButton.h"
|
||||||
|
#import "FBSDKDeviceViewControllerBase.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FBSDK_VERSION_STRING @"5.15.1"
|
||||||
|
#define FBSDK_TARGET_PLATFORM_VERSION @"v5.0"
|
||||||
39
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKDeviceButton.h
generated
Normal file
39
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKDeviceButton.h
generated
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKButton.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/*
|
||||||
|
An internal base class for device related flows.
|
||||||
|
|
||||||
|
This is an internal API that should not be used directly and is subject to change.
|
||||||
|
*/
|
||||||
|
NS_SWIFT_NAME(FBDeviceButton)
|
||||||
|
@interface FBSDKDeviceButton : FBSDKButton
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
#endif
|
||||||
147
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKDeviceButton.m
generated
Normal file
147
SwiftProject/Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/FBSDKDeviceButton.m
generated
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
// 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 "TargetConditionals.h"
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
|
||||||
|
#import "FBSDKDeviceButton.h"
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "FBSDKCoreKit+Internal.h"
|
||||||
|
|
||||||
|
static const CGFloat kFBLogoSize = 54.0;
|
||||||
|
static const CGFloat kFBLogoLeftMargin = 36.0;
|
||||||
|
static const CGFloat kRightMargin = 12.0;
|
||||||
|
static const CGFloat kPreferredPaddingBetweenLogoTitle = 44.0;
|
||||||
|
|
||||||
|
@implementation FBSDKDeviceButton
|
||||||
|
|
||||||
|
#pragma mark - Layout
|
||||||
|
|
||||||
|
- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
|
||||||
|
{
|
||||||
|
[super didUpdateFocusInContext:context withAnimationCoordinator:coordinator];
|
||||||
|
|
||||||
|
if (self == context.nextFocusedView) {
|
||||||
|
[coordinator addCoordinatedAnimations:^{
|
||||||
|
self.transform = CGAffineTransformMakeScale(1.05, 1.05);
|
||||||
|
self.layer.shadowOpacity = 0.5;
|
||||||
|
} completion:NULL];
|
||||||
|
} else if (self == context.previouslyFocusedView) {
|
||||||
|
[coordinator addCoordinatedAnimations:^{
|
||||||
|
self.transform = CGAffineTransformMakeScale(1.0, 1.0);
|
||||||
|
self.layer.shadowOpacity = 0;
|
||||||
|
} completion:NULL];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGRect)imageRectForContentRect:(CGRect)contentRect
|
||||||
|
{
|
||||||
|
CGFloat centerY = CGRectGetMidY(contentRect);
|
||||||
|
CGFloat y = centerY - (kFBLogoSize / 2.0);
|
||||||
|
return CGRectMake(kFBLogoLeftMargin, y, kFBLogoSize, kFBLogoSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGRect)titleRectForContentRect:(CGRect)contentRect
|
||||||
|
{
|
||||||
|
if (self.hidden || CGRectIsEmpty(self.bounds)) {
|
||||||
|
return CGRectZero;
|
||||||
|
}
|
||||||
|
CGRect imageRect = [self imageRectForContentRect:contentRect];
|
||||||
|
CGFloat titleX = CGRectGetMaxX(imageRect);
|
||||||
|
CGRect rect = CGRectMake(titleX, 0, CGRectGetWidth(contentRect) - titleX - kRightMargin, CGRectGetHeight(contentRect));
|
||||||
|
|
||||||
|
if (!self.layer.needsLayout) {
|
||||||
|
CGSize titleSize = [FBSDKMath ceilForSize:[self.titleLabel.attributedText boundingRectWithSize:contentRect.size
|
||||||
|
options:(NSStringDrawingUsesDeviceMetrics |
|
||||||
|
NSStringDrawingUsesLineFragmentOrigin |
|
||||||
|
NSStringDrawingUsesFontLeading)
|
||||||
|
context:NULL].size];
|
||||||
|
CGFloat titlePadding = ( CGRectGetWidth(rect) - titleSize.width ) / 2;
|
||||||
|
if (titlePadding > titleX) {
|
||||||
|
// if there's room to re-center the text, do so.
|
||||||
|
rect = CGRectMake(kRightMargin, 0, CGRectGetWidth(contentRect) - kRightMargin - kRightMargin, CGRectGetHeight(contentRect));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - FBSDKButton
|
||||||
|
|
||||||
|
- (UIFont *)defaultFont
|
||||||
|
{
|
||||||
|
return [UIFont systemFontOfSize:38];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)sizeThatFits:(CGSize)size attributedTitle:(NSAttributedString *)title
|
||||||
|
{
|
||||||
|
CGSize titleSize = [FBSDKMath ceilForSize:[title boundingRectWithSize:size
|
||||||
|
options:(NSStringDrawingUsesDeviceMetrics |
|
||||||
|
NSStringDrawingUsesLineFragmentOrigin |
|
||||||
|
NSStringDrawingUsesFontLeading)
|
||||||
|
context:NULL].size];
|
||||||
|
CGFloat logoAndTitleWidth = kFBLogoSize + kPreferredPaddingBetweenLogoTitle + titleSize.width + kPreferredPaddingBetweenLogoTitle;
|
||||||
|
CGFloat height = 108;
|
||||||
|
CGSize contentSize = CGSizeMake(kFBLogoLeftMargin + logoAndTitleWidth + kRightMargin,
|
||||||
|
height);
|
||||||
|
return contentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)sizeThatFits:(CGSize)size title:(NSString *)title
|
||||||
|
{
|
||||||
|
return [self sizeThatFits:size attributedTitle:[self attributedTitleStringFromString:title]];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Subclasses
|
||||||
|
|
||||||
|
- (NSAttributedString *)attributedTitleStringFromString:(NSString *)string
|
||||||
|
{
|
||||||
|
if (!string) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
|
||||||
|
style.alignment = NSTextAlignmentCenter;
|
||||||
|
style.lineBreakMode = NSLineBreakByClipping;
|
||||||
|
NSMutableAttributedString *attributedString =
|
||||||
|
[[NSMutableAttributedString alloc] initWithString:string
|
||||||
|
attributes:@{
|
||||||
|
NSParagraphStyleAttributeName: style,
|
||||||
|
NSFontAttributeName: [self defaultFont],
|
||||||
|
NSForegroundColorAttributeName: [UIColor whiteColor]
|
||||||
|
}];
|
||||||
|
// Now find all the spaces and widen their kerning.
|
||||||
|
NSRange range = NSMakeRange(0, string.length);
|
||||||
|
while (range.location != NSNotFound) {
|
||||||
|
NSRange spaceRange = [string rangeOfString:@" " options:0 range:range];
|
||||||
|
if (spaceRange.location == NSNotFound) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
[attributedString addAttribute:NSKernAttributeName
|
||||||
|
value:@2.7
|
||||||
|
range:spaceRange];
|
||||||
|
range = NSMakeRange(spaceRange.location + 1, string.length - spaceRange.location - 1);
|
||||||
|
}
|
||||||
|
return attributedString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user