├── Gemfile ├── clang-format ├── encrypt ├── dist.cer.enc ├── dist.p12.enc ├── apple.cer.enc ├── preengineeringPreDemObjcDemo_InHouse.mobileprovision.enc └── preengineeringPreDemSwiftDemo_InHouse.mobileprovision.enc ├── .codecov.yml ├── PreDemCocoaDemo ├── Pods │ ├── Target Support Files │ │ ├── PreDemCocoa │ │ │ ├── PreDemCocoa.modulemap │ │ │ ├── PreDemCocoa-dummy.m │ │ │ ├── PreDemCocoa-prefix.pch │ │ │ ├── PreDemCocoa-umbrella.h │ │ │ ├── PreDemCocoa.xcconfig │ │ │ ├── ResourceBundle-PREDResources-Info.plist │ │ │ └── Info.plist │ │ ├── UICKeyChainStore │ │ │ ├── UICKeyChainStore.modulemap │ │ │ ├── UICKeyChainStore-dummy.m │ │ │ ├── UICKeyChainStore-prefix.pch │ │ │ ├── UICKeyChainStore-umbrella.h │ │ │ ├── UICKeyChainStore.xcconfig │ │ │ └── Info.plist │ │ ├── Pods-PreDemObjcDemo │ │ │ ├── Pods-PreDemObjcDemo.modulemap │ │ │ ├── Pods-PreDemObjcDemo-dummy.m │ │ │ ├── Pods-PreDemObjcDemo-umbrella.h │ │ │ ├── Pods-PreDemObjcDemo.debug.xcconfig │ │ │ ├── Pods-PreDemObjcDemo.release.xcconfig │ │ │ ├── Info.plist │ │ │ ├── Pods-PreDemObjcDemo-acknowledgements.markdown │ │ │ ├── Pods-PreDemObjcDemo-acknowledgements.plist │ │ │ ├── Pods-PreDemObjcDemo-resources.sh │ │ │ └── Pods-PreDemObjcDemo-frameworks.sh │ │ ├── Pods-PreDemSwiftDemo │ │ │ ├── Pods-PreDemSwiftDemo.modulemap │ │ │ ├── Pods-PreDemSwiftDemo-dummy.m │ │ │ ├── Pods-PreDemSwiftDemo-umbrella.h │ │ │ ├── Pods-PreDemSwiftDemo.debug.xcconfig │ │ │ ├── Pods-PreDemSwiftDemo.release.xcconfig │ │ │ ├── Info.plist │ │ │ ├── Pods-PreDemSwiftDemo-acknowledgements.markdown │ │ │ ├── Pods-PreDemSwiftDemo-acknowledgements.plist │ │ │ └── Pods-PreDemSwiftDemo-resources.sh │ │ └── Pods-PreDemCocoaTests │ │ │ ├── Pods-PreDemCocoaTests.modulemap │ │ │ ├── Pods-PreDemCocoaTests-dummy.m │ │ │ ├── Pods-PreDemCocoaTests-umbrella.h │ │ │ ├── Pods-PreDemCocoaTests.debug.xcconfig │ │ │ ├── Pods-PreDemCocoaTests.release.xcconfig │ │ │ ├── Info.plist │ │ │ ├── Pods-PreDemCocoaTests-acknowledgements.markdown │ │ │ ├── Pods-PreDemCocoaTests-acknowledgements.plist │ │ │ └── Pods-PreDemCocoaTests-resources.sh │ ├── Manifest.lock │ ├── Local Podspecs │ │ └── PreDemCocoa.podspec.json │ └── UICKeyChainStore │ │ └── LICENSE ├── PreDemCocoaDemo.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ ├── xcbaselines │ │ └── B6548F351ECB0C7E0031DD42.xcbaseline │ │ │ ├── B28C264C-F388-4FF8-B266-857628BE8B1D.plist │ │ │ └── Info.plist │ │ └── xcschemes │ │ ├── PreDemCocoaTests.xcscheme │ │ ├── PreDemSwiftDemo.xcscheme │ │ └── PreDemObjcDemo.xcscheme ├── PreDemObjcDemo │ ├── ViewController.h │ ├── AppIDViewController.h │ ├── WebViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── Info.plist │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AppDelegate.m │ ├── AppIDViewController.m │ ├── WebViewController.m │ └── ViewController.m ├── PreDemCocoaDemo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Podfile ├── Podfile.lock ├── PreDemCocoaTests │ ├── Info.plist │ └── Tests │ │ ├── PREDSenderTests.m │ │ └── PREDTransactionTests.m └── PreDemSwiftDemo │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── AppIDViewController.swift │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ViewController.swift │ ├── AppDelegate.swift │ └── WebViewController.swift ├── PreDemCocoa ├── Config │ ├── PREDAppInfo.h │ ├── PREDAppInfo.m │ ├── PREDConfigManager.h │ ├── PREDConfig.h │ ├── PREDConfig.m │ └── PREDConfigManager.m ├── Helper │ ├── PREDCredential.h │ ├── PREDVersion.h │ ├── NSObject+Serialization.h │ ├── PREDError.m │ ├── PREDError.h │ ├── PREDCredential.m │ ├── PREDVersion.m │ ├── PREDHelper.h │ ├── PREDLogger.m │ ├── PREDLogger.h │ └── NSObject+Serialization.m ├── Resources │ └── Version.plist ├── Public │ ├── PreDemCocoa.h │ ├── PREDTransaction.h │ ├── PREDCustomEvent.h │ ├── PREDDefines.h │ ├── PREDManager.h │ └── PREDBaseModel.h ├── Core │ ├── PREDManagerPrivate.h │ ├── PREDConstants.h │ ├── PREDBaseModel.m │ ├── PREDCustomEvent.m │ └── PREDManager.m ├── Sender │ ├── PREDNetworkClient.h │ ├── PREDPersistence.h │ ├── PREDSender.h │ ├── PREDHTTPOperation.h │ ├── PREDHTTPOperation.m │ ├── PREDNetworkClient.m │ └── PREDPersistence.m └── Transaction │ ├── PREDTransactionPrivate.h │ └── PREDTransaction.m ├── fastlane ├── Gymfile ├── Scanfile ├── Fastfile └── README.md ├── format.sh ├── .gitignore ├── Contributing.md ├── PreDemCocoa.podspec ├── LICENSE ├── scripts ├── travis.sh └── add-key.sh ├── utils.sh ├── CHANGELOG.md ├── .travis.yml ├── README.md └── Gemfile.lock /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | gem "fir-cli" 5 | -------------------------------------------------------------------------------- /clang-format: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pre-dem/pre-dem-cocoa/HEAD/clang-format -------------------------------------------------------------------------------- /encrypt/dist.cer.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pre-dem/pre-dem-cocoa/HEAD/encrypt/dist.cer.enc -------------------------------------------------------------------------------- /encrypt/dist.p12.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pre-dem/pre-dem-cocoa/HEAD/encrypt/dist.p12.enc -------------------------------------------------------------------------------- /encrypt/apple.cer.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pre-dem/pre-dem-cocoa/HEAD/encrypt/apple.cer.enc -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "PreDemCocoaDemo/PreDemObjcDemo" 3 | - "PreDemCocoaDemo/PreDemSwiftDemo" 4 | - "PreDemCocoaDemo/Pods" 5 | -------------------------------------------------------------------------------- /encrypt/preengineeringPreDemObjcDemo_InHouse.mobileprovision.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pre-dem/pre-dem-cocoa/HEAD/encrypt/preengineeringPreDemObjcDemo_InHouse.mobileprovision.enc -------------------------------------------------------------------------------- /encrypt/preengineeringPreDemSwiftDemo_InHouse.mobileprovision.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pre-dem/pre-dem-cocoa/HEAD/encrypt/preengineeringPreDemSwiftDemo_InHouse.mobileprovision.enc -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/PreDemCocoa/PreDemCocoa.modulemap: -------------------------------------------------------------------------------- 1 | framework module PreDemCocoa { 2 | umbrella header "PreDemCocoa-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/PreDemCocoa/PreDemCocoa-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_PreDemCocoa : NSObject 3 | @end 4 | @implementation PodsDummy_PreDemCocoa 5 | @end 6 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/UICKeyChainStore/UICKeyChainStore.modulemap: -------------------------------------------------------------------------------- 1 | framework module UICKeyChainStore { 2 | umbrella header "UICKeyChainStore-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_PreDemObjcDemo { 2 | umbrella header "Pods-PreDemObjcDemo-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/UICKeyChainStore/UICKeyChainStore-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_UICKeyChainStore : NSObject 3 | @end 4 | @implementation PodsDummy_UICKeyChainStore 5 | @end 6 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Pods-PreDemSwiftDemo.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_PreDemSwiftDemo { 2 | umbrella header "Pods-PreDemSwiftDemo-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Pods-PreDemCocoaTests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_PreDemCocoaTests { 2 | umbrella header "Pods-PreDemCocoaTests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_PreDemObjcDemo : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_PreDemObjcDemo 5 | @end 6 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Pods-PreDemSwiftDemo-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_PreDemSwiftDemo : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_PreDemSwiftDemo 5 | @end 6 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Pods-PreDemCocoaTests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_PreDemCocoaTests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_PreDemCocoaTests 5 | @end 6 | -------------------------------------------------------------------------------- /PreDemCocoa/Config/PREDAppInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDAppInfo.h 3 | // Pods 4 | // 5 | // Created by 王思宇 on 19/09/2017. 6 | // 7 | // 8 | 9 | #import "PREDBaseModel.h" 10 | 11 | @interface PREDAppInfo : PREDBaseModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /fastlane/Gymfile: -------------------------------------------------------------------------------- 1 | workspace "PreDemCocoaDemo/PreDemCocoaDemo.xcworkspace" 2 | 3 | clean true 4 | 5 | silent true 6 | 7 | export_method "enterprise" 8 | 9 | # use staging for testing 10 | xcargs "GCC_PREPROCESSOR_DEFINITIONS='$(inherited) PREDEM_STAGING=1' OTHER_SWIFT_FLAGS='$(inherited) -DPREDEM_STAGING=1'" 11 | -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Change this if your clang-format executable is somewhere else 3 | #CLANG_FORMAT="$HOME/Library/Application Support/Alcatraz/Plug-ins/ClangFormat/bin/clang-format" 4 | CLANG_FORMAT=./clang-format 5 | find . \( -name '*.h' -or -name '*.m' -or -name '*.mm' \) -print0 | xargs -0 "$CLANG_FORMAT" -i 6 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDCredential.h: -------------------------------------------------------------------------------- 1 | // 2 | // PRECredential.h 3 | // Pods 4 | // 5 | // Created by BaiLong on 2017/9/5. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface PREDCredential : NSObject 12 | 13 | + (NSString *)authorize:(NSString *)data appKey:(NSString *)key; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/PreDemCocoa/PreDemCocoa-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // PreDemObjcDemo 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/UICKeyChainStore/UICKeyChainStore-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/AppIDViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppIDViewController.h 3 | // PreDemObjcDemo 4 | // 5 | // Created by 王思宇 on 8/1/17. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppIDViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/WebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewController.h 3 | // PreDemObjcDemo 4 | // 5 | // Created by WangSiyu on 02/11/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WebViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PreDemCocoa/Resources/Version.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Build 6 | 75cb653 7 | Version 8 | 2.1.1 9 | 10 | 11 | -------------------------------------------------------------------------------- /PreDemCocoa/Public/PreDemCocoa.h: -------------------------------------------------------------------------------- 1 | // 2 | // PreDemCocoa.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDBaseModel.h" 10 | #import "PREDCustomEvent.h" 11 | #import "PREDDefines.h" 12 | #import "PREDManager.h" 13 | #import "PREDTransaction.h" 14 | -------------------------------------------------------------------------------- /PreDemCocoa/Config/PREDAppInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDAppInfo.m 3 | // Pods 4 | // 5 | // Created by 王思宇 on 19/09/2017. 6 | // 7 | // 8 | 9 | #import "PREDAppInfo.h" 10 | #import "PREDConstants.h" 11 | 12 | @implementation PREDAppInfo 13 | 14 | - (instancetype)init { 15 | return [self initWithName:AppInfoEventName type:AutoCapturedEventType]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDVersion.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDVersion.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 22/05/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PREDVersion : NSObject 12 | 13 | + (NSString *)getSDKVersion; 14 | 15 | + (NSString *)getSDKBuild; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | use_frameworks! 3 | install! 'cocoapods', :deterministic_uuids => false 4 | 5 | target 'PreDemObjcDemo' do 6 | pod 'PreDemCocoa', :path => '../' 7 | end 8 | 9 | target 'PreDemSwiftDemo' do 10 | pod 'PreDemCocoa', :path => '../' 11 | end 12 | 13 | target 'PreDemCocoaTests' do 14 | pod 'PreDemCocoa', :path => '../' 15 | end 16 | 17 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PreDemObjcDemo 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property(strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/NSObject+Serialization.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Serialization.h 3 | // Pods 4 | // 5 | // Created by 王思宇 on 18/09/2017. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (Serialization) 12 | 13 | - (NSData *)toJsonWithError:(NSError **)error; 14 | 15 | - (NSMutableDictionary *)toDic; 16 | 17 | - (NSMutableDictionary *)toDicForClass:(Class) class; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /fastlane/Scanfile: -------------------------------------------------------------------------------- 1 | # For more information about this configuration visit 2 | # https://github.com/fastlane/fastlane/tree/master/scan#scanfile 3 | 4 | # In general, you can use the options available 5 | # fastlane scan --help 6 | 7 | # Remove the # in front of the line to enable the option 8 | 9 | workspace "PreDemCocoaDemo/PreDemCocoaDemo.xcworkspace" 10 | 11 | scheme "PreDemCocoaTests" 12 | 13 | clean true 14 | 15 | code_coverage true 16 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PreDemObjcDemo 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import 11 | 12 | int main(int argc, char *argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, 15 | NSStringFromClass([AppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | FOUNDATION_EXPORT double Pods_PreDemObjcDemoVersionNumber; 14 | FOUNDATION_EXPORT const unsigned char Pods_PreDemObjcDemoVersionString[]; 15 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Pods-PreDemSwiftDemo-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | FOUNDATION_EXPORT double Pods_PreDemSwiftDemoVersionNumber; 14 | FOUNDATION_EXPORT const unsigned char Pods_PreDemSwiftDemoVersionString[]; 15 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Pods-PreDemCocoaTests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | FOUNDATION_EXPORT double Pods_PreDemCocoaTestsVersionNumber; 14 | FOUNDATION_EXPORT const unsigned char Pods_PreDemCocoaTestsVersionString[]; 15 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/UICKeyChainStore/UICKeyChainStore-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "UICKeyChainStore.h" 14 | 15 | FOUNDATION_EXPORT double UICKeyChainStoreVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char UICKeyChainStoreVersionString[]; 17 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PreDemCocoa (2.1.1): 3 | - PreDemCocoa/Core (= 2.1.1) 4 | - PreDemCocoa/Core (2.1.1): 5 | - UICKeyChainStore 6 | - UICKeyChainStore (2.1.1) 7 | 8 | DEPENDENCIES: 9 | - PreDemCocoa (from `../`) 10 | 11 | EXTERNAL SOURCES: 12 | PreDemCocoa: 13 | :path: ../ 14 | 15 | SPEC CHECKSUMS: 16 | PreDemCocoa: 15d2fae2cb7a115ed6b6126fe4267247e4e874ab 17 | UICKeyChainStore: 239558492fa260531a0774cfc611ea83a6eaff3a 18 | 19 | PODFILE CHECKSUM: 4a95a6f68106e8e8bff2d114e5209668ffc939f7 20 | 21 | COCOAPODS: 1.4.0 22 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PreDemCocoa (2.1.1): 3 | - PreDemCocoa/Core (= 2.1.1) 4 | - PreDemCocoa/Core (2.1.1): 5 | - UICKeyChainStore 6 | - UICKeyChainStore (2.1.1) 7 | 8 | DEPENDENCIES: 9 | - PreDemCocoa (from `../`) 10 | 11 | EXTERNAL SOURCES: 12 | PreDemCocoa: 13 | :path: ../ 14 | 15 | SPEC CHECKSUMS: 16 | PreDemCocoa: 15d2fae2cb7a115ed6b6126fe4267247e4e874ab 17 | UICKeyChainStore: 239558492fa260531a0774cfc611ea83a6eaff3a 18 | 19 | PODFILE CHECKSUM: 4a95a6f68106e8e8bff2d114e5209668ffc939f7 20 | 21 | COCOAPODS: 1.4.0 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Xcode 4 | # 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | *.moved-aside 17 | DerivedData 18 | *.hmap 19 | *.ipa 20 | *.xcuserstate 21 | 22 | *.zip 23 | 24 | # fastlane specific 25 | fastlane/report.xml 26 | 27 | # deliver temporary files 28 | fastlane/Preview.html 29 | 30 | # snapshot generated screenshots 31 | fastlane/screenshots 32 | 33 | # scan temporary files 34 | fastlane/test_output 35 | .idea 36 | -------------------------------------------------------------------------------- /PreDemCocoa/Config/PREDConfigManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDConfig.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 10/05/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDConfig.h" 10 | #import "PREDPersistence.h" 11 | #import "PREDSender.h" 12 | #import 13 | 14 | extern NSString *kPREDConfigRefreshedNotification; 15 | extern NSString *kPREDConfigRefreshedNotificationConfigKey; 16 | 17 | @interface PREDConfigManager : NSObject 18 | 19 | - (instancetype)initWithSender:(PREDSender *)sender; 20 | 21 | - (PREDConfig *)getConfig; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /PreDemCocoa/Core/PREDManagerPrivate.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDManagerPrivate.h 3 | // PreDemCocoa 4 | // 5 | // Created by Troy on 2017/6/27. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #ifndef PREDManagerPrivate_h 10 | #define PREDManagerPrivate_h 11 | 12 | #import "PREDConfigManager.h" 13 | #import "PREDManager.h" 14 | #import "PREDNetworkClient.h" 15 | 16 | #define PREDAppIdLength 8 17 | 18 | @interface PREDManager () 19 | 20 | + (PREDManager *_Nonnull)sharedPREDManager; 21 | 22 | @property(nonatomic, nonnull) NSString *appKey; 23 | 24 | @end 25 | 26 | #endif /* PREDManagerPrivate_h */ 27 | -------------------------------------------------------------------------------- /PreDemCocoa/Sender/PREDNetworkClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDNetworkClient.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDHTTPOperation.h" //needed for typedef 10 | #import 11 | 12 | @interface PREDNetworkClient : NSObject 13 | 14 | - (instancetype)initWithBaseURL:(NSURL *)baseURL; 15 | 16 | - (void)postPath:(NSString *)path 17 | data:(NSData *)data 18 | headers:(NSMutableDictionary *)headers 19 | completion:(PREDNetworkCompletionBlock)completion; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/PreDemCocoa/PreDemCocoa-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "PREDBaseModel.h" 14 | #import "PREDCustomEvent.h" 15 | #import "PREDDefines.h" 16 | #import "PREDManager.h" 17 | #import "PREDTransaction.h" 18 | #import "PreDemCocoa.h" 19 | 20 | FOUNDATION_EXPORT double PreDemCocoaVersionNumber; 21 | FOUNDATION_EXPORT const unsigned char PreDemCocoaVersionString[]; 22 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/UICKeyChainStore/UICKeyChainStore.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_LDFLAGS = -framework "Security" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/UICKeyChainStore 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /PreDemCocoa/Config/PREDConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDConfig.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 10/05/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PREDConfig : NSObject 12 | 13 | @property(nonatomic, strong, class, readonly) PREDConfig *defaultConfig; 14 | @property(nonatomic, assign) BOOL httpMonitorEnabled; 15 | @property(nonatomic, assign) BOOL crashReportEnabled; 16 | @property(nonatomic, assign) BOOL lagMonitorEnabled; 17 | @property(nonatomic, assign) BOOL webviewEnabled; 18 | @property(nonatomic, assign) BOOL isVip; 19 | 20 | + (instancetype)configWithDic:(NSDictionary *)dic; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/PreDemCocoa/PreDemCocoa.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | OTHER_LDFLAGS = -l"c++" -l"z" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | -------------------------------------------------------------------------------- /PreDemCocoa/Sender/PREDPersistence.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDPersistence.h 3 | // Pods 4 | // 5 | // Created by 王思宇 on 14/09/2017. 6 | // 7 | // 8 | 9 | #import "PREDAppInfo.h" 10 | #import "PREDCustomEvent.h" 11 | #import 12 | 13 | @class PREDTransaction; 14 | 15 | @interface PREDPersistence : NSObject 16 | 17 | - (void)persist:(id)data; 18 | 19 | // 将收集到的相关数据序列化并持久化到本地 20 | - (void)persistSave:(NSData *)data; 21 | 22 | // 获取持久化在本地的各种数据文件地址 23 | - (NSString *)nextArchivedPath; 24 | 25 | // 清除缓存文件相关方法 26 | - (void)purgeFile:(NSString *)filePath; 27 | 28 | - (void)purgeFiles:(NSArray *)filePaths; 29 | 30 | - (void)purgeAll; 31 | 32 | - (instancetype)initWithPath:(NSString *)path queue:(NSString *)queue; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDError.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDError.m 3 | // Pods 4 | // 5 | // Created by 王思宇 on 04/09/2017. 6 | // 7 | // 8 | 9 | #import "PREDError.h" 10 | 11 | @implementation PREDError 12 | 13 | NSString *const PREDErrorDomain = @"PREDErrorDomain"; 14 | 15 | + (NSError *)GenerateNSError:(PREDErrorCode)code 16 | description:(NSString *)format, ... { 17 | va_list args; 18 | va_start(args, format); 19 | NSString *description = 20 | [[NSString alloc] initWithFormat:format arguments:args]; 21 | va_end(args); 22 | NSMutableDictionary *userInfo = [NSMutableDictionary new]; 23 | [userInfo setValue:description forKey:NSLocalizedDescriptionKey]; 24 | return [NSError errorWithDomain:PREDErrorDomain code:code userInfo:userInfo]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # 贡献代码指南 2 | 3 | 我们非常欢迎大家来贡献代码,我们会向贡献者致以最诚挚的敬意。 4 | 5 | 一般可以通过在Github上提交[Pull Request](https://github.com/pre-dem/pre-dem-cocoa/pulls)来贡献代码。 6 | 7 | ## Pull Request要求 8 | 9 | - **代码规范** 参考 https://github.com/NYTimes/objective-c-style-guide https://github.com/objc-zen/objc-zen-book 。 10 | 11 | - **代码格式** 提交前请使用项目里的format.sh进行格式化。 12 | 13 | - **必须添加测试!** - 如果没有测试(单元测试、集成测试都可以),那么提交的补丁是不会通过的。 14 | 15 | - **记得更新文档** - 保证`README.md`以及其他相关文档及时更新,和代码的变更保持一致性。 16 | 17 | - **考虑我们的发布周期** - 我们的版本号会服从[SemVer v2.0.0](http://semver.org/),我们绝对不会随意变更对外的API。 18 | 19 | - **创建feature分支** - 最好不要从你的master分支提交 pull request。 20 | 21 | - **一个feature提交一个pull请求** - 如果你的代码变更了多个操作,那就提交多个pull请求吧。 22 | 23 | - **清晰的commit历史** - 保证你的pull请求的每次commit操作都是有意义的。如果你开发中需要执行多次的即时commit操作,那么请把它们放到一起再提交pull请求。 24 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaDemo.xcodeproj/xcshareddata/xcbaselines/B6548F351ECB0C7E0031DD42.xcbaseline/B28C264C-F388-4FF8-B266-857628BE8B1D.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | PREDPersistenceTests 8 | 9 | testPerformanceExample 10 | 11 | com.apple.XCTPerformanceMetric_WallClockTime 12 | 13 | baselineAverage 14 | 3.058e-07 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDError.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDError.h 3 | // Pods 4 | // 5 | // Created by 王思宇 on 04/09/2017. 6 | // 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, PREDErrorCode) { 12 | kPREDErrorCodeUnknown = -1, 13 | kPREDErrorCodeInvalidServiceDomain = 100, 14 | kPREDErrorCodeInvalidAppKey = 101, 15 | kPREDErrorCodeInvalidJsonObject = 102, 16 | kPREDErrorCodeInternalError = 103, 17 | kPREDErrorCodeNotInitedError = 104, 18 | kPREDErrorCodeInvalidTransactionIDError = 105, 19 | kPREDErrorCodeCompressionError = 106, 20 | }; 21 | 22 | extern NSString *const PREDErrorDomain; 23 | 24 | @interface PREDError : NSObject 25 | 26 | + (NSError *)GenerateNSError:(PREDErrorCode)code 27 | description:(NSString *)format, ...; 28 | @end 29 | -------------------------------------------------------------------------------- /PreDemCocoa/Core/PREDConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.h 3 | // Pods 4 | // 5 | // Created by WangSiyu on 17/11/2017. 6 | // 7 | 8 | #ifndef Constants_h 9 | #define Constants_h 10 | 11 | #import 12 | 13 | static NSString *CustomEventType = @"custom"; 14 | static NSString *AutoCapturedEventType = @"auto_captured"; 15 | 16 | static NSString *AppInfoEventName = @"app"; 17 | static NSString *CrashReportEventName = @"crash"; 18 | static NSString *HttpMonitorEventName = @"monitor"; 19 | static NSString *NetDiagEventName = @"netdiag"; 20 | static NSString *LogCaptureEventName = @"log"; 21 | static NSString *LagMonitorEventName = @"lag_monitor"; 22 | static NSString *BreadcrumbEventName = @"breadcrumb"; 23 | static NSString *TransactionEventName = @"auto_captured_transaction"; 24 | 25 | #endif /* Constants_h */ 26 | -------------------------------------------------------------------------------- /PreDemCocoa/Transaction/PREDTransactionPrivate.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDTransaction.h 3 | // CocoaLumberjack 4 | // 5 | // Created by WangSiyu on 21/03/2018. 6 | // 7 | 8 | #import "PREDTransaction.h" 9 | 10 | @class PREDSender; 11 | 12 | typedef NS_ENUM(NSInteger, PREDTransactionType) { 13 | PREDTransactionTypeCompleted, 14 | PREDTransactionTypeCancelled, 15 | PREDTransactionTypeFailed, 16 | }; 17 | 18 | @interface PREDTransaction () 19 | 20 | @property(nonatomic, strong) NSString *transaction_name; 21 | @property(nonatomic, assign) uint64_t start_time; 22 | @property(nonatomic, assign) uint64_t end_time; 23 | // 0 正常结束,1 被取消,2 失败 24 | @property(nonatomic, assign) PREDTransactionType transaction_type; 25 | @property(nonatomic, assign) NSString *reason; 26 | 27 | + (PREDTransaction *)transactionWithSender:(PREDSender *)sender; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /PreDemCocoa.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "PreDemCocoa" 3 | s.version = `sh utils.sh get-release-version` 4 | s.summary = "A short description of PreDemCocoa." 5 | s.homepage = "https://github.com/pre-dem/pre-dem-cocoa" 6 | s.license = "MIT" 7 | s.author = { "qiniu" => "sdk@qiniu.com" } 8 | s.source = { :git => "https://github.com/pre-dem/pre-dem-cocoa.git", :tag => "v#{s.version}" } 9 | s.ios.deployment_target = "8.0" 10 | 11 | s.default_subspec = "Core" 12 | 13 | s.subspec 'Core' do |cs| 14 | cs.source_files = "PreDemCocoa/**/*.{h,m,mm,c,cpp}" 15 | cs.public_header_files = 'PreDemCocoa/Public/*.h' 16 | cs.libraries = "c++", "z" 17 | cs.resource_bundles = { 'PREDResources' => 'PreDemCocoa/Resources/*.plist' } 18 | cs.dependency "UICKeyChainStore" 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa/PreDemCocoa.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore/UICKeyChainStore.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "PreDemCocoa" -framework "UICKeyChainStore" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa/PreDemCocoa.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore/UICKeyChainStore.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "PreDemCocoa" -framework "UICKeyChainStore" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Pods-PreDemSwiftDemo.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa/PreDemCocoa.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore/UICKeyChainStore.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "PreDemCocoa" -framework "UICKeyChainStore" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Pods-PreDemCocoaTests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa/PreDemCocoa.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore/UICKeyChainStore.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "PreDemCocoa" -framework "UICKeyChainStore" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Pods-PreDemCocoaTests.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa/PreDemCocoa.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore/UICKeyChainStore.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "PreDemCocoa" -framework "UICKeyChainStore" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Pods-PreDemSwiftDemo.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PreDemCocoa/PreDemCocoa.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/UICKeyChainStore/UICKeyChainStore.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "PreDemCocoa" -framework "UICKeyChainStore" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /PreDemCocoa/Sender/PREDSender.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDSender.h 3 | // Pods 4 | // 5 | // Created by 王思宇 on 18/09/2017. 6 | // 7 | // 8 | 9 | #import "PREDNetworkClient.h" 10 | #import "PREDPersistence.h" 11 | #import 12 | 13 | @interface PREDSender : NSObject 14 | 15 | - (instancetype)initWithBaseUrl:(NSURL *)baseUrl; 16 | 17 | - (void)sendAllSavedData; 18 | 19 | - (void)purgeAll; 20 | 21 | - (void)sendAppInfo:(PREDNetworkCompletionBlock)completion; 22 | 23 | - (void)sendCustomEvents:(PREDNetworkCompletionBlock)completion 24 | recursively:(BOOL)recursively; 25 | 26 | - (void)sendTransactions:(PREDNetworkCompletionBlock)completion 27 | recursively:(BOOL)recursively; 28 | 29 | - (void)persistCustomEvent:(PREDCustomEvent *)event; 30 | 31 | - (void)persistTransaction:(PREDTransaction *)transaction; 32 | 33 | @property NSUInteger interval; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/PreDemCocoa/ResourceBundle-PREDResources-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 2.1.1 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /PreDemCocoa/Public/PREDTransaction.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDTransaction.h 3 | // CocoaLumberjack 4 | // 5 | // Created by WangSiyu on 21/03/2018. 6 | // 7 | 8 | #import "PREDBaseModel.h" 9 | 10 | @interface PREDTransaction : PREDBaseModel 11 | 12 | /** 13 | * transaction 正常结束并上报数据 14 | * 15 | */ 16 | - (void)complete; 17 | 18 | /** 19 | * transaction 取消并上报数据 20 | * 21 | * @param reason transaction 被取消的原因 22 | */ 23 | - (void)cancelWithReason:(NSString *_Nullable)reason; 24 | 25 | /** 26 | * transaction 失败并上报数据 27 | * 28 | * @param reason transaction 被取消的原因 29 | */ 30 | - (void)failWithReason:(NSString *_Nullable)reason; 31 | 32 | @end 33 | 34 | @interface PREDTransactionQueue : NSObject 35 | 36 | @property NSUInteger sizeThreshhold; 37 | @property NSUInteger sendInterval; 38 | 39 | - (PREDTransaction *_Nonnull)transactionStart: 40 | (NSString *_Nonnull)transactionName; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /PreDemCocoa/Sender/PREDHTTPOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDHTTPOperation.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class PREDHTTPOperation; 12 | 13 | typedef void (^PREDNetworkCompletionBlock)(PREDHTTPOperation *operation, 14 | NSData *data, NSError *error); 15 | 16 | @interface PREDHTTPOperation : NSOperation 17 | 18 | + (instancetype)operationWithRequest:(NSURLRequest *)urlRequest; 19 | 20 | @property(nonatomic, readonly) NSURLRequest *URLRequest; 21 | 22 | // the completion is only called if the operation wasn't cancelled 23 | - (void)setCompletion:(PREDNetworkCompletionBlock)completionBlock; 24 | 25 | @property(nonatomic, readonly) NSHTTPURLResponse *response; 26 | @property(nonatomic, readonly) NSData *data; 27 | @property(nonatomic, readonly) NSError *error; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/PreDemCocoa/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/UICKeyChainStore/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Local Podspecs/PreDemCocoa.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PreDemCocoa", 3 | "version": "2.1.1", 4 | "summary": "A short description of PreDemCocoa.", 5 | "homepage": "https://github.com/pre-dem/pre-dem-cocoa", 6 | "license": "MIT", 7 | "authors": { 8 | "qiniu": "sdk@qiniu.com" 9 | }, 10 | "source": { 11 | "git": "https://github.com/pre-dem/pre-dem-cocoa.git", 12 | "tag": "v2.1.1" 13 | }, 14 | "platforms": { 15 | "ios": "8.0" 16 | }, 17 | "default_subspecs": "Core", 18 | "subspecs": [ 19 | { 20 | "name": "Core", 21 | "source_files": "PreDemCocoa/**/*.{h,m,mm,c,cpp}", 22 | "public_header_files": "PreDemCocoa/Public/*.h", 23 | "libraries": [ 24 | "c++", 25 | "z" 26 | ], 27 | "resource_bundles": { 28 | "PREDResources": "PreDemCocoa/Resources/*.plist" 29 | }, 30 | "dependencies": { 31 | "UICKeyChainStore": [ 32 | 33 | ] 34 | } 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PreDemCocoa/Public/PREDCustomEvent.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDEvent.h 3 | // PreDemCocoa 4 | // 5 | // Created by Troy on 2017/9/26. 6 | // 7 | 8 | #ifndef PREDEvent_h 9 | #define PREDEvent_h 10 | 11 | #import "PREDBaseModel.h" 12 | #import 13 | 14 | /** 15 | * 自定义事件数据对象 16 | */ 17 | @interface PREDCustomEvent : PREDBaseModel 18 | 19 | /** 20 | * 自定义事件的内容,仅支持键值对类型的内容 21 | */ 22 | @property(nonatomic, strong, readonly) NSString *content; 23 | 24 | /** 25 | * 生成自定义事件的对象 26 | * 27 | * @param name 自定义事件的名称 28 | * @param contentDic 自定义事件的内容,仅支持键值对类型的内容,需要传入能够被 29 | * json 化的 NSDictionary 对象 30 | */ 31 | + (instancetype)eventWithName:(NSString *)name 32 | contentDic:(NSDictionary *)contentDic; 33 | 34 | @end 35 | 36 | @interface PREDEventQueue : NSObject 37 | 38 | @property NSUInteger sizeThreshhold; 39 | @property NSUInteger sendInterval; 40 | 41 | - (void)trackCustomEvent:(PREDCustomEvent *_Nonnull)event; 42 | 43 | @end 44 | 45 | #endif /* PREDEvent_h */ 46 | -------------------------------------------------------------------------------- /PreDemCocoa/Config/PREDConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDConfig.m 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 10/05/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDConfig.h" 10 | 11 | @implementation PREDConfig 12 | 13 | + (PREDConfig *)defaultConfig { 14 | PREDConfig *config = [PREDConfig new]; 15 | config.httpMonitorEnabled = YES; 16 | config.crashReportEnabled = YES; 17 | config.lagMonitorEnabled = YES; 18 | config.webviewEnabled = YES; 19 | config.isVip = NO; 20 | return config; 21 | } 22 | 23 | + (instancetype)configWithDic:(NSDictionary *)dic { 24 | PREDConfig *config = [PREDConfig new]; 25 | config.httpMonitorEnabled = [dic[@"http_monitor_enabled"] boolValue]; 26 | config.crashReportEnabled = [dic[@"crash_report_enabled"] boolValue]; 27 | config.lagMonitorEnabled = [dic[@"lag_monitor_enabled"] boolValue]; 28 | config.webviewEnabled = [dic[@"webview_enabled"] boolValue]; 29 | config.isVip = [dic[@"vip"] boolValue]; 30 | return config; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDCredential.m: -------------------------------------------------------------------------------- 1 | // 2 | // PRECredential.m 3 | // Pods 4 | // 5 | // Created by BaiLong on 2017/9/5. 6 | // 7 | // 8 | 9 | #include 10 | 11 | #import "PREDCredential.h" 12 | #import "PREDManagerPrivate.h" 13 | 14 | @implementation PREDCredential 15 | 16 | + (NSString *)authorize:(NSString *)data appKey:(NSString *)key { 17 | NSString *realK = [key substringFromIndex:PREDAppIdLength]; 18 | return 19 | [NSString stringWithFormat:@"DEMv1 %@", [self hmacSha1:data data:realK]]; 20 | } 21 | 22 | + (NSString *)hmacSha1:(NSString *)key data:(NSString *)data { 23 | const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding]; 24 | const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding]; 25 | 26 | unsigned char sha1HMAC[CC_SHA1_DIGEST_LENGTH]; 27 | CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), sha1HMAC); 28 | 29 | NSData *HMAC = 30 | [[NSData alloc] initWithBytes:sha1HMAC length:sizeof(sha1HMAC)]; 31 | 32 | NSString *hash = [HMAC base64EncodedStringWithOptions:0]; 33 | return hash; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDVersion.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDVersion.m 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 22/05/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDVersion.h" 10 | #import "PREDLogger.h" 11 | 12 | static NSString *version; 13 | static NSString *build; 14 | 15 | @implementation PREDVersion 16 | 17 | + (void)load { 18 | NSURL *bundleUrl = 19 | [[NSBundle bundleForClass:self] URLForResource:@"PREDResources" 20 | withExtension:@"bundle"]; 21 | if (!bundleUrl) { 22 | PREDLogWarning(@"version bundle is not detected"); 23 | return; 24 | } 25 | NSBundle *bundle = [NSBundle bundleWithURL:bundleUrl]; 26 | NSString *plistPath = [bundle pathForResource:@"Version" ofType:@"plist"]; 27 | NSDictionary *data = [[NSDictionary alloc] initWithContentsOfFile:plistPath]; 28 | version = data[@"Version"]; 29 | build = data[@"Build"]; 30 | } 31 | 32 | + (NSString *)getSDKVersion { 33 | return version.copy; 34 | } 35 | 36 | + (NSString *)getSDKBuild { 37 | return build.copy; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/UICKeyChainStore/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011 kishikawa katsumi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2016 Qiniu, Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaDemo.xcodeproj/xcshareddata/xcbaselines/B6548F351ECB0C7E0031DD42.xcbaseline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runDestinationsByUUID 6 | 7 | B28C264C-F388-4FF8-B266-857628BE8B1D 8 | 9 | localComputer 10 | 11 | busSpeedInMHz 12 | 100 13 | cpuCount 14 | 1 15 | cpuKind 16 | Intel Core i7 17 | cpuSpeedInMHz 18 | 2500 19 | logicalCPUCoresPerPackage 20 | 8 21 | modelCode 22 | MacBookPro11,5 23 | physicalCPUCoresPerPackage 24 | 4 25 | platformIdentifier 26 | com.apple.platform.macosx 27 | 28 | targetArchitecture 29 | x86_64 30 | targetDevice 31 | 32 | modelCode 33 | iPhone6,1 34 | platformIdentifier 35 | com.apple.platform.iphonesimulator 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemSwiftDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "iphone", 5 | "size": "29x29", 6 | "scale": "2x" 7 | }, 8 | { 9 | "idiom": "iphone", 10 | "size": "29x29", 11 | "scale": "3x" 12 | }, 13 | { 14 | "idiom": "iphone", 15 | "size": "40x40", 16 | "scale": "2x" 17 | }, 18 | { 19 | "idiom": "iphone", 20 | "size": "40x40", 21 | "scale": "3x" 22 | }, 23 | { 24 | "idiom": "iphone", 25 | "size": "60x60", 26 | "scale": "2x" 27 | }, 28 | { 29 | "idiom": "iphone", 30 | "size": "60x60", 31 | "scale": "3x" 32 | }, 33 | { 34 | "idiom": "ipad", 35 | "size": "29x29", 36 | "scale": "1x" 37 | }, 38 | { 39 | "idiom": "ipad", 40 | "size": "29x29", 41 | "scale": "2x" 42 | }, 43 | { 44 | "idiom": "ipad", 45 | "size": "40x40", 46 | "scale": "1x" 47 | }, 48 | { 49 | "idiom": "ipad", 50 | "size": "40x40", 51 | "scale": "2x" 52 | }, 53 | { 54 | "idiom": "ipad", 55 | "size": "76x76", 56 | "scale": "1x" 57 | }, 58 | { 59 | "idiom": "ipad", 60 | "size": "76x76", 61 | "scale": "2x" 62 | } 63 | ], 64 | "info": { 65 | "version": 1, 66 | "author": "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /PreDemCocoa/Public/PREDDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDEnums.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | /** 10 | * log 级别,用于过滤 log 11 | */ 12 | typedef NS_ENUM(NSUInteger, PREDLogLevel) { 13 | /** 14 | * 过滤掉所有 log 15 | */ 16 | PREDLogLevelOff = 0, 17 | 18 | /** 19 | * 仅打印 error 级别的 log 20 | */ 21 | PREDLogLevelError = 1 << 0, 22 | 23 | /** 24 | * 打印 Error 及 warning 级别的 log 25 | */ 26 | PREDLogLevelWarning = 1 << 1, 27 | 28 | /** 29 | * 打印 Error, warning 及 info 级别的 log 30 | */ 31 | PREDLogLevelInfo = 1 << 2, 32 | 33 | /** 34 | * 打印 Error, warning, info 及 debug 级别的 log 35 | */ 36 | PREDLogLevelDebug = 1 << 3, 37 | 38 | /** 39 | * 打印 Error, warning, info, debug 以及 verbose 级别的 log 40 | */ 41 | PREDLogLevelVerbose = 1 << 4, 42 | 43 | /** 44 | * 打印所有级别的 log 45 | */ 46 | PREDLogLevelAll = NSUIntegerMax 47 | }; 48 | 49 | typedef NSString *_Nullable (^PREDLogMessageProvider)(void); 50 | 51 | typedef void (^PREDLogHandler)(PREDLogMessageProvider _Nullable messageProvider, 52 | PREDLogLevel logLevel, 53 | const char *_Nullable file, 54 | const char *_Nonnull function, uint line); 55 | 56 | /** 57 | * sdk 启动结果返回 block 58 | */ 59 | typedef void (^PREDStartCompleteHandler)(BOOL succeess, 60 | NSError *_Nullable error); 61 | -------------------------------------------------------------------------------- /scripts/travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | bundle install 4 | 5 | reg_alpha="^v[0-9]+\.[0-9]+\.[0-9]+_alpha[0-9]*$" 6 | reg_release="^v[0-9]+\.[0-9]+\.[0-9]+$" 7 | 8 | prepare_sign_env() 9 | { 10 | openssl aes-256-cbc -K $encrypted_321b310503f8_key -iv $encrypted_321b310503f8_iv -in encrypt/dist.p12.enc -out encrypt/dist.p12 -d 11 | openssl aes-256-cbc -K $encrypted_321b310503f8_key -iv $encrypted_321b310503f8_iv -in encrypt/dist.cer.enc -out encrypt/dist.cer -d 12 | openssl aes-256-cbc -K $encrypted_321b310503f8_key -iv $encrypted_321b310503f8_iv -in encrypt/apple.cer.enc -out encrypt/apple.cer -d 13 | openssl aes-256-cbc -K $encrypted_321b310503f8_key -iv $encrypted_321b310503f8_iv -in encrypt/preengineeringPreDemObjcDemo_InHouse.mobileprovision.enc -out encrypt/preengineeringPreDemObjcDemo_InHouse.mobileprovision -d 14 | openssl aes-256-cbc -K $encrypted_321b310503f8_key -iv $encrypted_321b310503f8_iv -in encrypt/preengineeringPreDemSwiftDemo_InHouse.mobileprovision.enc -out encrypt/preengineeringPreDemSwiftDemo_InHouse.mobileprovision -d 15 | ./scripts/add-key.sh 16 | echo "keys and certs successfully added" 17 | } 18 | 19 | # alpha 20 | if [[ $TRAVIS_PULL_REQUEST == "false" && $TRAVIS_TAG =~ $reg_alpha ]]; then 21 | prepare_sign_env 22 | bundle exec fastlane beta 23 | exit $? 24 | # release 25 | elif [[ $TRAVIS_PULL_REQUEST == "false" && $TRAVIS_TAG =~ $reg_release ]]; then 26 | prepare_sign_env 27 | bundle exec fastlane release 28 | exit $? 29 | # commit or pr 30 | else 31 | bundle exec fastlane test 32 | exit $? 33 | fi 34 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | # Customise this file, documentation can be found here: 2 | # https://github.com/fastlane/fastlane/tree/master/fastlane/docs 3 | # All available actions: https://docs.fastlane.tools/actions 4 | # can also be listed using the `fastlane actions` command 5 | 6 | # Change the syntax highlighting to Ruby 7 | # All lines starting with a # are ignored when running `fastlane` 8 | 9 | # If you want to automatically update fastlane if a new version is available: 10 | # update_fastlane 11 | 12 | # This is the minimum version number required. 13 | # Update this, if you use features of a newer version 14 | fastlane_version "2.28.7" 15 | 16 | desc "Runs all the tests" 17 | lane :test do 18 | scan 19 | end 20 | 21 | desc "Submit a new Beta Build to fir.im" 22 | lane :beta do 23 | scan 24 | objcPath = gym( 25 | scheme: "PreDemObjcDemo", 26 | ) 27 | swiftPath = gym( 28 | scheme: "PreDemSwiftDemo", 29 | ) 30 | sh "bundle exec fir publish #{objcPath} -T " + ENV["FIR_TOKEN"] 31 | sh "bundle exec fir publish #{swiftPath} -T " + ENV["FIR_TOKEN"] 32 | end 33 | 34 | desc "Deploy a new version to the App Store" 35 | lane :release do 36 | # match(type: "appstore") 37 | # snapshot 38 | # gym 39 | # deliver(force: true) 40 | # frameit 41 | end 42 | 43 | # More information about multiple platforms in fastlane: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Platforms.md 44 | # All available actions: https://docs.fastlane.tools/actions 45 | 46 | # fastlane reports which actions are used 47 | # No personal data is recorded. Learn more at https://github.com/fastlane/enhancer 48 | -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ================ 3 | # Installation 4 | 5 | Make sure you have the latest version of the Xcode command line tools installed: 6 | 7 | ``` 8 | xcode-select --install 9 | ``` 10 | 11 | ## Choose your installation method: 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
Homebrew 16 | Installer Script 17 | Rubygems 18 |
macOSmacOSmacOS or Linux with Ruby 2.0.0 or above
brew cask install fastlaneDownload the zip file. Then double click on the install script (or run it in a terminal window).sudo gem install fastlane -NV
30 | 31 | # Available Actions 32 | ### test 33 | ``` 34 | fastlane test 35 | ``` 36 | Runs all the tests 37 | ### beta 38 | ``` 39 | fastlane beta 40 | ``` 41 | Submit a new Beta Build to fir.im 42 | ### release 43 | ``` 44 | fastlane release 45 | ``` 46 | Deploy a new version to the App Store 47 | 48 | ---- 49 | 50 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. 51 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). 52 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 53 | -------------------------------------------------------------------------------- /PreDemCocoa/Public/PREDManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDManager.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDCustomEvent.h" 10 | #import "PREDDefines.h" 11 | #import "PREDTransaction.h" 12 | #import 13 | 14 | /** 15 | * PREDManager 是 sdk 的核心类,提供 sdk 的主要对外接口 16 | */ 17 | @interface PREDManager : NSObject 18 | 19 | #pragma mark - Public Methods 20 | 21 | /** 22 | * 启动 PREDManager,如果您使用的是我们的公有云产品,相关参数请通过 23 | * https://predem.qiniu.com 获取 24 | * 25 | * @param appKey 用于唯一标识单个 app 26 | * @param serviceDomain 数据上传的服务器域名 27 | */ 28 | + (void)startWithAppKey:(NSString *_Nonnull)appKey 29 | serviceDomain:(NSString *_Nonnull)serviceDomain; 30 | 31 | /** 32 | * 开始一个 transaction 33 | * 34 | * @param transactionName 该 transaction 的名字 35 | * @return 该 transaction 对应的 实例 36 | */ 37 | + (PREDTransaction *_Nonnull)transactionStart: 38 | (NSString *_Nonnull)transactionName; 39 | 40 | /** 41 | * 上报自定义事件 42 | * 43 | * @param event 需要上报的自定义事件对象 44 | */ 45 | + (void)trackCustomEvent:(PREDCustomEvent *_Nonnull)event; 46 | 47 | /** 48 | * 返回 sdk 的版本号 49 | */ 50 | + (NSString *_Nonnull)version; 51 | 52 | /** 53 | * 返回 sdk 的构建号 54 | */ 55 | + (NSString *_Nonnull)build; 56 | 57 | #pragma mark - Public Properties 58 | 59 | /** 60 | * 用户标签,用于标识唯一用户,例如您可以传入用户ID,我们将透传该字段,以便您可以在后台通过用户标签查找对应用户的数据 61 | */ 62 | @property(class, nonnull, nonatomic, strong) NSString *tag; 63 | 64 | /** 65 | * 配置上报频率,单位秒,最小30秒,最大1800秒 66 | */ 67 | @property(class) NSUInteger updateInterval; 68 | 69 | /** 70 | * 返回 该终端是否是重点关注对象,终端可以根据这个字段调整队列参数 71 | */ 72 | + (BOOL)isVip; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /scripts/add-key.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # add-key.sh 4 | # PreDemObjcDemo 5 | # 6 | # Created by WangSiyu on 17/05/2017. 7 | # Copyright © 2017 pre-engineering. All rights reserved. 8 | 9 | # Create a custom keychain 10 | security create-keychain -p travis ios-build.keychain 11 | 12 | # Make the custom keychain default, so xcodebuild will use it for signing 13 | security default-keychain -s ios-build.keychain 14 | 15 | # Unlock the keychain 16 | security unlock-keychain -p travis ios-build.keychain 17 | 18 | # Set keychain timeout to 1 hour for long builds 19 | # see http://www.egeek.me/2013/02/23/jenkins-and-xcode-user-interaction-is-not-allowed/ 20 | security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain 21 | 22 | # Add certificates to keychain and allow codesign to access them 23 | security import ./encrypt/apple.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign 24 | security import ./encrypt/dist.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign 25 | security import ./encrypt/dist.p12 -k ~/Library/Keychains/ios-build.keychain -P $KEY_PASSWORD -T /usr/bin/codesign 26 | 27 | # Put the provisioning profile in place 28 | mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles 29 | cp "./encrypt/preengineeringPreDemObjcDemo_InHouse.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/ 30 | cp "./encrypt/preengineeringPreDemSwiftDemo_InHouse.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/ 31 | 32 | # avoid been asked to enter password while signing product 33 | # see https://github.com/fastlane/fastlane/issues/7104 34 | security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k travis ios-build.keychain 35 | 36 | exit $? 37 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 2.1.1 19 | CFBundleVersion 20 | 75cb653 21 | LSRequiresIPhoneOS 22 | 23 | NSAppTransportSecurity 24 | 25 | NSAllowsArbitraryLoads 26 | 27 | 28 | UILaunchStoryboardName 29 | LaunchScreen 30 | UIMainStoryboardFile 31 | Main 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemSwiftDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 2.1.1 19 | CFBundleVersion 20 | 75cb653 21 | LSRequiresIPhoneOS 22 | 23 | NSAppTransportSecurity 24 | 25 | NSAllowsArbitraryLoads 26 | 27 | 28 | UILaunchStoryboardName 29 | LaunchScreen 30 | UIMainStoryboardFile 31 | Main 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /utils.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PATH=/usr/libexec:$PATH 4 | 5 | COMMAND="$1" 6 | cd $(dirname "$0") 7 | 8 | case "$COMMAND" in 9 | 10 | ###################################### 11 | # Versioning 12 | ###################################### 13 | "get-version") 14 | version_file="PreDemCocoa/Resources/Version.plist" 15 | echo "$(PlistBuddy -c "Print :Version" "$version_file")" 16 | exit 0 17 | ;; 18 | 19 | "get-release-version") 20 | ./utils.sh get-version | cut -d v -f 2 | cut -d _ -f 1 21 | exit 0 22 | ;; 23 | 24 | "set-version") 25 | dst_version="$2" 26 | sdk_version_file="PreDemCocoa/Resources/Version.plist" 27 | demo_version_files="PreDemCocoaDemo/PreDemObjcDemo/Info.plist PreDemCocoaDemo/PreDemSwiftDemo/Info.plist" 28 | git_commit=`git rev-parse --short HEAD` 29 | 30 | if [ -z "$dst_version" ]; then 31 | echo "You must specify a version." 32 | exit 1 33 | fi 34 | PlistBuddy -c "Set :Version $dst_version" "$sdk_version_file" 35 | PlistBuddy -c "Set :Build $git_commit" "$sdk_version_file" 36 | 37 | for version_file in $demo_version_files; do 38 | PlistBuddy -c "Set :CFBundleVersion $git_commit" "$version_file" 39 | PlistBuddy -c "Set :CFBundleShortVersionString $dst_version" "$version_file" 40 | echo "$version_file" 41 | done 42 | 43 | cd PreDemCocoaDemo 44 | pod update --no-repo-update 45 | cd .. 46 | 47 | git add . 48 | git commit -m "bump version to $dst_version" 49 | git tag "$dst_version" 50 | 51 | exit 0 52 | ;; 53 | 54 | *) 55 | echo "Unknown command '$COMMAND'" 56 | usage 57 | exit 1 58 | ;; 59 | esac 60 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDHelper.h 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDDefines.h" 10 | #import 11 | 12 | @interface PREDHelper : NSObject 13 | 14 | @property(class, readonly) NSString *UUID; 15 | @property(class, readonly) NSString *osPlatform; 16 | @property(class, readonly) NSString *sdkVersion; 17 | @property(class, readonly) NSString *appVersion; 18 | @property(class, readonly) NSString *appName; 19 | @property(class, readonly) NSString *appBundleId; 20 | @property(class, readonly) NSString *osVersion; 21 | @property(class, readonly) NSString *osBuild; 22 | @property(class, readonly) NSString *deviceModel; 23 | @property(class, strong) NSString *tag; 24 | @property(class, readonly) NSString *sdkDirectory; 25 | @property(class, readonly) NSString *cacheDirectory; 26 | 27 | + (NSString *)MD5:(NSString *)mdStr; 28 | 29 | + (NSString *)lookupHostIPAddressForURL:(NSURL *)url; 30 | 31 | + (NSMutableDictionary *)parseQuery:(NSString *)query; 32 | 33 | /***************************************************************************/ /** 34 | Uses zlib to compress the given data. Note that gzip headers will be added so 35 | that the data can be easily decompressed using a tool like WinZip, gunzip, 36 | etc. 37 | 38 | Note: Special thanks to Robbie Hanson of Deusty Designs for sharing sample 39 | code 40 | showing how deflateInit2() can be used to make zlib generate a compressed file 41 | with gzip headers: 42 | 43 | http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html 44 | 45 | @param pUncompressedData memory buffer of bytes to compress 46 | @return Compressed data as an NSData object 47 | */ 48 | + (NSData *)gzipData:(NSData *)pUncompressedData error:(NSError **)error; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemSwiftDemo/AppIDViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppIDViewController.swift 3 | // PreDemSwiftDemo 4 | // 5 | // Created by 王思宇 on 22/09/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import PreDemCocoa 11 | import UICKeyChainStore 12 | 13 | class AppIDViewController: UIViewController { 14 | 15 | @IBOutlet var appIdTextField: UITextField! 16 | @IBOutlet var domainTextField: UITextField! 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | // Do any additional setup after loading the view. 21 | 22 | let keychian = UICKeyChainStore(service: "com.qiniu.pre.demo") 23 | 24 | if let prevID = keychian["appid"] { 25 | appIdTextField.text = prevID 26 | } 27 | 28 | if let prevDomain = keychian["domain"] { 29 | domainTextField.text = prevDomain 30 | } 31 | } 32 | 33 | override func didReceiveMemoryWarning() { 34 | super.didReceiveMemoryWarning() 35 | // Dispose of any resources that can be recreated. 36 | } 37 | 38 | @IBAction func tapped(sender: Any) { 39 | appIdTextField.resignFirstResponder() 40 | domainTextField.resignFirstResponder() 41 | } 42 | 43 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 44 | let keychian = UICKeyChainStore(service: "com.qiniu.pre.demo") 45 | keychian["appid"] = appIdTextField.text 46 | keychian["domain"] = domainTextField.text 47 | #if DEBUG 48 | PREDManager.start(withAppKey: appIdTextField.text!, serviceDomain: domainTextField.text!) 49 | PREDManager.tag = "userid_debug" 50 | #else 51 | PREDManager.start(withAppKey: appIdTextField.text!, serviceDomain: domainTextField.text!) 52 | PREDManager.tag = "userid_release" 53 | #endif 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemSwiftDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [2.0.0](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v2.0.0) / 2018-03-26 4 | - 删除 `log`、`crash`、`lag` 及 `breadcrumb` 监控 5 | - `http` 模块进行小幅重构 6 | - 添加更新单测用例 7 | 8 | ## [1.0.8](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.8) / 2018-03-26 9 | - 增加 `transaction` 监控的支持 10 | - 更新 demo 11 | - 默认关闭 `breadcrumb` 数据上报 12 | 13 | ## [1.0.7](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.7) / 2018-02-23 14 | - 修复 `http` 请求 `url` 为 `nil` 时会 crash 的问题 15 | - 添加网络诊断功能中 `host` 字段上报 16 | 17 | ## [1.0.6](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.6) / 2018-01-10 18 | - 将接口 `[PREDManager startWithAppKey:serviceDomain:complete:]` 改为 `[PREDManager startWithAppKey:serviceDomain:]` 19 | - 将部分 log 打印更改为中文 20 | 21 | ## [1.0.5](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.5) / 2017-12-02 22 | - lag 采集策略优化,避免出现过量采集情况 23 | - 更新 demo 支持 webview 以及将 log 打印到界面 24 | 25 | ## [1.0.4](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.4) / 2017-12-01 26 | - 更名为 `PreDemCocoa` 27 | - 更新为 v2 接口,上报数据统一使用 `content` 存储非公共数据 28 | - 添加面包屑采集 29 | - log 采集增加回调接口 30 | - 解决 log 采集与项目原有 `Cocoalumberjack` 冲突的问题 31 | 32 | ## [1.0.3](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.3) / 2017-12-01 33 | - 去除 crash 和卡顿采集的本地符号化以提升性能 34 | - 当服务器域名传入不正确时返回错误而不是直接抛出异常 35 | 36 | ## [1.0.2](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.2) / 2017-10-23 37 | - 增加 log 采集的支持 38 | - 增加发送事件之前的持久化存储 39 | - 将自定义事件的发送由单条发送更改为批量发送 40 | - 重构 SDK 的部分代码,提供更好的性能表现 41 | 42 | ## [1.0.2](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.2) / 2017-10-23 43 | - 增加 log 采集的支持 44 | - 增加发送事件之前的持久化存储 45 | - 将自定义事件的发送由单条发送更改为批量发送 46 | - 重构 SDK 的部分代码,提供更好的性能表现 47 | 48 | ## [1.0.1](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.1) / 2017-10-12 49 | - 修复一些 log 采集的 bug 50 | - 重构部分代码,提供更高的效率 51 | - 一些稳定性提升 52 | 53 | ## [1.0.0](https://github.com/pre-dem/pre-dem-cocoa/releases/tag/v1.0.0) / 2017-08-23 54 | * 初始化 55 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDLogger.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDLogger.m 3 | // PreDemObjc 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDLogger.h" 10 | 11 | @implementation PREDLogger 12 | 13 | static PREDLogLevel _currentLogLevel = PREDLogLevelWarning; 14 | static PREDLogHandler currentLogHandler; 15 | 16 | static NSString *levelString(PREDLogLevel logLevel) { 17 | switch (logLevel) { 18 | case PREDLogLevelError: 19 | return @"Error"; 20 | case PREDLogLevelWarning: 21 | return @"Warning"; 22 | case PREDLogLevelInfo: 23 | return @"Info"; 24 | case PREDLogLevelDebug: 25 | return @"Debug"; 26 | case PREDLogLevelVerbose: 27 | return @"Verbose"; 28 | default: 29 | return @""; 30 | } 31 | } 32 | 33 | PREDLogHandler defaultLogHandler = 34 | ^(PREDLogMessageProvider messageProvider, PREDLogLevel logLevel, 35 | const char *file, const char *function, uint line) { 36 | if (messageProvider) { 37 | if (_currentLogLevel < logLevel) { 38 | return; 39 | } 40 | NSLog((@"[PreDemObjc]%@: %s/%d %@"), levelString(logLevel), function, 41 | line, messageProvider()); 42 | } 43 | }; 44 | 45 | + (void)initialize { 46 | currentLogHandler = defaultLogHandler; 47 | } 48 | 49 | + (PREDLogLevel)currentLogLevel { 50 | return _currentLogLevel; 51 | } 52 | 53 | + (void)setCurrentLogLevel:(PREDLogLevel)currentLogLevel { 54 | _currentLogLevel = currentLogLevel; 55 | } 56 | 57 | + (void)setLogHandler:(PREDLogHandler)logHandler { 58 | currentLogHandler = logHandler; 59 | } 60 | 61 | + (void)logMessage:(PREDLogMessageProvider)messageProvider 62 | level:(PREDLogLevel)loglevel 63 | file:(const char *)file 64 | function:(const char *)function 65 | line:(uint)line { 66 | if (currentLogHandler) { 67 | currentLogHandler(messageProvider, loglevel, file, function, line); 68 | } 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /PreDemCocoa/Transaction/PREDTransaction.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDTransaction.m 3 | // CocoaLumberjack 4 | // 5 | // Created by WangSiyu on 21/03/2018. 6 | // 7 | 8 | #import "PREDTransactionPrivate.h" 9 | #import "PREDConstants.h" 10 | #import "PREDSender.h" 11 | 12 | #import "PREDManager.h" 13 | 14 | @implementation PREDTransaction { 15 | PREDSender *_sender; 16 | } 17 | 18 | + (PREDTransaction *)transactionWithSender:(PREDSender *)sender { 19 | PREDTransaction *object = 20 | [[PREDTransaction alloc] initWithName:TransactionEventName 21 | type:CustomEventType]; 22 | object->_sender = sender; 23 | return object; 24 | } 25 | 26 | - (void)complete { 27 | uint64_t endTime = (uint64_t)([[NSDate date] timeIntervalSince1970] * 1000); 28 | self.end_time = endTime; 29 | self.transaction_type = PREDTransactionTypeCompleted; 30 | [_sender persistTransaction:self]; 31 | } 32 | 33 | - (void)cancelWithReason:(NSString *)reason { 34 | uint64_t endTime = (uint64_t)([[NSDate date] timeIntervalSince1970] * 1000); 35 | self.end_time = endTime; 36 | self.transaction_type = PREDTransactionTypeCancelled; 37 | self.reason = reason; 38 | [_sender persistTransaction:self]; 39 | } 40 | 41 | - (void)failWithReason:(NSString *)reason { 42 | uint64_t endTime = (uint64_t)([[NSDate date] timeIntervalSince1970] * 1000); 43 | self.end_time = endTime; 44 | self.transaction_type = PREDTransactionTypeFailed; 45 | self.reason = reason; 46 | [_sender persistTransaction:self]; 47 | } 48 | 49 | @end 50 | 51 | @implementation PREDTransactionQueue 52 | 53 | - (void)setSizeThreshhold:(NSUInteger)size { 54 | } 55 | 56 | - (NSUInteger)sizeThreshhold { 57 | return 10; 58 | } 59 | 60 | - (void)setSendInterval:(NSUInteger)interval { 61 | } 62 | 63 | - (NSUInteger)sendInterval { 64 | return 30; 65 | } 66 | 67 | - (PREDTransaction *_Nonnull)transactionStart: 68 | (NSString *_Nonnull)transactionName { 69 | return [PREDManager transactionStart:transactionName]; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "iphone", 5 | "size": "20x20", 6 | "scale": "2x" 7 | }, 8 | { 9 | "idiom": "iphone", 10 | "size": "20x20", 11 | "scale": "3x" 12 | }, 13 | { 14 | "idiom": "iphone", 15 | "size": "29x29", 16 | "scale": "2x" 17 | }, 18 | { 19 | "idiom": "iphone", 20 | "size": "29x29", 21 | "scale": "3x" 22 | }, 23 | { 24 | "idiom": "iphone", 25 | "size": "40x40", 26 | "scale": "2x" 27 | }, 28 | { 29 | "idiom": "iphone", 30 | "size": "40x40", 31 | "scale": "3x" 32 | }, 33 | { 34 | "idiom": "iphone", 35 | "size": "60x60", 36 | "scale": "2x" 37 | }, 38 | { 39 | "idiom": "iphone", 40 | "size": "60x60", 41 | "scale": "3x" 42 | }, 43 | { 44 | "idiom": "ipad", 45 | "size": "20x20", 46 | "scale": "1x" 47 | }, 48 | { 49 | "idiom": "ipad", 50 | "size": "20x20", 51 | "scale": "2x" 52 | }, 53 | { 54 | "idiom": "ipad", 55 | "size": "29x29", 56 | "scale": "1x" 57 | }, 58 | { 59 | "idiom": "ipad", 60 | "size": "29x29", 61 | "scale": "2x" 62 | }, 63 | { 64 | "idiom": "ipad", 65 | "size": "40x40", 66 | "scale": "1x" 67 | }, 68 | { 69 | "idiom": "ipad", 70 | "size": "40x40", 71 | "scale": "2x" 72 | }, 73 | { 74 | "idiom": "ipad", 75 | "size": "76x76", 76 | "scale": "1x" 77 | }, 78 | { 79 | "idiom": "ipad", 80 | "size": "76x76", 81 | "scale": "2x" 82 | }, 83 | { 84 | "idiom": "ipad", 85 | "size": "83.5x83.5", 86 | "scale": "2x" 87 | }, 88 | { 89 | "idiom": "ios-marketing", 90 | "size": "1024x1024", 91 | "scale": "1x" 92 | } 93 | ], 94 | "info": { 95 | "version": 1, 96 | "author": "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /PreDemCocoa/Core/PREDBaseModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDBaseModel.m 3 | // Pods 4 | // 5 | // Created by 王思宇 on 15/09/2017. 6 | // 7 | // 8 | 9 | #import "PREDBaseModel.h" 10 | #import "NSObject+Serialization.h" 11 | #import "PREDHelper.h" 12 | #import 13 | 14 | @implementation PREDBaseModel 15 | 16 | + (instancetype)eventWithName:(NSString *)name type:(NSString *)type { 17 | return [[self alloc] initWithName:name type:type]; 18 | } 19 | 20 | - (instancetype)initWithName:(NSString *)name type:(NSString *)type { 21 | if (self = [super init]) { 22 | _name = name; 23 | _type = type; 24 | _time = (int64_t)(NSDate.date.timeIntervalSince1970 * 1000); 25 | _app_bundle_id = PREDHelper.appBundleId; 26 | _app_name = PREDHelper.appName; 27 | _app_version = PREDHelper.appVersion; 28 | _device_model = PREDHelper.deviceModel; 29 | _os_platform = PREDHelper.osPlatform; 30 | _os_version = PREDHelper.osVersion; 31 | _os_build = PREDHelper.osBuild; 32 | _sdk_version = PREDHelper.sdkVersion; 33 | _sdk_id = PREDHelper.UUID; 34 | _tag = PREDHelper.tag; 35 | _manufacturer = @"Apple"; 36 | } 37 | return self; 38 | } 39 | 40 | - (NSString *)description { 41 | return [self toDic].description; 42 | } 43 | 44 | - (NSData *)serializeForSending:(NSError **)error { 45 | // 需要同时获取该类及其父类的相关属性值 46 | Class class = self.class; 47 | Class superClass = class_getSuperclass(class); 48 | NSAssert([superClass isEqual:PREDBaseModel.class], 49 | @"%@ should be subclass of PREDBaseModel", class); 50 | NSMutableDictionary *dic = [self toDicForClass:superClass]; 51 | NSMutableDictionary *thisClassDic = [self toDicForClass:class]; 52 | if (thisClassDic.count > 0) { 53 | NSData *data = [NSJSONSerialization dataWithJSONObject:thisClassDic 54 | options:0 55 | error:error]; 56 | if (data) { 57 | dic[@"content"] = 58 | [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 59 | } 60 | } 61 | return [NSJSONSerialization dataWithJSONObject:dic options:0 error:error]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/PREDLogger.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDLogger.h 3 | // PreDemObjc 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDDefines.h" 10 | #import 11 | 12 | #define PREDLog(_level, _message) \ 13 | [PREDLogger logMessage:_message \ 14 | level:_level \ 15 | file:__FILE__ \ 16 | function:__PRETTY_FUNCTION__ \ 17 | line:__LINE__] 18 | 19 | #define PREDLogError(format, ...) \ 20 | PREDLog(PREDLogLevelError, (^{ \ 21 | return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ 22 | })) 23 | #define PREDLogWarning(format, ...) \ 24 | PREDLog(PREDLogLevelWarning, (^{ \ 25 | return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ 26 | })) 27 | #define PREDLogDebug(format, ...) \ 28 | PREDLog(PREDLogLevelDebug, (^{ \ 29 | return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ 30 | })) 31 | #define PREDLogVerbose(format, ...) \ 32 | PREDLog(PREDLogLevelVerbose, (^{ \ 33 | return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \ 34 | })) 35 | 36 | @interface PREDLogger : NSObject 37 | 38 | + (PREDLogLevel)currentLogLevel; 39 | + (void)setCurrentLogLevel:(PREDLogLevel)currentLogLevel; 40 | + (void)setLogHandler:(PREDLogHandler)logHandler; 41 | 42 | + (void)logMessage:(PREDLogMessageProvider)messageProvider 43 | level:(PREDLogLevel)loglevel 44 | file:(const char *)file 45 | function:(const char *)function 46 | line:(uint)line; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /PreDemCocoa/Core/PREDCustomEvent.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDEvent.m 3 | // PreDemCocoa 4 | // 5 | // Created by Troy on 2017/9/27. 6 | // 7 | 8 | #import "PREDCustomEvent.h" 9 | #import "NSObject+Serialization.h" 10 | #import "PREDConstants.h" 11 | #import "PREDLogger.h" 12 | 13 | #import "PREDManager.h" 14 | 15 | @implementation PREDCustomEvent 16 | 17 | + (instancetype)eventWithName:(NSString *)name 18 | contentDic:(NSDictionary *)contentDic { 19 | return [self eventWithName:name type:CustomEventType contentDic:contentDic]; 20 | } 21 | 22 | + (instancetype)eventWithName:(NSString *)name 23 | type:(NSString *)type 24 | contentDic:(NSDictionary *)contentDic { 25 | PREDCustomEvent *event = [self eventWithName:name type:type]; 26 | if (event) { 27 | if (!name.length) { 28 | PREDLogError(@"event name should not be empty"); 29 | return nil; 30 | } 31 | 32 | NSError *error; 33 | 34 | NSString *content; 35 | if (contentDic.count) { 36 | NSData *contentData = [NSJSONSerialization dataWithJSONObject:contentDic 37 | options:0 38 | error:&error]; 39 | if (error) { 40 | PREDLogError(@"jsonize custom events error: %@", error); 41 | return nil; 42 | } else if (!contentData.length) { 43 | PREDLogWarning(@"discard empty custom event"); 44 | return nil; 45 | } 46 | 47 | content = [[NSString alloc] initWithData:contentData 48 | encoding:NSUTF8StringEncoding]; 49 | } else { 50 | content = @""; 51 | } 52 | 53 | event->_content = content; 54 | } 55 | 56 | return event; 57 | } 58 | 59 | - (NSData *)serializeForSending:(NSError **)error { 60 | return [self toJsonWithError:error]; 61 | } 62 | 63 | @end 64 | 65 | @implementation PREDEventQueue 66 | - (void)setSizeThreshhold:(NSUInteger)size { 67 | } 68 | 69 | - (NSUInteger)sizeThreshhold { 70 | return 10; 71 | } 72 | 73 | - (void)setSendInterval:(NSUInteger)interval { 74 | } 75 | 76 | - (NSUInteger)sendInterval { 77 | return 30; 78 | } 79 | 80 | - (void)trackCustomEvent:(PREDCustomEvent *_Nonnull)event { 81 | [PREDManager trackCustomEvent:event]; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PreDemObjcDemo 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application 18 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. 25 | // This can occur for certain types of temporary interruptions (such as an 26 | // incoming phone call or SMS message) or when the user quits the application 27 | // and it begins the transition to the background state. 28 | // Use this method to pause ongoing tasks, disable timers, and invalidate 29 | // graphics rendering callbacks. Games should use this method to pause the 30 | // game. 31 | } 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application { 34 | // Use this method to release shared resources, save user data, invalidate 35 | // timers, and store enough application state information to restore your 36 | // application to its current state in case it is terminated later. 37 | // If your application supports background execution, this method is called 38 | // instead of applicationWillTerminate: when the user quits. 39 | } 40 | 41 | - (void)applicationWillEnterForeground:(UIApplication *)application { 42 | // Called as part of the transition from the background to the active state; 43 | // here you can undo many of the changes made on entering the background. 44 | } 45 | 46 | - (void)applicationDidBecomeActive:(UIApplication *)application { 47 | // Restart any tasks that were paused (or not yet started) while the 48 | // application was inactive. If the application was previously in the 49 | // background, optionally refresh the user interface. 50 | } 51 | 52 | - (void)applicationWillTerminate:(UIApplication *)application { 53 | // Called when the application is about to terminate. Save data if 54 | // appropriate. See also applicationDidEnterBackground:. 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemSwiftDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // PreDemSwiftDemo 4 | // 5 | // Created by 王思宇 on 05/09/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import PreDemCocoa 11 | 12 | class ViewController: UIViewController { 13 | 14 | enum CustomError: Error { 15 | case CustomError(String) 16 | } 17 | 18 | @IBOutlet var versionLable: UILabel! 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | // Do any additional setup after loading the view, typically from a nib. 23 | versionLable.text = "\(PREDManager.version())(\(PREDManager.build()))" 24 | } 25 | 26 | override func viewWillAppear(_ animated: Bool) { 27 | super.viewWillAppear(animated) 28 | self.navigationController?.isNavigationBarHidden = true 29 | } 30 | 31 | override func didReceiveMemoryWarning() { 32 | super.didReceiveMemoryWarning() 33 | // Dispose of any resources that can be recreated. 34 | } 35 | 36 | @IBAction func sendHttpRequest(sender: Any) { 37 | let urls = [ 38 | "http://www.baidu.com", 39 | "https://www.163.com", 40 | "http://www.qq.com", 41 | "https://www.dehenglalala.com", 42 | "http://www.balabalabalatest.com", 43 | "http://www.alipay.com", 44 | ] 45 | for urlString in urls { 46 | if let url = URL(string: urlString) { 47 | URLSession.shared.dataTask(with: URLRequest.init(url: url), completionHandler: { (_, response, _) in 48 | print("response \(response?.url?.absoluteString ?? "")") 49 | }).resume() 50 | } else { 51 | print("url not valid \(urlString)") 52 | } 53 | } 54 | } 55 | 56 | @IBAction func diagnoseNetwork(sender: Any) { 57 | PREDManager.diagnose("www.qiniu.com") { (result) in 58 | print("new diagnose completed with result:\n\(result)") 59 | } 60 | } 61 | 62 | @IBAction func diyEvent(sender: Any) { 63 | if let event = PREDCustomEvent(name: "viewDidLoadEvent", contentDic: ["helloKey": "worldValue", "hellonum": 7]) { 64 | PREDManager.trackCustomEvent(event) 65 | } 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemSwiftDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PreDemSwiftDemo 4 | // 5 | // Created by 王思宇 on 05/09/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /PreDemCocoa/Public/PREDBaseModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // PREDBaseModel.h 3 | // Pods 4 | // 5 | // Created by 王思宇 on 15/09/2017. 6 | // 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 上报数据的基类,包装一些基本信息 13 | */ 14 | @interface PREDBaseModel : NSObject 15 | 16 | /** 17 | * 自定义事件的名称 18 | */ 19 | @property(nonatomic, strong, readonly) NSString *name; 20 | 21 | /** 22 | * 事件的类型,自定义事件恒为 @"custom" 23 | */ 24 | @property(nonatomic, strong, readonly) NSString *type; 25 | 26 | /** 27 | * 事件生成的时间 28 | */ 29 | @property(nonatomic, assign) int64_t time; 30 | 31 | /** 32 | * 宿主 app 的包名,即宿主 app 的 CFBundleIdentifier 属性 33 | */ 34 | @property(nonatomic, strong) NSString *app_bundle_id; 35 | 36 | /** 37 | * 宿主 app 的名称,即宿主 app 的 CFBundleName 属性 38 | */ 39 | @property(nonatomic, strong) NSString *app_name; 40 | 41 | /** 42 | * 宿主 app 的版本,即宿主 app 的 CFBundleShortVersionString 属性 43 | */ 44 | @property(nonatomic, strong) NSString *app_version; 45 | 46 | /** 47 | * 宿主 app 的型号 48 | */ 49 | @property(nonatomic, strong) NSString *device_model; 50 | 51 | /** 52 | * 宿主 app 的平台 53 | */ 54 | @property(nonatomic, strong) NSString *os_platform; 55 | 56 | /** 57 | * 宿主 app 的系统版本号 58 | */ 59 | @property(nonatomic, strong) NSString *os_version; 60 | 61 | /** 62 | * 宿主 app 的构建号 63 | */ 64 | @property(nonatomic, strong) NSString *os_build; 65 | 66 | /** 67 | * sdk 的版本号 68 | */ 69 | @property(nonatomic, strong) NSString *sdk_version; 70 | 71 | /** 72 | * 设备及 app 唯一的识别号 73 | */ 74 | @property(nonatomic, strong) NSString *sdk_id; 75 | 76 | /** 77 | * 用户标签,与 PREDManager 设置的一致 78 | */ 79 | @property(nonatomic, strong) NSString *tag; 80 | 81 | /** 82 | * 设备制造商 83 | */ 84 | @property(nonatomic, strong) NSString *manufacturer; 85 | 86 | /** 87 | * 生成一个事件对象 88 | * 89 | * @param name 事件的名称 90 | * @param type 事件的类型 91 | */ 92 | + (instancetype)eventWithName:(NSString *)name type:(NSString *)type; 93 | 94 | /** 95 | * 初始化一个事件对象 96 | * 97 | * @param name 事件的名称 98 | * @param type 事件的类型 99 | */ 100 | - (instancetype)initWithName:(NSString *)name type:(NSString *)type; 101 | 102 | /** 103 | * 将事件序列化供发送 104 | */ 105 | - (NSData *)serializeForSending:(NSError **)error; 106 | 107 | @end 108 | 109 | @protocol PREDSerializeData 110 | 111 | /** 112 | * 将事件序列化供发送 113 | */ 114 | - (NSData *)serializeForSending:(NSError **)error; 115 | 116 | @end -------------------------------------------------------------------------------- /PreDemCocoa/Config/PREDConfigManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDConfig.m 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 10/05/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDConfigManager.h" 10 | #import "PREDSender.h" 11 | 12 | #define PREDConfigUserDefaultsKey @"PREDConfigUserDefaultsKey" 13 | 14 | NSString *kPREDConfigRefreshedNotification = @"com.qiniu.predem.config"; 15 | NSString *kPREDConfigRefreshedNotificationConfigKey = 16 | @"com.qiniu.predem.config"; 17 | 18 | @interface PREDConfigManager () 19 | 20 | @property(nonatomic, strong) NSDate *lastReportTime; 21 | 22 | @end 23 | 24 | @implementation PREDConfigManager { 25 | PREDSender *_sender; 26 | } 27 | 28 | - (instancetype)initWithSender:(PREDSender *)sender { 29 | if (self = [super init]) { 30 | _sender = sender; 31 | [[NSNotificationCenter defaultCenter] 32 | addObserver:self 33 | selector:@selector(didBecomeActive:) 34 | name:UIApplicationDidBecomeActiveNotification 35 | object:nil]; 36 | [[NSNotificationCenter defaultCenter] 37 | addObserver:self 38 | selector:@selector(configRefreshed:) 39 | name:kPREDConfigRefreshedNotificationConfigKey 40 | object:nil]; 41 | } 42 | return self; 43 | } 44 | 45 | - (void)dealloc { 46 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 47 | } 48 | 49 | - (PREDConfig *)getConfig { 50 | PREDConfig *defaultConfig; 51 | // 优先获取保存在 UserDefaults 中的配置 52 | NSDictionary *dic = [NSUserDefaults.standardUserDefaults 53 | objectForKey:PREDConfigUserDefaultsKey]; 54 | if (dic && [dic respondsToSelector:@selector(objectForKey:)]) { 55 | defaultConfig = [PREDConfig configWithDic:dic]; 56 | } else { 57 | defaultConfig = PREDConfig.defaultConfig; 58 | } 59 | 60 | [_sender sendAppInfo:nil]; 61 | 62 | return defaultConfig; 63 | } 64 | 65 | - (void)didBecomeActive:(NSNotification *)noty { 66 | // 每天只获取一次 67 | if (self.lastReportTime && 68 | [[NSDate date] timeIntervalSinceDate:self.lastReportTime] >= 69 | 60 * 60 * 12) { 70 | [self getConfig]; 71 | } 72 | } 73 | 74 | - (void)configRefreshed:(NSNotification *)noty { 75 | // 将获取到的配置保存在 UserDefaults 中 76 | NSDictionary *dic = noty.userInfo[kPREDConfigRefreshedNotificationConfigKey]; 77 | [NSUserDefaults.standardUserDefaults setObject:dic 78 | forKey:PREDConfigUserDefaultsKey]; 79 | self.lastReportTime = [NSDate date]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemSwiftDemo/WebViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewController.swift 3 | // PreDemSwiftDemo 4 | // 5 | // Created by WangSiyu on 28/11/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import WebKit 11 | 12 | class WebViewController: UIViewController, UITextFieldDelegate { 13 | var urlTextField = UITextField(frame: CGRect(x: 0, y: 0, width: 150, height: 30)) 14 | var webView: UIWebView! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | webView = UIWebView(frame: self.view.frame) 19 | self.view.addSubview(webView) 20 | urlTextField.placeholder = "请输入 URL" 21 | urlTextField.keyboardType = .URL 22 | urlTextField.returnKeyType = .go 23 | urlTextField.textContentType = .URL 24 | urlTextField.clearButtonMode = .whileEditing 25 | urlTextField.delegate = self 26 | self.navigationItem.titleView = urlTextField 27 | } 28 | 29 | override func viewWillAppear(_ animated: Bool) { 30 | super.viewWillAppear(animated) 31 | self.navigationController?.isNavigationBarHidden = false 32 | } 33 | 34 | @objc func didPressedCancelButton() { 35 | urlTextField.resignFirstResponder() 36 | self.navigationItem.rightBarButtonItem = nil 37 | } 38 | 39 | func textFieldDidBeginEditing(_ textField: UITextField) { 40 | self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "取消", style: .plain, target: self, action: #selector(didPressedCancelButton)) 41 | } 42 | 43 | func textFieldShouldReturn(_ textField: UITextField) -> Bool { 44 | if let text = textField.text { 45 | if text.count == 0 { 46 | let controller = UIAlertController(title: "错误", message: "请输入您要访问的 url", preferredStyle: .alert) 47 | controller.addAction(UIAlertAction(title: "好的", style: .default, handler: nil)) 48 | return false 49 | } 50 | 51 | urlTextField.resignFirstResponder() 52 | self.navigationItem.rightBarButtonItem = nil 53 | if var url = URL(string: text) { 54 | if url.scheme == nil { 55 | if let x = URL(string: "http://\(url.absoluteString)") { 56 | url = x 57 | } 58 | } 59 | webView.loadRequest(URLRequest(url: url)) 60 | } 61 | 62 | return true 63 | } else { 64 | return false 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## PreDemCocoa 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2011-2016 Qiniu, Ltd. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | 29 | ## UICKeyChainStore 30 | 31 | The MIT License 32 | 33 | Copyright (c) 2011 kishikawa katsumi 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 36 | 37 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 38 | 39 | 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. 40 | Generated by CocoaPods - https://cocoapods.org 41 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Pods-PreDemCocoaTests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## PreDemCocoa 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2011-2016 Qiniu, Ltd. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | 29 | ## UICKeyChainStore 30 | 31 | The MIT License 32 | 33 | Copyright (c) 2011 kishikawa katsumi 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 36 | 37 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 38 | 39 | 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. 40 | Generated by CocoaPods - https://cocoapods.org 41 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Pods-PreDemSwiftDemo-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## PreDemCocoa 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2011-2016 Qiniu, Ltd. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | 29 | ## UICKeyChainStore 30 | 31 | The MIT License 32 | 33 | Copyright (c) 2011 kishikawa katsumi 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 36 | 37 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 38 | 39 | 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. 40 | Generated by CocoaPods - https://cocoapods.org 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode9 3 | env: 4 | global: 5 | - secure: bO3AZL7z6yWd3+1Rs1nMQQWIwKie4ibJ9ms+KOa9uwnrsQ2RYYzcK6kk3SYErY6QzUPnwafPcjbwJKN0B6GLeZ4sNEV3fwME2pzhRpG7kOL7RP+J8lBk7pUmd1E3xwSwBz1q+qdLq5N+lhi+SndkiXP6AnyD4UWJkWQJPjBSne2/9f/2YE4123M/5AFQBHniiUsqqRsc8WjmP7iNmD3Pil7CJHdPBlsqc1L/uYvzdRatEohmG1GdUAwfbnwldzJljcF514C+hAPTsCkob1hXPWc7sXFLx/atW1C7LglvJn0t0eP6POwdKBzt4UYzZvuGsfF8UrzLXsw1mds+e6PJXuAzqI6kOOgyXxTOcqlvwlHcYf7ad1zikHVZM/+Wx98fWeNUSQ5GwGFFhiMUhSHZUMGiwO6ThdFOjcylpWrD3B5nyqAUCdVrK0mARAhE64GDeLNNLgUB4Y99eCaHaV1KSIWoAzPbjJIapeaaqu0jIKp9PUyfBFyOIJlCpmgaPPvO1SNYCX/hj5g3OSogfrMK5oI1Hdz27xczA+rMRfQ0PE6kzpGGY/8RoGEMIHxmcZ+FPBSFtngwZk8lwEKtPrAQ5pob48H3cdGqEOSWr3CY3jHW4lbntHrymuJfUK1S94r0rqxlDpjGotOt3rIku5wh2ydF/81Cz/a2RWMB39Eczwk= 6 | - secure: me1Mwpk/mHqTIa23hk1esxlP0nq4Z/P1kf5tP66uhZe/xsHmt7/DPJbvV2lXffiGcmgodcUnxyDCd6DyRZ8q/OH/bItK0MegLFsZpRJ/vAvi0klPpK/LolR/zwJAaSOE5Y7/mudQoP1YGPxTMJNUYhfG6iTgtdGz97nyNCczudImJDeSStzRSlTfm7CEL9tCnTY72OcNdwV0KH2gvzp73u+AVg7RNdS87QM9lj5QPfMKe3WE+uYYDGSYRMtaw4IrEx1yP1BDNW/hh2B8cNgfdvRMcWRyUIR9C6RyGf1zhawH4kFKGDfeo0gAXiIZjr9Kj1TSQDUhOARR1pzNDUv7cyvR5CJ44XHnLNB/aBsATXO/LIoIyc8zMEsFapiyw1zY52ErRbpzUkluuCJuREJtg5egtSQpMl8gDssqxVwgRo07S9JNw6e5ARmjpWo4l/9tgNowylVJ1l6jmxvH3vn+klG2hRrTywWmG8riUjdXJoAvsBGFG0FeaVOmj9ofddYvuhXqQXAz/qX2Si8GqJFMA7dTW49xZCb5ytHUJy5oMzwnqIBV9csfNM9nGrRy9TKkxyqrQlA9BLOBrm3tQWUbXguRYH+I3SGzx3+YolrwtKfkH8x6S8tRjE4SdyytIQVVuDPC/Jsa1aIvw35RyL2W1ZyMlbqJTPOL0rZp/WA33Wk= 7 | - secure: Q/96zlyxCD2tIVYWlsf945up33d2ieRA1GHGzfIyRg7EKDLWJPkxmIWy/gD/1fdKDAeuj6HsFS7rrEiGTivvfcSxq8XqpD/CLxgd9D1BVHV8Scn9BNNveiL86FpVVslQXw5toE5JyNFcvqk2Jm0jOP2h5XQ6mTei+ox9v/vUFAilEr+BynD4YukyLSamdHWaul1wiqnldAc9wTFPWD2CcrCTqlF5RQvJnzrYksXspXvjp5D9alAixRoFAn+eJ5b0sf13Nn1u+NbDNd3sPPHNcz+Kv5Nwl6+x4414z55iHNyKEo9X82XpwmaSa2wLzS5bwZj87D7mEmBXJV6O7L//+Lpe9UKd6oMxjt6kz+RMd5qLVQpR7J8rzMxMHtYWVTMct2n1uzu3E9ze3klIfx+8ISoB4hfQY/cQ3ENyR4dhR3LexaZAP8IFZnia2iS33KBDugLIVezL4vO/KaL0Lj877AkNlpZ51jMLugliriL6O8PLEjcJLob9kRpOg2otwtfXyY+nQgHTAmXT9OwpgSFNXwy3pcsmbq9gx6y0lWA33ksYsBt7BHGSfKUiQjN8zEh47dy23PjQP+n3cE1ZlaS5RDhTXTsHc0EKqNDhhPfs7H4Zhd6zWu71WHFZAcukJmP+FaeyxI+mqitKMX6blR1v2I4Unx1zVfkb7IIPZb/nH6o= 8 | - secure: wQSsHT7Nh5Fjy80ebUy/Il/uFxM5jvCDX7/eeOp6rKCEXXjrxEANP3VoqhyAPPSmdtgyn5IZTIzQgYwICr4WND3JJhr4CUBdt27/BChGLMRU20L+cyD+zxzylmBHrR9dbiYzsSKEPw9LKx2vLXeYxGnRGRzt8Ur8wnp/48fhDOPLGSaNszcqKwbFPOPewVfYiHK1I9DR+q1x5P+nvmSsNEcs05aoIUqZVQ6hYjN3MA8L2iccg1dJfRX72Nf8aflsSCCdYwtVuJlzoTLyt9foUIo4jriYU3h7yfx6746ASOLTsQptOhHgbH+bVaW1ZlMjgw2mu/6k1d0ANbZX16evc/amgfaxcb0k6rYNRpSAjs4Id3XI93g6nCV2eRdjfZGLA7dAY8kBnTD6Nk8DLgIuTZYXTTcc/IdS4m4IJNPmZHtervRcNiAM6kc4sBmee1l6HPP8dnVrXVZcExGWBsm5FW5BZgY9dQcInBGClnjAi26hp69eHChuOURB2azuHA8MDrZ0yx0oJK+tw0Vvp5y1q7vyv0V5keLpbezSOdLksRkJH0bsC6dDrN15JKziZ1+6i2zbPNUdzf0Wh2p/FQ152GQHA6gKATiBCMA25IkQarIRoAs5PGT1ia4D5uXLJeWaGKow/WRz8XA49bANoGb4Xyen8b2q+ZNLDcTNTnQGePA= 9 | script: 10 | - "./scripts/travis.sh" 11 | after_success: 12 | - bash <(curl -s https://codecov.io/bash) 13 | -------------------------------------------------------------------------------- /PreDemCocoa/Helper/NSObject+Serialization.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Serialization.m 3 | // Pods 4 | // 5 | // Created by 王思宇 on 18/09/2017. 6 | // 7 | // 8 | 9 | #import "NSObject+Serialization.h" 10 | #import "PREDError.h" 11 | #import 12 | 13 | @implementation NSObject (Serialization) 14 | 15 | - (NSData *)toJsonWithError:(NSError **)error { 16 | NSDictionary *dic; 17 | if ([self isKindOfClass:[NSDictionary class]]) { 18 | dic = (NSDictionary *)self; 19 | } else { 20 | dic = [self toDic]; 21 | } 22 | NSData *data; 23 | @try { 24 | data = [NSJSONSerialization dataWithJSONObject:dic options:0 error:error]; 25 | } @catch (NSException *exception) { 26 | *error = [PREDError GenerateNSError:kPREDErrorCodeInvalidJsonObject 27 | description:exception.reason]; 28 | } @finally { 29 | return data; 30 | } 31 | } 32 | 33 | - (NSMutableDictionary *)toDic { 34 | Class class = self.class; 35 | NSMutableDictionary *dic = [NSMutableDictionary dictionary]; 36 | while (class != NSObject.class) { 37 | [dic addEntriesFromDictionary:[self toDicForClass:class]]; 38 | class = class_getSuperclass(class); 39 | } 40 | return dic; 41 | } 42 | 43 | - (NSMutableDictionary *)toDicForClass:(Class) class { 44 | NSMutableDictionary *dic = [NSMutableDictionary dictionary]; 45 | unsigned int propsCount; 46 | 47 | objc_property_t *props = class_copyPropertyList(class, &propsCount); 48 | 49 | for (int i = 0; i < propsCount; i++) { 50 | 51 | objc_property_t prop = props[i]; 52 | NSString *propName = [NSString stringWithUTF8String:property_getName(prop)]; 53 | id value = [self valueForKey:propName]; 54 | if (value != nil) { 55 | value = [self getObjectInternal:value]; 56 | dic[propName] = value; 57 | } 58 | } 59 | 60 | if (props) { 61 | free(props); 62 | } 63 | return dic; 64 | } 65 | 66 | - (id)getObjectInternal : (id)obj { 67 | 68 | if ([obj isKindOfClass:[NSString class]] || 69 | [obj isKindOfClass:[NSNumber class]] || 70 | [obj isKindOfClass:[NSNull class]]) { 71 | 72 | return obj; 73 | } 74 | if ([obj isKindOfClass:[NSArray class]]) { 75 | 76 | NSArray *objarr = obj; 77 | NSMutableArray *arr = [NSMutableArray arrayWithCapacity:objarr.count]; 78 | 79 | for (int i = 0; i < objarr.count; i++) { 80 | 81 | arr[i] = [self getObjectInternal:[objarr objectAtIndex:i]]; 82 | } 83 | return arr; 84 | } 85 | if ([obj isKindOfClass:[NSDictionary class]]) { 86 | 87 | NSDictionary *objdic = obj; 88 | NSMutableDictionary *dic = 89 | [NSMutableDictionary dictionaryWithCapacity:[objdic count]]; 90 | 91 | for (NSString *key in objdic.allKeys) { 92 | 93 | dic[key] = [self getObjectInternal:[objdic objectForKey:key]]; 94 | } 95 | return dic; 96 | } 97 | return [self toDic]; 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/AppIDViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppIDViewController.m 3 | // PreDemObjcDemo 4 | // 5 | // Created by 王思宇 on 8/1/17. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "AppIDViewController.h" 10 | #import "PreDemCocoa/PreDemCocoa.h" 11 | #import 12 | 13 | @interface AppIDViewController () 14 | 15 | @property(nonatomic, strong) IBOutlet UITextField *appIdTextField; 16 | @property(nonatomic, strong) IBOutlet UITextField *domainTextField; 17 | 18 | @end 19 | 20 | @implementation AppIDViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view. 25 | UICKeyChainStore *keychain = 26 | [UICKeyChainStore keyChainStoreWithService:@"com.qiniu.pre.demo"]; 27 | NSString *prevID = keychain[@"appid"]; 28 | NSString *prevDomain = keychain[@"domain"]; 29 | if (prevID) { 30 | _appIdTextField.text = prevID; 31 | } 32 | if (prevDomain) { 33 | _domainTextField.text = prevDomain; 34 | } 35 | } 36 | 37 | - (void)viewWillAppear:(BOOL)animated { 38 | [super viewWillAppear:animated]; 39 | self.navigationController.navigationBarHidden = YES; 40 | } 41 | 42 | - (void)didReceiveMemoryWarning { 43 | [super didReceiveMemoryWarning]; 44 | // Dispose of any resources that can be recreated. 45 | } 46 | 47 | - (IBAction)tapped:(id)sender { 48 | [_appIdTextField resignFirstResponder]; 49 | [_domainTextField resignFirstResponder]; 50 | } 51 | 52 | - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier 53 | sender:(id)sender { 54 | if (_appIdTextField.text.length < 8 || _domainTextField.text.length == 0) { 55 | UIAlertController *alert = [UIAlertController 56 | alertControllerWithTitle:@"出错啦" 57 | message: 58 | @"appID 必须在8位以上,domain 不能为空,才能继续哦" 59 | preferredStyle:UIAlertControllerStyleAlert]; 60 | [alert addAction:[UIAlertAction actionWithTitle:@"好的" 61 | style:UIAlertActionStyleDefault 62 | handler:nil]]; 63 | [self presentViewController:alert animated:YES completion:nil]; 64 | return NO; 65 | } else { 66 | return YES; 67 | } 68 | } 69 | 70 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 71 | UICKeyChainStore *keychain = 72 | [UICKeyChainStore keyChainStoreWithService:@"com.qiniu.pre.demo"]; 73 | keychain[@"appid"] = _appIdTextField.text; 74 | keychain[@"domain"] = _domainTextField.text; 75 | #ifdef DEBUG 76 | [PREDManager startWithAppKey:_appIdTextField.text 77 | serviceDomain:_domainTextField.text]; 78 | PREDManager.tag = @"userid_debug"; 79 | #else 80 | [PREDManager startWithAppKey:_appIdTextField.text 81 | serviceDomain:_domainTextField.text]; 82 | PREDManager.tag = @"userid_release"; 83 | #endif 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /PreDemCocoa/Sender/PREDHTTPOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDHTTPOperation.m 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDHTTPOperation.h" 10 | 11 | @implementation PREDHTTPOperation { 12 | NSURLRequest *_URLRequest; 13 | NSURLSessionDataTask *_task; 14 | } 15 | 16 | @synthesize data = _data; 17 | @synthesize executing = _isExecuting; 18 | @synthesize finished = _isFinished; 19 | 20 | + (instancetype)operationWithRequest:(NSURLRequest *)urlRequest { 21 | PREDHTTPOperation *op = (PREDHTTPOperation *)[[self class] new]; 22 | op->_URLRequest = urlRequest; 23 | return op; 24 | } 25 | 26 | #pragma mark - NSOperation overrides 27 | 28 | - (BOOL)isAsynchronous { 29 | return YES; 30 | } 31 | 32 | - (void)cancel { 33 | [_task cancel]; 34 | [super cancel]; 35 | } 36 | 37 | - (void)completeWithData:(NSData *_Nullable)data 38 | response:(NSURLResponse *_Nullable)response 39 | error:(NSError *_Nullable)error { 40 | _response = (NSHTTPURLResponse *)response; 41 | if (error) { 42 | _error = error; 43 | } else { 44 | _data = data; 45 | } 46 | [self finish]; 47 | } 48 | 49 | - (void)start { 50 | if (self.isCancelled) { 51 | [self finish]; 52 | return; 53 | } 54 | 55 | [self willChangeValueForKey:@"isExecuting"]; 56 | _isExecuting = YES; 57 | [self didChangeValueForKey:@"isExecuting"]; 58 | 59 | _task = [[NSURLSession sharedSession] 60 | dataTaskWithRequest:_URLRequest 61 | completionHandler:^(NSData *_Nullable data, 62 | NSURLResponse *_Nullable response, 63 | NSError *_Nullable error) { 64 | [self completeWithData:data response:response error:error]; 65 | }]; 66 | [_task resume]; 67 | } 68 | 69 | - (void)finish { 70 | [self willChangeValueForKey:@"isExecuting"]; 71 | [self willChangeValueForKey:@"isFinished"]; 72 | _isExecuting = NO; 73 | _isFinished = YES; 74 | [self didChangeValueForKey:@"isExecuting"]; 75 | [self didChangeValueForKey:@"isFinished"]; 76 | } 77 | 78 | #pragma mark - Public interface 79 | 80 | - (void)setCompletion:(PREDNetworkCompletionBlock)completion { 81 | if (!completion) { 82 | [super setCompletionBlock:nil]; 83 | } else { 84 | __weak typeof(self) weakSelf = self; 85 | [super setCompletionBlock:^{ 86 | typeof(self) strongSelf = weakSelf; 87 | if (strongSelf) { 88 | dispatch_async(dispatch_get_main_queue(), ^{ 89 | if (!strongSelf.isCancelled) { 90 | completion(strongSelf, strongSelf->_data, strongSelf->_error); 91 | } 92 | [strongSelf setCompletionBlock:nil]; 93 | }); 94 | } 95 | }]; 96 | } 97 | } 98 | 99 | - (BOOL)isFinished { 100 | return _isFinished; 101 | } 102 | 103 | - (BOOL)isExecuting { 104 | return _isExecuting; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/WebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewController.m 3 | // PreDemObjcDemo 4 | // 5 | // Created by WangSiyu on 02/11/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "WebViewController.h" 10 | 11 | @interface WebViewController () 12 | 13 | @property(strong, nonatomic) UITextField *urlTextField; 14 | @property(strong, nonatomic) UIWebView *webView; 15 | 16 | @end 17 | 18 | @implementation WebViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view. 23 | _webView = [[UIWebView alloc] initWithFrame:self.view.frame]; 24 | [self.view addSubview:_webView]; 25 | _urlTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 150, 30)]; 26 | _urlTextField.placeholder = @"请输入 URL"; 27 | _urlTextField.keyboardType = UIKeyboardTypeURL; 28 | _urlTextField.returnKeyType = UIReturnKeyGo; 29 | _urlTextField.textContentType = UITextContentTypeURL; 30 | _urlTextField.clearButtonMode = UITextFieldViewModeWhileEditing; 31 | _urlTextField.delegate = self; 32 | self.navigationItem.titleView = _urlTextField; 33 | } 34 | 35 | - (void)viewWillAppear:(BOOL)animated { 36 | [super viewWillAppear:animated]; 37 | self.navigationController.navigationBarHidden = NO; 38 | } 39 | 40 | - (void)didReceiveMemoryWarning { 41 | [super didReceiveMemoryWarning]; 42 | // Dispose of any resources that can be recreated. 43 | } 44 | 45 | - (void)didPressedCancelButton { 46 | [_urlTextField resignFirstResponder]; 47 | self.navigationItem.rightBarButtonItem = nil; 48 | } 49 | 50 | - (void)textFieldDidBeginEditing:(UITextField *)textField { 51 | self.navigationItem.rightBarButtonItem = 52 | [[UIBarButtonItem alloc] initWithTitle:@"取消" 53 | style:UIBarButtonItemStylePlain 54 | target:self 55 | action:@selector(didPressedCancelButton)]; 56 | } 57 | 58 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 59 | if (!textField.text.length) { 60 | UIAlertController *controller = [UIAlertController 61 | alertControllerWithTitle:@"错误" 62 | message:@"请输入您要访问的 url" 63 | preferredStyle:UIAlertControllerStyleAlert]; 64 | [controller 65 | addAction:[UIAlertAction actionWithTitle:@"好的" 66 | style:UIAlertActionStyleDefault 67 | handler:nil]]; 68 | [self presentViewController:controller animated:YES completion:nil]; 69 | return NO; 70 | } 71 | [_urlTextField resignFirstResponder]; 72 | self.navigationItem.rightBarButtonItem = nil; 73 | NSURL *url = [NSURL URLWithString:textField.text]; 74 | if (!url.scheme) { 75 | url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@", 76 | url.absoluteString]]; 77 | } 78 | [_webView loadRequest:[NSURLRequest requestWithURL:url]]; 79 | return YES; 80 | } 81 | 82 | /* 83 | #pragma mark - Navigation 84 | 85 | // In a storyboard-based application, you will often want to do a little 86 | preparation before navigation 87 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 88 | // Get the new view controller using [segue destinationViewController]. 89 | // Pass the selected object to the new view controller. 90 | } 91 | */ 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemObjcDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // PreDemObjcDemo 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | 12 | @interface ViewController () 13 | 14 | @property(nonatomic, strong) IBOutlet UILabel *versionLable; 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view, typically from a nib. 23 | self.versionLable.text = [NSString 24 | stringWithFormat:@"%@(%@)", PREDManager.version, PREDManager.build]; 25 | } 26 | 27 | - (void)viewWillAppear:(BOOL)animated { 28 | [super viewWillAppear:animated]; 29 | self.navigationController.navigationBarHidden = YES; 30 | } 31 | 32 | - (IBAction)sendHTTPRequest:(id)sender { 33 | NSArray *urls = @[ 34 | @"http://www.baidu.com", 35 | @"https://www.163.com", 36 | @"http://www.qq.com", 37 | @"https://www.dehenglalala.com", 38 | @"http://www.balabalabalatest.com", 39 | @"http://www.alipay.com" 40 | ]; 41 | for (NSString *urlString in urls) { 42 | dispatch_async( 43 | dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 44 | NSURL *url = [NSURL URLWithString:urlString]; 45 | NSURLRequest *request = [NSURLRequest requestWithURL:url]; 46 | NSURLSession *session = [NSURLSession sharedSession]; 47 | NSURLSessionDataTask *task = [session dataTaskWithRequest:request]; 48 | [task resume]; 49 | }); 50 | } 51 | } 52 | 53 | - (IBAction)diagnoseNetwork:(id)sender { 54 | } 55 | 56 | - (IBAction)diyEvent:(id)sender { 57 | NSDictionary *dict = @{ 58 | @"stringKey" : 59 | [NSString stringWithFormat:@"test\t_\n%d", arc4random_uniform(100)], 60 | @"longKey" : @(arc4random_uniform(100)), 61 | @"floatKey" : @(arc4random_uniform(10000) / 100.0) 62 | }; 63 | PREDCustomEvent *event = 64 | [PREDCustomEvent eventWithName:@"test\t_\nios\t_\nevent_2" 65 | contentDic:dict]; 66 | [PREDManager trackCustomEvent:event]; 67 | } 68 | 69 | - (IBAction)completeTransaction:(id)sender { 70 | PREDTransaction *transaction = [PREDManager transactionStart:@"test"]; 71 | dispatch_after( 72 | dispatch_time(DISPATCH_TIME_NOW, arc4random() % 10 * NSEC_PER_SEC), 73 | dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 74 | [transaction complete]; 75 | }); 76 | } 77 | 78 | - (IBAction)failTransaction:(id)sender { 79 | PREDTransaction *transaction = [PREDManager transactionStart:@"test"]; 80 | dispatch_after( 81 | dispatch_time(DISPATCH_TIME_NOW, arc4random() % 10 * NSEC_PER_SEC), 82 | dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 83 | [transaction failWithReason:@"test reason for failed transaction"]; 84 | }); 85 | } 86 | 87 | - (IBAction)calcelTransaction:(id)sender { 88 | PREDTransaction *transaction = [PREDManager transactionStart:@"test"]; 89 | dispatch_after( 90 | dispatch_time(DISPATCH_TIME_NOW, arc4random() % 10 * NSEC_PER_SEC), 91 | dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 92 | [transaction cancelWithReason:@"test reason for cancelled transaction"]; 93 | }); 94 | } 95 | 96 | - (void)didReceiveMemoryWarning { 97 | [super didReceiveMemoryWarning]; 98 | // Dispose of any resources that can be recreated. 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaDemo.xcodeproj/xcshareddata/xcschemes/PreDemCocoaTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 85 | 86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Pods-PreDemCocoaTests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2011-2016 Qiniu, Ltd.<sdk@qiniu.com> 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | 39 | License 40 | MIT 41 | Title 42 | PreDemCocoa 43 | Type 44 | PSGroupSpecifier 45 | 46 | 47 | FooterText 48 | The MIT License 49 | 50 | Copyright (c) 2011 kishikawa katsumi 51 | 52 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 53 | 54 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 55 | 56 | 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. 57 | License 58 | MIT 59 | Title 60 | UICKeyChainStore 61 | Type 62 | PSGroupSpecifier 63 | 64 | 65 | FooterText 66 | Generated by CocoaPods - https://cocoapods.org 67 | Title 68 | 69 | Type 70 | PSGroupSpecifier 71 | 72 | 73 | StringsTable 74 | Acknowledgements 75 | Title 76 | Acknowledgements 77 | 78 | 79 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2011-2016 Qiniu, Ltd.<sdk@qiniu.com> 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | 39 | License 40 | MIT 41 | Title 42 | PreDemCocoa 43 | Type 44 | PSGroupSpecifier 45 | 46 | 47 | FooterText 48 | The MIT License 49 | 50 | Copyright (c) 2011 kishikawa katsumi 51 | 52 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 53 | 54 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 55 | 56 | 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. 57 | License 58 | MIT 59 | Title 60 | UICKeyChainStore 61 | Type 62 | PSGroupSpecifier 63 | 64 | 65 | FooterText 66 | Generated by CocoaPods - https://cocoapods.org 67 | Title 68 | 69 | Type 70 | PSGroupSpecifier 71 | 72 | 73 | StringsTable 74 | Acknowledgements 75 | Title 76 | Acknowledgements 77 | 78 | 79 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Pods-PreDemSwiftDemo-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2011-2016 Qiniu, Ltd.<sdk@qiniu.com> 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | 39 | License 40 | MIT 41 | Title 42 | PreDemCocoa 43 | Type 44 | PSGroupSpecifier 45 | 46 | 47 | FooterText 48 | The MIT License 49 | 50 | Copyright (c) 2011 kishikawa katsumi 51 | 52 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 53 | 54 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 55 | 56 | 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. 57 | License 58 | MIT 59 | Title 60 | UICKeyChainStore 61 | Type 62 | PSGroupSpecifier 63 | 64 | 65 | FooterText 66 | Generated by CocoaPods - https://cocoapods.org 67 | Title 68 | 69 | Type 70 | PSGroupSpecifier 71 | 72 | 73 | StringsTable 74 | Acknowledgements 75 | Title 76 | Acknowledgements 77 | 78 | 79 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaDemo.xcodeproj/xcshareddata/xcschemes/PreDemSwiftDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaTests/Tests/PREDSenderTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDCrashTests.m 3 | // PreDemObjcTests 4 | // 5 | // Created by 王思宇 on 29/09/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDManagerPrivate.h" 10 | #import "PREDPersistence.h" 11 | #import "PREDSender.h" 12 | #import "PREDTransactionPrivate.h" 13 | #import 14 | 15 | @interface PREDSenderTests : XCTestCase 16 | 17 | @end 18 | 19 | @implementation PREDSenderTests { 20 | PREDPersistence *_persistence; 21 | PREDSender *_sender; 22 | } 23 | 24 | - (void)setUp { 25 | [super setUp]; 26 | // Put setup code here. This method is called before the invocation of each 27 | // test method in the class. 28 | self.continueAfterFailure = NO; 29 | _sender = [[PREDSender alloc] 30 | initWithBaseUrl:[NSURL URLWithString:@"http://" 31 | @"bhk5aaghth5n.predem.qiniuapi." 32 | @"com/v2/A_5p9l3Z/"]]; 33 | [PREDManager sharedPREDManager].appKey = @"A_5p9l3Z"; 34 | PREDManager.tag = @"xcodetest"; 35 | } 36 | 37 | - (void)tearDown { 38 | // Put teardown code here. This method is called after the invocation of each 39 | // test method in the class. 40 | [super tearDown]; 41 | } 42 | 43 | - (void)testAppSender { 44 | __block NSData *originalData; 45 | __block NSError *originalError; 46 | XCTestExpectation *expectation = [self expectationWithDescription:@"sending"]; 47 | [_sender sendAppInfo:^(PREDHTTPOperation *operation, NSData *data, 48 | NSError *error) { 49 | originalData = data; 50 | originalError = error; 51 | [expectation fulfill]; 52 | }]; 53 | [self waitForExpectationsWithTimeout:10 54 | handler:^(NSError *error) { 55 | XCTAssertNil(error, @"%@", error); 56 | }]; 57 | XCTAssertNotNil(originalData); 58 | XCTAssertNil(originalError); 59 | } 60 | 61 | - (void)testCustomSender { 62 | [_sender purgeAll]; 63 | [_sender persistCustomEvent:[PREDCustomEvent eventWithName:@"testName" 64 | contentDic:nil]]; 65 | __block NSData *originalData; 66 | __block NSError *originalError; 67 | XCTestExpectation *expectation = [self expectationWithDescription:@"sending"]; 68 | [_sender sendCustomEvents:^(PREDHTTPOperation *operation, NSData *data, 69 | NSError *error) { 70 | originalData = data; 71 | originalError = error; 72 | [expectation fulfill]; 73 | } 74 | recursively:NO]; 75 | [self waitForExpectationsWithTimeout:10 76 | handler:^(NSError *error) { 77 | XCTAssertNil(error, @"%@", error); 78 | }]; 79 | XCTAssertNotNil(originalData); 80 | XCTAssertNil(originalError); 81 | [_sender purgeAll]; 82 | } 83 | 84 | - (void)testTransactionSender { 85 | [_sender purgeAll]; 86 | [_sender persistTransaction:[PREDTransaction transactionWithSender:_sender]]; 87 | __block NSData *originalData; 88 | __block NSError *originalError; 89 | XCTestExpectation *expectation = [self expectationWithDescription:@"sending"]; 90 | [_sender sendTransactions:^(PREDHTTPOperation *operation, NSData *data, 91 | NSError *error) { 92 | originalData = data; 93 | originalError = error; 94 | [expectation fulfill]; 95 | } 96 | recursively:NO]; 97 | [self waitForExpectationsWithTimeout:10 98 | handler:^(NSError *error) { 99 | XCTAssertNil(error, @"%@", error); 100 | }]; 101 | XCTAssertNotNil(originalData); 102 | XCTAssertNil(originalError); 103 | [_sender purgeAll]; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pre-dem-cocoa 2 | 3 | [![Build Status](https://travis-ci.org/pre-dem/pre-dem-cocoa.svg?branch=master)](https://travis-ci.org/pre-dem/pre-dem-cocoa) 4 | [![codecov](https://codecov.io/gh/pre-dem/pre-dem-cocoa/branch/master/graph/badge.svg)](https://codecov.io/gh/pre-dem/pre-dem-cocoa) 5 | [![Latest Stable Version](https://img.shields.io/cocoapods/v/PreDemCocoa.svg)](https://github.com/pre-dem/pre-dem-cocoa/releases) 6 | ![Platform](http://img.shields.io/cocoapods/p/PreDemCocoa.svg) 7 | 8 | ## 简介 9 | 10 | pre-dem-cocoa 是由[七牛云](https://www.qiniu.com)发起和维护的针对 iOS (Mac OS, Tv OS, Watch OS WIP) 等平台集用户体验监控及报障于一体的开源 SDK,用户可以将自定义数据上传到APM上进行分析 11 | 12 | ## 安装 13 | 14 | 使用 [CocoaPods](https://cocoapods.org) 进行安装 15 | 16 | ```ruby 17 | pod "PreDemCocoa" 18 | ``` 19 | 20 | ## 快速开始 21 | 22 | - 创建APP 23 | 首先到apm.qiniu.com 上登录并创建自己的APP,在配置信息中找到对应的APP KEY,以及消息上报的域名,填入到sdk中, 24 | 25 | - 初始化 26 | 27 | ``` objc 28 | NSError *error; 29 | [PREDManager startWithAppKey:@"YOUR_APP_KEY" 30 | serviceDomain:@"YOUR_REPORT_DOMAIN"]; 31 | ``` 32 | 33 | 初始化之后,SDK 便会自动定期从服务器更新配置信息,终端可根据配置来调整队列发送间隔时间 34 | 35 | - 自定义事件 36 | 37 | ``` objc 38 | NSDictionary *dict = @{ 39 | @"PARAMETER_KEY1": @"PARAMETER_VALUE1", 40 | @"PARAMETER_KEY2": @"PARAMETER_VALUE2" 41 | }; 42 | PREDEvent *event = [PREDEvent eventWithName:@"YOUR_EVENT_NAME" contentDic:dict]; 43 | [PREDManager trackEvent:event]; 44 | ``` 45 | 自定义事件上报功能能够将您自定义的事件直接上报至服务器。 46 | 47 | - 事务上报 48 | 49 | 开始一个事务 50 | ``` objc 51 | PREDTransaction *transaction = [PREDManager transactionStart:@"test"]; 52 | ``` 53 | 54 | 将一个事务标识为完成并上传数据到服务器(!注意一个事务只能标识一次完成,之后应该释放该对象,多次标识完成会造成统计出现偏差) 55 | ``` objc 56 | [transaction complete]; 57 | ``` 58 | 59 | 将一个事务标识为被取消并上传数据到服务器(!注意一个事务只能标识一次被取消,之后应该释放该对象,多次标识完成会造成统计出现偏差) 60 | ``` objc 61 | [transaction cancelWithReason:@"test reason for cancelled transaction"]; 62 | ``` 63 | 64 | 将一个事务标识为失败并上传数据到服务器(!注意一个事务只能标识一次被取消,之后应该释放该对象,多次标识完成会造成统计出现偏差) 65 | ``` objc 66 | [transaction failWithReason:@"test reason for failed transaction"]; 67 | ``` 68 | 69 | - 调整发送间隔 70 | 默认30s的发送间隔,如果想调整,可以通过如下方式调整 71 | PREDManager.updateInterval = 时间; 72 | 73 | ## 示例代码 74 | * 具体细节的一些配置 可参考 PreDemCocoaDemo/PreDemCocoaTests 下面的一些单元测试,以及源代码 75 | 76 | ## SDK 发送机制介绍 77 | ### 目的 78 | * 支持灵活的自定义事件上报 79 | * 提供可靠的缓存机制保障消息不丢失 80 | * 通过白名单以及其他用户需求,对发送的间隔进行控制 81 | * 发送组件作为核心,其他采集方式以插件组合方式进行使用 82 | 83 | ### 机制介绍 84 | 发送数据的主要流程主要分为三个阶段 85 | 1. 数据序列化,将自定义事件加上系统的一些参数,序列化为待上传的json数据 86 | 2. 数据缓存,通过缓存组件,将序列化过的数据缓存在文件中,保障数据不丢失,默认是512K大小换一个文件 87 | 3. 数据发送,将已经缓存过的数据,按照时间间隔进行发送,发送时使用gzip进行压缩,系统启动时发送一次,之后按照updateInterval 指定的时间进行发送,默认是30秒,失败后不会尝试重传(由于网络等问题,失败时大概率重试也会失败),等待到下一个周期继续 88 | 4. 另外,在发送的时候从服务器获取到的一些状态变更由 Sender 通过 Notification 的方式进行广播,内部变更状态的模块通过监听 Notification 的方式进行相关状态的变更。 89 | 90 | ### Todo 91 | * 使用protobuf 进行序列化 92 | * 限制最大存储空间进行滚动存储 93 | * 支持只在WI-FI下发送 94 | * 支持默认不发送,只在需要时候进行发送 95 | 96 | ## 常见问题 97 | 98 | - iOS 9+ 强制使用https,需要在project build info 添加NSAppTransportSecurity类型Dictionary。在NSAppTransportSecurity下添加NSAllowsArbitraryLoads类型Boolean,值设为YES。 具体操作可参见 http://blog.csdn.net/guoer9973/article/details/48622823 99 | - 如果碰到其他编译错误, 请参考 CocoaPods 的 [troubleshooting](http://guides.cocoapods.org/using/troubleshooting.html) 100 | 101 | ## 代码贡献 102 | 103 | 详情参考 [代码提交指南](https://github.com/pre-dem/pre-dem-cocoa/blob/master/Contributing.md). 104 | 105 | ## 贡献记录 106 | 107 | - [所有贡献者](https://github.com/pre-dem/pre-dem-cocoa/contributors) 108 | 109 | ## 联系我们 110 | 111 | - 如果需要帮助, 请提交工单 (在 portal 右侧点击咨询和建议提交工单, 或者直接向 support@qiniu.com 发送邮件) 112 | - 如果有什么问题, 可以到问答社区提问, [问答社区](http://qiniu.segmentfault.com/) 113 | - 如果发现了 bug, 欢迎提交 [issue](https://github.com/pre-dem/pre-dem-cocoa/issues) 114 | - 如果有功能需求, 欢迎提交 [issue](https://github.com/pre-dem/pre-dem-cocoa/issues) 115 | - 如果要提交代码, 欢迎提交 pull request 116 | - 欢迎关注我们的 [微信](http://www.qiniu.com/#weixin) && [微博](http://weibo.com/qiniutek), 及时获取动态信息 117 | 118 | ## 代码许可 119 | 120 | The MIT License (MIT). 详情见 [License 文件](https://github.com/qiniu/pre-dem-cocoa/blob/master/LICENSE). 121 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaDemo.xcodeproj/xcshareddata/xcschemes/PreDemObjcDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (2.3.5) 5 | addressable (2.5.2) 6 | public_suffix (>= 2.0.2, < 4.0) 7 | babosa (1.0.2) 8 | chunky_png (1.3.8) 9 | claide (1.0.2) 10 | colored (1.2) 11 | colored2 (3.1.2) 12 | commander-fastlane (4.4.5) 13 | highline (~> 1.7.2) 14 | declarative (0.0.10) 15 | declarative-option (0.1.0) 16 | domain_name (0.5.20170404) 17 | unf (>= 0.0.5, < 1.0.0) 18 | dotenv (2.2.1) 19 | excon (0.59.0) 20 | faraday (0.13.1) 21 | multipart-post (>= 1.2, < 3) 22 | faraday-cookie_jar (0.0.6) 23 | faraday (>= 0.7.4) 24 | http-cookie (~> 1.0.0) 25 | faraday_middleware (0.12.2) 26 | faraday (>= 0.7.4, < 1.0) 27 | fastimage (2.1.0) 28 | fastlane (2.61.0) 29 | CFPropertyList (>= 2.3, < 3.0.0) 30 | addressable (>= 2.3, < 3.0.0) 31 | babosa (>= 1.0.2, < 2.0.0) 32 | bundler (>= 1.12.0, < 2.0.0) 33 | colored 34 | commander-fastlane (>= 4.4.5, < 5.0.0) 35 | dotenv (>= 2.1.1, < 3.0.0) 36 | excon (>= 0.45.0, < 1.0.0) 37 | faraday (~> 0.9) 38 | faraday-cookie_jar (~> 0.0.6) 39 | faraday_middleware (~> 0.9) 40 | fastimage (>= 2.1.0, < 3.0.0) 41 | gh_inspector (>= 1.0.1, < 2.0.0) 42 | google-api-client (>= 0.13.1, < 0.14.0) 43 | highline (>= 1.7.2, < 2.0.0) 44 | json (< 3.0.0) 45 | mini_magick (~> 4.5.1) 46 | multi_json 47 | multi_xml (~> 0.5) 48 | multipart-post (~> 2.0.0) 49 | plist (>= 3.1.0, < 4.0.0) 50 | public_suffix (~> 2.0.0) 51 | rubyzip (>= 1.1.0, < 2.0.0) 52 | security (= 0.1.3) 53 | slack-notifier (>= 1.3, < 2.0.0) 54 | terminal-notifier (>= 1.6.2, < 2.0.0) 55 | terminal-table (>= 1.4.5, < 2.0.0) 56 | tty-screen (~> 0.5.0) 57 | word_wrap (~> 1.0.0) 58 | xcodeproj (>= 1.5.0, < 2.0.0) 59 | xcpretty (>= 0.2.4, < 1.0.0) 60 | xcpretty-travis-formatter (>= 0.0.3) 61 | fir-cli (1.6.3) 62 | CFPropertyList (~> 2.3) 63 | rest-client (~> 2.0) 64 | rqrcode (~> 0.7) 65 | ruby_android (~> 0.7.7) 66 | thor (~> 0.19) 67 | xcodeproj (~> 1.4) 68 | gh_inspector (1.0.3) 69 | google-api-client (0.13.6) 70 | addressable (~> 2.5, >= 2.5.1) 71 | googleauth (~> 0.5) 72 | httpclient (>= 2.8.1, < 3.0) 73 | mime-types (~> 3.0) 74 | representable (~> 3.0) 75 | retriable (>= 2.0, < 4.0) 76 | googleauth (0.5.3) 77 | faraday (~> 0.12) 78 | jwt (~> 1.4) 79 | logging (~> 2.0) 80 | memoist (~> 0.12) 81 | multi_json (~> 1.11) 82 | os (~> 0.9) 83 | signet (~> 0.7) 84 | highline (1.7.8) 85 | http-cookie (1.0.3) 86 | domain_name (~> 0.5) 87 | httpclient (2.8.3) 88 | json (2.1.0) 89 | jwt (1.5.6) 90 | little-plugger (1.1.4) 91 | logging (2.2.2) 92 | little-plugger (~> 1.1) 93 | multi_json (~> 1.10) 94 | memoist (0.16.0) 95 | mime-types (3.1) 96 | mime-types-data (~> 3.2015) 97 | mime-types-data (3.2016.0521) 98 | mini_magick (4.5.1) 99 | multi_json (1.12.2) 100 | multi_xml (0.6.0) 101 | multipart-post (2.0.0) 102 | nanaimo (0.2.3) 103 | netrc (0.11.0) 104 | os (0.9.6) 105 | plist (3.3.0) 106 | public_suffix (2.0.5) 107 | representable (3.0.4) 108 | declarative (< 0.1.0) 109 | declarative-option (< 0.2.0) 110 | uber (< 0.2.0) 111 | rest-client (2.0.2) 112 | http-cookie (>= 1.0.2, < 2.0) 113 | mime-types (>= 1.16, < 4.0) 114 | netrc (~> 0.8) 115 | retriable (3.1.1) 116 | rouge (2.0.7) 117 | rqrcode (0.10.1) 118 | chunky_png (~> 1.0) 119 | ruby_android (0.7.7) 120 | rubyzip (>= 1.1.6) 121 | rubyzip (1.2.1) 122 | security (0.1.3) 123 | signet (0.7.3) 124 | addressable (~> 2.3) 125 | faraday (~> 0.9) 126 | jwt (~> 1.5) 127 | multi_json (~> 1.10) 128 | slack-notifier (1.5.1) 129 | terminal-notifier (1.8.0) 130 | terminal-table (1.8.0) 131 | unicode-display_width (~> 1.1, >= 1.1.1) 132 | thor (0.20.0) 133 | tty-screen (0.5.0) 134 | uber (0.1.0) 135 | unf (0.1.4) 136 | unf_ext 137 | unf_ext (0.0.7.4) 138 | unicode-display_width (1.3.0) 139 | word_wrap (1.0.0) 140 | xcodeproj (1.5.2) 141 | CFPropertyList (~> 2.3.3) 142 | claide (>= 1.0.2, < 2.0) 143 | colored2 (~> 3.1) 144 | nanaimo (~> 0.2.3) 145 | xcpretty (0.2.8) 146 | rouge (~> 2.0.7) 147 | xcpretty-travis-formatter (0.0.4) 148 | xcpretty (~> 0.2, >= 0.0.7) 149 | 150 | PLATFORMS 151 | ruby 152 | 153 | DEPENDENCIES 154 | fastlane 155 | fir-cli 156 | 157 | BUNDLED WITH 158 | 1.15.4 159 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/PreDemCocoaTests/Tests/PREDTransactionTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDCrashTests.m 3 | // PreDemObjcTests 4 | // 5 | // Created by 王思宇 on 29/09/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDPersistence.h" 10 | #import "PREDTransactionPrivate.h" 11 | #import 12 | 13 | @interface PREDTransactionTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation PREDTransactionTests { 18 | PREDPersistence *_persistence; 19 | } 20 | 21 | - (void)setUp { 22 | [super setUp]; 23 | // Put setup code here. This method is called before the invocation of each 24 | // test method in the class. 25 | self.continueAfterFailure = NO; 26 | _persistence = [[PREDPersistence alloc] init]; 27 | } 28 | 29 | - (void)tearDown { 30 | // Put teardown code here. This method is called after the invocation of each 31 | // test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | //- (void)testCompletedTransaction { 36 | // [_persistence purgeAll]; 37 | // PREDTransaction *transaction = 38 | // [PREDTransaction transactionWithPersistence:_persistence]; 39 | // [transaction complete]; 40 | // NSString *filePath = [_persistence nextArchivedPath]; 41 | // XCTAssertNotEqual(filePath.length, 0); 42 | // NSData *data = [NSData dataWithContentsOfFile:filePath]; 43 | // XCTAssertNotEqual(data.length, 0); 44 | // NSError *error; 45 | // NSDictionary *parsedData = 46 | // [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; 47 | // XCTAssertNil(error, @"%@", error); 48 | // XCTAssertNotNil(parsedData); 49 | // XCTAssertEqual([parsedData respondsToSelector:@selector(objectForKey:)], 50 | // YES); 51 | // NSString *content = parsedData[@"content"]; 52 | // XCTAssertNotEqual([content length], 0); 53 | // NSDictionary *parsedContent = [NSJSONSerialization 54 | // JSONObjectWithData:[content dataUsingEncoding:NSUTF8StringEncoding] 55 | // options:0 56 | // error:&error]; 57 | // XCTAssertNil(error, @"%@", error); 58 | // XCTAssertNotNil(parsedContent); 59 | // [parsedContent[@"transaction_type"] 60 | // isEqual:@(PREDTransactionTypeCompleted)]; 61 | //} 62 | // 63 | //- (void)testCancelledTransaction { 64 | // [_persistence purgeAll]; 65 | // PREDTransaction *transaction = 66 | // [PREDTransaction transactionWithPersistence:_persistence]; 67 | // NSString *reason = @"test reason"; 68 | // [transaction cancelWithReason:reason]; 69 | // NSString *filePath = [_persistence nextArchivedPath]; 70 | // XCTAssertNotEqual(filePath.length, 0); 71 | // NSData *data = [NSData dataWithContentsOfFile:filePath]; 72 | // XCTAssertNotEqual(data.length, 0); 73 | // NSError *error; 74 | // NSDictionary *parsedData = 75 | // [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; 76 | // XCTAssertNil(error, @"%@", error); 77 | // XCTAssertNotNil(parsedData); 78 | // XCTAssertEqual([parsedData respondsToSelector:@selector(objectForKey:)], 79 | // YES); 80 | // NSString *content = parsedData[@"content"]; 81 | // XCTAssertNotEqual([content length], 0); 82 | // NSDictionary *parsedContent = [NSJSONSerialization 83 | // JSONObjectWithData:[content dataUsingEncoding:NSUTF8StringEncoding] 84 | // options:0 85 | // error:&error]; 86 | // XCTAssertNil(error, @"%@", error); 87 | // XCTAssertNotNil(parsedContent); 88 | // [parsedContent[@"transaction_type"] 89 | // isEqual:@(PREDTransactionTypeCancelled)]; 90 | // [parsedContent[@"reason"] isEqual:reason]; 91 | //} 92 | // 93 | //- (void)testfailedTransaction { 94 | // [_persistence purgeAll]; 95 | // PREDTransaction *transaction = 96 | // [PREDTransaction transactionWithPersistence:_persistence]; 97 | // NSString *reason = @"test reason"; 98 | // [transaction failWithReason:reason]; 99 | // NSString *filePath = [_persistence nextArchivedPath]; 100 | // XCTAssertNotEqual(filePath.length, 0); 101 | // NSData *data = [NSData dataWithContentsOfFile:filePath]; 102 | // XCTAssertNotEqual(data.length, 0); 103 | // NSError *error; 104 | // NSDictionary *parsedData = 105 | // [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; 106 | // XCTAssertNil(error, @"%@", error); 107 | // XCTAssertNotNil(parsedData); 108 | // XCTAssertEqual([parsedData respondsToSelector:@selector(objectForKey:)], 109 | // YES); 110 | // NSString *content = parsedData[@"content"]; 111 | // XCTAssertNotEqual([content length], 0); 112 | // NSDictionary *parsedContent = [NSJSONSerialization 113 | // JSONObjectWithData:[content dataUsingEncoding:NSUTF8StringEncoding] 114 | // options:0 115 | // error:&error]; 116 | // XCTAssertNil(error, @"%@", error); 117 | // XCTAssertNotNil(parsedContent); 118 | // [parsedContent[@"transaction_type"] isEqual:@(PREDTransactionTypeFailed)]; 119 | // [parsedContent[@"reason"] isEqual:reason]; 120 | //} 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /PreDemCocoa/Sender/PREDNetworkClient.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDNetworkClient.m 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PREDNetworkClient.h" 10 | #import "PREDCredential.h" 11 | #import "PREDError.h" 12 | #import "PREDHelper.h" 13 | #import "PREDLogger.h" 14 | #import "PREDManagerPrivate.h" 15 | 16 | static NSString *PRED_HTTPS_PREFIX = @"https://"; 17 | static NSString *PRED_HTTP_PREFIX = @"http://"; 18 | 19 | static NSString *pred_appendTime(NSString *url) { 20 | NSString *format = [url rangeOfString:@"?"].location == NSNotFound 21 | ? @"%@?t=%lld" 22 | : @"%@&t=%lld"; 23 | return [NSString 24 | stringWithFormat:format, url, 25 | (int64_t)[[NSDate date] timeIntervalSince1970]]; 26 | } 27 | 28 | @implementation PREDNetworkClient { 29 | NSURL *_baseURL; 30 | 31 | NSOperationQueue *_operationQueue; 32 | } 33 | 34 | - (instancetype)initWithBaseURL:(NSURL *)baseURL { 35 | self = [super init]; 36 | if (self) { 37 | _baseURL = baseURL; 38 | _operationQueue = [[NSOperationQueue alloc] init]; 39 | _operationQueue.maxConcurrentOperationCount = 3; 40 | } 41 | return self; 42 | } 43 | 44 | - (void)postPath:(NSString *)path 45 | data:(NSData *)data 46 | headers:(NSMutableDictionary *)headers 47 | completion:(PREDNetworkCompletionBlock)completion { 48 | NSMutableURLRequest *request = [NSMutableURLRequest 49 | requestWithURL:[NSURL URLWithString:path relativeToURL:_baseURL]]; 50 | [request setHTTPMethod:@"POST"]; 51 | NSError *error; 52 | NSData *compressedData = [PREDHelper gzipData:data error:&error]; 53 | if (!error) { 54 | headers[@"Content-Encoding"] = @"gzip"; 55 | data = compressedData; 56 | } else { 57 | PREDLogWarning(@"compress data failed, using raw data for sending"); 58 | } 59 | [request setHTTPBody:data]; 60 | if (headers) { 61 | [headers enumerateKeysAndObjectsUsingBlock:^( 62 | id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) { 63 | NSAssert([key isKindOfClass:[NSString class]], 64 | @"headers can only be string-string pairs"); 65 | NSAssert([obj isKindOfClass:[NSString class]], 66 | @"headers can only be string-string pairs"); 67 | [request setValue:obj forHTTPHeaderField:key]; 68 | }]; 69 | } 70 | [self sendRequest:request completion:completion]; 71 | } 72 | 73 | - (void)sendRequest:(NSMutableURLRequest *)request 74 | completion:(PREDNetworkCompletionBlock)completion { 75 | [NSURLProtocol setProperty:@YES 76 | forKey:@"PREDInternalRequest" 77 | inRequest:request]; 78 | [self authorizeRequest:request]; 79 | PREDHTTPOperation *operation = [self 80 | operationWithURLRequest:request 81 | completion:^(PREDHTTPOperation *operation, NSData *data, 82 | NSError *error) { 83 | if (operation.response.statusCode >= 400) { 84 | error = [PREDError 85 | GenerateNSError:kPREDErrorCodeInternalError 86 | description: 87 | @"server returned an error status code: %d, " 88 | @"body: %@", 89 | operation.response.statusCode, 90 | [[NSString alloc] 91 | initWithData:data 92 | encoding:NSUTF8StringEncoding]]; 93 | } 94 | completion(operation, data, error); 95 | }]; 96 | [_operationQueue addOperation:operation]; 97 | } 98 | 99 | - (PREDHTTPOperation *)operationWithURLRequest:(NSURLRequest *)request 100 | completion: 101 | (PREDNetworkCompletionBlock)completion { 102 | PREDHTTPOperation *operation = 103 | [PREDHTTPOperation operationWithRequest:request]; 104 | [operation setCompletion:completion]; 105 | return operation; 106 | } 107 | 108 | - (void)authorizeRequest:(NSMutableURLRequest *)request { 109 | NSString *url = request.URL.absoluteString; 110 | url = pred_appendTime(url); 111 | NSString *domainPath; 112 | if ([url hasPrefix:PRED_HTTPS_PREFIX]) { 113 | domainPath = [url substringFromIndex:[PRED_HTTPS_PREFIX length]]; 114 | } else if ([url hasPrefix:PRED_HTTP_PREFIX]) { 115 | domainPath = [url substringFromIndex:[PRED_HTTP_PREFIX length]]; 116 | } else { 117 | domainPath = url; 118 | } 119 | NSString *auth = 120 | [PREDCredential authorize:domainPath 121 | appKey:[[PREDManager sharedPREDManager] appKey]]; 122 | [request setValue:auth forHTTPHeaderField:@"Authorization"]; 123 | [request setURL:[NSURL URLWithString:url]]; 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemSwiftDemo/Pods-PreDemSwiftDemo-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemCocoaTests/Pods-PreDemCocoaTests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /PreDemCocoa/Core/PREDManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDManager.m 3 | // PreDemCocoa 4 | // 5 | // Created by WangSiyu on 21/02/2017. 6 | // Copyright © 2017 pre-engineering. All rights reserved. 7 | // 8 | 9 | #import "PreDemCocoa.h" 10 | #import "PREDError.h" 11 | #import "PREDHelper.h" 12 | #import "PREDLogger.h" 13 | #import "PREDManagerPrivate.h" 14 | #import "PREDSender.h" 15 | #import "PREDTransactionPrivate.h" 16 | #import "PREDVersion.h" 17 | 18 | static NSString *app_id(NSString *appKey) { 19 | if (appKey.length >= PREDAppIdLength) { 20 | return [appKey substringToIndex:PREDAppIdLength]; 21 | } else { 22 | return appKey; 23 | } 24 | } 25 | 26 | @implementation PREDManager { 27 | BOOL started; 28 | PREDConfigManager *configManager; 29 | PREDSender *sender; 30 | PREDConfig *mConfig; 31 | } 32 | 33 | #pragma mark - Public Class Methods 34 | 35 | + (void)startWithAppKey:(NSString *)appKey 36 | serviceDomain:(NSString *)serviceDomain { 37 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 38 | ^{ 39 | [[self sharedPREDManager] startWithAppKey:appKey 40 | serviceDomain:serviceDomain]; 41 | }); 42 | } 43 | 44 | + (PREDTransaction *)transactionStart:(NSString *)transactionName { 45 | uint64_t startTime = (uint64_t)([[NSDate date] timeIntervalSince1970] * 1000); 46 | PREDTransaction *transaction = 47 | [PREDTransaction transactionWithSender:[self sharedPREDManager]->sender]; 48 | transaction.transaction_name = transactionName; 49 | transaction.start_time = startTime; 50 | return transaction; 51 | } 52 | 53 | + (void)trackCustomEvent:(PREDCustomEvent *)event { 54 | if (!event) { 55 | PREDLogError(@"event should not be nil"); 56 | return; 57 | } 58 | [[self sharedPREDManager] trackEvent:event]; 59 | } 60 | 61 | - (void)trackEvent:(PREDCustomEvent *)event { 62 | [sender persistCustomEvent:event]; 63 | } 64 | 65 | + (BOOL)started { 66 | return [PREDManager sharedPREDManager]->started; 67 | } 68 | 69 | + (NSString *)tag { 70 | return PREDHelper.tag; 71 | } 72 | 73 | + (void)setTag:(NSString *)tag { 74 | PREDHelper.tag = tag; 75 | } 76 | 77 | + (NSUInteger)updateInterval { 78 | return [self sharedPREDManager]->sender.interval; 79 | } 80 | 81 | + (void)setUpdateInterval:(NSUInteger)interval { 82 | [self sharedPREDManager]->sender.interval = interval; 83 | } 84 | 85 | + (NSString *)version { 86 | return [PREDVersion getSDKVersion]; 87 | } 88 | 89 | + (NSString *)build { 90 | return [PREDVersion getSDKBuild]; 91 | } 92 | 93 | #pragma mark - Private Methods 94 | 95 | + (PREDManager *)sharedPREDManager { 96 | static PREDManager *sharedInstance = nil; 97 | static dispatch_once_t pred; 98 | 99 | dispatch_once(&pred, ^{ 100 | sharedInstance = [[PREDManager alloc] init]; 101 | }); 102 | 103 | return sharedInstance; 104 | } 105 | 106 | - (void)startInternalWithAppKey:(NSString *)appKey 107 | serviceDomain:(NSString *)serviceDomain { 108 | self.appKey = appKey; 109 | NSError *error; 110 | // 初始化 sender 111 | if (![self initSenderWithDomain:serviceDomain appKey:appKey error:&error]) { 112 | PREDLogError(@"%@", error); 113 | return; 114 | } 115 | 116 | // 进行其他功能模块的初始化 117 | [self initializeModules]; 118 | 119 | // 注册观察者,接收通知 120 | [self registerObservers]; 121 | 122 | // 开始循环发送数据 123 | [sender sendAllSavedData]; 124 | 125 | started = YES; 126 | } 127 | 128 | - (void)startWithAppKey:(NSString *)appKey 129 | serviceDomain:(NSString *)serviceDomain { 130 | static dispatch_once_t onceToken; 131 | dispatch_once(&onceToken, ^{ 132 | [self startInternalWithAppKey:appKey serviceDomain:serviceDomain]; 133 | }); 134 | return; 135 | } 136 | 137 | - (instancetype)init { 138 | if ((self = [super init])) { 139 | self.config = PREDConfig.defaultConfig; 140 | } 141 | return self; 142 | } 143 | 144 | - (BOOL)initSenderWithDomain:(NSString *)aServerURL 145 | appKey:(NSString *)appKey 146 | error:(NSError **)error { 147 | if (!aServerURL.length) { 148 | if (error) { 149 | *error = [PREDError 150 | GenerateNSError:kPREDErrorCodeInvalidServiceDomain 151 | description:@"你必须指定 server domain !!!!!!"]; 152 | } 153 | return NO; 154 | } 155 | if (appKey.length < PREDAppIdLength) { 156 | if (error) { 157 | *error = [PREDError 158 | GenerateNSError:kPREDErrorCodeInvalidAppKey 159 | description:@"app key 的长度必须大于等于 %d!!!!!!", 160 | PREDAppIdLength]; 161 | } 162 | return NO; 163 | } 164 | if (![aServerURL hasPrefix:@"http://"] && 165 | ![aServerURL hasPrefix:@"https://"]) { 166 | aServerURL = [NSString stringWithFormat:@"http://%@", aServerURL]; 167 | } 168 | 169 | aServerURL = 170 | [NSString stringWithFormat:@"%@/v2/%@/", aServerURL, app_id(appKey)]; 171 | 172 | NSURL *url = [NSURL URLWithString:aServerURL]; 173 | 174 | if (!url) { 175 | if (error) { 176 | *error = [PREDError 177 | GenerateNSError:kPREDErrorCodeInvalidServiceDomain 178 | description:@"service domain 的结构不正确: %@ !!!!!!", 179 | aServerURL]; 180 | } 181 | return NO; 182 | } 183 | 184 | sender = [[PREDSender alloc] initWithBaseUrl:url]; 185 | return YES; 186 | } 187 | 188 | - (void)initializeModules { 189 | configManager = [[PREDConfigManager alloc] initWithSender:sender]; 190 | 191 | // this process will get default config and then use it to initialize all 192 | // module, besides it will also retrieve config from the server and config 193 | // will refresh when done. 194 | [self setConfig:[configManager getConfig]]; 195 | } 196 | 197 | - (void)setConfig:(PREDConfig *)config { 198 | mConfig = config; 199 | } 200 | 201 | - (void)registerObservers { 202 | [[NSNotificationCenter defaultCenter] 203 | addObserver:self 204 | selector:@selector(configRefreshed:) 205 | name:kPREDConfigRefreshedNotification 206 | object:nil]; 207 | } 208 | 209 | - (void)configRefreshed:(NSNotification *)noty { 210 | NSDictionary *dic = noty.userInfo[kPREDConfigRefreshedNotificationConfigKey]; 211 | PREDConfig *config = [PREDConfig configWithDic:dic]; 212 | [self setConfig:config]; 213 | } 214 | 215 | + (BOOL)isVip { 216 | return [self sharedPREDManager]->mConfig.isVip; 217 | } 218 | 219 | @end 220 | -------------------------------------------------------------------------------- /PreDemCocoa/Sender/PREDPersistence.m: -------------------------------------------------------------------------------- 1 | // 2 | // PREDPersistence.m 3 | // Pods 4 | // 5 | // Created by 王思宇 on 14/09/2017. 6 | // 7 | // 8 | 9 | #import "PREDPersistence.h" 10 | #import "PREDError.h" 11 | #import "PREDHelper.h" 12 | #import "PREDLogger.h" 13 | #import "PREDTransaction.h" 14 | 15 | #define PREDMaxCacheFileSize 512 * 1024 // 512KB 16 | #define PREDMillisecondPerSecond 1000 17 | 18 | @implementation PREDPersistence { 19 | NSString *_dir; 20 | NSFileManager *_fileManager; 21 | NSFileHandle *_fileHandle; 22 | dispatch_queue_t _queue; 23 | NSString *_path; 24 | } 25 | 26 | - (instancetype)initWithPath:(NSString *)path queue:(NSString *)queue { 27 | if (self = [super init]) { 28 | _path = path; 29 | _fileManager = [NSFileManager defaultManager]; 30 | _dir = 31 | [NSString stringWithFormat:@"%@/%@", PREDHelper.cacheDirectory, path]; 32 | _queue = dispatch_queue_create( 33 | [queue cStringUsingEncoding:kCFStringEncodingUTF8], 34 | DISPATCH_QUEUE_SERIAL); 35 | 36 | NSError *error; 37 | [_fileManager createDirectoryAtPath:_dir 38 | withIntermediateDirectories:YES 39 | attributes:nil 40 | error:&error]; 41 | if (error) { 42 | PREDLogError(@"create dir %@ failed", _dir); 43 | } 44 | } 45 | return self; 46 | } 47 | 48 | - (void)persist:(id)data { 49 | dispatch_async(_queue, ^{ 50 | NSError *error; 51 | NSData *toSave = [data serializeForSending:&error]; 52 | if (error) { 53 | PREDLogError(@"jsonize transaction error: %@", error); 54 | return; 55 | } 56 | 57 | [self persistSave:toSave]; 58 | }); 59 | } 60 | 61 | - (void)persistSave:(NSData *)data { 62 | NSError *error; 63 | _fileHandle = [self updateFileHandle:_fileHandle dir:_dir]; 64 | if (!_fileHandle) { 65 | PREDLogError(@"no file handle drop %@ data", _path); 66 | return; 67 | } 68 | [_fileHandle writeData:data]; 69 | [_fileHandle writeData:[@"\n" dataUsingEncoding:NSUTF8StringEncoding]]; 70 | } 71 | 72 | // no batch 73 | - (NSString *)nextArchivedPath { 74 | NSFileHandle *fileHandle = _fileHandle; 75 | NSString *path = 76 | [self nextArchivedPathForDir:_dir fileHandle:&fileHandle inQueue:_queue]; 77 | _fileHandle = fileHandle; 78 | return path; 79 | } 80 | 81 | - (NSString *)nextArchivedPathForDirRun:(NSString *)dir 82 | fileHandle: 83 | (NSFileHandle *__autoreleasing *)fileHandle { 84 | NSString *archivedPath; 85 | for (NSString *filePath in [_fileManager enumeratorAtPath:dir]) { 86 | NSPredicate *predicate = 87 | [NSPredicate predicateWithFormat:@"SELF MATCHES %@", 88 | @"^[0-9]+\\.?[0-9]*\\.archive$"]; 89 | if ([predicate evaluateWithObject:filePath]) { 90 | archivedPath = [NSString stringWithFormat:@"%@/%@", dir, filePath]; 91 | } 92 | } 93 | // if no archived file found 94 | for (NSString *filePath in [_fileManager enumeratorAtPath:dir]) { 95 | NSPredicate *predicate = [NSPredicate 96 | predicateWithFormat:@"SELF MATCHES %@", @"^[0-9]+\\.?[0-9]*$"]; 97 | if ([predicate evaluateWithObject:filePath]) { 98 | if (*fileHandle) { 99 | [*fileHandle closeFile]; 100 | *fileHandle = nil; 101 | } 102 | NSError *error; 103 | archivedPath = 104 | [NSString stringWithFormat:@"%@/%@.archive", dir, filePath]; 105 | [_fileManager 106 | moveItemAtPath:[NSString stringWithFormat:@"%@/%@", dir, filePath] 107 | toPath:archivedPath 108 | error:&error]; 109 | if (error) { 110 | archivedPath = nil; 111 | NSLog(@"archive file %@ fail", filePath); 112 | continue; 113 | } 114 | } 115 | } 116 | return archivedPath; 117 | } 118 | 119 | - (NSString *)nextArchivedPathForDir:(NSString *)dir 120 | fileHandle:(NSFileHandle *__autoreleasing *)fileHandle 121 | inQueue:(dispatch_queue_t)queue { 122 | __block NSString *archivedPath; 123 | dispatch_sync(queue, ^{ 124 | archivedPath = [self nextArchivedPathForDirRun:dir fileHandle:fileHandle]; 125 | }); 126 | return archivedPath; 127 | } 128 | 129 | - (void)purgeFile:(NSString *)filePath { 130 | NSError *error; 131 | [_fileManager removeItemAtPath:filePath error:&error]; 132 | if (error) { 133 | PREDLogError(@"purge file %@ error %@", filePath, error); 134 | } else { 135 | PREDLogVerbose(@"purge file %@ succeeded", filePath); 136 | } 137 | } 138 | 139 | - (void)purgeAll { 140 | NSError *error; 141 | for (NSString *fileName in [_fileManager enumeratorAtPath:_dir]) { 142 | NSString *filePath = [NSString stringWithFormat:@"%@/%@", _dir, fileName]; 143 | [_fileManager removeItemAtPath:filePath error:&error]; 144 | if (error) { 145 | PREDLogError(@"purge file %@ error %@", filePath, error); 146 | } else { 147 | PREDLogVerbose(@"purge file %@ succeeded", filePath); 148 | } 149 | } 150 | } 151 | 152 | - (void)purgeFiles:(NSArray *)filePaths { 153 | __block NSError *error; 154 | [filePaths enumerateObjectsUsingBlock:^(NSString *_Nonnull filePath, 155 | NSUInteger idx, BOOL *_Nonnull stop) { 156 | [_fileManager removeItemAtPath:filePath error:&error]; 157 | if (error) { 158 | PREDLogError(@"purge file %@ error %@", filePath, error); 159 | } else { 160 | PREDLogVerbose(@"purge file %@ succeeded", filePath); 161 | } 162 | }]; 163 | } 164 | 165 | - (NSFileHandle *)updateFileHandle:(NSFileHandle *)oldFileHandle 166 | dir:(NSString *)dir { 167 | if (oldFileHandle) { 168 | if (oldFileHandle.offsetInFile <= PREDMaxCacheFileSize) { 169 | return oldFileHandle; 170 | } else { 171 | [oldFileHandle closeFile]; 172 | oldFileHandle = nil; 173 | } 174 | } 175 | 176 | NSString *availableFile; 177 | for (NSString *filePath in [_fileManager enumeratorAtPath:dir]) { 178 | NSString *normalFilePattern = @"^[0-9]+\\.?[0-9]*$"; 179 | NSPredicate *predicate = 180 | [NSPredicate predicateWithFormat:@"SELF MATCHES %@", normalFilePattern]; 181 | if ([predicate evaluateWithObject:filePath]) { 182 | availableFile = [NSString stringWithFormat:@"%@/%@", dir, filePath]; 183 | break; 184 | } 185 | } 186 | if (!availableFile) { 187 | availableFile = [NSString 188 | stringWithFormat:@"%@/%f", dir, [[NSDate date] timeIntervalSince1970]]; 189 | BOOL success = [_fileManager createFileAtPath:availableFile 190 | contents:nil 191 | attributes:nil]; 192 | if (!success) { 193 | PREDLogError(@"create file failed %@", availableFile); 194 | return nil; 195 | } 196 | } 197 | oldFileHandle = [NSFileHandle fileHandleForUpdatingAtPath:availableFile]; 198 | [oldFileHandle seekToEndOfFile]; 199 | return oldFileHandle; 200 | } 201 | 202 | @end 203 | -------------------------------------------------------------------------------- /PreDemCocoaDemo/Pods/Target Support Files/Pods-PreDemObjcDemo/Pods-PreDemObjcDemo-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | # Used as a return value for each invocation of `strip_invalid_archs` function. 10 | STRIP_BINARY_RETVAL=0 11 | 12 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 13 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 14 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 15 | 16 | # Copies and strips a vendored framework 17 | install_framework() 18 | { 19 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 20 | local source="${BUILT_PRODUCTS_DIR}/$1" 21 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 22 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 23 | elif [ -r "$1" ]; then 24 | local source="$1" 25 | fi 26 | 27 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 28 | 29 | if [ -L "${source}" ]; then 30 | echo "Symlinked..." 31 | source="$(readlink "${source}")" 32 | fi 33 | 34 | # Use filter instead of exclude so missing patterns don't throw errors. 35 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 36 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 37 | 38 | local basename 39 | basename="$(basename -s .framework "$1")" 40 | binary="${destination}/${basename}.framework/${basename}" 41 | if ! [ -r "$binary" ]; then 42 | binary="${destination}/${basename}" 43 | fi 44 | 45 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 46 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 47 | strip_invalid_archs "$binary" 48 | fi 49 | 50 | # Resign the code if required by the build settings to avoid unstable apps 51 | code_sign_if_enabled "${destination}/$(basename "$1")" 52 | 53 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 54 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 55 | local swift_runtime_libs 56 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 57 | for lib in $swift_runtime_libs; do 58 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 59 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 60 | code_sign_if_enabled "${destination}/${lib}" 61 | done 62 | fi 63 | } 64 | 65 | # Copies and strips a vendored dSYM 66 | install_dsym() { 67 | local source="$1" 68 | if [ -r "$source" ]; then 69 | # Copy the dSYM into a the targets temp dir. 70 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 71 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 72 | 73 | local basename 74 | basename="$(basename -s .framework.dSYM "$source")" 75 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 76 | 77 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 78 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 79 | strip_invalid_archs "$binary" 80 | fi 81 | 82 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 83 | # Move the stripped file into its final destination. 84 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 85 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 86 | else 87 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 88 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 89 | fi 90 | fi 91 | } 92 | 93 | # Signs a framework with the provided identity 94 | code_sign_if_enabled() { 95 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 96 | # Use the current code_sign_identitiy 97 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 98 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 99 | 100 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 101 | code_sign_cmd="$code_sign_cmd &" 102 | fi 103 | echo "$code_sign_cmd" 104 | eval "$code_sign_cmd" 105 | fi 106 | } 107 | 108 | # Strip invalid architectures 109 | strip_invalid_archs() { 110 | binary="$1" 111 | # Get architectures for current target binary 112 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 113 | # Intersect them with the architectures we are building for 114 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 115 | # If there are no archs supported by this binary then warn the user 116 | if [[ -z "$intersected_archs" ]]; then 117 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 118 | STRIP_BINARY_RETVAL=0 119 | return 120 | fi 121 | stripped="" 122 | for arch in $binary_archs; do 123 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 124 | # Strip non-valid architectures in-place 125 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 126 | stripped="$stripped $arch" 127 | fi 128 | done 129 | if [[ "$stripped" ]]; then 130 | echo "Stripped $binary of architectures:$stripped" 131 | fi 132 | STRIP_BINARY_RETVAL=1 133 | } 134 | 135 | 136 | if [[ "$CONFIGURATION" == "Debug" ]]; then 137 | install_framework "${BUILT_PRODUCTS_DIR}/PreDemCocoa/PreDemCocoa.framework" 138 | install_framework "${BUILT_PRODUCTS_DIR}/UICKeyChainStore/UICKeyChainStore.framework" 139 | fi 140 | if [[ "$CONFIGURATION" == "Release" ]]; then 141 | install_framework "${BUILT_PRODUCTS_DIR}/PreDemCocoa/PreDemCocoa.framework" 142 | install_framework "${BUILT_PRODUCTS_DIR}/UICKeyChainStore/UICKeyChainStore.framework" 143 | fi 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | --------------------------------------------------------------------------------