Repository: aeronxie/XFBaiSiBuDeJie Branch: master Commit: 4b697315fbc7 Files: 1030 Total size: 58.6 MB Directory structure: gitextract_5913_8e3/ ├── Podfile ├── Pods/ │ ├── AFNetworking/ │ │ ├── AFNetworking/ │ │ │ ├── AFHTTPSessionManager.h │ │ │ ├── AFHTTPSessionManager.m │ │ │ ├── AFNetworkReachabilityManager.h │ │ │ ├── AFNetworkReachabilityManager.m │ │ │ ├── AFNetworking.h │ │ │ ├── AFSecurityPolicy.h │ │ │ ├── AFSecurityPolicy.m │ │ │ ├── AFURLRequestSerialization.h │ │ │ ├── AFURLRequestSerialization.m │ │ │ ├── AFURLResponseSerialization.h │ │ │ ├── AFURLResponseSerialization.m │ │ │ ├── AFURLSessionManager.h │ │ │ └── AFURLSessionManager.m │ │ ├── LICENSE │ │ ├── README.md │ │ └── UIKit+AFNetworking/ │ │ ├── AFAutoPurgingImageCache.h │ │ ├── AFAutoPurgingImageCache.m │ │ ├── AFImageDownloader.h │ │ ├── AFImageDownloader.m │ │ ├── AFNetworkActivityIndicatorManager.h │ │ ├── AFNetworkActivityIndicatorManager.m │ │ ├── UIActivityIndicatorView+AFNetworking.h │ │ ├── UIActivityIndicatorView+AFNetworking.m │ │ ├── UIButton+AFNetworking.h │ │ ├── UIButton+AFNetworking.m │ │ ├── UIImage+AFNetworking.h │ │ ├── UIImageView+AFNetworking.h │ │ ├── UIImageView+AFNetworking.m │ │ ├── UIKit+AFNetworking.h │ │ ├── UIProgressView+AFNetworking.h │ │ ├── UIProgressView+AFNetworking.m │ │ ├── UIRefreshControl+AFNetworking.h │ │ ├── UIRefreshControl+AFNetworking.m │ │ ├── UIWebView+AFNetworking.h │ │ └── UIWebView+AFNetworking.m │ ├── DACircularProgress/ │ │ ├── DACircularProgress/ │ │ │ ├── DACircularProgressView.h │ │ │ ├── DACircularProgressView.m │ │ │ ├── DALabeledCircularProgressView.h │ │ │ └── DALabeledCircularProgressView.m │ │ ├── LICENSE.md │ │ └── README.md │ ├── MJExtension/ │ │ ├── LICENSE │ │ ├── MJExtension/ │ │ │ ├── MJExtension.h │ │ │ ├── MJExtensionConst.h │ │ │ ├── MJExtensionConst.m │ │ │ ├── MJFoundation.h │ │ │ ├── MJFoundation.m │ │ │ ├── MJProperty.h │ │ │ ├── MJProperty.m │ │ │ ├── MJPropertyKey.h │ │ │ ├── MJPropertyKey.m │ │ │ ├── MJPropertyType.h │ │ │ ├── MJPropertyType.m │ │ │ ├── NSObject+MJClass.h │ │ │ ├── NSObject+MJClass.m │ │ │ ├── NSObject+MJCoding.h │ │ │ ├── NSObject+MJCoding.m │ │ │ ├── NSObject+MJKeyValue.h │ │ │ ├── NSObject+MJKeyValue.m │ │ │ ├── NSObject+MJProperty.h │ │ │ ├── NSObject+MJProperty.m │ │ │ ├── NSString+MJExtension.h │ │ │ └── NSString+MJExtension.m │ │ └── README.md │ ├── MJRefresh/ │ │ ├── LICENSE │ │ ├── MJRefresh/ │ │ │ ├── Base/ │ │ │ │ ├── MJRefreshAutoFooter.h │ │ │ │ ├── MJRefreshAutoFooter.m │ │ │ │ ├── MJRefreshBackFooter.h │ │ │ │ ├── MJRefreshBackFooter.m │ │ │ │ ├── MJRefreshComponent.h │ │ │ │ ├── MJRefreshComponent.m │ │ │ │ ├── MJRefreshFooter.h │ │ │ │ ├── MJRefreshFooter.m │ │ │ │ ├── MJRefreshHeader.h │ │ │ │ └── MJRefreshHeader.m │ │ │ ├── Custom/ │ │ │ │ ├── Footer/ │ │ │ │ │ ├── Auto/ │ │ │ │ │ │ ├── MJRefreshAutoGifFooter.h │ │ │ │ │ │ ├── MJRefreshAutoGifFooter.m │ │ │ │ │ │ ├── MJRefreshAutoNormalFooter.h │ │ │ │ │ │ ├── MJRefreshAutoNormalFooter.m │ │ │ │ │ │ ├── MJRefreshAutoStateFooter.h │ │ │ │ │ │ └── MJRefreshAutoStateFooter.m │ │ │ │ │ └── Back/ │ │ │ │ │ ├── MJRefreshBackGifFooter.h │ │ │ │ │ ├── MJRefreshBackGifFooter.m │ │ │ │ │ ├── MJRefreshBackNormalFooter.h │ │ │ │ │ ├── MJRefreshBackNormalFooter.m │ │ │ │ │ ├── MJRefreshBackStateFooter.h │ │ │ │ │ └── MJRefreshBackStateFooter.m │ │ │ │ └── Header/ │ │ │ │ ├── MJRefreshGifHeader.h │ │ │ │ ├── MJRefreshGifHeader.m │ │ │ │ ├── MJRefreshNormalHeader.h │ │ │ │ ├── MJRefreshNormalHeader.m │ │ │ │ ├── MJRefreshStateHeader.h │ │ │ │ └── MJRefreshStateHeader.m │ │ │ ├── MJRefresh.h │ │ │ ├── MJRefreshConst.h │ │ │ ├── MJRefreshConst.m │ │ │ ├── UIScrollView+MJExtension.h │ │ │ ├── UIScrollView+MJExtension.m │ │ │ ├── UIScrollView+MJRefresh.h │ │ │ ├── UIScrollView+MJRefresh.m │ │ │ ├── UIView+MJExtension.h │ │ │ └── UIView+MJExtension.m │ │ └── README.md │ ├── NJKWebViewProgress/ │ │ ├── LICENSE │ │ ├── NJKWebViewProgress/ │ │ │ ├── NJKWebViewProgress.h │ │ │ ├── NJKWebViewProgress.m │ │ │ ├── NJKWebViewProgressView.h │ │ │ └── NJKWebViewProgressView.m │ │ └── README.md │ ├── Pods.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcuserdata/ │ │ └── FAY.xcuserdatad/ │ │ └── xcschemes/ │ │ ├── AFNetworking.xcscheme │ │ ├── DACircularProgress.xcscheme │ │ ├── MJExtension.xcscheme │ │ ├── MJRefresh.xcscheme │ │ ├── NJKWebViewProgress.xcscheme │ │ ├── Pods.xcscheme │ │ ├── ReactiveCocoa.xcscheme │ │ ├── Result.xcscheme │ │ ├── SDWebImage.xcscheme │ │ ├── SVProgressHUD.xcscheme │ │ └── xcschememanagement.plist │ ├── ReactiveCocoa/ │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── ReactiveCocoa/ │ │ ├── Objective-C/ │ │ │ ├── MKAnnotationView+RACSignalSupport.h │ │ │ ├── MKAnnotationView+RACSignalSupport.m │ │ │ ├── NSArray+RACSequenceAdditions.h │ │ │ ├── NSArray+RACSequenceAdditions.m │ │ │ ├── NSData+RACSupport.h │ │ │ ├── NSData+RACSupport.m │ │ │ ├── NSDictionary+RACSequenceAdditions.h │ │ │ ├── NSDictionary+RACSequenceAdditions.m │ │ │ ├── NSEnumerator+RACSequenceAdditions.h │ │ │ ├── NSEnumerator+RACSequenceAdditions.m │ │ │ ├── NSFileHandle+RACSupport.h │ │ │ ├── NSFileHandle+RACSupport.m │ │ │ ├── NSIndexSet+RACSequenceAdditions.h │ │ │ ├── NSIndexSet+RACSequenceAdditions.m │ │ │ ├── NSInvocation+RACTypeParsing.h │ │ │ ├── NSInvocation+RACTypeParsing.m │ │ │ ├── NSNotificationCenter+RACSupport.h │ │ │ ├── NSNotificationCenter+RACSupport.m │ │ │ ├── NSObject+RACDeallocating.h │ │ │ ├── NSObject+RACDeallocating.m │ │ │ ├── NSObject+RACDescription.h │ │ │ ├── NSObject+RACDescription.m │ │ │ ├── NSObject+RACKVOWrapper.h │ │ │ ├── NSObject+RACKVOWrapper.m │ │ │ ├── NSObject+RACLifting.h │ │ │ ├── NSObject+RACLifting.m │ │ │ ├── NSObject+RACPropertySubscribing.h │ │ │ ├── NSObject+RACPropertySubscribing.m │ │ │ ├── NSObject+RACSelectorSignal.h │ │ │ ├── NSObject+RACSelectorSignal.m │ │ │ ├── NSOrderedSet+RACSequenceAdditions.h │ │ │ ├── NSOrderedSet+RACSequenceAdditions.m │ │ │ ├── NSSet+RACSequenceAdditions.h │ │ │ ├── NSSet+RACSequenceAdditions.m │ │ │ ├── NSString+RACKeyPathUtilities.h │ │ │ ├── NSString+RACKeyPathUtilities.m │ │ │ ├── NSString+RACSequenceAdditions.h │ │ │ ├── NSString+RACSequenceAdditions.m │ │ │ ├── NSString+RACSupport.h │ │ │ ├── NSString+RACSupport.m │ │ │ ├── NSURLConnection+RACSupport.h │ │ │ ├── NSURLConnection+RACSupport.m │ │ │ ├── NSUserDefaults+RACSupport.h │ │ │ ├── NSUserDefaults+RACSupport.m │ │ │ ├── RACArraySequence.h │ │ │ ├── RACArraySequence.m │ │ │ ├── RACBehaviorSubject.h │ │ │ ├── RACBehaviorSubject.m │ │ │ ├── RACBlockTrampoline.h │ │ │ ├── RACBlockTrampoline.m │ │ │ ├── RACChannel.h │ │ │ ├── RACChannel.m │ │ │ ├── RACCommand.h │ │ │ ├── RACCommand.m │ │ │ ├── RACCompoundDisposable.h │ │ │ ├── RACCompoundDisposable.m │ │ │ ├── RACCompoundDisposableProvider.d │ │ │ ├── RACDelegateProxy.h │ │ │ ├── RACDelegateProxy.m │ │ │ ├── RACDisposable.h │ │ │ ├── RACDisposable.m │ │ │ ├── RACDynamicPropertySuperclass.h │ │ │ ├── RACDynamicPropertySuperclass.m │ │ │ ├── RACDynamicSequence.h │ │ │ ├── RACDynamicSequence.m │ │ │ ├── RACDynamicSignal.h │ │ │ ├── RACDynamicSignal.m │ │ │ ├── RACEagerSequence.h │ │ │ ├── RACEagerSequence.m │ │ │ ├── RACEmptySequence.h │ │ │ ├── RACEmptySequence.m │ │ │ ├── RACEmptySignal.h │ │ │ ├── RACEmptySignal.m │ │ │ ├── RACErrorSignal.h │ │ │ ├── RACErrorSignal.m │ │ │ ├── RACEvent.h │ │ │ ├── RACEvent.m │ │ │ ├── RACGroupedSignal.h │ │ │ ├── RACGroupedSignal.m │ │ │ ├── RACImmediateScheduler.h │ │ │ ├── RACImmediateScheduler.m │ │ │ ├── RACIndexSetSequence.h │ │ │ ├── RACIndexSetSequence.m │ │ │ ├── RACKVOChannel.h │ │ │ ├── RACKVOChannel.m │ │ │ ├── RACKVOProxy.h │ │ │ ├── RACKVOProxy.m │ │ │ ├── RACKVOTrampoline.h │ │ │ ├── RACKVOTrampoline.m │ │ │ ├── RACMulticastConnection+Private.h │ │ │ ├── RACMulticastConnection.h │ │ │ ├── RACMulticastConnection.m │ │ │ ├── RACObjCRuntime.h │ │ │ ├── RACObjCRuntime.m │ │ │ ├── RACPassthroughSubscriber.h │ │ │ ├── RACPassthroughSubscriber.m │ │ │ ├── RACQueueScheduler+Subclass.h │ │ │ ├── RACQueueScheduler.h │ │ │ ├── RACQueueScheduler.m │ │ │ ├── RACReplaySubject.h │ │ │ ├── RACReplaySubject.m │ │ │ ├── RACReturnSignal.h │ │ │ ├── RACReturnSignal.m │ │ │ ├── RACScheduler+Private.h │ │ │ ├── RACScheduler+Subclass.h │ │ │ ├── RACScheduler.h │ │ │ ├── RACScheduler.m │ │ │ ├── RACScopedDisposable.h │ │ │ ├── RACScopedDisposable.m │ │ │ ├── RACSequence.h │ │ │ ├── RACSequence.m │ │ │ ├── RACSerialDisposable.h │ │ │ ├── RACSerialDisposable.m │ │ │ ├── RACSignal+Operations.h │ │ │ ├── RACSignal+Operations.m │ │ │ ├── RACSignal.h │ │ │ ├── RACSignal.m │ │ │ ├── RACSignalProvider.d │ │ │ ├── RACSignalSequence.h │ │ │ ├── RACSignalSequence.m │ │ │ ├── RACStream+Private.h │ │ │ ├── RACStream.h │ │ │ ├── RACStream.m │ │ │ ├── RACStringSequence.h │ │ │ ├── RACStringSequence.m │ │ │ ├── RACSubject.h │ │ │ ├── RACSubject.m │ │ │ ├── RACSubscriber+Private.h │ │ │ ├── RACSubscriber.h │ │ │ ├── RACSubscriber.m │ │ │ ├── RACSubscriptingAssignmentTrampoline.h │ │ │ ├── RACSubscriptingAssignmentTrampoline.m │ │ │ ├── RACSubscriptionScheduler.h │ │ │ ├── RACSubscriptionScheduler.m │ │ │ ├── RACTargetQueueScheduler.h │ │ │ ├── RACTargetQueueScheduler.m │ │ │ ├── RACTestScheduler.h │ │ │ ├── RACTestScheduler.m │ │ │ ├── RACTuple.h │ │ │ ├── RACTuple.m │ │ │ ├── RACTupleSequence.h │ │ │ ├── RACTupleSequence.m │ │ │ ├── RACUnarySequence.h │ │ │ ├── RACUnarySequence.m │ │ │ ├── RACUnit.h │ │ │ ├── RACUnit.m │ │ │ ├── RACValueTransformer.h │ │ │ ├── RACValueTransformer.m │ │ │ ├── ReactiveCocoa-Bridging-Header.h │ │ │ ├── UIActionSheet+RACSignalSupport.h │ │ │ ├── UIActionSheet+RACSignalSupport.m │ │ │ ├── UIAlertView+RACSignalSupport.h │ │ │ ├── UIAlertView+RACSignalSupport.m │ │ │ ├── UIBarButtonItem+RACCommandSupport.h │ │ │ ├── UIBarButtonItem+RACCommandSupport.m │ │ │ ├── UIButton+RACCommandSupport.h │ │ │ ├── UIButton+RACCommandSupport.m │ │ │ ├── UICollectionReusableView+RACSignalSupport.h │ │ │ ├── UICollectionReusableView+RACSignalSupport.m │ │ │ ├── UIControl+RACSignalSupport.h │ │ │ ├── UIControl+RACSignalSupport.m │ │ │ ├── UIControl+RACSignalSupportPrivate.h │ │ │ ├── UIControl+RACSignalSupportPrivate.m │ │ │ ├── UIDatePicker+RACSignalSupport.h │ │ │ ├── UIDatePicker+RACSignalSupport.m │ │ │ ├── UIGestureRecognizer+RACSignalSupport.h │ │ │ ├── UIGestureRecognizer+RACSignalSupport.m │ │ │ ├── UIImagePickerController+RACSignalSupport.h │ │ │ ├── UIImagePickerController+RACSignalSupport.m │ │ │ ├── UIRefreshControl+RACCommandSupport.h │ │ │ ├── UIRefreshControl+RACCommandSupport.m │ │ │ ├── UISegmentedControl+RACSignalSupport.h │ │ │ ├── UISegmentedControl+RACSignalSupport.m │ │ │ ├── UISlider+RACSignalSupport.h │ │ │ ├── UISlider+RACSignalSupport.m │ │ │ ├── UIStepper+RACSignalSupport.h │ │ │ ├── UIStepper+RACSignalSupport.m │ │ │ ├── UISwitch+RACSignalSupport.h │ │ │ ├── UISwitch+RACSignalSupport.m │ │ │ ├── UITableViewCell+RACSignalSupport.h │ │ │ ├── UITableViewCell+RACSignalSupport.m │ │ │ ├── UITableViewHeaderFooterView+RACSignalSupport.h │ │ │ ├── UITableViewHeaderFooterView+RACSignalSupport.m │ │ │ ├── UITextField+RACSignalSupport.h │ │ │ ├── UITextField+RACSignalSupport.m │ │ │ ├── UITextView+RACSignalSupport.h │ │ │ ├── UITextView+RACSignalSupport.m │ │ │ └── extobjc/ │ │ │ ├── EXTKeyPathCoding.h │ │ │ ├── EXTRuntimeExtensions.h │ │ │ ├── EXTRuntimeExtensions.m │ │ │ ├── EXTScope.h │ │ │ └── metamacros.h │ │ ├── ReactiveCocoa.h │ │ └── Swift/ │ │ ├── Action.swift │ │ ├── Atomic.swift │ │ ├── Bag.swift │ │ ├── Disposable.swift │ │ ├── Errors.swift │ │ ├── Event.swift │ │ ├── FoundationExtensions.swift │ │ ├── ObjectiveCBridging.swift │ │ ├── Observer.swift │ │ ├── Optional.swift │ │ ├── Property.swift │ │ ├── Scheduler.swift │ │ ├── Signal.swift │ │ ├── SignalProducer.swift │ │ └── TupleExtensions.swift │ ├── Result/ │ │ ├── LICENSE │ │ ├── README.md │ │ └── Result/ │ │ ├── Result.swift │ │ └── ResultType.swift │ ├── SDWebImage/ │ │ ├── LICENSE │ │ ├── README.md │ │ └── SDWebImage/ │ │ ├── NSData+ImageContentType.h │ │ ├── NSData+ImageContentType.m │ │ ├── SDImageCache.h │ │ ├── SDImageCache.m │ │ ├── SDWebImageCompat.h │ │ ├── SDWebImageCompat.m │ │ ├── SDWebImageDecoder.h │ │ ├── SDWebImageDecoder.m │ │ ├── SDWebImageDownloader.h │ │ ├── SDWebImageDownloader.m │ │ ├── SDWebImageDownloaderOperation.h │ │ ├── SDWebImageDownloaderOperation.m │ │ ├── SDWebImageManager.h │ │ ├── SDWebImageManager.m │ │ ├── SDWebImageOperation.h │ │ ├── SDWebImagePrefetcher.h │ │ ├── SDWebImagePrefetcher.m │ │ ├── UIButton+WebCache.h │ │ ├── UIButton+WebCache.m │ │ ├── UIImage+GIF.h │ │ ├── UIImage+GIF.m │ │ ├── UIImage+MultiFormat.h │ │ ├── UIImage+MultiFormat.m │ │ ├── UIImageView+HighlightedWebCache.h │ │ ├── UIImageView+HighlightedWebCache.m │ │ ├── UIImageView+WebCache.h │ │ ├── UIImageView+WebCache.m │ │ ├── UIView+WebCacheOperation.h │ │ └── UIView+WebCacheOperation.m │ ├── SVProgressHUD/ │ │ ├── LICENSE.txt │ │ ├── README.md │ │ └── SVProgressHUD/ │ │ ├── SVIndefiniteAnimatedView.h │ │ ├── SVIndefiniteAnimatedView.m │ │ ├── SVProgressHUD.h │ │ ├── SVProgressHUD.m │ │ ├── SVRadialGradientLayer.h │ │ └── SVRadialGradientLayer.m │ ├── Target Support Files/ │ │ ├── AFNetworking/ │ │ │ ├── AFNetworking-dummy.m │ │ │ ├── AFNetworking-prefix.pch │ │ │ ├── AFNetworking-umbrella.h │ │ │ ├── AFNetworking.modulemap │ │ │ ├── AFNetworking.xcconfig │ │ │ └── Info.plist │ │ ├── DACircularProgress/ │ │ │ ├── DACircularProgress-dummy.m │ │ │ ├── DACircularProgress-prefix.pch │ │ │ ├── DACircularProgress-umbrella.h │ │ │ ├── DACircularProgress.modulemap │ │ │ ├── DACircularProgress.xcconfig │ │ │ └── Info.plist │ │ ├── MJExtension/ │ │ │ ├── Info.plist │ │ │ ├── MJExtension-dummy.m │ │ │ ├── MJExtension-prefix.pch │ │ │ ├── MJExtension-umbrella.h │ │ │ ├── MJExtension.modulemap │ │ │ └── MJExtension.xcconfig │ │ ├── MJRefresh/ │ │ │ ├── Info.plist │ │ │ ├── MJRefresh-dummy.m │ │ │ ├── MJRefresh-prefix.pch │ │ │ ├── MJRefresh-umbrella.h │ │ │ ├── MJRefresh.modulemap │ │ │ └── MJRefresh.xcconfig │ │ ├── NJKWebViewProgress/ │ │ │ ├── Info.plist │ │ │ ├── NJKWebViewProgress-dummy.m │ │ │ ├── NJKWebViewProgress-prefix.pch │ │ │ ├── NJKWebViewProgress-umbrella.h │ │ │ ├── NJKWebViewProgress.modulemap │ │ │ └── NJKWebViewProgress.xcconfig │ │ ├── Pods/ │ │ │ ├── Info.plist │ │ │ ├── Pods-acknowledgements.markdown │ │ │ ├── Pods-acknowledgements.plist │ │ │ ├── Pods-dummy.m │ │ │ ├── Pods-frameworks.sh │ │ │ ├── Pods-resources.sh │ │ │ ├── Pods-umbrella.h │ │ │ ├── Pods.debug.xcconfig │ │ │ ├── Pods.modulemap │ │ │ └── Pods.release.xcconfig │ │ ├── ReactiveCocoa/ │ │ │ ├── Info.plist │ │ │ ├── ReactiveCocoa-dummy.m │ │ │ ├── ReactiveCocoa-prefix.pch │ │ │ ├── ReactiveCocoa-umbrella.h │ │ │ ├── ReactiveCocoa.modulemap │ │ │ └── ReactiveCocoa.xcconfig │ │ ├── Result/ │ │ │ ├── Info.plist │ │ │ ├── Result-dummy.m │ │ │ ├── Result-prefix.pch │ │ │ ├── Result-umbrella.h │ │ │ ├── Result.modulemap │ │ │ └── Result.xcconfig │ │ ├── SDWebImage/ │ │ │ ├── Info.plist │ │ │ ├── SDWebImage-dummy.m │ │ │ ├── SDWebImage-prefix.pch │ │ │ ├── SDWebImage-umbrella.h │ │ │ ├── SDWebImage.modulemap │ │ │ └── SDWebImage.xcconfig │ │ └── SVProgressHUD/ │ │ ├── Info.plist │ │ ├── SVProgressHUD-dummy.m │ │ ├── SVProgressHUD-prefix.pch │ │ ├── SVProgressHUD-umbrella.h │ │ ├── SVProgressHUD.modulemap │ │ └── SVProgressHUD.xcconfig │ └── UMengSocial/ │ └── Umeng_SDK_Social_iOS_ARM64_4.4/ │ ├── UMSocial_Sdk_4.4/ │ │ ├── Header/ │ │ │ ├── UMSocial.h │ │ │ ├── UMSocialAccountManager.h │ │ │ ├── UMSocialBar.h │ │ │ ├── UMSocialConfig.h │ │ │ ├── UMSocialControllerService.h │ │ │ ├── UMSocialControllerServiceComment.h │ │ │ ├── UMSocialData.h │ │ │ ├── UMSocialDataService.h │ │ │ ├── UMSocialSnsData.h │ │ │ ├── UMSocialSnsPlatformManager.h │ │ │ └── UMSocialSnsService.h │ │ ├── SocialSDKXib/ │ │ │ ├── UMSCommentDetailController.xib │ │ │ ├── UMSCommentInputController.xib │ │ │ ├── UMSCommentInputControlleriPad.xib │ │ │ ├── UMSLoginViewController.xib │ │ │ ├── UMSShareListController.xib │ │ │ ├── UMShareEditViewController.xib │ │ │ ├── UMShareEditViewControlleriPad.xib │ │ │ └── UMSnsAccountViewController.xib │ │ ├── en.lproj/ │ │ │ └── UMSocialLocalizable.strings │ │ ├── libUMSocial_Sdk_4.4.a │ │ ├── libUMSocial_Sdk_Comment_4.4.a │ │ └── zh-Hans.lproj/ │ │ └── UMSocialLocalizable.strings │ └── UMSocial_Sdk_Extra_Frameworks/ │ ├── AlipayShare/ │ │ ├── APOpenAPI.h │ │ ├── APOpenAPIObject.h │ │ ├── UMSocialAlipayShareHandler.h │ │ ├── libAPOpenSdk.a │ │ └── libSocialAlipayShare.a │ ├── Facebook/ │ │ ├── FBSDKCoreKit.framework/ │ │ │ ├── FBSDKCoreKit │ │ │ ├── Headers/ │ │ │ │ ├── FBSDKAccessToken.h │ │ │ │ ├── FBSDKAppEvents.h │ │ │ │ ├── FBSDKAppLinkResolver.h │ │ │ │ ├── FBSDKAppLinkUtility.h │ │ │ │ ├── FBSDKApplicationDelegate.h │ │ │ │ ├── FBSDKButton.h │ │ │ │ ├── FBSDKConstants.h │ │ │ │ ├── FBSDKCopying.h │ │ │ │ ├── FBSDKCoreKit.h │ │ │ │ ├── FBSDKGraphErrorRecoveryProcessor.h │ │ │ │ ├── FBSDKGraphRequest.h │ │ │ │ ├── FBSDKGraphRequestConnection.h │ │ │ │ ├── FBSDKGraphRequestDataAttachment.h │ │ │ │ ├── FBSDKMacros.h │ │ │ │ ├── FBSDKMutableCopying.h │ │ │ │ ├── FBSDKProfile.h │ │ │ │ ├── FBSDKProfilePictureView.h │ │ │ │ ├── FBSDKSettings.h │ │ │ │ ├── FBSDKTestUsersManager.h │ │ │ │ └── FBSDKUtility.h │ │ │ ├── Info.plist │ │ │ ├── Modules/ │ │ │ │ └── module.modulemap │ │ │ └── PrivateHeaders/ │ │ │ ├── FBSDKAccessTokenCacheV4.h │ │ │ ├── FBSDKBridgeAPICrypto.h │ │ │ ├── FBSDKBridgeAPIProtocol.h │ │ │ ├── FBSDKBridgeAPIProtocolNativeV1.h │ │ │ ├── FBSDKBridgeAPIProtocolWebV1.h │ │ │ ├── FBSDKError.h │ │ │ ├── FBSDKGraphRequestBody.h │ │ │ ├── FBSDKGraphRequestMetadata.h │ │ │ ├── FBSDKURLConnection.h │ │ │ └── FBSDKWebDialogView.h │ │ ├── FBSDKLoginKit.framework/ │ │ │ ├── FBSDKLoginKit │ │ │ ├── Headers/ │ │ │ │ ├── FBSDKLoginButton.h │ │ │ │ ├── FBSDKLoginConstants.h │ │ │ │ ├── FBSDKLoginKit.h │ │ │ │ ├── FBSDKLoginManager.h │ │ │ │ ├── FBSDKLoginManagerLoginResult.h │ │ │ │ ├── FBSDKLoginTooltipView.h │ │ │ │ └── FBSDKTooltipView.h │ │ │ ├── Info.plist │ │ │ └── Modules/ │ │ │ └── module.modulemap │ │ ├── FBSDKShareKit.framework/ │ │ │ ├── FBSDKShareKit │ │ │ ├── Headers/ │ │ │ │ ├── FBSDKAppGroupAddDialog.h │ │ │ │ ├── FBSDKAppGroupContent.h │ │ │ │ ├── FBSDKAppGroupJoinDialog.h │ │ │ │ ├── FBSDKAppInviteContent.h │ │ │ │ ├── FBSDKAppInviteDialog.h │ │ │ │ ├── FBSDKGameRequestContent.h │ │ │ │ ├── FBSDKGameRequestDialog.h │ │ │ │ ├── FBSDKLikeButton.h │ │ │ │ ├── FBSDKLikeControl.h │ │ │ │ ├── FBSDKLikeObjectType.h │ │ │ │ ├── FBSDKLiking.h │ │ │ │ ├── FBSDKMessageDialog.h │ │ │ │ ├── FBSDKSendButton.h │ │ │ │ ├── FBSDKShareAPI.h │ │ │ │ ├── FBSDKShareButton.h │ │ │ │ ├── FBSDKShareConstants.h │ │ │ │ ├── FBSDKShareDialog.h │ │ │ │ ├── FBSDKShareDialogMode.h │ │ │ │ ├── FBSDKShareKit.h │ │ │ │ ├── FBSDKShareLinkContent.h │ │ │ │ ├── FBSDKShareOpenGraphAction.h │ │ │ │ ├── FBSDKShareOpenGraphContent.h │ │ │ │ ├── FBSDKShareOpenGraphObject.h │ │ │ │ ├── FBSDKShareOpenGraphValueContainer.h │ │ │ │ ├── FBSDKSharePhoto.h │ │ │ │ ├── FBSDKSharePhotoContent.h │ │ │ │ ├── FBSDKShareVideo.h │ │ │ │ ├── FBSDKShareVideoContent.h │ │ │ │ ├── FBSDKSharing.h │ │ │ │ ├── FBSDKSharingButton.h │ │ │ │ └── FBSDKSharingContent.h │ │ │ ├── Info.plist │ │ │ └── Modules/ │ │ │ └── module.modulemap │ │ ├── UMSocialFacebookHandler.h │ │ └── libSocialFacebook.a │ ├── Instagram/ │ │ ├── UMSocialInstagramHandler.h │ │ └── libSocialInstagram.a │ ├── LaiWang/ │ │ ├── UMSocialLaiwangHandler.h │ │ └── libSocialLaiWang.a │ ├── Line/ │ │ ├── UMSocialLineHandler.h │ │ └── libSocialLine.a │ ├── Sina/ │ │ ├── UMSocialSinaHandler.h │ │ └── libSocialSina.a │ ├── SinaSSO/ │ │ ├── UMSocialSinaSSOHandler.h │ │ ├── WBHttpRequest+WeiboGame.h │ │ ├── WBHttpRequest+WeiboShare.h │ │ ├── WBHttpRequest+WeiboToken.h │ │ ├── WBHttpRequest+WeiboUser.h │ │ ├── WBHttpRequest.h │ │ ├── WBSDKBasicButton.h │ │ ├── WBSDKCommentButton.h │ │ ├── WBSDKRelationshipButton.h │ │ ├── WeiboSDK.bundle/ │ │ │ └── others/ │ │ │ ├── countryList │ │ │ └── mfp.cer │ │ ├── WeiboSDK.h │ │ ├── WeiboUser.h │ │ ├── libSocialSinaSSO.a │ │ └── libWeiboSDK.a │ ├── TencentOpenAPI/ │ │ ├── TencentOpenAPI.framework/ │ │ │ ├── Headers/ │ │ │ │ ├── QQApiInterface.h │ │ │ │ ├── QQApiInterfaceObject.h │ │ │ │ ├── TencentApiInterface.h │ │ │ │ ├── TencentMessageObject.h │ │ │ │ ├── TencentOAuth.h │ │ │ │ ├── TencentOAuthObject.h │ │ │ │ ├── WeiBoAPI.h │ │ │ │ └── sdkdef.h │ │ │ └── TencentOpenAPI │ │ ├── TencentOpenApi_IOS_Bundle.bundle/ │ │ │ ├── ios_open_sdk_2.9.3.2_iphone │ │ │ └── local.html │ │ ├── UMSocialQQHandler.h │ │ └── libSocialQQ.a │ ├── Tumblr/ │ │ ├── UMSocialTumblrHandler.h │ │ └── libSocialTumblr.a │ ├── Twitter/ │ │ ├── Fabric.framework/ │ │ │ ├── Fabric │ │ │ ├── Headers/ │ │ │ │ ├── FABAttributes.h │ │ │ │ └── Fabric.h │ │ │ ├── Info.plist │ │ │ ├── Modules/ │ │ │ │ └── module.modulemap │ │ │ └── run │ │ ├── TwitterCore.framework/ │ │ │ ├── Headers/ │ │ │ │ ├── TWTRAPIErrorCode.h │ │ │ │ ├── TWTRAuthConfig.h │ │ │ │ ├── TWTRAuthSession.h │ │ │ │ ├── TWTRConstants.h │ │ │ │ ├── TWTRCoreOAuthSigning.h │ │ │ │ ├── TWTRGuestSession.h │ │ │ │ └── TwitterCore.h │ │ │ ├── Info.plist │ │ │ ├── Modules/ │ │ │ │ └── module.modulemap │ │ │ └── TwitterCore │ │ ├── TwitterKit.framework/ │ │ │ ├── Headers/ │ │ │ │ ├── TWTRAPIClient.h │ │ │ │ ├── TWTRCollectionTimelineDataSource.h │ │ │ │ ├── TWTRComposer.h │ │ │ │ ├── TWTRDefines.h │ │ │ │ ├── TWTRListTimelineDataSource.h │ │ │ │ ├── TWTRLogInButton.h │ │ │ │ ├── TWTROAuthSigning.h │ │ │ │ ├── TWTRSearchTimelineDataSource.h │ │ │ │ ├── TWTRSession.h │ │ │ │ ├── TWTRShareEmailViewController.h │ │ │ │ ├── TWTRTimelineDataSource.h │ │ │ │ ├── TWTRTimelineType.h │ │ │ │ ├── TWTRTimelineViewController.h │ │ │ │ ├── TWTRTweet.h │ │ │ │ ├── TWTRTweetTableViewCell.h │ │ │ │ ├── TWTRTweetView.h │ │ │ │ ├── TWTRTweetViewDelegate.h │ │ │ │ ├── TWTRUser.h │ │ │ │ ├── TWTRUserTimelineDataSource.h │ │ │ │ ├── Twitter.h │ │ │ │ └── TwitterKit.h │ │ │ ├── Info.plist │ │ │ ├── Modules/ │ │ │ │ └── module.modulemap │ │ │ ├── Resources/ │ │ │ │ └── TwitterKitResources.bundle/ │ │ │ │ ├── TFSScribe.momd/ │ │ │ │ │ ├── TFSScribe.mom │ │ │ │ │ └── VersionInfo.plist │ │ │ │ ├── ar.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── bn.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── cs.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── da.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── de.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── en-gb.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── en.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── es.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── fa.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── fi.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── fr.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── he.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── hi.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── hu.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── id.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── it.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ja.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ko.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ms.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── nb.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── nl.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── pl.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── pt.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ro.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ru.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── sv.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── th.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── tl.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── tr.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── uk.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ur.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── vi.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── zh-Hans.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ └── zh-Hant.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── TwitterKit │ │ │ └── Versions/ │ │ │ ├── A/ │ │ │ │ └── Resources/ │ │ │ │ └── TwitterKitResources.bundle/ │ │ │ │ ├── TFSScribe.momd/ │ │ │ │ │ ├── TFSScribe.mom │ │ │ │ │ └── VersionInfo.plist │ │ │ │ ├── ar.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── bn.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── cs.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── da.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── de.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── en-gb.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── en.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── es.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── fa.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── fi.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── fr.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── he.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── hi.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── hu.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── id.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── it.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ja.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ko.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ms.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── nb.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── nl.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── pl.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── pt.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ro.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ru.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── sv.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── th.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── tl.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── tr.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── uk.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── ur.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── vi.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ ├── zh-Hans.lproj/ │ │ │ │ │ └── Localizable.strings │ │ │ │ └── zh-Hant.lproj/ │ │ │ │ └── Localizable.strings │ │ │ └── Current/ │ │ │ └── Resources/ │ │ │ └── TwitterKitResources.bundle/ │ │ │ ├── TFSScribe.momd/ │ │ │ │ ├── TFSScribe.mom │ │ │ │ └── VersionInfo.plist │ │ │ ├── ar.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── bn.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── cs.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── da.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── de.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── en-gb.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── en.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── es.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── fa.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── fi.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── fr.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── he.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── hi.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── hu.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── id.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── it.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── ja.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── ko.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── ms.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── nb.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── nl.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── pl.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── pt.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── ro.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── ru.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── sv.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── th.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── tl.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── tr.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── uk.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── ur.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── vi.lproj/ │ │ │ │ └── Localizable.strings │ │ │ ├── zh-Hans.lproj/ │ │ │ │ └── Localizable.strings │ │ │ └── zh-Hant.lproj/ │ │ │ └── Localizable.strings │ │ ├── UMSocialTwitterHandler.h │ │ └── libSocialTwitter.a │ ├── Wechat/ │ │ ├── UMSocialWechatHandler.h │ │ ├── WXApi.h │ │ ├── WXApiObject.h │ │ ├── libSocialWechat.a │ │ └── libWeChatSDK.a │ └── Whatsapp/ │ ├── UMSocialWhatsappHandler.h │ └── libSocialWhatsapp.a ├── README.md ├── Web/ │ ├── Web/ │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets/ │ │ │ └── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ └── main.m │ └── Web.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata/ │ │ └── FAY.xcuserdatad/ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata/ │ └── FAY.xcuserdatad/ │ └── xcschemes/ │ ├── Web.xcscheme │ └── xcschememanagement.plist ├── XFBaiSiBuDeJie/ │ ├── Assets.xcassets/ │ │ ├── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Brand Assets.launchimage/ │ │ │ └── Contents.json │ │ ├── Comment/ │ │ │ ├── Contents.json │ │ │ ├── Profile_manIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── Profile_womanIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment-bar-bg.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment-bar-keyboard-click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment-bar-keyboard.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment-bar-record-click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment-bar-record.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment-bar-voice-click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment-bar-voice.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── commentLikeButton.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── commentLikeButtonClick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment_bar_at_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment_bar_at_icon_click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── comment_nav_item_share_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ └── comment_nav_item_share_icon_click.imageset/ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Essence/ │ │ │ ├── Contents.json │ │ │ ├── Profile_AddV_authen.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── cell-button-line.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── cell-content-line.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── cellFollowClickIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── cellFollowDisableIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── cellFollowIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── cellmorebtnclick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── cellmorebtnnormal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── common-gif.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── defaultUserIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── imageBackground.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellBackground.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellCai.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellCaiClick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellComment.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellCommentClick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellDing.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellDingClick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellShare.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mainCellShareClick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── playButton.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── playButtonClick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── playButtonPause.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── playButtonPlay.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── post_placeholderImage.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── see-big-picture-background.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── see-big-picture.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── show_image_back_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tagicon.imageset/ │ │ │ │ └── Contents.json │ │ │ └── video-play.imageset/ │ │ │ └── Contents.json │ │ ├── FriendTrends/ │ │ │ ├── Contents.json │ │ │ ├── FollowBtnBg.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── FollowBtnClickBg.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── friendsTrend_login.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── friendsTrend_login_click.imageset/ │ │ │ │ └── Contents.json │ │ │ └── header_cry_icon.imageset/ │ │ │ └── Contents.json │ │ ├── LoginRegister/ │ │ │ ├── loginBtnBg.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── loginBtnBgClick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_QQ_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_QQ_icon_click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_close_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_register_background.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_register_button.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_register_button_click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_register_left_line.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_register_right_line.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_rgister_textfield_bg.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_sina_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_sina_icon_click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── login_tecent_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ └── login_tecent_icon_click.imageset/ │ │ │ └── Contents.json │ │ ├── Me/ │ │ │ ├── mine-icon-activity.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-icon-feedback.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-icon-manhua.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-icon-more.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-icon-nearby.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-icon-preview.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-icon-recentHot.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-icon-search.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-my-post.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-setting-iconN.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine_icon_nearby.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine_icon_random.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine_msg_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ └── setup-head-default.imageset/ │ │ │ └── Contents.json │ │ ├── Navigation/ │ │ │ ├── Contents.json │ │ │ ├── MainTagSubIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── MainTagSubIconClick.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── MainTitle.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── friendsRecommentIcon-click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── friendsRecommentIcon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-moon-icon-click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-moon-icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-setting-icon-click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-setting-icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-sun-icon-click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── mine-sun-icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── nav_coin_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── nav_coin_icon_click.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── navigationButtonReturn.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── navigationButtonReturnClick.imageset/ │ │ │ │ └── Contents.json │ │ │ └── navigationbarBackgroundWhite.imageset/ │ │ │ └── Contents.json │ │ ├── Play/ │ │ │ ├── Contents.json │ │ │ ├── play-voice-bg-select.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── play-voice-bg.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── play-voice-bgN.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── play-voice-icon-0.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── play-voice-icon-1.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── play-voice-icon-2.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── play-voice-icon-3.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── play-voice-stop.imageset/ │ │ │ │ └── Contents.json │ │ │ └── play.imageset/ │ │ │ └── Contents.json │ │ ├── Publish/ │ │ │ ├── Contents.json │ │ │ ├── app_slogan.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── publish-audio.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── publish-offline.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── publish-picture.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── publish-review.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── publish-text.imageset/ │ │ │ │ └── Contents.json │ │ │ └── publish-video.imageset/ │ │ │ └── Contents.json │ │ ├── Pushguide/ │ │ │ ├── Contents.json │ │ │ ├── pushguidebg.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── pushguidebot.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── pushguidemid.imageset/ │ │ │ │ └── Contents.json │ │ │ └── pushguidetop.imageset/ │ │ │ └── Contents.json │ │ ├── TabBar/ │ │ │ ├── Contents.json │ │ │ ├── tabBar_essence_click_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_essence_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_friendTrends_click_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_friendTrends_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_me_click_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_me_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_new_click_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_new_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_publish_click_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tabBar_publish_icon.imageset/ │ │ │ │ └── Contents.json │ │ │ └── tabbar-light.imageset/ │ │ │ └── Contents.json │ │ └── kr-Icon/ │ │ ├── Contents.json │ │ ├── kr-video-player-close.imageset/ │ │ │ └── Contents.json │ │ ├── kr-video-player-fullscreen.imageset/ │ │ │ └── Contents.json │ │ ├── kr-video-player-pause.imageset/ │ │ │ └── Contents.json │ │ ├── kr-video-player-play.imageset/ │ │ │ └── Contents.json │ │ ├── kr-video-player-point.imageset/ │ │ │ └── Contents.json │ │ └── kr-video-player-shrinkscreen.imageset/ │ │ └── Contents.json │ ├── Base.lproj/ │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Classes/ │ │ ├── AppDelegate/ │ │ │ ├── AppDelegate.h │ │ │ └── AppDelegate.m │ │ ├── Category/ │ │ │ ├── NSString+XFTime.h │ │ │ ├── NSString+XFTime.m │ │ │ ├── UIImage+XFCircle.h │ │ │ ├── UIImage+XFCircle.m │ │ │ ├── UIImageView+Header.h │ │ │ ├── UIImageView+Header.m │ │ │ ├── UIView+Extension.h │ │ │ ├── UIView+Extension.m │ │ │ ├── XFMeCell.h │ │ │ ├── XFMeCell.m │ │ │ ├── XFSquare.h │ │ │ ├── XFSquare.m │ │ │ ├── XFSquareButton.h │ │ │ ├── XFSquareButton.m │ │ │ ├── XFSquareCell.h │ │ │ ├── XFSquareCell.m │ │ │ ├── XFSquareTool.h │ │ │ └── XFSquareTool.m │ │ ├── Concern/ │ │ │ ├── Controller/ │ │ │ │ ├── XFConcernViewController.h │ │ │ │ ├── XFConcernViewController.m │ │ │ │ ├── XFConcernViewController.xib │ │ │ │ ├── XFLoginViewController.h │ │ │ │ ├── XFLoginViewController.m │ │ │ │ ├── XFLoginViewController.xib │ │ │ │ ├── XFRecommendViewController.h │ │ │ │ ├── XFRecommendViewController.m │ │ │ │ └── XFRecommendViewController.xib │ │ │ ├── Model/ │ │ │ │ ├── XFCategoryModel.h │ │ │ │ ├── XFCategoryModel.m │ │ │ │ ├── XFMainTableModel.h │ │ │ │ └── XFMainTableModel.m │ │ │ ├── Tool/ │ │ │ │ ├── XFRcommandDataTool.h │ │ │ │ └── XFRcommandDataTool.m │ │ │ └── View/ │ │ │ ├── XFCategoryCell.h │ │ │ ├── XFCategoryCell.m │ │ │ ├── XFCategoryCell.xib │ │ │ ├── XFMainTableCell.h │ │ │ ├── XFMainTableCell.m │ │ │ ├── XFMainTableCell.xib │ │ │ ├── XFTextfield.h │ │ │ └── XFTextfield.m │ │ ├── Essence/ │ │ │ ├── Controller/ │ │ │ │ ├── XFAllViewController.h │ │ │ │ ├── XFAllViewController.m │ │ │ │ ├── XFCommentViewController.h │ │ │ │ ├── XFCommentViewController.m │ │ │ │ ├── XFCommentViewController.xib │ │ │ │ ├── XFDetailPictureController.h │ │ │ │ ├── XFDetailPictureController.m │ │ │ │ ├── XFEssenceViewController.h │ │ │ │ ├── XFEssenceViewController.m │ │ │ │ ├── XFPictrueViewController.h │ │ │ │ ├── XFPictrueViewController.m │ │ │ │ ├── XFTalkViewController.h │ │ │ │ ├── XFTalkViewController.m │ │ │ │ ├── XFVideoViewController.h │ │ │ │ ├── XFVideoViewController.m │ │ │ │ ├── XFVocieViewController.h │ │ │ │ └── XFVocieViewController.m │ │ │ ├── Model/ │ │ │ │ ├── XFCommentModel.h │ │ │ │ ├── XFCommentModel.m │ │ │ │ ├── XFTopicFrame.h │ │ │ │ ├── XFTopicFrame.m │ │ │ │ ├── XFTopicModel.h │ │ │ │ ├── XFTopicModel.m │ │ │ │ ├── XFUserModel.h │ │ │ │ └── XFUserModel.m │ │ │ ├── Tool/ │ │ │ │ ├── XFModuleDataTool.h │ │ │ │ └── XFModuleDataTool.m │ │ │ └── View/ │ │ │ ├── XFCommentCell.h │ │ │ ├── XFCommentCell.m │ │ │ ├── XFCommentCell.xib │ │ │ ├── XFContentPictureView.h │ │ │ ├── XFContentPictureView.m │ │ │ ├── XFContentPictureView.xib │ │ │ ├── XFContentVideoView.h │ │ │ ├── XFContentVideoView.m │ │ │ ├── XFContentVideoView.xib │ │ │ ├── XFContentVoiceView.h │ │ │ ├── XFContentVoiceView.m │ │ │ ├── XFContentVoiceView.xib │ │ │ ├── XFTopicCell.h │ │ │ ├── XFTopicCell.m │ │ │ └── XFTopicCell.xib │ │ ├── Latest/ │ │ │ └── Controller/ │ │ │ ├── XFLatestViewController.h │ │ │ └── XFLatestViewController.m │ │ ├── Lib/ │ │ │ ├── KRVideoPlayerController/ │ │ │ │ ├── KRVideoPlayerControlView.h │ │ │ │ ├── KRVideoPlayerControlView.m │ │ │ │ ├── KRVideoPlayerController.h │ │ │ │ ├── KRVideoPlayerController.m │ │ │ │ ├── XFVociePlayerController.h │ │ │ │ ├── XFVociePlayerController.m │ │ │ │ └── XFVociePlayerController.xib │ │ │ └── Tool/ │ │ │ ├── HttpTool.h │ │ │ └── HttpTool.m │ │ ├── Main/ │ │ │ ├── Controller/ │ │ │ │ ├── XFNavigationController.h │ │ │ │ ├── XFNavigationController.m │ │ │ │ ├── XFTabBarViewController.h │ │ │ │ └── XFTabBarViewController.m │ │ │ └── View/ │ │ │ ├── XFPublishView.h │ │ │ ├── XFPublishView.m │ │ │ ├── XFPublishView.xib │ │ │ ├── XFTabBar.h │ │ │ └── XFTabBar.m │ │ ├── Me/ │ │ │ ├── Controller/ │ │ │ │ ├── XFMeViewController.h │ │ │ │ ├── XFMeViewController.m │ │ │ │ ├── XFWebviewController.h │ │ │ │ └── XFWebviewController.m │ │ │ └── View/ │ │ │ ├── XFSquareFooterView.h │ │ │ └── XFSquareFooterView.m │ │ └── Other/ │ │ ├── PrefixHeader.pch │ │ └── View/ │ │ ├── XFGuideView.h │ │ ├── XFGuideView.m │ │ ├── XFGuideView.xib │ │ ├── XFShowWordBtn.h │ │ └── XFShowWordBtn.m │ ├── Info.plist │ └── main.m ├── XFBaiSiBuDeJie.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata/ │ │ └── FAY.xcuserdatad/ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata/ │ └── FAY.xcuserdatad/ │ ├── xcdebugger/ │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes/ │ ├── XFBaiSiBuDeJie.xcscheme │ └── xcschememanagement.plist └── XFBaiSiBuDeJie.xcworkspace/ ├── contents.xcworkspacedata └── xcuserdata/ └── FAY.xcuserdatad/ ├── UserInterfaceState.xcuserstate └── xcdebugger/ └── Breakpoints_v2.xcbkptlist ================================================ FILE CONTENTS ================================================ ================================================ FILE: Podfile ================================================ platform:ios,’8.3’ pod 'AFNetworking', '~> 3.0.0-beta.3' pod 'SDWebImage', '~> 3.7.3' pod 'SVProgressHUD', '~> 2.0-beta8' pod 'MJExtension', '~> 3.0.7' pod 'UMengSocial', '~> 4.3' use_frameworks! pod 'ReactiveCocoa', '~> 4.0.4-alpha-4’ pod 'MJRefresh', '~> 3.1.0' pod 'DACircularProgress', '~> 2.3.1' pod 'NJKWebViewProgress', '~> 0.2.3' ================================================ FILE: Pods/AFNetworking/AFNetworking/AFHTTPSessionManager.h ================================================ // AFHTTPSessionManager.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #if !TARGET_OS_WATCH #import #endif #import #if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV #import #else #import #endif #import "AFURLSessionManager.h" /** `AFHTTPSessionManager` is a subclass of `AFURLSessionManager` with convenience methods for making HTTP requests. When a `baseURL` is provided, requests made with the `GET` / `POST` / et al. convenience methods can be made with relative paths. ## Subclassing Notes Developers targeting iOS 7 or Mac OS X 10.9 or later that deal extensively with a web service are encouraged to subclass `AFHTTPSessionManager`, providing a class method that returns a shared singleton object on which authentication and other configuration can be shared across the application. For developers targeting iOS 6 or Mac OS X 10.8 or earlier, `AFHTTPRequestOperationManager` may be used to similar effect. ## Methods to Override To change the behavior of all data task operation construction, which is also used in the `GET` / `POST` / et al. convenience methods, override `dataTaskWithRequest:completionHandler:`. ## Serialization Requests created by an HTTP client will contain default headers and encode parameters according to the `requestSerializer` property, which is an object conforming to ``. Responses received from the server are automatically validated and serialized by the `responseSerializers` property, which is an object conforming to `` ## URL Construction Using Relative Paths For HTTP convenience methods, the request serializer constructs URLs from the path relative to the `-baseURL`, using `NSURL +URLWithString:relativeToURL:`, when provided. If `baseURL` is `nil`, `path` needs to resolve to a valid `NSURL` object using `NSURL +URLWithString:`. Below are a few examples of how `baseURL` and relative paths interact: NSURL *baseURL = [NSURL URLWithString:@"http://example.com/v1/"]; [NSURL URLWithString:@"foo" relativeToURL:baseURL]; // http://example.com/v1/foo [NSURL URLWithString:@"foo?bar=baz" relativeToURL:baseURL]; // http://example.com/v1/foo?bar=baz [NSURL URLWithString:@"/foo" relativeToURL:baseURL]; // http://example.com/foo [NSURL URLWithString:@"foo/" relativeToURL:baseURL]; // http://example.com/v1/foo [NSURL URLWithString:@"/foo/" relativeToURL:baseURL]; // http://example.com/foo/ [NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/ Also important to note is that a trailing slash will be added to any `baseURL` without one. This would otherwise cause unexpected behavior when constructing URLs using paths without a leading slash. @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance. */ NS_ASSUME_NONNULL_BEGIN @interface AFHTTPSessionManager : AFURLSessionManager /** The URL used to construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. */ @property (readonly, nonatomic, strong, nullable) NSURL *baseURL; /** Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies. @warning `requestSerializer` must not be `nil`. */ @property (nonatomic, strong) AFHTTPRequestSerializer * requestSerializer; /** Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an instance of `AFJSONResponseSerializer`. @warning `responseSerializer` must not be `nil`. */ @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; ///--------------------- /// @name Initialization ///--------------------- /** Creates and returns an `AFHTTPSessionManager` object. */ + (instancetype)manager; /** Initializes an `AFHTTPSessionManager` object with the specified base URL. @param url The base URL for the HTTP client. @return The newly-initialized HTTP client */ - (instancetype)initWithBaseURL:(nullable NSURL *)url; /** Initializes an `AFHTTPSessionManager` object with the specified base URL. This is the designated initializer. @param url The base URL for the HTTP client. @param configuration The configuration used to create the managed session. @return The newly-initialized HTTP client */ - (instancetype)initWithBaseURL:(nullable NSURL *)url sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; ///--------------------------- /// @name Making HTTP Requests ///--------------------------- /** Creates and runs an `NSURLSessionDataTask` with a `GET` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:completionHandler: */ - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE; /** Creates and runs an `NSURLSessionDataTask` with a `GET` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param progress A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler: */ - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(nullable id)parameters progress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `HEAD` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes a single arguments: the data task. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:completionHandler: */ - (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `POST` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:completionHandler: */ - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE; /** Creates and runs an `NSURLSessionDataTask` with a `POST` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param progress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler: */ - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters progress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:completionHandler: */ - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id formData))block success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE; /** Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. @param progress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler: */ - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id formData))block progress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `PUT` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:completionHandler: */ - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `PATCH` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:completionHandler: */ - (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `DELETE` request. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded according to the client request serializer. @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. @see -dataTaskWithRequest:completionHandler: */ - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; @end NS_ASSUME_NONNULL_END ================================================ FILE: Pods/AFNetworking/AFNetworking/AFHTTPSessionManager.m ================================================ // AFHTTPSessionManager.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "AFHTTPSessionManager.h" #import "AFURLRequestSerialization.h" #import "AFURLResponseSerialization.h" #import #import #import #import #import #import #import #import #if TARGET_OS_IOS || TARGET_OS_TV #import #elif TARGET_OS_WATCH #import #endif @interface AFHTTPSessionManager () @property (readwrite, nonatomic, strong) NSURL *baseURL; @end @implementation AFHTTPSessionManager @dynamic responseSerializer; + (instancetype)manager { return [[[self class] alloc] initWithBaseURL:nil]; } - (instancetype)init { return [self initWithBaseURL:nil]; } - (instancetype)initWithBaseURL:(NSURL *)url { return [self initWithBaseURL:url sessionConfiguration:nil]; } - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration { return [self initWithBaseURL:nil sessionConfiguration:configuration]; } - (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration { self = [super initWithSessionConfiguration:configuration]; if (!self) { return nil; } // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) { url = [url URLByAppendingPathComponent:@""]; } self.baseURL = url; self.requestSerializer = [AFHTTPRequestSerializer serializer]; self.responseSerializer = [AFJSONResponseSerializer serializer]; return self; } #pragma mark - - (void)setRequestSerializer:(AFHTTPRequestSerializer *)requestSerializer { NSParameterAssert(requestSerializer); _requestSerializer = requestSerializer; } - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { NSParameterAssert(responseSerializer); [super setResponseSerializer:responseSerializer]; } #pragma mark - - (NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { return [self GET:URLString parameters:parameters progress:nil success:success failure:failure]; } - (NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))downloadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure { NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:downloadProgress success:success failure:failure]; [dataTask resume]; return dataTask; } - (NSURLSessionDataTask *)HEAD:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, __unused id responseObject) { if (success) { success(task); } } failure:failure]; [dataTask resume]; return dataTask; } - (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { return [self POST:URLString parameters:parameters progress:nil success:success failure:failure]; } - (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure { NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure]; [dataTask resume]; return dataTask; } - (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id _Nonnull))block success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure { return [self POST:URLString parameters:parameters constructingBodyWithBlock:block progress:nil success:success failure:failure]; } - (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id formData))block progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { NSError *serializationError = nil; NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; if (serializationError) { if (failure) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError); }); #pragma clang diagnostic pop } return nil; } __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { if (error) { if (failure) { failure(task, error); } } else { if (success) { success(task, responseObject); } } }]; [task resume]; return task; } - (NSURLSessionDataTask *)PUT:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; [dataTask resume]; return dataTask; } - (NSURLSessionDataTask *)PATCH:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; [dataTask resume]; return dataTask; } - (NSURLSessionDataTask *)DELETE:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; [dataTask resume]; return dataTask; } - (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method URLString:(NSString *)URLString parameters:(id)parameters uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress success:(void (^)(NSURLSessionDataTask *, id))success failure:(void (^)(NSURLSessionDataTask *, NSError *))failure { NSError *serializationError = nil; NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; if (serializationError) { if (failure) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError); }); #pragma clang diagnostic pop } return nil; } __block NSURLSessionDataTask *dataTask = nil; dataTask = [self dataTaskWithRequest:request uploadProgress:uploadProgress downloadProgress:downloadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { if (error) { if (failure) { failure(dataTask, error); } } else { if (success) { success(dataTask, responseObject); } } }]; return dataTask; } #pragma mark - NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue]; } #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; } - (instancetype)initWithCoder:(NSCoder *)decoder { NSURL *baseURL = [decoder decodeObjectOfClass:[NSURL class] forKey:NSStringFromSelector(@selector(baseURL))]; NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"]; if (!configuration) { NSString *configurationIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"identifier"]; if (configurationIdentifier) { #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100) configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationIdentifier]; #else configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:configurationIdentifier]; #endif } } self = [self initWithBaseURL:baseURL sessionConfiguration:configuration]; if (!self) { return nil; } self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))]; if (decodedPolicy) { self.securityPolicy = decodedPolicy; } return self; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))]; if ([self.session.configuration conformsToProtocol:@protocol(NSCoding)]) { [coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"]; } else { [coder encodeObject:self.session.configuration.identifier forKey:@"identifier"]; } [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; [coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFHTTPSessionManager *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL sessionConfiguration:self.session.configuration]; HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone]; return HTTPClient; } @end ================================================ FILE: Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h ================================================ // AFNetworkReachabilityManager.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #if !TARGET_OS_WATCH #import typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { AFNetworkReachabilityStatusUnknown = -1, AFNetworkReachabilityStatusNotReachable = 0, AFNetworkReachabilityStatusReachableViaWWAN = 1, AFNetworkReachabilityStatusReachableViaWiFi = 2, }; NS_ASSUME_NONNULL_BEGIN /** `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability. See Apple's Reachability Sample Code (https://developer.apple.com/library/ios/samplecode/reachability/) @warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined. */ @interface AFNetworkReachabilityManager : NSObject /** The current network reachability status. */ @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; /** Whether or not the network is currently reachable. */ @property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable; /** Whether or not the network is currently reachable via WWAN. */ @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN; /** Whether or not the network is currently reachable via WiFi. */ @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi; ///--------------------- /// @name Initialization ///--------------------- /** Returns the shared network reachability manager. */ + (instancetype)sharedManager; /** Creates and returns a network reachability manager with the default socket address. @return An initialized network reachability manager, actively monitoring the default socket address. */ + (instancetype)manager; /** Creates and returns a network reachability manager for the specified domain. @param domain The domain used to evaluate network reachability. @return An initialized network reachability manager, actively monitoring the specified domain. */ + (instancetype)managerForDomain:(NSString *)domain; /** Creates and returns a network reachability manager for the socket address. @param address The socket address (`sockaddr_in6`) used to evaluate network reachability. @return An initialized network reachability manager, actively monitoring the specified socket address. */ + (instancetype)managerForAddress:(const void *)address; /** Initializes an instance of a network reachability manager from the specified reachability object. @param reachability The reachability object to monitor. @return An initialized network reachability manager, actively monitoring the specified reachability. */ - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; ///-------------------------------------------------- /// @name Starting & Stopping Reachability Monitoring ///-------------------------------------------------- /** Starts monitoring for changes in network reachability status. */ - (void)startMonitoring; /** Stops monitoring for changes in network reachability status. */ - (void)stopMonitoring; ///------------------------------------------------- /// @name Getting Localized Reachability Description ///------------------------------------------------- /** Returns a localized string representation of the current network reachability status. */ - (NSString *)localizedNetworkReachabilityStatusString; ///--------------------------------------------------- /// @name Setting Network Reachability Change Callback ///--------------------------------------------------- /** Sets a callback to be executed when the network availability of the `baseURL` host changes. @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. */ - (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block; @end ///---------------- /// @name Constants ///---------------- /** ## Network Reachability The following constants are provided by `AFNetworkReachabilityManager` as possible network reachability statuses. enum { AFNetworkReachabilityStatusUnknown, AFNetworkReachabilityStatusNotReachable, AFNetworkReachabilityStatusReachableViaWWAN, AFNetworkReachabilityStatusReachableViaWiFi, } `AFNetworkReachabilityStatusUnknown` The `baseURL` host reachability is not known. `AFNetworkReachabilityStatusNotReachable` The `baseURL` host cannot be reached. `AFNetworkReachabilityStatusReachableViaWWAN` The `baseURL` host can be reached via a cellular connection, such as EDGE or GPRS. `AFNetworkReachabilityStatusReachableViaWiFi` The `baseURL` host can be reached via a Wi-Fi connection. ### Keys for Notification UserInfo Dictionary Strings that are used as keys in a `userInfo` dictionary in a network reachability status change notification. `AFNetworkingReachabilityNotificationStatusItem` A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification. The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status. */ ///-------------------- /// @name Notifications ///-------------------- /** Posted when network reachability changes. This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability. @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). */ FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification; FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem; ///-------------------- /// @name Functions ///-------------------- /** Returns a localized string representation of an `AFNetworkReachabilityStatus` value. */ FOUNDATION_EXPORT NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m ================================================ // AFNetworkReachabilityManager.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "AFNetworkReachabilityManager.h" #if !TARGET_OS_WATCH #import #import #import #import #import NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change"; NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem"; typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status); NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) { switch (status) { case AFNetworkReachabilityStatusNotReachable: return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil); case AFNetworkReachabilityStatusReachableViaWWAN: return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil); case AFNetworkReachabilityStatusReachableViaWiFi: return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil); case AFNetworkReachabilityStatusUnknown: default: return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil); } } static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) { BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0); BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0); BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)); BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0); BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction)); AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown; if (isNetworkReachable == NO) { status = AFNetworkReachabilityStatusNotReachable; } #if TARGET_OS_IPHONE else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) { status = AFNetworkReachabilityStatusReachableViaWWAN; } #endif else { status = AFNetworkReachabilityStatusReachableViaWiFi; } return status; } /** * Queue a status change notification for the main thread. * * This is done to ensure that the notifications are received in the same order * as they are sent. If notifications are sent directly, it is possible that * a queued notification (for an earlier status condition) is processed after * the later update, resulting in the listener being left in the wrong state. */ static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) { AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); dispatch_async(dispatch_get_main_queue(), ^{ if (block) { block(status); } NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) }; [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo]; }); } static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info); } static const void * AFNetworkReachabilityRetainCallback(const void *info) { return Block_copy(info); } static void AFNetworkReachabilityReleaseCallback(const void *info) { if (info) { Block_release(info); } } @interface AFNetworkReachabilityManager () @property (readwrite, nonatomic, strong) id networkReachability; @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; @end @implementation AFNetworkReachabilityManager + (instancetype)sharedManager { static AFNetworkReachabilityManager *_sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedManager = [self manager]; }); return _sharedManager; } #ifndef __clang_analyzer__ + (instancetype)managerForDomain:(NSString *)domain { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; return manager; } #endif #ifndef __clang_analyzer__ + (instancetype)managerForAddress:(const void *)address { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; return manager; } #endif + (instancetype)manager { #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) struct sockaddr_in6 address; bzero(&address, sizeof(address)); address.sin6_len = sizeof(address); address.sin6_family = AF_INET6; #else struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_len = sizeof(address); address.sin_family = AF_INET; #endif return [self managerForAddress:&address]; } - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { self = [super init]; if (!self) { return nil; } self.networkReachability = CFBridgingRelease(reachability); self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; return self; } - (instancetype)init NS_UNAVAILABLE { return nil; } - (void)dealloc { [self stopMonitoring]; } #pragma mark - - (BOOL)isReachable { return [self isReachableViaWWAN] || [self isReachableViaWiFi]; } - (BOOL)isReachableViaWWAN { return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN; } - (BOOL)isReachableViaWiFi { return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi; } #pragma mark - - (void)startMonitoring { [self stopMonitoring]; if (!self.networkReachability) { return; } __weak __typeof(self)weakSelf = self; AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { __strong __typeof(weakSelf)strongSelf = weakSelf; strongSelf.networkReachabilityStatus = status; if (strongSelf.networkReachabilityStatusBlock) { strongSelf.networkReachabilityStatusBlock(status); } }; id networkReachability = self.networkReachability; SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; SCNetworkReachabilitySetCallback((__bridge SCNetworkReachabilityRef)networkReachability, AFNetworkReachabilityCallback, &context); SCNetworkReachabilityScheduleWithRunLoop((__bridge SCNetworkReachabilityRef)networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags((__bridge SCNetworkReachabilityRef)networkReachability, &flags)) { AFPostReachabilityStatusChange(flags, callback); } }); } - (void)stopMonitoring { if (!self.networkReachability) { return; } SCNetworkReachabilityUnscheduleFromRunLoop((__bridge SCNetworkReachabilityRef)self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); } #pragma mark - - (NSString *)localizedNetworkReachabilityStatusString { return AFStringFromNetworkReachabilityStatus(self.networkReachabilityStatus); } #pragma mark - - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block { self.networkReachabilityStatusBlock = block; } #pragma mark - NSKeyValueObserving + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) { return [NSSet setWithObject:@"networkReachabilityStatus"]; } return [super keyPathsForValuesAffectingValueForKey:key]; } @end #endif ================================================ FILE: Pods/AFNetworking/AFNetworking/AFNetworking.h ================================================ // AFNetworking.h // // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #import #ifndef _AFNETWORKING_ #define _AFNETWORKING_ #import "AFURLRequestSerialization.h" #import "AFURLResponseSerialization.h" #import "AFSecurityPolicy.h" #if !TARGET_OS_WATCH #import "AFNetworkReachabilityManager.h" #endif #import "AFURLSessionManager.h" #import "AFHTTPSessionManager.h" #endif /* _AFNETWORKING_ */ ================================================ FILE: Pods/AFNetworking/AFNetworking/AFSecurityPolicy.h ================================================ // AFSecurityPolicy.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { AFSSLPinningModeNone, AFSSLPinningModePublicKey, AFSSLPinningModeCertificate, }; /** `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. */ NS_ASSUME_NONNULL_BEGIN @interface AFSecurityPolicy : NSObject /** The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. */ @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode; /** The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the target compiling AFNetworking. Note that if you are using AFNetworking as embedded framework, no certificates will be pinned by default. Use `certificatesInBundle` to load certificates from your target, and then create a new policy by calling `policyWithPinningMode:withPinnedCertificates`. Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches. */ @property (nonatomic, strong, nullable) NSSet *pinnedCertificates; /** Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. */ @property (nonatomic, assign) BOOL allowInvalidCertificates; /** Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`. */ @property (nonatomic, assign) BOOL validatesDomainName; ///----------------------------------------- /// @name Getting Certificates from the Bundle ///----------------------------------------- /** Returns any certificates included in the bundle. If you are using AFNetworking as an embedded framework, you must use this method to find the certificates you have included in your app bundle, and use them when creating your security policy by calling `policyWithPinningMode:withPinnedCertificates`. @return The certificates included in the given bundle. */ + (NSSet *)certificatesInBundle:(NSBundle *)bundle; ///----------------------------------------- /// @name Getting Specific Security Policies ///----------------------------------------- /** Returns the shared default security policy, which does not allow invalid certificates, validates domain name, and does not validate against pinned certificates or public keys. @return The default security policy. */ + (instancetype)defaultPolicy; ///--------------------- /// @name Initialization ///--------------------- /** Creates and returns a security policy with the specified pinning mode. @param pinningMode The SSL pinning mode. @return A new security policy. */ + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode; /** Creates and returns a security policy with the specified pinning mode. @param pinningMode The SSL pinning mode. @param pinnedCertificates The certificates to pin against. @return A new security policy. */ + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates; ///------------------------------ /// @name Evaluating Server Trust ///------------------------------ /** Whether or not the specified server trust should be accepted, based on the security policy. This method should be used when responding to an authentication challenge from a server. @param serverTrust The X.509 certificate trust of the server. @param domain The domain of serverTrust. If `nil`, the domain will not be validated. @return Whether or not to trust the server. */ - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(nullable NSString *)domain; @end NS_ASSUME_NONNULL_END ///---------------- /// @name Constants ///---------------- /** ## SSL Pinning Modes The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes. enum { AFSSLPinningModeNone, AFSSLPinningModePublicKey, AFSSLPinningModeCertificate, } `AFSSLPinningModeNone` Do not used pinned certificates to validate servers. `AFSSLPinningModePublicKey` Validate host certificates against public keys of pinned certificates. `AFSSLPinningModeCertificate` Validate host certificates against pinned certificates. */ ================================================ FILE: Pods/AFNetworking/AFNetworking/AFSecurityPolicy.m ================================================ // AFSecurityPolicy.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "AFSecurityPolicy.h" #import #if !TARGET_OS_IOS && !TARGET_OS_WATCH && !TARGET_OS_TV static NSData * AFSecKeyGetData(SecKeyRef key) { CFDataRef data = NULL; __Require_noErr_Quiet(SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data), _out); return (__bridge_transfer NSData *)data; _out: if (data) { CFRelease(data); } return nil; } #endif static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) { #if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV return [(__bridge id)key1 isEqual:(__bridge id)key2]; #else return [AFSecKeyGetData(key1) isEqual:AFSecKeyGetData(key2)]; #endif } static id AFPublicKeyForCertificate(NSData *certificate) { id allowedPublicKey = nil; SecCertificateRef allowedCertificate; SecCertificateRef allowedCertificates[1]; CFArrayRef tempCertificates = nil; SecPolicyRef policy = nil; SecTrustRef allowedTrust = nil; SecTrustResultType result; allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate); __Require_Quiet(allowedCertificate != NULL, _out); allowedCertificates[0] = allowedCertificate; tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL); policy = SecPolicyCreateBasicX509(); __Require_noErr_Quiet(SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust), _out); __Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out); allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust); _out: if (allowedTrust) { CFRelease(allowedTrust); } if (policy) { CFRelease(policy); } if (tempCertificates) { CFRelease(tempCertificates); } if (allowedCertificate) { CFRelease(allowedCertificate); } return allowedPublicKey; } static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) { BOOL isValid = NO; SecTrustResultType result; __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out); isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); _out: return isValid; } static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust) { CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; for (CFIndex i = 0; i < certificateCount; i++) { SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); [trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]; } return [NSArray arrayWithArray:trustChain]; } static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { SecPolicyRef policy = SecPolicyCreateBasicX509(); CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; for (CFIndex i = 0; i < certificateCount; i++) { SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); SecCertificateRef someCertificates[] = {certificate}; CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL); SecTrustRef trust; __Require_noErr_Quiet(SecTrustCreateWithCertificates(certificates, policy, &trust), _out); SecTrustResultType result; __Require_noErr_Quiet(SecTrustEvaluate(trust, &result), _out); [trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)]; _out: if (trust) { CFRelease(trust); } if (certificates) { CFRelease(certificates); } continue; } CFRelease(policy); return [NSArray arrayWithArray:trustChain]; } #pragma mark - @interface AFSecurityPolicy() @property (readwrite, nonatomic, assign) AFSSLPinningMode SSLPinningMode; @property (readwrite, nonatomic, strong) NSSet *pinnedPublicKeys; @end @implementation AFSecurityPolicy + (NSSet *)certificatesInBundle:(NSBundle *)bundle { NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."]; NSMutableSet *certificates = [NSMutableSet setWithCapacity:[paths count]]; for (NSString *path in paths) { NSData *certificateData = [NSData dataWithContentsOfFile:path]; [certificates addObject:certificateData]; } return [NSSet setWithSet:certificates]; } + (NSSet *)defaultPinnedCertificates { static NSSet *_defaultPinnedCertificates = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSBundle *bundle = [NSBundle bundleForClass:[self class]]; _defaultPinnedCertificates = [self certificatesInBundle:bundle]; }); return _defaultPinnedCertificates; } + (instancetype)defaultPolicy { AFSecurityPolicy *securityPolicy = [[self alloc] init]; securityPolicy.SSLPinningMode = AFSSLPinningModeNone; return securityPolicy; } + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode { return [self policyWithPinningMode:pinningMode withPinnedCertificates:[self defaultPinnedCertificates]]; } + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates { AFSecurityPolicy *securityPolicy = [[self alloc] init]; securityPolicy.SSLPinningMode = pinningMode; [securityPolicy setPinnedCertificates:pinnedCertificates]; return securityPolicy; } - (instancetype)init { self = [super init]; if (!self) { return nil; } self.validatesDomainName = YES; return self; } - (void)setPinnedCertificates:(NSSet *)pinnedCertificates { _pinnedCertificates = pinnedCertificates; if (self.pinnedCertificates) { NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]]; for (NSData *certificate in self.pinnedCertificates) { id publicKey = AFPublicKeyForCertificate(certificate); if (!publicKey) { continue; } [mutablePinnedPublicKeys addObject:publicKey]; } self.pinnedPublicKeys = [NSSet setWithSet:mutablePinnedPublicKeys]; } else { self.pinnedPublicKeys = nil; } } #pragma mark - - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain { if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) { // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html // According to the docs, you should only trust your provided certs for evaluation. // Pinned certificates are added to the trust. Without pinned certificates, // there is nothing to evaluate against. // // From Apple Docs: // "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors). // Instead, add your own (self-signed) CA certificate to the list of trusted anchors." NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning."); return NO; } NSMutableArray *policies = [NSMutableArray array]; if (self.validatesDomainName) { [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; } else { [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()]; } SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); if (self.SSLPinningMode == AFSSLPinningModeNone) { return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust); } else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { return NO; } switch (self.SSLPinningMode) { case AFSSLPinningModeNone: default: return NO; case AFSSLPinningModeCertificate: { NSMutableArray *pinnedCertificates = [NSMutableArray array]; for (NSData *certificateData in self.pinnedCertificates) { [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)]; } SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates); if (!AFServerTrustIsValid(serverTrust)) { return NO; } // obtain the chain after being validated, which *should* contain the pinned certificate in the last position (if it's the Root CA) NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust); for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) { if ([self.pinnedCertificates containsObject:trustChainCertificate]) { return YES; } } return NO; } case AFSSLPinningModePublicKey: { NSUInteger trustedPublicKeyCount = 0; NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust); for (id trustChainPublicKey in publicKeys) { for (id pinnedPublicKey in self.pinnedPublicKeys) { if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) { trustedPublicKeyCount += 1; } } } return trustedPublicKeyCount > 0; } } return NO; } #pragma mark - NSKeyValueObserving + (NSSet *)keyPathsForValuesAffectingPinnedPublicKeys { return [NSSet setWithObject:@"pinnedCertificates"]; } #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; } - (instancetype)initWithCoder:(NSCoder *)decoder { self = [self init]; if (!self) { return nil; } self.SSLPinningMode = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(SSLPinningMode))] unsignedIntegerValue]; self.allowInvalidCertificates = [decoder decodeBoolForKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; self.validatesDomainName = [decoder decodeBoolForKey:NSStringFromSelector(@selector(validatesDomainName))]; self.pinnedCertificates = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(pinnedCertificates))]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:[NSNumber numberWithUnsignedInteger:self.SSLPinningMode] forKey:NSStringFromSelector(@selector(SSLPinningMode))]; [coder encodeBool:self.allowInvalidCertificates forKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; [coder encodeBool:self.validatesDomainName forKey:NSStringFromSelector(@selector(validatesDomainName))]; [coder encodeObject:self.pinnedCertificates forKey:NSStringFromSelector(@selector(pinnedCertificates))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFSecurityPolicy *securityPolicy = [[[self class] allocWithZone:zone] init]; securityPolicy.SSLPinningMode = self.SSLPinningMode; securityPolicy.allowInvalidCertificates = self.allowInvalidCertificates; securityPolicy.validatesDomainName = self.validatesDomainName; securityPolicy.pinnedCertificates = [self.pinnedCertificates copyWithZone:zone]; return securityPolicy; } @end ================================================ FILE: Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.h ================================================ // AFURLRequestSerialization.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS || TARGET_OS_TV #import #elif TARGET_OS_WATCH #import #endif NS_ASSUME_NONNULL_BEGIN /** The `AFURLRequestSerialization` protocol is adopted by an object that encodes parameters for a specified HTTP requests. Request serializers may encode parameters as query strings, HTTP bodies, setting the appropriate HTTP header fields as necessary. For example, a JSON request serializer may set the HTTP body of the request to a JSON representation, and set the `Content-Type` HTTP header field value to `application/json`. */ @protocol AFURLRequestSerialization /** Returns a request with the specified parameters encoded into a copy of the original request. @param request The original request. @param parameters The parameters to be encoded. @param error The error that occurred while attempting to encode the request parameters. @return A serialized request. */ - (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(nullable id)parameters error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW; @end #pragma mark - /** */ typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) { AFHTTPRequestQueryStringDefaultStyle = 0, }; @protocol AFMultipartFormData; /** `AFHTTPRequestSerializer` conforms to the `AFURLRequestSerialization` & `AFURLResponseSerialization` protocols, offering a concrete base implementation of query string / URL form-encoded parameter serialization and default request headers, as well as response status code and content type validation. Any request or response serializer dealing with HTTP is encouraged to subclass `AFHTTPRequestSerializer` in order to ensure consistent default behavior. */ @interface AFHTTPRequestSerializer : NSObject /** The string encoding used to serialize parameters. `NSUTF8StringEncoding` by default. */ @property (nonatomic, assign) NSStringEncoding stringEncoding; /** Whether created requests can use the device’s cellular radio (if present). `YES` by default. @see NSMutableURLRequest -setAllowsCellularAccess: */ @property (nonatomic, assign) BOOL allowsCellularAccess; /** The cache policy of created requests. `NSURLRequestUseProtocolCachePolicy` by default. @see NSMutableURLRequest -setCachePolicy: */ @property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy; /** Whether created requests should use the default cookie handling. `YES` by default. @see NSMutableURLRequest -setHTTPShouldHandleCookies: */ @property (nonatomic, assign) BOOL HTTPShouldHandleCookies; /** Whether created requests can continue transmitting data before receiving a response from an earlier transmission. `NO` by default @see NSMutableURLRequest -setHTTPShouldUsePipelining: */ @property (nonatomic, assign) BOOL HTTPShouldUsePipelining; /** The network service type for created requests. `NSURLNetworkServiceTypeDefault` by default. @see NSMutableURLRequest -setNetworkServiceType: */ @property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType; /** The timeout interval, in seconds, for created requests. The default timeout interval is 60 seconds. @see NSMutableURLRequest -setTimeoutInterval: */ @property (nonatomic, assign) NSTimeInterval timeoutInterval; ///--------------------------------------- /// @name Configuring HTTP Request Headers ///--------------------------------------- /** Default HTTP header field values to be applied to serialized requests. By default, these include the following: - `Accept-Language` with the contents of `NSLocale +preferredLanguages` - `User-Agent` with the contents of various bundle identifiers and OS designations @discussion To add or remove default request headers, use `setValue:forHTTPHeaderField:`. */ @property (readonly, nonatomic, strong) NSDictionary *HTTPRequestHeaders; /** Creates and returns a serializer with default configuration. */ + (instancetype)serializer; /** Sets the value for the HTTP headers set in request objects made by the HTTP client. If `nil`, removes the existing value for that header. @param field The HTTP header to set a default value for @param value The value set as default for the specified header, or `nil` */ - (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field; /** Returns the value for the HTTP headers set in the request serializer. @param field The HTTP header to retrieve the default value for @return The value set as default for the specified header, or `nil` */ - (nullable NSString *)valueForHTTPHeaderField:(NSString *)field; /** Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header. @param username The HTTP basic auth username @param password The HTTP basic auth password */ - (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username password:(NSString *)password; /** Clears any existing value for the "Authorization" HTTP header. */ - (void)clearAuthorizationHeader; ///------------------------------------------------------- /// @name Configuring Query String Parameter Serialization ///------------------------------------------------------- /** HTTP methods for which serialized requests will encode parameters as a query string. `GET`, `HEAD`, and `DELETE` by default. */ @property (nonatomic, strong) NSSet *HTTPMethodsEncodingParametersInURI; /** Set the method of query string serialization according to one of the pre-defined styles. @param style The serialization style. @see AFHTTPRequestQueryStringSerializationStyle */ - (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style; /** Set the a custom method of query string serialization according to the specified block. @param block A block that defines a process of encoding parameters into a query string. This block returns the query string and takes three arguments: the request, the parameters to encode, and the error that occurred when attempting to encode parameters for the given request. */ - (void)setQueryStringSerializationWithBlock:(nullable NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block; ///------------------------------- /// @name Creating Request Objects ///------------------------------- /** Creates an `NSMutableURLRequest` object with the specified HTTP method and URL string. If the HTTP method is `GET`, `HEAD`, or `DELETE`, the parameters will be used to construct a url-encoded query string that is appended to the request's URL. Otherwise, the parameters will be encoded according to the value of the `parameterEncoding` property, and set as the request body. @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE`. This parameter must not be `nil`. @param URLString The URL string used to create the request URL. @param parameters The parameters to be either set as a query string for `GET` requests, or the request HTTP body. @param error The error that occurred while constructing the request. @return An `NSMutableURLRequest` object. */ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method URLString:(NSString *)URLString parameters:(nullable id)parameters error:(NSError * _Nullable __autoreleasing *)error; /** Creates an `NSMutableURLRequest` object with the specified HTTP method and URLString, and constructs a `multipart/form-data` HTTP body, using the specified parameters and multipart form data block. See http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.2 Multipart form requests are automatically streamed, reading files directly from disk along with in-memory data in a single HTTP body. The resulting `NSMutableURLRequest` object has an `HTTPBodyStream` property, so refrain from setting `HTTPBodyStream` or `HTTPBody` on this request object, as it will clear out the multipart form body stream. @param method The HTTP method for the request. This parameter must not be `GET` or `HEAD`, or `nil`. @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded and set in the request HTTP body. @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. @param error The error that occurred while constructing the request. @return An `NSMutableURLRequest` object */ - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method URLString:(NSString *)URLString parameters:(nullable NSDictionary *)parameters constructingBodyWithBlock:(nullable void (^)(id formData))block error:(NSError * _Nullable __autoreleasing *)error; /** Creates an `NSMutableURLRequest` by removing the `HTTPBodyStream` from a request, and asynchronously writing its contents into the specified file, invoking the completion handler when finished. @param request The multipart form request. The `HTTPBodyStream` property of `request` must not be `nil`. @param fileURL The file URL to write multipart form contents to. @param handler A handler block to execute. @discussion There is a bug in `NSURLSessionTask` that causes requests to not send a `Content-Length` header when streaming contents from an HTTP body, which is notably problematic when interacting with the Amazon S3 webservice. As a workaround, this method takes a request constructed with `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error:`, or any other request with an `HTTPBodyStream`, writes the contents to the specified file and returns a copy of the original request with the `HTTPBodyStream` property set to `nil`. From here, the file can either be passed to `AFURLSessionManager -uploadTaskWithRequest:fromFile:progress:completionHandler:`, or have its contents read into an `NSData` that's assigned to the `HTTPBody` property of the request. @see https://github.com/AFNetworking/AFNetworking/issues/1398 */ - (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request writingStreamContentsToFile:(NSURL *)fileURL completionHandler:(nullable void (^)(NSError * _Nullable error))handler; @end #pragma mark - /** The `AFMultipartFormData` protocol defines the methods supported by the parameter in the block argument of `AFHTTPRequestSerializer -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:`. */ @protocol AFMultipartFormData /** Appends the HTTP header `Content-Disposition: file; filename=#{generated filename}; name=#{name}"` and `Content-Type: #{generated mimeType}`, followed by the encoded file data and the multipart form boundary. The filename and MIME type for this data in the form will be automatically generated, using the last path component of the `fileURL` and system associated MIME type for the `fileURL` extension, respectively. @param fileURL The URL corresponding to the file whose content will be appended to the form. This parameter must not be `nil`. @param name The name to be associated with the specified data. This parameter must not be `nil`. @param error If an error occurs, upon return contains an `NSError` object that describes the problem. @return `YES` if the file data was successfully appended, otherwise `NO`. */ - (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name error:(NSError * _Nullable __autoreleasing *)error; /** Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary. @param fileURL The URL corresponding to the file whose content will be appended to the form. This parameter must not be `nil`. @param name The name to be associated with the specified data. This parameter must not be `nil`. @param fileName The file name to be used in the `Content-Disposition` header. This parameter must not be `nil`. @param mimeType The declared MIME type of the file data. This parameter must not be `nil`. @param error If an error occurs, upon return contains an `NSError` object that describes the problem. @return `YES` if the file data was successfully appended otherwise `NO`. */ - (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType error:(NSError * _Nullable __autoreleasing *)error; /** Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the data from the input stream and the multipart form boundary. @param inputStream The input stream to be appended to the form data @param name The name to be associated with the specified input stream. This parameter must not be `nil`. @param fileName The filename to be associated with the specified input stream. This parameter must not be `nil`. @param length The length of the specified input stream in bytes. @param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`. */ - (void)appendPartWithInputStream:(nullable NSInputStream *)inputStream name:(NSString *)name fileName:(NSString *)fileName length:(int64_t)length mimeType:(NSString *)mimeType; /** Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary. @param data The data to be encoded and appended to the form data. @param name The name to be associated with the specified data. This parameter must not be `nil`. @param fileName The filename to be associated with the specified data. This parameter must not be `nil`. @param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`. */ - (void)appendPartWithFileData:(NSData *)data name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType; /** Appends the HTTP headers `Content-Disposition: form-data; name=#{name}"`, followed by the encoded data and the multipart form boundary. @param data The data to be encoded and appended to the form data. @param name The name to be associated with the specified data. This parameter must not be `nil`. */ - (void)appendPartWithFormData:(NSData *)data name:(NSString *)name; /** Appends HTTP headers, followed by the encoded data and the multipart form boundary. @param headers The HTTP headers to be appended to the form data. @param body The data to be encoded and appended to the form data. This parameter must not be `nil`. */ - (void)appendPartWithHeaders:(nullable NSDictionary *)headers body:(NSData *)body; /** Throttles request bandwidth by limiting the packet size and adding a delay for each chunk read from the upload stream. When uploading over a 3G or EDGE connection, requests may fail with "request body stream exhausted". Setting a maximum packet size and delay according to the recommended values (`kAFUploadStream3GSuggestedPacketSize` and `kAFUploadStream3GSuggestedDelay`) lowers the risk of the input stream exceeding its allocated bandwidth. Unfortunately, there is no definite way to distinguish between a 3G, EDGE, or LTE connection over `NSURLConnection`. As such, it is not recommended that you throttle bandwidth based solely on network reachability. Instead, you should consider checking for the "request body stream exhausted" in a failure block, and then retrying the request with throttled bandwidth. @param numberOfBytes Maximum packet size, in number of bytes. The default packet size for an input stream is 16kb. @param delay Duration of delay each time a packet is read. By default, no delay is set. */ - (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay; @end #pragma mark - /** `AFJSONRequestSerializer` is a subclass of `AFHTTPRequestSerializer` that encodes parameters as JSON using `NSJSONSerialization`, setting the `Content-Type` of the encoded request to `application/json`. */ @interface AFJSONRequestSerializer : AFHTTPRequestSerializer /** Options for writing the request JSON data from Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONWritingOptions". `0` by default. */ @property (nonatomic, assign) NSJSONWritingOptions writingOptions; /** Creates and returns a JSON serializer with specified reading and writing options. @param writingOptions The specified JSON writing options. */ + (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions; @end #pragma mark - /** `AFPropertyListRequestSerializer` is a subclass of `AFHTTPRequestSerializer` that encodes parameters as JSON using `NSPropertyListSerializer`, setting the `Content-Type` of the encoded request to `application/x-plist`. */ @interface AFPropertyListRequestSerializer : AFHTTPRequestSerializer /** The property list format. Possible values are described in "NSPropertyListFormat". */ @property (nonatomic, assign) NSPropertyListFormat format; /** @warning The `writeOptions` property is currently unused. */ @property (nonatomic, assign) NSPropertyListWriteOptions writeOptions; /** Creates and returns a property list serializer with a specified format, read options, and write options. @param format The property list format. @param writeOptions The property list write options. @warning The `writeOptions` property is currently unused. */ + (instancetype)serializerWithFormat:(NSPropertyListFormat)format writeOptions:(NSPropertyListWriteOptions)writeOptions; @end #pragma mark - ///---------------- /// @name Constants ///---------------- /** ## Error Domains The following error domain is predefined. - `NSString * const AFURLRequestSerializationErrorDomain` ### Constants `AFURLRequestSerializationErrorDomain` AFURLRequestSerializer errors. Error codes for `AFURLRequestSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. */ FOUNDATION_EXPORT NSString * const AFURLRequestSerializationErrorDomain; /** ## User info dictionary keys These keys may exist in the user info dictionary, in addition to those defined for NSError. - `NSString * const AFNetworkingOperationFailingURLRequestErrorKey` ### Constants `AFNetworkingOperationFailingURLRequestErrorKey` The corresponding value is an `NSURLRequest` containing the request of the operation associated with an error. This key is only present in the `AFURLRequestSerializationErrorDomain`. */ FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLRequestErrorKey; /** ## Throttling Bandwidth for HTTP Request Input Streams @see -throttleBandwidthWithPacketSize:delay: ### Constants `kAFUploadStream3GSuggestedPacketSize` Maximum packet size, in number of bytes. Equal to 16kb. `kAFUploadStream3GSuggestedDelay` Duration of delay each time a packet is read. Equal to 0.2 seconds. */ FOUNDATION_EXPORT NSUInteger const kAFUploadStream3GSuggestedPacketSize; FOUNDATION_EXPORT NSTimeInterval const kAFUploadStream3GSuggestedDelay; NS_ASSUME_NONNULL_END ================================================ FILE: Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.m ================================================ // AFURLRequestSerialization.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "AFURLRequestSerialization.h" #if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV #import #else #import #endif NSString * const AFURLRequestSerializationErrorDomain = @"com.alamofire.error.serialization.request"; NSString * const AFNetworkingOperationFailingURLRequestErrorKey = @"com.alamofire.serialization.request.error.response"; typedef NSString * (^AFQueryStringSerializationBlock)(NSURLRequest *request, id parameters, NSError *__autoreleasing *error); /** Returns a percent-escaped string following RFC 3986 for a query string key or value. RFC 3986 states that the following characters are "reserved" characters. - General Delimiters: ":", "#", "[", "]", "@", "?", "/" - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" should be percent-escaped in the query string. - parameter string: The string to be percent-escaped. - returns: The percent-escaped string. */ static NSString * AFPercentEscapedStringFromString(NSString *string) { static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4 static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;="; NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]]; // FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028 // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; static NSUInteger const batchSize = 50; NSUInteger index = 0; NSMutableString *escaped = @"".mutableCopy; while (index < string.length) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wgnu" NSUInteger length = MIN(string.length - index, batchSize); #pragma GCC diagnostic pop NSRange range = NSMakeRange(index, length); // To avoid breaking up character sequences such as 👴🏻👮🏽 range = [string rangeOfComposedCharacterSequencesForRange:range]; NSString *substring = [string substringWithRange:range]; NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; [escaped appendString:encoded]; index += range.length; } return escaped; } #pragma mark - @interface AFQueryStringPair : NSObject @property (readwrite, nonatomic, strong) id field; @property (readwrite, nonatomic, strong) id value; - (instancetype)initWithField:(id)field value:(id)value; - (NSString *)URLEncodedStringValue; @end @implementation AFQueryStringPair - (instancetype)initWithField:(id)field value:(id)value { self = [super init]; if (!self) { return nil; } self.field = field; self.value = value; return self; } - (NSString *)URLEncodedStringValue { if (!self.value || [self.value isEqual:[NSNull null]]) { return AFPercentEscapedStringFromString([self.field description]); } else { return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedStringFromString([self.field description]), AFPercentEscapedStringFromString([self.value description])]; } } @end #pragma mark - FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary); FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value); static NSString * AFQueryStringFromParameters(NSDictionary *parameters) { NSMutableArray *mutablePairs = [NSMutableArray array]; for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) { [mutablePairs addObject:[pair URLEncodedStringValue]]; } return [mutablePairs componentsJoinedByString:@"&"]; } NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) { return AFQueryStringPairsFromKeyAndValue(nil, dictionary); } NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) { NSMutableArray *mutableQueryStringComponents = [NSMutableArray array]; NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)]; if ([value isKindOfClass:[NSDictionary class]]) { NSDictionary *dictionary = value; // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { id nestedValue = dictionary[nestedKey]; if (nestedValue) { [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)]; } } } else if ([value isKindOfClass:[NSArray class]]) { NSArray *array = value; for (id nestedValue in array) { [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)]; } } else if ([value isKindOfClass:[NSSet class]]) { NSSet *set = value; for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)]; } } else { [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]]; } return mutableQueryStringComponents; } #pragma mark - @interface AFStreamingMultipartFormData : NSObject - (instancetype)initWithURLRequest:(NSMutableURLRequest *)urlRequest stringEncoding:(NSStringEncoding)encoding; - (NSMutableURLRequest *)requestByFinalizingMultipartFormData; @end #pragma mark - static NSArray * AFHTTPRequestSerializerObservedKeyPaths() { static NSArray *_AFHTTPRequestSerializerObservedKeyPaths = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _AFHTTPRequestSerializerObservedKeyPaths = @[NSStringFromSelector(@selector(allowsCellularAccess)), NSStringFromSelector(@selector(cachePolicy)), NSStringFromSelector(@selector(HTTPShouldHandleCookies)), NSStringFromSelector(@selector(HTTPShouldUsePipelining)), NSStringFromSelector(@selector(networkServiceType)), NSStringFromSelector(@selector(timeoutInterval))]; }); return _AFHTTPRequestSerializerObservedKeyPaths; } static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerObserverContext; @interface AFHTTPRequestSerializer () @property (readwrite, nonatomic, strong) NSMutableSet *mutableObservedChangedKeyPaths; @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableHTTPRequestHeaders; @property (readwrite, nonatomic, assign) AFHTTPRequestQueryStringSerializationStyle queryStringSerializationStyle; @property (readwrite, nonatomic, copy) AFQueryStringSerializationBlock queryStringSerialization; @end @implementation AFHTTPRequestSerializer + (instancetype)serializer { return [[self alloc] init]; } - (instancetype)init { self = [super init]; if (!self) { return nil; } self.stringEncoding = NSUTF8StringEncoding; self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary]; // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4 NSMutableArray *acceptLanguagesComponents = [NSMutableArray array]; [[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { float q = 1.0f - (idx * 0.1f); [acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]]; *stop = q <= 0.5f; }]; [self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"]; NSString *userAgent = nil; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" #if TARGET_OS_IOS // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; #elif TARGET_OS_WATCH // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]]; #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]; #endif #pragma clang diagnostic pop if (userAgent) { if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) { NSMutableString *mutableUserAgent = [userAgent mutableCopy]; if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) { userAgent = mutableUserAgent; } } [self setValue:userAgent forHTTPHeaderField:@"User-Agent"]; } // HTTP Method Definitions; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html self.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", @"DELETE", nil]; self.mutableObservedChangedKeyPaths = [NSMutableSet set]; for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) { if ([self respondsToSelector:NSSelectorFromString(keyPath)]) { [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext]; } } return self; } - (void)dealloc { for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) { if ([self respondsToSelector:NSSelectorFromString(keyPath)]) { [self removeObserver:self forKeyPath:keyPath context:AFHTTPRequestSerializerObserverContext]; } } } #pragma mark - // Workarounds for crashing behavior using Key-Value Observing with XCTest // See https://github.com/AFNetworking/AFNetworking/issues/2523 - (void)setAllowsCellularAccess:(BOOL)allowsCellularAccess { [self willChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))]; _allowsCellularAccess = allowsCellularAccess; [self didChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))]; } - (void)setCachePolicy:(NSURLRequestCachePolicy)cachePolicy { [self willChangeValueForKey:NSStringFromSelector(@selector(cachePolicy))]; _cachePolicy = cachePolicy; [self didChangeValueForKey:NSStringFromSelector(@selector(cachePolicy))]; } - (void)setHTTPShouldHandleCookies:(BOOL)HTTPShouldHandleCookies { [self willChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldHandleCookies))]; _HTTPShouldHandleCookies = HTTPShouldHandleCookies; [self didChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldHandleCookies))]; } - (void)setHTTPShouldUsePipelining:(BOOL)HTTPShouldUsePipelining { [self willChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldUsePipelining))]; _HTTPShouldUsePipelining = HTTPShouldUsePipelining; [self didChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldUsePipelining))]; } - (void)setNetworkServiceType:(NSURLRequestNetworkServiceType)networkServiceType { [self willChangeValueForKey:NSStringFromSelector(@selector(networkServiceType))]; _networkServiceType = networkServiceType; [self didChangeValueForKey:NSStringFromSelector(@selector(networkServiceType))]; } - (void)setTimeoutInterval:(NSTimeInterval)timeoutInterval { [self willChangeValueForKey:NSStringFromSelector(@selector(timeoutInterval))]; _timeoutInterval = timeoutInterval; [self didChangeValueForKey:NSStringFromSelector(@selector(timeoutInterval))]; } #pragma mark - - (NSDictionary *)HTTPRequestHeaders { return [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders]; } - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field { [self.mutableHTTPRequestHeaders setValue:value forKey:field]; } - (NSString *)valueForHTTPHeaderField:(NSString *)field { return [self.mutableHTTPRequestHeaders valueForKey:field]; } - (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username password:(NSString *)password { NSData *basicAuthCredentials = [[NSString stringWithFormat:@"%@:%@", username, password] dataUsingEncoding:NSUTF8StringEncoding]; NSString *base64AuthCredentials = [basicAuthCredentials base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]; [self setValue:[NSString stringWithFormat:@"Basic %@", base64AuthCredentials] forHTTPHeaderField:@"Authorization"]; } - (void)clearAuthorizationHeader { [self.mutableHTTPRequestHeaders removeObjectForKey:@"Authorization"]; } #pragma mark - - (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style { self.queryStringSerializationStyle = style; self.queryStringSerialization = nil; } - (void)setQueryStringSerializationWithBlock:(NSString *(^)(NSURLRequest *, id, NSError *__autoreleasing *))block { self.queryStringSerialization = block; } #pragma mark - - (NSMutableURLRequest *)requestWithMethod:(NSString *)method URLString:(NSString *)URLString parameters:(id)parameters error:(NSError *__autoreleasing *)error { NSParameterAssert(method); NSParameterAssert(URLString); NSURL *url = [NSURL URLWithString:URLString]; NSParameterAssert(url); NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url]; mutableRequest.HTTPMethod = method; for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) { if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) { [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath]; } } mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy]; return mutableRequest; } - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method URLString:(NSString *)URLString parameters:(NSDictionary *)parameters constructingBodyWithBlock:(void (^)(id formData))block error:(NSError *__autoreleasing *)error { NSParameterAssert(method); NSParameterAssert(![method isEqualToString:@"GET"] && ![method isEqualToString:@"HEAD"]); NSMutableURLRequest *mutableRequest = [self requestWithMethod:method URLString:URLString parameters:nil error:error]; __block AFStreamingMultipartFormData *formData = [[AFStreamingMultipartFormData alloc] initWithURLRequest:mutableRequest stringEncoding:NSUTF8StringEncoding]; if (parameters) { for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) { NSData *data = nil; if ([pair.value isKindOfClass:[NSData class]]) { data = pair.value; } else if ([pair.value isEqual:[NSNull null]]) { data = [NSData data]; } else { data = [[pair.value description] dataUsingEncoding:self.stringEncoding]; } if (data) { [formData appendPartWithFormData:data name:[pair.field description]]; } } } if (block) { block(formData); } return [formData requestByFinalizingMultipartFormData]; } - (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request writingStreamContentsToFile:(NSURL *)fileURL completionHandler:(void (^)(NSError *error))handler { NSParameterAssert(request.HTTPBodyStream); NSParameterAssert([fileURL isFileURL]); NSInputStream *inputStream = request.HTTPBodyStream; NSOutputStream *outputStream = [[NSOutputStream alloc] initWithURL:fileURL append:NO]; __block NSError *error = nil; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [inputStream open]; [outputStream open]; while ([inputStream hasBytesAvailable] && [outputStream hasSpaceAvailable]) { uint8_t buffer[1024]; NSInteger bytesRead = [inputStream read:buffer maxLength:1024]; if (inputStream.streamError || bytesRead < 0) { error = inputStream.streamError; break; } NSInteger bytesWritten = [outputStream write:buffer maxLength:(NSUInteger)bytesRead]; if (outputStream.streamError || bytesWritten < 0) { error = outputStream.streamError; break; } if (bytesRead == 0 && bytesWritten == 0) { break; } } [outputStream close]; [inputStream close]; if (handler) { dispatch_async(dispatch_get_main_queue(), ^{ handler(error); }); } }); NSMutableURLRequest *mutableRequest = [request mutableCopy]; mutableRequest.HTTPBodyStream = nil; return mutableRequest; } #pragma mark - AFURLRequestSerialization - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(id)parameters error:(NSError *__autoreleasing *)error { NSParameterAssert(request); NSMutableURLRequest *mutableRequest = [request mutableCopy]; [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) { if (![request valueForHTTPHeaderField:field]) { [mutableRequest setValue:value forHTTPHeaderField:field]; } }]; NSString *query = nil; if (parameters) { if (self.queryStringSerialization) { NSError *serializationError; query = self.queryStringSerialization(request, parameters, &serializationError); if (serializationError) { if (error) { *error = serializationError; } return nil; } } else { switch (self.queryStringSerializationStyle) { case AFHTTPRequestQueryStringDefaultStyle: query = AFQueryStringFromParameters(parameters); break; } } } if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { if (query) { mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]]; } } else { // #2864: an empty string is a valid x-www-form-urlencoded payload if (!query) { query = @""; } if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; } [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; } return mutableRequest; } #pragma mark - NSKeyValueObserving + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { if ([AFHTTPRequestSerializerObservedKeyPaths() containsObject:key]) { return NO; } return [super automaticallyNotifiesObserversForKey:key]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(__unused id)object change:(NSDictionary *)change context:(void *)context { if (context == AFHTTPRequestSerializerObserverContext) { if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) { [self.mutableObservedChangedKeyPaths removeObject:keyPath]; } else { [self.mutableObservedChangedKeyPaths addObject:keyPath]; } } } #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; } - (instancetype)initWithCoder:(NSCoder *)decoder { self = [self init]; if (!self) { return nil; } self.mutableHTTPRequestHeaders = [[decoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))] mutableCopy]; self.queryStringSerializationStyle = (AFHTTPRequestQueryStringSerializationStyle)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))] unsignedIntegerValue]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.mutableHTTPRequestHeaders forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))]; [coder encodeInteger:self.queryStringSerializationStyle forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFHTTPRequestSerializer *serializer = [[[self class] allocWithZone:zone] init]; serializer.mutableHTTPRequestHeaders = [self.mutableHTTPRequestHeaders mutableCopyWithZone:zone]; serializer.queryStringSerializationStyle = self.queryStringSerializationStyle; serializer.queryStringSerialization = self.queryStringSerialization; return serializer; } @end #pragma mark - static NSString * AFCreateMultipartFormBoundary() { return [NSString stringWithFormat:@"Boundary+%08X%08X", arc4random(), arc4random()]; } static NSString * const kAFMultipartFormCRLF = @"\r\n"; static inline NSString * AFMultipartFormInitialBoundary(NSString *boundary) { return [NSString stringWithFormat:@"--%@%@", boundary, kAFMultipartFormCRLF]; } static inline NSString * AFMultipartFormEncapsulationBoundary(NSString *boundary) { return [NSString stringWithFormat:@"%@--%@%@", kAFMultipartFormCRLF, boundary, kAFMultipartFormCRLF]; } static inline NSString * AFMultipartFormFinalBoundary(NSString *boundary) { return [NSString stringWithFormat:@"%@--%@--%@", kAFMultipartFormCRLF, boundary, kAFMultipartFormCRLF]; } static inline NSString * AFContentTypeForPathExtension(NSString *extension) { NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL); NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType); if (!contentType) { return @"application/octet-stream"; } else { return contentType; } } NSUInteger const kAFUploadStream3GSuggestedPacketSize = 1024 * 16; NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; @interface AFHTTPBodyPart : NSObject @property (nonatomic, assign) NSStringEncoding stringEncoding; @property (nonatomic, strong) NSDictionary *headers; @property (nonatomic, copy) NSString *boundary; @property (nonatomic, strong) id body; @property (nonatomic, assign) unsigned long long bodyContentLength; @property (nonatomic, strong) NSInputStream *inputStream; @property (nonatomic, assign) BOOL hasInitialBoundary; @property (nonatomic, assign) BOOL hasFinalBoundary; @property (readonly, nonatomic, assign, getter = hasBytesAvailable) BOOL bytesAvailable; @property (readonly, nonatomic, assign) unsigned long long contentLength; - (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)length; @end @interface AFMultipartBodyStream : NSInputStream @property (nonatomic, assign) NSUInteger numberOfBytesInPacket; @property (nonatomic, assign) NSTimeInterval delay; @property (nonatomic, strong) NSInputStream *inputStream; @property (readonly, nonatomic, assign) unsigned long long contentLength; @property (readonly, nonatomic, assign, getter = isEmpty) BOOL empty; - (instancetype)initWithStringEncoding:(NSStringEncoding)encoding; - (void)setInitialAndFinalBoundaries; - (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart; @end #pragma mark - @interface AFStreamingMultipartFormData () @property (readwrite, nonatomic, copy) NSMutableURLRequest *request; @property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding; @property (readwrite, nonatomic, copy) NSString *boundary; @property (readwrite, nonatomic, strong) AFMultipartBodyStream *bodyStream; @end @implementation AFStreamingMultipartFormData - (instancetype)initWithURLRequest:(NSMutableURLRequest *)urlRequest stringEncoding:(NSStringEncoding)encoding { self = [super init]; if (!self) { return nil; } self.request = urlRequest; self.stringEncoding = encoding; self.boundary = AFCreateMultipartFormBoundary(); self.bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding]; return self; } - (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name error:(NSError * __autoreleasing *)error { NSParameterAssert(fileURL); NSParameterAssert(name); NSString *fileName = [fileURL lastPathComponent]; NSString *mimeType = AFContentTypeForPathExtension([fileURL pathExtension]); return [self appendPartWithFileURL:fileURL name:name fileName:fileName mimeType:mimeType error:error]; } - (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType error:(NSError * __autoreleasing *)error { NSParameterAssert(fileURL); NSParameterAssert(name); NSParameterAssert(fileName); NSParameterAssert(mimeType); if (![fileURL isFileURL]) { NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil)}; if (error) { *error = [[NSError alloc] initWithDomain:AFURLRequestSerializationErrorDomain code:NSURLErrorBadURL userInfo:userInfo]; } return NO; } else if ([fileURL checkResourceIsReachableAndReturnError:error] == NO) { NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedStringFromTable(@"File URL not reachable.", @"AFNetworking", nil)}; if (error) { *error = [[NSError alloc] initWithDomain:AFURLRequestSerializationErrorDomain code:NSURLErrorBadURL userInfo:userInfo]; } return NO; } NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:error]; if (!fileAttributes) { return NO; } NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary]; [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"]; [mutableHeaders setValue:mimeType forKey:@"Content-Type"]; AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init]; bodyPart.stringEncoding = self.stringEncoding; bodyPart.headers = mutableHeaders; bodyPart.boundary = self.boundary; bodyPart.body = fileURL; bodyPart.bodyContentLength = [fileAttributes[NSFileSize] unsignedLongLongValue]; [self.bodyStream appendHTTPBodyPart:bodyPart]; return YES; } - (void)appendPartWithInputStream:(NSInputStream *)inputStream name:(NSString *)name fileName:(NSString *)fileName length:(int64_t)length mimeType:(NSString *)mimeType { NSParameterAssert(name); NSParameterAssert(fileName); NSParameterAssert(mimeType); NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary]; [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"]; [mutableHeaders setValue:mimeType forKey:@"Content-Type"]; AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init]; bodyPart.stringEncoding = self.stringEncoding; bodyPart.headers = mutableHeaders; bodyPart.boundary = self.boundary; bodyPart.body = inputStream; bodyPart.bodyContentLength = (unsigned long long)length; [self.bodyStream appendHTTPBodyPart:bodyPart]; } - (void)appendPartWithFileData:(NSData *)data name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType { NSParameterAssert(name); NSParameterAssert(fileName); NSParameterAssert(mimeType); NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary]; [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"]; [mutableHeaders setValue:mimeType forKey:@"Content-Type"]; [self appendPartWithHeaders:mutableHeaders body:data]; } - (void)appendPartWithFormData:(NSData *)data name:(NSString *)name { NSParameterAssert(name); NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary]; [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"]; [self appendPartWithHeaders:mutableHeaders body:data]; } - (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body { NSParameterAssert(body); AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init]; bodyPart.stringEncoding = self.stringEncoding; bodyPart.headers = headers; bodyPart.boundary = self.boundary; bodyPart.bodyContentLength = [body length]; bodyPart.body = body; [self.bodyStream appendHTTPBodyPart:bodyPart]; } - (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay { self.bodyStream.numberOfBytesInPacket = numberOfBytes; self.bodyStream.delay = delay; } - (NSMutableURLRequest *)requestByFinalizingMultipartFormData { if ([self.bodyStream isEmpty]) { return self.request; } // Reset the initial and final boundaries to ensure correct Content-Length [self.bodyStream setInitialAndFinalBoundaries]; [self.request setHTTPBodyStream:self.bodyStream]; [self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", self.boundary] forHTTPHeaderField:@"Content-Type"]; [self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"]; return self.request; } @end #pragma mark - @interface NSStream () @property (readwrite) NSStreamStatus streamStatus; @property (readwrite, copy) NSError *streamError; @end @interface AFMultipartBodyStream () @property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding; @property (readwrite, nonatomic, strong) NSMutableArray *HTTPBodyParts; @property (readwrite, nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator; @property (readwrite, nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart; @property (readwrite, nonatomic, strong) NSOutputStream *outputStream; @property (readwrite, nonatomic, strong) NSMutableData *buffer; @end @implementation AFMultipartBodyStream #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wimplicit-atomic-properties" #if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1100) @synthesize delegate; #endif @synthesize streamStatus; @synthesize streamError; #pragma clang diagnostic pop - (instancetype)initWithStringEncoding:(NSStringEncoding)encoding { self = [super init]; if (!self) { return nil; } self.stringEncoding = encoding; self.HTTPBodyParts = [NSMutableArray array]; self.numberOfBytesInPacket = NSIntegerMax; return self; } - (void)setInitialAndFinalBoundaries { if ([self.HTTPBodyParts count] > 0) { for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) { bodyPart.hasInitialBoundary = NO; bodyPart.hasFinalBoundary = NO; } [[self.HTTPBodyParts firstObject] setHasInitialBoundary:YES]; [[self.HTTPBodyParts lastObject] setHasFinalBoundary:YES]; } } - (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart { [self.HTTPBodyParts addObject:bodyPart]; } - (BOOL)isEmpty { return [self.HTTPBodyParts count] == 0; } #pragma mark - NSInputStream - (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)length { if ([self streamStatus] == NSStreamStatusClosed) { return 0; } NSInteger totalNumberOfBytesRead = 0; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" while ((NSUInteger)totalNumberOfBytesRead < MIN(length, self.numberOfBytesInPacket)) { if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) { if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) { break; } } else { NSUInteger maxLength = MIN(length, self.numberOfBytesInPacket) - (NSUInteger)totalNumberOfBytesRead; NSInteger numberOfBytesRead = [self.currentHTTPBodyPart read:&buffer[totalNumberOfBytesRead] maxLength:maxLength]; if (numberOfBytesRead == -1) { self.streamError = self.currentHTTPBodyPart.inputStream.streamError; break; } else { totalNumberOfBytesRead += numberOfBytesRead; if (self.delay > 0.0f) { [NSThread sleepForTimeInterval:self.delay]; } } } } #pragma clang diagnostic pop return totalNumberOfBytesRead; } - (BOOL)getBuffer:(__unused uint8_t **)buffer length:(__unused NSUInteger *)len { return NO; } - (BOOL)hasBytesAvailable { return [self streamStatus] == NSStreamStatusOpen; } #pragma mark - NSStream - (void)open { if (self.streamStatus == NSStreamStatusOpen) { return; } self.streamStatus = NSStreamStatusOpen; [self setInitialAndFinalBoundaries]; self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator]; } - (void)close { self.streamStatus = NSStreamStatusClosed; } - (id)propertyForKey:(__unused NSString *)key { return nil; } - (BOOL)setProperty:(__unused id)property forKey:(__unused NSString *)key { return NO; } - (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop forMode:(__unused NSString *)mode {} - (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop forMode:(__unused NSString *)mode {} - (unsigned long long)contentLength { unsigned long long length = 0; for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) { length += [bodyPart contentLength]; } return length; } #pragma mark - Undocumented CFReadStream Bridged Methods - (void)_scheduleInCFRunLoop:(__unused CFRunLoopRef)aRunLoop forMode:(__unused CFStringRef)aMode {} - (void)_unscheduleFromCFRunLoop:(__unused CFRunLoopRef)aRunLoop forMode:(__unused CFStringRef)aMode {} - (BOOL)_setCFClientFlags:(__unused CFOptionFlags)inFlags callback:(__unused CFReadStreamClientCallBack)inCallback context:(__unused CFStreamClientContext *)inContext { return NO; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFMultipartBodyStream *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding]; for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) { [bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]]; } [bodyStreamCopy setInitialAndFinalBoundaries]; return bodyStreamCopy; } @end #pragma mark - typedef enum { AFEncapsulationBoundaryPhase = 1, AFHeaderPhase = 2, AFBodyPhase = 3, AFFinalBoundaryPhase = 4, } AFHTTPBodyPartReadPhase; @interface AFHTTPBodyPart () { AFHTTPBodyPartReadPhase _phase; NSInputStream *_inputStream; unsigned long long _phaseReadOffset; } - (BOOL)transitionToNextPhase; - (NSInteger)readData:(NSData *)data intoBuffer:(uint8_t *)buffer maxLength:(NSUInteger)length; @end @implementation AFHTTPBodyPart - (instancetype)init { self = [super init]; if (!self) { return nil; } [self transitionToNextPhase]; return self; } - (void)dealloc { if (_inputStream) { [_inputStream close]; _inputStream = nil; } } - (NSInputStream *)inputStream { if (!_inputStream) { if ([self.body isKindOfClass:[NSData class]]) { _inputStream = [NSInputStream inputStreamWithData:self.body]; } else if ([self.body isKindOfClass:[NSURL class]]) { _inputStream = [NSInputStream inputStreamWithURL:self.body]; } else if ([self.body isKindOfClass:[NSInputStream class]]) { _inputStream = self.body; } else { _inputStream = [NSInputStream inputStreamWithData:[NSData data]]; } } return _inputStream; } - (NSString *)stringForHeaders { NSMutableString *headerString = [NSMutableString string]; for (NSString *field in [self.headers allKeys]) { [headerString appendString:[NSString stringWithFormat:@"%@: %@%@", field, [self.headers valueForKey:field], kAFMultipartFormCRLF]]; } [headerString appendString:kAFMultipartFormCRLF]; return [NSString stringWithString:headerString]; } - (unsigned long long)contentLength { unsigned long long length = 0; NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary(self.boundary) : AFMultipartFormEncapsulationBoundary(self.boundary)) dataUsingEncoding:self.stringEncoding]; length += [encapsulationBoundaryData length]; NSData *headersData = [[self stringForHeaders] dataUsingEncoding:self.stringEncoding]; length += [headersData length]; length += _bodyContentLength; NSData *closingBoundaryData = ([self hasFinalBoundary] ? [AFMultipartFormFinalBoundary(self.boundary) dataUsingEncoding:self.stringEncoding] : [NSData data]); length += [closingBoundaryData length]; return length; } - (BOOL)hasBytesAvailable { // Allows `read:maxLength:` to be called again if `AFMultipartFormFinalBoundary` doesn't fit into the available buffer if (_phase == AFFinalBoundaryPhase) { return YES; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wcovered-switch-default" switch (self.inputStream.streamStatus) { case NSStreamStatusNotOpen: case NSStreamStatusOpening: case NSStreamStatusOpen: case NSStreamStatusReading: case NSStreamStatusWriting: return YES; case NSStreamStatusAtEnd: case NSStreamStatusClosed: case NSStreamStatusError: default: return NO; } #pragma clang diagnostic pop } - (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)length { NSInteger totalNumberOfBytesRead = 0; if (_phase == AFEncapsulationBoundaryPhase) { NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary(self.boundary) : AFMultipartFormEncapsulationBoundary(self.boundary)) dataUsingEncoding:self.stringEncoding]; totalNumberOfBytesRead += [self readData:encapsulationBoundaryData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)]; } if (_phase == AFHeaderPhase) { NSData *headersData = [[self stringForHeaders] dataUsingEncoding:self.stringEncoding]; totalNumberOfBytesRead += [self readData:headersData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)]; } if (_phase == AFBodyPhase) { NSInteger numberOfBytesRead = 0; numberOfBytesRead = [self.inputStream read:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)]; if (numberOfBytesRead == -1) { return -1; } else { totalNumberOfBytesRead += numberOfBytesRead; if ([self.inputStream streamStatus] >= NSStreamStatusAtEnd) { [self transitionToNextPhase]; } } } if (_phase == AFFinalBoundaryPhase) { NSData *closingBoundaryData = ([self hasFinalBoundary] ? [AFMultipartFormFinalBoundary(self.boundary) dataUsingEncoding:self.stringEncoding] : [NSData data]); totalNumberOfBytesRead += [self readData:closingBoundaryData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)]; } return totalNumberOfBytesRead; } - (NSInteger)readData:(NSData *)data intoBuffer:(uint8_t *)buffer maxLength:(NSUInteger)length { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" NSRange range = NSMakeRange((NSUInteger)_phaseReadOffset, MIN([data length] - ((NSUInteger)_phaseReadOffset), length)); [data getBytes:buffer range:range]; #pragma clang diagnostic pop _phaseReadOffset += range.length; if (((NSUInteger)_phaseReadOffset) >= [data length]) { [self transitionToNextPhase]; } return (NSInteger)range.length; } - (BOOL)transitionToNextPhase { if (![[NSThread currentThread] isMainThread]) { dispatch_sync(dispatch_get_main_queue(), ^{ [self transitionToNextPhase]; }); return YES; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wcovered-switch-default" switch (_phase) { case AFEncapsulationBoundaryPhase: _phase = AFHeaderPhase; break; case AFHeaderPhase: [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [self.inputStream open]; _phase = AFBodyPhase; break; case AFBodyPhase: [self.inputStream close]; _phase = AFFinalBoundaryPhase; break; case AFFinalBoundaryPhase: default: _phase = AFEncapsulationBoundaryPhase; break; } _phaseReadOffset = 0; #pragma clang diagnostic pop return YES; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFHTTPBodyPart *bodyPart = [[[self class] allocWithZone:zone] init]; bodyPart.stringEncoding = self.stringEncoding; bodyPart.headers = self.headers; bodyPart.bodyContentLength = self.bodyContentLength; bodyPart.body = self.body; bodyPart.boundary = self.boundary; return bodyPart; } @end #pragma mark - @implementation AFJSONRequestSerializer + (instancetype)serializer { return [self serializerWithWritingOptions:(NSJSONWritingOptions)0]; } + (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions { AFJSONRequestSerializer *serializer = [[self alloc] init]; serializer.writingOptions = writingOptions; return serializer; } #pragma mark - AFURLRequestSerialization - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(id)parameters error:(NSError *__autoreleasing *)error { NSParameterAssert(request); if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { return [super requestBySerializingRequest:request withParameters:parameters error:error]; } NSMutableURLRequest *mutableRequest = [request mutableCopy]; [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) { if (![request valueForHTTPHeaderField:field]) { [mutableRequest setValue:value forHTTPHeaderField:field]; } }]; if (parameters) { if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; } [mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]]; } return mutableRequest; } #pragma mark - NSSecureCoding - (instancetype)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; if (!self) { return nil; } self.writingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writingOptions))] unsignedIntegerValue]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeInteger:self.writingOptions forKey:NSStringFromSelector(@selector(writingOptions))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFJSONRequestSerializer *serializer = [super copyWithZone:zone]; serializer.writingOptions = self.writingOptions; return serializer; } @end #pragma mark - @implementation AFPropertyListRequestSerializer + (instancetype)serializer { return [self serializerWithFormat:NSPropertyListXMLFormat_v1_0 writeOptions:0]; } + (instancetype)serializerWithFormat:(NSPropertyListFormat)format writeOptions:(NSPropertyListWriteOptions)writeOptions { AFPropertyListRequestSerializer *serializer = [[self alloc] init]; serializer.format = format; serializer.writeOptions = writeOptions; return serializer; } #pragma mark - AFURLRequestSerializer - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(id)parameters error:(NSError *__autoreleasing *)error { NSParameterAssert(request); if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { return [super requestBySerializingRequest:request withParameters:parameters error:error]; } NSMutableURLRequest *mutableRequest = [request mutableCopy]; [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) { if (![request valueForHTTPHeaderField:field]) { [mutableRequest setValue:value forHTTPHeaderField:field]; } }]; if (parameters) { if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/x-plist" forHTTPHeaderField:@"Content-Type"]; } [mutableRequest setHTTPBody:[NSPropertyListSerialization dataWithPropertyList:parameters format:self.format options:self.writeOptions error:error]]; } return mutableRequest; } #pragma mark - NSSecureCoding - (instancetype)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; if (!self) { return nil; } self.format = (NSPropertyListFormat)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; self.writeOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writeOptions))] unsignedIntegerValue]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeInteger:self.format forKey:NSStringFromSelector(@selector(format))]; [coder encodeObject:@(self.writeOptions) forKey:NSStringFromSelector(@selector(writeOptions))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFPropertyListRequestSerializer *serializer = [super copyWithZone:zone]; serializer.format = self.format; serializer.writeOptions = self.writeOptions; return serializer; } @end ================================================ FILE: Pods/AFNetworking/AFNetworking/AFURLResponseSerialization.h ================================================ // AFURLResponseSerialization.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import NS_ASSUME_NONNULL_BEGIN /** The `AFURLResponseSerialization` protocol is adopted by an object that decodes data into a more useful object representation, according to details in the server response. Response serializers may additionally perform validation on the incoming response and data. For example, a JSON response serializer may check for an acceptable status code (`2XX` range) and content type (`application/json`), decoding a valid JSON response into an object. */ @protocol AFURLResponseSerialization /** The response object decoded from the data associated with a specified response. @param response The response to be processed. @param data The response data to be decoded. @param error The error that occurred while attempting to decode the response data. @return The object decoded from the specified response data. */ - (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response data:(nullable NSData *)data error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW; @end #pragma mark - /** `AFHTTPResponseSerializer` conforms to the `AFURLRequestSerialization` & `AFURLResponseSerialization` protocols, offering a concrete base implementation of query string / URL form-encoded parameter serialization and default request headers, as well as response status code and content type validation. Any request or response serializer dealing with HTTP is encouraged to subclass `AFHTTPResponseSerializer` in order to ensure consistent default behavior. */ @interface AFHTTPResponseSerializer : NSObject - (instancetype)init; /** The string encoding used to serialize data received from the server, when no string encoding is specified by the response. `NSUTF8StringEncoding` by default. */ @property (nonatomic, assign) NSStringEncoding stringEncoding; /** Creates and returns a serializer with default configuration. */ + (instancetype)serializer; ///----------------------------------------- /// @name Configuring Response Serialization ///----------------------------------------- /** The acceptable HTTP status codes for responses. When non-`nil`, responses with status codes not contained by the set will result in an error during validation. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html */ @property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes; /** The acceptable MIME types for responses. When non-`nil`, responses with a `Content-Type` with MIME types that do not intersect with the set will result in an error during validation. */ @property (nonatomic, copy, nullable) NSSet *acceptableContentTypes; /** Validates the specified response and data. In its base implementation, this method checks for an acceptable status code and content type. Subclasses may wish to add other domain-specific checks. @param response The response to be validated. @param data The data associated with the response. @param error The error that occurred while attempting to validate the response. @return `YES` if the response is valid, otherwise `NO`. */ - (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response data:(nullable NSData *)data error:(NSError * _Nullable __autoreleasing *)error; @end #pragma mark - /** `AFJSONResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes JSON responses. By default, `AFJSONResponseSerializer` accepts the following MIME types, which includes the official standard, `application/json`, as well as other commonly-used types: - `application/json` - `text/json` - `text/javascript` */ @interface AFJSONResponseSerializer : AFHTTPResponseSerializer - (instancetype)init; /** Options for reading the response JSON data and creating the Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. */ @property (nonatomic, assign) NSJSONReadingOptions readingOptions; /** Whether to remove keys with `NSNull` values from response JSON. Defaults to `NO`. */ @property (nonatomic, assign) BOOL removesKeysWithNullValues; /** Creates and returns a JSON serializer with specified reading and writing options. @param readingOptions The specified JSON reading options. */ + (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions; @end #pragma mark - /** `AFXMLParserResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLParser` objects. By default, `AFXMLParserResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types: - `application/xml` - `text/xml` */ @interface AFXMLParserResponseSerializer : AFHTTPResponseSerializer @end #pragma mark - #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED /** `AFXMLDocumentResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects. By default, `AFXMLDocumentResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types: - `application/xml` - `text/xml` */ @interface AFXMLDocumentResponseSerializer : AFHTTPResponseSerializer - (instancetype)init; /** Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. */ @property (nonatomic, assign) NSUInteger options; /** Creates and returns an XML document serializer with the specified options. @param mask The XML document options. */ + (instancetype)serializerWithXMLDocumentOptions:(NSUInteger)mask; @end #endif #pragma mark - /** `AFPropertyListResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects. By default, `AFPropertyListResponseSerializer` accepts the following MIME types: - `application/x-plist` */ @interface AFPropertyListResponseSerializer : AFHTTPResponseSerializer - (instancetype)init; /** The property list format. Possible values are described in "NSPropertyListFormat". */ @property (nonatomic, assign) NSPropertyListFormat format; /** The property list reading options. Possible values are described in "NSPropertyListMutabilityOptions." */ @property (nonatomic, assign) NSPropertyListReadOptions readOptions; /** Creates and returns a property list serializer with a specified format, read options, and write options. @param format The property list format. @param readOptions The property list reading options. */ + (instancetype)serializerWithFormat:(NSPropertyListFormat)format readOptions:(NSPropertyListReadOptions)readOptions; @end #pragma mark - /** `AFImageResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes image responses. By default, `AFImageResponseSerializer` accepts the following MIME types, which correspond to the image formats supported by UIImage or NSImage: - `image/tiff` - `image/jpeg` - `image/gif` - `image/png` - `image/ico` - `image/x-icon` - `image/bmp` - `image/x-bmp` - `image/x-xbitmap` - `image/x-win-bitmap` */ @interface AFImageResponseSerializer : AFHTTPResponseSerializer #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH /** The scale factor used when interpreting the image data to construct `responseImage`. Specifying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the size property. This is set to the value of scale of the main screen by default, which automatically scales images for retina displays, for instance. */ @property (nonatomic, assign) CGFloat imageScale; /** Whether to automatically inflate response image data for compressed formats (such as PNG or JPEG). Enabling this can significantly improve drawing performance on iOS when used with `setCompletionBlockWithSuccess:failure:`, as it allows a bitmap representation to be constructed in the background rather than on the main thread. `YES` by default. */ @property (nonatomic, assign) BOOL automaticallyInflatesResponseImage; #endif @end #pragma mark - /** `AFCompoundSerializer` is a subclass of `AFHTTPResponseSerializer` that delegates the response serialization to the first `AFHTTPResponseSerializer` object that returns an object for `responseObjectForResponse:data:error:`, falling back on the default behavior of `AFHTTPResponseSerializer`. This is useful for supporting multiple potential types and structures of server responses with a single serializer. */ @interface AFCompoundResponseSerializer : AFHTTPResponseSerializer /** The component response serializers. */ @property (readonly, nonatomic, copy) NSArray > *responseSerializers; /** Creates and returns a compound serializer comprised of the specified response serializers. @warning Each response serializer specified must be a subclass of `AFHTTPResponseSerializer`, and response to `-validateResponse:data:error:`. */ + (instancetype)compoundSerializerWithResponseSerializers:(NSArray > *)responseSerializers; @end ///---------------- /// @name Constants ///---------------- /** ## Error Domains The following error domain is predefined. - `NSString * const AFURLResponseSerializationErrorDomain` ### Constants `AFURLResponseSerializationErrorDomain` AFURLResponseSerializer errors. Error codes for `AFURLResponseSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. */ FOUNDATION_EXPORT NSString * const AFURLResponseSerializationErrorDomain; /** ## User info dictionary keys These keys may exist in the user info dictionary, in addition to those defined for NSError. - `NSString * const AFNetworkingOperationFailingURLResponseErrorKey` - `NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey` ### Constants `AFNetworkingOperationFailingURLResponseErrorKey` The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. `AFNetworkingOperationFailingURLResponseDataErrorKey` The corresponding value is an `NSData` containing the original data of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. */ FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseErrorKey; FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; NS_ASSUME_NONNULL_END ================================================ FILE: Pods/AFNetworking/AFNetworking/AFURLResponseSerialization.m ================================================ // AFURLResponseSerialization.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "AFURLResponseSerialization.h" #import #if TARGET_OS_IOS #import #elif TARGET_OS_WATCH #import #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) #import #endif NSString * const AFURLResponseSerializationErrorDomain = @"com.alamofire.error.serialization.response"; NSString * const AFNetworkingOperationFailingURLResponseErrorKey = @"com.alamofire.serialization.response.error.response"; NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey = @"com.alamofire.serialization.response.error.data"; static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) { if (!error) { return underlyingError; } if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) { return error; } NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy]; mutableUserInfo[NSUnderlyingErrorKey] = underlyingError; return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo]; } static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) { if ([error.domain isEqualToString:domain] && error.code == code) { return YES; } else if (error.userInfo[NSUnderlyingErrorKey]) { return AFErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain); } return NO; } static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) { if ([JSONObject isKindOfClass:[NSArray class]]) { NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]]; for (id value in (NSArray *)JSONObject) { [mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)]; } return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray]; } else if ([JSONObject isKindOfClass:[NSDictionary class]]) { NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject]; for (id key in [(NSDictionary *)JSONObject allKeys]) { id value = (NSDictionary *)JSONObject[key]; if (!value || [value isEqual:[NSNull null]]) { [mutableDictionary removeObjectForKey:key]; } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) { mutableDictionary[key] = AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions); } } return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary]; } return JSONObject; } @implementation AFHTTPResponseSerializer + (instancetype)serializer { return [[self alloc] init]; } - (instancetype)init { self = [super init]; if (!self) { return nil; } self.stringEncoding = NSUTF8StringEncoding; self.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)]; self.acceptableContentTypes = nil; return self; } #pragma mark - - (BOOL)validateResponse:(NSHTTPURLResponse *)response data:(NSData *)data error:(NSError * __autoreleasing *)error { BOOL responseIsValid = YES; NSError *validationError = nil; if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) { if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]]) { if ([data length] > 0 && [response URL]) { NSMutableDictionary *mutableUserInfo = [@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]], NSURLErrorFailingURLErrorKey:[response URL], AFNetworkingOperationFailingURLResponseErrorKey: response, } mutableCopy]; if (data) { mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data; } validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError); } responseIsValid = NO; } if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) { NSMutableDictionary *mutableUserInfo = [@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode], NSURLErrorFailingURLErrorKey:[response URL], AFNetworkingOperationFailingURLResponseErrorKey: response, } mutableCopy]; if (data) { mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data; } validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError); responseIsValid = NO; } } if (error && !responseIsValid) { *error = validationError; } return responseIsValid; } #pragma mark - AFURLResponseSerialization - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { [self validateResponse:(NSHTTPURLResponse *)response data:data error:error]; return data; } #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; } - (instancetype)initWithCoder:(NSCoder *)decoder { self = [self init]; if (!self) { return nil; } self.acceptableStatusCodes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableStatusCodes))]; self.acceptableContentTypes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableContentTypes))]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.acceptableStatusCodes forKey:NSStringFromSelector(@selector(acceptableStatusCodes))]; [coder encodeObject:self.acceptableContentTypes forKey:NSStringFromSelector(@selector(acceptableContentTypes))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFHTTPResponseSerializer *serializer = [[[self class] allocWithZone:zone] init]; serializer.acceptableStatusCodes = [self.acceptableStatusCodes copyWithZone:zone]; serializer.acceptableContentTypes = [self.acceptableContentTypes copyWithZone:zone]; return serializer; } @end #pragma mark - @implementation AFJSONResponseSerializer + (instancetype)serializer { return [self serializerWithReadingOptions:(NSJSONReadingOptions)0]; } + (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions { AFJSONResponseSerializer *serializer = [[self alloc] init]; serializer.readingOptions = readingOptions; return serializer; } - (instancetype)init { self = [super init]; if (!self) { return nil; } self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil]; return self; } #pragma mark - AFURLResponseSerialization - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) { if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) { return nil; } } // Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization. // See https://github.com/rails/rails/issues/1742 NSStringEncoding stringEncoding = self.stringEncoding; if (response.textEncodingName) { CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName); if (encoding != kCFStringEncodingInvalidId) { stringEncoding = CFStringConvertEncodingToNSStringEncoding(encoding); } } id responseObject = nil; NSError *serializationError = nil; @autoreleasepool { NSString *responseString = [[NSString alloc] initWithData:data encoding:stringEncoding]; if (responseString && ![responseString isEqualToString:@" "]) { // Workaround for a bug in NSJSONSerialization when Unicode character escape codes are used instead of the actual character // See http://stackoverflow.com/a/12843465/157142 data = [responseString dataUsingEncoding:NSUTF8StringEncoding]; if (data) { if ([data length] > 0) { responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError]; } else { return nil; } } else { NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string", @"AFNetworking", nil), NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", @"AFNetworking", nil), responseString] }; serializationError = [NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo]; } } } if (self.removesKeysWithNullValues && responseObject) { responseObject = AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions); } if (error) { *error = AFErrorWithUnderlyingError(serializationError, *error); } return responseObject; } #pragma mark - NSSecureCoding - (instancetype)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; if (!self) { return nil; } self.readingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readingOptions))] unsignedIntegerValue]; self.removesKeysWithNullValues = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))] boolValue]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeObject:@(self.readingOptions) forKey:NSStringFromSelector(@selector(readingOptions))]; [coder encodeObject:@(self.removesKeysWithNullValues) forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFJSONResponseSerializer *serializer = [[[self class] allocWithZone:zone] init]; serializer.readingOptions = self.readingOptions; serializer.removesKeysWithNullValues = self.removesKeysWithNullValues; return serializer; } @end #pragma mark - @implementation AFXMLParserResponseSerializer + (instancetype)serializer { AFXMLParserResponseSerializer *serializer = [[self alloc] init]; return serializer; } - (instancetype)init { self = [super init]; if (!self) { return nil; } self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml", nil]; return self; } #pragma mark - AFURLResponseSerialization - (id)responseObjectForResponse:(NSHTTPURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) { if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) { return nil; } } return [[NSXMLParser alloc] initWithData:data]; } @end #pragma mark - #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED @implementation AFXMLDocumentResponseSerializer + (instancetype)serializer { return [self serializerWithXMLDocumentOptions:0]; } + (instancetype)serializerWithXMLDocumentOptions:(NSUInteger)mask { AFXMLDocumentResponseSerializer *serializer = [[self alloc] init]; serializer.options = mask; return serializer; } - (instancetype)init { self = [super init]; if (!self) { return nil; } self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml", nil]; return self; } #pragma mark - AFURLResponseSerialization - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) { if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) { return nil; } } NSError *serializationError = nil; NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data options:self.options error:&serializationError]; if (error) { *error = AFErrorWithUnderlyingError(serializationError, *error); } return document; } #pragma mark - NSSecureCoding - (instancetype)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; if (!self) { return nil; } self.options = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(options))] unsignedIntegerValue]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeObject:@(self.options) forKey:NSStringFromSelector(@selector(options))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFXMLDocumentResponseSerializer *serializer = [[[self class] allocWithZone:zone] init]; serializer.options = self.options; return serializer; } @end #endif #pragma mark - @implementation AFPropertyListResponseSerializer + (instancetype)serializer { return [self serializerWithFormat:NSPropertyListXMLFormat_v1_0 readOptions:0]; } + (instancetype)serializerWithFormat:(NSPropertyListFormat)format readOptions:(NSPropertyListReadOptions)readOptions { AFPropertyListResponseSerializer *serializer = [[self alloc] init]; serializer.format = format; serializer.readOptions = readOptions; return serializer; } - (instancetype)init { self = [super init]; if (!self) { return nil; } self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/x-plist", nil]; return self; } #pragma mark - AFURLResponseSerialization - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) { if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) { return nil; } } id responseObject; NSError *serializationError = nil; if (data) { responseObject = [NSPropertyListSerialization propertyListWithData:data options:self.readOptions format:NULL error:&serializationError]; } if (error) { *error = AFErrorWithUnderlyingError(serializationError, *error); } return responseObject; } #pragma mark - NSSecureCoding - (instancetype)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; if (!self) { return nil; } self.format = (NSPropertyListFormat)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; self.readOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readOptions))] unsignedIntegerValue]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeObject:@(self.format) forKey:NSStringFromSelector(@selector(format))]; [coder encodeObject:@(self.readOptions) forKey:NSStringFromSelector(@selector(readOptions))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFPropertyListResponseSerializer *serializer = [[[self class] allocWithZone:zone] init]; serializer.format = self.format; serializer.readOptions = self.readOptions; return serializer; } @end #pragma mark - #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH #import #import @interface UIImage (AFNetworkingSafeImageLoading) + (UIImage *)af_safeImageWithData:(NSData *)data; @end static NSLock* imageLock = nil; @implementation UIImage (AFNetworkingSafeImageLoading) + (UIImage *)af_safeImageWithData:(NSData *)data { UIImage* image = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ imageLock = [[NSLock alloc] init]; }); [imageLock lock]; image = [UIImage imageWithData:data]; [imageLock unlock]; return image; } @end static UIImage * AFImageWithDataAtScale(NSData *data, CGFloat scale) { UIImage *image = [UIImage af_safeImageWithData:data]; if (image.images) { return image; } return [[UIImage alloc] initWithCGImage:[image CGImage] scale:scale orientation:image.imageOrientation]; } static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *response, NSData *data, CGFloat scale) { if (!data || [data length] == 0) { return nil; } CGImageRef imageRef = NULL; CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); if ([response.MIMEType isEqualToString:@"image/png"]) { imageRef = CGImageCreateWithPNGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault); } else if ([response.MIMEType isEqualToString:@"image/jpeg"]) { imageRef = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault); if (imageRef) { CGColorSpaceRef imageColorSpace = CGImageGetColorSpace(imageRef); CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(imageColorSpace); // CGImageCreateWithJPEGDataProvider does not properly handle CMKY, so fall back to AFImageWithDataAtScale if (imageColorSpaceModel == kCGColorSpaceModelCMYK) { CGImageRelease(imageRef); imageRef = NULL; } } } CGDataProviderRelease(dataProvider); UIImage *image = AFImageWithDataAtScale(data, scale); if (!imageRef) { if (image.images || !image) { return image; } imageRef = CGImageCreateCopy([image CGImage]); if (!imageRef) { return nil; } } size_t width = CGImageGetWidth(imageRef); size_t height = CGImageGetHeight(imageRef); size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef); if (width * height > 1024 * 1024 || bitsPerComponent > 8) { CGImageRelease(imageRef); return image; } // CGImageGetBytesPerRow() calculates incorrectly in iOS 5.0, so defer to CGBitmapContextCreate size_t bytesPerRow = 0; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef); if (colorSpaceModel == kCGColorSpaceModelRGB) { uint32_t alpha = (bitmapInfo & kCGBitmapAlphaInfoMask); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wassign-enum" if (alpha == kCGImageAlphaNone) { bitmapInfo &= ~kCGBitmapAlphaInfoMask; bitmapInfo |= kCGImageAlphaNoneSkipFirst; } else if (!(alpha == kCGImageAlphaNoneSkipFirst || alpha == kCGImageAlphaNoneSkipLast)) { bitmapInfo &= ~kCGBitmapAlphaInfoMask; bitmapInfo |= kCGImageAlphaPremultipliedFirst; } #pragma clang diagnostic pop } CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); CGColorSpaceRelease(colorSpace); if (!context) { CGImageRelease(imageRef); return image; } CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), imageRef); CGImageRef inflatedImageRef = CGBitmapContextCreateImage(context); CGContextRelease(context); UIImage *inflatedImage = [[UIImage alloc] initWithCGImage:inflatedImageRef scale:scale orientation:image.imageOrientation]; CGImageRelease(inflatedImageRef); CGImageRelease(imageRef); return inflatedImage; } #endif @implementation AFImageResponseSerializer - (instancetype)init { self = [super init]; if (!self) { return nil; } self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon", @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", nil]; #if TARGET_OS_IOS || TARGET_OS_TV self.imageScale = [[UIScreen mainScreen] scale]; self.automaticallyInflatesResponseImage = YES; #elif TARGET_OS_WATCH self.imageScale = [[WKInterfaceDevice currentDevice] screenScale]; self.automaticallyInflatesResponseImage = YES; #endif return self; } #pragma mark - AFURLResponseSerializer - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) { if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) { return nil; } } #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH if (self.automaticallyInflatesResponseImage) { return AFInflatedImageFromResponseWithDataAtScale((NSHTTPURLResponse *)response, data, self.imageScale); } else { return AFImageWithDataAtScale(data, self.imageScale); } #else // Ensure that the image is set to it's correct pixel width and height NSBitmapImageRep *bitimage = [[NSBitmapImageRep alloc] initWithData:data]; NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize([bitimage pixelsWide], [bitimage pixelsHigh])]; [image addRepresentation:bitimage]; return image; #endif return nil; } #pragma mark - NSSecureCoding - (instancetype)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; if (!self) { return nil; } #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH NSNumber *imageScale = [decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(imageScale))]; #if CGFLOAT_IS_DOUBLE self.imageScale = [imageScale doubleValue]; #else self.imageScale = [imageScale floatValue]; #endif self.automaticallyInflatesResponseImage = [decoder decodeBoolForKey:NSStringFromSelector(@selector(automaticallyInflatesResponseImage))]; #endif return self; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH [coder encodeObject:@(self.imageScale) forKey:NSStringFromSelector(@selector(imageScale))]; [coder encodeBool:self.automaticallyInflatesResponseImage forKey:NSStringFromSelector(@selector(automaticallyInflatesResponseImage))]; #endif } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFImageResponseSerializer *serializer = [[[self class] allocWithZone:zone] init]; #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH serializer.imageScale = self.imageScale; serializer.automaticallyInflatesResponseImage = self.automaticallyInflatesResponseImage; #endif return serializer; } @end #pragma mark - @interface AFCompoundResponseSerializer () @property (readwrite, nonatomic, copy) NSArray *responseSerializers; @end @implementation AFCompoundResponseSerializer + (instancetype)compoundSerializerWithResponseSerializers:(NSArray *)responseSerializers { AFCompoundResponseSerializer *serializer = [[self alloc] init]; serializer.responseSerializers = responseSerializers; return serializer; } #pragma mark - AFURLResponseSerialization - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { for (id serializer in self.responseSerializers) { if (![serializer isKindOfClass:[AFHTTPResponseSerializer class]]) { continue; } NSError *serializerError = nil; id responseObject = [serializer responseObjectForResponse:response data:data error:&serializerError]; if (responseObject) { if (error) { *error = AFErrorWithUnderlyingError(serializerError, *error); } return responseObject; } } return [super responseObjectForResponse:response data:data error:error]; } #pragma mark - NSSecureCoding - (instancetype)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; if (!self) { return nil; } self.responseSerializers = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(responseSerializers))]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeObject:self.responseSerializers forKey:NSStringFromSelector(@selector(responseSerializers))]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { AFCompoundResponseSerializer *serializer = [[[self class] allocWithZone:zone] init]; serializer.responseSerializers = self.responseSerializers; return serializer; } @end ================================================ FILE: Pods/AFNetworking/AFNetworking/AFURLSessionManager.h ================================================ // AFURLSessionManager.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import "AFURLResponseSerialization.h" #import "AFURLRequestSerialization.h" #import "AFSecurityPolicy.h" #if !TARGET_OS_WATCH #import "AFNetworkReachabilityManager.h" #endif /** `AFURLSessionManager` creates and manages an `NSURLSession` object based on a specified `NSURLSessionConfiguration` object, which conforms to ``, ``, ``, and ``. ## Subclassing Notes This is the base class for `AFHTTPSessionManager`, which adds functionality specific to making HTTP requests. If you are looking to extend `AFURLSessionManager` specifically for HTTP, consider subclassing `AFHTTPSessionManager` instead. ## NSURLSession & NSURLSessionTask Delegate Methods `AFURLSessionManager` implements the following delegate methods: ### `NSURLSessionDelegate` - `URLSession:didBecomeInvalidWithError:` - `URLSession:didReceiveChallenge:completionHandler:` - `URLSessionDidFinishEventsForBackgroundURLSession:` ### `NSURLSessionTaskDelegate` - `URLSession:willPerformHTTPRedirection:newRequest:completionHandler:` - `URLSession:task:didReceiveChallenge:completionHandler:` - `URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:` - `URLSession:task:didCompleteWithError:` ### `NSURLSessionDataDelegate` - `URLSession:dataTask:didReceiveResponse:completionHandler:` - `URLSession:dataTask:didBecomeDownloadTask:` - `URLSession:dataTask:didReceiveData:` - `URLSession:dataTask:willCacheResponse:completionHandler:` ### `NSURLSessionDownloadDelegate` - `URLSession:downloadTask:didFinishDownloadingToURL:` - `URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite:` - `URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:` If any of these methods are overridden in a subclass, they _must_ call the `super` implementation first. ## Network Reachability Monitoring Network reachability status and change monitoring is available through the `reachabilityManager` property. Applications may choose to monitor network reachability conditions in order to prevent or suspend any outbound requests. See `AFNetworkReachabilityManager` for more details. ## NSCoding Caveats - Encoded managers do not include any block properties. Be sure to set delegate callback blocks when using `-initWithCoder:` or `NSKeyedUnarchiver`. ## NSCopying Caveats - `-copy` and `-copyWithZone:` return a new manager with a new `NSURLSession` created from the configuration of the original. - Operation copies do not include any delegate callback blocks, as they often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ session manager when copied. @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance. */ NS_ASSUME_NONNULL_BEGIN @interface AFURLSessionManager : NSObject /** The managed session. */ @property (readonly, nonatomic, strong) NSURLSession *session; /** The operation queue on which delegate callbacks are run. */ @property (readonly, nonatomic, strong) NSOperationQueue *operationQueue; /** Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an instance of `AFJSONResponseSerializer`. @warning `responseSerializer` must not be `nil`. */ @property (nonatomic, strong) id responseSerializer; ///------------------------------- /// @name Managing Security Policy ///------------------------------- /** The security policy used by created session to evaluate server trust for secure connections. `AFURLSessionManager` uses the `defaultPolicy` unless otherwise specified. */ @property (nonatomic, strong) AFSecurityPolicy *securityPolicy; #if !TARGET_OS_WATCH ///-------------------------------------- /// @name Monitoring Network Reachability ///-------------------------------------- /** The network reachability manager. `AFURLSessionManager` uses the `sharedManager` by default. */ @property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager; #endif ///---------------------------- /// @name Getting Session Tasks ///---------------------------- /** The data, upload, and download tasks currently run by the managed session. */ @property (readonly, nonatomic, strong) NSArray *tasks; /** The data tasks currently run by the managed session. */ @property (readonly, nonatomic, strong) NSArray *dataTasks; /** The upload tasks currently run by the managed session. */ @property (readonly, nonatomic, strong) NSArray *uploadTasks; /** The download tasks currently run by the managed session. */ @property (readonly, nonatomic, strong) NSArray *downloadTasks; ///------------------------------- /// @name Managing Callback Queues ///------------------------------- /** The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used. */ @property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; /** The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used. */ @property (nonatomic, strong, nullable) dispatch_group_t completionGroup; ///--------------------------------- /// @name Working Around System Bugs ///--------------------------------- /** Whether to attempt to retry creation of upload tasks for background sessions when initial call returns `nil`. `NO` by default. @bug As of iOS 7.0, there is a bug where upload tasks created for background tasks are sometimes `nil`. As a workaround, if this property is `YES`, AFNetworking will follow Apple's recommendation to try creating the task again. @see https://github.com/AFNetworking/AFNetworking/issues/1675 */ @property (nonatomic, assign) BOOL attemptsToRecreateUploadTasksForBackgroundSessions; ///--------------------- /// @name Initialization ///--------------------- /** Creates and returns a manager for a session created with the specified configuration. This is the designated initializer. @param configuration The configuration used to create the managed session. @return A manager for a newly-created session. */ - (instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; /** Invalidates the managed session, optionally canceling pending tasks. @param cancelPendingTasks Whether or not to cancel pending tasks. */ - (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks; ///------------------------- /// @name Running Data Tasks ///------------------------- /** Creates an `NSURLSessionDataTask` with the specified request. @param request The HTTP request for the request. @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; /** Creates an `NSURLSessionDataTask` with the specified request. @param request The HTTP request for the request. @param uploadProgress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue. @param downloadProgress A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue. @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; ///--------------------------- /// @name Running Upload Tasks ///--------------------------- /** Creates an `NSURLSessionUploadTask` with the specified request for a local file. @param request The HTTP request for the request. @param fileURL A URL to the local file to be uploaded. @param progress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue. @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. @see `attemptsToRecreateUploadTasksForBackgroundSessions` */ - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL progress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; /** Creates an `NSURLSessionUploadTask` with the specified request for an HTTP body. @param request The HTTP request for the request. @param bodyData A data object containing the HTTP body to be uploaded. @param progress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue. @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(nullable NSData *)bodyData progress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; /** Creates an `NSURLSessionUploadTask` with the specified streaming request. @param request The HTTP request for the request. @param progress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue. @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request progress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; ///----------------------------- /// @name Running Download Tasks ///----------------------------- /** Creates an `NSURLSessionDownloadTask` with the specified request. @param request The HTTP request for the request. @param progress A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue. @param destination A block object to be executed in order to determine the destination of the downloaded file. This block takes two arguments, the target path & the server response, and returns the desired file URL of the resulting download. The temporary file used during the download will be automatically deleted after being moved to the returned URL. @param completionHandler A block to be executed when a task finishes. This block has no return value and takes three arguments: the server response, the path of the downloaded file, and the error describing the network or parsing error that occurred, if any. @warning If using a background `NSURLSessionConfiguration` on iOS, these blocks will be lost when the app is terminated. Background sessions may prefer to use `-setDownloadTaskDidFinishDownloadingBlock:` to specify the URL for saving the downloaded file, rather than the destination block of this method. */ - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request progress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler; /** Creates an `NSURLSessionDownloadTask` with the specified resume data. @param resumeData The data used to resume downloading. @param progress A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue. @param destination A block object to be executed in order to determine the destination of the downloaded file. This block takes two arguments, the target path & the server response, and returns the desired file URL of the resulting download. The temporary file used during the download will be automatically deleted after being moved to the returned URL. @param completionHandler A block to be executed when a task finishes. This block has no return value and takes three arguments: the server response, the path of the downloaded file, and the error describing the network or parsing error that occurred, if any. */ - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData progress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler; ///--------------------------------- /// @name Getting Progress for Tasks ///--------------------------------- /** Returns the upload progress of the specified task. @param task The session task. Must not be `nil`. @return An `NSProgress` object reporting the upload progress of a task, or `nil` if the progress is unavailable. */ - (nullable NSProgress *)uploadProgressForTask:(NSURLSessionTask *)task; /** Returns the download progress of the specified task. @param task The session task. Must not be `nil`. @return An `NSProgress` object reporting the download progress of a task, or `nil` if the progress is unavailable. */ - (nullable NSProgress *)downloadProgressForTask:(NSURLSessionTask *)task; ///----------------------------------------- /// @name Setting Session Delegate Callbacks ///----------------------------------------- /** Sets a block to be executed when the managed session becomes invalid, as handled by the `NSURLSessionDelegate` method `URLSession:didBecomeInvalidWithError:`. @param block A block object to be executed when the managed session becomes invalid. The block has no return value, and takes two arguments: the session, and the error related to the cause of invalidation. */ - (void)setSessionDidBecomeInvalidBlock:(nullable void (^)(NSURLSession *session, NSError *error))block; /** Sets a block to be executed when a connection level authentication challenge has occurred, as handled by the `NSURLSessionDelegate` method `URLSession:didReceiveChallenge:completionHandler:`. @param block A block object to be executed when a connection level authentication challenge has occurred. The block returns the disposition of the authentication challenge, and takes three arguments: the session, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge. */ - (void)setSessionDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block; ///-------------------------------------- /// @name Setting Task Delegate Callbacks ///-------------------------------------- /** Sets a block to be executed when a task requires a new request body stream to send to the remote server, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:needNewBodyStream:`. @param block A block object to be executed when a task requires a new request body stream. */ - (void)setTaskNeedNewBodyStreamBlock:(nullable NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block; /** Sets a block to be executed when an HTTP request is attempting to perform a redirection to a different URL, as handled by the `NSURLSessionTaskDelegate` method `URLSession:willPerformHTTPRedirection:newRequest:completionHandler:`. @param block A block object to be executed when an HTTP request is attempting to perform a redirection to a different URL. The block returns the request to be made for the redirection, and takes four arguments: the session, the task, the redirection response, and the request corresponding to the redirection response. */ - (void)setTaskWillPerformHTTPRedirectionBlock:(nullable NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block; /** Sets a block to be executed when a session task has received a request specific authentication challenge, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didReceiveChallenge:completionHandler:`. @param block A block object to be executed when a session task has received a request specific authentication challenge. The block returns the disposition of the authentication challenge, and takes four arguments: the session, the task, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge. */ - (void)setTaskDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block; /** Sets a block to be executed periodically to track upload progress, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:`. @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes five arguments: the session, the task, the number of bytes written since the last time the upload progress block was called, the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times, and will execute on the main thread. */ - (void)setTaskDidSendBodyDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block; /** Sets a block to be executed as the last message related to a specific task, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didCompleteWithError:`. @param block A block object to be executed when a session task is completed. The block has no return value, and takes three arguments: the session, the task, and any error that occurred in the process of executing the task. */ - (void)setTaskDidCompleteBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSError * _Nullable error))block; ///------------------------------------------- /// @name Setting Data Task Delegate Callbacks ///------------------------------------------- /** Sets a block to be executed when a data task has received a response, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didReceiveResponse:completionHandler:`. @param block A block object to be executed when a data task has received a response. The block returns the disposition of the session response, and takes three arguments: the session, the data task, and the received response. */ - (void)setDataTaskDidReceiveResponseBlock:(nullable NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block; /** Sets a block to be executed when a data task has become a download task, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didBecomeDownloadTask:`. @param block A block object to be executed when a data task has become a download task. The block has no return value, and takes three arguments: the session, the data task, and the download task it has become. */ - (void)setDataTaskDidBecomeDownloadTaskBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block; /** Sets a block to be executed when a data task receives data, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didReceiveData:`. @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the session, the data task, and the data received. This block may be called multiple times, and will execute on the session manager operation queue. */ - (void)setDataTaskDidReceiveDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block; /** Sets a block to be executed to determine the caching behavior of a data task, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:willCacheResponse:completionHandler:`. @param block A block object to be executed to determine the caching behavior of a data task. The block returns the response to cache, and takes three arguments: the session, the data task, and the proposed cached URL response. */ - (void)setDataTaskWillCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block; /** Sets a block to be executed once all messages enqueued for a session have been delivered, as handled by the `NSURLSessionDataDelegate` method `URLSessionDidFinishEventsForBackgroundURLSession:`. @param block A block object to be executed once all messages enqueued for a session have been delivered. The block has no return value and takes a single argument: the session. */ - (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block; ///----------------------------------------------- /// @name Setting Download Task Delegate Callbacks ///----------------------------------------------- /** Sets a block to be executed when a download task has completed a download, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didFinishDownloadingToURL:`. @param block A block object to be executed when a download task has completed. The block returns the URL the download should be moved to, and takes three arguments: the session, the download task, and the temporary location of the downloaded file. If the file manager encounters an error while attempting to move the temporary file to the destination, an `AFURLSessionDownloadTaskDidFailToMoveFileNotification` will be posted, with the download task as its object, and the user info of the error. */ - (void)setDownloadTaskDidFinishDownloadingBlock:(nullable NSURL * _Nullable (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block; /** Sets a block to be executed periodically to track download progress, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite:`. @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes five arguments: the session, the download task, the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the session manager operation queue. */ - (void)setDownloadTaskDidWriteDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block; /** Sets a block to be executed when a download task has been resumed, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:`. @param block A block object to be executed when a download task has been resumed. The block has no return value and takes four arguments: the session, the download task, the file offset of the resumed download, and the total number of bytes expected to be downloaded. */ - (void)setDownloadTaskDidResumeBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block; @end ///-------------------- /// @name Notifications ///-------------------- /** Posted when a task resumes. */ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification; /** Posted when a task finishes executing. Includes a userInfo dictionary with additional information about the task. */ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteNotification; /** Posted when a task suspends its execution. */ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidSuspendNotification; /** Posted when a session is invalidated. */ FOUNDATION_EXPORT NSString * const AFURLSessionDidInvalidateNotification; /** Posted when a session download task encountered an error when moving the temporary download file to a specified destination. */ FOUNDATION_EXPORT NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification; /** The raw response data of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if response data exists for the task. */ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseDataKey; /** The serialized response object of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if the response was serialized. */ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey; /** The response serializer used to serialize the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if the task has an associated response serializer. */ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey; /** The file path associated with the download task. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if an the response data has been stored directly to disk. */ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteAssetPathKey; /** Any error associated with the task, or the serialization of the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if an error exists. */ FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteErrorKey; NS_ASSUME_NONNULL_END ================================================ FILE: Pods/AFNetworking/AFNetworking/AFURLSessionManager.m ================================================ // AFURLSessionManager.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "AFURLSessionManager.h" #import #ifndef NSFoundationVersionNumber_iOS_8_0 #define NSFoundationVersionNumber_With_Fixed_5871104061079552_bug 1140.11 #else #define NSFoundationVersionNumber_With_Fixed_5871104061079552_bug NSFoundationVersionNumber_iOS_8_0 #endif static dispatch_queue_t url_session_manager_creation_queue() { static dispatch_queue_t af_url_session_manager_creation_queue; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ af_url_session_manager_creation_queue = dispatch_queue_create("com.alamofire.networking.session.manager.creation", DISPATCH_QUEUE_SERIAL); }); return af_url_session_manager_creation_queue; } static void url_session_manager_create_task_safely(dispatch_block_t block) { if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) { // Fix of bug // Open Radar:http://openradar.appspot.com/radar?id=5871104061079552 (status: Fixed in iOS8) // Issue about:https://github.com/AFNetworking/AFNetworking/issues/2093 dispatch_sync(url_session_manager_creation_queue(), block); } else { block(); } } static dispatch_queue_t url_session_manager_processing_queue() { static dispatch_queue_t af_url_session_manager_processing_queue; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ af_url_session_manager_processing_queue = dispatch_queue_create("com.alamofire.networking.session.manager.processing", DISPATCH_QUEUE_CONCURRENT); }); return af_url_session_manager_processing_queue; } static dispatch_group_t url_session_manager_completion_group() { static dispatch_group_t af_url_session_manager_completion_group; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ af_url_session_manager_completion_group = dispatch_group_create(); }); return af_url_session_manager_completion_group; } NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume"; NSString * const AFNetworkingTaskDidCompleteNotification = @"com.alamofire.networking.task.complete"; NSString * const AFNetworkingTaskDidSuspendNotification = @"com.alamofire.networking.task.suspend"; NSString * const AFURLSessionDidInvalidateNotification = @"com.alamofire.networking.session.invalidate"; NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification = @"com.alamofire.networking.session.download.file-manager-error"; NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey = @"com.alamofire.networking.task.complete.serializedresponse"; NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey = @"com.alamofire.networking.task.complete.responseserializer"; NSString * const AFNetworkingTaskDidCompleteResponseDataKey = @"com.alamofire.networking.complete.finish.responsedata"; NSString * const AFNetworkingTaskDidCompleteErrorKey = @"com.alamofire.networking.task.complete.error"; NSString * const AFNetworkingTaskDidCompleteAssetPathKey = @"com.alamofire.networking.task.complete.assetpath"; static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock"; static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3; static void * AFTaskStateChangedContext = &AFTaskStateChangedContext; typedef void (^AFURLSessionDidBecomeInvalidBlock)(NSURLSession *session, NSError *error); typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential); typedef NSURLRequest * (^AFURLSessionTaskWillPerformHTTPRedirectionBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request); typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionTaskDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential); typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSession *session); typedef NSInputStream * (^AFURLSessionTaskNeedNewBodyStreamBlock)(NSURLSession *session, NSURLSessionTask *task); typedef void (^AFURLSessionTaskDidSendBodyDataBlock)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend); typedef void (^AFURLSessionTaskDidCompleteBlock)(NSURLSession *session, NSURLSessionTask *task, NSError *error); typedef NSURLSessionResponseDisposition (^AFURLSessionDataTaskDidReceiveResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response); typedef void (^AFURLSessionDataTaskDidBecomeDownloadTaskBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask); typedef void (^AFURLSessionDataTaskDidReceiveDataBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data); typedef NSCachedURLResponse * (^AFURLSessionDataTaskWillCacheResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse); typedef NSURL * (^AFURLSessionDownloadTaskDidFinishDownloadingBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location); typedef void (^AFURLSessionDownloadTaskDidWriteDataBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite); typedef void (^AFURLSessionDownloadTaskDidResumeBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes); typedef void (^AFURLSessionTaskProgressBlock)(NSProgress *); typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id responseObject, NSError *error); #pragma mark - @interface AFURLSessionManagerTaskDelegate : NSObject @property (nonatomic, weak) AFURLSessionManager *manager; @property (nonatomic, strong) NSMutableData *mutableData; @property (nonatomic, strong) NSProgress *uploadProgress; @property (nonatomic, strong) NSProgress *downloadProgress; @property (nonatomic, copy) NSURL *downloadFileURL; @property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading; @property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock; @property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock; @property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler; @end @implementation AFURLSessionManagerTaskDelegate - (instancetype)init { self = [super init]; if (!self) { return nil; } self.mutableData = [NSMutableData data]; self.uploadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil]; self.uploadProgress.totalUnitCount = NSURLSessionTransferSizeUnknown; self.downloadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil]; self.downloadProgress.totalUnitCount = NSURLSessionTransferSizeUnknown; return self; } #pragma mark - NSProgress Tracking - (void)setupProgressForTask:(NSURLSessionTask *)task { __weak __typeof__(task) weakTask = task; self.uploadProgress.totalUnitCount = task.countOfBytesExpectedToSend; self.downloadProgress.totalUnitCount = task.countOfBytesExpectedToReceive; [self.uploadProgress setCancellable:YES]; [self.uploadProgress setCancellationHandler:^{ __typeof__(weakTask) strongTask = weakTask; [strongTask cancel]; }]; [self.uploadProgress setPausable:YES]; [self.uploadProgress setPausingHandler:^{ __typeof__(weakTask) strongTask = weakTask; [strongTask suspend]; }]; if ([self.uploadProgress respondsToSelector:@selector(setResumingHandler:)]) { [self.uploadProgress setResumingHandler:^{ __typeof__(weakTask) strongTask = weakTask; [strongTask resume]; }]; } [self.downloadProgress setCancellable:YES]; [self.downloadProgress setCancellationHandler:^{ __typeof__(weakTask) strongTask = weakTask; [strongTask cancel]; }]; [self.downloadProgress setPausable:YES]; [self.downloadProgress setPausingHandler:^{ __typeof__(weakTask) strongTask = weakTask; [strongTask suspend]; }]; if ([self.downloadProgress respondsToSelector:@selector(setResumingHandler:)]) { [self.downloadProgress setResumingHandler:^{ __typeof__(weakTask) strongTask = weakTask; [strongTask resume]; }]; } [task addObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived)) options:NSKeyValueObservingOptionNew context:NULL]; [task addObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToReceive)) options:NSKeyValueObservingOptionNew context:NULL]; [task addObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent)) options:NSKeyValueObservingOptionNew context:NULL]; [task addObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToSend)) options:NSKeyValueObservingOptionNew context:NULL]; [self.downloadProgress addObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted)) options:NSKeyValueObservingOptionNew context:NULL]; [self.uploadProgress addObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted)) options:NSKeyValueObservingOptionNew context:NULL]; } - (void)cleanUpProgressForTask:(NSURLSessionTask *)task { [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))]; [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))]; [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))]; [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToSend))]; [self.downloadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))]; [self.uploadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([object isKindOfClass:[NSURLSessionTask class]]) { if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) { self.downloadProgress.completedUnitCount = [change[@"new"] longLongValue]; } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))]) { self.downloadProgress.totalUnitCount = [change[@"new"] longLongValue]; } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) { self.uploadProgress.completedUnitCount = [change[@"new"] longLongValue]; } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesExpectedToSend))]) { self.uploadProgress.totalUnitCount = [change[@"new"] longLongValue]; } } else if ([object isEqual:self.downloadProgress]) { if (self.downloadProgressBlock) { self.downloadProgressBlock(object); } } else if ([object isEqual:self.uploadProgress]) { if (self.uploadProgressBlock) { self.uploadProgressBlock(object); } } } #pragma mark - NSURLSessionTaskDelegate - (void)URLSession:(__unused NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" __strong AFURLSessionManager *manager = self.manager; __block id responseObject = nil; __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer; //Performance Improvement from #2672 NSData *data = nil; if (self.mutableData) { data = [self.mutableData copy]; //We no longer need the reference, so nil it out to gain back some memory. self.mutableData = nil; } if (self.downloadFileURL) { userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL; } else if (data) { userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data; } if (error) { userInfo[AFNetworkingTaskDidCompleteErrorKey] = error; dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{ if (self.completionHandler) { self.completionHandler(task.response, responseObject, error); } dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo]; }); }); } else { dispatch_async(url_session_manager_processing_queue(), ^{ NSError *serializationError = nil; responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError]; if (self.downloadFileURL) { responseObject = self.downloadFileURL; } if (responseObject) { userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject; } if (serializationError) { userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError; } dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{ if (self.completionHandler) { self.completionHandler(task.response, responseObject, serializationError); } dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo]; }); }); }); } #pragma clang diagnostic pop } #pragma mark - NSURLSessionDataTaskDelegate - (void)URLSession:(__unused NSURLSession *)session dataTask:(__unused NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { [self.mutableData appendData:data]; } #pragma mark - NSURLSessionDownloadTaskDelegate - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSError *fileManagerError = nil; self.downloadFileURL = nil; if (self.downloadTaskDidFinishDownloading) { self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location); if (self.downloadFileURL) { [[NSFileManager defaultManager] moveItemAtURL:location toURL:self.downloadFileURL error:&fileManagerError]; if (fileManagerError) { [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:fileManagerError.userInfo]; } } } } @end #pragma mark - /** * A workaround for issues related to key-value observing the `state` of an `NSURLSessionTask`. * * See: * - https://github.com/AFNetworking/AFNetworking/issues/1477 * - https://github.com/AFNetworking/AFNetworking/issues/2638 * - https://github.com/AFNetworking/AFNetworking/pull/2702 */ static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) { Method originalMethod = class_getInstanceMethod(theClass, originalSelector); Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector); method_exchangeImplementations(originalMethod, swizzledMethod); } static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) { return class_addMethod(theClass, selector, method_getImplementation(method), method_getTypeEncoding(method)); } static NSString * const AFNSURLSessionTaskDidResumeNotification = @"com.alamofire.networking.nsurlsessiontask.resume"; static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofire.networking.nsurlsessiontask.suspend"; @interface _AFURLSessionTaskSwizzling : NSObject @end @implementation _AFURLSessionTaskSwizzling + (void)load { /** WARNING: Trouble Ahead https://github.com/AFNetworking/AFNetworking/pull/2702 */ if (NSClassFromString(@"NSURLSessionTask")) { /** iOS 7 and iOS 8 differ in NSURLSessionTask implementation, which makes the next bit of code a bit tricky. Many Unit Tests have been built to validate as much of this behavior has possible. Here is what we know: - NSURLSessionTasks are implemented with class clusters, meaning the class you request from the API isn't actually the type of class you will get back. - Simply referencing `[NSURLSessionTask class]` will not work. You need to ask an `NSURLSession` to actually create an object, and grab the class from there. - On iOS 7, `localDataTask` is a `__NSCFLocalDataTask`, which inherits from `__NSCFLocalSessionTask`, which inherits from `__NSCFURLSessionTask`. - On iOS 8, `localDataTask` is a `__NSCFLocalDataTask`, which inherits from `__NSCFLocalSessionTask`, which inherits from `NSURLSessionTask`. - On iOS 7, `__NSCFLocalSessionTask` and `__NSCFURLSessionTask` are the only two classes that have their own implementations of `resume` and `suspend`, and `__NSCFLocalSessionTask` DOES NOT CALL SUPER. This means both classes need to be swizzled. - On iOS 8, `NSURLSessionTask` is the only class that implements `resume` and `suspend`. This means this is the only class that needs to be swizzled. - Because `NSURLSessionTask` is not involved in the class hierarchy for every version of iOS, its easier to add the swizzled methods to a dummy class and manage them there. Some Assumptions: - No implementations of `resume` or `suspend` call super. If this were to change in a future version of iOS, we'd need to handle it. - No background task classes override `resume` or `suspend` The current solution: 1) Grab an instance of `__NSCFLocalDataTask` by asking an instance of `NSURLSession` for a data task. 2) Grab a pointer to the original implementation of `af_resume` 3) Check to see if the current class has an implementation of resume. If so, continue to step 4. 4) Grab the super class of the current class. 5) Grab a pointer for the current class to the current implementation of `resume`. 6) Grab a pointer for the super class to the current implementation of `resume`. 7) If the current class implementation of `resume` is not equal to the super class implementation of `resume` AND the current implementation of `resume` is not equal to the original implementation of `af_resume`, THEN swizzle the methods 8) Set the current class to the super class, and repeat steps 3-8 */ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; NSURLSession * session = [NSURLSession sessionWithConfiguration:configuration]; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnonnull" NSURLSessionDataTask *localDataTask = [session dataTaskWithURL:nil]; #pragma clang diagnostic pop IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self class], @selector(af_resume))); Class currentClass = [localDataTask class]; while (class_getInstanceMethod(currentClass, @selector(resume))) { Class superClass = [currentClass superclass]; IMP classResumeIMP = method_getImplementation(class_getInstanceMethod(currentClass, @selector(resume))); IMP superclassResumeIMP = method_getImplementation(class_getInstanceMethod(superClass, @selector(resume))); if (classResumeIMP != superclassResumeIMP && originalAFResumeIMP != classResumeIMP) { [self swizzleResumeAndSuspendMethodForClass:currentClass]; } currentClass = [currentClass superclass]; } [localDataTask cancel]; [session finishTasksAndInvalidate]; } } + (void)swizzleResumeAndSuspendMethodForClass:(Class)theClass { Method afResumeMethod = class_getInstanceMethod(self, @selector(af_resume)); Method afSuspendMethod = class_getInstanceMethod(self, @selector(af_suspend)); if (af_addMethod(theClass, @selector(af_resume), afResumeMethod)) { af_swizzleSelector(theClass, @selector(resume), @selector(af_resume)); } if (af_addMethod(theClass, @selector(af_suspend), afSuspendMethod)) { af_swizzleSelector(theClass, @selector(suspend), @selector(af_suspend)); } } - (NSURLSessionTaskState)state { NSAssert(NO, @"State method should never be called in the actual dummy class"); return NSURLSessionTaskStateCanceling; } - (void)af_resume { NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state"); NSURLSessionTaskState state = [self state]; [self af_resume]; if (state != NSURLSessionTaskStateRunning) { [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidResumeNotification object:self]; } } - (void)af_suspend { NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state"); NSURLSessionTaskState state = [self state]; [self af_suspend]; if (state != NSURLSessionTaskStateSuspended) { [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidSuspendNotification object:self]; } } @end #pragma mark - @interface AFURLSessionManager () @property (readwrite, nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration; @property (readwrite, nonatomic, strong) NSOperationQueue *operationQueue; @property (readwrite, nonatomic, strong) NSURLSession *session; @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier; @property (readonly, nonatomic, copy) NSString *taskDescriptionForSessionTasks; @property (readwrite, nonatomic, strong) NSLock *lock; @property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid; @property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge; @property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession; @property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection; @property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge; @property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream; @property (readwrite, nonatomic, copy) AFURLSessionTaskDidSendBodyDataBlock taskDidSendBodyData; @property (readwrite, nonatomic, copy) AFURLSessionTaskDidCompleteBlock taskDidComplete; @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveResponseBlock dataTaskDidReceiveResponse; @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask; @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData; @property (readwrite, nonatomic, copy) AFURLSessionDataTaskWillCacheResponseBlock dataTaskWillCacheResponse; @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading; @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidWriteDataBlock downloadTaskDidWriteData; @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidResumeBlock downloadTaskDidResume; @end @implementation AFURLSessionManager - (instancetype)init { return [self initWithSessionConfiguration:nil]; } - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration { self = [super init]; if (!self) { return nil; } if (!configuration) { configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; } self.sessionConfiguration = configuration; self.operationQueue = [[NSOperationQueue alloc] init]; self.operationQueue.maxConcurrentOperationCount = 1; self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue]; self.responseSerializer = [AFJSONResponseSerializer serializer]; self.securityPolicy = [AFSecurityPolicy defaultPolicy]; #if !TARGET_OS_WATCH self.reachabilityManager = [AFNetworkReachabilityManager sharedManager]; #endif self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init]; self.lock = [[NSLock alloc] init]; self.lock.name = AFURLSessionManagerLockName; [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { for (NSURLSessionDataTask *task in dataTasks) { [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil]; } for (NSURLSessionUploadTask *uploadTask in uploadTasks) { [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil]; } for (NSURLSessionDownloadTask *downloadTask in downloadTasks) { [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil]; } }]; return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - - (NSString *)taskDescriptionForSessionTasks { return [NSString stringWithFormat:@"%p", self]; } - (void)taskDidResume:(NSNotification *)notification { NSURLSessionTask *task = notification.object; if ([task respondsToSelector:@selector(taskDescription)]) { if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidResumeNotification object:task]; }); } } } - (void)taskDidSuspend:(NSNotification *)notification { NSURLSessionTask *task = notification.object; if ([task respondsToSelector:@selector(taskDescription)]) { if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidSuspendNotification object:task]; }); } } } #pragma mark - - (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task { NSParameterAssert(task); AFURLSessionManagerTaskDelegate *delegate = nil; [self.lock lock]; delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)]; [self.lock unlock]; return delegate; } - (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate forTask:(NSURLSessionTask *)task { NSParameterAssert(task); NSParameterAssert(delegate); [self.lock lock]; self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate; [delegate setupProgressForTask:task]; [self addNotificationObserverForTask:task]; [self.lock unlock]; } - (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init]; delegate.manager = self; delegate.completionHandler = completionHandler; dataTask.taskDescription = self.taskDescriptionForSessionTasks; [self setDelegate:delegate forTask:dataTask]; delegate.uploadProgressBlock = uploadProgressBlock; delegate.downloadProgressBlock = downloadProgressBlock; } - (void)addDelegateForUploadTask:(NSURLSessionUploadTask *)uploadTask progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init]; delegate.manager = self; delegate.completionHandler = completionHandler; uploadTask.taskDescription = self.taskDescriptionForSessionTasks; [self setDelegate:delegate forTask:uploadTask]; delegate.uploadProgressBlock = uploadProgressBlock; } - (void)addDelegateForDownloadTask:(NSURLSessionDownloadTask *)downloadTask progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler { AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init]; delegate.manager = self; delegate.completionHandler = completionHandler; if (destination) { delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) { return destination(location, task.response); }; } downloadTask.taskDescription = self.taskDescriptionForSessionTasks; [self setDelegate:delegate forTask:downloadTask]; delegate.downloadProgressBlock = downloadProgressBlock; } - (void)removeDelegateForTask:(NSURLSessionTask *)task { NSParameterAssert(task); AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task]; [self.lock lock]; [delegate cleanUpProgressForTask:task]; [self removeNotificationObserverForTask:task]; [self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)]; [self.lock unlock]; } #pragma mark - - (NSArray *)tasksForKeyPath:(NSString *)keyPath { __block NSArray *tasks = nil; dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { if ([keyPath isEqualToString:NSStringFromSelector(@selector(dataTasks))]) { tasks = dataTasks; } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(uploadTasks))]) { tasks = uploadTasks; } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(downloadTasks))]) { tasks = downloadTasks; } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(tasks))]) { tasks = [@[dataTasks, uploadTasks, downloadTasks] valueForKeyPath:@"@unionOfArrays.self"]; } dispatch_semaphore_signal(semaphore); }]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); return tasks; } - (NSArray *)tasks { return [self tasksForKeyPath:NSStringFromSelector(_cmd)]; } - (NSArray *)dataTasks { return [self tasksForKeyPath:NSStringFromSelector(_cmd)]; } - (NSArray *)uploadTasks { return [self tasksForKeyPath:NSStringFromSelector(_cmd)]; } - (NSArray *)downloadTasks { return [self tasksForKeyPath:NSStringFromSelector(_cmd)]; } #pragma mark - - (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks { dispatch_async(dispatch_get_main_queue(), ^{ if (cancelPendingTasks) { [self.session invalidateAndCancel]; } else { [self.session finishTasksAndInvalidate]; } }); } #pragma mark - - (void)setResponseSerializer:(id )responseSerializer { NSParameterAssert(responseSerializer); _responseSerializer = responseSerializer; } #pragma mark - - (void)addNotificationObserverForTask:(NSURLSessionTask *)task { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidResume:) name:AFNSURLSessionTaskDidResumeNotification object:task]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidSuspend:) name:AFNSURLSessionTaskDidSuspendNotification object:task]; } - (void)removeNotificationObserverForTask:(NSURLSessionTask *)task { [[NSNotificationCenter defaultCenter] removeObserver:self name:AFNSURLSessionTaskDidSuspendNotification object:task]; [[NSNotificationCenter defaultCenter] removeObserver:self name:AFNSURLSessionTaskDidResumeNotification object:task]; } #pragma mark - - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { return [self dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:completionHandler]; } - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler { __block NSURLSessionDataTask *dataTask = nil; url_session_manager_create_task_safely(^{ dataTask = [self.session dataTaskWithRequest:request]; }); [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler]; return dataTask; } #pragma mark - - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { __block NSURLSessionUploadTask *uploadTask = nil; url_session_manager_create_task_safely(^{ uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL]; }); if (!uploadTask && self.attemptsToRecreateUploadTasksForBackgroundSessions && self.session.configuration.identifier) { for (NSUInteger attempts = 0; !uploadTask && attempts < AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask; attempts++) { uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL]; } } [self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler]; return uploadTask; } - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { __block NSURLSessionUploadTask *uploadTask = nil; url_session_manager_create_task_safely(^{ uploadTask = [self.session uploadTaskWithRequest:request fromData:bodyData]; }); [self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler]; return uploadTask; } - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { __block NSURLSessionUploadTask *uploadTask = nil; url_session_manager_create_task_safely(^{ uploadTask = [self.session uploadTaskWithStreamedRequest:request]; }); [self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler]; return uploadTask; } #pragma mark - - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler { __block NSURLSessionDownloadTask *downloadTask = nil; url_session_manager_create_task_safely(^{ downloadTask = [self.session downloadTaskWithRequest:request]; }); [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler]; return downloadTask; } - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler { __block NSURLSessionDownloadTask *downloadTask = nil; url_session_manager_create_task_safely(^{ downloadTask = [self.session downloadTaskWithResumeData:resumeData]; }); [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler]; return downloadTask; } #pragma mark - - (NSProgress *)uploadProgressForTask:(NSURLSessionTask *)task { return [[self delegateForTask:task] uploadProgress]; } - (NSProgress *)downloadProgressForTask:(NSURLSessionTask *)task { return [[self delegateForTask:task] downloadProgress]; } #pragma mark - - (void)setSessionDidBecomeInvalidBlock:(void (^)(NSURLSession *session, NSError *error))block { self.sessionDidBecomeInvalid = block; } - (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block { self.sessionDidReceiveAuthenticationChallenge = block; } - (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block { self.didFinishEventsForBackgroundURLSession = block; } #pragma mark - - (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block { self.taskNeedNewBodyStream = block; } - (void)setTaskWillPerformHTTPRedirectionBlock:(NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block { self.taskWillPerformHTTPRedirection = block; } - (void)setTaskDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block { self.taskDidReceiveAuthenticationChallenge = block; } - (void)setTaskDidSendBodyDataBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block { self.taskDidSendBodyData = block; } - (void)setTaskDidCompleteBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, NSError *error))block { self.taskDidComplete = block; } #pragma mark - - (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block { self.dataTaskDidReceiveResponse = block; } - (void)setDataTaskDidBecomeDownloadTaskBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block { self.dataTaskDidBecomeDownloadTask = block; } - (void)setDataTaskDidReceiveDataBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block { self.dataTaskDidReceiveData = block; } - (void)setDataTaskWillCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block { self.dataTaskWillCacheResponse = block; } #pragma mark - - (void)setDownloadTaskDidFinishDownloadingBlock:(NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block { self.downloadTaskDidFinishDownloading = block; } - (void)setDownloadTaskDidWriteDataBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block { self.downloadTaskDidWriteData = block; } - (void)setDownloadTaskDidResumeBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block { self.downloadTaskDidResume = block; } #pragma mark - NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, self.session, self.operationQueue]; } - (BOOL)respondsToSelector:(SEL)selector { if (selector == @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)) { return self.taskWillPerformHTTPRedirection != nil; } else if (selector == @selector(URLSession:dataTask:didReceiveResponse:completionHandler:)) { return self.dataTaskDidReceiveResponse != nil; } else if (selector == @selector(URLSession:dataTask:willCacheResponse:completionHandler:)) { return self.dataTaskWillCacheResponse != nil; } else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) { return self.didFinishEventsForBackgroundURLSession != nil; } return [[self class] instancesRespondToSelector:selector]; } #pragma mark - NSURLSessionDelegate - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error { if (self.sessionDidBecomeInvalid) { self.sessionDidBecomeInvalid(session, error); } [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDidInvalidateNotification object:session]; } - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling; __block NSURLCredential *credential = nil; if (self.sessionDidReceiveAuthenticationChallenge) { disposition = self.sessionDidReceiveAuthenticationChallenge(session, challenge, &credential); } else { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) { credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; if (credential) { disposition = NSURLSessionAuthChallengeUseCredential; } else { disposition = NSURLSessionAuthChallengePerformDefaultHandling; } } else { disposition = NSURLSessionAuthChallengeRejectProtectionSpace; } } else { disposition = NSURLSessionAuthChallengePerformDefaultHandling; } } if (completionHandler) { completionHandler(disposition, credential); } } #pragma mark - NSURLSessionTaskDelegate - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler { NSURLRequest *redirectRequest = request; if (self.taskWillPerformHTTPRedirection) { redirectRequest = self.taskWillPerformHTTPRedirection(session, task, response, request); } if (completionHandler) { completionHandler(redirectRequest); } } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling; __block NSURLCredential *credential = nil; if (self.taskDidReceiveAuthenticationChallenge) { disposition = self.taskDidReceiveAuthenticationChallenge(session, task, challenge, &credential); } else { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) { disposition = NSURLSessionAuthChallengeUseCredential; credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; } else { disposition = NSURLSessionAuthChallengeRejectProtectionSpace; } } else { disposition = NSURLSessionAuthChallengePerformDefaultHandling; } } if (completionHandler) { completionHandler(disposition, credential); } } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler { NSInputStream *inputStream = nil; if (self.taskNeedNewBodyStream) { inputStream = self.taskNeedNewBodyStream(session, task); } else if (task.originalRequest.HTTPBodyStream && [task.originalRequest.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) { inputStream = [task.originalRequest.HTTPBodyStream copy]; } if (completionHandler) { completionHandler(inputStream); } } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { int64_t totalUnitCount = totalBytesExpectedToSend; if(totalUnitCount == NSURLSessionTransferSizeUnknown) { NSString *contentLength = [task.originalRequest valueForHTTPHeaderField:@"Content-Length"]; if(contentLength) { totalUnitCount = (int64_t) [contentLength longLongValue]; } } if (self.taskDidSendBodyData) { self.taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalUnitCount); } } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task]; // delegate may be nil when completing a task in the background if (delegate) { [delegate URLSession:session task:task didCompleteWithError:error]; [self removeDelegateForTask:task]; } if (self.taskDidComplete) { self.taskDidComplete(session, task, error); } } #pragma mark - NSURLSessionDataDelegate - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow; if (self.dataTaskDidReceiveResponse) { disposition = self.dataTaskDidReceiveResponse(session, dataTask, response); } if (completionHandler) { completionHandler(disposition); } } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask { AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask]; if (delegate) { [self removeDelegateForTask:dataTask]; [self setDelegate:delegate forTask:downloadTask]; } if (self.dataTaskDidBecomeDownloadTask) { self.dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask); } } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask]; [delegate URLSession:session dataTask:dataTask didReceiveData:data]; if (self.dataTaskDidReceiveData) { self.dataTaskDidReceiveData(session, dataTask, data); } } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler { NSCachedURLResponse *cachedResponse = proposedResponse; if (self.dataTaskWillCacheResponse) { cachedResponse = self.dataTaskWillCacheResponse(session, dataTask, proposedResponse); } if (completionHandler) { completionHandler(cachedResponse); } } - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { if (self.didFinishEventsForBackgroundURLSession) { dispatch_async(dispatch_get_main_queue(), ^{ self.didFinishEventsForBackgroundURLSession(session); }); } } #pragma mark - NSURLSessionDownloadDelegate - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask]; if (self.downloadTaskDidFinishDownloading) { NSURL *fileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location); if (fileURL) { delegate.downloadFileURL = fileURL; NSError *error = nil; [[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error]; if (error) { [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo]; } return; } } if (delegate) { [delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location]; } } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { if (self.downloadTaskDidWriteData) { self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); } } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { if (self.downloadTaskDidResume) { self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes); } } #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; } - (instancetype)initWithCoder:(NSCoder *)decoder { NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"]; self = [self initWithSessionConfiguration:configuration]; if (!self) { return nil; } return self; } - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { return [[[self class] allocWithZone:zone] initWithSessionConfiguration:self.session.configuration]; } @end ================================================ FILE: Pods/AFNetworking/LICENSE ================================================ Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/AFNetworking/README.md ================================================

AFNetworking

[![Build Status](https://travis-ci.org/AFNetworking/AFNetworking.svg)](https://travis-ci.org/AFNetworking/AFNetworking) [![codecov.io](https://codecov.io/github/AFNetworking/AFNetworking/coverage.svg?branch=master)](https://codecov.io/github/AFNetworking/AFNetworking?branch=master) [![Cocoapods Compatible](https://img.shields.io/cocoapods/v/AFNetworking.svg)](https://img.shields.io/cocoapods/v/AFNetworking.svg) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Platform](https://img.shields.io/cocoapods/p/AFNetworking.svg?style=flat)](http://cocoadocs.org/docsets/AFNetworking) [![Twitter](https://img.shields.io/badge/twitter-@AFNetworking-blue.svg?style=flat)](http://twitter.com/AFNetworking) AFNetworking is a delightful networking library for iOS and Mac OS X. It's built on top of the [Foundation URL Loading System](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html), extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use. Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac. Choose AFNetworking for your next project, or migrate over your existing projects—you'll be happy you did! ## How To Get Started - [Download AFNetworking](https://github.com/AFNetworking/AFNetworking/archive/master.zip) and try out the included Mac and iPhone example apps - Read the ["Getting Started" guide](https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking), [FAQ](https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ), or [other articles on the Wiki](https://github.com/AFNetworking/AFNetworking/wiki) - Check out the [documentation](http://cocoadocs.org/docsets/AFNetworking/) for a comprehensive look at all of the APIs available in AFNetworking - Read the [AFNetworking 3.0 Migration Guide](https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-3.0-Migration-Guide) for an overview of the architectural changes from 2.0. ## Communication - If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/afnetworking). (Tag 'afnetworking') - If you'd like to **ask a general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/afnetworking). - If you **found a bug**, _and can provide steps to reliably reproduce it_, open an issue. - If you **have a feature request**, open an issue. - If you **want to contribute**, submit a pull request. ## Installation AFNetworking supports multiple methods for installing the library in a project. ## Installation with CocoaPods [CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like AFNetworking in your projects. See the ["Getting Started" guide for more information](https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking). You can install it with the following command: ```bash $ gem install cocoapods ``` > CocoaPods 0.39.0+ is required to build AFNetworking 3.0.0+. #### Podfile To integrate AFNetworking into your Xcode project using CocoaPods, specify it in your `Podfile`: ```ruby source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' pod 'AFNetworking', '~> 3.0' ``` Then, run the following command: ```bash $ pod install ``` ### Installation with Carthage [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. You can install Carthage with [Homebrew](http://brew.sh/) using the following command: ```bash $ brew update $ brew install carthage ``` To integrate AFNetworking into your Xcode project using Carthage, specify it in your `Cartfile`: ```ogdl github "AFNetworking/AFNetworking" ~> 3.0 ``` Run `carthage` to build the framework and drag the built `AFNetworking.framework` into your Xcode project. ## Requirements | AFNetworking Version | Minimum iOS Target | Minimum OS X Target | Minimum watchOS Target | Minimum tvOS Target | Notes | |:--------------------:|:---------------------------:|:----------------------------:|:----------------------------:|:----------------------------:|:-------------------------------------------------------------------------:| | 3.x | iOS 7 | OS X 10.9 | watchOS 2.0 | tvOS 9.0 | Xcode 7+ is required. `NSURLConnectionOperation` support has been removed. | | 2.6 -> 2.6.3 | iOS 7 | OS X 10.9 | watchOS 2.0 | n/a | Xcode 7+ is required. | | 2.0 -> 2.5.4 | iOS 6 | OS X 10.8 | n/a | n/a | Xcode 5+ is required. `NSURLSession` subspec requires iOS 7 or OS X 10.9. | | 1.x | iOS 5 | Mac OS X 10.7 | n/a | n/a | | 0.10.x | iOS 4 | Mac OS X 10.6 | n/a | n/a | (OS X projects must support [64-bit with modern Cocoa runtime](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html)). > Programming in Swift? Try [Alamofire](https://github.com/Alamofire/Alamofire) for a more conventional set of APIs. ## Architecture ### NSURLSession - `AFURLSessionManager` - `AFHTTPSessionManager` ### Serialization * `` - `AFHTTPRequestSerializer` - `AFJSONRequestSerializer` - `AFPropertyListRequestSerializer` * `` - `AFHTTPResponseSerializer` - `AFJSONResponseSerializer` - `AFXMLParserResponseSerializer` - `AFXMLDocumentResponseSerializer` _(Mac OS X)_ - `AFPropertyListResponseSerializer` - `AFImageResponseSerializer` - `AFCompoundResponseSerializer` ### Additional Functionality - `AFSecurityPolicy` - `AFNetworkReachabilityManager` ## Usage ### AFURLSessionManager `AFURLSessionManager` creates and manages an `NSURLSession` object based on a specified `NSURLSessionConfiguration` object, which conforms to ``, ``, ``, and ``. #### Creating a Download Task ```objective-c NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]]; } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { NSLog(@"File downloaded to: %@", filePath); }]; [downloadTask resume]; ``` #### Creating an Upload Task ```objective-c NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"]; NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { if (error) { NSLog(@"Error: %@", error); } else { NSLog(@"Success: %@ %@", response, responseObject); } }]; [uploadTask resume]; ``` #### Creating an Upload Task for a Multi-Part Request, with Progress ```objective-c NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id formData) { [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil]; } error:nil]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; NSURLSessionUploadTask *uploadTask; uploadTask = [manager uploadTaskWithStreamedRequest:request progress:^(NSProgress * _Nonnull uploadProgress) { // This is not called back on the main queue. // You are responsible for dispatching to the main queue for UI updates dispatch_async(dispatch_get_main_queue(), ^{ //Update the progress view [progressView setProgress:uploadProgress.fractionCompleted]; }); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error) { NSLog(@"Error: %@", error); } else { NSLog(@"%@ %@", response, responseObject); } }]; [uploadTask resume]; ``` #### Creating a Data Task ```objective-c NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { if (error) { NSLog(@"Error: %@", error); } else { NSLog(@"%@ %@", response, responseObject); } }]; [dataTask resume]; ``` --- ### Request Serialization Request serializers create requests from URL strings, encoding parameters as either a query string or HTTP body. ```objective-c NSString *URLString = @"http://example.com"; NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]}; ``` #### Query String Parameter Encoding ```objective-c [[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:URLString parameters:parameters error:nil]; ``` GET http://example.com?foo=bar&baz[]=1&baz[]=2&baz[]=3 #### URL Form Parameter Encoding ```objective-c [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters]; ``` POST http://example.com/ Content-Type: application/x-www-form-urlencoded foo=bar&baz[]=1&baz[]=2&baz[]=3 #### JSON Parameter Encoding ```objective-c [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters]; ``` POST http://example.com/ Content-Type: application/json {"foo": "bar", "baz": [1,2,3]} --- ### Network Reachability Manager `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. * Do not use Reachability to determine if the original request should be sent. * You should try to send it. * You can use Reachability to determine when a request should be automatically retried. * Although it may still fail, a Reachability notification that the connectivity is available is a good time to retry something. * Network reachability is a useful tool for determining why a request might have failed. * After a network request has failed, telling the user they're offline is better than giving them a more technical but accurate error, such as "request timed out." See also [WWDC 2012 session 706, "Networking Best Practices."](https://developer.apple.com/videos/play/wwdc2012-706/). #### Shared Network Reachability ```objective-c [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status)); }]; [[AFNetworkReachabilityManager sharedManager] startMonitoring]; ``` --- ### Security Policy `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. #### Allowing Invalid SSL Certificates ```objective-c AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.securityPolicy.allowInvalidCertificates = YES; // not recommended for production ``` --- ## Unit Tests AFNetworking includes a suite of unit tests within the Tests subdirectory. These tests can be run simply be executed the test action on the platform framework you would like to test. ## Credits AFNetworking is owned and maintained by the [Alamofire Software Foundation](http://alamofire.org). AFNetworking was originally created by [Scott Raymond](https://github.com/sco/) and [Mattt Thompson](https://github.com/mattt/) in the development of [Gowalla for iPhone](http://en.wikipedia.org/wiki/Gowalla). AFNetworking's logo was designed by [Alan Defibaugh](http://www.alandefibaugh.com/). And most of all, thanks to AFNetworking's [growing list of contributors](https://github.com/AFNetworking/AFNetworking/contributors). ### Security Disclosure If you believe you have identified a security vulnerability with AFNetworking, you should report it as soon as possible via email to security@alamofire.org. Please do not post it to a public issue tracker. ## License AFNetworking is released under the MIT license. See LICENSE for details. ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/AFAutoPurgingImageCache.h ================================================ // AFAutoPurgingImageCache.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS || TARGET_OS_TV #import NS_ASSUME_NONNULL_BEGIN /** The `AFImageCache` protocol defines a set of APIs for adding, removing and fetching images from a cache synchronously. */ @protocol AFImageCache /** Adds the image to the cache with the given identifier. @param image The image to cache. @param identifier The unique identifier for the image in the cache. */ - (void)addImage:(UIImage *)image withIdentifier:(NSString *)identifier; /** Removes the image from the cache matching the given identifier. @param identifier The unique identifier for the image in the cache. @return A BOOL indicating whether or not the image was removed from the cache. */ - (BOOL)removeImageWithIdentifier:(NSString *)identifier; /** Removes all images from the cache. @return A BOOL indicating whether or not all images were removed from the cache. */ - (BOOL)removeAllImages; /** Returns the image in the cache associated with the given identifier. @param identifier The unique identifier for the image in the cache. @return An image for the matching identifier, or nil. */ - (nullable UIImage *)imageWithIdentifier:(NSString *)identifier; @end /** The `ImageRequestCache` protocol extends the `ImageCache` protocol by adding methods for adding, removing and fetching images from a cache given an `NSURLRequest` and additional identifier. */ @protocol AFImageRequestCache /** Adds the image to the cache using an identifier created from the request and additional identifier. @param image The image to cache. @param request The unique URL request identifing the image asset. @param identifier The additional identifier to apply to the URL request to identify the image. */ - (void)addImage:(UIImage *)image forRequest:(NSURLRequest *)request withAdditionalIdentifier:(nullable NSString *)identifier; /** Removes the image from the cache using an identifier created from the request and additional identifier. @param request The unique URL request identifing the image asset. @param identifier The additional identifier to apply to the URL request to identify the image. @return A BOOL indicating whether or not all images were removed from the cache. */ - (BOOL)removeImageforRequest:(NSURLRequest *)request withAdditionalIdentifier:(nullable NSString *)identifier; /** Returns the image from the cache associated with an identifier created from the request and additional identifier. @param request The unique URL request identifing the image asset. @param identifier The additional identifier to apply to the URL request to identify the image. @return An image for the matching request and identifier, or nil. */ - (nullable UIImage *)imageforRequest:(NSURLRequest *)request withAdditionalIdentifier:(nullable NSString *)identifier; @end /** The `AutoPurgingImageCache` in an in-memory image cache used to store images up to a given memory capacity. When the memory capacity is reached, the image cache is sorted by last access date, then the oldest image is continuously purged until the preferred memory usage after purge is met. Each time an image is accessed through the cache, the internal access date of the image is updated. */ @interface AFAutoPurgingImageCache : NSObject /** The total memory capacity of the cache in bytes. */ @property (nonatomic, assign) UInt64 memoryCapacity; /** The preferred memory usage after purge in bytes. During a purge, images will be purged until the memory capacity drops below this limit. */ @property (nonatomic, assign) UInt64 preferredMemoryUsageAfterPurge; /** The current total memory usage in bytes of all images stored within the cache. */ @property (nonatomic, assign, readonly) UInt64 memoryUsage; /** Initialies the `AutoPurgingImageCache` instance with default values for memory capacity and preferred memory usage after purge limit. `memoryCapcity` defaults to `100 MB`. `preferredMemoryUsageAfterPurge` defaults to `60 MB`. @return The new `AutoPurgingImageCache` instance. */ - (instancetype)init; /** Initialies the `AutoPurgingImageCache` instance with the given memory capacity and preferred memory usage after purge limit. @param memoryCapacity The total memory capacity of the cache in bytes. @param preferredMemoryUsageAfterPurge The preferred memory usage after purge in bytes. @return The new `AutoPurgingImageCache` instance. */ - (instancetype)initWithMemoryCapacity:(UInt64)memoryCapacity preferredMemoryCapacity:(UInt64)preferredMemoryCapacity; @end NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/AFAutoPurgingImageCache.m ================================================ // AFAutoPurgingImageCache.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #if TARGET_OS_IOS || TARGET_OS_TV #import "AFAutoPurgingImageCache.h" @interface AFCachedImage : NSObject @property (nonatomic, strong) UIImage *image; @property (nonatomic, strong) NSString *identifier; @property (nonatomic, assign) UInt64 totalBytes; @property (nonatomic, strong) NSDate *lastAccessDate; @property (nonatomic, assign) UInt64 currentMemoryUsage; @end @implementation AFCachedImage -(instancetype)initWithImage:(UIImage *)image identifier:(NSString *)identifier { if (self = [self init]) { self.image = image; self.identifier = identifier; CGSize imageSize = CGSizeMake(image.size.width * image.scale, image.size.height * image.scale); CGFloat bytesPerPixel = 4.0; CGFloat bytesPerRow = imageSize.width * bytesPerPixel; self.totalBytes = (UInt64)bytesPerPixel * (UInt64)bytesPerRow; self.lastAccessDate = [NSDate date]; } return self; } - (UIImage*)accessImage { self.lastAccessDate = [NSDate date]; return self.image; } - (NSString *)description { NSString *descriptionString = [NSString stringWithFormat:@"Idenfitier: %@ lastAccessDate: %@ ", self.identifier, self.lastAccessDate]; return descriptionString; } @end @interface AFAutoPurgingImageCache () @property (nonatomic, strong) NSMutableDictionary *cachedImages; @property (nonatomic, assign) UInt64 currentMemoryUsage; @property (nonatomic, strong) dispatch_queue_t synchronizationQueue; @end @implementation AFAutoPurgingImageCache - (instancetype)init { return [self initWithMemoryCapacity:100 * 1024 * 1024 preferredMemoryCapacity:60 * 1024 * 1024]; } - (instancetype)initWithMemoryCapacity:(UInt64)memoryCapacity preferredMemoryCapacity:(UInt64)preferredMemoryCapacity { if (self = [super init]) { self.memoryCapacity = memoryCapacity; self.preferredMemoryUsageAfterPurge = preferredMemoryCapacity; self.cachedImages = [[NSMutableDictionary alloc] init]; NSString *queueName = [NSString stringWithFormat:@"com.alamofire.autopurgingimagecache-%@", [[NSUUID UUID] UUIDString]]; self.synchronizationQueue = dispatch_queue_create([queueName cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_CONCURRENT); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeAllImages) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (UInt64)memoryUsage { __block UInt64 result = 0; dispatch_sync(self.synchronizationQueue, ^{ result = self.currentMemoryUsage; }); return result; } - (void)addImage:(UIImage *)image withIdentifier:(NSString *)identifier { dispatch_barrier_async(self.synchronizationQueue, ^{ AFCachedImage *cacheImage = [[AFCachedImage alloc] initWithImage:image identifier:identifier]; AFCachedImage *previousCachedImage = self.cachedImages[identifier]; if (previousCachedImage != nil) { self.currentMemoryUsage -= previousCachedImage.totalBytes; } self.cachedImages[identifier] = cacheImage; self.currentMemoryUsage += cacheImage.totalBytes; }); dispatch_barrier_async(self.synchronizationQueue, ^{ if (self.currentMemoryUsage > self.memoryCapacity) { UInt64 bytesToPurge = self.currentMemoryUsage - self.preferredMemoryUsageAfterPurge; NSMutableArray *sortedImages = [NSMutableArray arrayWithArray:self.cachedImages.allValues]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastAccessDate" ascending:YES]; [sortedImages sortUsingDescriptors:@[sortDescriptor]]; UInt64 bytesPurged = 0; for (AFCachedImage *cachedImage in sortedImages) { [self.cachedImages removeObjectForKey:cachedImage.identifier]; bytesPurged += cachedImage.totalBytes; if (bytesPurged >= bytesToPurge) { break ; } } self.currentMemoryUsage -= bytesPurged; } }); } - (BOOL)removeImageWithIdentifier:(NSString *)identifier { __block BOOL removed = NO; dispatch_barrier_sync(self.synchronizationQueue, ^{ AFCachedImage *cachedImage = self.cachedImages[identifier]; if (cachedImage != nil) { [self.cachedImages removeObjectForKey:identifier]; self.currentMemoryUsage -= cachedImage.totalBytes; removed = YES; } }); return removed; } - (BOOL)removeAllImages { __block BOOL removed = NO; dispatch_barrier_sync(self.synchronizationQueue, ^{ if (self.cachedImages.count > 0) { [self.cachedImages removeAllObjects]; self.currentMemoryUsage = 0; removed = YES; } }); return removed; } - (nullable UIImage *)imageWithIdentifier:(NSString *)identifier { __block UIImage *image = nil; dispatch_sync(self.synchronizationQueue, ^{ AFCachedImage *cachedImage = self.cachedImages[identifier]; image = [cachedImage accessImage]; }); return image; } - (void)addImage:(UIImage *)image forRequest:(NSURLRequest *)request withAdditionalIdentifier:(NSString *)identifier { [self addImage:image withIdentifier:[self imageCacheKeyFromURLRequest:request withAdditionalIdentifier:identifier]]; } - (BOOL)removeImageforRequest:(NSURLRequest *)request withAdditionalIdentifier:(NSString *)identifier { return [self removeImageWithIdentifier:[self imageCacheKeyFromURLRequest:request withAdditionalIdentifier:identifier]]; } - (nullable UIImage *)imageforRequest:(NSURLRequest *)request withAdditionalIdentifier:(NSString *)identifier { return [self imageWithIdentifier:[self imageCacheKeyFromURLRequest:request withAdditionalIdentifier:identifier]]; } - (NSString *)imageCacheKeyFromURLRequest:(NSURLRequest *)request withAdditionalIdentifier:(NSString *)additionalIdentifier { NSString *key = request.URL.absoluteString; if (additionalIdentifier != nil) { key = [key stringByAppendingString:additionalIdentifier]; } return key; } @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/AFImageDownloader.h ================================================ // AFImageDownloader.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #if TARGET_OS_IOS || TARGET_OS_TV #import #import "AFAutoPurgingImageCache.h" #import "AFHTTPSessionManager.h" NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSInteger, AFImageDownloadPrioritization) { AFImageDownloadPrioritizationFIFO, AFImageDownloadPrioritizationLIFO }; /** The `AFImageDownloadReceipt` is an object vended by the `AFImageDownloader` when starting a data task. It can be used to cancel active tasks running on the `AFImageDownloader` session. As a general rule, image data tasks should be cancelled using the `AFImageDownloadReceipt` instead of calling `cancel` directly on the `task` itself. The `AFImageDownloader` is optimized to handle duplicate task scenarios as well as pending versus active downloads. */ @interface AFImageDownloadReceipt : NSObject /** The data task created by the `AFImageDownloader`. */ @property (nonatomic, strong) NSURLSessionDataTask *task; /** The unique identifier for the success and failure blocks when duplicate requests are made. */ @property (nonatomic, strong) NSUUID *receiptID; @end /** The `AFImageDownloader` class is responsible for downloading images in parallel on a prioritized queue. Incoming downloads are added to the front or back of the queue depending on the download prioritization. Each downloaded image is cached in the underlying `NSURLCache` as well as the in-memory image cache. By default, any download request with a cached image equivalent in the image cache will automatically be served the cached image representation. */ @interface AFImageDownloader : NSObject /** The image cache used to store all downloaded images in. `AFAutoPurgingImageCache` by default. */ @property (nonatomic, strong, nullable) id imageCache; /** The `AFHTTPSessionManager` used to download images. By default, this is configured with an `AFImageResponseSerializer`, and a shared `NSURLCache` for all image downloads. */ @property (nonatomic, strong) AFHTTPSessionManager *sessionManager; /** Defines the order prioritization of incoming download requests being inserted into the queue. `AFImageDownloadPrioritizationFIFO` by default. */ @property (nonatomic, assign) AFImageDownloadPrioritization downloadPrioritizaton; /** The shared default instance of `AFImageDownloader` initialized with default values. */ + (instancetype)defaultInstance; /** Creates a default `NSURLCache` with common usage parameter values. @returns The default `NSURLCache` instance. */ + (NSURLCache *)defaultURLCache; /** Default initializer @return An instance of `AFImageDownloader` initialized with default values. */ - (instancetype)init; /** Initializes the `AFImageDownloader` instance with the given session manager, download prioritization, maximum active download count and image cache. @param sessionManager The session manager to use to download images. @param downloadPrioritization The download prioritization of the download queue. @param maximumActiveDownloads The maximum number of active downloads allowed at any given time. Recommend `4`. @param imageCache The image cache used to store all downloaded images in. @return The new `AFImageDownloader` instance. */ - (instancetype)initWithSessionManager:(AFHTTPSessionManager *)sessionManager downloadPrioritization:(AFImageDownloadPrioritization)downloadPrioritization maximumActiveDownloads:(NSInteger)maximumActiveDownloads imageCache:(nullable id )imageCache; /** Creates a data task using the `sessionManager` instance for the specified URL request. If the same data task is already in the queue or currently being downloaded, the success and failure blocks are appended to the already existing task. Once the task completes, all success or failure blocks attached to the task are executed in the order they were added. @param request The URL request. @param success A block to be executed when the image data task finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image data task finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. @return The image download receipt for the data task if available. `nil` if the image is stored in the cache. cache and the URL request cache policy allows the cache to be used. */ - (nullable AFImageDownloadReceipt *)downloadImageForURLRequest:(NSURLRequest *)request success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *responseObject))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure; /** Creates a data task using the `sessionManager` instance for the specified URL request. If the same data task is already in the queue or currently being downloaded, the success and failure blocks are appended to the already existing task. Once the task completes, all success or failure blocks attached to the task are executed in the order they were added. @param request The URL request. @param request The identifier to use for the download receipt that will be created for this request. This must be a unique identifier that does not represent any other request. @param success A block to be executed when the image data task finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image data task finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. @return The image download receipt for the data task if available. `nil` if the image is stored in the cache. cache and the URL request cache policy allows the cache to be used. */ - (nullable AFImageDownloadReceipt *)downloadImageForURLRequest:(NSURLRequest *)request withReceiptID:(NSUUID *)receiptID success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *responseObject))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure; /** Cancels the data task in the receipt by removing the corresponding success and failure blocks and cancelling the data task if necessary. If the data task is pending in the queue, it will be cancelled if no other success and failure blocks are registered with the data task. If the data task is currently executing or is already completed, the success and failure blocks are removed and will not be called when the task finishes. @param imageDownloadReceipt The image download receipt to cancel. */ - (void)cancelTaskForImageDownloadReceipt:(AFImageDownloadReceipt *)imageDownloadReceipt; @end #endif NS_ASSUME_NONNULL_END ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/AFImageDownloader.m ================================================ // AFImageDownloader.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #if TARGET_OS_IOS || TARGET_OS_TV #import "AFImageDownloader.h" #import "AFHTTPSessionManager.h" @interface AFImageDownloaderResponseHandler : NSObject @property (nonatomic, strong) NSUUID *uuid; @property (nonatomic, copy) void (^successBlock)(NSURLRequest*, NSHTTPURLResponse*, UIImage*); @property (nonatomic, copy) void (^failureBlock)(NSURLRequest*, NSHTTPURLResponse*, NSError*); @end @implementation AFImageDownloaderResponseHandler - (instancetype)initWithUUID:(NSUUID *)uuid success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *responseObject))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure { if (self = [self init]) { self.uuid = uuid; self.successBlock = success; self.failureBlock = failure; } return self; } - (NSString *)description { return [NSString stringWithFormat: @"UUID: %@", [self.uuid UUIDString]]; } @end @interface AFImageDownloaderMergedTask : NSObject @property (nonatomic, strong) NSString *identifier; @property (nonatomic, strong) NSURLSessionDataTask *task; @property (nonatomic, strong) NSMutableArray *responseHandlers; @end @implementation AFImageDownloaderMergedTask - (instancetype)initWithIdentifier:(NSString *)identifier task:(NSURLSessionDataTask *)task { if (self = [self init]) { self.identifier = identifier; self.task = task; self.responseHandlers = [[NSMutableArray alloc] init]; } return self; } - (void)addResponseHandler:(AFImageDownloaderResponseHandler*)handler { [self.responseHandlers addObject:handler]; } - (void)removeResponseHandler:(AFImageDownloaderResponseHandler*)handler { [self.responseHandlers removeObject:handler]; } @end @implementation AFImageDownloadReceipt - (instancetype)initWithReceiptID:(NSUUID *)receiptID task:(NSURLSessionDataTask *)task { if (self = [self init]) { self.receiptID = receiptID; self.task = task; } return self; } @end @interface AFImageDownloader () @property (nonatomic, strong) dispatch_queue_t synchronizationQueue; @property (nonatomic, strong) dispatch_queue_t responseQueue; @property (nonatomic, assign) NSInteger maximumActiveDownloads; @property (nonatomic, assign) NSInteger activeRequestCount; @property (nonatomic, strong) NSMutableArray *queuedMergedTasks; @property (nonatomic, strong) NSMutableDictionary *mergedTasks; @end @implementation AFImageDownloader + (NSURLCache *)defaultURLCache { return [[NSURLCache alloc] initWithMemoryCapacity:20 * 1024 * 1024 diskCapacity:150 * 1024 * 1024 diskPath:@"com.alamofire.imagedownloader"]; } + (NSURLSessionConfiguration *)defaultURLSessionConfiguration { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; //TODO set the default HTTP headers configuration.HTTPShouldSetCookies = YES; configuration.HTTPShouldUsePipelining = NO; configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; configuration.allowsCellularAccess = YES; configuration.timeoutIntervalForRequest = 60.0; configuration.URLCache = [AFImageDownloader defaultURLCache]; return configuration; } - (instancetype)init { NSURLSessionConfiguration *defaultConfiguration = [self.class defaultURLSessionConfiguration]; AFHTTPSessionManager *sessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:defaultConfiguration]; sessionManager.responseSerializer = [AFImageResponseSerializer serializer]; return [self initWithSessionManager:sessionManager downloadPrioritization:AFImageDownloadPrioritizationFIFO maximumActiveDownloads:4 imageCache:[[AFAutoPurgingImageCache alloc] init]]; } - (instancetype)initWithSessionManager:(AFHTTPSessionManager *)sessionManager downloadPrioritization:(AFImageDownloadPrioritization)downloadPrioritization maximumActiveDownloads:(NSInteger)maximumActiveDownloads imageCache:(id )imageCache { if (self = [super init]) { self.sessionManager = sessionManager; self.downloadPrioritizaton = downloadPrioritization; self.maximumActiveDownloads = maximumActiveDownloads; self.imageCache = imageCache; self.queuedMergedTasks = [[NSMutableArray alloc] init]; self.mergedTasks = [[NSMutableDictionary alloc] init]; self.activeRequestCount = 0; NSString *name = [NSString stringWithFormat:@"com.alamofire.imagedownloader.synchronizationqueue-%@", [[NSUUID UUID] UUIDString]]; self.synchronizationQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_SERIAL); name = [NSString stringWithFormat:@"com.alamofire.imagedownloader.responsequeue-%@", [[NSUUID UUID] UUIDString]]; self.responseQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_CONCURRENT); } return self; } + (instancetype)defaultInstance { static AFImageDownloader *sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } - (nullable AFImageDownloadReceipt *)downloadImageForURLRequest:(NSURLRequest *)request success:(void (^)(NSURLRequest * _Nonnull, NSHTTPURLResponse * _Nullable, UIImage * _Nonnull))success failure:(void (^)(NSURLRequest * _Nonnull, NSHTTPURLResponse * _Nullable, NSError * _Nonnull))failure { return [self downloadImageForURLRequest:request withReceiptID:[NSUUID UUID] success:success failure:failure]; } - (nullable AFImageDownloadReceipt *)downloadImageForURLRequest:(NSURLRequest *)request withReceiptID:(nonnull NSUUID *)receiptID success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *responseObject))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure { __block NSURLSessionDataTask *task = nil; dispatch_sync(self.synchronizationQueue, ^{ NSString *identifier = request.URL.absoluteString; // 1) Append the success and failure blocks to a pre-existing request if it already exists AFImageDownloaderMergedTask *existingMergedTask = self.mergedTasks[identifier]; if (existingMergedTask != nil) { AFImageDownloaderResponseHandler *handler = [[AFImageDownloaderResponseHandler alloc] initWithUUID:receiptID success:success failure:failure]; [existingMergedTask addResponseHandler:handler]; task = existingMergedTask.task; return; } // 2) Attempt to load the image from the image cache if the cache policy allows it switch (request.cachePolicy) { case NSURLRequestUseProtocolCachePolicy: case NSURLRequestReturnCacheDataElseLoad: case NSURLRequestReturnCacheDataDontLoad: { UIImage *cachedImage = [self.imageCache imageforRequest:request withAdditionalIdentifier:nil]; if (cachedImage != nil) { if (success) { dispatch_async(dispatch_get_main_queue(), ^{ success(request, nil, cachedImage); }); } return; } break; } default: break; } // 3) Create the request and set up authentication, validation and response serialization NSURLSessionDataTask *createdTask; __weak __typeof__(self) weakSelf = self; createdTask = [self.sessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { dispatch_async(self.responseQueue, ^{ __strong __typeof__(weakSelf) strongSelf = weakSelf; AFImageDownloaderMergedTask *mergedTask = [strongSelf safelyRemoveMergedTaskWithIdentifier:identifier]; if (error) { for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) { if (handler.failureBlock) { dispatch_async(dispatch_get_main_queue(), ^{ handler.failureBlock(request, (NSHTTPURLResponse*)response, error); }); } } } else { [strongSelf.imageCache addImage:responseObject forRequest:request withAdditionalIdentifier:nil]; for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) { if (handler.successBlock) { dispatch_async(dispatch_get_main_queue(), ^{ handler.successBlock(request, (NSHTTPURLResponse*)response, responseObject); }); } } } [strongSelf safelyDecrementActiveTaskCount]; [strongSelf safelyStartNextTaskIfNecessary]; }); }]; // 4) Store the response handler for use when the request completes AFImageDownloaderResponseHandler *handler = [[AFImageDownloaderResponseHandler alloc] initWithUUID:receiptID success:success failure:failure]; AFImageDownloaderMergedTask *mergedTask = [[AFImageDownloaderMergedTask alloc] initWithIdentifier:identifier task:createdTask]; [mergedTask addResponseHandler:handler]; self.mergedTasks[identifier] = mergedTask; // 5) Either start the request or enqueue it depending on the current active request count if ([self isActiveRequestCountBelowMaximumLimit]) { [self startMergedTask:mergedTask]; } else { [self enqueueMergedTask:mergedTask]; } task = mergedTask.task; }); if (task) { return [[AFImageDownloadReceipt alloc] initWithReceiptID:receiptID task:task]; } else { return nil; } } - (void)cancelTaskForImageDownloadReceipt:(AFImageDownloadReceipt *)imageDownloadReceipt { dispatch_sync(self.synchronizationQueue, ^{ NSString *identifier = imageDownloadReceipt.task.originalRequest.URL.absoluteString; AFImageDownloaderMergedTask *mergedTask = self.mergedTasks[identifier]; NSUInteger index = [mergedTask.responseHandlers indexOfObjectPassingTest:^BOOL(AFImageDownloaderResponseHandler * _Nonnull handler, __unused NSUInteger idx, __unused BOOL * _Nonnull stop) { return handler.uuid == imageDownloadReceipt.receiptID; }]; if (index != NSNotFound) { AFImageDownloaderResponseHandler *handler = mergedTask.responseHandlers[index]; [mergedTask removeResponseHandler:handler]; NSString *failureReason = [NSString stringWithFormat:@"ImageDownloader cancelled URL request: %@",imageDownloadReceipt.task.originalRequest.URL.absoluteString]; NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey:failureReason}; NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:userInfo]; if (handler.failureBlock) { dispatch_async(dispatch_get_main_queue(), ^{ handler.failureBlock(imageDownloadReceipt.task.originalRequest, nil, error); }); } } if (mergedTask.responseHandlers.count == 0 && mergedTask.task.state == NSURLSessionTaskStateSuspended) { [mergedTask.task cancel]; } }); } - (AFImageDownloaderMergedTask*)safelyRemoveMergedTaskWithIdentifier:(NSString *)identifier { __block AFImageDownloaderMergedTask *mergedTask = nil; dispatch_sync(self.synchronizationQueue, ^{ mergedTask = self.mergedTasks[identifier]; [self.mergedTasks removeObjectForKey:identifier]; }); return mergedTask; } - (void)safelyDecrementActiveTaskCount { dispatch_sync(self.synchronizationQueue, ^{ if (self.activeRequestCount > 0) { self.activeRequestCount -= 1; } }); } - (void)safelyStartNextTaskIfNecessary { dispatch_sync(self.synchronizationQueue, ^{ if ([self isActiveRequestCountBelowMaximumLimit]) { while (self.queuedMergedTasks.count > 0) { AFImageDownloaderMergedTask *mergedTask = [self dequeueMergedTask]; if (mergedTask.task.state == NSURLSessionTaskStateSuspended) { [self startMergedTask:mergedTask]; break; } } } }); } - (void)startMergedTask:(AFImageDownloaderMergedTask *)mergedTask { [mergedTask.task resume]; ++self.activeRequestCount; } - (void)enqueueMergedTask:(AFImageDownloaderMergedTask *)mergedTask { switch (self.downloadPrioritizaton) { case AFImageDownloadPrioritizationFIFO: [self.queuedMergedTasks addObject:mergedTask]; break; case AFImageDownloadPrioritizationLIFO: [self.queuedMergedTasks insertObject:mergedTask atIndex:0]; break; } } - (AFImageDownloaderMergedTask *)dequeueMergedTask { AFImageDownloaderMergedTask *mergedTask = nil; mergedTask = [self.queuedMergedTasks firstObject]; [self.queuedMergedTasks removeObject:mergedTask]; return mergedTask; } - (BOOL)isActiveRequestCountBelowMaximumLimit { return self.activeRequestCount < self.maximumActiveDownloads; } @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h ================================================ // AFNetworkActivityIndicatorManager.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS #import NS_ASSUME_NONNULL_BEGIN /** `AFNetworkActivityIndicatorManager` manages the state of the network activity indicator in the status bar. When enabled, it will listen for notifications indicating that a session task has started or finished, and start or stop animating the indicator accordingly. The number of active requests is incremented and decremented much like a stack or a semaphore, and the activity indicator will animate so long as that number is greater than zero. You should enable the shared instance of `AFNetworkActivityIndicatorManager` when your application finishes launching. In `AppDelegate application:didFinishLaunchingWithOptions:` you can do so with the following code: [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES]; By setting `enabled` to `YES` for `sharedManager`, the network activity indicator will show and hide automatically as requests start and finish. You should not ever need to call `incrementActivityCount` or `decrementActivityCount` yourself. See the Apple Human Interface Guidelines section about the Network Activity Indicator for more information: http://developer.apple.com/library/iOS/#documentation/UserExperience/Conceptual/MobileHIG/UIElementGuidelines/UIElementGuidelines.html#//apple_ref/doc/uid/TP40006556-CH13-SW44 */ NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.") @interface AFNetworkActivityIndicatorManager : NSObject /** A Boolean value indicating whether the manager is enabled. If YES, the manager will change status bar network activity indicator according to network operation notifications it receives. The default value is NO. */ @property (nonatomic, assign, getter = isEnabled) BOOL enabled; /** A Boolean value indicating whether the network activity indicator manager is currently active. */ @property (readonly, nonatomic, assign, getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible; /** A time interval indicating the minimum duration of networking activity that should occur before the activity indicator is displayed. The default value 1 second. If the network activity indicator should be displayed immediately when network activity occurs, this value should be set to 0 seconds. Apple's HIG describes the following: > Display the network activity indicator to provide feedback when your app accesses the network for more than a couple of seconds. If the operation finishes sooner than that, you don’t have to show the network activity indicator, because the indicator is likely to disappear before users notice its presence. */ @property (nonatomic, assign) NSTimeInterval activationDelay; /** A time interval indicating the duration of time of no networking activity required before the activity indicator is disabled. This allows for continuous display of the network activity indicator across multiple requests. The default value is 0.17 seconds. */ @property (nonatomic, assign) NSTimeInterval completionDelay; /** Returns the shared network activity indicator manager object for the system. @return The systemwide network activity indicator manager. */ + (instancetype)sharedManager; /** Increments the number of active network requests. If this number was zero before incrementing, this will start animating the status bar network activity indicator. */ - (void)incrementActivityCount; /** Decrements the number of active network requests. If this number becomes zero after decrementing, this will stop animating the status bar network activity indicator. */ - (void)decrementActivityCount; /** Set the a custom method to be executed when the network activity indicator manager should be hidden/shown. By default, this is null, and the UIApplication Network Activity Indicator will be managed automatically. If this block is set, it is the responsiblity of the caller to manager the network activity indicator going forward. @param block A block to be executed when the network activity indicator status changes. */ - (void)setNetworkingActivityActionWithBlock:(nullable void (^)(BOOL networkActivityIndicatorVisible))block; @end NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m ================================================ // AFNetworkActivityIndicatorManager.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "AFNetworkActivityIndicatorManager.h" #if TARGET_OS_IOS #import "AFURLSessionManager.h" typedef NS_ENUM(NSInteger, AFNetworkActivityManagerState) { AFNetworkActivityManagerStateNotActive, AFNetworkActivityManagerStateDelayingStart, AFNetworkActivityManagerStateActive, AFNetworkActivityManagerStateDelayingEnd }; static NSTimeInterval const kDefaultAFNetworkActivityManagerActivationDelay = 1.0; static NSTimeInterval const kDefaultAFNetworkActivityManagerCompletionDelay = 0.17; static NSURLRequest * AFNetworkRequestFromNotification(NSNotification *notification) { if ([[notification object] respondsToSelector:@selector(originalRequest)]) { return [(NSURLSessionTask *)[notification object] originalRequest]; } else { return nil; } } typedef void (^AFNetworkActivityActionBlock)(BOOL networkActivityIndicatorVisible); @interface AFNetworkActivityIndicatorManager () @property (readwrite, nonatomic, assign) NSInteger activityCount; @property (readwrite, nonatomic, strong) NSTimer *activationDelayTimer; @property (readwrite, nonatomic, strong) NSTimer *completionDelayTimer; @property (readonly, nonatomic, getter = isNetworkActivityOccurring) BOOL networkActivityOccurring; @property (nonatomic, copy) AFNetworkActivityActionBlock networkActivityActionBlock; @property (nonatomic, assign) AFNetworkActivityManagerState currentState; @property (nonatomic, assign, getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible; - (void)updateCurrentStateForNetworkActivityChange; @end @implementation AFNetworkActivityIndicatorManager + (instancetype)sharedManager { static AFNetworkActivityIndicatorManager *_sharedManager = nil; static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, ^{ _sharedManager = [[self alloc] init]; }); return _sharedManager; } - (instancetype)init { self = [super init]; if (!self) { return nil; } self.currentState = AFNetworkActivityManagerStateNotActive; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidStart:) name:AFNetworkingTaskDidResumeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingTaskDidSuspendNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingTaskDidCompleteNotification object:nil]; self.activationDelay = kDefaultAFNetworkActivityManagerActivationDelay; self.completionDelay = kDefaultAFNetworkActivityManagerCompletionDelay; return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [_activationDelayTimer invalidate]; [_completionDelayTimer invalidate]; } - (void)setEnabled:(BOOL)enabled { _enabled = enabled; if (enabled == NO) { [self setCurrentState:AFNetworkActivityManagerStateNotActive]; } } - (void)setNetworkingActivityActionWithBlock:(void (^)(BOOL networkActivityIndicatorVisible))block { self.networkActivityActionBlock = block; } - (BOOL)isNetworkActivityOccurring { @synchronized(self) { return self.activityCount > 0; } } - (void)setNetworkActivityIndicatorVisible:(BOOL)networkActivityIndicatorVisible { if (_networkActivityIndicatorVisible != networkActivityIndicatorVisible) { [self willChangeValueForKey:@"networkActivityIndicatorVisible"]; @synchronized(self) { _networkActivityIndicatorVisible = networkActivityIndicatorVisible; } [self didChangeValueForKey:@"networkActivityIndicatorVisible"]; if (self.networkActivityActionBlock) { self.networkActivityActionBlock(networkActivityIndicatorVisible); } else { [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:networkActivityIndicatorVisible]; } } } - (void)setActivityCount:(NSInteger)activityCount { @synchronized(self) { _activityCount = activityCount; } dispatch_async(dispatch_get_main_queue(), ^{ [self updateCurrentStateForNetworkActivityChange]; }); } - (void)incrementActivityCount { [self willChangeValueForKey:@"activityCount"]; @synchronized(self) { _activityCount++; } [self didChangeValueForKey:@"activityCount"]; dispatch_async(dispatch_get_main_queue(), ^{ [self updateCurrentStateForNetworkActivityChange]; }); } - (void)decrementActivityCount { [self willChangeValueForKey:@"activityCount"]; @synchronized(self) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" _activityCount = MAX(_activityCount - 1, 0); #pragma clang diagnostic pop } [self didChangeValueForKey:@"activityCount"]; dispatch_async(dispatch_get_main_queue(), ^{ [self updateCurrentStateForNetworkActivityChange]; }); } - (void)networkRequestDidStart:(NSNotification *)notification { if ([AFNetworkRequestFromNotification(notification) URL]) { [self incrementActivityCount]; } } - (void)networkRequestDidFinish:(NSNotification *)notification { if ([AFNetworkRequestFromNotification(notification) URL]) { [self decrementActivityCount]; } } #pragma mark - Internal State Management - (void)setCurrentState:(AFNetworkActivityManagerState)currentState { @synchronized(self) { if (_currentState != currentState) { [self willChangeValueForKey:@"currentState"]; _currentState = currentState; switch (currentState) { case AFNetworkActivityManagerStateNotActive: [self cancelActivationDelayTimer]; [self cancelCompletionDelayTimer]; [self setNetworkActivityIndicatorVisible:NO]; break; case AFNetworkActivityManagerStateDelayingStart: [self startActivationDelayTimer]; break; case AFNetworkActivityManagerStateActive: [self cancelCompletionDelayTimer]; [self setNetworkActivityIndicatorVisible:YES]; break; case AFNetworkActivityManagerStateDelayingEnd: [self startCompletionDelayTimer]; break; } } [self didChangeValueForKey:@"currentState"]; } } - (void)updateCurrentStateForNetworkActivityChange { if (self.enabled) { switch (self.currentState) { case AFNetworkActivityManagerStateNotActive: if (self.isNetworkActivityOccurring) { [self setCurrentState:AFNetworkActivityManagerStateDelayingStart]; } break; case AFNetworkActivityManagerStateDelayingStart: //No op. Let the delay timer finish out. break; case AFNetworkActivityManagerStateActive: if (!self.isNetworkActivityOccurring) { [self setCurrentState:AFNetworkActivityManagerStateDelayingEnd]; } break; case AFNetworkActivityManagerStateDelayingEnd: if (self.isNetworkActivityOccurring) { [self setCurrentState:AFNetworkActivityManagerStateActive]; } break; } } } - (void)startActivationDelayTimer { self.activationDelayTimer = [NSTimer timerWithTimeInterval:self.activationDelay target:self selector:@selector(activationDelayTimerFired) userInfo:nil repeats:NO]; [[NSRunLoop mainRunLoop] addTimer:self.activationDelayTimer forMode:NSRunLoopCommonModes]; } - (void)activationDelayTimerFired { if (self.networkActivityOccurring) { [self setCurrentState:AFNetworkActivityManagerStateActive]; } else { [self setCurrentState:AFNetworkActivityManagerStateNotActive]; } } - (void)startCompletionDelayTimer { [self.completionDelayTimer invalidate]; self.completionDelayTimer = [NSTimer timerWithTimeInterval:self.completionDelay target:self selector:@selector(completionDelayTimerFired) userInfo:nil repeats:NO]; [[NSRunLoop mainRunLoop] addTimer:self.completionDelayTimer forMode:NSRunLoopCommonModes]; } - (void)completionDelayTimerFired { [self setCurrentState:AFNetworkActivityManagerStateNotActive]; } - (void)cancelActivationDelayTimer { [self.activationDelayTimer invalidate]; } - (void)cancelCompletionDelayTimer { [self.completionDelayTimer invalidate]; } @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h ================================================ // UIActivityIndicatorView+AFNetworking.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS || TARGET_OS_TV #import /** This category adds methods to the UIKit framework's `UIActivityIndicatorView` class. The methods in this category provide support for automatically starting and stopping animation depending on the loading state of a session task. */ @interface UIActivityIndicatorView (AFNetworking) ///---------------------------------- /// @name Animating for Session Tasks ///---------------------------------- /** Binds the animating state to the state of the specified task. @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. */ - (void)setAnimatingWithStateOfTask:(nullable NSURLSessionTask *)task; @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m ================================================ // UIActivityIndicatorView+AFNetworking.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "UIActivityIndicatorView+AFNetworking.h" #import #if TARGET_OS_IOS || TARGET_OS_TV #import "AFURLSessionManager.h" @interface AFActivityIndicatorViewNotificationObserver : NSObject @property (readonly, nonatomic, weak) UIActivityIndicatorView *activityIndicatorView; - (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView; - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task; @end @implementation UIActivityIndicatorView (AFNetworking) - (AFActivityIndicatorViewNotificationObserver *)af_notificationObserver { AFActivityIndicatorViewNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver)); if (notificationObserver == nil) { notificationObserver = [[AFActivityIndicatorViewNotificationObserver alloc] initWithActivityIndicatorView:self]; objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return notificationObserver; } - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { [[self af_notificationObserver] setAnimatingWithStateOfTask:task]; } @end @implementation AFActivityIndicatorViewNotificationObserver - (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView { self = [super init]; if (self) { _activityIndicatorView = activityIndicatorView; } return self; } - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; if (task) { if (task.state != NSURLSessionTaskStateCompleted) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreceiver-is-weak" #pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if (task.state == NSURLSessionTaskStateRunning) { [self.activityIndicatorView startAnimating]; } else { [self.activityIndicatorView stopAnimating]; } #pragma clang diagnostic pop [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidSuspendNotification object:task]; } } } #pragma mark - - (void)af_startAnimating { dispatch_async(dispatch_get_main_queue(), ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreceiver-is-weak" [self.activityIndicatorView startAnimating]; #pragma clang diagnostic pop }); } - (void)af_stopAnimating { dispatch_async(dispatch_get_main_queue(), ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreceiver-is-weak" [self.activityIndicatorView stopAnimating]; #pragma clang diagnostic pop }); } #pragma mark - - (void)dealloc { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; } @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h ================================================ // UIButton+AFNetworking.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS || TARGET_OS_TV #import NS_ASSUME_NONNULL_BEGIN @class AFImageDownloader; /** This category adds methods to the UIKit framework's `UIButton` class. The methods in this category provide support for loading remote images and background images asynchronously from a URL. @warning Compound values for control `state` (such as `UIControlStateHighlighted | UIControlStateDisabled`) are unsupported. */ @interface UIButton (AFNetworking) ///------------------------------------ /// @name Accessing the Image Downloader ///------------------------------------ /** Set the shared image downloader used to download images. @param imageDownloader The shared image downloader used to download images. */ + (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader; /** The shared image downloader used to download images. */ + (AFImageDownloader *)sharedImageDownloader; ///-------------------- /// @name Setting Image ///-------------------- /** Asynchronously downloads an image from the specified URL, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. @param state The control state. @param url The URL used for the image request. */ - (void)setImageForState:(UIControlState)state withURL:(NSURL *)url; /** Asynchronously downloads an image from the specified URL, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. @param state The control state. @param url The URL used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the button will not change its image until the image request finishes. */ - (void)setImageForState:(UIControlState)state withURL:(NSURL *)url placeholderImage:(nullable UIImage *)placeholderImage; /** Asynchronously downloads an image from the specified URL request, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. If a success block is specified, it is the responsibility of the block to set the image of the button before returning. If no success block is specified, the default behavior of setting the image with `setImage:forState:` is applied. @param state The control state. @param urlRequest The URL request used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the button will not change its image until the image request finishes. @param success A block to be executed when the image data task finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image data task finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. */ - (void)setImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest placeholderImage:(nullable UIImage *)placeholderImage success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure; ///------------------------------- /// @name Setting Background Image ///------------------------------- /** Asynchronously downloads an image from the specified URL, and sets it as the background image for the specified state once the request is finished. Any previous background image request for the receiver will be cancelled. If the background image is cached locally, the background image is set immediately, otherwise the specified placeholder background image will be set immediately, and then the remote background image will be set once the request is finished. @param state The control state. @param url The URL used for the background image request. */ - (void)setBackgroundImageForState:(UIControlState)state withURL:(NSURL *)url; /** Asynchronously downloads an image from the specified URL, and sets it as the background image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. @param state The control state. @param url The URL used for the background image request. @param placeholderImage The background image to be set initially, until the background image request finishes. If `nil`, the button will not change its background image until the background image request finishes. */ - (void)setBackgroundImageForState:(UIControlState)state withURL:(NSURL *)url placeholderImage:(nullable UIImage *)placeholderImage; /** Asynchronously downloads an image from the specified URL request, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. If a success block is specified, it is the responsibility of the block to set the image of the button before returning. If no success block is specified, the default behavior of setting the image with `setBackgroundImage:forState:` is applied. @param state The control state. @param urlRequest The URL request used for the image request. @param placeholderImage The background image to be set initially, until the background image request finishes. If `nil`, the button will not change its background image until the background image request finishes. @param success A block to be executed when the image data task finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image data task finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. */ - (void)setBackgroundImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest placeholderImage:(nullable UIImage *)placeholderImage success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure; ///------------------------------ /// @name Canceling Image Loading ///------------------------------ /** Cancels any executing image task for the specified control state of the receiver, if one exists. @param state The control state. */ - (void)cancelImageDownloadTaskForState:(UIControlState)state; /** Cancels any executing background image task for the specified control state of the receiver, if one exists. @param state The control state. */ - (void)cancelBackgroundImageDownloadTaskForState:(UIControlState)state; @end NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m ================================================ // UIButton+AFNetworking.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "UIButton+AFNetworking.h" #import #if TARGET_OS_IOS || TARGET_OS_TV #import "UIImageView+AFNetworking.h" #import "AFImageDownloader.h" @interface UIButton (_AFNetworking) @end @implementation UIButton (_AFNetworking) #pragma mark - static char AFImageDownloadReceiptNormal; static char AFImageDownloadReceiptHighlighted; static char AFImageDownloadReceiptSelected; static char AFImageDownloadReceiptDisabled; static const char * af_imageDownloadReceiptKeyForState(UIControlState state) { switch (state) { case UIControlStateHighlighted: return &AFImageDownloadReceiptHighlighted; case UIControlStateSelected: return &AFImageDownloadReceiptSelected; case UIControlStateDisabled: return &AFImageDownloadReceiptDisabled; case UIControlStateNormal: default: return &AFImageDownloadReceiptNormal; } } - (AFImageDownloadReceipt *)af_imageDownloadReceiptForState:(UIControlState)state { return (AFImageDownloadReceipt *)objc_getAssociatedObject(self, af_imageDownloadReceiptKeyForState(state)); } - (void)af_setImageDownloadReceipt:(AFImageDownloadReceipt *)imageDownloadReceipt forState:(UIControlState)state { objc_setAssociatedObject(self, af_imageDownloadReceiptKeyForState(state), imageDownloadReceipt, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - static char AFBackgroundImageDownloadReceiptNormal; static char AFBackgroundImageDownloadReceiptHighlighted; static char AFBackgroundImageDownloadReceiptSelected; static char AFBackgroundImageDownloadReceiptDisabled; static const char * af_backgroundImageDownloadReceiptKeyForState(UIControlState state) { switch (state) { case UIControlStateHighlighted: return &AFBackgroundImageDownloadReceiptHighlighted; case UIControlStateSelected: return &AFBackgroundImageDownloadReceiptSelected; case UIControlStateDisabled: return &AFBackgroundImageDownloadReceiptDisabled; case UIControlStateNormal: default: return &AFBackgroundImageDownloadReceiptNormal; } } - (AFImageDownloadReceipt *)af_backgroundImageDownloadReceiptForState:(UIControlState)state { return (AFImageDownloadReceipt *)objc_getAssociatedObject(self, af_backgroundImageDownloadReceiptKeyForState(state)); } - (void)af_setBackgroundImageDownloadReceipt:(AFImageDownloadReceipt *)imageDownloadReceipt forState:(UIControlState)state { objc_setAssociatedObject(self, af_backgroundImageDownloadReceiptKeyForState(state), imageDownloadReceipt, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end #pragma mark - @implementation UIButton (AFNetworking) + (AFImageDownloader *)sharedImageDownloader { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" return objc_getAssociatedObject(self, @selector(sharedImageDownloader)) ?: [AFImageDownloader defaultInstance]; #pragma clang diagnostic pop } + (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader { objc_setAssociatedObject(self, @selector(sharedImageDownloader), imageDownloader, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - - (void)setImageForState:(UIControlState)state withURL:(NSURL *)url { [self setImageForState:state withURL:url placeholderImage:nil]; } - (void)setImageForState:(UIControlState)state withURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request addValue:@"image/*" forHTTPHeaderField:@"Accept"]; [self setImageForState:state withURLRequest:request placeholderImage:placeholderImage success:nil failure:nil]; } - (void)setImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest placeholderImage:(nullable UIImage *)placeholderImage success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure { if ([self isActiveTaskURLEqualToURLRequest:urlRequest forState:state]) { return; } [self cancelImageDownloadTaskForState:state]; AFImageDownloader *downloader = [[self class] sharedImageDownloader]; id imageCache = downloader.imageCache; //Use the image from the image cache if it exists UIImage *cachedImage = [imageCache imageforRequest:urlRequest withAdditionalIdentifier:nil]; if (cachedImage) { if (success) { success(urlRequest, nil, cachedImage); } else { [self setImage:cachedImage forState:state]; } [self af_setImageDownloadReceipt:nil forState:state]; } else { if (placeholderImage) { [self setImage:placeholderImage forState:state]; } __weak __typeof(self)weakSelf = self; NSUUID *downloadID = [NSUUID UUID]; AFImageDownloadReceipt *receipt; receipt = [downloader downloadImageForURLRequest:urlRequest withReceiptID:downloadID success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull responseObject) { __strong __typeof(weakSelf)strongSelf = weakSelf; if ([[strongSelf af_imageDownloadReceiptForState:state].receiptID isEqual:downloadID]) { if (success) { success(request, response, responseObject); } else if(responseObject) { [strongSelf setImage:responseObject forState:state]; } [strongSelf af_setImageDownloadReceipt:nil forState:state]; } } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) { __strong __typeof(weakSelf)strongSelf = weakSelf; if ([[strongSelf af_imageDownloadReceiptForState:state].receiptID isEqual:downloadID]) { if (failure) { failure(request, response, error); } [strongSelf af_setImageDownloadReceipt:nil forState:state]; } }]; [self af_setImageDownloadReceipt:receipt forState:state]; } } #pragma mark - - (void)setBackgroundImageForState:(UIControlState)state withURL:(NSURL *)url { [self setBackgroundImageForState:state withURL:url placeholderImage:nil]; } - (void)setBackgroundImageForState:(UIControlState)state withURL:(NSURL *)url placeholderImage:(nullable UIImage *)placeholderImage { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request addValue:@"image/*" forHTTPHeaderField:@"Accept"]; [self setBackgroundImageForState:state withURLRequest:request placeholderImage:placeholderImage success:nil failure:nil]; } - (void)setBackgroundImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest placeholderImage:(nullable UIImage *)placeholderImage success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure { if ([self isActiveBackgroundTaskURLEqualToURLRequest:urlRequest forState:state]) { return; } [self cancelImageDownloadTaskForState:state]; AFImageDownloader *downloader = [[self class] sharedImageDownloader]; id imageCache = downloader.imageCache; //Use the image from the image cache if it exists UIImage *cachedImage = [imageCache imageforRequest:urlRequest withAdditionalIdentifier:nil]; if (cachedImage) { if (success) { success(urlRequest, nil, cachedImage); } else { [self setBackgroundImage:cachedImage forState:state]; } [self af_setBackgroundImageDownloadReceipt:nil forState:state]; } else { if (placeholderImage) { [self setBackgroundImage:placeholderImage forState:state]; } __weak __typeof(self)weakSelf = self; NSUUID *downloadID = [NSUUID UUID]; AFImageDownloadReceipt *receipt; receipt = [downloader downloadImageForURLRequest:urlRequest withReceiptID:downloadID success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull responseObject) { __strong __typeof(weakSelf)strongSelf = weakSelf; if ([[strongSelf af_backgroundImageDownloadReceiptForState:state].receiptID isEqual:downloadID]) { if (success) { success(request, response, responseObject); } else if(responseObject) { [strongSelf setBackgroundImage:responseObject forState:state]; } [strongSelf af_setImageDownloadReceipt:nil forState:state]; } } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) { __strong __typeof(weakSelf)strongSelf = weakSelf; if ([[strongSelf af_backgroundImageDownloadReceiptForState:state].receiptID isEqual:downloadID]) { if (failure) { failure(request, response, error); } [strongSelf af_setBackgroundImageDownloadReceipt:nil forState:state]; } }]; [self af_setBackgroundImageDownloadReceipt:receipt forState:state]; } } #pragma mark - - (void)cancelImageDownloadTaskForState:(UIControlState)state { AFImageDownloadReceipt *receipt = [self af_imageDownloadReceiptForState:state]; if (receipt != nil) { [[self.class sharedImageDownloader] cancelTaskForImageDownloadReceipt:receipt]; [self af_setImageDownloadReceipt:nil forState:state]; } } - (void)cancelBackgroundImageDownloadTaskForState:(UIControlState)state { AFImageDownloadReceipt *receipt = [self af_backgroundImageDownloadReceiptForState:state]; if (receipt != nil) { [[self.class sharedImageDownloader] cancelTaskForImageDownloadReceipt:receipt]; [self af_setBackgroundImageDownloadReceipt:nil forState:state]; } } - (BOOL)isActiveTaskURLEqualToURLRequest:(NSURLRequest *)urlRequest forState:(UIControlState)state { AFImageDownloadReceipt *receipt = [self af_imageDownloadReceiptForState:state]; return [receipt.task.originalRequest.URL.absoluteString isEqualToString:urlRequest.URL.absoluteString]; } - (BOOL)isActiveBackgroundTaskURLEqualToURLRequest:(NSURLRequest *)urlRequest forState:(UIControlState)state { AFImageDownloadReceipt *receipt = [self af_backgroundImageDownloadReceiptForState:state]; return [receipt.task.originalRequest.URL.absoluteString isEqualToString:urlRequest.URL.absoluteString]; } @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIImage+AFNetworking.h ================================================ // // UIImage+AFNetworking.h // // // Created by Paulo Ferreira on 08/07/15. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #if TARGET_OS_IOS || TARGET_OS_TV #import @interface UIImage (AFNetworking) + (UIImage*) safeImageWithData:(NSData*)data; @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h ================================================ // UIImageView+AFNetworking.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS || TARGET_OS_TV #import NS_ASSUME_NONNULL_BEGIN @class AFImageDownloader; /** This category adds methods to the UIKit framework's `UIImageView` class. The methods in this category provide support for loading remote images asynchronously from a URL. */ @interface UIImageView (AFNetworking) ///------------------------------------ /// @name Accessing the Image Downloader ///------------------------------------ /** Set the shared image downloader used to download images. @param imageDownloader The shared image downloader used to download images. */ + (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader; /** The shared image downloader used to download images. */ + (AFImageDownloader *)sharedImageDownloader; ///-------------------- /// @name Setting Image ///-------------------- /** Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. By default, URL requests have a `Accept` header field value of "image / *", a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` @param url The URL used for the image request. */ - (void)setImageWithURL:(NSURL *)url; /** Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. By default, URL requests have a `Accept` header field value of "image / *", a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` @param url The URL used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. */ - (void)setImageWithURL:(NSURL *)url placeholderImage:(nullable UIImage *)placeholderImage; /** Asynchronously downloads an image from the specified URL request, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. If a success block is specified, it is the responsibility of the block to set the image of the image view before returning. If no success block is specified, the default behavior of setting the image with `self.image = image` is applied. @param urlRequest The URL request used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. @param success A block to be executed when the image data task finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image data task finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. */ - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest placeholderImage:(nullable UIImage *)placeholderImage success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure; /** Cancels any executing image operation for the receiver, if one exists. */ - (void)cancelImageDownloadTask; @end NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m ================================================ // UIImageView+AFNetworking.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "UIImageView+AFNetworking.h" #import #if TARGET_OS_IOS || TARGET_OS_TV #import "AFImageDownloader.h" @interface UIImageView (_AFNetworking) @property (readwrite, nonatomic, strong, setter = af_setActiveImageDownloadReceipt:) AFImageDownloadReceipt *af_activeImageDownloadReceipt; @end @implementation UIImageView (_AFNetworking) - (AFImageDownloadReceipt *)af_activeImageDownloadReceipt { return (AFImageDownloadReceipt *)objc_getAssociatedObject(self, @selector(af_activeImageDownloadReceipt)); } - (void)af_setActiveImageDownloadReceipt:(AFImageDownloadReceipt *)imageDownloadReceipt { objc_setAssociatedObject(self, @selector(af_activeImageDownloadReceipt), imageDownloadReceipt, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end #pragma mark - @implementation UIImageView (AFNetworking) + (AFImageDownloader *)sharedImageDownloader { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" return objc_getAssociatedObject(self, @selector(sharedImageDownloader)) ?: [AFImageDownloader defaultInstance]; #pragma clang diagnostic pop } + (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader { objc_setAssociatedObject(self, @selector(sharedImageDownloader), imageDownloader, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - - (void)setImageWithURL:(NSURL *)url { [self setImageWithURL:url placeholderImage:nil]; } - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request addValue:@"image/*" forHTTPHeaderField:@"Accept"]; [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil]; } - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure { if ([urlRequest URL] == nil) { [self cancelImageDownloadTask]; self.image = placeholderImage; return; } if ([self isActiveTaskURLEqualToURLRequest:urlRequest]){ return; } [self cancelImageDownloadTask]; AFImageDownloader *downloader = [[self class] sharedImageDownloader]; id imageCache = downloader.imageCache; //Use the image from the image cache if it exists UIImage *cachedImage = [imageCache imageforRequest:urlRequest withAdditionalIdentifier:nil]; if (cachedImage) { if (success) { success(urlRequest, nil, cachedImage); } else { self.image = cachedImage; } [self clearActiveDownloadInformation]; } else { if (placeholderImage) { self.image = placeholderImage; } __weak __typeof(self)weakSelf = self; NSUUID *downloadID = [NSUUID UUID]; AFImageDownloadReceipt *receipt; receipt = [downloader downloadImageForURLRequest:urlRequest withReceiptID:downloadID success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull responseObject) { __strong __typeof(weakSelf)strongSelf = weakSelf; if ([strongSelf.af_activeImageDownloadReceipt.receiptID isEqual:downloadID]) { if (success) { success(request, response, responseObject); } else if(responseObject) { strongSelf.image = responseObject; } [strongSelf clearActiveDownloadInformation]; } } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) { __strong __typeof(weakSelf)strongSelf = weakSelf; if ([strongSelf.af_activeImageDownloadReceipt.receiptID isEqual:downloadID]) { if (failure) { failure(request, response, error); } [strongSelf clearActiveDownloadInformation]; } }]; self.af_activeImageDownloadReceipt = receipt; } } - (void)cancelImageDownloadTask { if (self.af_activeImageDownloadReceipt != nil) { [[self.class sharedImageDownloader] cancelTaskForImageDownloadReceipt:self.af_activeImageDownloadReceipt]; [self clearActiveDownloadInformation]; } } - (void)clearActiveDownloadInformation { self.af_activeImageDownloadReceipt = nil; } - (BOOL)isActiveTaskURLEqualToURLRequest:(NSURLRequest *)urlRequest { return [self.af_activeImageDownloadReceipt.task.originalRequest.URL.absoluteString isEqualToString:urlRequest.URL.absoluteString]; } @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h ================================================ // UIKit+AFNetworking.h // // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #if TARGET_OS_IOS || TARGET_OS_TV #import #ifndef _UIKIT_AFNETWORKING_ #define _UIKIT_AFNETWORKING_ #if TARGET_OS_IOS #import "AFAutoPurgingImageCache.h" #import "AFImageDownloader.h" #import "AFNetworkActivityIndicatorManager.h" #import "UIRefreshControl+AFNetworking.h" #import "UIWebView+AFNetworking.h" #endif #import "UIActivityIndicatorView+AFNetworking.h" #import "UIButton+AFNetworking.h" #import "UIImageView+AFNetworking.h" #import "UIProgressView+AFNetworking.h" #endif /* _UIKIT_AFNETWORKING_ */ #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h ================================================ // UIProgressView+AFNetworking.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS || TARGET_OS_TV #import NS_ASSUME_NONNULL_BEGIN /** This category adds methods to the UIKit framework's `UIProgressView` class. The methods in this category provide support for binding the progress to the upload and download progress of a session task. */ @interface UIProgressView (AFNetworking) ///------------------------------------ /// @name Setting Session Task Progress ///------------------------------------ /** Binds the progress to the upload progress of the specified session task. @param task The session task. @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. */ - (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task animated:(BOOL)animated; /** Binds the progress to the download progress of the specified session task. @param task The session task. @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. */ - (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task animated:(BOOL)animated; @end NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.m ================================================ // UIProgressView+AFNetworking.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "UIProgressView+AFNetworking.h" #import #if TARGET_OS_IOS || TARGET_OS_TV #import "AFURLSessionManager.h" static void * AFTaskCountOfBytesSentContext = &AFTaskCountOfBytesSentContext; static void * AFTaskCountOfBytesReceivedContext = &AFTaskCountOfBytesReceivedContext; #pragma mark - @implementation UIProgressView (AFNetworking) - (BOOL)af_uploadProgressAnimated { return [(NSNumber *)objc_getAssociatedObject(self, @selector(af_uploadProgressAnimated)) boolValue]; } - (void)af_setUploadProgressAnimated:(BOOL)animated { objc_setAssociatedObject(self, @selector(af_uploadProgressAnimated), @(animated), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (BOOL)af_downloadProgressAnimated { return [(NSNumber *)objc_getAssociatedObject(self, @selector(af_downloadProgressAnimated)) boolValue]; } - (void)af_setDownloadProgressAnimated:(BOOL)animated { objc_setAssociatedObject(self, @selector(af_downloadProgressAnimated), @(animated), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - - (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task animated:(BOOL)animated { [task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesSentContext]; [task addObserver:self forKeyPath:@"countOfBytesSent" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesSentContext]; [self af_setUploadProgressAnimated:animated]; } - (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task animated:(BOOL)animated { [task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext]; [task addObserver:self forKeyPath:@"countOfBytesReceived" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext]; [self af_setDownloadProgressAnimated:animated]; } #pragma mark - NSKeyValueObserving - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(__unused NSDictionary *)change context:(void *)context { if (context == AFTaskCountOfBytesSentContext || context == AFTaskCountOfBytesReceivedContext) { if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) { if ([object countOfBytesExpectedToSend] > 0) { dispatch_async(dispatch_get_main_queue(), ^{ [self setProgress:[object countOfBytesSent] / ([object countOfBytesExpectedToSend] * 1.0f) animated:self.af_uploadProgressAnimated]; }); } } if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) { if ([object countOfBytesExpectedToReceive] > 0) { dispatch_async(dispatch_get_main_queue(), ^{ [self setProgress:[object countOfBytesReceived] / ([object countOfBytesExpectedToReceive] * 1.0f) animated:self.af_downloadProgressAnimated]; }); } } if ([keyPath isEqualToString:NSStringFromSelector(@selector(state))]) { if ([(NSURLSessionTask *)object state] == NSURLSessionTaskStateCompleted) { @try { [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state))]; if (context == AFTaskCountOfBytesSentContext) { [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))]; } if (context == AFTaskCountOfBytesReceivedContext) { [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))]; } } @catch (NSException * __unused exception) {} } } } } @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h ================================================ // UIRefreshControl+AFNetworking.m // // Copyright (c) 2014 AFNetworking (http://afnetworking.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS #import NS_ASSUME_NONNULL_BEGIN /** This category adds methods to the UIKit framework's `UIRefreshControl` class. The methods in this category provide support for automatically beginning and ending refreshing depending on the loading state of a session task. */ @interface UIRefreshControl (AFNetworking) ///----------------------------------- /// @name Refreshing for Session Tasks ///----------------------------------- /** Binds the refreshing state to the state of the specified task. @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. */ - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task; @end NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m ================================================ // UIRefreshControl+AFNetworking.m // // Copyright (c) 2014 AFNetworking (http://afnetworking.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "UIRefreshControl+AFNetworking.h" #import #if TARGET_OS_IOS #import "AFURLSessionManager.h" @interface AFRefreshControlNotificationObserver : NSObject @property (readonly, nonatomic, weak) UIRefreshControl *refreshControl; - (instancetype)initWithActivityRefreshControl:(UIRefreshControl *)refreshControl; - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task; @end @implementation UIRefreshControl (AFNetworking) - (AFRefreshControlNotificationObserver *)af_notificationObserver { AFRefreshControlNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver)); if (notificationObserver == nil) { notificationObserver = [[AFRefreshControlNotificationObserver alloc] initWithActivityRefreshControl:self]; objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return notificationObserver; } - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { [[self af_notificationObserver] setRefreshingWithStateOfTask:task]; } @end @implementation AFRefreshControlNotificationObserver - (instancetype)initWithActivityRefreshControl:(UIRefreshControl *)refreshControl { self = [super init]; if (self) { _refreshControl = refreshControl; } return self; } - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; if (task) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreceiver-is-weak" #pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if (task.state == NSURLSessionTaskStateRunning) { [self.refreshControl beginRefreshing]; [notificationCenter addObserver:self selector:@selector(af_beginRefreshing) name:AFNetworkingTaskDidResumeNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidCompleteNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidSuspendNotification object:task]; } else { [self.refreshControl endRefreshing]; } #pragma clang diagnostic pop } } #pragma mark - - (void)af_beginRefreshing { dispatch_async(dispatch_get_main_queue(), ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreceiver-is-weak" [self.refreshControl beginRefreshing]; #pragma clang diagnostic pop }); } - (void)af_endRefreshing { dispatch_async(dispatch_get_main_queue(), ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreceiver-is-weak" [self.refreshControl endRefreshing]; #pragma clang diagnostic pop }); } #pragma mark - - (void)dealloc { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; } @end #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h ================================================ // UIWebView+AFNetworking.h // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import #import #if TARGET_OS_IOS #import NS_ASSUME_NONNULL_BEGIN @class AFHTTPSessionManager; /** This category adds methods to the UIKit framework's `UIWebView` class. The methods in this category provide increased control over the request cycle, including progress monitoring and success / failure handling. @discussion When using these category methods, make sure to assign `delegate` for the web view, which implements `–webView:shouldStartLoadWithRequest:navigationType:` appropriately. This allows for tapped links to be loaded through AFNetworking, and can ensure that `canGoBack` & `canGoForward` update their values correctly. */ @interface UIWebView (AFNetworking) /** The session manager used to download all requests. */ @property (nonatomic, strong) AFHTTPSessionManager *sessionManager; /** Asynchronously loads the specified request. @param request A URL request identifying the location of the content to load. This must not be `nil`. @param progress A progress object monitoring the current download progress. @param success A block object to be executed when the request finishes loading successfully. This block returns the HTML string to be loaded by the web view, and takes two arguments: the response, and the response string. @param failure A block object to be executed when the data task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. */ - (void)loadRequest:(NSURLRequest *)request progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress success:(nullable NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success failure:(nullable void (^)(NSError *error))failure; /** Asynchronously loads the data associated with a particular request with a specified MIME type and text encoding. @param request A URL request identifying the location of the content to load. This must not be `nil`. @param MIMEType The MIME type of the content. Defaults to the content type of the response if not specified. @param textEncodingName The IANA encoding name, as in `utf-8` or `utf-16`. Defaults to the response text encoding if not specified. @param progress A progress object monitoring the current download progress. @param success A block object to be executed when the request finishes loading successfully. This block returns the data to be loaded by the web view and takes two arguments: the response, and the downloaded data. @param failure A block object to be executed when the data task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. */ - (void)loadRequest:(NSURLRequest *)request MIMEType:(nullable NSString *)MIMEType textEncodingName:(nullable NSString *)textEncodingName progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress success:(nullable NSData * (^)(NSHTTPURLResponse *response, NSData *data))success failure:(nullable void (^)(NSError *error))failure; @end NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.m ================================================ // UIWebView+AFNetworking.m // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #import "UIWebView+AFNetworking.h" #import #if TARGET_OS_IOS #import "AFHTTPSessionManager.h" #import "AFURLResponseSerialization.h" #import "AFURLRequestSerialization.h" @interface UIWebView (_AFNetworking) @property (readwrite, nonatomic, strong, setter = af_setURLSessionTask:) NSURLSessionDataTask *af_URLSessionTask; @end @implementation UIWebView (_AFNetworking) - (NSURLSessionDataTask *)af_URLSessionTask { return (NSURLSessionDataTask *)objc_getAssociatedObject(self, @selector(af_URLSessionTask)); } - (void)af_setURLSessionTask:(NSURLSessionDataTask *)af_URLSessionTask { objc_setAssociatedObject(self, @selector(af_URLSessionTask), af_URLSessionTask, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end #pragma mark - @implementation UIWebView (AFNetworking) - (AFHTTPSessionManager *)sessionManager { static AFHTTPSessionManager *_af_defaultHTTPSessionManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _af_defaultHTTPSessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; _af_defaultHTTPSessionManager.requestSerializer = [AFHTTPRequestSerializer serializer]; _af_defaultHTTPSessionManager.responseSerializer = [AFHTTPResponseSerializer serializer]; }); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" return objc_getAssociatedObject(self, @selector(sessionManager)) ?: _af_defaultHTTPSessionManager; #pragma clang diagnostic pop } - (void)setSessionManager:(AFHTTPSessionManager *)sessionManager { objc_setAssociatedObject(self, @selector(sessionManager), sessionManager, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (AFHTTPResponseSerializer *)responseSerializer { static AFHTTPResponseSerializer *_af_defaultResponseSerializer = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _af_defaultResponseSerializer = [AFHTTPResponseSerializer serializer]; }); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" return objc_getAssociatedObject(self, @selector(responseSerializer)) ?: _af_defaultResponseSerializer; #pragma clang diagnostic pop } - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { objc_setAssociatedObject(self, @selector(responseSerializer), responseSerializer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - - (void)loadRequest:(NSURLRequest *)request progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress success:(NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success failure:(void (^)(NSError *error))failure { [self loadRequest:request MIMEType:nil textEncodingName:nil progress:progress success:^NSData *(NSHTTPURLResponse *response, NSData *data) { NSStringEncoding stringEncoding = NSUTF8StringEncoding; if (response.textEncodingName) { CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName); if (encoding != kCFStringEncodingInvalidId) { stringEncoding = CFStringConvertEncodingToNSStringEncoding(encoding); } } NSString *string = [[NSString alloc] initWithData:data encoding:stringEncoding]; if (success) { string = success(response, string); } return [string dataUsingEncoding:stringEncoding]; } failure:failure]; } - (void)loadRequest:(NSURLRequest *)request MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress success:(NSData * (^)(NSHTTPURLResponse *response, NSData *data))success failure:(void (^)(NSError *error))failure { NSParameterAssert(request); if (self.af_URLSessionTask.state == NSURLSessionTaskStateRunning || self.af_URLSessionTask.state == NSURLSessionTaskStateSuspended) { [self.af_URLSessionTask cancel]; } self.af_URLSessionTask = nil; __weak __typeof(self)weakSelf = self; NSURLSessionDataTask *dataTask; dataTask = [self.sessionManager GET:request.URL.absoluteString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { __strong __typeof(weakSelf) strongSelf = weakSelf; if (success) { success((NSHTTPURLResponse *)task.response, responseObject); } [strongSelf loadData:responseObject MIMEType:MIMEType textEncodingName:textEncodingName baseURL:[task.currentRequest URL]]; if ([strongSelf.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { [strongSelf.delegate webViewDidFinishLoad:strongSelf]; } } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) { if (failure) { failure(error); } }]; self.af_URLSessionTask = dataTask; *progress = [self.sessionManager downloadProgressForTask:dataTask]; [self.af_URLSessionTask resume]; if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { [self.delegate webViewDidStartLoad:self]; } } @end #endif ================================================ FILE: Pods/DACircularProgress/DACircularProgress/DACircularProgressView.h ================================================ // // DACircularProgressView.h // DACircularProgress // // Created by Daniel Amitay on 2/6/12. // Copyright (c) 2012 Daniel Amitay. All rights reserved. // #import @interface DACircularProgressView : UIView @property(nonatomic, strong) UIColor *trackTintColor UI_APPEARANCE_SELECTOR; @property(nonatomic, strong) UIColor *progressTintColor UI_APPEARANCE_SELECTOR; @property(nonatomic, strong) UIColor *innerTintColor UI_APPEARANCE_SELECTOR; @property(nonatomic) NSInteger roundedCorners UI_APPEARANCE_SELECTOR; // Can not use BOOL with UI_APPEARANCE_SELECTOR :-( @property(nonatomic) CGFloat thicknessRatio UI_APPEARANCE_SELECTOR; @property(nonatomic) NSInteger clockwiseProgress UI_APPEARANCE_SELECTOR; // Can not use BOOL with UI_APPEARANCE_SELECTOR :-( @property(nonatomic) CGFloat progress; @property(nonatomic) CGFloat indeterminateDuration UI_APPEARANCE_SELECTOR; @property(nonatomic) NSInteger indeterminate UI_APPEARANCE_SELECTOR; // Can not use BOOL with UI_APPEARANCE_SELECTOR :-( - (void)setProgress:(CGFloat)progress animated:(BOOL)animated; - (void)setProgress:(CGFloat)progress animated:(BOOL)animated initialDelay:(CFTimeInterval)initialDelay; - (void)setProgress:(CGFloat)progress animated:(BOOL)animated initialDelay:(CFTimeInterval)initialDelay withDuration:(CFTimeInterval)duration; @end ================================================ FILE: Pods/DACircularProgress/DACircularProgress/DACircularProgressView.m ================================================ // // DACircularProgressView.m // DACircularProgress // // Created by Daniel Amitay on 2/6/12. // Copyright (c) 2012 Daniel Amitay. All rights reserved. // #import "DACircularProgressView.h" #import @interface DACircularProgressLayer : CALayer @property(nonatomic, strong) UIColor *trackTintColor; @property(nonatomic, strong) UIColor *progressTintColor; @property(nonatomic, strong) UIColor *innerTintColor; @property(nonatomic) NSInteger roundedCorners; @property(nonatomic) CGFloat thicknessRatio; @property(nonatomic) CGFloat progress; @property(nonatomic) NSInteger clockwiseProgress; @end @implementation DACircularProgressLayer @dynamic trackTintColor; @dynamic progressTintColor; @dynamic innerTintColor; @dynamic roundedCorners; @dynamic thicknessRatio; @dynamic progress; @dynamic clockwiseProgress; + (BOOL)needsDisplayForKey:(NSString *)key { if ([key isEqualToString:@"progress"]) { return YES; } else { return [super needsDisplayForKey:key]; } } - (void)drawInContext:(CGContextRef)context { CGRect rect = self.bounds; CGPoint centerPoint = CGPointMake(rect.size.width / 2.0f, rect.size.height / 2.0f); CGFloat radius = MIN(rect.size.height, rect.size.width) / 2.0f; BOOL clockwise = (self.clockwiseProgress != 0); CGFloat progress = MIN(self.progress, 1.0f - FLT_EPSILON); CGFloat radians = 0; if (clockwise) { radians = (float)((progress * 2.0f * M_PI) - M_PI_2); } else { radians = (float)(3 * M_PI_2 - (progress * 2.0f * M_PI)); } CGContextSetFillColorWithColor(context, self.trackTintColor.CGColor); CGMutablePathRef trackPath = CGPathCreateMutable(); CGPathMoveToPoint(trackPath, NULL, centerPoint.x, centerPoint.y); CGPathAddArc(trackPath, NULL, centerPoint.x, centerPoint.y, radius, (float)(2.0f * M_PI), 0.0f, TRUE); CGPathCloseSubpath(trackPath); CGContextAddPath(context, trackPath); CGContextFillPath(context); CGPathRelease(trackPath); if (progress > 0.0f) { CGContextSetFillColorWithColor(context, self.progressTintColor.CGColor); CGMutablePathRef progressPath = CGPathCreateMutable(); CGPathMoveToPoint(progressPath, NULL, centerPoint.x, centerPoint.y); CGPathAddArc(progressPath, NULL, centerPoint.x, centerPoint.y, radius, (float)(3.0f * M_PI_2), radians, !clockwise); CGPathCloseSubpath(progressPath); CGContextAddPath(context, progressPath); CGContextFillPath(context); CGPathRelease(progressPath); } if (progress > 0.0f && self.roundedCorners) { CGFloat pathWidth = radius * self.thicknessRatio; CGFloat xOffset = radius * (1.0f + ((1.0f - (self.thicknessRatio / 2.0f)) * cosf(radians))); CGFloat yOffset = radius * (1.0f + ((1.0f - (self.thicknessRatio / 2.0f)) * sinf(radians))); CGPoint endPoint = CGPointMake(xOffset, yOffset); CGRect startEllipseRect = (CGRect) { .origin.x = centerPoint.x - pathWidth / 2.0f, .origin.y = 0.0f, .size.width = pathWidth, .size.height = pathWidth }; CGContextAddEllipseInRect(context, startEllipseRect); CGContextFillPath(context); CGRect endEllipseRect = (CGRect) { .origin.x = endPoint.x - pathWidth / 2.0f, .origin.y = endPoint.y - pathWidth / 2.0f, .size.width = pathWidth, .size.height = pathWidth }; CGContextAddEllipseInRect(context, endEllipseRect); CGContextFillPath(context); } CGContextSetBlendMode(context, kCGBlendModeClear); CGFloat innerRadius = radius * (1.0f - self.thicknessRatio); CGRect clearRect = (CGRect) { .origin.x = centerPoint.x - innerRadius, .origin.y = centerPoint.y - innerRadius, .size.width = innerRadius * 2.0f, .size.height = innerRadius * 2.0f }; CGContextAddEllipseInRect(context, clearRect); CGContextFillPath(context); if (self.innerTintColor) { CGContextSetBlendMode(context, kCGBlendModeNormal); CGContextSetFillColorWithColor(context, [self.innerTintColor CGColor]); CGContextAddEllipseInRect(context, clearRect); CGContextFillPath(context); } } @end @interface DACircularProgressView () @end @implementation DACircularProgressView + (void) initialize { if (self == [DACircularProgressView class]) { DACircularProgressView *circularProgressViewAppearance = [DACircularProgressView appearance]; [circularProgressViewAppearance setTrackTintColor:[[UIColor whiteColor] colorWithAlphaComponent:0.3f]]; [circularProgressViewAppearance setProgressTintColor:[UIColor whiteColor]]; [circularProgressViewAppearance setInnerTintColor:nil]; [circularProgressViewAppearance setBackgroundColor:[UIColor clearColor]]; [circularProgressViewAppearance setThicknessRatio:0.3f]; [circularProgressViewAppearance setRoundedCorners:NO]; [circularProgressViewAppearance setClockwiseProgress:YES]; [circularProgressViewAppearance setIndeterminateDuration:2.0f]; [circularProgressViewAppearance setIndeterminate:NO]; } } + (Class)layerClass { return [DACircularProgressLayer class]; } - (DACircularProgressLayer *)circularProgressLayer { return (DACircularProgressLayer *)self.layer; } - (id)init { return [super initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)]; } - (void)didMoveToWindow { CGFloat windowContentsScale = self.window.screen.scale; self.circularProgressLayer.contentsScale = windowContentsScale; [self.circularProgressLayer setNeedsDisplay]; } #pragma mark - Progress - (CGFloat)progress { return self.circularProgressLayer.progress; } - (void)setProgress:(CGFloat)progress { [self setProgress:progress animated:NO]; } - (void)setProgress:(CGFloat)progress animated:(BOOL)animated { [self setProgress:progress animated:animated initialDelay:0.0]; } - (void)setProgress:(CGFloat)progress animated:(BOOL)animated initialDelay:(CFTimeInterval)initialDelay { CGFloat pinnedProgress = MIN(MAX(progress, 0.0f), 1.0f); [self setProgress:progress animated:animated initialDelay:initialDelay withDuration:fabs(self.progress - pinnedProgress)]; } - (void)setProgress:(CGFloat)progress animated:(BOOL)animated initialDelay:(CFTimeInterval)initialDelay withDuration:(CFTimeInterval)duration { [self.layer removeAnimationForKey:@"indeterminateAnimation"]; [self.circularProgressLayer removeAnimationForKey:@"progress"]; CGFloat pinnedProgress = MIN(MAX(progress, 0.0f), 1.0f); if (animated) { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"progress"]; animation.duration = duration; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; animation.fillMode = kCAFillModeForwards; animation.fromValue = [NSNumber numberWithFloat:self.progress]; animation.toValue = [NSNumber numberWithFloat:pinnedProgress]; animation.beginTime = CACurrentMediaTime() + initialDelay; animation.delegate = self; [self.circularProgressLayer addAnimation:animation forKey:@"progress"]; } else { [self.circularProgressLayer setNeedsDisplay]; self.circularProgressLayer.progress = pinnedProgress; } } - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag { NSNumber *pinnedProgressNumber = [animation valueForKey:@"toValue"]; self.circularProgressLayer.progress = [pinnedProgressNumber floatValue]; } #pragma mark - UIAppearance methods - (UIColor *)trackTintColor { return self.circularProgressLayer.trackTintColor; } - (void)setTrackTintColor:(UIColor *)trackTintColor { self.circularProgressLayer.trackTintColor = trackTintColor; [self.circularProgressLayer setNeedsDisplay]; } - (UIColor *)progressTintColor { return self.circularProgressLayer.progressTintColor; } - (void)setProgressTintColor:(UIColor *)progressTintColor { self.circularProgressLayer.progressTintColor = progressTintColor; [self.circularProgressLayer setNeedsDisplay]; } - (UIColor *)innerTintColor { return self.circularProgressLayer.innerTintColor; } - (void)setInnerTintColor:(UIColor *)innerTintColor { self.circularProgressLayer.innerTintColor = innerTintColor; [self.circularProgressLayer setNeedsDisplay]; } - (NSInteger)roundedCorners { return self.roundedCorners; } - (void)setRoundedCorners:(NSInteger)roundedCorners { self.circularProgressLayer.roundedCorners = roundedCorners; [self.circularProgressLayer setNeedsDisplay]; } - (CGFloat)thicknessRatio { return self.circularProgressLayer.thicknessRatio; } - (void)setThicknessRatio:(CGFloat)thicknessRatio { self.circularProgressLayer.thicknessRatio = MIN(MAX(thicknessRatio, 0.f), 1.f); [self.circularProgressLayer setNeedsDisplay]; } - (NSInteger)indeterminate { CAAnimation *spinAnimation = [self.layer animationForKey:@"indeterminateAnimation"]; return (spinAnimation == nil ? 0 : 1); } - (void)setIndeterminate:(NSInteger)indeterminate { if (indeterminate) { if (!self.indeterminate) { CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; spinAnimation.byValue = [NSNumber numberWithDouble:indeterminate > 0 ? 2.0f*M_PI : -2.0f*M_PI]; spinAnimation.duration = self.indeterminateDuration; spinAnimation.repeatCount = HUGE_VALF; [self.layer addAnimation:spinAnimation forKey:@"indeterminateAnimation"]; } } else { [self.layer removeAnimationForKey:@"indeterminateAnimation"]; } } - (NSInteger)clockwiseProgress { return self.circularProgressLayer.clockwiseProgress; } - (void)setClockwiseProgress:(NSInteger)clockwiseProgres { self.circularProgressLayer.clockwiseProgress = clockwiseProgres; [self.circularProgressLayer setNeedsDisplay]; } @end ================================================ FILE: Pods/DACircularProgress/DACircularProgress/DALabeledCircularProgressView.h ================================================ // // DALabeledCircularProgressView.h // DACircularProgressExample // // Created by Josh Sklar on 4/8/14. // Copyright (c) 2014 Shout Messenger. All rights reserved. // #import "DACircularProgressView.h" /** @class DALabeledCircularProgressView @brief Subclass of DACircularProgressView that adds a UILabel. */ @interface DALabeledCircularProgressView : DACircularProgressView /** UILabel placed right on the DACircularProgressView. */ @property (strong, nonatomic) UILabel *progressLabel; @end ================================================ FILE: Pods/DACircularProgress/DACircularProgress/DALabeledCircularProgressView.m ================================================ // // DALabeledCircularProgressView.m // DACircularProgressExample // // Created by Josh Sklar on 4/8/14. // Copyright (c) 2014 Shout Messenger. All rights reserved. // #import "DALabeledCircularProgressView.h" @implementation DALabeledCircularProgressView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initializeLabel]; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self initializeLabel]; } return self; } #pragma mark - Internal methods /** Creates and initializes -[DALabeledCircularProgressView progressLabel]. */ - (void)initializeLabel { self.progressLabel = [[UILabel alloc] initWithFrame:self.bounds]; self.progressLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; self.progressLabel.textAlignment = NSTextAlignmentCenter; self.progressLabel.backgroundColor = [UIColor clearColor]; [self addSubview:self.progressLabel]; } @end ================================================ FILE: Pods/DACircularProgress/LICENSE.md ================================================ # License ## MIT License Copyright (c) 2013 Daniel Amitay (http://danielamitay.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/DACircularProgress/README.md ================================================ ## DACircularProgress `DACircularProgress` is a `UIView` subclass with circular `UIProgressView` properties. It was originally built to be an imitation of Facebook's photo progress indicator. View the included example project for a demonstration. ![Screenshot](https://github.com/danielamitay/DACircularProgress/raw/master/screenshot.png) ## Installation To use `DACircularProgress`: - Copy over the `DACircularProgress` folder to your project folder. - Make sure that your project includes ``. - `#import "DACircularProgressView.h"` ### Example Code ```objective-c self.progressView = [[DACircularProgressView alloc] initWithFrame:CGRectMake(140.0f, 30.0f, 40.0f, 40.0f)]; self.progressView.roundedCorners = YES; self.progressView.trackTintColor = [UIColor clearColor]; [self.view addSubview:self.progressView]; ``` - You can also use Interface Builder by adding a `UIView` element and setting its class to `DACircularProgress` ## Notes ### Compatibility iOS5.0+ ### Automatic Reference Counting (ARC) support `DACircularProgress` was made with ARC enabled by default. ## Contact - [Personal website](http://danielamitay.com) - [GitHub](http://github.com/danielamitay) - [Twitter](http://twitter.com/danielamitay) - [LinkedIn](http://www.linkedin.com/in/danielamitay) - [Email](hello@danielamitay.com) If you use/enjoy `DACircularProgress`, let me know! ## Credits `DACircularProgress` is brought to you by [Daniel Amitay](http://www.amitay.us) and [contributors to the project](https://github.com/danielamitay/DACircularProgress/contributors). A special thanks to [Cédric Luthi](https://github.com/0xced) for a significant amount of changes. If you have feature suggestions or bug reports, feel free to help out by sending pull requests or by [creating new issues](https://github.com/danielamitay/DACircularProgress/issues/new). ## License ### MIT License Copyright (c) 2013 Daniel Amitay (http://danielamitay.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/MJExtension/LICENSE ================================================ Copyright (c) 2013-2015 MJExtension (https://github.com/CoderMJLee/MJExtension) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/MJExtension/MJExtension/MJExtension.h ================================================ // // MJExtension.h // MJExtension // // Created by mj on 14-1-15. // Copyright (c) 2014年 小码哥. All rights reserved. // 代码地址:https://github.com/CoderMJLee/MJExtension // 代码地址:http://code4app.com/ios/%E5%AD%97%E5%85%B8-JSON-%E4%B8%8E%E6%A8%A1%E5%9E%8B%E7%9A%84%E8%BD%AC%E6%8D%A2/5339992a933bf062608b4c57 #import "NSObject+MJCoding.h" #import "NSObject+MJProperty.h" #import "NSObject+MJClass.h" #import "NSObject+MJKeyValue.h" #import "NSString+MJExtension.h" #import "MJExtensionConst.h" ================================================ FILE: Pods/MJExtension/MJExtension/MJExtensionConst.h ================================================ #ifndef __MJExtensionConst__H__ #define __MJExtensionConst__H__ #import // 过期 #define MJExtensionDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead) // 构建错误 #define MJExtensionBuildError(clazz, msg) \ NSError *error = [NSError errorWithDomain:msg code:250 userInfo:nil]; \ [clazz setMj_error:error]; // 日志输出 #ifdef DEBUG #define MJExtensionLog(...) NSLog(__VA_ARGS__) #else #define MJExtensionLog(...) #endif /** * 断言 * @param condition 条件 * @param returnValue 返回值 */ #define MJExtensionAssertError(condition, returnValue, clazz, msg) \ [clazz setMj_error:nil]; \ if ((condition) == NO) { \ MJExtensionBuildError(clazz, msg); \ return returnValue;\ } #define MJExtensionAssert2(condition, returnValue) \ if ((condition) == NO) return returnValue; /** * 断言 * @param condition 条件 */ #define MJExtensionAssert(condition) MJExtensionAssert2(condition, ) /** * 断言 * @param param 参数 * @param returnValue 返回值 */ #define MJExtensionAssertParamNotNil2(param, returnValue) \ MJExtensionAssert2((param) != nil, returnValue) /** * 断言 * @param param 参数 */ #define MJExtensionAssertParamNotNil(param) MJExtensionAssertParamNotNil2(param, ) /** * 打印所有的属性 */ #define MJLogAllIvars \ -(NSString *)description \ { \ return [self mj_keyValues].description; \ } #define MJExtensionLogAllProperties MJLogAllIvars /** * 类型(属性类型) */ extern NSString *const MJPropertyTypeInt; extern NSString *const MJPropertyTypeShort; extern NSString *const MJPropertyTypeFloat; extern NSString *const MJPropertyTypeDouble; extern NSString *const MJPropertyTypeLong; extern NSString *const MJPropertyTypeLongLong; extern NSString *const MJPropertyTypeChar; extern NSString *const MJPropertyTypeBOOL1; extern NSString *const MJPropertyTypeBOOL2; extern NSString *const MJPropertyTypePointer; extern NSString *const MJPropertyTypeIvar; extern NSString *const MJPropertyTypeMethod; extern NSString *const MJPropertyTypeBlock; extern NSString *const MJPropertyTypeClass; extern NSString *const MJPropertyTypeSEL; extern NSString *const MJPropertyTypeId; #endif ================================================ FILE: Pods/MJExtension/MJExtension/MJExtensionConst.m ================================================ #ifndef __MJExtensionConst__M__ #define __MJExtensionConst__M__ #import /** * 成员变量类型(属性类型) */ NSString *const MJPropertyTypeInt = @"i"; NSString *const MJPropertyTypeShort = @"s"; NSString *const MJPropertyTypeFloat = @"f"; NSString *const MJPropertyTypeDouble = @"d"; NSString *const MJPropertyTypeLong = @"l"; NSString *const MJPropertyTypeLongLong = @"q"; NSString *const MJPropertyTypeChar = @"c"; NSString *const MJPropertyTypeBOOL1 = @"c"; NSString *const MJPropertyTypeBOOL2 = @"b"; NSString *const MJPropertyTypePointer = @"*"; NSString *const MJPropertyTypeIvar = @"^{objc_ivar=}"; NSString *const MJPropertyTypeMethod = @"^{objc_method=}"; NSString *const MJPropertyTypeBlock = @"@?"; NSString *const MJPropertyTypeClass = @"#"; NSString *const MJPropertyTypeSEL = @":"; NSString *const MJPropertyTypeId = @"@"; #endif ================================================ FILE: Pods/MJExtension/MJExtension/MJFoundation.h ================================================ // // MJFoundation.h // MJExtensionExample // // Created by MJ Lee on 14/7/16. // Copyright (c) 2014年 小码哥. All rights reserved. // #import @interface MJFoundation : NSObject + (BOOL)isClassFromFoundation:(Class)c; @end ================================================ FILE: Pods/MJExtension/MJExtension/MJFoundation.m ================================================ // // MJFoundation.m // MJExtensionExample // // Created by MJ Lee on 14/7/16. // Copyright (c) 2014年 小码哥. All rights reserved. // #import "MJFoundation.h" #import "MJExtensionConst.h" #import static NSSet *foundationClasses_; @implementation MJFoundation + (NSSet *)foundationClasses { if (foundationClasses_ == nil) { // 集合中没有NSObject,因为几乎所有的类都是继承自NSObject,具体是不是NSObject需要特殊判断 foundationClasses_ = [NSSet setWithObjects: [NSURL class], [NSDate class], [NSValue class], [NSData class], [NSError class], [NSArray class], [NSDictionary class], [NSString class], [NSAttributedString class], nil]; } return foundationClasses_; } + (BOOL)isClassFromFoundation:(Class)c { if (c == [NSObject class] || c == [NSManagedObject class]) return YES; __block BOOL result = NO; [[self foundationClasses] enumerateObjectsUsingBlock:^(Class foundationClass, BOOL *stop) { if ([c isSubclassOfClass:foundationClass]) { result = YES; *stop = YES; } }]; return result; } @end ================================================ FILE: Pods/MJExtension/MJExtension/MJProperty.h ================================================ // // MJProperty.h // MJExtensionExample // // Created by MJ Lee on 15/4/17. // Copyright (c) 2015年 小码哥. All rights reserved. // 包装一个成员属性 #import #import #import "MJPropertyType.h" #import "MJPropertyKey.h" /** * 包装一个成员 */ @interface MJProperty : NSObject /** 成员属性 */ @property (nonatomic, assign) objc_property_t property; /** 成员属性的名字 */ @property (nonatomic, readonly) NSString *name; /** 成员属性的类型 */ @property (nonatomic, readonly) MJPropertyType *type; /** 成员属性来源于哪个类(可能是父类) */ @property (nonatomic, assign) Class srcClass; /**** 同一个成员属性 - 父类和子类的行为可能不一致(originKey、propertyKeys、objectClassInArray) ****/ /** 设置最原始的key */ - (void)setOriginKey:(id)originKey forClass:(Class)c; /** 对应着字典中的多级key(里面存放的数组,数组里面都是MJPropertyKey对象) */ - (NSArray *)propertyKeysForClass:(Class)c; /** 模型数组中的模型类型 */ - (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c; - (Class)objectClassInArrayForClass:(Class)c; /**** 同一个成员变量 - 父类和子类的行为可能不一致(key、keys、objectClassInArray) ****/ /** * 设置object的成员变量值 */ - (void)setValue:(id)value forObject:(id)object; /** * 得到object的成员属性值 */ - (id)valueForObject:(id)object; /** * 初始化 */ + (instancetype)cachedPropertyWithProperty:(objc_property_t)property; @end ================================================ FILE: Pods/MJExtension/MJExtension/MJProperty.m ================================================ // // MJProperty.m // MJExtensionExample // // Created by MJ Lee on 15/4/17. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJProperty.h" #import "MJFoundation.h" #import "MJExtensionConst.h" #import @interface MJProperty() @property (strong, nonatomic) NSMutableDictionary *propertyKeysDict; @property (strong, nonatomic) NSMutableDictionary *objectClassInArrayDict; @end @implementation MJProperty #pragma mark - 懒加载 - (NSMutableDictionary *)propertyKeysDict { if (!_propertyKeysDict) { _propertyKeysDict = [NSMutableDictionary dictionary]; } return _propertyKeysDict; } - (NSMutableDictionary *)objectClassInArrayDict { if (!_objectClassInArrayDict) { _objectClassInArrayDict = [NSMutableDictionary dictionary]; } return _objectClassInArrayDict; } #pragma mark - 缓存 + (instancetype)cachedPropertyWithProperty:(objc_property_t)property { MJProperty *propertyObj = objc_getAssociatedObject(self, property); if (propertyObj == nil) { propertyObj = [[self alloc] init]; propertyObj.property = property; objc_setAssociatedObject(self, property, propertyObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return propertyObj; } #pragma mark - 公共方法 - (void)setProperty:(objc_property_t)property { _property = property; MJExtensionAssertParamNotNil(property); // 1.属性名 _name = @(property_getName(property)); // 2.成员类型 NSString *attrs = @(property_getAttributes(property)); NSUInteger dotLoc = [attrs rangeOfString:@","].location; NSString *code = nil; NSUInteger loc = 1; if (dotLoc == NSNotFound) { // 没有, code = [attrs substringFromIndex:loc]; } else { code = [attrs substringWithRange:NSMakeRange(loc, dotLoc - loc)]; } _type = [MJPropertyType cachedTypeWithCode:code]; } /** * 获得成员变量的值 */ - (id)valueForObject:(id)object { if (self.type.KVCDisabled) return [NSNull null]; return [object valueForKey:self.name]; } /** * 设置成员变量的值 */ - (void)setValue:(id)value forObject:(id)object { if (self.type.KVCDisabled || value == nil) return; [object setValue:value forKey:self.name]; } /** * 通过字符串key创建对应的keys */ - (NSArray *)propertyKeysWithStringKey:(NSString *)stringKey { if (stringKey.length == 0) return nil; NSMutableArray *propertyKeys = [NSMutableArray array]; // 如果有多级映射 NSArray *oldKeys = [stringKey componentsSeparatedByString:@"."]; for (NSString *oldKey in oldKeys) { NSUInteger start = [oldKey rangeOfString:@"["].location; if (start != NSNotFound) { // 有索引的key NSString *prefixKey = [oldKey substringToIndex:start]; NSString *indexKey = prefixKey; if (prefixKey.length) { MJPropertyKey *propertyKey = [[MJPropertyKey alloc] init]; propertyKey.name = prefixKey; [propertyKeys addObject:propertyKey]; indexKey = [oldKey stringByReplacingOccurrencesOfString:prefixKey withString:@""]; } /** 解析索引 **/ // 元素 NSArray *cmps = [[indexKey stringByReplacingOccurrencesOfString:@"[" withString:@""] componentsSeparatedByString:@"]"]; for (NSInteger i = 0; i typedef enum { MJPropertyKeyTypeDictionary = 0, // 字典的key MJPropertyKeyTypeArray // 数组的key } MJPropertyKeyType; /** * 属性的key */ @interface MJPropertyKey : NSObject /** key的名字 */ @property (copy, nonatomic) NSString *name; /** key的种类,可能是@"10",可能是@"age" */ @property (assign, nonatomic) MJPropertyKeyType type; /** * 根据当前的key,也就是name,从object(字典或者数组)中取值 */ - (id)valueInObject:(id)object; @end ================================================ FILE: Pods/MJExtension/MJExtension/MJPropertyKey.m ================================================ // // MJPropertyKey.m // MJExtensionExample // // Created by MJ Lee on 15/8/11. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJPropertyKey.h" @implementation MJPropertyKey - (id)valueInObject:(id)object { if ([object isKindOfClass:[NSDictionary class]] && self.type == MJPropertyKeyTypeDictionary) { return object[self.name]; } else if ([object isKindOfClass:[NSArray class]] && self.type == MJPropertyKeyTypeArray) { NSArray *array = object; NSUInteger index = self.name.intValue; if (index < array.count) return array[index]; return nil; } return nil; } @end ================================================ FILE: Pods/MJExtension/MJExtension/MJPropertyType.h ================================================ // // MJPropertyType.h // MJExtension // // Created by mj on 14-1-15. // Copyright (c) 2014年 小码哥. All rights reserved. // 包装一种类型 #import /** * 包装一种类型 */ @interface MJPropertyType : NSObject /** 类型标识符 */ @property (nonatomic, copy) NSString *code; /** 是否为id类型 */ @property (nonatomic, readonly, getter=isIdType) BOOL idType; /** 是否为基本数字类型:int、float等 */ @property (nonatomic, readonly, getter=isNumberType) BOOL numberType; /** 是否为BOOL类型 */ @property (nonatomic, readonly, getter=isBoolType) BOOL boolType; /** 对象类型(如果是基本数据类型,此值为nil) */ @property (nonatomic, readonly) Class typeClass; /** 类型是否来自于Foundation框架,比如NSString、NSArray */ @property (nonatomic, readonly, getter = isFromFoundation) BOOL fromFoundation; /** 类型是否不支持KVC */ @property (nonatomic, readonly, getter = isKVCDisabled) BOOL KVCDisabled; /** * 获得缓存的类型对象 */ + (instancetype)cachedTypeWithCode:(NSString *)code; @end ================================================ FILE: Pods/MJExtension/MJExtension/MJPropertyType.m ================================================ // // MJPropertyType.m // MJExtension // // Created by mj on 14-1-15. // Copyright (c) 2014年 小码哥. All rights reserved. // #import "MJPropertyType.h" #import "MJExtension.h" #import "MJFoundation.h" #import "MJExtensionConst.h" @implementation MJPropertyType static NSMutableDictionary *types_; + (void)initialize { types_ = [NSMutableDictionary dictionary]; } + (instancetype)cachedTypeWithCode:(NSString *)code { MJExtensionAssertParamNotNil2(code, nil); MJPropertyType *type = types_[code]; if (type == nil) { type = [[self alloc] init]; type.code = code; types_[code] = type; } return type; } #pragma mark - 公共方法 - (void)setCode:(NSString *)code { _code = code; MJExtensionAssertParamNotNil(code); if ([code isEqualToString:MJPropertyTypeId]) { _idType = YES; } else if (code.length == 0) { _KVCDisabled = YES; } else if (code.length > 3 && [code hasPrefix:@"@\""]) { // 去掉@"和",截取中间的类型名称 _code = [code substringWithRange:NSMakeRange(2, code.length - 3)]; _typeClass = NSClassFromString(_code); _fromFoundation = [MJFoundation isClassFromFoundation:_typeClass]; _numberType = [_typeClass isSubclassOfClass:[NSNumber class]]; } else if ([code isEqualToString:MJPropertyTypeSEL] || [code isEqualToString:MJPropertyTypeIvar] || [code isEqualToString:MJPropertyTypeMethod]) { _KVCDisabled = YES; } // 是否为数字类型 NSString *lowerCode = _code.lowercaseString; NSArray *numberTypes = @[MJPropertyTypeInt, MJPropertyTypeShort, MJPropertyTypeBOOL1, MJPropertyTypeBOOL2, MJPropertyTypeFloat, MJPropertyTypeDouble, MJPropertyTypeLong, MJPropertyTypeLongLong, MJPropertyTypeChar]; if ([numberTypes containsObject:lowerCode]) { _numberType = YES; if ([lowerCode isEqualToString:MJPropertyTypeBOOL1] || [lowerCode isEqualToString:MJPropertyTypeBOOL2]) { _boolType = YES; } } } @end ================================================ FILE: Pods/MJExtension/MJExtension/NSObject+MJClass.h ================================================ // // NSObject+MJClass.h // MJExtensionExample // // Created by MJ Lee on 15/8/11. // Copyright (c) 2015年 小码哥. All rights reserved. // #import /** * 遍历所有类的block(父类) */ typedef void (^MJClassesEnumeration)(Class c, BOOL *stop); /** 这个数组中的属性名才会进行字典和模型的转换 */ typedef NSArray * (^MJAllowedPropertyNames)(); /** 这个数组中的属性名才会进行归档 */ typedef NSArray * (^MJAllowedCodingPropertyNames)(); /** 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */ typedef NSArray * (^MJIgnoredPropertyNames)(); /** 这个数组中的属性名将会被忽略:不进行归档 */ typedef NSArray * (^MJIgnoredCodingPropertyNames)(); /** * 类相关的扩展 */ @interface NSObject (MJClass) /** * 遍历所有的类 */ + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration; + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration; #pragma mark - 属性白名单配置 /** * 这个数组中的属性名才会进行字典和模型的转换 * * @param allowedPropertyNames 这个数组中的属性名才会进行字典和模型的转换 */ + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames; /** * 这个数组中的属性名才会进行字典和模型的转换 */ + (NSMutableArray *)mj_totalAllowedPropertyNames; #pragma mark - 属性黑名单配置 /** * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 * * @param ignoredPropertyNames 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */ + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames; /** * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */ + (NSMutableArray *)mj_totalIgnoredPropertyNames; #pragma mark - 归档属性白名单配置 /** * 这个数组中的属性名才会进行归档 * * @param allowedCodingPropertyNames 这个数组中的属性名才会进行归档 */ + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames; /** * 这个数组中的属性名才会进行字典和模型的转换 */ + (NSMutableArray *)mj_totalAllowedCodingPropertyNames; #pragma mark - 归档属性黑名单配置 /** * 这个数组中的属性名将会被忽略:不进行归档 * * @param ignoredCodingPropertyNames 这个数组中的属性名将会被忽略:不进行归档 */ + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames; /** * 这个数组中的属性名将会被忽略:不进行归档 */ + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames; #pragma mark - 内部使用 + (void)mj_setupBlockReturnValue:(id (^)())block key:(const char *)key; @end ================================================ FILE: Pods/MJExtension/MJExtension/NSObject+MJClass.m ================================================ // // NSObject+MJClass.m // MJExtensionExample // // Created by MJ Lee on 15/8/11. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "NSObject+MJClass.h" #import "NSObject+MJCoding.h" #import "NSObject+MJKeyValue.h" #import "MJFoundation.h" #import static const char MJAllowedPropertyNamesKey = '\0'; static const char MJIgnoredPropertyNamesKey = '\0'; static const char MJAllowedCodingPropertyNamesKey = '\0'; static const char MJIgnoredCodingPropertyNamesKey = '\0'; static NSMutableDictionary *allowedPropertyNamesDict_; static NSMutableDictionary *ignoredPropertyNamesDict_; static NSMutableDictionary *allowedCodingPropertyNamesDict_; static NSMutableDictionary *ignoredCodingPropertyNamesDict_; @implementation NSObject (MJClass) + (void)load { allowedPropertyNamesDict_ = [NSMutableDictionary dictionary]; ignoredPropertyNamesDict_ = [NSMutableDictionary dictionary]; allowedCodingPropertyNamesDict_ = [NSMutableDictionary dictionary]; ignoredCodingPropertyNamesDict_ = [NSMutableDictionary dictionary]; } + (NSMutableDictionary *)dictForKey:(const void *)key { if (key == &MJAllowedPropertyNamesKey) return allowedPropertyNamesDict_; if (key == &MJIgnoredPropertyNamesKey) return ignoredPropertyNamesDict_; if (key == &MJAllowedCodingPropertyNamesKey) return allowedCodingPropertyNamesDict_; if (key == &MJIgnoredCodingPropertyNamesKey) return ignoredCodingPropertyNamesDict_; return nil; } + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration { // 1.没有block就直接返回 if (enumeration == nil) return; // 2.停止遍历的标记 BOOL stop = NO; // 3.当前正在遍历的类 Class c = self; // 4.开始遍历每一个类 while (c && !stop) { // 4.1.执行操作 enumeration(c, &stop); // 4.2.获得父类 c = class_getSuperclass(c); if ([MJFoundation isClassFromFoundation:c]) break; } } + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration { // 1.没有block就直接返回 if (enumeration == nil) return; // 2.停止遍历的标记 BOOL stop = NO; // 3.当前正在遍历的类 Class c = self; // 4.开始遍历每一个类 while (c && !stop) { // 4.1.执行操作 enumeration(c, &stop); // 4.2.获得父类 c = class_getSuperclass(c); } } #pragma mark - 属性黑名单配置 + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames { [self mj_setupBlockReturnValue:ignoredPropertyNames key:&MJIgnoredPropertyNamesKey]; } + (NSMutableArray *)mj_totalIgnoredPropertyNames { return [self mj_totalObjectsWithSelector:@selector(mj_ignoredPropertyNames) key:&MJIgnoredPropertyNamesKey]; } #pragma mark - 归档属性黑名单配置 + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames { [self mj_setupBlockReturnValue:ignoredCodingPropertyNames key:&MJIgnoredCodingPropertyNamesKey]; } + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames { return [self mj_totalObjectsWithSelector:@selector(mj_ignoredCodingPropertyNames) key:&MJIgnoredCodingPropertyNamesKey]; } #pragma mark - 属性白名单配置 + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames; { [self mj_setupBlockReturnValue:allowedPropertyNames key:&MJAllowedPropertyNamesKey]; } + (NSMutableArray *)mj_totalAllowedPropertyNames { return [self mj_totalObjectsWithSelector:@selector(mj_allowedPropertyNames) key:&MJAllowedPropertyNamesKey]; } #pragma mark - 归档属性白名单配置 + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames { [self mj_setupBlockReturnValue:allowedCodingPropertyNames key:&MJAllowedCodingPropertyNamesKey]; } + (NSMutableArray *)mj_totalAllowedCodingPropertyNames { return [self mj_totalObjectsWithSelector:@selector(mj_allowedCodingPropertyNames) key:&MJAllowedCodingPropertyNamesKey]; } #pragma mark - block和方法处理:存储block的返回值 + (void)mj_setupBlockReturnValue:(id (^)())block key:(const char *)key { if (block) { objc_setAssociatedObject(self, key, block(), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } else { objc_setAssociatedObject(self, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } // 清空数据 [[self dictForKey:key] removeAllObjects]; } + (NSMutableArray *)mj_totalObjectsWithSelector:(SEL)selector key:(const char *)key { NSMutableArray *array = [self dictForKey:key][NSStringFromClass(self)]; if (array) return array; // 创建、存储 [self dictForKey:key][NSStringFromClass(self)] = array = [NSMutableArray array]; if ([self respondsToSelector:selector]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" NSArray *subArray = [self performSelector:selector]; #pragma clang diagnostic pop if (subArray) { [array addObjectsFromArray:subArray]; } } [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { NSArray *subArray = objc_getAssociatedObject(c, key); [array addObjectsFromArray:subArray]; }]; return array; } @end ================================================ FILE: Pods/MJExtension/MJExtension/NSObject+MJCoding.h ================================================ // // NSObject+MJCoding.h // MJExtension // // Created by mj on 14-1-15. // Copyright (c) 2014年 小码哥. All rights reserved. // #import #import "MJExtensionConst.h" /** * Codeing协议 */ @protocol MJCoding @optional /** * 这个数组中的属性名才会进行归档 */ + (NSArray *)mj_allowedCodingPropertyNames; /** * 这个数组中的属性名将会被忽略:不进行归档 */ + (NSArray *)mj_ignoredCodingPropertyNames; @end @interface NSObject (MJCoding) /** * 解码(从文件中解析对象) */ - (void)mj_decode:(NSCoder *)decoder; /** * 编码(将对象写入文件中) */ - (void)mj_encode:(NSCoder *)encoder; @end /** 归档的实现 */ #define MJCodingImplementation \ - (id)initWithCoder:(NSCoder *)decoder \ { \ if (self = [super init]) { \ [self mj_decode:decoder]; \ } \ return self; \ } \ \ - (void)encodeWithCoder:(NSCoder *)encoder \ { \ [self mj_encode:encoder]; \ } #define MJExtensionCodingImplementation MJCodingImplementation ================================================ FILE: Pods/MJExtension/MJExtension/NSObject+MJCoding.m ================================================ // // NSObject+MJCoding.m // MJExtension // // Created by mj on 14-1-15. // Copyright (c) 2014年 小码哥. All rights reserved. // #import "NSObject+MJCoding.h" #import "NSObject+MJClass.h" #import "NSObject+MJProperty.h" #import "MJProperty.h" @implementation NSObject (MJCoding) - (void)mj_encode:(NSCoder *)encoder { Class clazz = [self class]; NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames]; NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames]; [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { // 检测是否被忽略 if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return; if ([ignoredCodingPropertyNames containsObject:property.name]) return; id value = [property valueForObject:self]; if (value == nil) return; [encoder encodeObject:value forKey:property.name]; }]; } - (void)mj_decode:(NSCoder *)decoder { Class clazz = [self class]; NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames]; NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames]; [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { // 检测是否被忽略 if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return; if ([ignoredCodingPropertyNames containsObject:property.name]) return; id value = [decoder decodeObjectForKey:property.name]; if (value == nil) { // 兼容以前的MJExtension版本 value = [decoder decodeObjectForKey:[@"_" stringByAppendingString:property.name]]; } if (value == nil) return; [property setValue:value forObject:self]; }]; } @end ================================================ FILE: Pods/MJExtension/MJExtension/NSObject+MJKeyValue.h ================================================ // // NSObject+MJKeyValue.h // MJExtension // // Created by mj on 13-8-24. // Copyright (c) 2013年 小码哥. All rights reserved. // #import #import "MJExtensionConst.h" #import #import "MJProperty.h" /** * KeyValue协议 */ @protocol MJKeyValue @optional /** * 只有这个数组中的属性名才允许进行字典和模型的转换 */ + (NSArray *)mj_allowedPropertyNames; /** * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */ + (NSArray *)mj_ignoredPropertyNames; /** * 将属性名换为其他key去字典中取值 * * @return 字典中的key是属性名,value是从字典中取值用的key */ + (NSDictionary *)mj_replacedKeyFromPropertyName; /** * 将属性名换为其他key去字典中取值 * * @return 从字典中取值用的key */ + (NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName; /** * 数组中需要转换的模型类 * * @return 字典中的key是数组属性名,value是数组中存放模型的Class(Class类型或者NSString类型) */ + (NSDictionary *)mj_objectClassInArray; /** * 旧值换新值,用于过滤字典中的值 * * @param oldValue 旧值 * * @return 新值 */ - (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property; /** * 当字典转模型完毕时调用 */ - (void)mj_keyValuesDidFinishConvertingToObject; /** * 当模型转字典完毕时调用 */ - (void)mj_objectDidFinishConvertingToKeyValues; @end @interface NSObject (MJKeyValue) #pragma mark - 类方法 /** * 字典转模型过程中遇到的错误 */ + (NSError *)mj_error; /** * 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来) */ + (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference; #pragma mark - 对象方法 /** * 将字典的键值对转成模型属性 * @param keyValues 字典(可以是NSDictionary、NSData、NSString) */ - (instancetype)mj_setKeyValues:(id)keyValues; /** * 将字典的键值对转成模型属性 * @param keyValues 字典(可以是NSDictionary、NSData、NSString) * @param context CoreData上下文 */ - (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context; /** * 将模型转成字典 * @return 字典 */ - (NSMutableDictionary *)mj_keyValues; - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys; - (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys; /** * 通过模型数组来创建一个字典数组 * @param objectArray 模型数组 * @return 字典数组 */ + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray; + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys; + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys; #pragma mark - 字典转模型 /** * 通过字典来创建一个模型 * @param keyValues 字典(可以是NSDictionary、NSData、NSString) * @return 新建的对象 */ + (instancetype)mj_objectWithKeyValues:(id)keyValues; /** * 通过字典来创建一个CoreData模型 * @param keyValues 字典(可以是NSDictionary、NSData、NSString) * @param context CoreData上下文 * @return 新建的对象 */ + (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context; /** * 通过plist来创建一个模型 * @param filename 文件名(仅限于mainBundle中的文件) * @return 新建的对象 */ + (instancetype)mj_objectWithFilename:(NSString *)filename; /** * 通过plist来创建一个模型 * @param file 文件全路径 * @return 新建的对象 */ + (instancetype)mj_objectWithFile:(NSString *)file; #pragma mark - 字典数组转模型数组 /** * 通过字典数组来创建一个模型数组 * @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString) * @return 模型数组 */ + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray; /** * 通过字典数组来创建一个模型数组 * @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString) * @param context CoreData上下文 * @return 模型数组 */ + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context; /** * 通过plist来创建一个模型数组 * @param filename 文件名(仅限于mainBundle中的文件) * @return 模型数组 */ + (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename; /** * 通过plist来创建一个模型数组 * @param file 文件全路径 * @return 模型数组 */ + (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file; #pragma mark - 转换为JSON /** * 转换为JSON Data */ - (NSData *)mj_JSONData; /** * 转换为字典或者数组 */ - (id)mj_JSONObject; /** * 转换为JSON 字符串 */ - (NSString *)mj_JSONString; @end @interface NSObject (MJKeyValueDeprecated_v_2_5_16) - (instancetype)setKeyValues:(id)keyValue MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (instancetype)setKeyValues:(id)keyValues error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (void)referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSMutableDictionary *)keyValues MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSMutableDictionary *)keyValuesWithError:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (instancetype)objectWithKeyValues:(id)keyValues MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (instancetype)objectWithKeyValues:(id)keyValues error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (instancetype)objectWithFilename:(NSString *)filename MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (instancetype)objectWithFilename:(NSString *)filename error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (instancetype)objectWithFile:(NSString *)file MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (instancetype)objectWithFile:(NSString *)file error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)objectArrayWithFile:(NSString *)file MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSData *)JSONData MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (id)JSONObject MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSString *)JSONString MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); @end ================================================ FILE: Pods/MJExtension/MJExtension/NSObject+MJKeyValue.m ================================================ // // NSObject+MJKeyValue.m // MJExtension // // Created by mj on 13-8-24. // Copyright (c) 2013年 小码哥. All rights reserved. // #import "NSObject+MJKeyValue.h" #import "NSObject+MJProperty.h" #import "NSString+MJExtension.h" #import "MJProperty.h" #import "MJPropertyType.h" #import "MJExtensionConst.h" #import "MJFoundation.h" #import "NSString+MJExtension.h" #import "NSObject+MJClass.h" @implementation NSObject (MJKeyValue) #pragma mark - 错误 static const char MJErrorKey = '\0'; + (NSError *)mj_error { return objc_getAssociatedObject(self, &MJErrorKey); } + (void)setMj_error:(NSError *)error { objc_setAssociatedObject(self, &MJErrorKey, error, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - 模型 -> 字典时的参考 /** 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来) */ static const char MJReferenceReplacedKeyWhenCreatingKeyValuesKey = '\0'; + (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference { objc_setAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey, @(reference), OBJC_ASSOCIATION_ASSIGN); } + (BOOL)mj_isReferenceReplacedKeyWhenCreatingKeyValues { __block id value = objc_getAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey); if (!value) { [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { value = objc_getAssociatedObject(c, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey); if (value) *stop = YES; }]; } return [value boolValue]; } #pragma mark - --常用的对象-- static NSNumberFormatter *numberFormatter_; + (void)load { numberFormatter_ = [[NSNumberFormatter alloc] init]; // 默认设置 [self mj_referenceReplacedKeyWhenCreatingKeyValues:YES]; } #pragma mark - --公共方法-- #pragma mark - 字典 -> 模型 - (instancetype)mj_setKeyValues:(id)keyValues { return [self mj_setKeyValues:keyValues context:nil]; } /** 核心代码: */ - (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context { // 获得JSON对象 keyValues = [keyValues mj_JSONObject]; MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], self, [self class], @"keyValues参数不是一个字典"); Class clazz = [self class]; NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames]; NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames]; //通过封装的方法回调一个通过运行时编写的,用于返回属性列表的方法。 [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { @try { // 0.检测是否被忽略 if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return; if ([ignoredPropertyNames containsObject:property.name]) return; // 1.取出属性值 id value; NSArray *propertyKeyses = [property propertyKeysForClass:clazz]; for (NSArray *propertyKeys in propertyKeyses) { value = keyValues; for (MJPropertyKey *propertyKey in propertyKeys) { value = [propertyKey valueInObject:value]; } if (value) break; } // 值的过滤 id newValue = [clazz mj_getNewValueFromObject:self oldValue:value property:property]; if (newValue != value) { // 有过滤后的新值 [property setValue:newValue forObject:self]; return; } // 如果没有值,就直接返回 if (!value || value == [NSNull null]) return; // 2.复杂处理 MJPropertyType *type = property.type; Class propertyClass = type.typeClass; Class objectClass = [property objectClassInArrayForClass:[self class]]; // 不可变 -> 可变处理 if (propertyClass == [NSMutableArray class] && [value isKindOfClass:[NSArray class]]) { value = [NSMutableArray arrayWithArray:value]; } else if (propertyClass == [NSMutableDictionary class] && [value isKindOfClass:[NSDictionary class]]) { value = [NSMutableDictionary dictionaryWithDictionary:value]; } else if (propertyClass == [NSMutableString class] && [value isKindOfClass:[NSString class]]) { value = [NSMutableString stringWithString:value]; } else if (propertyClass == [NSMutableData class] && [value isKindOfClass:[NSData class]]) { value = [NSMutableData dataWithData:value]; } if (!type.isFromFoundation && propertyClass) { // 模型属性 value = [propertyClass mj_objectWithKeyValues:value context:context]; } else if (objectClass) { if (objectClass == [NSURL class] && [value isKindOfClass:[NSArray class]]) { // string array -> url array NSMutableArray *urlArray = [NSMutableArray array]; for (NSString *string in value) { if (![string isKindOfClass:[NSString class]]) continue; [urlArray addObject:string.mj_url]; } value = urlArray; } else { // 字典数组-->模型数组 value = [objectClass mj_objectArrayWithKeyValuesArray:value context:context]; } } else { if (propertyClass == [NSString class]) { if ([value isKindOfClass:[NSNumber class]]) { // NSNumber -> NSString value = [value description]; } else if ([value isKindOfClass:[NSURL class]]) { // NSURL -> NSString value = [value absoluteString]; } } else if ([value isKindOfClass:[NSString class]]) { if (propertyClass == [NSURL class]) { // NSString -> NSURL // 字符串转码 value = [value mj_url]; } else if (type.isNumberType) { NSString *oldValue = value; // NSString -> NSNumber if (type.typeClass == [NSDecimalNumber class]) { value = [NSDecimalNumber decimalNumberWithString:oldValue]; } else { value = [numberFormatter_ numberFromString:oldValue]; } // 如果是BOOL if (type.isBoolType) { // 字符串转BOOL(字符串没有charValue方法) // 系统会调用字符串的charValue转为BOOL类型 NSString *lower = [oldValue lowercaseString]; if ([lower isEqualToString:@"yes"] || [lower isEqualToString:@"true"]) { value = @YES; } else if ([lower isEqualToString:@"no"] || [lower isEqualToString:@"false"]) { value = @NO; } } } } // value和property类型不匹配 if (propertyClass && ![value isKindOfClass:propertyClass]) { value = nil; } } // 3.赋值 [property setValue:value forObject:self]; } @catch (NSException *exception) { MJExtensionBuildError([self class], exception.reason); MJExtensionLog(@"%@", exception); } }]; // 转换完毕 if ([self respondsToSelector:@selector(mj_keyValuesDidFinishConvertingToObject)]) { [self mj_keyValuesDidFinishConvertingToObject]; } return self; } + (instancetype)mj_objectWithKeyValues:(id)keyValues { return [self mj_objectWithKeyValues:keyValues context:nil]; } + (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context { // 获得JSON对象 keyValues = [keyValues mj_JSONObject]; MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], nil, [self class], @"keyValues参数不是一个字典"); if ([self isSubclassOfClass:[NSManagedObject class]] && context) { return [[NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass(self) inManagedObjectContext:context] mj_setKeyValues:keyValues context:context]; } return [[[self alloc] init] mj_setKeyValues:keyValues]; } + (instancetype)mj_objectWithFilename:(NSString *)filename { MJExtensionAssertError(filename != nil, nil, [self class], @"filename参数为nil"); return [self mj_objectWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil]]; } + (instancetype)mj_objectWithFile:(NSString *)file { MJExtensionAssertError(file != nil, nil, [self class], @"file参数为nil"); return [self mj_objectWithKeyValues:[NSDictionary dictionaryWithContentsOfFile:file]]; } #pragma mark - 字典数组 -> 模型数组 + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray { return [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:nil]; } + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context { // 如果是JSON字符串 keyValuesArray = [keyValuesArray mj_JSONObject]; // 1.判断真实性 MJExtensionAssertError([keyValuesArray isKindOfClass:[NSArray class]], nil, [self class], @"keyValuesArray参数不是一个数组"); // 如果数组里面放的是NSString、NSNumber等数据 if ([MJFoundation isClassFromFoundation:self]) return [NSMutableArray arrayWithArray:keyValuesArray]; // 2.创建数组 NSMutableArray *modelArray = [NSMutableArray array]; // 3.遍历 for (NSDictionary *keyValues in keyValuesArray) { if ([keyValues isKindOfClass:[NSArray class]]){ [modelArray addObject:[self mj_objectArrayWithKeyValuesArray:keyValues context:context]]; } else { id model = [self mj_objectWithKeyValues:keyValues context:context]; if (model) [modelArray addObject:model]; } } return modelArray; } + (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename { MJExtensionAssertError(filename != nil, nil, [self class], @"filename参数为nil"); return [self mj_objectArrayWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil]]; } + (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file { MJExtensionAssertError(file != nil, nil, [self class], @"file参数为nil"); return [self mj_objectArrayWithKeyValuesArray:[NSArray arrayWithContentsOfFile:file]]; } #pragma mark - 模型 -> 字典 - (NSMutableDictionary *)mj_keyValues { return [self mj_keyValuesWithKeys:nil ignoredKeys:nil]; } - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys { return [self mj_keyValuesWithKeys:keys ignoredKeys:nil]; } - (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys { return [self mj_keyValuesWithKeys:nil ignoredKeys:ignoredKeys]; } - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys { // 如果自己不是模型类, 那就返回自己 MJExtensionAssertError(![MJFoundation isClassFromFoundation:[self class]], (NSMutableDictionary *)self, [self class], @"不是自定义的模型类") id keyValues = [NSMutableDictionary dictionary]; Class clazz = [self class]; NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames]; NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames]; [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { @try { // 0.检测是否被忽略 if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return; if ([ignoredPropertyNames containsObject:property.name]) return; if (keys.count && ![keys containsObject:property.name]) return; if ([ignoredKeys containsObject:property.name]) return; // 1.取出属性值 id value = [property valueForObject:self]; if (!value) return; // 2.如果是模型属性 MJPropertyType *type = property.type; Class propertyClass = type.typeClass; if (!type.isFromFoundation && propertyClass) { value = [value mj_keyValues]; } else if ([value isKindOfClass:[NSArray class]]) { // 3.处理数组里面有模型的情况 value = [NSObject mj_keyValuesArrayWithObjectArray:value]; } else if (propertyClass == [NSURL class]) { value = [value absoluteString]; } // 4.赋值 if ([clazz mj_isReferenceReplacedKeyWhenCreatingKeyValues]) { NSArray *propertyKeys = [[property propertyKeysForClass:clazz] firstObject]; NSUInteger keyCount = propertyKeys.count; // 创建字典 __block id innerContainer = keyValues; [propertyKeys enumerateObjectsUsingBlock:^(MJPropertyKey *propertyKey, NSUInteger idx, BOOL *stop) { // 下一个属性 MJPropertyKey *nextPropertyKey = nil; if (idx != keyCount - 1) { nextPropertyKey = propertyKeys[idx + 1]; } if (nextPropertyKey) { // 不是最后一个key // 当前propertyKey对应的字典或者数组 id tempInnerContainer = [propertyKey valueInObject:innerContainer]; if (tempInnerContainer == nil || [tempInnerContainer isKindOfClass:[NSNull class]]) { if (nextPropertyKey.type == MJPropertyKeyTypeDictionary) { tempInnerContainer = [NSMutableDictionary dictionary]; } else { tempInnerContainer = [NSMutableArray array]; } if (propertyKey.type == MJPropertyKeyTypeDictionary) { innerContainer[propertyKey.name] = tempInnerContainer; } else { innerContainer[propertyKey.name.intValue] = tempInnerContainer; } } if ([tempInnerContainer isKindOfClass:[NSMutableArray class]]) { NSMutableArray *tempInnerContainerArray = tempInnerContainer; int index = nextPropertyKey.name.intValue; while (tempInnerContainerArray.count < index + 1) { [tempInnerContainerArray addObject:[NSNull null]]; } } innerContainer = tempInnerContainer; } else { // 最后一个key if (propertyKey.type == MJPropertyKeyTypeDictionary) { innerContainer[propertyKey.name] = value; } else { innerContainer[propertyKey.name.intValue] = value; } } }]; } else { keyValues[property.name] = value; } } @catch (NSException *exception) { MJExtensionBuildError([self class], exception.reason); MJExtensionLog(@"%@", exception); } }]; // 转换完毕 if ([self respondsToSelector:@selector(mj_objectDidFinishConvertingToKeyValues)]) { [self mj_objectDidFinishConvertingToKeyValues]; } return keyValues; } #pragma mark - 模型数组 -> 字典数组 + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray { return [self mj_keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:nil]; } + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys { return [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys ignoredKeys:nil]; } + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys { return [self mj_keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:ignoredKeys]; } + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys { // 0.判断真实性 MJExtensionAssertError([objectArray isKindOfClass:[NSArray class]], nil, [self class], @"objectArray参数不是一个数组"); // 1.创建数组 NSMutableArray *keyValuesArray = [NSMutableArray array]; for (id object in objectArray) { if (keys) { [keyValuesArray addObject:[object mj_keyValuesWithKeys:keys]]; } else { [keyValuesArray addObject:[object mj_keyValuesWithIgnoredKeys:ignoredKeys]]; } } return keyValuesArray; } #pragma mark - 转换为JSON - (NSData *)mj_JSONData { if ([self isKindOfClass:[NSString class]]) { return [((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding]; } else if ([self isKindOfClass:[NSData class]]) { return (NSData *)self; } return [NSJSONSerialization dataWithJSONObject:[self mj_JSONObject] options:kNilOptions error:nil]; } - (id)mj_JSONObject { if ([self isKindOfClass:[NSString class]]) { return [NSJSONSerialization JSONObjectWithData:[((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil]; } else if ([self isKindOfClass:[NSData class]]) { return [NSJSONSerialization JSONObjectWithData:(NSData *)self options:kNilOptions error:nil]; } return self.mj_keyValues; } - (NSString *)mj_JSONString { if ([self isKindOfClass:[NSString class]]) { return (NSString *)self; } else if ([self isKindOfClass:[NSData class]]) { return [[NSString alloc] initWithData:(NSData *)self encoding:NSUTF8StringEncoding]; } return [[NSString alloc] initWithData:[self mj_JSONData] encoding:NSUTF8StringEncoding]; } @end @implementation NSObject (MJKeyValueDeprecated_v_2_5_16) - (instancetype)setKeyValues:(id)keyValues { return [self mj_setKeyValues:keyValues]; } - (instancetype)setKeyValues:(id)keyValues error:(NSError **)error { id value = [self mj_setKeyValues:keyValues]; if (error != NULL) { *error = [self.class mj_error]; } return value; } - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context { return [self mj_setKeyValues:keyValues context:context]; } - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error { id value = [self mj_setKeyValues:keyValues context:context]; if (error != NULL) { *error = [self.class mj_error]; } return value; } + (void)referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference { [self mj_referenceReplacedKeyWhenCreatingKeyValues:reference]; } - (NSMutableDictionary *)keyValues { return [self mj_keyValues]; } - (NSMutableDictionary *)keyValuesWithError:(NSError **)error { id value = [self mj_keyValues]; if (error != NULL) { *error = [self.class mj_error]; } return value; } - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys { return [self mj_keyValuesWithKeys:keys]; } - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError **)error { id value = [self mj_keyValuesWithKeys:keys]; if (error != NULL) { *error = [self.class mj_error]; } return value; } - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys { return [self mj_keyValuesWithIgnoredKeys:ignoredKeys]; } - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError **)error { id value = [self mj_keyValuesWithIgnoredKeys:ignoredKeys]; if (error != NULL) { *error = [self.class mj_error]; } return value; } + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray { return [self mj_keyValuesArrayWithObjectArray:objectArray]; } + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError **)error { id value = [self mj_keyValuesArrayWithObjectArray:objectArray]; if (error != NULL) { *error = [self mj_error]; } return value; } + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys { return [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys]; } + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError **)error { id value = [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys]; if (error != NULL) { *error = [self mj_error]; } return value; } + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys { return [self mj_keyValuesArrayWithObjectArray:objectArray ignoredKeys:ignoredKeys]; } + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError **)error { id value = [self mj_keyValuesArrayWithObjectArray:objectArray ignoredKeys:ignoredKeys]; if (error != NULL) { *error = [self mj_error]; } return value; } + (instancetype)objectWithKeyValues:(id)keyValues { return [self mj_objectWithKeyValues:keyValues]; } + (instancetype)objectWithKeyValues:(id)keyValues error:(NSError **)error { id value = [self mj_objectWithKeyValues:keyValues]; if (error != NULL) { *error = [self mj_error]; } return value; } + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context { return [self mj_objectWithKeyValues:keyValues context:context]; } + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error { id value = [self mj_objectWithKeyValues:keyValues context:context]; if (error != NULL) { *error = [self mj_error]; } return value; } + (instancetype)objectWithFilename:(NSString *)filename { return [self mj_objectWithFilename:filename]; } + (instancetype)objectWithFilename:(NSString *)filename error:(NSError **)error { id value = [self mj_objectWithFilename:filename]; if (error != NULL) { *error = [self mj_error]; } return value; } + (instancetype)objectWithFile:(NSString *)file { return [self mj_objectWithFile:file]; } + (instancetype)objectWithFile:(NSString *)file error:(NSError **)error { id value = [self mj_objectWithFile:file]; if (error != NULL) { *error = [self mj_error]; } return value; } + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray { return [self mj_objectArrayWithKeyValuesArray:keyValuesArray]; } + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray error:(NSError **)error { id value = [self mj_objectArrayWithKeyValuesArray:keyValuesArray]; if (error != NULL) { *error = [self mj_error]; } return value; } + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context { return [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:context]; } + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError **)error { id value = [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:context]; if (error != NULL) { *error = [self mj_error]; } return value; } + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename { return [self mj_objectArrayWithFilename:filename]; } + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError **)error { id value = [self mj_objectArrayWithFilename:filename]; if (error != NULL) { *error = [self mj_error]; } return value; } + (NSMutableArray *)objectArrayWithFile:(NSString *)file { return [self mj_objectArrayWithFile:file]; } + (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError **)error { id value = [self mj_objectArrayWithFile:file]; if (error != NULL) { *error = [self mj_error]; } return value; } - (NSData *)JSONData { return [self mj_JSONData]; } - (id)JSONObject { return [self mj_JSONObject]; } - (NSString *)JSONString { return [self mj_JSONString]; } @end ================================================ FILE: Pods/MJExtension/MJExtension/NSObject+MJProperty.h ================================================ // // NSObject+MJProperty.h // MJExtensionExample // // Created by MJ Lee on 15/4/17. // Copyright (c) 2015年 小码哥. All rights reserved. // #import #import "MJExtensionConst.h" @class MJProperty; /** * 遍历成员变量用的block * * @param property 成员的包装对象 * @param stop YES代表停止遍历,NO代表继续遍历 */ typedef void (^MJPropertiesEnumeration)(MJProperty *property, BOOL *stop); /** 将属性名换为其他key去字典中取值 */ typedef NSDictionary * (^MJReplacedKeyFromPropertyName)(); typedef NSString * (^MJReplacedKeyFromPropertyName121)(NSString *propertyName); /** 数组中需要转换的模型类 */ typedef NSDictionary * (^MJObjectClassInArray)(); /** 用于过滤字典中的值 */ typedef id (^MJNewValueFromOldValue)(id object, id oldValue, MJProperty *property); /** * 成员属性相关的扩展 */ @interface NSObject (MJProperty) #pragma mark - 遍历 /** * 遍历所有的成员 */ + (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration; #pragma mark - 新值配置 /** * 用于过滤字典中的值 * * @param newValueFormOldValue 用于过滤字典中的值 */ + (void)mj_setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue; + (id)mj_getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property; #pragma mark - key配置 /** * 将属性名换为其他key去字典中取值 * * @param replacedKeyFromPropertyName 将属性名换为其他key去字典中取值 */ + (void)mj_setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName; /** * 将属性名换为其他key去字典中取值 * * @param replacedKeyFromPropertyName121 将属性名换为其他key去字典中取值 */ + (void)mj_setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121; #pragma mark - array model class配置 /** * 数组中需要转换的模型类 * * @param objectClassInArray 数组中需要转换的模型类 */ + (void)mj_setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray; @end @interface NSObject (MJPropertyDeprecated_v_2_5_16) + (void)enumerateProperties:(MJPropertiesEnumeration)enumeration MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (void)setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (id)getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (void)setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (void)setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121 MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); + (void)setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); @end ================================================ FILE: Pods/MJExtension/MJExtension/NSObject+MJProperty.m ================================================ // // NSObject+MJProperty.m // MJExtensionExample // // Created by MJ Lee on 15/4/17. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "NSObject+MJProperty.h" #import "NSObject+MJKeyValue.h" #import "NSObject+MJCoding.h" #import "NSObject+MJClass.h" #import "MJProperty.h" #import "MJFoundation.h" #import #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wundeclared-selector" #pragma clang diagnostic ignored "-Warc-performSelector-leaks" static const char MJReplacedKeyFromPropertyNameKey = '\0'; static const char MJReplacedKeyFromPropertyName121Key = '\0'; static const char MJNewValueFromOldValueKey = '\0'; static const char MJObjectClassInArrayKey = '\0'; static const char MJCachedPropertiesKey = '\0'; @implementation NSObject (Property) static NSMutableDictionary *replacedKeyFromPropertyNameDict_; static NSMutableDictionary *replacedKeyFromPropertyName121Dict_; static NSMutableDictionary *newValueFromOldValueDict_; static NSMutableDictionary *objectClassInArrayDict_; static NSMutableDictionary *cachedPropertiesDict_; + (void)load { replacedKeyFromPropertyNameDict_ = [NSMutableDictionary dictionary]; replacedKeyFromPropertyName121Dict_ = [NSMutableDictionary dictionary]; newValueFromOldValueDict_ = [NSMutableDictionary dictionary]; objectClassInArrayDict_ = [NSMutableDictionary dictionary]; cachedPropertiesDict_ = [NSMutableDictionary dictionary]; } + (NSMutableDictionary *)dictForKey:(const void *)key { if (key == &MJReplacedKeyFromPropertyNameKey) return replacedKeyFromPropertyNameDict_; if (key == &MJReplacedKeyFromPropertyName121Key) return replacedKeyFromPropertyName121Dict_; if (key == &MJNewValueFromOldValueKey) return newValueFromOldValueDict_; if (key == &MJObjectClassInArrayKey) return objectClassInArrayDict_; if (key == &MJCachedPropertiesKey) return cachedPropertiesDict_; return nil; } #pragma mark - --私有方法-- + (NSString *)propertyKey:(NSString *)propertyName { MJExtensionAssertParamNotNil2(propertyName, nil); __block NSString *key = nil; // 查看有没有需要替换的key if ([self respondsToSelector:@selector(mj_replacedKeyFromPropertyName121:)]) { key = [self mj_replacedKeyFromPropertyName121:propertyName]; } // 兼容旧版本 if ([self respondsToSelector:@selector(replacedKeyFromPropertyName121:)]) { key = [self performSelector:@selector(replacedKeyFromPropertyName121) withObject:propertyName]; } // 调用block if (!key) { [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { MJReplacedKeyFromPropertyName121 block = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyName121Key); if (block) { key = block(propertyName); } if (key) *stop = YES; }]; } // 查看有没有需要替换的key if (!key && [self respondsToSelector:@selector(mj_replacedKeyFromPropertyName)]) { key = [self mj_replacedKeyFromPropertyName][propertyName]; } // 兼容旧版本 if (!key && [self respondsToSelector:@selector(replacedKeyFromPropertyName)]) { key = [self performSelector:@selector(replacedKeyFromPropertyName)][propertyName]; } if (!key) { [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { NSDictionary *dict = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyNameKey); if (dict) { key = dict[propertyName]; } if (key) *stop = YES; }]; } // 2.用属性名作为key if (!key) key = propertyName; return key; } + (Class)propertyObjectClassInArray:(NSString *)propertyName { __block id clazz = nil; if ([self respondsToSelector:@selector(mj_objectClassInArray)]) { clazz = [self mj_objectClassInArray][propertyName]; } // 兼容旧版本 if ([self respondsToSelector:@selector(objectClassInArray)]) { clazz = [self performSelector:@selector(objectClassInArray)][propertyName]; } if (!clazz) { [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { NSDictionary *dict = objc_getAssociatedObject(c, &MJObjectClassInArrayKey); if (dict) { clazz = dict[propertyName]; } if (clazz) *stop = YES; }]; } // 如果是NSString类型 if ([clazz isKindOfClass:[NSString class]]) { clazz = NSClassFromString(clazz); } return clazz; } #pragma mark - --公共方法-- + (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration { // 获得成员变量 NSArray *cachedProperties = [self properties]; // 遍历成员变量 BOOL stop = NO; for (MJProperty *property in cachedProperties) { enumeration(property, &stop); if (stop) break; } } #pragma mark - 公共方法 + (NSMutableArray *)properties { NSMutableArray *cachedProperties = [self dictForKey:&MJCachedPropertiesKey][NSStringFromClass(self)]; if (cachedProperties == nil) { cachedProperties = [NSMutableArray array]; [self mj_enumerateClasses:^(__unsafe_unretained Class c, BOOL *stop) { // 1.获得所有的成员变量 unsigned int outCount = 0; objc_property_t *properties = class_copyPropertyList(c, &outCount); // 2.遍历每一个成员变量 for (unsigned int i = 0; i #import "MJExtensionConst.h" @interface NSString (MJExtension) /** * 驼峰转下划线(loveYou -> love_you) */ - (NSString *)mj_underlineFromCamel; /** * 下划线转驼峰(love_you -> loveYou) */ - (NSString *)mj_camelFromUnderline; /** * 首字母变大写 */ - (NSString *)mj_firstCharUpper; /** * 首字母变小写 */ - (NSString *)mj_firstCharLower; - (BOOL)mj_isPureInt; - (NSURL *)mj_url; @end @interface NSString (MJExtensionDeprecated_v_2_5_16) - (NSString *)underlineFromCamel MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSString *)camelFromUnderline MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSString *)firstCharUpper MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSString *)firstCharLower MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (BOOL)isPureInt MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); - (NSURL *)url MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); @end ================================================ FILE: Pods/MJExtension/MJExtension/NSString+MJExtension.m ================================================ // // NSString+MJExtension.m // MJExtensionExample // // Created by MJ Lee on 15/6/7. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "NSString+MJExtension.h" @implementation NSString (MJExtension) - (NSString *)mj_underlineFromCamel { if (self.length == 0) return self; NSMutableString *string = [NSMutableString string]; for (NSUInteger i = 0; i= 2) [string appendString:[cmp substringFromIndex:1]]; } else { [string appendString:cmp]; } } return string; } - (NSString *)mj_firstCharLower { if (self.length == 0) return self; NSMutableString *string = [NSMutableString string]; [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].lowercaseString]; if (self.length >= 2) [string appendString:[self substringFromIndex:1]]; return string; } - (NSString *)mj_firstCharUpper { if (self.length == 0) return self; NSMutableString *string = [NSMutableString string]; [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].uppercaseString]; if (self.length >= 2) [string appendString:[self substringFromIndex:1]]; return string; } - (BOOL)mj_isPureInt { NSScanner *scan = [NSScanner scannerWithString:self]; int val; return [scan scanInt:&val] && [scan isAtEnd]; } - (NSURL *)mj_url { // [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"!$&'()*+,-./:;=?@_~%#[]"]]; return [NSURL URLWithString:(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8))]; } @end @implementation NSString (MJExtensionDeprecated_v_2_5_16) - (NSString *)underlineFromCamel { return self.mj_underlineFromCamel; } - (NSString *)camelFromUnderline { return self.mj_camelFromUnderline; } - (NSString *)firstCharLower { return self.mj_firstCharLower; } - (NSString *)firstCharUpper { return self.mj_firstCharUpper; } - (BOOL)isPureInt { return self.mj_isPureInt; } - (NSURL *)url { return self.mj_url; } @end ================================================ FILE: Pods/MJExtension/README.md ================================================ ![Logo](http://images.cnitblog.com/blog2015/497279/201505/051004316736641.png) MJExtension === - A fast, convenient and nonintrusive conversion between JSON and model. - 转换速度快、使用简单方便的字典转模型框架 GitHub:[CoderMJLee](https://github.com/CoderMJLee) | Blog:[mjios(Chinese)](http://www.cnblogs.com/mjios) | PR is welcome,or [feedback](mailto:richermj123go@vip.qq.com) ## Contents * [Getting Started 【开始使用】](#Getting_Started) * [Features 【能做什么】](#Features) * [Installation 【安装】](#Installation) * [Examples 【示例】](#Examples) * [JSON -> Model](#JSON_Model) * [JSONString -> Model](#JSONString_Model) * [Model contains model](#Model_contains_model) * [Model contains model-array](#Model_contains_model_array) * [Model name - JSON key mapping](#Model_name_JSON_key_mapping) * [JSON array -> model array](#JSON_array_model_array) * [Model -> JSON](#Model_JSON) * [Model array -> JSON array](#Model_array_JSON_array) * [Core Data](#Core_Data) * [Coding](#Coding) * [Camel -> underline](#Camel_underline) * [NSString -> NSDate, nil -> @""](#NSString_NSDate) * [More use cases](#More_use_cases) --- # Getting Started【开始使用】 ## Features【能做什么】 - MJExtension是一套字典和模型之间互相转换的超轻量级框架 * `JSON` --> `Model`、`Core Data Model` * `JSONString` --> `Model`、`Core Data Model` * `Model`、`Core Data Model` --> `JSON` * `JSON Array` --> `Model Array`、`Core Data Model Array` * `JSONString` --> `Model Array`、`Core Data Model Array` * `Model Array`、`Core Data Model Array` --> `JSON Array` * Coding all properties of model in one line code. * 只需要一行代码,就能实现模型的所有属性进行Coding(归档和解档) ## Installation【安装】 ### From CocoaPods【使用CocoaPods】 ```ruby pod 'MJExtension' ``` ### Manually【手动导入】 - Drag all source files under floder `MJExtension` to your project.【将`MJExtension`文件夹中的所有源代码拽入项目中】 - Import the main header file:`#import "MJExtension.h"`【导入主头文件:`#import "MJExtension.h"`】 ```objc MJExtension.h MJConst.h MJConst.m MJFoundation.h MJFoundation.m MJProperty.h MJProperty.m MJType.h MJType.m NSObject+MJCoding.h NSObject+MJCoding.m NSObject+MJProperty.h NSObject+MJProperty.m NSObject+MJKeyValue.h NSObject+MJKeyValue.m ``` # Examples【示例】 ### The most simple JSON -> Model【最简单的字典转模型】 ```objc typedef enum { SexMale, SexFemale } Sex; @interface User : NSObject @property (copy, nonatomic) NSString *name; @property (copy, nonatomic) NSString *icon; @property (assign, nonatomic) unsigned int age; @property (copy, nonatomic) NSString *height; @property (strong, nonatomic) NSNumber *money; @property (assign, nonatomic) Sex sex; @property (assign, nonatomic, getter=isGay) BOOL gay; @end /***********************************************/ NSDictionary *dict = @{ @"name" : @"Jack", @"icon" : @"lufy.png", @"age" : @20, @"height" : @"1.55", @"money" : @100.9, @"sex" : @(SexFemale), @"gay" : @"true" // @"gay" : @"1" // @"gay" : @"NO" }; // JSON -> User User *user = [User mj_objectWithKeyValues:dict]; NSLog(@"name=%@, icon=%@, age=%zd, height=%@, money=%@, sex=%d, gay=%d", user.name, user.icon, user.age, user.height, user.money, user.sex, user.gay); // name=Jack, icon=lufy.png, age=20, height=1.550000, money=100.9, sex=1 ``` ### JSONString -> Model【JSON字符串转模型】 ```objc // 1.Define a JSONString NSString *jsonString = @"{\"name\":\"Jack\", \"icon\":\"lufy.png\", \"age\":20}"; // 2.JSONString -> User User *user = [User mj_objectWithKeyValues:jsonString]; // 3.Print user's properties NSLog(@"name=%@, icon=%@, age=%d", user.name, user.icon, user.age); // name=Jack, icon=lufy.png, age=20 ``` ### Model contains model【模型中嵌套模型】 ```objc @interface Status : NSObject @property (copy, nonatomic) NSString *text; @property (strong, nonatomic) User *user; @property (strong, nonatomic) Status *retweetedStatus; @end /***********************************************/ NSDictionary *dict = @{ @"text" : @"Agree!Nice weather!", @"user" : @{ @"name" : @"Jack", @"icon" : @"lufy.png" }, @"retweetedStatus" : @{ @"text" : @"Nice weather!", @"user" : @{ @"name" : @"Rose", @"icon" : @"nami.png" } } }; // JSON -> Status Status *status = [Status mj_objectWithKeyValues:dict]; NSString *text = status.text; NSString *name = status.user.name; NSString *icon = status.user.icon; NSLog(@"text=%@, name=%@, icon=%@", text, name, icon); // text=Agree!Nice weather!, name=Jack, icon=lufy.png NSString *text2 = status.retweetedStatus.text; NSString *name2 = status.retweetedStatus.user.name; NSString *icon2 = status.retweetedStatus.user.icon; NSLog(@"text2=%@, name2=%@, icon2=%@", text2, name2, icon2); // text2=Nice weather!, name2=Rose, icon2=nami.png ``` ### Model contains model-array【模型中有个数组属性,数组里面又要装着其他模型】 ```objc @interface Ad : NSObject @property (copy, nonatomic) NSString *image; @property (copy, nonatomic) NSString *url; @end @interface StatusResult : NSObject /** Contatins status model */ @property (strong, nonatomic) NSMutableArray *statuses; /** Contatins ad model */ @property (strong, nonatomic) NSArray *ads; @property (strong, nonatomic) NSNumber *totalNumber; @end /***********************************************/ // Tell MJExtension what type model will be contained in statuses and ads. [StatusResult mj_setupObjectClassInArray:^NSDictionary *{ return @{ @"statuses" : @"Status", // @"statuses" : [Status class], @"ads" : @"Ad" // @"ads" : [Ad class] }; }]; // Equals: StatusResult.m implements +mj_objectClassInArray method. NSDictionary *dict = @{ @"statuses" : @[ @{ @"text" : @"Nice weather!", @"user" : @{ @"name" : @"Rose", @"icon" : @"nami.png" } }, @{ @"text" : @"Go camping tomorrow!", @"user" : @{ @"name" : @"Jack", @"icon" : @"lufy.png" } } ], @"ads" : @[ @{ @"image" : @"ad01.png", @"url" : @"http://www.ad01.com" }, @{ @"image" : @"ad02.png", @"url" : @"http://www.ad02.com" } ], @"totalNumber" : @"2014" }; // JSON -> StatusResult StatusResult *result = [StatusResult mj_objectWithKeyValues:dict]; NSLog(@"totalNumber=%@", result.totalNumber); // totalNumber=2014 // Printing for (Status *status in result.statuses) { NSString *text = status.text; NSString *name = status.user.name; NSString *icon = status.user.icon; NSLog(@"text=%@, name=%@, icon=%@", text, name, icon); } // text=Nice weather!, name=Rose, icon=nami.png // text=Go camping tomorrow!, name=Jack, icon=lufy.png // Printing for (Ad *ad in result.ads) { NSLog(@"image=%@, url=%@", ad.image, ad.url); } // image=ad01.png, url=http://www.ad01.com // image=ad02.png, url=http://www.ad02.com ``` ### Model name - JSON key mapping【模型中的属性名和字典中的key不相同(或者需要多级映射)】 ```objc @interface Bag : NSObject @property (copy, nonatomic) NSString *name; @property (assign, nonatomic) double price; @end @interface Student : NSObject @property (copy, nonatomic) NSString *ID; @property (copy, nonatomic) NSString *desc; @property (copy, nonatomic) NSString *nowName; @property (copy, nonatomic) NSString *oldName; @property (copy, nonatomic) NSString *nameChangedTime; @property (strong, nonatomic) Bag *bag; @end /***********************************************/ // How to map [Student mj_setupReplacedKeyFromPropertyName:^NSDictionary *{ return @{ @"ID" : @"id", @"desc" : @"desciption", @"oldName" : @"name.oldName", @"nowName" : @"name.newName", @"nameChangedTime" : @"name.info[1].nameChangedTime", @"bag" : @"other.bag" }; }]; // Equals: Student.m implements +mj_replacedKeyFromPropertyName method. NSDictionary *dict = @{ @"id" : @"20", @"desciption" : @"kids", @"name" : @{ @"newName" : @"lufy", @"oldName" : @"kitty", @"info" : @[ @"test-data", @{ @"nameChangedTime" : @"2013-08" } ] }, @"other" : @{ @"bag" : @{ @"name" : @"a red bag", @"price" : @100.7 } } }; // JSON -> Student Student *stu = [Student mj_objectWithKeyValues:dict]; // Printing NSLog(@"ID=%@, desc=%@, oldName=%@, nowName=%@, nameChangedTime=%@", stu.ID, stu.desc, stu.oldName, stu.nowName, stu.nameChangedTime); // ID=20, desc=kids, oldName=kitty, nowName=lufy, nameChangedTime=2013-08 NSLog(@"bagName=%@, bagPrice=%f", stu.bag.name, stu.bag.price); // bagName=a red bag, bagPrice=100.700000 ``` ### JSON array -> model array【将一个字典数组转成模型数组】 ```objc NSArray *dictArray = @[ @{ @"name" : @"Jack", @"icon" : @"lufy.png" }, @{ @"name" : @"Rose", @"icon" : @"nami.png" } ]; // JSON array -> User array NSArray *userArray = [User mj_objectArrayWithKeyValuesArray:dictArray]; // Printing for (User *user in userArray) { NSLog(@"name=%@, icon=%@", user.name, user.icon); } // name=Jack, icon=lufy.png // name=Rose, icon=nami.png ``` ### Model -> JSON【将一个模型转成字典】 ```objc // New model User *user = [[User alloc] init]; user.name = @"Jack"; user.icon = @"lufy.png"; Status *status = [[Status alloc] init]; status.user = user; status.text = @"Nice mood!"; // Status -> JSON NSDictionary *statusDict = status.mj_keyValues; NSLog(@"%@", statusDict); /* { text = "Nice mood!"; user = { icon = "lufy.png"; name = Jack; }; } */ // More complex situation Student *stu = [[Student alloc] init]; stu.ID = @"123"; stu.oldName = @"rose"; stu.nowName = @"jack"; stu.desc = @"handsome"; stu.nameChangedTime = @"2018-09-08"; Bag *bag = [[Bag alloc] init]; bag.name = @"a red bag"; bag.price = 205; stu.bag = bag; NSDictionary *stuDict = stu.mj_keyValues; NSLog(@"%@", stuDict); /* { ID = 123; bag = { name = "\U5c0f\U4e66\U5305"; price = 205; }; desc = handsome; nameChangedTime = "2018-09-08"; nowName = jack; oldName = rose; } */ ``` ### Model array -> JSON array【将一个模型数组转成字典数组】 ```objc // New model array User *user1 = [[User alloc] init]; user1.name = @"Jack"; user1.icon = @"lufy.png"; User *user2 = [[User alloc] init]; user2.name = @"Rose"; user2.icon = @"nami.png"; NSArray *userArray = @[user1, user2]; // Model array -> JSON array NSArray *dictArray = [User mj_keyValuesArrayWithObjectArray:userArray]; NSLog(@"%@", dictArray); /* ( { icon = "lufy.png"; name = Jack; }, { icon = "nami.png"; name = Rose; } ) */ ``` ### Core Data ```objc NSDictionary *dict = @{ @"name" : @"Jack", @"icon" : @"lufy.png", @"age" : @20, @"height" : @1.55, @"money" : @"100.9", @"sex" : @(SexFemale), @"gay" : @"true" }; // This demo just provide simple steps NSManagedObjectContext *context = nil; User *user = [User mj_objectWithKeyValues:dict context:context]; [context save:nil]; ``` ### Coding ```objc #import "MJExtension.h" @implementation Bag // NSCoding Implementation MJExtensionCodingImplementation @end /***********************************************/ // what properties not to be coded [Bag mj_setupIgnoredCodingPropertyNames:^NSArray *{ return @[@"name"]; }]; // Equals: Bag.m implements +mj_ignoredCodingPropertyNames method. // Create model Bag *bag = [[Bag alloc] init]; bag.name = @"Red bag"; bag.price = 200.8; NSString *file = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop/bag.data"]; // Encoding [NSKeyedArchiver archiveRootObject:bag toFile:file]; // Decoding Bag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file]; NSLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price); // name=(null), price=200.800000 ``` ### Camel -> underline【统一转换属性名(比如驼峰转下划线)】 ```objc // Dog #import "MJExtension.h" @implementation Dog + (NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName { // nickName -> nick_name return [propertyName mj_underlineFromCamel]; } @end // NSDictionary NSDictionary *dict = @{ @"nick_name" : @"旺财", @"sale_price" : @"10.5", @"run_speed" : @"100.9" }; // NSDictionary -> Dog Dog *dog = [Dog mj_objectWithKeyValues:dict]; // printing NSLog(@"nickName=%@, scalePrice=%f runSpeed=%f", dog.nickName, dog.salePrice, dog.runSpeed); ``` ### NSString -> NSDate, nil -> @""【过滤字典的值(比如字符串日期处理为NSDate、字符串nil处理为@"")】 ```objc // Book #import "MJExtension.h" @implementation Book - (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property { if ([property.name isEqualToString:@"publisher"]) { if (oldValue == nil) return @""; } else if (property.type.typeClass == [NSDate class]) { NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"yyyy-MM-dd"; return [fmt dateFromString:oldValue]; } return oldValue; } @end // NSDictionary NSDictionary *dict = @{ @"name" : @"5分钟突破iOS开发", @"publishedTime" : @"2011-09-10" }; // NSDictionary -> Book Book *book = [Book mj_objectWithKeyValues:dict]; // printing NSLog(@"name=%@, publisher=%@, publishedTime=%@", book.name, book.publisher, book.publishedTime); ``` ### More use cases【更多用法】 - Please reference to `NSObject+MJKeyValue.h` and `NSObject+MJCoding.h` ## 期待 * 如果在使用过程中遇到BUG,希望你能Issues我,谢谢(或者尝试下载最新的框架代码看看BUG修复没有) * 如果在使用过程中发现功能不够用,希望你能Issues我,我非常想为这个框架增加更多好用的功能,谢谢 * 如果你想为MJExtension输出代码,请拼命Pull Requests我 ================================================ FILE: Pods/MJRefresh/LICENSE ================================================ Copyright (c) 2013-2015 MJRefresh (https://github.com/CoderMJLee/MJRefresh) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.h ================================================ // // MJRefreshAutoFooter.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshFooter.h" @interface MJRefreshAutoFooter : MJRefreshFooter /** 是否自动刷新(默认为YES) */ @property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh; /** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */ @property (assign, nonatomic) CGFloat appearencePercentTriggerAutoRefresh MJRefreshDeprecated("请使用automaticallyChangeAlpha属性"); /** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */ @property (assign, nonatomic) CGFloat triggerAutomaticallyRefreshPercent; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.m ================================================ // // MJRefreshAutoFooter.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshAutoFooter.h" @interface MJRefreshAutoFooter() @end @implementation MJRefreshAutoFooter #pragma mark - 初始化 - (void)willMoveToSuperview:(UIView *)newSuperview { [super willMoveToSuperview:newSuperview]; if (newSuperview) { // 新的父控件 if (self.hidden == NO) { self.scrollView.mj_insetB += self.mj_h; } // 设置位置 self.mj_y = _scrollView.mj_contentH; } else { // 被移除了 if (self.hidden == NO) { self.scrollView.mj_insetB -= self.mj_h; } } } #pragma mark - 过期方法 - (void)setAppearencePercentTriggerAutoRefresh:(CGFloat)appearencePercentTriggerAutoRefresh { self.triggerAutomaticallyRefreshPercent = appearencePercentTriggerAutoRefresh; } - (CGFloat)appearencePercentTriggerAutoRefresh { return self.triggerAutomaticallyRefreshPercent; } #pragma mark - 实现父类的方法 - (void)prepare { [super prepare]; // 默认底部控件100%出现时才会自动刷新 self.triggerAutomaticallyRefreshPercent = 1.0; // 设置为默认状态 self.automaticallyRefresh = YES; } - (void)scrollViewContentSizeDidChange:(NSDictionary *)change { [super scrollViewContentSizeDidChange:change]; // 设置位置 self.mj_y = self.scrollView.mj_contentH; } - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change { [super scrollViewContentOffsetDidChange:change]; if (self.state != MJRefreshStateIdle || !self.automaticallyRefresh || self.mj_y == 0) return; if (_scrollView.mj_insetT + _scrollView.mj_contentH > _scrollView.mj_h) { // 内容超过一个屏幕 // 这里的_scrollView.mj_contentH替换掉self.mj_y更为合理 if (_scrollView.mj_offsetY >= _scrollView.mj_contentH - _scrollView.mj_h + self.mj_h * self.triggerAutomaticallyRefreshPercent + _scrollView.mj_insetB - self.mj_h) { // 防止手松开时连续调用 CGPoint old = [change[@"old"] CGPointValue]; CGPoint new = [change[@"new"] CGPointValue]; if (new.y <= old.y) return; // 当底部刷新控件完全出现时,才刷新 [self beginRefreshing]; } } } - (void)scrollViewPanStateDidChange:(NSDictionary *)change { [super scrollViewPanStateDidChange:change]; if (self.state != MJRefreshStateIdle) return; if (_scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded) {// 手松开 if (_scrollView.mj_insetT + _scrollView.mj_contentH <= _scrollView.mj_h) { // 不够一个屏幕 if (_scrollView.mj_offsetY >= - _scrollView.mj_insetT) { // 向上拽 [self beginRefreshing]; } } else { // 超出一个屏幕 if (_scrollView.mj_offsetY >= _scrollView.mj_contentH + _scrollView.mj_insetB - _scrollView.mj_h) { [self beginRefreshing]; } } } } - (void)setState:(MJRefreshState)state { MJRefreshCheckState if (state == MJRefreshStateRefreshing) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self executeRefreshingCallback]; }); } } - (void)setHidden:(BOOL)hidden { BOOL lastHidden = self.isHidden; [super setHidden:hidden]; if (!lastHidden && hidden) { self.state = MJRefreshStateIdle; self.scrollView.mj_insetB -= self.mj_h; } else if (lastHidden && !hidden) { self.scrollView.mj_insetB += self.mj_h; // 设置位置 self.mj_y = _scrollView.mj_contentH; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.h ================================================ // // MJRefreshBackFooter.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshFooter.h" @interface MJRefreshBackFooter : MJRefreshFooter @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.m ================================================ // // MJRefreshBackFooter.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshBackFooter.h" @interface MJRefreshBackFooter() @property (assign, nonatomic) NSInteger lastRefreshCount; @property (assign, nonatomic) CGFloat lastBottomDelta; @end @implementation MJRefreshBackFooter #pragma mark - 初始化 - (void)willMoveToSuperview:(UIView *)newSuperview { [super willMoveToSuperview:newSuperview]; [self scrollViewContentSizeDidChange:nil]; } #pragma mark - 实现父类的方法 - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change { [super scrollViewContentOffsetDidChange:change]; // 如果正在刷新,直接返回 if (self.state == MJRefreshStateRefreshing) return; _scrollViewOriginalInset = self.scrollView.contentInset; // 当前的contentOffset CGFloat currentOffsetY = self.scrollView.mj_offsetY; // 尾部控件刚好出现的offsetY CGFloat happenOffsetY = [self happenOffsetY]; // 如果是向下滚动到看不见尾部控件,直接返回 if (currentOffsetY <= happenOffsetY) return; CGFloat pullingPercent = (currentOffsetY - happenOffsetY) / self.mj_h; // 如果已全部加载,仅设置pullingPercent,然后返回 if (self.state == MJRefreshStateNoMoreData) { self.pullingPercent = pullingPercent; return; } if (self.scrollView.isDragging) { self.pullingPercent = pullingPercent; // 普通 和 即将刷新 的临界点 CGFloat normal2pullingOffsetY = happenOffsetY + self.mj_h; if (self.state == MJRefreshStateIdle && currentOffsetY > normal2pullingOffsetY) { // 转为即将刷新状态 self.state = MJRefreshStatePulling; } else if (self.state == MJRefreshStatePulling && currentOffsetY <= normal2pullingOffsetY) { // 转为普通状态 self.state = MJRefreshStateIdle; } } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开 // 开始刷新 [self beginRefreshing]; } else if (pullingPercent < 1) { self.pullingPercent = pullingPercent; } } - (void)scrollViewContentSizeDidChange:(NSDictionary *)change { [super scrollViewContentSizeDidChange:change]; // 内容的高度 CGFloat contentHeight = self.scrollView.mj_contentH + self.ignoredScrollViewContentInsetBottom; // 表格的高度 CGFloat scrollHeight = self.scrollView.mj_h - self.scrollViewOriginalInset.top - self.scrollViewOriginalInset.bottom + self.ignoredScrollViewContentInsetBottom; // 设置位置和尺寸 self.mj_y = MAX(contentHeight, scrollHeight); } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 根据状态来设置属性 if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) { // 刷新完毕 if (MJRefreshStateRefreshing == oldState) { [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{ self.scrollView.mj_insetB -= self.lastBottomDelta; // 自动调整透明度 if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0; } completion:^(BOOL finished) { self.pullingPercent = 0.0; }]; } CGFloat deltaH = [self heightForContentBreakView]; // 刚刷新完毕 if (MJRefreshStateRefreshing == oldState && deltaH > 0 && self.scrollView.mj_totalDataCount != self.lastRefreshCount) { self.scrollView.mj_offsetY = self.scrollView.mj_offsetY; } } else if (state == MJRefreshStateRefreshing) { // 记录刷新前的数量 self.lastRefreshCount = self.scrollView.mj_totalDataCount; [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{ CGFloat bottom = self.mj_h + self.scrollViewOriginalInset.bottom; CGFloat deltaH = [self heightForContentBreakView]; if (deltaH < 0) { // 如果内容高度小于view的高度 bottom -= deltaH; } self.lastBottomDelta = bottom - self.scrollView.mj_insetB; self.scrollView.mj_insetB = bottom; self.scrollView.mj_offsetY = [self happenOffsetY] + self.mj_h; } completion:^(BOOL finished) { [self executeRefreshingCallback]; }]; } } #pragma mark - 公共方法 - (void)endRefreshing { if ([self.scrollView isKindOfClass:[UICollectionView class]]) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [super endRefreshing]; }); } else { [super endRefreshing]; } } - (void)noticeNoMoreData { if ([self.scrollView isKindOfClass:[UICollectionView class]]) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [super noticeNoMoreData]; }); } else { [super noticeNoMoreData]; } } #pragma mark - 私有方法 #pragma mark 获得scrollView的内容 超出 view 的高度 - (CGFloat)heightForContentBreakView { CGFloat h = self.scrollView.frame.size.height - self.scrollViewOriginalInset.bottom - self.scrollViewOriginalInset.top; return self.scrollView.contentSize.height - h; } #pragma mark 刚好看到上拉刷新控件时的contentOffset.y - (CGFloat)happenOffsetY { CGFloat deltaH = [self heightForContentBreakView]; if (deltaH > 0) { return deltaH - self.scrollViewOriginalInset.top; } else { return - self.scrollViewOriginalInset.top; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.h ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // MJRefreshComponent.h // MJRefreshExample // // Created by MJ Lee on 15/3/4. // Copyright (c) 2015年 小码哥. All rights reserved. // 刷新控件的基类 #import #import "MJRefreshConst.h" #import "UIView+MJExtension.h" #import "UIScrollView+MJExtension.h" #import "UIScrollView+MJRefresh.h" /** 刷新控件的状态 */ typedef NS_ENUM(NSInteger, MJRefreshState) { /** 普通闲置状态 */ MJRefreshStateIdle = 1, /** 松开就可以进行刷新的状态 */ MJRefreshStatePulling, /** 正在刷新中的状态 */ MJRefreshStateRefreshing, /** 即将刷新的状态 */ MJRefreshStateWillRefresh, /** 所有数据加载完毕,没有更多的数据了 */ MJRefreshStateNoMoreData }; /** 进入刷新状态的回调 */ typedef void (^MJRefreshComponentRefreshingBlock)(); /** 刷新控件的基类 */ @interface MJRefreshComponent : UIView { /** 记录scrollView刚开始的inset */ UIEdgeInsets _scrollViewOriginalInset; /** 父控件 */ __weak UIScrollView *_scrollView; } #pragma mark - 刷新回调 /** 正在刷新的回调 */ @property (copy, nonatomic) MJRefreshComponentRefreshingBlock refreshingBlock; /** 设置回调对象和回调方法 */ - (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action; /** 回调对象 */ @property (weak, nonatomic) id refreshingTarget; /** 回调方法 */ @property (assign, nonatomic) SEL refreshingAction; /** 触发回调(交给子类去调用) */ - (void)executeRefreshingCallback; #pragma mark - 刷新状态控制 /** 进入刷新状态 */ - (void)beginRefreshing; /** 结束刷新状态 */ - (void)endRefreshing; /** 是否正在刷新 */ - (BOOL)isRefreshing; /** 刷新状态 一般交给子类内部实现 */ @property (assign, nonatomic) MJRefreshState state; #pragma mark - 交给子类去访问 /** 记录scrollView刚开始的inset */ @property (assign, nonatomic, readonly) UIEdgeInsets scrollViewOriginalInset; /** 父控件 */ @property (weak, nonatomic, readonly) UIScrollView *scrollView; #pragma mark - 交给子类们去实现 /** 初始化 */ - (void)prepare NS_REQUIRES_SUPER; /** 摆放子控件frame */ - (void)placeSubviews NS_REQUIRES_SUPER; /** 当scrollView的contentOffset发生改变的时候调用 */ - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change NS_REQUIRES_SUPER; /** 当scrollView的contentSize发生改变的时候调用 */ - (void)scrollViewContentSizeDidChange:(NSDictionary *)change NS_REQUIRES_SUPER; /** 当scrollView的拖拽状态发生改变的时候调用 */ - (void)scrollViewPanStateDidChange:(NSDictionary *)change NS_REQUIRES_SUPER; #pragma mark - 其他 /** 拉拽的百分比(交给子类重写) */ @property (assign, nonatomic) CGFloat pullingPercent; /** 根据拖拽比例自动切换透明度 */ @property (assign, nonatomic, getter=isAutoChangeAlpha) BOOL autoChangeAlpha MJRefreshDeprecated("请使用automaticallyChangeAlpha属性"); /** 根据拖拽比例自动切换透明度 */ @property (assign, nonatomic, getter=isAutomaticallyChangeAlpha) BOOL automaticallyChangeAlpha; @end @interface UILabel(MJRefresh) + (instancetype)label; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.m ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // MJRefreshComponent.m // MJRefreshExample // // Created by MJ Lee on 15/3/4. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshComponent.h" #import "MJRefreshConst.h" #import "UIView+MJExtension.h" #import "UIScrollView+MJRefresh.h" @interface MJRefreshComponent() @property (strong, nonatomic) UIPanGestureRecognizer *pan; @end @implementation MJRefreshComponent #pragma mark - 初始化 - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // 准备工作 [self prepare]; // 默认是普通状态 self.state = MJRefreshStateIdle; } return self; } - (void)prepare { // 基本属性 self.autoresizingMask = UIViewAutoresizingFlexibleWidth; self.backgroundColor = [UIColor clearColor]; } - (void)layoutSubviews { [super layoutSubviews]; [self placeSubviews]; } - (void)placeSubviews{} - (void)willMoveToSuperview:(UIView *)newSuperview { [super willMoveToSuperview:newSuperview]; // 如果不是UIScrollView,不做任何事情 if (newSuperview && ![newSuperview isKindOfClass:[UIScrollView class]]) return; // 旧的父控件移除监听 [self removeObservers]; if (newSuperview) { // 新的父控件 // 设置宽度 self.mj_w = newSuperview.mj_w; // 设置位置 self.mj_x = 0; // 记录UIScrollView _scrollView = (UIScrollView *)newSuperview; // 设置永远支持垂直弹簧效果 _scrollView.alwaysBounceVertical = YES; // 记录UIScrollView最开始的contentInset _scrollViewOriginalInset = _scrollView.contentInset; // 添加监听 [self addObservers]; } } - (void)drawRect:(CGRect)rect { [super drawRect:rect]; if (self.state == MJRefreshStateWillRefresh) { // 预防view还没显示出来就调用了beginRefreshing self.state = MJRefreshStateRefreshing; } } #pragma mark - KVO监听 - (void)addObservers { NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld; [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentOffset options:options context:nil]; [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentSize options:options context:nil]; self.pan = self.scrollView.panGestureRecognizer; [self.pan addObserver:self forKeyPath:MJRefreshKeyPathPanState options:options context:nil]; } - (void)removeObservers { [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentOffset]; [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentSize];; [self.pan removeObserver:self forKeyPath:MJRefreshKeyPathPanState]; self.pan = nil; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // 遇到这些情况就直接返回 if (!self.userInteractionEnabled) return; // 这个就算看不见也需要处理 if ([keyPath isEqualToString:MJRefreshKeyPathContentSize]) { [self scrollViewContentSizeDidChange:change]; } // 看不见 if (self.hidden) return; if ([keyPath isEqualToString:MJRefreshKeyPathContentOffset]) { [self scrollViewContentOffsetDidChange:change]; } else if ([keyPath isEqualToString:MJRefreshKeyPathPanState]) { [self scrollViewPanStateDidChange:change]; } } - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change{} - (void)scrollViewContentSizeDidChange:(NSDictionary *)change{} - (void)scrollViewPanStateDidChange:(NSDictionary *)change{} #pragma mark - 公共方法 #pragma mark 设置回调对象和回调方法 - (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action { self.refreshingTarget = target; self.refreshingAction = action; } #pragma mark 进入刷新状态 - (void)beginRefreshing { [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{ self.alpha = 1.0; }]; self.pullingPercent = 1.0; // 只要正在刷新,就完全显示 if (self.window) { self.state = MJRefreshStateRefreshing; } else { self.state = MJRefreshStateWillRefresh; // 刷新(预防从另一个控制器回到这个控制器的情况,回来要重新刷新一下) [self setNeedsDisplay]; } } #pragma mark 结束刷新状态 - (void)endRefreshing { self.state = MJRefreshStateIdle; } #pragma mark 是否正在刷新 - (BOOL)isRefreshing { return self.state == MJRefreshStateRefreshing || self.state == MJRefreshStateWillRefresh; } #pragma mark 自动切换透明度 - (void)setAutoChangeAlpha:(BOOL)autoChangeAlpha { self.automaticallyChangeAlpha = autoChangeAlpha; } - (BOOL)isAutoChangeAlpha { return self.isAutomaticallyChangeAlpha; } - (void)setAutomaticallyChangeAlpha:(BOOL)automaticallyChangeAlpha { _automaticallyChangeAlpha = automaticallyChangeAlpha; if (self.isRefreshing) return; if (automaticallyChangeAlpha) { self.alpha = self.pullingPercent; } else { self.alpha = 1.0; } } #pragma mark 根据拖拽进度设置透明度 - (void)setPullingPercent:(CGFloat)pullingPercent { _pullingPercent = pullingPercent; if (self.isRefreshing) return; if (self.isAutomaticallyChangeAlpha) { self.alpha = pullingPercent; } } #pragma mark - 内部方法 - (void)executeRefreshingCallback { dispatch_async(dispatch_get_main_queue(), ^{ if (self.refreshingBlock) { self.refreshingBlock(); } if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) { MJRefreshMsgSend(MJRefreshMsgTarget(self.refreshingTarget), self.refreshingAction, self); } }); } @end @implementation UILabel(MJRefresh) + (instancetype)label { UILabel *label = [[self alloc] init]; label.font = MJRefreshLabelFont; label.textColor = MJRefreshLabelTextColor; label.autoresizingMask = UIViewAutoresizingFlexibleWidth; label.textAlignment = NSTextAlignmentCenter; label.backgroundColor = [UIColor clearColor]; return label; } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.h ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // MJRefreshFooter.h // MJRefreshExample // // Created by MJ Lee on 15/3/5. // Copyright (c) 2015年 小码哥. All rights reserved. // 上拉刷新控件 #import "MJRefreshComponent.h" @interface MJRefreshFooter : MJRefreshComponent /** 创建footer */ + (instancetype)footerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock; /** 创建footer */ + (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; /** 提示没有更多的数据 */ - (void)endRefreshingWithNoMoreData; - (void)noticeNoMoreData MJRefreshDeprecated("使用endRefreshingWithNoMoreData"); /** 重置没有更多的数据(消除没有更多数据的状态) */ - (void)resetNoMoreData; /** 忽略多少scrollView的contentInset的bottom */ @property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom; /** 自动根据有无数据来显示和隐藏(有数据就显示,没有数据隐藏。默认是NO) */ @property (assign, nonatomic, getter=isAutomaticallyHidden) BOOL automaticallyHidden; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.m ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // MJRefreshFooter.m // MJRefreshExample // // Created by MJ Lee on 15/3/5. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshFooter.h" @interface MJRefreshFooter() @end @implementation MJRefreshFooter #pragma mark - 构造方法 + (instancetype)footerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock { MJRefreshFooter *cmp = [[self alloc] init]; cmp.refreshingBlock = refreshingBlock; return cmp; } + (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action { MJRefreshFooter *cmp = [[self alloc] init]; [cmp setRefreshingTarget:target refreshingAction:action]; return cmp; } #pragma mark - 重写父类的方法 - (void)prepare { [super prepare]; // 设置自己的高度 self.mj_h = MJRefreshFooterHeight; // 默认不会自动隐藏 self.automaticallyHidden = NO; } - (void)willMoveToSuperview:(UIView *)newSuperview { [super willMoveToSuperview:newSuperview]; if (newSuperview) { // 监听scrollView数据的变化 if ([self.scrollView isKindOfClass:[UITableView class]] || [self.scrollView isKindOfClass:[UICollectionView class]]) { [self.scrollView setMj_reloadDataBlock:^(NSInteger totalDataCount) { if (self.isAutomaticallyHidden) { self.hidden = (totalDataCount == 0); } }]; } } } #pragma mark - 公共方法 - (void)endRefreshingWithNoMoreData { self.state = MJRefreshStateNoMoreData; } - (void)noticeNoMoreData { [self endRefreshingWithNoMoreData]; } - (void)resetNoMoreData { self.state = MJRefreshStateIdle; } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.h ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // MJRefreshHeader.h // MJRefreshExample // // Created by MJ Lee on 15/3/4. // Copyright (c) 2015年 小码哥. All rights reserved. // 下拉刷新控件:负责监控用户下拉的状态 #import "MJRefreshComponent.h" @interface MJRefreshHeader : MJRefreshComponent /** 创建header */ + (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock; /** 创建header */ + (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; /** 这个key用来存储上一次下拉刷新成功的时间 */ @property (copy, nonatomic) NSString *lastUpdatedTimeKey; /** 上一次下拉刷新成功的时间 */ @property (strong, nonatomic, readonly) NSDate *lastUpdatedTime; /** 忽略多少scrollView的contentInset的top */ @property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetTop; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.m ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // MJRefreshHeader.m // MJRefreshExample // // Created by MJ Lee on 15/3/4. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshHeader.h" @interface MJRefreshHeader() @property (assign, nonatomic) CGFloat insetTDelta; @end @implementation MJRefreshHeader #pragma mark - 构造方法 + (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock { MJRefreshHeader *cmp = [[self alloc] init]; cmp.refreshingBlock = refreshingBlock; return cmp; } + (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action { MJRefreshHeader *cmp = [[self alloc] init]; [cmp setRefreshingTarget:target refreshingAction:action]; return cmp; } #pragma mark - 覆盖父类的方法 - (void)prepare { [super prepare]; // 设置key self.lastUpdatedTimeKey = MJRefreshHeaderLastUpdatedTimeKey; // 设置高度 self.mj_h = MJRefreshHeaderHeight; } - (void)placeSubviews { [super placeSubviews]; // 设置y值(当自己的高度发生改变了,肯定要重新调整Y值,所以放到placeSubviews方法中设置y值) self.mj_y = - self.mj_h - self.ignoredScrollViewContentInsetTop; } - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change { [super scrollViewContentOffsetDidChange:change]; // 在刷新的refreshing状态 if (self.state == MJRefreshStateRefreshing) { if (self.window == nil) return; // sectionheader停留解决 CGFloat insetT = - self.scrollView.mj_offsetY > _scrollViewOriginalInset.top ? - self.scrollView.mj_offsetY : _scrollViewOriginalInset.top; insetT = insetT > self.mj_h + _scrollViewOriginalInset.top ? self.mj_h + _scrollViewOriginalInset.top : insetT; self.scrollView.mj_insetT = insetT; self.insetTDelta = _scrollViewOriginalInset.top - insetT; return; } // 跳转到下一个控制器时,contentInset可能会变 _scrollViewOriginalInset = self.scrollView.contentInset; // 当前的contentOffset CGFloat offsetY = self.scrollView.mj_offsetY; // 头部控件刚好出现的offsetY CGFloat happenOffsetY = - self.scrollViewOriginalInset.top; // 如果是向上滚动到看不见头部控件,直接返回 // >= -> > if (offsetY > happenOffsetY) return; // 普通 和 即将刷新 的临界点 CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_h; CGFloat pullingPercent = (happenOffsetY - offsetY) / self.mj_h; if (self.scrollView.isDragging) { // 如果正在拖拽 self.pullingPercent = pullingPercent; if (self.state == MJRefreshStateIdle && offsetY < normal2pullingOffsetY) { // 转为即将刷新状态 self.state = MJRefreshStatePulling; } else if (self.state == MJRefreshStatePulling && offsetY >= normal2pullingOffsetY) { // 转为普通状态 self.state = MJRefreshStateIdle; } } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开 // 开始刷新 [self beginRefreshing]; } else if (pullingPercent < 1) { self.pullingPercent = pullingPercent; } } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 根据状态做事情 if (state == MJRefreshStateIdle) { if (oldState != MJRefreshStateRefreshing) return; // 保存刷新时间 [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:self.lastUpdatedTimeKey]; [[NSUserDefaults standardUserDefaults] synchronize]; // 恢复inset和offset [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{ self.scrollView.mj_insetT += self.insetTDelta; // 自动调整透明度 if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0; } completion:^(BOOL finished) { self.pullingPercent = 0.0; }]; } else if (state == MJRefreshStateRefreshing) { [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{ // 增加滚动区域 CGFloat top = self.scrollViewOriginalInset.top + self.mj_h; self.scrollView.mj_insetT = top; // 设置滚动位置 self.scrollView.mj_offsetY = - top; } completion:^(BOOL finished) { [self executeRefreshingCallback]; }]; } } - (void)drawRect:(CGRect)rect { [super drawRect:rect]; } #pragma mark - 公共方法 - (void)endRefreshing { if ([self.scrollView isKindOfClass:[UICollectionView class]]) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [super endRefreshing]; }); } else { [super endRefreshing]; } } - (NSDate *)lastUpdatedTime { return [[NSUserDefaults standardUserDefaults] objectForKey:self.lastUpdatedTimeKey]; } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h ================================================ // // MJRefreshAutoGifFooter.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshAutoStateFooter.h" @interface MJRefreshAutoGifFooter : MJRefreshAutoStateFooter @property (weak, nonatomic, readonly) UIImageView *gifView; /** 设置state状态下的动画图片images 动画持续时间duration*/ - (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state; - (void)setImages:(NSArray *)images forState:(MJRefreshState)state; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m ================================================ // // MJRefreshAutoGifFooter.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshAutoGifFooter.h" @interface MJRefreshAutoGifFooter() { __unsafe_unretained UIImageView *_gifView; } /** 所有状态对应的动画图片 */ @property (strong, nonatomic) NSMutableDictionary *stateImages; /** 所有状态对应的动画时间 */ @property (strong, nonatomic) NSMutableDictionary *stateDurations; @end @implementation MJRefreshAutoGifFooter #pragma mark - 懒加载 - (UIImageView *)gifView { if (!_gifView) { UIImageView *gifView = [[UIImageView alloc] init]; [self addSubview:_gifView = gifView]; } return _gifView; } - (NSMutableDictionary *)stateImages { if (!_stateImages) { self.stateImages = [NSMutableDictionary dictionary]; } return _stateImages; } - (NSMutableDictionary *)stateDurations { if (!_stateDurations) { self.stateDurations = [NSMutableDictionary dictionary]; } return _stateDurations; } #pragma mark - 公共方法 - (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state { if (images == nil) return; self.stateImages[@(state)] = images; self.stateDurations[@(state)] = @(duration); /* 根据图片设置控件的高度 */ UIImage *image = [images firstObject]; if (image.size.height > self.mj_h) { self.mj_h = image.size.height; } } - (void)setImages:(NSArray *)images forState:(MJRefreshState)state { [self setImages:images duration:images.count * 0.1 forState:state]; } #pragma mark - 实现父类的方法 - (void)placeSubviews { [super placeSubviews]; if (self.gifView.constraints.count) return; self.gifView.frame = self.bounds; if (self.isRefreshingTitleHidden) { self.gifView.contentMode = UIViewContentModeCenter; } else { self.gifView.contentMode = UIViewContentModeRight; self.gifView.mj_w = self.mj_w * 0.5 - 90; } } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 根据状态做事情 if (state == MJRefreshStateRefreshing) { NSArray *images = self.stateImages[@(state)]; if (images.count == 0) return; [self.gifView stopAnimating]; self.gifView.hidden = NO; if (images.count == 1) { // 单张图片 self.gifView.image = [images lastObject]; } else { // 多张图片 self.gifView.animationImages = images; self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue]; [self.gifView startAnimating]; } } else if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) { [self.gifView stopAnimating]; self.gifView.hidden = YES; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h ================================================ // // MJRefreshAutoNormalFooter.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshAutoStateFooter.h" @interface MJRefreshAutoNormalFooter : MJRefreshAutoStateFooter /** 菊花的样式 */ @property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m ================================================ // // MJRefreshAutoNormalFooter.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshAutoNormalFooter.h" @interface MJRefreshAutoNormalFooter() @property (weak, nonatomic) UIActivityIndicatorView *loadingView; @end @implementation MJRefreshAutoNormalFooter #pragma mark - 懒加载子控件 - (UIActivityIndicatorView *)loadingView { if (!_loadingView) { UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle]; loadingView.hidesWhenStopped = YES; [self addSubview:_loadingView = loadingView]; } return _loadingView; } - (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle { _activityIndicatorViewStyle = activityIndicatorViewStyle; self.loadingView = nil; [self setNeedsLayout]; } #pragma makr - 重写父类的方法 - (void)prepare { [super prepare]; self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; } - (void)placeSubviews { [super placeSubviews]; if (self.loadingView.constraints.count) return; // 圈圈 CGFloat loadingCenterX = self.mj_w * 0.5; if (!self.isRefreshingTitleHidden) { loadingCenterX -= 100; } CGFloat loadingCenterY = self.mj_h * 0.5; self.loadingView.center = CGPointMake(loadingCenterX, loadingCenterY); } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 根据状态做事情 if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) { [self.loadingView stopAnimating]; } else if (state == MJRefreshStateRefreshing) { [self.loadingView startAnimating]; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h ================================================ // // MJRefreshAutoStateFooter.h // MJRefreshExample // // Created by MJ Lee on 15/6/13. // Copyright © 2015年 小码哥. All rights reserved. // #import "MJRefreshAutoFooter.h" @interface MJRefreshAutoStateFooter : MJRefreshAutoFooter /** 显示刷新状态的label */ @property (weak, nonatomic, readonly) UILabel *stateLabel; /** 设置state状态下的文字 */ - (void)setTitle:(NSString *)title forState:(MJRefreshState)state; /** 隐藏刷新状态的文字 */ @property (assign, nonatomic, getter=isRefreshingTitleHidden) BOOL refreshingTitleHidden; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m ================================================ // // MJRefreshAutoStateFooter.m // MJRefreshExample // // Created by MJ Lee on 15/6/13. // Copyright © 2015年 小码哥. All rights reserved. // #import "MJRefreshAutoStateFooter.h" @interface MJRefreshAutoStateFooter() { /** 显示刷新状态的label */ __unsafe_unretained UILabel *_stateLabel; } /** 所有状态对应的文字 */ @property (strong, nonatomic) NSMutableDictionary *stateTitles; @end @implementation MJRefreshAutoStateFooter #pragma mark - 懒加载 - (NSMutableDictionary *)stateTitles { if (!_stateTitles) { self.stateTitles = [NSMutableDictionary dictionary]; } return _stateTitles; } - (UILabel *)stateLabel { if (!_stateLabel) { [self addSubview:_stateLabel = [UILabel label]]; } return _stateLabel; } #pragma mark - 公共方法 - (void)setTitle:(NSString *)title forState:(MJRefreshState)state { if (title == nil) return; self.stateTitles[@(state)] = title; self.stateLabel.text = self.stateTitles[@(self.state)]; } #pragma mark - 私有方法 - (void)stateLabelClick { if (self.state == MJRefreshStateIdle) { [self beginRefreshing]; } } #pragma mark - 重写父类的方法 - (void)prepare { [super prepare]; // 初始化文字 [self setTitle:MJRefreshAutoFooterIdleText forState:MJRefreshStateIdle]; [self setTitle:MJRefreshAutoFooterRefreshingText forState:MJRefreshStateRefreshing]; [self setTitle:MJRefreshAutoFooterNoMoreDataText forState:MJRefreshStateNoMoreData]; // 监听label self.stateLabel.userInteractionEnabled = YES; [self.stateLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stateLabelClick)]]; } - (void)placeSubviews { [super placeSubviews]; if (self.stateLabel.constraints.count) return; // 状态标签 self.stateLabel.frame = self.bounds; } - (void)setState:(MJRefreshState)state { MJRefreshCheckState if (self.isRefreshingTitleHidden && state == MJRefreshStateRefreshing) { self.stateLabel.text = nil; } else { self.stateLabel.text = self.stateTitles[@(state)]; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h ================================================ // // MJRefreshBackGifFooter.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshBackStateFooter.h" @interface MJRefreshBackGifFooter : MJRefreshBackStateFooter @property (weak, nonatomic, readonly) UIImageView *gifView; /** 设置state状态下的动画图片images 动画持续时间duration*/ - (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state; - (void)setImages:(NSArray *)images forState:(MJRefreshState)state; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m ================================================ // // MJRefreshBackGifFooter.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshBackGifFooter.h" @interface MJRefreshBackGifFooter() { __unsafe_unretained UIImageView *_gifView; } /** 所有状态对应的动画图片 */ @property (strong, nonatomic) NSMutableDictionary *stateImages; /** 所有状态对应的动画时间 */ @property (strong, nonatomic) NSMutableDictionary *stateDurations; @end @implementation MJRefreshBackGifFooter #pragma mark - 懒加载 - (UIImageView *)gifView { if (!_gifView) { UIImageView *gifView = [[UIImageView alloc] init]; [self addSubview:_gifView = gifView]; } return _gifView; } - (NSMutableDictionary *)stateImages { if (!_stateImages) { self.stateImages = [NSMutableDictionary dictionary]; } return _stateImages; } - (NSMutableDictionary *)stateDurations { if (!_stateDurations) { self.stateDurations = [NSMutableDictionary dictionary]; } return _stateDurations; } #pragma mark - 公共方法 - (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state { if (images == nil) return; self.stateImages[@(state)] = images; self.stateDurations[@(state)] = @(duration); /* 根据图片设置控件的高度 */ UIImage *image = [images firstObject]; if (image.size.height > self.mj_h) { self.mj_h = image.size.height; } } - (void)setImages:(NSArray *)images forState:(MJRefreshState)state { [self setImages:images duration:images.count * 0.1 forState:state]; } #pragma mark - 实现父类的方法 - (void)setPullingPercent:(CGFloat)pullingPercent { [super setPullingPercent:pullingPercent]; NSArray *images = self.stateImages[@(MJRefreshStateIdle)]; if (self.state != MJRefreshStateIdle || images.count == 0) return; [self.gifView stopAnimating]; NSUInteger index = images.count * pullingPercent; if (index >= images.count) index = images.count - 1; self.gifView.image = images[index]; } - (void)placeSubviews { [super placeSubviews]; if (self.gifView.constraints.count) return; self.gifView.frame = self.bounds; if (self.stateLabel.hidden) { self.gifView.contentMode = UIViewContentModeCenter; } else { self.gifView.contentMode = UIViewContentModeRight; self.gifView.mj_w = self.mj_w * 0.5 - 90; } } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 根据状态做事情 if (state == MJRefreshStatePulling || state == MJRefreshStateRefreshing) { NSArray *images = self.stateImages[@(state)]; if (images.count == 0) return; self.gifView.hidden = NO; [self.gifView stopAnimating]; if (images.count == 1) { // 单张图片 self.gifView.image = [images lastObject]; } else { // 多张图片 self.gifView.animationImages = images; self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue]; [self.gifView startAnimating]; } } else if (state == MJRefreshStateIdle) { self.gifView.hidden = NO; } else if (state == MJRefreshStateNoMoreData) { self.gifView.hidden = YES; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h ================================================ // // MJRefreshBackNormalFooter.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshBackStateFooter.h" @interface MJRefreshBackNormalFooter : MJRefreshBackStateFooter @property (weak, nonatomic, readonly) UIImageView *arrowView; /** 菊花的样式 */ @property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m ================================================ // // MJRefreshBackNormalFooter.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshBackNormalFooter.h" @interface MJRefreshBackNormalFooter() { __unsafe_unretained UIImageView *_arrowView; } @property (weak, nonatomic) UIActivityIndicatorView *loadingView; @end @implementation MJRefreshBackNormalFooter #pragma mark - 懒加载子控件 - (UIImageView *)arrowView { if (!_arrowView) { UIImage *image = [UIImage imageNamed:MJRefreshSrcName(@"arrow.png")] ?: [UIImage imageNamed:MJRefreshFrameworkSrcName(@"arrow.png")]; UIImageView *arrowView = [[UIImageView alloc] initWithImage:image]; [self addSubview:_arrowView = arrowView]; } return _arrowView; } - (UIActivityIndicatorView *)loadingView { if (!_loadingView) { UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle]; loadingView.hidesWhenStopped = YES; [self addSubview:_loadingView = loadingView]; } return _loadingView; } - (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle { _activityIndicatorViewStyle = activityIndicatorViewStyle; self.loadingView = nil; [self setNeedsLayout]; } #pragma makr - 重写父类的方法 - (void)prepare { [super prepare]; self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; } - (void)placeSubviews { [super placeSubviews]; // 箭头的中心点 CGFloat arrowCenterX = self.mj_w * 0.5; if (!self.stateLabel.hidden) { arrowCenterX -= 100; } CGFloat arrowCenterY = self.mj_h * 0.5; CGPoint arrowCenter = CGPointMake(arrowCenterX, arrowCenterY); // 箭头 if (self.arrowView.constraints.count == 0) { self.arrowView.mj_size = self.arrowView.image.size; self.arrowView.center = arrowCenter; } // 圈圈 if (self.loadingView.constraints.count == 0) { self.loadingView.center = arrowCenter; } } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 根据状态做事情 if (state == MJRefreshStateIdle) { if (oldState == MJRefreshStateRefreshing) { self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{ self.loadingView.alpha = 0.0; } completion:^(BOOL finished) { self.loadingView.alpha = 1.0; [self.loadingView stopAnimating]; self.arrowView.hidden = NO; }]; } else { self.arrowView.hidden = NO; [self.loadingView stopAnimating]; [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{ self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); }]; } } else if (state == MJRefreshStatePulling) { self.arrowView.hidden = NO; [self.loadingView stopAnimating]; [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{ self.arrowView.transform = CGAffineTransformIdentity; }]; } else if (state == MJRefreshStateRefreshing) { self.arrowView.hidden = YES; [self.loadingView startAnimating]; } else if (state == MJRefreshStateNoMoreData) { self.arrowView.hidden = YES; [self.loadingView stopAnimating]; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h ================================================ // // MJRefreshBackStateFooter.h // MJRefreshExample // // Created by MJ Lee on 15/6/13. // Copyright © 2015年 小码哥. All rights reserved. // #import "MJRefreshBackFooter.h" @interface MJRefreshBackStateFooter : MJRefreshBackFooter /** 显示刷新状态的label */ @property (weak, nonatomic, readonly) UILabel *stateLabel; /** 设置state状态下的文字 */ - (void)setTitle:(NSString *)title forState:(MJRefreshState)state; /** 获取state状态下的title */ - (NSString *)titleForState:(MJRefreshState)state; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m ================================================ // // MJRefreshBackStateFooter.m // MJRefreshExample // // Created by MJ Lee on 15/6/13. // Copyright © 2015年 小码哥. All rights reserved. // #import "MJRefreshBackStateFooter.h" @interface MJRefreshBackStateFooter() { /** 显示刷新状态的label */ __unsafe_unretained UILabel *_stateLabel; } /** 所有状态对应的文字 */ @property (strong, nonatomic) NSMutableDictionary *stateTitles; @end @implementation MJRefreshBackStateFooter #pragma mark - 懒加载 - (NSMutableDictionary *)stateTitles { if (!_stateTitles) { self.stateTitles = [NSMutableDictionary dictionary]; } return _stateTitles; } - (UILabel *)stateLabel { if (!_stateLabel) { [self addSubview:_stateLabel = [UILabel label]]; } return _stateLabel; } #pragma mark - 公共方法 - (void)setTitle:(NSString *)title forState:(MJRefreshState)state { if (title == nil) return; self.stateTitles[@(state)] = title; self.stateLabel.text = self.stateTitles[@(self.state)]; } - (NSString *)titleForState:(MJRefreshState)state { return self.stateTitles[@(state)]; } #pragma mark - 重写父类的方法 - (void)prepare { [super prepare]; // 初始化文字 [self setTitle:MJRefreshBackFooterIdleText forState:MJRefreshStateIdle]; [self setTitle:MJRefreshBackFooterPullingText forState:MJRefreshStatePulling]; [self setTitle:MJRefreshBackFooterRefreshingText forState:MJRefreshStateRefreshing]; [self setTitle:MJRefreshBackFooterNoMoreDataText forState:MJRefreshStateNoMoreData]; } - (void)placeSubviews { [super placeSubviews]; if (self.stateLabel.constraints.count) return; // 状态标签 self.stateLabel.frame = self.bounds; } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 设置状态文字 self.stateLabel.text = self.stateTitles[@(state)]; } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.h ================================================ // // MJRefreshGifHeader.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshStateHeader.h" @interface MJRefreshGifHeader : MJRefreshStateHeader @property (weak, nonatomic, readonly) UIImageView *gifView; /** 设置state状态下的动画图片images 动画持续时间duration*/ - (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state; - (void)setImages:(NSArray *)images forState:(MJRefreshState)state; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.m ================================================ // // MJRefreshGifHeader.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshGifHeader.h" @interface MJRefreshGifHeader() { __unsafe_unretained UIImageView *_gifView; } /** 所有状态对应的动画图片 */ @property (strong, nonatomic) NSMutableDictionary *stateImages; /** 所有状态对应的动画时间 */ @property (strong, nonatomic) NSMutableDictionary *stateDurations; @end @implementation MJRefreshGifHeader #pragma mark - 懒加载 - (UIImageView *)gifView { if (!_gifView) { UIImageView *gifView = [[UIImageView alloc] init]; [self addSubview:_gifView = gifView]; } return _gifView; } - (NSMutableDictionary *)stateImages { if (!_stateImages) { self.stateImages = [NSMutableDictionary dictionary]; } return _stateImages; } - (NSMutableDictionary *)stateDurations { if (!_stateDurations) { self.stateDurations = [NSMutableDictionary dictionary]; } return _stateDurations; } #pragma mark - 公共方法 - (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state { if (images == nil) return; self.stateImages[@(state)] = images; self.stateDurations[@(state)] = @(duration); /* 根据图片设置控件的高度 */ UIImage *image = [images firstObject]; if (image.size.height > self.mj_h) { self.mj_h = image.size.height; } } - (void)setImages:(NSArray *)images forState:(MJRefreshState)state { [self setImages:images duration:images.count * 0.1 forState:state]; } #pragma mark - 实现父类的方法 - (void)setPullingPercent:(CGFloat)pullingPercent { [super setPullingPercent:pullingPercent]; NSArray *images = self.stateImages[@(MJRefreshStateIdle)]; if (self.state != MJRefreshStateIdle || images.count == 0) return; // 停止动画 [self.gifView stopAnimating]; // 设置当前需要显示的图片 NSUInteger index = images.count * pullingPercent; if (index >= images.count) index = images.count - 1; self.gifView.image = images[index]; } - (void)placeSubviews { [super placeSubviews]; if (self.gifView.constraints.count) return; self.gifView.frame = self.bounds; if (self.stateLabel.hidden && self.lastUpdatedTimeLabel.hidden) { self.gifView.contentMode = UIViewContentModeCenter; } else { self.gifView.contentMode = UIViewContentModeRight; self.gifView.mj_w = self.mj_w * 0.5 - 90; } } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 根据状态做事情 if (state == MJRefreshStatePulling || state == MJRefreshStateRefreshing) { NSArray *images = self.stateImages[@(state)]; if (images.count == 0) return; [self.gifView stopAnimating]; if (images.count == 1) { // 单张图片 self.gifView.image = [images lastObject]; } else { // 多张图片 self.gifView.animationImages = images; self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue]; [self.gifView startAnimating]; } } else if (state == MJRefreshStateIdle) { [self.gifView stopAnimating]; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.h ================================================ // // MJRefreshNormalHeader.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshStateHeader.h" @interface MJRefreshNormalHeader : MJRefreshStateHeader @property (weak, nonatomic, readonly) UIImageView *arrowView; /** 菊花的样式 */ @property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.m ================================================ // // MJRefreshNormalHeader.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshNormalHeader.h" @interface MJRefreshNormalHeader() { __unsafe_unretained UIImageView *_arrowView; } @property (weak, nonatomic) UIActivityIndicatorView *loadingView; @end @implementation MJRefreshNormalHeader #pragma mark - 懒加载子控件 - (UIImageView *)arrowView { if (!_arrowView) { UIImage *image = [UIImage imageNamed:MJRefreshSrcName(@"arrow.png")] ?: [UIImage imageNamed:MJRefreshFrameworkSrcName(@"arrow.png")]; UIImageView *arrowView = [[UIImageView alloc] initWithImage:image]; [self addSubview:_arrowView = arrowView]; } return _arrowView; } - (UIActivityIndicatorView *)loadingView { if (!_loadingView) { UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle]; loadingView.hidesWhenStopped = YES; [self addSubview:_loadingView = loadingView]; } return _loadingView; } #pragma mark - 公共方法 - (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle { _activityIndicatorViewStyle = activityIndicatorViewStyle; self.loadingView = nil; [self setNeedsLayout]; } #pragma makr - 重写父类的方法 - (void)prepare { [super prepare]; self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; } - (void)placeSubviews { [super placeSubviews]; // 箭头的中心点 CGFloat arrowCenterX = self.mj_w * 0.5; if (!self.stateLabel.hidden) { arrowCenterX -= 100; } CGFloat arrowCenterY = self.mj_h * 0.5; CGPoint arrowCenter = CGPointMake(arrowCenterX, arrowCenterY); // 箭头 if (self.arrowView.constraints.count == 0) { self.arrowView.mj_size = self.arrowView.image.size; self.arrowView.center = arrowCenter; } // 圈圈 if (self.loadingView.constraints.count == 0) { self.loadingView.center = arrowCenter; } } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 根据状态做事情 if (state == MJRefreshStateIdle) { if (oldState == MJRefreshStateRefreshing) { self.arrowView.transform = CGAffineTransformIdentity; [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{ self.loadingView.alpha = 0.0; } completion:^(BOOL finished) { // 如果执行完动画发现不是idle状态,就直接返回,进入其他状态 if (self.state != MJRefreshStateIdle) return; self.loadingView.alpha = 1.0; [self.loadingView stopAnimating]; self.arrowView.hidden = NO; }]; } else { [self.loadingView stopAnimating]; self.arrowView.hidden = NO; [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{ self.arrowView.transform = CGAffineTransformIdentity; }]; } } else if (state == MJRefreshStatePulling) { [self.loadingView stopAnimating]; self.arrowView.hidden = NO; [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{ self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); }]; } else if (state == MJRefreshStateRefreshing) { self.loadingView.alpha = 1.0; // 防止refreshing -> idle的动画完毕动作没有被执行 [self.loadingView startAnimating]; self.arrowView.hidden = YES; } } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.h ================================================ // // MJRefreshStateHeader.h // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshHeader.h" @interface MJRefreshStateHeader : MJRefreshHeader #pragma mark - 刷新时间相关 /** 利用这个block来决定显示的更新时间文字 */ @property (copy, nonatomic) NSString *(^lastUpdatedTimeText)(NSDate *lastUpdatedTime); /** 显示上一次刷新时间的label */ @property (weak, nonatomic, readonly) UILabel *lastUpdatedTimeLabel; #pragma mark - 状态相关 /** 显示刷新状态的label */ @property (weak, nonatomic, readonly) UILabel *stateLabel; /** 设置state状态下的文字 */ - (void)setTitle:(NSString *)title forState:(MJRefreshState)state; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.m ================================================ // // MJRefreshStateHeader.m // MJRefreshExample // // Created by MJ Lee on 15/4/24. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "MJRefreshStateHeader.h" @interface MJRefreshStateHeader() { /** 显示上一次刷新时间的label */ __unsafe_unretained UILabel *_lastUpdatedTimeLabel; /** 显示刷新状态的label */ __unsafe_unretained UILabel *_stateLabel; } /** 所有状态对应的文字 */ @property (strong, nonatomic) NSMutableDictionary *stateTitles; @end @implementation MJRefreshStateHeader #pragma mark - 懒加载 - (NSMutableDictionary *)stateTitles { if (!_stateTitles) { self.stateTitles = [NSMutableDictionary dictionary]; } return _stateTitles; } - (UILabel *)stateLabel { if (!_stateLabel) { [self addSubview:_stateLabel = [UILabel label]]; } return _stateLabel; } - (UILabel *)lastUpdatedTimeLabel { if (!_lastUpdatedTimeLabel) { [self addSubview:_lastUpdatedTimeLabel = [UILabel label]]; } return _lastUpdatedTimeLabel; } #pragma mark - 公共方法 - (void)setTitle:(NSString *)title forState:(MJRefreshState)state { if (title == nil) return; self.stateTitles[@(state)] = title; self.stateLabel.text = self.stateTitles[@(self.state)]; } #pragma mark - 日历获取在9.x之后的系统使用currentCalendar会出异常。在8.0之后使用系统新API。 - (NSCalendar *)currentCalendar { if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) { return [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; } return [NSCalendar currentCalendar]; } #pragma mark key的处理 - (void)setLastUpdatedTimeKey:(NSString *)lastUpdatedTimeKey { [super setLastUpdatedTimeKey:lastUpdatedTimeKey]; // 如果label隐藏了,就不用再处理 if (self.lastUpdatedTimeLabel.hidden) return; NSDate *lastUpdatedTime = [[NSUserDefaults standardUserDefaults] objectForKey:lastUpdatedTimeKey]; // 如果有block if (self.lastUpdatedTimeText) { self.lastUpdatedTimeLabel.text = self.lastUpdatedTimeText(lastUpdatedTime); return; } if (lastUpdatedTime) { // 1.获得年月日 NSCalendar *calendar = [self currentCalendar]; NSUInteger unitFlags = NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour |NSCalendarUnitMinute; NSDateComponents *cmp1 = [calendar components:unitFlags fromDate:lastUpdatedTime]; NSDateComponents *cmp2 = [calendar components:unitFlags fromDate:[NSDate date]]; // 2.格式化日期 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; if ([cmp1 day] == [cmp2 day]) { // 今天 formatter.dateFormat = @"今天 HH:mm"; } else if ([cmp1 year] == [cmp2 year]) { // 今年 formatter.dateFormat = @"MM-dd HH:mm"; } else { formatter.dateFormat = @"yyyy-MM-dd HH:mm"; } NSString *time = [formatter stringFromDate:lastUpdatedTime]; // 3.显示日期 self.lastUpdatedTimeLabel.text = [NSString stringWithFormat:@"最后更新:%@", time]; } else { self.lastUpdatedTimeLabel.text = @"最后更新:无记录"; } } #pragma mark - 覆盖父类的方法 - (void)prepare { [super prepare]; // 初始化文字 [self setTitle:MJRefreshHeaderIdleText forState:MJRefreshStateIdle]; [self setTitle:MJRefreshHeaderPullingText forState:MJRefreshStatePulling]; [self setTitle:MJRefreshHeaderRefreshingText forState:MJRefreshStateRefreshing]; } - (void)placeSubviews { [super placeSubviews]; if (self.stateLabel.hidden) return; BOOL noConstrainsOnStatusLabel = self.stateLabel.constraints.count == 0; if (self.lastUpdatedTimeLabel.hidden) { // 状态 if (noConstrainsOnStatusLabel) self.stateLabel.frame = self.bounds; } else { CGFloat stateLabelH = self.mj_h * 0.5; // 状态 if (noConstrainsOnStatusLabel) { self.stateLabel.mj_x = 0; self.stateLabel.mj_y = 0; self.stateLabel.mj_w = self.mj_w; self.stateLabel.mj_h = stateLabelH; } // 更新时间 if (self.lastUpdatedTimeLabel.constraints.count == 0) { self.lastUpdatedTimeLabel.mj_x = 0; self.lastUpdatedTimeLabel.mj_y = stateLabelH; self.lastUpdatedTimeLabel.mj_w = self.mj_w; self.lastUpdatedTimeLabel.mj_h = self.mj_h - self.lastUpdatedTimeLabel.mj_y; } } } - (void)setState:(MJRefreshState)state { MJRefreshCheckState // 设置状态文字 self.stateLabel.text = self.stateTitles[@(state)]; // 重新设置key(重新显示时间) self.lastUpdatedTimeKey = self.lastUpdatedTimeKey; } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/MJRefresh.h ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 #import "UIScrollView+MJRefresh.h" #import "UIScrollView+MJExtension.h" #import "UIView+MJExtension.h" #import "MJRefreshNormalHeader.h" #import "MJRefreshGifHeader.h" #import "MJRefreshBackNormalFooter.h" #import "MJRefreshBackGifFooter.h" #import "MJRefreshAutoNormalFooter.h" #import "MJRefreshAutoGifFooter.h" ================================================ FILE: Pods/MJRefresh/MJRefresh/MJRefreshConst.h ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 #import #import // 弱引用 #define MJWeakSelf __weak typeof(self) weakSelf = self; // 日志输出 #ifdef DEBUG #define MJRefreshLog(...) NSLog(__VA_ARGS__) #else #define MJRefreshLog(...) #endif // 过期提醒 #define MJRefreshDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead) // 运行时objc_msgSend #define MJRefreshMsgSend(...) ((void (*)(void *, SEL, UIView *))objc_msgSend)(__VA_ARGS__) #define MJRefreshMsgTarget(target) (__bridge void *)(target) // RGB颜色 #define MJRefreshColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0] // 文字颜色 #define MJRefreshLabelTextColor MJRefreshColor(90, 90, 90) // 字体大小 #define MJRefreshLabelFont [UIFont boldSystemFontOfSize:14] // 图片路径 #define MJRefreshSrcName(file) [@"MJRefresh.bundle" stringByAppendingPathComponent:file] #define MJRefreshFrameworkSrcName(file) [@"Frameworks/MJRefresh.framework/MJRefresh.bundle" stringByAppendingPathComponent:file] // 常量 UIKIT_EXTERN const CGFloat MJRefreshHeaderHeight; UIKIT_EXTERN const CGFloat MJRefreshFooterHeight; UIKIT_EXTERN const CGFloat MJRefreshFastAnimationDuration; UIKIT_EXTERN const CGFloat MJRefreshSlowAnimationDuration; UIKIT_EXTERN NSString *const MJRefreshKeyPathContentOffset; UIKIT_EXTERN NSString *const MJRefreshKeyPathContentSize; UIKIT_EXTERN NSString *const MJRefreshKeyPathContentInset; UIKIT_EXTERN NSString *const MJRefreshKeyPathPanState; UIKIT_EXTERN NSString *const MJRefreshHeaderLastUpdatedTimeKey; UIKIT_EXTERN NSString *const MJRefreshHeaderIdleText; UIKIT_EXTERN NSString *const MJRefreshHeaderPullingText; UIKIT_EXTERN NSString *const MJRefreshHeaderRefreshingText; UIKIT_EXTERN NSString *const MJRefreshAutoFooterIdleText; UIKIT_EXTERN NSString *const MJRefreshAutoFooterRefreshingText; UIKIT_EXTERN NSString *const MJRefreshAutoFooterNoMoreDataText; UIKIT_EXTERN NSString *const MJRefreshBackFooterIdleText; UIKIT_EXTERN NSString *const MJRefreshBackFooterPullingText; UIKIT_EXTERN NSString *const MJRefreshBackFooterRefreshingText; UIKIT_EXTERN NSString *const MJRefreshBackFooterNoMoreDataText; // 状态检查 #define MJRefreshCheckState \ MJRefreshState oldState = self.state; \ if (state == oldState) return; \ [super setState:state]; ================================================ FILE: Pods/MJRefresh/MJRefresh/MJRefreshConst.m ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 #import const CGFloat MJRefreshHeaderHeight = 54.0; const CGFloat MJRefreshFooterHeight = 44.0; const CGFloat MJRefreshFastAnimationDuration = 0.25; const CGFloat MJRefreshSlowAnimationDuration = 0.4; NSString *const MJRefreshKeyPathContentOffset = @"contentOffset"; NSString *const MJRefreshKeyPathContentInset = @"contentInset"; NSString *const MJRefreshKeyPathContentSize = @"contentSize"; NSString *const MJRefreshKeyPathPanState = @"state"; NSString *const MJRefreshHeaderLastUpdatedTimeKey = @"MJRefreshHeaderLastUpdatedTimeKey"; NSString *const MJRefreshHeaderIdleText = @"下拉可以刷新"; NSString *const MJRefreshHeaderPullingText = @"松开立即刷新"; NSString *const MJRefreshHeaderRefreshingText = @"正在刷新数据中..."; NSString *const MJRefreshAutoFooterIdleText = @"点击或上拉加载更多"; NSString *const MJRefreshAutoFooterRefreshingText = @"正在加载更多的数据..."; NSString *const MJRefreshAutoFooterNoMoreDataText = @"已经全部加载完毕"; NSString *const MJRefreshBackFooterIdleText = @"上拉可以加载更多"; NSString *const MJRefreshBackFooterPullingText = @"松开立即加载更多"; NSString *const MJRefreshBackFooterRefreshingText = @"正在加载更多的数据..."; NSString *const MJRefreshBackFooterNoMoreDataText = @"已经全部加载完毕"; ================================================ FILE: Pods/MJRefresh/MJRefresh/UIScrollView+MJExtension.h ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // UIScrollView+Extension.h // MJRefreshExample // // Created by MJ Lee on 14-5-28. // Copyright (c) 2014年 小码哥. All rights reserved. // #import @interface UIScrollView (MJExtension) @property (assign, nonatomic) CGFloat mj_insetT; @property (assign, nonatomic) CGFloat mj_insetB; @property (assign, nonatomic) CGFloat mj_insetL; @property (assign, nonatomic) CGFloat mj_insetR; @property (assign, nonatomic) CGFloat mj_offsetX; @property (assign, nonatomic) CGFloat mj_offsetY; @property (assign, nonatomic) CGFloat mj_contentW; @property (assign, nonatomic) CGFloat mj_contentH; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/UIScrollView+MJExtension.m ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // UIScrollView+Extension.m // MJRefreshExample // // Created by MJ Lee on 14-5-28. // Copyright (c) 2014年 小码哥. All rights reserved. // #import "UIScrollView+MJExtension.h" #import @implementation UIScrollView (MJExtension) - (void)setMj_insetT:(CGFloat)mj_insetT { UIEdgeInsets inset = self.contentInset; inset.top = mj_insetT; self.contentInset = inset; } - (CGFloat)mj_insetT { return self.contentInset.top; } - (void)setMj_insetB:(CGFloat)mj_insetB { UIEdgeInsets inset = self.contentInset; inset.bottom = mj_insetB; self.contentInset = inset; } - (CGFloat)mj_insetB { return self.contentInset.bottom; } - (void)setMj_insetL:(CGFloat)mj_insetL { UIEdgeInsets inset = self.contentInset; inset.left = mj_insetL; self.contentInset = inset; } - (CGFloat)mj_insetL { return self.contentInset.left; } - (void)setMj_insetR:(CGFloat)mj_insetR { UIEdgeInsets inset = self.contentInset; inset.right = mj_insetR; self.contentInset = inset; } - (CGFloat)mj_insetR { return self.contentInset.right; } - (void)setMj_offsetX:(CGFloat)mj_offsetX { CGPoint offset = self.contentOffset; offset.x = mj_offsetX; self.contentOffset = offset; } - (CGFloat)mj_offsetX { return self.contentOffset.x; } - (void)setMj_offsetY:(CGFloat)mj_offsetY { CGPoint offset = self.contentOffset; offset.y = mj_offsetY; self.contentOffset = offset; } - (CGFloat)mj_offsetY { return self.contentOffset.y; } - (void)setMj_contentW:(CGFloat)mj_contentW { CGSize size = self.contentSize; size.width = mj_contentW; self.contentSize = size; } - (CGFloat)mj_contentW { return self.contentSize.width; } - (void)setMj_contentH:(CGFloat)mj_contentH { CGSize size = self.contentSize; size.height = mj_contentH; self.contentSize = size; } - (CGFloat)mj_contentH { return self.contentSize.height; } @end ================================================ FILE: Pods/MJRefresh/MJRefresh/UIScrollView+MJRefresh.h ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // UIScrollView+MJRefresh.h // MJRefreshExample // // Created by MJ Lee on 15/3/4. // Copyright (c) 2015年 小码哥. All rights reserved. // 给ScrollView增加下拉刷新、上拉刷新的功能 #import #import "MJRefreshConst.h" @class MJRefreshHeader, MJRefreshFooter; @interface UIScrollView (MJRefresh) /** 下拉刷新控件 */ @property (strong, nonatomic) MJRefreshHeader *mj_header; @property (strong, nonatomic) MJRefreshHeader *header MJRefreshDeprecated("使用mj_header"); /** 上拉刷新控件 */ @property (strong, nonatomic) MJRefreshFooter *mj_footer; @property (strong, nonatomic) MJRefreshFooter *footer MJRefreshDeprecated("使用mj_footer"); #pragma mark - other - (NSInteger)mj_totalDataCount; @property (copy, nonatomic) void (^mj_reloadDataBlock)(NSInteger totalDataCount); @end ================================================ FILE: Pods/MJRefresh/MJRefresh/UIScrollView+MJRefresh.m ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // UIScrollView+MJRefresh.m // MJRefreshExample // // Created by MJ Lee on 15/3/4. // Copyright (c) 2015年 小码哥. All rights reserved. // #import "UIScrollView+MJRefresh.h" #import "MJRefreshHeader.h" #import "MJRefreshFooter.h" #import @implementation NSObject (MJRefresh) + (void)exchangeInstanceMethod1:(SEL)method1 method2:(SEL)method2 { method_exchangeImplementations(class_getInstanceMethod(self, method1), class_getInstanceMethod(self, method2)); } + (void)exchangeClassMethod1:(SEL)method1 method2:(SEL)method2 { method_exchangeImplementations(class_getClassMethod(self, method1), class_getClassMethod(self, method2)); } @end @implementation UIScrollView (MJRefresh) #pragma mark - header static const char MJRefreshHeaderKey = '\0'; - (void)setMj_header:(MJRefreshHeader *)mj_header { if (mj_header != self.mj_header) { // 删除旧的,添加新的 [self.mj_header removeFromSuperview]; [self insertSubview:mj_header atIndex:0]; // 存储新的 [self willChangeValueForKey:@"mj_header"]; // KVO objc_setAssociatedObject(self, &MJRefreshHeaderKey, mj_header, OBJC_ASSOCIATION_ASSIGN); [self didChangeValueForKey:@"mj_header"]; // KVO } } - (MJRefreshHeader *)mj_header { return objc_getAssociatedObject(self, &MJRefreshHeaderKey); } #pragma mark - footer static const char MJRefreshFooterKey = '\0'; - (void)setMj_footer:(MJRefreshFooter *)mj_footer { if (mj_footer != self.mj_footer) { // 删除旧的,添加新的 [self.mj_footer removeFromSuperview]; [self addSubview:mj_footer]; // 存储新的 [self willChangeValueForKey:@"mj_footer"]; // KVO objc_setAssociatedObject(self, &MJRefreshFooterKey, mj_footer, OBJC_ASSOCIATION_ASSIGN); [self didChangeValueForKey:@"mj_footer"]; // KVO } } - (MJRefreshFooter *)mj_footer { return objc_getAssociatedObject(self, &MJRefreshFooterKey); } #pragma mark - 过期 - (void)setFooter:(MJRefreshFooter *)footer { self.mj_footer = footer; } - (MJRefreshFooter *)footer { return self.mj_footer; } - (void)setHeader:(MJRefreshHeader *)header { self.mj_header = header; } - (MJRefreshHeader *)header { return self.mj_header; } #pragma mark - other - (NSInteger)mj_totalDataCount { NSInteger totalCount = 0; if ([self isKindOfClass:[UITableView class]]) { UITableView *tableView = (UITableView *)self; for (NSInteger section = 0; section @interface UIView (MJExtension) @property (assign, nonatomic) CGFloat mj_x; @property (assign, nonatomic) CGFloat mj_y; @property (assign, nonatomic) CGFloat mj_w; @property (assign, nonatomic) CGFloat mj_h; @property (assign, nonatomic) CGSize mj_size; @property (assign, nonatomic) CGPoint mj_origin; @end ================================================ FILE: Pods/MJRefresh/MJRefresh/UIView+MJExtension.m ================================================ // 代码地址: https://github.com/CoderMJLee/MJRefresh // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000 // UIView+Extension.m // MJRefreshExample // // Created by MJ Lee on 14-5-28. // Copyright (c) 2014年 小码哥. All rights reserved. // #import "UIView+MJExtension.h" @implementation UIView (MJExtension) - (void)setMj_x:(CGFloat)mj_x { CGRect frame = self.frame; frame.origin.x = mj_x; self.frame = frame; } - (CGFloat)mj_x { return self.frame.origin.x; } - (void)setMj_y:(CGFloat)mj_y { CGRect frame = self.frame; frame.origin.y = mj_y; self.frame = frame; } - (CGFloat)mj_y { return self.frame.origin.y; } - (void)setMj_w:(CGFloat)mj_w { CGRect frame = self.frame; frame.size.width = mj_w; self.frame = frame; } - (CGFloat)mj_w { return self.frame.size.width; } - (void)setMj_h:(CGFloat)mj_h { CGRect frame = self.frame; frame.size.height = mj_h; self.frame = frame; } - (CGFloat)mj_h { return self.frame.size.height; } - (void)setMj_size:(CGSize)mj_size { CGRect frame = self.frame; frame.size = mj_size; self.frame = frame; } - (CGSize)mj_size { return self.frame.size; } - (void)setMj_origin:(CGPoint)mj_origin { CGRect frame = self.frame; frame.origin = mj_origin; self.frame = frame; } - (CGPoint)mj_origin { return self.frame.origin; } @end ================================================ FILE: Pods/MJRefresh/README.md ================================================ ![(logo)](http://images.cnitblog.com/blog2015/497279/201505/051004492043385.png) ## MJRefresh * An easy way to use pull-to-refresh * 用法简单的下拉刷新框架:一行代码搞定 ## Contents * Getting Started * [Features【支持哪些控件的刷新】](#支持哪些控件的刷新) * [Installation【如何使用MJRefresh】](#如何使用MJRefresh) * [Who's using【已经超过上百个App正在使用MJRefresh】](#已经超过上百个App正在使用MJRefresh) * [Classes【MJRefresh类结构图】](#MJRefresh类结构图) * 常见API * [MJRefreshComponent.h](#MJRefreshComponent.h) * [MJRefreshHeader.h](#MJRefreshHeader.h) * [MJRefreshFooter.h](#MJRefreshFooter.h) * [MJRefreshAutoFooter.h](#MJRefreshAutoFooter.h) * Examples * [Reference【参考】](#参考) * [下拉刷新01-默认](#下拉刷新01-默认) * [下拉刷新02-动画图片](#下拉刷新02-动画图片) * [下拉刷新03-隐藏时间](#下拉刷新03-隐藏时间) * [下拉刷新04-隐藏状态和时间](#下拉刷新04-隐藏状态和时间) * [下拉刷新05-自定义文字](#下拉刷新05-自定义文字) * [下拉刷新06-自定义刷新控件](#下拉刷新06-自定义刷新控件) * [上拉刷新01-默认](#上拉刷新01-默认) * [上拉刷新02-动画图片](#上拉刷新02-动画图片) * [上拉刷新03-隐藏刷新状态的文字](#上拉刷新03-隐藏刷新状态的文字) * [上拉刷新04-全部加载完毕](#上拉刷新04-全部加载完毕) * [上拉刷新05-自定义文字](#上拉刷新05-自定义文字) * [上拉刷新06-加载后隐藏](#上拉刷新06-加载后隐藏) * [上拉刷新07-自动回弹的上拉01](#上拉刷新07-自动回弹的上拉01) * [上拉刷新08-自动回弹的上拉02](#上拉刷新08-自动回弹的上拉02) * [上拉刷新09-自定义刷新控件(自动刷新)](#上拉刷新09-自定义刷新控件(自动刷新)) * [上拉刷新10-自定义刷新控件(自动回弹)](#上拉刷新10-自定义刷新控件(自动回弹)) * [UICollectionView01-上下拉刷新](#UICollectionView01-上下拉刷新) * [UIWebView01-下拉刷新](#UIWebView01-下拉刷新) * [期待](#期待) ## 支持哪些控件的刷新 * `UIScrollView`、`UITableView`、`UICollectionView`、`UIWebView` ## 如何使用MJRefresh * cocoapods导入:`pod 'MJRefresh'` * 手动导入: * 将`MJRefresh`文件夹中的所有文件拽入项目中 * 导入主头文件:`#import "MJRefresh.h"` ```objc Base Custom MJRefresh.bundle MJRefresh.h MJRefreshConst.h MJRefreshConst.m UIScrollView+MJExtension.h UIScrollView+MJExtension.m UIScrollView+MJRefresh.h UIScrollView+MJRefresh.m UIView+MJExtension.h UIView+MJExtension.m ``` ## 已经超过上百个App正在使用MJRefresh * 更多App信息可以关注:[M了个J-博客园](http://www.cnblogs.com/mjios/p/4409853.html) ## MJRefresh类结构图 ![](http://images0.cnblogs.com/blog2015/497279/201506/132232456139177.png) - 图中`红色文字的类`:可以直接拿来用 - 下拉刷新控件的种类 - 默认(Normal):`MJRefreshNormalHeader` - 动图(Gif):`MJRefreshGifHeader` - 上拉刷新控件的种类 - 自动刷新(Auto) - 默认(Normal):`MJRefreshAutoNormalFooter` - 动图(Gif):`MJRefreshAutoGifFooter` - 自动回弹(Back) - 默认(Normal):`MJRefreshBackNormalFooter` - 动图(Gif):`MJRefreshBackGifFooter` - 图中`非红色文字的类`:拿来继承,用于自定义刷新控件 - 关于如何自定义刷新控件,可以参考下图的类
## MJRefreshComponent.h ```objc /** 刷新控件的基类 */ @interface MJRefreshComponent : UIView #pragma mark - 刷新状态控制 /** 进入刷新状态 */ - (void)beginRefreshing; /** 结束刷新状态 */ - (void)endRefreshing; /** 是否正在刷新 */ - (BOOL)isRefreshing; #pragma mark - 其他 /** 根据拖拽比例自动切换透明度 */ @property (assign, nonatomic, getter=isAutomaticallyChangeAlpha) BOOL automaticallyChangeAlpha; @end ``` ## MJRefreshHeader.h ```objc @interface MJRefreshHeader : MJRefreshComponent /** 创建header */ + (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock; /** 创建header */ + (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; /** 这个key用来存储上一次下拉刷新成功的时间 */ @property (copy, nonatomic) NSString *lastUpdatedTimeKey; /** 上一次下拉刷新成功的时间 */ @property (strong, nonatomic, readonly) NSDate *lastUpdatedTime; /** 忽略多少scrollView的contentInset的top */ @property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetTop; @end ``` ## MJRefreshFooter.h ```objc @interface MJRefreshFooter : MJRefreshComponent /** 创建footer */ + (instancetype)footerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock; /** 创建footer */ + (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; /** 提示没有更多的数据 */ - (void)endRefreshingWithNoMoreData; /** 重置没有更多的数据(消除没有更多数据的状态) */ - (void)resetNoMoreData; /** 忽略多少scrollView的contentInset的bottom */ @property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom; /** 自动根据有无数据来显示和隐藏(有数据就显示,没有数据隐藏) */ @property (assign, nonatomic) BOOL automaticallyHidden; @end ``` ## MJRefreshAutoFooter.h ```objc @interface MJRefreshAutoFooter : MJRefreshFooter /** 是否自动刷新(默认为YES) */ @property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh; /** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */ @property (assign, nonatomic) CGFloat triggerAutomaticallyRefreshPercent; @end ``` ## 参考 ```objc * 由于这个框架的功能较多,就不写具体文字描述其用法 * 大家可以直接参考示例中的MJTableViewController、MJCollectionViewController、MJWebViewController,更为直观快速 ``` ## 下拉刷新01-默认 ```objc self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ // 进入刷新状态后会自动调用这个block }]; 或 // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法) self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // 马上进入刷新状态 [self.tableView.header beginRefreshing]; ``` ![(下拉刷新01-普通)](http://images0.cnblogs.com/blog2015/497279/201506/141204343486151.gif) ## 下拉刷新02-动画图片 ```objc // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法) MJRefreshGifHeader *header = [MJRefreshGifHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // 设置普通状态的动画图片 [header setImages:idleImages forState:MJRefreshStateIdle]; // 设置即将刷新状态的动画图片(一松开就会刷新的状态) [header setImages:pullingImages forState:MJRefreshStatePulling]; // 设置正在刷新状态的动画图片 [header setImages:refreshingImages forState:MJRefreshStateRefreshing]; // 设置header self.tableView.mj_header = header; ``` ![(下拉刷新02-动画图片)](http://images0.cnblogs.com/blog2015/497279/201506/141204402238389.gif) ## 下拉刷新03-隐藏时间 ```objc // 隐藏时间 header.lastUpdatedTimeLabel.hidden = YES; ``` ![(下拉刷新03-隐藏时间)](http://images0.cnblogs.com/blog2015/497279/201506/141204456132944.gif) ## 下拉刷新04-隐藏状态和时间 ```objc // 隐藏时间 header.lastUpdatedTimeLabel.hidden = YES; // 隐藏状态 header.stateLabel.hidden = YES; ``` ![(下拉刷新04-隐藏状态和时间0)](http://images0.cnblogs.com/blog2015/497279/201506/141204508639539.gif) ## 下拉刷新05-自定义文字 ```objc // 设置文字 [header setTitle:@"Pull down to refresh" forState:MJRefreshStateIdle]; [header setTitle:@"Release to refresh" forState:MJRefreshStatePulling]; [header setTitle:@"Loading ..." forState:MJRefreshStateRefreshing]; // 设置字体 header.stateLabel.font = [UIFont systemFontOfSize:15]; header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:14]; // 设置颜色 header.stateLabel.textColor = [UIColor redColor]; header.lastUpdatedTimeLabel.textColor = [UIColor blueColor]; ``` ![(下拉刷新05-自定义文字)](http://images0.cnblogs.com/blog2015/497279/201506/141204563633593.gif) ## 下拉刷新06-自定义刷新控件 ```objc self.tableView.mj_header = [MJDIYHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // 具体实现参考MJDIYHeader.h和MJDIYHeader.m ``` ![(下拉刷新06-自定义刷新控件)](http://images0.cnblogs.com/blog2015/497279/201506/141205019261159.gif) ## 上拉刷新01-默认 ```objc self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ // 进入刷新状态后会自动调用这个block }]; 或 // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; ``` ![(上拉刷新01-默认)](http://images0.cnblogs.com/blog2015/497279/201506/141205090047696.gif) ## 上拉刷新02-动画图片 ```objc // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法) MJRefreshAutoGifFooter *footer = [MJRefreshAutoGifFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // 设置刷新图片 [footer setImages:refreshingImages forState:MJRefreshStateRefreshing]; // 设置尾部 self.tableView.mj_footer = footer; ``` ![(上拉刷新02-动画图片)](http://images0.cnblogs.com/blog2015/497279/201506/141205141445793.gif) ## 上拉刷新03-隐藏刷新状态的文字 ```objc // 隐藏刷新状态的文字 footer.refreshingTitleHidden = YES; // 如果没有上面的方法,就用footer.stateLabel.hidden = YES; ``` ![(上拉刷新03-隐藏刷新状态的文字)](http://images0.cnblogs.com/blog2015/497279/201506/141205200985774.gif) ## 上拉刷新04-全部加载完毕 ```objc // 变为没有更多数据的状态 [footer endRefreshingWithNoMoreData]; ``` ![(上拉刷新04-全部加载完毕)](http://images0.cnblogs.com/blog2015/497279/201506/141205248634686.gif) ## 上拉刷新05-自定义文字 ```objc // 设置文字 [footer setTitle:@"Click or drag up to refresh" forState:MJRefreshStateIdle]; [footer setTitle:@"Loading more ..." forState:MJRefreshStateRefreshing]; [footer setTitle:@"No more data" forState:MJRefreshStateNoMoreData]; // 设置字体 footer.stateLabel.font = [UIFont systemFontOfSize:17]; // 设置颜色 footer.stateLabel.textColor = [UIColor blueColor]; ``` ![(上拉刷新05-自定义文字)](http://images0.cnblogs.com/blog2015/497279/201506/141205295511153.gif) ## 上拉刷新06-加载后隐藏 ```objc // 隐藏当前的上拉刷新控件 self.tableView.mj_footer.hidden = YES; ``` ![(上拉刷新06-加载后隐藏)](http://images0.cnblogs.com/blog2015/497279/201506/141205343481821.gif) ## 上拉刷新07-自动回弹的上拉01 ```objc self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; ``` ![(上拉刷新07-自动回弹的上拉01)](http://images0.cnblogs.com/blog2015/497279/201506/141205392239231.gif) ## 上拉刷新08-自动回弹的上拉02 ```objc MJRefreshBackGifFooter *footer = [MJRefreshBackGifFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // 设置普通状态的动画图片 [footer setImages:idleImages forState:MJRefreshStateIdle]; // 设置即将刷新状态的动画图片(一松开就会刷新的状态) [footer setImages:pullingImages forState:MJRefreshStatePulling]; // 设置正在刷新状态的动画图片 [footer setImages:refreshingImages forState:MJRefreshStateRefreshing]; // 设置尾部 self.tableView.mj_footer = footer; ``` ![(上拉刷新07-自动回弹的上拉02)](http://images0.cnblogs.com/blog2015/497279/201506/141205441443628.gif) ## 上拉刷新09-自定义刷新控件(自动刷新) ```objc self.tableView.mj_footer = [MJDIYAutoFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // 具体实现参考MJDIYAutoFooter.h和MJDIYAutoFooter.m ``` ![(上拉刷新09-自定义刷新控件(自动刷新))](http://images0.cnblogs.com/blog2015/497279/201506/141205500195866.gif) ## 上拉刷新10-自定义刷新控件(自动回弹) ```objc self.tableView.mj_footer = [MJDIYBackFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; // 具体实现参考MJDIYBackFooter.h和MJDIYBackFooter.m ``` ![(上拉刷新10-自定义刷新控件(自动回弹))](http://images0.cnblogs.com/blog2015/497279/201506/141205560666819.gif) ## UICollectionView01-上下拉刷新 ```objc // 下拉刷新 self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ // 进入刷新状态后会自动调用这个block }]; // 上拉刷新 self.collectionView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ // 进入刷新状态后会自动调用这个block }]; ``` ![(UICollectionView01-上下拉刷新)](http://images0.cnblogs.com/blog2015/497279/201506/141206021603758.gif) ## UIWebView01-下拉刷新 ```objc // 添加下拉刷新控件 self.webView.scrollView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ // 进入刷新状态后会自动调用这个block }]; ``` ![(UICollectionView01-上下拉刷新)](http://images0.cnblogs.com/blog2015/497279/201506/141206080514524.gif) ## 提醒 * 本框架纯ARC,兼容的系统>=iOS6.0、iPhone\iPad横竖屏 ## 期待 * 如果在使用过程中遇到BUG,希望你能Issues我,谢谢(或者尝试下载最新的框架代码看看BUG修复没有) * 如果在使用过程中发现功能不够用,希望你能Issues我,我非常想为这个框架增加更多好用的功能,谢谢 * 如果你想为MJRefresh输出代码,请拼命Pull Requests我 * 如果你开发的应用中用到了MJRefresh,希望你能到[CocoaControls](https://www.cocoacontrols.com/controls/mjrefresh)添加你应用的iTunes路径,我将会安装使用你的应用,并且根据众多应用的使用情况,对MJRefresh进行一个更好的设计和完善,提供更多好用的功能,谢谢 * 步骤01(微信是举个例子,百度“你的应用名称 itunes”) ![(step01)](http://ww4.sinaimg.cn/mw1024/800cdf9ctw1eq0viiv5rsj20sm0ea41t.jpg) * 步骤02 ![(step02)](http://ww2.sinaimg.cn/mw1024/800cdf9ctw1eq0vilejxlj20tu0me7a0.jpg) * 步骤03 ![(step03)](http://ww1.sinaimg.cn/mw1024/800cdf9ctw1eq0viocpo5j20wc0dc0un.jpg) * 步骤04 ![(step04)](http://ww3.sinaimg.cn/mw1024/800cdf9ctw1eq0vir137xj20si0gewgu.jpg) ================================================ FILE: Pods/NJKWebViewProgress/LICENSE ================================================ The MIT License (MIT) Copyright (c) 2013 Satoshi Asano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/NJKWebViewProgress/NJKWebViewProgress/NJKWebViewProgress.h ================================================ // // NJKWebViewProgress.h // // Created by Satoshi Aasano on 4/20/13. // Copyright (c) 2013 Satoshi Asano. All rights reserved. // #import #undef njk_weak #if __has_feature(objc_arc_weak) #define njk_weak weak #else #define njk_weak unsafe_unretained #endif extern const float NJKInitialProgressValue; extern const float NJKInteractiveProgressValue; extern const float NJKFinalProgressValue; typedef void (^NJKWebViewProgressBlock)(float progress); @protocol NJKWebViewProgressDelegate; @interface NJKWebViewProgress : NSObject @property (nonatomic, njk_weak) idprogressDelegate; @property (nonatomic, njk_weak) idwebViewProxyDelegate; @property (nonatomic, copy) NJKWebViewProgressBlock progressBlock; @property (nonatomic, readonly) float progress; // 0.0..1.0 - (void)reset; @end @protocol NJKWebViewProgressDelegate - (void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress; @end ================================================ FILE: Pods/NJKWebViewProgress/NJKWebViewProgress/NJKWebViewProgress.m ================================================ // // NJKWebViewProgress.m // // Created by Satoshi Aasano on 4/20/13. // Copyright (c) 2013 Satoshi Asano. All rights reserved. // #import "NJKWebViewProgress.h" NSString *completeRPCURL = @"webviewprogressproxy:///complete"; const float NJKInitialProgressValue = 0.1f; const float NJKInteractiveProgressValue = 0.5f; const float NJKFinalProgressValue = 0.9f; @implementation NJKWebViewProgress { NSUInteger _loadingCount; NSUInteger _maxLoadCount; NSURL *_currentURL; BOOL _interactive; } - (id)init { self = [super init]; if (self) { _maxLoadCount = _loadingCount = 0; _interactive = NO; } return self; } - (void)startProgress { if (_progress < NJKInitialProgressValue) { [self setProgress:NJKInitialProgressValue]; } } - (void)incrementProgress { float progress = self.progress; float maxProgress = _interactive ? NJKFinalProgressValue : NJKInteractiveProgressValue; float remainPercent = (float)_loadingCount / (float)_maxLoadCount; float increment = (maxProgress - progress) * remainPercent; progress += increment; progress = fmin(progress, maxProgress); [self setProgress:progress]; } - (void)completeProgress { [self setProgress:1.0]; } - (void)setProgress:(float)progress { // progress should be incremental only if (progress > _progress || progress == 0) { _progress = progress; if ([_progressDelegate respondsToSelector:@selector(webViewProgress:updateProgress:)]) { [_progressDelegate webViewProgress:self updateProgress:progress]; } if (_progressBlock) { _progressBlock(progress); } } } - (void)reset { _maxLoadCount = _loadingCount = 0; _interactive = NO; [self setProgress:0.0]; } #pragma mark - #pragma mark UIWebViewDelegate - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if ([request.URL.absoluteString isEqualToString:completeRPCURL]) { [self completeProgress]; return NO; } BOOL ret = YES; if ([_webViewProxyDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { ret = [_webViewProxyDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; } BOOL isFragmentJump = NO; if (request.URL.fragment) { NSString *nonFragmentURL = [request.URL.absoluteString stringByReplacingOccurrencesOfString:[@"#" stringByAppendingString:request.URL.fragment] withString:@""]; isFragmentJump = [nonFragmentURL isEqualToString:webView.request.URL.absoluteString]; } BOOL isTopLevelNavigation = [request.mainDocumentURL isEqual:request.URL]; BOOL isHTTP = [request.URL.scheme isEqualToString:@"http"] || [request.URL.scheme isEqualToString:@"https"]; if (ret && !isFragmentJump && isHTTP && isTopLevelNavigation) { _currentURL = request.URL; [self reset]; } return ret; } - (void)webViewDidStartLoad:(UIWebView *)webView { if ([_webViewProxyDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { [_webViewProxyDelegate webViewDidStartLoad:webView]; } _loadingCount++; _maxLoadCount = fmax(_maxLoadCount, _loadingCount); [self startProgress]; } - (void)webViewDidFinishLoad:(UIWebView *)webView { if ([_webViewProxyDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { [_webViewProxyDelegate webViewDidFinishLoad:webView]; } _loadingCount--; [self incrementProgress]; NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; BOOL interactive = [readyState isEqualToString:@"interactive"]; if (interactive) { _interactive = YES; NSString *waitForCompleteJS = [NSString stringWithFormat:@"window.addEventListener('load',function() { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = '%@'; document.body.appendChild(iframe); }, false);", completeRPCURL]; [webView stringByEvaluatingJavaScriptFromString:waitForCompleteJS]; } BOOL isNotRedirect = _currentURL && [_currentURL isEqual:webView.request.mainDocumentURL]; BOOL complete = [readyState isEqualToString:@"complete"]; if (complete && isNotRedirect) { [self completeProgress]; } } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { if ([_webViewProxyDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { [_webViewProxyDelegate webView:webView didFailLoadWithError:error]; } _loadingCount--; [self incrementProgress]; NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; BOOL interactive = [readyState isEqualToString:@"interactive"]; if (interactive) { _interactive = YES; NSString *waitForCompleteJS = [NSString stringWithFormat:@"window.addEventListener('load',function() { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = '%@'; document.body.appendChild(iframe); }, false);", completeRPCURL]; [webView stringByEvaluatingJavaScriptFromString:waitForCompleteJS]; } BOOL isNotRedirect = _currentURL && [_currentURL isEqual:webView.request.mainDocumentURL]; BOOL complete = [readyState isEqualToString:@"complete"]; if (complete && isNotRedirect) { [self completeProgress]; } } #pragma mark - #pragma mark Method Forwarding // for future UIWebViewDelegate impl - (BOOL)respondsToSelector:(SEL)aSelector { if ( [super respondsToSelector:aSelector] ) return YES; if ([self.webViewProxyDelegate respondsToSelector:aSelector]) return YES; return NO; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { NSMethodSignature *signature = [super methodSignatureForSelector:selector]; if(!signature) { if([_webViewProxyDelegate respondsToSelector:selector]) { return [(NSObject *)_webViewProxyDelegate methodSignatureForSelector:selector]; } } return signature; } - (void)forwardInvocation:(NSInvocation*)invocation { if ([_webViewProxyDelegate respondsToSelector:[invocation selector]]) { [invocation invokeWithTarget:_webViewProxyDelegate]; } } @end ================================================ FILE: Pods/NJKWebViewProgress/NJKWebViewProgress/NJKWebViewProgressView.h ================================================ // // NJKWebViewProgressView.h // iOS 7 Style WebView Progress Bar // // Created by Satoshi Aasano on 11/16/13. // Copyright (c) 2013 Satoshi Asano. All rights reserved. // #import @interface NJKWebViewProgressView : UIView @property (nonatomic) float progress; @property (nonatomic) UIView *progressBarView; @property (nonatomic) NSTimeInterval barAnimationDuration; // default 0.1 @property (nonatomic) NSTimeInterval fadeAnimationDuration; // default 0.27 @property (nonatomic) NSTimeInterval fadeOutDelay; // default 0.1 - (void)setProgress:(float)progress animated:(BOOL)animated; @end ================================================ FILE: Pods/NJKWebViewProgress/NJKWebViewProgress/NJKWebViewProgressView.m ================================================ // // NJKWebViewProgressView.m // // Created by Satoshi Aasanoon 11/16/13. // Copyright (c) 2013 Satoshi Asano. All rights reserved. // #import "NJKWebViewProgressView.h" @implementation NJKWebViewProgressView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self configureViews]; } return self; } - (void)awakeFromNib { [super awakeFromNib]; [self configureViews]; } -(void)configureViews { self.userInteractionEnabled = NO; self.autoresizingMask = UIViewAutoresizingFlexibleWidth; _progressBarView = [[UIView alloc] initWithFrame:self.bounds]; _progressBarView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; UIColor *tintColor = [UIColor colorWithRed:22.f / 255.f green:126.f / 255.f blue:251.f / 255.f alpha:1.0]; // iOS7 Safari bar color if ([UIApplication.sharedApplication.delegate.window respondsToSelector:@selector(setTintColor:)] && UIApplication.sharedApplication.delegate.window.tintColor) { tintColor = UIApplication.sharedApplication.delegate.window.tintColor; } _progressBarView.backgroundColor = tintColor; [self addSubview:_progressBarView]; _barAnimationDuration = 0.27f; _fadeAnimationDuration = 0.27f; _fadeOutDelay = 0.1f; } -(void)setProgress:(float)progress { [self setProgress:progress animated:NO]; } - (void)setProgress:(float)progress animated:(BOOL)animated { BOOL isGrowing = progress > 0.0; [UIView animateWithDuration:(isGrowing && animated) ? _barAnimationDuration : 0.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ CGRect frame = _progressBarView.frame; frame.size.width = progress * self.bounds.size.width; _progressBarView.frame = frame; } completion:nil]; if (progress >= 1.0) { [UIView animateWithDuration:animated ? _fadeAnimationDuration : 0.0 delay:_fadeOutDelay options:UIViewAnimationOptionCurveEaseInOut animations:^{ _progressBarView.alpha = 0.0; } completion:^(BOOL completed){ CGRect frame = _progressBarView.frame; frame.size.width = 0; _progressBarView.frame = frame; }]; } else { [UIView animateWithDuration:animated ? _fadeAnimationDuration : 0.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ _progressBarView.alpha = 1.0; } completion:nil]; } } @end ================================================ FILE: Pods/NJKWebViewProgress/README.md ================================================ # NJKWebViewProgress NJKWebViewProgress is a progress interface library for UIWebView. Currently, UIWebView doesn't have official progress interface. You can implement progress bar for your in-app browser using this module. iOS ScreenShot 1 NJKWebViewProgress doesn't use CocoaTouch's private methods. It's AppStore safe. # Used in Production - [Yahoo! JAPAN](https://itunes.apple.com/app/yahoo!-japan/id299147843?mt=8) - [Facebook](https://itunes.apple.com/app/facebook/id284882215?mt=8‎) # Requirements - iOS 4.3 or later - ARC # Usage Instance `NJKWebViewProgress` and set `UIWebViewDelegate`. If you set `webViewProxyDelegate`, `NJKWebViewProgress` should perform as a proxy object. ```objc _progressProxy = [[NJKWebViewProgress alloc] init]; // instance variable webView.delegate = _progressProxy; _progressProxy.webViewProxyDelegate = self; _progressProxy.progressDelegate = self; ``` When UIWebView start loading, `NJKWebViewProgress` call delegate method and block with progress. ```objc -(void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress { [progressView setProgress:progress animated:NO]; } ``` ```objc progressProxy.progressBlock = ^(float progress) { [progressView setProgress:progress animated:NO]; }; ``` You can determine the current state of the document by comparing the `progress` value to one of the provided constants: ```objc -(void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress { if (progress == NJKInteractiveProgressValue) { // The web view has finished parsing the document, // but is still loading sub-resources } } ``` This repository contains iOS 7 Safari style bar `NJKWebViewProgressView`. You can choose `NJKWebViewProgressView`, `UIProgressView` or your custom bar. # Install ## CocoaPods ``` pod 'NJKWebViewProgress' ``` # License [Apache]: http://www.apache.org/licenses/LICENSE-2.0 [MIT]: http://www.opensource.org/licenses/mit-license.php [GPL]: http://www.gnu.org/licenses/gpl.html [BSD]: http://opensource.org/licenses/bsd-license.php [MIT license][MIT]. ================================================ FILE: Pods/Pods.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 00724B07B0A479DCD63B547C930BF202 /* RACEmptySequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 99B636AEBE4F97178E01D3B80FEEB991 /* RACEmptySequence.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0387355C50F377A44E1161FE0F16F7F7 /* RACSerialDisposable.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D77C8A4DFBF971B00581F616C5C3AA5 /* RACSerialDisposable.m */; }; 03AC2048B8CCA5AADB8BF23135CB47EA /* RACCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D01E0F3F1F8BA7C23356819729299A1 /* RACCommand.m */; }; 0497875A83FEFFE6FA8C21190B15FE24 /* NSArray+RACSequenceAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A55E6FACC73AF55EF9836CC6A9EF858 /* NSArray+RACSequenceAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 04D1F0C5715EBF0DA0A59B8C80D7B4D3 /* NSEnumerator+RACSequenceAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF286368DF6F4FD3E718A8DDF0B1329 /* NSEnumerator+RACSequenceAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 04D69F84002443FD2881A5BBA179854C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; 081E72BFD20CC752979F2FA5FA0A9C42 /* NSString+RACSequenceAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BED186263438A97A14FFFB416C0B465 /* NSString+RACSequenceAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 09F3D0ED576A78F226E6EEC993284BAF /* RACSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C3F23F399EF62C8DEDADC7C32F2654B /* RACSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0A8ECD4D136D26E0D73B078DE75BAA2B /* RACStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 17FC11D339BD88DE46A3832ADB2E7698 /* RACStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0AB2C696D41303218E29F03493594296 /* MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B7DA8685E9F6509969D1AC3428C9AC1 /* MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0C81071CF813878A9947510748992FC2 /* Result-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EFBC1962ABC17786F033C5D955C426A /* Result-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0D7ED1B1D76230793B749C5107FC60A3 /* NSData+RACSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 99C98D7479B3CF2EF91FF077AFC2E3FA /* NSData+RACSupport.m */; }; 0DDC94CFCC6EC337D701BA9CE07395AB /* UIScrollView+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = A09567EF6A6A8400BEC6E81380B768F6 /* UIScrollView+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0E98EC3E7AEA7162CFAE6EF57D2B28AF /* RACSignalSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FACA2BDAE37AF70AF131A9DD8C8F023 /* RACSignalSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0F12BAF3BF633C35A7CC0994F141D84A /* MJRefreshStateHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 24AC80CE0FB0E80AF69BF07269013518 /* MJRefreshStateHeader.m */; }; 0F584B41F61BD287EF16D346CF64D80F /* RACDisposable.m in Sources */ = {isa = PBXBuildFile; fileRef = E82FFE3AE1A6AD452A3B2CD3EEFCEC61 /* RACDisposable.m */; }; 0FB27BA2048911FE563797AA16E79557 /* RACStringSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A0B49C3C170F533DDC330533C388200 /* RACStringSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0FC3BB949D35D24F32CE9BD37BD4724F /* MJRefreshFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = D30739FD0BBBC87DCA328AB763D58A85 /* MJRefreshFooter.m */; }; 10867C687E423B0F969783EE5B69D138 /* NSUserDefaults+RACSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B20AC59ED957F2FFCFD375B980767D8 /* NSUserDefaults+RACSupport.m */; }; 10F1286131E7834EB6C42998503C8A11 /* SVRadialGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7094B67ADA79A207B80ED1C678096C56 /* SVRadialGradientLayer.m */; }; 110CC60B2EF89629C7A98C691B694DB2 /* NSString+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C4DB204F82A21C053C14A75D8A2253D /* NSString+MJExtension.m */; }; 11CCD157B8D314668F913B066D01ABD8 /* NSData+ImageContentType.m in Sources */ = {isa = PBXBuildFile; fileRef = AA298557E9E97C6386EC51A27CB4206B /* NSData+ImageContentType.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 129CB9A6396C5E3D0404A2993BDFA089 /* NSURLConnection+RACSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0200FADDFC41780A72461242A8933469 /* NSURLConnection+RACSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12CFBCACB2BCB8BDDA05893B31D87692 /* RACCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = FB5F5A3768964DE4BF07FD98955E6581 /* RACCommand.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12D9E2794BC032F7945EF8D62E2DFB6D /* UITableViewHeaderFooterView+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C179B4B0A25E2587F438F48E729F964 /* UITableViewHeaderFooterView+RACSignalSupport.m */; }; 13AEADBEC76DB1C060C123080CFCCD6E /* MJRefreshBackStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 327D589BF0F977BFF88D99840464BD9B /* MJRefreshBackStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13CDA14946A4311259575FB563E4C475 /* NSObject+RACSelectorSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = EC40E5CC64338F892D0C9C3F62F4F58C /* NSObject+RACSelectorSignal.m */; }; 145DF26BD5EDAF491625C13FF2E638E0 /* RACReturnSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F0D58F39A052B2E7FD5A8DBF7C70C6C /* RACReturnSignal.m */; }; 1480F4923DBBF217F60572EEECB4027C /* AFNetworkActivityIndicatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3ECE5AD23F674D5730471BE3A13366F8 /* AFNetworkActivityIndicatorManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1681F1426F8DB09870F4F2BB8D44F51D /* UITableViewCell+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 70335EEB3F3ED4753931F862F6AE2D4C /* UITableViewCell+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1698F95CBDC543F4C347CD51A0FD034F /* UITextView+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 2571CE5A2B6427EE7C1CD76E1A71FE5F /* UITextView+RACSignalSupport.m */; }; 174202BD6AE0E4A41F5CE66E975EAE52 /* UIRefreshControl+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = FCCD810BBA0A1C5CBD98C80A0740A751 /* UIRefreshControl+AFNetworking.m */; }; 17EB39392F9E486B79933146AE4260C9 /* DACircularProgress-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D433893D61787615D32A3BB9DA9D51A /* DACircularProgress-dummy.m */; }; 184AEAF1B4DAC4EC608312ECF96CA682 /* UIStepper+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = CFF28FD09E7B21D2B491C785A9F1752F /* UIStepper+RACSignalSupport.m */; }; 194BE0684BEBC29B137094C4491DC9AB /* MJRefreshConst.m in Sources */ = {isa = PBXBuildFile; fileRef = D394875D112D2406E07D6783972EAA9E /* MJRefreshConst.m */; }; 1AFC2415B88A6E4E696131828997E417 /* SDWebImageDownloaderOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 06B28D9101904B3DDA53E7542414905D /* SDWebImageDownloaderOperation.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 1B625386A867038C73A98AF1DA0FB5A5 /* RACSubscriptingAssignmentTrampoline.h in Headers */ = {isa = PBXBuildFile; fileRef = ED3B91A5243892EA1305E4F5870D3AF0 /* RACSubscriptingAssignmentTrampoline.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1DF62BEA1160CCD444A1E3E43EB568FB /* RACSubscriber.m in Sources */ = {isa = PBXBuildFile; fileRef = 2ACEC0A293FEFB84F29DD8A55BA24605 /* RACSubscriber.m */; }; 1E37383432F16FB3D6F6F8043C358217 /* MJRefreshBackFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 779C75D5D0D23A1AB35ECFF926AAD43E /* MJRefreshBackFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1E5B8F12ED7CC40ECDB9B1F755F387E5 /* UIActivityIndicatorView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CFB09319D3043B97E87098173ACB6A3 /* UIActivityIndicatorView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1F6F88E5512E3C7C12F253386DF12E00 /* RACArraySequence.m in Sources */ = {isa = PBXBuildFile; fileRef = A96EA91189E9737332A144B71892B45D /* RACArraySequence.m */; }; 204EF58021934704EA0E32FBDF5E031F /* MJRefreshFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = F0D450CC9C0FF76EC8DD1E7380FB0A6F /* MJRefreshFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20607BE2B1E5F31765026E5AC64DB27D /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8CEF4CEDA5F903EFD528676610423C /* AFSecurityPolicy.m */; }; 20745870A76E57E9AC3B66605226821F /* ReactiveCocoa-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D310D5AB2204F87230BFC6C3C9B0134E /* ReactiveCocoa-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20EE8030FCF2402DAC7F1C9B9DDAEF79 /* AFURLRequestSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = B1E666B007C5C55BDB7AA3FB5D798960 /* AFURLRequestSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; 210B48234B872F3081567E5FA1B56C0C /* MJRefreshAutoStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC76762C8413ACAEF0462E770E5BADE3 /* MJRefreshAutoStateFooter.m */; }; 21842D1B00812EE8754713B0E9B08514 /* MJRefreshBackNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 760C68EEB4C3B3288B8D028C95AF4A5B /* MJRefreshBackNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21C7737CC4A052AA1EE2E8758FE0346F /* Bag.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0798A8391AC76966E0969FC1E819EBD /* Bag.swift */; }; 2304694ADD5E56A50B15A5705A3342A0 /* UIStepper+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 67A6E7EE4BABE5B9C6F5BC0A445F4BF5 /* UIStepper+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23FD63A798C947A567842AFE4C49D7D2 /* TupleExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B68E10B6BA0F1B0D4E3C8096500C8DBF /* TupleExtensions.swift */; }; 24C537660666185D8B113F4A0830E6FB /* MJRefreshBackNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F26B0A5160BB003B5AA2DEE23E1CF27 /* MJRefreshBackNormalFooter.m */; }; 251707CDFB6180CE3DF78837B79F9BB7 /* RACUnit.m in Sources */ = {isa = PBXBuildFile; fileRef = 39B819887AD00091E47EFEBB1C4D6293 /* RACUnit.m */; }; 253B94DA5A839424B768C83B45A050FB /* DALabeledCircularProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = D443DF293DAD2B3569FB6C2757DE5DEE /* DALabeledCircularProgressView.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 258E4A137C79920CCEE9C7D01EC99A67 /* RACTuple.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B9F762F0010F498291E76E02D8E7F51 /* RACTuple.m */; }; 26AC9A4F41F0FFE516782716202CB6E6 /* Pods-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 894E5DA93A9F359521A89826BE6DA777 /* Pods-dummy.m */; }; 271E9F901C547EBFAA6EBFBF0BC5604A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; 279A0F937F96FB714A42A09E839EB8C3 /* MJPropertyType.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD56469E8EF363D5728F35AFF09628D /* MJPropertyType.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27FF9D7097A5696D8B9630C19C83ED24 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; 2881816427D93B7FC0A086299BBA23F4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; 288886A12930E5129511977F8563DA28 /* DALabeledCircularProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = BB6D9CAD4BED373DCB3EEE7170CDFEB2 /* DALabeledCircularProgressView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 28AF8EAC58ABA02BD0F59B0AF8A69D7D /* RACBlockTrampoline.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D287DD867B406F2ADEB2636891D4EBE /* RACBlockTrampoline.m */; }; 28F9E23A6D412DF172FD4EEDEC7507A0 /* RACTuple.h in Headers */ = {isa = PBXBuildFile; fileRef = BD7C6AC814B6C827D15CA018A32E68D6 /* RACTuple.h */; settings = {ATTRIBUTES = (Public, ); }; }; 293446B78D3872E897C9AAD4798FBA93 /* MJProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = D947872ED90AA60B0F658492E4AEC97E /* MJProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; 29838BA5F72777DD963F2C4D9B21770C /* RACKVOChannel.m in Sources */ = {isa = PBXBuildFile; fileRef = 178C15910519FE8A1A6EDF25064EBAC9 /* RACKVOChannel.m */; }; 2A86D12018C01DEA1A0A652CEAA8A60F /* SDWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = BDAB1FFC1AAA7DC65A96E0DD0E808705 /* SDWebImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2ABF9BBDAE5215C2FEA04D9F220446EC /* MJRefreshAutoFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = B5516D92939621BD471E86FDA40744D6 /* MJRefreshAutoFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2AFAEAE18B28D77C49D7E4FC8ED26041 /* RACGroupedSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = BA4602700DF3E5C3D59A8073A330C497 /* RACGroupedSignal.m */; }; 2B432A2CA37699689687A3B625E9C957 /* RACDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = B30ECCFDDBE8A3CD9FBD6985CA8C516A /* RACDelegateProxy.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2B46C2FC31AD47B30D1F4D26E9F23318 /* RACBehaviorSubject.h in Headers */ = {isa = PBXBuildFile; fileRef = F5FFB3C8AD598A1BD00CC6AD1A661249 /* RACBehaviorSubject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2DE5F9002497B8304F130584A7B8E9BC /* MJRefreshAutoGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 93C4F71361B0469BE16C31AB9579776F /* MJRefreshAutoGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2E10FBB442212F0FACF0A2B3E7AE6495 /* NSObject+RACLifting.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AE78463FCE5D33E21D15A0EE9DB7957 /* NSObject+RACLifting.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2E8A32ED46194EDBE22146271F6D26DE /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 81385A2C31D5D660F1189632254CB601 /* UIImageView+AFNetworking.m */; }; 2ED13D4A87D269ADA038C269093F3AE3 /* UIActionSheet+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F89340C49BD17D20E0A729312481FD /* UIActionSheet+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2ED25110C57F536506C512DC2EAA6F04 /* RACValueTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BC0DC5C5BD1AAD23974E567532B5A3F /* RACValueTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2FA7914B3CEF5CD29FDDDA2CC8D7DBD8 /* NSObject+RACDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 6856BC220D1A3E3FBEFDF2A9F6FE2659 /* NSObject+RACDescription.m */; }; 304D6E134A4BAD7BF36C90FE55A331CF /* NSObject+MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 02E1B6AA6AA6390F3F754295B465C3A7 /* NSObject+MJProperty.m */; }; 31F2FDB763BB011A256808751590329E /* RACUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F61C5CC2A3A56EB81D4794106C378AC /* RACUnit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 33391B350D746D0ECC0A3E1918A9CEEF /* UISegmentedControl+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 089193F3B7A92B972D1332D86CC8A3D8 /* UISegmentedControl+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 33AF5F27C6E285B73FEC9024938A884F /* UITextView+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A9964D7562908E51C1C056A746B0AE49 /* UITextView+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 362778BBAA748228039CA8882770A72D /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA8B7E4FBDC083EDF3149135E2DEE349 /* Property.swift */; }; 36C86787510E3AA04357D7DBCABE25FC /* RACObjCRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 54A77C4EA7F3B970E9396FD77260DC39 /* RACObjCRuntime.h */; settings = {ATTRIBUTES = (Public, ); }; }; 373BBB3417DA29B53A80B329E2ABA6EE /* UITextField+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D0C2271A31DC0318C3F599828368EED /* UITextField+RACSignalSupport.m */; }; 37CFC18B5DF1320C54DD8A28C1EA5118 /* MJRefreshHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 287EEB49D92EC73042E3C0D5A7376FFF /* MJRefreshHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3856564171C0B06F0B921E8AC6DBDC9A /* RACStringSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = A89FC17E6B10BFEF06045D45EC8F6FF8 /* RACStringSequence.m */; }; 393009168925491E8921A9D528B68A05 /* RACEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FA901B394FEF81CC1CBCDE93E4E4E33 /* RACEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3A10EF6ABF51D1D00B06AC5EF3A8C28C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EBF5ED419CFAF406CAB22FC12D646EE /* SystemConfiguration.framework */; }; 3A4577E765151065542A2FE61049AEB6 /* NSData+ImageContentType.h in Headers */ = {isa = PBXBuildFile; fileRef = B448D8632DF91896DFCD0BEFF7244E5D /* NSData+ImageContentType.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3B8C19501B83034CBD92BC35F32E9B55 /* ReactiveCocoa-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 131F1B7D90AD4CDC3DC4D5002774196F /* ReactiveCocoa-Bridging-Header.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3C0C307560729C357B4AE20D44EE9A42 /* RACSerialDisposable.h in Headers */ = {isa = PBXBuildFile; fileRef = 421D68D254751D710514290C3F142623 /* RACSerialDisposable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3D264EAFC6A30E26A7325BB38B4230B5 /* UIDatePicker+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 81D25D4F4D6B7D02E21F5C8C0BB43218 /* UIDatePicker+RACSignalSupport.m */; }; 3D2789FC760A97301909F0B1201626CD /* AFNetworking-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D28CE0133DF0CAD2C661C21BD8804D7 /* AFNetworking-dummy.m */; }; 3EFE7CAD294140A8E9550A8A267D0676 /* RACEmptySignal.m in Sources */ = {isa = PBXBuildFile; fileRef = CAD8C2C811FA110EB1D85F0F6BDC41A3 /* RACEmptySignal.m */; }; 3F1BC9BAFFEEABB1ABC7614DF0FC97D5 /* AFAutoPurgingImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 83D878636318BC9BC302D1BA76A4CC46 /* AFAutoPurgingImageCache.m */; }; 4023867FB0DEFB7CBF1428DFB783E7D9 /* UICollectionReusableView+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = F837CA4A39C79C92F66C2AC2957863E3 /* UICollectionReusableView+RACSignalSupport.m */; }; 40DEAC560BE1E33237B2B035B0C3C262 /* UIImagePickerController+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 487C7B37C3A3AE467452EB40973AB2E3 /* UIImagePickerController+RACSignalSupport.m */; }; 413A819F1C48B8B9903B8EF88B92D58C /* UIImageView+HighlightedWebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B3EACFC90A3853E0536A4DA5562CE760 /* UIImageView+HighlightedWebCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 41A7867BEFE2E46807C97D08D3C6BF46 /* UITableViewHeaderFooterView+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D181778EACAB30C2DF3EB81AFCC312D /* UITableViewHeaderFooterView+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 421F3D9FD0162A3EA02B1F2C6BE5860B /* RACEagerSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD0C1BD3A05CF5DDAA0C32F95C7CCFC /* RACEagerSequence.m */; }; 424879726EBBB16DFE90D267551D472C /* NSSet+RACSequenceAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B9CBA6ACA140F7557934629609816945 /* NSSet+RACSequenceAdditions.m */; }; 42593A48BAACE31A0FEDAEF23883D63A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AE98AF69BAD8F07BB16232D800176C8 /* QuartzCore.framework */; }; 42705136A12B109D3390F706FD017D4A /* NJKWebViewProgress.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A6E8E3B715B4995F7DEE5A5FDF8EDE /* NJKWebViewProgress.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4287E4DDF78271B6AF8715292D6FC512 /* RACScheduler+Subclass.h in Headers */ = {isa = PBXBuildFile; fileRef = 36C67D4D144F82BB460E86417F992329 /* RACScheduler+Subclass.h */; settings = {ATTRIBUTES = (Public, ); }; }; 42BE038A05A9E0D9A0ED57857F3DC2C4 /* UIGestureRecognizer+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = F398BCA5C354DE916BE3F66F46468339 /* UIGestureRecognizer+RACSignalSupport.m */; }; 433478893128C30315BC255A44723D53 /* RACDynamicSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = 32422BA7F298B775A904F182146351C0 /* RACDynamicSequence.m */; }; 44C9FF75FB900236B6073645EE05D412 /* MJRefresh-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 23EC168D4DE256790968AF644F46052A /* MJRefresh-dummy.m */; }; 44DFF77EE49C02DB5A164C9014D396CD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; 459DE06B198852EAC2C492888162ED11 /* MJPropertyKey.m in Sources */ = {isa = PBXBuildFile; fileRef = AA50E3F6E4BFEC14F9568DF42598C79D /* MJPropertyKey.m */; }; 467233A8180FB272DAB57FD1FE8D516D /* SDWebImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CC208244E551D18584AE550743152D /* SDWebImage-dummy.m */; }; 48245FBC81E27E0F30C357B7A6D32090 /* RACCompoundDisposable.m in Sources */ = {isa = PBXBuildFile; fileRef = 50EFB6EA010031514D3C926778AE4B28 /* RACCompoundDisposable.m */; }; 494D62C84A6BA6EE9AAE3A8AE2A1A3CE /* RACKVOChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 06880042FBC5FCBF625C5CFF84286B13 /* RACKVOChannel.h */; settings = {ATTRIBUTES = (Public, ); }; }; 49975810AF5B32D24D3EAAE9E4776E93 /* MJExtension-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B82339D1E8C4BE689DDD67A528D77FF /* MJExtension-dummy.m */; }; 4B3CA2CA6977D05A9175EC8166226DB8 /* NSFileHandle+RACSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 519DC0F16ADF084A298A1C1FBCBFD8FB /* NSFileHandle+RACSupport.m */; }; 4B983DCAE762551646E5782347B7287A /* MJRefreshAutoGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 701745585DCF4B7F3AD5CA8E9A3283E6 /* MJRefreshAutoGifFooter.m */; }; 4D05FB8DA7185611612A386D92AE490A /* MJRefreshAutoStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = FD9BF1E603B15AF71FFFCB71245E0CAB /* MJRefreshAutoStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D51DA2C84DABDB517491E5414B09659 /* RACImmediateScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = 11D6C1C4122D8FE7CA3BC466EB85EA0C /* RACImmediateScheduler.m */; }; 4E3E184ADF8AB31FB3475A12997109E1 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5C539E675EC20D05160336D5856B14 /* Errors.swift */; }; 4F68348E2A31F997408476E01728417B /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FC2184908F405511534A14E70D16DAF /* Result.framework */; }; 5023BE708F043790DC1EEE1C1FD82C65 /* SDWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D1435E2B8DC44D70DAD2E74DB5ED4F48 /* SDWebImageOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5030B65ECDFC47218E46FF3022228735 /* SDWebImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C9992D6643E6705FB59DFECB608AFA /* SDWebImageDownloader.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 50E93FB3B4A7BB080E108302F1DAD186 /* NSObject+RACDeallocating.m in Sources */ = {isa = PBXBuildFile; fileRef = 62099B3D70733BED521A40A4AE13014B /* NSObject+RACDeallocating.m */; }; 511FD83A2DFE095A686E38263A7070F6 /* NSObject+RACDeallocating.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5FB4710E695F1BAE791F9A50A108E2 /* NSObject+RACDeallocating.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5185EE40B00B0C1B29AD983337395ECA /* UIView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = F0D1B728EB6048D8D5B0AC2D40EC9E40 /* UIView+MJExtension.m */; }; 521D09952B30FFC7243BE3F320E37EB8 /* NSObject+RACPropertySubscribing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F12FBEE960935A37F82ED5D29FDA3CC /* NSObject+RACPropertySubscribing.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5289231C360AA65EB109132B58C986A6 /* RACDynamicSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = E0C6216E113A1F9A069260ED5B50111F /* RACDynamicSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; 535CA73BCA2B2AFF75EA7E12F3CA7DB6 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80687972DF9A550FCDC275E9D92735D /* Action.swift */; }; 547CD9A3386E91DAEE0DBFBB8EF0235B /* RACEmptySignal.h in Headers */ = {isa = PBXBuildFile; fileRef = 99940E95018B693482DA0E603FBE96E1 /* RACEmptySignal.h */; settings = {ATTRIBUTES = (Private, ); }; }; 54E8EEF1AF4EC853E8A626318018D461 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8CB0F2BBB3216F8BC69ABD64494045 /* Result.swift */; }; 5573127307BDE2B33F75A242B4CE842A /* NSObject+RACLifting.m in Sources */ = {isa = PBXBuildFile; fileRef = 20740BE7A5516344AB7DC38CDD8896E0 /* NSObject+RACLifting.m */; }; 560698A4D707DCBCC1C8F98BC9B89B23 /* AFURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F58E4B445DAA8708DBC10F3116C81417 /* AFURLSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 56AADC1B87576F8B8175BE4B99C3F5B5 /* MJRefreshComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A7B5DD43A49B31BDAEEA9D8A50D6DDF /* MJRefreshComponent.m */; }; 577BEE9E06FE5EC16DDCE8AD88B09979 /* NSObject+MJKeyValue.h in Headers */ = {isa = PBXBuildFile; fileRef = C44B145F63067DA65072538D023F78C9 /* NSObject+MJKeyValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; 579985D58E8BCBBBB532AD722F73E9CC /* RACSignalSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = A715FDA5CEEA5F15D55327E810A04267 /* RACSignalSequence.m */; }; 5808B477EFF509D810B5CDCFDC944F80 /* AFImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = FDE6FE508EE14BE865B0AED358D641BB /* AFImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5896DB746ABBB4D6BE7EE7F8C4F548FE /* RACEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 25ADFA74A42F4EA16E025EAFFC997CE2 /* RACEvent.m */; }; 5936075C0501A4F055261D7641B4F6E9 /* MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 6587A73A29A00806426C245D436CC4DB /* MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5A9215CA981A4E85D205898F066F2672 /* RACPassthroughSubscriber.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D8C52C4C1363BDAB126CC314303CF68 /* RACPassthroughSubscriber.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5BAF5BDEF5580DF0D6D3BE4BA9F50C08 /* NSIndexSet+RACSequenceAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 866913B5AAAA621C55BF26E3F1FA5F19 /* NSIndexSet+RACSequenceAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5BBC034F990B6A23EAAD08B6A8A761E7 /* RACDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B7FC9995CDD31296CD24310BD75FE95 /* RACDelegateProxy.m */; }; 5BE17C62DC3644DA27BE4C6053F88D17 /* RACObjCRuntime.m in Sources */ = {isa = PBXBuildFile; fileRef = 50D655ED3DED0D8733D35DBF167C1F8B /* RACObjCRuntime.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 5DE3DFFCB8D5FDE635632112A4E0F005 /* SDWebImageDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 31BF7F9D6F415EE6D53EF01F9B610BA5 /* SDWebImageDecoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5E19E6D0B84161D5C1D91C1B3102D3C1 /* MKAnnotationView+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A4BFD7235669DFC6C5F8A7CA037E2BB0 /* MKAnnotationView+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F264302142FCAFE3AC672E773A3A534 /* UITextField+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = E73089F923B47D3893EED446E53C7E28 /* UITextField+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F657C8B9A31DD446865DA4F5EC67B60 /* RACMulticastConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 761B06747C21716F22BC760FB21E4D34 /* RACMulticastConnection.m */; }; 5FF6453E55785669885F626B853FD2AA /* UIProgressView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = BA49143A92AE77748413FEEE2654B389 /* UIProgressView+AFNetworking.m */; }; 60E3009342BEE96D32C546BE2DB60052 /* UIImageView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F8C104E2ECD5DAA7DF07B8AF6DC4E7C /* UIImageView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; 61305CCB40A29FF26DAF1C011ED8155B /* RACChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = B34411085B6CE8449ECF3DA79473A40A /* RACChannel.h */; settings = {ATTRIBUTES = (Public, ); }; }; 613581FE33A08B7F901B0A4FE5E18BB8 /* NSNotificationCenter+RACSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = B9A5FBE2156B8A0DA7B3F8FF89613307 /* NSNotificationCenter+RACSupport.m */; }; 62496692FFE6DC75E13074AB607992A5 /* NSOrderedSet+RACSequenceAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 388FDAF47EFEF8E2354262065ACD5432 /* NSOrderedSet+RACSequenceAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 63EAE2CF50A076295582BAC0ECECC503 /* NSOrderedSet+RACSequenceAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = E8C38A2B732C0C6570EA75D32ABC4EF4 /* NSOrderedSet+RACSequenceAdditions.m */; }; 6565E06393BF320ABDF8E2F838115A6E /* UIRefreshControl+RACCommandSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 7304BB1549A9A2B972545AEAD38EC23B /* UIRefreshControl+RACCommandSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 659960F7E28E993E08CCC1E8A383E710 /* UIKit+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 7762D610F1224AB1BA7F5CE589B317F1 /* UIKit+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6633446E76D3CC84B07DEF918907D4A0 /* NSDictionary+RACSequenceAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F57914A519C2E92A90FCBAC4C56BCA1 /* NSDictionary+RACSequenceAdditions.m */; }; 669460524FC57AB51CD3FC2A0822975B /* NJKWebViewProgress-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = ECB9285932E9DF2DD113CB88004F8A48 /* NJKWebViewProgress-dummy.m */; }; 66C7D6A69FD0247134E6149A6F09D5DC /* RACDynamicSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EED8A20E4204DC6AA2E74CC61A3E8BA /* RACDynamicSignal.h */; settings = {ATTRIBUTES = (Public, ); }; }; 670BE350467C2B2DA70FEA66DB726475 /* NSNotificationCenter+RACSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = D1F686D628D8073F4C50C9171C6F7F38 /* NSNotificationCenter+RACSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 677F340D45A43C07863B5CFB9F16FDFC /* MJRefreshAutoFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 665306F25921CE243C77B2179A928FC6 /* MJRefreshAutoFooter.m */; }; 6788B6B8B3FA97B1D3813482381457F6 /* MJRefresh.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 8DF2A484755B6BFAB3DD9E8749E0E32A /* MJRefresh.bundle */; }; 67B59A03535B18CDD348CF3204FCC8CD /* RACSubject.h in Headers */ = {isa = PBXBuildFile; fileRef = 2637ADDE4A30CF2CEF128EC9561C0B08 /* RACSubject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 68152D921ABF6A423C192C04FDF94F0F /* AFNetworkReachabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E02EC8F52BB28C3F34F78F3034DB4B0A /* AFNetworkReachabilityManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 68A38977EBAE334DC3C22386D00D2622 /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D380A4F4137C3191AC8C38C3844F6F9 /* AFNetworkReachabilityManager.m */; }; 6AEDCFF3FA4CFA352837DA11AE4A1B93 /* RACSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = 65B87D4C329AFCFF4F76B02AD0E6481D /* RACSignal.m */; }; 6B4898BC56C3A781EEE21E2ABE0E4E62 /* EXTRuntimeExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = F356A0AA79F9864B6198AEF0BF333D72 /* EXTRuntimeExtensions.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6C5C41305CB8F2C4B633C9F5A6D0742D /* RACSignalProvider.d in Sources */ = {isa = PBXBuildFile; fileRef = 99D86F5858BD2991F4054295DB9A6B81 /* RACSignalProvider.d */; }; 6D315C50D9018D7EEE3ABCE6D36EEBB4 /* SDWebImageCompat.m in Sources */ = {isa = PBXBuildFile; fileRef = 62BCF26D36C4317CFB733A51294C580A /* SDWebImageCompat.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 6DF2DEDC95B582C261A4ED2888891603 /* MJRefreshAutoNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = B8D50A20C640AA87771EF793A3B33D58 /* MJRefreshAutoNormalFooter.m */; }; 6E14DFC821D96FC7FE0C831682CFAC05 /* NSObject+MJCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E9E45A488ECF89F98B18D04BA6C46BF /* NSObject+MJCoding.m */; }; 6E62CB71F8583167781294A91D6EA743 /* NSObject+MJProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 65A88C62ACB26C7993D78A9751E7C43E /* NSObject+MJProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E887BF6A924958E7F9CFF227E9E1586 /* SignalProducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49D487F354F79D8D6D367F2EA263F418 /* SignalProducer.swift */; }; 6ED4ABEE8A5F51F5ECB59FA1781D29C6 /* UIActivityIndicatorView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F6E24019AF1B2A6251029C2F9F1C101 /* UIActivityIndicatorView+AFNetworking.m */; }; 7027D9AA84049E1083A7AC48CA979F08 /* NJKWebViewProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A80563F26E1898D391EBDD72319194A /* NJKWebViewProgressView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 705C497EAAA2CE57A920C4D9CC05B1A0 /* NSString+RACSequenceAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B9EB10C652C1C526AD0AD72B0542845A /* NSString+RACSequenceAdditions.m */; }; 707B1A7541C8DBDDE8C27896A61370BE /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C887DA74F733F87971CCE2DC0A90581 /* AFURLSessionManager.m */; }; 70C3C414596FB1C3E21F3C00996F39EF /* RACStream+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 11DF06DCB011608D84991AD684676153 /* RACStream+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 70D07B077BDD5EE5910BD44309DFB020 /* Observer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C164F0023335CC42ABF57B6AC5E3DCA /* Observer.swift */; }; 71B8F18B3823DAF8C6183EC3A1D0519A /* NSObject+RACSelectorSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = 29474BDF519166A22324D16A7341AF4A /* NSObject+RACSelectorSignal.h */; settings = {ATTRIBUTES = (Public, ); }; }; 731D869357FE82DBEA18142155FA5334 /* NSData+RACSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 88068B890B9C0588AC3CF4B903532BAC /* NSData+RACSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 732A6076A35301AFE02553A38DAEE618 /* RACTestScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5625480188612898E004BC6C041065 /* RACTestScheduler.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7332F15718920917F544F35CE2C038AA /* AFURLResponseSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4ADCC2A12D303D037DAF0853CCA30850 /* AFURLResponseSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; 733C2E31D6AB9A8A851D42B0BD6C45AC /* RACEmptySequence.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC03A006CBCD628BCEB58193DC7A5D2 /* RACEmptySequence.m */; }; 73EFFC322D098B3B8F91D86B0398B537 /* RACScopedDisposable.m in Sources */ = {isa = PBXBuildFile; fileRef = 615FAAC3A47F83CB019987185921481F /* RACScopedDisposable.m */; }; 7667A35A331F96CAACBC6B64CEBE43C0 /* RACReplaySubject.m in Sources */ = {isa = PBXBuildFile; fileRef = 51D219983844DE91EED12BF6C498F8CD /* RACReplaySubject.m */; }; 769106E9AC019F85C5188E44428ACD22 /* UISwitch+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 87D85553FDF0A6201B95EB15FD0276BE /* UISwitch+RACSignalSupport.m */; }; 76F1DD8C3C209438B307B1D329D54267 /* UIAlertView+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F84DC6C0850AC07A1B378574B872FF1 /* UIAlertView+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7790A780B0275647A252AA9FB1EBC276 /* RACTargetQueueScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F30E05A946B7A54A30BC72162F70A36 /* RACTargetQueueScheduler.m */; }; 77BE511C80FDD8423A3367AEBDEA9851 /* MJRefreshConst.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DD9D6B81C51F4F24E457F66295A90AE /* MJRefreshConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; 78106ADC03AC37B5BD2B14C45D033369 /* MJRefreshBackStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = D5C99DD591CB596FCA58275314A1283F /* MJRefreshBackStateFooter.m */; }; 784CF489F031186518D41D803E19B7D3 /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CD1EAE74FA692AC8BAEEACB053B9324 /* UIImage+GIF.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 791DC115A0616D0E1D76C2008830CDDD /* SVProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 665FD1AEECD5FFCFCE9EB168AEC03E6F /* SVProgressHUD.bundle */; }; 79AE09A7EA7C916F2249A23AD02A1A9F /* UIDatePicker+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 2566085556C7C46E97B0513F6A39D71B /* UIDatePicker+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 79D1BB6E7BA2EF1E1388F39F7BFD8D48 /* NSString+RACKeyPathUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = BD932B09F529355D99F88697668B2BD3 /* NSString+RACKeyPathUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7B0A87FD85C30E150E62FE2F6AFD714C /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB32F54022E8F7E71D5C575C764203F5 /* Event.swift */; }; 7B9B711ECADE8C962ED30B7747A7A60F /* MJRefreshBackGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D10AD9F1ACB5CD9CA679673D87F616C /* MJRefreshBackGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7CFD83CD3C93E655BDBDD20EDBE3AC89 /* RACUnarySequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC6ACF21F2B99DF847E417F2B74C659 /* RACUnarySequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7D686CEEA943ED9A03534418A1618F13 /* NJKWebViewProgress.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FE3B9592D5E80C0D98EB8611F9F7F05 /* NJKWebViewProgress.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 7DAE8A60D7FF35905A1199C13ADF1334 /* EXTKeyPathCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = ABC4CD8CC0631C4558A895B20BD1CE24 /* EXTKeyPathCoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7E6A4EFA32969CDB9F9C57903152BA54 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E186E931D518F5F01762FEACCE1188D9 /* CoreGraphics.framework */; }; 7E74E7B68C4D68223728386898038D20 /* NSString+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 91E412FCE5D6DD365C60CB8076F60FF3 /* NSString+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7E9FFD62DCF1B399B3E5C7F0ABF2A8B9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; 7EAFA40A7D8A7738076EC982D1FCB9F8 /* UIRefreshControl+RACCommandSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 19857320382C3934D1AA924AC1C439BF /* UIRefreshControl+RACCommandSupport.m */; }; 7F17EA5E2787B6F2BBB359854B42A0E3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; 7F3929881C52F1CAB7EDA45FADE72C5B /* UIControl+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E2982CC1BE3091121DC05292B2FDC00 /* UIControl+RACSignalSupport.m */; }; 7F8E4DFC4EB7B6EC92D2AE56790E4698 /* NSString+RACKeyPathUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D3789BA9ECCCC7F74C14776D5F7D2A76 /* NSString+RACKeyPathUtilities.m */; }; 7F925F8DF61ED6356DF8A6DFBA4F42F6 /* SVIndefiniteAnimatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 201A7F251D317877BB1F942144C004A3 /* SVIndefiniteAnimatedView.m */; }; 7FC128F6416C57B73631DDA5028F7EA4 /* NSIndexSet+RACSequenceAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = C91C625319E115577646BDAC4769DF5A /* NSIndexSet+RACSequenceAdditions.m */; }; 8068D341BFDBD17F71ADBCE0427CB6DC /* SVProgressHUD-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9C03D203D73109E5356C40978B6837 /* SVProgressHUD-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8176B584C906633CF35025C19C46B71B /* RACIndexSetSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = 32205878DBB803322E1B42440847ECAB /* RACIndexSetSequence.m */; }; 81B617F8D26BB10C5726D75E85D21EB7 /* UIButton+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D0D354758AEE84330634F2194E38953 /* UIButton+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; 838B46E9C2E5B00F39E34A69675505F4 /* SDWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 671C8806A9FB4EEF4D16B5DCB8DCB7A0 /* SDWebImageManager.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 83D63CF1C4BF96018964A868A8C3B19D /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B5A83C364AF6A759B6FAB36D1B3A4D /* FoundationExtensions.swift */; }; 83EBCD957DAAE26B53E30075624D161E /* UIImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 384B11EF54740D94671EBC40277A4AE1 /* UIImageView+WebCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 83F690D0EB0A3D033DE19B513DC38F31 /* RACErrorSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = B3EA5D64AD312484AAD0C2EA4F03BB66 /* RACErrorSignal.m */; }; 8419132DDBEA3303309BD94D048F046C /* UIButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F37169A84687244F35CFCC5ABEA8A01A /* UIButton+WebCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 84310740D64824ED883E984C2D715E8F /* ReactiveCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C3A4E7DDAA72BBF33F0FBB6D4C26C07 /* ReactiveCocoa.h */; settings = {ATTRIBUTES = (Public, ); }; }; 84378F3384B8A8A7D790547418600D1C /* RACKVOProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C329F969DD5A15D9B7DB7E2CE1CCD0 /* RACKVOProxy.h */; settings = {ATTRIBUTES = (Public, ); }; }; 843942BBF374018B605D9121EC7C259F /* SDWebImageDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 187AA5C92CBF850647DD36DB96B441C8 /* SDWebImageDecoder.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 85F961A88372C4AC3BBC1DE6DF16BB19 /* RACDynamicPropertySuperclass.m in Sources */ = {isa = PBXBuildFile; fileRef = FF23168D180714E936A4C3C601B08D1E /* RACDynamicPropertySuperclass.m */; }; 88DD07E075B4404F25112BA9230B688D /* UIBarButtonItem+RACCommandSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AB4385785B935EEAF37EFC56F267112 /* UIBarButtonItem+RACCommandSupport.m */; }; 89C4FA168E3BAB208640E8856D4139B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; 8B5CF5758057EA65EAF8D83BBDCD2970 /* NSFileHandle+RACSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = D283ADAA967B772489287A1DE7161B90 /* NSFileHandle+RACSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8D2EF02863C819015C4E2CB0871CEA8C /* RACTupleSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = C8320B310F2C0E3E62DC8D36525674BC /* RACTupleSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; 908F6453F4D78F2B67AFE459C199CA79 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05290D288C6535325D67AFBF86D00468 /* Atomic.swift */; }; 92C8799C7DDCDFBB08FCD3445950E8A7 /* NSUserDefaults+RACSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A72841D503B7B4AABD02FE508DABEDF /* NSUserDefaults+RACSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 937F27426A73331AFF12B021D1754419 /* MJRefreshNormalHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = DE3CAA2C90009AB04A9C1A9233566CA0 /* MJRefreshNormalHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 93EE6196A5980B844FD3D53EE66F83CA /* SDWebImagePrefetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = AB031EAC44BA3ABEDD23851F5D0892DB /* SDWebImagePrefetcher.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 94BB9BF355B759C0A3B64DC39D3EF053 /* UIGestureRecognizer+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = E4BE7396A99977EA27137A889AB23A82 /* UIGestureRecognizer+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 95062E558978E16F2F13BB5D665B2C4B /* RACReplaySubject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1832EC5F5771FBEA5CE0B7E5C0C3C60C /* RACReplaySubject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 961B768DF18068867B281C6D2075DF26 /* NSObject+MJClass.m in Sources */ = {isa = PBXBuildFile; fileRef = D09C25D5FC16E6F61F1AA912B9A39B65 /* NSObject+MJClass.m */; }; 96BABE17042E8F3CE7F8029ABE3A686D /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08C93F88B6CA9D68E60D8989E39989F /* Scheduler.swift */; }; 98B00B62E980F6C474D221C5F120E7D6 /* EXTScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 48B920D6E809F194511B3781F25F9055 /* EXTScope.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9ACB2C22B46D4A8A80A0B5591B4240E1 /* SDWebImageCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = 2664FC6FC44BC040C045CBF9826A5956 /* SDWebImageCompat.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C3A46A67A2FE2F8E46E18617426453A /* RACSignal+Operations.h in Headers */ = {isa = PBXBuildFile; fileRef = 74B2F1E2E8F5A521CF8C020F68AE9401 /* RACSignal+Operations.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9E1E90DED74B73ECE53C9AD76DE53E2D /* UIImage+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 04C7E2FB01F5334FA335665D00EF1375 /* UIImage+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9F720D7EB674C321DA30F74FED315FA3 /* UIImage+MultiFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = B109B965D74D1DF7895555155F9167B4 /* UIImage+MultiFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9FACD31A94E2DA587946657B52EB7A6B /* NJKWebViewProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 77A8DBFA8332F76E243E6674682DC696 /* NJKWebViewProgressView.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; A4581B24DDCCDCDA24F4392F0E378E1A /* RACMulticastConnection+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AF52700EF1A07BD7C472480318D5B449 /* RACMulticastConnection+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; A462945883F7729B185B64B679A6BFBE /* UIWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 000949CDEA7AFB499C89010D145F3459 /* UIWebView+AFNetworking.m */; }; A535499166018F49DDA66EE7B0A2EBF7 /* MJRefresh-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B26C89BAEA96E55DC008D427750C820E /* MJRefresh-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; A54611F727A8AAEAE219AE89290A94F8 /* MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E079EE3DDE330831C21F8180FEF0A0F /* MJProperty.m */; }; A6C6019D45BE62C61210A9CC619368EF /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2163FDD9A29250721D08889D6226D26C /* AFNetworkActivityIndicatorManager.m */; }; A7A5FDEE47DE5468D0B739E0277A85AB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; A7E50BF7F9042381769B72E3EB0B424B /* NSObject+RACPropertySubscribing.m in Sources */ = {isa = PBXBuildFile; fileRef = 798FAF630718310A3CD51B9F2109F585 /* NSObject+RACPropertySubscribing.m */; }; A818AD7A582F331310F1A3AD66F9DB26 /* RACDynamicSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D71B771102AEA2F2D5E4D6D85AB4D6 /* RACDynamicSignal.m */; }; A874D60B6C69FFE15C329256755B058C /* MJRefreshHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = A19678BE408B5098995BFB18144274C9 /* MJRefreshHeader.m */; }; A8D1C2B2AD592CCE2776BC404E5C74CD /* RACDynamicPropertySuperclass.h in Headers */ = {isa = PBXBuildFile; fileRef = E3B89EEBCE0A896C3213236412974A4F /* RACDynamicPropertySuperclass.h */; settings = {ATTRIBUTES = (Public, ); }; }; A8FACFFCA9F80A82E95AF6890EC16553 /* UIControl+RACSignalSupportPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C32EE2F3025F97F3982477A027FD6DE /* UIControl+RACSignalSupportPrivate.m */; }; A901A8DA830B4B4679507C4E69EDF8A1 /* RACSignal+Operations.m in Sources */ = {isa = PBXBuildFile; fileRef = 091ED5B0512672DE61D555CCB7142FD1 /* RACSignal+Operations.m */; }; AA3ACC8EAC430A22F002C2A67B9ECB37 /* NSString+RACSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = FABB85ED518C4DA0BB4262DAAC3A1EE7 /* NSString+RACSupport.m */; }; AB39AC9746E7575D7449700475E41B0B /* AFHTTPSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CC43C0D25552A4CC426C3FCF6371BF12 /* AFHTTPSessionManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; ABAFA39827840EDE6A4527D2EFDA97E5 /* DACircularProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C57774CFCB37FFF487DE6AC84BAA0AC /* DACircularProgressView.h */; settings = {ATTRIBUTES = (Public, ); }; }; ABE9ACD59269A2BBE000F4667BC8B70A /* NJKWebViewProgress-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 64BB381E9FC1EB317BD2DB17212FBB4E /* NJKWebViewProgress-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; AC452E1429618AFF74F34953ED044819 /* EXTRuntimeExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 36E0783D29417C70557ADA2D3812BAFE /* EXTRuntimeExtensions.m */; }; AC5B479241D890A457651FB489A5D17B /* UIActionSheet+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 429BA83EA95D1725559EFE5276560A3D /* UIActionSheet+RACSignalSupport.m */; }; ADA6FC12E44039C91AFB67F2B5D1E3E6 /* SDImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = AFD4BA75EC240FA027E3566EEB6BE607 /* SDImageCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; AE2A07407FB50BA249984DC0620E84C0 /* UIWebView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 647B1602B2F0939011C20E21D90DCA51 /* UIWebView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; AEFB3ADEA9F4FE938ECA832BF2F05F4B /* RACScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = F89D1F8452E50ECE7ACCDD5DE95FAE9C /* RACScheduler.h */; settings = {ATTRIBUTES = (Public, ); }; }; AF03C11A1FAC8132AD3749D8F541701A /* UIButton+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 85E976B9474660285C492769605631FA /* UIButton+AFNetworking.m */; }; AF20359522D1E719FE9B4462D8F2031A /* RACReturnSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = 48F5F604D4E0464A77C336CCDFC5C06E /* RACReturnSignal.h */; settings = {ATTRIBUTES = (Public, ); }; }; AFC9968F21AF2109C71F534C32AE3D49 /* NSObject+RACKVOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 5524B69733BB0ED106175FD5542CF25E /* NSObject+RACKVOWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; }; B01B7989C730E6B8D0FC189379C8829B /* SDWebImageDownloaderOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D0A6CE7ADD9A9435F7C5A00304B02C8 /* SDWebImageDownloaderOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; B15E465C81F5D9E5888A196B31B25C28 /* MJPropertyKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A750DFECCFC1702DACB94D6B04486E2 /* MJPropertyKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; B1ACC3AD8AD6262A25054286293843DE /* UISwitch+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A6B443A889FFE21F2568DF7F9051B834 /* UISwitch+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; B21385BDDFE01601BBC8E4EA20DAA481 /* RACQueueScheduler+Subclass.h in Headers */ = {isa = PBXBuildFile; fileRef = 9946203DCEC78A5FF966F92C3E2F0E0B /* RACQueueScheduler+Subclass.h */; settings = {ATTRIBUTES = (Public, ); }; }; B2CDFA4E0CCE564CBC6D0987E83746D2 /* SVRadialGradientLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = D0BA0F92F89081D2609638A9895AB503 /* SVRadialGradientLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; B3A97031390F94C0DA848612C6053D05 /* MJExtensionConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 06B1B1B7E283AD4CEB7C1B2417929E46 /* MJExtensionConst.m */; }; B4298E9294D5BED493FD436EFB68C84A /* UIImageView+HighlightedWebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = FFA49582C65298F437501438338FF005 /* UIImageView+HighlightedWebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; B4ECCBCCD080040E3DEDF1F66A7AF896 /* RACEagerSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CE37C161C0EE70794E73D87B40E5090 /* RACEagerSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; B5852322ADE88AAD56EE042B80BA81E4 /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F2AD288D4DCF53E728C1A1466A87875 /* AFURLResponseSerialization.m */; }; B5A3B3D4ACD5A5D5B8A93860AA934818 /* NSEnumerator+RACSequenceAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C9AFF3F620F4F27318F5092C63D2D65 /* NSEnumerator+RACSequenceAdditions.m */; }; B5ACB9544A28B944C634FB6432AA18F2 /* NSInvocation+RACTypeParsing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A8D84F0ACCE5A92EAE2B4EFFA3A5BC7 /* NSInvocation+RACTypeParsing.h */; settings = {ATTRIBUTES = (Public, ); }; }; B66558616A2ED20387925E1F8A899B6A /* SVProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FF21EEA83A4B4C2E956BB8ADC79804 /* SVProgressHUD.m */; }; B699EB0285A21875290BD8149C742FCA /* UIImagePickerController+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 184550CBD6D9758741E5C62753EBA270 /* UIImagePickerController+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; B72796279A879D1178B529D14E479EED /* UISlider+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = B59240F4E6C2D09A8AECBE4EB339E04D /* UISlider+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; B7D0A5BDD2EA028A51D8A17F1A738969 /* RACIndexSetSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = AFB4F39A97EEA4CB606A257BD52621B8 /* RACIndexSetSequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8620D72DAD3CD23AB157BBD7A7B782F /* RACSubscriptionScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA125B459F46A34746B8F375E042CE2 /* RACSubscriptionScheduler.m */; }; B8F9E818A69721581FB3B1D67678A7BE /* MJExtensionConst.h in Headers */ = {isa = PBXBuildFile; fileRef = 49FEAB8BBDA81884BB5B3C142A954D81 /* MJExtensionConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8FF0B1C5F3D57D704C48DECE022E1CE /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AA8B431CCA64EDE836AA2CCD05AC950 /* UIView+WebCacheOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; B927754D552A855E288BBF6B56893830 /* RACMulticastConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = EB6C3290DEE08AE7ED2C7AC1B98D3154 /* RACMulticastConnection.h */; settings = {ATTRIBUTES = (Public, ); }; }; B92B9E7F4DC2ACAE1148554AD22C7B01 /* Pods-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BCC458FDD5F692BBB2BFC64BB5701FC /* Pods-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; B9D9121C3E99742689213EE0A5CA943A /* UIImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D5541ACE685641DA75EE8D016327EBCA /* UIImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; BB55FFD36D685105A750534A4DF0DB02 /* RACImmediateScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BFE01EDE2323976347DF54E4B71D510 /* RACImmediateScheduler.h */; settings = {ATTRIBUTES = (Public, ); }; }; BBCC9B911833546C10283453DE8D1948 /* Result-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D0469FCCA9E4851070CF89D690EB5D12 /* Result-dummy.m */; }; BC119AAAD4BAD26B893AA6E552B8D452 /* UIControl+RACSignalSupportPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 85FF1DEBB8560D116AE8785E3D9500ED /* UIControl+RACSignalSupportPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; BD88BABCCF32770C64B6998FA43265D5 /* ObjectiveCBridging.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6CC38E13D731C62DE79A7084DFB924 /* ObjectiveCBridging.swift */; }; BD8A850E68B7FBCA60C0ED501100C971 /* UIScrollView+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = A6BEE214C0861CABFEC4A99A3E61A6C2 /* UIScrollView+MJRefresh.m */; }; BDE21C4F50664111E97A27C07842D0F6 /* SDWebImagePrefetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F9873A6369DD78A4B7547F192454404 /* SDWebImagePrefetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; BE6C56A057F7B765EDE4A270563E5E04 /* MJRefreshGifHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DE1DF3A1C8F5A26C0E0C151BCCB8E40 /* MJRefreshGifHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; BE7742B51F6C55A6A63E7D7E4225D9EC /* UIButton+RACCommandSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = E00F85DF61A097080D9B006A42852B08 /* UIButton+RACCommandSupport.m */; }; BF0EB23D88E0C06CC3892A2B42600580 /* MJRefreshComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 030BE5B2566DC2DE1DF6C75DF5014D4E /* MJRefreshComponent.h */; settings = {ATTRIBUTES = (Public, ); }; }; C01AC3BAD9037A8A1E45FD17336C15F3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9022EE9051D51B98121F849F4769EE2 /* Security.framework */; }; C0FD4C225F2E320005F7649F5106D009 /* UIAlertView+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E025561039B8FAD2BF3E4DFD1400ED9 /* UIAlertView+RACSignalSupport.m */; }; C1E60365B988A3A5E3C6F083B2904919 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */; }; C2DD28375E1F0B1D0D1D2E4E607C499F /* AFSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = CC607CF5B5D9B3420B30AA34AA024E44 /* AFSecurityPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; C6354FEC7728A4C86DAD8092509BA7D4 /* UIRefreshControl+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 65F5B35589F9DB55205F95B1029703C4 /* UIRefreshControl+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; C703739EA6DBB2B29230A9F6386D7140 /* RACBlockTrampoline.h in Headers */ = {isa = PBXBuildFile; fileRef = 63F4526194B00D140E9F43CFE83CC868 /* RACBlockTrampoline.h */; settings = {ATTRIBUTES = (Public, ); }; }; C73C5346DE106B194B8D52E0DD10DFFF /* MJRefreshStateHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BA3B0CDC3DFF8020BE9CF970087F087 /* MJRefreshStateHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; C755E7FA789E3A1EBC477F2096106FB3 /* UIButton+RACCommandSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E82D8F966DFF2EDFECC4638BB6E2390 /* UIButton+RACCommandSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; C9497D947A0E66DB13242885B53F6946 /* MJRefreshBackGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A2021E9945FEF95138597F73185383E /* MJRefreshBackGifFooter.m */; }; C9C7707877E21F715401B691B5A154BB /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A47E80BB0414B90A81EAEFA3F6D9239 /* ImageIO.framework */; }; C9EC67BE9E06CCD7ED3388783D767CFB /* UIControl+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 873D1ADD735B27286236748899F7921F /* UIControl+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; CAC483EF637FB4A2C2E2FC75BA631B87 /* AFAutoPurgingImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 657579FA1269B3702EB29DA0B5E20336 /* AFAutoPurgingImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; CBE63803A9E627929E76CBD11DA70A73 /* MJFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = 02C9A313B91705AC4C5D0CDCFD20143A /* MJFoundation.m */; }; CC325F40FB14EC0BB26F853EB9F0C13C /* RACErrorSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = A3026BC8DB8F8F2CA36E8535E1F643F5 /* RACErrorSignal.h */; settings = {ATTRIBUTES = (Public, ); }; }; CD8F026F153BE67E954FB3A6624171E2 /* SVIndefiniteAnimatedView.h in Headers */ = {isa = PBXBuildFile; fileRef = C16C390DA92494698A0B5A96D2E0BDF1 /* SVIndefiniteAnimatedView.h */; settings = {ATTRIBUTES = (Public, ); }; }; CDFB56B7343AA2F63B0590E077FECD05 /* UIBarButtonItem+RACCommandSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D9AD3CBF51B0E685856C97780A563F5 /* UIBarButtonItem+RACCommandSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; CF1036F4BD25E2E1ED3137287B5394DC /* RACScopedDisposable.h in Headers */ = {isa = PBXBuildFile; fileRef = A4E03F5541C865B1E97472EB309106B0 /* RACScopedDisposable.h */; settings = {ATTRIBUTES = (Public, ); }; }; CF8456F107FFCD2C20298F63CD23216F /* UIScrollView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = A1061C71204A323EDD42383C339969CB /* UIScrollView+MJExtension.m */; }; CFA8D6B529A0EBFF0316F2629AB2556E /* AFImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 4368C683284C961AA2A8FB0F7BD9DBF8 /* AFImageDownloader.m */; }; D03ED3E1E9EB4F27320394A36C43982E /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24C33EE3C87C90B83137CAC380D44D59 /* Optional.swift */; }; D04B84B53456B9CD8A7236126075571B /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C30356461CD94DCCEB2CA832125EFDC4 /* MobileCoreServices.framework */; }; D0DABCBD3F1A6255126CF13B71E9DD8A /* NSObject+RACKVOWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C4B0AD995AF74E076A53F619FE89D1C /* NSObject+RACKVOWrapper.m */; }; D13F54EA636464A6872BFD4FAF4CA39C /* ResultType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D79EB7D14F41D48652E69458403F4457 /* ResultType.swift */; }; D182C799FA0CAA54FFBC3C2C55D8167F /* RACKVOProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F3F99995BE381D39F038649654DEBD7 /* RACKVOProxy.m */; }; D1C210B87C732659BE699941EBB79A1A /* UISlider+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 14B5A6DBE283E02BB4999634060D8117 /* UISlider+RACSignalSupport.m */; }; D4C7FE23F66BA3A46162593A9918D7EA /* RACCompoundDisposableProvider.d in Sources */ = {isa = PBXBuildFile; fileRef = 5944D7D3FBA790E75B7ED7D9DF3AB43D /* RACCompoundDisposableProvider.d */; }; D57B7D25D8A7A39A84BF9F27200FBD44 /* RACTargetQueueScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 415ED47AFF2997401513C873C0E15531 /* RACTargetQueueScheduler.h */; settings = {ATTRIBUTES = (Public, ); }; }; D62A9D152379946263D494931F44CF27 /* UIView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A9D916B5F5972DEC7187DC4C1A69560 /* UIView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; D661ED5B7D23D5B19B15B7C0BBBFD9A3 /* RACChannel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A08FDFD6F4116F62414049A7E08EB28 /* RACChannel.m */; }; D676F0CF5892D9986952CE30CAF08710 /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BD83ACABD6CFE31B6B652747D04962D /* Disposable.swift */; }; D72B9283EE25F9A12BD0FA7C84221684 /* RACSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = A5DDFF4D75D3D1D9A7B7D99D8B0BF03B /* RACSequence.m */; }; D7E5966C32EDC4A86575A3B3EF570ACD /* RACSubscriber.h in Headers */ = {isa = PBXBuildFile; fileRef = 553B52FBE486D38BBCE50610A111FB83 /* RACSubscriber.h */; settings = {ATTRIBUTES = (Public, ); }; }; D8D832C26EFBE040BE6C23F1121B1945 /* SDImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 489AC57D7F55028173024FC11F7BEF63 /* SDImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; D90D224837D808EFE79F724A722C753C /* NSObject+MJKeyValue.m in Sources */ = {isa = PBXBuildFile; fileRef = E2B6F1FAA9D6337E9009E98F903961E3 /* NSObject+MJKeyValue.m */; }; D9B2CB5E6AB64E0D92B89E7B29B3A6A3 /* metamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AACEC6CC96EE165C763F0FA461DC68 /* metamacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; D9F4E833E37B611B432F6B5D7072DDA2 /* UIProgressView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = A9A24C7194EB1F183CE6B4C9AE06AD99 /* UIProgressView+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA956B14A3C671B585308EF7F8BC0BF2 /* NSURLConnection+RACSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A89DA1D225B160992C2CA9696C73776 /* NSURLConnection+RACSupport.m */; }; DADFC17F37F89D6668042A55D1950225 /* RACSubscriber+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AC06CA5C148C1CE619B48A5749C301D /* RACSubscriber+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; DD9B17C25EB68901D26243C6F97EEE56 /* UITableViewCell+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = FA8F7C14656D9F2B06C707A058346B31 /* UITableViewCell+RACSignalSupport.m */; }; DE1C43D7F6F319234B4A9A4017736298 /* RACValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9935967190930CA33F32A0BD9292552A /* RACValueTransformer.m */; }; DFFA215EEAA8DDBD540076927535275C /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F04C630FB7E53F60E360F879CBE5F7D9 /* AFURLRequestSerialization.m */; }; E00424EF864015DE51C3ECBF8D676B46 /* RACSubscriptionScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = B9D638C8A921514FC49BBDBEDA760214 /* RACSubscriptionScheduler.h */; settings = {ATTRIBUTES = (Public, ); }; }; E03653384C7BE69DCDB564E3BBC78FEF /* RACScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = 2292A1728848AF097FEEC307886BAA65 /* RACScheduler.m */; }; E0CF3FDA599B19EF3F1A47B5BDC2F9AB /* MKAnnotationView+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = A824F0BE4B5F3D459BAD005E6212EA0B /* MKAnnotationView+RACSignalSupport.m */; }; E0D4045AC4C1B41917FCA23A042D18B2 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B7C4539ED08962A5251CFBC170F4E5B1 /* AFHTTPSessionManager.m */; }; E264E4B47C3F3A3B9C1F3733560E5D19 /* RACTupleSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F4978074EEC4F723B9E4B212BD1287B /* RACTupleSequence.m */; }; E4D2FB975E5C435F4D758B06AC530744 /* NSObject+RACDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = CD3FB75CDCA680D6B2DD50EDEE181762 /* NSObject+RACDescription.h */; settings = {ATTRIBUTES = (Public, ); }; }; E51167E24F41574BC3CD6FCEECCC0A4D /* SVProgressHUD.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0FC659831F2AF2F86179BC38BE9888 /* SVProgressHUD.h */; settings = {ATTRIBUTES = (Public, ); }; }; E603DFF6866D326AE8BCF8D75E4A01AC /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8845A5317A9A2E5C9AC34BB8582BF9 /* UIImage+GIF.h */; settings = {ATTRIBUTES = (Public, ); }; }; E6548000C8BF4FA50A4E1A1908A90574 /* RACSubject.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D3BCF589E4CFF8B4CFEC14816C6550A /* RACSubject.m */; }; E6B3E98FA9C09AEA32AA9ACE662F6728 /* UIImage+MultiFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = D8843362CAD0A95F12D3944CF21DF90A /* UIImage+MultiFormat.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; E74D191277E0920749063EBE80FE4CE6 /* NSString+RACSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = C12EABC206D6422B92011E9A5DBAC8A8 /* NSString+RACSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; E7988678C81F7CCB95D239375FC6986D /* AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = C1E1D8502CC717DA524B7E464CFA9D60 /* AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; E91DDE6EB5FAF6E1C7A77E2D0ADFF6D1 /* RACKVOTrampoline.m in Sources */ = {isa = PBXBuildFile; fileRef = 8987D14700FA10B9378E7ED1AE673C27 /* RACKVOTrampoline.m */; }; EA6F0B146700B71CB0FF0C77156BBFCF /* DACircularProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8E11456820F951465A69447AE2714 /* DACircularProgressView.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; EA928E4C4FD61092C3AA97E471411FE4 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AE98AF69BAD8F07BB16232D800176C8 /* QuartzCore.framework */; }; EAE2E750ADDF535A1696470C745C0485 /* NSObject+MJCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 085980395FF6AC05DA09B11655E637FA /* NSObject+MJCoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; EAFCB77D63E5960EB0A7925228A833CF /* MJExtension-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 91A4C2A30C90A73B281741E7282FA276 /* MJExtension-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; EB16E6D7F4B34537C4320D1AD26867F3 /* RACStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F510D3EE3ACA142792DDF627F485853 /* RACStream.m */; }; EBB71D7EFF5566E9B87F9DE36E973FBC /* UISegmentedControl+RACSignalSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 08657BE6CE5968B484BCDC9708782CD9 /* UISegmentedControl+RACSignalSupport.m */; }; EC7CADE416A78A1CD6936018A6695126 /* AFNetworking-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 300A322BAF334D1838F5EB0C49CEBDC6 /* AFNetworking-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; ED004EB9D9F0AD265FB04088DF40F4F2 /* SDWebImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 90C95D49530F835B55F4CA43885E06F4 /* SDWebImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; ED097F975473B7CB4020FFF06B1F3BE3 /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = A76F3456E072E02608565E8C86A0D8F7 /* Signal.swift */; }; EDFA4A46C1B346922751E86DE8537CC5 /* RACQueueScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A685DCF4657094755205817A226A13C /* RACQueueScheduler.h */; settings = {ATTRIBUTES = (Public, ); }; }; EE03F4DCA502AA65D27174159582A551 /* RACKVOTrampoline.h in Headers */ = {isa = PBXBuildFile; fileRef = 58E9BDFCC6E8C48ABF1532E15BA9F727 /* RACKVOTrampoline.h */; settings = {ATTRIBUTES = (Public, ); }; }; F0ACC773C5671197A4322ED45F40B117 /* NSSet+RACSequenceAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = A0BDBDB77D7F3942C80739E5B95267D1 /* NSSet+RACSequenceAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; F11C5E7C4923AE968981B5F7198683EA /* RACQueueScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E2DBB302C680CE8C1D520ACBFD60A9 /* RACQueueScheduler.m */; }; F29FF0F9A22BFE0EA8754DFF41894244 /* RACTestScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C1F4583A78B09D927E29BEBA9551586 /* RACTestScheduler.m */; }; F3015B3D06F13F36E624A4E8B591E529 /* NSObject+MJClass.h in Headers */ = {isa = PBXBuildFile; fileRef = E66CAF5003E9213A4537D17DF0140B4D /* NSObject+MJClass.h */; settings = {ATTRIBUTES = (Public, ); }; }; F37796CDD34641CEC272FC24C85C5901 /* MJRefreshGifHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8858F9E080A925223FA42F75EE78F6A8 /* MJRefreshGifHeader.m */; }; F3ED07928731E8E005504139177DBB8B /* RACDisposable.h in Headers */ = {isa = PBXBuildFile; fileRef = 04686EC2F9E6B07BE356ECAC172AD7D1 /* RACDisposable.h */; settings = {ATTRIBUTES = (Public, ); }; }; F448ADD6D89AEF9B156A18E704713B4F /* RACCompoundDisposable.h in Headers */ = {isa = PBXBuildFile; fileRef = BD5D799295EE6F34460C45067C971D09 /* RACCompoundDisposable.h */; settings = {ATTRIBUTES = (Public, ); }; }; F488F203073C7C6B918B5211FC21A1A7 /* UIView+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 963FABC9E999205BCBCAB1347CE4E5CD /* UIView+WebCacheOperation.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; F49F1264B4611318E830BEE2F56918CE /* SDWebImage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C8EDB2613EF74A96A98805E88478BA6A /* SDWebImage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; F55C8CF969F3FD3BD80555F26AEB5289 /* RACGroupedSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = 01C52214559D7845B69F76EAF3EA5AB4 /* RACGroupedSignal.h */; settings = {ATTRIBUTES = (Public, ); }; }; F66B2090A94AAB1AF4E1CC51D9268D85 /* RACSubscriptingAssignmentTrampoline.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AF24A9D371339EA3A8950DA892A2CEC /* RACSubscriptingAssignmentTrampoline.m */; }; F67D5D0C2FE807F7D5ACCCC981F6E089 /* RACPassthroughSubscriber.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD93D46AB6FEFB9207551729F2D8D90 /* RACPassthroughSubscriber.m */; }; F69F3F4018550D6B9F7E3B40B7733F2D /* RACScheduler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EDB048279E2B3CA010EFE2AE186AB08 /* RACScheduler+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; F70504B745ABB3940711E6A3A5D863E5 /* MJRefreshBackFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = BB4A068D4F391DFF007C5E826F88C673 /* MJRefreshBackFooter.m */; }; F799F156F28A70FF5412DF8CF34057A8 /* NSInvocation+RACTypeParsing.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B63C8C72A4078D0527C9DAA478C2DB0 /* NSInvocation+RACTypeParsing.m */; }; F852A0869AF27611809B656DACFFEABD /* MJPropertyType.m in Sources */ = {isa = PBXBuildFile; fileRef = B4B17DECE01AAC9BA272506436DE73FF /* MJPropertyType.m */; }; F877A6DAE2F8D2F9170474700EFD5603 /* UIButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D05FD8E528963F2685FFD2B80E1CD5E /* UIButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; F878D888E0FDBA293E5876E8AA42EC26 /* ReactiveCocoa-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 94645B657EE6D5FF0163C672CB64099E /* ReactiveCocoa-dummy.m */; }; F8A8AD0A7F4653C09DE7B5EAD44ADAAB /* RACUnarySequence.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F27F7DA0D449258B474893084F7C6AB /* RACUnarySequence.m */; }; F8BE146084791BD01DA89B78191CB59A /* UICollectionReusableView+RACSignalSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A80F20F9A079897F7763E34E2C5597E /* UICollectionReusableView+RACSignalSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; FA3220E5BF47A4AF0A88802437EA8536 /* MJFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C7A502A4891DEBCB4FCC707DE4681FE /* MJFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; }; FA603034F1C2D30DA9D6C5BEF1417083 /* MJRefreshAutoNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F40BC006E0930A50E0266C73DA609FE /* MJRefreshAutoNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; FB0D56033C8D28431FFE4C081D26CA3D /* SVProgressHUD-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 470BF47D43361B7ABCAD26320AD329A3 /* SVProgressHUD-dummy.m */; }; FB4AABB168DCA42AB0B7617E9FEA51E0 /* NSArray+RACSequenceAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = BDA934FAC50E5908597A06861F54876A /* NSArray+RACSequenceAdditions.m */; }; FB4FAB46E8CAA1A4DADAE3394DAC15FC /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AFAB896F150D62C666F8599CF7C13AC /* UIKit.framework */; }; FC2E6AF0090625D11944B93E271C21B6 /* RACSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = 79FC08DDDA96EE7F692A9CA244FDD07A /* RACSignal.h */; settings = {ATTRIBUTES = (Public, ); }; }; FC83FA010A755F146143A9935CDE0AC5 /* UIScrollView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AC9A7040E9A886D917833A5E38B4494 /* UIScrollView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; FD800E1FAF78230644012D0BC5F89B7D /* RACBehaviorSubject.m in Sources */ = {isa = PBXBuildFile; fileRef = A527A6B121AE049337AA777E6D937E07 /* RACBehaviorSubject.m */; }; FDCAA63373782AB405AFD4716FE32F02 /* RACArraySequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A7194B1C09FCC0468DD8C0F335E2010 /* RACArraySequence.h */; settings = {ATTRIBUTES = (Public, ); }; }; FE96A3DA7D324EF1AEA9A099B977848A /* NSDictionary+RACSequenceAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AEFE2CAD5E3DEA1ED6CF01584279D16 /* NSDictionary+RACSequenceAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; FF6C2855509136F8DEF9FAC173597944 /* MJRefreshNormalHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 827EE8470BA8113E1D08BA60A9DB4AE4 /* MJRefreshNormalHeader.m */; }; FF708399B1A87AB052034F635FB70A2A /* DACircularProgress-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9FE8F3328FD5DA10E662D3E3612E892E /* DACircularProgress-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 046888DED34D27F5F4AB0261833B3313 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 147E210E10219F7AA15F6AE1A920B9B7; remoteInfo = SVProgressHUD; }; 1984B50C9738B84D132B2564CFC34D0A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 1C3436CEA5C3D39764C5F54374794ECB; remoteInfo = AFNetworking; }; 35412EC18D3EBC733D04C08AA497FAD9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 0B33F15A364332914D715DD4C9844CC9; remoteInfo = Result; }; 40FAF901B699BBCF70EF8CEE190342DD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 94624EC6C9739263AA965CFE2D8933F5; remoteInfo = DACircularProgress; }; 452023F999638CC54D778CE994CAFCA6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 9EAC110EBAECD60D92AC9F4B2A6B835F; remoteInfo = SDWebImage; }; 5259EE160B2F5B5116E7D287864BFEC3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 7C0126D717EB28DC6DB2EEA2E20B5172; remoteInfo = MJExtension; }; 72095AA5AE5EE61B7E287B4AC6107854 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 6847254D016329D4A531D34ED2B6DF81; remoteInfo = MJRefresh; }; 85F6A6C5CFB2F62C2DAFB3EC4059A054 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = E31FBC1304C5757C98D97C5AE31F36A2; remoteInfo = ReactiveCocoa; }; B22B6F7D22325424FE20717F6CBA8756 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 33B42E21671AAC905130853EDCADA43B; remoteInfo = NJKWebViewProgress; }; FC14D2248C5EDD81CDB6EE98554AF8FD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 0B33F15A364332914D715DD4C9844CC9; remoteInfo = Result; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 000949CDEA7AFB499C89010D145F3459 /* UIWebView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIWebView+AFNetworking.m"; path = "UIKit+AFNetworking/UIWebView+AFNetworking.m"; sourceTree = ""; }; 017F6516B54EC1196D28908E8C6EA8D4 /* TencentOpenApi_IOS_Bundle.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = TencentOpenApi_IOS_Bundle.bundle; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenApi_IOS_Bundle.bundle; sourceTree = ""; }; 01C52214559D7845B69F76EAF3EA5AB4 /* RACGroupedSignal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACGroupedSignal.h; path = "ReactiveCocoa/Objective-C/RACGroupedSignal.h"; sourceTree = ""; }; 0200FADDFC41780A72461242A8933469 /* NSURLConnection+RACSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSURLConnection+RACSupport.h"; path = "ReactiveCocoa/Objective-C/NSURLConnection+RACSupport.h"; sourceTree = ""; }; 02C9A313B91705AC4C5D0CDCFD20143A /* MJFoundation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJFoundation.m; path = MJExtension/MJFoundation.m; sourceTree = ""; }; 02E1B6AA6AA6390F3F754295B465C3A7 /* NSObject+MJProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJProperty.m"; path = "MJExtension/NSObject+MJProperty.m"; sourceTree = ""; }; 030BE5B2566DC2DE1DF6C75DF5014D4E /* MJRefreshComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshComponent.h; path = MJRefresh/Base/MJRefreshComponent.h; sourceTree = ""; }; 045F7E40F91896E7BE7FD6A45C0D6947 /* WBHttpRequest+WeiboShare.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "WBHttpRequest+WeiboShare.h"; path = "Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest+WeiboShare.h"; sourceTree = ""; }; 04686EC2F9E6B07BE356ECAC172AD7D1 /* RACDisposable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACDisposable.h; path = "ReactiveCocoa/Objective-C/RACDisposable.h"; sourceTree = ""; }; 04791F30EB17FA5F95CCE83E1EC06C5A /* MJExtension.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJExtension.xcconfig; sourceTree = ""; }; 04C7E2FB01F5334FA335665D00EF1375 /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+AFNetworking.h"; path = "UIKit+AFNetworking/UIImage+AFNetworking.h"; sourceTree = ""; }; 05290D288C6535325D67AFBF86D00468 /* Atomic.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Atomic.swift; path = ReactiveCocoa/Swift/Atomic.swift; sourceTree = ""; }; 05B12FA0E0FAB888F4A96E62780AE0FB /* UMSocialData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialData.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialData.h; sourceTree = ""; }; 0673809329E6ADFE94FC8615FD00A33A /* UMSLoginViewController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = UMSLoginViewController.xib; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSLoginViewController.xib; sourceTree = ""; }; 06880042FBC5FCBF625C5CFF84286B13 /* RACKVOChannel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACKVOChannel.h; path = "ReactiveCocoa/Objective-C/RACKVOChannel.h"; sourceTree = ""; }; 06B1B1B7E283AD4CEB7C1B2417929E46 /* MJExtensionConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJExtensionConst.m; path = MJExtension/MJExtensionConst.m; sourceTree = ""; }; 06B28D9101904B3DDA53E7542414905D /* SDWebImageDownloaderOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderOperation.m; path = SDWebImage/SDWebImageDownloaderOperation.m; sourceTree = ""; }; 081A9360B5E6C2BFED633BA37FB21586 /* WXApiObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WXApiObject.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Wechat/WXApiObject.h; sourceTree = ""; }; 085980395FF6AC05DA09B11655E637FA /* NSObject+MJCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJCoding.h"; path = "MJExtension/NSObject+MJCoding.h"; sourceTree = ""; }; 08657BE6CE5968B484BCDC9708782CD9 /* UISegmentedControl+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UISegmentedControl+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UISegmentedControl+RACSignalSupport.m"; sourceTree = ""; }; 089193F3B7A92B972D1332D86CC8A3D8 /* UISegmentedControl+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UISegmentedControl+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UISegmentedControl+RACSignalSupport.h"; sourceTree = ""; }; 08B291FA25C28B624B02BDADA44546F6 /* UMSocialSnsPlatformManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialSnsPlatformManager.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialSnsPlatformManager.h; sourceTree = ""; }; 091ED5B0512672DE61D555CCB7142FD1 /* RACSignal+Operations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "RACSignal+Operations.m"; path = "ReactiveCocoa/Objective-C/RACSignal+Operations.m"; sourceTree = ""; }; 0A1826FA89F1FDC1F788AD5A5DC5931E /* AFNetworking.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = AFNetworking.modulemap; sourceTree = ""; }; 0A72841D503B7B4AABD02FE508DABEDF /* NSUserDefaults+RACSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSUserDefaults+RACSupport.h"; path = "ReactiveCocoa/Objective-C/NSUserDefaults+RACSupport.h"; sourceTree = ""; }; 0B20AC59ED957F2FFCFD375B980767D8 /* NSUserDefaults+RACSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSUserDefaults+RACSupport.m"; path = "ReactiveCocoa/Objective-C/NSUserDefaults+RACSupport.m"; sourceTree = ""; }; 0C7A502A4891DEBCB4FCC707DE4681FE /* MJFoundation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJFoundation.h; path = MJExtension/MJFoundation.h; sourceTree = ""; }; 0C887DA74F733F87971CCE2DC0A90581 /* AFURLSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLSessionManager.m; path = AFNetworking/AFURLSessionManager.m; sourceTree = ""; }; 0D01E0F3F1F8BA7C23356819729299A1 /* RACCommand.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACCommand.m; path = "ReactiveCocoa/Objective-C/RACCommand.m"; sourceTree = ""; }; 0D0C2271A31DC0318C3F599828368EED /* UITextField+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITextField+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UITextField+RACSignalSupport.m"; sourceTree = ""; }; 0D57074F48179390AA303927C134EE2C /* SDWebImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-prefix.pch"; sourceTree = ""; }; 0EBF5ED419CFAF406CAB22FC12D646EE /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; 0EFBC1962ABC17786F033C5D955C426A /* Result-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Result-umbrella.h"; sourceTree = ""; }; 0FC8E11456820F951465A69447AE2714 /* DACircularProgressView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DACircularProgressView.m; path = DACircularProgress/DACircularProgressView.m; sourceTree = ""; }; 0FF286368DF6F4FD3E718A8DDF0B1329 /* NSEnumerator+RACSequenceAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSEnumerator+RACSequenceAdditions.h"; path = "ReactiveCocoa/Objective-C/NSEnumerator+RACSequenceAdditions.h"; sourceTree = ""; }; 11D6C1C4122D8FE7CA3BC466EB85EA0C /* RACImmediateScheduler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACImmediateScheduler.m; path = "ReactiveCocoa/Objective-C/RACImmediateScheduler.m"; sourceTree = ""; }; 11DF06DCB011608D84991AD684676153 /* RACStream+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RACStream+Private.h"; path = "ReactiveCocoa/Objective-C/RACStream+Private.h"; sourceTree = ""; }; 12400663AFAE4279135158CC2CE30B83 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 131F1B7D90AD4CDC3DC4D5002774196F /* ReactiveCocoa-Bridging-Header.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ReactiveCocoa-Bridging-Header.h"; path = "ReactiveCocoa/Objective-C/ReactiveCocoa-Bridging-Header.h"; sourceTree = ""; }; 1398A95C37D93AD7F730390712926A23 /* UMSShareListController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = UMSShareListController.xib; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSShareListController.xib; sourceTree = ""; }; 14B5A6DBE283E02BB4999634060D8117 /* UISlider+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UISlider+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UISlider+RACSignalSupport.m"; sourceTree = ""; }; 150227C4D00F0EC7F13BBB5EE273B707 /* UMSocialAlipayShareHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialAlipayShareHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/AlipayShare/UMSocialAlipayShareHandler.h; sourceTree = ""; }; 15E8523EE6597A955B0FADAC061A8133 /* DACircularProgress.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DACircularProgress.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 178C15910519FE8A1A6EDF25064EBAC9 /* RACKVOChannel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACKVOChannel.m; path = "ReactiveCocoa/Objective-C/RACKVOChannel.m"; sourceTree = ""; }; 17FC11D339BD88DE46A3832ADB2E7698 /* RACStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACStream.h; path = "ReactiveCocoa/Objective-C/RACStream.h"; sourceTree = ""; }; 1832EC5F5771FBEA5CE0B7E5C0C3C60C /* RACReplaySubject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACReplaySubject.h; path = "ReactiveCocoa/Objective-C/RACReplaySubject.h"; sourceTree = ""; }; 184550CBD6D9758741E5C62753EBA270 /* UIImagePickerController+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImagePickerController+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UIImagePickerController+RACSignalSupport.h"; sourceTree = ""; }; 187AA5C92CBF850647DD36DB96B441C8 /* SDWebImageDecoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDecoder.m; path = SDWebImage/SDWebImageDecoder.m; sourceTree = ""; }; 19857320382C3934D1AA924AC1C439BF /* UIRefreshControl+RACCommandSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIRefreshControl+RACCommandSupport.m"; path = "ReactiveCocoa/Objective-C/UIRefreshControl+RACCommandSupport.m"; sourceTree = ""; }; 1AC9A7040E9A886D917833A5E38B4494 /* UIScrollView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJExtension.h"; path = "MJRefresh/UIScrollView+MJExtension.h"; sourceTree = ""; }; 1B63C8C72A4078D0527C9DAA478C2DB0 /* NSInvocation+RACTypeParsing.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSInvocation+RACTypeParsing.m"; path = "ReactiveCocoa/Objective-C/NSInvocation+RACTypeParsing.m"; sourceTree = ""; }; 1B82339D1E8C4BE689DDD67A528D77FF /* MJExtension-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJExtension-dummy.m"; sourceTree = ""; }; 1C4DB204F82A21C053C14A75D8A2253D /* NSString+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+MJExtension.m"; path = "MJExtension/NSString+MJExtension.m"; sourceTree = ""; }; 1C9AFF3F620F4F27318F5092C63D2D65 /* NSEnumerator+RACSequenceAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSEnumerator+RACSequenceAdditions.m"; path = "ReactiveCocoa/Objective-C/NSEnumerator+RACSequenceAdditions.m"; sourceTree = ""; }; 1D0A6CE7ADD9A9435F7C5A00304B02C8 /* SDWebImageDownloaderOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderOperation.h; path = SDWebImage/SDWebImageDownloaderOperation.h; sourceTree = ""; }; 1E079EE3DDE330831C21F8180FEF0A0F /* MJProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJProperty.m; path = MJExtension/MJProperty.m; sourceTree = ""; }; 1E2982CC1BE3091121DC05292B2FDC00 /* UIControl+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIControl+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UIControl+RACSignalSupport.m"; sourceTree = ""; }; 1F0D58F39A052B2E7FD5A8DBF7C70C6C /* RACReturnSignal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACReturnSignal.m; path = "ReactiveCocoa/Objective-C/RACReturnSignal.m"; sourceTree = ""; }; 1F510D3EE3ACA142792DDF627F485853 /* RACStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACStream.m; path = "ReactiveCocoa/Objective-C/RACStream.m"; sourceTree = ""; }; 1FC2184908F405511534A14E70D16DAF /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 201A7F251D317877BB1F942144C004A3 /* SVIndefiniteAnimatedView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SVIndefiniteAnimatedView.m; path = SVProgressHUD/SVIndefiniteAnimatedView.m; sourceTree = ""; }; 20740BE7A5516344AB7DC38CDD8896E0 /* NSObject+RACLifting.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+RACLifting.m"; path = "ReactiveCocoa/Objective-C/NSObject+RACLifting.m"; sourceTree = ""; }; 2163FDD9A29250721D08889D6226D26C /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m"; sourceTree = ""; }; 21E2DBB302C680CE8C1D520ACBFD60A9 /* RACQueueScheduler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACQueueScheduler.m; path = "ReactiveCocoa/Objective-C/RACQueueScheduler.m"; sourceTree = ""; }; 227C76A819C4FFC8125A8C3D0DFCD049 /* UMShareEditViewControlleriPad.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = UMShareEditViewControlleriPad.xib; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMShareEditViewControlleriPad.xib; sourceTree = ""; }; 2292A1728848AF097FEEC307886BAA65 /* RACScheduler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACScheduler.m; path = "ReactiveCocoa/Objective-C/RACScheduler.m"; sourceTree = ""; }; 23EC168D4DE256790968AF644F46052A /* MJRefresh-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJRefresh-dummy.m"; sourceTree = ""; }; 243D9C27745BC9586B92EBB5A67F296A /* WBHttpRequest+WeiboToken.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "WBHttpRequest+WeiboToken.h"; path = "Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest+WeiboToken.h"; sourceTree = ""; }; 2457232127A191B824275DF0FFD5E159 /* WBHttpRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WBHttpRequest.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest.h; sourceTree = ""; }; 24AC80CE0FB0E80AF69BF07269013518 /* MJRefreshStateHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateHeader.m; path = MJRefresh/Custom/Header/MJRefreshStateHeader.m; sourceTree = ""; }; 24C33EE3C87C90B83137CAC380D44D59 /* Optional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Optional.swift; path = ReactiveCocoa/Swift/Optional.swift; sourceTree = ""; }; 251DE2052E0DAB0482CE383D5ED31C30 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 255FD6ED59CC3DF6C897A751AA4A3371 /* APOpenAPI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = APOpenAPI.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/AlipayShare/APOpenAPI.h; sourceTree = ""; }; 2566085556C7C46E97B0513F6A39D71B /* UIDatePicker+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIDatePicker+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UIDatePicker+RACSignalSupport.h"; sourceTree = ""; }; 2571CE5A2B6427EE7C1CD76E1A71FE5F /* UITextView+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITextView+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UITextView+RACSignalSupport.m"; sourceTree = ""; }; 25ADFA74A42F4EA16E025EAFFC997CE2 /* RACEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACEvent.m; path = "ReactiveCocoa/Objective-C/RACEvent.m"; sourceTree = ""; }; 25F86FA19738CEA4C142BB2B35A7F8EF /* WBSDKRelationshipButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WBSDKRelationshipButton.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBSDKRelationshipButton.h; sourceTree = ""; }; 2637ADDE4A30CF2CEF128EC9561C0B08 /* RACSubject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACSubject.h; path = "ReactiveCocoa/Objective-C/RACSubject.h"; sourceTree = ""; }; 2664FC6FC44BC040C045CBF9826A5956 /* SDWebImageCompat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCompat.h; path = SDWebImage/SDWebImageCompat.h; sourceTree = ""; }; 26D3111BD2C1AEE320FE04F08468F1B4 /* UMSCommentInputControlleriPad.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = UMSCommentInputControlleriPad.xib; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentInputControlleriPad.xib; sourceTree = ""; }; 27FD06D92698931BEEBB79F967135D8C /* MJExtension-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJExtension-prefix.pch"; sourceTree = ""; }; 287EEB49D92EC73042E3C0D5A7376FFF /* MJRefreshHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshHeader.h; path = MJRefresh/Base/MJRefreshHeader.h; sourceTree = ""; }; 29474BDF519166A22324D16A7341AF4A /* NSObject+RACSelectorSignal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+RACSelectorSignal.h"; path = "ReactiveCocoa/Objective-C/NSObject+RACSelectorSignal.h"; sourceTree = ""; }; 2A96124D03EBB27BFF5CEA0256356CD8 /* WBHttpRequest+WeiboGame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "WBHttpRequest+WeiboGame.h"; path = "Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest+WeiboGame.h"; sourceTree = ""; }; 2ACEC0A293FEFB84F29DD8A55BA24605 /* RACSubscriber.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACSubscriber.m; path = "ReactiveCocoa/Objective-C/RACSubscriber.m"; sourceTree = ""; }; 2AD56469E8EF363D5728F35AFF09628D /* MJPropertyType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJPropertyType.h; path = MJExtension/MJPropertyType.h; sourceTree = ""; }; 2BCC458FDD5F692BBB2BFC64BB5701FC /* Pods-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-umbrella.h"; sourceTree = ""; }; 2CE36BF68E3D265CC0A3C6FCE26500E3 /* Result-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Result-prefix.pch"; sourceTree = ""; }; 2D28CE0133DF0CAD2C661C21BD8804D7 /* AFNetworking-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AFNetworking-dummy.m"; sourceTree = ""; }; 2E2E58931A4E5052311F3883A191B2BE /* UMSocialQQHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialQQHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/UMSocialQQHandler.h; sourceTree = ""; }; 2E9E45A488ECF89F98B18D04BA6C46BF /* NSObject+MJCoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJCoding.m"; path = "MJExtension/NSObject+MJCoding.m"; sourceTree = ""; }; 2F3F99995BE381D39F038649654DEBD7 /* RACKVOProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACKVOProxy.m; path = "ReactiveCocoa/Objective-C/RACKVOProxy.m"; sourceTree = ""; }; 2FACA2BDAE37AF70AF131A9DD8C8F023 /* RACSignalSequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACSignalSequence.h; path = "ReactiveCocoa/Objective-C/RACSignalSequence.h"; sourceTree = ""; }; 300A322BAF334D1838F5EB0C49CEBDC6 /* AFNetworking-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-umbrella.h"; sourceTree = ""; }; 31BF7F9D6F415EE6D53EF01F9B610BA5 /* SDWebImageDecoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDecoder.h; path = SDWebImage/SDWebImageDecoder.h; sourceTree = ""; }; 32205878DBB803322E1B42440847ECAB /* RACIndexSetSequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACIndexSetSequence.m; path = "ReactiveCocoa/Objective-C/RACIndexSetSequence.m"; sourceTree = ""; }; 32422BA7F298B775A904F182146351C0 /* RACDynamicSequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACDynamicSequence.m; path = "ReactiveCocoa/Objective-C/RACDynamicSequence.m"; sourceTree = ""; }; 327D589BF0F977BFF88D99840464BD9B /* MJRefreshBackStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackStateFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h; sourceTree = ""; }; 34FF21EEA83A4B4C2E956BB8ADC79804 /* SVProgressHUD.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SVProgressHUD.m; path = SVProgressHUD/SVProgressHUD.m; sourceTree = ""; }; 36C67D4D144F82BB460E86417F992329 /* RACScheduler+Subclass.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RACScheduler+Subclass.h"; path = "ReactiveCocoa/Objective-C/RACScheduler+Subclass.h"; sourceTree = ""; }; 36E0783D29417C70557ADA2D3812BAFE /* EXTRuntimeExtensions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = EXTRuntimeExtensions.m; path = "ReactiveCocoa/Objective-C/extobjc/EXTRuntimeExtensions.m"; sourceTree = ""; }; 384B11EF54740D94671EBC40277A4AE1 /* UIImageView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+WebCache.m"; path = "SDWebImage/UIImageView+WebCache.m"; sourceTree = ""; }; 388FDAF47EFEF8E2354262065ACD5432 /* NSOrderedSet+RACSequenceAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSOrderedSet+RACSequenceAdditions.h"; path = "ReactiveCocoa/Objective-C/NSOrderedSet+RACSequenceAdditions.h"; sourceTree = ""; }; 39B819887AD00091E47EFEBB1C4D6293 /* RACUnit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACUnit.m; path = "ReactiveCocoa/Objective-C/RACUnit.m"; sourceTree = ""; }; 3A2021E9945FEF95138597F73185383E /* MJRefreshBackGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackGifFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m; sourceTree = ""; }; 3AC06CA5C148C1CE619B48A5749C301D /* RACSubscriber+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RACSubscriber+Private.h"; path = "ReactiveCocoa/Objective-C/RACSubscriber+Private.h"; sourceTree = ""; }; 3BE0743F558E9A037CAB60C2B8775642 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3BFE01EDE2323976347DF54E4B71D510 /* RACImmediateScheduler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACImmediateScheduler.h; path = "ReactiveCocoa/Objective-C/RACImmediateScheduler.h"; sourceTree = ""; }; 3C32EE2F3025F97F3982477A027FD6DE /* UIControl+RACSignalSupportPrivate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIControl+RACSignalSupportPrivate.m"; path = "ReactiveCocoa/Objective-C/UIControl+RACSignalSupportPrivate.m"; sourceTree = ""; }; 3D433893D61787615D32A3BB9DA9D51A /* DACircularProgress-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "DACircularProgress-dummy.m"; sourceTree = ""; }; 3D8C52C4C1363BDAB126CC314303CF68 /* RACPassthroughSubscriber.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACPassthroughSubscriber.h; path = "ReactiveCocoa/Objective-C/RACPassthroughSubscriber.h"; sourceTree = ""; }; 3E025561039B8FAD2BF3E4DFD1400ED9 /* UIAlertView+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIAlertView+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UIAlertView+RACSignalSupport.m"; sourceTree = ""; }; 3ECE5AD23F674D5730471BE3A13366F8 /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h"; sourceTree = ""; }; 3F8C104E2ECD5DAA7DF07B8AF6DC4E7C /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; 3F9873A6369DD78A4B7547F192454404 /* SDWebImagePrefetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImagePrefetcher.h; path = SDWebImage/SDWebImagePrefetcher.h; sourceTree = ""; }; 3FE3B9592D5E80C0D98EB8611F9F7F05 /* NJKWebViewProgress.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NJKWebViewProgress.m; path = NJKWebViewProgress/NJKWebViewProgress.m; sourceTree = ""; }; 415ED47AFF2997401513C873C0E15531 /* RACTargetQueueScheduler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACTargetQueueScheduler.h; path = "ReactiveCocoa/Objective-C/RACTargetQueueScheduler.h"; sourceTree = ""; }; 421D68D254751D710514290C3F142623 /* RACSerialDisposable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACSerialDisposable.h; path = "ReactiveCocoa/Objective-C/RACSerialDisposable.h"; sourceTree = ""; }; 429BA83EA95D1725559EFE5276560A3D /* UIActionSheet+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActionSheet+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UIActionSheet+RACSignalSupport.m"; sourceTree = ""; }; 4368C683284C961AA2A8FB0F7BD9DBF8 /* AFImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFImageDownloader.m; path = "UIKit+AFNetworking/AFImageDownloader.m"; sourceTree = ""; }; 437E022A46A480754C54F00725EAFB64 /* SVProgressHUD-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SVProgressHUD-prefix.pch"; sourceTree = ""; }; 43B2555C309E0CF30EAF226C769EA1FA /* UMSocialTumblrHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialTumblrHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Tumblr/UMSocialTumblrHandler.h; sourceTree = ""; }; 43F7462D2BD9A5A5B1F5C60FA43E0036 /* WBSDKBasicButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WBSDKBasicButton.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBSDKBasicButton.h; sourceTree = ""; }; 44EF620D15E9F97CBEA8FF45B112E6ED /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 465941E4DC4A34F2B7FEBBA369329062 /* WeiboSDK.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WeiboSDK.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WeiboSDK.h; sourceTree = ""; }; 470BF47D43361B7ABCAD26320AD329A3 /* SVProgressHUD-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SVProgressHUD-dummy.m"; sourceTree = ""; }; 478A7113A4700506C8345783A2E0D02B /* UMSocialFacebookHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialFacebookHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/UMSocialFacebookHandler.h; sourceTree = ""; }; 487C7B37C3A3AE467452EB40973AB2E3 /* UIImagePickerController+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImagePickerController+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UIImagePickerController+RACSignalSupport.m"; sourceTree = ""; }; 48974FB2D05D403AEF69BFCC9EB4EBF3 /* ReactiveCocoa.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ReactiveCocoa.xcconfig; sourceTree = ""; }; 489AC57D7F55028173024FC11F7BEF63 /* SDImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCache.h; path = SDWebImage/SDImageCache.h; sourceTree = ""; }; 48B920D6E809F194511B3781F25F9055 /* EXTScope.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTScope.h; path = "ReactiveCocoa/Objective-C/extobjc/EXTScope.h"; sourceTree = ""; }; 48F5F604D4E0464A77C336CCDFC5C06E /* RACReturnSignal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACReturnSignal.h; path = "ReactiveCocoa/Objective-C/RACReturnSignal.h"; sourceTree = ""; }; 49D487F354F79D8D6D367F2EA263F418 /* SignalProducer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SignalProducer.swift; path = ReactiveCocoa/Swift/SignalProducer.swift; sourceTree = ""; }; 49FEAB8BBDA81884BB5B3C142A954D81 /* MJExtensionConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJExtensionConst.h; path = MJExtension/MJExtensionConst.h; sourceTree = ""; }; 4A47E80BB0414B90A81EAEFA3F6D9239 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/ImageIO.framework; sourceTree = DEVELOPER_DIR; }; 4A4EBDA864BE36414BFF88BD8F686033 /* UMSocialLaiwangHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialLaiwangHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/LaiWang/UMSocialLaiwangHandler.h; sourceTree = ""; }; 4A55E6FACC73AF55EF9836CC6A9EF858 /* NSArray+RACSequenceAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+RACSequenceAdditions.h"; path = "ReactiveCocoa/Objective-C/NSArray+RACSequenceAdditions.h"; sourceTree = ""; }; 4A7194B1C09FCC0468DD8C0F335E2010 /* RACArraySequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACArraySequence.h; path = "ReactiveCocoa/Objective-C/RACArraySequence.h"; sourceTree = ""; }; 4AA8B431CCA64EDE836AA2CCD05AC950 /* UIView+WebCacheOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCacheOperation.h"; path = "SDWebImage/UIView+WebCacheOperation.h"; sourceTree = ""; }; 4ADCC2A12D303D037DAF0853CCA30850 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLResponseSerialization.h; path = AFNetworking/AFURLResponseSerialization.h; sourceTree = ""; }; 4AE78463FCE5D33E21D15A0EE9DB7957 /* NSObject+RACLifting.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+RACLifting.h"; path = "ReactiveCocoa/Objective-C/NSObject+RACLifting.h"; sourceTree = ""; }; 4AF24A9D371339EA3A8950DA892A2CEC /* RACSubscriptingAssignmentTrampoline.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACSubscriptingAssignmentTrampoline.m; path = "ReactiveCocoa/Objective-C/RACSubscriptingAssignmentTrampoline.m"; sourceTree = ""; }; 4B0FC659831F2AF2F86179BC38BE9888 /* SVProgressHUD.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SVProgressHUD.h; path = SVProgressHUD/SVProgressHUD.h; sourceTree = ""; }; 4B7DA8685E9F6509969D1AC3428C9AC1 /* MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJExtension.h; path = MJExtension/MJExtension.h; sourceTree = ""; }; 4B8845A5317A9A2E5C9AC34BB8582BF9 /* UIImage+GIF.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+GIF.h"; path = "SDWebImage/UIImage+GIF.h"; sourceTree = ""; }; 4BB03C64E18C548BBB12543740048695 /* WeiboUser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WeiboUser.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WeiboUser.h; sourceTree = ""; }; 4BC03A006CBCD628BCEB58193DC7A5D2 /* RACEmptySequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACEmptySequence.m; path = "ReactiveCocoa/Objective-C/RACEmptySequence.m"; sourceTree = ""; }; 4C164F0023335CC42ABF57B6AC5E3DCA /* Observer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Observer.swift; path = ReactiveCocoa/Swift/Observer.swift; sourceTree = ""; }; 4C5C539E675EC20D05160336D5856B14 /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = ReactiveCocoa/Swift/Errors.swift; sourceTree = ""; }; 4C5FB4710E695F1BAE791F9A50A108E2 /* NSObject+RACDeallocating.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+RACDeallocating.h"; path = "ReactiveCocoa/Objective-C/NSObject+RACDeallocating.h"; sourceTree = ""; }; 4CC6ACF21F2B99DF847E417F2B74C659 /* RACUnarySequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACUnarySequence.h; path = "ReactiveCocoa/Objective-C/RACUnarySequence.h"; sourceTree = ""; }; 4D9AD3CBF51B0E685856C97780A563F5 /* UIBarButtonItem+RACCommandSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIBarButtonItem+RACCommandSupport.h"; path = "ReactiveCocoa/Objective-C/UIBarButtonItem+RACCommandSupport.h"; sourceTree = ""; }; 4EED8A20E4204DC6AA2E74CC61A3E8BA /* RACDynamicSignal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACDynamicSignal.h; path = "ReactiveCocoa/Objective-C/RACDynamicSignal.h"; sourceTree = ""; }; 4F2AD288D4DCF53E728C1A1466A87875 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = AFNetworking/AFURLResponseSerialization.m; sourceTree = ""; }; 4F84DC6C0850AC07A1B378574B872FF1 /* UIAlertView+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIAlertView+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UIAlertView+RACSignalSupport.h"; sourceTree = ""; }; 50D655ED3DED0D8733D35DBF167C1F8B /* RACObjCRuntime.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACObjCRuntime.m; path = "ReactiveCocoa/Objective-C/RACObjCRuntime.m"; sourceTree = ""; }; 50EFB6EA010031514D3C926778AE4B28 /* RACCompoundDisposable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACCompoundDisposable.m; path = "ReactiveCocoa/Objective-C/RACCompoundDisposable.m"; sourceTree = ""; }; 519DC0F16ADF084A298A1C1FBCBFD8FB /* NSFileHandle+RACSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSFileHandle+RACSupport.m"; path = "ReactiveCocoa/Objective-C/NSFileHandle+RACSupport.m"; sourceTree = ""; }; 51D219983844DE91EED12BF6C498F8CD /* RACReplaySubject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACReplaySubject.m; path = "ReactiveCocoa/Objective-C/RACReplaySubject.m"; sourceTree = ""; }; 546A223BCB351F8EE7D67820F6ED34BB /* WBSDKCommentButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WBSDKCommentButton.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBSDKCommentButton.h; sourceTree = ""; }; 54A77C4EA7F3B970E9396FD77260DC39 /* RACObjCRuntime.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACObjCRuntime.h; path = "ReactiveCocoa/Objective-C/RACObjCRuntime.h"; sourceTree = ""; }; 5524B69733BB0ED106175FD5542CF25E /* NSObject+RACKVOWrapper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+RACKVOWrapper.h"; path = "ReactiveCocoa/Objective-C/NSObject+RACKVOWrapper.h"; sourceTree = ""; }; 553B52FBE486D38BBCE50610A111FB83 /* RACSubscriber.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACSubscriber.h; path = "ReactiveCocoa/Objective-C/RACSubscriber.h"; sourceTree = ""; }; 5631B7A82C687959FE85664EC5C9473E /* UMSocialDataService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialDataService.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialDataService.h; sourceTree = ""; }; 58E9BDFCC6E8C48ABF1532E15BA9F727 /* RACKVOTrampoline.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACKVOTrampoline.h; path = "ReactiveCocoa/Objective-C/RACKVOTrampoline.h"; sourceTree = ""; }; 5944D7D3FBA790E75B7ED7D9DF3AB43D /* RACCompoundDisposableProvider.d */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.dtrace; name = RACCompoundDisposableProvider.d; path = "ReactiveCocoa/Objective-C/RACCompoundDisposableProvider.d"; sourceTree = ""; }; 595A5A876B3C808F023DC56B4B96D198 /* UMSocialSinaHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialSinaHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Sina/UMSocialSinaHandler.h; sourceTree = ""; }; 59F7AB9A67264A98A676B0AD2F4CC4D3 /* UMSocialConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialConfig.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialConfig.h; sourceTree = ""; }; 5A685DCF4657094755205817A226A13C /* RACQueueScheduler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACQueueScheduler.h; path = "ReactiveCocoa/Objective-C/RACQueueScheduler.h"; sourceTree = ""; }; 5A80F20F9A079897F7763E34E2C5597E /* UICollectionReusableView+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionReusableView+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UICollectionReusableView+RACSignalSupport.h"; sourceTree = ""; }; 5A8D84F0ACCE5A92EAE2B4EFFA3A5BC7 /* NSInvocation+RACTypeParsing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSInvocation+RACTypeParsing.h"; path = "ReactiveCocoa/Objective-C/NSInvocation+RACTypeParsing.h"; sourceTree = ""; }; 5BED186263438A97A14FFFB416C0B465 /* NSString+RACSequenceAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+RACSequenceAdditions.h"; path = "ReactiveCocoa/Objective-C/NSString+RACSequenceAdditions.h"; sourceTree = ""; }; 5BF6AE1FDCE77051A8C839CED59BB34D /* UMSocialLineHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialLineHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Line/UMSocialLineHandler.h; sourceTree = ""; }; 5C3A4E7DDAA72BBF33F0FBB6D4C26C07 /* ReactiveCocoa.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ReactiveCocoa.h; path = ReactiveCocoa/ReactiveCocoa.h; sourceTree = ""; }; 5CE37C161C0EE70794E73D87B40E5090 /* RACEagerSequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACEagerSequence.h; path = "ReactiveCocoa/Objective-C/RACEagerSequence.h"; sourceTree = ""; }; 5CFB09319D3043B97E87098173ACB6A3 /* UIActivityIndicatorView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActivityIndicatorView+AFNetworking.h"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h"; sourceTree = ""; }; 5D05FD8E528963F2685FFD2B80E1CD5E /* UIButton+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+WebCache.h"; path = "SDWebImage/UIButton+WebCache.h"; sourceTree = ""; }; 5F12FBEE960935A37F82ED5D29FDA3CC /* NSObject+RACPropertySubscribing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+RACPropertySubscribing.h"; path = "ReactiveCocoa/Objective-C/NSObject+RACPropertySubscribing.h"; sourceTree = ""; }; 615FAAC3A47F83CB019987185921481F /* RACScopedDisposable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACScopedDisposable.m; path = "ReactiveCocoa/Objective-C/RACScopedDisposable.m"; sourceTree = ""; }; 62099B3D70733BED521A40A4AE13014B /* NSObject+RACDeallocating.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+RACDeallocating.m"; path = "ReactiveCocoa/Objective-C/NSObject+RACDeallocating.m"; sourceTree = ""; }; 62BCF26D36C4317CFB733A51294C580A /* SDWebImageCompat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCompat.m; path = SDWebImage/SDWebImageCompat.m; sourceTree = ""; }; 6322DCAD38692D58EBEEF58939665257 /* Result.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Result.modulemap; sourceTree = ""; }; 63F4526194B00D140E9F43CFE83CC868 /* RACBlockTrampoline.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACBlockTrampoline.h; path = "ReactiveCocoa/Objective-C/RACBlockTrampoline.h"; sourceTree = ""; }; 647B1602B2F0939011C20E21D90DCA51 /* UIWebView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIWebView+AFNetworking.h"; path = "UIKit+AFNetworking/UIWebView+AFNetworking.h"; sourceTree = ""; }; 64B2BBC280624DAA5159807DD47EDA7C /* SDWebImage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SDWebImage.xcconfig; sourceTree = ""; }; 64BB381E9FC1EB317BD2DB17212FBB4E /* NJKWebViewProgress-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "NJKWebViewProgress-umbrella.h"; sourceTree = ""; }; 657579FA1269B3702EB29DA0B5E20336 /* AFAutoPurgingImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFAutoPurgingImageCache.h; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.h"; sourceTree = ""; }; 6587A73A29A00806426C245D436CC4DB /* MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefresh.h; path = MJRefresh/MJRefresh.h; sourceTree = ""; }; 65A88C62ACB26C7993D78A9751E7C43E /* NSObject+MJProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJProperty.h"; path = "MJExtension/NSObject+MJProperty.h"; sourceTree = ""; }; 65B87D4C329AFCFF4F76B02AD0E6481D /* RACSignal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACSignal.m; path = "ReactiveCocoa/Objective-C/RACSignal.m"; sourceTree = ""; }; 65F5B35589F9DB55205F95B1029703C4 /* UIRefreshControl+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIRefreshControl+AFNetworking.h"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.h"; sourceTree = ""; }; 665306F25921CE243C77B2179A928FC6 /* MJRefreshAutoFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoFooter.m; path = MJRefresh/Base/MJRefreshAutoFooter.m; sourceTree = ""; }; 665FD1AEECD5FFCFCE9EB168AEC03E6F /* SVProgressHUD.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = SVProgressHUD.bundle; path = SVProgressHUD/SVProgressHUD.bundle; sourceTree = ""; }; 671C8806A9FB4EEF4D16B5DCB8DCB7A0 /* SDWebImageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageManager.m; path = SDWebImage/SDWebImageManager.m; sourceTree = ""; }; 67A6E7EE4BABE5B9C6F5BC0A445F4BF5 /* UIStepper+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIStepper+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UIStepper+RACSignalSupport.h"; sourceTree = ""; }; 6856BC220D1A3E3FBEFDF2A9F6FE2659 /* NSObject+RACDescription.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+RACDescription.m"; path = "ReactiveCocoa/Objective-C/NSObject+RACDescription.m"; sourceTree = ""; }; 687CFE33E261EA13466B67A115B31C17 /* DACircularProgress-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DACircularProgress-prefix.pch"; sourceTree = ""; }; 69325818E2697FC23FBCBC49ED966437 /* UMSocialBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialBar.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialBar.h; sourceTree = ""; }; 693263AF622FE0B5862A74F23A9332D1 /* UMSCommentInputController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = UMSCommentInputController.xib; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentInputController.xib; sourceTree = ""; }; 6A0C7C592DBC93BCC8F09A5FD589C92A /* UMSocialControllerServiceComment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialControllerServiceComment.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialControllerServiceComment.h; sourceTree = ""; }; 6AB4385785B935EEAF37EFC56F267112 /* UIBarButtonItem+RACCommandSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIBarButtonItem+RACCommandSupport.m"; path = "ReactiveCocoa/Objective-C/UIBarButtonItem+RACCommandSupport.m"; sourceTree = ""; }; 6BD83ACABD6CFE31B6B652747D04962D /* Disposable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Disposable.swift; path = ReactiveCocoa/Swift/Disposable.swift; sourceTree = ""; }; 6C3F23F399EF62C8DEDADC7C32F2654B /* RACSequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACSequence.h; path = "ReactiveCocoa/Objective-C/RACSequence.h"; sourceTree = ""; }; 6C57774CFCB37FFF487DE6AC84BAA0AC /* DACircularProgressView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DACircularProgressView.h; path = DACircularProgress/DACircularProgressView.h; sourceTree = ""; }; 6D380A4F4137C3191AC8C38C3844F6F9 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkReachabilityManager.m; path = AFNetworking/AFNetworkReachabilityManager.m; sourceTree = ""; }; 6D3BCF589E4CFF8B4CFEC14816C6550A /* RACSubject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACSubject.m; path = "ReactiveCocoa/Objective-C/RACSubject.m"; sourceTree = ""; }; 6F40BC006E0930A50E0266C73DA609FE /* MJRefreshAutoNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoNormalFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h; sourceTree = ""; }; 6F4978074EEC4F723B9E4B212BD1287B /* RACTupleSequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACTupleSequence.m; path = "ReactiveCocoa/Objective-C/RACTupleSequence.m"; sourceTree = ""; }; 6FA901B394FEF81CC1CBCDE93E4E4E33 /* RACEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACEvent.h; path = "ReactiveCocoa/Objective-C/RACEvent.h"; sourceTree = ""; }; 701745585DCF4B7F3AD5CA8E9A3283E6 /* MJRefreshAutoGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoGifFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m; sourceTree = ""; }; 70335EEB3F3ED4753931F862F6AE2D4C /* UITableViewCell+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITableViewCell+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UITableViewCell+RACSignalSupport.h"; sourceTree = ""; }; 7094B67ADA79A207B80ED1C678096C56 /* SVRadialGradientLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SVRadialGradientLayer.m; path = SVProgressHUD/SVRadialGradientLayer.m; sourceTree = ""; }; 72C090B30816C4545F44566AF6DA4DB5 /* DACircularProgress.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = DACircularProgress.modulemap; sourceTree = ""; }; 7304BB1549A9A2B972545AEAD38EC23B /* UIRefreshControl+RACCommandSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIRefreshControl+RACCommandSupport.h"; path = "ReactiveCocoa/Objective-C/UIRefreshControl+RACCommandSupport.h"; sourceTree = ""; }; 74B2F1E2E8F5A521CF8C020F68AE9401 /* RACSignal+Operations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RACSignal+Operations.h"; path = "ReactiveCocoa/Objective-C/RACSignal+Operations.h"; sourceTree = ""; }; 74CC208244E551D18584AE550743152D /* SDWebImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SDWebImage-dummy.m"; sourceTree = ""; }; 760C68EEB4C3B3288B8D028C95AF4A5B /* MJRefreshBackNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackNormalFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h; sourceTree = ""; }; 761B06747C21716F22BC760FB21E4D34 /* RACMulticastConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACMulticastConnection.m; path = "ReactiveCocoa/Objective-C/RACMulticastConnection.m"; sourceTree = ""; }; 7699487F8E111F337425EA20CA75C6BC /* UMSocialInstagramHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialInstagramHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Instagram/UMSocialInstagramHandler.h; sourceTree = ""; }; 7762D610F1224AB1BA7F5CE589B317F1 /* UIKit+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIKit+AFNetworking.h"; path = "UIKit+AFNetworking/UIKit+AFNetworking.h"; sourceTree = ""; }; 779C75D5D0D23A1AB35ECFF926AAD43E /* MJRefreshBackFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackFooter.h; path = MJRefresh/Base/MJRefreshBackFooter.h; sourceTree = ""; }; 77A8DBFA8332F76E243E6674682DC696 /* NJKWebViewProgressView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NJKWebViewProgressView.m; path = NJKWebViewProgress/NJKWebViewProgressView.m; sourceTree = ""; }; 798FAF630718310A3CD51B9F2109F585 /* NSObject+RACPropertySubscribing.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+RACPropertySubscribing.m"; path = "ReactiveCocoa/Objective-C/NSObject+RACPropertySubscribing.m"; sourceTree = ""; }; 79A9DEDC89FE8336BF5FEDAAF75BF7FC /* Pods.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Pods.modulemap; sourceTree = ""; }; 79FC08DDDA96EE7F692A9CA244FDD07A /* RACSignal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACSignal.h; path = "ReactiveCocoa/Objective-C/RACSignal.h"; sourceTree = ""; }; 7AFAB896F150D62C666F8599CF7C13AC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 7B9F762F0010F498291E76E02D8E7F51 /* RACTuple.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACTuple.m; path = "ReactiveCocoa/Objective-C/RACTuple.m"; sourceTree = ""; }; 7BC0DC5C5BD1AAD23974E567532B5A3F /* RACValueTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACValueTransformer.h; path = "ReactiveCocoa/Objective-C/RACValueTransformer.h"; sourceTree = ""; }; 7D0D354758AEE84330634F2194E38953 /* UIButton+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+AFNetworking.h"; path = "UIKit+AFNetworking/UIButton+AFNetworking.h"; sourceTree = ""; }; 7DE1DF3A1C8F5A26C0E0C151BCCB8E40 /* MJRefreshGifHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshGifHeader.h; path = MJRefresh/Custom/Header/MJRefreshGifHeader.h; sourceTree = ""; }; 7E94EF582B3E464F2BEA71C5346895AC /* WXApi.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = WXApi.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Wechat/WXApi.h; sourceTree = ""; }; 7EDB048279E2B3CA010EFE2AE186AB08 /* RACScheduler+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RACScheduler+Private.h"; path = "ReactiveCocoa/Objective-C/RACScheduler+Private.h"; sourceTree = ""; }; 7F27F7DA0D449258B474893084F7C6AB /* RACUnarySequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACUnarySequence.m; path = "ReactiveCocoa/Objective-C/RACUnarySequence.m"; sourceTree = ""; }; 7F61C5CC2A3A56EB81D4794106C378AC /* RACUnit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACUnit.h; path = "ReactiveCocoa/Objective-C/RACUnit.h"; sourceTree = ""; }; 80E7DDD0E7E084DAF534D6B073631BB2 /* MJRefresh.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = MJRefresh.modulemap; sourceTree = ""; }; 81235D80D900A74FD1968D9C6B1C7655 /* AFNetworking-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-prefix.pch"; sourceTree = ""; }; 81385A2C31D5D660F1189632254CB601 /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; 81D25D4F4D6B7D02E21F5C8C0BB43218 /* UIDatePicker+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIDatePicker+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UIDatePicker+RACSignalSupport.m"; sourceTree = ""; }; 827EE8470BA8113E1D08BA60A9DB4AE4 /* MJRefreshNormalHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalHeader.m; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.m; sourceTree = ""; }; 83CDCC039BDE0A01444E5637C01D5AB3 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 83D878636318BC9BC302D1BA76A4CC46 /* AFAutoPurgingImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFAutoPurgingImageCache.m; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.m"; sourceTree = ""; }; 85E976B9474660285C492769605631FA /* UIButton+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+AFNetworking.m"; path = "UIKit+AFNetworking/UIButton+AFNetworking.m"; sourceTree = ""; }; 85FF1DEBB8560D116AE8785E3D9500ED /* UIControl+RACSignalSupportPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIControl+RACSignalSupportPrivate.h"; path = "ReactiveCocoa/Objective-C/UIControl+RACSignalSupportPrivate.h"; sourceTree = ""; }; 866913B5AAAA621C55BF26E3F1FA5F19 /* NSIndexSet+RACSequenceAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSIndexSet+RACSequenceAdditions.h"; path = "ReactiveCocoa/Objective-C/NSIndexSet+RACSequenceAdditions.h"; sourceTree = ""; }; 873D1ADD735B27286236748899F7921F /* UIControl+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIControl+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UIControl+RACSignalSupport.h"; sourceTree = ""; }; 87B213035BAC5F75386F62D3C75D2342 /* Pods-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-acknowledgements.plist"; sourceTree = ""; }; 87D85553FDF0A6201B95EB15FD0276BE /* UISwitch+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UISwitch+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UISwitch+RACSignalSupport.m"; sourceTree = ""; }; 88068B890B9C0588AC3CF4B903532BAC /* NSData+RACSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+RACSupport.h"; path = "ReactiveCocoa/Objective-C/NSData+RACSupport.h"; sourceTree = ""; }; 8858F9E080A925223FA42F75EE78F6A8 /* MJRefreshGifHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshGifHeader.m; path = MJRefresh/Custom/Header/MJRefreshGifHeader.m; sourceTree = ""; }; 894E5DA93A9F359521A89826BE6DA777 /* Pods-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-dummy.m"; sourceTree = ""; }; 8987D14700FA10B9378E7ED1AE673C27 /* RACKVOTrampoline.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACKVOTrampoline.m; path = "ReactiveCocoa/Objective-C/RACKVOTrampoline.m"; sourceTree = ""; }; 8A0B49C3C170F533DDC330533C388200 /* RACStringSequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACStringSequence.h; path = "ReactiveCocoa/Objective-C/RACStringSequence.h"; sourceTree = ""; }; 8A9D916B5F5972DEC7187DC4C1A69560 /* UIView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MJExtension.h"; path = "MJRefresh/UIView+MJExtension.h"; sourceTree = ""; }; 8AEFE2CAD5E3DEA1ED6CF01584279D16 /* NSDictionary+RACSequenceAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+RACSequenceAdditions.h"; path = "ReactiveCocoa/Objective-C/NSDictionary+RACSequenceAdditions.h"; sourceTree = ""; }; 8B7FC9995CDD31296CD24310BD75FE95 /* RACDelegateProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACDelegateProxy.m; path = "ReactiveCocoa/Objective-C/RACDelegateProxy.m"; sourceTree = ""; }; 8C179B4B0A25E2587F438F48E729F964 /* UITableViewHeaderFooterView+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITableViewHeaderFooterView+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UITableViewHeaderFooterView+RACSignalSupport.m"; sourceTree = ""; }; 8D10AD9F1ACB5CD9CA679673D87F616C /* MJRefreshBackGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackGifFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h; sourceTree = ""; }; 8D181778EACAB30C2DF3EB81AFCC312D /* UITableViewHeaderFooterView+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITableViewHeaderFooterView+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UITableViewHeaderFooterView+RACSignalSupport.h"; sourceTree = ""; }; 8D287DD867B406F2ADEB2636891D4EBE /* RACBlockTrampoline.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACBlockTrampoline.m; path = "ReactiveCocoa/Objective-C/RACBlockTrampoline.m"; sourceTree = ""; }; 8DF2A484755B6BFAB3DD9E8749E0E32A /* MJRefresh.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MJRefresh.bundle; path = MJRefresh/MJRefresh.bundle; sourceTree = ""; }; 8E82D8F966DFF2EDFECC4638BB6E2390 /* UIButton+RACCommandSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+RACCommandSupport.h"; path = "ReactiveCocoa/Objective-C/UIButton+RACCommandSupport.h"; sourceTree = ""; }; 8F26B0A5160BB003B5AA2DEE23E1CF27 /* MJRefreshBackNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackNormalFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m; sourceTree = ""; }; 8F6E24019AF1B2A6251029C2F9F1C101 /* UIActivityIndicatorView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActivityIndicatorView+AFNetworking.m"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m"; sourceTree = ""; }; 8FDD15F4292E86F2B50815F0697C4DAB /* UMSocialControllerService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialControllerService.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialControllerService.h; sourceTree = ""; }; 90C95D49530F835B55F4CA43885E06F4 /* SDWebImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloader.h; path = SDWebImage/SDWebImageDownloader.h; sourceTree = ""; }; 91A4C2A30C90A73B281741E7282FA276 /* MJExtension-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJExtension-umbrella.h"; sourceTree = ""; }; 91E412FCE5D6DD365C60CB8076F60FF3 /* NSString+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+MJExtension.h"; path = "MJExtension/NSString+MJExtension.h"; sourceTree = ""; }; 92C9992D6643E6705FB59DFECB608AFA /* SDWebImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloader.m; path = SDWebImage/SDWebImageDownloader.m; sourceTree = ""; }; 92EAED162A87EB212AEB28B7B66FBCA0 /* Result.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Result.xcconfig; sourceTree = ""; }; 93375D6B669C56C745FB6849F302058B /* UMSocialSDKResourcesNew.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = UMSocialSDKResourcesNew.bundle; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/UMSocialSDKResourcesNew.bundle; sourceTree = ""; }; 93C4F71361B0469BE16C31AB9579776F /* MJRefreshAutoGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoGifFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h; sourceTree = ""; }; 94645B657EE6D5FF0163C672CB64099E /* ReactiveCocoa-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ReactiveCocoa-dummy.m"; sourceTree = ""; }; 94A82F40FBE3032EF7B279257D1620D9 /* UMSocialWhatsappHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialWhatsappHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Whatsapp/UMSocialWhatsappHandler.h; sourceTree = ""; }; 951959C78934236EBF5CD3C36F733FCC /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 95AACEC6CC96EE165C763F0FA461DC68 /* metamacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = metamacros.h; path = "ReactiveCocoa/Objective-C/extobjc/metamacros.h"; sourceTree = ""; }; 962469AB44C0A99BBC308F1885FD3448 /* ReactiveCocoa.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = ReactiveCocoa.modulemap; sourceTree = ""; }; 963FABC9E999205BCBCAB1347CE4E5CD /* UIView+WebCacheOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCacheOperation.m"; path = "SDWebImage/UIView+WebCacheOperation.m"; sourceTree = ""; }; 977577C045EDA9D9D1F46E2598D19FC7 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.debug.xcconfig; sourceTree = ""; }; 9935967190930CA33F32A0BD9292552A /* RACValueTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACValueTransformer.m; path = "ReactiveCocoa/Objective-C/RACValueTransformer.m"; sourceTree = ""; }; 9946203DCEC78A5FF966F92C3E2F0E0B /* RACQueueScheduler+Subclass.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RACQueueScheduler+Subclass.h"; path = "ReactiveCocoa/Objective-C/RACQueueScheduler+Subclass.h"; sourceTree = ""; }; 99940E95018B693482DA0E603FBE96E1 /* RACEmptySignal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACEmptySignal.h; path = "ReactiveCocoa/Objective-C/RACEmptySignal.h"; sourceTree = ""; }; 99B636AEBE4F97178E01D3B80FEEB991 /* RACEmptySequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACEmptySequence.h; path = "ReactiveCocoa/Objective-C/RACEmptySequence.h"; sourceTree = ""; }; 99C98D7479B3CF2EF91FF077AFC2E3FA /* NSData+RACSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+RACSupport.m"; path = "ReactiveCocoa/Objective-C/NSData+RACSupport.m"; sourceTree = ""; }; 99D86F5858BD2991F4054295DB9A6B81 /* RACSignalProvider.d */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.dtrace; name = RACSignalProvider.d; path = "ReactiveCocoa/Objective-C/RACSignalProvider.d"; sourceTree = ""; }; 9A08FDFD6F4116F62414049A7E08EB28 /* RACChannel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACChannel.m; path = "ReactiveCocoa/Objective-C/RACChannel.m"; sourceTree = ""; }; 9A750DFECCFC1702DACB94D6B04486E2 /* MJPropertyKey.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJPropertyKey.h; path = MJExtension/MJPropertyKey.h; sourceTree = ""; }; 9A7B5DD43A49B31BDAEEA9D8A50D6DDF /* MJRefreshComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshComponent.m; path = MJRefresh/Base/MJRefreshComponent.m; sourceTree = ""; }; 9A80563F26E1898D391EBDD72319194A /* NJKWebViewProgressView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NJKWebViewProgressView.h; path = NJKWebViewProgress/NJKWebViewProgressView.h; sourceTree = ""; }; 9A89DA1D225B160992C2CA9696C73776 /* NSURLConnection+RACSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSURLConnection+RACSupport.m"; path = "ReactiveCocoa/Objective-C/NSURLConnection+RACSupport.m"; sourceTree = ""; }; 9AE98AF69BAD8F07BB16232D800176C8 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; 9B5625480188612898E004BC6C041065 /* RACTestScheduler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACTestScheduler.h; path = "ReactiveCocoa/Objective-C/RACTestScheduler.h"; sourceTree = ""; }; 9BA3B0CDC3DFF8020BE9CF970087F087 /* MJRefreshStateHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateHeader.h; path = MJRefresh/Custom/Header/MJRefreshStateHeader.h; sourceTree = ""; }; 9BC995660210D5DE77B68627738CBAF0 /* NJKWebViewProgress-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "NJKWebViewProgress-prefix.pch"; sourceTree = ""; }; 9C1F4583A78B09D927E29BEBA9551586 /* RACTestScheduler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACTestScheduler.m; path = "ReactiveCocoa/Objective-C/RACTestScheduler.m"; sourceTree = ""; }; 9C4B0AD995AF74E076A53F619FE89D1C /* NSObject+RACKVOWrapper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+RACKVOWrapper.m"; path = "ReactiveCocoa/Objective-C/NSObject+RACKVOWrapper.m"; sourceTree = ""; }; 9CD1EAE74FA692AC8BAEEACB053B9324 /* UIImage+GIF.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+GIF.m"; path = "SDWebImage/UIImage+GIF.m"; sourceTree = ""; }; 9D77C8A4DFBF971B00581F616C5C3AA5 /* RACSerialDisposable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACSerialDisposable.m; path = "ReactiveCocoa/Objective-C/RACSerialDisposable.m"; sourceTree = ""; }; 9DD0C1BD3A05CF5DDAA0C32F95C7CCFC /* RACEagerSequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACEagerSequence.m; path = "ReactiveCocoa/Objective-C/RACEagerSequence.m"; sourceTree = ""; }; 9DD9D6B81C51F4F24E457F66295A90AE /* MJRefreshConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConst.h; path = MJRefresh/MJRefreshConst.h; sourceTree = ""; }; 9F30E05A946B7A54A30BC72162F70A36 /* RACTargetQueueScheduler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACTargetQueueScheduler.m; path = "ReactiveCocoa/Objective-C/RACTargetQueueScheduler.m"; sourceTree = ""; }; 9F57914A519C2E92A90FCBAC4C56BCA1 /* NSDictionary+RACSequenceAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+RACSequenceAdditions.m"; path = "ReactiveCocoa/Objective-C/NSDictionary+RACSequenceAdditions.m"; sourceTree = ""; }; 9FE8F3328FD5DA10E662D3E3612E892E /* DACircularProgress-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DACircularProgress-umbrella.h"; sourceTree = ""; }; A08C93F88B6CA9D68E60D8989E39989F /* Scheduler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Scheduler.swift; path = ReactiveCocoa/Swift/Scheduler.swift; sourceTree = ""; }; A09567EF6A6A8400BEC6E81380B768F6 /* UIScrollView+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJRefresh.h"; path = "MJRefresh/UIScrollView+MJRefresh.h"; sourceTree = ""; }; A0BDBDB77D7F3942C80739E5B95267D1 /* NSSet+RACSequenceAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSSet+RACSequenceAdditions.h"; path = "ReactiveCocoa/Objective-C/NSSet+RACSequenceAdditions.h"; sourceTree = ""; }; A1061C71204A323EDD42383C339969CB /* UIScrollView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJExtension.m"; path = "MJRefresh/UIScrollView+MJExtension.m"; sourceTree = ""; }; A19678BE408B5098995BFB18144274C9 /* MJRefreshHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshHeader.m; path = MJRefresh/Base/MJRefreshHeader.m; sourceTree = ""; }; A1D060C7FA4F15BC07B9C71EF1B5B91C /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A1DF584D946B78214595DA9CBCB0E938 /* NJKWebViewProgress.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = NJKWebViewProgress.xcconfig; sourceTree = ""; }; A3026BC8DB8F8F2CA36E8535E1F643F5 /* RACErrorSignal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACErrorSignal.h; path = "ReactiveCocoa/Objective-C/RACErrorSignal.h"; sourceTree = ""; }; A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; A4BFD7235669DFC6C5F8A7CA037E2BB0 /* MKAnnotationView+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MKAnnotationView+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/MKAnnotationView+RACSignalSupport.h"; sourceTree = ""; }; A4E03F5541C865B1E97472EB309106B0 /* RACScopedDisposable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACScopedDisposable.h; path = "ReactiveCocoa/Objective-C/RACScopedDisposable.h"; sourceTree = ""; }; A527A6B121AE049337AA777E6D937E07 /* RACBehaviorSubject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACBehaviorSubject.m; path = "ReactiveCocoa/Objective-C/RACBehaviorSubject.m"; sourceTree = ""; }; A5DDFF4D75D3D1D9A7B7D99D8B0BF03B /* RACSequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACSequence.m; path = "ReactiveCocoa/Objective-C/RACSequence.m"; sourceTree = ""; }; A6B443A889FFE21F2568DF7F9051B834 /* UISwitch+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UISwitch+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UISwitch+RACSignalSupport.h"; sourceTree = ""; }; A6BEE214C0861CABFEC4A99A3E61A6C2 /* UIScrollView+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJRefresh.m"; path = "MJRefresh/UIScrollView+MJRefresh.m"; sourceTree = ""; }; A715FDA5CEEA5F15D55327E810A04267 /* RACSignalSequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACSignalSequence.m; path = "ReactiveCocoa/Objective-C/RACSignalSequence.m"; sourceTree = ""; }; A7644E1E2725ED44B3E4C3E712764243 /* AFNetworking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AFNetworking.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A76F3456E072E02608565E8C86A0D8F7 /* Signal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Signal.swift; path = ReactiveCocoa/Swift/Signal.swift; sourceTree = ""; }; A7B9D2E1FF56188A82EB12A38064A264 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A824F0BE4B5F3D459BAD005E6212EA0B /* MKAnnotationView+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MKAnnotationView+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/MKAnnotationView+RACSignalSupport.m"; sourceTree = ""; }; A89FC17E6B10BFEF06045D45EC8F6FF8 /* RACStringSequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACStringSequence.m; path = "ReactiveCocoa/Objective-C/RACStringSequence.m"; sourceTree = ""; }; A8AD00FA1CE9CD81E01F7DF7FEA36CC2 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A8E5B203CAD658FDF4CD5D2CCE3A6057 /* ReactiveCocoa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveCocoa.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A96EA91189E9737332A144B71892B45D /* RACArraySequence.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACArraySequence.m; path = "ReactiveCocoa/Objective-C/RACArraySequence.m"; sourceTree = ""; }; A9964D7562908E51C1C056A746B0AE49 /* UITextView+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITextView+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UITextView+RACSignalSupport.h"; sourceTree = ""; }; A9A24C7194EB1F183CE6B4C9AE06AD99 /* UIProgressView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIProgressView+AFNetworking.h"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.h"; sourceTree = ""; }; A9F89340C49BD17D20E0A729312481FD /* UIActionSheet+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActionSheet+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UIActionSheet+RACSignalSupport.h"; sourceTree = ""; }; AA298557E9E97C6386EC51A27CB4206B /* NSData+ImageContentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+ImageContentType.m"; path = "SDWebImage/NSData+ImageContentType.m"; sourceTree = ""; }; AA50E3F6E4BFEC14F9568DF42598C79D /* MJPropertyKey.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJPropertyKey.m; path = MJExtension/MJPropertyKey.m; sourceTree = ""; }; AA9C03D203D73109E5356C40978B6837 /* SVProgressHUD-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SVProgressHUD-umbrella.h"; sourceTree = ""; }; AB031EAC44BA3ABEDD23851F5D0892DB /* SDWebImagePrefetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImagePrefetcher.m; path = SDWebImage/SDWebImagePrefetcher.m; sourceTree = ""; }; ABC4CD8CC0631C4558A895B20BD1CE24 /* EXTKeyPathCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTKeyPathCoding.h; path = "ReactiveCocoa/Objective-C/extobjc/EXTKeyPathCoding.h"; sourceTree = ""; }; AF52700EF1A07BD7C472480318D5B449 /* RACMulticastConnection+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RACMulticastConnection+Private.h"; path = "ReactiveCocoa/Objective-C/RACMulticastConnection+Private.h"; sourceTree = ""; }; AFB4F39A97EEA4CB606A257BD52621B8 /* RACIndexSetSequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACIndexSetSequence.h; path = "ReactiveCocoa/Objective-C/RACIndexSetSequence.h"; sourceTree = ""; }; AFD4BA75EC240FA027E3566EEB6BE607 /* SDImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCache.m; path = SDWebImage/SDImageCache.m; sourceTree = ""; }; B07B1BE566B8C25733CCFC2905C60E92 /* MJRefresh-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-prefix.pch"; sourceTree = ""; }; B109B965D74D1DF7895555155F9167B4 /* UIImage+MultiFormat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MultiFormat.h"; path = "SDWebImage/UIImage+MultiFormat.h"; sourceTree = ""; }; B146CE257A00226824E49ECF3C629F4F /* UMSocialTwitterHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialTwitterHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/UMSocialTwitterHandler.h; sourceTree = ""; }; B1E666B007C5C55BDB7AA3FB5D798960 /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLRequestSerialization.h; path = AFNetworking/AFURLRequestSerialization.h; sourceTree = ""; }; B20C17CD12A642AE53D6EB41DADC0F2B /* DACircularProgress.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = DACircularProgress.xcconfig; sourceTree = ""; }; B26C89BAEA96E55DC008D427750C820E /* MJRefresh-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-umbrella.h"; sourceTree = ""; }; B30ECCFDDBE8A3CD9FBD6985CA8C516A /* RACDelegateProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACDelegateProxy.h; path = "ReactiveCocoa/Objective-C/RACDelegateProxy.h"; sourceTree = ""; }; B34411085B6CE8449ECF3DA79473A40A /* RACChannel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACChannel.h; path = "ReactiveCocoa/Objective-C/RACChannel.h"; sourceTree = ""; }; B3A6E8E3B715B4995F7DEE5A5FDF8EDE /* NJKWebViewProgress.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NJKWebViewProgress.h; path = NJKWebViewProgress/NJKWebViewProgress.h; sourceTree = ""; }; B3EA5D64AD312484AAD0C2EA4F03BB66 /* RACErrorSignal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACErrorSignal.m; path = "ReactiveCocoa/Objective-C/RACErrorSignal.m"; sourceTree = ""; }; B3EACFC90A3853E0536A4DA5562CE760 /* UIImageView+HighlightedWebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+HighlightedWebCache.m"; path = "SDWebImage/UIImageView+HighlightedWebCache.m"; sourceTree = ""; }; B448D8632DF91896DFCD0BEFF7244E5D /* NSData+ImageContentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+ImageContentType.h"; path = "SDWebImage/NSData+ImageContentType.h"; sourceTree = ""; }; B4B17DECE01AAC9BA272506436DE73FF /* MJPropertyType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJPropertyType.m; path = MJExtension/MJPropertyType.m; sourceTree = ""; }; B5516D92939621BD471E86FDA40744D6 /* MJRefreshAutoFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoFooter.h; path = MJRefresh/Base/MJRefreshAutoFooter.h; sourceTree = ""; }; B59240F4E6C2D09A8AECBE4EB339E04D /* UISlider+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UISlider+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UISlider+RACSignalSupport.h"; sourceTree = ""; }; B5CCA305F7FAD724BA8C81AE7C18BDA7 /* NJKWebViewProgress.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = NJKWebViewProgress.modulemap; sourceTree = ""; }; B61855E7AF94D92A56B2E5742C24E5DD /* UMSCommentDetailController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = UMSCommentDetailController.xib; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentDetailController.xib; sourceTree = ""; }; B68E10B6BA0F1B0D4E3C8096500C8DBF /* TupleExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TupleExtensions.swift; path = ReactiveCocoa/Swift/TupleExtensions.swift; sourceTree = ""; }; B69789BB77F174CEABB55543FDCDCBBD /* AFNetworking.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.xcconfig; sourceTree = ""; }; B7C4539ED08962A5251CFBC170F4E5B1 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPSessionManager.m; path = AFNetworking/AFHTTPSessionManager.m; sourceTree = ""; }; B80687972DF9A550FCDC275E9D92735D /* Action.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Action.swift; path = ReactiveCocoa/Swift/Action.swift; sourceTree = ""; }; B8D50A20C640AA87771EF793A3B33D58 /* MJRefreshAutoNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoNormalFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m; sourceTree = ""; }; B9A5FBE2156B8A0DA7B3F8FF89613307 /* NSNotificationCenter+RACSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSNotificationCenter+RACSupport.m"; path = "ReactiveCocoa/Objective-C/NSNotificationCenter+RACSupport.m"; sourceTree = ""; }; B9CBA6ACA140F7557934629609816945 /* NSSet+RACSequenceAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSSet+RACSequenceAdditions.m"; path = "ReactiveCocoa/Objective-C/NSSet+RACSequenceAdditions.m"; sourceTree = ""; }; B9D638C8A921514FC49BBDBEDA760214 /* RACSubscriptionScheduler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACSubscriptionScheduler.h; path = "ReactiveCocoa/Objective-C/RACSubscriptionScheduler.h"; sourceTree = ""; }; B9EB10C652C1C526AD0AD72B0542845A /* NSString+RACSequenceAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+RACSequenceAdditions.m"; path = "ReactiveCocoa/Objective-C/NSString+RACSequenceAdditions.m"; sourceTree = ""; }; BA4602700DF3E5C3D59A8073A330C497 /* RACGroupedSignal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACGroupedSignal.m; path = "ReactiveCocoa/Objective-C/RACGroupedSignal.m"; sourceTree = ""; }; BA49143A92AE77748413FEEE2654B389 /* UIProgressView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIProgressView+AFNetworking.m"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.m"; sourceTree = ""; }; BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; BB32F54022E8F7E71D5C575C764203F5 /* Event.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Event.swift; path = ReactiveCocoa/Swift/Event.swift; sourceTree = ""; }; BB4A068D4F391DFF007C5E826F88C673 /* MJRefreshBackFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackFooter.m; path = MJRefresh/Base/MJRefreshBackFooter.m; sourceTree = ""; }; BB6D9CAD4BED373DCB3EEE7170CDFEB2 /* DALabeledCircularProgressView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DALabeledCircularProgressView.h; path = DACircularProgress/DALabeledCircularProgressView.h; sourceTree = ""; }; BB8CB0F2BBB3216F8BC69ABD64494045 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Result/Result.swift; sourceTree = ""; }; BC76762C8413ACAEF0462E770E5BADE3 /* MJRefreshAutoStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoStateFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m; sourceTree = ""; }; BD5D799295EE6F34460C45067C971D09 /* RACCompoundDisposable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACCompoundDisposable.h; path = "ReactiveCocoa/Objective-C/RACCompoundDisposable.h"; sourceTree = ""; }; BD7C6AC814B6C827D15CA018A32E68D6 /* RACTuple.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACTuple.h; path = "ReactiveCocoa/Objective-C/RACTuple.h"; sourceTree = ""; }; BD932B09F529355D99F88697668B2BD3 /* NSString+RACKeyPathUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+RACKeyPathUtilities.h"; path = "ReactiveCocoa/Objective-C/NSString+RACKeyPathUtilities.h"; sourceTree = ""; }; BDA934FAC50E5908597A06861F54876A /* NSArray+RACSequenceAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+RACSequenceAdditions.m"; path = "ReactiveCocoa/Objective-C/NSArray+RACSequenceAdditions.m"; sourceTree = ""; }; BDAB1FFC1AAA7DC65A96E0DD0E808705 /* SDWebImageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageManager.h; path = SDWebImage/SDWebImageManager.h; sourceTree = ""; }; BE52FC1BA382E1B3451103330DC78B99 /* UMSocialSnsService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialSnsService.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialSnsService.h; sourceTree = ""; }; C0798A8391AC76966E0969FC1E819EBD /* Bag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Bag.swift; path = ReactiveCocoa/Swift/Bag.swift; sourceTree = ""; }; C12EABC206D6422B92011E9A5DBAC8A8 /* NSString+RACSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+RACSupport.h"; path = "ReactiveCocoa/Objective-C/NSString+RACSupport.h"; sourceTree = ""; }; C16C390DA92494698A0B5A96D2E0BDF1 /* SVIndefiniteAnimatedView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SVIndefiniteAnimatedView.h; path = SVProgressHUD/SVIndefiniteAnimatedView.h; sourceTree = ""; }; C1E1D8502CC717DA524B7E464CFA9D60 /* AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworking.h; path = AFNetworking/AFNetworking.h; sourceTree = ""; }; C1F8238C534EF89A54816DB436C8853D /* UMSocialSinaSSOHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialSinaSSOHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/UMSocialSinaSSOHandler.h; sourceTree = ""; }; C30356461CD94DCCEB2CA832125EFDC4 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; }; C34BF5CCAF6CC03BF645C76B848286D8 /* MJExtension.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = MJExtension.modulemap; sourceTree = ""; }; C44B145F63067DA65072538D023F78C9 /* NSObject+MJKeyValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJKeyValue.h"; path = "MJExtension/NSObject+MJKeyValue.h"; sourceTree = ""; }; C6AE4F60540D6788200F546AF6F8431A /* UMSocial.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocial.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocial.h; sourceTree = ""; }; C81BBE1B6B6942EA554D22570C8EF8F3 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C8320B310F2C0E3E62DC8D36525674BC /* RACTupleSequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACTupleSequence.h; path = "ReactiveCocoa/Objective-C/RACTupleSequence.h"; sourceTree = ""; }; C8B3E37B1644A5A6620F06F58E3297F0 /* MJRefresh.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MJRefresh.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C8EDB2613EF74A96A98805E88478BA6A /* SDWebImage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-umbrella.h"; sourceTree = ""; }; C91C625319E115577646BDAC4769DF5A /* NSIndexSet+RACSequenceAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSIndexSet+RACSequenceAdditions.m"; path = "ReactiveCocoa/Objective-C/NSIndexSet+RACSequenceAdditions.m"; sourceTree = ""; }; C9B5A83C364AF6A759B6FAB36D1B3A4D /* FoundationExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FoundationExtensions.swift; path = ReactiveCocoa/Swift/FoundationExtensions.swift; sourceTree = ""; }; C9CEEC8B3653DF7ECDD9F6994C125AE8 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CA69C4C7C21FC84A6C3ACDDAF6AE98A4 /* WeiboSDK.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = WeiboSDK.bundle; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WeiboSDK.bundle; sourceTree = ""; }; CA8B7E4FBDC083EDF3149135E2DEE349 /* Property.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Property.swift; path = ReactiveCocoa/Swift/Property.swift; sourceTree = ""; }; CAD8C2C811FA110EB1D85F0F6BDC41A3 /* RACEmptySignal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACEmptySignal.m; path = "ReactiveCocoa/Objective-C/RACEmptySignal.m"; sourceTree = ""; }; CBC0F7C552B739C909B650A0F42F7F38 /* Pods-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-resources.sh"; sourceTree = ""; }; CC43C0D25552A4CC426C3FCF6371BF12 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPSessionManager.h; path = AFNetworking/AFHTTPSessionManager.h; sourceTree = ""; }; CC607CF5B5D9B3420B30AA34AA024E44 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFSecurityPolicy.h; path = AFNetworking/AFSecurityPolicy.h; sourceTree = ""; }; CD3FB75CDCA680D6B2DD50EDEE181762 /* NSObject+RACDescription.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+RACDescription.h"; path = "ReactiveCocoa/Objective-C/NSObject+RACDescription.h"; sourceTree = ""; }; CFF28FD09E7B21D2B491C785A9F1752F /* UIStepper+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIStepper+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UIStepper+RACSignalSupport.m"; sourceTree = ""; }; D0405803033A2A777B8E4DFA0C1800ED /* Pods-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-acknowledgements.markdown"; sourceTree = ""; }; D0469FCCA9E4851070CF89D690EB5D12 /* Result-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Result-dummy.m"; sourceTree = ""; }; D09C25D5FC16E6F61F1AA912B9A39B65 /* NSObject+MJClass.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJClass.m"; path = "MJExtension/NSObject+MJClass.m"; sourceTree = ""; }; D0BA0F92F89081D2609638A9895AB503 /* SVRadialGradientLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SVRadialGradientLayer.h; path = SVProgressHUD/SVRadialGradientLayer.h; sourceTree = ""; }; D1435E2B8DC44D70DAD2E74DB5ED4F48 /* SDWebImageOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageOperation.h; path = SDWebImage/SDWebImageOperation.h; sourceTree = ""; }; D1F686D628D8073F4C50C9171C6F7F38 /* NSNotificationCenter+RACSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSNotificationCenter+RACSupport.h"; path = "ReactiveCocoa/Objective-C/NSNotificationCenter+RACSupport.h"; sourceTree = ""; }; D283ADAA967B772489287A1DE7161B90 /* NSFileHandle+RACSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSFileHandle+RACSupport.h"; path = "ReactiveCocoa/Objective-C/NSFileHandle+RACSupport.h"; sourceTree = ""; }; D30739FD0BBBC87DCA328AB763D58A85 /* MJRefreshFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshFooter.m; path = MJRefresh/Base/MJRefreshFooter.m; sourceTree = ""; }; D310D5AB2204F87230BFC6C3C9B0134E /* ReactiveCocoa-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ReactiveCocoa-umbrella.h"; sourceTree = ""; }; D3789BA9ECCCC7F74C14776D5F7D2A76 /* NSString+RACKeyPathUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+RACKeyPathUtilities.m"; path = "ReactiveCocoa/Objective-C/NSString+RACKeyPathUtilities.m"; sourceTree = ""; }; D394875D112D2406E07D6783972EAA9E /* MJRefreshConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConst.m; path = MJRefresh/MJRefreshConst.m; sourceTree = ""; }; D3D71B771102AEA2F2D5E4D6D85AB4D6 /* RACDynamicSignal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACDynamicSignal.m; path = "ReactiveCocoa/Objective-C/RACDynamicSignal.m"; sourceTree = ""; }; D3DFE9D8C8B7B5975B79A3ED6CD36509 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D443DF293DAD2B3569FB6C2757DE5DEE /* DALabeledCircularProgressView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DALabeledCircularProgressView.m; path = DACircularProgress/DALabeledCircularProgressView.m; sourceTree = ""; }; D5541ACE685641DA75EE8D016327EBCA /* UIImageView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+WebCache.h"; path = "SDWebImage/UIImageView+WebCache.h"; sourceTree = ""; }; D5C99DD591CB596FCA58275314A1283F /* MJRefreshBackStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackStateFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m; sourceTree = ""; }; D68DE6C9FA55C107BB0E743C027D4F0F /* NJKWebViewProgress.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NJKWebViewProgress.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D79EB7D14F41D48652E69458403F4457 /* ResultType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResultType.swift; path = Result/ResultType.swift; sourceTree = ""; }; D8843362CAD0A95F12D3944CF21DF90A /* UIImage+MultiFormat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MultiFormat.m"; path = "SDWebImage/UIImage+MultiFormat.m"; sourceTree = ""; }; D947872ED90AA60B0F658492E4AEC97E /* MJProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJProperty.h; path = MJExtension/MJProperty.h; sourceTree = ""; }; DA1B4DF6E7E13554316A8775838EC8A6 /* ReactiveCocoa-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ReactiveCocoa-prefix.pch"; sourceTree = ""; }; DA312349A49333542E6F4B36B329960E /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.release.xcconfig; sourceTree = ""; }; DAA125B459F46A34746B8F375E042CE2 /* RACSubscriptionScheduler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACSubscriptionScheduler.m; path = "ReactiveCocoa/Objective-C/RACSubscriptionScheduler.m"; sourceTree = ""; }; DC7B18D7C2CA308A468FD2D083CEEB0A /* APOpenAPIObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = APOpenAPIObject.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/AlipayShare/APOpenAPIObject.h; sourceTree = ""; }; DD6CC38E13D731C62DE79A7084DFB924 /* ObjectiveCBridging.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ObjectiveCBridging.swift; path = ReactiveCocoa/Swift/ObjectiveCBridging.swift; sourceTree = ""; }; DE3CAA2C90009AB04A9C1A9233566CA0 /* MJRefreshNormalHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalHeader.h; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.h; sourceTree = ""; }; E00F85DF61A097080D9B006A42852B08 /* UIButton+RACCommandSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+RACCommandSupport.m"; path = "ReactiveCocoa/Objective-C/UIButton+RACCommandSupport.m"; sourceTree = ""; }; E02EC8F52BB28C3F34F78F3034DB4B0A /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkReachabilityManager.h; path = AFNetworking/AFNetworkReachabilityManager.h; sourceTree = ""; }; E0C6216E113A1F9A069260ED5B50111F /* RACDynamicSequence.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACDynamicSequence.h; path = "ReactiveCocoa/Objective-C/RACDynamicSequence.h"; sourceTree = ""; }; E186E931D518F5F01762FEACCE1188D9 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; E2B6F1FAA9D6337E9009E98F903961E3 /* NSObject+MJKeyValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+MJKeyValue.m"; path = "MJExtension/NSObject+MJKeyValue.m"; sourceTree = ""; }; E3B89EEBCE0A896C3213236412974A4F /* RACDynamicPropertySuperclass.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACDynamicPropertySuperclass.h; path = "ReactiveCocoa/Objective-C/RACDynamicPropertySuperclass.h"; sourceTree = ""; }; E3C329F969DD5A15D9B7DB7E2CE1CCD0 /* RACKVOProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACKVOProxy.h; path = "ReactiveCocoa/Objective-C/RACKVOProxy.h"; sourceTree = ""; }; E4BE7396A99977EA27137A889AB23A82 /* UIGestureRecognizer+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIGestureRecognizer+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UIGestureRecognizer+RACSignalSupport.h"; sourceTree = ""; }; E5CD8F5EBE3094663634930E490C7286 /* MJRefresh.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.xcconfig; sourceTree = ""; }; E5F0B5EED1468E45BF3B9E55D0921211 /* WBHttpRequest+WeiboUser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "WBHttpRequest+WeiboUser.h"; path = "Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest+WeiboUser.h"; sourceTree = ""; }; E66CAF5003E9213A4537D17DF0140B4D /* NSObject+MJClass.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+MJClass.h"; path = "MJExtension/NSObject+MJClass.h"; sourceTree = ""; }; E73089F923B47D3893EED446E53C7E28 /* UITextField+RACSignalSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITextField+RACSignalSupport.h"; path = "ReactiveCocoa/Objective-C/UITextField+RACSignalSupport.h"; sourceTree = ""; }; E7F21354943D9F42A70697D5A5EF72E9 /* Pods-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-frameworks.sh"; sourceTree = ""; }; E81AB1499B5BC494FB166DC100E727D2 /* SVProgressHUD.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SVProgressHUD.xcconfig; sourceTree = ""; }; E82FFE3AE1A6AD452A3B2CD3EEFCEC61 /* RACDisposable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACDisposable.m; path = "ReactiveCocoa/Objective-C/RACDisposable.m"; sourceTree = ""; }; E8446514FBAD26C0E18F24A5715AEF67 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E8C38A2B732C0C6570EA75D32ABC4EF4 /* NSOrderedSet+RACSequenceAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSOrderedSet+RACSequenceAdditions.m"; path = "ReactiveCocoa/Objective-C/NSOrderedSet+RACSequenceAdditions.m"; sourceTree = ""; }; E9022EE9051D51B98121F849F4769EE2 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; EB6C3290DEE08AE7ED2C7AC1B98D3154 /* RACMulticastConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACMulticastConnection.h; path = "ReactiveCocoa/Objective-C/RACMulticastConnection.h"; sourceTree = ""; }; EBCA2833B9CE5CDF9FF6D8991B9E0455 /* en.lproj */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder; name = en.lproj; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/en.lproj; sourceTree = ""; }; EBD8EC21AF605F5B2C221E911F03A04E /* SDWebImage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = SDWebImage.modulemap; sourceTree = ""; }; EC40E5CC64338F892D0C9C3F62F4F58C /* NSObject+RACSelectorSignal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+RACSelectorSignal.m"; path = "ReactiveCocoa/Objective-C/NSObject+RACSelectorSignal.m"; sourceTree = ""; }; ECB9285932E9DF2DD113CB88004F8A48 /* NJKWebViewProgress-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "NJKWebViewProgress-dummy.m"; sourceTree = ""; }; ED3B91A5243892EA1305E4F5870D3AF0 /* RACSubscriptingAssignmentTrampoline.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACSubscriptingAssignmentTrampoline.h; path = "ReactiveCocoa/Objective-C/RACSubscriptingAssignmentTrampoline.h"; sourceTree = ""; }; EF82F55068FEFF3AEA0F3E84A46183E1 /* zh-Hans.lproj */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder; name = "zh-Hans.lproj"; path = "Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/zh-Hans.lproj"; sourceTree = ""; }; F04C630FB7E53F60E360F879CBE5F7D9 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLRequestSerialization.m; path = AFNetworking/AFURLRequestSerialization.m; sourceTree = ""; }; F0D1B728EB6048D8D5B0AC2D40EC9E40 /* UIView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MJExtension.m"; path = "MJRefresh/UIView+MJExtension.m"; sourceTree = ""; }; F0D450CC9C0FF76EC8DD1E7380FB0A6F /* MJRefreshFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshFooter.h; path = MJRefresh/Base/MJRefreshFooter.h; sourceTree = ""; }; F356A0AA79F9864B6198AEF0BF333D72 /* EXTRuntimeExtensions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = EXTRuntimeExtensions.h; path = "ReactiveCocoa/Objective-C/extobjc/EXTRuntimeExtensions.h"; sourceTree = ""; }; F37169A84687244F35CFCC5ABEA8A01A /* UIButton+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+WebCache.m"; path = "SDWebImage/UIButton+WebCache.m"; sourceTree = ""; }; F398BCA5C354DE916BE3F66F46468339 /* UIGestureRecognizer+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIGestureRecognizer+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UIGestureRecognizer+RACSignalSupport.m"; sourceTree = ""; }; F3CC7C65E6195DE0F13C516AA3B7CD19 /* UMSocialSnsData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialSnsData.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialSnsData.h; sourceTree = ""; }; F58E4B445DAA8708DBC10F3116C81417 /* AFURLSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLSessionManager.h; path = AFNetworking/AFURLSessionManager.h; sourceTree = ""; }; F5FFB3C8AD598A1BD00CC6AD1A661249 /* RACBehaviorSubject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACBehaviorSubject.h; path = "ReactiveCocoa/Objective-C/RACBehaviorSubject.h"; sourceTree = ""; }; F7C0815343868D09101769AA016A9EBC /* SVProgressHUD.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SVProgressHUD.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F837CA4A39C79C92F66C2AC2957863E3 /* UICollectionReusableView+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionReusableView+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UICollectionReusableView+RACSignalSupport.m"; sourceTree = ""; }; F881DF03DBE295AF59B1CF9B9E6DC007 /* UMSnsAccountViewController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = UMSnsAccountViewController.xib; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSnsAccountViewController.xib; sourceTree = ""; }; F89D1F8452E50ECE7ACCDD5DE95FAE9C /* RACScheduler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACScheduler.h; path = "ReactiveCocoa/Objective-C/RACScheduler.h"; sourceTree = ""; }; FA4100EF250D4DDD7C65BEBE719E943A /* SVProgressHUD.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = SVProgressHUD.modulemap; sourceTree = ""; }; FA8F7C14656D9F2B06C707A058346B31 /* UITableViewCell+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITableViewCell+RACSignalSupport.m"; path = "ReactiveCocoa/Objective-C/UITableViewCell+RACSignalSupport.m"; sourceTree = ""; }; FABB85ED518C4DA0BB4262DAAC3A1EE7 /* NSString+RACSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+RACSupport.m"; path = "ReactiveCocoa/Objective-C/NSString+RACSupport.m"; sourceTree = ""; }; FB35F887EFA3E741160AF6B1C118B082 /* UMSocialWechatHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialWechatHandler.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Wechat/UMSocialWechatHandler.h; sourceTree = ""; }; FB5F5A3768964DE4BF07FD98955E6581 /* RACCommand.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RACCommand.h; path = "ReactiveCocoa/Objective-C/RACCommand.h"; sourceTree = ""; }; FB659CCBAA26184991F162A631D1674B /* UMSocialAccountManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = UMSocialAccountManager.h; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialAccountManager.h; sourceTree = ""; }; FB8CEF4CEDA5F903EFD528676610423C /* AFSecurityPolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = AFNetworking/AFSecurityPolicy.m; sourceTree = ""; }; FBD93D46AB6FEFB9207551729F2D8D90 /* RACPassthroughSubscriber.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACPassthroughSubscriber.m; path = "ReactiveCocoa/Objective-C/RACPassthroughSubscriber.m"; sourceTree = ""; }; FBDDFA23D0529AD6C9280D6CEBB943E5 /* UMShareEditViewController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = UMShareEditViewController.xib; path = Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMShareEditViewController.xib; sourceTree = ""; }; FCCD810BBA0A1C5CBD98C80A0740A751 /* UIRefreshControl+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIRefreshControl+AFNetworking.m"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.m"; sourceTree = ""; }; FD9BF1E603B15AF71FFFCB71245E0CAB /* MJRefreshAutoStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoStateFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h; sourceTree = ""; }; FDE6FE508EE14BE865B0AED358D641BB /* AFImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFImageDownloader.h; path = "UIKit+AFNetworking/AFImageDownloader.h"; sourceTree = ""; }; FF23168D180714E936A4C3C601B08D1E /* RACDynamicPropertySuperclass.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RACDynamicPropertySuperclass.m; path = "ReactiveCocoa/Objective-C/RACDynamicPropertySuperclass.m"; sourceTree = ""; }; FFA49582C65298F437501438338FF005 /* UIImageView+HighlightedWebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+HighlightedWebCache.h"; path = "SDWebImage/UIImageView+HighlightedWebCache.h"; sourceTree = ""; }; FFF59AD42E90A38A6117396458DF1399 /* MJExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MJExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 2624FA01F2315084A8580A7172FA7AEA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 44DFF77EE49C02DB5A164C9014D396CD /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 43DC17E93088EE0302BE1E295EE2CC24 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 7E9FFD62DCF1B399B3E5C7F0ABF2A8B9 /* Foundation.framework in Frameworks */, 42593A48BAACE31A0FEDAEF23883D63A /* QuartzCore.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 6C1769B27D10552DD14117AB5C2BA628 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 04D69F84002443FD2881A5BBA179854C /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 7465D1D3DA3B4F4CE97C9DEB1BC461DE /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 89C4FA168E3BAB208640E8856D4139B1 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 88D29C88C57F1AEDB50E7E466C2EDA68 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( A7A5FDEE47DE5468D0B739E0277A85AB /* Foundation.framework in Frameworks */, 4F68348E2A31F997408476E01728417B /* Result.framework in Frameworks */, FB4FAB46E8CAA1A4DADAE3394DAC15FC /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; A1E32F8DFC56E52DD7A9CCB32FB3306B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 2881816427D93B7FC0A086299BBA23F4 /* Foundation.framework in Frameworks */, C9C7707877E21F715401B691B5A154BB /* ImageIO.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; B7DAFD442AA213456909FD79758AF7DF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( C1E60365B988A3A5E3C6F083B2904919 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; C151364F15F39F7CC60CBF9A3AB49B44 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 7E6A4EFA32969CDB9F9C57903152BA54 /* CoreGraphics.framework in Frameworks */, 7F17EA5E2787B6F2BBB359854B42A0E3 /* Foundation.framework in Frameworks */, D04B84B53456B9CD8A7236126075571B /* MobileCoreServices.framework in Frameworks */, C01AC3BAD9037A8A1E45FD17336C15F3 /* Security.framework in Frameworks */, 3A10EF6ABF51D1D00B06AC5EF3A8C28C /* SystemConfiguration.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; DBDDBD33224A7EEE1B6B90D09BD3DED5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 271E9F901C547EBFAA6EBFBF0BC5604A /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; DEF0F9C828729C23E117A97CB4E88714 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 27FF9D7097A5696D8B9630C19C83ED24 /* Foundation.framework in Frameworks */, EA928E4C4FD61092C3AA97E471411FE4 /* QuartzCore.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 035EA1098AD97B414DF3D2AD09947173 /* ProgressView */ = { isa = PBXGroup; children = ( 9A80563F26E1898D391EBDD72319194A /* NJKWebViewProgressView.h */, 77A8DBFA8332F76E243E6674682DC696 /* NJKWebViewProgressView.m */, ); name = ProgressView; sourceTree = ""; }; 05625802EB36799D6A66F9D9600065E8 /* Products */ = { isa = PBXGroup; children = ( A7644E1E2725ED44B3E4C3E712764243 /* AFNetworking.framework */, 15E8523EE6597A955B0FADAC061A8133 /* DACircularProgress.framework */, FFF59AD42E90A38A6117396458DF1399 /* MJExtension.framework */, C8B3E37B1644A5A6620F06F58E3297F0 /* MJRefresh.framework */, D68DE6C9FA55C107BB0E743C027D4F0F /* NJKWebViewProgress.framework */, 3BE0743F558E9A037CAB60C2B8775642 /* Pods.framework */, A8E5B203CAD658FDF4CD5D2CCE3A6057 /* ReactiveCocoa.framework */, A8AD00FA1CE9CD81E01F7DF7FEA36CC2 /* Result.framework */, C9CEEC8B3653DF7ECDD9F6994C125AE8 /* SDWebImage.framework */, F7C0815343868D09101769AA016A9EBC /* SVProgressHUD.framework */, ); name = Products; sourceTree = ""; }; 10416184854FD41D94849BB2B1D40142 /* DACircularProgress */ = { isa = PBXGroup; children = ( 6C57774CFCB37FFF487DE6AC84BAA0AC /* DACircularProgressView.h */, 0FC8E11456820F951465A69447AE2714 /* DACircularProgressView.m */, BB6D9CAD4BED373DCB3EEE7170CDFEB2 /* DALabeledCircularProgressView.h */, D443DF293DAD2B3569FB6C2757DE5DEE /* DALabeledCircularProgressView.m */, 946DEBAC2F979A510AB5C0ED719EA21F /* Support Files */, ); path = DACircularProgress; sourceTree = ""; }; 16CCE631D181C9BC6F8F1784A7A4312E /* Support Files */ = { isa = PBXGroup; children = ( 251DE2052E0DAB0482CE383D5ED31C30 /* Info.plist */, 6322DCAD38692D58EBEEF58939665257 /* Result.modulemap */, 92EAED162A87EB212AEB28B7B66FBCA0 /* Result.xcconfig */, D0469FCCA9E4851070CF89D690EB5D12 /* Result-dummy.m */, 2CE36BF68E3D265CC0A3C6FCE26500E3 /* Result-prefix.pch */, 0EFBC1962ABC17786F033C5D955C426A /* Result-umbrella.h */, ); name = "Support Files"; path = "../Target Support Files/Result"; sourceTree = ""; }; 1758D09ECAB283AE1B67EE88C5AA6A28 /* no-arc */ = { isa = PBXGroup; children = ( 54A77C4EA7F3B970E9396FD77260DC39 /* RACObjCRuntime.h */, 50D655ED3DED0D8733D35DBF167C1F8B /* RACObjCRuntime.m */, ); name = "no-arc"; sourceTree = ""; }; 19A4B5EF16AD928363E1F8C9BCC77434 /* Core */ = { isa = PBXGroup; children = ( B448D8632DF91896DFCD0BEFF7244E5D /* NSData+ImageContentType.h */, AA298557E9E97C6386EC51A27CB4206B /* NSData+ImageContentType.m */, 489AC57D7F55028173024FC11F7BEF63 /* SDImageCache.h */, AFD4BA75EC240FA027E3566EEB6BE607 /* SDImageCache.m */, 2664FC6FC44BC040C045CBF9826A5956 /* SDWebImageCompat.h */, 62BCF26D36C4317CFB733A51294C580A /* SDWebImageCompat.m */, 31BF7F9D6F415EE6D53EF01F9B610BA5 /* SDWebImageDecoder.h */, 187AA5C92CBF850647DD36DB96B441C8 /* SDWebImageDecoder.m */, 90C95D49530F835B55F4CA43885E06F4 /* SDWebImageDownloader.h */, 92C9992D6643E6705FB59DFECB608AFA /* SDWebImageDownloader.m */, 1D0A6CE7ADD9A9435F7C5A00304B02C8 /* SDWebImageDownloaderOperation.h */, 06B28D9101904B3DDA53E7542414905D /* SDWebImageDownloaderOperation.m */, BDAB1FFC1AAA7DC65A96E0DD0E808705 /* SDWebImageManager.h */, 671C8806A9FB4EEF4D16B5DCB8DCB7A0 /* SDWebImageManager.m */, D1435E2B8DC44D70DAD2E74DB5ED4F48 /* SDWebImageOperation.h */, 3F9873A6369DD78A4B7547F192454404 /* SDWebImagePrefetcher.h */, AB031EAC44BA3ABEDD23851F5D0892DB /* SDWebImagePrefetcher.m */, 5D05FD8E528963F2685FFD2B80E1CD5E /* UIButton+WebCache.h */, F37169A84687244F35CFCC5ABEA8A01A /* UIButton+WebCache.m */, 4B8845A5317A9A2E5C9AC34BB8582BF9 /* UIImage+GIF.h */, 9CD1EAE74FA692AC8BAEEACB053B9324 /* UIImage+GIF.m */, B109B965D74D1DF7895555155F9167B4 /* UIImage+MultiFormat.h */, D8843362CAD0A95F12D3944CF21DF90A /* UIImage+MultiFormat.m */, FFA49582C65298F437501438338FF005 /* UIImageView+HighlightedWebCache.h */, B3EACFC90A3853E0536A4DA5562CE760 /* UIImageView+HighlightedWebCache.m */, D5541ACE685641DA75EE8D016327EBCA /* UIImageView+WebCache.h */, 384B11EF54740D94671EBC40277A4AE1 /* UIImageView+WebCache.m */, 4AA8B431CCA64EDE836AA2CCD05AC950 /* UIView+WebCacheOperation.h */, 963FABC9E999205BCBCAB1347CE4E5CD /* UIView+WebCacheOperation.m */, ); name = Core; sourceTree = ""; }; 19FCDF91704DF91A3629B5A077295357 /* Core */ = { isa = PBXGroup; children = ( B80687972DF9A550FCDC275E9D92735D /* Action.swift */, 05290D288C6535325D67AFBF86D00468 /* Atomic.swift */, C0798A8391AC76966E0969FC1E819EBD /* Bag.swift */, 6BD83ACABD6CFE31B6B652747D04962D /* Disposable.swift */, 4C5C539E675EC20D05160336D5856B14 /* Errors.swift */, BB32F54022E8F7E71D5C575C764203F5 /* Event.swift */, ABC4CD8CC0631C4558A895B20BD1CE24 /* EXTKeyPathCoding.h */, F356A0AA79F9864B6198AEF0BF333D72 /* EXTRuntimeExtensions.h */, 36E0783D29417C70557ADA2D3812BAFE /* EXTRuntimeExtensions.m */, 48B920D6E809F194511B3781F25F9055 /* EXTScope.h */, C9B5A83C364AF6A759B6FAB36D1B3A4D /* FoundationExtensions.swift */, 95AACEC6CC96EE165C763F0FA461DC68 /* metamacros.h */, 4A55E6FACC73AF55EF9836CC6A9EF858 /* NSArray+RACSequenceAdditions.h */, BDA934FAC50E5908597A06861F54876A /* NSArray+RACSequenceAdditions.m */, 88068B890B9C0588AC3CF4B903532BAC /* NSData+RACSupport.h */, 99C98D7479B3CF2EF91FF077AFC2E3FA /* NSData+RACSupport.m */, 8AEFE2CAD5E3DEA1ED6CF01584279D16 /* NSDictionary+RACSequenceAdditions.h */, 9F57914A519C2E92A90FCBAC4C56BCA1 /* NSDictionary+RACSequenceAdditions.m */, 0FF286368DF6F4FD3E718A8DDF0B1329 /* NSEnumerator+RACSequenceAdditions.h */, 1C9AFF3F620F4F27318F5092C63D2D65 /* NSEnumerator+RACSequenceAdditions.m */, D283ADAA967B772489287A1DE7161B90 /* NSFileHandle+RACSupport.h */, 519DC0F16ADF084A298A1C1FBCBFD8FB /* NSFileHandle+RACSupport.m */, 866913B5AAAA621C55BF26E3F1FA5F19 /* NSIndexSet+RACSequenceAdditions.h */, C91C625319E115577646BDAC4769DF5A /* NSIndexSet+RACSequenceAdditions.m */, 5A8D84F0ACCE5A92EAE2B4EFFA3A5BC7 /* NSInvocation+RACTypeParsing.h */, 1B63C8C72A4078D0527C9DAA478C2DB0 /* NSInvocation+RACTypeParsing.m */, D1F686D628D8073F4C50C9171C6F7F38 /* NSNotificationCenter+RACSupport.h */, B9A5FBE2156B8A0DA7B3F8FF89613307 /* NSNotificationCenter+RACSupport.m */, 4C5FB4710E695F1BAE791F9A50A108E2 /* NSObject+RACDeallocating.h */, 62099B3D70733BED521A40A4AE13014B /* NSObject+RACDeallocating.m */, CD3FB75CDCA680D6B2DD50EDEE181762 /* NSObject+RACDescription.h */, 6856BC220D1A3E3FBEFDF2A9F6FE2659 /* NSObject+RACDescription.m */, 5524B69733BB0ED106175FD5542CF25E /* NSObject+RACKVOWrapper.h */, 9C4B0AD995AF74E076A53F619FE89D1C /* NSObject+RACKVOWrapper.m */, 4AE78463FCE5D33E21D15A0EE9DB7957 /* NSObject+RACLifting.h */, 20740BE7A5516344AB7DC38CDD8896E0 /* NSObject+RACLifting.m */, 5F12FBEE960935A37F82ED5D29FDA3CC /* NSObject+RACPropertySubscribing.h */, 798FAF630718310A3CD51B9F2109F585 /* NSObject+RACPropertySubscribing.m */, 29474BDF519166A22324D16A7341AF4A /* NSObject+RACSelectorSignal.h */, EC40E5CC64338F892D0C9C3F62F4F58C /* NSObject+RACSelectorSignal.m */, 388FDAF47EFEF8E2354262065ACD5432 /* NSOrderedSet+RACSequenceAdditions.h */, E8C38A2B732C0C6570EA75D32ABC4EF4 /* NSOrderedSet+RACSequenceAdditions.m */, A0BDBDB77D7F3942C80739E5B95267D1 /* NSSet+RACSequenceAdditions.h */, B9CBA6ACA140F7557934629609816945 /* NSSet+RACSequenceAdditions.m */, BD932B09F529355D99F88697668B2BD3 /* NSString+RACKeyPathUtilities.h */, D3789BA9ECCCC7F74C14776D5F7D2A76 /* NSString+RACKeyPathUtilities.m */, 5BED186263438A97A14FFFB416C0B465 /* NSString+RACSequenceAdditions.h */, B9EB10C652C1C526AD0AD72B0542845A /* NSString+RACSequenceAdditions.m */, C12EABC206D6422B92011E9A5DBAC8A8 /* NSString+RACSupport.h */, FABB85ED518C4DA0BB4262DAAC3A1EE7 /* NSString+RACSupport.m */, 0200FADDFC41780A72461242A8933469 /* NSURLConnection+RACSupport.h */, 9A89DA1D225B160992C2CA9696C73776 /* NSURLConnection+RACSupport.m */, 0A72841D503B7B4AABD02FE508DABEDF /* NSUserDefaults+RACSupport.h */, 0B20AC59ED957F2FFCFD375B980767D8 /* NSUserDefaults+RACSupport.m */, DD6CC38E13D731C62DE79A7084DFB924 /* ObjectiveCBridging.swift */, 4C164F0023335CC42ABF57B6AC5E3DCA /* Observer.swift */, 24C33EE3C87C90B83137CAC380D44D59 /* Optional.swift */, CA8B7E4FBDC083EDF3149135E2DEE349 /* Property.swift */, 4A7194B1C09FCC0468DD8C0F335E2010 /* RACArraySequence.h */, A96EA91189E9737332A144B71892B45D /* RACArraySequence.m */, F5FFB3C8AD598A1BD00CC6AD1A661249 /* RACBehaviorSubject.h */, A527A6B121AE049337AA777E6D937E07 /* RACBehaviorSubject.m */, 63F4526194B00D140E9F43CFE83CC868 /* RACBlockTrampoline.h */, 8D287DD867B406F2ADEB2636891D4EBE /* RACBlockTrampoline.m */, B34411085B6CE8449ECF3DA79473A40A /* RACChannel.h */, 9A08FDFD6F4116F62414049A7E08EB28 /* RACChannel.m */, FB5F5A3768964DE4BF07FD98955E6581 /* RACCommand.h */, 0D01E0F3F1F8BA7C23356819729299A1 /* RACCommand.m */, BD5D799295EE6F34460C45067C971D09 /* RACCompoundDisposable.h */, 50EFB6EA010031514D3C926778AE4B28 /* RACCompoundDisposable.m */, 5944D7D3FBA790E75B7ED7D9DF3AB43D /* RACCompoundDisposableProvider.d */, B30ECCFDDBE8A3CD9FBD6985CA8C516A /* RACDelegateProxy.h */, 8B7FC9995CDD31296CD24310BD75FE95 /* RACDelegateProxy.m */, 04686EC2F9E6B07BE356ECAC172AD7D1 /* RACDisposable.h */, E82FFE3AE1A6AD452A3B2CD3EEFCEC61 /* RACDisposable.m */, E3B89EEBCE0A896C3213236412974A4F /* RACDynamicPropertySuperclass.h */, FF23168D180714E936A4C3C601B08D1E /* RACDynamicPropertySuperclass.m */, E0C6216E113A1F9A069260ED5B50111F /* RACDynamicSequence.h */, 32422BA7F298B775A904F182146351C0 /* RACDynamicSequence.m */, 4EED8A20E4204DC6AA2E74CC61A3E8BA /* RACDynamicSignal.h */, D3D71B771102AEA2F2D5E4D6D85AB4D6 /* RACDynamicSignal.m */, 5CE37C161C0EE70794E73D87B40E5090 /* RACEagerSequence.h */, 9DD0C1BD3A05CF5DDAA0C32F95C7CCFC /* RACEagerSequence.m */, 99B636AEBE4F97178E01D3B80FEEB991 /* RACEmptySequence.h */, 4BC03A006CBCD628BCEB58193DC7A5D2 /* RACEmptySequence.m */, 99940E95018B693482DA0E603FBE96E1 /* RACEmptySignal.h */, CAD8C2C811FA110EB1D85F0F6BDC41A3 /* RACEmptySignal.m */, A3026BC8DB8F8F2CA36E8535E1F643F5 /* RACErrorSignal.h */, B3EA5D64AD312484AAD0C2EA4F03BB66 /* RACErrorSignal.m */, 6FA901B394FEF81CC1CBCDE93E4E4E33 /* RACEvent.h */, 25ADFA74A42F4EA16E025EAFFC997CE2 /* RACEvent.m */, 01C52214559D7845B69F76EAF3EA5AB4 /* RACGroupedSignal.h */, BA4602700DF3E5C3D59A8073A330C497 /* RACGroupedSignal.m */, 3BFE01EDE2323976347DF54E4B71D510 /* RACImmediateScheduler.h */, 11D6C1C4122D8FE7CA3BC466EB85EA0C /* RACImmediateScheduler.m */, AFB4F39A97EEA4CB606A257BD52621B8 /* RACIndexSetSequence.h */, 32205878DBB803322E1B42440847ECAB /* RACIndexSetSequence.m */, 06880042FBC5FCBF625C5CFF84286B13 /* RACKVOChannel.h */, 178C15910519FE8A1A6EDF25064EBAC9 /* RACKVOChannel.m */, E3C329F969DD5A15D9B7DB7E2CE1CCD0 /* RACKVOProxy.h */, 2F3F99995BE381D39F038649654DEBD7 /* RACKVOProxy.m */, 58E9BDFCC6E8C48ABF1532E15BA9F727 /* RACKVOTrampoline.h */, 8987D14700FA10B9378E7ED1AE673C27 /* RACKVOTrampoline.m */, EB6C3290DEE08AE7ED2C7AC1B98D3154 /* RACMulticastConnection.h */, 761B06747C21716F22BC760FB21E4D34 /* RACMulticastConnection.m */, AF52700EF1A07BD7C472480318D5B449 /* RACMulticastConnection+Private.h */, 3D8C52C4C1363BDAB126CC314303CF68 /* RACPassthroughSubscriber.h */, FBD93D46AB6FEFB9207551729F2D8D90 /* RACPassthroughSubscriber.m */, 5A685DCF4657094755205817A226A13C /* RACQueueScheduler.h */, 21E2DBB302C680CE8C1D520ACBFD60A9 /* RACQueueScheduler.m */, 9946203DCEC78A5FF966F92C3E2F0E0B /* RACQueueScheduler+Subclass.h */, 1832EC5F5771FBEA5CE0B7E5C0C3C60C /* RACReplaySubject.h */, 51D219983844DE91EED12BF6C498F8CD /* RACReplaySubject.m */, 48F5F604D4E0464A77C336CCDFC5C06E /* RACReturnSignal.h */, 1F0D58F39A052B2E7FD5A8DBF7C70C6C /* RACReturnSignal.m */, F89D1F8452E50ECE7ACCDD5DE95FAE9C /* RACScheduler.h */, 2292A1728848AF097FEEC307886BAA65 /* RACScheduler.m */, 7EDB048279E2B3CA010EFE2AE186AB08 /* RACScheduler+Private.h */, 36C67D4D144F82BB460E86417F992329 /* RACScheduler+Subclass.h */, A4E03F5541C865B1E97472EB309106B0 /* RACScopedDisposable.h */, 615FAAC3A47F83CB019987185921481F /* RACScopedDisposable.m */, 6C3F23F399EF62C8DEDADC7C32F2654B /* RACSequence.h */, A5DDFF4D75D3D1D9A7B7D99D8B0BF03B /* RACSequence.m */, 421D68D254751D710514290C3F142623 /* RACSerialDisposable.h */, 9D77C8A4DFBF971B00581F616C5C3AA5 /* RACSerialDisposable.m */, 79FC08DDDA96EE7F692A9CA244FDD07A /* RACSignal.h */, 65B87D4C329AFCFF4F76B02AD0E6481D /* RACSignal.m */, 74B2F1E2E8F5A521CF8C020F68AE9401 /* RACSignal+Operations.h */, 091ED5B0512672DE61D555CCB7142FD1 /* RACSignal+Operations.m */, 99D86F5858BD2991F4054295DB9A6B81 /* RACSignalProvider.d */, 2FACA2BDAE37AF70AF131A9DD8C8F023 /* RACSignalSequence.h */, A715FDA5CEEA5F15D55327E810A04267 /* RACSignalSequence.m */, 17FC11D339BD88DE46A3832ADB2E7698 /* RACStream.h */, 1F510D3EE3ACA142792DDF627F485853 /* RACStream.m */, 11DF06DCB011608D84991AD684676153 /* RACStream+Private.h */, 8A0B49C3C170F533DDC330533C388200 /* RACStringSequence.h */, A89FC17E6B10BFEF06045D45EC8F6FF8 /* RACStringSequence.m */, 2637ADDE4A30CF2CEF128EC9561C0B08 /* RACSubject.h */, 6D3BCF589E4CFF8B4CFEC14816C6550A /* RACSubject.m */, 553B52FBE486D38BBCE50610A111FB83 /* RACSubscriber.h */, 2ACEC0A293FEFB84F29DD8A55BA24605 /* RACSubscriber.m */, 3AC06CA5C148C1CE619B48A5749C301D /* RACSubscriber+Private.h */, ED3B91A5243892EA1305E4F5870D3AF0 /* RACSubscriptingAssignmentTrampoline.h */, 4AF24A9D371339EA3A8950DA892A2CEC /* RACSubscriptingAssignmentTrampoline.m */, B9D638C8A921514FC49BBDBEDA760214 /* RACSubscriptionScheduler.h */, DAA125B459F46A34746B8F375E042CE2 /* RACSubscriptionScheduler.m */, 415ED47AFF2997401513C873C0E15531 /* RACTargetQueueScheduler.h */, 9F30E05A946B7A54A30BC72162F70A36 /* RACTargetQueueScheduler.m */, 9B5625480188612898E004BC6C041065 /* RACTestScheduler.h */, 9C1F4583A78B09D927E29BEBA9551586 /* RACTestScheduler.m */, BD7C6AC814B6C827D15CA018A32E68D6 /* RACTuple.h */, 7B9F762F0010F498291E76E02D8E7F51 /* RACTuple.m */, C8320B310F2C0E3E62DC8D36525674BC /* RACTupleSequence.h */, 6F4978074EEC4F723B9E4B212BD1287B /* RACTupleSequence.m */, 4CC6ACF21F2B99DF847E417F2B74C659 /* RACUnarySequence.h */, 7F27F7DA0D449258B474893084F7C6AB /* RACUnarySequence.m */, 7F61C5CC2A3A56EB81D4794106C378AC /* RACUnit.h */, 39B819887AD00091E47EFEBB1C4D6293 /* RACUnit.m */, 7BC0DC5C5BD1AAD23974E567532B5A3F /* RACValueTransformer.h */, 9935967190930CA33F32A0BD9292552A /* RACValueTransformer.m */, 131F1B7D90AD4CDC3DC4D5002774196F /* ReactiveCocoa-Bridging-Header.h */, A08C93F88B6CA9D68E60D8989E39989F /* Scheduler.swift */, A76F3456E072E02608565E8C86A0D8F7 /* Signal.swift */, 49D487F354F79D8D6D367F2EA263F418 /* SignalProducer.swift */, B68E10B6BA0F1B0D4E3C8096500C8DBF /* TupleExtensions.swift */, ); name = Core; sourceTree = ""; }; 1D8123D14ADB51DABCCC0B97626935F3 /* Support Files */ = { isa = PBXGroup; children = ( A1D060C7FA4F15BC07B9C71EF1B5B91C /* Info.plist */, C34BF5CCAF6CC03BF645C76B848286D8 /* MJExtension.modulemap */, 04791F30EB17FA5F95CCE83E1EC06C5A /* MJExtension.xcconfig */, 1B82339D1E8C4BE689DDD67A528D77FF /* MJExtension-dummy.m */, 27FD06D92698931BEEBB79F967135D8C /* MJExtension-prefix.pch */, 91A4C2A30C90A73B281741E7282FA276 /* MJExtension-umbrella.h */, ); name = "Support Files"; path = "../Target Support Files/MJExtension"; sourceTree = ""; }; 24E906343C3D913A1424BAD03A40A862 /* Security */ = { isa = PBXGroup; children = ( CC607CF5B5D9B3420B30AA34AA024E44 /* AFSecurityPolicy.h */, FB8CEF4CEDA5F903EFD528676610423C /* AFSecurityPolicy.m */, ); name = Security; sourceTree = ""; }; 27CEF9C34142EF94C10256EA61BF2103 /* SDWebImage */ = { isa = PBXGroup; children = ( 19A4B5EF16AD928363E1F8C9BCC77434 /* Core */, FC309676B230757BCD55F90EF979186A /* Support Files */, ); path = SDWebImage; sourceTree = ""; }; 30A75A9231556D0EABE7C433059A29DC /* iOS */ = { isa = PBXGroup; children = ( E186E931D518F5F01762FEACCE1188D9 /* CoreGraphics.framework */, A31F38BDCBF968F1FE983012F29A1D1B /* Foundation.framework */, 4A47E80BB0414B90A81EAEFA3F6D9239 /* ImageIO.framework */, C30356461CD94DCCEB2CA832125EFDC4 /* MobileCoreServices.framework */, 9AE98AF69BAD8F07BB16232D800176C8 /* QuartzCore.framework */, E9022EE9051D51B98121F849F4769EE2 /* Security.framework */, 0EBF5ED419CFAF406CAB22FC12D646EE /* SystemConfiguration.framework */, 7AFAB896F150D62C666F8599CF7C13AC /* UIKit.framework */, ); name = iOS; sourceTree = ""; }; 30A99B751B6CE99D15588A49C58CF7EC /* Support Files */ = { isa = PBXGroup; children = ( 951959C78934236EBF5CD3C36F733FCC /* Info.plist */, B5CCA305F7FAD724BA8C81AE7C18BDA7 /* NJKWebViewProgress.modulemap */, A1DF584D946B78214595DA9CBCB0E938 /* NJKWebViewProgress.xcconfig */, ECB9285932E9DF2DD113CB88004F8A48 /* NJKWebViewProgress-dummy.m */, 9BC995660210D5DE77B68627738CBAF0 /* NJKWebViewProgress-prefix.pch */, 64BB381E9FC1EB317BD2DB17212FBB4E /* NJKWebViewProgress-umbrella.h */, ); name = "Support Files"; path = "../Target Support Files/NJKWebViewProgress"; sourceTree = ""; }; 414501B168AF288C6754125576401A60 /* NJKWebViewProgress */ = { isa = PBXGroup; children = ( C42E52EFFB1970E6E90F8FD5666912AA /* Core */, 035EA1098AD97B414DF3D2AD09947173 /* ProgressView */, 30A99B751B6CE99D15588A49C58CF7EC /* Support Files */, ); path = NJKWebViewProgress; sourceTree = ""; }; 4520E585A5562A5F017A51195818E02C /* Pods */ = { isa = PBXGroup; children = ( DE0BCB693B01DB277AAF930158E42517 /* AFNetworking */, 10416184854FD41D94849BB2B1D40142 /* DACircularProgress */, 8A00A02031E9754C50BF0A6EC0671101 /* MJExtension */, 8FFBB2344146495C4C7142EFA27769F8 /* MJRefresh */, 414501B168AF288C6754125576401A60 /* NJKWebViewProgress */, FFC3B531FB4F6F24825B5A555A0AFE6F /* ReactiveCocoa */, 6DB739B824B584412FC4A1F47EEC3326 /* Result */, 27CEF9C34142EF94C10256EA61BF2103 /* SDWebImage */, 69C69B4343629F93A0AFCA4945F8084C /* SVProgressHUD */, 8F5EE05597A20DB22DD369B20C322B64 /* UMengSocial */, ); name = Pods; sourceTree = ""; }; 4F5133CB2DB2CEE4A35B2D2AA246B36C /* Support Files */ = { isa = PBXGroup; children = ( 44EF620D15E9F97CBEA8FF45B112E6ED /* Info.plist */, FA4100EF250D4DDD7C65BEBE719E943A /* SVProgressHUD.modulemap */, E81AB1499B5BC494FB166DC100E727D2 /* SVProgressHUD.xcconfig */, 470BF47D43361B7ABCAD26320AD329A3 /* SVProgressHUD-dummy.m */, 437E022A46A480754C54F00725EAFB64 /* SVProgressHUD-prefix.pch */, AA9C03D203D73109E5356C40978B6837 /* SVProgressHUD-umbrella.h */, ); name = "Support Files"; path = "../Target Support Files/SVProgressHUD"; sourceTree = ""; }; 5A65C831AECFF8484EFEF4FDA6D0AA8A /* Support Files */ = { isa = PBXGroup; children = ( D3DFE9D8C8B7B5975B79A3ED6CD36509 /* Info.plist */, 962469AB44C0A99BBC308F1885FD3448 /* ReactiveCocoa.modulemap */, 48974FB2D05D403AEF69BFCC9EB4EBF3 /* ReactiveCocoa.xcconfig */, 94645B657EE6D5FF0163C672CB64099E /* ReactiveCocoa-dummy.m */, DA1B4DF6E7E13554316A8775838EC8A6 /* ReactiveCocoa-prefix.pch */, D310D5AB2204F87230BFC6C3C9B0134E /* ReactiveCocoa-umbrella.h */, ); name = "Support Files"; path = "../Target Support Files/ReactiveCocoa"; sourceTree = ""; }; 5CAD5D7399A454CAB6C06438A3560148 /* Resources */ = { isa = PBXGroup; children = ( 665FD1AEECD5FFCFCE9EB168AEC03E6F /* SVProgressHUD.bundle */, ); name = Resources; sourceTree = ""; }; 61689670790DE787983EC871AFD9AD8F /* UIKit */ = { isa = PBXGroup; children = ( 657579FA1269B3702EB29DA0B5E20336 /* AFAutoPurgingImageCache.h */, 83D878636318BC9BC302D1BA76A4CC46 /* AFAutoPurgingImageCache.m */, FDE6FE508EE14BE865B0AED358D641BB /* AFImageDownloader.h */, 4368C683284C961AA2A8FB0F7BD9DBF8 /* AFImageDownloader.m */, 3ECE5AD23F674D5730471BE3A13366F8 /* AFNetworkActivityIndicatorManager.h */, 2163FDD9A29250721D08889D6226D26C /* AFNetworkActivityIndicatorManager.m */, 5CFB09319D3043B97E87098173ACB6A3 /* UIActivityIndicatorView+AFNetworking.h */, 8F6E24019AF1B2A6251029C2F9F1C101 /* UIActivityIndicatorView+AFNetworking.m */, 7D0D354758AEE84330634F2194E38953 /* UIButton+AFNetworking.h */, 85E976B9474660285C492769605631FA /* UIButton+AFNetworking.m */, 04C7E2FB01F5334FA335665D00EF1375 /* UIImage+AFNetworking.h */, 3F8C104E2ECD5DAA7DF07B8AF6DC4E7C /* UIImageView+AFNetworking.h */, 81385A2C31D5D660F1189632254CB601 /* UIImageView+AFNetworking.m */, 7762D610F1224AB1BA7F5CE589B317F1 /* UIKit+AFNetworking.h */, A9A24C7194EB1F183CE6B4C9AE06AD99 /* UIProgressView+AFNetworking.h */, BA49143A92AE77748413FEEE2654B389 /* UIProgressView+AFNetworking.m */, 65F5B35589F9DB55205F95B1029703C4 /* UIRefreshControl+AFNetworking.h */, FCCD810BBA0A1C5CBD98C80A0740A751 /* UIRefreshControl+AFNetworking.m */, 647B1602B2F0939011C20E21D90DCA51 /* UIWebView+AFNetworking.h */, 000949CDEA7AFB499C89010D145F3459 /* UIWebView+AFNetworking.m */, ); name = UIKit; sourceTree = ""; }; 69C69B4343629F93A0AFCA4945F8084C /* SVProgressHUD */ = { isa = PBXGroup; children = ( C16C390DA92494698A0B5A96D2E0BDF1 /* SVIndefiniteAnimatedView.h */, 201A7F251D317877BB1F942144C004A3 /* SVIndefiniteAnimatedView.m */, 4B0FC659831F2AF2F86179BC38BE9888 /* SVProgressHUD.h */, 34FF21EEA83A4B4C2E956BB8ADC79804 /* SVProgressHUD.m */, D0BA0F92F89081D2609638A9895AB503 /* SVRadialGradientLayer.h */, 7094B67ADA79A207B80ED1C678096C56 /* SVRadialGradientLayer.m */, 5CAD5D7399A454CAB6C06438A3560148 /* Resources */, 4F5133CB2DB2CEE4A35B2D2AA246B36C /* Support Files */, ); path = SVProgressHUD; sourceTree = ""; }; 6DB739B824B584412FC4A1F47EEC3326 /* Result */ = { isa = PBXGroup; children = ( BB8CB0F2BBB3216F8BC69ABD64494045 /* Result.swift */, D79EB7D14F41D48652E69458403F4457 /* ResultType.swift */, 16CCE631D181C9BC6F8F1784A7A4312E /* Support Files */, ); path = Result; sourceTree = ""; }; 6FC1A2869FDA3A940401A05F15D65C50 /* Resources */ = { isa = PBXGroup; children = ( 8DF2A484755B6BFAB3DD9E8749E0E32A /* MJRefresh.bundle */, ); name = Resources; sourceTree = ""; }; 75D98FF52E597A11900E131B6C4E1ADA /* Pods */ = { isa = PBXGroup; children = ( E8446514FBAD26C0E18F24A5715AEF67 /* Info.plist */, 79A9DEDC89FE8336BF5FEDAAF75BF7FC /* Pods.modulemap */, D0405803033A2A777B8E4DFA0C1800ED /* Pods-acknowledgements.markdown */, 87B213035BAC5F75386F62D3C75D2342 /* Pods-acknowledgements.plist */, 894E5DA93A9F359521A89826BE6DA777 /* Pods-dummy.m */, E7F21354943D9F42A70697D5A5EF72E9 /* Pods-frameworks.sh */, CBC0F7C552B739C909B650A0F42F7F38 /* Pods-resources.sh */, 2BCC458FDD5F692BBB2BFC64BB5701FC /* Pods-umbrella.h */, 977577C045EDA9D9D1F46E2598D19FC7 /* Pods.debug.xcconfig */, DA312349A49333542E6F4B36B329960E /* Pods.release.xcconfig */, ); name = Pods; path = "Target Support Files/Pods"; sourceTree = ""; }; 7A77D1FA965B8E01462D754DC1416442 /* Support Files */ = { isa = PBXGroup; children = ( 0A1826FA89F1FDC1F788AD5A5DC5931E /* AFNetworking.modulemap */, B69789BB77F174CEABB55543FDCDCBBD /* AFNetworking.xcconfig */, 2D28CE0133DF0CAD2C661C21BD8804D7 /* AFNetworking-dummy.m */, 81235D80D900A74FD1968D9C6B1C7655 /* AFNetworking-prefix.pch */, 300A322BAF334D1838F5EB0C49CEBDC6 /* AFNetworking-umbrella.h */, 12400663AFAE4279135158CC2CE30B83 /* Info.plist */, ); name = "Support Files"; path = "../Target Support Files/AFNetworking"; sourceTree = ""; }; 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */, C81C6F3DF20B4E6AEA670648484B9F09 /* Frameworks */, 4520E585A5562A5F017A51195818E02C /* Pods */, 05625802EB36799D6A66F9D9600065E8 /* Products */, B7B80995527643776607AFFA75B91E24 /* Targets Support Files */, ); sourceTree = ""; }; 8A00A02031E9754C50BF0A6EC0671101 /* MJExtension */ = { isa = PBXGroup; children = ( 4B7DA8685E9F6509969D1AC3428C9AC1 /* MJExtension.h */, 49FEAB8BBDA81884BB5B3C142A954D81 /* MJExtensionConst.h */, 06B1B1B7E283AD4CEB7C1B2417929E46 /* MJExtensionConst.m */, 0C7A502A4891DEBCB4FCC707DE4681FE /* MJFoundation.h */, 02C9A313B91705AC4C5D0CDCFD20143A /* MJFoundation.m */, D947872ED90AA60B0F658492E4AEC97E /* MJProperty.h */, 1E079EE3DDE330831C21F8180FEF0A0F /* MJProperty.m */, 9A750DFECCFC1702DACB94D6B04486E2 /* MJPropertyKey.h */, AA50E3F6E4BFEC14F9568DF42598C79D /* MJPropertyKey.m */, 2AD56469E8EF363D5728F35AFF09628D /* MJPropertyType.h */, B4B17DECE01AAC9BA272506436DE73FF /* MJPropertyType.m */, E66CAF5003E9213A4537D17DF0140B4D /* NSObject+MJClass.h */, D09C25D5FC16E6F61F1AA912B9A39B65 /* NSObject+MJClass.m */, 085980395FF6AC05DA09B11655E637FA /* NSObject+MJCoding.h */, 2E9E45A488ECF89F98B18D04BA6C46BF /* NSObject+MJCoding.m */, C44B145F63067DA65072538D023F78C9 /* NSObject+MJKeyValue.h */, E2B6F1FAA9D6337E9009E98F903961E3 /* NSObject+MJKeyValue.m */, 65A88C62ACB26C7993D78A9751E7C43E /* NSObject+MJProperty.h */, 02E1B6AA6AA6390F3F754295B465C3A7 /* NSObject+MJProperty.m */, 91E412FCE5D6DD365C60CB8076F60FF3 /* NSString+MJExtension.h */, 1C4DB204F82A21C053C14A75D8A2253D /* NSString+MJExtension.m */, 1D8123D14ADB51DABCCC0B97626935F3 /* Support Files */, ); path = MJExtension; sourceTree = ""; }; 8F5EE05597A20DB22DD369B20C322B64 /* UMengSocial */ = { isa = PBXGroup; children = ( 255FD6ED59CC3DF6C897A751AA4A3371 /* APOpenAPI.h */, DC7B18D7C2CA308A468FD2D083CEEB0A /* APOpenAPIObject.h */, C6AE4F60540D6788200F546AF6F8431A /* UMSocial.h */, FB659CCBAA26184991F162A631D1674B /* UMSocialAccountManager.h */, 150227C4D00F0EC7F13BBB5EE273B707 /* UMSocialAlipayShareHandler.h */, 69325818E2697FC23FBCBC49ED966437 /* UMSocialBar.h */, 59F7AB9A67264A98A676B0AD2F4CC4D3 /* UMSocialConfig.h */, 8FDD15F4292E86F2B50815F0697C4DAB /* UMSocialControllerService.h */, 6A0C7C592DBC93BCC8F09A5FD589C92A /* UMSocialControllerServiceComment.h */, 05B12FA0E0FAB888F4A96E62780AE0FB /* UMSocialData.h */, 5631B7A82C687959FE85664EC5C9473E /* UMSocialDataService.h */, 478A7113A4700506C8345783A2E0D02B /* UMSocialFacebookHandler.h */, 7699487F8E111F337425EA20CA75C6BC /* UMSocialInstagramHandler.h */, 4A4EBDA864BE36414BFF88BD8F686033 /* UMSocialLaiwangHandler.h */, 5BF6AE1FDCE77051A8C839CED59BB34D /* UMSocialLineHandler.h */, 2E2E58931A4E5052311F3883A191B2BE /* UMSocialQQHandler.h */, 595A5A876B3C808F023DC56B4B96D198 /* UMSocialSinaHandler.h */, C1F8238C534EF89A54816DB436C8853D /* UMSocialSinaSSOHandler.h */, F3CC7C65E6195DE0F13C516AA3B7CD19 /* UMSocialSnsData.h */, 08B291FA25C28B624B02BDADA44546F6 /* UMSocialSnsPlatformManager.h */, BE52FC1BA382E1B3451103330DC78B99 /* UMSocialSnsService.h */, 43B2555C309E0CF30EAF226C769EA1FA /* UMSocialTumblrHandler.h */, B146CE257A00226824E49ECF3C629F4F /* UMSocialTwitterHandler.h */, FB35F887EFA3E741160AF6B1C118B082 /* UMSocialWechatHandler.h */, 94A82F40FBE3032EF7B279257D1620D9 /* UMSocialWhatsappHandler.h */, 2457232127A191B824275DF0FFD5E159 /* WBHttpRequest.h */, 2A96124D03EBB27BFF5CEA0256356CD8 /* WBHttpRequest+WeiboGame.h */, 045F7E40F91896E7BE7FD6A45C0D6947 /* WBHttpRequest+WeiboShare.h */, 243D9C27745BC9586B92EBB5A67F296A /* WBHttpRequest+WeiboToken.h */, E5F0B5EED1468E45BF3B9E55D0921211 /* WBHttpRequest+WeiboUser.h */, 43F7462D2BD9A5A5B1F5C60FA43E0036 /* WBSDKBasicButton.h */, 546A223BCB351F8EE7D67820F6ED34BB /* WBSDKCommentButton.h */, 25F86FA19738CEA4C142BB2B35A7F8EF /* WBSDKRelationshipButton.h */, 465941E4DC4A34F2B7FEBBA369329062 /* WeiboSDK.h */, 4BB03C64E18C548BBB12543740048695 /* WeiboUser.h */, 7E94EF582B3E464F2BEA71C5346895AC /* WXApi.h */, 081A9360B5E6C2BFED633BA37FB21586 /* WXApiObject.h */, A680E3FA3C23CC5D14253787AFBF782B /* Resources */, ); path = UMengSocial; sourceTree = ""; }; 8FFBB2344146495C4C7142EFA27769F8 /* MJRefresh */ = { isa = PBXGroup; children = ( 6587A73A29A00806426C245D436CC4DB /* MJRefresh.h */, B5516D92939621BD471E86FDA40744D6 /* MJRefreshAutoFooter.h */, 665306F25921CE243C77B2179A928FC6 /* MJRefreshAutoFooter.m */, 93C4F71361B0469BE16C31AB9579776F /* MJRefreshAutoGifFooter.h */, 701745585DCF4B7F3AD5CA8E9A3283E6 /* MJRefreshAutoGifFooter.m */, 6F40BC006E0930A50E0266C73DA609FE /* MJRefreshAutoNormalFooter.h */, B8D50A20C640AA87771EF793A3B33D58 /* MJRefreshAutoNormalFooter.m */, FD9BF1E603B15AF71FFFCB71245E0CAB /* MJRefreshAutoStateFooter.h */, BC76762C8413ACAEF0462E770E5BADE3 /* MJRefreshAutoStateFooter.m */, 779C75D5D0D23A1AB35ECFF926AAD43E /* MJRefreshBackFooter.h */, BB4A068D4F391DFF007C5E826F88C673 /* MJRefreshBackFooter.m */, 8D10AD9F1ACB5CD9CA679673D87F616C /* MJRefreshBackGifFooter.h */, 3A2021E9945FEF95138597F73185383E /* MJRefreshBackGifFooter.m */, 760C68EEB4C3B3288B8D028C95AF4A5B /* MJRefreshBackNormalFooter.h */, 8F26B0A5160BB003B5AA2DEE23E1CF27 /* MJRefreshBackNormalFooter.m */, 327D589BF0F977BFF88D99840464BD9B /* MJRefreshBackStateFooter.h */, D5C99DD591CB596FCA58275314A1283F /* MJRefreshBackStateFooter.m */, 030BE5B2566DC2DE1DF6C75DF5014D4E /* MJRefreshComponent.h */, 9A7B5DD43A49B31BDAEEA9D8A50D6DDF /* MJRefreshComponent.m */, 9DD9D6B81C51F4F24E457F66295A90AE /* MJRefreshConst.h */, D394875D112D2406E07D6783972EAA9E /* MJRefreshConst.m */, F0D450CC9C0FF76EC8DD1E7380FB0A6F /* MJRefreshFooter.h */, D30739FD0BBBC87DCA328AB763D58A85 /* MJRefreshFooter.m */, 7DE1DF3A1C8F5A26C0E0C151BCCB8E40 /* MJRefreshGifHeader.h */, 8858F9E080A925223FA42F75EE78F6A8 /* MJRefreshGifHeader.m */, 287EEB49D92EC73042E3C0D5A7376FFF /* MJRefreshHeader.h */, A19678BE408B5098995BFB18144274C9 /* MJRefreshHeader.m */, DE3CAA2C90009AB04A9C1A9233566CA0 /* MJRefreshNormalHeader.h */, 827EE8470BA8113E1D08BA60A9DB4AE4 /* MJRefreshNormalHeader.m */, 9BA3B0CDC3DFF8020BE9CF970087F087 /* MJRefreshStateHeader.h */, 24AC80CE0FB0E80AF69BF07269013518 /* MJRefreshStateHeader.m */, 1AC9A7040E9A886D917833A5E38B4494 /* UIScrollView+MJExtension.h */, A1061C71204A323EDD42383C339969CB /* UIScrollView+MJExtension.m */, A09567EF6A6A8400BEC6E81380B768F6 /* UIScrollView+MJRefresh.h */, A6BEE214C0861CABFEC4A99A3E61A6C2 /* UIScrollView+MJRefresh.m */, 8A9D916B5F5972DEC7187DC4C1A69560 /* UIView+MJExtension.h */, F0D1B728EB6048D8D5B0AC2D40EC9E40 /* UIView+MJExtension.m */, 6FC1A2869FDA3A940401A05F15D65C50 /* Resources */, A2C292C95C910CE51462A21CC6E58B38 /* Support Files */, ); path = MJRefresh; sourceTree = ""; }; 946DEBAC2F979A510AB5C0ED719EA21F /* Support Files */ = { isa = PBXGroup; children = ( 72C090B30816C4545F44566AF6DA4DB5 /* DACircularProgress.modulemap */, B20C17CD12A642AE53D6EB41DADC0F2B /* DACircularProgress.xcconfig */, 3D433893D61787615D32A3BB9DA9D51A /* DACircularProgress-dummy.m */, 687CFE33E261EA13466B67A115B31C17 /* DACircularProgress-prefix.pch */, 9FE8F3328FD5DA10E662D3E3612E892E /* DACircularProgress-umbrella.h */, 83CDCC039BDE0A01444E5637C01D5AB3 /* Info.plist */, ); name = "Support Files"; path = "../Target Support Files/DACircularProgress"; sourceTree = ""; }; 9C2D1DB4C0EC57338B3A72B5DBD9531A /* Reachability */ = { isa = PBXGroup; children = ( E02EC8F52BB28C3F34F78F3034DB4B0A /* AFNetworkReachabilityManager.h */, 6D380A4F4137C3191AC8C38C3844F6F9 /* AFNetworkReachabilityManager.m */, ); name = Reachability; sourceTree = ""; }; A2C292C95C910CE51462A21CC6E58B38 /* Support Files */ = { isa = PBXGroup; children = ( A7B9D2E1FF56188A82EB12A38064A264 /* Info.plist */, 80E7DDD0E7E084DAF534D6B073631BB2 /* MJRefresh.modulemap */, E5CD8F5EBE3094663634930E490C7286 /* MJRefresh.xcconfig */, 23EC168D4DE256790968AF644F46052A /* MJRefresh-dummy.m */, B07B1BE566B8C25733CCFC2905C60E92 /* MJRefresh-prefix.pch */, B26C89BAEA96E55DC008D427750C820E /* MJRefresh-umbrella.h */, ); name = "Support Files"; path = "../Target Support Files/MJRefresh"; sourceTree = ""; }; A680E3FA3C23CC5D14253787AFBF782B /* Resources */ = { isa = PBXGroup; children = ( EBCA2833B9CE5CDF9FF6D8991B9E0455 /* en.lproj */, 017F6516B54EC1196D28908E8C6EA8D4 /* TencentOpenApi_IOS_Bundle.bundle */, B61855E7AF94D92A56B2E5742C24E5DD /* UMSCommentDetailController.xib */, 693263AF622FE0B5862A74F23A9332D1 /* UMSCommentInputController.xib */, 26D3111BD2C1AEE320FE04F08468F1B4 /* UMSCommentInputControlleriPad.xib */, FBDDFA23D0529AD6C9280D6CEBB943E5 /* UMShareEditViewController.xib */, 227C76A819C4FFC8125A8C3D0DFCD049 /* UMShareEditViewControlleriPad.xib */, 0673809329E6ADFE94FC8615FD00A33A /* UMSLoginViewController.xib */, F881DF03DBE295AF59B1CF9B9E6DC007 /* UMSnsAccountViewController.xib */, 93375D6B669C56C745FB6849F302058B /* UMSocialSDKResourcesNew.bundle */, 1398A95C37D93AD7F730390712926A23 /* UMSShareListController.xib */, CA69C4C7C21FC84A6C3ACDDAF6AE98A4 /* WeiboSDK.bundle */, EF82F55068FEFF3AEA0F3E84A46183E1 /* zh-Hans.lproj */, ); name = Resources; sourceTree = ""; }; B7B80995527643776607AFFA75B91E24 /* Targets Support Files */ = { isa = PBXGroup; children = ( 75D98FF52E597A11900E131B6C4E1ADA /* Pods */, ); name = "Targets Support Files"; sourceTree = ""; }; C42E52EFFB1970E6E90F8FD5666912AA /* Core */ = { isa = PBXGroup; children = ( B3A6E8E3B715B4995F7DEE5A5FDF8EDE /* NJKWebViewProgress.h */, 3FE3B9592D5E80C0D98EB8611F9F7F05 /* NJKWebViewProgress.m */, ); name = Core; sourceTree = ""; }; C81C6F3DF20B4E6AEA670648484B9F09 /* Frameworks */ = { isa = PBXGroup; children = ( 1FC2184908F405511534A14E70D16DAF /* Result.framework */, 30A75A9231556D0EABE7C433059A29DC /* iOS */, ); name = Frameworks; sourceTree = ""; }; D408DEE0DDD0ACC4D78E546BEEE2C1F2 /* Serialization */ = { isa = PBXGroup; children = ( B1E666B007C5C55BDB7AA3FB5D798960 /* AFURLRequestSerialization.h */, F04C630FB7E53F60E360F879CBE5F7D9 /* AFURLRequestSerialization.m */, 4ADCC2A12D303D037DAF0853CCA30850 /* AFURLResponseSerialization.h */, 4F2AD288D4DCF53E728C1A1466A87875 /* AFURLResponseSerialization.m */, ); name = Serialization; sourceTree = ""; }; DE0BCB693B01DB277AAF930158E42517 /* AFNetworking */ = { isa = PBXGroup; children = ( C1E1D8502CC717DA524B7E464CFA9D60 /* AFNetworking.h */, FB8B96B4F52AE817153975E3A0CAB48B /* NSURLSession */, 9C2D1DB4C0EC57338B3A72B5DBD9531A /* Reachability */, 24E906343C3D913A1424BAD03A40A862 /* Security */, D408DEE0DDD0ACC4D78E546BEEE2C1F2 /* Serialization */, 7A77D1FA965B8E01462D754DC1416442 /* Support Files */, 61689670790DE787983EC871AFD9AD8F /* UIKit */, ); path = AFNetworking; sourceTree = ""; }; EE7017A1B4AAA75BFF03B90AEADF113E /* UI */ = { isa = PBXGroup; children = ( A4BFD7235669DFC6C5F8A7CA037E2BB0 /* MKAnnotationView+RACSignalSupport.h */, A824F0BE4B5F3D459BAD005E6212EA0B /* MKAnnotationView+RACSignalSupport.m */, 5C3A4E7DDAA72BBF33F0FBB6D4C26C07 /* ReactiveCocoa.h */, A9F89340C49BD17D20E0A729312481FD /* UIActionSheet+RACSignalSupport.h */, 429BA83EA95D1725559EFE5276560A3D /* UIActionSheet+RACSignalSupport.m */, 4F84DC6C0850AC07A1B378574B872FF1 /* UIAlertView+RACSignalSupport.h */, 3E025561039B8FAD2BF3E4DFD1400ED9 /* UIAlertView+RACSignalSupport.m */, 4D9AD3CBF51B0E685856C97780A563F5 /* UIBarButtonItem+RACCommandSupport.h */, 6AB4385785B935EEAF37EFC56F267112 /* UIBarButtonItem+RACCommandSupport.m */, 8E82D8F966DFF2EDFECC4638BB6E2390 /* UIButton+RACCommandSupport.h */, E00F85DF61A097080D9B006A42852B08 /* UIButton+RACCommandSupport.m */, 5A80F20F9A079897F7763E34E2C5597E /* UICollectionReusableView+RACSignalSupport.h */, F837CA4A39C79C92F66C2AC2957863E3 /* UICollectionReusableView+RACSignalSupport.m */, 873D1ADD735B27286236748899F7921F /* UIControl+RACSignalSupport.h */, 1E2982CC1BE3091121DC05292B2FDC00 /* UIControl+RACSignalSupport.m */, 85FF1DEBB8560D116AE8785E3D9500ED /* UIControl+RACSignalSupportPrivate.h */, 3C32EE2F3025F97F3982477A027FD6DE /* UIControl+RACSignalSupportPrivate.m */, 2566085556C7C46E97B0513F6A39D71B /* UIDatePicker+RACSignalSupport.h */, 81D25D4F4D6B7D02E21F5C8C0BB43218 /* UIDatePicker+RACSignalSupport.m */, E4BE7396A99977EA27137A889AB23A82 /* UIGestureRecognizer+RACSignalSupport.h */, F398BCA5C354DE916BE3F66F46468339 /* UIGestureRecognizer+RACSignalSupport.m */, 184550CBD6D9758741E5C62753EBA270 /* UIImagePickerController+RACSignalSupport.h */, 487C7B37C3A3AE467452EB40973AB2E3 /* UIImagePickerController+RACSignalSupport.m */, 7304BB1549A9A2B972545AEAD38EC23B /* UIRefreshControl+RACCommandSupport.h */, 19857320382C3934D1AA924AC1C439BF /* UIRefreshControl+RACCommandSupport.m */, 089193F3B7A92B972D1332D86CC8A3D8 /* UISegmentedControl+RACSignalSupport.h */, 08657BE6CE5968B484BCDC9708782CD9 /* UISegmentedControl+RACSignalSupport.m */, B59240F4E6C2D09A8AECBE4EB339E04D /* UISlider+RACSignalSupport.h */, 14B5A6DBE283E02BB4999634060D8117 /* UISlider+RACSignalSupport.m */, 67A6E7EE4BABE5B9C6F5BC0A445F4BF5 /* UIStepper+RACSignalSupport.h */, CFF28FD09E7B21D2B491C785A9F1752F /* UIStepper+RACSignalSupport.m */, A6B443A889FFE21F2568DF7F9051B834 /* UISwitch+RACSignalSupport.h */, 87D85553FDF0A6201B95EB15FD0276BE /* UISwitch+RACSignalSupport.m */, 70335EEB3F3ED4753931F862F6AE2D4C /* UITableViewCell+RACSignalSupport.h */, FA8F7C14656D9F2B06C707A058346B31 /* UITableViewCell+RACSignalSupport.m */, 8D181778EACAB30C2DF3EB81AFCC312D /* UITableViewHeaderFooterView+RACSignalSupport.h */, 8C179B4B0A25E2587F438F48E729F964 /* UITableViewHeaderFooterView+RACSignalSupport.m */, E73089F923B47D3893EED446E53C7E28 /* UITextField+RACSignalSupport.h */, 0D0C2271A31DC0318C3F599828368EED /* UITextField+RACSignalSupport.m */, A9964D7562908E51C1C056A746B0AE49 /* UITextView+RACSignalSupport.h */, 2571CE5A2B6427EE7C1CD76E1A71FE5F /* UITextView+RACSignalSupport.m */, ); name = UI; sourceTree = ""; }; FB8B96B4F52AE817153975E3A0CAB48B /* NSURLSession */ = { isa = PBXGroup; children = ( CC43C0D25552A4CC426C3FCF6371BF12 /* AFHTTPSessionManager.h */, B7C4539ED08962A5251CFBC170F4E5B1 /* AFHTTPSessionManager.m */, F58E4B445DAA8708DBC10F3116C81417 /* AFURLSessionManager.h */, 0C887DA74F733F87971CCE2DC0A90581 /* AFURLSessionManager.m */, ); name = NSURLSession; sourceTree = ""; }; FC309676B230757BCD55F90EF979186A /* Support Files */ = { isa = PBXGroup; children = ( C81BBE1B6B6942EA554D22570C8EF8F3 /* Info.plist */, EBD8EC21AF605F5B2C221E911F03A04E /* SDWebImage.modulemap */, 64B2BBC280624DAA5159807DD47EDA7C /* SDWebImage.xcconfig */, 74CC208244E551D18584AE550743152D /* SDWebImage-dummy.m */, 0D57074F48179390AA303927C134EE2C /* SDWebImage-prefix.pch */, C8EDB2613EF74A96A98805E88478BA6A /* SDWebImage-umbrella.h */, ); name = "Support Files"; path = "../Target Support Files/SDWebImage"; sourceTree = ""; }; FFC3B531FB4F6F24825B5A555A0AFE6F /* ReactiveCocoa */ = { isa = PBXGroup; children = ( 19FCDF91704DF91A3629B5A077295357 /* Core */, 1758D09ECAB283AE1B67EE88C5AA6A28 /* no-arc */, 5A65C831AECFF8484EFEF4FDA6D0AA8A /* Support Files */, EE7017A1B4AAA75BFF03B90AEADF113E /* UI */, ); path = ReactiveCocoa; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 1EE53E0729698439B9B5D574F56FFA25 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( B92B9E7F4DC2ACAE1148554AD22C7B01 /* Pods-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 22DDE9A4759D6D82E423746B199E4FD4 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 3A4577E765151065542A2FE61049AEB6 /* NSData+ImageContentType.h in Headers */, D8D832C26EFBE040BE6C23F1121B1945 /* SDImageCache.h in Headers */, F49F1264B4611318E830BEE2F56918CE /* SDWebImage-umbrella.h in Headers */, 9ACB2C22B46D4A8A80A0B5591B4240E1 /* SDWebImageCompat.h in Headers */, 5DE3DFFCB8D5FDE635632112A4E0F005 /* SDWebImageDecoder.h in Headers */, ED004EB9D9F0AD265FB04088DF40F4F2 /* SDWebImageDownloader.h in Headers */, B01B7989C730E6B8D0FC189379C8829B /* SDWebImageDownloaderOperation.h in Headers */, 2A86D12018C01DEA1A0A652CEAA8A60F /* SDWebImageManager.h in Headers */, 5023BE708F043790DC1EEE1C1FD82C65 /* SDWebImageOperation.h in Headers */, BDE21C4F50664111E97A27C07842D0F6 /* SDWebImagePrefetcher.h in Headers */, F877A6DAE2F8D2F9170474700EFD5603 /* UIButton+WebCache.h in Headers */, E603DFF6866D326AE8BCF8D75E4A01AC /* UIImage+GIF.h in Headers */, 9F720D7EB674C321DA30F74FED315FA3 /* UIImage+MultiFormat.h in Headers */, B4298E9294D5BED493FD436EFB68C84A /* UIImageView+HighlightedWebCache.h in Headers */, B9D9121C3E99742689213EE0A5CA943A /* UIImageView+WebCache.h in Headers */, B8FF0B1C5F3D57D704C48DECE022E1CE /* UIView+WebCacheOperation.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 4C2D46665A289FB0E196AD3D28D92954 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 0C81071CF813878A9947510748992FC2 /* Result-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 4CBF24217076736867211BCB7ECB30E4 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 7DAE8A60D7FF35905A1199C13ADF1334 /* EXTKeyPathCoding.h in Headers */, 6B4898BC56C3A781EEE21E2ABE0E4E62 /* EXTRuntimeExtensions.h in Headers */, 98B00B62E980F6C474D221C5F120E7D6 /* EXTScope.h in Headers */, D9B2CB5E6AB64E0D92B89E7B29B3A6A3 /* metamacros.h in Headers */, 5E19E6D0B84161D5C1D91C1B3102D3C1 /* MKAnnotationView+RACSignalSupport.h in Headers */, 0497875A83FEFFE6FA8C21190B15FE24 /* NSArray+RACSequenceAdditions.h in Headers */, 731D869357FE82DBEA18142155FA5334 /* NSData+RACSupport.h in Headers */, FE96A3DA7D324EF1AEA9A099B977848A /* NSDictionary+RACSequenceAdditions.h in Headers */, 04D1F0C5715EBF0DA0A59B8C80D7B4D3 /* NSEnumerator+RACSequenceAdditions.h in Headers */, 8B5CF5758057EA65EAF8D83BBDCD2970 /* NSFileHandle+RACSupport.h in Headers */, 5BAF5BDEF5580DF0D6D3BE4BA9F50C08 /* NSIndexSet+RACSequenceAdditions.h in Headers */, B5ACB9544A28B944C634FB6432AA18F2 /* NSInvocation+RACTypeParsing.h in Headers */, 670BE350467C2B2DA70FEA66DB726475 /* NSNotificationCenter+RACSupport.h in Headers */, 511FD83A2DFE095A686E38263A7070F6 /* NSObject+RACDeallocating.h in Headers */, E4D2FB975E5C435F4D758B06AC530744 /* NSObject+RACDescription.h in Headers */, AFC9968F21AF2109C71F534C32AE3D49 /* NSObject+RACKVOWrapper.h in Headers */, 2E10FBB442212F0FACF0A2B3E7AE6495 /* NSObject+RACLifting.h in Headers */, 521D09952B30FFC7243BE3F320E37EB8 /* NSObject+RACPropertySubscribing.h in Headers */, 71B8F18B3823DAF8C6183EC3A1D0519A /* NSObject+RACSelectorSignal.h in Headers */, 62496692FFE6DC75E13074AB607992A5 /* NSOrderedSet+RACSequenceAdditions.h in Headers */, F0ACC773C5671197A4322ED45F40B117 /* NSSet+RACSequenceAdditions.h in Headers */, 79D1BB6E7BA2EF1E1388F39F7BFD8D48 /* NSString+RACKeyPathUtilities.h in Headers */, 081E72BFD20CC752979F2FA5FA0A9C42 /* NSString+RACSequenceAdditions.h in Headers */, E74D191277E0920749063EBE80FE4CE6 /* NSString+RACSupport.h in Headers */, 129CB9A6396C5E3D0404A2993BDFA089 /* NSURLConnection+RACSupport.h in Headers */, 92C8799C7DDCDFBB08FCD3445950E8A7 /* NSUserDefaults+RACSupport.h in Headers */, FDCAA63373782AB405AFD4716FE32F02 /* RACArraySequence.h in Headers */, 2B46C2FC31AD47B30D1F4D26E9F23318 /* RACBehaviorSubject.h in Headers */, C703739EA6DBB2B29230A9F6386D7140 /* RACBlockTrampoline.h in Headers */, 61305CCB40A29FF26DAF1C011ED8155B /* RACChannel.h in Headers */, 12CFBCACB2BCB8BDDA05893B31D87692 /* RACCommand.h in Headers */, F448ADD6D89AEF9B156A18E704713B4F /* RACCompoundDisposable.h in Headers */, 2B432A2CA37699689687A3B625E9C957 /* RACDelegateProxy.h in Headers */, F3ED07928731E8E005504139177DBB8B /* RACDisposable.h in Headers */, A8D1C2B2AD592CCE2776BC404E5C74CD /* RACDynamicPropertySuperclass.h in Headers */, 5289231C360AA65EB109132B58C986A6 /* RACDynamicSequence.h in Headers */, 66C7D6A69FD0247134E6149A6F09D5DC /* RACDynamicSignal.h in Headers */, B4ECCBCCD080040E3DEDF1F66A7AF896 /* RACEagerSequence.h in Headers */, 00724B07B0A479DCD63B547C930BF202 /* RACEmptySequence.h in Headers */, 547CD9A3386E91DAEE0DBFBB8EF0235B /* RACEmptySignal.h in Headers */, CC325F40FB14EC0BB26F853EB9F0C13C /* RACErrorSignal.h in Headers */, 393009168925491E8921A9D528B68A05 /* RACEvent.h in Headers */, F55C8CF969F3FD3BD80555F26AEB5289 /* RACGroupedSignal.h in Headers */, BB55FFD36D685105A750534A4DF0DB02 /* RACImmediateScheduler.h in Headers */, B7D0A5BDD2EA028A51D8A17F1A738969 /* RACIndexSetSequence.h in Headers */, 494D62C84A6BA6EE9AAE3A8AE2A1A3CE /* RACKVOChannel.h in Headers */, 84378F3384B8A8A7D790547418600D1C /* RACKVOProxy.h in Headers */, EE03F4DCA502AA65D27174159582A551 /* RACKVOTrampoline.h in Headers */, A4581B24DDCCDCDA24F4392F0E378E1A /* RACMulticastConnection+Private.h in Headers */, B927754D552A855E288BBF6B56893830 /* RACMulticastConnection.h in Headers */, 36C86787510E3AA04357D7DBCABE25FC /* RACObjCRuntime.h in Headers */, 5A9215CA981A4E85D205898F066F2672 /* RACPassthroughSubscriber.h in Headers */, B21385BDDFE01601BBC8E4EA20DAA481 /* RACQueueScheduler+Subclass.h in Headers */, EDFA4A46C1B346922751E86DE8537CC5 /* RACQueueScheduler.h in Headers */, 95062E558978E16F2F13BB5D665B2C4B /* RACReplaySubject.h in Headers */, AF20359522D1E719FE9B4462D8F2031A /* RACReturnSignal.h in Headers */, F69F3F4018550D6B9F7E3B40B7733F2D /* RACScheduler+Private.h in Headers */, 4287E4DDF78271B6AF8715292D6FC512 /* RACScheduler+Subclass.h in Headers */, AEFB3ADEA9F4FE938ECA832BF2F05F4B /* RACScheduler.h in Headers */, CF1036F4BD25E2E1ED3137287B5394DC /* RACScopedDisposable.h in Headers */, 09F3D0ED576A78F226E6EEC993284BAF /* RACSequence.h in Headers */, 3C0C307560729C357B4AE20D44EE9A42 /* RACSerialDisposable.h in Headers */, 9C3A46A67A2FE2F8E46E18617426453A /* RACSignal+Operations.h in Headers */, FC2E6AF0090625D11944B93E271C21B6 /* RACSignal.h in Headers */, 0E98EC3E7AEA7162CFAE6EF57D2B28AF /* RACSignalSequence.h in Headers */, 70C3C414596FB1C3E21F3C00996F39EF /* RACStream+Private.h in Headers */, 0A8ECD4D136D26E0D73B078DE75BAA2B /* RACStream.h in Headers */, 0FB27BA2048911FE563797AA16E79557 /* RACStringSequence.h in Headers */, 67B59A03535B18CDD348CF3204FCC8CD /* RACSubject.h in Headers */, DADFC17F37F89D6668042A55D1950225 /* RACSubscriber+Private.h in Headers */, D7E5966C32EDC4A86575A3B3EF570ACD /* RACSubscriber.h in Headers */, 1B625386A867038C73A98AF1DA0FB5A5 /* RACSubscriptingAssignmentTrampoline.h in Headers */, E00424EF864015DE51C3ECBF8D676B46 /* RACSubscriptionScheduler.h in Headers */, D57B7D25D8A7A39A84BF9F27200FBD44 /* RACTargetQueueScheduler.h in Headers */, 732A6076A35301AFE02553A38DAEE618 /* RACTestScheduler.h in Headers */, 28F9E23A6D412DF172FD4EEDEC7507A0 /* RACTuple.h in Headers */, 8D2EF02863C819015C4E2CB0871CEA8C /* RACTupleSequence.h in Headers */, 7CFD83CD3C93E655BDBDD20EDBE3AC89 /* RACUnarySequence.h in Headers */, 31F2FDB763BB011A256808751590329E /* RACUnit.h in Headers */, 2ED25110C57F536506C512DC2EAA6F04 /* RACValueTransformer.h in Headers */, 3B8C19501B83034CBD92BC35F32E9B55 /* ReactiveCocoa-Bridging-Header.h in Headers */, 20745870A76E57E9AC3B66605226821F /* ReactiveCocoa-umbrella.h in Headers */, 84310740D64824ED883E984C2D715E8F /* ReactiveCocoa.h in Headers */, 2ED13D4A87D269ADA038C269093F3AE3 /* UIActionSheet+RACSignalSupport.h in Headers */, 76F1DD8C3C209438B307B1D329D54267 /* UIAlertView+RACSignalSupport.h in Headers */, CDFB56B7343AA2F63B0590E077FECD05 /* UIBarButtonItem+RACCommandSupport.h in Headers */, C755E7FA789E3A1EBC477F2096106FB3 /* UIButton+RACCommandSupport.h in Headers */, F8BE146084791BD01DA89B78191CB59A /* UICollectionReusableView+RACSignalSupport.h in Headers */, C9EC67BE9E06CCD7ED3388783D767CFB /* UIControl+RACSignalSupport.h in Headers */, BC119AAAD4BAD26B893AA6E552B8D452 /* UIControl+RACSignalSupportPrivate.h in Headers */, 79AE09A7EA7C916F2249A23AD02A1A9F /* UIDatePicker+RACSignalSupport.h in Headers */, 94BB9BF355B759C0A3B64DC39D3EF053 /* UIGestureRecognizer+RACSignalSupport.h in Headers */, B699EB0285A21875290BD8149C742FCA /* UIImagePickerController+RACSignalSupport.h in Headers */, 6565E06393BF320ABDF8E2F838115A6E /* UIRefreshControl+RACCommandSupport.h in Headers */, 33391B350D746D0ECC0A3E1918A9CEEF /* UISegmentedControl+RACSignalSupport.h in Headers */, B72796279A879D1178B529D14E479EED /* UISlider+RACSignalSupport.h in Headers */, 2304694ADD5E56A50B15A5705A3342A0 /* UIStepper+RACSignalSupport.h in Headers */, B1ACC3AD8AD6262A25054286293843DE /* UISwitch+RACSignalSupport.h in Headers */, 1681F1426F8DB09870F4F2BB8D44F51D /* UITableViewCell+RACSignalSupport.h in Headers */, 41A7867BEFE2E46807C97D08D3C6BF46 /* UITableViewHeaderFooterView+RACSignalSupport.h in Headers */, 5F264302142FCAFE3AC672E773A3A534 /* UITextField+RACSignalSupport.h in Headers */, 33AF5F27C6E285B73FEC9024938A884F /* UITextView+RACSignalSupport.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 4EEA2EBA009A3CCC55611D2D572DFC43 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( EAFCB77D63E5960EB0A7925228A833CF /* MJExtension-umbrella.h in Headers */, 0AB2C696D41303218E29F03493594296 /* MJExtension.h in Headers */, B8F9E818A69721581FB3B1D67678A7BE /* MJExtensionConst.h in Headers */, FA3220E5BF47A4AF0A88802437EA8536 /* MJFoundation.h in Headers */, 293446B78D3872E897C9AAD4798FBA93 /* MJProperty.h in Headers */, B15E465C81F5D9E5888A196B31B25C28 /* MJPropertyKey.h in Headers */, 279A0F937F96FB714A42A09E839EB8C3 /* MJPropertyType.h in Headers */, F3015B3D06F13F36E624A4E8B591E529 /* NSObject+MJClass.h in Headers */, EAE2E750ADDF535A1696470C745C0485 /* NSObject+MJCoding.h in Headers */, 577BEE9E06FE5EC16DDCE8AD88B09979 /* NSObject+MJKeyValue.h in Headers */, 6E62CB71F8583167781294A91D6EA743 /* NSObject+MJProperty.h in Headers */, 7E74E7B68C4D68223728386898038D20 /* NSString+MJExtension.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 5B039065F78D452E6463B4B2038B72A4 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( FF708399B1A87AB052034F635FB70A2A /* DACircularProgress-umbrella.h in Headers */, ABAFA39827840EDE6A4527D2EFDA97E5 /* DACircularProgressView.h in Headers */, 288886A12930E5129511977F8563DA28 /* DALabeledCircularProgressView.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 7C6A0D99A9CC32A19A92A62F8A941139 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( CAC483EF637FB4A2C2E2FC75BA631B87 /* AFAutoPurgingImageCache.h in Headers */, AB39AC9746E7575D7449700475E41B0B /* AFHTTPSessionManager.h in Headers */, 5808B477EFF509D810B5CDCFDC944F80 /* AFImageDownloader.h in Headers */, 1480F4923DBBF217F60572EEECB4027C /* AFNetworkActivityIndicatorManager.h in Headers */, EC7CADE416A78A1CD6936018A6695126 /* AFNetworking-umbrella.h in Headers */, E7988678C81F7CCB95D239375FC6986D /* AFNetworking.h in Headers */, 68152D921ABF6A423C192C04FDF94F0F /* AFNetworkReachabilityManager.h in Headers */, C2DD28375E1F0B1D0D1D2E4E607C499F /* AFSecurityPolicy.h in Headers */, 20EE8030FCF2402DAC7F1C9B9DDAEF79 /* AFURLRequestSerialization.h in Headers */, 7332F15718920917F544F35CE2C038AA /* AFURLResponseSerialization.h in Headers */, 560698A4D707DCBCC1C8F98BC9B89B23 /* AFURLSessionManager.h in Headers */, 1E5B8F12ED7CC40ECDB9B1F755F387E5 /* UIActivityIndicatorView+AFNetworking.h in Headers */, 81B617F8D26BB10C5726D75E85D21EB7 /* UIButton+AFNetworking.h in Headers */, 9E1E90DED74B73ECE53C9AD76DE53E2D /* UIImage+AFNetworking.h in Headers */, 60E3009342BEE96D32C546BE2DB60052 /* UIImageView+AFNetworking.h in Headers */, 659960F7E28E993E08CCC1E8A383E710 /* UIKit+AFNetworking.h in Headers */, D9F4E833E37B611B432F6B5D7072DDA2 /* UIProgressView+AFNetworking.h in Headers */, C6354FEC7728A4C86DAD8092509BA7D4 /* UIRefreshControl+AFNetworking.h in Headers */, AE2A07407FB50BA249984DC0620E84C0 /* UIWebView+AFNetworking.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; B106C9B808F7EB39F2E051B4DD3F452A /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ABE9ACD59269A2BBE000F4667BC8B70A /* NJKWebViewProgress-umbrella.h in Headers */, 42705136A12B109D3390F706FD017D4A /* NJKWebViewProgress.h in Headers */, 7027D9AA84049E1083A7AC48CA979F08 /* NJKWebViewProgressView.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; D981343AF503F433F80E3DB2E576DCCD /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( A535499166018F49DDA66EE7B0A2EBF7 /* MJRefresh-umbrella.h in Headers */, 5936075C0501A4F055261D7641B4F6E9 /* MJRefresh.h in Headers */, 2ABF9BBDAE5215C2FEA04D9F220446EC /* MJRefreshAutoFooter.h in Headers */, 2DE5F9002497B8304F130584A7B8E9BC /* MJRefreshAutoGifFooter.h in Headers */, FA603034F1C2D30DA9D6C5BEF1417083 /* MJRefreshAutoNormalFooter.h in Headers */, 4D05FB8DA7185611612A386D92AE490A /* MJRefreshAutoStateFooter.h in Headers */, 1E37383432F16FB3D6F6F8043C358217 /* MJRefreshBackFooter.h in Headers */, 7B9B711ECADE8C962ED30B7747A7A60F /* MJRefreshBackGifFooter.h in Headers */, 21842D1B00812EE8754713B0E9B08514 /* MJRefreshBackNormalFooter.h in Headers */, 13AEADBEC76DB1C060C123080CFCCD6E /* MJRefreshBackStateFooter.h in Headers */, BF0EB23D88E0C06CC3892A2B42600580 /* MJRefreshComponent.h in Headers */, 77BE511C80FDD8423A3367AEBDEA9851 /* MJRefreshConst.h in Headers */, 204EF58021934704EA0E32FBDF5E031F /* MJRefreshFooter.h in Headers */, BE6C56A057F7B765EDE4A270563E5E04 /* MJRefreshGifHeader.h in Headers */, 37CFC18B5DF1320C54DD8A28C1EA5118 /* MJRefreshHeader.h in Headers */, 937F27426A73331AFF12B021D1754419 /* MJRefreshNormalHeader.h in Headers */, C73C5346DE106B194B8D52E0DD10DFFF /* MJRefreshStateHeader.h in Headers */, FC83FA010A755F146143A9935CDE0AC5 /* UIScrollView+MJExtension.h in Headers */, 0DDC94CFCC6EC337D701BA9CE07395AB /* UIScrollView+MJRefresh.h in Headers */, D62A9D152379946263D494931F44CF27 /* UIView+MJExtension.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; DC893688F5FA844F9053E7AA1AC7C25B /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( CD8F026F153BE67E954FB3A6624171E2 /* SVIndefiniteAnimatedView.h in Headers */, 8068D341BFDBD17F71ADBCE0427CB6DC /* SVProgressHUD-umbrella.h in Headers */, E51167E24F41574BC3CD6FCEECCC0A4D /* SVProgressHUD.h in Headers */, B2CDFA4E0CCE564CBC6D0987E83746D2 /* SVRadialGradientLayer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 0B33F15A364332914D715DD4C9844CC9 /* Result */ = { isa = PBXNativeTarget; buildConfigurationList = 2AD731CB4B83AAC6255A9D365FBBC832 /* Build configuration list for PBXNativeTarget "Result" */; buildPhases = ( E0A62DDD8599D6CA862578DB5885CB68 /* Sources */, B7DAFD442AA213456909FD79758AF7DF /* Frameworks */, 4C2D46665A289FB0E196AD3D28D92954 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = Result; productName = Result; productReference = A8AD00FA1CE9CD81E01F7DF7FEA36CC2 /* Result.framework */; productType = "com.apple.product-type.framework"; }; 147E210E10219F7AA15F6AE1A920B9B7 /* SVProgressHUD */ = { isa = PBXNativeTarget; buildConfigurationList = 4A114DC8E1B3172F98BEAE79A4166348 /* Build configuration list for PBXNativeTarget "SVProgressHUD" */; buildPhases = ( FD5AE255675BB474B25C588800022D89 /* Sources */, 43DC17E93088EE0302BE1E295EE2CC24 /* Frameworks */, DC893688F5FA844F9053E7AA1AC7C25B /* Headers */, 92E00E9E03FCD01DDC74B3D97A4432A7 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = SVProgressHUD; productName = SVProgressHUD; productReference = F7C0815343868D09101769AA016A9EBC /* SVProgressHUD.framework */; productType = "com.apple.product-type.framework"; }; 1C3436CEA5C3D39764C5F54374794ECB /* AFNetworking */ = { isa = PBXNativeTarget; buildConfigurationList = 57800A0D1724774333EF09E83030AA81 /* Build configuration list for PBXNativeTarget "AFNetworking" */; buildPhases = ( 1F17F426378DF5EC8DFB10304B8C4BA4 /* Sources */, C151364F15F39F7CC60CBF9A3AB49B44 /* Frameworks */, 7C6A0D99A9CC32A19A92A62F8A941139 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = AFNetworking; productName = AFNetworking; productReference = A7644E1E2725ED44B3E4C3E712764243 /* AFNetworking.framework */; productType = "com.apple.product-type.framework"; }; 33B42E21671AAC905130853EDCADA43B /* NJKWebViewProgress */ = { isa = PBXNativeTarget; buildConfigurationList = EF7786C027E37F1CE95FC5981C421D79 /* Build configuration list for PBXNativeTarget "NJKWebViewProgress" */; buildPhases = ( 51011E2CCFDF06639C80890BFDB202DA /* Sources */, 7465D1D3DA3B4F4CE97C9DEB1BC461DE /* Frameworks */, B106C9B808F7EB39F2E051B4DD3F452A /* Headers */, ); buildRules = ( ); dependencies = ( ); name = NJKWebViewProgress; productName = NJKWebViewProgress; productReference = D68DE6C9FA55C107BB0E743C027D4F0F /* NJKWebViewProgress.framework */; productType = "com.apple.product-type.framework"; }; 6847254D016329D4A531D34ED2B6DF81 /* MJRefresh */ = { isa = PBXNativeTarget; buildConfigurationList = 69253631388691DC9A46422CA5ED4053 /* Build configuration list for PBXNativeTarget "MJRefresh" */; buildPhases = ( 70314E702A5E767E7EBE167255643B1C /* Sources */, 2624FA01F2315084A8580A7172FA7AEA /* Frameworks */, D981343AF503F433F80E3DB2E576DCCD /* Headers */, C385A7B832B3AA02C87B054CE987380F /* Resources */, ); buildRules = ( ); dependencies = ( ); name = MJRefresh; productName = MJRefresh; productReference = C8B3E37B1644A5A6620F06F58E3297F0 /* MJRefresh.framework */; productType = "com.apple.product-type.framework"; }; 7C0126D717EB28DC6DB2EEA2E20B5172 /* MJExtension */ = { isa = PBXNativeTarget; buildConfigurationList = 1A2C31B6742E8C0B22231867140CB6DA /* Build configuration list for PBXNativeTarget "MJExtension" */; buildPhases = ( F9C59B0D3F828011CFDDAC70989AE04A /* Sources */, 6C1769B27D10552DD14117AB5C2BA628 /* Frameworks */, 4EEA2EBA009A3CCC55611D2D572DFC43 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = MJExtension; productName = MJExtension; productReference = FFF59AD42E90A38A6117396458DF1399 /* MJExtension.framework */; productType = "com.apple.product-type.framework"; }; 94624EC6C9739263AA965CFE2D8933F5 /* DACircularProgress */ = { isa = PBXNativeTarget; buildConfigurationList = 9AC7D3DFF2D8FB12135A3F900032F5C7 /* Build configuration list for PBXNativeTarget "DACircularProgress" */; buildPhases = ( 0E8B98481B30E39056192DB648333FDA /* Sources */, DEF0F9C828729C23E117A97CB4E88714 /* Frameworks */, 5B039065F78D452E6463B4B2038B72A4 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = DACircularProgress; productName = DACircularProgress; productReference = 15E8523EE6597A955B0FADAC061A8133 /* DACircularProgress.framework */; productType = "com.apple.product-type.framework"; }; 9EAC110EBAECD60D92AC9F4B2A6B835F /* SDWebImage */ = { isa = PBXNativeTarget; buildConfigurationList = DF0C5DA74278CC593919DA7B4ADFE8C8 /* Build configuration list for PBXNativeTarget "SDWebImage" */; buildPhases = ( 036037CB48CE95B2558E9E0B6006E3E6 /* Sources */, A1E32F8DFC56E52DD7A9CCB32FB3306B /* Frameworks */, 22DDE9A4759D6D82E423746B199E4FD4 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = SDWebImage; productName = SDWebImage; productReference = C9CEEC8B3653DF7ECDD9F6994C125AE8 /* SDWebImage.framework */; productType = "com.apple.product-type.framework"; }; CD66F4C120F99EBA4539035A6A5612C9 /* Pods */ = { isa = PBXNativeTarget; buildConfigurationList = BEB36C5B1522BDA82EA8CA4DF74135A5 /* Build configuration list for PBXNativeTarget "Pods" */; buildPhases = ( D980C58C0BB778C2BCF81D3F6B13390E /* Sources */, DBDDBD33224A7EEE1B6B90D09BD3DED5 /* Frameworks */, 1EE53E0729698439B9B5D574F56FFA25 /* Headers */, ); buildRules = ( ); dependencies = ( 4EEF128D01E0561864E98CBC1AFF6BFE /* PBXTargetDependency */, 025FAD7A644C0137B5D00761055FAAC5 /* PBXTargetDependency */, A01F20CB528C1DF567FABAE0E54766C5 /* PBXTargetDependency */, 8571ABE2D39054908B2CB852515F36D3 /* PBXTargetDependency */, F9965D4355863FDF83F594DD97628327 /* PBXTargetDependency */, 4B03309278AEB0C597EE01B1A65EC6CD /* PBXTargetDependency */, 5C699460B92B16EAE32D6B57C501D831 /* PBXTargetDependency */, 654926D6716028F37EC79CC1D66E254F /* PBXTargetDependency */, E042E296BE20749678F5660B8A56ADE4 /* PBXTargetDependency */, ); name = Pods; productName = Pods; productReference = 3BE0743F558E9A037CAB60C2B8775642 /* Pods.framework */; productType = "com.apple.product-type.framework"; }; E31FBC1304C5757C98D97C5AE31F36A2 /* ReactiveCocoa */ = { isa = PBXNativeTarget; buildConfigurationList = CD72496FC67F0FD51C0B64DB1B1186E5 /* Build configuration list for PBXNativeTarget "ReactiveCocoa" */; buildPhases = ( 81CDD4EFE16EC987B8758D155B7BA694 /* Sources */, 88D29C88C57F1AEDB50E7E466C2EDA68 /* Frameworks */, 4CBF24217076736867211BCB7ECB30E4 /* Headers */, ); buildRules = ( ); dependencies = ( 3EC661973054E577E6339915421C1AF8 /* PBXTargetDependency */, ); name = ReactiveCocoa; productName = ReactiveCocoa; productReference = A8E5B203CAD658FDF4CD5D2CCE3A6057 /* ReactiveCocoa.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0700; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 7DB346D0F39D3F0E887471402A8071AB; productRefGroup = 05625802EB36799D6A66F9D9600065E8 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 1C3436CEA5C3D39764C5F54374794ECB /* AFNetworking */, 94624EC6C9739263AA965CFE2D8933F5 /* DACircularProgress */, 7C0126D717EB28DC6DB2EEA2E20B5172 /* MJExtension */, 6847254D016329D4A531D34ED2B6DF81 /* MJRefresh */, 33B42E21671AAC905130853EDCADA43B /* NJKWebViewProgress */, CD66F4C120F99EBA4539035A6A5612C9 /* Pods */, E31FBC1304C5757C98D97C5AE31F36A2 /* ReactiveCocoa */, 0B33F15A364332914D715DD4C9844CC9 /* Result */, 9EAC110EBAECD60D92AC9F4B2A6B835F /* SDWebImage */, 147E210E10219F7AA15F6AE1A920B9B7 /* SVProgressHUD */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 92E00E9E03FCD01DDC74B3D97A4432A7 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 791DC115A0616D0E1D76C2008830CDDD /* SVProgressHUD.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; C385A7B832B3AA02C87B054CE987380F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6788B6B8B3FA97B1D3813482381457F6 /* MJRefresh.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 036037CB48CE95B2558E9E0B6006E3E6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 11CCD157B8D314668F913B066D01ABD8 /* NSData+ImageContentType.m in Sources */, ADA6FC12E44039C91AFB67F2B5D1E3E6 /* SDImageCache.m in Sources */, 467233A8180FB272DAB57FD1FE8D516D /* SDWebImage-dummy.m in Sources */, 6D315C50D9018D7EEE3ABCE6D36EEBB4 /* SDWebImageCompat.m in Sources */, 843942BBF374018B605D9121EC7C259F /* SDWebImageDecoder.m in Sources */, 5030B65ECDFC47218E46FF3022228735 /* SDWebImageDownloader.m in Sources */, 1AFC2415B88A6E4E696131828997E417 /* SDWebImageDownloaderOperation.m in Sources */, 838B46E9C2E5B00F39E34A69675505F4 /* SDWebImageManager.m in Sources */, 93EE6196A5980B844FD3D53EE66F83CA /* SDWebImagePrefetcher.m in Sources */, 8419132DDBEA3303309BD94D048F046C /* UIButton+WebCache.m in Sources */, 784CF489F031186518D41D803E19B7D3 /* UIImage+GIF.m in Sources */, E6B3E98FA9C09AEA32AA9ACE662F6728 /* UIImage+MultiFormat.m in Sources */, 413A819F1C48B8B9903B8EF88B92D58C /* UIImageView+HighlightedWebCache.m in Sources */, 83EBCD957DAAE26B53E30075624D161E /* UIImageView+WebCache.m in Sources */, F488F203073C7C6B918B5211FC21A1A7 /* UIView+WebCacheOperation.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 0E8B98481B30E39056192DB648333FDA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 17EB39392F9E486B79933146AE4260C9 /* DACircularProgress-dummy.m in Sources */, EA6F0B146700B71CB0FF0C77156BBFCF /* DACircularProgressView.m in Sources */, 253B94DA5A839424B768C83B45A050FB /* DALabeledCircularProgressView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 1F17F426378DF5EC8DFB10304B8C4BA4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 3F1BC9BAFFEEABB1ABC7614DF0FC97D5 /* AFAutoPurgingImageCache.m in Sources */, E0D4045AC4C1B41917FCA23A042D18B2 /* AFHTTPSessionManager.m in Sources */, CFA8D6B529A0EBFF0316F2629AB2556E /* AFImageDownloader.m in Sources */, A6C6019D45BE62C61210A9CC619368EF /* AFNetworkActivityIndicatorManager.m in Sources */, 3D2789FC760A97301909F0B1201626CD /* AFNetworking-dummy.m in Sources */, 68A38977EBAE334DC3C22386D00D2622 /* AFNetworkReachabilityManager.m in Sources */, 20607BE2B1E5F31765026E5AC64DB27D /* AFSecurityPolicy.m in Sources */, DFFA215EEAA8DDBD540076927535275C /* AFURLRequestSerialization.m in Sources */, B5852322ADE88AAD56EE042B80BA81E4 /* AFURLResponseSerialization.m in Sources */, 707B1A7541C8DBDDE8C27896A61370BE /* AFURLSessionManager.m in Sources */, 6ED4ABEE8A5F51F5ECB59FA1781D29C6 /* UIActivityIndicatorView+AFNetworking.m in Sources */, AF03C11A1FAC8132AD3749D8F541701A /* UIButton+AFNetworking.m in Sources */, 2E8A32ED46194EDBE22146271F6D26DE /* UIImageView+AFNetworking.m in Sources */, 5FF6453E55785669885F626B853FD2AA /* UIProgressView+AFNetworking.m in Sources */, 174202BD6AE0E4A41F5CE66E975EAE52 /* UIRefreshControl+AFNetworking.m in Sources */, A462945883F7729B185B64B679A6BFBE /* UIWebView+AFNetworking.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 51011E2CCFDF06639C80890BFDB202DA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 669460524FC57AB51CD3FC2A0822975B /* NJKWebViewProgress-dummy.m in Sources */, 7D686CEEA943ED9A03534418A1618F13 /* NJKWebViewProgress.m in Sources */, 9FACD31A94E2DA587946657B52EB7A6B /* NJKWebViewProgressView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 70314E702A5E767E7EBE167255643B1C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 44C9FF75FB900236B6073645EE05D412 /* MJRefresh-dummy.m in Sources */, 677F340D45A43C07863B5CFB9F16FDFC /* MJRefreshAutoFooter.m in Sources */, 4B983DCAE762551646E5782347B7287A /* MJRefreshAutoGifFooter.m in Sources */, 6DF2DEDC95B582C261A4ED2888891603 /* MJRefreshAutoNormalFooter.m in Sources */, 210B48234B872F3081567E5FA1B56C0C /* MJRefreshAutoStateFooter.m in Sources */, F70504B745ABB3940711E6A3A5D863E5 /* MJRefreshBackFooter.m in Sources */, C9497D947A0E66DB13242885B53F6946 /* MJRefreshBackGifFooter.m in Sources */, 24C537660666185D8B113F4A0830E6FB /* MJRefreshBackNormalFooter.m in Sources */, 78106ADC03AC37B5BD2B14C45D033369 /* MJRefreshBackStateFooter.m in Sources */, 56AADC1B87576F8B8175BE4B99C3F5B5 /* MJRefreshComponent.m in Sources */, 194BE0684BEBC29B137094C4491DC9AB /* MJRefreshConst.m in Sources */, 0FC3BB949D35D24F32CE9BD37BD4724F /* MJRefreshFooter.m in Sources */, F37796CDD34641CEC272FC24C85C5901 /* MJRefreshGifHeader.m in Sources */, A874D60B6C69FFE15C329256755B058C /* MJRefreshHeader.m in Sources */, FF6C2855509136F8DEF9FAC173597944 /* MJRefreshNormalHeader.m in Sources */, 0F12BAF3BF633C35A7CC0994F141D84A /* MJRefreshStateHeader.m in Sources */, CF8456F107FFCD2C20298F63CD23216F /* UIScrollView+MJExtension.m in Sources */, BD8A850E68B7FBCA60C0ED501100C971 /* UIScrollView+MJRefresh.m in Sources */, 5185EE40B00B0C1B29AD983337395ECA /* UIView+MJExtension.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 81CDD4EFE16EC987B8758D155B7BA694 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 535CA73BCA2B2AFF75EA7E12F3CA7DB6 /* Action.swift in Sources */, 908F6453F4D78F2B67AFE459C199CA79 /* Atomic.swift in Sources */, 21C7737CC4A052AA1EE2E8758FE0346F /* Bag.swift in Sources */, D676F0CF5892D9986952CE30CAF08710 /* Disposable.swift in Sources */, 4E3E184ADF8AB31FB3475A12997109E1 /* Errors.swift in Sources */, 7B0A87FD85C30E150E62FE2F6AFD714C /* Event.swift in Sources */, AC452E1429618AFF74F34953ED044819 /* EXTRuntimeExtensions.m in Sources */, 83D63CF1C4BF96018964A868A8C3B19D /* FoundationExtensions.swift in Sources */, E0CF3FDA599B19EF3F1A47B5BDC2F9AB /* MKAnnotationView+RACSignalSupport.m in Sources */, FB4AABB168DCA42AB0B7617E9FEA51E0 /* NSArray+RACSequenceAdditions.m in Sources */, 0D7ED1B1D76230793B749C5107FC60A3 /* NSData+RACSupport.m in Sources */, 6633446E76D3CC84B07DEF918907D4A0 /* NSDictionary+RACSequenceAdditions.m in Sources */, B5A3B3D4ACD5A5D5B8A93860AA934818 /* NSEnumerator+RACSequenceAdditions.m in Sources */, 4B3CA2CA6977D05A9175EC8166226DB8 /* NSFileHandle+RACSupport.m in Sources */, 7FC128F6416C57B73631DDA5028F7EA4 /* NSIndexSet+RACSequenceAdditions.m in Sources */, F799F156F28A70FF5412DF8CF34057A8 /* NSInvocation+RACTypeParsing.m in Sources */, 613581FE33A08B7F901B0A4FE5E18BB8 /* NSNotificationCenter+RACSupport.m in Sources */, 50E93FB3B4A7BB080E108302F1DAD186 /* NSObject+RACDeallocating.m in Sources */, 2FA7914B3CEF5CD29FDDDA2CC8D7DBD8 /* NSObject+RACDescription.m in Sources */, D0DABCBD3F1A6255126CF13B71E9DD8A /* NSObject+RACKVOWrapper.m in Sources */, 5573127307BDE2B33F75A242B4CE842A /* NSObject+RACLifting.m in Sources */, A7E50BF7F9042381769B72E3EB0B424B /* NSObject+RACPropertySubscribing.m in Sources */, 13CDA14946A4311259575FB563E4C475 /* NSObject+RACSelectorSignal.m in Sources */, 63EAE2CF50A076295582BAC0ECECC503 /* NSOrderedSet+RACSequenceAdditions.m in Sources */, 424879726EBBB16DFE90D267551D472C /* NSSet+RACSequenceAdditions.m in Sources */, 7F8E4DFC4EB7B6EC92D2AE56790E4698 /* NSString+RACKeyPathUtilities.m in Sources */, 705C497EAAA2CE57A920C4D9CC05B1A0 /* NSString+RACSequenceAdditions.m in Sources */, AA3ACC8EAC430A22F002C2A67B9ECB37 /* NSString+RACSupport.m in Sources */, DA956B14A3C671B585308EF7F8BC0BF2 /* NSURLConnection+RACSupport.m in Sources */, 10867C687E423B0F969783EE5B69D138 /* NSUserDefaults+RACSupport.m in Sources */, BD88BABCCF32770C64B6998FA43265D5 /* ObjectiveCBridging.swift in Sources */, 70D07B077BDD5EE5910BD44309DFB020 /* Observer.swift in Sources */, D03ED3E1E9EB4F27320394A36C43982E /* Optional.swift in Sources */, 362778BBAA748228039CA8882770A72D /* Property.swift in Sources */, 1F6F88E5512E3C7C12F253386DF12E00 /* RACArraySequence.m in Sources */, FD800E1FAF78230644012D0BC5F89B7D /* RACBehaviorSubject.m in Sources */, 28AF8EAC58ABA02BD0F59B0AF8A69D7D /* RACBlockTrampoline.m in Sources */, D661ED5B7D23D5B19B15B7C0BBBFD9A3 /* RACChannel.m in Sources */, 03AC2048B8CCA5AADB8BF23135CB47EA /* RACCommand.m in Sources */, 48245FBC81E27E0F30C357B7A6D32090 /* RACCompoundDisposable.m in Sources */, D4C7FE23F66BA3A46162593A9918D7EA /* RACCompoundDisposableProvider.d in Sources */, 5BBC034F990B6A23EAAD08B6A8A761E7 /* RACDelegateProxy.m in Sources */, 0F584B41F61BD287EF16D346CF64D80F /* RACDisposable.m in Sources */, 85F961A88372C4AC3BBC1DE6DF16BB19 /* RACDynamicPropertySuperclass.m in Sources */, 433478893128C30315BC255A44723D53 /* RACDynamicSequence.m in Sources */, A818AD7A582F331310F1A3AD66F9DB26 /* RACDynamicSignal.m in Sources */, 421F3D9FD0162A3EA02B1F2C6BE5860B /* RACEagerSequence.m in Sources */, 733C2E31D6AB9A8A851D42B0BD6C45AC /* RACEmptySequence.m in Sources */, 3EFE7CAD294140A8E9550A8A267D0676 /* RACEmptySignal.m in Sources */, 83F690D0EB0A3D033DE19B513DC38F31 /* RACErrorSignal.m in Sources */, 5896DB746ABBB4D6BE7EE7F8C4F548FE /* RACEvent.m in Sources */, 2AFAEAE18B28D77C49D7E4FC8ED26041 /* RACGroupedSignal.m in Sources */, 4D51DA2C84DABDB517491E5414B09659 /* RACImmediateScheduler.m in Sources */, 8176B584C906633CF35025C19C46B71B /* RACIndexSetSequence.m in Sources */, 29838BA5F72777DD963F2C4D9B21770C /* RACKVOChannel.m in Sources */, D182C799FA0CAA54FFBC3C2C55D8167F /* RACKVOProxy.m in Sources */, E91DDE6EB5FAF6E1C7A77E2D0ADFF6D1 /* RACKVOTrampoline.m in Sources */, 5F657C8B9A31DD446865DA4F5EC67B60 /* RACMulticastConnection.m in Sources */, 5BE17C62DC3644DA27BE4C6053F88D17 /* RACObjCRuntime.m in Sources */, F67D5D0C2FE807F7D5ACCCC981F6E089 /* RACPassthroughSubscriber.m in Sources */, F11C5E7C4923AE968981B5F7198683EA /* RACQueueScheduler.m in Sources */, 7667A35A331F96CAACBC6B64CEBE43C0 /* RACReplaySubject.m in Sources */, 145DF26BD5EDAF491625C13FF2E638E0 /* RACReturnSignal.m in Sources */, E03653384C7BE69DCDB564E3BBC78FEF /* RACScheduler.m in Sources */, 73EFFC322D098B3B8F91D86B0398B537 /* RACScopedDisposable.m in Sources */, D72B9283EE25F9A12BD0FA7C84221684 /* RACSequence.m in Sources */, 0387355C50F377A44E1161FE0F16F7F7 /* RACSerialDisposable.m in Sources */, A901A8DA830B4B4679507C4E69EDF8A1 /* RACSignal+Operations.m in Sources */, 6AEDCFF3FA4CFA352837DA11AE4A1B93 /* RACSignal.m in Sources */, 6C5C41305CB8F2C4B633C9F5A6D0742D /* RACSignalProvider.d in Sources */, 579985D58E8BCBBBB532AD722F73E9CC /* RACSignalSequence.m in Sources */, EB16E6D7F4B34537C4320D1AD26867F3 /* RACStream.m in Sources */, 3856564171C0B06F0B921E8AC6DBDC9A /* RACStringSequence.m in Sources */, E6548000C8BF4FA50A4E1A1908A90574 /* RACSubject.m in Sources */, 1DF62BEA1160CCD444A1E3E43EB568FB /* RACSubscriber.m in Sources */, F66B2090A94AAB1AF4E1CC51D9268D85 /* RACSubscriptingAssignmentTrampoline.m in Sources */, B8620D72DAD3CD23AB157BBD7A7B782F /* RACSubscriptionScheduler.m in Sources */, 7790A780B0275647A252AA9FB1EBC276 /* RACTargetQueueScheduler.m in Sources */, F29FF0F9A22BFE0EA8754DFF41894244 /* RACTestScheduler.m in Sources */, 258E4A137C79920CCEE9C7D01EC99A67 /* RACTuple.m in Sources */, E264E4B47C3F3A3B9C1F3733560E5D19 /* RACTupleSequence.m in Sources */, F8A8AD0A7F4653C09DE7B5EAD44ADAAB /* RACUnarySequence.m in Sources */, 251707CDFB6180CE3DF78837B79F9BB7 /* RACUnit.m in Sources */, DE1C43D7F6F319234B4A9A4017736298 /* RACValueTransformer.m in Sources */, F878D888E0FDBA293E5876E8AA42EC26 /* ReactiveCocoa-dummy.m in Sources */, 96BABE17042E8F3CE7F8029ABE3A686D /* Scheduler.swift in Sources */, ED097F975473B7CB4020FFF06B1F3BE3 /* Signal.swift in Sources */, 6E887BF6A924958E7F9CFF227E9E1586 /* SignalProducer.swift in Sources */, 23FD63A798C947A567842AFE4C49D7D2 /* TupleExtensions.swift in Sources */, AC5B479241D890A457651FB489A5D17B /* UIActionSheet+RACSignalSupport.m in Sources */, C0FD4C225F2E320005F7649F5106D009 /* UIAlertView+RACSignalSupport.m in Sources */, 88DD07E075B4404F25112BA9230B688D /* UIBarButtonItem+RACCommandSupport.m in Sources */, BE7742B51F6C55A6A63E7D7E4225D9EC /* UIButton+RACCommandSupport.m in Sources */, 4023867FB0DEFB7CBF1428DFB783E7D9 /* UICollectionReusableView+RACSignalSupport.m in Sources */, 7F3929881C52F1CAB7EDA45FADE72C5B /* UIControl+RACSignalSupport.m in Sources */, A8FACFFCA9F80A82E95AF6890EC16553 /* UIControl+RACSignalSupportPrivate.m in Sources */, 3D264EAFC6A30E26A7325BB38B4230B5 /* UIDatePicker+RACSignalSupport.m in Sources */, 42BE038A05A9E0D9A0ED57857F3DC2C4 /* UIGestureRecognizer+RACSignalSupport.m in Sources */, 40DEAC560BE1E33237B2B035B0C3C262 /* UIImagePickerController+RACSignalSupport.m in Sources */, 7EAFA40A7D8A7738076EC982D1FCB9F8 /* UIRefreshControl+RACCommandSupport.m in Sources */, EBB71D7EFF5566E9B87F9DE36E973FBC /* UISegmentedControl+RACSignalSupport.m in Sources */, D1C210B87C732659BE699941EBB79A1A /* UISlider+RACSignalSupport.m in Sources */, 184AEAF1B4DAC4EC608312ECF96CA682 /* UIStepper+RACSignalSupport.m in Sources */, 769106E9AC019F85C5188E44428ACD22 /* UISwitch+RACSignalSupport.m in Sources */, DD9B17C25EB68901D26243C6F97EEE56 /* UITableViewCell+RACSignalSupport.m in Sources */, 12D9E2794BC032F7945EF8D62E2DFB6D /* UITableViewHeaderFooterView+RACSignalSupport.m in Sources */, 373BBB3417DA29B53A80B329E2ABA6EE /* UITextField+RACSignalSupport.m in Sources */, 1698F95CBDC543F4C347CD51A0FD034F /* UITextView+RACSignalSupport.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; D980C58C0BB778C2BCF81D3F6B13390E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 26AC9A4F41F0FFE516782716202CB6E6 /* Pods-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E0A62DDD8599D6CA862578DB5885CB68 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( BBCC9B911833546C10283453DE8D1948 /* Result-dummy.m in Sources */, 54E8EEF1AF4EC853E8A626318018D461 /* Result.swift in Sources */, D13F54EA636464A6872BFD4FAF4CA39C /* ResultType.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; F9C59B0D3F828011CFDDAC70989AE04A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 49975810AF5B32D24D3EAAE9E4776E93 /* MJExtension-dummy.m in Sources */, B3A97031390F94C0DA848612C6053D05 /* MJExtensionConst.m in Sources */, CBE63803A9E627929E76CBD11DA70A73 /* MJFoundation.m in Sources */, A54611F727A8AAEAE219AE89290A94F8 /* MJProperty.m in Sources */, 459DE06B198852EAC2C492888162ED11 /* MJPropertyKey.m in Sources */, F852A0869AF27611809B656DACFFEABD /* MJPropertyType.m in Sources */, 961B768DF18068867B281C6D2075DF26 /* NSObject+MJClass.m in Sources */, 6E14DFC821D96FC7FE0C831682CFAC05 /* NSObject+MJCoding.m in Sources */, D90D224837D808EFE79F724A722C753C /* NSObject+MJKeyValue.m in Sources */, 304D6E134A4BAD7BF36C90FE55A331CF /* NSObject+MJProperty.m in Sources */, 110CC60B2EF89629C7A98C691B694DB2 /* NSString+MJExtension.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; FD5AE255675BB474B25C588800022D89 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7F925F8DF61ED6356DF8A6DFBA4F42F6 /* SVIndefiniteAnimatedView.m in Sources */, FB0D56033C8D28431FFE4C081D26CA3D /* SVProgressHUD-dummy.m in Sources */, B66558616A2ED20387925E1F8A899B6A /* SVProgressHUD.m in Sources */, 10F1286131E7834EB6C42998503C8A11 /* SVRadialGradientLayer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 025FAD7A644C0137B5D00761055FAAC5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = DACircularProgress; target = 94624EC6C9739263AA965CFE2D8933F5 /* DACircularProgress */; targetProxy = 40FAF901B699BBCF70EF8CEE190342DD /* PBXContainerItemProxy */; }; 3EC661973054E577E6339915421C1AF8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Result; target = 0B33F15A364332914D715DD4C9844CC9 /* Result */; targetProxy = 35412EC18D3EBC733D04C08AA497FAD9 /* PBXContainerItemProxy */; }; 4B03309278AEB0C597EE01B1A65EC6CD /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = ReactiveCocoa; target = E31FBC1304C5757C98D97C5AE31F36A2 /* ReactiveCocoa */; targetProxy = 85F6A6C5CFB2F62C2DAFB3EC4059A054 /* PBXContainerItemProxy */; }; 4EEF128D01E0561864E98CBC1AFF6BFE /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = AFNetworking; target = 1C3436CEA5C3D39764C5F54374794ECB /* AFNetworking */; targetProxy = 1984B50C9738B84D132B2564CFC34D0A /* PBXContainerItemProxy */; }; 5C699460B92B16EAE32D6B57C501D831 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Result; target = 0B33F15A364332914D715DD4C9844CC9 /* Result */; targetProxy = FC14D2248C5EDD81CDB6EE98554AF8FD /* PBXContainerItemProxy */; }; 654926D6716028F37EC79CC1D66E254F /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SDWebImage; target = 9EAC110EBAECD60D92AC9F4B2A6B835F /* SDWebImage */; targetProxy = 452023F999638CC54D778CE994CAFCA6 /* PBXContainerItemProxy */; }; 8571ABE2D39054908B2CB852515F36D3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = MJRefresh; target = 6847254D016329D4A531D34ED2B6DF81 /* MJRefresh */; targetProxy = 72095AA5AE5EE61B7E287B4AC6107854 /* PBXContainerItemProxy */; }; A01F20CB528C1DF567FABAE0E54766C5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = MJExtension; target = 7C0126D717EB28DC6DB2EEA2E20B5172 /* MJExtension */; targetProxy = 5259EE160B2F5B5116E7D287864BFEC3 /* PBXContainerItemProxy */; }; E042E296BE20749678F5660B8A56ADE4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SVProgressHUD; target = 147E210E10219F7AA15F6AE1A920B9B7 /* SVProgressHUD */; targetProxy = 046888DED34D27F5F4AB0261833B3313 /* PBXContainerItemProxy */; }; F9965D4355863FDF83F594DD97628327 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = NJKWebViewProgress; target = 33B42E21671AAC905130853EDCADA43B /* NJKWebViewProgress */; targetProxy = B22B6F7D22325424FE20717F6CBA8756 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 042BA4040696E1B93FAEAA8E283D4D44 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 92EAED162A87EB212AEB28B7B66FBCA0 /* Result.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/Result/Result-prefix.pch"; INFOPLIST_FILE = "Target Support Files/Result/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/Result/Result.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = Result; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 0437D37BA526171A274A2BB60AD5A2C1 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A1DF584D946B78214595DA9CBCB0E938 /* NJKWebViewProgress.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/NJKWebViewProgress/NJKWebViewProgress-prefix.pch"; INFOPLIST_FILE = "Target Support Files/NJKWebViewProgress/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/NJKWebViewProgress/NJKWebViewProgress.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = NJKWebViewProgress; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 0498437E24DC4D8DE030FD20F0B33720 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 48974FB2D05D403AEF69BFCC9EB4EBF3 /* ReactiveCocoa.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/ReactiveCocoa/ReactiveCocoa-prefix.pch"; INFOPLIST_FILE = "Target Support Files/ReactiveCocoa/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/ReactiveCocoa/ReactiveCocoa.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = ReactiveCocoa; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 10DE1947DAC0ED28F6C0A9F9BD75D546 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1"; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; STRIP_INSTALLED_PRODUCT = NO; SYMROOT = "${SRCROOT}/../build"; VALIDATE_PRODUCT = YES; }; name = Release; }; 25F52C16B60405E77517E9387B65175C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 48974FB2D05D403AEF69BFCC9EB4EBF3 /* ReactiveCocoa.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/ReactiveCocoa/ReactiveCocoa-prefix.pch"; INFOPLIST_FILE = "Target Support Files/ReactiveCocoa/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/ReactiveCocoa/ReactiveCocoa.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = ReactiveCocoa; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 2B2E39563061D7D787CF8560567C376D /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 64B2BBC280624DAA5159807DD47EDA7C /* SDWebImage.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/SDWebImage/SDWebImage-prefix.pch"; INFOPLIST_FILE = "Target Support Files/SDWebImage/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/SDWebImage/SDWebImage.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = SDWebImage; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 367FBEC16BD982E0A8D9489F869225CB /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = E5CD8F5EBE3094663634930E490C7286 /* MJRefresh.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/MJRefresh/MJRefresh-prefix.pch"; INFOPLIST_FILE = "Target Support Files/MJRefresh/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/MJRefresh/MJRefresh.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = MJRefresh; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 54A599ACC730FCC7E785A369E2F3C101 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = DA312349A49333542E6F4B36B329960E /* Pods.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; INFOPLIST_FILE = "Target Support Files/Pods/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods/Pods.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_NAME = Pods; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 552D02D5BA751AC2E8790D2811D496CA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.3; ONLY_ACTIVE_ARCH = YES; STRIP_INSTALLED_PRODUCT = NO; SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; 68684A1BC17D00FE1CEE255866475104 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 04791F30EB17FA5F95CCE83E1EC06C5A /* MJExtension.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/MJExtension/MJExtension-prefix.pch"; INFOPLIST_FILE = "Target Support Files/MJExtension/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/MJExtension/MJExtension.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = MJExtension; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 6C3058F20CAECDF7004D3B5FF9E3A5C3 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = E81AB1499B5BC494FB166DC100E727D2 /* SVProgressHUD.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch"; INFOPLIST_FILE = "Target Support Files/SVProgressHUD/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/SVProgressHUD/SVProgressHUD.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = SVProgressHUD; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 76888A2F00EF2D84A119AB347667CE4A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 04791F30EB17FA5F95CCE83E1EC06C5A /* MJExtension.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/MJExtension/MJExtension-prefix.pch"; INFOPLIST_FILE = "Target Support Files/MJExtension/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/MJExtension/MJExtension.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = MJExtension; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 8A235AF33A4AFC4EC3F9345F48177E4E /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = B69789BB77F174CEABB55543FDCDCBBD /* AFNetworking.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch"; INFOPLIST_FILE = "Target Support Files/AFNetworking/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/AFNetworking/AFNetworking.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = AFNetworking; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; A5EAFA37A3115A3DF8AD41047612AA3C /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = A1DF584D946B78214595DA9CBCB0E938 /* NJKWebViewProgress.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/NJKWebViewProgress/NJKWebViewProgress-prefix.pch"; INFOPLIST_FILE = "Target Support Files/NJKWebViewProgress/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/NJKWebViewProgress/NJKWebViewProgress.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = NJKWebViewProgress; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; A8D9490749BD0DEC6F5EF7B6949611BC /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 977577C045EDA9D9D1F46E2598D19FC7 /* Pods.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; INFOPLIST_FILE = "Target Support Files/Pods/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods/Pods.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_NAME = Pods; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; ADE540A3B64DC14022EC89DE232C62C0 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = E5CD8F5EBE3094663634930E490C7286 /* MJRefresh.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/MJRefresh/MJRefresh-prefix.pch"; INFOPLIST_FILE = "Target Support Files/MJRefresh/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/MJRefresh/MJRefresh.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = MJRefresh; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; AEBAC072046B430CEDF3D1943B8652C4 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 64B2BBC280624DAA5159807DD47EDA7C /* SDWebImage.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/SDWebImage/SDWebImage-prefix.pch"; INFOPLIST_FILE = "Target Support Files/SDWebImage/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/SDWebImage/SDWebImage.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = SDWebImage; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; BCD50DBF92DCB7FF7B5FD3D2EADC4AF5 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = B20C17CD12A642AE53D6EB41DADC0F2B /* DACircularProgress.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/DACircularProgress/DACircularProgress-prefix.pch"; INFOPLIST_FILE = "Target Support Files/DACircularProgress/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/DACircularProgress/DACircularProgress.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = DACircularProgress; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; BFC95FB0FE8741CEE4B5430A6060403E /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = B69789BB77F174CEABB55543FDCDCBBD /* AFNetworking.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch"; INFOPLIST_FILE = "Target Support Files/AFNetworking/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/AFNetworking/AFNetworking.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = AFNetworking; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; C0A6445E44B5CE76762489F419FA87B7 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = E81AB1499B5BC494FB166DC100E727D2 /* SVProgressHUD.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch"; INFOPLIST_FILE = "Target Support Files/SVProgressHUD/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/SVProgressHUD/SVProgressHUD.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = SVProgressHUD; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; D82B4483F7E405EBAFF752A54B8476F1 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 92EAED162A87EB212AEB28B7B66FBCA0 /* Result.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/Result/Result-prefix.pch"; INFOPLIST_FILE = "Target Support Files/Result/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/Result/Result.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = Result; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; EF00535DAFE71C9C9E068976AD240552 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = B20C17CD12A642AE53D6EB41DADC0F2B /* DACircularProgress.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREFIX_HEADER = "Target Support Files/DACircularProgress/DACircularProgress-prefix.pch"; INFOPLIST_FILE = "Target Support Files/DACircularProgress/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/DACircularProgress/DACircularProgress.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = DACircularProgress; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 1A2C31B6742E8C0B22231867140CB6DA /* Build configuration list for PBXNativeTarget "MJExtension" */ = { isa = XCConfigurationList; buildConfigurations = ( 76888A2F00EF2D84A119AB347667CE4A /* Debug */, 68684A1BC17D00FE1CEE255866475104 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 2AD731CB4B83AAC6255A9D365FBBC832 /* Build configuration list for PBXNativeTarget "Result" */ = { isa = XCConfigurationList; buildConfigurations = ( D82B4483F7E405EBAFF752A54B8476F1 /* Debug */, 042BA4040696E1B93FAEAA8E283D4D44 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( 552D02D5BA751AC2E8790D2811D496CA /* Debug */, 10DE1947DAC0ED28F6C0A9F9BD75D546 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 4A114DC8E1B3172F98BEAE79A4166348 /* Build configuration list for PBXNativeTarget "SVProgressHUD" */ = { isa = XCConfigurationList; buildConfigurations = ( C0A6445E44B5CE76762489F419FA87B7 /* Debug */, 6C3058F20CAECDF7004D3B5FF9E3A5C3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 57800A0D1724774333EF09E83030AA81 /* Build configuration list for PBXNativeTarget "AFNetworking" */ = { isa = XCConfigurationList; buildConfigurations = ( 8A235AF33A4AFC4EC3F9345F48177E4E /* Debug */, BFC95FB0FE8741CEE4B5430A6060403E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 69253631388691DC9A46422CA5ED4053 /* Build configuration list for PBXNativeTarget "MJRefresh" */ = { isa = XCConfigurationList; buildConfigurations = ( ADE540A3B64DC14022EC89DE232C62C0 /* Debug */, 367FBEC16BD982E0A8D9489F869225CB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 9AC7D3DFF2D8FB12135A3F900032F5C7 /* Build configuration list for PBXNativeTarget "DACircularProgress" */ = { isa = XCConfigurationList; buildConfigurations = ( BCD50DBF92DCB7FF7B5FD3D2EADC4AF5 /* Debug */, EF00535DAFE71C9C9E068976AD240552 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; BEB36C5B1522BDA82EA8CA4DF74135A5 /* Build configuration list for PBXNativeTarget "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( A8D9490749BD0DEC6F5EF7B6949611BC /* Debug */, 54A599ACC730FCC7E785A369E2F3C101 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; CD72496FC67F0FD51C0B64DB1B1186E5 /* Build configuration list for PBXNativeTarget "ReactiveCocoa" */ = { isa = XCConfigurationList; buildConfigurations = ( 25F52C16B60405E77517E9387B65175C /* Debug */, 0498437E24DC4D8DE030FD20F0B33720 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; DF0C5DA74278CC593919DA7B4ADFE8C8 /* Build configuration list for PBXNativeTarget "SDWebImage" */ = { isa = XCConfigurationList; buildConfigurations = ( AEBAC072046B430CEDF3D1943B8652C4 /* Debug */, 2B2E39563061D7D787CF8560567C376D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; EF7786C027E37F1CE95FC5981C421D79 /* Build configuration list for PBXNativeTarget "NJKWebViewProgress" */ = { isa = XCConfigurationList; buildConfigurations = ( 0437D37BA526171A274A2BB60AD5A2C1 /* Debug */, A5EAFA37A3115A3DF8AD41047612AA3C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; } ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/AFNetworking.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/DACircularProgress.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/MJExtension.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/MJRefresh.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/NJKWebViewProgress.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/Pods.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/ReactiveCocoa.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/Result.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/SDWebImage.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/SVProgressHUD.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState AFNetworking.xcscheme isShown DACircularProgress.xcscheme isShown MJExtension.xcscheme isShown MJRefresh.xcscheme isShown NJKWebViewProgress.xcscheme isShown Pods.xcscheme isShown ReactiveCocoa.xcscheme isShown Result.xcscheme isShown SDWebImage.xcscheme isShown SVProgressHUD.xcscheme isShown SuppressBuildableAutocreation 0B33F15A364332914D715DD4C9844CC9 primary 147E210E10219F7AA15F6AE1A920B9B7 primary 1C3436CEA5C3D39764C5F54374794ECB primary 33B42E21671AAC905130853EDCADA43B primary 6847254D016329D4A531D34ED2B6DF81 primary 7C0126D717EB28DC6DB2EEA2E20B5172 primary 94624EC6C9739263AA965CFE2D8933F5 primary 9EAC110EBAECD60D92AC9F4B2A6B835F primary CD66F4C120F99EBA4539035A6A5612C9 primary E31FBC1304C5757C98D97C5AE31F36A2 primary ================================================ FILE: Pods/ReactiveCocoa/LICENSE.md ================================================ **Copyright (c) 2012 - 2015, GitHub, Inc.** **All rights reserved.** Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/ReactiveCocoa/README.md ================================================ ![](Logo/header.png) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![GitHub release](https://img.shields.io/github/release/ReactiveCocoa/ReactiveCocoa.svg)](https://github.com/ReactiveCocoa/ReactiveCocoa/releases) ReactiveCocoa (RAC) is a Cocoa framework inspired by [Functional Reactive Programming](https://en.wikipedia.org/wiki/Functional_reactive_programming). It provides APIs for composing and transforming **streams of values over time**. 1. [Introduction](#introduction) 1. [Example: online search](#example-online-search) 1. [Objective-C and Swift](#objective-c-and-swift) 1. [How does ReactiveCocoa relate to Rx?](#how-does-reactivecocoa-relate-to-rx) 1. [Getting started](#getting-started) If you’re already familiar with functional reactive programming or what ReactiveCocoa is about, check out the [Documentation][] folder for more in-depth information about how it all works. Then, dive straight into our [documentation comments][Code] for learning more about individual APIs. If you have a question, please see if any discussions in our [GitHub issues](https://github.com/ReactiveCocoa/ReactiveCocoa/issues?q=is%3Aissue+label%3Aquestion+) or [Stack Overflow](http://stackoverflow.com/questions/tagged/reactive-cocoa) have already answered it. If not, please feel free to [file your own](https://github.com/ReactiveCocoa/ReactiveCocoa/issues/new)! #### Compatibility This documents the RAC 4 (currently alpha) which targets Swift 2.x. For Swift 1.2 support see the [RAC 3](https://github.com/ReactiveCocoa/ReactiveCocoa/tree/v3.0.0). _Many thanks to [Rheinfabrik](http://www.rheinfabrik.de) for generously sponsoring the development of ReactiveCocoa 3!_ ## Introduction ReactiveCocoa is inspired by [functional reactive programming](http://blog.maybeapps.com/post/42894317939/input-and-output). Rather than using mutable variables which are replaced and modified in-place, RAC offers “event streams,” represented by the [`Signal`][Signals] and [`SignalProducer`][Signal producers] types, that send values over time. Event streams unify all of Cocoa’s common patterns for asynchrony and event handling, including: * Delegate methods * Callback blocks * `NSNotification`s * Control actions and responder chain events * [Futures and promises](https://en.wikipedia.org/wiki/Futures_and_promises) * [Key-value observing](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html) (KVO) Because all of these different mechanisms can be represented in the _same_ way, it’s easy to declaratively chain and combine them together, with less spaghetti code and state to bridge the gap. For more information about the concepts in ReactiveCocoa, see the [Framework Overview][]. ## Example: online search Let’s say you have a text field, and whenever the user types something into it, you want to make a network request which searches for that query. #### Observing text edits The first step is to observe edits to the text field, using a RAC extension to `UITextField` specifically for this purpose: ```swift let searchStrings = textField.rac_textSignal() .toSignalProducer() .map { text in text as! String } ``` This gives us a [signal producer][Signal producers] which sends values of type `String`. _(The cast is [currently necessary](https://github.com/ReactiveCocoa/ReactiveCocoa/issues/2182) to bridge this extension method from Objective-C.)_ #### Making network requests With each string, we want to execute a network request. Luckily, RAC offers an `NSURLSession` extension for doing exactly that: ```swift let searchResults = searchStrings .flatMap(.Latest) { (query: String) -> SignalProducer<(NSData, NSURLResponse), NSError> in let URLRequest = self.searchRequestWithEscapedQuery(query) return NSURLSession.sharedSession().rac_dataWithRequest(URLRequest) } .map { (data, URLResponse) -> String in let string = String(data: data, encoding: NSUTF8StringEncoding)! return self.parseJSONResultsFromString(string) } .observeOn(UIScheduler()) ``` This has transformed our producer of `String`s into a producer of `Array`s containing the search results, which will be forwarded on the main thread (thanks to the [`UIScheduler`][Schedulers]). Additionally, [`flatMap(.Latest)`][flatMapLatest] here ensures that _only one search_—the latest—is allowed to be running. If the user types another character while the network request is still in flight, it will be cancelled before starting a new one. Just think of how much code that would take to do by hand! #### Receiving the results This won’t actually execute yet, because producers must be _started_ in order to receive the results (which prevents doing work when the results are never used). That’s easy enough: ```swift searchResults.startWithNext { results in print("Search results: \(results)") } ``` Here, we watch for the `Next` [event][Events], which contains our results, and just log them to the console. This could easily do something else instead, like update a table view or a label on screen. #### Handling failures In this example so far, any network error will generate a `Failed` [event][Events], which will terminate the event stream. Unfortunately, this means that future queries won’t even be attempted. To remedy this, we need to decide what to do with failures that occur. The quickest solution would be to log them, then ignore them: ```swift .flatMap(.Latest) { (query: String) -> SignalProducer<(NSData, NSURLResponse), NSError> in let URLRequest = self.searchRequestWithEscapedQuery(query) return NSURLSession.sharedSession() .rac_dataWithRequest(URLRequest) .flatMapError { error in print("Network error occurred: \(error)") return SignalProducer.empty } } ``` By replacing failures with the `empty` event stream, we’re able to effectively ignore them. However, it’s probably more appropriate to retry at least a couple of times before giving up. Conveniently, there’s a [`retry`][retry] operator to do exactly that! Our improved `searchResults` producer might look like this: ```swift let searchResults = searchStrings .flatMap(.Latest) { (query: String) -> SignalProducer<(NSData, NSURLResponse), NSError> in let URLRequest = self.searchRequestWithEscapedQuery(query) return NSURLSession.sharedSession() .rac_dataWithRequest(URLRequest) .retry(2) .flatMapError { error in print("Network error occurred: \(error)") return SignalProducer.empty } } .map { (data, URLResponse) -> String in let string = String(data: data, encoding: NSUTF8StringEncoding)! return self.parseJSONResultsFromString(string) } .observeOn(UIScheduler()) ``` #### Throttling requests Now, let’s say you only want to actually perform the search when the user pauses typing, to minimize traffic. ReactiveCocoa has a declarative `throttle` operator that we can apply to our search strings: ```swift let searchStrings = textField.rac_textSignal() .toSignalProducer() .map { text in text as! String } .throttle(0.5, onScheduler: QueueScheduler.mainQueueScheduler) ``` This prevents values from being sent less than 0.5 seconds apart, so the user must stop editing for at least that long before we’ll use their search string. To do this manually would require significant state, and end up much harder to read! With ReactiveCocoa, we can use just one operator to incorporate _time_ into our event stream. ## Objective-C and Swift Although ReactiveCocoa was started as an Objective-C framework, as of [version 3.0][CHANGELOG], all major feature development is concentrated on the [Swift API][]. RAC’s [Objective-C API][] and Swift API are entirely separate, but there is a [bridge][Objective-C Bridging] to convert between the two. This is mostly meant as a compatibility layer for older ReactiveCocoa projects, or to use Cocoa extensions which haven’t been added to the Swift API yet. The Objective-C API will continue to exist and be supported for the foreseeable future, but it won’t receive many improvements. For more information about using this API, please consult our [legacy documentation][]. **We highly recommend that all new projects use the Swift API.** ## How does ReactiveCocoa relate to Rx? ReactiveCocoa was originally inspired, and therefore heavily influenced, by Microsoft’s [Reactive Extensions](https://msdn.microsoft.com/en-us/data/gg577609.aspx) (Rx) library. There are many ports of Rx, including [RxSwift](https://github.com/ReactiveX/RxSwift), but ReactiveCocoa is _intentionally_ not a direct port. **Where RAC differs from Rx**, it is usually to: * Create a simpler API * Address common sources of confusion * More closely match Cocoa conventions The following are some of the concrete differences, along with their rationales. ### Naming In most versions of Rx, Streams over time are known as `Observable`s, which parallels the `Enumerable` type in .NET. Additionally, most operations in Rx.NET borrow names from [LINQ](https://msdn.microsoft.com/en-us/library/bb397926.aspx), which uses terms reminiscient of relational databases, like `Select` and `Where`. **RAC is focused on matching Swift naming first and foremost**, with terms like `map` and `filter` instead. Other naming differences are typically inspired by significantly better alternatives from [Haskell](https://www.haskell.org) or [Elm](http://elm-lang.org) (which is the primary source for the “signal” terminology). ### Signals and Signal Producers (“hot” and “cold” observables) One of the most confusing aspects of Rx is that of [“hot”, “cold”, and “warm” observables](http://www.introtorx.com/content/v1.0.10621.0/14_HotAndColdObservables.html) (event streams). In short, given just a method or function declaration like this, in C#: ```csharp IObservable Search(string query) ``` … it is **impossible to tell** whether subscribing to (observing) that `IObservable` will involve side effects. If it _does_ involve side effects, it’s also impossible to tell whether _each subscription_ has a side effect, or if only the first one does. This example is contrived, but it demonstrates **a real, pervasive problem** that makes it extremely hard to understand Rx code (and pre-3.0 ReactiveCocoa code) at a glance. [ReactiveCocoa 3.0][CHANGELOG] has solved this problem by distinguishing side effects with the separate [`Signal`][Signals] and [`SignalProducer`][Signal producers] types. Although this means there’s another type to learn about, it improves code clarity and helps communicates intent much better. In other words, **ReactiveCocoa’s changes here are [simple, not easy](http://www.infoq.com/presentations/Simple-Made-Easy)**. ### Typed errors When [signals][] and [signal producers][] are allowed to [fail][Events] in ReactiveCocoa, the kind of error must be specified in the type system. For example, `Signal` is a signal of integer values that may fail with an error of type `NSError`. More importantly, RAC allows the special type `NoError` to be used instead, which _statically guarantees_ that an event stream is not allowed to send a failure. **This eliminates many bugs caused by unexpected failure events.** In Rx systems with types, event streams only specify the type of their values—not the type of their errors—so this sort of guarantee is impossible. ### UI programming Rx is basically agnostic as to how it’s used. Although UI programming with Rx is very common, it has few features tailored to that particular case. RAC takes a lot of inspiration from [ReactiveUI](http://reactiveui.net/), including the basis for [Actions][]. Unlike ReactiveUI, which unfortunately cannot directly change Rx to make it more friendly for UI programming, **ReactiveCocoa has been improved many times specifically for this purpose**—even when it means diverging further from Rx. ## Getting started ReactiveCocoa supports OS X 10.9+ and iOS 8.0+. To add RAC to your application: 1. Add the ReactiveCocoa repository as a [submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) of your application’s repository. 1. Run `script/bootstrap` from within the ReactiveCocoa folder. 1. Drag and drop `ReactiveCocoa.xcodeproj` and `Carthage/Checkouts/Result/Result.xcodeproj` into your application’s Xcode project or workspace. 1. On the “General” tab of your application target’s settings, add `ReactiveCocoa.framework` and `Result.framework` to the “Embedded Binaries” section. 1. If your application target does not contain Swift code at all, you should also set the `EMBEDDED_CONTENT_CONTAINS_SWIFT` build setting to “Yes”. Or, if you’re using [Carthage](https://github.com/Carthage/Carthage), simply add ReactiveCocoa to your `Cartfile`: ``` github "ReactiveCocoa/ReactiveCocoa" ``` If you would prefer to use [CocoaPods](https://cocoapods.org), there are some [unofficial podspecs](https://github.com/CocoaPods/Specs/tree/master/Specs/ReactiveCocoa) that have been generously contributed by third parties. Once you’ve set up your project, check out the [Framework Overview][] for a tour of ReactiveCocoa’s concepts, and the [Basic Operators][] for some introductory examples of using it. [Actions]: Documentation/FrameworkOverview.md#actions [Basic Operators]: Documentation/BasicOperators.md [CHANGELOG]: CHANGELOG.md [Code]: ReactiveCocoa [Documentation]: Documentation [Events]: Documentation/FrameworkOverview.md#events [Framework Overview]: Documentation/FrameworkOverview.md [Legacy Documentation]: Documentation/Legacy [Objective-C API]: ReactiveCocoa/Objective-C [Objective-C Bridging]: Documentation/ObjectiveCBridging.md [Schedulers]: Documentation/FrameworkOverview.md#schedulers [Signal producers]: Documentation/FrameworkOverview.md#signal-producers [Signals]: Documentation/FrameworkOverview.md#signals [Swift API]: ReactiveCocoa/Swift [flatMapLatest]: Documentation/BasicOperators.md#switching-to-the-latest [retry]: Documentation/BasicOperators.md#retrying ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/MKAnnotationView+RACSignalSupport.h ================================================ // // MKAnnotationView+RACSignalSupport.h // ReactiveCocoa // // Created by Zak Remer on 3/31/15. // Copyright (c) 2015 GitHub. All rights reserved. // #import #import @class RACSignal; @interface MKAnnotationView (RACSignalSupport) /// A signal which will send a RACUnit whenever -prepareForReuse is invoked upon /// the receiver. /// /// Examples /// /// [[[self.cancelButton /// rac_signalForControlEvents:UIControlEventTouchUpInside] /// takeUntil:self.rac_prepareForReuseSignal] /// subscribeNext:^(UIButton *x) { /// // do other things /// }]; @property (nonatomic, strong, readonly) RACSignal *rac_prepareForReuseSignal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/MKAnnotationView+RACSignalSupport.m ================================================ // // MKAnnotationView+RACSignalSupport.m // ReactiveCocoa // // Created by Zak Remer on 3/31/15. // Copyright (c) 2015 GitHub. All rights reserved. // #import "MKAnnotationView+RACSignalSupport.h" #import "NSObject+RACDescription.h" #import "NSObject+RACSelectorSignal.h" #import "RACSignal+Operations.h" #import "RACUnit.h" #import @implementation MKAnnotationView (RACSignalSupport) - (RACSignal *)rac_prepareForReuseSignal { RACSignal *signal = objc_getAssociatedObject(self, _cmd); if (signal != nil) return signal; signal = [[[self rac_signalForSelector:@selector(prepareForReuse)] mapReplace:RACUnit.defaultUnit] setNameWithFormat:@"%@ -rac_prepareForReuseSignal", RACDescription(self)]; objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return signal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSArray+RACSequenceAdditions.h ================================================ // // NSArray+RACSequenceAdditions.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import @class RACSequence; @interface NSArray (RACSequenceAdditions) /// Creates and returns a sequence corresponding to the receiver. /// /// Mutating the receiver will not affect the sequence after it's been created. @property (nonatomic, copy, readonly) RACSequence *rac_sequence; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSArray+RACSequenceAdditions.m ================================================ // // NSArray+RACSequenceAdditions.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "NSArray+RACSequenceAdditions.h" #import "RACArraySequence.h" @implementation NSArray (RACSequenceAdditions) - (RACSequence *)rac_sequence { return [RACArraySequence sequenceWithArray:self offset:0]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSData+RACSupport.h ================================================ // // NSData+RACSupport.h // ReactiveCocoa // // Created by Josh Abernathy on 5/11/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACScheduler; @class RACSignal; @interface NSData (RACSupport) // Read the data at the URL using -[NSData initWithContentsOfURL:options:error:]. // Sends the data or the error. // // scheduler - cannot be nil. + (RACSignal *)rac_readContentsOfURL:(NSURL *)URL options:(NSDataReadingOptions)options scheduler:(RACScheduler *)scheduler; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSData+RACSupport.m ================================================ // // NSData+RACSupport.m // ReactiveCocoa // // Created by Josh Abernathy on 5/11/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "NSData+RACSupport.h" #import "RACReplaySubject.h" #import "RACScheduler.h" @implementation NSData (RACSupport) + (RACSignal *)rac_readContentsOfURL:(NSURL *)URL options:(NSDataReadingOptions)options scheduler:(RACScheduler *)scheduler { NSCParameterAssert(scheduler != nil); RACReplaySubject *subject = [RACReplaySubject subject]; [subject setNameWithFormat:@"+rac_readContentsOfURL: %@ options: %lu scheduler: %@", URL, (unsigned long)options, scheduler]; [scheduler schedule:^{ NSError *error = nil; NSData *data = [[NSData alloc] initWithContentsOfURL:URL options:options error:&error]; if (data == nil) { [subject sendError:error]; } else { [subject sendNext:data]; [subject sendCompleted]; } }]; return subject; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSDictionary+RACSequenceAdditions.h ================================================ // // NSDictionary+RACSequenceAdditions.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import @class RACSequence; @interface NSDictionary (RACSequenceAdditions) /// Creates and returns a sequence of RACTuple key/value pairs. The key will be /// the first element in the tuple, and the value will be the second. /// /// Mutating the receiver will not affect the sequence after it's been created. @property (nonatomic, copy, readonly) RACSequence *rac_sequence; /// Creates and returns a sequence corresponding to the keys in the receiver. /// /// Mutating the receiver will not affect the sequence after it's been created. @property (nonatomic, copy, readonly) RACSequence *rac_keySequence; /// Creates and returns a sequence corresponding to the values in the receiver. /// /// Mutating the receiver will not affect the sequence after it's been created. @property (nonatomic, copy, readonly) RACSequence *rac_valueSequence; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSDictionary+RACSequenceAdditions.m ================================================ // // NSDictionary+RACSequenceAdditions.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "NSDictionary+RACSequenceAdditions.h" #import "NSArray+RACSequenceAdditions.h" #import "RACSequence.h" #import "RACTuple.h" @implementation NSDictionary (RACSequenceAdditions) - (RACSequence *)rac_sequence { NSDictionary *immutableDict = [self copy]; // TODO: First class support for dictionary sequences. return [immutableDict.allKeys.rac_sequence map:^(id key) { id value = immutableDict[key]; return RACTuplePack(key, value); }]; } - (RACSequence *)rac_keySequence { return self.allKeys.rac_sequence; } - (RACSequence *)rac_valueSequence { return self.allValues.rac_sequence; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSEnumerator+RACSequenceAdditions.h ================================================ // // NSEnumerator+RACSequenceAdditions.h // ReactiveCocoa // // Created by Uri Baghin on 07/01/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACSequence; @interface NSEnumerator (RACSequenceAdditions) /// Creates and returns a sequence corresponding to the receiver. /// /// The receiver is exhausted lazily as the sequence is enumerated. @property (nonatomic, copy, readonly) RACSequence *rac_sequence; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSEnumerator+RACSequenceAdditions.m ================================================ // // NSEnumerator+RACSequenceAdditions.m // ReactiveCocoa // // Created by Uri Baghin on 07/01/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "NSEnumerator+RACSequenceAdditions.h" #import "RACSequence.h" @implementation NSEnumerator (RACSequenceAdditions) - (RACSequence *)rac_sequence { return [RACSequence sequenceWithHeadBlock:^{ return [self nextObject]; } tailBlock:^{ return self.rac_sequence; }]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSFileHandle+RACSupport.h ================================================ // // NSFileHandle+RACSupport.h // ReactiveCocoa // // Created by Josh Abernathy on 5/10/12. // Copyright (c) 2012 GitHub. All rights reserved. // #import @class RACSignal; @interface NSFileHandle (RACSupport) // Read any available data in the background and send it. Completes when data // length is <= 0. - (RACSignal *)rac_readInBackground; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSFileHandle+RACSupport.m ================================================ // // NSFileHandle+RACSupport.m // ReactiveCocoa // // Created by Josh Abernathy on 5/10/12. // Copyright (c) 2012 GitHub. All rights reserved. // #import "NSFileHandle+RACSupport.h" #import "NSNotificationCenter+RACSupport.h" #import "NSObject+RACDescription.h" #import "RACReplaySubject.h" #import "RACDisposable.h" @implementation NSFileHandle (RACSupport) - (RACSignal *)rac_readInBackground { RACReplaySubject *subject = [RACReplaySubject subject]; [subject setNameWithFormat:@"%@ -rac_readInBackground", RACDescription(self)]; RACSignal *dataNotification = [[[NSNotificationCenter defaultCenter] rac_addObserverForName:NSFileHandleReadCompletionNotification object:self] map:^(NSNotification *note) { return note.userInfo[NSFileHandleNotificationDataItem]; }]; __block RACDisposable *subscription = [dataNotification subscribeNext:^(NSData *data) { if (data.length > 0) { [subject sendNext:data]; [self readInBackgroundAndNotify]; } else { [subject sendCompleted]; [subscription dispose]; } }]; [self readInBackgroundAndNotify]; return subject; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSIndexSet+RACSequenceAdditions.h ================================================ // // NSIndexSet+RACSequenceAdditions.h // ReactiveCocoa // // Created by Sergey Gavrilyuk on 12/17/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACSequence; @interface NSIndexSet (RACSequenceAdditions) /// Creates and returns a sequence of indexes (as `NSNumber`s) corresponding to /// the receiver. /// /// Mutating the receiver will not affect the sequence after it's been created. @property (nonatomic, copy, readonly) RACSequence *rac_sequence; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSIndexSet+RACSequenceAdditions.m ================================================ // // NSIndexSet+RACSequenceAdditions.m // ReactiveCocoa // // Created by Sergey Gavrilyuk on 12/17/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "NSIndexSet+RACSequenceAdditions.h" #import "RACIndexSetSequence.h" @implementation NSIndexSet (RACSequenceAdditions) - (RACSequence *)rac_sequence { return [RACIndexSetSequence sequenceWithIndexSet:self]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSInvocation+RACTypeParsing.h ================================================ // // NSInvocation+RACTypeParsing.h // ReactiveCocoa // // Created by Josh Abernathy on 11/17/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACTuple; // A private category of methods to handle wrapping and unwrapping of values. @interface NSInvocation (RACTypeParsing) // Sets the argument for the invocation at the given index by unboxing the given // object based on the type signature of the argument. // // This does not support C arrays or unions. // // Note that calling this on a char * or const char * argument can cause all // arguments to be retained. // // object - The object to unbox and set as the argument. // index - The index of the argument to set. - (void)rac_setArgument:(id)object atIndex:(NSUInteger)index; // Gets the argument for the invocation at the given index based on the // invocation's method signature. The value is then wrapped in the appropriate // object type. // // This does not support C arrays or unions. // // index - The index of the argument to get. // // Returns the argument of the invocation, wrapped in an object. - (id)rac_argumentAtIndex:(NSUInteger)index; // Arguments tuple for the invocation. // // The arguments tuple excludes implicit variables `self` and `_cmd`. // // See -rac_argumentAtIndex: and -rac_setArgumentAtIndex: for further // description of the underlying behavior. @property (nonatomic, copy) RACTuple *rac_argumentsTuple; // Gets the return value from the invocation based on the invocation's method // signature. The value is then wrapped in the appropriate object type. // // This does not support C arrays or unions. // // Returns the return value of the invocation, wrapped in an object. Voids are // returned as `RACUnit.defaultUnit`. - (id)rac_returnValue; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSInvocation+RACTypeParsing.m ================================================ // // NSInvocation+RACTypeParsing.m // ReactiveCocoa // // Created by Josh Abernathy on 11/17/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "NSInvocation+RACTypeParsing.h" #import "RACTuple.h" #import "RACUnit.h" #import @implementation NSInvocation (RACTypeParsing) - (void)rac_setArgument:(id)object atIndex:(NSUInteger)index { #define PULL_AND_SET(type, selector) \ do { \ type val = [object selector]; \ [self setArgument:&val atIndex:(NSInteger)index]; \ } while (0) const char *argType = [self.methodSignature getArgumentTypeAtIndex:index]; // Skip const type qualifier. if (argType[0] == 'r') { argType++; } if (strcmp(argType, @encode(id)) == 0 || strcmp(argType, @encode(Class)) == 0) { [self setArgument:&object atIndex:(NSInteger)index]; } else if (strcmp(argType, @encode(char)) == 0) { PULL_AND_SET(char, charValue); } else if (strcmp(argType, @encode(int)) == 0) { PULL_AND_SET(int, intValue); } else if (strcmp(argType, @encode(short)) == 0) { PULL_AND_SET(short, shortValue); } else if (strcmp(argType, @encode(long)) == 0) { PULL_AND_SET(long, longValue); } else if (strcmp(argType, @encode(long long)) == 0) { PULL_AND_SET(long long, longLongValue); } else if (strcmp(argType, @encode(unsigned char)) == 0) { PULL_AND_SET(unsigned char, unsignedCharValue); } else if (strcmp(argType, @encode(unsigned int)) == 0) { PULL_AND_SET(unsigned int, unsignedIntValue); } else if (strcmp(argType, @encode(unsigned short)) == 0) { PULL_AND_SET(unsigned short, unsignedShortValue); } else if (strcmp(argType, @encode(unsigned long)) == 0) { PULL_AND_SET(unsigned long, unsignedLongValue); } else if (strcmp(argType, @encode(unsigned long long)) == 0) { PULL_AND_SET(unsigned long long, unsignedLongLongValue); } else if (strcmp(argType, @encode(float)) == 0) { PULL_AND_SET(float, floatValue); } else if (strcmp(argType, @encode(double)) == 0) { PULL_AND_SET(double, doubleValue); } else if (strcmp(argType, @encode(BOOL)) == 0) { PULL_AND_SET(BOOL, boolValue); } else if (strcmp(argType, @encode(char *)) == 0) { const char *cString = [object UTF8String]; [self setArgument:&cString atIndex:(NSInteger)index]; [self retainArguments]; } else if (strcmp(argType, @encode(void (^)(void))) == 0) { [self setArgument:&object atIndex:(NSInteger)index]; } else { NSCParameterAssert([object isKindOfClass:NSValue.class]); NSUInteger valueSize = 0; NSGetSizeAndAlignment([object objCType], &valueSize, NULL); #if DEBUG NSUInteger argSize = 0; NSGetSizeAndAlignment(argType, &argSize, NULL); NSCAssert(valueSize == argSize, @"Value size does not match argument size in -rac_setArgument: %@ atIndex: %lu", object, (unsigned long)index); #endif unsigned char valueBytes[valueSize]; [object getValue:valueBytes]; [self setArgument:valueBytes atIndex:(NSInteger)index]; } #undef PULL_AND_SET } - (id)rac_argumentAtIndex:(NSUInteger)index { #define WRAP_AND_RETURN(type) \ do { \ type val = 0; \ [self getArgument:&val atIndex:(NSInteger)index]; \ return @(val); \ } while (0) const char *argType = [self.methodSignature getArgumentTypeAtIndex:index]; // Skip const type qualifier. if (argType[0] == 'r') { argType++; } if (strcmp(argType, @encode(id)) == 0 || strcmp(argType, @encode(Class)) == 0) { __autoreleasing id returnObj; [self getArgument:&returnObj atIndex:(NSInteger)index]; return returnObj; } else if (strcmp(argType, @encode(char)) == 0) { WRAP_AND_RETURN(char); } else if (strcmp(argType, @encode(int)) == 0) { WRAP_AND_RETURN(int); } else if (strcmp(argType, @encode(short)) == 0) { WRAP_AND_RETURN(short); } else if (strcmp(argType, @encode(long)) == 0) { WRAP_AND_RETURN(long); } else if (strcmp(argType, @encode(long long)) == 0) { WRAP_AND_RETURN(long long); } else if (strcmp(argType, @encode(unsigned char)) == 0) { WRAP_AND_RETURN(unsigned char); } else if (strcmp(argType, @encode(unsigned int)) == 0) { WRAP_AND_RETURN(unsigned int); } else if (strcmp(argType, @encode(unsigned short)) == 0) { WRAP_AND_RETURN(unsigned short); } else if (strcmp(argType, @encode(unsigned long)) == 0) { WRAP_AND_RETURN(unsigned long); } else if (strcmp(argType, @encode(unsigned long long)) == 0) { WRAP_AND_RETURN(unsigned long long); } else if (strcmp(argType, @encode(float)) == 0) { WRAP_AND_RETURN(float); } else if (strcmp(argType, @encode(double)) == 0) { WRAP_AND_RETURN(double); } else if (strcmp(argType, @encode(BOOL)) == 0) { WRAP_AND_RETURN(BOOL); } else if (strcmp(argType, @encode(char *)) == 0) { WRAP_AND_RETURN(const char *); } else if (strcmp(argType, @encode(void (^)(void))) == 0) { __unsafe_unretained id block = nil; [self getArgument:&block atIndex:(NSInteger)index]; return [block copy]; } else { NSUInteger valueSize = 0; NSGetSizeAndAlignment(argType, &valueSize, NULL); unsigned char valueBytes[valueSize]; [self getArgument:valueBytes atIndex:(NSInteger)index]; return [NSValue valueWithBytes:valueBytes objCType:argType]; } return nil; #undef WRAP_AND_RETURN } - (RACTuple *)rac_argumentsTuple { NSUInteger numberOfArguments = self.methodSignature.numberOfArguments; NSMutableArray *argumentsArray = [NSMutableArray arrayWithCapacity:numberOfArguments - 2]; for (NSUInteger index = 2; index < numberOfArguments; index++) { [argumentsArray addObject:[self rac_argumentAtIndex:index] ?: RACTupleNil.tupleNil]; } return [RACTuple tupleWithObjectsFromArray:argumentsArray]; } - (void)setRac_argumentsTuple:(RACTuple *)arguments { NSCAssert(arguments.count == self.methodSignature.numberOfArguments - 2, @"Number of supplied arguments (%lu), does not match the number expected by the signature (%lu)", (unsigned long)arguments.count, (unsigned long)self.methodSignature.numberOfArguments - 2); NSUInteger index = 2; for (id arg in arguments) { [self rac_setArgument:(arg == RACTupleNil.tupleNil ? nil : arg) atIndex:index]; index++; } } - (id)rac_returnValue { #define WRAP_AND_RETURN(type) \ do { \ type val = 0; \ [self getReturnValue:&val]; \ return @(val); \ } while (0) const char *returnType = self.methodSignature.methodReturnType; // Skip const type qualifier. if (returnType[0] == 'r') { returnType++; } if (strcmp(returnType, @encode(id)) == 0 || strcmp(returnType, @encode(Class)) == 0 || strcmp(returnType, @encode(void (^)(void))) == 0) { __autoreleasing id returnObj; [self getReturnValue:&returnObj]; return returnObj; } else if (strcmp(returnType, @encode(char)) == 0) { WRAP_AND_RETURN(char); } else if (strcmp(returnType, @encode(int)) == 0) { WRAP_AND_RETURN(int); } else if (strcmp(returnType, @encode(short)) == 0) { WRAP_AND_RETURN(short); } else if (strcmp(returnType, @encode(long)) == 0) { WRAP_AND_RETURN(long); } else if (strcmp(returnType, @encode(long long)) == 0) { WRAP_AND_RETURN(long long); } else if (strcmp(returnType, @encode(unsigned char)) == 0) { WRAP_AND_RETURN(unsigned char); } else if (strcmp(returnType, @encode(unsigned int)) == 0) { WRAP_AND_RETURN(unsigned int); } else if (strcmp(returnType, @encode(unsigned short)) == 0) { WRAP_AND_RETURN(unsigned short); } else if (strcmp(returnType, @encode(unsigned long)) == 0) { WRAP_AND_RETURN(unsigned long); } else if (strcmp(returnType, @encode(unsigned long long)) == 0) { WRAP_AND_RETURN(unsigned long long); } else if (strcmp(returnType, @encode(float)) == 0) { WRAP_AND_RETURN(float); } else if (strcmp(returnType, @encode(double)) == 0) { WRAP_AND_RETURN(double); } else if (strcmp(returnType, @encode(BOOL)) == 0) { WRAP_AND_RETURN(BOOL); } else if (strcmp(returnType, @encode(char *)) == 0) { WRAP_AND_RETURN(const char *); } else if (strcmp(returnType, @encode(void)) == 0) { return RACUnit.defaultUnit; } else { NSUInteger valueSize = 0; NSGetSizeAndAlignment(returnType, &valueSize, NULL); unsigned char valueBytes[valueSize]; [self getReturnValue:valueBytes]; return [NSValue valueWithBytes:valueBytes objCType:returnType]; } return nil; #undef WRAP_AND_RETURN } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSNotificationCenter+RACSupport.h ================================================ // // NSNotificationCenter+RACSupport.h // ReactiveCocoa // // Created by Josh Abernathy on 5/10/12. // Copyright (c) 2012 GitHub. All rights reserved. // #import @class RACSignal; @interface NSNotificationCenter (RACSupport) // Sends the NSNotification every time the notification is posted. - (RACSignal *)rac_addObserverForName:(NSString *)notificationName object:(id)object; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSNotificationCenter+RACSupport.m ================================================ // // NSNotificationCenter+RACSupport.m // ReactiveCocoa // // Created by Josh Abernathy on 5/10/12. // Copyright (c) 2012 GitHub. All rights reserved. // #import "NSNotificationCenter+RACSupport.h" #import "EXTScope.h" #import "RACSignal.h" #import "RACSubscriber.h" #import "RACDisposable.h" @implementation NSNotificationCenter (RACSupport) - (RACSignal *)rac_addObserverForName:(NSString *)notificationName object:(id)object { @unsafeify(object); return [[RACSignal createSignal:^(id subscriber) { @strongify(object); id observer = [self addObserverForName:notificationName object:object queue:nil usingBlock:^(NSNotification *note) { [subscriber sendNext:note]; }]; return [RACDisposable disposableWithBlock:^{ [self removeObserver:observer]; }]; }] setNameWithFormat:@"-rac_addObserverForName: %@ object: <%@: %p>", notificationName, [object class], object]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACDeallocating.h ================================================ // // NSObject+RACDeallocating.h // ReactiveCocoa // // Created by Kazuo Koga on 2013/03/15. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACCompoundDisposable; @class RACDisposable; @class RACSignal; @interface NSObject (RACDeallocating) /// The compound disposable which will be disposed of when the receiver is /// deallocated. @property (atomic, readonly, strong) RACCompoundDisposable *rac_deallocDisposable; /// Returns a signal that will complete immediately before the receiver is fully /// deallocated. If already deallocated when the signal is subscribed to, /// a `completed` event will be sent immediately. - (RACSignal *)rac_willDeallocSignal; @end @interface NSObject (RACUnavailableDeallocating) - (RACSignal *)rac_didDeallocSignal __attribute__((unavailable("Use -rac_willDeallocSignal"))); - (void)rac_addDeallocDisposable:(RACDisposable *)disposable __attribute__((unavailable("Add disposables to -rac_deallocDisposable instead"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACDeallocating.m ================================================ // // NSObject+RACDeallocating.m // ReactiveCocoa // // Created by Kazuo Koga on 2013/03/15. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "NSObject+RACDeallocating.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACReplaySubject.h" #import #import static const void *RACObjectCompoundDisposable = &RACObjectCompoundDisposable; static NSMutableSet *swizzledClasses() { static dispatch_once_t onceToken; static NSMutableSet *swizzledClasses = nil; dispatch_once(&onceToken, ^{ swizzledClasses = [[NSMutableSet alloc] init]; }); return swizzledClasses; } static void swizzleDeallocIfNeeded(Class classToSwizzle) { @synchronized (swizzledClasses()) { NSString *className = NSStringFromClass(classToSwizzle); if ([swizzledClasses() containsObject:className]) return; SEL deallocSelector = sel_registerName("dealloc"); __block void (*originalDealloc)(__unsafe_unretained id, SEL) = NULL; id newDealloc = ^(__unsafe_unretained id self) { RACCompoundDisposable *compoundDisposable = objc_getAssociatedObject(self, RACObjectCompoundDisposable); [compoundDisposable dispose]; if (originalDealloc == NULL) { struct objc_super superInfo = { .receiver = self, .super_class = class_getSuperclass(classToSwizzle) }; void (*msgSend)(struct objc_super *, SEL) = (__typeof__(msgSend))objc_msgSendSuper; msgSend(&superInfo, deallocSelector); } else { originalDealloc(self, deallocSelector); } }; IMP newDeallocIMP = imp_implementationWithBlock(newDealloc); if (!class_addMethod(classToSwizzle, deallocSelector, newDeallocIMP, "v@:")) { // The class already contains a method implementation. Method deallocMethod = class_getInstanceMethod(classToSwizzle, deallocSelector); // We need to store original implementation before setting new implementation // in case method is called at the time of setting. originalDealloc = (__typeof__(originalDealloc))method_getImplementation(deallocMethod); // We need to store original implementation again, in case it just changed. originalDealloc = (__typeof__(originalDealloc))method_setImplementation(deallocMethod, newDeallocIMP); } [swizzledClasses() addObject:className]; } } @implementation NSObject (RACDeallocating) - (RACSignal *)rac_willDeallocSignal { RACSignal *signal = objc_getAssociatedObject(self, _cmd); if (signal != nil) return signal; RACReplaySubject *subject = [RACReplaySubject subject]; [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ [subject sendCompleted]; }]]; objc_setAssociatedObject(self, _cmd, subject, OBJC_ASSOCIATION_RETAIN); return subject; } - (RACCompoundDisposable *)rac_deallocDisposable { @synchronized (self) { RACCompoundDisposable *compoundDisposable = objc_getAssociatedObject(self, RACObjectCompoundDisposable); if (compoundDisposable != nil) return compoundDisposable; swizzleDeallocIfNeeded(self.class); compoundDisposable = [RACCompoundDisposable compoundDisposable]; objc_setAssociatedObject(self, RACObjectCompoundDisposable, compoundDisposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return compoundDisposable; } } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACDescription.h ================================================ // // NSObject+RACDescription.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-05-13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import // A simplified description of the object, which does not invoke -description // (and thus should be much faster in many cases). // // This is for debugging purposes only, and will return a constant string // unless the RAC_DEBUG_SIGNAL_NAMES environment variable is set. NSString *RACDescription(id object); ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACDescription.m ================================================ // // NSObject+RACDescription.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-05-13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "NSObject+RACDescription.h" #import "RACTuple.h" @implementation NSValue (RACDescription) - (NSString *)rac_description { return self.description; } @end @implementation NSString (RACDescription) - (NSString *)rac_description { return self.description; } @end @implementation RACTuple (RACDescription) - (NSString *)rac_description { if (getenv("RAC_DEBUG_SIGNAL_NAMES") != NULL) { return self.allObjects.description; } else { return @"(description skipped)"; } } @end NSString *RACDescription(id object) { if (getenv("RAC_DEBUG_SIGNAL_NAMES") != NULL) { if ([object respondsToSelector:@selector(rac_description)]) { return [object rac_description]; } else { return [[NSString alloc] initWithFormat:@"<%@: %p>", [object class], object]; } } else { return @"(description skipped)"; } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACKVOWrapper.h ================================================ // // NSObject+RACKVOWrapper.h // ReactiveCocoa // // Created by Josh Abernathy on 10/11/11. // Copyright (c) 2011 GitHub. All rights reserved. // #import @class RACDisposable; @class RACKVOTrampoline; // A private category providing a block based interface to KVO. @interface NSObject (RACKVOWrapper) // Adds the given block as the callbacks for when the key path changes. // // Unlike direct KVO observation, this handles deallocation of `weak` properties // by generating an appropriate notification. This will only occur if there is // an `@property` declaration visible in the observed class, with the `weak` // memory management attribute. // // The observation does not need to be explicitly removed. It will be removed // when the observer or the receiver deallocate. // // keyPath - The key path to observe. Must not be nil. // options - The KVO observation options. // observer - The object that requested the observation. May be nil. // block - The block called when the value at the key path changes. It is // passed the current value of the key path and the extended KVO // change dictionary including RAC-specific keys and values. Must not // be nil. // // Returns a disposable that can be used to stop the observation. - (RACDisposable *)rac_observeKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(__weak NSObject *)observer block:(void (^)(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent))block; @end typedef void (^RACKVOBlock)(id target, id observer, NSDictionary *change); @interface NSObject (RACUnavailableKVOWrapper) - (RACKVOTrampoline *)rac_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(RACKVOBlock)block __attribute((unavailable("Use rac_observeKeyPath:options:observer:block: instead."))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACKVOWrapper.m ================================================ // // NSObject+RACKVOWrapper.m // ReactiveCocoa // // Created by Josh Abernathy on 10/11/11. // Copyright (c) 2011 GitHub. All rights reserved. // #import "NSObject+RACKVOWrapper.h" #import "EXTRuntimeExtensions.h" #import "EXTScope.h" #import "NSObject+RACDeallocating.h" #import "NSString+RACKeyPathUtilities.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACKVOTrampoline.h" #import "RACSerialDisposable.h" @implementation NSObject (RACKVOWrapper) - (RACDisposable *)rac_observeKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(__weak NSObject *)weakObserver block:(void (^)(id, NSDictionary *, BOOL, BOOL))block { NSCParameterAssert(block != nil); NSCParameterAssert(keyPath.rac_keyPathComponents.count > 0); keyPath = [keyPath copy]; NSObject *strongObserver = weakObserver; NSArray *keyPathComponents = keyPath.rac_keyPathComponents; BOOL keyPathHasOneComponent = (keyPathComponents.count == 1); NSString *keyPathHead = keyPathComponents[0]; NSString *keyPathTail = keyPath.rac_keyPathByDeletingFirstKeyPathComponent; RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; // The disposable that groups all disposal necessary to clean up the callbacks // added to the value of the first key path component. RACSerialDisposable *firstComponentSerialDisposable = [RACSerialDisposable serialDisposableWithDisposable:[RACCompoundDisposable compoundDisposable]]; RACCompoundDisposable * (^firstComponentDisposable)(void) = ^{ return (RACCompoundDisposable *)firstComponentSerialDisposable.disposable; }; [disposable addDisposable:firstComponentSerialDisposable]; BOOL shouldAddDeallocObserver = NO; objc_property_t property = class_getProperty(object_getClass(self), keyPathHead.UTF8String); if (property != NULL) { rac_propertyAttributes *attributes = rac_copyPropertyAttributes(property); if (attributes != NULL) { @onExit { free(attributes); }; BOOL isObject = attributes->objectClass != nil || strstr(attributes->type, @encode(id)) == attributes->type; BOOL isProtocol = attributes->objectClass == NSClassFromString(@"Protocol"); BOOL isBlock = strcmp(attributes->type, @encode(void(^)())) == 0; BOOL isWeak = attributes->weak; // If this property isn't actually an object (or is a Class object), // no point in observing the deallocation of the wrapper returned by // KVC. // // If this property is an object, but not declared `weak`, we // don't need to watch for it spontaneously being set to nil. // // Attempting to observe non-weak properties will result in // broken behavior for dynamic getters, so don't even try. shouldAddDeallocObserver = isObject && isWeak && !isBlock && !isProtocol; } } // Adds the callback block to the value's deallocation. Also adds the logic to // clean up the callback to the firstComponentDisposable. void (^addDeallocObserverToPropertyValue)(NSObject *) = ^(NSObject *value) { if (!shouldAddDeallocObserver) return; // If a key path value is the observer, commonly when a key path begins // with "self", we prevent deallocation triggered callbacks for any such key // path components. Thus, the observer's deallocation is not considered a // change to the key path. if (value == weakObserver) return; NSDictionary *change = @{ NSKeyValueChangeKindKey: @(NSKeyValueChangeSetting), NSKeyValueChangeNewKey: NSNull.null, }; RACCompoundDisposable *valueDisposable = value.rac_deallocDisposable; RACDisposable *deallocDisposable = [RACDisposable disposableWithBlock:^{ block(nil, change, YES, keyPathHasOneComponent); }]; [valueDisposable addDisposable:deallocDisposable]; [firstComponentDisposable() addDisposable:[RACDisposable disposableWithBlock:^{ [valueDisposable removeDisposable:deallocDisposable]; }]]; }; // Adds the callback block to the remaining path components on the value. Also // adds the logic to clean up the callbacks to the firstComponentDisposable. void (^addObserverToValue)(NSObject *) = ^(NSObject *value) { RACDisposable *observerDisposable = [value rac_observeKeyPath:keyPathTail options:(options & ~NSKeyValueObservingOptionInitial) observer:weakObserver block:block]; [firstComponentDisposable() addDisposable:observerDisposable]; }; // Observe only the first key path component, when the value changes clean up // the callbacks on the old value, add callbacks to the new value and call the // callback block as needed. // // Note this does not use NSKeyValueObservingOptionInitial so this only // handles changes to the value, callbacks to the initial value must be added // separately. NSKeyValueObservingOptions trampolineOptions = (options | NSKeyValueObservingOptionPrior) & ~NSKeyValueObservingOptionInitial; RACKVOTrampoline *trampoline = [[RACKVOTrampoline alloc] initWithTarget:self observer:strongObserver keyPath:keyPathHead options:trampolineOptions block:^(id trampolineTarget, id trampolineObserver, NSDictionary *change) { // If this is a prior notification, clean up all the callbacks added to the // previous value and call the callback block. Everything else is deferred // until after we get the notification after the change. if ([change[NSKeyValueChangeNotificationIsPriorKey] boolValue]) { [firstComponentDisposable() dispose]; if ((options & NSKeyValueObservingOptionPrior) != 0) { block([trampolineTarget valueForKeyPath:keyPath], change, NO, keyPathHasOneComponent); } return; } // From here the notification is not prior. NSObject *value = [trampolineTarget valueForKey:keyPathHead]; // If the value has changed but is nil, there is no need to add callbacks to // it, just call the callback block. if (value == nil) { block(nil, change, NO, keyPathHasOneComponent); return; } // From here the notification is not prior and the value is not nil. // Create a new firstComponentDisposable while getting rid of the old one at // the same time, in case this is being called concurrently. RACDisposable *oldFirstComponentDisposable = [firstComponentSerialDisposable swapInDisposable:[RACCompoundDisposable compoundDisposable]]; [oldFirstComponentDisposable dispose]; addDeallocObserverToPropertyValue(value); // If there are no further key path components, there is no need to add the // other callbacks, just call the callback block with the value itself. if (keyPathHasOneComponent) { block(value, change, NO, keyPathHasOneComponent); return; } // The value has changed, is not nil, and there are more key path components // to consider. Add the callbacks to the value for the remaining key path // components and call the callback block with the current value of the full // key path. addObserverToValue(value); block([value valueForKeyPath:keyPathTail], change, NO, keyPathHasOneComponent); }]; // Stop the KVO observation when this one is disposed of. [disposable addDisposable:trampoline]; // Add the callbacks to the initial value if needed. NSObject *value = [self valueForKey:keyPathHead]; if (value != nil) { addDeallocObserverToPropertyValue(value); if (!keyPathHasOneComponent) { addObserverToValue(value); } } // Call the block with the initial value if needed. if ((options & NSKeyValueObservingOptionInitial) != 0) { id initialValue = [self valueForKeyPath:keyPath]; NSDictionary *initialChange = @{ NSKeyValueChangeKindKey: @(NSKeyValueChangeSetting), NSKeyValueChangeNewKey: initialValue ?: NSNull.null, }; block(initialValue, initialChange, NO, keyPathHasOneComponent); } RACCompoundDisposable *observerDisposable = strongObserver.rac_deallocDisposable; RACCompoundDisposable *selfDisposable = self.rac_deallocDisposable; // Dispose of this observation if the receiver or the observer deallocate. [observerDisposable addDisposable:disposable]; [selfDisposable addDisposable:disposable]; return [RACDisposable disposableWithBlock:^{ [disposable dispose]; [observerDisposable removeDisposable:disposable]; [selfDisposable removeDisposable:disposable]; }]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACLifting.h ================================================ // // NSObject+RACLifting.h // ReactiveCocoa // // Created by Josh Abernathy on 10/13/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACSignal; @interface NSObject (RACLifting) /// Lifts the selector on the receiver into the reactive world. The selector will /// be invoked whenever any signal argument sends a value, but only after each /// signal has sent an initial value. /// /// It will replay the most recently sent value to new subscribers. /// /// This does not support C arrays or unions. /// /// selector - The selector on self to invoke. /// firstSignal - The signal corresponding to the first method argument. This /// must not be nil. /// ... - A list of RACSignals corresponding to the remaining arguments. /// There must be a non-nil signal for each method argument. /// /// Examples /// /// [button rac_liftSelector:@selector(setTitleColor:forState:) withSignals:textColorSignal, [RACSignal return:@(UIControlStateNormal)], nil]; /// /// Returns a signal which sends the return value from each invocation of the /// selector. If the selector returns void, it instead sends RACUnit.defaultUnit. /// It completes only after all the signal arguments complete. - (RACSignal *)rac_liftSelector:(SEL)selector withSignals:(RACSignal *)firstSignal, ... NS_REQUIRES_NIL_TERMINATION; /// Like -rac_liftSelector:withSignals:, but accepts an array instead of /// a variadic list of arguments. - (RACSignal *)rac_liftSelector:(SEL)selector withSignalsFromArray:(NSArray *)signals; /// Like -rac_liftSelector:withSignals:, but accepts a signal sending tuples of /// arguments instead of a variadic list of arguments. - (RACSignal *)rac_liftSelector:(SEL)selector withSignalOfArguments:(RACSignal *)arguments; @end @interface NSObject (RACUnavailableLifting) - (RACSignal *)rac_liftSelector:(SEL)selector withObjects:(id)arg, ... __attribute__((unavailable("Use -rac_liftSelector:withSignals: instead"))); - (RACSignal *)rac_liftSelector:(SEL)selector withObjectsFromArray:(NSArray *)args __attribute__((unavailable("Use -rac_liftSelector:withSignalsFromArray: instead"))); - (RACSignal *)rac_liftBlock:(id)block withArguments:(id)arg, ... NS_REQUIRES_NIL_TERMINATION __attribute__((unavailable("Use +combineLatest:reduce: instead"))); - (RACSignal *)rac_liftBlock:(id)block withArgumentsFromArray:(NSArray *)args __attribute__((unavailable("Use +combineLatest:reduce: instead"))); - (instancetype)rac_lift __attribute__((unavailable("Use -rac_liftSelector:withSignals: instead"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACLifting.m ================================================ // // NSObject+RACLifting.m // ReactiveCocoa // // Created by Josh Abernathy on 10/13/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "NSObject+RACLifting.h" #import "EXTScope.h" #import "NSInvocation+RACTypeParsing.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import "RACSignal+Operations.h" #import "RACTuple.h" @implementation NSObject (RACLifting) - (RACSignal *)rac_liftSelector:(SEL)selector withSignalOfArguments:(RACSignal *)arguments { NSCParameterAssert(selector != NULL); NSCParameterAssert(arguments != nil); @unsafeify(self); NSMethodSignature *methodSignature = [self methodSignatureForSelector:selector]; NSCAssert(methodSignature != nil, @"%@ does not respond to %@", self, NSStringFromSelector(selector)); return [[[[arguments takeUntil:self.rac_willDeallocSignal] map:^(RACTuple *arguments) { @strongify(self); NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; invocation.selector = selector; invocation.rac_argumentsTuple = arguments; [invocation invokeWithTarget:self]; return invocation.rac_returnValue; }] replayLast] setNameWithFormat:@"%@ -rac_liftSelector: %s withSignalsOfArguments: %@", RACDescription(self), sel_getName(selector), arguments]; } - (RACSignal *)rac_liftSelector:(SEL)selector withSignalsFromArray:(NSArray *)signals { NSCParameterAssert(signals != nil); NSCParameterAssert(signals.count > 0); NSMethodSignature *methodSignature = [self methodSignatureForSelector:selector]; NSCAssert(methodSignature != nil, @"%@ does not respond to %@", self, NSStringFromSelector(selector)); NSUInteger numberOfArguments __attribute__((unused)) = methodSignature.numberOfArguments - 2; NSCAssert(numberOfArguments == signals.count, @"Wrong number of signals for %@ (expected %lu, got %lu)", NSStringFromSelector(selector), (unsigned long)numberOfArguments, (unsigned long)signals.count); return [[self rac_liftSelector:selector withSignalOfArguments:[RACSignal combineLatest:signals]] setNameWithFormat:@"%@ -rac_liftSelector: %s withSignalsFromArray: %@", RACDescription(self), sel_getName(selector), signals]; } - (RACSignal *)rac_liftSelector:(SEL)selector withSignals:(RACSignal *)firstSignal, ... { NSCParameterAssert(firstSignal != nil); NSMutableArray *signals = [NSMutableArray array]; va_list args; va_start(args, firstSignal); for (id currentSignal = firstSignal; currentSignal != nil; currentSignal = va_arg(args, id)) { NSCAssert([currentSignal isKindOfClass:RACSignal.class], @"Argument %@ is not a RACSignal", currentSignal); [signals addObject:currentSignal]; } va_end(args); return [[self rac_liftSelector:selector withSignalsFromArray:signals] setNameWithFormat:@"%@ -rac_liftSelector: %s withSignals: %@", RACDescription(self), sel_getName(selector), signals]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACPropertySubscribing.h ================================================ // // NSObject+RACPropertySubscribing.h // ReactiveCocoa // // Created by Josh Abernathy on 3/2/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import #import "EXTKeyPathCoding.h" #import "metamacros.h" /// Creates a signal which observes `KEYPATH` on `TARGET` for changes. /// /// In either case, the observation continues until `TARGET` _or self_ is /// deallocated. If any intermediate object is deallocated instead, it will be /// assumed to have been set to nil. /// /// Make sure to `@strongify(self)` when using this macro within a block! The /// macro will _always_ reference `self`, which can silently introduce a retain /// cycle within a block. As a result, you should make sure that `self` is a weak /// reference (e.g., created by `@weakify` and `@strongify`) before the /// expression that uses `RACObserve`. /// /// Examples /// /// // Observes self, and doesn't stop until self is deallocated. /// RACSignal *selfSignal = RACObserve(self, arrayController.items); /// /// // Observes the array controller, and stops when self _or_ the array /// // controller is deallocated. /// RACSignal *arrayControllerSignal = RACObserve(self.arrayController, items); /// /// // Observes obj.arrayController, and stops when self _or_ the array /// // controller is deallocated. /// RACSignal *signal2 = RACObserve(obj.arrayController, items); /// /// @weakify(self); /// RACSignal *signal3 = [anotherSignal flattenMap:^(NSArrayController *arrayController) { /// // Avoids a retain cycle because of RACObserve implicitly referencing /// // self. /// @strongify(self); /// return RACObserve(arrayController, items); /// }]; /// /// Returns a signal which sends the current value of the key path on /// subscription, then sends the new value every time it changes, and sends /// completed if self or observer is deallocated. #define RACObserve(TARGET, KEYPATH) \ ({ \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wreceiver-is-weak\"") \ __weak id target_ = (TARGET); \ [target_ rac_valuesForKeyPath:@keypath(TARGET, KEYPATH) observer:self]; \ _Pragma("clang diagnostic pop") \ }) @class RACDisposable; @class RACSignal; @interface NSObject (RACPropertySubscribing) /// Creates a signal to observe the value at the given key path. /// /// The initial value is sent on subscription, the subsequent values are sent /// from whichever thread the change occured on, even if it doesn't have a valid /// scheduler. /// /// Returns a signal that immediately sends the receiver's current value at the /// given keypath, then any changes thereafter. #if OS_OBJECT_HAVE_OBJC_SUPPORT - (RACSignal *)rac_valuesForKeyPath:(NSString *)keyPath observer:(__weak NSObject *)observer; #else // Swift builds with OS_OBJECT_HAVE_OBJC_SUPPORT=0 for Playgrounds and LLDB :( - (RACSignal *)rac_valuesForKeyPath:(NSString *)keyPath observer:(NSObject *)observer; #endif /// Creates a signal to observe the changes of the given key path. /// /// The initial value is sent on subscription if `NSKeyValueObservingOptionInitial` is set. /// The subsequent values are sent from whichever thread the change occured on, /// even if it doesn't have a valid scheduler. /// /// Returns a signal that sends tuples containing the current value at the key /// path and the change dictionary for each KVO callback. #if OS_OBJECT_HAVE_OBJC_SUPPORT - (RACSignal *)rac_valuesAndChangesForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(__weak NSObject *)observer; #else - (RACSignal *)rac_valuesAndChangesForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(NSObject *)observer; #endif @end #define RACAble(...) \ metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \ (_RACAbleObject(self, __VA_ARGS__)) \ (_RACAbleObject(__VA_ARGS__)) #define _RACAbleObject(object, property) [object rac_signalForKeyPath:@keypath(object, property) observer:self] #define RACAbleWithStart(...) \ metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \ (_RACAbleWithStartObject(self, __VA_ARGS__)) \ (_RACAbleWithStartObject(__VA_ARGS__)) #define _RACAbleWithStartObject(object, property) [object rac_signalWithStartingValueForKeyPath:@keypath(object, property) observer:self] @interface NSObject (RACUnavailablePropertySubscribing) + (RACSignal *)rac_signalFor:(NSObject *)object keyPath:(NSString *)keyPath observer:(NSObject *)observer __attribute__((unavailable("Use -rac_valuesForKeyPath:observer: or RACObserve() instead."))); + (RACSignal *)rac_signalWithStartingValueFor:(NSObject *)object keyPath:(NSString *)keyPath observer:(NSObject *)observer __attribute__((unavailable("Use -rac_valuesForKeyPath:observer: or RACObserve() instead."))); + (RACSignal *)rac_signalWithChangesFor:(NSObject *)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(NSObject *)observer __attribute__((unavailable("Use -rac_valuesAndChangesForKeyPath:options:observer: instead."))); - (RACSignal *)rac_signalForKeyPath:(NSString *)keyPath observer:(NSObject *)observer __attribute__((unavailable("Use -rac_valuesForKeyPath:observer: or RACObserve() instead."))); - (RACSignal *)rac_signalWithStartingValueForKeyPath:(NSString *)keyPath observer:(NSObject *)observer __attribute__((unavailable("Use -rac_valuesForKeyPath:observer: or RACObserve() instead."))); - (RACDisposable *)rac_deriveProperty:(NSString *)keyPath from:(RACSignal *)signal __attribute__((unavailable("Use -[RACSignal setKeyPath:onObject:] instead"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACPropertySubscribing.m ================================================ // // NSObject+RACPropertySubscribing.m // ReactiveCocoa // // Created by Josh Abernathy on 3/2/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "NSObject+RACPropertySubscribing.h" #import "EXTScope.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import "NSObject+RACKVOWrapper.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACKVOTrampoline.h" #import "RACSubscriber.h" #import "RACSignal+Operations.h" #import "RACTuple.h" #import @implementation NSObject (RACPropertySubscribing) - (RACSignal *)rac_valuesForKeyPath:(NSString *)keyPath observer:(__weak NSObject *)observer { return [[[self rac_valuesAndChangesForKeyPath:keyPath options:NSKeyValueObservingOptionInitial observer:observer] map:^(RACTuple *value) { // -map: because it doesn't require the block trampoline that -reduceEach: uses return value[0]; }] setNameWithFormat:@"RACObserve(%@, %@)", RACDescription(self), keyPath]; } - (RACSignal *)rac_valuesAndChangesForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options observer:(__weak NSObject *)weakObserver { NSObject *strongObserver = weakObserver; keyPath = [keyPath copy]; NSRecursiveLock *objectLock = [[NSRecursiveLock alloc] init]; objectLock.name = @"org.reactivecocoa.ReactiveCocoa.NSObjectRACPropertySubscribing"; __weak NSObject *weakSelf = self; RACSignal *deallocSignal = [[RACSignal zip:@[ self.rac_willDeallocSignal, strongObserver.rac_willDeallocSignal ?: [RACSignal never] ]] doCompleted:^{ // Forces deallocation to wait if the object variables are currently // being read on another thread. [objectLock lock]; @onExit { [objectLock unlock]; }; }]; return [[[RACSignal createSignal:^ RACDisposable * (id subscriber) { // Hold onto the lock the whole time we're setting up the KVO // observation, because any resurrection that might be caused by our // retaining below must be balanced out by the time -dealloc returns // (if another thread is waiting on the lock above). [objectLock lock]; @onExit { [objectLock unlock]; }; __strong NSObject *observer __attribute__((objc_precise_lifetime)) = weakObserver; __strong NSObject *self __attribute__((objc_precise_lifetime)) = weakSelf; if (self == nil) { [subscriber sendCompleted]; return nil; } return [self rac_observeKeyPath:keyPath options:options observer:observer block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) { [subscriber sendNext:RACTuplePack(value, change)]; }]; }] takeUntil:deallocSignal] setNameWithFormat:@"%@ -rac_valueAndChangesForKeyPath: %@ options: %lu observer: %@", RACDescription(self), keyPath, (unsigned long)options, RACDescription(strongObserver)]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACSelectorSignal.h ================================================ // // NSObject+RACSelectorSignal.h // ReactiveCocoa // // Created by Josh Abernathy on 3/18/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACSignal; /// The domain for any errors originating from -rac_signalForSelector:. extern NSString * const RACSelectorSignalErrorDomain; /// -rac_signalForSelector: was going to add a new method implementation for /// `selector`, but another thread added an implementation before it was able to. /// /// This will _not_ occur for cases where a method implementation exists before /// -rac_signalForSelector: is invoked. extern const NSInteger RACSelectorSignalErrorMethodSwizzlingRace; @interface NSObject (RACSelectorSignal) /// Creates a signal associated with the receiver, which will send a tuple of the /// method's arguments each time the given selector is invoked. /// /// If the selector is already implemented on the receiver, the existing /// implementation will be invoked _before_ the signal fires. /// /// If the selector is not yet implemented on the receiver, the injected /// implementation will have a `void` return type and accept only object /// arguments. Invoking the added implementation with non-object values, or /// expecting a return value, will result in undefined behavior. /// /// This is useful for changing an event or delegate callback into a signal. For /// example, on an NSView: /// /// [[view rac_signalForSelector:@selector(mouseDown:)] subscribeNext:^(RACTuple *args) { /// NSEvent *event = args.first; /// NSLog(@"mouse button pressed: %@", event); /// }]; /// /// selector - The selector for whose invocations are to be observed. If it /// doesn't exist, it will be implemented to accept object arguments /// and return void. This cannot have C arrays or unions as arguments /// or C arrays, unions, structs, complex or vector types as return /// type. /// /// Returns a signal which will send a tuple of arguments upon each invocation of /// the selector, then completes when the receiver is deallocated. `next` events /// will be sent synchronously from the thread that invoked the method. If /// a runtime call fails, the signal will send an error in the /// RACSelectorSignalErrorDomain. - (RACSignal *)rac_signalForSelector:(SEL)selector; /// Behaves like -rac_signalForSelector:, but if the selector is not yet /// implemented on the receiver, its method signature is looked up within /// `protocol`, and may accept non-object arguments. /// /// If the selector is not yet implemented and has a return value, the injected /// method will return all zero bits (equal to `nil`, `NULL`, 0, 0.0f, etc.). /// /// selector - The selector for whose invocations are to be observed. If it /// doesn't exist, it will be implemented using information from /// `protocol`, and may accept non-object arguments and return /// a value. This cannot have C arrays or unions as arguments or /// return type. /// protocol - The protocol in which `selector` is declared. This will be used /// for type information if the selector is not already implemented on /// the receiver. This must not be `NULL`, and `selector` must exist /// in this protocol. /// /// Returns a signal which will send a tuple of arguments on each invocation of /// the selector, or an error in RACSelectorSignalErrorDomain if a runtime /// call fails. - (RACSignal *)rac_signalForSelector:(SEL)selector fromProtocol:(Protocol *)protocol; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSObject+RACSelectorSignal.m ================================================ // // NSObject+RACSelectorSignal.m // ReactiveCocoa // // Created by Josh Abernathy on 3/18/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "NSObject+RACSelectorSignal.h" #import "EXTRuntimeExtensions.h" #import "NSInvocation+RACTypeParsing.h" #import "NSObject+RACDeallocating.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACObjCRuntime.h" #import "RACSubject.h" #import "RACTuple.h" #import "NSObject+RACDescription.h" #import #import NSString * const RACSelectorSignalErrorDomain = @"RACSelectorSignalErrorDomain"; const NSInteger RACSelectorSignalErrorMethodSwizzlingRace = 1; static NSString * const RACSignalForSelectorAliasPrefix = @"rac_alias_"; static NSString * const RACSubclassSuffix = @"_RACSelectorSignal"; static void *RACSubclassAssociationKey = &RACSubclassAssociationKey; static NSMutableSet *swizzledClasses() { static NSMutableSet *set; static dispatch_once_t pred; dispatch_once(&pred, ^{ set = [[NSMutableSet alloc] init]; }); return set; } @implementation NSObject (RACSelectorSignal) static BOOL RACForwardInvocation(id self, NSInvocation *invocation) { SEL aliasSelector = RACAliasForSelector(invocation.selector); RACSubject *subject = objc_getAssociatedObject(self, aliasSelector); Class class = object_getClass(invocation.target); BOOL respondsToAlias = [class instancesRespondToSelector:aliasSelector]; if (respondsToAlias) { invocation.selector = aliasSelector; [invocation invoke]; } if (subject == nil) return respondsToAlias; [subject sendNext:invocation.rac_argumentsTuple]; return YES; } static void RACSwizzleForwardInvocation(Class class) { SEL forwardInvocationSEL = @selector(forwardInvocation:); Method forwardInvocationMethod = class_getInstanceMethod(class, forwardInvocationSEL); // Preserve any existing implementation of -forwardInvocation:. void (*originalForwardInvocation)(id, SEL, NSInvocation *) = NULL; if (forwardInvocationMethod != NULL) { originalForwardInvocation = (__typeof__(originalForwardInvocation))method_getImplementation(forwardInvocationMethod); } // Set up a new version of -forwardInvocation:. // // If the selector has been passed to -rac_signalForSelector:, invoke // the aliased method, and forward the arguments to any attached signals. // // If the selector has not been passed to -rac_signalForSelector:, // invoke any existing implementation of -forwardInvocation:. If there // was no existing implementation, throw an unrecognized selector // exception. id newForwardInvocation = ^(id self, NSInvocation *invocation) { BOOL matched = RACForwardInvocation(self, invocation); if (matched) return; if (originalForwardInvocation == NULL) { [self doesNotRecognizeSelector:invocation.selector]; } else { originalForwardInvocation(self, forwardInvocationSEL, invocation); } }; class_replaceMethod(class, forwardInvocationSEL, imp_implementationWithBlock(newForwardInvocation), "v@:@"); } static void RACSwizzleRespondsToSelector(Class class) { SEL respondsToSelectorSEL = @selector(respondsToSelector:); // Preserve existing implementation of -respondsToSelector:. Method respondsToSelectorMethod = class_getInstanceMethod(class, respondsToSelectorSEL); BOOL (*originalRespondsToSelector)(id, SEL, SEL) = (__typeof__(originalRespondsToSelector))method_getImplementation(respondsToSelectorMethod); // Set up a new version of -respondsToSelector: that returns YES for methods // added by -rac_signalForSelector:. // // If the selector has a method defined on the receiver's actual class, and // if that method's implementation is _objc_msgForward, then returns whether // the instance has a signal for the selector. // Otherwise, call the original -respondsToSelector:. id newRespondsToSelector = ^ BOOL (id self, SEL selector) { Method method = rac_getImmediateInstanceMethod(class, selector); if (method != NULL && method_getImplementation(method) == _objc_msgForward) { SEL aliasSelector = RACAliasForSelector(selector); if (objc_getAssociatedObject(self, aliasSelector) != nil) return YES; } return originalRespondsToSelector(self, respondsToSelectorSEL, selector); }; class_replaceMethod(class, respondsToSelectorSEL, imp_implementationWithBlock(newRespondsToSelector), method_getTypeEncoding(respondsToSelectorMethod)); } static void RACSwizzleGetClass(Class class, Class statedClass) { SEL selector = @selector(class); Method method = class_getInstanceMethod(class, selector); IMP newIMP = imp_implementationWithBlock(^(id self) { return statedClass; }); class_replaceMethod(class, selector, newIMP, method_getTypeEncoding(method)); } static void RACSwizzleMethodSignatureForSelector(Class class) { IMP newIMP = imp_implementationWithBlock(^(id self, SEL selector) { // Don't send the -class message to the receiver because we've changed // that to return the original class. Class actualClass = object_getClass(self); Method method = class_getInstanceMethod(actualClass, selector); if (method == NULL) { // Messages that the original class dynamically implements fall // here. // // Call the original class' -methodSignatureForSelector:. struct objc_super target = { .super_class = class_getSuperclass(class), .receiver = self, }; NSMethodSignature * (*messageSend)(struct objc_super *, SEL, SEL) = (__typeof__(messageSend))objc_msgSendSuper; return messageSend(&target, @selector(methodSignatureForSelector:), selector); } char const *encoding = method_getTypeEncoding(method); return [NSMethodSignature signatureWithObjCTypes:encoding]; }); SEL selector = @selector(methodSignatureForSelector:); Method methodSignatureForSelectorMethod = class_getInstanceMethod(class, selector); class_replaceMethod(class, selector, newIMP, method_getTypeEncoding(methodSignatureForSelectorMethod)); } // It's hard to tell which struct return types use _objc_msgForward, and // which use _objc_msgForward_stret instead, so just exclude all struct, array, // union, complex and vector return types. static void RACCheckTypeEncoding(const char *typeEncoding) { #if !NS_BLOCK_ASSERTIONS // Some types, including vector types, are not encoded. In these cases the // signature starts with the size of the argument frame. NSCAssert(*typeEncoding < '1' || *typeEncoding > '9', @"unknown method return type not supported in type encoding: %s", typeEncoding); NSCAssert(strstr(typeEncoding, "(") != typeEncoding, @"union method return type not supported"); NSCAssert(strstr(typeEncoding, "{") != typeEncoding, @"struct method return type not supported"); NSCAssert(strstr(typeEncoding, "[") != typeEncoding, @"array method return type not supported"); NSCAssert(strstr(typeEncoding, @encode(_Complex float)) != typeEncoding, @"complex float method return type not supported"); NSCAssert(strstr(typeEncoding, @encode(_Complex double)) != typeEncoding, @"complex double method return type not supported"); NSCAssert(strstr(typeEncoding, @encode(_Complex long double)) != typeEncoding, @"complex long double method return type not supported"); #endif // !NS_BLOCK_ASSERTIONS } static RACSignal *NSObjectRACSignalForSelector(NSObject *self, SEL selector, Protocol *protocol) { SEL aliasSelector = RACAliasForSelector(selector); @synchronized (self) { RACSubject *subject = objc_getAssociatedObject(self, aliasSelector); if (subject != nil) return subject; Class class = RACSwizzleClass(self); NSCAssert(class != nil, @"Could not swizzle class of %@", self); subject = [[RACSubject subject] setNameWithFormat:@"%@ -rac_signalForSelector: %s", RACDescription(self), sel_getName(selector)]; objc_setAssociatedObject(self, aliasSelector, subject, OBJC_ASSOCIATION_RETAIN); [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ [subject sendCompleted]; }]]; Method targetMethod = class_getInstanceMethod(class, selector); if (targetMethod == NULL) { const char *typeEncoding; if (protocol == NULL) { typeEncoding = RACSignatureForUndefinedSelector(selector); } else { // Look for the selector as an optional instance method. struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES); if (methodDescription.name == NULL) { // Then fall back to looking for a required instance // method. methodDescription = protocol_getMethodDescription(protocol, selector, YES, YES); NSCAssert(methodDescription.name != NULL, @"Selector %@ does not exist in <%s>", NSStringFromSelector(selector), protocol_getName(protocol)); } typeEncoding = methodDescription.types; } RACCheckTypeEncoding(typeEncoding); // Define the selector to call -forwardInvocation:. if (!class_addMethod(class, selector, _objc_msgForward, typeEncoding)) { NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedString(@"A race condition occurred implementing %@ on class %@", nil), NSStringFromSelector(selector), class], NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Invoke -rac_signalForSelector: again to override the implementation.", nil) }; return [RACSignal error:[NSError errorWithDomain:RACSelectorSignalErrorDomain code:RACSelectorSignalErrorMethodSwizzlingRace userInfo:userInfo]]; } } else if (method_getImplementation(targetMethod) != _objc_msgForward) { // Make a method alias for the existing method implementation. const char *typeEncoding = method_getTypeEncoding(targetMethod); RACCheckTypeEncoding(typeEncoding); BOOL addedAlias __attribute__((unused)) = class_addMethod(class, aliasSelector, method_getImplementation(targetMethod), typeEncoding); NSCAssert(addedAlias, @"Original implementation for %@ is already copied to %@ on %@", NSStringFromSelector(selector), NSStringFromSelector(aliasSelector), class); // Redefine the selector to call -forwardInvocation:. class_replaceMethod(class, selector, _objc_msgForward, method_getTypeEncoding(targetMethod)); } return subject; } } static SEL RACAliasForSelector(SEL originalSelector) { NSString *selectorName = NSStringFromSelector(originalSelector); return NSSelectorFromString([RACSignalForSelectorAliasPrefix stringByAppendingString:selectorName]); } static const char *RACSignatureForUndefinedSelector(SEL selector) { const char *name = sel_getName(selector); NSMutableString *signature = [NSMutableString stringWithString:@"v@:"]; while ((name = strchr(name, ':')) != NULL) { [signature appendString:@"@"]; name++; } return signature.UTF8String; } static Class RACSwizzleClass(NSObject *self) { Class statedClass = self.class; Class baseClass = object_getClass(self); // The "known dynamic subclass" is the subclass generated by RAC. // It's stored as an associated object on every instance that's already // been swizzled, so that even if something else swizzles the class of // this instance, we can still access the RAC generated subclass. Class knownDynamicSubclass = objc_getAssociatedObject(self, RACSubclassAssociationKey); if (knownDynamicSubclass != Nil) return knownDynamicSubclass; NSString *className = NSStringFromClass(baseClass); if (statedClass != baseClass) { // If the class is already lying about what it is, it's probably a KVO // dynamic subclass or something else that we shouldn't subclass // ourselves. // // Just swizzle -forwardInvocation: in-place. Since the object's class // was almost certainly dynamically changed, we shouldn't see another of // these classes in the hierarchy. // // Additionally, swizzle -respondsToSelector: because the default // implementation may be ignorant of methods added to this class. @synchronized (swizzledClasses()) { if (![swizzledClasses() containsObject:className]) { RACSwizzleForwardInvocation(baseClass); RACSwizzleRespondsToSelector(baseClass); RACSwizzleGetClass(baseClass, statedClass); RACSwizzleGetClass(object_getClass(baseClass), statedClass); RACSwizzleMethodSignatureForSelector(baseClass); [swizzledClasses() addObject:className]; } } return baseClass; } const char *subclassName = [className stringByAppendingString:RACSubclassSuffix].UTF8String; Class subclass = objc_getClass(subclassName); if (subclass == nil) { subclass = [RACObjCRuntime createClass:subclassName inheritingFromClass:baseClass]; if (subclass == nil) return nil; RACSwizzleForwardInvocation(subclass); RACSwizzleRespondsToSelector(subclass); RACSwizzleGetClass(subclass, statedClass); RACSwizzleGetClass(object_getClass(subclass), statedClass); RACSwizzleMethodSignatureForSelector(subclass); objc_registerClassPair(subclass); } object_setClass(self, subclass); objc_setAssociatedObject(self, RACSubclassAssociationKey, subclass, OBJC_ASSOCIATION_ASSIGN); return subclass; } - (RACSignal *)rac_signalForSelector:(SEL)selector { NSCParameterAssert(selector != NULL); return NSObjectRACSignalForSelector(self, selector, NULL); } - (RACSignal *)rac_signalForSelector:(SEL)selector fromProtocol:(Protocol *)protocol { NSCParameterAssert(selector != NULL); NSCParameterAssert(protocol != NULL); return NSObjectRACSignalForSelector(self, selector, protocol); } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSOrderedSet+RACSequenceAdditions.h ================================================ // // NSOrderedSet+RACSequenceAdditions.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import @class RACSequence; @interface NSOrderedSet (RACSequenceAdditions) /// Creates and returns a sequence corresponding to the receiver. /// /// Mutating the receiver will not affect the sequence after it's been created. @property (nonatomic, copy, readonly) RACSequence *rac_sequence; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSOrderedSet+RACSequenceAdditions.m ================================================ // // NSOrderedSet+RACSequenceAdditions.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "NSOrderedSet+RACSequenceAdditions.h" #import "NSArray+RACSequenceAdditions.h" @implementation NSOrderedSet (RACSequenceAdditions) - (RACSequence *)rac_sequence { // TODO: First class support for ordered set sequences. return self.array.rac_sequence; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSSet+RACSequenceAdditions.h ================================================ // // NSSet+RACSequenceAdditions.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import @class RACSequence; @interface NSSet (RACSequenceAdditions) /// Creates and returns a sequence corresponding to the receiver. /// /// Mutating the receiver will not affect the sequence after it's been created. @property (nonatomic, copy, readonly) RACSequence *rac_sequence; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSSet+RACSequenceAdditions.m ================================================ // // NSSet+RACSequenceAdditions.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "NSSet+RACSequenceAdditions.h" #import "NSArray+RACSequenceAdditions.h" @implementation NSSet (RACSequenceAdditions) - (RACSequence *)rac_sequence { // TODO: First class support for set sequences. return self.allObjects.rac_sequence; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSString+RACKeyPathUtilities.h ================================================ // // NSString+RACKeyPathUtilities.h // ReactiveCocoa // // Created by Uri Baghin on 05/05/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import // A private category of methods to extract parts of a key path. @interface NSString (RACKeyPathUtilities) // Returns an array of the components of the receiver. // // Calling this method on a string that isn't a key path is considered undefined // behavior. - (NSArray *)rac_keyPathComponents; // Returns a key path with all the components of the receiver except for the // last one. // // Calling this method on a string that isn't a key path is considered undefined // behavior. - (NSString *)rac_keyPathByDeletingLastKeyPathComponent; // Returns a key path with all the components of the receiver expect for the // first one. // // Calling this method on a string that isn't a key path is considered undefined // behavior. - (NSString *)rac_keyPathByDeletingFirstKeyPathComponent; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSString+RACKeyPathUtilities.m ================================================ // // NSString+RACKeyPathUtilities.m // ReactiveCocoa // // Created by Uri Baghin on 05/05/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "NSString+RACKeyPathUtilities.h" @implementation NSString (RACKeyPathUtilities) - (NSArray *)rac_keyPathComponents { if (self.length == 0) { return nil; } return [self componentsSeparatedByString:@"."]; } - (NSString *)rac_keyPathByDeletingLastKeyPathComponent { NSUInteger lastDotIndex = [self rangeOfString:@"." options:NSBackwardsSearch].location; if (lastDotIndex == NSNotFound) { return nil; } return [self substringToIndex:lastDotIndex]; } - (NSString *)rac_keyPathByDeletingFirstKeyPathComponent { NSUInteger firstDotIndex = [self rangeOfString:@"."].location; if (firstDotIndex == NSNotFound) { return nil; } return [self substringFromIndex:firstDotIndex + 1]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSString+RACSequenceAdditions.h ================================================ // // NSString+RACSequenceAdditions.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import @class RACSequence; @interface NSString (RACSequenceAdditions) /// Creates and returns a sequence containing strings corresponding to each /// composed character sequence in the receiver. /// /// Mutating the receiver will not affect the sequence after it's been created. @property (nonatomic, copy, readonly) RACSequence *rac_sequence; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSString+RACSequenceAdditions.m ================================================ // // NSString+RACSequenceAdditions.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "NSString+RACSequenceAdditions.h" #import "RACStringSequence.h" @implementation NSString (RACSequenceAdditions) - (RACSequence *)rac_sequence { return [RACStringSequence sequenceWithString:self offset:0]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSString+RACSupport.h ================================================ // // NSString+RACSupport.h // ReactiveCocoa // // Created by Josh Abernathy on 5/11/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACScheduler; @class RACSignal; @interface NSString (RACSupport) // Reads in the contents of the file using +[NSString stringWithContentsOfURL:usedEncoding:error:]. // Note that encoding won't be valid until the signal completes successfully. // // scheduler - cannot be nil. + (RACSignal *)rac_readContentsOfURL:(NSURL *)URL usedEncoding:(NSStringEncoding *)encoding scheduler:(RACScheduler *)scheduler; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSString+RACSupport.m ================================================ // // NSString+RACSupport.m // ReactiveCocoa // // Created by Josh Abernathy on 5/11/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "NSString+RACSupport.h" #import "RACReplaySubject.h" #import "RACScheduler.h" @implementation NSString (RACSupport) + (RACSignal *)rac_readContentsOfURL:(NSURL *)URL usedEncoding:(NSStringEncoding *)encoding scheduler:(RACScheduler *)scheduler { NSCParameterAssert(scheduler != nil); RACReplaySubject *subject = [RACReplaySubject subject]; [subject setNameWithFormat:@"+rac_readContentsOfURL: %@ usedEncoding:scheduler: %@", URL, scheduler]; [scheduler schedule:^{ NSError *error = nil; NSString *string = [NSString stringWithContentsOfURL:URL usedEncoding:encoding error:&error]; if (string == nil) { [subject sendError:error]; } else { [subject sendNext:string]; [subject sendCompleted]; } }]; return subject; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSURLConnection+RACSupport.h ================================================ // // NSURLConnection+RACSupport.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-01. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACSignal; @interface NSURLConnection (RACSupport) // Lazily loads data for the given request in the background. // // request - The URL request to load. This must not be nil. // // Returns a signal which will begin loading the request upon each subscription, // then send a `RACTuple` of the received `NSURLResponse` and downloaded // `NSData`, and complete on a background thread. If any errors occur, the // returned signal will error out. + (RACSignal *)rac_sendAsynchronousRequest:(NSURLRequest *)request; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSURLConnection+RACSupport.m ================================================ // // NSURLConnection+RACSupport.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-01. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "NSURLConnection+RACSupport.h" #import "RACDisposable.h" #import "RACSignal.h" #import "RACSubscriber.h" #import "RACTuple.h" @implementation NSURLConnection (RACSupport) + (RACSignal *)rac_sendAsynchronousRequest:(NSURLRequest *)request { NSCParameterAssert(request != nil); return [[RACSignal createSignal:^(id subscriber) { NSOperationQueue *queue = [[NSOperationQueue alloc] init]; queue.name = @"org.reactivecocoa.ReactiveCocoa.NSURLConnectionRACSupport"; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { // The docs say that `nil` data means an error occurred, but // `nil` responses can also occur in practice (circumstances // unknown). Consider either to be an error. // // Note that _empty_ data is not necessarily erroneous, as there // may be headers but no HTTP body. if (response == nil || data == nil) { [subscriber sendError:error]; } else { [subscriber sendNext:RACTuplePack(response, data)]; [subscriber sendCompleted]; } }]; #pragma clang diagnostic pop return [RACDisposable disposableWithBlock:^{ // It's not clear if this will actually cancel the connection, // but we can at least prevent _some_ unnecessary work -- // without writing all the code for a proper delegate, which // doesn't really belong in RAC. queue.suspended = YES; [queue cancelAllOperations]; }]; }] setNameWithFormat:@"+rac_sendAsynchronousRequest: %@", request]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSUserDefaults+RACSupport.h ================================================ // // NSUserDefaults+RACSupport.h // ReactiveCocoa // // Created by Matt Diephouse on 12/19/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACChannelTerminal; @interface NSUserDefaults (RACSupport) /// Creates and returns a terminal for binding the user defaults key. /// /// **Note:** The value in the user defaults is *asynchronously* updated with /// values sent to the channel. /// /// key - The user defaults key to create the channel terminal for. /// /// Returns a channel terminal that sends the value of the user defaults key /// upon subscription, sends an updated value whenever the default changes, and /// updates the default asynchronously with values it receives. - (RACChannelTerminal *)rac_channelTerminalForKey:(NSString *)key; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/NSUserDefaults+RACSupport.m ================================================ // // NSUserDefaults+RACSupport.m // ReactiveCocoa // // Created by Matt Diephouse on 12/19/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "NSUserDefaults+RACSupport.h" #import "EXTScope.h" #import "NSNotificationCenter+RACSupport.h" #import "NSObject+RACDeallocating.h" #import "RACChannel.h" #import "RACScheduler.h" #import "RACSignal+Operations.h" @implementation NSUserDefaults (RACSupport) - (RACChannelTerminal *)rac_channelTerminalForKey:(NSString *)key { RACChannel *channel = [RACChannel new]; RACScheduler *scheduler = [RACScheduler scheduler]; __block BOOL ignoreNextValue = NO; @weakify(self); [[[[[[[NSNotificationCenter.defaultCenter rac_addObserverForName:NSUserDefaultsDidChangeNotification object:self] map:^(id _) { @strongify(self); return [self objectForKey:key]; }] startWith:[self objectForKey:key]] // Don't send values that were set on the other side of the terminal. filter:^ BOOL (id _) { if (RACScheduler.currentScheduler == scheduler && ignoreNextValue) { ignoreNextValue = NO; return NO; } return YES; }] distinctUntilChanged] takeUntil:self.rac_willDeallocSignal] subscribe:channel.leadingTerminal]; [[channel.leadingTerminal deliverOn:scheduler] subscribeNext:^(id value) { @strongify(self); ignoreNextValue = YES; [self setObject:value forKey:key]; }]; return channel.followingTerminal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACArraySequence.h ================================================ // // RACArraySequence.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACSequence.h" // Private class that adapts an array to the RACSequence interface. @interface RACArraySequence : RACSequence // Returns a sequence for enumerating over the given array, starting from the // given offset. The array will be copied to prevent mutation. + (instancetype)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACArraySequence.m ================================================ // // RACArraySequence.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACArraySequence.h" @interface RACArraySequence () // Redeclared from the superclass and marked deprecated to prevent using `array` // where `backingArray` is intended. @property (nonatomic, copy, readonly) NSArray *array __attribute__((deprecated)); // The array being sequenced. @property (nonatomic, copy, readonly) NSArray *backingArray; // The index in the array from which the sequence starts. @property (nonatomic, assign, readonly) NSUInteger offset; @end @implementation RACArraySequence #pragma mark Lifecycle + (instancetype)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset { NSCParameterAssert(offset <= array.count); if (offset == array.count) return self.empty; RACArraySequence *seq = [[self alloc] init]; seq->_backingArray = [array copy]; seq->_offset = offset; return seq; } #pragma mark RACSequence - (id)head { return self.backingArray[self.offset]; } - (RACSequence *)tail { RACSequence *sequence = [self.class sequenceWithArray:self.backingArray offset:self.offset + 1]; sequence.name = self.name; return sequence; } #pragma mark NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id[])stackbuf count:(NSUInteger)len { NSCParameterAssert(len > 0); if (state->state >= self.backingArray.count) { // Enumeration has completed. return 0; } if (state->state == 0) { state->state = self.offset; // Since a sequence doesn't mutate, this just needs to be set to // something non-NULL. state->mutationsPtr = state->extra; } state->itemsPtr = stackbuf; NSUInteger startIndex = state->state; NSUInteger index = 0; for (id value in self.backingArray) { // Constructing an index set for -enumerateObjectsAtIndexes: can actually be // slower than just skipping the items we don't care about. if (index < startIndex) { ++index; continue; } stackbuf[index - startIndex] = value; ++index; if (index - startIndex >= len) break; } NSCAssert(index > startIndex, @"Final index (%lu) should be greater than start index (%lu)", (unsigned long)index, (unsigned long)startIndex); state->state = index; return index - startIndex; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-implementations" - (NSArray *)array { return [self.backingArray subarrayWithRange:NSMakeRange(self.offset, self.backingArray.count - self.offset)]; } #pragma clang diagnostic pop #pragma mark NSCoding - (id)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self == nil) return nil; _backingArray = [coder decodeObjectForKey:@"array"]; _offset = 0; return self; } - (void)encodeWithCoder:(NSCoder *)coder { // Encoding is handled in RACSequence. [super encodeWithCoder:coder]; } #pragma mark NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p>{ name = %@, array = %@ }", self.class, self, self.name, self.backingArray]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACBehaviorSubject.h ================================================ // // RACBehaviorSubject.h // ReactiveCocoa // // Created by Josh Abernathy on 3/16/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSubject.h" /// A behavior subject sends the last value it received when it is subscribed to. @interface RACBehaviorSubject : RACSubject /// Creates a new behavior subject with a default value. If it hasn't received /// any values when it gets subscribed to, it sends the default value. + (instancetype)behaviorSubjectWithDefaultValue:(id)value; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACBehaviorSubject.m ================================================ // // RACBehaviorSubject.m // ReactiveCocoa // // Created by Josh Abernathy on 3/16/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACBehaviorSubject.h" #import "RACDisposable.h" #import "RACScheduler+Private.h" @interface RACBehaviorSubject () // This property should only be used while synchronized on self. @property (nonatomic, strong) id currentValue; @end @implementation RACBehaviorSubject #pragma mark Lifecycle + (instancetype)behaviorSubjectWithDefaultValue:(id)value { RACBehaviorSubject *subject = [self subject]; subject.currentValue = value; return subject; } #pragma mark RACSignal - (RACDisposable *)subscribe:(id)subscriber { RACDisposable *subscriptionDisposable = [super subscribe:subscriber]; RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{ @synchronized (self) { [subscriber sendNext:self.currentValue]; } }]; return [RACDisposable disposableWithBlock:^{ [subscriptionDisposable dispose]; [schedulingDisposable dispose]; }]; } #pragma mark RACSubscriber - (void)sendNext:(id)value { @synchronized (self) { self.currentValue = value; [super sendNext:value]; } } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACBlockTrampoline.h ================================================ // // RACBlockTrampoline.h // ReactiveCocoa // // Created by Josh Abernathy on 10/21/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACTuple; // A private class that allows a limited type of dynamic block invocation. @interface RACBlockTrampoline : NSObject // Invokes the given block with the given arguments. All of the block's // argument types must be objects and it must be typed to return an object. // // At this time, it only supports blocks that take up to 15 arguments. Any more // is just cray. // // block - The block to invoke. Must accept as many arguments as are given in // the arguments array. Cannot be nil. // arguments - The arguments with which to invoke the block. `RACTupleNil`s will // be passed as nils. // // Returns the return value of invoking the block. + (id)invokeBlock:(id)block withArguments:(RACTuple *)arguments; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACBlockTrampoline.m ================================================ // // RACBlockTrampoline.m // ReactiveCocoa // // Created by Josh Abernathy on 10/21/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACBlockTrampoline.h" #import "RACTuple.h" @interface RACBlockTrampoline () @property (nonatomic, readonly, copy) id block; @end @implementation RACBlockTrampoline #pragma mark API - (id)initWithBlock:(id)block { self = [super init]; if (self == nil) return nil; _block = [block copy]; return self; } + (id)invokeBlock:(id)block withArguments:(RACTuple *)arguments { NSCParameterAssert(block != NULL); RACBlockTrampoline *trampoline = [[self alloc] initWithBlock:block]; return [trampoline invokeWithArguments:arguments]; } - (id)invokeWithArguments:(RACTuple *)arguments { SEL selector = [self selectorForArgumentCount:arguments.count]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:selector]]; invocation.selector = selector; invocation.target = self; for (NSUInteger i = 0; i < arguments.count; i++) { id arg = arguments[i]; NSInteger argIndex = (NSInteger)(i + 2); [invocation setArgument:&arg atIndex:argIndex]; } [invocation invoke]; __unsafe_unretained id returnVal; [invocation getReturnValue:&returnVal]; return returnVal; } - (SEL)selectorForArgumentCount:(NSUInteger)count { NSCParameterAssert(count > 0); switch (count) { case 0: return NULL; case 1: return @selector(performWith:); case 2: return @selector(performWith::); case 3: return @selector(performWith:::); case 4: return @selector(performWith::::); case 5: return @selector(performWith:::::); case 6: return @selector(performWith::::::); case 7: return @selector(performWith:::::::); case 8: return @selector(performWith::::::::); case 9: return @selector(performWith:::::::::); case 10: return @selector(performWith::::::::::); case 11: return @selector(performWith:::::::::::); case 12: return @selector(performWith::::::::::::); case 13: return @selector(performWith:::::::::::::); case 14: return @selector(performWith::::::::::::::); case 15: return @selector(performWith:::::::::::::::); } NSCAssert(NO, @"The argument count is too damn high! Only blocks of up to 15 arguments are currently supported."); return NULL; } - (id)performWith:(id)obj1 { id (^block)(id) = self.block; return block(obj1); } - (id)performWith:(id)obj1 :(id)obj2 { id (^block)(id, id) = self.block; return block(obj1, obj2); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 { id (^block)(id, id, id) = self.block; return block(obj1, obj2, obj3); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 { id (^block)(id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 { id (^block)(id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 { id (^block)(id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 { id (^block)(id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 { id (^block)(id, id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 { id (^block)(id, id, id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 { id (^block)(id, id, id, id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 { id (^block)(id, id, id, id, id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 { id (^block)(id, id, id, id, id, id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 { id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 :(id)obj14 { id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14); } - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 :(id)obj14 :(id)obj15 { id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block; return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14, obj15); } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACChannel.h ================================================ // // RACChannel.h // ReactiveCocoa // // Created by Uri Baghin on 01/01/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSignal.h" #import "RACSubscriber.h" @class RACChannelTerminal; /// A two-way channel. /// /// Conceptually, RACChannel can be thought of as a bidirectional connection, /// composed of two controllable signals that work in parallel. /// /// For example, when connecting between a view and a model: /// /// Model View /// `leadingTerminal` ------> `followingTerminal` /// `leadingTerminal` <------ `followingTerminal` /// /// The initial value of the model and all future changes to it are _sent on_ the /// `leadingTerminal`, and _received by_ subscribers of the `followingTerminal`. /// /// Likewise, whenever the user changes the value of the view, that value is sent /// on the `followingTerminal`, and received in the model from the /// `leadingTerminal`. However, the initial value of the view is not received /// from the `leadingTerminal` (only future changes). @interface RACChannel : NSObject /// The terminal which "leads" the channel, by sending its latest value /// immediately to new subscribers of the `followingTerminal`. /// /// New subscribers to this terminal will not receive a starting value, but will /// receive all future values that are sent to the `followingTerminal`. @property (nonatomic, strong, readonly) RACChannelTerminal *leadingTerminal; /// The terminal which "follows" the lead of the other terminal, only sending /// _future_ values to the subscribers of the `leadingTerminal`. /// /// The latest value sent to the `leadingTerminal` (if any) will be sent /// immediately to new subscribers of this terminal, and then all future values /// as well. @property (nonatomic, strong, readonly) RACChannelTerminal *followingTerminal; @end /// Represents one end of a RACChannel. /// /// An terminal is similar to a socket or pipe -- it represents one end of /// a connection (the RACChannel, in this case). Values sent to this terminal /// will _not_ be received by its subscribers. Instead, the values will be sent /// to the subscribers of the RACChannel's _other_ terminal. /// /// For example, when using the `followingTerminal`, _sent_ values can only be /// _received_ from the `leadingTerminal`, and vice versa. /// /// To make it easy to terminate a RACChannel, `error` and `completed` events /// sent to either terminal will be received by the subscribers of _both_ /// terminals. /// /// Do not instantiate this class directly. Create a RACChannel instead. @interface RACChannelTerminal : RACSignal - (id)init __attribute__((unavailable("Instantiate a RACChannel instead"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACChannel.m ================================================ // // RACChannel.m // ReactiveCocoa // // Created by Uri Baghin on 01/01/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACChannel.h" #import "RACDisposable.h" #import "RACReplaySubject.h" #import "RACSignal+Operations.h" @interface RACChannelTerminal () // The values for this terminal. @property (nonatomic, strong, readonly) RACSignal *values; // A subscriber will will send values to the other terminal. @property (nonatomic, strong, readonly) id otherTerminal; - (id)initWithValues:(RACSignal *)values otherTerminal:(id)otherTerminal; @end @implementation RACChannel - (id)init { self = [super init]; if (self == nil) return nil; // We don't want any starting value from the leadingSubject, but we do want // error and completion to be replayed. RACReplaySubject *leadingSubject = [[RACReplaySubject replaySubjectWithCapacity:0] setNameWithFormat:@"leadingSubject"]; RACReplaySubject *followingSubject = [[RACReplaySubject replaySubjectWithCapacity:1] setNameWithFormat:@"followingSubject"]; // Propagate errors and completion to everything. [[leadingSubject ignoreValues] subscribe:followingSubject]; [[followingSubject ignoreValues] subscribe:leadingSubject]; _leadingTerminal = [[[RACChannelTerminal alloc] initWithValues:leadingSubject otherTerminal:followingSubject] setNameWithFormat:@"leadingTerminal"]; _followingTerminal = [[[RACChannelTerminal alloc] initWithValues:followingSubject otherTerminal:leadingSubject] setNameWithFormat:@"followingTerminal"]; return self; } @end @implementation RACChannelTerminal #pragma mark Lifecycle - (id)initWithValues:(RACSignal *)values otherTerminal:(id)otherTerminal { NSCParameterAssert(values != nil); NSCParameterAssert(otherTerminal != nil); self = [super init]; if (self == nil) return nil; _values = values; _otherTerminal = otherTerminal; return self; } #pragma mark RACSignal - (RACDisposable *)subscribe:(id)subscriber { return [self.values subscribe:subscriber]; } #pragma mark - (void)sendNext:(id)value { [self.otherTerminal sendNext:value]; } - (void)sendError:(NSError *)error { [self.otherTerminal sendError:error]; } - (void)sendCompleted { [self.otherTerminal sendCompleted]; } - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable { [self.otherTerminal didSubscribeWithDisposable:disposable]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACCommand.h ================================================ // // RACCommand.h // ReactiveCocoa // // Created by Josh Abernathy on 3/3/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACSignal; /// The domain for errors originating within `RACCommand`. extern NSString * const RACCommandErrorDomain; /// -execute: was invoked while the command was disabled. extern const NSInteger RACCommandErrorNotEnabled; /// A `userInfo` key for an error, associated with the `RACCommand` that the /// error originated from. /// /// This is included only when the error code is `RACCommandErrorNotEnabled`. extern NSString * const RACUnderlyingCommandErrorKey; /// A command is a signal triggered in response to some action, typically /// UI-related. @interface RACCommand : NSObject /// A signal of the signals returned by successful invocations of -execute: /// (i.e., while the receiver is `enabled`). /// /// Errors will be automatically caught upon the inner signals, and sent upon /// `errors` instead. If you _want_ to receive inner errors, use -execute: or /// -[RACSignal materialize]. /// /// Only executions that begin _after_ subscription will be sent upon this /// signal. All inner signals will arrive upon the main thread. @property (nonatomic, strong, readonly) RACSignal *executionSignals; /// A signal of whether this command is currently executing. /// /// This will send YES whenever -execute: is invoked and the created signal has /// not yet terminated. Once all executions have terminated, `executing` will /// send NO. /// /// This signal will send its current value upon subscription, and then all /// future values on the main thread. @property (nonatomic, strong, readonly) RACSignal *executing; /// A signal of whether this command is able to execute. /// /// This will send NO if: /// /// - The command was created with an `enabledSignal`, and NO is sent upon that /// signal, or /// - `allowsConcurrentExecution` is NO and the command has started executing. /// /// Once the above conditions are no longer met, the signal will send YES. /// /// This signal will send its current value upon subscription, and then all /// future values on the main thread. @property (nonatomic, strong, readonly) RACSignal *enabled; /// Forwards any errors that occur within signals returned by -execute:. /// /// When an error occurs on a signal returned from -execute:, this signal will /// send the associated NSError value as a `next` event (since an `error` event /// would terminate the stream). /// /// After subscription, this signal will send all future errors on the main /// thread. @property (nonatomic, strong, readonly) RACSignal *errors; /// Whether the command allows multiple executions to proceed concurrently. /// /// The default value for this property is NO. @property (atomic, assign) BOOL allowsConcurrentExecution; /// Invokes -initWithEnabled:signalBlock: with a nil `enabledSignal`. - (id)initWithSignalBlock:(RACSignal * (^)(id input))signalBlock; /// Initializes a command that is conditionally enabled. /// /// This is the designated initializer for this class. /// /// enabledSignal - A signal of BOOLs which indicate whether the command should /// be enabled. `enabled` will be based on the latest value sent /// from this signal. Before any values are sent, `enabled` will /// default to YES. This argument may be nil. /// signalBlock - A block which will map each input value (passed to -execute:) /// to a signal of work. The returned signal will be multicasted /// to a replay subject, sent on `executionSignals`, then /// subscribed to synchronously. Neither the block nor the /// returned signal may be nil. - (id)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock; /// If the receiver is enabled, this method will: /// /// 1. Invoke the `signalBlock` given at the time of initialization. /// 2. Multicast the returned signal to a RACReplaySubject. /// 3. Send the multicasted signal on `executionSignals`. /// 4. Subscribe (connect) to the original signal on the main thread. /// /// input - The input value to pass to the receiver's `signalBlock`. This may be /// nil. /// /// Returns the multicasted signal, after subscription. If the receiver is not /// enabled, returns a signal that will send an error with code /// RACCommandErrorNotEnabled. - (RACSignal *)execute:(id)input; @end @interface RACCommand (Unavailable) @property (atomic, readonly) BOOL canExecute __attribute__((unavailable("Use the 'enabled' signal instead"))); + (instancetype)command __attribute__((unavailable("Use -initWithSignalBlock: instead"))); + (instancetype)commandWithCanExecuteSignal:(RACSignal *)canExecuteSignal __attribute__((unavailable("Use -initWithEnabled:signalBlock: instead"))); - (id)initWithCanExecuteSignal:(RACSignal *)canExecuteSignal __attribute__((unavailable("Use -initWithEnabled:signalBlock: instead"))); - (RACSignal *)addSignalBlock:(RACSignal * (^)(id value))signalBlock __attribute__((unavailable("Pass the signalBlock to -initWithSignalBlock: instead"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACCommand.m ================================================ // // RACCommand.m // ReactiveCocoa // // Created by Josh Abernathy on 3/3/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACCommand.h" #import "EXTScope.h" #import "NSArray+RACSequenceAdditions.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import "NSObject+RACPropertySubscribing.h" #import "RACMulticastConnection.h" #import "RACReplaySubject.h" #import "RACScheduler.h" #import "RACSequence.h" #import "RACSignal+Operations.h" #import NSString * const RACCommandErrorDomain = @"RACCommandErrorDomain"; NSString * const RACUnderlyingCommandErrorKey = @"RACUnderlyingCommandErrorKey"; const NSInteger RACCommandErrorNotEnabled = 1; @interface RACCommand () { // Atomic backing variable for `allowsConcurrentExecution`. volatile uint32_t _allowsConcurrentExecution; } /// A subject that sends added execution signals. @property (nonatomic, strong, readonly) RACSubject *addedExecutionSignalsSubject; /// A subject that sends the new value of `allowsConcurrentExecution` whenever it changes. @property (nonatomic, strong, readonly) RACSubject *allowsConcurrentExecutionSubject; // `enabled`, but without a hop to the main thread. // // Values from this signal may arrive on any thread. @property (nonatomic, strong, readonly) RACSignal *immediateEnabled; // The signal block that the receiver was initialized with. @property (nonatomic, copy, readonly) RACSignal * (^signalBlock)(id input); @end @implementation RACCommand #pragma mark Properties - (BOOL)allowsConcurrentExecution { return _allowsConcurrentExecution != 0; } - (void)setAllowsConcurrentExecution:(BOOL)allowed { if (allowed) { OSAtomicOr32Barrier(1, &_allowsConcurrentExecution); } else { OSAtomicAnd32Barrier(0, &_allowsConcurrentExecution); } [self.allowsConcurrentExecutionSubject sendNext:@(_allowsConcurrentExecution)]; } #pragma mark Lifecycle - (id)init { NSCAssert(NO, @"Use -initWithSignalBlock: instead"); return nil; } - (id)initWithSignalBlock:(RACSignal * (^)(id input))signalBlock { return [self initWithEnabled:nil signalBlock:signalBlock]; } - (void)dealloc { [_addedExecutionSignalsSubject sendCompleted]; [_allowsConcurrentExecutionSubject sendCompleted]; } - (id)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock { NSCParameterAssert(signalBlock != nil); self = [super init]; if (self == nil) return nil; _addedExecutionSignalsSubject = [RACSubject new]; _allowsConcurrentExecutionSubject = [RACSubject new]; _signalBlock = [signalBlock copy]; _executionSignals = [[[self.addedExecutionSignalsSubject map:^(RACSignal *signal) { return [signal catchTo:[RACSignal empty]]; }] deliverOn:RACScheduler.mainThreadScheduler] setNameWithFormat:@"%@ -executionSignals", self]; // `errors` needs to be multicasted so that it picks up all // `activeExecutionSignals` that are added. // // In other words, if someone subscribes to `errors` _after_ an execution // has started, it should still receive any error from that execution. RACMulticastConnection *errorsConnection = [[[self.addedExecutionSignalsSubject flattenMap:^(RACSignal *signal) { return [[signal ignoreValues] catch:^(NSError *error) { return [RACSignal return:error]; }]; }] deliverOn:RACScheduler.mainThreadScheduler] publish]; _errors = [errorsConnection.signal setNameWithFormat:@"%@ -errors", self]; [errorsConnection connect]; RACSignal *immediateExecuting = [[[[self.addedExecutionSignalsSubject flattenMap:^(RACSignal *signal) { return [[[signal catchTo:[RACSignal empty]] then:^{ return [RACSignal return:@-1]; }] startWith:@1]; }] scanWithStart:@0 reduce:^(NSNumber *running, NSNumber *next) { return @(running.integerValue + next.integerValue); }] map:^(NSNumber *count) { return @(count.integerValue > 0); }] startWith:@NO]; _executing = [[[[[immediateExecuting deliverOn:RACScheduler.mainThreadScheduler] // This is useful before the first value arrives on the main thread. startWith:@NO] distinctUntilChanged] replayLast] setNameWithFormat:@"%@ -executing", self]; RACSignal *moreExecutionsAllowed = [RACSignal if:[self.allowsConcurrentExecutionSubject startWith:@NO] then:[RACSignal return:@YES] else:[immediateExecuting not]]; if (enabledSignal == nil) { enabledSignal = [RACSignal return:@YES]; } else { enabledSignal = [enabledSignal startWith:@YES]; } _immediateEnabled = [[[[RACSignal combineLatest:@[ enabledSignal, moreExecutionsAllowed ]] and] takeUntil:self.rac_willDeallocSignal] replayLast]; _enabled = [[[[[self.immediateEnabled take:1] concat:[[self.immediateEnabled skip:1] deliverOn:RACScheduler.mainThreadScheduler]] distinctUntilChanged] replayLast] setNameWithFormat:@"%@ -enabled", self]; return self; } #pragma mark Execution - (RACSignal *)execute:(id)input { // `immediateEnabled` is guaranteed to send a value upon subscription, so // -first is acceptable here. BOOL enabled = [[self.immediateEnabled first] boolValue]; if (!enabled) { NSError *error = [NSError errorWithDomain:RACCommandErrorDomain code:RACCommandErrorNotEnabled userInfo:@{ NSLocalizedDescriptionKey: NSLocalizedString(@"The command is disabled and cannot be executed", nil), RACUnderlyingCommandErrorKey: self }]; return [RACSignal error:error]; } RACSignal *signal = self.signalBlock(input); NSCAssert(signal != nil, @"nil signal returned from signal block for value: %@", input); // We subscribe to the signal on the main thread so that it occurs _after_ // -addActiveExecutionSignal: completes below. // // This means that `executing` and `enabled` will send updated values before // the signal actually starts performing work. RACMulticastConnection *connection = [[signal subscribeOn:RACScheduler.mainThreadScheduler] multicast:[RACReplaySubject subject]]; [self.addedExecutionSignalsSubject sendNext:connection.signal]; [connection connect]; return [connection.signal setNameWithFormat:@"%@ -execute: %@", self, RACDescription(input)]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACCompoundDisposable.h ================================================ // // RACCompoundDisposable.h // ReactiveCocoa // // Created by Josh Abernathy on 11/30/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACDisposable.h" /// A disposable of disposables. When it is disposed, it disposes of all its /// contained disposables. /// /// If -addDisposable: is called after the compound disposable has been disposed /// of, the given disposable is immediately disposed. This allows a compound /// disposable to act as a stand-in for a disposable that will be delivered /// asynchronously. @interface RACCompoundDisposable : RACDisposable /// Creates and returns a new compound disposable. + (instancetype)compoundDisposable; /// Creates and returns a new compound disposable containing the given /// disposables. + (instancetype)compoundDisposableWithDisposables:(NSArray *)disposables; /// Adds the given disposable. If the receiving disposable has already been /// disposed of, the given disposable is disposed immediately. /// /// This method is thread-safe. /// /// disposable - The disposable to add. This may be nil, in which case nothing /// happens. - (void)addDisposable:(RACDisposable *)disposable; /// Removes the specified disposable from the compound disposable (regardless of /// its disposed status), or does nothing if it's not in the compound disposable. /// /// This is mainly useful for limiting the memory usage of the compound /// disposable for long-running operations. /// /// This method is thread-safe. /// /// disposable - The disposable to remove. This argument may be nil (to make the /// use of weak references easier). - (void)removeDisposable:(RACDisposable *)disposable; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACCompoundDisposable.m ================================================ // // RACCompoundDisposable.m // ReactiveCocoa // // Created by Josh Abernathy on 11/30/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACCompoundDisposable.h" #import "RACCompoundDisposableProvider.h" #import // The number of child disposables for which space will be reserved directly in // `RACCompoundDisposable`. // // This number has been empirically determined to provide a good tradeoff // between performance, memory usage, and `RACCompoundDisposable` instance size // in a moderately complex GUI application. // // Profile any change! #define RACCompoundDisposableInlineCount 2 static CFMutableArrayRef RACCreateDisposablesArray(void) { // Compare values using only pointer equality. CFArrayCallBacks callbacks = kCFTypeArrayCallBacks; callbacks.equal = NULL; return CFArrayCreateMutable(NULL, 0, &callbacks); } @interface RACCompoundDisposable () { // Used for synchronization. OSSpinLock _spinLock; #if RACCompoundDisposableInlineCount // A fast array to the first N of the receiver's disposables. // // Once this is full, `_disposables` will be created and used for additional // disposables. // // This array should only be manipulated while _spinLock is held. RACDisposable *_inlineDisposables[RACCompoundDisposableInlineCount]; #endif // Contains the receiver's disposables. // // This array should only be manipulated while _spinLock is held. If // `_disposed` is YES, this may be NULL. CFMutableArrayRef _disposables; // Whether the receiver has already been disposed. // // This ivar should only be accessed while _spinLock is held. BOOL _disposed; } @end @implementation RACCompoundDisposable #pragma mark Properties - (BOOL)isDisposed { OSSpinLockLock(&_spinLock); BOOL disposed = _disposed; OSSpinLockUnlock(&_spinLock); return disposed; } #pragma mark Lifecycle + (instancetype)compoundDisposable { return [[self alloc] initWithDisposables:nil]; } + (instancetype)compoundDisposableWithDisposables:(NSArray *)disposables { return [[self alloc] initWithDisposables:disposables]; } - (id)initWithDisposables:(NSArray *)otherDisposables { self = [self init]; if (self == nil) return nil; #if RACCompoundDisposableInlineCount [otherDisposables enumerateObjectsUsingBlock:^(RACDisposable *disposable, NSUInteger index, BOOL *stop) { _inlineDisposables[index] = disposable; // Stop after this iteration if we've reached the end of the inlined // array. if (index == RACCompoundDisposableInlineCount - 1) *stop = YES; }]; #endif if (otherDisposables.count > RACCompoundDisposableInlineCount) { _disposables = RACCreateDisposablesArray(); CFRange range = CFRangeMake(RACCompoundDisposableInlineCount, (CFIndex)otherDisposables.count - RACCompoundDisposableInlineCount); CFArrayAppendArray(_disposables, (__bridge CFArrayRef)otherDisposables, range); } return self; } - (id)initWithBlock:(void (^)(void))block { RACDisposable *disposable = [RACDisposable disposableWithBlock:block]; return [self initWithDisposables:@[ disposable ]]; } - (void)dealloc { #if RACCompoundDisposableInlineCount for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) { _inlineDisposables[i] = nil; } #endif if (_disposables != NULL) { CFRelease(_disposables); _disposables = NULL; } } #pragma mark Addition and Removal - (void)addDisposable:(RACDisposable *)disposable { NSCParameterAssert(disposable != self); if (disposable == nil || disposable.disposed) return; BOOL shouldDispose = NO; OSSpinLockLock(&_spinLock); { if (_disposed) { shouldDispose = YES; } else { #if RACCompoundDisposableInlineCount for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) { if (_inlineDisposables[i] == nil) { _inlineDisposables[i] = disposable; goto foundSlot; } } #endif if (_disposables == NULL) _disposables = RACCreateDisposablesArray(); CFArrayAppendValue(_disposables, (__bridge void *)disposable); if (RACCOMPOUNDDISPOSABLE_ADDED_ENABLED()) { RACCOMPOUNDDISPOSABLE_ADDED(self.description.UTF8String, disposable.description.UTF8String, CFArrayGetCount(_disposables) + RACCompoundDisposableInlineCount); } #if RACCompoundDisposableInlineCount foundSlot:; #endif } } OSSpinLockUnlock(&_spinLock); // Performed outside of the lock in case the compound disposable is used // recursively. if (shouldDispose) [disposable dispose]; } - (void)removeDisposable:(RACDisposable *)disposable { if (disposable == nil) return; OSSpinLockLock(&_spinLock); { if (!_disposed) { #if RACCompoundDisposableInlineCount for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) { if (_inlineDisposables[i] == disposable) _inlineDisposables[i] = nil; } #endif if (_disposables != NULL) { CFIndex count = CFArrayGetCount(_disposables); for (CFIndex i = count - 1; i >= 0; i--) { const void *item = CFArrayGetValueAtIndex(_disposables, i); if (item == (__bridge void *)disposable) { CFArrayRemoveValueAtIndex(_disposables, i); } } if (RACCOMPOUNDDISPOSABLE_REMOVED_ENABLED()) { RACCOMPOUNDDISPOSABLE_REMOVED(self.description.UTF8String, disposable.description.UTF8String, CFArrayGetCount(_disposables) + RACCompoundDisposableInlineCount); } } } } OSSpinLockUnlock(&_spinLock); } #pragma mark RACDisposable static void disposeEach(const void *value, void *context) { RACDisposable *disposable = (__bridge id)value; [disposable dispose]; } - (void)dispose { #if RACCompoundDisposableInlineCount RACDisposable *inlineCopy[RACCompoundDisposableInlineCount]; #endif CFArrayRef remainingDisposables = NULL; OSSpinLockLock(&_spinLock); { _disposed = YES; #if RACCompoundDisposableInlineCount for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) { inlineCopy[i] = _inlineDisposables[i]; _inlineDisposables[i] = nil; } #endif remainingDisposables = _disposables; _disposables = NULL; } OSSpinLockUnlock(&_spinLock); #if RACCompoundDisposableInlineCount // Dispose outside of the lock in case the compound disposable is used // recursively. for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) { [inlineCopy[i] dispose]; } #endif if (remainingDisposables == NULL) return; CFIndex count = CFArrayGetCount(remainingDisposables); CFArrayApplyFunction(remainingDisposables, CFRangeMake(0, count), &disposeEach, NULL); CFRelease(remainingDisposables); } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACCompoundDisposableProvider.d ================================================ provider RACCompoundDisposable { probe added(char *compoundDisposable, char *disposable, long newTotal); probe removed(char *compoundDisposable, char *disposable, long newTotal); }; ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDelegateProxy.h ================================================ // // RACDelegateProxy.h // ReactiveCocoa // // Created by Cody Krieger on 5/19/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACSignal; // A private delegate object suitable for using // -rac_signalForSelector:fromProtocol: upon. @interface RACDelegateProxy : NSObject // The delegate to which messages should be forwarded if not handled by // any -signalForSelector: applications. @property (nonatomic, unsafe_unretained) id rac_proxiedDelegate; // Creates a delegate proxy capable of responding to selectors from `protocol`. - (instancetype)initWithProtocol:(Protocol *)protocol; // Calls -rac_signalForSelector:fromProtocol: using the `protocol` specified // during initialization. - (RACSignal *)signalForSelector:(SEL)selector; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDelegateProxy.m ================================================ // // RACDelegateProxy.m // ReactiveCocoa // // Created by Cody Krieger on 5/19/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACDelegateProxy.h" #import "NSObject+RACSelectorSignal.h" #import @interface RACDelegateProxy () { // Declared as an ivar to avoid method naming conflicts. Protocol *_protocol; } @end @implementation RACDelegateProxy #pragma mark Lifecycle - (instancetype)initWithProtocol:(Protocol *)protocol { NSCParameterAssert(protocol != NULL); self = [super init]; if (self == nil) return nil; class_addProtocol(self.class, protocol); _protocol = protocol; return self; } #pragma mark API - (RACSignal *)signalForSelector:(SEL)selector { return [self rac_signalForSelector:selector fromProtocol:_protocol]; } #pragma mark NSObject - (BOOL)isProxy { return YES; } - (void)forwardInvocation:(NSInvocation *)invocation { [invocation invokeWithTarget:self.rac_proxiedDelegate]; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { // Look for the selector as an optional instance method. struct objc_method_description methodDescription = protocol_getMethodDescription(_protocol, selector, NO, YES); if (methodDescription.name == NULL) { // Then fall back to looking for a required instance // method. methodDescription = protocol_getMethodDescription(_protocol, selector, YES, YES); if (methodDescription.name == NULL) return [super methodSignatureForSelector:selector]; } return [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; } - (BOOL)respondsToSelector:(SEL)selector { // Add the delegate to the autorelease pool, so it doesn't get deallocated // between this method call and -forwardInvocation:. __autoreleasing id delegate = self.rac_proxiedDelegate; if ([delegate respondsToSelector:selector]) return YES; return [super respondsToSelector:selector]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDisposable.h ================================================ // // RACDisposable.h // ReactiveCocoa // // Created by Josh Abernathy on 3/16/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACScopedDisposable; /// A disposable encapsulates the work necessary to tear down and cleanup a /// subscription. @interface RACDisposable : NSObject /// Whether the receiver has been disposed. /// /// Use of this property is discouraged, since it may be set to `YES` /// concurrently at any time. /// /// This property is not KVO-compliant. @property (atomic, assign, getter = isDisposed, readonly) BOOL disposed; + (instancetype)disposableWithBlock:(void (^)(void))block; /// Performs the disposal work. Can be called multiple times, though subsequent /// calls won't do anything. - (void)dispose; /// Returns a new disposable which will dispose of this disposable when it gets /// dealloc'd. - (RACScopedDisposable *)asScopedDisposable; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDisposable.m ================================================ // // RACDisposable.m // ReactiveCocoa // // Created by Josh Abernathy on 3/16/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACDisposable.h" #import "RACScopedDisposable.h" #import @interface RACDisposable () { // A copied block of type void (^)(void) containing the logic for disposal, // a pointer to `self` if no logic should be performed upon disposal, or // NULL if the receiver is already disposed. // // This should only be used atomically. void * volatile _disposeBlock; } @end @implementation RACDisposable #pragma mark Properties - (BOOL)isDisposed { return _disposeBlock == NULL; } #pragma mark Lifecycle - (id)init { self = [super init]; if (self == nil) return nil; _disposeBlock = (__bridge void *)self; OSMemoryBarrier(); return self; } - (id)initWithBlock:(void (^)(void))block { NSCParameterAssert(block != nil); self = [super init]; if (self == nil) return nil; _disposeBlock = (void *)CFBridgingRetain([block copy]); OSMemoryBarrier(); return self; } + (instancetype)disposableWithBlock:(void (^)(void))block { return [[self alloc] initWithBlock:block]; } - (void)dealloc { if (_disposeBlock == NULL || _disposeBlock == (__bridge void *)self) return; CFRelease(_disposeBlock); _disposeBlock = NULL; } #pragma mark Disposal - (void)dispose { void (^disposeBlock)(void) = NULL; while (YES) { void *blockPtr = _disposeBlock; if (OSAtomicCompareAndSwapPtrBarrier(blockPtr, NULL, &_disposeBlock)) { if (blockPtr != (__bridge void *)self) { disposeBlock = CFBridgingRelease(blockPtr); } break; } } if (disposeBlock != nil) disposeBlock(); } #pragma mark Scoped Disposables - (RACScopedDisposable *)asScopedDisposable { return [RACScopedDisposable scopedDisposableWithDisposable:self]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDynamicPropertySuperclass.h ================================================ // Copyright (c) 2015 GitHub. All rights reserved. #import /// This superclass is an implementation detail of DynamicProperty. Do /// not use it. @interface RACDynamicPropertySuperclass : NSObject @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDynamicPropertySuperclass.m ================================================ // Copyright (c) 2015 GitHub. All rights reserved. #import "RACDynamicPropertySuperclass.h" @interface RACDynamicPropertySuperclass () @property id value; @property id rac_value; @end @implementation RACDynamicPropertySuperclass - (id)value { return self.rac_value; } - (void)setValue:(id)value { self.rac_value = value; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDynamicSequence.h ================================================ // // RACDynamicSequence.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACSequence.h" // Private class that implements a sequence dynamically using blocks. @interface RACDynamicSequence : RACSequence // Returns a sequence which evaluates `dependencyBlock` only once, the first // time either `headBlock` or `tailBlock` is evaluated. The result of // `dependencyBlock` will be passed into `headBlock` and `tailBlock` when // invoked. + (RACSequence *)sequenceWithLazyDependency:(id (^)(void))dependencyBlock headBlock:(id (^)(id dependency))headBlock tailBlock:(RACSequence *(^)(id dependency))tailBlock; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDynamicSequence.m ================================================ // // RACDynamicSequence.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACDynamicSequence.h" #import // Determines how RACDynamicSequences will be deallocated before the next one is // shifted onto the autorelease pool. // // This avoids stack overflows when deallocating long chains of dynamic // sequences. #define DEALLOC_OVERFLOW_GUARD 100 @interface RACDynamicSequence () { // The value for the "head" property, if it's been evaluated already. // // Because it's legal for head to be nil, this ivar is valid any time // headBlock is nil. // // This ivar should only be accessed while synchronized on self. id _head; // The value for the "tail" property, if it's been evaluated already. // // Because it's legal for tail to be nil, this ivar is valid any time // tailBlock is nil. // // This ivar should only be accessed while synchronized on self. RACSequence *_tail; // The result of an evaluated `dependencyBlock`. // // This ivar is valid any time `hasDependency` is YES and `dependencyBlock` // is nil. // // This ivar should only be accessed while synchronized on self. id _dependency; } // A block used to evaluate head. This should be set to nil after `_head` has been // initialized. // // This is marked `strong` instead of `copy` because of some bizarre block // copying bug. See https://github.com/ReactiveCocoa/ReactiveCocoa/pull/506. // // The signature of this block varies based on the value of `hasDependency`: // // - If YES, this block is of type `id (^)(id)`. // - If NO, this block is of type `id (^)(void)`. // // This property should only be accessed while synchronized on self. @property (nonatomic, strong) id headBlock; // A block used to evaluate tail. This should be set to nil after `_tail` has been // initialized. // // This is marked `strong` instead of `copy` because of some bizarre block // copying bug. See https://github.com/ReactiveCocoa/ReactiveCocoa/pull/506. // // The signature of this block varies based on the value of `hasDependency`: // // - If YES, this block is of type `RACSequence * (^)(id)`. // - If NO, this block is of type `RACSequence * (^)(void)`. // // This property should only be accessed while synchronized on self. @property (nonatomic, strong) id tailBlock; // Whether the receiver was initialized with a `dependencyBlock`. // // This property should only be accessed while synchronized on self. @property (nonatomic, assign) BOOL hasDependency; // A dependency which must be evaluated before `headBlock` and `tailBlock`. This // should be set to nil after `_dependency` and `dependencyBlockExecuted` have // been set. // // This is marked `strong` instead of `copy` because of some bizarre block // copying bug. See https://github.com/ReactiveCocoa/ReactiveCocoa/pull/506. // // This property should only be accessed while synchronized on self. @property (nonatomic, strong) id (^dependencyBlock)(void); @end @implementation RACDynamicSequence #pragma mark Lifecycle + (RACSequence *)sequenceWithHeadBlock:(id (^)(void))headBlock tailBlock:(RACSequence *(^)(void))tailBlock { NSCParameterAssert(headBlock != nil); RACDynamicSequence *seq = [[RACDynamicSequence alloc] init]; seq.headBlock = [headBlock copy]; seq.tailBlock = [tailBlock copy]; seq.hasDependency = NO; return seq; } + (RACSequence *)sequenceWithLazyDependency:(id (^)(void))dependencyBlock headBlock:(id (^)(id dependency))headBlock tailBlock:(RACSequence *(^)(id dependency))tailBlock { NSCParameterAssert(dependencyBlock != nil); NSCParameterAssert(headBlock != nil); RACDynamicSequence *seq = [[RACDynamicSequence alloc] init]; seq.headBlock = [headBlock copy]; seq.tailBlock = [tailBlock copy]; seq.dependencyBlock = [dependencyBlock copy]; seq.hasDependency = YES; return seq; } - (void)dealloc { static volatile int32_t directDeallocCount = 0; if (OSAtomicIncrement32(&directDeallocCount) >= DEALLOC_OVERFLOW_GUARD) { OSAtomicAdd32(-DEALLOC_OVERFLOW_GUARD, &directDeallocCount); // Put this sequence's tail onto the autorelease pool so we stop // recursing. __autoreleasing RACSequence *tail __attribute__((unused)) = _tail; } _tail = nil; } #pragma mark RACSequence - (id)head { @synchronized (self) { id untypedHeadBlock = self.headBlock; if (untypedHeadBlock == nil) return _head; if (self.hasDependency) { if (self.dependencyBlock != nil) { _dependency = self.dependencyBlock(); self.dependencyBlock = nil; } id (^headBlock)(id) = untypedHeadBlock; _head = headBlock(_dependency); } else { id (^headBlock)(void) = untypedHeadBlock; _head = headBlock(); } self.headBlock = nil; return _head; } } - (RACSequence *)tail { @synchronized (self) { id untypedTailBlock = self.tailBlock; if (untypedTailBlock == nil) return _tail; if (self.hasDependency) { if (self.dependencyBlock != nil) { _dependency = self.dependencyBlock(); self.dependencyBlock = nil; } RACSequence * (^tailBlock)(id) = untypedTailBlock; _tail = tailBlock(_dependency); } else { RACSequence * (^tailBlock)(void) = untypedTailBlock; _tail = tailBlock(); } if (_tail.name == nil) _tail.name = self.name; self.tailBlock = nil; return _tail; } } #pragma mark NSObject - (NSString *)description { id head = @"(unresolved)"; id tail = @"(unresolved)"; @synchronized (self) { if (self.headBlock == nil) head = _head; if (self.tailBlock == nil) { tail = _tail; if (tail == self) tail = @"(self)"; } } return [NSString stringWithFormat:@"<%@: %p>{ name = %@, head = %@, tail = %@ }", self.class, self, self.name, head, tail]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDynamicSignal.h ================================================ // // RACDynamicSignal.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-10. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSignal.h" // A private `RACSignal` subclasses that implements its subscription behavior // using a block. @interface RACDynamicSignal : RACSignal + (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACDynamicSignal.m ================================================ // // RACDynamicSignal.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-10. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACDynamicSignal.h" #import "EXTScope.h" #import "RACCompoundDisposable.h" #import "RACPassthroughSubscriber.h" #import "RACScheduler+Private.h" #import "RACSubscriber.h" #import @interface RACDynamicSignal () // The block to invoke for each subscriber. @property (nonatomic, copy, readonly) RACDisposable * (^didSubscribe)(id subscriber); @end @implementation RACDynamicSignal #pragma mark Lifecycle + (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe { RACDynamicSignal *signal = [[self alloc] init]; signal->_didSubscribe = [didSubscribe copy]; return [signal setNameWithFormat:@"+createSignal:"]; } #pragma mark Managing Subscribers - (RACDisposable *)subscribe:(id)subscriber { NSCParameterAssert(subscriber != nil); RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable]; if (self.didSubscribe != NULL) { RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{ RACDisposable *innerDisposable = self.didSubscribe(subscriber); [disposable addDisposable:innerDisposable]; }]; [disposable addDisposable:schedulingDisposable]; } return disposable; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACEagerSequence.h ================================================ // // RACEagerSequence.h // ReactiveCocoa // // Created by Uri Baghin on 02/01/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACArraySequence.h" // Private class that implements an eager sequence. @interface RACEagerSequence : RACArraySequence @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACEagerSequence.m ================================================ // // RACEagerSequence.m // ReactiveCocoa // // Created by Uri Baghin on 02/01/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACEagerSequence.h" #import "NSObject+RACDescription.h" #import "RACArraySequence.h" @implementation RACEagerSequence #pragma mark RACStream + (instancetype)return:(id)value { return [[self sequenceWithArray:@[ value ] offset:0] setNameWithFormat:@"+return: %@", RACDescription(value)]; } - (instancetype)bind:(RACStreamBindBlock (^)(void))block { NSCParameterAssert(block != nil); RACStreamBindBlock bindBlock = block(); NSArray *currentArray = self.array; NSMutableArray *resultArray = [NSMutableArray arrayWithCapacity:currentArray.count]; for (id value in currentArray) { BOOL stop = NO; RACSequence *boundValue = (id)bindBlock(value, &stop); if (boundValue == nil) break; for (id x in boundValue) { [resultArray addObject:x]; } if (stop) break; } return [[self.class sequenceWithArray:resultArray offset:0] setNameWithFormat:@"[%@] -bind:", self.name]; } - (instancetype)concat:(RACSequence *)sequence { NSCParameterAssert(sequence != nil); NSCParameterAssert([sequence isKindOfClass:RACSequence.class]); NSArray *array = [self.array arrayByAddingObjectsFromArray:sequence.array]; return [[self.class sequenceWithArray:array offset:0] setNameWithFormat:@"[%@] -concat: %@", self.name, sequence]; } #pragma mark Extended methods - (RACSequence *)eagerSequence { return self; } - (RACSequence *)lazySequence { return [RACArraySequence sequenceWithArray:self.array offset:0]; } - (id)foldRightWithStart:(id)start reduce:(id (^)(id, RACSequence *rest))reduce { return [super foldRightWithStart:start reduce:^(id first, RACSequence *rest) { return reduce(first, rest.eagerSequence); }]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACEmptySequence.h ================================================ // // RACEmptySequence.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACSequence.h" // Private class representing an empty sequence. @interface RACEmptySequence : RACSequence @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACEmptySequence.m ================================================ // // RACEmptySequence.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACEmptySequence.h" @implementation RACEmptySequence #pragma mark Lifecycle + (instancetype)empty { static id singleton; static dispatch_once_t pred; dispatch_once(&pred, ^{ singleton = [[self alloc] init]; }); return singleton; } #pragma mark RACSequence - (id)head { return nil; } - (RACSequence *)tail { return nil; } - (RACSequence *)bind:(RACStreamBindBlock)bindBlock passingThroughValuesFromSequence:(RACSequence *)passthroughSequence { return passthroughSequence ?: self; } #pragma mark NSCoding - (Class)classForCoder { // Empty sequences should be encoded as themselves, not array sequences. return self.class; } - (id)initWithCoder:(NSCoder *)coder { // Return the singleton. return self.class.empty; } - (void)encodeWithCoder:(NSCoder *)coder { } #pragma mark NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p>{ name = %@ }", self.class, self, self.name]; } - (NSUInteger)hash { // This hash isn't ideal, but it's better than -[RACSequence hash], which // would just be zero because we have no head. return (NSUInteger)(__bridge void *)self; } - (BOOL)isEqual:(RACSequence *)seq { return (self == seq); } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACEmptySignal.h ================================================ // // RACEmptySignal.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-10. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSignal.h" // A private `RACSignal` subclasses that synchronously sends completed to any // subscribers. @interface RACEmptySignal : RACSignal + (RACSignal *)empty; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACEmptySignal.m ================================================ // // RACEmptySignal.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-10. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACEmptySignal.h" #import "RACScheduler+Private.h" #import "RACSubscriber.h" @implementation RACEmptySignal #pragma mark Properties // Only allow this signal's name to be customized in DEBUG, since it's // a singleton in release builds (see +empty). - (void)setName:(NSString *)name { #ifdef DEBUG [super setName:name]; #endif } - (NSString *)name { #ifdef DEBUG return super.name; #else return @"+empty"; #endif } #pragma mark Lifecycle + (RACSignal *)empty { #ifdef DEBUG // Create multiple instances of this class in DEBUG so users can set custom // names on each. return [[[self alloc] init] setNameWithFormat:@"+empty"]; #else static id singleton; static dispatch_once_t pred; dispatch_once(&pred, ^{ singleton = [[self alloc] init]; }); return singleton; #endif } #pragma mark Subscription - (RACDisposable *)subscribe:(id)subscriber { NSCParameterAssert(subscriber != nil); return [RACScheduler.subscriptionScheduler schedule:^{ [subscriber sendCompleted]; }]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACErrorSignal.h ================================================ // // RACErrorSignal.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-10. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSignal.h" // A private `RACSignal` subclasses that synchronously sends an error to any // subscribers. @interface RACErrorSignal : RACSignal + (RACSignal *)error:(NSError *)error; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACErrorSignal.m ================================================ // // RACErrorSignal.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-10. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACErrorSignal.h" #import "RACScheduler+Private.h" #import "RACSubscriber.h" @interface RACErrorSignal () // The error to send upon subscription. @property (nonatomic, strong, readonly) NSError *error; @end @implementation RACErrorSignal #pragma mark Lifecycle + (RACSignal *)error:(NSError *)error { RACErrorSignal *signal = [[self alloc] init]; signal->_error = error; #ifdef DEBUG [signal setNameWithFormat:@"+error: %@", error]; #else signal.name = @"+error:"; #endif return signal; } #pragma mark Subscription - (RACDisposable *)subscribe:(id)subscriber { NSCParameterAssert(subscriber != nil); return [RACScheduler.subscriptionScheduler schedule:^{ [subscriber sendError:self.error]; }]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACEvent.h ================================================ // // RACEvent.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-01-07. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import /// Describes the type of a RACEvent. /// /// RACEventTypeCompleted - A `completed` event. /// RACEventTypeError - An `error` event. /// RACEventTypeNext - A `next` event. typedef NS_ENUM(NSUInteger, RACEventType) { RACEventTypeCompleted, RACEventTypeError, RACEventTypeNext }; /// Represents an event sent by a RACSignal. /// /// This corresponds to the `Notification` class in Rx. @interface RACEvent : NSObject /// Returns a singleton RACEvent representing the `completed` event. + (instancetype)completedEvent; /// Returns a new event of type RACEventTypeError, containing the given error. + (instancetype)eventWithError:(NSError *)error; /// Returns a new event of type RACEventTypeNext, containing the given value. + (instancetype)eventWithValue:(id)value; /// The type of event represented by the receiver. @property (nonatomic, assign, readonly) RACEventType eventType; /// Returns whether the receiver is of type RACEventTypeCompleted or /// RACEventTypeError. @property (nonatomic, getter = isFinished, assign, readonly) BOOL finished; /// The error associated with an event of type RACEventTypeError. This will be /// nil for all other event types. @property (nonatomic, strong, readonly) NSError *error; /// The value associated with an event of type RACEventTypeNext. This will be /// nil for all other event types. @property (nonatomic, strong, readonly) id value; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACEvent.m ================================================ // // RACEvent.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-01-07. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACEvent.h" @interface RACEvent () // An object associated with this event. This will be used for the error and // value properties. @property (nonatomic, strong, readonly) id object; // Initializes the receiver with the given type and object. - (id)initWithEventType:(RACEventType)type object:(id)object; @end @implementation RACEvent #pragma mark Properties - (BOOL)isFinished { return self.eventType == RACEventTypeCompleted || self.eventType == RACEventTypeError; } - (NSError *)error { return (self.eventType == RACEventTypeError ? self.object : nil); } - (id)value { return (self.eventType == RACEventTypeNext ? self.object : nil); } #pragma mark Lifecycle + (instancetype)completedEvent { static dispatch_once_t pred; static id singleton; dispatch_once(&pred, ^{ singleton = [[self alloc] initWithEventType:RACEventTypeCompleted object:nil]; }); return singleton; } + (instancetype)eventWithError:(NSError *)error { return [[self alloc] initWithEventType:RACEventTypeError object:error]; } + (instancetype)eventWithValue:(id)value { return [[self alloc] initWithEventType:RACEventTypeNext object:value]; } - (id)initWithEventType:(RACEventType)type object:(id)object { self = [super init]; if (self == nil) return nil; _eventType = type; _object = object; return self; } #pragma mark NSCopying - (id)copyWithZone:(NSZone *)zone { return self; } #pragma mark NSObject - (NSString *)description { NSString *eventDescription = nil; switch (self.eventType) { case RACEventTypeCompleted: eventDescription = @"completed"; break; case RACEventTypeError: eventDescription = [NSString stringWithFormat:@"error = %@", self.object]; break; case RACEventTypeNext: eventDescription = [NSString stringWithFormat:@"next = %@", self.object]; break; default: NSCAssert(NO, @"Unrecognized event type: %i", (int)self.eventType); } return [NSString stringWithFormat:@"<%@: %p>{ %@ }", self.class, self, eventDescription]; } - (NSUInteger)hash { return self.eventType ^ [self.object hash]; } - (BOOL)isEqual:(id)event { if (event == self) return YES; if (![event isKindOfClass:RACEvent.class]) return NO; if (self.eventType != [event eventType]) return NO; // Catches the nil case too. return self.object == [event object] || [self.object isEqual:[event object]]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACGroupedSignal.h ================================================ // // RACGroupedSignal.h // ReactiveCocoa // // Created by Josh Abernathy on 5/2/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSubject.h" /// A grouped signal is used by -[RACSignal groupBy:transform:]. @interface RACGroupedSignal : RACSubject /// The key shared by the group. @property (nonatomic, readonly, copy) id key; + (instancetype)signalWithKey:(id)key; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACGroupedSignal.m ================================================ // // RACGroupedSignal.m // ReactiveCocoa // // Created by Josh Abernathy on 5/2/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACGroupedSignal.h" @interface RACGroupedSignal () @property (nonatomic, copy) id key; @end @implementation RACGroupedSignal #pragma mark API + (instancetype)signalWithKey:(id)key { RACGroupedSignal *subject = [self subject]; subject.key = key; return subject; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACImmediateScheduler.h ================================================ // // RACImmediateScheduler.h // ReactiveCocoa // // Created by Josh Abernathy on 11/30/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACScheduler.h" // A private scheduler which immediately executes its scheduled blocks. @interface RACImmediateScheduler : RACScheduler @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACImmediateScheduler.m ================================================ // // RACImmediateScheduler.m // ReactiveCocoa // // Created by Josh Abernathy on 11/30/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACImmediateScheduler.h" #import "RACScheduler+Private.h" @implementation RACImmediateScheduler #pragma mark Lifecycle - (id)init { return [super initWithName:@"com.ReactiveCocoa.RACScheduler.immediateScheduler"]; } #pragma mark RACScheduler - (RACDisposable *)schedule:(void (^)(void))block { NSCParameterAssert(block != NULL); block(); return nil; } - (RACDisposable *)after:(NSDate *)date schedule:(void (^)(void))block { NSCParameterAssert(date != nil); NSCParameterAssert(block != NULL); [NSThread sleepUntilDate:date]; block(); return nil; } - (RACDisposable *)after:(NSDate *)date repeatingEvery:(NSTimeInterval)interval withLeeway:(NSTimeInterval)leeway schedule:(void (^)(void))block { NSCAssert(NO, @"+[RACScheduler immediateScheduler] does not support %@.", NSStringFromSelector(_cmd)); return nil; } - (RACDisposable *)scheduleRecursiveBlock:(RACSchedulerRecursiveBlock)recursiveBlock { for (__block NSUInteger remaining = 1; remaining > 0; remaining--) { recursiveBlock(^{ remaining++; }); } return nil; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACIndexSetSequence.h ================================================ // // RACIndexSetSequence.h // ReactiveCocoa // // Created by Sergey Gavrilyuk on 12/18/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSequence.h" // Private class that adapts an array to the RACSequence interface. @interface RACIndexSetSequence : RACSequence + (instancetype)sequenceWithIndexSet:(NSIndexSet *)indexSet; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACIndexSetSequence.m ================================================ // // RACIndexSetSequence.m // ReactiveCocoa // // Created by Sergey Gavrilyuk on 12/18/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACIndexSetSequence.h" @interface RACIndexSetSequence () // A buffer holding the `NSUInteger` values to enumerate over. // // This is mostly used for memory management. Most access should go through // `indexes` instead. @property (nonatomic, strong, readonly) NSData *data; // The indexes that this sequence should enumerate. @property (nonatomic, readonly) const NSUInteger *indexes; // The number of indexes to enumerate. @property (nonatomic, readonly) NSUInteger count; @end @implementation RACIndexSetSequence #pragma mark Lifecycle + (instancetype)sequenceWithIndexSet:(NSIndexSet *)indexSet { NSUInteger count = indexSet.count; if (count == 0) return self.empty; NSUInteger sizeInBytes = sizeof(NSUInteger) * count; NSMutableData *data = [[NSMutableData alloc] initWithCapacity:sizeInBytes]; [indexSet getIndexes:data.mutableBytes maxCount:count inIndexRange:NULL]; RACIndexSetSequence *seq = [[self alloc] init]; seq->_data = data; seq->_indexes = data.bytes; seq->_count = count; return seq; } + (instancetype)sequenceWithIndexSetSequence:(RACIndexSetSequence *)indexSetSequence offset:(NSUInteger)offset { NSCParameterAssert(offset < indexSetSequence.count); RACIndexSetSequence *seq = [[self alloc] init]; seq->_data = indexSetSequence.data; seq->_indexes = indexSetSequence.indexes + offset; seq->_count = indexSetSequence.count - offset; return seq; } #pragma mark RACSequence - (id)head { return @(self.indexes[0]); } - (RACSequence *)tail { if (self.count <= 1) return [RACSequence empty]; return [self.class sequenceWithIndexSetSequence:self offset:1]; } #pragma mark NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id[])stackbuf count:(NSUInteger)len { NSCParameterAssert(len > 0); if (state->state >= self.count) { // Enumeration has completed. return 0; } if (state->state == 0) { // Enumeration begun, mark the mutation flag. state->mutationsPtr = state->extra; } state->itemsPtr = stackbuf; unsigned long index = 0; while (index < MIN(self.count - state->state, len)) { stackbuf[index] = @(self.indexes[index + state->state]); ++index; } state->state += index; return index; } #pragma mark NSObject - (NSString *)description { NSMutableString *indexesStr = [NSMutableString string]; for (unsigned int i = 0; i < self.count; ++i) { if (i > 0) [indexesStr appendString:@", "]; [indexesStr appendFormat:@"%lu", (unsigned long)self.indexes[i]]; } return [NSString stringWithFormat:@"<%@: %p>{ name = %@, indexes = %@ }", self.class, self, self.name, indexesStr]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACKVOChannel.h ================================================ // // RACKVOChannel.h // ReactiveCocoa // // Created by Uri Baghin on 27/12/2012. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACChannel.h" #import "EXTKeyPathCoding.h" #import "metamacros.h" /// Creates a RACKVOChannel to the given key path. When the targeted object /// deallocates, the channel will complete. /// /// If RACChannelTo() is used as an expression, it returns a RACChannelTerminal that /// can be used to watch the specified property for changes, and set new values /// for it. The terminal will start with the property's current value upon /// subscription. /// /// If RACChannelTo() is used on the left-hand side of an assignment, there must a /// RACChannelTerminal on the right-hand side of the assignment. The two will be /// subscribed to one another: the property's value is immediately set to the /// value of the channel terminal on the right-hand side, and subsequent changes /// to either terminal will be reflected on the other. /// /// There are two different versions of this macro: /// /// - RACChannelTo(TARGET, KEYPATH, NILVALUE) will create a channel to the `KEYPATH` /// of `TARGET`. If the terminal is ever sent a `nil` value, the property will /// be set to `NILVALUE` instead. `NILVALUE` may itself be `nil` for object /// properties, but an NSValue should be used for primitive properties, to /// avoid an exception if `nil` is sent (which might occur if an intermediate /// object is set to `nil`). /// - RACChannelTo(TARGET, KEYPATH) is the same as the above, but `NILVALUE` defaults to /// `nil`. /// /// Examples /// /// RACChannelTerminal *integerChannel = RACChannelTo(self, integerProperty, @42); /// /// // Sets self.integerProperty to 5. /// [integerChannel sendNext:@5]; /// /// // Logs the current value of self.integerProperty, and all future changes. /// [integerChannel subscribeNext:^(id value) { /// NSLog(@"value: %@", value); /// }]; /// /// // Binds properties to each other, taking the initial value from the right /// side. /// RACChannelTo(view, objectProperty) = RACChannelTo(model, objectProperty); /// RACChannelTo(view, integerProperty, @2) = RACChannelTo(model, integerProperty, @10); #define RACChannelTo(TARGET, ...) \ metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \ (RACChannelTo_(TARGET, __VA_ARGS__, nil)) \ (RACChannelTo_(TARGET, __VA_ARGS__)) /// Do not use this directly. Use the RACChannelTo macro above. #define RACChannelTo_(TARGET, KEYPATH, NILVALUE) \ [[RACKVOChannel alloc] initWithTarget:(TARGET) keyPath:@keypath(TARGET, KEYPATH) nilValue:(NILVALUE)][@keypath(RACKVOChannel.new, followingTerminal)] /// A RACChannel that observes a KVO-compliant key path for changes. @interface RACKVOChannel : RACChannel /// Initializes a channel that will observe the given object and key path. /// /// The current value of the key path, and future KVO notifications for the given /// key path, will be sent to subscribers of the channel's `followingTerminal`. /// Values sent to the `followingTerminal` will be set at the given key path using /// key-value coding. /// /// When the target object deallocates, the channel will complete. Signal errors /// are considered undefined behavior. /// /// This is the designated initializer for this class. /// /// target - The object to bind to. /// keyPath - The key path to observe and set the value of. /// nilValue - The value to set at the key path whenever a `nil` value is /// received. This may be nil when connecting to object properties, but /// an NSValue should be used for primitive properties, to avoid an /// exception if `nil` is received (which might occur if an intermediate /// object is set to `nil`). #if OS_OBJECT_HAVE_OBJC_SUPPORT - (id)initWithTarget:(__weak NSObject *)target keyPath:(NSString *)keyPath nilValue:(id)nilValue; #else // Swift builds with OS_OBJECT_HAVE_OBJC_SUPPORT=0 for Playgrounds and LLDB :( - (id)initWithTarget:(NSObject *)target keyPath:(NSString *)keyPath nilValue:(id)nilValue; #endif - (id)init __attribute__((unavailable("Use -initWithTarget:keyPath:nilValue: instead"))); @end /// Methods needed for the convenience macro. Do not call explicitly. @interface RACKVOChannel (RACChannelTo) - (RACChannelTerminal *)objectForKeyedSubscript:(NSString *)key; - (void)setObject:(RACChannelTerminal *)otherTerminal forKeyedSubscript:(NSString *)key; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACKVOChannel.m ================================================ // // RACKVOChannel.m // ReactiveCocoa // // Created by Uri Baghin on 27/12/2012. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACKVOChannel.h" #import "EXTScope.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACKVOWrapper.h" #import "NSString+RACKeyPathUtilities.h" #import "RACChannel.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACSignal+Operations.h" // Key for the array of RACKVOChannel's additional thread local // data in the thread dictionary. static NSString * const RACKVOChannelDataDictionaryKey = @"RACKVOChannelKey"; // Wrapper class for additional thread local data. @interface RACKVOChannelData : NSObject // The flag used to ignore updates the channel itself has triggered. @property (nonatomic, assign) BOOL ignoreNextUpdate; // A pointer to the owner of the data. Only use this for pointer comparison, // never as an object reference. @property (nonatomic, assign) void *owner; + (instancetype)dataForChannel:(RACKVOChannel *)channel; @end @interface RACKVOChannel () // The object whose key path the channel is wrapping. @property (atomic, weak) NSObject *target; // The key path the channel is wrapping. @property (nonatomic, copy, readonly) NSString *keyPath; // Returns the existing thread local data container or nil if none exists. @property (nonatomic, strong, readonly) RACKVOChannelData *currentThreadData; // Creates the thread local data container for the channel. - (void)createCurrentThreadData; // Destroy the thread local data container for the channel. - (void)destroyCurrentThreadData; @end @implementation RACKVOChannel #pragma mark Properties - (RACKVOChannelData *)currentThreadData { NSMutableArray *dataArray = NSThread.currentThread.threadDictionary[RACKVOChannelDataDictionaryKey]; for (RACKVOChannelData *data in dataArray) { if (data.owner == (__bridge void *)self) return data; } return nil; } #pragma mark Lifecycle - (id)initWithTarget:(__weak NSObject *)target keyPath:(NSString *)keyPath nilValue:(id)nilValue { NSCParameterAssert(keyPath.rac_keyPathComponents.count > 0); NSObject *strongTarget = target; self = [super init]; if (self == nil) return nil; _target = target; _keyPath = [keyPath copy]; [self.leadingTerminal setNameWithFormat:@"[-initWithTarget: %@ keyPath: %@ nilValue: %@] -leadingTerminal", target, keyPath, nilValue]; [self.followingTerminal setNameWithFormat:@"[-initWithTarget: %@ keyPath: %@ nilValue: %@] -followingTerminal", target, keyPath, nilValue]; if (strongTarget == nil) { [self.leadingTerminal sendCompleted]; return self; } // Observe the key path on target for changes and forward the changes to the // terminal. // // Intentionally capturing `self` strongly in the blocks below, so the // channel object stays alive while observing. RACDisposable *observationDisposable = [strongTarget rac_observeKeyPath:keyPath options:NSKeyValueObservingOptionInitial observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) { // If the change wasn't triggered by deallocation, only affects the last // path component, and ignoreNextUpdate is set, then it was triggered by // this channel and should not be forwarded. if (!causedByDealloc && affectedOnlyLastComponent && self.currentThreadData.ignoreNextUpdate) { [self destroyCurrentThreadData]; return; } [self.leadingTerminal sendNext:value]; }]; NSString *keyPathByDeletingLastKeyPathComponent = keyPath.rac_keyPathByDeletingLastKeyPathComponent; NSArray *keyPathComponents = keyPath.rac_keyPathComponents; NSUInteger keyPathComponentsCount = keyPathComponents.count; NSString *lastKeyPathComponent = keyPathComponents.lastObject; // Update the value of the property with the values received. [[self.leadingTerminal finally:^{ [observationDisposable dispose]; }] subscribeNext:^(id x) { // Check the value of the second to last key path component. Since the // channel can only update the value of a property on an object, and not // update intermediate objects, it can only update the value of the whole // key path if this object is not nil. NSObject *object = (keyPathComponentsCount > 1 ? [self.target valueForKeyPath:keyPathByDeletingLastKeyPathComponent] : self.target); if (object == nil) return; // Set the ignoreNextUpdate flag before setting the value so this channel // ignores the value in the subsequent -didChangeValueForKey: callback. [self createCurrentThreadData]; self.currentThreadData.ignoreNextUpdate = YES; [object setValue:x ?: nilValue forKey:lastKeyPathComponent]; } error:^(NSError *error) { NSCAssert(NO, @"Received error in %@: %@", self, error); // Log the error if we're running with assertions disabled. NSLog(@"Received error in %@: %@", self, error); }]; // Capture `self` weakly for the target's deallocation disposable, so we can // freely deallocate if we complete before then. @weakify(self); [strongTarget.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ @strongify(self); [self.leadingTerminal sendCompleted]; self.target = nil; }]]; return self; } - (void)createCurrentThreadData { NSMutableArray *dataArray = NSThread.currentThread.threadDictionary[RACKVOChannelDataDictionaryKey]; if (dataArray == nil) { dataArray = [NSMutableArray array]; NSThread.currentThread.threadDictionary[RACKVOChannelDataDictionaryKey] = dataArray; [dataArray addObject:[RACKVOChannelData dataForChannel:self]]; return; } for (RACKVOChannelData *data in dataArray) { if (data.owner == (__bridge void *)self) return; } [dataArray addObject:[RACKVOChannelData dataForChannel:self]]; } - (void)destroyCurrentThreadData { NSMutableArray *dataArray = NSThread.currentThread.threadDictionary[RACKVOChannelDataDictionaryKey]; NSUInteger index = [dataArray indexOfObjectPassingTest:^ BOOL (RACKVOChannelData *data, NSUInteger idx, BOOL *stop) { return data.owner == (__bridge void *)self; }]; if (index != NSNotFound) [dataArray removeObjectAtIndex:index]; } @end @implementation RACKVOChannel (RACChannelTo) - (RACChannelTerminal *)objectForKeyedSubscript:(NSString *)key { NSCParameterAssert(key != nil); RACChannelTerminal *terminal = [self valueForKey:key]; NSCAssert([terminal isKindOfClass:RACChannelTerminal.class], @"Key \"%@\" does not identify a channel terminal", key); return terminal; } - (void)setObject:(RACChannelTerminal *)otherTerminal forKeyedSubscript:(NSString *)key { NSCParameterAssert(otherTerminal != nil); RACChannelTerminal *selfTerminal = [self objectForKeyedSubscript:key]; [otherTerminal subscribe:selfTerminal]; [[selfTerminal skip:1] subscribe:otherTerminal]; } @end @implementation RACKVOChannelData + (instancetype)dataForChannel:(RACKVOChannel *)channel { RACKVOChannelData *data = [[self alloc] init]; data->_owner = (__bridge void *)channel; return data; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACKVOProxy.h ================================================ // // RACKVOProxy.h // ReactiveCocoa // // Created by Richard Speyer on 4/10/14. // Copyright (c) 2014 GitHub, Inc. All rights reserved. // #import /// A singleton that can act as a proxy between a KVO observation and a RAC /// subscriber, in order to protect against KVO lifetime issues. @interface RACKVOProxy : NSObject /// Returns the singleton KVO proxy object. + (instancetype)sharedProxy; /// Registers an observer with the proxy, such that when the proxy receives a /// KVO change with the given context, it forwards it to the observer. /// /// observer - True observer of the KVO change. Must not be nil. /// context - Arbitrary context object used to differentiate multiple /// observations of the same keypath. Must be unique, cannot be nil. - (void)addObserver:(__weak NSObject *)observer forContext:(void *)context; /// Removes an observer from the proxy. Parameters must match those passed to /// addObserver:forContext:. /// /// observer - True observer of the KVO change. Must not be nil. /// context - Arbitrary context object used to differentiate multiple /// observations of the same keypath. Must be unique, cannot be nil. - (void)removeObserver:(NSObject *)observer forContext:(void *)context; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACKVOProxy.m ================================================ // // RACKVOProxy.m // ReactiveCocoa // // Created by Richard Speyer on 4/10/14. // Copyright (c) 2014 GitHub, Inc. All rights reserved. // #import "RACKVOProxy.h" @interface RACKVOProxy() @property (strong, nonatomic, readonly) NSMapTable *trampolines; @property (strong, nonatomic, readonly) dispatch_queue_t queue; @end @implementation RACKVOProxy + (instancetype)sharedProxy { static RACKVOProxy *proxy; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ proxy = [[self alloc] init]; }); return proxy; } - (instancetype)init { self = [super init]; if (self == nil) return nil; _queue = dispatch_queue_create("org.reactivecocoa.ReactiveCocoa.RACKVOProxy", DISPATCH_QUEUE_SERIAL); _trampolines = [NSMapTable strongToWeakObjectsMapTable]; return self; } - (void)addObserver:(__weak NSObject *)observer forContext:(void *)context { NSValue *valueContext = [NSValue valueWithPointer:context]; dispatch_sync(self.queue, ^{ [self.trampolines setObject:observer forKey:valueContext]; }); } - (void)removeObserver:(NSObject *)observer forContext:(void *)context { NSValue *valueContext = [NSValue valueWithPointer:context]; dispatch_sync(self.queue, ^{ [self.trampolines removeObjectForKey:valueContext]; }); } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { NSValue *valueContext = [NSValue valueWithPointer:context]; __block NSObject *trueObserver; dispatch_sync(self.queue, ^{ trueObserver = [self.trampolines objectForKey:valueContext]; }); if (trueObserver != nil) { [trueObserver observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACKVOTrampoline.h ================================================ // // RACKVOTrampoline.h // ReactiveCocoa // // Created by Josh Abernathy on 1/15/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import #import "NSObject+RACKVOWrapper.h" #import "RACDisposable.h" // A private trampoline object that represents a KVO observation. // // Disposing of the trampoline will stop observation. @interface RACKVOTrampoline : RACDisposable // Initializes the receiver with the given parameters. // // target - The object whose key path should be observed. Cannot be nil. // observer - The object that gets notified when the value at the key path // changes. Can be nil. // keyPath - The key path on `target` to observe. Cannot be nil. // options - Any key value observing options to use in the observation. // block - The block to call when the value at the observed key path changes. // Cannot be nil. // // Returns the initialized object. - (id)initWithTarget:(__weak NSObject *)target observer:(__weak NSObject *)observer keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(RACKVOBlock)block; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACKVOTrampoline.m ================================================ // // RACKVOTrampoline.m // ReactiveCocoa // // Created by Josh Abernathy on 1/15/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACKVOTrampoline.h" #import "NSObject+RACDeallocating.h" #import "RACCompoundDisposable.h" #import "RACKVOProxy.h" @interface RACKVOTrampoline () // The keypath which the trampoline is observing. @property (nonatomic, readonly, copy) NSString *keyPath; // These properties should only be manipulated while synchronized on the // receiver. @property (nonatomic, readonly, copy) RACKVOBlock block; @property (nonatomic, readonly, unsafe_unretained) NSObject *unsafeTarget; @property (nonatomic, readonly, weak) NSObject *weakTarget; @property (nonatomic, readonly, weak) NSObject *observer; @end @implementation RACKVOTrampoline #pragma mark Lifecycle - (id)initWithTarget:(__weak NSObject *)target observer:(__weak NSObject *)observer keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(RACKVOBlock)block { NSCParameterAssert(keyPath != nil); NSCParameterAssert(block != nil); NSObject *strongTarget = target; if (strongTarget == nil) return nil; self = [super init]; if (self == nil) return nil; _keyPath = [keyPath copy]; _block = [block copy]; _weakTarget = target; _unsafeTarget = strongTarget; _observer = observer; [RACKVOProxy.sharedProxy addObserver:self forContext:(__bridge void *)self]; [strongTarget addObserver:RACKVOProxy.sharedProxy forKeyPath:self.keyPath options:options context:(__bridge void *)self]; [strongTarget.rac_deallocDisposable addDisposable:self]; [self.observer.rac_deallocDisposable addDisposable:self]; return self; } - (void)dealloc { [self dispose]; } #pragma mark Observation - (void)dispose { NSObject *target; NSObject *observer; @synchronized (self) { _block = nil; // The target should still exist at this point, because we still need to // tear down its KVO observation. Therefore, we can use the unsafe // reference (and need to, because the weak one will have been zeroed by // now). target = self.unsafeTarget; observer = self.observer; _unsafeTarget = nil; _observer = nil; } [target.rac_deallocDisposable removeDisposable:self]; [observer.rac_deallocDisposable removeDisposable:self]; [target removeObserver:RACKVOProxy.sharedProxy forKeyPath:self.keyPath context:(__bridge void *)self]; [RACKVOProxy.sharedProxy removeObserver:self forContext:(__bridge void *)self]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context != (__bridge void *)self) { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; return; } RACKVOBlock block; id observer; id target; @synchronized (self) { block = self.block; observer = self.observer; target = self.weakTarget; } if (block == nil || target == nil) return; block(target, observer, change); } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACMulticastConnection+Private.h ================================================ // // RACMulticastConnection+Private.h // ReactiveCocoa // // Created by Josh Abernathy on 4/11/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACMulticastConnection.h" @class RACSubject; @interface RACMulticastConnection () - (id)initWithSourceSignal:(RACSignal *)source subject:(RACSubject *)subject; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACMulticastConnection.h ================================================ // // RACMulticastConnection.h // ReactiveCocoa // // Created by Josh Abernathy on 4/11/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACDisposable; @class RACSignal; /// A multicast connection encapsulates the idea of sharing one subscription to a /// signal to many subscribers. This is most often needed if the subscription to /// the underlying signal involves side-effects or shouldn't be called more than /// once. /// /// The multicasted signal is only subscribed to when /// -[RACMulticastConnection connect] is called. Until that happens, no values /// will be sent on `signal`. See -[RACMulticastConnection autoconnect] for how /// -[RACMulticastConnection connect] can be called automatically. /// /// Note that you shouldn't create RACMulticastConnection manually. Instead use /// -[RACSignal publish] or -[RACSignal multicast:]. @interface RACMulticastConnection : NSObject /// The multicasted signal. @property (nonatomic, strong, readonly) RACSignal *signal; /// Connect to the underlying signal by subscribing to it. Calling this multiple /// times does nothing but return the existing connection's disposable. /// /// Returns the disposable for the subscription to the multicasted signal. - (RACDisposable *)connect; /// Connects to the underlying signal when the returned signal is first /// subscribed to, and disposes of the subscription to the multicasted signal /// when the returned signal has no subscribers. /// /// If new subscribers show up after being disposed, they'll subscribe and then /// be immediately disposed of. The returned signal will never re-connect to the /// multicasted signal. /// /// Returns the autoconnecting signal. - (RACSignal *)autoconnect; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACMulticastConnection.m ================================================ // // RACMulticastConnection.m // ReactiveCocoa // // Created by Josh Abernathy on 4/11/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACMulticastConnection.h" #import "RACMulticastConnection+Private.h" #import "RACDisposable.h" #import "RACSerialDisposable.h" #import "RACSubject.h" #import @interface RACMulticastConnection () { RACSubject *_signal; // When connecting, a caller should attempt to atomically swap the value of this // from `0` to `1`. // // If the swap is successful the caller is resposible for subscribing `_signal` // to `sourceSignal` and storing the returned disposable in `serialDisposable`. // // If the swap is unsuccessful it means that `_sourceSignal` has already been // connected and the caller has no action to take. int32_t volatile _hasConnected; } @property (nonatomic, readonly, strong) RACSignal *sourceSignal; @property (strong) RACSerialDisposable *serialDisposable; @end @implementation RACMulticastConnection #pragma mark Lifecycle - (id)initWithSourceSignal:(RACSignal *)source subject:(RACSubject *)subject { NSCParameterAssert(source != nil); NSCParameterAssert(subject != nil); self = [super init]; if (self == nil) return nil; _sourceSignal = source; _serialDisposable = [[RACSerialDisposable alloc] init]; _signal = subject; return self; } #pragma mark Connecting - (RACDisposable *)connect { BOOL shouldConnect = OSAtomicCompareAndSwap32Barrier(0, 1, &_hasConnected); if (shouldConnect) { self.serialDisposable.disposable = [self.sourceSignal subscribe:_signal]; } return self.serialDisposable; } - (RACSignal *)autoconnect { __block volatile int32_t subscriberCount = 0; return [[RACSignal createSignal:^(id subscriber) { OSAtomicIncrement32Barrier(&subscriberCount); RACDisposable *subscriptionDisposable = [self.signal subscribe:subscriber]; RACDisposable *connectionDisposable = [self connect]; return [RACDisposable disposableWithBlock:^{ [subscriptionDisposable dispose]; if (OSAtomicDecrement32Barrier(&subscriberCount) == 0) { [connectionDisposable dispose]; } }]; }] setNameWithFormat:@"[%@] -autoconnect", self.signal.name]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACObjCRuntime.h ================================================ // // RACObjCRuntime.h // ReactiveCocoa // // Created by Cody Krieger on 5/19/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import // A private class containing wrappers to runtime functions. @interface RACObjCRuntime : NSObject // Invokes objc_allocateClassPair(). Can be called from ARC code. + (Class)createClass:(const char *)className inheritingFromClass:(Class)superclass; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACObjCRuntime.m ================================================ // // RACObjCRuntime.m // ReactiveCocoa // // Created by Cody Krieger on 5/19/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACObjCRuntime.h" #import #if __has_feature(objc_arc) #error "This file must be compiled without ARC." #endif @implementation RACObjCRuntime + (Class)createClass:(const char *)className inheritingFromClass:(Class)superclass { return objc_allocateClassPair(superclass, className, 0); } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACPassthroughSubscriber.h ================================================ // // RACPassthroughSubscriber.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-06-13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import #import "RACSubscriber.h" @class RACCompoundDisposable; @class RACSignal; // A private subscriber that passes through all events to another subscriber // while not disposed. @interface RACPassthroughSubscriber : NSObject // Initializes the receiver to pass through events until disposed. // // subscriber - The subscriber to forward events to. This must not be nil. // signal - The signal that will be sending events to the receiver. // disposable - When this disposable is disposed, no more events will be // forwarded. This must not be nil. // // Returns an initialized passthrough subscriber. - (instancetype)initWithSubscriber:(id)subscriber signal:(RACSignal *)signal disposable:(RACCompoundDisposable *)disposable; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACPassthroughSubscriber.m ================================================ // // RACPassthroughSubscriber.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-06-13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACPassthroughSubscriber.h" #import "RACCompoundDisposable.h" #import "RACSignal.h" #import "RACSignalProvider.h" #if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED static const char *cleanedDTraceString(NSString *original) { return [original stringByReplacingOccurrencesOfString:@"\\s+" withString:@" " options:NSRegularExpressionSearch range:NSMakeRange(0, original.length)].UTF8String; } static const char *cleanedSignalDescription(RACSignal *signal) { NSString *desc = signal.description; NSRange range = [desc rangeOfString:@" name:"]; if (range.location != NSNotFound) { desc = [desc stringByReplacingCharactersInRange:range withString:@""]; } return cleanedDTraceString(desc); } #endif @interface RACPassthroughSubscriber () // The subscriber to which events should be forwarded. @property (nonatomic, strong, readonly) id innerSubscriber; // The signal sending events to this subscriber. // // This property isn't `weak` because it's only used for DTrace probes, so // a zeroing weak reference would incur an unnecessary performance penalty in // normal usage. @property (nonatomic, unsafe_unretained, readonly) RACSignal *signal; // A disposable representing the subscription. When disposed, no further events // should be sent to the `innerSubscriber`. @property (nonatomic, strong, readonly) RACCompoundDisposable *disposable; @end @implementation RACPassthroughSubscriber #pragma mark Lifecycle - (instancetype)initWithSubscriber:(id)subscriber signal:(RACSignal *)signal disposable:(RACCompoundDisposable *)disposable { NSCParameterAssert(subscriber != nil); self = [super init]; if (self == nil) return nil; _innerSubscriber = subscriber; _signal = signal; _disposable = disposable; [self.innerSubscriber didSubscribeWithDisposable:self.disposable]; return self; } #pragma mark RACSubscriber - (void)sendNext:(id)value { if (self.disposable.disposed) return; if (RACSIGNAL_NEXT_ENABLED()) { RACSIGNAL_NEXT(cleanedSignalDescription(self.signal), cleanedDTraceString(self.innerSubscriber.description), cleanedDTraceString([value description])); } [self.innerSubscriber sendNext:value]; } - (void)sendError:(NSError *)error { if (self.disposable.disposed) return; if (RACSIGNAL_ERROR_ENABLED()) { RACSIGNAL_ERROR(cleanedSignalDescription(self.signal), cleanedDTraceString(self.innerSubscriber.description), cleanedDTraceString(error.description)); } [self.innerSubscriber sendError:error]; } - (void)sendCompleted { if (self.disposable.disposed) return; if (RACSIGNAL_COMPLETED_ENABLED()) { RACSIGNAL_COMPLETED(cleanedSignalDescription(self.signal), cleanedDTraceString(self.innerSubscriber.description)); } [self.innerSubscriber sendCompleted]; } - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable { if (disposable != self.disposable) { [self.disposable addDisposable:disposable]; } } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACQueueScheduler+Subclass.h ================================================ // // RACQueueScheduler+Subclass.h // ReactiveCocoa // // Created by Josh Abernathy on 6/6/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACQueueScheduler.h" #import "RACScheduler+Subclass.h" /// An interface for use by GCD queue-based subclasses. /// /// See RACScheduler+Subclass.h for subclassing notes. @interface RACQueueScheduler () /// The queue on which blocks are enqueued. #if OS_OBJECT_USE_OBJC @property (nonatomic, strong, readonly) dispatch_queue_t queue; #else // Swift builds with OS_OBJECT_HAVE_OBJC_SUPPORT=0 for Playgrounds and LLDB :( @property (nonatomic, assign, readonly) dispatch_queue_t queue; #endif /// Initializes the receiver with the name of the scheduler and the queue which /// the scheduler should use. /// /// name - The name of the scheduler. If nil, a default name will be used. /// queue - The queue upon which the receiver should enqueue scheduled blocks. /// This argument must not be NULL. /// /// Returns the initialized object. - (id)initWithName:(NSString *)name queue:(dispatch_queue_t)queue; /// Converts a date into a GCD time using dispatch_walltime(). /// /// date - The date to convert. This must not be nil. + (dispatch_time_t)wallTimeWithDate:(NSDate *)date; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACQueueScheduler.h ================================================ // // RACQueueScheduler.h // ReactiveCocoa // // Created by Josh Abernathy on 11/30/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACScheduler.h" /// An abstract scheduler which asynchronously enqueues all its work to a Grand /// Central Dispatch queue. /// /// Because RACQueueScheduler is abstract, it should not be instantiated /// directly. Create a subclass using the `RACQueueScheduler+Subclass.h` /// interface and use that instead. @interface RACQueueScheduler : RACScheduler @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACQueueScheduler.m ================================================ // // RACQueueScheduler.m // ReactiveCocoa // // Created by Josh Abernathy on 11/30/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACQueueScheduler.h" #import "RACDisposable.h" #import "RACQueueScheduler+Subclass.h" #import "RACScheduler+Private.h" @implementation RACQueueScheduler #pragma mark Lifecycle - (id)initWithName:(NSString *)name queue:(dispatch_queue_t)queue { NSCParameterAssert(queue != NULL); self = [super initWithName:name]; if (self == nil) return nil; _queue = queue; #if !OS_OBJECT_USE_OBJC dispatch_retain(_queue); #endif return self; } #if !OS_OBJECT_USE_OBJC - (void)dealloc { if (_queue != NULL) { dispatch_release(_queue); _queue = NULL; } } #endif #pragma mark Date Conversions + (dispatch_time_t)wallTimeWithDate:(NSDate *)date { NSCParameterAssert(date != nil); double seconds = 0; double frac = modf(date.timeIntervalSince1970, &seconds); struct timespec walltime = { .tv_sec = (time_t)fmin(fmax(seconds, LONG_MIN), LONG_MAX), .tv_nsec = (long)fmin(fmax(frac * NSEC_PER_SEC, LONG_MIN), LONG_MAX) }; return dispatch_walltime(&walltime, 0); } #pragma mark RACScheduler - (RACDisposable *)schedule:(void (^)(void))block { NSCParameterAssert(block != NULL); RACDisposable *disposable = [[RACDisposable alloc] init]; dispatch_async(self.queue, ^{ if (disposable.disposed) return; [self performAsCurrentScheduler:block]; }); return disposable; } - (RACDisposable *)after:(NSDate *)date schedule:(void (^)(void))block { NSCParameterAssert(date != nil); NSCParameterAssert(block != NULL); RACDisposable *disposable = [[RACDisposable alloc] init]; dispatch_after([self.class wallTimeWithDate:date], self.queue, ^{ if (disposable.disposed) return; [self performAsCurrentScheduler:block]; }); return disposable; } - (RACDisposable *)after:(NSDate *)date repeatingEvery:(NSTimeInterval)interval withLeeway:(NSTimeInterval)leeway schedule:(void (^)(void))block { NSCParameterAssert(date != nil); NSCParameterAssert(interval > 0.0 && interval < INT64_MAX / NSEC_PER_SEC); NSCParameterAssert(leeway >= 0.0 && leeway < INT64_MAX / NSEC_PER_SEC); NSCParameterAssert(block != NULL); uint64_t intervalInNanoSecs = (uint64_t)(interval * NSEC_PER_SEC); uint64_t leewayInNanoSecs = (uint64_t)(leeway * NSEC_PER_SEC); dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue); dispatch_source_set_timer(timer, [self.class wallTimeWithDate:date], intervalInNanoSecs, leewayInNanoSecs); dispatch_source_set_event_handler(timer, block); dispatch_resume(timer); return [RACDisposable disposableWithBlock:^{ dispatch_source_cancel(timer); }]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACReplaySubject.h ================================================ // // RACReplaySubject.h // ReactiveCocoa // // Created by Josh Abernathy on 3/14/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSubject.h" extern const NSUInteger RACReplaySubjectUnlimitedCapacity; /// A replay subject saves the values it is sent (up to its defined capacity) /// and resends those to new subscribers. It will also replay an error or /// completion. @interface RACReplaySubject : RACSubject /// Creates a new replay subject with the given capacity. A capacity of /// RACReplaySubjectUnlimitedCapacity means values are never trimmed. + (instancetype)replaySubjectWithCapacity:(NSUInteger)capacity; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACReplaySubject.m ================================================ // // RACReplaySubject.m // ReactiveCocoa // // Created by Josh Abernathy on 3/14/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACReplaySubject.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACScheduler+Private.h" #import "RACSubscriber.h" #import "RACTuple.h" const NSUInteger RACReplaySubjectUnlimitedCapacity = NSUIntegerMax; @interface RACReplaySubject () @property (nonatomic, assign, readonly) NSUInteger capacity; // These properties should only be modified while synchronized on self. @property (nonatomic, strong, readonly) NSMutableArray *valuesReceived; @property (nonatomic, assign) BOOL hasCompleted; @property (nonatomic, assign) BOOL hasError; @property (nonatomic, strong) NSError *error; @end @implementation RACReplaySubject #pragma mark Lifecycle + (instancetype)replaySubjectWithCapacity:(NSUInteger)capacity { return [(RACReplaySubject *)[self alloc] initWithCapacity:capacity]; } - (instancetype)init { return [self initWithCapacity:RACReplaySubjectUnlimitedCapacity]; } - (instancetype)initWithCapacity:(NSUInteger)capacity { self = [super init]; if (self == nil) return nil; _capacity = capacity; _valuesReceived = (capacity == RACReplaySubjectUnlimitedCapacity ? [NSMutableArray array] : [NSMutableArray arrayWithCapacity:capacity]); return self; } #pragma mark RACSignal - (RACDisposable *)subscribe:(id)subscriber { RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable]; RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{ @synchronized (self) { for (id value in self.valuesReceived) { if (compoundDisposable.disposed) return; [subscriber sendNext:(value == RACTupleNil.tupleNil ? nil : value)]; } if (compoundDisposable.disposed) return; if (self.hasCompleted) { [subscriber sendCompleted]; } else if (self.hasError) { [subscriber sendError:self.error]; } else { RACDisposable *subscriptionDisposable = [super subscribe:subscriber]; [compoundDisposable addDisposable:subscriptionDisposable]; } } }]; [compoundDisposable addDisposable:schedulingDisposable]; return compoundDisposable; } #pragma mark RACSubscriber - (void)sendNext:(id)value { @synchronized (self) { [self.valuesReceived addObject:value ?: RACTupleNil.tupleNil]; [super sendNext:value]; if (self.capacity != RACReplaySubjectUnlimitedCapacity && self.valuesReceived.count > self.capacity) { [self.valuesReceived removeObjectsInRange:NSMakeRange(0, self.valuesReceived.count - self.capacity)]; } } } - (void)sendCompleted { @synchronized (self) { self.hasCompleted = YES; [super sendCompleted]; } } - (void)sendError:(NSError *)e { @synchronized (self) { self.hasError = YES; self.error = e; [super sendError:e]; } } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACReturnSignal.h ================================================ // // RACReturnSignal.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-10. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSignal.h" // A private `RACSignal` subclasses that synchronously sends a value to any // subscribers, then completes. @interface RACReturnSignal : RACSignal + (RACSignal *)return:(id)value; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACReturnSignal.m ================================================ // // RACReturnSignal.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-10-10. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACReturnSignal.h" #import "RACScheduler+Private.h" #import "RACSubscriber.h" #import "RACUnit.h" @interface RACReturnSignal () // The value to send upon subscription. @property (nonatomic, strong, readonly) id value; @end @implementation RACReturnSignal #pragma mark Properties // Only allow this signal's name to be customized in DEBUG, since it's // potentially a singleton in release builds (see +return:). - (void)setName:(NSString *)name { #ifdef DEBUG [super setName:name]; #endif } - (NSString *)name { #ifdef DEBUG return super.name; #else return @"+return:"; #endif } #pragma mark Lifecycle + (RACSignal *)return:(id)value { #ifndef DEBUG // In release builds, use singletons for two very common cases. if (value == RACUnit.defaultUnit) { static RACReturnSignal *unitSingleton; static dispatch_once_t unitPred; dispatch_once(&unitPred, ^{ unitSingleton = [[self alloc] init]; unitSingleton->_value = RACUnit.defaultUnit; }); return unitSingleton; } else if (value == nil) { static RACReturnSignal *nilSingleton; static dispatch_once_t nilPred; dispatch_once(&nilPred, ^{ nilSingleton = [[self alloc] init]; nilSingleton->_value = nil; }); return nilSingleton; } #endif RACReturnSignal *signal = [[self alloc] init]; signal->_value = value; #ifdef DEBUG [signal setNameWithFormat:@"+return: %@", value]; #endif return signal; } #pragma mark Subscription - (RACDisposable *)subscribe:(id)subscriber { NSCParameterAssert(subscriber != nil); return [RACScheduler.subscriptionScheduler schedule:^{ [subscriber sendNext:self.value]; [subscriber sendCompleted]; }]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACScheduler+Private.h ================================================ // // RACScheduler+Private.h // ReactiveCocoa // // Created by Josh Abernathy on 11/29/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACScheduler.h" // The thread-specific current scheduler key. extern NSString * const RACSchedulerCurrentSchedulerKey; // A private interface for internal RAC use only. @interface RACScheduler () // A dedicated scheduler that fills two requirements: // // 1. By the time subscription happens, we need a valid +currentScheduler. // 2. Subscription should happen as soon as possible. // // To fulfill those two, if we already have a valid +currentScheduler, it // immediately executes scheduled blocks. If we don't, it will execute scheduled // blocks with a private background scheduler. + (instancetype)subscriptionScheduler; // Initializes the receiver with the given name. // // name - The name of the scheduler. If nil, a default name will be used. // // Returns the initialized object. - (id)initWithName:(NSString *)name; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACScheduler+Subclass.h ================================================ // // RACScheduler.m // ReactiveCocoa // // Created by Miķelis Vindavs on 5/27/14. // Copyright (c) 2014 GitHub, Inc. All rights reserved. // #import #import "RACScheduler.h" /// An interface for use by subclasses. /// /// Subclasses should use `-performAsCurrentScheduler:` to do the actual block /// invocation so that +[RACScheduler currentScheduler] behaves as expected. /// /// **Note that RACSchedulers are expected to be serial**. Subclasses must honor /// that contract. See `RACTargetQueueScheduler` for a queue-based scheduler /// which will enforce the serialization guarantee. @interface RACScheduler () /// Performs the given block with the receiver as the current scheduler for /// its thread. This should only be called by subclasses to perform their /// scheduled blocks. /// /// block - The block to execute. Cannot be NULL. - (void)performAsCurrentScheduler:(void (^)(void))block; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACScheduler.h ================================================ // // RACScheduler.h // ReactiveCocoa // // Created by Josh Abernathy on 4/16/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import /// The priority for the scheduler. /// /// RACSchedulerPriorityHigh - High priority. /// RACSchedulerPriorityDefault - Default priority. /// RACSchedulerPriorityLow - Low priority. /// RACSchedulerPriorityBackground - Background priority. typedef enum : long { RACSchedulerPriorityHigh = DISPATCH_QUEUE_PRIORITY_HIGH, RACSchedulerPriorityDefault = DISPATCH_QUEUE_PRIORITY_DEFAULT, RACSchedulerPriorityLow = DISPATCH_QUEUE_PRIORITY_LOW, RACSchedulerPriorityBackground = DISPATCH_QUEUE_PRIORITY_BACKGROUND, } RACSchedulerPriority; /// Scheduled with -scheduleRecursiveBlock:, this type of block is passed a block /// with which it can call itself recursively. typedef void (^RACSchedulerRecursiveBlock)(void (^reschedule)(void)); @class RACDisposable; /// Schedulers are used to control when and where work is performed. @interface RACScheduler : NSObject /// A singleton scheduler that immediately executes the blocks it is given. /// /// **Note:** Unlike most other schedulers, this does not set the current /// scheduler. There may still be a valid +currentScheduler if this is used /// within a block scheduled on a different scheduler. + (RACScheduler *)immediateScheduler; /// A singleton scheduler that executes blocks in the main thread. + (RACScheduler *)mainThreadScheduler; /// Creates and returns a new background scheduler with the given priority and /// name. The name is for debug and instrumentation purposes only. /// /// Scheduler creation is cheap. It's unnecessary to save the result of this /// method call unless you want to serialize some actions on the same background /// scheduler. + (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority name:(NSString *)name; /// Invokes +schedulerWithPriority:name: with a default name. + (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority; /// Invokes +schedulerWithPriority: with RACSchedulerPriorityDefault. + (RACScheduler *)scheduler; /// The current scheduler. This will only be valid when used from within a /// -[RACScheduler schedule:] block or when on the main thread. + (RACScheduler *)currentScheduler; /// Schedule the given block for execution on the scheduler. /// /// Scheduled blocks will be executed in the order in which they were scheduled. /// /// block - The block to schedule for execution. Cannot be nil. /// /// Returns a disposable which can be used to cancel the scheduled block before /// it begins executing, or nil if cancellation is not supported. - (RACDisposable *)schedule:(void (^)(void))block; /// Schedule the given block for execution on the scheduler at or after /// a specific time. /// /// Note that blocks scheduled for a certain time will not preempt any other /// scheduled work that is executing at the time. /// /// When invoked on the +immediateScheduler, the calling thread **will block** /// until the specified time. /// /// date - The earliest time at which `block` should begin executing. The block /// may not execute immediately at this time, whether due to system load /// or another block on the scheduler currently being run. Cannot be nil. /// block - The block to schedule for execution. Cannot be nil. /// /// Returns a disposable which can be used to cancel the scheduled block before /// it begins executing, or nil if cancellation is not supported. - (RACDisposable *)after:(NSDate *)date schedule:(void (^)(void))block; /// Schedule the given block for execution on the scheduler after the delay. /// /// Converts the delay into an NSDate, then invokes `-after:schedule:`. - (RACDisposable *)afterDelay:(NSTimeInterval)delay schedule:(void (^)(void))block; /// Reschedule the given block at a particular interval, starting at a specific /// time, and with a given leeway for deferral. /// /// Note that blocks scheduled for a certain time will not preempt any other /// scheduled work that is executing at the time. /// /// Regardless of the value of `leeway`, the given block may not execute exactly /// at `when` or exactly on successive intervals, whether due to system load or /// because another block is currently being run on the scheduler. /// /// It is considered undefined behavior to invoke this method on the /// +immediateScheduler. /// /// date - The earliest time at which `block` should begin executing. The /// block may not execute immediately at this time, whether due to /// system load or another block on the scheduler currently being /// run. Cannot be nil. /// interval - The interval at which the block should be rescheduled, starting /// from `date`. This will use the system wall clock, to avoid /// skew when the computer goes to sleep. /// leeway - A hint to the system indicating the number of seconds that each /// scheduling can be deferred. Note that this is just a hint, and /// there may be some additional latency no matter what. /// block - The block to repeatedly schedule for execution. Cannot be nil. /// /// Returns a disposable which can be used to cancel the automatic scheduling and /// rescheduling, or nil if cancellation is not supported. - (RACDisposable *)after:(NSDate *)date repeatingEvery:(NSTimeInterval)interval withLeeway:(NSTimeInterval)leeway schedule:(void (^)(void))block; /// Schedule the given recursive block for execution on the scheduler. The /// scheduler will automatically flatten any recursive scheduling into iteration /// instead, so this can be used without issue for blocks that may keep invoking /// themselves forever. /// /// Scheduled blocks will be executed in the order in which they were scheduled. /// /// recursiveBlock - The block to schedule for execution. When invoked, the /// recursive block will be passed a `void (^)(void)` block /// which will reschedule the recursive block at the end of the /// receiver's queue. This passed-in block will automatically /// skip scheduling if the scheduling of the `recursiveBlock` /// was disposed in the meantime. /// /// Returns a disposable which can be used to cancel the scheduled block before /// it begins executing, or to stop it from rescheduling if it's already begun /// execution. - (RACDisposable *)scheduleRecursiveBlock:(RACSchedulerRecursiveBlock)recursiveBlock; @end @interface RACScheduler (Unavailable) + (RACScheduler *)schedulerWithQueue:(dispatch_queue_t)queue name:(NSString *)name __attribute__((unavailable("Use -[RACTargetQueueScheduler initWithName:targetQueue:] instead."))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACScheduler.m ================================================ // // RACScheduler.m // ReactiveCocoa // // Created by Josh Abernathy on 4/16/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACScheduler.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACImmediateScheduler.h" #import "RACScheduler+Private.h" #import "RACSubscriptionScheduler.h" #import "RACTargetQueueScheduler.h" // The key for the thread-specific current scheduler. NSString * const RACSchedulerCurrentSchedulerKey = @"RACSchedulerCurrentSchedulerKey"; @interface RACScheduler () @property (nonatomic, readonly, copy) NSString *name; @end @implementation RACScheduler #pragma mark NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p> %@", self.class, self, self.name]; } #pragma mark Initializers - (id)initWithName:(NSString *)name { self = [super init]; if (self == nil) return nil; if (name == nil) { _name = [NSString stringWithFormat:@"com.ReactiveCocoa.%@.anonymousScheduler", self.class]; } else { _name = [name copy]; } return self; } #pragma mark Schedulers + (instancetype)immediateScheduler { static dispatch_once_t onceToken; static RACScheduler *immediateScheduler; dispatch_once(&onceToken, ^{ immediateScheduler = [[RACImmediateScheduler alloc] init]; }); return immediateScheduler; } + (instancetype)mainThreadScheduler { static dispatch_once_t onceToken; static RACScheduler *mainThreadScheduler; dispatch_once(&onceToken, ^{ mainThreadScheduler = [[RACTargetQueueScheduler alloc] initWithName:@"com.ReactiveCocoa.RACScheduler.mainThreadScheduler" targetQueue:dispatch_get_main_queue()]; }); return mainThreadScheduler; } + (instancetype)schedulerWithPriority:(RACSchedulerPriority)priority name:(NSString *)name { return [[RACTargetQueueScheduler alloc] initWithName:name targetQueue:dispatch_get_global_queue(priority, 0)]; } + (instancetype)schedulerWithPriority:(RACSchedulerPriority)priority { return [self schedulerWithPriority:priority name:@"com.ReactiveCocoa.RACScheduler.backgroundScheduler"]; } + (instancetype)scheduler { return [self schedulerWithPriority:RACSchedulerPriorityDefault]; } + (instancetype)subscriptionScheduler { static dispatch_once_t onceToken; static RACScheduler *subscriptionScheduler; dispatch_once(&onceToken, ^{ subscriptionScheduler = [[RACSubscriptionScheduler alloc] init]; }); return subscriptionScheduler; } + (BOOL)isOnMainThread { return [NSOperationQueue.currentQueue isEqual:NSOperationQueue.mainQueue] || [NSThread isMainThread]; } + (instancetype)currentScheduler { RACScheduler *scheduler = NSThread.currentThread.threadDictionary[RACSchedulerCurrentSchedulerKey]; if (scheduler != nil) return scheduler; if ([self.class isOnMainThread]) return RACScheduler.mainThreadScheduler; return nil; } #pragma mark Scheduling - (RACDisposable *)schedule:(void (^)(void))block { NSCAssert(NO, @"%@ must be implemented by subclasses.", NSStringFromSelector(_cmd)); return nil; } - (RACDisposable *)after:(NSDate *)date schedule:(void (^)(void))block { NSCAssert(NO, @"%@ must be implemented by subclasses.", NSStringFromSelector(_cmd)); return nil; } - (RACDisposable *)afterDelay:(NSTimeInterval)delay schedule:(void (^)(void))block { return [self after:[NSDate dateWithTimeIntervalSinceNow:delay] schedule:block]; } - (RACDisposable *)after:(NSDate *)date repeatingEvery:(NSTimeInterval)interval withLeeway:(NSTimeInterval)leeway schedule:(void (^)(void))block { NSCAssert(NO, @"%@ must be implemented by subclasses.", NSStringFromSelector(_cmd)); return nil; } - (RACDisposable *)scheduleRecursiveBlock:(RACSchedulerRecursiveBlock)recursiveBlock { RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; [self scheduleRecursiveBlock:[recursiveBlock copy] addingToDisposable:disposable]; return disposable; } - (void)scheduleRecursiveBlock:(RACSchedulerRecursiveBlock)recursiveBlock addingToDisposable:(RACCompoundDisposable *)disposable { @autoreleasepool { RACCompoundDisposable *selfDisposable = [RACCompoundDisposable compoundDisposable]; [disposable addDisposable:selfDisposable]; __weak RACDisposable *weakSelfDisposable = selfDisposable; RACDisposable *schedulingDisposable = [self schedule:^{ @autoreleasepool { // At this point, we've been invoked, so our disposable is now useless. [disposable removeDisposable:weakSelfDisposable]; } if (disposable.disposed) return; void (^reallyReschedule)(void) = ^{ if (disposable.disposed) return; [self scheduleRecursiveBlock:recursiveBlock addingToDisposable:disposable]; }; // Protects the variables below. // // This doesn't actually need to be __block qualified, but Clang // complains otherwise. :C __block NSLock *lock = [[NSLock alloc] init]; lock.name = [NSString stringWithFormat:@"%@ %s", self, sel_getName(_cmd)]; __block NSUInteger rescheduleCount = 0; // Set to YES once synchronous execution has finished. Further // rescheduling should occur immediately (rather than being // flattened). __block BOOL rescheduleImmediately = NO; @autoreleasepool { recursiveBlock(^{ [lock lock]; BOOL immediate = rescheduleImmediately; if (!immediate) ++rescheduleCount; [lock unlock]; if (immediate) reallyReschedule(); }); } [lock lock]; NSUInteger synchronousCount = rescheduleCount; rescheduleImmediately = YES; [lock unlock]; for (NSUInteger i = 0; i < synchronousCount; i++) { reallyReschedule(); } }]; [selfDisposable addDisposable:schedulingDisposable]; } } - (void)performAsCurrentScheduler:(void (^)(void))block { NSCParameterAssert(block != NULL); // If we're using a concurrent queue, we could end up in here concurrently, // in which case we *don't* want to clear the current scheduler immediately // after our block is done executing, but only *after* all our concurrent // invocations are done. RACScheduler *previousScheduler = RACScheduler.currentScheduler; NSThread.currentThread.threadDictionary[RACSchedulerCurrentSchedulerKey] = self; @autoreleasepool { block(); } if (previousScheduler != nil) { NSThread.currentThread.threadDictionary[RACSchedulerCurrentSchedulerKey] = previousScheduler; } else { [NSThread.currentThread.threadDictionary removeObjectForKey:RACSchedulerCurrentSchedulerKey]; } } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACScopedDisposable.h ================================================ // // RACScopedDisposable.h // ReactiveCocoa // // Created by Josh Abernathy on 3/28/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACDisposable.h" /// A disposable that calls its own -dispose when it is dealloc'd. @interface RACScopedDisposable : RACDisposable /// Creates a new scoped disposable that will also dispose of the given /// disposable when it is dealloc'd. + (instancetype)scopedDisposableWithDisposable:(RACDisposable *)disposable; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACScopedDisposable.m ================================================ // // RACScopedDisposable.m // ReactiveCocoa // // Created by Josh Abernathy on 3/28/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACScopedDisposable.h" @implementation RACScopedDisposable #pragma mark Lifecycle + (instancetype)scopedDisposableWithDisposable:(RACDisposable *)disposable { return [self disposableWithBlock:^{ [disposable dispose]; }]; } - (void)dealloc { [self dispose]; } #pragma mark RACDisposable - (RACScopedDisposable *)asScopedDisposable { // totally already are return self; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSequence.h ================================================ // // RACSequence.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import #import "RACStream.h" @class RACScheduler; @class RACSignal; /// Represents an immutable sequence of values. Unless otherwise specified, the /// sequences' values are evaluated lazily on demand. Like Cocoa collections, /// sequences cannot contain nil. /// /// Most inherited RACStream methods that accept a block will execute the block /// _at most_ once for each value that is evaluated in the returned sequence. /// Side effects are subject to the behavior described in /// +sequenceWithHeadBlock:tailBlock:. /// /// Implemented as a class cluster. A minimal implementation for a subclass /// consists simply of -head and -tail. @interface RACSequence : RACStream /// The first object in the sequence, or nil if the sequence is empty. /// /// Subclasses must provide an implementation of this method. @property (nonatomic, strong, readonly) id head; /// All but the first object in the sequence, or nil if the sequence is empty. /// /// Subclasses must provide an implementation of this method. @property (nonatomic, strong, readonly) RACSequence *tail; /// Evaluates the full sequence to produce an equivalently-sized array. @property (nonatomic, copy, readonly) NSArray *array; /// Returns an enumerator of all objects in the sequence. @property (nonatomic, copy, readonly) NSEnumerator *objectEnumerator; /// Converts a sequence into an eager sequence. /// /// An eager sequence fully evaluates all of its values immediately. Sequences /// derived from an eager sequence will also be eager. /// /// Returns a new eager sequence, or the receiver if the sequence is already /// eager. @property (nonatomic, copy, readonly) RACSequence *eagerSequence; /// Converts a sequence into a lazy sequence. /// /// A lazy sequence evaluates its values on demand, as they are accessed. /// Sequences derived from a lazy sequence will also be lazy. /// /// Returns a new lazy sequence, or the receiver if the sequence is already lazy. @property (nonatomic, copy, readonly) RACSequence *lazySequence; /// Invokes -signalWithScheduler: with a new RACScheduler. - (RACSignal *)signal; /// Evaluates the full sequence on the given scheduler. /// /// Each item is evaluated in its own scheduled block, such that control of the /// scheduler is yielded between each value. /// /// Returns a signal which sends the receiver's values on the given scheduler as /// they're evaluated. - (RACSignal *)signalWithScheduler:(RACScheduler *)scheduler; /// Applies a left fold to the sequence. /// /// This is the same as iterating the sequence along with a provided start value. /// This uses a constant amount of memory. A left fold is left-associative so in /// the sequence [1,2,3] the block would applied in the following order: /// reduce(reduce(reduce(start, 1), 2), 3) /// /// start - The starting value for the fold. Used as `accumulator` for the /// first fold. /// reduce - The block used to combine the accumulated value and the next value. /// Cannot be nil. /// /// Returns a reduced value. - (id)foldLeftWithStart:(id)start reduce:(id (^)(id accumulator, id value))reduce; /// Applies a right fold to the sequence. /// /// A right fold is equivalent to recursion on the list. The block is evaluated /// from the right to the left in list. It is right associative so it's applied /// to the rightmost elements first. For example, in the sequence [1,2,3] the /// block is applied in the order: /// reduce(1, reduce(2, reduce(3, start))) /// /// start - The starting value for the fold. /// reduce - The block used to combine the accumulated value and the next head. /// The block is given the accumulated value and the value of the rest /// of the computation (result of the recursion). This is computed when /// you retrieve its value using `rest.head`. This allows you to /// prevent unnecessary computation by not accessing `rest.head` if you /// don't need to. /// /// Returns a reduced value. - (id)foldRightWithStart:(id)start reduce:(id (^)(id first, RACSequence *rest))reduce; /// Check if any value in sequence passes the block. /// /// block - The block predicate used to check each item. Cannot be nil. /// /// Returns a boolean indiciating if any value in the sequence passed. - (BOOL)any:(BOOL (^)(id value))block; /// Check if all values in the sequence pass the block. /// /// block - The block predicate used to check each item. Cannot be nil. /// /// Returns a boolean indicating if all values in the sequence passed. - (BOOL)all:(BOOL (^)(id value))block; /// Returns the first object that passes the block. /// /// block - The block predicate used to check each item. Cannot be nil. /// /// Returns an object that passes the block or nil if no objects passed. - (id)objectPassingTest:(BOOL (^)(id value))block; /// Creates a sequence that dynamically generates its values. /// /// headBlock - Invoked the first time -head is accessed. /// tailBlock - Invoked the first time -tail is accessed. /// /// The results from each block are memoized, so each block will be invoked at /// most once, no matter how many times the head and tail properties of the /// sequence are accessed. /// /// Any side effects in `headBlock` or `tailBlock` should be thread-safe, since /// the sequence may be evaluated at any time from any thread. Not only that, but /// -tail may be accessed before -head, or both may be accessed simultaneously. /// As noted above, side effects will only be triggered the _first_ time -head or /// -tail is invoked. /// /// Returns a sequence that lazily invokes the given blocks to provide head and /// tail. `headBlock` must not be nil. + (RACSequence *)sequenceWithHeadBlock:(id (^)(void))headBlock tailBlock:(RACSequence *(^)(void))tailBlock; @end @interface RACSequence (Unavailable) - (id)foldLeftWithStart:(id)start combine:(id (^)(id accumulator, id value))combine __attribute__((unavailable("Renamed to -foldLeftWithStart:reduce:"))); - (id)foldRightWithStart:(id)start combine:(id (^)(id first, RACSequence *rest))combine __attribute__((unavailable("Renamed to -foldRightWithStart:reduce:"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSequence.m ================================================ // // RACSequence.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACSequence.h" #import "RACArraySequence.h" #import "RACDynamicSequence.h" #import "RACEagerSequence.h" #import "RACEmptySequence.h" #import "RACScheduler.h" #import "RACSignal.h" #import "RACSubscriber.h" #import "RACTuple.h" #import "RACUnarySequence.h" // An enumerator over sequences. @interface RACSequenceEnumerator : NSEnumerator // The sequence the enumerator is enumerating. // // This will change as the enumerator is exhausted. This property should only be // accessed while synchronized on self. @property (nonatomic, strong) RACSequence *sequence; @end @interface RACSequence () // Performs one iteration of lazy binding, passing through values from `current` // until the sequence is exhausted, then recursively binding the remaining // values in the receiver. // // Returns a new sequence which contains `current`, followed by the combined // result of all applications of `block` to the remaining values in the receiver. - (instancetype)bind:(RACStreamBindBlock)block passingThroughValuesFromSequence:(RACSequence *)current; @end @implementation RACSequenceEnumerator - (id)nextObject { id object = nil; @synchronized (self) { object = self.sequence.head; self.sequence = self.sequence.tail; } return object; } @end @implementation RACSequence #pragma mark Lifecycle + (RACSequence *)sequenceWithHeadBlock:(id (^)(void))headBlock tailBlock:(RACSequence *(^)(void))tailBlock { return [[RACDynamicSequence sequenceWithHeadBlock:headBlock tailBlock:tailBlock] setNameWithFormat:@"+sequenceWithHeadBlock:tailBlock:"]; } #pragma mark Class cluster primitives - (id)head { NSCAssert(NO, @"%s must be overridden by subclasses", __func__); return nil; } - (RACSequence *)tail { NSCAssert(NO, @"%s must be overridden by subclasses", __func__); return nil; } #pragma mark RACStream + (instancetype)empty { return RACEmptySequence.empty; } + (instancetype)return:(id)value { return [RACUnarySequence return:value]; } - (instancetype)bind:(RACStreamBindBlock (^)(void))block { RACStreamBindBlock bindBlock = block(); return [[self bind:bindBlock passingThroughValuesFromSequence:nil] setNameWithFormat:@"[%@] -bind:", self.name]; } - (instancetype)bind:(RACStreamBindBlock)bindBlock passingThroughValuesFromSequence:(RACSequence *)passthroughSequence { // Store values calculated in the dependency here instead, avoiding any kind // of temporary collection and boxing. // // This relies on the implementation of RACDynamicSequence synchronizing // access to its head, tail, and dependency, and we're only doing it because // we really need the performance. __block RACSequence *valuesSeq = self; __block RACSequence *current = passthroughSequence; __block BOOL stop = NO; RACSequence *sequence = [RACDynamicSequence sequenceWithLazyDependency:^ id { while (current.head == nil) { if (stop) return nil; // We've exhausted the current sequence, create a sequence from the // next value. id value = valuesSeq.head; if (value == nil) { // We've exhausted all the sequences. stop = YES; return nil; } current = (id)bindBlock(value, &stop); if (current == nil) { stop = YES; return nil; } valuesSeq = valuesSeq.tail; } NSCAssert([current isKindOfClass:RACSequence.class], @"-bind: block returned an object that is not a sequence: %@", current); return nil; } headBlock:^(id _) { return current.head; } tailBlock:^ id (id _) { if (stop) return nil; return [valuesSeq bind:bindBlock passingThroughValuesFromSequence:current.tail]; }]; sequence.name = self.name; return sequence; } - (instancetype)concat:(RACStream *)stream { NSCParameterAssert(stream != nil); return [[[RACArraySequence sequenceWithArray:@[ self, stream ] offset:0] flatten] setNameWithFormat:@"[%@] -concat: %@", self.name, stream]; } - (instancetype)zipWith:(RACSequence *)sequence { NSCParameterAssert(sequence != nil); return [[RACSequence sequenceWithHeadBlock:^ id { if (self.head == nil || sequence.head == nil) return nil; return RACTuplePack(self.head, sequence.head); } tailBlock:^ id { if (self.tail == nil || [[RACSequence empty] isEqual:self.tail]) return nil; if (sequence.tail == nil || [[RACSequence empty] isEqual:sequence.tail]) return nil; return [self.tail zipWith:sequence.tail]; }] setNameWithFormat:@"[%@] -zipWith: %@", self.name, sequence]; } #pragma mark Extended methods - (NSArray *)array { NSMutableArray *array = [NSMutableArray array]; for (id obj in self) { [array addObject:obj]; } return [array copy]; } - (NSEnumerator *)objectEnumerator { RACSequenceEnumerator *enumerator = [[RACSequenceEnumerator alloc] init]; enumerator.sequence = self; return enumerator; } - (RACSignal *)signal { return [[self signalWithScheduler:[RACScheduler scheduler]] setNameWithFormat:@"[%@] -signal", self.name]; } - (RACSignal *)signalWithScheduler:(RACScheduler *)scheduler { return [[RACSignal createSignal:^(id subscriber) { __block RACSequence *sequence = self; return [scheduler scheduleRecursiveBlock:^(void (^reschedule)(void)) { if (sequence.head == nil) { [subscriber sendCompleted]; return; } [subscriber sendNext:sequence.head]; sequence = sequence.tail; reschedule(); }]; }] setNameWithFormat:@"[%@] -signalWithScheduler: %@", self.name, scheduler]; } - (id)foldLeftWithStart:(id)start reduce:(id (^)(id, id))reduce { NSCParameterAssert(reduce != NULL); if (self.head == nil) return start; for (id value in self) { start = reduce(start, value); } return start; } - (id)foldRightWithStart:(id)start reduce:(id (^)(id, RACSequence *))reduce { NSCParameterAssert(reduce != NULL); if (self.head == nil) return start; RACSequence *rest = [RACSequence sequenceWithHeadBlock:^{ return [self.tail foldRightWithStart:start reduce:reduce]; } tailBlock:nil]; return reduce(self.head, rest); } - (BOOL)any:(BOOL (^)(id))block { NSCParameterAssert(block != NULL); return [self objectPassingTest:block] != nil; } - (BOOL)all:(BOOL (^)(id))block { NSCParameterAssert(block != NULL); NSNumber *result = [self foldLeftWithStart:@YES reduce:^(NSNumber *accumulator, id value) { return @(accumulator.boolValue && block(value)); }]; return result.boolValue; } - (id)objectPassingTest:(BOOL (^)(id))block { NSCParameterAssert(block != NULL); return [self filter:block].head; } - (RACSequence *)eagerSequence { return [RACEagerSequence sequenceWithArray:self.array offset:0]; } - (RACSequence *)lazySequence { return self; } #pragma mark NSCopying - (id)copyWithZone:(NSZone *)zone { return self; } #pragma mark NSCoding - (Class)classForCoder { // Most sequences should be archived as RACArraySequences. return RACArraySequence.class; } - (id)initWithCoder:(NSCoder *)coder { if (![self isKindOfClass:RACArraySequence.class]) return [[RACArraySequence alloc] initWithCoder:coder]; // Decoding is handled in RACArraySequence. return [super init]; } - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.array forKey:@"array"]; } #pragma mark NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id *)stackbuf count:(NSUInteger)len { if (state->state == ULONG_MAX) { // Enumeration has completed. return 0; } // We need to traverse the sequence itself on repeated calls to this // method, so use the 'state' field to track the current head. RACSequence *(^getSequence)(void) = ^{ return (__bridge RACSequence *)(void *)state->state; }; void (^setSequence)(RACSequence *) = ^(RACSequence *sequence) { // Release the old sequence and retain the new one. CFBridgingRelease((void *)state->state); state->state = (unsigned long)CFBridgingRetain(sequence); }; void (^complete)(void) = ^{ // Release any stored sequence. setSequence(nil); state->state = ULONG_MAX; }; if (state->state == 0) { // Since a sequence doesn't mutate, this just needs to be set to // something non-NULL. state->mutationsPtr = state->extra; setSequence(self); } state->itemsPtr = stackbuf; NSUInteger enumeratedCount = 0; while (enumeratedCount < len) { RACSequence *seq = getSequence(); // Because the objects in a sequence may be generated lazily, we want to // prevent them from being released until the enumerator's used them. __autoreleasing id obj = seq.head; if (obj == nil) { complete(); break; } stackbuf[enumeratedCount++] = obj; if (seq.tail == nil) { complete(); break; } setSequence(seq.tail); } return enumeratedCount; } #pragma mark NSObject - (NSUInteger)hash { return [self.head hash]; } - (BOOL)isEqual:(RACSequence *)seq { if (self == seq) return YES; if (![seq isKindOfClass:RACSequence.class]) return NO; for (id selfObj in self) { id seqObj = seq.head; // Handles the nil case too. if (![seqObj isEqual:selfObj]) return NO; seq = seq.tail; } // self is now depleted -- the argument should be too. return (seq.head == nil); } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSerialDisposable.h ================================================ // // RACSerialDisposable.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-07-22. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACDisposable.h" /// A disposable that contains exactly one other disposable and allows it to be /// swapped out atomically. @interface RACSerialDisposable : RACDisposable /// The inner disposable managed by the serial disposable. /// /// This property is thread-safe for reading and writing. However, if you want to /// read the current value _and_ write a new one atomically, use /// -swapInDisposable: instead. /// /// Disposing of the receiver will also dispose of the current disposable set for /// this property, then set the property to nil. If any new disposable is set /// after the receiver is disposed, it will be disposed immediately and this /// property will remain set to nil. @property (atomic, strong) RACDisposable *disposable; /// Creates a serial disposable which will wrap the given disposable. /// /// disposable - The value to set for `disposable`. This may be nil. /// /// Returns a RACSerialDisposable, or nil if an error occurs. + (instancetype)serialDisposableWithDisposable:(RACDisposable *)disposable; /// Atomically swaps the receiver's `disposable` for `newDisposable`. /// /// newDisposable - The new value for `disposable`. If the receiver has already /// been disposed, this disposable will be too, and `disposable` /// will remain set to nil. This argument may be nil. /// /// Returns the previous value for the `disposable` property. - (RACDisposable *)swapInDisposable:(RACDisposable *)newDisposable; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSerialDisposable.m ================================================ // // RACSerialDisposable.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-07-22. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSerialDisposable.h" #import @interface RACSerialDisposable () { // The receiver's `disposable`. This variable must only be referenced while // _spinLock is held. RACDisposable * _disposable; // YES if the receiver has been disposed. This variable must only be modified // while _spinLock is held. BOOL _disposed; // A spinlock to protect access to _disposable and _disposed. // // It must be used when _disposable is mutated or retained and when _disposed // is mutated. OSSpinLock _spinLock; } @end @implementation RACSerialDisposable #pragma mark Properties - (BOOL)isDisposed { return _disposed; } - (RACDisposable *)disposable { RACDisposable *result; OSSpinLockLock(&_spinLock); result = _disposable; OSSpinLockUnlock(&_spinLock); return result; } - (void)setDisposable:(RACDisposable *)disposable { [self swapInDisposable:disposable]; } #pragma mark Lifecycle + (instancetype)serialDisposableWithDisposable:(RACDisposable *)disposable { RACSerialDisposable *serialDisposable = [[self alloc] init]; serialDisposable.disposable = disposable; return serialDisposable; } - (id)initWithBlock:(void (^)(void))block { self = [self init]; if (self == nil) return nil; self.disposable = [RACDisposable disposableWithBlock:block]; return self; } #pragma mark Inner Disposable - (RACDisposable *)swapInDisposable:(RACDisposable *)newDisposable { RACDisposable *existingDisposable; BOOL alreadyDisposed; OSSpinLockLock(&_spinLock); alreadyDisposed = _disposed; if (!alreadyDisposed) { existingDisposable = _disposable; _disposable = newDisposable; } OSSpinLockUnlock(&_spinLock); if (alreadyDisposed) { [newDisposable dispose]; return nil; } return existingDisposable; } #pragma mark Disposal - (void)dispose { RACDisposable *existingDisposable; OSSpinLockLock(&_spinLock); if (!_disposed) { existingDisposable = _disposable; _disposed = YES; _disposable = nil; } OSSpinLockUnlock(&_spinLock); [existingDisposable dispose]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSignal+Operations.h ================================================ // // RACSignal+Operations.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-09-06. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import #import "RACSignal.h" /// The domain for errors originating in RACSignal operations. extern NSString * const RACSignalErrorDomain; /// The error code used with -timeout:. extern const NSInteger RACSignalErrorTimedOut; /// The error code used when a value passed into +switch:cases:default: does not /// match any of the cases, and no default was given. extern const NSInteger RACSignalErrorNoMatchingCase; @class RACCommand; @class RACDisposable; @class RACMulticastConnection; @class RACScheduler; @class RACSequence; @class RACSubject; @class RACTuple; @protocol RACSubscriber; @interface RACSignal (Operations) /// Do the given block on `next`. This should be used to inject side effects into /// the signal. - (RACSignal *)doNext:(void (^)(id x))block; /// Do the given block on `error`. This should be used to inject side effects /// into the signal. - (RACSignal *)doError:(void (^)(NSError *error))block; /// Do the given block on `completed`. This should be used to inject side effects /// into the signal. - (RACSignal *)doCompleted:(void (^)(void))block; /// Sends `next`s only if we don't receive another `next` in `interval` seconds. /// /// If a `next` is received, and then another `next` is received before /// `interval` seconds have passed, the first value is discarded. /// /// After `interval` seconds have passed since the most recent `next` was sent, /// the most recent `next` is forwarded on the scheduler that the value was /// originally received on. If +[RACScheduler currentScheduler] was nil at the /// time, a private background scheduler is used. /// /// Returns a signal which sends throttled and delayed `next` events. Completion /// and errors are always forwarded immediately. - (RACSignal *)throttle:(NSTimeInterval)interval; /// Throttles `next`s for which `predicate` returns YES. /// /// When `predicate` returns YES for a `next`: /// /// 1. If another `next` is received before `interval` seconds have passed, the /// prior value is discarded. This happens regardless of whether the new /// value will be throttled. /// 2. After `interval` seconds have passed since the value was originally /// received, it will be forwarded on the scheduler that it was received /// upon. If +[RACScheduler currentScheduler] was nil at the time, a private /// background scheduler is used. /// /// When `predicate` returns NO for a `next`, it is forwarded immediately, /// without any throttling. /// /// interval - The number of seconds for which to buffer the latest value that /// passes `predicate`. /// predicate - Passed each `next` from the receiver, this block returns /// whether the given value should be throttled. This argument must /// not be nil. /// /// Returns a signal which sends `next` events, throttled when `predicate` /// returns YES. Completion and errors are always forwarded immediately. - (RACSignal *)throttle:(NSTimeInterval)interval valuesPassingTest:(BOOL (^)(id next))predicate; /// Forwards `next` and `completed` events after delaying for `interval` seconds /// on the current scheduler (on which the events were delivered). /// /// If +[RACScheduler currentScheduler] is nil when `next` or `completed` is /// received, a private background scheduler is used. /// /// Returns a signal which sends delayed `next` and `completed` events. Errors /// are always forwarded immediately. - (RACSignal *)delay:(NSTimeInterval)interval; /// Resubscribes when the signal completes. - (RACSignal *)repeat; /// Executes the given block each time a subscription is created. /// /// block - A block which defines the subscription side effects. Cannot be `nil`. /// /// Example: /// /// // Write new file, with backup. /// [[[[fileManager /// rac_createFileAtPath:path contents:data] /// initially:^{ /// // 2. Second, backup current file /// [fileManager moveItemAtPath:path toPath:backupPath error:nil]; /// }] /// initially:^{ /// // 1. First, acquire write lock. /// [writeLock lock]; /// }] /// finally:^{ /// [writeLock unlock]; /// }]; /// /// Returns a signal that passes through all events of the receiver, plus /// introduces side effects which occur prior to any subscription side effects /// of the receiver. - (RACSignal *)initially:(void (^)(void))block; /// Executes the given block when the signal completes or errors. - (RACSignal *)finally:(void (^)(void))block; /// Divides the receiver's `next`s into buffers which deliver every `interval` /// seconds. /// /// interval - The interval in which values are grouped into one buffer. /// scheduler - The scheduler upon which the returned signal will deliver its /// values. This must not be nil or +[RACScheduler /// immediateScheduler]. /// /// Returns a signal which sends RACTuples of the buffered values at each /// interval on `scheduler`. When the receiver completes, any currently-buffered /// values will be sent immediately. - (RACSignal *)bufferWithTime:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler; /// Collects all receiver's `next`s into a NSArray. Nil values will be converted /// to NSNull. /// /// This corresponds to the `ToArray` method in Rx. /// /// Returns a signal which sends a single NSArray when the receiver completes /// successfully. - (RACSignal *)collect; /// Takes the last `count` `next`s after the receiving signal completes. - (RACSignal *)takeLast:(NSUInteger)count; /// Combines the latest values from the receiver and the given signal into /// RACTuples, once both have sent at least one `next`. /// /// Any additional `next`s will result in a new RACTuple with the latest values /// from both signals. /// /// signal - The signal to combine with. This argument must not be nil. /// /// Returns a signal which sends RACTuples of the combined values, forwards any /// `error` events, and completes when both input signals complete. - (RACSignal *)combineLatestWith:(RACSignal *)signal; /// Combines the latest values from the given signals into RACTuples, once all /// the signals have sent at least one `next`. /// /// Any additional `next`s will result in a new RACTuple with the latest values /// from all signals. /// /// signals - The signals to combine. If this collection is empty, the returned /// signal will immediately complete upon subscription. /// /// Returns a signal which sends RACTuples of the combined values, forwards any /// `error` events, and completes when all input signals complete. + (RACSignal *)combineLatest:(id)signals; /// Combines signals using +combineLatest:, then reduces the resulting tuples /// into a single value using -reduceEach:. /// /// signals - The signals to combine. If this collection is empty, the /// returned signal will immediately complete upon subscription. /// reduceBlock - The block which reduces the latest values from all the /// signals into one value. It must take as many arguments as the /// number of signals given. Each argument will be an object /// argument. The return value must be an object. This argument /// must not be nil. /// /// Example: /// /// [RACSignal combineLatest:@[ stringSignal, intSignal ] reduce:^(NSString *string, NSNumber *number) { /// return [NSString stringWithFormat:@"%@: %@", string, number]; /// }]; /// /// Returns a signal which sends the results from each invocation of /// `reduceBlock`. + (RACSignal *)combineLatest:(id)signals reduce:(id (^)())reduceBlock; /// Merges the receiver and the given signal with `+merge:` and returns the /// resulting signal. - (RACSignal *)merge:(RACSignal *)signal; /// Sends the latest `next` from any of the signals. /// /// Returns a signal that passes through values from each of the given signals, /// and sends `completed` when all of them complete. If any signal sends an error, /// the returned signal sends `error` immediately. + (RACSignal *)merge:(id)signals; /// Merges the signals sent by the receiver into a flattened signal, but only /// subscribes to `maxConcurrent` number of signals at a time. New signals are /// queued and subscribed to as other signals complete. /// /// If an error occurs on any of the signals, it is sent on the returned signal. /// It completes only after the receiver and all sent signals have completed. /// /// This corresponds to `Merge(IObservable>, Int32)` /// in Rx. /// /// maxConcurrent - the maximum number of signals to subscribe to at a /// time. If 0, it subscribes to an unlimited number of /// signals. - (RACSignal *)flatten:(NSUInteger)maxConcurrent; /// Ignores all `next`s from the receiver, waits for the receiver to complete, /// then subscribes to a new signal. /// /// block - A block which will create or obtain a new signal to subscribe to, /// executed only after the receiver completes. This block must not be /// nil, and it must not return a nil signal. /// /// Returns a signal which will pass through the events of the signal created in /// `block`. If the receiver errors out, the returned signal will error as well. - (RACSignal *)then:(RACSignal * (^)(void))block; /// Concats the inner signals of a signal of signals. - (RACSignal *)concat; /// Aggregates the `next` values of the receiver into a single combined value. /// /// The algorithm proceeds as follows: /// /// 1. `start` is passed into the block as the `running` value, and the first /// element of the receiver is passed into the block as the `next` value. /// 2. The result of the invocation (`running`) and the next element of the /// receiver (`next`) is passed into `reduceBlock`. /// 3. Steps 2 and 3 are repeated until all values have been processed. /// 4. The last result of `reduceBlock` is sent on the returned signal. /// /// This method is similar to -scanWithStart:reduce:, except that only the /// final result is sent on the returned signal. /// /// start - The value to be combined with the first element of the /// receiver. This value may be `nil`. /// reduceBlock - The block that describes how to combine values of the /// receiver. If the receiver is empty, this block will never be /// invoked. Cannot be nil. /// /// Returns a signal that will send the aggregated value when the receiver /// completes, then itself complete. If the receiver never sends any values, /// `start` will be sent instead. - (RACSignal *)aggregateWithStart:(id)start reduce:(id (^)(id running, id next))reduceBlock; /// Aggregates the `next` values of the receiver into a single combined value. /// This is indexed version of -aggregateWithStart:reduce:. /// /// start - The value to be combined with the first element of the /// receiver. This value may be `nil`. /// reduceBlock - The block that describes how to combine values of the /// receiver. This block takes zero-based index value as the last /// parameter. If the receiver is empty, this block will never be /// invoked. Cannot be nil. /// /// Returns a signal that will send the aggregated value when the receiver /// completes, then itself complete. If the receiver never sends any values, /// `start` will be sent instead. - (RACSignal *)aggregateWithStart:(id)start reduceWithIndex:(id (^)(id running, id next, NSUInteger index))reduceBlock; /// Aggregates the `next` values of the receiver into a single combined value. /// /// This invokes `startFactory` block on each subscription, then calls /// -aggregateWithStart:reduce: with the return value of the block as start value. /// /// startFactory - The block that returns start value which will be combined /// with the first element of the receiver. Cannot be nil. /// reduceBlock - The block that describes how to combine values of the /// receiver. If the receiver is empty, this block will never be /// invoked. Cannot be nil. /// /// Returns a signal that will send the aggregated value when the receiver /// completes, then itself complete. If the receiver never sends any values, /// the return value of `startFactory` will be sent instead. - (RACSignal *)aggregateWithStartFactory:(id (^)(void))startFactory reduce:(id (^)(id running, id next))reduceBlock; /// Invokes -setKeyPath:onObject:nilValue: with `nil` for the nil value. /// /// WARNING: Under certain conditions, this method is known to be thread-unsafe. /// See the description in -setKeyPath:onObject:nilValue:. - (RACDisposable *)setKeyPath:(NSString *)keyPath onObject:(NSObject *)object; /// Binds the receiver to an object, automatically setting the given key path on /// every `next`. When the signal completes, the binding is automatically /// disposed of. /// /// WARNING: Under certain conditions, this method is known to be thread-unsafe. /// A crash can result if `object` is deallocated concurrently on /// another thread within a window of time between a value being sent /// on this signal and immediately prior to the invocation of /// -setValue:forKeyPath:, which sets the property. To prevent this, /// ensure `object` is deallocated on the same thread the receiver /// sends on, or ensure that the returned disposable is disposed of /// before `object` deallocates. /// See https://github.com/ReactiveCocoa/ReactiveCocoa/pull/1184 /// /// Sending an error on the signal is considered undefined behavior, and will /// generate an assertion failure in Debug builds. /// /// A given key on an object should only have one active signal bound to it at any /// given time. Binding more than one signal to the same property is considered /// undefined behavior. /// /// keyPath - The key path to update with `next`s from the receiver. /// object - The object that `keyPath` is relative to. /// nilValue - The value to set at the key path whenever `nil` is sent by the /// receiver. This may be nil when binding to object properties, but /// an NSValue should be used for primitive properties, to avoid an /// exception if `nil` is sent (which might occur if an intermediate /// object is set to `nil`). /// /// Returns a disposable which can be used to terminate the binding. - (RACDisposable *)setKeyPath:(NSString *)keyPath onObject:(NSObject *)object nilValue:(id)nilValue; /// Sends NSDate.date every `interval` seconds. /// /// interval - The time interval in seconds at which the current time is sent. /// scheduler - The scheduler upon which the current NSDate should be sent. This /// must not be nil or +[RACScheduler immediateScheduler]. /// /// Returns a signal that sends the current date/time every `interval` on /// `scheduler`. + (RACSignal *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler; /// Sends NSDate.date at intervals of at least `interval` seconds, up to /// approximately `interval` + `leeway` seconds. /// /// The created signal will defer sending each `next` for at least `interval` /// seconds, and for an additional amount of time up to `leeway` seconds in the /// interest of performance or power consumption. Note that some additional /// latency is to be expected, even when specifying a `leeway` of 0. /// /// interval - The base interval between `next`s. /// scheduler - The scheduler upon which the current NSDate should be sent. This /// must not be nil or +[RACScheduler immediateScheduler]. /// leeway - The maximum amount of additional time the `next` can be deferred. /// /// Returns a signal that sends the current date/time at intervals of at least /// `interval seconds` up to approximately `interval` + `leeway` seconds on /// `scheduler`. + (RACSignal *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler withLeeway:(NSTimeInterval)leeway; /// Takes `next`s until the `signalTrigger` sends `next` or `completed`. /// /// Returns a signal which passes through all events from the receiver until /// `signalTrigger` sends `next` or `completed`, at which point the returned signal /// will send `completed`. - (RACSignal *)takeUntil:(RACSignal *)signalTrigger; /// Takes `next`s until the `replacement` sends an event. /// /// replacement - The signal which replaces the receiver as soon as it sends an /// event. /// /// Returns a signal which passes through `next`s and `error` from the receiver /// until `replacement` sends an event, at which point the returned signal will /// send that event and switch to passing through events from `replacement` /// instead, regardless of whether the receiver has sent events already. - (RACSignal *)takeUntilReplacement:(RACSignal *)replacement; /// Subscribes to the returned signal when an error occurs. - (RACSignal *)catch:(RACSignal * (^)(NSError *error))catchBlock; /// Subscribes to the given signal when an error occurs. - (RACSignal *)catchTo:(RACSignal *)signal; /// Returns a signal that will either immediately send the return value of /// `tryBlock` and complete, or error using the `NSError` passed out from the /// block. /// /// tryBlock - An action that performs some computation that could fail. If the /// block returns nil, the block must return an error via the /// `errorPtr` parameter. /// /// Example: /// /// [RACSignal try:^(NSError **error) { /// return [NSJSONSerialization JSONObjectWithData:someJSONData options:0 error:error]; /// }]; + (RACSignal *)try:(id (^)(NSError **errorPtr))tryBlock; /// Runs `tryBlock` against each of the receiver's values, passing values /// until `tryBlock` returns NO, or the receiver completes. /// /// tryBlock - An action to run against each of the receiver's values. /// The block should return YES to indicate that the action was /// successful. This block must not be nil. /// /// Example: /// /// // The returned signal will send an error if data values cannot be /// // written to `someFileURL`. /// [signal try:^(NSData *data, NSError **errorPtr) { /// return [data writeToURL:someFileURL options:NSDataWritingAtomic error:errorPtr]; /// }]; /// /// Returns a signal which passes through all the values of the receiver. If /// `tryBlock` fails for any value, the returned signal will error using the /// `NSError` passed out from the block. - (RACSignal *)try:(BOOL (^)(id value, NSError **errorPtr))tryBlock; /// Runs `mapBlock` against each of the receiver's values, mapping values until /// `mapBlock` returns nil, or the receiver completes. /// /// mapBlock - An action to map each of the receiver's values. The block should /// return a non-nil value to indicate that the action was successful. /// This block must not be nil. /// /// Example: /// /// // The returned signal will send an error if data cannot be read from /// // `fileURL`. /// [signal tryMap:^(NSURL *fileURL, NSError **errorPtr) { /// return [NSData dataWithContentsOfURL:fileURL options:0 error:errorPtr]; /// }]; /// /// Returns a signal which transforms all the values of the receiver. If /// `mapBlock` returns nil for any value, the returned signal will error using /// the `NSError` passed out from the block. - (RACSignal *)tryMap:(id (^)(id value, NSError **errorPtr))mapBlock; /// Returns the first `next`. Note that this is a blocking call. - (id)first; /// Returns the first `next` or `defaultValue` if the signal completes or errors /// without sending a `next`. Note that this is a blocking call. - (id)firstOrDefault:(id)defaultValue; /// Returns the first `next` or `defaultValue` if the signal completes or errors /// without sending a `next`. If an error occurs success will be NO and error /// will be populated. Note that this is a blocking call. /// /// Both success and error may be NULL. - (id)firstOrDefault:(id)defaultValue success:(BOOL *)success error:(NSError **)error; /// Blocks the caller and waits for the signal to complete. /// /// error - If not NULL, set to any error that occurs. /// /// Returns whether the signal completed successfully. If NO, `error` will be set /// to the error that occurred. - (BOOL)waitUntilCompleted:(NSError **)error; /// Defers creation of a signal until the signal's actually subscribed to. /// /// This can be used to effectively turn a hot signal into a cold signal. + (RACSignal *)defer:(RACSignal * (^)(void))block; /// Every time the receiver sends a new RACSignal, subscribes and sends `next`s and /// `error`s only for that signal. /// /// The receiver must be a signal of signals. /// /// Returns a signal which passes through `next`s and `error`s from the latest /// signal sent by the receiver, and sends `completed` when both the receiver and /// the last sent signal complete. - (RACSignal *)switchToLatest; /// Switches between the signals in `cases` as well as `defaultSignal` based on /// the latest value sent by `signal`. /// /// signal - A signal of objects used as keys in the `cases` dictionary. /// This argument must not be nil. /// cases - A dictionary that has signals as values. This argument must /// not be nil. A RACTupleNil key in this dictionary will match /// nil `next` events that are received on `signal`. /// defaultSignal - The signal to pass through after `signal` sends a value for /// which `cases` does not contain a signal. If nil, any /// unmatched values will result in /// a RACSignalErrorNoMatchingCase error. /// /// Returns a signal which passes through `next`s and `error`s from one of the /// the signals in `cases` or `defaultSignal`, and sends `completed` when both /// `signal` and the last used signal complete. If no `defaultSignal` is given, /// an unmatched `next` will result in an error on the returned signal. + (RACSignal *)switch:(RACSignal *)signal cases:(NSDictionary *)cases default:(RACSignal *)defaultSignal; /// Switches between `trueSignal` and `falseSignal` based on the latest value /// sent by `boolSignal`. /// /// boolSignal - A signal of BOOLs determining whether `trueSignal` or /// `falseSignal` should be active. This argument must not be nil. /// trueSignal - The signal to pass through after `boolSignal` has sent YES. /// This argument must not be nil. /// falseSignal - The signal to pass through after `boolSignal` has sent NO. This /// argument must not be nil. /// /// Returns a signal which passes through `next`s and `error`s from `trueSignal` /// and/or `falseSignal`, and sends `completed` when both `boolSignal` and the /// last switched signal complete. + (RACSignal *)if:(RACSignal *)boolSignal then:(RACSignal *)trueSignal else:(RACSignal *)falseSignal; /// Adds every `next` to an array. Nils are represented by NSNulls. Note that /// this is a blocking call. /// /// **This is not the same as the `ToArray` method in Rx.** See -collect for /// that behavior instead. /// /// Returns the array of `next` values, or nil if an error occurs. - (NSArray *)toArray; /// Adds every `next` to a sequence. Nils are represented by NSNulls. /// /// This corresponds to the `ToEnumerable` method in Rx. /// /// Returns a sequence which provides values from the signal as they're sent. /// Trying to retrieve a value from the sequence which has not yet been sent will /// block. @property (nonatomic, strong, readonly) RACSequence *sequence; /// Creates and returns a multicast connection. This allows you to share a single /// subscription to the underlying signal. - (RACMulticastConnection *)publish; /// Creates and returns a multicast connection that pushes values into the given /// subject. This allows you to share a single subscription to the underlying /// signal. - (RACMulticastConnection *)multicast:(RACSubject *)subject; /// Multicasts the signal to a RACReplaySubject of unlimited capacity, and /// immediately connects to the resulting RACMulticastConnection. /// /// Returns the connected, multicasted signal. - (RACSignal *)replay; /// Multicasts the signal to a RACReplaySubject of capacity 1, and immediately /// connects to the resulting RACMulticastConnection. /// /// Returns the connected, multicasted signal. - (RACSignal *)replayLast; /// Multicasts the signal to a RACReplaySubject of unlimited capacity, and /// lazily connects to the resulting RACMulticastConnection. /// /// This means the returned signal will subscribe to the multicasted signal only /// when the former receives its first subscription. /// /// Returns the lazily connected, multicasted signal. - (RACSignal *)replayLazily; /// Sends an error after `interval` seconds if the source doesn't complete /// before then. /// /// The error will be in the RACSignalErrorDomain and have a code of /// RACSignalErrorTimedOut. /// /// interval - The number of seconds after which the signal should error out. /// scheduler - The scheduler upon which any timeout error should be sent. This /// must not be nil or +[RACScheduler immediateScheduler]. /// /// Returns a signal that passes through the receiver's events, until the stream /// finishes or times out, at which point an error will be sent on `scheduler`. - (RACSignal *)timeout:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler; /// Creates and returns a signal that delivers its events on the given scheduler. /// Any side effects of the receiver will still be performed on the original /// thread. /// /// This is ideal when the signal already performs its work on the desired /// thread, but you want to handle its events elsewhere. /// /// This corresponds to the `ObserveOn` method in Rx. - (RACSignal *)deliverOn:(RACScheduler *)scheduler; /// Creates and returns a signal that executes its side effects and delivers its /// events on the given scheduler. /// /// Use of this operator should be avoided whenever possible, because the /// receiver's side effects may not be safe to run on another thread. If you just /// want to receive the signal's events on `scheduler`, use -deliverOn: instead. - (RACSignal *)subscribeOn:(RACScheduler *)scheduler; /// Creates and returns a signal that delivers its events on the main thread. /// If events are already being sent on the main thread, they may be passed on /// without delay. An event will instead be queued for later delivery on the main /// thread if sent on another thread, or if a previous event is already being /// processed, or has been queued. /// /// Any side effects of the receiver will still be performed on the original /// thread. /// /// This can be used when a signal will cause UI updates, to avoid potential /// flicker caused by delayed delivery of events, such as the first event from /// a RACObserve at view instantiation. - (RACSignal *)deliverOnMainThread; /// Groups each received object into a group, as determined by calling `keyBlock` /// with that object. The object sent is transformed by calling `transformBlock` /// with the object. If `transformBlock` is nil, it sends the original object. /// /// The returned signal is a signal of RACGroupedSignal. - (RACSignal *)groupBy:(id (^)(id object))keyBlock transform:(id (^)(id object))transformBlock; /// Calls -[RACSignal groupBy:keyBlock transform:nil]. - (RACSignal *)groupBy:(id (^)(id object))keyBlock; /// Sends an [NSNumber numberWithBool:YES] if the receiving signal sends any /// objects. - (RACSignal *)any; /// Sends an [NSNumber numberWithBool:YES] if the receiving signal sends any /// objects that pass `predicateBlock`. /// /// predicateBlock - cannot be nil. - (RACSignal *)any:(BOOL (^)(id object))predicateBlock; /// Sends an [NSNumber numberWithBool:YES] if all the objects the receiving /// signal sends pass `predicateBlock`. /// /// predicateBlock - cannot be nil. - (RACSignal *)all:(BOOL (^)(id object))predicateBlock; /// Resubscribes to the receiving signal if an error occurs, up until it has /// retried the given number of times. /// /// retryCount - if 0, it keeps retrying until it completes. - (RACSignal *)retry:(NSInteger)retryCount; /// Resubscribes to the receiving signal if an error occurs. - (RACSignal *)retry; /// Sends the latest value from the receiver only when `sampler` sends a value. /// The returned signal could repeat values if `sampler` fires more often than /// the receiver. Values from `sampler` are ignored before the receiver sends /// its first value. /// /// sampler - The signal that controls when the latest value from the receiver /// is sent. Cannot be nil. - (RACSignal *)sample:(RACSignal *)sampler; /// Ignores all `next`s from the receiver. /// /// Returns a signal which only passes through `error` or `completed` events from /// the receiver. - (RACSignal *)ignoreValues; /// Converts each of the receiver's events into a RACEvent object. /// /// Returns a signal which sends the receiver's events as RACEvents, and /// completes after the receiver sends `completed` or `error`. - (RACSignal *)materialize; /// Converts each RACEvent in the receiver back into "real" RACSignal events. /// /// Returns a signal which sends `next` for each value RACEvent, `error` for each /// error RACEvent, and `completed` for each completed RACEvent. - (RACSignal *)dematerialize; /// Inverts each NSNumber-wrapped BOOL sent by the receiver. It will assert if /// the receiver sends anything other than NSNumbers. /// /// Returns a signal of inverted NSNumber-wrapped BOOLs. - (RACSignal *)not; /// Performs a boolean AND on all of the RACTuple of NSNumbers in sent by the receiver. /// /// Asserts if the receiver sends anything other than a RACTuple of one or more NSNumbers. /// /// Returns a signal that applies AND to each NSNumber in the tuple. - (RACSignal *)and; /// Performs a boolean OR on all of the RACTuple of NSNumbers in sent by the receiver. /// /// Asserts if the receiver sends anything other than a RACTuple of one or more NSNumbers. /// /// Returns a signal that applies OR to each NSNumber in the tuple. - (RACSignal *)or; /// Sends the result of calling the block with arguments as packed in each RACTuple /// sent by the receiver. /// /// The receiver must send tuple values, where the first element of the tuple is /// a block, taking a number of parameters equal to the count of the remaining /// elements of the tuple, and returning an object. Each block must take at least /// one argument, so each tuple must contain at least 2 elements. /// /// Example: /// /// RACSignal *adder = [RACSignal return:^(NSNumber *a, NSNumber *b) { /// return @(a.intValue + b.intValue); /// }]; /// RACSignal *sums = [[RACSignal /// combineLatest:@[ adder, as, bs ]] /// reduceApply]; /// /// Returns a signal of the result of applying the first element of each tuple /// to the remaining elements. - (RACSignal *)reduceApply; @end @interface RACSignal (UnavailableOperations) - (RACSignal *)windowWithStart:(RACSignal *)openSignal close:(RACSignal * (^)(RACSignal *start))closeBlock __attribute__((unavailable("See https://github.com/ReactiveCocoa/ReactiveCocoa/issues/587"))); - (RACSignal *)buffer:(NSUInteger)bufferCount __attribute__((unavailable("See https://github.com/ReactiveCocoa/ReactiveCocoa/issues/587"))); - (RACSignal *)let:(RACSignal * (^)(RACSignal *sharedSignal))letBlock __attribute__((unavailable("Use -publish instead"))); + (RACSignal *)interval:(NSTimeInterval)interval __attribute__((unavailable("Use +interval:onScheduler: instead"))); + (RACSignal *)interval:(NSTimeInterval)interval withLeeway:(NSTimeInterval)leeway __attribute__((unavailable("Use +interval:onScheduler:withLeeway: instead"))); - (RACSignal *)bufferWithTime:(NSTimeInterval)interval __attribute__((unavailable("Use -bufferWithTime:onScheduler: instead"))); - (RACSignal *)timeout:(NSTimeInterval)interval __attribute__((unavailable("Use -timeout:onScheduler: instead"))); - (RACDisposable *)toProperty:(NSString *)keyPath onObject:(NSObject *)object __attribute__((unavailable("Renamed to -setKeyPath:onObject:"))); - (RACSignal *)ignoreElements __attribute__((unavailable("Renamed to -ignoreValues"))); - (RACSignal *)sequenceNext:(RACSignal * (^)(void))block __attribute__((unavailable("Renamed to -then:"))); - (RACSignal *)aggregateWithStart:(id)start combine:(id (^)(id running, id next))combineBlock __attribute__((unavailable("Renamed to -aggregateWithStart:reduce:"))); - (RACSignal *)aggregateWithStartFactory:(id (^)(void))startFactory combine:(id (^)(id running, id next))combineBlock __attribute__((unavailable("Renamed to -aggregateWithStartFactory:reduce:"))); - (RACDisposable *)executeCommand:(RACCommand *)command __attribute__((unavailable("Use -flattenMap: or -subscribeNext: instead"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSignal+Operations.m ================================================ // // RACSignal+Operations.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-09-06. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSignal+Operations.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import "RACBlockTrampoline.h" #import "RACCommand.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACEvent.h" #import "RACGroupedSignal.h" #import "RACMulticastConnection+Private.h" #import "RACReplaySubject.h" #import "RACScheduler.h" #import "RACSerialDisposable.h" #import "RACSignalSequence.h" #import "RACStream+Private.h" #import "RACSubject.h" #import "RACSubscriber+Private.h" #import "RACSubscriber.h" #import "RACTuple.h" #import "RACUnit.h" #import #import NSString * const RACSignalErrorDomain = @"RACSignalErrorDomain"; const NSInteger RACSignalErrorTimedOut = 1; const NSInteger RACSignalErrorNoMatchingCase = 2; // Subscribes to the given signal with the given blocks. // // If the signal errors or completes, the corresponding block is invoked. If the // disposable passed to the block is _not_ disposed, then the signal is // subscribed to again. static RACDisposable *subscribeForever (RACSignal *signal, void (^next)(id), void (^error)(NSError *, RACDisposable *), void (^completed)(RACDisposable *)) { next = [next copy]; error = [error copy]; completed = [completed copy]; RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable]; RACSchedulerRecursiveBlock recursiveBlock = ^(void (^recurse)(void)) { RACCompoundDisposable *selfDisposable = [RACCompoundDisposable compoundDisposable]; [compoundDisposable addDisposable:selfDisposable]; __weak RACDisposable *weakSelfDisposable = selfDisposable; RACDisposable *subscriptionDisposable = [signal subscribeNext:next error:^(NSError *e) { @autoreleasepool { error(e, compoundDisposable); [compoundDisposable removeDisposable:weakSelfDisposable]; } recurse(); } completed:^{ @autoreleasepool { completed(compoundDisposable); [compoundDisposable removeDisposable:weakSelfDisposable]; } recurse(); }]; [selfDisposable addDisposable:subscriptionDisposable]; }; // Subscribe once immediately, and then use recursive scheduling for any // further resubscriptions. recursiveBlock(^{ RACScheduler *recursiveScheduler = RACScheduler.currentScheduler ?: [RACScheduler scheduler]; RACDisposable *schedulingDisposable = [recursiveScheduler scheduleRecursiveBlock:recursiveBlock]; [compoundDisposable addDisposable:schedulingDisposable]; }); return compoundDisposable; } @implementation RACSignal (Operations) - (RACSignal *)doNext:(void (^)(id x))block { NSCParameterAssert(block != NULL); return [[RACSignal createSignal:^(id subscriber) { return [self subscribeNext:^(id x) { block(x); [subscriber sendNext:x]; } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ [subscriber sendCompleted]; }]; }] setNameWithFormat:@"[%@] -doNext:", self.name]; } - (RACSignal *)doError:(void (^)(NSError *error))block { NSCParameterAssert(block != NULL); return [[RACSignal createSignal:^(id subscriber) { return [self subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { block(error); [subscriber sendError:error]; } completed:^{ [subscriber sendCompleted]; }]; }] setNameWithFormat:@"[%@] -doError:", self.name]; } - (RACSignal *)doCompleted:(void (^)(void))block { NSCParameterAssert(block != NULL); return [[RACSignal createSignal:^(id subscriber) { return [self subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ block(); [subscriber sendCompleted]; }]; }] setNameWithFormat:@"[%@] -doCompleted:", self.name]; } - (RACSignal *)throttle:(NSTimeInterval)interval { return [[self throttle:interval valuesPassingTest:^(id _) { return YES; }] setNameWithFormat:@"[%@] -throttle: %f", self.name, (double)interval]; } - (RACSignal *)throttle:(NSTimeInterval)interval valuesPassingTest:(BOOL (^)(id next))predicate { NSCParameterAssert(interval >= 0); NSCParameterAssert(predicate != nil); return [[RACSignal createSignal:^(id subscriber) { RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable]; // We may never use this scheduler, but we need to set it up ahead of // time so that our scheduled blocks are run serially if we do. RACScheduler *scheduler = [RACScheduler scheduler]; // Information about any currently-buffered `next` event. __block id nextValue = nil; __block BOOL hasNextValue = NO; RACSerialDisposable *nextDisposable = [[RACSerialDisposable alloc] init]; void (^flushNext)(BOOL send) = ^(BOOL send) { @synchronized (compoundDisposable) { [nextDisposable.disposable dispose]; if (!hasNextValue) return; if (send) [subscriber sendNext:nextValue]; nextValue = nil; hasNextValue = NO; } }; RACDisposable *subscriptionDisposable = [self subscribeNext:^(id x) { RACScheduler *delayScheduler = RACScheduler.currentScheduler ?: scheduler; BOOL shouldThrottle = predicate(x); @synchronized (compoundDisposable) { flushNext(NO); if (!shouldThrottle) { [subscriber sendNext:x]; return; } nextValue = x; hasNextValue = YES; nextDisposable.disposable = [delayScheduler afterDelay:interval schedule:^{ flushNext(YES); }]; } } error:^(NSError *error) { [compoundDisposable dispose]; [subscriber sendError:error]; } completed:^{ flushNext(YES); [subscriber sendCompleted]; }]; [compoundDisposable addDisposable:subscriptionDisposable]; return compoundDisposable; }] setNameWithFormat:@"[%@] -throttle: %f valuesPassingTest:", self.name, (double)interval]; } - (RACSignal *)delay:(NSTimeInterval)interval { return [[RACSignal createSignal:^(id subscriber) { RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; // We may never use this scheduler, but we need to set it up ahead of // time so that our scheduled blocks are run serially if we do. RACScheduler *scheduler = [RACScheduler scheduler]; void (^schedule)(dispatch_block_t) = ^(dispatch_block_t block) { RACScheduler *delayScheduler = RACScheduler.currentScheduler ?: scheduler; RACDisposable *schedulerDisposable = [delayScheduler afterDelay:interval schedule:block]; [disposable addDisposable:schedulerDisposable]; }; RACDisposable *subscriptionDisposable = [self subscribeNext:^(id x) { schedule(^{ [subscriber sendNext:x]; }); } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ schedule(^{ [subscriber sendCompleted]; }); }]; [disposable addDisposable:subscriptionDisposable]; return disposable; }] setNameWithFormat:@"[%@] -delay: %f", self.name, (double)interval]; } - (RACSignal *)repeat { return [[RACSignal createSignal:^(id subscriber) { return subscribeForever(self, ^(id x) { [subscriber sendNext:x]; }, ^(NSError *error, RACDisposable *disposable) { [disposable dispose]; [subscriber sendError:error]; }, ^(RACDisposable *disposable) { // Resubscribe. }); }] setNameWithFormat:@"[%@] -repeat", self.name]; } - (RACSignal *)catch:(RACSignal * (^)(NSError *error))catchBlock { NSCParameterAssert(catchBlock != NULL); return [[RACSignal createSignal:^(id subscriber) { RACSerialDisposable *catchDisposable = [[RACSerialDisposable alloc] init]; RACDisposable *subscriptionDisposable = [self subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { RACSignal *signal = catchBlock(error); NSCAssert(signal != nil, @"Expected non-nil signal from catch block on %@", self); catchDisposable.disposable = [signal subscribe:subscriber]; } completed:^{ [subscriber sendCompleted]; }]; return [RACDisposable disposableWithBlock:^{ [catchDisposable dispose]; [subscriptionDisposable dispose]; }]; }] setNameWithFormat:@"[%@] -catch:", self.name]; } - (RACSignal *)catchTo:(RACSignal *)signal { return [[self catch:^(NSError *error) { return signal; }] setNameWithFormat:@"[%@] -catchTo: %@", self.name, signal]; } + (RACSignal *)try:(id (^)(NSError **errorPtr))tryBlock { NSCParameterAssert(tryBlock != NULL); return [[RACSignal createSignal:^(id subscriber) { NSError *error; id value = tryBlock(&error); RACSignal *signal = (value == nil ? [RACSignal error:error] : [RACSignal return:value]); return [signal subscribe:subscriber]; }] setNameWithFormat:@"+try:"]; } - (RACSignal *)try:(BOOL (^)(id value, NSError **errorPtr))tryBlock { NSCParameterAssert(tryBlock != NULL); return [[self flattenMap:^(id value) { NSError *error = nil; BOOL passed = tryBlock(value, &error); return (passed ? [RACSignal return:value] : [RACSignal error:error]); }] setNameWithFormat:@"[%@] -try:", self.name]; } - (RACSignal *)tryMap:(id (^)(id value, NSError **errorPtr))mapBlock { NSCParameterAssert(mapBlock != NULL); return [[self flattenMap:^(id value) { NSError *error = nil; id mappedValue = mapBlock(value, &error); return (mappedValue == nil ? [RACSignal error:error] : [RACSignal return:mappedValue]); }] setNameWithFormat:@"[%@] -tryMap:", self.name]; } - (RACSignal *)initially:(void (^)(void))block { NSCParameterAssert(block != NULL); return [[RACSignal defer:^{ block(); return self; }] setNameWithFormat:@"[%@] -initially:", self.name]; } - (RACSignal *)finally:(void (^)(void))block { NSCParameterAssert(block != NULL); return [[[self doError:^(NSError *error) { block(); }] doCompleted:^{ block(); }] setNameWithFormat:@"[%@] -finally:", self.name]; } - (RACSignal *)bufferWithTime:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler { NSCParameterAssert(scheduler != nil); NSCParameterAssert(scheduler != RACScheduler.immediateScheduler); return [[RACSignal createSignal:^(id subscriber) { RACSerialDisposable *timerDisposable = [[RACSerialDisposable alloc] init]; NSMutableArray *values = [NSMutableArray array]; void (^flushValues)() = ^{ @synchronized (values) { [timerDisposable.disposable dispose]; if (values.count == 0) return; RACTuple *tuple = [RACTuple tupleWithObjectsFromArray:values]; [values removeAllObjects]; [subscriber sendNext:tuple]; } }; RACDisposable *selfDisposable = [self subscribeNext:^(id x) { @synchronized (values) { if (values.count == 0) { timerDisposable.disposable = [scheduler afterDelay:interval schedule:flushValues]; } [values addObject:x ?: RACTupleNil.tupleNil]; } } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ flushValues(); [subscriber sendCompleted]; }]; return [RACDisposable disposableWithBlock:^{ [selfDisposable dispose]; [timerDisposable dispose]; }]; }] setNameWithFormat:@"[%@] -bufferWithTime: %f onScheduler: %@", self.name, (double)interval, scheduler]; } - (RACSignal *)collect { return [[self aggregateWithStartFactory:^{ return [[NSMutableArray alloc] init]; } reduce:^(NSMutableArray *collectedValues, id x) { [collectedValues addObject:(x ?: NSNull.null)]; return collectedValues; }] setNameWithFormat:@"[%@] -collect", self.name]; } - (RACSignal *)takeLast:(NSUInteger)count { return [[RACSignal createSignal:^(id subscriber) { NSMutableArray *valuesTaken = [NSMutableArray arrayWithCapacity:count]; return [self subscribeNext:^(id x) { [valuesTaken addObject:x ? : RACTupleNil.tupleNil]; while (valuesTaken.count > count) { [valuesTaken removeObjectAtIndex:0]; } } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ for (id value in valuesTaken) { [subscriber sendNext:value == RACTupleNil.tupleNil ? nil : value]; } [subscriber sendCompleted]; }]; }] setNameWithFormat:@"[%@] -takeLast: %lu", self.name, (unsigned long)count]; } - (RACSignal *)combineLatestWith:(RACSignal *)signal { NSCParameterAssert(signal != nil); return [[RACSignal createSignal:^(id subscriber) { RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; __block id lastSelfValue = nil; __block BOOL selfCompleted = NO; __block id lastOtherValue = nil; __block BOOL otherCompleted = NO; void (^sendNext)(void) = ^{ @synchronized (disposable) { if (lastSelfValue == nil || lastOtherValue == nil) return; [subscriber sendNext:RACTuplePack(lastSelfValue, lastOtherValue)]; } }; RACDisposable *selfDisposable = [self subscribeNext:^(id x) { @synchronized (disposable) { lastSelfValue = x ?: RACTupleNil.tupleNil; sendNext(); } } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ @synchronized (disposable) { selfCompleted = YES; if (otherCompleted) [subscriber sendCompleted]; } }]; [disposable addDisposable:selfDisposable]; RACDisposable *otherDisposable = [signal subscribeNext:^(id x) { @synchronized (disposable) { lastOtherValue = x ?: RACTupleNil.tupleNil; sendNext(); } } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ @synchronized (disposable) { otherCompleted = YES; if (selfCompleted) [subscriber sendCompleted]; } }]; [disposable addDisposable:otherDisposable]; return disposable; }] setNameWithFormat:@"[%@] -combineLatestWith: %@", self.name, signal]; } + (RACSignal *)combineLatest:(id)signals { return [[self join:signals block:^(RACSignal *left, RACSignal *right) { return [left combineLatestWith:right]; }] setNameWithFormat:@"+combineLatest: %@", signals]; } + (RACSignal *)combineLatest:(id)signals reduce:(id (^)())reduceBlock { NSCParameterAssert(reduceBlock != nil); RACSignal *result = [self combineLatest:signals]; // Although we assert this condition above, older versions of this method // supported this argument being nil. Avoid crashing Release builds of // apps that depended on that. if (reduceBlock != nil) result = [result reduceEach:reduceBlock]; return [result setNameWithFormat:@"+combineLatest: %@ reduce:", signals]; } - (RACSignal *)merge:(RACSignal *)signal { return [[RACSignal merge:@[ self, signal ]] setNameWithFormat:@"[%@] -merge: %@", self.name, signal]; } + (RACSignal *)merge:(id)signals { NSMutableArray *copiedSignals = [[NSMutableArray alloc] init]; for (RACSignal *signal in signals) { [copiedSignals addObject:signal]; } return [[[RACSignal createSignal:^ RACDisposable * (id subscriber) { for (RACSignal *signal in copiedSignals) { [subscriber sendNext:signal]; } [subscriber sendCompleted]; return nil; }] flatten] setNameWithFormat:@"+merge: %@", copiedSignals]; } - (RACSignal *)flatten:(NSUInteger)maxConcurrent { return [[RACSignal createSignal:^(id subscriber) { RACCompoundDisposable *compoundDisposable = [[RACCompoundDisposable alloc] init]; // Contains disposables for the currently active subscriptions. // // This should only be used while synchronized on `subscriber`. NSMutableArray *activeDisposables = [[NSMutableArray alloc] initWithCapacity:maxConcurrent]; // Whether the signal-of-signals has completed yet. // // This should only be used while synchronized on `subscriber`. __block BOOL selfCompleted = NO; // Subscribes to the given signal. __block void (^subscribeToSignal)(RACSignal *); // Weak reference to the above, to avoid a leak. __weak __block void (^recur)(RACSignal *); // Sends completed to the subscriber if all signals are finished. // // This should only be used while synchronized on `subscriber`. void (^completeIfAllowed)(void) = ^{ if (selfCompleted && activeDisposables.count == 0) { [subscriber sendCompleted]; } }; // The signals waiting to be started. // // This array should only be used while synchronized on `subscriber`. NSMutableArray *queuedSignals = [NSMutableArray array]; recur = subscribeToSignal = ^(RACSignal *signal) { RACSerialDisposable *serialDisposable = [[RACSerialDisposable alloc] init]; @synchronized (subscriber) { [compoundDisposable addDisposable:serialDisposable]; [activeDisposables addObject:serialDisposable]; } serialDisposable.disposable = [signal subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ __strong void (^subscribeToSignal)(RACSignal *) = recur; RACSignal *nextSignal; @synchronized (subscriber) { [compoundDisposable removeDisposable:serialDisposable]; [activeDisposables removeObjectIdenticalTo:serialDisposable]; if (queuedSignals.count == 0) { completeIfAllowed(); return; } nextSignal = queuedSignals[0]; [queuedSignals removeObjectAtIndex:0]; } subscribeToSignal(nextSignal); }]; }; [compoundDisposable addDisposable:[self subscribeNext:^(RACSignal *signal) { if (signal == nil) return; NSCAssert([signal isKindOfClass:RACSignal.class], @"Expected a RACSignal, got %@", signal); @synchronized (subscriber) { if (maxConcurrent > 0 && activeDisposables.count >= maxConcurrent) { [queuedSignals addObject:signal]; // If we need to wait, skip subscribing to this // signal. return; } } subscribeToSignal(signal); } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ @synchronized (subscriber) { selfCompleted = YES; completeIfAllowed(); } }]]; [compoundDisposable addDisposable:[RACDisposable disposableWithBlock:^{ // A strong reference is held to `subscribeToSignal` until we're // done, preventing it from deallocating early. subscribeToSignal = nil; }]]; return compoundDisposable; }] setNameWithFormat:@"[%@] -flatten: %lu", self.name, (unsigned long)maxConcurrent]; } - (RACSignal *)then:(RACSignal * (^)(void))block { NSCParameterAssert(block != nil); return [[[self ignoreValues] concat:[RACSignal defer:block]] setNameWithFormat:@"[%@] -then:", self.name]; } - (RACSignal *)concat { return [[self flatten:1] setNameWithFormat:@"[%@] -concat", self.name]; } - (RACSignal *)aggregateWithStartFactory:(id (^)(void))startFactory reduce:(id (^)(id running, id next))reduceBlock { NSCParameterAssert(startFactory != NULL); NSCParameterAssert(reduceBlock != NULL); return [[RACSignal defer:^{ return [self aggregateWithStart:startFactory() reduce:reduceBlock]; }] setNameWithFormat:@"[%@] -aggregateWithStartFactory:reduce:", self.name]; } - (RACSignal *)aggregateWithStart:(id)start reduce:(id (^)(id running, id next))reduceBlock { return [[self aggregateWithStart:start reduceWithIndex:^(id running, id next, NSUInteger index) { return reduceBlock(running, next); }] setNameWithFormat:@"[%@] -aggregateWithStart: %@ reduce:", self.name, RACDescription(start)]; } - (RACSignal *)aggregateWithStart:(id)start reduceWithIndex:(id (^)(id, id, NSUInteger))reduceBlock { return [[[[self scanWithStart:start reduceWithIndex:reduceBlock] startWith:start] takeLast:1] setNameWithFormat:@"[%@] -aggregateWithStart: %@ reduceWithIndex:", self.name, RACDescription(start)]; } - (RACDisposable *)setKeyPath:(NSString *)keyPath onObject:(NSObject *)object { return [self setKeyPath:keyPath onObject:object nilValue:nil]; } - (RACDisposable *)setKeyPath:(NSString *)keyPath onObject:(NSObject *)object nilValue:(id)nilValue { NSCParameterAssert(keyPath != nil); NSCParameterAssert(object != nil); keyPath = [keyPath copy]; RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; // Purposely not retaining 'object', since we want to tear down the binding // when it deallocates normally. __block void * volatile objectPtr = (__bridge void *)object; RACDisposable *subscriptionDisposable = [self subscribeNext:^(id x) { // Possibly spec, possibly compiler bug, but this __bridge cast does not // result in a retain here, effectively an invisible __unsafe_unretained // qualifier. Using objc_precise_lifetime gives the __strong reference // desired. The explicit use of __strong is strictly defensive. __strong NSObject *object __attribute__((objc_precise_lifetime)) = (__bridge __strong id)objectPtr; [object setValue:x ?: nilValue forKeyPath:keyPath]; } error:^(NSError *error) { __strong NSObject *object __attribute__((objc_precise_lifetime)) = (__bridge __strong id)objectPtr; NSCAssert(NO, @"Received error from %@ in binding for key path \"%@\" on %@: %@", self, keyPath, object, error); // Log the error if we're running with assertions disabled. NSLog(@"Received error from %@ in binding for key path \"%@\" on %@: %@", self, keyPath, object, error); [disposable dispose]; } completed:^{ [disposable dispose]; }]; [disposable addDisposable:subscriptionDisposable]; #if DEBUG static void *bindingsKey = &bindingsKey; NSMutableDictionary *bindings; @synchronized (object) { bindings = objc_getAssociatedObject(object, bindingsKey); if (bindings == nil) { bindings = [NSMutableDictionary dictionary]; objc_setAssociatedObject(object, bindingsKey, bindings, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } @synchronized (bindings) { NSCAssert(bindings[keyPath] == nil, @"Signal %@ is already bound to key path \"%@\" on object %@, adding signal %@ is undefined behavior", [bindings[keyPath] nonretainedObjectValue], keyPath, object, self); bindings[keyPath] = [NSValue valueWithNonretainedObject:self]; } #endif RACDisposable *clearPointerDisposable = [RACDisposable disposableWithBlock:^{ #if DEBUG @synchronized (bindings) { [bindings removeObjectForKey:keyPath]; } #endif while (YES) { void *ptr = objectPtr; if (OSAtomicCompareAndSwapPtrBarrier(ptr, NULL, &objectPtr)) { break; } } }]; [disposable addDisposable:clearPointerDisposable]; [object.rac_deallocDisposable addDisposable:disposable]; RACCompoundDisposable *objectDisposable = object.rac_deallocDisposable; return [RACDisposable disposableWithBlock:^{ [objectDisposable removeDisposable:disposable]; [disposable dispose]; }]; } + (RACSignal *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler { return [[RACSignal interval:interval onScheduler:scheduler withLeeway:0.0] setNameWithFormat:@"+interval: %f onScheduler: %@", (double)interval, scheduler]; } + (RACSignal *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler withLeeway:(NSTimeInterval)leeway { NSCParameterAssert(scheduler != nil); NSCParameterAssert(scheduler != RACScheduler.immediateScheduler); return [[RACSignal createSignal:^(id subscriber) { return [scheduler after:[NSDate dateWithTimeIntervalSinceNow:interval] repeatingEvery:interval withLeeway:leeway schedule:^{ [subscriber sendNext:[NSDate date]]; }]; }] setNameWithFormat:@"+interval: %f onScheduler: %@ withLeeway: %f", (double)interval, scheduler, (double)leeway]; } - (RACSignal *)takeUntil:(RACSignal *)signalTrigger { return [[RACSignal createSignal:^(id subscriber) { RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; void (^triggerCompletion)(void) = ^{ [disposable dispose]; [subscriber sendCompleted]; }; RACDisposable *triggerDisposable = [signalTrigger subscribeNext:^(id _) { triggerCompletion(); } completed:^{ triggerCompletion(); }]; [disposable addDisposable:triggerDisposable]; if (!disposable.disposed) { RACDisposable *selfDisposable = [self subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ [disposable dispose]; [subscriber sendCompleted]; }]; [disposable addDisposable:selfDisposable]; } return disposable; }] setNameWithFormat:@"[%@] -takeUntil: %@", self.name, signalTrigger]; } - (RACSignal *)takeUntilReplacement:(RACSignal *)replacement { return [RACSignal createSignal:^(id subscriber) { RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init]; RACDisposable *replacementDisposable = [replacement subscribeNext:^(id x) { [selfDisposable dispose]; [subscriber sendNext:x]; } error:^(NSError *error) { [selfDisposable dispose]; [subscriber sendError:error]; } completed:^{ [selfDisposable dispose]; [subscriber sendCompleted]; }]; if (!selfDisposable.disposed) { selfDisposable.disposable = [[self concat:[RACSignal never]] subscribe:subscriber]; } return [RACDisposable disposableWithBlock:^{ [selfDisposable dispose]; [replacementDisposable dispose]; }]; }]; } - (RACSignal *)switchToLatest { return [[RACSignal createSignal:^(id subscriber) { RACMulticastConnection *connection = [self publish]; RACDisposable *subscriptionDisposable = [[connection.signal flattenMap:^(RACSignal *x) { NSCAssert(x == nil || [x isKindOfClass:RACSignal.class], @"-switchToLatest requires that the source signal (%@) send signals. Instead we got: %@", self, x); // -concat:[RACSignal never] prevents completion of the receiver from // prematurely terminating the inner signal. return [x takeUntil:[connection.signal concat:[RACSignal never]]]; }] subscribe:subscriber]; RACDisposable *connectionDisposable = [connection connect]; return [RACDisposable disposableWithBlock:^{ [subscriptionDisposable dispose]; [connectionDisposable dispose]; }]; }] setNameWithFormat:@"[%@] -switchToLatest", self.name]; } + (RACSignal *)switch:(RACSignal *)signal cases:(NSDictionary *)cases default:(RACSignal *)defaultSignal { NSCParameterAssert(signal != nil); NSCParameterAssert(cases != nil); for (id key in cases) { id value __attribute__((unused)) = cases[key]; NSCAssert([value isKindOfClass:RACSignal.class], @"Expected all cases to be RACSignals, %@ isn't", value); } NSDictionary *copy = [cases copy]; return [[[signal map:^(id key) { if (key == nil) key = RACTupleNil.tupleNil; RACSignal *signal = copy[key] ?: defaultSignal; if (signal == nil) { NSString *description = [NSString stringWithFormat:NSLocalizedString(@"No matching signal found for value %@", @""), key]; return [RACSignal error:[NSError errorWithDomain:RACSignalErrorDomain code:RACSignalErrorNoMatchingCase userInfo:@{ NSLocalizedDescriptionKey: description }]]; } return signal; }] switchToLatest] setNameWithFormat:@"+switch: %@ cases: %@ default: %@", signal, cases, defaultSignal]; } + (RACSignal *)if:(RACSignal *)boolSignal then:(RACSignal *)trueSignal else:(RACSignal *)falseSignal { NSCParameterAssert(boolSignal != nil); NSCParameterAssert(trueSignal != nil); NSCParameterAssert(falseSignal != nil); return [[[boolSignal map:^(NSNumber *value) { NSCAssert([value isKindOfClass:NSNumber.class], @"Expected %@ to send BOOLs, not %@", boolSignal, value); return (value.boolValue ? trueSignal : falseSignal); }] switchToLatest] setNameWithFormat:@"+if: %@ then: %@ else: %@", boolSignal, trueSignal, falseSignal]; } - (id)first { return [self firstOrDefault:nil]; } - (id)firstOrDefault:(id)defaultValue { return [self firstOrDefault:defaultValue success:NULL error:NULL]; } - (id)firstOrDefault:(id)defaultValue success:(BOOL *)success error:(NSError **)error { NSCondition *condition = [[NSCondition alloc] init]; condition.name = [NSString stringWithFormat:@"[%@] -firstOrDefault: %@ success:error:", self.name, defaultValue]; __block id value = defaultValue; __block BOOL done = NO; // Ensures that we don't pass values across thread boundaries by reference. __block NSError *localError; __block BOOL localSuccess; [[self take:1] subscribeNext:^(id x) { [condition lock]; value = x; localSuccess = YES; done = YES; [condition broadcast]; [condition unlock]; } error:^(NSError *e) { [condition lock]; if (!done) { localSuccess = NO; localError = e; done = YES; [condition broadcast]; } [condition unlock]; } completed:^{ [condition lock]; localSuccess = YES; done = YES; [condition broadcast]; [condition unlock]; }]; [condition lock]; while (!done) { [condition wait]; } if (success != NULL) *success = localSuccess; if (error != NULL) *error = localError; [condition unlock]; return value; } - (BOOL)waitUntilCompleted:(NSError **)error { BOOL success = NO; [[[self ignoreValues] setNameWithFormat:@"[%@] -waitUntilCompleted:", self.name] firstOrDefault:nil success:&success error:error]; return success; } + (RACSignal *)defer:(RACSignal * (^)(void))block { NSCParameterAssert(block != NULL); return [[RACSignal createSignal:^(id subscriber) { return [block() subscribe:subscriber]; }] setNameWithFormat:@"+defer:"]; } - (NSArray *)toArray { return [[[self collect] first] copy]; } - (RACSequence *)sequence { return [[RACSignalSequence sequenceWithSignal:self] setNameWithFormat:@"[%@] -sequence", self.name]; } - (RACMulticastConnection *)publish { RACSubject *subject = [[RACSubject subject] setNameWithFormat:@"[%@] -publish", self.name]; RACMulticastConnection *connection = [self multicast:subject]; return connection; } - (RACMulticastConnection *)multicast:(RACSubject *)subject { [subject setNameWithFormat:@"[%@] -multicast: %@", self.name, subject.name]; RACMulticastConnection *connection = [[RACMulticastConnection alloc] initWithSourceSignal:self subject:subject]; return connection; } - (RACSignal *)replay { RACReplaySubject *subject = [[RACReplaySubject subject] setNameWithFormat:@"[%@] -replay", self.name]; RACMulticastConnection *connection = [self multicast:subject]; [connection connect]; return connection.signal; } - (RACSignal *)replayLast { RACReplaySubject *subject = [[RACReplaySubject replaySubjectWithCapacity:1] setNameWithFormat:@"[%@] -replayLast", self.name]; RACMulticastConnection *connection = [self multicast:subject]; [connection connect]; return connection.signal; } - (RACSignal *)replayLazily { RACMulticastConnection *connection = [self multicast:[RACReplaySubject subject]]; return [[RACSignal defer:^{ [connection connect]; return connection.signal; }] setNameWithFormat:@"[%@] -replayLazily", self.name]; } - (RACSignal *)timeout:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler { NSCParameterAssert(scheduler != nil); NSCParameterAssert(scheduler != RACScheduler.immediateScheduler); return [[RACSignal createSignal:^(id subscriber) { RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; RACDisposable *timeoutDisposable = [scheduler afterDelay:interval schedule:^{ [disposable dispose]; [subscriber sendError:[NSError errorWithDomain:RACSignalErrorDomain code:RACSignalErrorTimedOut userInfo:nil]]; }]; [disposable addDisposable:timeoutDisposable]; RACDisposable *subscriptionDisposable = [self subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { [disposable dispose]; [subscriber sendError:error]; } completed:^{ [disposable dispose]; [subscriber sendCompleted]; }]; [disposable addDisposable:subscriptionDisposable]; return disposable; }] setNameWithFormat:@"[%@] -timeout: %f onScheduler: %@", self.name, (double)interval, scheduler]; } - (RACSignal *)deliverOn:(RACScheduler *)scheduler { return [[RACSignal createSignal:^(id subscriber) { return [self subscribeNext:^(id x) { [scheduler schedule:^{ [subscriber sendNext:x]; }]; } error:^(NSError *error) { [scheduler schedule:^{ [subscriber sendError:error]; }]; } completed:^{ [scheduler schedule:^{ [subscriber sendCompleted]; }]; }]; }] setNameWithFormat:@"[%@] -deliverOn: %@", self.name, scheduler]; } - (RACSignal *)subscribeOn:(RACScheduler *)scheduler { return [[RACSignal createSignal:^(id subscriber) { RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; RACDisposable *schedulingDisposable = [scheduler schedule:^{ RACDisposable *subscriptionDisposable = [self subscribe:subscriber]; [disposable addDisposable:subscriptionDisposable]; }]; [disposable addDisposable:schedulingDisposable]; return disposable; }] setNameWithFormat:@"[%@] -subscribeOn: %@", self.name, scheduler]; } - (RACSignal *)deliverOnMainThread { return [[RACSignal createSignal:^(id subscriber) { __block volatile int32_t queueLength = 0; void (^performOnMainThread)(dispatch_block_t) = ^(dispatch_block_t block) { int32_t queued = OSAtomicIncrement32(&queueLength); if (NSThread.isMainThread && queued == 1) { block(); OSAtomicDecrement32(&queueLength); } else { dispatch_async(dispatch_get_main_queue(), ^{ block(); OSAtomicDecrement32(&queueLength); }); } }; return [self subscribeNext:^(id x) { performOnMainThread(^{ [subscriber sendNext:x]; }); } error:^(NSError *error) { performOnMainThread(^{ [subscriber sendError:error]; }); } completed:^{ performOnMainThread(^{ [subscriber sendCompleted]; }); }]; }] setNameWithFormat:@"[%@] -deliverOnMainThread", self.name]; } - (RACSignal *)groupBy:(id (^)(id object))keyBlock transform:(id (^)(id object))transformBlock { NSCParameterAssert(keyBlock != NULL); return [[RACSignal createSignal:^(id subscriber) { NSMutableDictionary *groups = [NSMutableDictionary dictionary]; NSMutableArray *orderedGroups = [NSMutableArray array]; return [self subscribeNext:^(id x) { id key = keyBlock(x); RACGroupedSignal *groupSubject = nil; @synchronized(groups) { groupSubject = groups[key]; if (groupSubject == nil) { groupSubject = [RACGroupedSignal signalWithKey:key]; groups[key] = groupSubject; [orderedGroups addObject:groupSubject]; [subscriber sendNext:groupSubject]; } } [groupSubject sendNext:transformBlock != NULL ? transformBlock(x) : x]; } error:^(NSError *error) { [subscriber sendError:error]; [orderedGroups makeObjectsPerformSelector:@selector(sendError:) withObject:error]; } completed:^{ [subscriber sendCompleted]; [orderedGroups makeObjectsPerformSelector:@selector(sendCompleted)]; }]; }] setNameWithFormat:@"[%@] -groupBy:transform:", self.name]; } - (RACSignal *)groupBy:(id (^)(id object))keyBlock { return [[self groupBy:keyBlock transform:nil] setNameWithFormat:@"[%@] -groupBy:", self.name]; } - (RACSignal *)any { return [[self any:^(id x) { return YES; }] setNameWithFormat:@"[%@] -any", self.name]; } - (RACSignal *)any:(BOOL (^)(id object))predicateBlock { NSCParameterAssert(predicateBlock != NULL); return [[[self materialize] bind:^{ return ^(RACEvent *event, BOOL *stop) { if (event.finished) { *stop = YES; return [RACSignal return:@NO]; } if (predicateBlock(event.value)) { *stop = YES; return [RACSignal return:@YES]; } return [RACSignal empty]; }; }] setNameWithFormat:@"[%@] -any:", self.name]; } - (RACSignal *)all:(BOOL (^)(id object))predicateBlock { NSCParameterAssert(predicateBlock != NULL); return [[[self materialize] bind:^{ return ^(RACEvent *event, BOOL *stop) { if (event.eventType == RACEventTypeCompleted) { *stop = YES; return [RACSignal return:@YES]; } if (event.eventType == RACEventTypeError || !predicateBlock(event.value)) { *stop = YES; return [RACSignal return:@NO]; } return [RACSignal empty]; }; }] setNameWithFormat:@"[%@] -all:", self.name]; } - (RACSignal *)retry:(NSInteger)retryCount { return [[RACSignal createSignal:^(id subscriber) { __block NSInteger currentRetryCount = 0; return subscribeForever(self, ^(id x) { [subscriber sendNext:x]; }, ^(NSError *error, RACDisposable *disposable) { if (retryCount == 0 || currentRetryCount < retryCount) { // Resubscribe. currentRetryCount++; return; } [disposable dispose]; [subscriber sendError:error]; }, ^(RACDisposable *disposable) { [disposable dispose]; [subscriber sendCompleted]; }); }] setNameWithFormat:@"[%@] -retry: %lu", self.name, (unsigned long)retryCount]; } - (RACSignal *)retry { return [[self retry:0] setNameWithFormat:@"[%@] -retry", self.name]; } - (RACSignal *)sample:(RACSignal *)sampler { NSCParameterAssert(sampler != nil); return [[RACSignal createSignal:^(id subscriber) { NSLock *lock = [[NSLock alloc] init]; __block id lastValue; __block BOOL hasValue = NO; RACSerialDisposable *samplerDisposable = [[RACSerialDisposable alloc] init]; RACDisposable *sourceDisposable = [self subscribeNext:^(id x) { [lock lock]; hasValue = YES; lastValue = x; [lock unlock]; } error:^(NSError *error) { [samplerDisposable dispose]; [subscriber sendError:error]; } completed:^{ [samplerDisposable dispose]; [subscriber sendCompleted]; }]; samplerDisposable.disposable = [sampler subscribeNext:^(id _) { BOOL shouldSend = NO; id value; [lock lock]; shouldSend = hasValue; value = lastValue; [lock unlock]; if (shouldSend) { [subscriber sendNext:value]; } } error:^(NSError *error) { [sourceDisposable dispose]; [subscriber sendError:error]; } completed:^{ [sourceDisposable dispose]; [subscriber sendCompleted]; }]; return [RACDisposable disposableWithBlock:^{ [samplerDisposable dispose]; [sourceDisposable dispose]; }]; }] setNameWithFormat:@"[%@] -sample: %@", self.name, sampler]; } - (RACSignal *)ignoreValues { return [[self filter:^(id _) { return NO; }] setNameWithFormat:@"[%@] -ignoreValues", self.name]; } - (RACSignal *)materialize { return [[RACSignal createSignal:^(id subscriber) { return [self subscribeNext:^(id x) { [subscriber sendNext:[RACEvent eventWithValue:x]]; } error:^(NSError *error) { [subscriber sendNext:[RACEvent eventWithError:error]]; [subscriber sendCompleted]; } completed:^{ [subscriber sendNext:RACEvent.completedEvent]; [subscriber sendCompleted]; }]; }] setNameWithFormat:@"[%@] -materialize", self.name]; } - (RACSignal *)dematerialize { return [[self bind:^{ return ^(RACEvent *event, BOOL *stop) { switch (event.eventType) { case RACEventTypeCompleted: *stop = YES; return [RACSignal empty]; case RACEventTypeError: *stop = YES; return [RACSignal error:event.error]; case RACEventTypeNext: return [RACSignal return:event.value]; } }; }] setNameWithFormat:@"[%@] -dematerialize", self.name]; } - (RACSignal *)not { return [[self map:^(NSNumber *value) { NSCAssert([value isKindOfClass:NSNumber.class], @"-not must only be used on a signal of NSNumbers. Instead, got: %@", value); return @(!value.boolValue); }] setNameWithFormat:@"[%@] -not", self.name]; } - (RACSignal *)and { return [[self map:^(RACTuple *tuple) { NSCAssert([tuple isKindOfClass:RACTuple.class], @"-and must only be used on a signal of RACTuples of NSNumbers. Instead, received: %@", tuple); NSCAssert(tuple.count > 0, @"-and must only be used on a signal of RACTuples of NSNumbers, with at least 1 value in the tuple"); return @([tuple.rac_sequence all:^(NSNumber *number) { NSCAssert([number isKindOfClass:NSNumber.class], @"-and must only be used on a signal of RACTuples of NSNumbers. Instead, tuple contains a non-NSNumber value: %@", tuple); return number.boolValue; }]); }] setNameWithFormat:@"[%@] -and", self.name]; } - (RACSignal *)or { return [[self map:^(RACTuple *tuple) { NSCAssert([tuple isKindOfClass:RACTuple.class], @"-or must only be used on a signal of RACTuples of NSNumbers. Instead, received: %@", tuple); NSCAssert(tuple.count > 0, @"-or must only be used on a signal of RACTuples of NSNumbers, with at least 1 value in the tuple"); return @([tuple.rac_sequence any:^(NSNumber *number) { NSCAssert([number isKindOfClass:NSNumber.class], @"-or must only be used on a signal of RACTuples of NSNumbers. Instead, tuple contains a non-NSNumber value: %@", tuple); return number.boolValue; }]); }] setNameWithFormat:@"[%@] -or", self.name]; } - (RACSignal *)reduceApply { return [[self map:^(RACTuple *tuple) { NSCAssert([tuple isKindOfClass:RACTuple.class], @"-reduceApply must only be used on a signal of RACTuples. Instead, received: %@", tuple); NSCAssert(tuple.count > 1, @"-reduceApply must only be used on a signal of RACTuples, with at least a block in tuple[0] and its first argument in tuple[1]"); // We can't use -array, because we need to preserve RACTupleNil NSMutableArray *tupleArray = [NSMutableArray arrayWithCapacity:tuple.count]; for (id val in tuple) { [tupleArray addObject:val]; } RACTuple *arguments = [RACTuple tupleWithObjectsFromArray:[tupleArray subarrayWithRange:NSMakeRange(1, tupleArray.count - 1)]]; return [RACBlockTrampoline invokeBlock:tuple[0] withArguments:arguments]; }] setNameWithFormat:@"[%@] -reduceApply", self.name]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSignal.h ================================================ // // RACSignal.h // ReactiveCocoa // // Created by Josh Abernathy on 3/1/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import #import "RACStream.h" @class RACDisposable; @class RACScheduler; @class RACSubject; @protocol RACSubscriber; @interface RACSignal : RACStream /// Creates a new signal. This is the preferred way to create a new signal /// operation or behavior. /// /// Events can be sent to new subscribers immediately in the `didSubscribe` /// block, but the subscriber will not be able to dispose of the signal until /// a RACDisposable is returned from `didSubscribe`. In the case of infinite /// signals, this won't _ever_ happen if events are sent immediately. /// /// To ensure that the signal is disposable, events can be scheduled on the /// +[RACScheduler currentScheduler] (so that they're deferred, not sent /// immediately), or they can be sent in the background. The RACDisposable /// returned by the `didSubscribe` block should cancel any such scheduling or /// asynchronous work. /// /// didSubscribe - Called when the signal is subscribed to. The new subscriber is /// passed in. You can then manually control the by /// sending it -sendNext:, -sendError:, and -sendCompleted, /// as defined by the operation you're implementing. This block /// should return a RACDisposable which cancels any ongoing work /// triggered by the subscription, and cleans up any resources or /// disposables created as part of it. When the disposable is /// disposed of, the signal must not send any more events to the /// `subscriber`. If no cleanup is necessary, return nil. /// /// **Note:** The `didSubscribe` block is called every time a new subscriber /// subscribes. Any side effects within the block will thus execute once for each /// subscription, not necessarily on one thread, and possibly even /// simultaneously! + (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe; /// Returns a signal that immediately sends the given error. + (RACSignal *)error:(NSError *)error; /// Returns a signal that never completes. + (RACSignal *)never; /// Immediately schedules the given block on the given scheduler. The block is /// given a subscriber to which it can send events. /// /// scheduler - The scheduler on which `block` will be scheduled and results /// delivered. Cannot be nil. /// block - The block to invoke. Cannot be NULL. /// /// Returns a signal which will send all events sent on the subscriber given to /// `block`. All events will be sent on `scheduler` and it will replay any missed /// events to new subscribers. + (RACSignal *)startEagerlyWithScheduler:(RACScheduler *)scheduler block:(void (^)(id subscriber))block; /// Invokes the given block only on the first subscription. The block is given a /// subscriber to which it can send events. /// /// Note that disposing of the subscription to the returned signal will *not* /// dispose of the underlying subscription. If you need that behavior, see /// -[RACMulticastConnection autoconnect]. The underlying subscription will never /// be disposed of. Because of this, `block` should never return an infinite /// signal since there would be no way of ending it. /// /// scheduler - The scheduler on which the block should be scheduled. Note that /// if given +[RACScheduler immediateScheduler], the block will be /// invoked synchronously on the first subscription. Cannot be nil. /// block - The block to invoke on the first subscription. Cannot be NULL. /// /// Returns a signal which will pass through the events sent to the subscriber /// given to `block` and replay any missed events to new subscribers. + (RACSignal *)startLazilyWithScheduler:(RACScheduler *)scheduler block:(void (^)(id subscriber))block; @end @interface RACSignal (RACStream) /// Returns a signal that immediately sends the given value and then completes. + (RACSignal *)return:(id)value; /// Returns a signal that immediately completes. + (RACSignal *)empty; /// Subscribes to `signal` when the source signal completes. - (RACSignal *)concat:(RACSignal *)signal; /// Zips the values in the receiver with those of the given signal to create /// RACTuples. /// /// The first `next` of each stream will be combined, then the second `next`, and /// so forth, until either signal completes or errors. /// /// signal - The signal to zip with. This must not be `nil`. /// /// Returns a new signal of RACTuples, representing the combined values of the /// two signals. Any error from one of the original signals will be forwarded on /// the returned signal. - (RACSignal *)zipWith:(RACSignal *)signal; @end @interface RACSignal (Subscription) /// Subscribes `subscriber` to changes on the receiver. The receiver defines which /// events it actually sends and in what situations the events are sent. /// /// Subscription will always happen on a valid RACScheduler. If the /// +[RACScheduler currentScheduler] cannot be determined at the time of /// subscription (e.g., because the calling code is running on a GCD queue or /// NSOperationQueue), subscription will occur on a private background scheduler. /// On the main thread, subscriptions will always occur immediately, with a /// +[RACScheduler currentScheduler] of +[RACScheduler mainThreadScheduler]. /// /// This method must be overridden by any subclasses. /// /// Returns nil or a disposable. You can call -[RACDisposable dispose] if you /// need to end your subscription before it would "naturally" end, either by /// completing or erroring. Once the disposable has been disposed, the subscriber /// won't receive any more events from the subscription. - (RACDisposable *)subscribe:(id)subscriber; /// Convenience method to subscribe to the `next` event. /// /// This corresponds to `IObserver.OnNext` in Rx. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock; /// Convenience method to subscribe to the `next` and `completed` events. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock completed:(void (^)(void))completedBlock; /// Convenience method to subscribe to the `next`, `completed`, and `error` events. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock completed:(void (^)(void))completedBlock; /// Convenience method to subscribe to `error` events. /// /// This corresponds to the `IObserver.OnError` in Rx. - (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock; /// Convenience method to subscribe to `completed` events. /// /// This corresponds to the `IObserver.OnCompleted` in Rx. - (RACDisposable *)subscribeCompleted:(void (^)(void))completedBlock; /// Convenience method to subscribe to `next` and `error` events. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock; /// Convenience method to subscribe to `error` and `completed` events. - (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock completed:(void (^)(void))completedBlock; @end /// Additional methods to assist with debugging. @interface RACSignal (Debugging) /// Logs all events that the receiver sends. - (RACSignal *)logAll; /// Logs each `next` that the receiver sends. - (RACSignal *)logNext; /// Logs any error that the receiver sends. - (RACSignal *)logError; /// Logs any `completed` event that the receiver sends. - (RACSignal *)logCompleted; @end /// Additional methods to assist with unit testing. /// /// **These methods should never ship in production code.** @interface RACSignal (Testing) /// Spins the main run loop for a short while, waiting for the receiver to send a `next`. /// /// **Because this method executes the run loop recursively, it should only be used /// on the main thread, and only from a unit test.** /// /// defaultValue - Returned if the receiver completes or errors before sending /// a `next`, or if the method times out. This argument may be /// nil. /// success - If not NULL, set to whether the receiver completed /// successfully. /// error - If not NULL, set to any error that occurred. /// /// Returns the first value received, or `defaultValue` if no value is received /// before the signal finishes or the method times out. - (id)asynchronousFirstOrDefault:(id)defaultValue success:(BOOL *)success error:(NSError **)error; /// Spins the main run loop for a short while, waiting for the receiver to complete. /// /// **Because this method executes the run loop recursively, it should only be used /// on the main thread, and only from a unit test.** /// /// error - If not NULL, set to any error that occurs. /// /// Returns whether the signal completed successfully before timing out. If NO, /// `error` will be set to any error that occurred. - (BOOL)asynchronouslyWaitUntilCompleted:(NSError **)error; @end @interface RACSignal (Unavailable) + (RACSignal *)start:(id (^)(BOOL *success, NSError **error))block __attribute__((unavailable("Use +startEagerlyWithScheduler:block: instead"))); + (RACSignal *)startWithScheduler:(RACScheduler *)scheduler subjectBlock:(void (^)(RACSubject *subject))block __attribute__((unavailable("Use +startEagerlyWithScheduler:block: instead"))); + (RACSignal *)startWithScheduler:(RACScheduler *)scheduler block:(id (^)(BOOL *success, NSError **error))block __attribute__((unavailable("Use +startEagerlyWithScheduler:block: instead"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSignal.m ================================================ // // RACSignal.m // ReactiveCocoa // // Created by Josh Abernathy on 3/15/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSignal.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACDynamicSignal.h" #import "RACEmptySignal.h" #import "RACErrorSignal.h" #import "RACMulticastConnection.h" #import "RACReplaySubject.h" #import "RACReturnSignal.h" #import "RACScheduler.h" #import "RACSerialDisposable.h" #import "RACSignal+Operations.h" #import "RACSubject.h" #import "RACSubscriber+Private.h" #import "RACTuple.h" @implementation RACSignal #pragma mark Lifecycle + (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe { return [RACDynamicSignal createSignal:didSubscribe]; } + (RACSignal *)error:(NSError *)error { return [RACErrorSignal error:error]; } + (RACSignal *)never { return [[self createSignal:^ RACDisposable * (id subscriber) { return nil; }] setNameWithFormat:@"+never"]; } + (RACSignal *)startEagerlyWithScheduler:(RACScheduler *)scheduler block:(void (^)(id subscriber))block { NSCParameterAssert(scheduler != nil); NSCParameterAssert(block != NULL); RACSignal *signal = [self startLazilyWithScheduler:scheduler block:block]; // Subscribe to force the lazy signal to call its block. [[signal publish] connect]; return [signal setNameWithFormat:@"+startEagerlyWithScheduler: %@ block:", scheduler]; } + (RACSignal *)startLazilyWithScheduler:(RACScheduler *)scheduler block:(void (^)(id subscriber))block { NSCParameterAssert(scheduler != nil); NSCParameterAssert(block != NULL); RACMulticastConnection *connection = [[RACSignal createSignal:^ id (id subscriber) { block(subscriber); return nil; }] multicast:[RACReplaySubject subject]]; return [[[RACSignal createSignal:^ id (id subscriber) { [connection.signal subscribe:subscriber]; [connection connect]; return nil; }] subscribeOn:scheduler] setNameWithFormat:@"+startLazilyWithScheduler: %@ block:", scheduler]; } #pragma mark NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p> name: %@", self.class, self, self.name]; } @end @implementation RACSignal (RACStream) + (RACSignal *)empty { return [RACEmptySignal empty]; } + (RACSignal *)return:(id)value { return [RACReturnSignal return:value]; } - (RACSignal *)bind:(RACStreamBindBlock (^)(void))block { NSCParameterAssert(block != NULL); /* * -bind: should: * * 1. Subscribe to the original signal of values. * 2. Any time the original signal sends a value, transform it using the binding block. * 3. If the binding block returns a signal, subscribe to it, and pass all of its values through to the subscriber as they're received. * 4. If the binding block asks the bind to terminate, complete the _original_ signal. * 5. When _all_ signals complete, send completed to the subscriber. * * If any signal sends an error at any point, send that to the subscriber. */ return [[RACSignal createSignal:^(id subscriber) { RACStreamBindBlock bindingBlock = block(); NSMutableArray *signals = [NSMutableArray arrayWithObject:self]; RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable]; void (^completeSignal)(RACSignal *, RACDisposable *) = ^(RACSignal *signal, RACDisposable *finishedDisposable) { BOOL removeDisposable = NO; @synchronized (signals) { [signals removeObject:signal]; if (signals.count == 0) { [subscriber sendCompleted]; [compoundDisposable dispose]; } else { removeDisposable = YES; } } if (removeDisposable) [compoundDisposable removeDisposable:finishedDisposable]; }; void (^addSignal)(RACSignal *) = ^(RACSignal *signal) { @synchronized (signals) { [signals addObject:signal]; } RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init]; [compoundDisposable addDisposable:selfDisposable]; RACDisposable *disposable = [signal subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { [compoundDisposable dispose]; [subscriber sendError:error]; } completed:^{ @autoreleasepool { completeSignal(signal, selfDisposable); } }]; selfDisposable.disposable = disposable; }; @autoreleasepool { RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init]; [compoundDisposable addDisposable:selfDisposable]; RACDisposable *bindingDisposable = [self subscribeNext:^(id x) { // Manually check disposal to handle synchronous errors. if (compoundDisposable.disposed) return; BOOL stop = NO; id signal = bindingBlock(x, &stop); @autoreleasepool { if (signal != nil) addSignal(signal); if (signal == nil || stop) { [selfDisposable dispose]; completeSignal(self, selfDisposable); } } } error:^(NSError *error) { [compoundDisposable dispose]; [subscriber sendError:error]; } completed:^{ @autoreleasepool { completeSignal(self, selfDisposable); } }]; selfDisposable.disposable = bindingDisposable; } return compoundDisposable; }] setNameWithFormat:@"[%@] -bind:", self.name]; } - (RACSignal *)concat:(RACSignal *)signal { return [[RACSignal createSignal:^(id subscriber) { RACCompoundDisposable *compoundDisposable = [[RACCompoundDisposable alloc] init]; RACDisposable *sourceDisposable = [self subscribeNext:^(id x) { [subscriber sendNext:x]; } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ RACDisposable *concattedDisposable = [signal subscribe:subscriber]; [compoundDisposable addDisposable:concattedDisposable]; }]; [compoundDisposable addDisposable:sourceDisposable]; return compoundDisposable; }] setNameWithFormat:@"[%@] -concat: %@", self.name, signal]; } - (RACSignal *)zipWith:(RACSignal *)signal { NSCParameterAssert(signal != nil); return [[RACSignal createSignal:^(id subscriber) { __block BOOL selfCompleted = NO; NSMutableArray *selfValues = [NSMutableArray array]; __block BOOL otherCompleted = NO; NSMutableArray *otherValues = [NSMutableArray array]; void (^sendCompletedIfNecessary)(void) = ^{ @synchronized (selfValues) { BOOL selfEmpty = (selfCompleted && selfValues.count == 0); BOOL otherEmpty = (otherCompleted && otherValues.count == 0); if (selfEmpty || otherEmpty) [subscriber sendCompleted]; } }; void (^sendNext)(void) = ^{ @synchronized (selfValues) { if (selfValues.count == 0) return; if (otherValues.count == 0) return; RACTuple *tuple = RACTuplePack(selfValues[0], otherValues[0]); [selfValues removeObjectAtIndex:0]; [otherValues removeObjectAtIndex:0]; [subscriber sendNext:tuple]; sendCompletedIfNecessary(); } }; RACDisposable *selfDisposable = [self subscribeNext:^(id x) { @synchronized (selfValues) { [selfValues addObject:x ?: RACTupleNil.tupleNil]; sendNext(); } } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ @synchronized (selfValues) { selfCompleted = YES; sendCompletedIfNecessary(); } }]; RACDisposable *otherDisposable = [signal subscribeNext:^(id x) { @synchronized (selfValues) { [otherValues addObject:x ?: RACTupleNil.tupleNil]; sendNext(); } } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ @synchronized (selfValues) { otherCompleted = YES; sendCompletedIfNecessary(); } }]; return [RACDisposable disposableWithBlock:^{ [selfDisposable dispose]; [otherDisposable dispose]; }]; }] setNameWithFormat:@"[%@] -zipWith: %@", self.name, signal]; } @end @implementation RACSignal (Subscription) - (RACDisposable *)subscribe:(id)subscriber { NSCAssert(NO, @"This method must be overridden by subclasses"); return nil; } - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock { NSCParameterAssert(nextBlock != NULL); RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL]; return [self subscribe:o]; } - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock completed:(void (^)(void))completedBlock { NSCParameterAssert(nextBlock != NULL); NSCParameterAssert(completedBlock != NULL); RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:completedBlock]; return [self subscribe:o]; } - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock completed:(void (^)(void))completedBlock { NSCParameterAssert(nextBlock != NULL); NSCParameterAssert(errorBlock != NULL); NSCParameterAssert(completedBlock != NULL); RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:errorBlock completed:completedBlock]; return [self subscribe:o]; } - (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock { NSCParameterAssert(errorBlock != NULL); RACSubscriber *o = [RACSubscriber subscriberWithNext:NULL error:errorBlock completed:NULL]; return [self subscribe:o]; } - (RACDisposable *)subscribeCompleted:(void (^)(void))completedBlock { NSCParameterAssert(completedBlock != NULL); RACSubscriber *o = [RACSubscriber subscriberWithNext:NULL error:NULL completed:completedBlock]; return [self subscribe:o]; } - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock error:(void (^)(NSError *error))errorBlock { NSCParameterAssert(nextBlock != NULL); NSCParameterAssert(errorBlock != NULL); RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:errorBlock completed:NULL]; return [self subscribe:o]; } - (RACDisposable *)subscribeError:(void (^)(NSError *))errorBlock completed:(void (^)(void))completedBlock { NSCParameterAssert(completedBlock != NULL); NSCParameterAssert(errorBlock != NULL); RACSubscriber *o = [RACSubscriber subscriberWithNext:NULL error:errorBlock completed:completedBlock]; return [self subscribe:o]; } @end @implementation RACSignal (Debugging) - (RACSignal *)logAll { return [[[self logNext] logError] logCompleted]; } - (RACSignal *)logNext { return [[self doNext:^(id x) { NSLog(@"%@ next: %@", self, x); }] setNameWithFormat:@"%@", self.name]; } - (RACSignal *)logError { return [[self doError:^(NSError *error) { NSLog(@"%@ error: %@", self, error); }] setNameWithFormat:@"%@", self.name]; } - (RACSignal *)logCompleted { return [[self doCompleted:^{ NSLog(@"%@ completed", self); }] setNameWithFormat:@"%@", self.name]; } @end @implementation RACSignal (Testing) static const NSTimeInterval RACSignalAsynchronousWaitTimeout = 10; - (id)asynchronousFirstOrDefault:(id)defaultValue success:(BOOL *)success error:(NSError **)error { NSCAssert([NSThread isMainThread], @"%s should only be used from the main thread", __func__); __block id result = defaultValue; __block BOOL done = NO; // Ensures that we don't pass values across thread boundaries by reference. __block NSError *localError; __block BOOL localSuccess = YES; [[[[self take:1] timeout:RACSignalAsynchronousWaitTimeout onScheduler:[RACScheduler scheduler]] deliverOn:RACScheduler.mainThreadScheduler] subscribeNext:^(id x) { result = x; done = YES; } error:^(NSError *e) { if (!done) { localSuccess = NO; localError = e; done = YES; } } completed:^{ done = YES; }]; do { [NSRunLoop.mainRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; } while (!done); if (success != NULL) *success = localSuccess; if (error != NULL) *error = localError; return result; } - (BOOL)asynchronouslyWaitUntilCompleted:(NSError **)error { BOOL success = NO; [[self ignoreValues] asynchronousFirstOrDefault:nil success:&success error:error]; return success; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSignalProvider.d ================================================ provider RACSignal { probe next(char *signal, char *subscriber, char *valueDescription); probe completed(char *signal, char *subscriber); probe error(char *signal, char *subscriber, char *errorDescription); }; ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSignalSequence.h ================================================ // // RACSignalSequence.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-11-09. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSequence.h" @class RACSignal; // Private class that adapts a RACSignal to the RACSequence interface. @interface RACSignalSequence : RACSequence // Returns a sequence for enumerating over the given signal. + (RACSequence *)sequenceWithSignal:(RACSignal *)signal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSignalSequence.m ================================================ // // RACSignalSequence.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-11-09. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSignalSequence.h" #import "RACDisposable.h" #import "RACReplaySubject.h" #import "RACSignal+Operations.h" @interface RACSignalSequence () // Replays the signal given on initialization. @property (nonatomic, strong, readonly) RACReplaySubject *subject; @end @implementation RACSignalSequence #pragma mark Lifecycle + (RACSequence *)sequenceWithSignal:(RACSignal *)signal { RACSignalSequence *seq = [[self alloc] init]; RACReplaySubject *subject = [RACReplaySubject subject]; [signal subscribeNext:^(id value) { [subject sendNext:value]; } error:^(NSError *error) { [subject sendError:error]; } completed:^{ [subject sendCompleted]; }]; seq->_subject = subject; return seq; } #pragma mark RACSequence - (id)head { id value = [self.subject firstOrDefault:self]; if (value == self) { return nil; } else { return value ?: NSNull.null; } } - (RACSequence *)tail { RACSequence *sequence = [self.class sequenceWithSignal:[self.subject skip:1]]; sequence.name = self.name; return sequence; } - (NSArray *)array { return self.subject.toArray; } #pragma mark NSObject - (NSString *)description { // Synchronously accumulate the values that have been sent so far. NSMutableArray *values = [NSMutableArray array]; RACDisposable *disposable = [self.subject subscribeNext:^(id value) { @synchronized (values) { [values addObject:value ?: NSNull.null]; } }]; [disposable dispose]; return [NSString stringWithFormat:@"<%@: %p>{ name = %@, values = %@ … }", self.class, self, self.name, values]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACStream+Private.h ================================================ // // RACStream+Private.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-07-22. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACStream.h" @interface RACStream () // Combines a list of streams using the logic of the given block. // // streams - The streams to combine. // block - An operator that combines two streams and returns a new one. The // returned stream should contain 2-tuples of the streams' combined // values. // // Returns a combined stream. + (instancetype)join:(id)streams block:(RACStream * (^)(id, id))block; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACStream.h ================================================ // // RACStream.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-31. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACStream; /// A block which accepts a value from a RACStream and returns a new instance /// of the same stream class. /// /// Setting `stop` to `YES` will cause the bind to terminate after the returned /// value. Returning `nil` will result in immediate termination. typedef RACStream * (^RACStreamBindBlock)(id value, BOOL *stop); /// An abstract class representing any stream of values. /// /// This class represents a monad, upon which many stream-based operations can /// be built. /// /// When subclassing RACStream, only the methods in the main @interface body need /// to be overridden. @interface RACStream : NSObject /// Returns an empty stream. + (instancetype)empty; /// Lifts `value` into the stream monad. /// /// Returns a stream containing only the given value. + (instancetype)return:(id)value; /// Lazily binds a block to the values in the receiver. /// /// This should only be used if you need to terminate the bind early, or close /// over some state. -flattenMap: is more appropriate for all other cases. /// /// block - A block returning a RACStreamBindBlock. This block will be invoked /// each time the bound stream is re-evaluated. This block must not be /// nil or return nil. /// /// Returns a new stream which represents the combined result of all lazy /// applications of `block`. - (instancetype)bind:(RACStreamBindBlock (^)(void))block; /// Appends the values of `stream` to the values in the receiver. /// /// stream - A stream to concatenate. This must be an instance of the same /// concrete class as the receiver, and should not be `nil`. /// /// Returns a new stream representing the receiver followed by `stream`. - (instancetype)concat:(RACStream *)stream; /// Zips the values in the receiver with those of the given stream to create /// RACTuples. /// /// The first value of each stream will be combined, then the second value, and /// so forth, until at least one of the streams is exhausted. /// /// stream - The stream to zip with. This must be an instance of the same /// concrete class as the receiver, and should not be `nil`. /// /// Returns a new stream of RACTuples, representing the zipped values of the /// two streams. - (instancetype)zipWith:(RACStream *)stream; @end /// This extension contains functionality to support naming streams for /// debugging. /// /// Subclasses do not need to override the methods here. @interface RACStream () /// The name of the stream. This is for debugging/human purposes only. @property (copy) NSString *name; /// Sets the name of the receiver to the given format string. /// /// This is for debugging purposes only, and won't do anything unless the /// RAC_DEBUG_SIGNAL_NAMES environment variable is set. /// /// Returns the receiver, for easy method chaining. - (instancetype)setNameWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); @end /// Operations built on the RACStream primitives. /// /// These methods do not need to be overridden, although subclasses may /// occasionally gain better performance from doing so. @interface RACStream (Operations) /// Maps `block` across the values in the receiver and flattens the result. /// /// Note that operators applied _after_ -flattenMap: behave differently from /// operators _within_ -flattenMap:. See the Examples section below. /// /// This corresponds to the `SelectMany` method in Rx. /// /// block - A block which accepts the values in the receiver and returns a new /// instance of the receiver's class. Returning `nil` from this block is /// equivalent to returning an empty signal. /// /// Examples /// /// [signal flattenMap:^(id x) { /// // Logs each time a returned signal completes. /// return [[RACSignal return:x] logCompleted]; /// }]; /// /// [[signal /// flattenMap:^(id x) { /// return [RACSignal return:x]; /// }] /// // Logs only once, when all of the signals complete. /// logCompleted]; /// /// Returns a new stream which represents the combined streams resulting from /// mapping `block`. - (instancetype)flattenMap:(RACStream * (^)(id value))block; /// Flattens a stream of streams. /// /// This corresponds to the `Merge` method in Rx. /// /// Returns a stream consisting of the combined streams obtained from the /// receiver. - (instancetype)flatten; /// Maps `block` across the values in the receiver. /// /// This corresponds to the `Select` method in Rx. /// /// Returns a new stream with the mapped values. - (instancetype)map:(id (^)(id value))block; /// Replaces each value in the receiver with the given object. /// /// Returns a new stream which includes the given object once for each value in /// the receiver. - (instancetype)mapReplace:(id)object; /// Filters out values in the receiver that don't pass the given test. /// /// This corresponds to the `Where` method in Rx. /// /// Returns a new stream with only those values that passed. - (instancetype)filter:(BOOL (^)(id value))block; /// Filters out values in the receiver that equal (via -isEqual:) the provided value. /// /// value - The value can be `nil`, in which case it ignores `nil` values. /// /// Returns a new stream containing only the values which did not compare equal /// to `value`. - (instancetype)ignore:(id)value; /// Unpacks each RACTuple in the receiver and maps the values to a new value. /// /// reduceBlock - The block which reduces each RACTuple's values into one value. /// It must take as many arguments as the number of tuple elements /// to process. Each argument will be an object argument. The /// return value must be an object. This argument cannot be nil. /// /// Returns a new stream of reduced tuple values. - (instancetype)reduceEach:(id (^)())reduceBlock; /// Returns a stream consisting of `value`, followed by the values in the /// receiver. - (instancetype)startWith:(id)value; /// Skips the first `skipCount` values in the receiver. /// /// Returns the receiver after skipping the first `skipCount` values. If /// `skipCount` is greater than the number of values in the stream, an empty /// stream is returned. - (instancetype)skip:(NSUInteger)skipCount; /// Returns a stream of the first `count` values in the receiver. If `count` is /// greater than or equal to the number of values in the stream, a stream /// equivalent to the receiver is returned. - (instancetype)take:(NSUInteger)count; /// Zips the values in the given streams to create RACTuples. /// /// The first value of each stream will be combined, then the second value, and /// so forth, until at least one of the streams is exhausted. /// /// streams - The streams to combine. These must all be instances of the same /// concrete class implementing the protocol. If this collection is /// empty, the returned stream will be empty. /// /// Returns a new stream containing RACTuples of the zipped values from the /// streams. + (instancetype)zip:(id)streams; /// Zips streams using +zip:, then reduces the resulting tuples into a single /// value using -reduceEach: /// /// streams - The streams to combine. These must all be instances of the /// same concrete class implementing the protocol. If this /// collection is empty, the returned stream will be empty. /// reduceBlock - The block which reduces the values from all the streams /// into one value. It must take as many arguments as the /// number of streams given. Each argument will be an object /// argument. The return value must be an object. This argument /// must not be nil. /// /// Example: /// /// [RACStream zip:@[ stringSignal, intSignal ] reduce:^(NSString *string, NSNumber *number) { /// return [NSString stringWithFormat:@"%@: %@", string, number]; /// }]; /// /// Returns a new stream containing the results from each invocation of /// `reduceBlock`. + (instancetype)zip:(id)streams reduce:(id (^)())reduceBlock; /// Returns a stream obtained by concatenating `streams` in order. + (instancetype)concat:(id)streams; /// Combines values in the receiver from left to right using the given block. /// /// The algorithm proceeds as follows: /// /// 1. `startingValue` is passed into the block as the `running` value, and the /// first element of the receiver is passed into the block as the `next` value. /// 2. The result of the invocation is added to the returned stream. /// 3. The result of the invocation (`running`) and the next element of the /// receiver (`next`) is passed into `block`. /// 4. Steps 2 and 3 are repeated until all values have been processed. /// /// startingValue - The value to be combined with the first element of the /// receiver. This value may be `nil`. /// reduceBlock - The block that describes how to combine values of the /// receiver. If the receiver is empty, this block will never be /// invoked. Cannot be nil. /// /// Examples /// /// RACSequence *numbers = @[ @1, @2, @3, @4 ].rac_sequence; /// /// // Contains 1, 3, 6, 10 /// RACSequence *sums = [numbers scanWithStart:@0 reduce:^(NSNumber *sum, NSNumber *next) { /// return @(sum.integerValue + next.integerValue); /// }]; /// /// Returns a new stream that consists of each application of `reduceBlock`. If the /// receiver is empty, an empty stream is returned. - (instancetype)scanWithStart:(id)startingValue reduce:(id (^)(id running, id next))reduceBlock; /// Combines values in the receiver from left to right using the given block /// which also takes zero-based index of the values. /// /// startingValue - The value to be combined with the first element of the /// receiver. This value may be `nil`. /// reduceBlock - The block that describes how to combine values of the /// receiver. This block takes zero-based index value as the last /// parameter. If the receiver is empty, this block will never /// be invoked. Cannot be nil. /// /// Returns a new stream that consists of each application of `reduceBlock`. If the /// receiver is empty, an empty stream is returned. - (instancetype)scanWithStart:(id)startingValue reduceWithIndex:(id (^)(id running, id next, NSUInteger index))reduceBlock; /// Combines each previous and current value into one object. /// /// This method is similar to -scanWithStart:reduce:, but only ever operates on /// the previous and current values (instead of the whole stream), and does not /// pass the return value of `reduceBlock` into the next invocation of it. /// /// start - The value passed into `reduceBlock` as `previous` for the /// first value. /// reduceBlock - The block that combines the previous value and the current /// value to create the reduced value. Cannot be nil. /// /// Examples /// /// RACSequence *numbers = @[ @1, @2, @3, @4 ].rac_sequence; /// /// // Contains 1, 3, 5, 7 /// RACSequence *sums = [numbers combinePreviousWithStart:@0 reduce:^(NSNumber *previous, NSNumber *next) { /// return @(previous.integerValue + next.integerValue); /// }]; /// /// Returns a new stream consisting of the return values from each application of /// `reduceBlock`. - (instancetype)combinePreviousWithStart:(id)start reduce:(id (^)(id previous, id current))reduceBlock; /// Takes values until the given block returns `YES`. /// /// Returns a stream of the initial values in the receiver that fail `predicate`. /// If `predicate` never returns `YES`, a stream equivalent to the receiver is /// returned. - (instancetype)takeUntilBlock:(BOOL (^)(id x))predicate; /// Takes values until the given block returns `NO`. /// /// Returns a stream of the initial values in the receiver that pass `predicate`. /// If `predicate` never returns `NO`, a stream equivalent to the receiver is /// returned. - (instancetype)takeWhileBlock:(BOOL (^)(id x))predicate; /// Skips values until the given block returns `YES`. /// /// Returns a stream containing the values of the receiver that follow any /// initial values failing `predicate`. If `predicate` never returns `YES`, /// an empty stream is returned. - (instancetype)skipUntilBlock:(BOOL (^)(id x))predicate; /// Skips values until the given block returns `NO`. /// /// Returns a stream containing the values of the receiver that follow any /// initial values passing `predicate`. If `predicate` never returns `NO`, an /// empty stream is returned. - (instancetype)skipWhileBlock:(BOOL (^)(id x))predicate; /// Returns a stream of values for which -isEqual: returns NO when compared to the /// previous value. - (instancetype)distinctUntilChanged; @end @interface RACStream (Unavailable) - (instancetype)sequenceMany:(RACStream * (^)(void))block __attribute__((unavailable("Use -flattenMap: instead"))); - (instancetype)scanWithStart:(id)startingValue combine:(id (^)(id running, id next))block __attribute__((unavailable("Renamed to -scanWithStart:reduce:"))); - (instancetype)mapPreviousWithStart:(id)start reduce:(id (^)(id previous, id current))combineBlock __attribute__((unavailable("Renamed to -combinePreviousWithStart:reduce:"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACStream.m ================================================ // // RACStream.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-31. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACStream.h" #import "NSObject+RACDescription.h" #import "RACBlockTrampoline.h" #import "RACTuple.h" @implementation RACStream #pragma mark Lifecycle - (id)init { self = [super init]; if (self == nil) return nil; self.name = @""; return self; } #pragma mark Abstract methods + (instancetype)empty { return nil; } - (instancetype)bind:(RACStreamBindBlock (^)(void))block { return nil; } + (instancetype)return:(id)value { return nil; } - (instancetype)concat:(RACStream *)stream { return nil; } - (instancetype)zipWith:(RACStream *)stream { return nil; } #pragma mark Naming - (instancetype)setNameWithFormat:(NSString *)format, ... { if (getenv("RAC_DEBUG_SIGNAL_NAMES") == NULL) return self; NSCParameterAssert(format != nil); va_list args; va_start(args, format); NSString *str = [[NSString alloc] initWithFormat:format arguments:args]; va_end(args); self.name = str; return self; } @end @implementation RACStream (Operations) - (instancetype)flattenMap:(RACStream * (^)(id value))block { Class class = self.class; return [[self bind:^{ return ^(id value, BOOL *stop) { id stream = block(value) ?: [class empty]; NSCAssert([stream isKindOfClass:RACStream.class], @"Value returned from -flattenMap: is not a stream: %@", stream); return stream; }; }] setNameWithFormat:@"[%@] -flattenMap:", self.name]; } - (instancetype)flatten { __weak RACStream *stream __attribute__((unused)) = self; return [[self flattenMap:^(id value) { return value; }] setNameWithFormat:@"[%@] -flatten", self.name]; } - (instancetype)map:(id (^)(id value))block { NSCParameterAssert(block != nil); Class class = self.class; return [[self flattenMap:^(id value) { return [class return:block(value)]; }] setNameWithFormat:@"[%@] -map:", self.name]; } - (instancetype)mapReplace:(id)object { return [[self map:^(id _) { return object; }] setNameWithFormat:@"[%@] -mapReplace: %@", self.name, RACDescription(object)]; } - (instancetype)combinePreviousWithStart:(id)start reduce:(id (^)(id previous, id next))reduceBlock { NSCParameterAssert(reduceBlock != NULL); return [[[self scanWithStart:RACTuplePack(start) reduce:^(RACTuple *previousTuple, id next) { id value = reduceBlock(previousTuple[0], next); return RACTuplePack(next, value); }] map:^(RACTuple *tuple) { return tuple[1]; }] setNameWithFormat:@"[%@] -combinePreviousWithStart: %@ reduce:", self.name, RACDescription(start)]; } - (instancetype)filter:(BOOL (^)(id value))block { NSCParameterAssert(block != nil); Class class = self.class; return [[self flattenMap:^ id (id value) { if (block(value)) { return [class return:value]; } else { return class.empty; } }] setNameWithFormat:@"[%@] -filter:", self.name]; } - (instancetype)ignore:(id)value { return [[self filter:^ BOOL (id innerValue) { return innerValue != value && ![innerValue isEqual:value]; }] setNameWithFormat:@"[%@] -ignore: %@", self.name, RACDescription(value)]; } - (instancetype)reduceEach:(id (^)())reduceBlock { NSCParameterAssert(reduceBlock != nil); __weak RACStream *stream __attribute__((unused)) = self; return [[self map:^(RACTuple *t) { NSCAssert([t isKindOfClass:RACTuple.class], @"Value from stream %@ is not a tuple: %@", stream, t); return [RACBlockTrampoline invokeBlock:reduceBlock withArguments:t]; }] setNameWithFormat:@"[%@] -reduceEach:", self.name]; } - (instancetype)startWith:(id)value { return [[[self.class return:value] concat:self] setNameWithFormat:@"[%@] -startWith: %@", self.name, RACDescription(value)]; } - (instancetype)skip:(NSUInteger)skipCount { Class class = self.class; return [[self bind:^{ __block NSUInteger skipped = 0; return ^(id value, BOOL *stop) { if (skipped >= skipCount) return [class return:value]; skipped++; return class.empty; }; }] setNameWithFormat:@"[%@] -skip: %lu", self.name, (unsigned long)skipCount]; } - (instancetype)take:(NSUInteger)count { Class class = self.class; if (count == 0) return class.empty; return [[self bind:^{ __block NSUInteger taken = 0; return ^ id (id value, BOOL *stop) { if (taken < count) { ++taken; if (taken == count) *stop = YES; return [class return:value]; } else { return nil; } }; }] setNameWithFormat:@"[%@] -take: %lu", self.name, (unsigned long)count]; } + (instancetype)join:(id)streams block:(RACStream * (^)(id, id))block { RACStream *current = nil; // Creates streams of successively larger tuples by combining the input // streams one-by-one. for (RACStream *stream in streams) { // For the first stream, just wrap its values in a RACTuple. That way, // if only one stream is given, the result is still a stream of tuples. if (current == nil) { current = [stream map:^(id x) { return RACTuplePack(x); }]; continue; } current = block(current, stream); } if (current == nil) return [self empty]; return [current map:^(RACTuple *xs) { // Right now, each value is contained in its own tuple, sorta like: // // (((1), 2), 3) // // We need to unwrap all the layers and create a tuple out of the result. NSMutableArray *values = [[NSMutableArray alloc] init]; while (xs != nil) { [values insertObject:xs.last ?: RACTupleNil.tupleNil atIndex:0]; xs = (xs.count > 1 ? xs.first : nil); } return [RACTuple tupleWithObjectsFromArray:values]; }]; } + (instancetype)zip:(id)streams { return [[self join:streams block:^(RACStream *left, RACStream *right) { return [left zipWith:right]; }] setNameWithFormat:@"+zip: %@", streams]; } + (instancetype)zip:(id)streams reduce:(id (^)())reduceBlock { NSCParameterAssert(reduceBlock != nil); RACStream *result = [self zip:streams]; // Although we assert this condition above, older versions of this method // supported this argument being nil. Avoid crashing Release builds of // apps that depended on that. if (reduceBlock != nil) result = [result reduceEach:reduceBlock]; return [result setNameWithFormat:@"+zip: %@ reduce:", streams]; } + (instancetype)concat:(id)streams { RACStream *result = self.empty; for (RACStream *stream in streams) { result = [result concat:stream]; } return [result setNameWithFormat:@"+concat: %@", streams]; } - (instancetype)scanWithStart:(id)startingValue reduce:(id (^)(id running, id next))reduceBlock { NSCParameterAssert(reduceBlock != nil); return [[self scanWithStart:startingValue reduceWithIndex:^(id running, id next, NSUInteger index) { return reduceBlock(running, next); }] setNameWithFormat:@"[%@] -scanWithStart: %@ reduce:", self.name, RACDescription(startingValue)]; } - (instancetype)scanWithStart:(id)startingValue reduceWithIndex:(id (^)(id, id, NSUInteger))reduceBlock { NSCParameterAssert(reduceBlock != nil); Class class = self.class; return [[self bind:^{ __block id running = startingValue; __block NSUInteger index = 0; return ^(id value, BOOL *stop) { running = reduceBlock(running, value, index++); return [class return:running]; }; }] setNameWithFormat:@"[%@] -scanWithStart: %@ reduceWithIndex:", self.name, RACDescription(startingValue)]; } - (instancetype)takeUntilBlock:(BOOL (^)(id x))predicate { NSCParameterAssert(predicate != nil); Class class = self.class; return [[self bind:^{ return ^ id (id value, BOOL *stop) { if (predicate(value)) return nil; return [class return:value]; }; }] setNameWithFormat:@"[%@] -takeUntilBlock:", self.name]; } - (instancetype)takeWhileBlock:(BOOL (^)(id x))predicate { NSCParameterAssert(predicate != nil); return [[self takeUntilBlock:^ BOOL (id x) { return !predicate(x); }] setNameWithFormat:@"[%@] -takeWhileBlock:", self.name]; } - (instancetype)skipUntilBlock:(BOOL (^)(id x))predicate { NSCParameterAssert(predicate != nil); Class class = self.class; return [[self bind:^{ __block BOOL skipping = YES; return ^ id (id value, BOOL *stop) { if (skipping) { if (predicate(value)) { skipping = NO; } else { return class.empty; } } return [class return:value]; }; }] setNameWithFormat:@"[%@] -skipUntilBlock:", self.name]; } - (instancetype)skipWhileBlock:(BOOL (^)(id x))predicate { NSCParameterAssert(predicate != nil); return [[self skipUntilBlock:^ BOOL (id x) { return !predicate(x); }] setNameWithFormat:@"[%@] -skipWhileBlock:", self.name]; } - (instancetype)distinctUntilChanged { Class class = self.class; return [[self bind:^{ __block id lastValue = nil; __block BOOL initial = YES; return ^(id x, BOOL *stop) { if (!initial && (lastValue == x || [x isEqual:lastValue])) return [class empty]; initial = NO; lastValue = x; return [class return:x]; }; }] setNameWithFormat:@"[%@] -distinctUntilChanged", self.name]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACStringSequence.h ================================================ // // RACStringSequence.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACSequence.h" // Private class that adapts a string to the RACSequence interface. @interface RACStringSequence : RACSequence // Returns a sequence for enumerating over the given string, starting from the // given character offset. The string will be copied to prevent mutation. + (RACSequence *)sequenceWithString:(NSString *)string offset:(NSUInteger)offset; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACStringSequence.m ================================================ // // RACStringSequence.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2012-10-29. // Copyright (c) 2012 GitHub. All rights reserved. // #import "RACStringSequence.h" @interface RACStringSequence () // The string being sequenced. @property (nonatomic, copy, readonly) NSString *string; // The index in the string from which the sequence starts. @property (nonatomic, assign, readonly) NSUInteger offset; @end @implementation RACStringSequence #pragma mark Lifecycle + (RACSequence *)sequenceWithString:(NSString *)string offset:(NSUInteger)offset { NSCParameterAssert(offset <= string.length); if (offset == string.length) return self.empty; RACStringSequence *seq = [[self alloc] init]; seq->_string = [string copy]; seq->_offset = offset; return seq; } #pragma mark RACSequence - (id)head { return [self.string substringWithRange:NSMakeRange(self.offset, 1)]; } - (RACSequence *)tail { RACSequence *sequence = [self.class sequenceWithString:self.string offset:self.offset + 1]; sequence.name = self.name; return sequence; } - (NSArray *)array { NSUInteger substringLength = self.string.length - self.offset; NSMutableArray *array = [NSMutableArray arrayWithCapacity:substringLength]; [self.string enumerateSubstringsInRange:NSMakeRange(self.offset, substringLength) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { [array addObject:substring]; }]; return [array copy]; } #pragma mark NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p>{ name = %@, string = %@ }", self.class, self, self.name, [self.string substringFromIndex:self.offset]]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubject.h ================================================ // // RACSubject.h // ReactiveCocoa // // Created by Josh Abernathy on 3/9/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSignal.h" #import "RACSubscriber.h" /// A subject can be thought of as a signal that you can manually control by /// sending next, completed, and error. /// /// They're most helpful in bridging the non-RAC world to RAC, since they let you /// manually control the sending of events. @interface RACSubject : RACSignal /// Returns a new subject. + (instancetype)subject; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubject.m ================================================ // // RACSubject.m // ReactiveCocoa // // Created by Josh Abernathy on 3/9/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSubject.h" #import "EXTScope.h" #import "RACCompoundDisposable.h" #import "RACPassthroughSubscriber.h" @interface RACSubject () // Contains all current subscribers to the receiver. // // This should only be used while synchronized on `self`. @property (nonatomic, strong, readonly) NSMutableArray *subscribers; // Contains all of the receiver's subscriptions to other signals. @property (nonatomic, strong, readonly) RACCompoundDisposable *disposable; // Enumerates over each of the receiver's `subscribers` and invokes `block` for // each. - (void)enumerateSubscribersUsingBlock:(void (^)(id subscriber))block; @end @implementation RACSubject #pragma mark Lifecycle + (instancetype)subject { return [[self alloc] init]; } - (id)init { self = [super init]; if (self == nil) return nil; _disposable = [RACCompoundDisposable compoundDisposable]; _subscribers = [[NSMutableArray alloc] initWithCapacity:1]; return self; } - (void)dealloc { [self.disposable dispose]; } #pragma mark Subscription - (RACDisposable *)subscribe:(id)subscriber { NSCParameterAssert(subscriber != nil); RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable]; subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable]; NSMutableArray *subscribers = self.subscribers; @synchronized (subscribers) { [subscribers addObject:subscriber]; } return [RACDisposable disposableWithBlock:^{ @synchronized (subscribers) { // Since newer subscribers are generally shorter-lived, search // starting from the end of the list. NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id obj, NSUInteger index, BOOL *stop) { return obj == subscriber; }]; if (index != NSNotFound) [subscribers removeObjectAtIndex:index]; } }]; } - (void)enumerateSubscribersUsingBlock:(void (^)(id subscriber))block { NSArray *subscribers; @synchronized (self.subscribers) { subscribers = [self.subscribers copy]; } for (id subscriber in subscribers) { block(subscriber); } } #pragma mark RACSubscriber - (void)sendNext:(id)value { [self enumerateSubscribersUsingBlock:^(id subscriber) { [subscriber sendNext:value]; }]; } - (void)sendError:(NSError *)error { [self.disposable dispose]; [self enumerateSubscribersUsingBlock:^(id subscriber) { [subscriber sendError:error]; }]; } - (void)sendCompleted { [self.disposable dispose]; [self enumerateSubscribersUsingBlock:^(id subscriber) { [subscriber sendCompleted]; }]; } - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)d { if (d.disposed) return; [self.disposable addDisposable:d]; @weakify(self, d); [d addDisposable:[RACDisposable disposableWithBlock:^{ @strongify(self, d); [self.disposable removeDisposable:d]; }]]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubscriber+Private.h ================================================ // // RACSubscriber+Private.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-06-13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSubscriber.h" // A simple block-based subscriber. @interface RACSubscriber : NSObject // Creates a new subscriber with the given blocks. + (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubscriber.h ================================================ // // RACSubscriber.h // ReactiveCocoa // // Created by Josh Abernathy on 3/1/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACCompoundDisposable; /// Represents any object which can directly receive values from a RACSignal. /// /// You generally shouldn't need to implement this protocol. +[RACSignal /// createSignal:], RACSignal's subscription methods, or RACSubject should work /// for most uses. /// /// Implementors of this protocol may receive messages and values from multiple /// threads simultaneously, and so should be thread-safe. Subscribers will also /// be weakly referenced so implementations must allow that. @protocol RACSubscriber @required /// Sends the next value to subscribers. /// /// value - The value to send. This can be `nil`. - (void)sendNext:(id)value; /// Sends the error to subscribers. /// /// error - The error to send. This can be `nil`. /// /// This terminates the subscription, and invalidates the subscriber (such that /// it cannot subscribe to anything else in the future). - (void)sendError:(NSError *)error; /// Sends completed to subscribers. /// /// This terminates the subscription, and invalidates the subscriber (such that /// it cannot subscribe to anything else in the future). - (void)sendCompleted; /// Sends the subscriber a disposable that represents one of its subscriptions. /// /// A subscriber may receive multiple disposables if it gets subscribed to /// multiple signals; however, any error or completed events must terminate _all_ /// subscriptions. - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubscriber.m ================================================ // // RACSubscriber.m // ReactiveCocoa // // Created by Josh Abernathy on 3/1/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSubscriber.h" #import "RACSubscriber+Private.h" #import "EXTScope.h" #import "RACCompoundDisposable.h" @interface RACSubscriber () // These callbacks should only be accessed while synchronized on self. @property (nonatomic, copy) void (^next)(id value); @property (nonatomic, copy) void (^error)(NSError *error); @property (nonatomic, copy) void (^completed)(void); @property (nonatomic, strong, readonly) RACCompoundDisposable *disposable; @end @implementation RACSubscriber #pragma mark Lifecycle + (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed { RACSubscriber *subscriber = [[self alloc] init]; subscriber->_next = [next copy]; subscriber->_error = [error copy]; subscriber->_completed = [completed copy]; return subscriber; } - (id)init { self = [super init]; if (self == nil) return nil; @unsafeify(self); RACDisposable *selfDisposable = [RACDisposable disposableWithBlock:^{ @strongify(self); @synchronized (self) { self.next = nil; self.error = nil; self.completed = nil; } }]; _disposable = [RACCompoundDisposable compoundDisposable]; [_disposable addDisposable:selfDisposable]; return self; } - (void)dealloc { [self.disposable dispose]; } #pragma mark RACSubscriber - (void)sendNext:(id)value { @synchronized (self) { void (^nextBlock)(id) = [self.next copy]; if (nextBlock == nil) return; nextBlock(value); } } - (void)sendError:(NSError *)e { @synchronized (self) { void (^errorBlock)(NSError *) = [self.error copy]; [self.disposable dispose]; if (errorBlock == nil) return; errorBlock(e); } } - (void)sendCompleted { @synchronized (self) { void (^completedBlock)(void) = [self.completed copy]; [self.disposable dispose]; if (completedBlock == nil) return; completedBlock(); } } - (void)didSubscribeWithDisposable:(RACCompoundDisposable *)otherDisposable { if (otherDisposable.disposed) return; RACCompoundDisposable *selfDisposable = self.disposable; [selfDisposable addDisposable:otherDisposable]; @unsafeify(otherDisposable); // If this subscription terminates, purge its disposable to avoid unbounded // memory growth. [otherDisposable addDisposable:[RACDisposable disposableWithBlock:^{ @strongify(otherDisposable); [selfDisposable removeDisposable:otherDisposable]; }]]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubscriptingAssignmentTrampoline.h ================================================ // // RACSubscriptingAssignmentTrampoline.h // ReactiveCocoa // // Created by Josh Abernathy on 9/24/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import #import "EXTKeyPathCoding.h" @class RACSignal; /// Assigns a signal to an object property, automatically setting the given key /// path on every `next`. When the signal completes, the binding is automatically /// disposed of. /// /// There are two different versions of this macro: /// /// - RAC(TARGET, KEYPATH, NILVALUE) will bind the `KEYPATH` of `TARGET` to the /// given signal. If the signal ever sends a `nil` value, the property will be /// set to `NILVALUE` instead. `NILVALUE` may itself be `nil` for object /// properties, but an NSValue should be used for primitive properties, to /// avoid an exception if `nil` is sent (which might occur if an intermediate /// object is set to `nil`). /// - RAC(TARGET, KEYPATH) is the same as the above, but `NILVALUE` defaults to /// `nil`. /// /// See -[RACSignal setKeyPath:onObject:nilValue:] for more information about the /// binding's semantics. /// /// Examples /// /// RAC(self, objectProperty) = objectSignal; /// RAC(self, stringProperty, @"foobar") = stringSignal; /// RAC(self, integerProperty, @42) = integerSignal; /// /// WARNING: Under certain conditions, use of this macro can be thread-unsafe. /// See the documentation of -setKeyPath:onObject:nilValue:. #define RAC(TARGET, ...) \ metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \ (RAC_(TARGET, __VA_ARGS__, nil)) \ (RAC_(TARGET, __VA_ARGS__)) /// Do not use this directly. Use the RAC macro above. #define RAC_(TARGET, KEYPATH, NILVALUE) \ [[RACSubscriptingAssignmentTrampoline alloc] initWithTarget:(TARGET) nilValue:(NILVALUE)][@keypath(TARGET, KEYPATH)] @interface RACSubscriptingAssignmentTrampoline : NSObject - (id)initWithTarget:(id)target nilValue:(id)nilValue; - (void)setObject:(RACSignal *)signal forKeyedSubscript:(NSString *)keyPath; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubscriptingAssignmentTrampoline.m ================================================ // // RACSubscriptingAssignmentTrampoline.m // ReactiveCocoa // // Created by Josh Abernathy on 9/24/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSubscriptingAssignmentTrampoline.h" #import "RACSignal+Operations.h" @interface RACSubscriptingAssignmentTrampoline () // The object to bind to. @property (nonatomic, strong, readonly) id target; // A value to use when `nil` is sent on the bound signal. @property (nonatomic, strong, readonly) id nilValue; @end @implementation RACSubscriptingAssignmentTrampoline - (id)initWithTarget:(id)target nilValue:(id)nilValue { // This is often a programmer error, but this prevents crashes if the target // object has unexpectedly deallocated. if (target == nil) return nil; self = [super init]; if (self == nil) return nil; _target = target; _nilValue = nilValue; return self; } - (void)setObject:(RACSignal *)signal forKeyedSubscript:(NSString *)keyPath { [signal setKeyPath:keyPath onObject:self.target nilValue:self.nilValue]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubscriptionScheduler.h ================================================ // // RACSubscriptionScheduler.h // ReactiveCocoa // // Created by Josh Abernathy on 11/30/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACScheduler.h" // A private scheduler used only for subscriptions. See the private // +[RACScheduler subscriptionScheduler] method for more information. @interface RACSubscriptionScheduler : RACScheduler @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACSubscriptionScheduler.m ================================================ // // RACSubscriptionScheduler.m // ReactiveCocoa // // Created by Josh Abernathy on 11/30/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACSubscriptionScheduler.h" #import "RACScheduler+Private.h" @interface RACSubscriptionScheduler () // A private background scheduler on which to subscribe if the +currentScheduler // is unknown. @property (nonatomic, strong, readonly) RACScheduler *backgroundScheduler; @end @implementation RACSubscriptionScheduler #pragma mark Lifecycle - (id)init { self = [super initWithName:@"com.ReactiveCocoa.RACScheduler.subscriptionScheduler"]; if (self == nil) return nil; _backgroundScheduler = [RACScheduler scheduler]; return self; } #pragma mark RACScheduler - (RACDisposable *)schedule:(void (^)(void))block { NSCParameterAssert(block != NULL); if (RACScheduler.currentScheduler == nil) return [self.backgroundScheduler schedule:block]; block(); return nil; } - (RACDisposable *)after:(NSDate *)date schedule:(void (^)(void))block { RACScheduler *scheduler = RACScheduler.currentScheduler ?: self.backgroundScheduler; return [scheduler after:date schedule:block]; } - (RACDisposable *)after:(NSDate *)date repeatingEvery:(NSTimeInterval)interval withLeeway:(NSTimeInterval)leeway schedule:(void (^)(void))block { RACScheduler *scheduler = RACScheduler.currentScheduler ?: self.backgroundScheduler; return [scheduler after:date repeatingEvery:interval withLeeway:leeway schedule:block]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACTargetQueueScheduler.h ================================================ // // RACTargetQueueScheduler.h // ReactiveCocoa // // Created by Josh Abernathy on 6/6/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACQueueScheduler.h" /// A scheduler that enqueues blocks on a private serial queue, targeting an /// arbitrary GCD queue. @interface RACTargetQueueScheduler : RACQueueScheduler /// Initializes the receiver with a serial queue that will target the given /// `targetQueue`. /// /// name - The name of the scheduler. If nil, a default name will be used. /// targetQueue - The queue to target. Cannot be NULL. /// /// Returns the initialized object. - (id)initWithName:(NSString *)name targetQueue:(dispatch_queue_t)targetQueue; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACTargetQueueScheduler.m ================================================ // // RACTargetQueueScheduler.m // ReactiveCocoa // // Created by Josh Abernathy on 6/6/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACTargetQueueScheduler.h" #import "RACQueueScheduler+Subclass.h" @implementation RACTargetQueueScheduler #pragma mark Lifecycle - (id)initWithName:(NSString *)name targetQueue:(dispatch_queue_t)targetQueue { NSCParameterAssert(targetQueue != NULL); if (name == nil) { name = [NSString stringWithFormat:@"com.ReactiveCocoa.RACTargetQueueScheduler(%s)", dispatch_queue_get_label(targetQueue)]; } dispatch_queue_t queue = dispatch_queue_create(name.UTF8String, DISPATCH_QUEUE_SERIAL); if (queue == NULL) return nil; dispatch_set_target_queue(queue, targetQueue); return [super initWithName:name queue:queue]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACTestScheduler.h ================================================ // // RACTestScheduler.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-07-06. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACScheduler.h" /// A special kind of scheduler that steps through virtualized time. /// /// This scheduler class can be used in unit tests to verify asynchronous /// behaviors without spending significant time waiting. /// /// This class can be used from multiple threads, but only one thread can `step` /// through the enqueued actions at a time. Other threads will wait while the /// scheduled blocks are being executed. @interface RACTestScheduler : RACScheduler /// Initializes a new test scheduler. - (instancetype)init; /// Executes the next scheduled block, if any. /// /// This method will block until the scheduled action has completed. - (void)step; /// Executes up to the next `ticks` scheduled blocks. /// /// This method will block until the scheduled actions have completed. /// /// ticks - The number of scheduled blocks to execute. If there aren't this many /// blocks enqueued, all scheduled blocks are executed. - (void)step:(NSUInteger)ticks; /// Executes all of the scheduled blocks on the receiver. /// /// This method will block until the scheduled actions have completed. - (void)stepAll; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACTestScheduler.m ================================================ // // RACTestScheduler.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-07-06. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACTestScheduler.h" #import "EXTScope.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACScheduler+Private.h" @interface RACTestSchedulerAction : NSObject // The date at which the action should be executed. // // This absolute time will not actually be honored. This date is only used for // comparison, to determine which block should be run _next_. @property (nonatomic, copy, readonly) NSDate *date; // The scheduled block. @property (nonatomic, copy, readonly) void (^block)(void); // A disposable for this action. // // When disposed, the action should not start executing if it hasn't already. @property (nonatomic, strong, readonly) RACDisposable *disposable; // Initializes a new scheduler action. - (id)initWithDate:(NSDate *)date block:(void (^)(void))block; @end static CFComparisonResult RACCompareScheduledActions(const void *ptr1, const void *ptr2, void *info) { RACTestSchedulerAction *action1 = (__bridge id)ptr1; RACTestSchedulerAction *action2 = (__bridge id)ptr2; return CFDateCompare((__bridge CFDateRef)action1.date, (__bridge CFDateRef)action2.date, NULL); } static const void *RACRetainScheduledAction(CFAllocatorRef allocator, const void *ptr) { return CFRetain(ptr); } static void RACReleaseScheduledAction(CFAllocatorRef allocator, const void *ptr) { CFRelease(ptr); } @interface RACTestScheduler () // All of the RACTestSchedulerActions that have been enqueued and not yet // executed. // // The minimum value in the heap represents the action to execute next. // // This property should only be used while synchronized on self. @property (nonatomic, assign, readonly) CFBinaryHeapRef scheduledActions; // The number of blocks that have been directly enqueued with -schedule: so // far. // // This is used to ensure unique dates when two blocks are enqueued // simultaneously. // // This property should only be used while synchronized on self. @property (nonatomic, assign) NSUInteger numberOfDirectlyScheduledBlocks; @end @implementation RACTestScheduler #pragma mark Lifecycle - (instancetype)init { self = [super initWithName:@"org.reactivecocoa.ReactiveCocoa.RACTestScheduler"]; if (self == nil) return nil; CFBinaryHeapCallBacks callbacks = (CFBinaryHeapCallBacks){ .version = 0, .retain = &RACRetainScheduledAction, .release = &RACReleaseScheduledAction, .copyDescription = &CFCopyDescription, .compare = &RACCompareScheduledActions }; _scheduledActions = CFBinaryHeapCreate(NULL, 0, &callbacks, NULL); return self; } - (void)dealloc { [self stepAll]; if (_scheduledActions != NULL) { CFBridgingRelease(_scheduledActions); _scheduledActions = NULL; } } #pragma mark Execution - (void)step { [self step:1]; } - (void)step:(NSUInteger)ticks { @synchronized (self) { for (NSUInteger i = 0; i < ticks; i++) { const void *actionPtr = NULL; if (!CFBinaryHeapGetMinimumIfPresent(self.scheduledActions, &actionPtr)) break; RACTestSchedulerAction *action = (__bridge id)actionPtr; CFBinaryHeapRemoveMinimumValue(self.scheduledActions); if (action.disposable.disposed) continue; RACScheduler *previousScheduler = RACScheduler.currentScheduler; NSThread.currentThread.threadDictionary[RACSchedulerCurrentSchedulerKey] = self; action.block(); if (previousScheduler != nil) { NSThread.currentThread.threadDictionary[RACSchedulerCurrentSchedulerKey] = previousScheduler; } else { [NSThread.currentThread.threadDictionary removeObjectForKey:RACSchedulerCurrentSchedulerKey]; } } } } - (void)stepAll { [self step:NSUIntegerMax]; } #pragma mark RACScheduler - (RACDisposable *)schedule:(void (^)(void))block { NSCParameterAssert(block != nil); @synchronized (self) { NSDate *uniqueDate = [NSDate dateWithTimeIntervalSinceReferenceDate:self.numberOfDirectlyScheduledBlocks]; self.numberOfDirectlyScheduledBlocks++; RACTestSchedulerAction *action = [[RACTestSchedulerAction alloc] initWithDate:uniqueDate block:block]; CFBinaryHeapAddValue(self.scheduledActions, (__bridge void *)action); return action.disposable; } } - (RACDisposable *)after:(NSDate *)date schedule:(void (^)(void))block { NSCParameterAssert(date != nil); NSCParameterAssert(block != nil); @synchronized (self) { RACTestSchedulerAction *action = [[RACTestSchedulerAction alloc] initWithDate:date block:block]; CFBinaryHeapAddValue(self.scheduledActions, (__bridge void *)action); return action.disposable; } } - (RACDisposable *)after:(NSDate *)date repeatingEvery:(NSTimeInterval)interval withLeeway:(NSTimeInterval)leeway schedule:(void (^)(void))block { NSCParameterAssert(date != nil); NSCParameterAssert(block != nil); NSCParameterAssert(interval >= 0); NSCParameterAssert(leeway >= 0); RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable]; @weakify(self); @synchronized (self) { __block RACDisposable *thisDisposable = nil; void (^reschedulingBlock)(void) = ^{ @strongify(self); [compoundDisposable removeDisposable:thisDisposable]; // Schedule the next interval. RACDisposable *schedulingDisposable = [self after:[date dateByAddingTimeInterval:interval] repeatingEvery:interval withLeeway:leeway schedule:block]; [compoundDisposable addDisposable:schedulingDisposable]; block(); }; RACTestSchedulerAction *action = [[RACTestSchedulerAction alloc] initWithDate:date block:reschedulingBlock]; CFBinaryHeapAddValue(self.scheduledActions, (__bridge void *)action); thisDisposable = action.disposable; [compoundDisposable addDisposable:thisDisposable]; } return compoundDisposable; } @end @implementation RACTestSchedulerAction #pragma mark Lifecycle - (id)initWithDate:(NSDate *)date block:(void (^)(void))block { NSCParameterAssert(date != nil); NSCParameterAssert(block != nil); self = [super init]; if (self == nil) return nil; _date = [date copy]; _block = [block copy]; _disposable = [[RACDisposable alloc] init]; return self; } #pragma mark NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p>{ date: %@ }", self.class, self, self.date]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACTuple.h ================================================ // // RACTuple.h // ReactiveCocoa // // Created by Josh Abernathy on 4/12/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import #import "metamacros.h" @class RACSequence; /// Creates a new tuple with the given values. At least one value must be given. /// Values can be nil. #define RACTuplePack(...) \ RACTuplePack_(__VA_ARGS__) /// Declares new object variables and unpacks a RACTuple into them. /// /// This macro should be used on the left side of an assignment, with the /// tuple on the right side. Nothing else should appear on the same line, and the /// macro should not be the only statement in a conditional or loop body. /// /// If the tuple has more values than there are variables listed, the excess /// values are ignored. /// /// If the tuple has fewer values than there are variables listed, the excess /// variables are initialized to nil. /// /// Examples /// /// RACTupleUnpack(NSString *string, NSNumber *num) = [RACTuple tupleWithObjects:@"foo", @5, nil]; /// NSLog(@"string: %@", string); /// NSLog(@"num: %@", num); /// /// /* The above is equivalent to: */ /// RACTuple *t = [RACTuple tupleWithObjects:@"foo", @5, nil]; /// NSString *string = t[0]; /// NSNumber *num = t[1]; /// NSLog(@"string: %@", string); /// NSLog(@"num: %@", num); #define RACTupleUnpack(...) \ RACTupleUnpack_(__VA_ARGS__) /// A sentinel object that represents nils in the tuple. /// /// It should never be necessary to create a tuple nil yourself. Just use /// +tupleNil. @interface RACTupleNil : NSObject /// A singleton instance. + (RACTupleNil *)tupleNil; @end /// A tuple is an ordered collection of objects. It may contain nils, represented /// by RACTupleNil. @interface RACTuple : NSObject @property (nonatomic, readonly) NSUInteger count; /// These properties all return the object at that index or nil if the number of /// objects is less than the index. @property (nonatomic, readonly) id first; @property (nonatomic, readonly) id second; @property (nonatomic, readonly) id third; @property (nonatomic, readonly) id fourth; @property (nonatomic, readonly) id fifth; @property (nonatomic, readonly) id last; /// Creates a new tuple out of the array. Does not convert nulls to nils. + (instancetype)tupleWithObjectsFromArray:(NSArray *)array; /// Creates a new tuple out of the array. If `convert` is YES, it also converts /// every NSNull to RACTupleNil. + (instancetype)tupleWithObjectsFromArray:(NSArray *)array convertNullsToNils:(BOOL)convert; /// Creates a new tuple with the given objects. Use RACTupleNil to represent /// nils. + (instancetype)tupleWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION; /// Returns the object at `index` or nil if the object is a RACTupleNil. Unlike /// NSArray and friends, it's perfectly fine to ask for the object at an index /// past the tuple's count - 1. It will simply return nil. - (id)objectAtIndex:(NSUInteger)index; /// Returns an array of all the objects. RACTupleNils are converted to NSNulls. - (NSArray *)allObjects; /// Appends `obj` to the receiver. /// /// obj - The object to add to the tuple. This argument may be nil. /// /// Returns a new tuple. - (instancetype)tupleByAddingObject:(id)obj; @end @interface RACTuple (RACSequenceAdditions) /// Returns a sequence of all the objects. RACTupleNils are converted to NSNulls. @property (nonatomic, copy, readonly) RACSequence *rac_sequence; @end @interface RACTuple (ObjectSubscripting) /// Returns the object at that index or nil if the number of objects is less /// than the index. - (id)objectAtIndexedSubscript:(NSUInteger)idx; @end /// This and everything below is for internal use only. /// /// See RACTuplePack() and RACTupleUnpack() instead. #define RACTuplePack_(...) \ ([RACTuple tupleWithObjectsFromArray:@[ metamacro_foreach(RACTuplePack_object_or_ractuplenil,, __VA_ARGS__) ]]) #define RACTuplePack_object_or_ractuplenil(INDEX, ARG) \ (ARG) ?: RACTupleNil.tupleNil, #define RACTupleUnpack_(...) \ metamacro_foreach(RACTupleUnpack_decl,, __VA_ARGS__) \ \ int RACTupleUnpack_state = 0; \ \ RACTupleUnpack_after: \ ; \ metamacro_foreach(RACTupleUnpack_assign,, __VA_ARGS__) \ if (RACTupleUnpack_state != 0) RACTupleUnpack_state = 2; \ \ while (RACTupleUnpack_state != 2) \ if (RACTupleUnpack_state == 1) { \ goto RACTupleUnpack_after; \ } else \ for (; RACTupleUnpack_state != 1; RACTupleUnpack_state = 1) \ [RACTupleUnpackingTrampoline trampoline][ @[ metamacro_foreach(RACTupleUnpack_value,, __VA_ARGS__) ] ] #define RACTupleUnpack_state metamacro_concat(RACTupleUnpack_state, __LINE__) #define RACTupleUnpack_after metamacro_concat(RACTupleUnpack_after, __LINE__) #define RACTupleUnpack_loop metamacro_concat(RACTupleUnpack_loop, __LINE__) #define RACTupleUnpack_decl_name(INDEX) \ metamacro_concat(metamacro_concat(RACTupleUnpack, __LINE__), metamacro_concat(_var, INDEX)) #define RACTupleUnpack_decl(INDEX, ARG) \ __strong id RACTupleUnpack_decl_name(INDEX); #define RACTupleUnpack_assign(INDEX, ARG) \ __strong ARG = RACTupleUnpack_decl_name(INDEX); #define RACTupleUnpack_value(INDEX, ARG) \ [NSValue valueWithPointer:&RACTupleUnpack_decl_name(INDEX)], @interface RACTupleUnpackingTrampoline : NSObject + (instancetype)trampoline; - (void)setObject:(RACTuple *)tuple forKeyedSubscript:(NSArray *)variables; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACTuple.m ================================================ // // RACTuple.m // ReactiveCocoa // // Created by Josh Abernathy on 4/12/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACTuple.h" #import "EXTKeyPathCoding.h" #import "RACTupleSequence.h" @implementation RACTupleNil + (RACTupleNil *)tupleNil { static dispatch_once_t onceToken; static RACTupleNil *tupleNil = nil; dispatch_once(&onceToken, ^{ tupleNil = [[self alloc] init]; }); return tupleNil; } #pragma mark NSCopying - (id)copyWithZone:(NSZone *)zone { return self; } #pragma mark NSCoding - (id)initWithCoder:(NSCoder *)coder { // Always return the singleton. return self.class.tupleNil; } - (void)encodeWithCoder:(NSCoder *)coder { } @end @interface RACTuple () @property (nonatomic, strong) NSArray *backingArray; @end @implementation RACTuple - (instancetype)init { self = [super init]; if (self == nil) return nil; self.backingArray = [NSArray array]; return self; } - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p> %@", self.class, self, self.allObjects]; } - (BOOL)isEqual:(RACTuple *)object { if (object == self) return YES; if (![object isKindOfClass:self.class]) return NO; return [self.backingArray isEqual:object.backingArray]; } - (NSUInteger)hash { return self.backingArray.hash; } #pragma mark NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len { return [self.backingArray countByEnumeratingWithState:state objects:buffer count:len]; } #pragma mark NSCopying - (instancetype)copyWithZone:(NSZone *)zone { // we're immutable, bitches! return self; } #pragma mark NSCoding - (id)initWithCoder:(NSCoder *)coder { self = [self init]; if (self == nil) return nil; self.backingArray = [coder decodeObjectForKey:@keypath(self.backingArray)]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { if (self.backingArray != nil) [coder encodeObject:self.backingArray forKey:@keypath(self.backingArray)]; } #pragma mark API + (instancetype)tupleWithObjectsFromArray:(NSArray *)array { return [self tupleWithObjectsFromArray:array convertNullsToNils:NO]; } + (instancetype)tupleWithObjectsFromArray:(NSArray *)array convertNullsToNils:(BOOL)convert { RACTuple *tuple = [[self alloc] init]; if (convert) { NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:array.count]; for (id object in array) { [newArray addObject:(object == NSNull.null ? RACTupleNil.tupleNil : object)]; } tuple.backingArray = newArray; } else { tuple.backingArray = [array copy]; } return tuple; } + (instancetype)tupleWithObjects:(id)object, ... { RACTuple *tuple = [[self alloc] init]; va_list args; va_start(args, object); NSUInteger count = 0; for (id currentObject = object; currentObject != nil; currentObject = va_arg(args, id)) { ++count; } va_end(args); if (count == 0) { tuple.backingArray = @[]; return tuple; } NSMutableArray *objects = [[NSMutableArray alloc] initWithCapacity:count]; va_start(args, object); for (id currentObject = object; currentObject != nil; currentObject = va_arg(args, id)) { [objects addObject:currentObject]; } va_end(args); tuple.backingArray = objects; return tuple; } - (id)objectAtIndex:(NSUInteger)index { if (index >= self.count) return nil; id object = self.backingArray[index]; return (object == RACTupleNil.tupleNil ? nil : object); } - (NSArray *)allObjects { NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:self.backingArray.count]; for (id object in self.backingArray) { [newArray addObject:(object == RACTupleNil.tupleNil ? NSNull.null : object)]; } return newArray; } - (instancetype)tupleByAddingObject:(id)obj { NSArray *newArray = [self.backingArray arrayByAddingObject:obj ?: RACTupleNil.tupleNil]; return [self.class tupleWithObjectsFromArray:newArray]; } - (NSUInteger)count { return self.backingArray.count; } - (id)first { return self[0]; } - (id)second { return self[1]; } - (id)third { return self[2]; } - (id)fourth { return self[3]; } - (id)fifth { return self[4]; } - (id)last { return self[self.count - 1]; } @end @implementation RACTuple (RACSequenceAdditions) - (RACSequence *)rac_sequence { return [RACTupleSequence sequenceWithTupleBackingArray:self.backingArray offset:0]; } @end @implementation RACTuple (ObjectSubscripting) - (id)objectAtIndexedSubscript:(NSUInteger)idx { return [self objectAtIndex:idx]; } @end @implementation RACTupleUnpackingTrampoline #pragma mark Lifecycle + (instancetype)trampoline { static dispatch_once_t onceToken; static id trampoline = nil; dispatch_once(&onceToken, ^{ trampoline = [[self alloc] init]; }); return trampoline; } - (void)setObject:(RACTuple *)tuple forKeyedSubscript:(NSArray *)variables { NSCParameterAssert(variables != nil); [variables enumerateObjectsUsingBlock:^(NSValue *value, NSUInteger index, BOOL *stop) { __strong id *ptr = (__strong id *)value.pointerValue; *ptr = tuple[index]; }]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACTupleSequence.h ================================================ // // RACTupleSequence.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-05-01. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSequence.h" // Private class that adapts a RACTuple to the RACSequence interface. @interface RACTupleSequence : RACSequence // Returns a sequence for enumerating over the given backing array (from a // RACTuple), starting from the given offset. + (instancetype)sequenceWithTupleBackingArray:(NSArray *)backingArray offset:(NSUInteger)offset; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACTupleSequence.m ================================================ // // RACTupleSequence.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-05-01. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACTupleSequence.h" #import "RACTuple.h" @interface RACTupleSequence () // The array being sequenced, as taken from RACTuple.backingArray. @property (nonatomic, strong, readonly) NSArray *tupleBackingArray; // The index in the array from which the sequence starts. @property (nonatomic, assign, readonly) NSUInteger offset; @end @implementation RACTupleSequence #pragma mark Lifecycle + (instancetype)sequenceWithTupleBackingArray:(NSArray *)backingArray offset:(NSUInteger)offset { NSCParameterAssert(offset <= backingArray.count); if (offset == backingArray.count) return self.empty; RACTupleSequence *seq = [[self alloc] init]; seq->_tupleBackingArray = backingArray; seq->_offset = offset; return seq; } #pragma mark RACSequence - (id)head { id object = self.tupleBackingArray[self.offset]; return (object == RACTupleNil.tupleNil ? NSNull.null : object); } - (RACSequence *)tail { RACSequence *sequence = [self.class sequenceWithTupleBackingArray:self.tupleBackingArray offset:self.offset + 1]; sequence.name = self.name; return sequence; } - (NSArray *)array { NSRange range = NSMakeRange(self.offset, self.tupleBackingArray.count - self.offset); NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:range.length]; [self.tupleBackingArray enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:range] options:0 usingBlock:^(id object, NSUInteger index, BOOL *stop) { id mappedObject = (object == RACTupleNil.tupleNil ? NSNull.null : object); [array addObject:mappedObject]; }]; return array; } #pragma mark NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p>{ name = %@, tuple = %@ }", self.class, self, self.name, self.tupleBackingArray]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACUnarySequence.h ================================================ // // RACUnarySequence.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-05-01. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACSequence.h" // Private class representing a sequence of exactly one value. @interface RACUnarySequence : RACSequence @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACUnarySequence.m ================================================ // // RACUnarySequence.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-05-01. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "RACUnarySequence.h" #import "EXTKeyPathCoding.h" #import "NSObject+RACDescription.h" @interface RACUnarySequence () // The single value stored in this sequence. @property (nonatomic, strong, readwrite) id head; @end @implementation RACUnarySequence #pragma mark Properties @synthesize head = _head; #pragma mark Lifecycle + (instancetype)return:(id)value { RACUnarySequence *sequence = [[self alloc] init]; sequence.head = value; return [sequence setNameWithFormat:@"+return: %@", RACDescription(value)]; } #pragma mark RACSequence - (RACSequence *)tail { return nil; } - (instancetype)bind:(RACStreamBindBlock (^)(void))block { RACStreamBindBlock bindBlock = block(); BOOL stop = NO; RACSequence *result = (id)[bindBlock(self.head, &stop) setNameWithFormat:@"[%@] -bind:", self.name]; return result ?: self.class.empty; } #pragma mark NSCoding - (Class)classForCoder { // Unary sequences should be encoded as themselves, not array sequences. return self.class; } - (id)initWithCoder:(NSCoder *)coder { id value = [coder decodeObjectForKey:@keypath(self.head)]; return [self.class return:value]; } - (void)encodeWithCoder:(NSCoder *)coder { if (self.head != nil) [coder encodeObject:self.head forKey:@keypath(self.head)]; } #pragma mark NSObject - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p>{ name = %@, head = %@ }", self.class, self, self.name, self.head]; } - (NSUInteger)hash { return [self.head hash]; } - (BOOL)isEqual:(RACUnarySequence *)seq { if (self == seq) return YES; if (![seq isKindOfClass:RACUnarySequence.class]) return NO; return self.head == seq.head || [(NSObject *)self.head isEqual:seq.head]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACUnit.h ================================================ // // RACUnit.h // ReactiveCocoa // // Created by Josh Abernathy on 3/27/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import /// A unit represents an empty value. /// /// It should never be necessary to create a unit yourself. Just use +defaultUnit. @interface RACUnit : NSObject /// A singleton instance. + (RACUnit *)defaultUnit; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACUnit.m ================================================ // // RACUnit.m // ReactiveCocoa // // Created by Josh Abernathy on 3/27/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACUnit.h" @implementation RACUnit #pragma mark API + (RACUnit *)defaultUnit { static dispatch_once_t onceToken; static RACUnit *defaultUnit = nil; dispatch_once(&onceToken, ^{ defaultUnit = [[self alloc] init]; }); return defaultUnit; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACValueTransformer.h ================================================ // // RACValueTransformer.h // ReactiveCocoa // // Created by Josh Abernathy on 3/6/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import // A private block based transformer. @interface RACValueTransformer : NSValueTransformer + (instancetype)transformerWithBlock:(id (^)(id value))block; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/RACValueTransformer.m ================================================ // // RACValueTransformer.m // ReactiveCocoa // // Created by Josh Abernathy on 3/6/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "RACValueTransformer.h" @interface RACValueTransformer () @property (nonatomic, copy) id (^transformBlock)(id value); @end @implementation RACValueTransformer #pragma mark NSValueTransformer + (BOOL)allowsReverseTransformation { return NO; } - (id)transformedValue:(id)value { return self.transformBlock(value); } #pragma mark API @synthesize transformBlock; + (instancetype)transformerWithBlock:(id (^)(id value))block { NSCParameterAssert(block != NULL); RACValueTransformer *transformer = [[self alloc] init]; transformer.transformBlock = block; return transformer; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/ReactiveCocoa-Bridging-Header.h ================================================ // // Use this file to import your target's public headers that you would like to expose to Swift. // #import "RACCommand.h" #import "RACDisposable.h" #import "RACEvent.h" #import "RACScheduler.h" #import "RACTargetQueueScheduler.h" #import "RACSignal.h" #import "RACSignal+Operations.h" #import "RACStream.h" #import "RACSubscriber.h" ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIActionSheet+RACSignalSupport.h ================================================ // // UIActionSheet+RACSignalSupport.h // ReactiveCocoa // // Created by Dave Lee on 2013-06-22. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACDelegateProxy; @class RACSignal; @interface UIActionSheet (RACSignalSupport) /// A delegate proxy which will be set as the receiver's delegate when any of the /// methods in this category are used. @property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy; /// Creates a signal for button clicks on the receiver. /// /// When this method is invoked, the `rac_delegateProxy` will become the /// receiver's delegate. Any previous delegate will become the -[RACDelegateProxy /// rac_proxiedDelegate], so that it receives any messages that the proxy doesn't /// know how to handle. Setting the receiver's `delegate` afterward is /// considered undefined behavior. /// /// Returns a signal which will send the index of the specific button clicked. /// The signal will complete when the receiver is deallocated. - (RACSignal *)rac_buttonClickedSignal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIActionSheet+RACSignalSupport.m ================================================ // // UIActionSheet+RACSignalSupport.m // ReactiveCocoa // // Created by Dave Lee on 2013-06-22. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UIActionSheet+RACSignalSupport.h" #import "RACDelegateProxy.h" #import "RACSignal+Operations.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import @implementation UIActionSheet (RACSignalSupport) static void RACUseDelegateProxy(UIActionSheet *self) { if (self.delegate == self.rac_delegateProxy) return; self.rac_delegateProxy.rac_proxiedDelegate = self.delegate; self.delegate = (id)self.rac_delegateProxy; } - (RACDelegateProxy *)rac_delegateProxy { RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd); if (proxy == nil) { proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UIActionSheetDelegate)]; objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return proxy; } - (RACSignal *)rac_buttonClickedSignal { RACSignal *signal = [[[[self.rac_delegateProxy signalForSelector:@selector(actionSheet:clickedButtonAtIndex:)] reduceEach:^(UIActionSheet *actionSheet, NSNumber *buttonIndex) { return buttonIndex; }] takeUntil:self.rac_willDeallocSignal] setNameWithFormat:@"%@ -rac_buttonClickedSignal", RACDescription(self)]; RACUseDelegateProxy(self); return signal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIAlertView+RACSignalSupport.h ================================================ // // UIAlertView+RACSignalSupport.h // ReactiveCocoa // // Created by Henrik Hodne on 6/16/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACDelegateProxy; @class RACSignal; @interface UIAlertView (RACSignalSupport) /// A delegate proxy which will be set as the receiver's delegate when any of the /// methods in this category are used. @property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy; /// Creates a signal for button clicks on the receiver. /// /// When this method is invoked, the `rac_delegateProxy` will become the /// receiver's delegate. Any previous delegate will become the -[RACDelegateProxy /// rac_proxiedDelegate], so that it receives any messages that the proxy doesn't /// know how to handle. Setting the receiver's `delegate` afterward is considered /// undefined behavior. /// /// Note that this signal will not send a value when the alert is dismissed /// programatically. /// /// Returns a signal which will send the index of the specific button clicked. /// The signal will complete itself when the receiver is deallocated. - (RACSignal *)rac_buttonClickedSignal; /// Creates a signal for dismissal of the receiver. /// /// When this method is invoked, the `rac_delegateProxy` will become the /// receiver's delegate. Any previous delegate will become the -[RACDelegateProxy /// rac_proxiedDelegate], so that it receives any messages that the proxy doesn't /// know how to handle. Setting the receiver's `delegate` afterward is considered /// undefined behavior. /// /// Returns a signal which will send the index of the button associated with the /// dismissal. The signal will complete itself when the receiver is deallocated. - (RACSignal *)rac_willDismissSignal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIAlertView+RACSignalSupport.m ================================================ // // UIAlertView+RACSignalSupport.m // ReactiveCocoa // // Created by Henrik Hodne on 6/16/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UIAlertView+RACSignalSupport.h" #import "RACDelegateProxy.h" #import "RACSignal+Operations.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import @implementation UIAlertView (RACSignalSupport) static void RACUseDelegateProxy(UIAlertView *self) { if (self.delegate == self.rac_delegateProxy) return; self.rac_delegateProxy.rac_proxiedDelegate = self.delegate; self.delegate = (id)self.rac_delegateProxy; } - (RACDelegateProxy *)rac_delegateProxy { RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd); if (proxy == nil) { proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UIAlertViewDelegate)]; objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return proxy; } - (RACSignal *)rac_buttonClickedSignal { RACSignal *signal = [[[[self.rac_delegateProxy signalForSelector:@selector(alertView:clickedButtonAtIndex:)] reduceEach:^(UIAlertView *alertView, NSNumber *buttonIndex) { return buttonIndex; }] takeUntil:self.rac_willDeallocSignal] setNameWithFormat:@"%@ -rac_buttonClickedSignal", RACDescription(self)]; RACUseDelegateProxy(self); return signal; } - (RACSignal *)rac_willDismissSignal { RACSignal *signal = [[[[self.rac_delegateProxy signalForSelector:@selector(alertView:willDismissWithButtonIndex:)] reduceEach:^(UIAlertView *alertView, NSNumber *buttonIndex) { return buttonIndex; }] takeUntil:self.rac_willDeallocSignal] setNameWithFormat:@"%@ -rac_willDismissSignal", RACDescription(self)]; RACUseDelegateProxy(self); return signal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIBarButtonItem+RACCommandSupport.h ================================================ // // UIBarButtonItem+RACCommandSupport.h // ReactiveCocoa // // Created by Kyle LeNeau on 3/27/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACCommand; @interface UIBarButtonItem (RACCommandSupport) /// Sets the control's command. When the control is clicked, the command is /// executed with the sender of the event. The control's enabledness is bound /// to the command's `canExecute`. /// /// Note: this will reset the control's target and action. @property (nonatomic, strong) RACCommand *rac_command; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIBarButtonItem+RACCommandSupport.m ================================================ // // UIBarButtonItem+RACCommandSupport.m // ReactiveCocoa // // Created by Kyle LeNeau on 3/27/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UIBarButtonItem+RACCommandSupport.h" #import "EXTKeyPathCoding.h" #import "RACCommand.h" #import "RACDisposable.h" #import "RACSignal+Operations.h" #import static void *UIControlRACCommandKey = &UIControlRACCommandKey; static void *UIControlEnabledDisposableKey = &UIControlEnabledDisposableKey; @implementation UIBarButtonItem (RACCommandSupport) - (RACCommand *)rac_command { return objc_getAssociatedObject(self, UIControlRACCommandKey); } - (void)setRac_command:(RACCommand *)command { objc_setAssociatedObject(self, UIControlRACCommandKey, command, OBJC_ASSOCIATION_RETAIN_NONATOMIC); // Check for stored signal in order to remove it and add a new one RACDisposable *disposable = objc_getAssociatedObject(self, UIControlEnabledDisposableKey); [disposable dispose]; if (command == nil) return; disposable = [command.enabled setKeyPath:@keypath(self.enabled) onObject:self]; objc_setAssociatedObject(self, UIControlEnabledDisposableKey, disposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self rac_hijackActionAndTargetIfNeeded]; } - (void)rac_hijackActionAndTargetIfNeeded { SEL hijackSelector = @selector(rac_commandPerformAction:); if (self.target == self && self.action == hijackSelector) return; if (self.target != nil) NSLog(@"WARNING: UIBarButtonItem.rac_command hijacks the control's existing target and action."); self.target = self; self.action = hijackSelector; } - (void)rac_commandPerformAction:(id)sender { [self.rac_command execute:sender]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIButton+RACCommandSupport.h ================================================ // // UIButton+RACCommandSupport.h // ReactiveCocoa // // Created by Ash Furrow on 2013-06-06. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACCommand; @interface UIButton (RACCommandSupport) /// Sets the button's command. When the button is clicked, the command is /// executed with the sender of the event. The button's enabledness is bound /// to the command's `canExecute`. @property (nonatomic, strong) RACCommand *rac_command; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIButton+RACCommandSupport.m ================================================ // // UIButton+RACCommandSupport.m // ReactiveCocoa // // Created by Ash Furrow on 2013-06-06. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UIButton+RACCommandSupport.h" #import "EXTKeyPathCoding.h" #import "RACCommand.h" #import "RACDisposable.h" #import "RACSignal+Operations.h" #import static void *UIButtonRACCommandKey = &UIButtonRACCommandKey; static void *UIButtonEnabledDisposableKey = &UIButtonEnabledDisposableKey; @implementation UIButton (RACCommandSupport) - (RACCommand *)rac_command { return objc_getAssociatedObject(self, UIButtonRACCommandKey); } - (void)setRac_command:(RACCommand *)command { objc_setAssociatedObject(self, UIButtonRACCommandKey, command, OBJC_ASSOCIATION_RETAIN_NONATOMIC); // Check for stored signal in order to remove it and add a new one RACDisposable *disposable = objc_getAssociatedObject(self, UIButtonEnabledDisposableKey); [disposable dispose]; if (command == nil) return; disposable = [command.enabled setKeyPath:@keypath(self.enabled) onObject:self]; objc_setAssociatedObject(self, UIButtonEnabledDisposableKey, disposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self rac_hijackActionAndTargetIfNeeded]; } - (void)rac_hijackActionAndTargetIfNeeded { SEL hijackSelector = @selector(rac_commandPerformAction:); for (NSString *selector in [self actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) { if (hijackSelector == NSSelectorFromString(selector)) { return; } } [self addTarget:self action:hijackSelector forControlEvents:UIControlEventTouchUpInside]; } - (void)rac_commandPerformAction:(id)sender { [self.rac_command execute:sender]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UICollectionReusableView+RACSignalSupport.h ================================================ // // UICollectionReusableView+RACSignalSupport.h // ReactiveCocoa // // Created by Kent Wong on 2013-10-04. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACSignal; // This category is only applicable to iOS >= 6.0. @interface UICollectionReusableView (RACSignalSupport) /// A signal which will send a RACUnit whenever -prepareForReuse is invoked upon /// the receiver. /// /// Examples /// /// [[[self.cancelButton /// rac_signalForControlEvents:UIControlEventTouchUpInside] /// takeUntil:self.rac_prepareForReuseSignal] /// subscribeNext:^(UIButton *x) { /// // do other things /// }]; @property (nonatomic, strong, readonly) RACSignal *rac_prepareForReuseSignal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UICollectionReusableView+RACSignalSupport.m ================================================ // // UICollectionReusableView+RACSignalSupport.m // ReactiveCocoa // // Created by Kent Wong on 2013-10-04. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UICollectionReusableView+RACSignalSupport.h" #import "NSObject+RACDescription.h" #import "NSObject+RACSelectorSignal.h" #import "RACSignal+Operations.h" #import "RACUnit.h" #import @implementation UICollectionReusableView (RACSignalSupport) - (RACSignal *)rac_prepareForReuseSignal { RACSignal *signal = objc_getAssociatedObject(self, _cmd); if (signal != nil) return signal; signal = [[[self rac_signalForSelector:@selector(prepareForReuse)] mapReplace:RACUnit.defaultUnit] setNameWithFormat:@"%@ -rac_prepareForReuseSignal", RACDescription(self)]; objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return signal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIControl+RACSignalSupport.h ================================================ // // UIControl+RACSignalSupport.h // ReactiveCocoa // // Created by Josh Abernathy on 4/17/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACSignal; @interface UIControl (RACSignalSupport) /// Creates and returns a signal that sends the sender of the control event /// whenever one of the control events is triggered. - (RACSignal *)rac_signalForControlEvents:(UIControlEvents)controlEvents; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIControl+RACSignalSupport.m ================================================ // // UIControl+RACSignalSupport.m // ReactiveCocoa // // Created by Josh Abernathy on 4/17/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "UIControl+RACSignalSupport.h" #import "EXTScope.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACSignal.h" #import "RACSubscriber.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" @implementation UIControl (RACSignalSupport) - (RACSignal *)rac_signalForControlEvents:(UIControlEvents)controlEvents { @weakify(self); return [[RACSignal createSignal:^(id subscriber) { @strongify(self); [self addTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents]; [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ [subscriber sendCompleted]; }]]; return [RACDisposable disposableWithBlock:^{ @strongify(self); [self removeTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents]; }]; }] setNameWithFormat:@"%@ -rac_signalForControlEvents: %lx", RACDescription(self), (unsigned long)controlEvents]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIControl+RACSignalSupportPrivate.h ================================================ // // UIControl+RACSignalSupportPrivate.h // ReactiveCocoa // // Created by Uri Baghin on 06/08/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACChannelTerminal; @interface UIControl (RACSignalSupportPrivate) // Adds a RACChannel-based interface to the receiver for the given // UIControlEvents and exposes it. // // controlEvents - A mask of UIControlEvents on which to send new values. // key - The key whose value should be read and set when a control // event fires and when a value is sent to the // RACChannelTerminal respectively. // nilValue - The value to be assigned to the key when `nil` is sent to the // RACChannelTerminal. // // Returns a RACChannelTerminal which will send future values from the receiver, // and update the receiver when values are sent to the terminal. - (RACChannelTerminal *)rac_channelForControlEvents:(UIControlEvents)controlEvents key:(NSString *)key nilValue:(id)nilValue; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIControl+RACSignalSupportPrivate.m ================================================ // // UIControl+RACSignalSupportPrivate.m // ReactiveCocoa // // Created by Uri Baghin on 06/08/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UIControl+RACSignalSupportPrivate.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACLifting.h" #import "RACChannel.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACSignal+Operations.h" #import "UIControl+RACSignalSupport.h" @implementation UIControl (RACSignalSupportPrivate) - (RACChannelTerminal *)rac_channelForControlEvents:(UIControlEvents)controlEvents key:(NSString *)key nilValue:(id)nilValue { NSCParameterAssert(key.length > 0); key = [key copy]; RACChannel *channel = [[RACChannel alloc] init]; [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ [channel.followingTerminal sendCompleted]; }]]; RACSignal *eventSignal = [[[self rac_signalForControlEvents:controlEvents] mapReplace:key] takeUntil:[[channel.followingTerminal ignoreValues] catchTo:RACSignal.empty]]; [[self rac_liftSelector:@selector(valueForKey:) withSignals:eventSignal, nil] subscribe:channel.followingTerminal]; RACSignal *valuesSignal = [channel.followingTerminal map:^(id value) { return value ?: nilValue; }]; [self rac_liftSelector:@selector(setValue:forKey:) withSignals:valuesSignal, [RACSignal return:key], nil]; return channel.leadingTerminal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIDatePicker+RACSignalSupport.h ================================================ // // UIDatePicker+RACSignalSupport.h // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACChannelTerminal; @interface UIDatePicker (RACSignalSupport) /// Creates a new RACChannel-based binding to the receiver. /// /// nilValue - The date to set when the terminal receives `nil`. /// /// Returns a RACChannelTerminal that sends the receiver's date whenever the /// UIControlEventValueChanged control event is fired, and sets the date to the /// values it receives. - (RACChannelTerminal *)rac_newDateChannelWithNilValue:(NSDate *)nilValue; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIDatePicker+RACSignalSupport.m ================================================ // // UIDatePicker+RACSignalSupport.m // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UIDatePicker+RACSignalSupport.h" #import "EXTKeyPathCoding.h" #import "UIControl+RACSignalSupportPrivate.h" @implementation UIDatePicker (RACSignalSupport) - (RACChannelTerminal *)rac_newDateChannelWithNilValue:(NSDate *)nilValue { return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.date) nilValue:nilValue]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIGestureRecognizer+RACSignalSupport.h ================================================ // // UIGestureRecognizer+RACSignalSupport.h // ReactiveCocoa // // Created by Josh Vera on 5/5/13. // Copyright (c) 2013 GitHub. All rights reserved. // #import @class RACSignal; @interface UIGestureRecognizer (RACSignalSupport) /// Returns a signal that sends the receiver when its gesture occurs. - (RACSignal *)rac_gestureSignal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIGestureRecognizer+RACSignalSupport.m ================================================ // // UIGestureRecognizer+RACSignalSupport.m // ReactiveCocoa // // Created by Josh Vera on 5/5/13. // Copyright (c) 2013 GitHub. All rights reserved. // #import "UIGestureRecognizer+RACSignalSupport.h" #import "EXTScope.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACSignal.h" #import "RACSubscriber.h" @implementation UIGestureRecognizer (RACSignalSupport) - (RACSignal *)rac_gestureSignal { @weakify(self); return [[RACSignal createSignal:^(id subscriber) { @strongify(self); [self addTarget:subscriber action:@selector(sendNext:)]; [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ [subscriber sendCompleted]; }]]; return [RACDisposable disposableWithBlock:^{ @strongify(self); [self removeTarget:subscriber action:@selector(sendNext:)]; }]; }] setNameWithFormat:@"%@ -rac_gestureSignal", RACDescription(self)]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIImagePickerController+RACSignalSupport.h ================================================ // // UIImagePickerController+RACSignalSupport.h // ReactiveCocoa // // Created by Timur Kuchkarov on 28.03.14. // Copyright (c) 2014 GitHub. All rights reserved. // #import @class RACDelegateProxy; @class RACSignal; @interface UIImagePickerController (RACSignalSupport) /// A delegate proxy which will be set as the receiver's delegate when any of the /// methods in this category are used. @property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy; /// Creates a signal for every new selected image. /// /// When this method is invoked, the `rac_delegateProxy` will become the /// receiver's delegate. Any previous delegate will become the -[RACDelegateProxy /// rac_proxiedDelegate], so that it receives any messages that the proxy doesn't /// know how to handle. Setting the receiver's `delegate` afterward is considered /// undefined behavior. /// /// Returns a signal which will send the dictionary with info for the selected image. /// Caller is responsible for picker controller dismissal. The signal will complete /// itself when the receiver is deallocated or when user cancels selection. - (RACSignal *)rac_imageSelectedSignal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIImagePickerController+RACSignalSupport.m ================================================ // // UIImagePickerController+RACSignalSupport.m // ReactiveCocoa // // Created by Timur Kuchkarov on 28.03.14. // Copyright (c) 2014 GitHub. All rights reserved. // #import "UIImagePickerController+RACSignalSupport.h" #import "RACDelegateProxy.h" #import "RACSignal+Operations.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import @implementation UIImagePickerController (RACSignalSupport) static void RACUseDelegateProxy(UIImagePickerController *self) { if (self.delegate == self.rac_delegateProxy) return; self.rac_delegateProxy.rac_proxiedDelegate = self.delegate; self.delegate = (id)self.rac_delegateProxy; } - (RACDelegateProxy *)rac_delegateProxy { RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd); if (proxy == nil) { proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UIImagePickerControllerDelegate)]; objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return proxy; } - (RACSignal *)rac_imageSelectedSignal { RACSignal *pickerCancelledSignal = [[self.rac_delegateProxy signalForSelector:@selector(imagePickerControllerDidCancel:)] merge:self.rac_willDeallocSignal]; RACSignal *imagePickerSignal = [[[[self.rac_delegateProxy signalForSelector:@selector(imagePickerController:didFinishPickingMediaWithInfo:)] reduceEach:^(UIImagePickerController *pickerController, NSDictionary *userInfo) { return userInfo; }] takeUntil:pickerCancelledSignal] setNameWithFormat:@"%@ -rac_imageSelectedSignal", RACDescription(self)]; RACUseDelegateProxy(self); return imagePickerSignal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIRefreshControl+RACCommandSupport.h ================================================ // // UIRefreshControl+RACCommandSupport.h // ReactiveCocoa // // Created by Dave Lee on 2013-10-17. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACCommand; @interface UIRefreshControl (RACCommandSupport) /// Manipulate the RACCommand property associated with this refresh control. /// /// When this refresh control is activated by the user, the command will be /// executed. Upon completion or error of the execution signal, -endRefreshing /// will be invoked. @property (nonatomic, strong) RACCommand *rac_command; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIRefreshControl+RACCommandSupport.m ================================================ // // UIRefreshControl+RACCommandSupport.m // ReactiveCocoa // // Created by Dave Lee on 2013-10-17. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UIRefreshControl+RACCommandSupport.h" #import "EXTKeyPathCoding.h" #import "RACCommand.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACSignal.h" #import "RACSignal+Operations.h" #import "UIControl+RACSignalSupport.h" #import static void *UIRefreshControlRACCommandKey = &UIRefreshControlRACCommandKey; static void *UIRefreshControlDisposableKey = &UIRefreshControlDisposableKey; @implementation UIRefreshControl (RACCommandSupport) - (RACCommand *)rac_command { return objc_getAssociatedObject(self, UIRefreshControlRACCommandKey); } - (void)setRac_command:(RACCommand *)command { objc_setAssociatedObject(self, UIRefreshControlRACCommandKey, command, OBJC_ASSOCIATION_RETAIN_NONATOMIC); // Dispose of any active command associations. [objc_getAssociatedObject(self, UIRefreshControlDisposableKey) dispose]; if (command == nil) return; // Like RAC(self, enabled) = command.enabled; but with access to disposable. RACDisposable *enabledDisposable = [command.enabled setKeyPath:@keypath(self.enabled) onObject:self]; RACDisposable *executionDisposable = [[[[[self rac_signalForControlEvents:UIControlEventValueChanged] map:^(UIRefreshControl *x) { return [[[command execute:x] catchTo:[RACSignal empty]] then:^{ return [RACSignal return:x]; }]; }] concat] deliverOnMainThread] subscribeNext:^(UIRefreshControl *x) { [x endRefreshing]; }]; RACDisposable *commandDisposable = [RACCompoundDisposable compoundDisposableWithDisposables:@[ enabledDisposable, executionDisposable ]]; objc_setAssociatedObject(self, UIRefreshControlDisposableKey, commandDisposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UISegmentedControl+RACSignalSupport.h ================================================ // // UISegmentedControl+RACSignalSupport.h // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACChannelTerminal; @interface UISegmentedControl (RACSignalSupport) /// Creates a new RACChannel-based binding to the receiver. /// /// nilValue - The segment to select when the terminal receives `nil`. /// /// Returns a RACChannelTerminal that sends the receiver's currently selected /// segment's index whenever the UIControlEventValueChanged control event is /// fired, and sets the selected segment index to the values it receives. - (RACChannelTerminal *)rac_newSelectedSegmentIndexChannelWithNilValue:(NSNumber *)nilValue; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UISegmentedControl+RACSignalSupport.m ================================================ // // UISegmentedControl+RACSignalSupport.m // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UISegmentedControl+RACSignalSupport.h" #import "EXTKeyPathCoding.h" #import "UIControl+RACSignalSupportPrivate.h" @implementation UISegmentedControl (RACSignalSupport) - (RACChannelTerminal *)rac_newSelectedSegmentIndexChannelWithNilValue:(NSNumber *)nilValue { return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.selectedSegmentIndex) nilValue:nilValue]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UISlider+RACSignalSupport.h ================================================ // // UISlider+RACSignalSupport.h // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACChannelTerminal; @interface UISlider (RACSignalSupport) /// Creates a new RACChannel-based binding to the receiver. /// /// nilValue - The value to set when the terminal receives `nil`. /// /// Returns a RACChannelTerminal that sends the receiver's value whenever the /// UIControlEventValueChanged control event is fired, and sets the value to the /// values it receives. - (RACChannelTerminal *)rac_newValueChannelWithNilValue:(NSNumber *)nilValue; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UISlider+RACSignalSupport.m ================================================ // // UISlider+RACSignalSupport.m // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UISlider+RACSignalSupport.h" #import "EXTKeyPathCoding.h" #import "UIControl+RACSignalSupportPrivate.h" @implementation UISlider (RACSignalSupport) - (RACChannelTerminal *)rac_newValueChannelWithNilValue:(NSNumber *)nilValue { return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.value) nilValue:nilValue]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIStepper+RACSignalSupport.h ================================================ // // UIStepper+RACSignalSupport.h // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACChannelTerminal; @interface UIStepper (RACSignalSupport) /// Creates a new RACChannel-based binding to the receiver. /// /// nilValue - The value to set when the terminal receives `nil`. /// /// Returns a RACChannelTerminal that sends the receiver's value whenever the /// UIControlEventValueChanged control event is fired, and sets the value to the /// values it receives. - (RACChannelTerminal *)rac_newValueChannelWithNilValue:(NSNumber *)nilValue; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UIStepper+RACSignalSupport.m ================================================ // // UIStepper+RACSignalSupport.m // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UIStepper+RACSignalSupport.h" #import "EXTKeyPathCoding.h" #import "UIControl+RACSignalSupportPrivate.h" @implementation UIStepper (RACSignalSupport) - (RACChannelTerminal *)rac_newValueChannelWithNilValue:(NSNumber *)nilValue { return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.value) nilValue:nilValue]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UISwitch+RACSignalSupport.h ================================================ // // UISwitch+RACSignalSupport.h // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACChannelTerminal; @interface UISwitch (RACSignalSupport) /// Creates a new RACChannel-based binding to the receiver. /// /// Returns a RACChannelTerminal that sends whether the receiver is on whenever /// the UIControlEventValueChanged control event is fired, and sets it on or off /// when it receives @YES or @NO respectively. - (RACChannelTerminal *)rac_newOnChannel; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UISwitch+RACSignalSupport.m ================================================ // // UISwitch+RACSignalSupport.m // ReactiveCocoa // // Created by Uri Baghin on 20/07/2013. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UISwitch+RACSignalSupport.h" #import "EXTKeyPathCoding.h" #import "UIControl+RACSignalSupportPrivate.h" @implementation UISwitch (RACSignalSupport) - (RACChannelTerminal *)rac_newOnChannel { return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.on) nilValue:@NO]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UITableViewCell+RACSignalSupport.h ================================================ // // UITableViewCell+RACSignalSupport.h // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-07-22. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACSignal; @interface UITableViewCell (RACSignalSupport) /// A signal which will send a RACUnit whenever -prepareForReuse is invoked upon /// the receiver. /// /// Examples /// /// [[[self.cancelButton /// rac_signalForControlEvents:UIControlEventTouchUpInside] /// takeUntil:self.rac_prepareForReuseSignal] /// subscribeNext:^(UIButton *x) { /// // do other things /// }]; @property (nonatomic, strong, readonly) RACSignal *rac_prepareForReuseSignal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UITableViewCell+RACSignalSupport.m ================================================ // // UITableViewCell+RACSignalSupport.m // ReactiveCocoa // // Created by Justin Spahr-Summers on 2013-07-22. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UITableViewCell+RACSignalSupport.h" #import "NSObject+RACDescription.h" #import "NSObject+RACSelectorSignal.h" #import "RACSignal+Operations.h" #import "RACUnit.h" #import @implementation UITableViewCell (RACSignalSupport) - (RACSignal *)rac_prepareForReuseSignal { RACSignal *signal = objc_getAssociatedObject(self, _cmd); if (signal != nil) return signal; signal = [[[self rac_signalForSelector:@selector(prepareForReuse)] mapReplace:RACUnit.defaultUnit] setNameWithFormat:@"%@ -rac_prepareForReuseSignal", RACDescription(self)]; objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return signal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UITableViewHeaderFooterView+RACSignalSupport.h ================================================ // // UITableViewHeaderFooterView+RACSignalSupport.h // ReactiveCocoa // // Created by Syo Ikeda on 12/30/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import @class RACSignal; // This category is only applicable to iOS >= 6.0. @interface UITableViewHeaderFooterView (RACSignalSupport) /// A signal which will send a RACUnit whenever -prepareForReuse is invoked upon /// the receiver. /// /// Examples /// /// [[[self.cancelButton /// rac_signalForControlEvents:UIControlEventTouchUpInside] /// takeUntil:self.rac_prepareForReuseSignal] /// subscribeNext:^(UIButton *x) { /// // do other things /// }]; @property (nonatomic, strong, readonly) RACSignal *rac_prepareForReuseSignal; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UITableViewHeaderFooterView+RACSignalSupport.m ================================================ // // UITableViewHeaderFooterView+RACSignalSupport.m // ReactiveCocoa // // Created by Syo Ikeda on 12/30/13. // Copyright (c) 2013 GitHub, Inc. All rights reserved. // #import "UITableViewHeaderFooterView+RACSignalSupport.h" #import "NSObject+RACDescription.h" #import "NSObject+RACSelectorSignal.h" #import "RACSignal+Operations.h" #import "RACUnit.h" #import @implementation UITableViewHeaderFooterView (RACSignalSupport) - (RACSignal *)rac_prepareForReuseSignal { RACSignal *signal = objc_getAssociatedObject(self, _cmd); if (signal != nil) return signal; signal = [[[self rac_signalForSelector:@selector(prepareForReuse)] mapReplace:RACUnit.defaultUnit] setNameWithFormat:@"%@ -rac_prepareForReuseSignal", RACDescription(self)]; objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return signal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UITextField+RACSignalSupport.h ================================================ // // UITextField+RACSignalSupport.h // ReactiveCocoa // // Created by Josh Abernathy on 4/17/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACChannelTerminal; @class RACSignal; @interface UITextField (RACSignalSupport) /// Creates and returns a signal for the text of the field. It always starts with /// the current text. The signal sends next when the UIControlEventAllEditingEvents /// control event is fired on the control. - (RACSignal *)rac_textSignal; /// Creates a new RACChannel-based binding to the receiver. /// /// Returns a RACChannelTerminal that sends the receiver's text whenever the /// UIControlEventAllEditingEvents control event is fired, and sets the text /// to the values it receives. - (RACChannelTerminal *)rac_newTextChannel; @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UITextField+RACSignalSupport.m ================================================ // // UITextField+RACSignalSupport.m // ReactiveCocoa // // Created by Josh Abernathy on 4/17/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import "UITextField+RACSignalSupport.h" #import "EXTKeyPathCoding.h" #import "EXTScope.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import "RACSignal+Operations.h" #import "UIControl+RACSignalSupport.h" #import "UIControl+RACSignalSupportPrivate.h" @implementation UITextField (RACSignalSupport) - (RACSignal *)rac_textSignal { @weakify(self); return [[[[[RACSignal defer:^{ @strongify(self); return [RACSignal return:self]; }] concat:[self rac_signalForControlEvents:UIControlEventAllEditingEvents]] map:^(UITextField *x) { return x.text; }] takeUntil:self.rac_willDeallocSignal] setNameWithFormat:@"%@ -rac_textSignal", RACDescription(self)]; } - (RACChannelTerminal *)rac_newTextChannel { return [self rac_channelForControlEvents:UIControlEventAllEditingEvents key:@keypath(self.text) nilValue:@""]; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UITextView+RACSignalSupport.h ================================================ // // UITextView+RACSignalSupport.h // ReactiveCocoa // // Created by Cody Krieger on 5/18/12. // Copyright (c) 2012 Cody Krieger. All rights reserved. // #import @class RACDelegateProxy; @class RACSignal; @interface UITextView (RACSignalSupport) /// A delegate proxy which will be set as the receiver's delegate when any of the /// methods in this category are used. @property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy; /// Creates a signal for the text of the receiver. /// /// When this method is invoked, the `rac_delegateProxy` will become the /// receiver's delegate. Any previous delegate will become the -[RACDelegateProxy /// rac_proxiedDelegate], so that it receives any messages that the proxy doesn't /// know how to handle. Setting the receiver's `delegate` afterward is /// considered undefined behavior. /// /// Returns a signal which will send the current text upon subscription, then /// again whenever the receiver's text is changed. The signal will complete when /// the receiver is deallocated. - (RACSignal *)rac_textSignal; @end @interface UITextView (RACSignalSupportUnavailable) - (RACSignal *)rac_signalForDelegateMethod:(SEL)method __attribute__((unavailable("Use -rac_signalForSelector:fromProtocol: instead"))); @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/UITextView+RACSignalSupport.m ================================================ // // UITextView+RACSignalSupport.m // ReactiveCocoa // // Created by Cody Krieger on 5/18/12. // Copyright (c) 2012 Cody Krieger. All rights reserved. // #import "UITextView+RACSignalSupport.h" #import "EXTScope.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import "RACDelegateProxy.h" #import "RACSignal+Operations.h" #import "RACTuple.h" #import @implementation UITextView (RACSignalSupport) static void RACUseDelegateProxy(UITextView *self) { if (self.delegate == self.rac_delegateProxy) return; self.rac_delegateProxy.rac_proxiedDelegate = self.delegate; self.delegate = (id)self.rac_delegateProxy; } - (RACDelegateProxy *)rac_delegateProxy { RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd); if (proxy == nil) { proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UITextViewDelegate)]; objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return proxy; } - (RACSignal *)rac_textSignal { @weakify(self); RACSignal *signal = [[[[[RACSignal defer:^{ @strongify(self); return [RACSignal return:RACTuplePack(self)]; }] concat:[self.rac_delegateProxy signalForSelector:@selector(textViewDidChange:)]] reduceEach:^(UITextView *x) { return x.text; }] takeUntil:self.rac_willDeallocSignal] setNameWithFormat:@"%@ -rac_textSignal", RACDescription(self)]; RACUseDelegateProxy(self); return signal; } @end ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/extobjc/EXTKeyPathCoding.h ================================================ // // EXTKeyPathCoding.h // extobjc // // Created by Justin Spahr-Summers on 19.06.12. // Copyright (C) 2012 Justin Spahr-Summers. // Released under the MIT license. // #import #import "metamacros.h" /** * \@keypath allows compile-time verification of key paths. Given a real object * receiver and key path: * * @code NSString *UTF8StringPath = @keypath(str.lowercaseString.UTF8String); // => @"lowercaseString.UTF8String" NSString *versionPath = @keypath(NSObject, version); // => @"version" NSString *lowercaseStringPath = @keypath(NSString.new, lowercaseString); // => @"lowercaseString" * @endcode * * ... the macro returns an \c NSString containing all but the first path * component or argument (e.g., @"lowercaseString.UTF8String", @"version"). * * In addition to simply creating a key path, this macro ensures that the key * path is valid at compile-time (causing a syntax error if not), and supports * refactoring, such that changing the name of the property will also update any * uses of \@keypath. */ #define keypath(...) \ metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__))(keypath1(__VA_ARGS__))(keypath2(__VA_ARGS__)) #define keypath1(PATH) \ (((void)(NO && ((void)PATH, NO)), strchr(# PATH, '.') + 1)) #define keypath2(OBJ, PATH) \ (((void)(NO && ((void)OBJ.PATH, NO)), # PATH)) /** * \@collectionKeypath allows compile-time verification of key paths across collections NSArray/NSSet etc. Given a real object * receiver, collection object receiver and related keypaths: * * @code NSString *employessFirstNamePath = @collectionKeypath(department.employees, Employee.new, firstName) // => @"employees.firstName" NSString *employessFirstNamePath = @collectionKeypath(Department.new, employees, Employee.new, firstName) // => @"employees.firstName" * @endcode * */ #define collectionKeypath(...) \ metamacro_if_eq(3, metamacro_argcount(__VA_ARGS__))(collectionKeypath3(__VA_ARGS__))(collectionKeypath4(__VA_ARGS__)) #define collectionKeypath3(PATH, COLLECTION_OBJECT, COLLECTION_PATH) ([[NSString stringWithFormat:@"%s.%s",keypath(PATH), keypath(COLLECTION_OBJECT, COLLECTION_PATH)] UTF8String]) #define collectionKeypath4(OBJ, PATH, COLLECTION_OBJECT, COLLECTION_PATH) ([[NSString stringWithFormat:@"%s.%s",keypath(OBJ, PATH), keypath(COLLECTION_OBJECT, COLLECTION_PATH)] UTF8String]) ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/extobjc/EXTRuntimeExtensions.h ================================================ // // EXTRuntimeExtensions.h // extobjc // // Created by Justin Spahr-Summers on 2011-03-05. // Copyright (C) 2012 Justin Spahr-Summers. // Released under the MIT license. // #import /** * Describes the memory management policy of a property. */ typedef enum { /** * The value is assigned. */ rac_propertyMemoryManagementPolicyAssign = 0, /** * The value is retained. */ rac_propertyMemoryManagementPolicyRetain, /** * The value is copied. */ rac_propertyMemoryManagementPolicyCopy } rac_propertyMemoryManagementPolicy; /** * Describes the attributes and type information of a property. */ typedef struct { /** * Whether this property was declared with the \c readonly attribute. */ BOOL readonly; /** * Whether this property was declared with the \c nonatomic attribute. */ BOOL nonatomic; /** * Whether the property is a weak reference. */ BOOL weak; /** * Whether the property is eligible for garbage collection. */ BOOL canBeCollected; /** * Whether this property is defined with \c \@dynamic. */ BOOL dynamic; /** * The memory management policy for this property. This will always be * #rac_propertyMemoryManagementPolicyAssign if #readonly is \c YES. */ rac_propertyMemoryManagementPolicy memoryManagementPolicy; /** * The selector for the getter of this property. This will reflect any * custom \c getter= attribute provided in the property declaration, or the * inferred getter name otherwise. */ SEL getter; /** * The selector for the setter of this property. This will reflect any * custom \c setter= attribute provided in the property declaration, or the * inferred setter name otherwise. * * @note If #readonly is \c YES, this value will represent what the setter * \e would be, if the property were writable. */ SEL setter; /** * The backing instance variable for this property, or \c NULL if \c * \c @synthesize was not used, and therefore no instance variable exists. This * would also be the case if the property is implemented dynamically. */ const char *ivar; /** * If this property is defined as being an instance of a specific class, * this will be the class object representing it. * * This will be \c nil if the property was defined as type \c id, if the * property is not of an object type, or if the class could not be found at * runtime. */ Class objectClass; /** * The type encoding for the value of this property. This is the type as it * would be returned by the \c \@encode() directive. */ char type[]; } rac_propertyAttributes; /** * Finds the instance method named \a aSelector on \a aClass and returns it, or * returns \c NULL if no such instance method exists. Unlike \c * class_getInstanceMethod(), this does not search superclasses. * * @note To get class methods in this manner, use a metaclass for \a aClass. */ Method rac_getImmediateInstanceMethod (Class aClass, SEL aSelector); /** * Returns a pointer to a structure containing information about \a property. * You must \c free() the returned pointer. Returns \c NULL if there is an error * obtaining information from \a property. */ rac_propertyAttributes *rac_copyPropertyAttributes (objc_property_t property); ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/extobjc/EXTRuntimeExtensions.m ================================================ // // EXTRuntimeExtensions.m // extobjc // // Created by Justin Spahr-Summers on 2011-03-05. // Copyright (C) 2012 Justin Spahr-Summers. // Released under the MIT license. // #import "EXTRuntimeExtensions.h" #import #import #import #import #import #import #import #import rac_propertyAttributes *rac_copyPropertyAttributes (objc_property_t property) { const char * const attrString = property_getAttributes(property); if (!attrString) { fprintf(stderr, "ERROR: Could not get attribute string from property %s\n", property_getName(property)); return NULL; } if (attrString[0] != 'T') { fprintf(stderr, "ERROR: Expected attribute string \"%s\" for property %s to start with 'T'\n", attrString, property_getName(property)); return NULL; } const char *typeString = attrString + 1; const char *next = NSGetSizeAndAlignment(typeString, NULL, NULL); if (!next) { fprintf(stderr, "ERROR: Could not read past type in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); return NULL; } size_t typeLength = (size_t)(next - typeString); if (!typeLength) { fprintf(stderr, "ERROR: Invalid type in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); return NULL; } // allocate enough space for the structure and the type string (plus a NUL) rac_propertyAttributes *attributes = calloc(1, sizeof(rac_propertyAttributes) + typeLength + 1); if (!attributes) { fprintf(stderr, "ERROR: Could not allocate rac_propertyAttributes structure for attribute string \"%s\" for property %s\n", attrString, property_getName(property)); return NULL; } // copy the type string strncpy(attributes->type, typeString, typeLength); attributes->type[typeLength] = '\0'; // if this is an object type, and immediately followed by a quoted string... if (typeString[0] == *(@encode(id)) && typeString[1] == '"') { // we should be able to extract a class name const char *className = typeString + 2; next = strchr(className, '"'); if (!next) { fprintf(stderr, "ERROR: Could not read class name in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); return NULL; } if (className != next) { size_t classNameLength = (size_t)(next - className); char trimmedName[classNameLength + 1]; strncpy(trimmedName, className, classNameLength); trimmedName[classNameLength] = '\0'; // attempt to look up the class in the runtime attributes->objectClass = objc_getClass(trimmedName); } } if (*next != '\0') { // skip past any junk before the first flag next = strchr(next, ','); } while (next && *next == ',') { char flag = next[1]; next += 2; switch (flag) { case '\0': break; case 'R': attributes->readonly = YES; break; case 'C': attributes->memoryManagementPolicy = rac_propertyMemoryManagementPolicyCopy; break; case '&': attributes->memoryManagementPolicy = rac_propertyMemoryManagementPolicyRetain; break; case 'N': attributes->nonatomic = YES; break; case 'G': case 'S': { const char *nextFlag = strchr(next, ','); SEL name = NULL; if (!nextFlag) { // assume that the rest of the string is the selector const char *selectorString = next; next = ""; name = sel_registerName(selectorString); } else { size_t selectorLength = (size_t)(nextFlag - next); if (!selectorLength) { fprintf(stderr, "ERROR: Found zero length selector name in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); goto errorOut; } char selectorString[selectorLength + 1]; strncpy(selectorString, next, selectorLength); selectorString[selectorLength] = '\0'; name = sel_registerName(selectorString); next = nextFlag; } if (flag == 'G') attributes->getter = name; else attributes->setter = name; } break; case 'D': attributes->dynamic = YES; attributes->ivar = NULL; break; case 'V': // assume that the rest of the string (if present) is the ivar name if (*next == '\0') { // if there's nothing there, let's assume this is dynamic attributes->ivar = NULL; } else { attributes->ivar = next; next = ""; } break; case 'W': attributes->weak = YES; break; case 'P': attributes->canBeCollected = YES; break; case 't': fprintf(stderr, "ERROR: Old-style type encoding is unsupported in attribute string \"%s\" for property %s\n", attrString, property_getName(property)); // skip over this type encoding while (*next != ',' && *next != '\0') ++next; break; default: fprintf(stderr, "ERROR: Unrecognized attribute string flag '%c' in attribute string \"%s\" for property %s\n", flag, attrString, property_getName(property)); } } if (next && *next != '\0') { fprintf(stderr, "Warning: Unparsed data \"%s\" in attribute string \"%s\" for property %s\n", next, attrString, property_getName(property)); } if (!attributes->getter) { // use the property name as the getter by default attributes->getter = sel_registerName(property_getName(property)); } if (!attributes->setter) { const char *propertyName = property_getName(property); size_t propertyNameLength = strlen(propertyName); // we want to transform the name to setProperty: style size_t setterLength = propertyNameLength + 4; char setterName[setterLength + 1]; strncpy(setterName, "set", 3); strncpy(setterName + 3, propertyName, propertyNameLength); // capitalize property name for the setter setterName[3] = (char)toupper(setterName[3]); setterName[setterLength - 1] = ':'; setterName[setterLength] = '\0'; attributes->setter = sel_registerName(setterName); } return attributes; errorOut: free(attributes); return NULL; } Method rac_getImmediateInstanceMethod (Class aClass, SEL aSelector) { unsigned methodCount = 0; Method *methods = class_copyMethodList(aClass, &methodCount); Method foundMethod = NULL; for (unsigned methodIndex = 0;methodIndex < methodCount;++methodIndex) { if (method_getName(methods[methodIndex]) == aSelector) { foundMethod = methods[methodIndex]; break; } } free(methods); return foundMethod; } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/extobjc/EXTScope.h ================================================ // // EXTScope.h // extobjc // // Created by Justin Spahr-Summers on 2011-05-04. // Copyright (C) 2012 Justin Spahr-Summers. // Released under the MIT license. // #import "metamacros.h" /** * \@onExit defines some code to be executed when the current scope exits. The * code must be enclosed in braces and terminated with a semicolon, and will be * executed regardless of how the scope is exited, including from exceptions, * \c goto, \c return, \c break, and \c continue. * * Provided code will go into a block to be executed later. Keep this in mind as * it pertains to memory management, restrictions on assignment, etc. Because * the code is used within a block, \c return is a legal (though perhaps * confusing) way to exit the cleanup block early. * * Multiple \@onExit statements in the same scope are executed in reverse * lexical order. This helps when pairing resource acquisition with \@onExit * statements, as it guarantees teardown in the opposite order of acquisition. * * @note This statement cannot be used within scopes defined without braces * (like a one line \c if). In practice, this is not an issue, since \@onExit is * a useless construct in such a case anyways. */ #define onExit \ rac_keywordify \ __strong rac_cleanupBlock_t metamacro_concat(rac_exitBlock_, __LINE__) __attribute__((cleanup(rac_executeCleanupBlock), unused)) = ^ /** * Creates \c __weak shadow variables for each of the variables provided as * arguments, which can later be made strong again with #strongify. * * This is typically used to weakly reference variables in a block, but then * ensure that the variables stay alive during the actual execution of the block * (if they were live upon entry). * * See #strongify for an example of usage. */ #define weakify(...) \ rac_keywordify \ metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__) /** * Like #weakify, but uses \c __unsafe_unretained instead, for targets or * classes that do not support weak references. */ #define unsafeify(...) \ rac_keywordify \ metamacro_foreach_cxt(rac_weakify_,, __unsafe_unretained, __VA_ARGS__) /** * Strongly references each of the variables provided as arguments, which must * have previously been passed to #weakify. * * The strong references created will shadow the original variable names, such * that the original names can be used without issue (and a significantly * reduced risk of retain cycles) in the current scope. * * @code id foo = [[NSObject alloc] init]; id bar = [[NSObject alloc] init]; @weakify(foo, bar); // this block will not keep 'foo' or 'bar' alive BOOL (^matchesFooOrBar)(id) = ^ BOOL (id obj){ // but now, upon entry, 'foo' and 'bar' will stay alive until the block has // finished executing @strongify(foo, bar); return [foo isEqual:obj] || [bar isEqual:obj]; }; * @endcode */ #define strongify(...) \ rac_keywordify \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wshadow\"") \ metamacro_foreach(rac_strongify_,, __VA_ARGS__) \ _Pragma("clang diagnostic pop") /*** implementation details follow ***/ typedef void (^rac_cleanupBlock_t)(); static inline void rac_executeCleanupBlock (__strong rac_cleanupBlock_t *block) { (*block)(); } #define rac_weakify_(INDEX, CONTEXT, VAR) \ CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR); #define rac_strongify_(INDEX, VAR) \ __strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_); // Details about the choice of backing keyword: // // The use of @try/@catch/@finally can cause the compiler to suppress // return-type warnings. // The use of @autoreleasepool {} is not optimized away by the compiler, // resulting in superfluous creation of autorelease pools. // // Since neither option is perfect, and with no other alternatives, the // compromise is to use @autorelease in DEBUG builds to maintain compiler // analysis, and to use @try/@catch otherwise to avoid insertion of unnecessary // autorelease pools. #if DEBUG #define rac_keywordify autoreleasepool {} #else #define rac_keywordify try {} @catch (...) {} #endif ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Objective-C/extobjc/metamacros.h ================================================ /** * Macros for metaprogramming * ExtendedC * * Copyright (C) 2012 Justin Spahr-Summers * Released under the MIT license */ #ifndef EXTC_METAMACROS_H #define EXTC_METAMACROS_H /** * Executes one or more expressions (which may have a void type, such as a call * to a function that returns no value) and always returns true. */ #define metamacro_exprify(...) \ ((__VA_ARGS__), true) /** * Returns a string representation of VALUE after full macro expansion. */ #define metamacro_stringify(VALUE) \ metamacro_stringify_(VALUE) /** * Returns A and B concatenated after full macro expansion. */ #define metamacro_concat(A, B) \ metamacro_concat_(A, B) /** * Returns the Nth variadic argument (starting from zero). At least * N + 1 variadic arguments must be given. N must be between zero and twenty, * inclusive. */ #define metamacro_at(N, ...) \ metamacro_concat(metamacro_at, N)(__VA_ARGS__) /** * Returns the number of arguments (up to twenty) provided to the macro. At * least one argument must be provided. * * Inspired by P99: http://p99.gforge.inria.fr */ #define metamacro_argcount(...) \ metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) /** * Identical to #metamacro_foreach_cxt, except that no CONTEXT argument is * given. Only the index and current argument will thus be passed to MACRO. */ #define metamacro_foreach(MACRO, SEP, ...) \ metamacro_foreach_cxt(metamacro_foreach_iter, SEP, MACRO, __VA_ARGS__) /** * For each consecutive variadic argument (up to twenty), MACRO is passed the * zero-based index of the current argument, CONTEXT, and then the argument * itself. The results of adjoining invocations of MACRO are then separated by * SEP. * * Inspired by P99: http://p99.gforge.inria.fr */ #define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \ metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__) /** * Identical to #metamacro_foreach_cxt. This can be used when the former would * fail due to recursive macro expansion. */ #define metamacro_foreach_cxt_recursive(MACRO, SEP, CONTEXT, ...) \ metamacro_concat(metamacro_foreach_cxt_recursive, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__) /** * In consecutive order, appends each variadic argument (up to twenty) onto * BASE. The resulting concatenations are then separated by SEP. * * This is primarily useful to manipulate a list of macro invocations into instead * invoking a different, possibly related macro. */ #define metamacro_foreach_concat(BASE, SEP, ...) \ metamacro_foreach_cxt(metamacro_foreach_concat_iter, SEP, BASE, __VA_ARGS__) /** * Iterates COUNT times, each time invoking MACRO with the current index * (starting at zero) and CONTEXT. The results of adjoining invocations of MACRO * are then separated by SEP. * * COUNT must be an integer between zero and twenty, inclusive. */ #define metamacro_for_cxt(COUNT, MACRO, SEP, CONTEXT) \ metamacro_concat(metamacro_for_cxt, COUNT)(MACRO, SEP, CONTEXT) /** * Returns the first argument given. At least one argument must be provided. * * This is useful when implementing a variadic macro, where you may have only * one variadic argument, but no way to retrieve it (for example, because \c ... * always needs to match at least one argument). * * @code #define varmacro(...) \ metamacro_head(__VA_ARGS__) * @endcode */ #define metamacro_head(...) \ metamacro_head_(__VA_ARGS__, 0) /** * Returns every argument except the first. At least two arguments must be * provided. */ #define metamacro_tail(...) \ metamacro_tail_(__VA_ARGS__) /** * Returns the first N (up to twenty) variadic arguments as a new argument list. * At least N variadic arguments must be provided. */ #define metamacro_take(N, ...) \ metamacro_concat(metamacro_take, N)(__VA_ARGS__) /** * Removes the first N (up to twenty) variadic arguments from the given argument * list. At least N variadic arguments must be provided. */ #define metamacro_drop(N, ...) \ metamacro_concat(metamacro_drop, N)(__VA_ARGS__) /** * Decrements VAL, which must be a number between zero and twenty, inclusive. * * This is primarily useful when dealing with indexes and counts in * metaprogramming. */ #define metamacro_dec(VAL) \ metamacro_at(VAL, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) /** * Increments VAL, which must be a number between zero and twenty, inclusive. * * This is primarily useful when dealing with indexes and counts in * metaprogramming. */ #define metamacro_inc(VAL) \ metamacro_at(VAL, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21) /** * If A is equal to B, the next argument list is expanded; otherwise, the * argument list after that is expanded. A and B must be numbers between zero * and twenty, inclusive. Additionally, B must be greater than or equal to A. * * @code // expands to true metamacro_if_eq(0, 0)(true)(false) // expands to false metamacro_if_eq(0, 1)(true)(false) * @endcode * * This is primarily useful when dealing with indexes and counts in * metaprogramming. */ #define metamacro_if_eq(A, B) \ metamacro_concat(metamacro_if_eq, A)(B) /** * Identical to #metamacro_if_eq. This can be used when the former would fail * due to recursive macro expansion. */ #define metamacro_if_eq_recursive(A, B) \ metamacro_concat(metamacro_if_eq_recursive, A)(B) /** * Returns 1 if N is an even number, or 0 otherwise. N must be between zero and * twenty, inclusive. * * For the purposes of this test, zero is considered even. */ #define metamacro_is_even(N) \ metamacro_at(N, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1) /** * Returns the logical NOT of B, which must be the number zero or one. */ #define metamacro_not(B) \ metamacro_at(B, 1, 0) // IMPLEMENTATION DETAILS FOLLOW! // Do not write code that depends on anything below this line. #define metamacro_stringify_(VALUE) # VALUE #define metamacro_concat_(A, B) A ## B #define metamacro_foreach_iter(INDEX, MACRO, ARG) MACRO(INDEX, ARG) #define metamacro_head_(FIRST, ...) FIRST #define metamacro_tail_(FIRST, ...) __VA_ARGS__ #define metamacro_consume_(...) #define metamacro_expand_(...) __VA_ARGS__ // implemented from scratch so that metamacro_concat() doesn't end up nesting #define metamacro_foreach_concat_iter(INDEX, BASE, ARG) metamacro_foreach_concat_iter_(BASE, ARG) #define metamacro_foreach_concat_iter_(BASE, ARG) BASE ## ARG // metamacro_at expansions #define metamacro_at0(...) metamacro_head(__VA_ARGS__) #define metamacro_at1(_0, ...) metamacro_head(__VA_ARGS__) #define metamacro_at2(_0, _1, ...) metamacro_head(__VA_ARGS__) #define metamacro_at3(_0, _1, _2, ...) metamacro_head(__VA_ARGS__) #define metamacro_at4(_0, _1, _2, _3, ...) metamacro_head(__VA_ARGS__) #define metamacro_at5(_0, _1, _2, _3, _4, ...) metamacro_head(__VA_ARGS__) #define metamacro_at6(_0, _1, _2, _3, _4, _5, ...) metamacro_head(__VA_ARGS__) #define metamacro_at7(_0, _1, _2, _3, _4, _5, _6, ...) metamacro_head(__VA_ARGS__) #define metamacro_at8(_0, _1, _2, _3, _4, _5, _6, _7, ...) metamacro_head(__VA_ARGS__) #define metamacro_at9(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) metamacro_head(__VA_ARGS__) #define metamacro_at10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) metamacro_head(__VA_ARGS__) #define metamacro_at11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) metamacro_head(__VA_ARGS__) #define metamacro_at12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, ...) metamacro_head(__VA_ARGS__) #define metamacro_at13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) metamacro_head(__VA_ARGS__) #define metamacro_at14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) metamacro_head(__VA_ARGS__) #define metamacro_at15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) metamacro_head(__VA_ARGS__) #define metamacro_at16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) metamacro_head(__VA_ARGS__) #define metamacro_at17(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) metamacro_head(__VA_ARGS__) #define metamacro_at18(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, ...) metamacro_head(__VA_ARGS__) #define metamacro_at19(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, ...) metamacro_head(__VA_ARGS__) #define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) metamacro_head(__VA_ARGS__) // metamacro_foreach_cxt expansions #define metamacro_foreach_cxt0(MACRO, SEP, CONTEXT) #define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0) #define metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \ metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) \ SEP \ MACRO(1, CONTEXT, _1) #define metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \ metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \ SEP \ MACRO(2, CONTEXT, _2) #define metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \ SEP \ MACRO(3, CONTEXT, _3) #define metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ SEP \ MACRO(4, CONTEXT, _4) #define metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ SEP \ MACRO(5, CONTEXT, _5) #define metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ SEP \ MACRO(6, CONTEXT, _6) #define metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ SEP \ MACRO(7, CONTEXT, _7) #define metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ SEP \ MACRO(8, CONTEXT, _8) #define metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ SEP \ MACRO(9, CONTEXT, _9) #define metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ SEP \ MACRO(10, CONTEXT, _10) #define metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ SEP \ MACRO(11, CONTEXT, _11) #define metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ SEP \ MACRO(12, CONTEXT, _12) #define metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ SEP \ MACRO(13, CONTEXT, _13) #define metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ SEP \ MACRO(14, CONTEXT, _14) #define metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ SEP \ MACRO(15, CONTEXT, _15) #define metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ SEP \ MACRO(16, CONTEXT, _16) #define metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ SEP \ MACRO(17, CONTEXT, _17) #define metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ SEP \ MACRO(18, CONTEXT, _18) #define metamacro_foreach_cxt20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \ metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ SEP \ MACRO(19, CONTEXT, _19) // metamacro_foreach_cxt_recursive expansions #define metamacro_foreach_cxt_recursive0(MACRO, SEP, CONTEXT) #define metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0) #define metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \ metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) \ SEP \ MACRO(1, CONTEXT, _1) #define metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \ metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \ SEP \ MACRO(2, CONTEXT, _2) #define metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \ SEP \ MACRO(3, CONTEXT, _3) #define metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ SEP \ MACRO(4, CONTEXT, _4) #define metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ SEP \ MACRO(5, CONTEXT, _5) #define metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ SEP \ MACRO(6, CONTEXT, _6) #define metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ SEP \ MACRO(7, CONTEXT, _7) #define metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ SEP \ MACRO(8, CONTEXT, _8) #define metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ SEP \ MACRO(9, CONTEXT, _9) #define metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ SEP \ MACRO(10, CONTEXT, _10) #define metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ SEP \ MACRO(11, CONTEXT, _11) #define metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ SEP \ MACRO(12, CONTEXT, _12) #define metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ SEP \ MACRO(13, CONTEXT, _13) #define metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ SEP \ MACRO(14, CONTEXT, _14) #define metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ SEP \ MACRO(15, CONTEXT, _15) #define metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ SEP \ MACRO(16, CONTEXT, _16) #define metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ SEP \ MACRO(17, CONTEXT, _17) #define metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ SEP \ MACRO(18, CONTEXT, _18) #define metamacro_foreach_cxt_recursive20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \ metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ SEP \ MACRO(19, CONTEXT, _19) // metamacro_for_cxt expansions #define metamacro_for_cxt0(MACRO, SEP, CONTEXT) #define metamacro_for_cxt1(MACRO, SEP, CONTEXT) MACRO(0, CONTEXT) #define metamacro_for_cxt2(MACRO, SEP, CONTEXT) \ metamacro_for_cxt1(MACRO, SEP, CONTEXT) \ SEP \ MACRO(1, CONTEXT) #define metamacro_for_cxt3(MACRO, SEP, CONTEXT) \ metamacro_for_cxt2(MACRO, SEP, CONTEXT) \ SEP \ MACRO(2, CONTEXT) #define metamacro_for_cxt4(MACRO, SEP, CONTEXT) \ metamacro_for_cxt3(MACRO, SEP, CONTEXT) \ SEP \ MACRO(3, CONTEXT) #define metamacro_for_cxt5(MACRO, SEP, CONTEXT) \ metamacro_for_cxt4(MACRO, SEP, CONTEXT) \ SEP \ MACRO(4, CONTEXT) #define metamacro_for_cxt6(MACRO, SEP, CONTEXT) \ metamacro_for_cxt5(MACRO, SEP, CONTEXT) \ SEP \ MACRO(5, CONTEXT) #define metamacro_for_cxt7(MACRO, SEP, CONTEXT) \ metamacro_for_cxt6(MACRO, SEP, CONTEXT) \ SEP \ MACRO(6, CONTEXT) #define metamacro_for_cxt8(MACRO, SEP, CONTEXT) \ metamacro_for_cxt7(MACRO, SEP, CONTEXT) \ SEP \ MACRO(7, CONTEXT) #define metamacro_for_cxt9(MACRO, SEP, CONTEXT) \ metamacro_for_cxt8(MACRO, SEP, CONTEXT) \ SEP \ MACRO(8, CONTEXT) #define metamacro_for_cxt10(MACRO, SEP, CONTEXT) \ metamacro_for_cxt9(MACRO, SEP, CONTEXT) \ SEP \ MACRO(9, CONTEXT) #define metamacro_for_cxt11(MACRO, SEP, CONTEXT) \ metamacro_for_cxt10(MACRO, SEP, CONTEXT) \ SEP \ MACRO(10, CONTEXT) #define metamacro_for_cxt12(MACRO, SEP, CONTEXT) \ metamacro_for_cxt11(MACRO, SEP, CONTEXT) \ SEP \ MACRO(11, CONTEXT) #define metamacro_for_cxt13(MACRO, SEP, CONTEXT) \ metamacro_for_cxt12(MACRO, SEP, CONTEXT) \ SEP \ MACRO(12, CONTEXT) #define metamacro_for_cxt14(MACRO, SEP, CONTEXT) \ metamacro_for_cxt13(MACRO, SEP, CONTEXT) \ SEP \ MACRO(13, CONTEXT) #define metamacro_for_cxt15(MACRO, SEP, CONTEXT) \ metamacro_for_cxt14(MACRO, SEP, CONTEXT) \ SEP \ MACRO(14, CONTEXT) #define metamacro_for_cxt16(MACRO, SEP, CONTEXT) \ metamacro_for_cxt15(MACRO, SEP, CONTEXT) \ SEP \ MACRO(15, CONTEXT) #define metamacro_for_cxt17(MACRO, SEP, CONTEXT) \ metamacro_for_cxt16(MACRO, SEP, CONTEXT) \ SEP \ MACRO(16, CONTEXT) #define metamacro_for_cxt18(MACRO, SEP, CONTEXT) \ metamacro_for_cxt17(MACRO, SEP, CONTEXT) \ SEP \ MACRO(17, CONTEXT) #define metamacro_for_cxt19(MACRO, SEP, CONTEXT) \ metamacro_for_cxt18(MACRO, SEP, CONTEXT) \ SEP \ MACRO(18, CONTEXT) #define metamacro_for_cxt20(MACRO, SEP, CONTEXT) \ metamacro_for_cxt19(MACRO, SEP, CONTEXT) \ SEP \ MACRO(19, CONTEXT) // metamacro_if_eq expansions #define metamacro_if_eq0(VALUE) \ metamacro_concat(metamacro_if_eq0_, VALUE) #define metamacro_if_eq0_0(...) __VA_ARGS__ metamacro_consume_ #define metamacro_if_eq0_1(...) metamacro_expand_ #define metamacro_if_eq0_2(...) metamacro_expand_ #define metamacro_if_eq0_3(...) metamacro_expand_ #define metamacro_if_eq0_4(...) metamacro_expand_ #define metamacro_if_eq0_5(...) metamacro_expand_ #define metamacro_if_eq0_6(...) metamacro_expand_ #define metamacro_if_eq0_7(...) metamacro_expand_ #define metamacro_if_eq0_8(...) metamacro_expand_ #define metamacro_if_eq0_9(...) metamacro_expand_ #define metamacro_if_eq0_10(...) metamacro_expand_ #define metamacro_if_eq0_11(...) metamacro_expand_ #define metamacro_if_eq0_12(...) metamacro_expand_ #define metamacro_if_eq0_13(...) metamacro_expand_ #define metamacro_if_eq0_14(...) metamacro_expand_ #define metamacro_if_eq0_15(...) metamacro_expand_ #define metamacro_if_eq0_16(...) metamacro_expand_ #define metamacro_if_eq0_17(...) metamacro_expand_ #define metamacro_if_eq0_18(...) metamacro_expand_ #define metamacro_if_eq0_19(...) metamacro_expand_ #define metamacro_if_eq0_20(...) metamacro_expand_ #define metamacro_if_eq1(VALUE) metamacro_if_eq0(metamacro_dec(VALUE)) #define metamacro_if_eq2(VALUE) metamacro_if_eq1(metamacro_dec(VALUE)) #define metamacro_if_eq3(VALUE) metamacro_if_eq2(metamacro_dec(VALUE)) #define metamacro_if_eq4(VALUE) metamacro_if_eq3(metamacro_dec(VALUE)) #define metamacro_if_eq5(VALUE) metamacro_if_eq4(metamacro_dec(VALUE)) #define metamacro_if_eq6(VALUE) metamacro_if_eq5(metamacro_dec(VALUE)) #define metamacro_if_eq7(VALUE) metamacro_if_eq6(metamacro_dec(VALUE)) #define metamacro_if_eq8(VALUE) metamacro_if_eq7(metamacro_dec(VALUE)) #define metamacro_if_eq9(VALUE) metamacro_if_eq8(metamacro_dec(VALUE)) #define metamacro_if_eq10(VALUE) metamacro_if_eq9(metamacro_dec(VALUE)) #define metamacro_if_eq11(VALUE) metamacro_if_eq10(metamacro_dec(VALUE)) #define metamacro_if_eq12(VALUE) metamacro_if_eq11(metamacro_dec(VALUE)) #define metamacro_if_eq13(VALUE) metamacro_if_eq12(metamacro_dec(VALUE)) #define metamacro_if_eq14(VALUE) metamacro_if_eq13(metamacro_dec(VALUE)) #define metamacro_if_eq15(VALUE) metamacro_if_eq14(metamacro_dec(VALUE)) #define metamacro_if_eq16(VALUE) metamacro_if_eq15(metamacro_dec(VALUE)) #define metamacro_if_eq17(VALUE) metamacro_if_eq16(metamacro_dec(VALUE)) #define metamacro_if_eq18(VALUE) metamacro_if_eq17(metamacro_dec(VALUE)) #define metamacro_if_eq19(VALUE) metamacro_if_eq18(metamacro_dec(VALUE)) #define metamacro_if_eq20(VALUE) metamacro_if_eq19(metamacro_dec(VALUE)) // metamacro_if_eq_recursive expansions #define metamacro_if_eq_recursive0(VALUE) \ metamacro_concat(metamacro_if_eq_recursive0_, VALUE) #define metamacro_if_eq_recursive0_0(...) __VA_ARGS__ metamacro_consume_ #define metamacro_if_eq_recursive0_1(...) metamacro_expand_ #define metamacro_if_eq_recursive0_2(...) metamacro_expand_ #define metamacro_if_eq_recursive0_3(...) metamacro_expand_ #define metamacro_if_eq_recursive0_4(...) metamacro_expand_ #define metamacro_if_eq_recursive0_5(...) metamacro_expand_ #define metamacro_if_eq_recursive0_6(...) metamacro_expand_ #define metamacro_if_eq_recursive0_7(...) metamacro_expand_ #define metamacro_if_eq_recursive0_8(...) metamacro_expand_ #define metamacro_if_eq_recursive0_9(...) metamacro_expand_ #define metamacro_if_eq_recursive0_10(...) metamacro_expand_ #define metamacro_if_eq_recursive0_11(...) metamacro_expand_ #define metamacro_if_eq_recursive0_12(...) metamacro_expand_ #define metamacro_if_eq_recursive0_13(...) metamacro_expand_ #define metamacro_if_eq_recursive0_14(...) metamacro_expand_ #define metamacro_if_eq_recursive0_15(...) metamacro_expand_ #define metamacro_if_eq_recursive0_16(...) metamacro_expand_ #define metamacro_if_eq_recursive0_17(...) metamacro_expand_ #define metamacro_if_eq_recursive0_18(...) metamacro_expand_ #define metamacro_if_eq_recursive0_19(...) metamacro_expand_ #define metamacro_if_eq_recursive0_20(...) metamacro_expand_ #define metamacro_if_eq_recursive1(VALUE) metamacro_if_eq_recursive0(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive2(VALUE) metamacro_if_eq_recursive1(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive3(VALUE) metamacro_if_eq_recursive2(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive4(VALUE) metamacro_if_eq_recursive3(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive5(VALUE) metamacro_if_eq_recursive4(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive6(VALUE) metamacro_if_eq_recursive5(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive7(VALUE) metamacro_if_eq_recursive6(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive8(VALUE) metamacro_if_eq_recursive7(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive9(VALUE) metamacro_if_eq_recursive8(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive10(VALUE) metamacro_if_eq_recursive9(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive11(VALUE) metamacro_if_eq_recursive10(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive12(VALUE) metamacro_if_eq_recursive11(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive13(VALUE) metamacro_if_eq_recursive12(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive14(VALUE) metamacro_if_eq_recursive13(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive15(VALUE) metamacro_if_eq_recursive14(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive16(VALUE) metamacro_if_eq_recursive15(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive17(VALUE) metamacro_if_eq_recursive16(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive18(VALUE) metamacro_if_eq_recursive17(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive19(VALUE) metamacro_if_eq_recursive18(metamacro_dec(VALUE)) #define metamacro_if_eq_recursive20(VALUE) metamacro_if_eq_recursive19(metamacro_dec(VALUE)) // metamacro_take expansions #define metamacro_take0(...) #define metamacro_take1(...) metamacro_head(__VA_ARGS__) #define metamacro_take2(...) metamacro_head(__VA_ARGS__), metamacro_take1(metamacro_tail(__VA_ARGS__)) #define metamacro_take3(...) metamacro_head(__VA_ARGS__), metamacro_take2(metamacro_tail(__VA_ARGS__)) #define metamacro_take4(...) metamacro_head(__VA_ARGS__), metamacro_take3(metamacro_tail(__VA_ARGS__)) #define metamacro_take5(...) metamacro_head(__VA_ARGS__), metamacro_take4(metamacro_tail(__VA_ARGS__)) #define metamacro_take6(...) metamacro_head(__VA_ARGS__), metamacro_take5(metamacro_tail(__VA_ARGS__)) #define metamacro_take7(...) metamacro_head(__VA_ARGS__), metamacro_take6(metamacro_tail(__VA_ARGS__)) #define metamacro_take8(...) metamacro_head(__VA_ARGS__), metamacro_take7(metamacro_tail(__VA_ARGS__)) #define metamacro_take9(...) metamacro_head(__VA_ARGS__), metamacro_take8(metamacro_tail(__VA_ARGS__)) #define metamacro_take10(...) metamacro_head(__VA_ARGS__), metamacro_take9(metamacro_tail(__VA_ARGS__)) #define metamacro_take11(...) metamacro_head(__VA_ARGS__), metamacro_take10(metamacro_tail(__VA_ARGS__)) #define metamacro_take12(...) metamacro_head(__VA_ARGS__), metamacro_take11(metamacro_tail(__VA_ARGS__)) #define metamacro_take13(...) metamacro_head(__VA_ARGS__), metamacro_take12(metamacro_tail(__VA_ARGS__)) #define metamacro_take14(...) metamacro_head(__VA_ARGS__), metamacro_take13(metamacro_tail(__VA_ARGS__)) #define metamacro_take15(...) metamacro_head(__VA_ARGS__), metamacro_take14(metamacro_tail(__VA_ARGS__)) #define metamacro_take16(...) metamacro_head(__VA_ARGS__), metamacro_take15(metamacro_tail(__VA_ARGS__)) #define metamacro_take17(...) metamacro_head(__VA_ARGS__), metamacro_take16(metamacro_tail(__VA_ARGS__)) #define metamacro_take18(...) metamacro_head(__VA_ARGS__), metamacro_take17(metamacro_tail(__VA_ARGS__)) #define metamacro_take19(...) metamacro_head(__VA_ARGS__), metamacro_take18(metamacro_tail(__VA_ARGS__)) #define metamacro_take20(...) metamacro_head(__VA_ARGS__), metamacro_take19(metamacro_tail(__VA_ARGS__)) // metamacro_drop expansions #define metamacro_drop0(...) __VA_ARGS__ #define metamacro_drop1(...) metamacro_tail(__VA_ARGS__) #define metamacro_drop2(...) metamacro_drop1(metamacro_tail(__VA_ARGS__)) #define metamacro_drop3(...) metamacro_drop2(metamacro_tail(__VA_ARGS__)) #define metamacro_drop4(...) metamacro_drop3(metamacro_tail(__VA_ARGS__)) #define metamacro_drop5(...) metamacro_drop4(metamacro_tail(__VA_ARGS__)) #define metamacro_drop6(...) metamacro_drop5(metamacro_tail(__VA_ARGS__)) #define metamacro_drop7(...) metamacro_drop6(metamacro_tail(__VA_ARGS__)) #define metamacro_drop8(...) metamacro_drop7(metamacro_tail(__VA_ARGS__)) #define metamacro_drop9(...) metamacro_drop8(metamacro_tail(__VA_ARGS__)) #define metamacro_drop10(...) metamacro_drop9(metamacro_tail(__VA_ARGS__)) #define metamacro_drop11(...) metamacro_drop10(metamacro_tail(__VA_ARGS__)) #define metamacro_drop12(...) metamacro_drop11(metamacro_tail(__VA_ARGS__)) #define metamacro_drop13(...) metamacro_drop12(metamacro_tail(__VA_ARGS__)) #define metamacro_drop14(...) metamacro_drop13(metamacro_tail(__VA_ARGS__)) #define metamacro_drop15(...) metamacro_drop14(metamacro_tail(__VA_ARGS__)) #define metamacro_drop16(...) metamacro_drop15(metamacro_tail(__VA_ARGS__)) #define metamacro_drop17(...) metamacro_drop16(metamacro_tail(__VA_ARGS__)) #define metamacro_drop18(...) metamacro_drop17(metamacro_tail(__VA_ARGS__)) #define metamacro_drop19(...) metamacro_drop18(metamacro_tail(__VA_ARGS__)) #define metamacro_drop20(...) metamacro_drop19(metamacro_tail(__VA_ARGS__)) #endif ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/ReactiveCocoa.h ================================================ // // ReactiveCocoa.h // ReactiveCocoa // // Created by Josh Abernathy on 3/5/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import //! Project version number for ReactiveCocoa. FOUNDATION_EXPORT double ReactiveCocoaVersionNumber; //! Project version string for ReactiveCocoa. FOUNDATION_EXPORT const unsigned char ReactiveCocoaVersionString[]; #import "EXTKeyPathCoding.h" #import "EXTScope.h" #import "NSArray+RACSequenceAdditions.h" #import "NSData+RACSupport.h" #import "NSDictionary+RACSequenceAdditions.h" #import "NSEnumerator+RACSequenceAdditions.h" #import "NSFileHandle+RACSupport.h" #import "NSNotificationCenter+RACSupport.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACLifting.h" #import "NSObject+RACPropertySubscribing.h" #import "NSObject+RACSelectorSignal.h" #import "NSOrderedSet+RACSequenceAdditions.h" #import "NSSet+RACSequenceAdditions.h" #import "NSString+RACSequenceAdditions.h" #import "NSString+RACSupport.h" #import "NSIndexSet+RACSequenceAdditions.h" #import "NSUserDefaults+RACSupport.h" #import "RACBehaviorSubject.h" #import "RACChannel.h" #import "RACCommand.h" #import "RACCompoundDisposable.h" #import "RACDisposable.h" #import "RACDynamicPropertySuperclass.h" #import "RACEvent.h" #import "RACGroupedSignal.h" #import "RACKVOChannel.h" #import "RACMulticastConnection.h" #import "RACQueueScheduler.h" #import "RACQueueScheduler+Subclass.h" #import "RACReplaySubject.h" #import "RACScheduler.h" #import "RACScheduler+Subclass.h" #import "RACScopedDisposable.h" #import "RACSequence.h" #import "RACSerialDisposable.h" #import "RACSignal+Operations.h" #import "RACSignal.h" #import "RACStream.h" #import "RACSubject.h" #import "RACSubscriber.h" #import "RACSubscriptingAssignmentTrampoline.h" #import "RACTargetQueueScheduler.h" #import "RACTestScheduler.h" #import "RACTuple.h" #import "RACUnit.h" #if TARGET_OS_WATCH #elif TARGET_OS_TV #elif TARGET_OS_IPHONE #import "MKAnnotationView+RACSignalSupport.h" #import "UIActionSheet+RACSignalSupport.h" #import "UIAlertView+RACSignalSupport.h" #import "UIBarButtonItem+RACCommandSupport.h" #import "UIButton+RACCommandSupport.h" #import "UICollectionReusableView+RACSignalSupport.h" #import "UIControl+RACSignalSupport.h" #import "UIDatePicker+RACSignalSupport.h" #import "UIGestureRecognizer+RACSignalSupport.h" #import "UIImagePickerController+RACSignalSupport.h" #import "UIRefreshControl+RACCommandSupport.h" #import "UISegmentedControl+RACSignalSupport.h" #import "UISlider+RACSignalSupport.h" #import "UIStepper+RACSignalSupport.h" #import "UISwitch+RACSignalSupport.h" #import "UITableViewCell+RACSignalSupport.h" #import "UITableViewHeaderFooterView+RACSignalSupport.h" #import "UITextField+RACSignalSupport.h" #import "UITextView+RACSignalSupport.h" #import "NSURLConnection+RACSupport.h" #elif TARGET_OS_MAC #import "NSControl+RACCommandSupport.h" #import "NSControl+RACTextSignalSupport.h" #import "NSObject+RACAppKitBindings.h" #import "NSText+RACSignalSupport.h" #import "NSURLConnection+RACSupport.h" #endif ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Action.swift ================================================ /// Represents an action that will do some work when executed with a value of /// type `Input`, then return zero or more values of type `Output` and/or fail /// with an error of type `Error`. If no failure should be possible, NoError can /// be specified for the `Error` parameter. /// /// Actions enforce serial execution. Any attempt to execute an action multiple /// times concurrently will return an error. public final class Action { private let executeClosure: Input -> SignalProducer private let eventsObserver: Signal, NoError>.Observer /// A signal of all events generated from applications of the Action. /// /// In other words, this will send every `Event` from every signal generated /// by each SignalProducer returned from apply(). public let events: Signal, NoError> /// A signal of all values generated from applications of the Action. /// /// In other words, this will send every value from every signal generated /// by each SignalProducer returned from apply(). public let values: Signal /// A signal of all errors generated from applications of the Action. /// /// In other words, this will send errors from every signal generated by /// each SignalProducer returned from apply(). public let errors: Signal /// Whether the action is currently executing. public var executing: AnyProperty { return AnyProperty(_executing) } private let _executing: MutableProperty = MutableProperty(false) /// Whether the action is currently enabled. public var enabled: AnyProperty { return AnyProperty(_enabled) } private let _enabled: MutableProperty = MutableProperty(false) /// Whether the instantiator of this action wants it to be enabled. private let userEnabled: AnyProperty /// Lazy creation and storage of a UI bindable `CocoaAction`. The default behavior /// force casts the AnyObject? input to match the action's `Input` type. This makes /// it unsafe for use when the action is parameterized for something like `Void` /// input. In those cases, explicitly assign a value to this property that transforms /// the input to suit your needs. public lazy var unsafeCocoaAction: CocoaAction = CocoaAction(self) { $0 as! Input } /// This queue is used for read-modify-write operations on the `_executing` /// property. private let executingQueue = dispatch_queue_create("org.reactivecocoa.ReactiveCocoa.Action.executingQueue", DISPATCH_QUEUE_SERIAL) /// Whether the action should be enabled for the given combination of user /// enabledness and executing status. private static func shouldBeEnabled(userEnabled userEnabled: Bool, executing: Bool) -> Bool { return userEnabled && !executing } /// Initializes an action that will be conditionally enabled, and create a /// SignalProducer for each input. public init(enabledIf: P, _ execute: Input -> SignalProducer) { executeClosure = execute userEnabled = AnyProperty(enabledIf) (events, eventsObserver) = Signal, NoError>.pipe() values = events.map { $0.value }.ignoreNil() errors = events.map { $0.error }.ignoreNil() _enabled <~ enabledIf.producer .combineLatestWith(executing.producer) .map(Action.shouldBeEnabled) } /// Initializes an action that will be enabled by default, and create a /// SignalProducer for each input. public convenience init(_ execute: Input -> SignalProducer) { self.init(enabledIf: ConstantProperty(true), execute) } deinit { eventsObserver.sendCompleted() } /// Creates a SignalProducer that, when started, will execute the action /// with the given input, then forward the results upon the produced Signal. /// /// If the action is disabled when the returned SignalProducer is started, /// the produced signal will send `ActionError.NotEnabled`, and nothing will /// be sent upon `values` or `errors` for that particular signal. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func apply(input: Input) -> SignalProducer> { return SignalProducer { observer, disposable in var startedExecuting = false dispatch_sync(self.executingQueue) { if self._enabled.value { self._executing.value = true startedExecuting = true } } if !startedExecuting { observer.sendFailed(.NotEnabled) return } self.executeClosure(input).startWithSignal { signal, signalDisposable in disposable.addDisposable(signalDisposable) signal.observe { event in observer.action(event.mapError { .ProducerError($0) }) self.eventsObserver.sendNext(event) } } disposable.addDisposable { self._executing.value = false } } } } /// Wraps an Action for use by a GUI control (such as `NSControl` or /// `UIControl`), with KVO, or with Cocoa Bindings. public final class CocoaAction: NSObject { /// The selector that a caller should invoke upon a CocoaAction in order to /// execute it. public static let selector: Selector = "execute:" /// Whether the action is enabled. /// /// This property will only change on the main thread, and will generate a /// KVO notification for every change. public var enabled: Bool { return _enabled } /// Whether the action is executing. /// /// This property will only change on the main thread, and will generate a /// KVO notification for every change. public var executing: Bool { return _executing } private var _enabled = false private var _executing = false private let _execute: AnyObject? -> () private let disposable = CompositeDisposable() /// Initializes a Cocoa action that will invoke the given Action by /// transforming the object given to execute(). public init(_ action: Action, _ inputTransform: AnyObject? -> Input) { _execute = { input in let producer = action.apply(inputTransform(input)) producer.start() } super.init() disposable += action.enabled.producer .observeOn(UIScheduler()) .startWithNext { [weak self] value in self?.willChangeValueForKey("enabled") self?._enabled = value self?.didChangeValueForKey("enabled") } disposable += action.executing.producer .observeOn(UIScheduler()) .startWithNext { [weak self] value in self?.willChangeValueForKey("executing") self?._executing = value self?.didChangeValueForKey("executing") } } /// Initializes a Cocoa action that will invoke the given Action by /// always providing the given input. public convenience init(_ action: Action, input: Input) { self.init(action, { _ in input }) } deinit { disposable.dispose() } /// Attempts to execute the underlying action with the given input, subject /// to the behavior described by the initializer that was used. @IBAction public func execute(input: AnyObject?) { _execute(input) } public override class func automaticallyNotifiesObserversForKey(key: String) -> Bool { return false } } /// The type of error that can occur from Action.apply, where `Error` is the type of /// error that can be generated by the specific Action instance. public enum ActionError: ErrorType { /// The producer returned from apply() was started while the Action was /// disabled. case NotEnabled /// The producer returned from apply() sent the given error. case ProducerError(Error) } public func == (lhs: ActionError, rhs: ActionError) -> Bool { switch (lhs, rhs) { case (.NotEnabled, .NotEnabled): return true case let (.ProducerError(left), .ProducerError(right)): return left == right default: return false } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Atomic.swift ================================================ // // Atomic.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2014-06-10. // Copyright (c) 2014 GitHub. All rights reserved. // /// An atomic variable. public final class Atomic { private var spinLock = OS_SPINLOCK_INIT private var _value: Value /// Atomically gets or sets the value of the variable. public var value: Value { get { lock() let v = _value unlock() return v } set(newValue) { lock() _value = newValue unlock() } } /// Initializes the variable with the given initial value. public init(_ value: Value) { _value = value } private func lock() { OSSpinLockLock(&spinLock) } private func unlock() { OSSpinLockUnlock(&spinLock) } /// Atomically replaces the contents of the variable. /// /// Returns the old value. public func swap(newValue: Value) -> Value { return modify { _ in newValue } } /// Atomically modifies the variable. /// /// Returns the old value. public func modify(@noescape action: Value -> Value) -> Value { lock() let oldValue = _value _value = action(_value) unlock() return oldValue } /// Atomically performs an arbitrary action using the current value of the /// variable. /// /// Returns the result of the action. public func withValue(@noescape action: Value -> U) -> U { lock() let result = action(_value) unlock() return result } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Bag.swift ================================================ // // Bag.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2014-07-10. // Copyright (c) 2014 GitHub. All rights reserved. // /// A uniquely identifying token for removing a value that was inserted into a /// Bag. public final class RemovalToken { private var identifier: UInt? private init(identifier: UInt) { self.identifier = identifier } } /// An unordered, non-unique collection of values of type `Element`. public struct Bag { private var elements: [BagElement] = [] private var currentIdentifier: UInt = 0 public init() { } /// Inserts the given value in the collection, and returns a token that can /// later be passed to removeValueForToken(). public mutating func insert(value: Element) -> RemovalToken { let (nextIdentifier, overflow) = UInt.addWithOverflow(currentIdentifier, 1) if overflow { reindex() } let token = RemovalToken(identifier: currentIdentifier) let element = BagElement(value: value, identifier: currentIdentifier, token: token) elements.append(element) currentIdentifier = nextIdentifier return token } /// Removes a value, given the token returned from insert(). /// /// If the value has already been removed, nothing happens. public mutating func removeValueForToken(token: RemovalToken) { if let identifier = token.identifier { // Removal is more likely for recent objects than old ones. for i in elements.indices.reverse() { if elements[i].identifier == identifier { elements.removeAtIndex(i) token.identifier = nil break } } } } /// In the event of an identifier overflow (highly, highly unlikely), this /// will reset all current identifiers to reclaim a contiguous set of /// available identifiers for the future. private mutating func reindex() { for i in elements.indices { currentIdentifier = UInt(i) elements[i].identifier = currentIdentifier elements[i].token.identifier = currentIdentifier } } } extension Bag: CollectionType { public typealias Index = Array.Index public var startIndex: Index { return elements.startIndex } public var endIndex: Index { return elements.endIndex } public subscript(index: Index) -> Element { return elements[index].value } } private struct BagElement { let value: Value var identifier: UInt let token: RemovalToken } extension BagElement: CustomStringConvertible { var description: String { return "BagElement(\(value))" } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Disposable.swift ================================================ // // Disposable.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2014-06-02. // Copyright (c) 2014 GitHub. All rights reserved. // /// Represents something that can be “disposed,” usually associated with freeing /// resources or canceling work. public protocol Disposable { /// Whether this disposable has been disposed already. var disposed: Bool { get } func dispose() } /// A disposable that only flips `disposed` upon disposal, and performs no other /// work. public final class SimpleDisposable: Disposable { private let _disposed = Atomic(false) public var disposed: Bool { return _disposed.value } public init() {} public func dispose() { _disposed.value = true } } /// A disposable that will run an action upon disposal. public final class ActionDisposable: Disposable { private let action: Atomic<(() -> ())?> public var disposed: Bool { return action.value == nil } /// Initializes the disposable to run the given action upon disposal. public init(action: () -> ()) { self.action = Atomic(action) } public func dispose() { let oldAction = action.swap(nil) oldAction?() } } /// A disposable that will dispose of any number of other disposables. public final class CompositeDisposable: Disposable { private let disposables: Atomic?> /// Represents a handle to a disposable previously added to a /// CompositeDisposable. public final class DisposableHandle { private let bagToken: Atomic private weak var disposable: CompositeDisposable? private static let empty = DisposableHandle() private init() { self.bagToken = Atomic(nil) } private init(bagToken: RemovalToken, disposable: CompositeDisposable) { self.bagToken = Atomic(bagToken) self.disposable = disposable } /// Removes the pointed-to disposable from its CompositeDisposable. /// /// This is useful to minimize memory growth, by removing disposables /// that are no longer needed. public func remove() { if let token = bagToken.swap(nil) { disposable?.disposables.modify { bag in guard var bag = bag else { return nil } bag.removeValueForToken(token) return bag } } } } public var disposed: Bool { return disposables.value == nil } /// Initializes a CompositeDisposable containing the given sequence of /// disposables. public init(_ disposables: S) { var bag: Bag = Bag() for disposable in disposables { bag.insert(disposable) } self.disposables = Atomic(bag) } /// Initializes an empty CompositeDisposable. public convenience init() { self.init([]) } public func dispose() { if let ds = disposables.swap(nil) { for d in ds.reverse() { d.dispose() } } } /// Adds the given disposable to the list, then returns a handle which can /// be used to opaquely remove the disposable later (if desired). public func addDisposable(d: Disposable?) -> DisposableHandle { guard let d = d else { return DisposableHandle.empty } var handle: DisposableHandle? = nil disposables.modify { ds in guard var ds = ds else { return nil } let token = ds.insert(d) handle = DisposableHandle(bagToken: token, disposable: self) return ds } if let handle = handle { return handle } else { d.dispose() return DisposableHandle.empty } } /// Adds an ActionDisposable to the list. public func addDisposable(action: () -> ()) -> DisposableHandle { return addDisposable(ActionDisposable(action: action)) } } /// A disposable that, upon deinitialization, will automatically dispose of /// another disposable. public final class ScopedDisposable: Disposable { /// The disposable which will be disposed when the ScopedDisposable /// deinitializes. public let innerDisposable: Disposable public var disposed: Bool { return innerDisposable.disposed } /// Initializes the receiver to dispose of the argument upon /// deinitialization. public init(_ disposable: Disposable) { innerDisposable = disposable } deinit { dispose() } public func dispose() { innerDisposable.dispose() } } /// A disposable that will optionally dispose of another disposable. public final class SerialDisposable: Disposable { private struct State { var innerDisposable: Disposable? = nil var disposed = false } private let state = Atomic(State()) public var disposed: Bool { return state.value.disposed } /// The inner disposable to dispose of. /// /// Whenever this property is set (even to the same value!), the previous /// disposable is automatically disposed. public var innerDisposable: Disposable? { get { return state.value.innerDisposable } set(d) { let oldState = state.modify { (var state) in state.innerDisposable = d return state } oldState.innerDisposable?.dispose() if oldState.disposed { d?.dispose() } } } /// Initializes the receiver to dispose of the argument when the /// SerialDisposable is disposed. public init(_ disposable: Disposable? = nil) { innerDisposable = disposable } public func dispose() { let orig = state.swap(State(innerDisposable: nil, disposed: true)) orig.innerDisposable?.dispose() } } /// Adds the right-hand-side disposable to the left-hand-side /// `CompositeDisposable`. /// /// disposable += producer /// .filter { ... } /// .map { ... } /// .start(observer) /// public func +=(lhs: CompositeDisposable, rhs: Disposable?) -> CompositeDisposable.DisposableHandle { return lhs.addDisposable(rhs) } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Errors.swift ================================================ // // Errors.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2014-07-13. // Copyright (c) 2014 GitHub. All rights reserved. // /// An “error” that is impossible to construct. /// /// This can be used to describe signals or producers where errors will never /// be generated. For example, `Signal` describes a signal that /// sends integers and is guaranteed never to error out. public enum NoError: ErrorType { } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Event.swift ================================================ // // Event.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2015-01-16. // Copyright (c) 2015 GitHub. All rights reserved. // /// Represents a signal event. /// /// Signals must conform to the grammar: /// `Next* (Failed | Completed | Interrupted)?` public enum Event { /// A value provided by the signal. case Next(Value) /// The signal terminated because of an error. No further events will be /// received. case Failed(Error) /// The signal successfully terminated. No further events will be received. case Completed /// Event production on the signal has been interrupted. No further events /// will be received. case Interrupted /// Whether this event indicates signal termination (i.e., that no further /// events will be received). public var isTerminating: Bool { switch self { case .Next: return false case .Failed, .Completed, .Interrupted: return true } } /// Lifts the given function over the event's value. public func map(f: Value -> U) -> Event { switch self { case let .Next(value): return .Next(f(value)) case let .Failed(error): return .Failed(error) case .Completed: return .Completed case .Interrupted: return .Interrupted } } /// Lifts the given function over the event's error. public func mapError(f: Error -> F) -> Event { switch self { case let .Next(value): return .Next(value) case let .Failed(error): return .Failed(f(error)) case .Completed: return .Completed case .Interrupted: return .Interrupted } } /// Unwraps the contained `Next` value. public var value: Value? { if case let .Next(value) = self { return value } else { return nil } } /// Unwraps the contained `Error` value. public var error: Error? { if case let .Failed(error) = self { return error } else { return nil } } } public func == (lhs: Event, rhs: Event) -> Bool { switch (lhs, rhs) { case let (.Next(left), .Next(right)): return left == right case let (.Failed(left), .Failed(right)): return left == right case (.Completed, .Completed): return true case (.Interrupted, .Interrupted): return true default: return false } } extension Event: CustomStringConvertible { public var description: String { switch self { case let .Next(value): return "NEXT \(value)" case let .Failed(error): return "FAILED \(error)" case .Completed: return "COMPLETED" case .Interrupted: return "INTERRUPTED" } } } /// Event protocol for constraining signal extensions public protocol EventType { // The value type of an event. typealias Value /// The error type of an event. If errors aren't possible then `NoError` can be used. typealias Error: ErrorType /// Extracts the event from the receiver. var event: Event { get } } extension Event: EventType { public var event: Event { return self } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/FoundationExtensions.swift ================================================ // // FoundationExtensions.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2014-10-19. // Copyright (c) 2014 GitHub. All rights reserved. // import Foundation extension NSNotificationCenter { /// Returns a producer of notifications posted that match the given criteria. /// This producer will not terminate naturally, so it must be explicitly /// disposed to avoid leaks. public func rac_notifications(name: String? = nil, object: AnyObject? = nil) -> SignalProducer { return SignalProducer { observer, disposable in let notificationObserver = self.addObserverForName(name, object: object, queue: nil) { notification in observer.sendNext(notification) } disposable.addDisposable { self.removeObserver(notificationObserver) } } } } private let defaultSessionError = NSError(domain: "org.reactivecocoa.ReactiveCocoa.rac_dataWithRequest", code: 1, userInfo: nil) extension NSURLSession { /// Returns a producer that will execute the given request once for each /// invocation of start(). public func rac_dataWithRequest(request: NSURLRequest) -> SignalProducer<(NSData, NSURLResponse), NSError> { return SignalProducer { observer, disposable in let task = self.dataTaskWithRequest(request) { data, response, error in if let data = data, response = response { observer.sendNext((data, response)) observer.sendCompleted() } else { observer.sendFailed(error ?? defaultSessionError) } } disposable.addDisposable { task.cancel() } task.resume() } } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/ObjectiveCBridging.swift ================================================ // // ObjectiveCBridging.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2014-07-02. // Copyright (c) 2014 GitHub, Inc. All rights reserved. // import Result extension RACDisposable: Disposable {} extension RACScheduler: DateSchedulerType { public var currentDate: NSDate { return NSDate() } public func schedule(action: () -> ()) -> Disposable? { let disposable: RACDisposable = self.schedule(action) // Call the Objective-C implementation return disposable as Disposable? } public func scheduleAfter(date: NSDate, action: () -> ()) -> Disposable? { return self.after(date, schedule: action) } public func scheduleAfter(date: NSDate, repeatingEvery: NSTimeInterval, withLeeway: NSTimeInterval, action: () -> ()) -> Disposable? { return self.after(date, repeatingEvery: repeatingEvery, withLeeway: withLeeway, schedule: action) } } extension ImmediateScheduler { public func toRACScheduler() -> RACScheduler { return RACScheduler.immediateScheduler() } } extension UIScheduler { public func toRACScheduler() -> RACScheduler { return RACScheduler.mainThreadScheduler() } } extension QueueScheduler { public func toRACScheduler() -> RACScheduler { return RACTargetQueueScheduler(name: "org.reactivecocoa.ReactiveCocoa.QueueScheduler.toRACScheduler()", targetQueue: queue) } } private func defaultNSError(message: String, file: String, line: Int) -> NSError { return Result<(), NSError>.error(message, file: file, line: line) } extension RACSignal { /// Creates a SignalProducer which will subscribe to the receiver once for /// each invocation of start(). public func toSignalProducer(file: String = __FILE__, line: Int = __LINE__) -> SignalProducer { return SignalProducer { observer, disposable in let next = { obj in observer.sendNext(obj) } let failed = { nsError in observer.sendFailed(nsError ?? defaultNSError("Nil RACSignal error", file: file, line: line)) } let completed = { observer.sendCompleted() } disposable += self.subscribeNext(next, error: failed, completed: completed) } } } extension SignalType { /// Turns each value into an Optional. private func optionalize() -> Signal { return signal.map(Optional.init) } } // MARK: - toRACSignal extension SignalProducerType where Value: AnyObject { /// Creates a RACSignal that will start() the producer once for each /// subscription. /// /// Any `Interrupted` events will be silently discarded. public func toRACSignal() -> RACSignal { return self .lift { $0.optionalize() } .toRACSignal() } } extension SignalProducerType where Value: OptionalType, Value.Wrapped: AnyObject { /// Creates a RACSignal that will start() the producer once for each /// subscription. /// /// Any `Interrupted` events will be silently discarded. public func toRACSignal() -> RACSignal { return self .mapError { $0 as NSError } .toRACSignal() } } extension SignalProducerType where Value: AnyObject, Error: NSError { /// Creates a RACSignal that will start() the producer once for each /// subscription. /// /// Any `Interrupted` events will be silently discarded. public func toRACSignal() -> RACSignal { return self .lift { $0.optionalize() } .toRACSignal() } } extension SignalProducerType where Value: OptionalType, Value.Wrapped: AnyObject, Error: NSError { /// Creates a RACSignal that will start() the producer once for each /// subscription. /// /// Any `Interrupted` events will be silently discarded. public func toRACSignal() -> RACSignal { // This special casing of `Error: NSError` is a workaround for rdar://22708537 // which causes an NSError's UserInfo dictionary to get discarded // during a cast from ErrorType to NSError in a generic function return RACSignal.createSignal { subscriber in let selfDisposable = self.start { event in switch event { case let .Next(value): subscriber.sendNext(value.optional) case let .Failed(error): subscriber.sendError(error) case .Completed: subscriber.sendCompleted() case .Interrupted: break } } return RACDisposable { selfDisposable.dispose() } } } } extension SignalType where Value: AnyObject { /// Creates a RACSignal that will observe the given signal. /// /// Any `Interrupted` event will be silently discarded. public func toRACSignal() -> RACSignal { return self .optionalize() .toRACSignal() } } extension SignalType where Value: AnyObject, Error: NSError { /// Creates a RACSignal that will observe the given signal. /// /// Any `Interrupted` event will be silently discarded. public func toRACSignal() -> RACSignal { return self .optionalize() .toRACSignal() } } extension SignalType where Value: OptionalType, Value.Wrapped: AnyObject { /// Creates a RACSignal that will observe the given signal. /// /// Any `Interrupted` event will be silently discarded. public func toRACSignal() -> RACSignal { return self .mapError { $0 as NSError } .toRACSignal() } } extension SignalType where Value: OptionalType, Value.Wrapped: AnyObject, Error: NSError { /// Creates a RACSignal that will observe the given signal. /// /// Any `Interrupted` event will be silently discarded. public func toRACSignal() -> RACSignal { // This special casing of `Error: NSError` is a workaround for rdar://22708537 // which causes an NSError's UserInfo dictionary to get discarded // during a cast from ErrorType to NSError in a generic function return RACSignal.createSignal { subscriber in let selfDisposable = self.observe { event in switch event { case let .Next(value): subscriber.sendNext(value.optional) case let .Failed(error): subscriber.sendError(error) case .Completed: subscriber.sendCompleted() case .Interrupted: break } } return RACDisposable { selfDisposable?.dispose() } } } } // MARK: - extension RACCommand { /// Creates an Action that will execute the receiver. /// /// Note that the returned Action will not necessarily be marked as /// executing when the command is. However, the reverse is always true: /// the RACCommand will always be marked as executing when the action is. public func toAction(file: String = __FILE__, line: Int = __LINE__) -> Action { let enabledProperty = MutableProperty(true) enabledProperty <~ self.enabled.toSignalProducer() .map { $0 as! Bool } .flatMapError { _ in SignalProducer(value: false) } return Action(enabledIf: enabledProperty) { input -> SignalProducer in let executionSignal = RACSignal.`defer` { return self.execute(input) } return executionSignal.toSignalProducer(file, line: line) } } } extension Action { private var commandEnabled: RACSignal { return self.enabled.producer .map { $0 as NSNumber } .toRACSignal() } } /// Creates a RACCommand that will execute the action. /// /// Note that the returned command will not necessarily be marked as /// executing when the action is. However, the reverse is always true: /// the Action will always be marked as executing when the RACCommand is. public func toRACCommand(action: Action) -> RACCommand { return RACCommand(enabled: action.commandEnabled) { input -> RACSignal in return action .apply(input) .toRACSignal() } } /// Creates a RACCommand that will execute the action. /// /// Note that the returned command will not necessarily be marked as /// executing when the action is. However, the reverse is always true: /// the Action will always be marked as executing when the RACCommand is. public func toRACCommand(action: Action) -> RACCommand { return RACCommand(enabled: action.commandEnabled) { input -> RACSignal in return action .apply(input) .toRACSignal() } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Observer.swift ================================================ // // Observer.swift // ReactiveCocoa // // Created by Andy Matuschak on 10/2/15. // Copyright © 2015 GitHub. All rights reserved. // /// An Observer is a simple wrapper around a function which can receive Events /// (typically from a Signal). public struct Observer { public typealias Action = Event -> () public let action: Action public init(_ action: Action) { self.action = action } public init(failed: (Error -> ())? = nil, completed: (() -> ())? = nil, interrupted: (() -> ())? = nil, next: (Value -> ())? = nil) { self.init { event in switch event { case let .Next(value): next?(value) case let .Failed(error): failed?(error) case .Completed: completed?() case .Interrupted: interrupted?() } } } /// Puts a `Next` event into the given observer. public func sendNext(value: Value) { action(.Next(value)) } /// Puts an `Failed` event into the given observer. public func sendFailed(error: Error) { action(.Failed(error)) } /// Puts a `Completed` event into the given observer. public func sendCompleted() { action(.Completed) } /// Puts a `Interrupted` event into the given observer. public func sendInterrupted() { action(.Interrupted) } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Optional.swift ================================================ // // Optional.swift // ReactiveCocoa // // Created by Neil Pankey on 6/24/15. // Copyright (c) 2015 GitHub. All rights reserved. // /// An optional protocol for use in type constraints. public protocol OptionalType { /// The type contained in the otpional. typealias Wrapped /// Extracts an optional from the receiver. var optional: Wrapped? { get } } extension Optional: OptionalType { public var optional: Wrapped? { return self } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Property.swift ================================================ /// Represents a property that allows observation of its changes. public protocol PropertyType { typealias Value /// The current value of the property. var value: Value { get } /// A producer for Signals that will send the property's current value, /// followed by all changes over time. var producer: SignalProducer { get } } /// A read-only property that allows observation of its changes. public struct AnyProperty: PropertyType { private let _value: () -> Value private let _producer: () -> SignalProducer public var value: Value { return _value() } public var producer: SignalProducer { return _producer() } /// Initializes a property as a read-only view of the given property. public init(_ property: P) { _value = { property.value } _producer = { property.producer } } /// Initializes a property that first takes on `initialValue`, then each value /// sent on a signal created by `producer`. public init(initialValue: Value, producer: SignalProducer) { let mutableProperty = MutableProperty(initialValue) mutableProperty <~ producer self.init(mutableProperty) } /// Initializes a property that first takes on `initialValue`, then each value /// sent on `signal`. public init(initialValue: Value, signal: Signal) { let mutableProperty = MutableProperty(initialValue) mutableProperty <~ signal self.init(mutableProperty) } } /// A property that never changes. public struct ConstantProperty: PropertyType { public let value: Value public let producer: SignalProducer /// Initializes the property to have the given value. public init(_ value: Value) { self.value = value self.producer = SignalProducer(value: value) } } /// Represents an observable property that can be mutated directly. /// /// Only classes can conform to this protocol, because instances must support /// weak references (and value types currently do not). public protocol MutablePropertyType: class, PropertyType { var value: Value { get set } } /// A mutable property of type `Value` that allows observation of its changes. /// /// Instances of this class are thread-safe. public final class MutableProperty: MutablePropertyType { private let observer: Signal.Observer /// Need a recursive lock around `value` to allow recursive access to /// `value`. Note that recursive sets will still deadlock because the /// underlying producer prevents sending recursive events. private let lock = NSRecursiveLock() private var _value: Value /// The current value of the property. /// /// Setting this to a new value will notify all observers of any Signals /// created from the `values` producer. public var value: Value { get { lock.lock() let value = _value lock.unlock() return value } set { lock.lock() _value = newValue observer.sendNext(newValue) lock.unlock() } } /// A producer for Signals that will send the property's current value, /// followed by all changes over time, then complete when the property has /// deinitialized. public let producer: SignalProducer /// Initializes the property with the given value to start. public init(_ initialValue: Value) { lock.name = "org.reactivecocoa.ReactiveCocoa.MutableProperty" (producer, observer) = SignalProducer.buffer(1) _value = initialValue observer.sendNext(initialValue) } deinit { observer.sendCompleted() } } /// Wraps a `dynamic` property, or one defined in Objective-C, using Key-Value /// Coding and Key-Value Observing. /// /// Use this class only as a last resort! `MutableProperty` is generally better /// unless KVC/KVO is required by the API you're using (for example, /// `NSOperation`). @objc public final class DynamicProperty: RACDynamicPropertySuperclass, MutablePropertyType { public typealias Value = AnyObject? private weak var object: NSObject? private let keyPath: String /// The current value of the property, as read and written using Key-Value /// Coding. public var value: AnyObject? { @objc(rac_value) get { return object?.valueForKeyPath(keyPath) } @objc(setRac_value:) set(newValue) { object?.setValue(newValue, forKeyPath: keyPath) } } /// A producer that will create a Key-Value Observer for the given object, /// send its initial value then all changes over time, and then complete /// when the observed object has deallocated. /// /// By definition, this only works if the object given to init() is /// KVO-compliant. Most UI controls are not! public var producer: SignalProducer { if let object = object { return object.rac_valuesForKeyPath(keyPath, observer: nil).toSignalProducer() // Errors aren't possible, but the compiler doesn't know that. .flatMapError { error in fatalError("Received unexpected error from KVO signal: \(error)") return .empty } } else { return .empty } } /// Initializes a property that will observe and set the given key path of /// the given object. `object` must support weak references! public init(object: NSObject?, keyPath: String) { self.object = object self.keyPath = keyPath /// DynamicProperty stay alive as long as object is alive. /// This is made possible by strong reference cycles. super.init() object?.rac_willDeallocSignal()?.toSignalProducer().startWithCompleted { self } } } infix operator <~ { associativity right // Binds tighter than assignment but looser than everything else precedence 93 } /// Binds a signal to a property, updating the property's value to the latest /// value sent by the signal. /// /// The binding will automatically terminate when the property is deinitialized, /// or when the signal sends a `Completed` event. public func <~ (property: P, signal: Signal) -> Disposable { let disposable = CompositeDisposable() disposable += property.producer.startWithCompleted { disposable.dispose() } disposable += signal.observe { [weak property] event in switch event { case let .Next(value): property?.value = value case .Completed: disposable.dispose() default: break } } return disposable } /// Creates a signal from the given producer, which will be immediately bound to /// the given property, updating the property's value to the latest value sent /// by the signal. /// /// The binding will automatically terminate when the property is deinitialized, /// or when the created signal sends a `Completed` event. public func <~ (property: P, producer: SignalProducer) -> Disposable { var disposable: Disposable! producer.startWithSignal { signal, signalDisposable in property <~ signal disposable = signalDisposable property.producer.startWithCompleted { signalDisposable.dispose() } } return disposable } /// Binds `destinationProperty` to the latest values of `sourceProperty`. /// /// The binding will automatically terminate when either property is /// deinitialized. public func <~ (destinationProperty: Destination, sourceProperty: Source) -> Disposable { return destinationProperty <~ sourceProperty.producer } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Scheduler.swift ================================================ // // Scheduler.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2014-06-02. // Copyright (c) 2014 GitHub. All rights reserved. // import Foundation /// Represents a serial queue of work items. public protocol SchedulerType { /// Enqueues an action on the scheduler. /// /// When the work is executed depends on the scheduler in use. /// /// Optionally returns a disposable that can be used to cancel the work /// before it begins. func schedule(action: () -> ()) -> Disposable? } /// A particular kind of scheduler that supports enqueuing actions at future /// dates. public protocol DateSchedulerType: SchedulerType { /// The current date, as determined by this scheduler. /// /// This can be implemented to deterministic return a known date (e.g., for /// testing purposes). var currentDate: NSDate { get } /// Schedules an action for execution at or after the given date. /// /// Optionally returns a disposable that can be used to cancel the work /// before it begins. func scheduleAfter(date: NSDate, action: () -> ()) -> Disposable? /// Schedules a recurring action at the given interval, beginning at the /// given start time. /// /// Optionally returns a disposable that can be used to cancel the work /// before it begins. func scheduleAfter(date: NSDate, repeatingEvery: NSTimeInterval, withLeeway: NSTimeInterval, action: () -> ()) -> Disposable? } /// A scheduler that performs all work synchronously. public final class ImmediateScheduler: SchedulerType { public init() {} public func schedule(action: () -> ()) -> Disposable? { action() return nil } } /// A scheduler that performs all work on the main thread, as soon as possible. /// /// If the caller is already running on the main thread when an action is /// scheduled, it may be run synchronously. However, ordering between actions /// will always be preserved. public final class UIScheduler: SchedulerType { private var queueLength: Int32 = 0 public init() {} public func schedule(action: () -> ()) -> Disposable? { let disposable = SimpleDisposable() let actionAndDecrement: () -> () = { if !disposable.disposed { action() } OSAtomicDecrement32(&self.queueLength) } let queued = OSAtomicIncrement32(&queueLength) // If we're already running on the main thread, and there isn't work // already enqueued, we can skip scheduling and just execute directly. if NSThread.isMainThread() && queued == 1 { actionAndDecrement() } else { dispatch_async(dispatch_get_main_queue(), actionAndDecrement) } return disposable } } /// A scheduler backed by a serial GCD queue. public final class QueueScheduler: DateSchedulerType { internal let queue: dispatch_queue_t internal init(internalQueue: dispatch_queue_t) { queue = internalQueue } /// Initializes a scheduler that will target the given queue with its work. /// /// Even if the queue is concurrent, all work items enqueued with the /// QueueScheduler will be serial with respect to each other. /// /// - warning: Obsoleted in OS X 10.11 @available(OSX, deprecated=10.10, obsoleted=10.11, message="Use init(qos:, name:) instead") public convenience init(queue: dispatch_queue_t, name: String = "org.reactivecocoa.ReactiveCocoa.QueueScheduler") { self.init(internalQueue: dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL)) dispatch_set_target_queue(self.queue, queue) } /// A singleton QueueScheduler that always targets the main thread's GCD /// queue. /// /// Unlike UIScheduler, this scheduler supports scheduling for a future /// date, and will always schedule asynchronously (even if already running /// on the main thread). public static let mainQueueScheduler = QueueScheduler(internalQueue: dispatch_get_main_queue()) public var currentDate: NSDate { return NSDate() } /// Initializes a scheduler that will target the global queue with the given /// quality of service class. @available(iOS 8, watchOS 2, OSX 10.10, *) public convenience init(qos: dispatch_qos_class_t = QOS_CLASS_DEFAULT, name: String = "org.reactivecocoa.ReactiveCocoa.QueueScheduler") { self.init(internalQueue: dispatch_queue_create(name, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qos, 0))) } public func schedule(action: () -> ()) -> Disposable? { let d = SimpleDisposable() dispatch_async(queue) { if !d.disposed { action() } } return d } private func wallTimeWithDate(date: NSDate) -> dispatch_time_t { let (seconds, frac) = modf(date.timeIntervalSince1970) let nsec: Double = frac * Double(NSEC_PER_SEC) var walltime = timespec(tv_sec: Int(seconds), tv_nsec: Int(nsec)) return dispatch_walltime(&walltime, 0) } public func scheduleAfter(date: NSDate, action: () -> ()) -> Disposable? { let d = SimpleDisposable() dispatch_after(wallTimeWithDate(date), queue) { if !d.disposed { action() } } return d } /// Schedules a recurring action at the given interval, beginning at the /// given start time, and with a reasonable default leeway. /// /// Optionally returns a disposable that can be used to cancel the work /// before it begins. public func scheduleAfter(date: NSDate, repeatingEvery: NSTimeInterval, action: () -> ()) -> Disposable? { // Apple's "Power Efficiency Guide for Mac Apps" recommends a leeway of // at least 10% of the timer interval. return scheduleAfter(date, repeatingEvery: repeatingEvery, withLeeway: repeatingEvery * 0.1, action: action) } public func scheduleAfter(date: NSDate, repeatingEvery: NSTimeInterval, withLeeway leeway: NSTimeInterval, action: () -> ()) -> Disposable? { precondition(repeatingEvery >= 0) precondition(leeway >= 0) let nsecInterval = repeatingEvery * Double(NSEC_PER_SEC) let nsecLeeway = leeway * Double(NSEC_PER_SEC) let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) dispatch_source_set_timer(timer, wallTimeWithDate(date), UInt64(nsecInterval), UInt64(nsecLeeway)) dispatch_source_set_event_handler(timer, action) dispatch_resume(timer) return ActionDisposable { dispatch_source_cancel(timer) } } } /// A scheduler that implements virtualized time, for use in testing. public final class TestScheduler: DateSchedulerType { private final class ScheduledAction { let date: NSDate let action: () -> () init(date: NSDate, action: () -> ()) { self.date = date self.action = action } func less(rhs: ScheduledAction) -> Bool { return date.compare(rhs.date) == .OrderedAscending } } private let lock = NSRecursiveLock() private var _currentDate: NSDate /// The virtual date that the scheduler is currently at. public var currentDate: NSDate { let d: NSDate lock.lock() d = _currentDate lock.unlock() return d } private var scheduledActions: [ScheduledAction] = [] /// Initializes a TestScheduler with the given start date. public init(startDate: NSDate = NSDate(timeIntervalSinceReferenceDate: 0)) { lock.name = "org.reactivecocoa.ReactiveCocoa.TestScheduler" _currentDate = startDate } private func schedule(action: ScheduledAction) -> Disposable { lock.lock() scheduledActions.append(action) scheduledActions.sortInPlace { $0.less($1) } lock.unlock() return ActionDisposable { self.lock.lock() self.scheduledActions = self.scheduledActions.filter { $0 !== action } self.lock.unlock() } } public func schedule(action: () -> ()) -> Disposable? { return schedule(ScheduledAction(date: currentDate, action: action)) } /// Schedules an action for execution at or after the given interval /// (counted from `currentDate`). /// /// Optionally returns a disposable that can be used to cancel the work /// before it begins. public func scheduleAfter(interval: NSTimeInterval, action: () -> ()) -> Disposable? { return scheduleAfter(currentDate.dateByAddingTimeInterval(interval), action: action) } public func scheduleAfter(date: NSDate, action: () -> ()) -> Disposable? { return schedule(ScheduledAction(date: date, action: action)) } private func scheduleAfter(date: NSDate, repeatingEvery: NSTimeInterval, disposable: SerialDisposable, action: () -> ()) { precondition(repeatingEvery >= 0) disposable.innerDisposable = scheduleAfter(date) { [unowned self] in action() self.scheduleAfter(date.dateByAddingTimeInterval(repeatingEvery), repeatingEvery: repeatingEvery, disposable: disposable, action: action) } } /// Schedules a recurring action at the given interval, beginning at the /// given interval (counted from `currentDate`). /// /// Optionally returns a disposable that can be used to cancel the work /// before it begins. public func scheduleAfter(interval: NSTimeInterval, repeatingEvery: NSTimeInterval, withLeeway leeway: NSTimeInterval = 0, action: () -> ()) -> Disposable? { return scheduleAfter(currentDate.dateByAddingTimeInterval(interval), repeatingEvery: repeatingEvery, withLeeway: leeway, action: action) } public func scheduleAfter(date: NSDate, repeatingEvery: NSTimeInterval, withLeeway: NSTimeInterval = 0, action: () -> ()) -> Disposable? { let disposable = SerialDisposable() scheduleAfter(date, repeatingEvery: repeatingEvery, disposable: disposable, action: action) return disposable } /// Advances the virtualized clock by an extremely tiny interval, dequeuing /// and executing any actions along the way. /// /// This is intended to be used as a way to execute actions that have been /// scheduled to run as soon as possible. public func advance() { advanceByInterval(DBL_EPSILON) } /// Advances the virtualized clock by the given interval, dequeuing and /// executing any actions along the way. public func advanceByInterval(interval: NSTimeInterval) { lock.lock() advanceToDate(currentDate.dateByAddingTimeInterval(interval)) lock.unlock() } /// Advances the virtualized clock to the given future date, dequeuing and /// executing any actions up until that point. public func advanceToDate(newDate: NSDate) { lock.lock() assert(currentDate.compare(newDate) != .OrderedDescending) _currentDate = newDate while scheduledActions.count > 0 { if newDate.compare(scheduledActions[0].date) == .OrderedAscending { break } let scheduledAction = scheduledActions[0] scheduledActions.removeAtIndex(0) scheduledAction.action() } lock.unlock() } /// Dequeues and executes all scheduled actions, leaving the scheduler's /// date at `NSDate.distantFuture()`. public func run() { advanceToDate(NSDate.distantFuture()) } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/Signal.swift ================================================ import Result /// A push-driven stream that sends Events over time, parameterized by the type /// of values being sent (`Value`) and the type of failure that can occur (`Error`). /// If no failures should be possible, NoError can be specified for `Error`. /// /// An observer of a Signal will see the exact same sequence of events as all /// other observers. In other words, events will be sent to all observers at the /// same time. /// /// Signals are generally used to represent event streams that are already “in /// progress,” like notifications, user input, etc. To represent streams that /// must first be _started_, see the SignalProducer type. /// /// Signals do not need to be retained. A Signal will be automatically kept /// alive until the event stream has terminated. public final class Signal { public typealias Observer = ReactiveCocoa.Observer private let atomicObservers: Atomic?> = Atomic(Bag()) /// Initializes a Signal that will immediately invoke the given generator, /// then forward events sent to the given observer. /// /// The disposable returned from the closure will be automatically disposed /// if a terminating event is sent to the observer. The Signal itself will /// remain alive until the observer is released. public init(@noescape _ generator: Observer -> Disposable?) { /// Used to ensure that events are serialized during delivery to observers. let sendLock = NSLock() sendLock.name = "org.reactivecocoa.ReactiveCocoa.Signal" let generatorDisposable = SerialDisposable() /// When set to `true`, the Signal should interrupt as soon as possible. let interrupted = Atomic(false) let observer = Observer { event in if case .Interrupted = event { // Normally we disallow recursive events, but // Interrupted is kind of a special snowflake, since it // can inadvertently be sent by downstream consumers. // // So we'll flag Interrupted events specially, and if it // happened to occur while we're sending something else, // we'll wait to deliver it. interrupted.value = true if sendLock.tryLock() { self.interrupt() sendLock.unlock() generatorDisposable.dispose() } } else { if let observers = (event.isTerminating ? self.atomicObservers.swap(nil) : self.atomicObservers.value) { sendLock.lock() for observer in observers { observer.action(event) } let shouldInterrupt = !event.isTerminating && interrupted.value if shouldInterrupt { self.interrupt() } sendLock.unlock() if event.isTerminating || shouldInterrupt { // Dispose only after notifying observers, so disposal logic // is consistently the last thing to run. generatorDisposable.dispose() } } } } generatorDisposable.innerDisposable = generator(observer) } /// A Signal that never sends any events to its observers. public static var never: Signal { return self.init { _ in nil } } /// Creates a Signal that will be controlled by sending events to the given /// observer. /// /// The Signal will remain alive until a terminating event is sent to the /// observer. public static func pipe() -> (Signal, Observer) { var observer: Observer! let signal = self.init { innerObserver in observer = innerObserver return nil } return (signal, observer) } /// Interrupts all observers and terminates the stream. private func interrupt() { if let observers = self.atomicObservers.swap(nil) { for observer in observers { observer.sendInterrupted() } } } /// Observes the Signal by sending any future events to the given observer. If /// the Signal has already terminated, the observer will immediately receive an /// `Interrupted` event. /// /// Returns a Disposable which can be used to disconnect the observer. Disposing /// of the Disposable will have no effect on the Signal itself. public func observe(observer: Observer) -> Disposable? { var token: RemovalToken? atomicObservers.modify { observers in guard var observers = observers else { return nil } token = observers.insert(observer) return observers } if let token = token { return ActionDisposable { self.atomicObservers.modify { observers in guard var observers = observers else { return nil } observers.removeValueForToken(token) return observers } } } else { observer.sendInterrupted() return nil } } } public protocol SignalType { /// The type of values being sent on the signal. typealias Value /// The type of error that can occur on the signal. If errors aren't possible /// then `NoError` can be used. typealias Error: ErrorType /// Extracts a signal from the receiver. var signal: Signal { get } /// Observes the Signal by sending any future events to the given observer. func observe(observer: Signal.Observer) -> Disposable? } extension Signal: SignalType { public var signal: Signal { return self } } extension SignalType { /// Convenience override for observe(_:) to allow trailing-closure style /// invocations. public func observe(action: Signal.Observer.Action) -> Disposable? { return observe(Observer(action)) } /// Observes the Signal by invoking the given callback when `next` events are /// received. /// /// Returns a Disposable which can be used to stop the invocation of the /// callbacks. Disposing of the Disposable will have no effect on the Signal /// itself. public func observeNext(next: Value -> ()) -> Disposable? { return observe(Observer(next: next)) } /// Observes the Signal by invoking the given callback when a `completed` event is /// received. /// /// Returns a Disposable which can be used to stop the invocation of the /// callback. Disposing of the Disposable will have no effect on the Signal /// itself. public func observeCompleted(completed: () -> ()) -> Disposable? { return observe(Observer(completed: completed)) } /// Observes the Signal by invoking the given callback when a `failed` event is /// received. /// /// Returns a Disposable which can be used to stop the invocation of the /// callback. Disposing of the Disposable will have no effect on the Signal /// itself. public func observeFailed(error: Error -> ()) -> Disposable? { return observe(Observer(failed: error)) } /// Observes the Signal by invoking the given callback when an `interrupted` event is /// received. If the Signal has already terminated, the callback will be invoked /// immediately. /// /// Returns a Disposable which can be used to stop the invocation of the /// callback. Disposing of the Disposable will have no effect on the Signal /// itself. public func observeInterrupted(interrupted: () -> ()) -> Disposable? { return observe(Observer(interrupted: interrupted)) } /// Maps each value in the signal to a new value. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func map(transform: Value -> U) -> Signal { return Signal { observer in return self.observe { event in observer.action(event.map(transform)) } } } /// Maps errors in the signal to a new error. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func mapError(transform: Error -> F) -> Signal { return Signal { observer in return self.observe { event in observer.action(event.mapError(transform)) } } } /// Catches any failure that may occur on the input signal, mapping to a new producer /// that starts in its place. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func flatMapError(handler: Error -> SignalProducer) -> Signal { return Signal { observer in let serialDisposable = SerialDisposable() serialDisposable.innerDisposable = self.observe { event in switch event { case let .Next(value): observer.sendNext(value) case let .Failed(error): handler(error).startWithSignal { signal, signalDisposable in serialDisposable.innerDisposable = signalDisposable signal.observe(observer) } case .Completed: observer.sendCompleted() case .Interrupted: observer.sendInterrupted() } } return serialDisposable } } /// Preserves only the values of the signal that pass the given predicate. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func filter(predicate: Value -> Bool) -> Signal { return Signal { observer in return self.observe { (event: Event) -> () in if case let .Next(value) = event { if predicate(value) { observer.sendNext(value) } } else { observer.action(event) } } } } } /// Describes how multiple producers should be joined together. public enum FlattenStrategy: Equatable { /// The producers should be merged, so that any value received on any of the /// input producers will be forwarded immediately to the output producer. /// /// The resulting producer will complete only when all inputs have completed. case Merge /// The producers should be concatenated, so that their values are sent in the /// order of the producers themselves. /// /// The resulting producer will complete only when all inputs have completed. case Concat /// Only the events from the latest input producer should be considered for /// the output. Any producers received before that point will be disposed of. /// /// The resulting producer will complete only when the producer-of-producers and /// the latest producer has completed. case Latest } extension SignalType where Value: SignalType, Error == Value.Error { /// Flattens the inner signals sent upon `signal` (into a single signal of /// values), according to the semantics of the given strategy. /// /// If `signal` or an active inner signal emits an error, the returned /// signal will forward that error immediately. /// /// `Interrupted` events on inner signals will be treated like `Completed` /// events on inner signals. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func flatten(strategy: FlattenStrategy) -> Signal { return self.map(SignalProducer.init).flatten(strategy) } } extension SignalType where Value: SignalProducerType, Error == Value.Error { /// Flattens the inner producers sent upon `signal` (into a single signal of /// values), according to the semantics of the given strategy. /// /// If `signal` or an active inner producer fails, the returned signal will /// forward that failure immediately. /// /// `Interrupted` events on inner producers will be treated like `Completed` /// events on inner producers. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func flatten(strategy: FlattenStrategy) -> Signal { switch strategy { case .Merge: return self.merge() case .Concat: return self.concat() case .Latest: return self.switchToLatest() } } } extension SignalType { /// Maps each event from `signal` to a new producer, then flattens the /// resulting producers (into a signal of values), according to the /// semantics of the given strategy. /// /// If `signal` or any of the created producers fail, the returned signal /// will forward that failure immediately. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func flatMap(strategy: FlattenStrategy, transform: Value -> SignalProducer) -> Signal { return map(transform).flatten(strategy) } /// Maps each event from `signal` to a new signal, then flattens the /// resulting signals (into a signal of values), according to the /// semantics of the given strategy. /// /// If `signal` or any of the created signals emit an error, the returned /// signal will forward that error immediately. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func flatMap(strategy: FlattenStrategy, transform: Value -> Signal) -> Signal { return map(transform).flatten(strategy) } } extension SignalType { /// Merges the given signals into a single `Signal` that will emit all values /// from each of them, and complete when all of them have completed. public static func merge>(signals: S) -> Signal { let producer = SignalProducer, Error>(values: signals) var result: Signal! producer.startWithSignal { (signal, _) in result = signal.flatten(.Merge) } return result } } extension SignalType where Value: SignalProducerType, Error == Value.Error { /// Returns a signal which sends all the values from producer signal emitted from /// `signal`, waiting until each inner producer completes before beginning to /// send the values from the next inner producer. /// /// If any of the inner producers fail, the returned signal will forward /// that failure immediately /// /// The returned signal completes only when `signal` and all producers /// emitted from `signal` complete. @warn_unused_result(message="Did you forget to call `observe` on the signal?") private func concat() -> Signal { return Signal { observer in let disposable = CompositeDisposable() let state = ConcatState(observer: observer, disposable: disposable) disposable += self.observe { event in switch event { case let .Next(value): state.enqueueSignalProducer(value.producer) case let .Failed(error): observer.sendFailed(error) case .Completed: // Add one last producer to the queue, whose sole job is to // "turn out the lights" by completing `observer`. state.enqueueSignalProducer(SignalProducer.empty.on(completed: { observer.sendCompleted() })) case .Interrupted: observer.sendInterrupted() } } return disposable } } } private final class ConcatState { /// The observer of a started `concat` producer. let observer: Signal.Observer /// The top level disposable of a started `concat` producer. let disposable: CompositeDisposable /// The active producer, if any, and the producers waiting to be started. let queuedSignalProducers: Atomic<[SignalProducer]> = Atomic([]) init(observer: Signal.Observer, disposable: CompositeDisposable) { self.observer = observer self.disposable = disposable } func enqueueSignalProducer(producer: SignalProducer) { if disposable.disposed { return } var shouldStart = true queuedSignalProducers.modify { (var queue) in // An empty queue means the concat is idle, ready & waiting to start // the next producer. shouldStart = queue.isEmpty queue.append(producer) return queue } if shouldStart { startNextSignalProducer(producer) } } func dequeueSignalProducer() -> SignalProducer? { if disposable.disposed { return nil } var nextSignalProducer: SignalProducer? queuedSignalProducers.modify { (var queue) in // Active producers remain in the queue until completed. Since // dequeueing happens at completion of the active producer, the // first producer in the queue can be removed. if !queue.isEmpty { queue.removeAtIndex(0) } nextSignalProducer = queue.first return queue } return nextSignalProducer } /// Subscribes to the given signal producer. func startNextSignalProducer(signalProducer: SignalProducer) { signalProducer.startWithSignal { signal, disposable in let handle = self.disposable.addDisposable(disposable) signal.observe { event in switch event { case .Completed, .Interrupted: handle.remove() if let nextSignalProducer = self.dequeueSignalProducer() { self.startNextSignalProducer(nextSignalProducer) } default: self.observer.action(event) } } } } } extension SignalType where Value: SignalProducerType, Error == Value.Error { /// Merges a `signal` of SignalProducers down into a single signal, biased toward the producer /// added earlier. Returns a Signal that will forward events from the inner producers as they arrive. @warn_unused_result(message="Did you forget to call `start` on the producer?") private func merge() -> Signal { return Signal { relayObserver in let inFlight = Atomic(1) let decrementInFlight: () -> () = { let orig = inFlight.modify { $0 - 1 } if orig == 1 { relayObserver.sendCompleted() } } let disposable = CompositeDisposable() self.observe { event in switch event { case let .Next(producer): producer.startWithSignal { innerSignal, innerDisposable in inFlight.modify { $0 + 1 } let handle = disposable.addDisposable(innerDisposable) innerSignal.observe { event in switch event { case .Completed, .Interrupted: if event.isTerminating { handle.remove() } decrementInFlight() default: relayObserver.action(event) } } } case let .Failed(error): relayObserver.sendFailed(error) case .Completed: decrementInFlight() case .Interrupted: relayObserver.sendInterrupted() } } return disposable } } /// Returns a signal that forwards values from the latest signal sent on /// `signal`, ignoring values sent on previous inner signal. /// /// An error sent on `signal` or the latest inner signal will be sent on the /// returned signal. /// /// The returned signal completes when `signal` and the latest inner /// signal have both completed. @warn_unused_result(message="Did you forget to call `observe` on the signal?") private func switchToLatest() -> Signal { return Signal { observer in let disposable = CompositeDisposable() let latestInnerDisposable = SerialDisposable() disposable.addDisposable(latestInnerDisposable) let state = Atomic(LatestState()) self.observe { event in switch event { case let .Next(innerProducer): innerProducer.startWithSignal { innerSignal, innerDisposable in state.modify { (var state) in // When we replace the disposable below, this prevents the // generated Interrupted event from doing any work. state.replacingInnerSignal = true return state } latestInnerDisposable.innerDisposable = innerDisposable state.modify { (var state) in state.replacingInnerSignal = false state.innerSignalComplete = false return state } innerSignal.observe { event in switch event { case .Interrupted: // If interruption occurred as a result of a new producer // arriving, we don't want to notify our observer. let original = state.modify { (var state) in if !state.replacingInnerSignal { state.innerSignalComplete = true } return state } if !original.replacingInnerSignal && original.outerSignalComplete { observer.sendCompleted() } case .Completed: let original = state.modify { (var state) in state.innerSignalComplete = true return state } if original.outerSignalComplete { observer.sendCompleted() } default: observer.action(event) } } } case let .Failed(error): observer.sendFailed(error) case .Completed: let original = state.modify { (var state) in state.outerSignalComplete = true return state } if original.innerSignalComplete { observer.sendCompleted() } case .Interrupted: observer.sendInterrupted() } } return disposable } } } private struct LatestState { var outerSignalComplete: Bool = false var innerSignalComplete: Bool = true var replacingInnerSignal: Bool = false } extension SignalType where Value: OptionalType { /// Unwraps non-`nil` values and forwards them on the returned signal, `nil` /// values are dropped. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func ignoreNil() -> Signal { return filter { $0.optional != nil }.map { $0.optional! } } } extension SignalType { /// Returns a signal that will yield the first `count` values from `self` @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func take(count: Int) -> Signal { precondition(count >= 0) return Signal { observer in if count == 0 { observer.sendCompleted() return nil } var taken = 0 return self.observe { event in if case let .Next(value) = event { if taken < count { taken++ observer.sendNext(value) } if taken == count { observer.sendCompleted() } } else { observer.action(event) } } } } } /// A reference type which wraps an array to avoid copying it for performance and /// memory usage optimization. private final class CollectState { var values: [Value] = [] func append(value: Value) -> Self { values.append(value) return self } } extension SignalType { /// Returns a signal that will yield an array of values when `self` completes. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func collect() -> Signal<[Value], Error> { return self .reduce(CollectState()) { $0.append($1) } .map { $0.values } } /// Forwards all events onto the given scheduler, instead of whichever /// scheduler they originally arrived upon. public func observeOn(scheduler: SchedulerType) -> Signal { return Signal { observer in return self.observe { event in scheduler.schedule { observer.action(event) } } } } } private final class CombineLatestState { var latestValue: Value? var completed = false } extension SignalType { private func observeWithStates(signalState: CombineLatestState, _ otherState: CombineLatestState, _ lock: NSLock, _ onBothNext: () -> (), _ onFailed: Error -> (), _ onBothCompleted: () -> (), _ onInterrupted: () -> ()) -> Disposable? { return self.observe { event in switch event { case let .Next(value): lock.lock() signalState.latestValue = value if otherState.latestValue != nil { onBothNext() } lock.unlock() case let .Failed(error): onFailed(error) case .Completed: lock.lock() signalState.completed = true if otherState.completed { onBothCompleted() } lock.unlock() case .Interrupted: onInterrupted() } } } /// Combines the latest value of the receiver with the latest value from /// the given signal. /// /// The returned signal will not send a value until both inputs have sent /// at least one value each. If either signal is interrupted, the returned signal /// will also be interrupted. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatestWith(otherSignal: Signal) -> Signal<(Value, U), Error> { return Signal { observer in let lock = NSLock() lock.name = "org.reactivecocoa.ReactiveCocoa.combineLatestWith" let signalState = CombineLatestState() let otherState = CombineLatestState() let onBothNext = { () -> () in observer.sendNext((signalState.latestValue!, otherState.latestValue!)) } let onFailed = observer.sendFailed let onBothCompleted = observer.sendCompleted let onInterrupted = observer.sendInterrupted let disposable = CompositeDisposable() disposable += self.observeWithStates(signalState, otherState, lock, onBothNext, onFailed, onBothCompleted, onInterrupted) disposable += otherSignal.observeWithStates(otherState, signalState, lock, onBothNext, onFailed, onBothCompleted, onInterrupted) return disposable } } /// Delays `Next` and `Completed` events by the given interval, forwarding /// them on the given scheduler. /// /// `Failed` and `Interrupted` events are always scheduled immediately. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func delay(interval: NSTimeInterval, onScheduler scheduler: DateSchedulerType) -> Signal { precondition(interval >= 0) return Signal { observer in return self.observe { event in switch event { case .Failed, .Interrupted: scheduler.schedule { observer.action(event) } default: let date = scheduler.currentDate.dateByAddingTimeInterval(interval) scheduler.scheduleAfter(date) { observer.action(event) } } } } } /// Returns a signal that will skip the first `count` values, then forward /// everything afterward. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func skip(count: Int) -> Signal { precondition(count >= 0) if count == 0 { return signal } return Signal { observer in var skipped = 0 return self.observe { event in if case .Next = event where skipped < count { skipped++ } else { observer.action(event) } } } } /// Treats all Events from `self` as plain values, allowing them to be manipulated /// just like any other value. /// /// In other words, this brings Events “into the monad.” /// /// When a Completed or Failed event is received, the resulting signal will send /// the Event itself and then complete. When an Interrupted event is received, /// the resulting signal will send the Event itself and then interrupt. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func materialize() -> Signal, NoError> { return Signal { observer in return self.observe { event in observer.sendNext(event) switch event { case .Interrupted: observer.sendInterrupted() case .Completed, .Failed: observer.sendCompleted() case .Next: break } } } } } extension SignalType where Value: EventType, Error == NoError { /// The inverse of materialize(), this will translate a signal of `Event` /// _values_ into a signal of those events themselves. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func dematerialize() -> Signal { return Signal { observer in return self.observe { event in switch event { case let .Next(innerEvent): observer.action(innerEvent.event) case .Failed: fatalError("NoError is impossible to construct") case .Completed: observer.sendCompleted() case .Interrupted: observer.sendInterrupted() } } } } } extension SignalType { /// Injects side effects to be performed upon the specified signal events. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func on(event event: (Event -> ())? = nil, failed: (Error -> ())? = nil, completed: (() -> ())? = nil, interrupted: (() -> ())? = nil, terminated: (() -> ())? = nil, disposed: (() -> ())? = nil, next: (Value -> ())? = nil) -> Signal { return Signal { observer in let disposable = CompositeDisposable() _ = disposed.map(disposable.addDisposable) disposable += signal.observe { receivedEvent in event?(receivedEvent) switch receivedEvent { case let .Next(value): next?(value) case let .Failed(error): failed?(error) case .Completed: completed?() case .Interrupted: interrupted?() } if receivedEvent.isTerminating { terminated?() } observer.action(receivedEvent) } return disposable } } } private struct SampleState { var latestValue: Value? = nil var signalCompleted: Bool = false var samplerCompleted: Bool = false } extension SignalType { /// Forwards the latest value from `signal` whenever `sampler` sends a Next /// event. /// /// If `sampler` fires before a value has been observed on `signal`, nothing /// happens. /// /// Returns a signal that will send values from `signal`, sampled (possibly /// multiple times) by `sampler`, then complete once both input signals have /// completed, or interrupt if either input signal is interrupted. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func sampleOn(sampler: Signal<(), NoError>) -> Signal { return Signal { observer in let state = Atomic(SampleState()) let disposable = CompositeDisposable() disposable += self.observe { event in switch event { case let .Next(value): state.modify { (var st) in st.latestValue = value return st } case let .Failed(error): observer.sendFailed(error) case .Completed: let oldState = state.modify { (var st) in st.signalCompleted = true return st } if oldState.samplerCompleted { observer.sendCompleted() } case .Interrupted: observer.sendInterrupted() } } disposable += sampler.observe { event in switch event { case .Next: if let value = state.value.latestValue { observer.sendNext(value) } case .Completed: let oldState = state.modify { (var st) in st.samplerCompleted = true return st } if oldState.signalCompleted { observer.sendCompleted() } case .Interrupted: observer.sendInterrupted() default: break } } return disposable } } /// Forwards events from `self` until `trigger` sends a Next or Completed /// event, at which point the returned signal will complete. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func takeUntil(trigger: Signal<(), NoError>) -> Signal { return Signal { observer in let disposable = CompositeDisposable() disposable += self.observe(observer) disposable += trigger.observe { event in switch event { case .Next, .Completed: observer.sendCompleted() case .Failed, .Interrupted: break } } return disposable } } /// Does not forward any values from `self` until `trigger` sends a Next or /// Completed event, at which point the returned signal behaves exactly like /// `signal`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func skipUntil(trigger: Signal<(), NoError>) -> Signal { return Signal { observer in let disposable = SerialDisposable() disposable.innerDisposable = trigger.observe { event in switch event { case .Next, .Completed: disposable.innerDisposable = self.observe(observer) case .Failed, .Interrupted: break } } return disposable } } /// Forwards events from `self` with history: values of the returned signal /// are a tuple whose first member is the previous value and whose second member /// is the current value. `initial` is supplied as the first member when `self` /// sends its first value. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combinePrevious(initial: Value) -> Signal<(Value, Value), Error> { return scan((initial, initial)) { previousCombinedValues, newValue in return (previousCombinedValues.1, newValue) } } /// Like `scan`, but sends only the final value and then immediately completes. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func reduce(initial: U, _ combine: (U, Value) -> U) -> Signal { // We need to handle the special case in which `signal` sends no values. // We'll do that by sending `initial` on the output signal (before taking // the last value). let (scannedSignalWithInitialValue, outputSignalObserver) = Signal.pipe() let outputSignal = scannedSignalWithInitialValue.takeLast(1) // Now that we've got takeLast() listening to the piped signal, send that initial value. outputSignalObserver.sendNext(initial) // Pipe the scanned input signal into the output signal. scan(initial, combine).observe(outputSignalObserver) return outputSignal } /// Aggregates `selfs`'s values into a single combined value. When `self` emits /// its first value, `combine` is invoked with `initial` as the first argument and /// that emitted value as the second argument. The result is emitted from the /// signal returned from `scan`. That result is then passed to `combine` as the /// first argument when the next value is emitted, and so on. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func scan(initial: U, _ combine: (U, Value) -> U) -> Signal { return Signal { observer in var accumulator = initial return self.observe { event in observer.action(event.map { value in accumulator = combine(accumulator, value) return accumulator }) } } } } extension SignalType where Value: Equatable { /// Forwards only those values from `self` which are not duplicates of the /// immedately preceding value. The first value is always forwarded. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func skipRepeats() -> Signal { return skipRepeats(==) } } extension SignalType { /// Forwards only those values from `self` which do not pass `isRepeat` with /// respect to the previous value. The first value is always forwarded. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func skipRepeats(isRepeat: (Value, Value) -> Bool) -> Signal { return self .map(Optional.init) .combinePrevious(nil) .filter { a, b in if let a = a, b = b where isRepeat(a, b) { return false } else { return true } } .map { $0.1! } } /// Does not forward any values from `self` until `predicate` returns false, /// at which point the returned signal behaves exactly like `signal`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func skipWhile(predicate: Value -> Bool) -> Signal { return Signal { observer in var shouldSkip = true return self.observe { event in switch event { case let .Next(value): shouldSkip = shouldSkip && predicate(value) if !shouldSkip { fallthrough } default: observer.action(event) } } } } /// Forwards events from `self` until `replacement` begins sending events. /// /// Returns a signal which passes through `Next`, `Failed`, and `Interrupted` /// events from `signal` until `replacement` sends an event, at which point the /// returned signal will send that event and switch to passing through events /// from `replacement` instead, regardless of whether `self` has sent events /// already. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func takeUntilReplacement(replacement: Signal) -> Signal { return Signal { observer in let disposable = CompositeDisposable() let signalDisposable = self.observe { event in switch event { case .Completed: break case .Next, .Failed, .Interrupted: observer.action(event) } } disposable += signalDisposable disposable += replacement.observe { event in signalDisposable?.dispose() observer.action(event) } return disposable } } /// Waits until `self` completes and then forwards the final `count` values /// on the returned signal. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func takeLast(count: Int) -> Signal { return Signal { observer in var buffer: [Value] = [] buffer.reserveCapacity(count) return self.observe { event in switch event { case let .Next(value): // To avoid exceeding the reserved capacity of the buffer, we remove then add. // Remove elements until we have room to add one more. while (buffer.count + 1) > count { buffer.removeAtIndex(0) } buffer.append(value) case let .Failed(error): observer.sendFailed(error) case .Completed: for bufferedValue in buffer { observer.sendNext(bufferedValue) } observer.sendCompleted() case .Interrupted: observer.sendInterrupted() } } } } /// Forwards any values from `self` until `predicate` returns false, /// at which point the returned signal will complete. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func takeWhile(predicate: Value -> Bool) -> Signal { return Signal { observer in return self.observe { event in if case let .Next(value) = event where !predicate(value) { observer.sendCompleted() } else { observer.action(event) } } } } } private struct ZipState { var values: [Value] = [] var completed = false var isFinished: Bool { return values.isEmpty && completed } } extension SignalType { /// Zips elements of two signals into pairs. The elements of any Nth pair /// are the Nth elements of the two input signals. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zipWith(otherSignal: Signal) -> Signal<(Value, U), Error> { return Signal { observer in let states = Atomic(ZipState(), ZipState()) let disposable = CompositeDisposable() let flush = { () -> () in var originalStates: (ZipState, ZipState)! states.modify { states in originalStates = states var updatedStates = states let extractCount = min(states.0.values.count, states.1.values.count) updatedStates.0.values.removeRange(0 ..< extractCount) updatedStates.1.values.removeRange(0 ..< extractCount) return updatedStates } while !originalStates.0.values.isEmpty && !originalStates.1.values.isEmpty { let left = originalStates.0.values.removeAtIndex(0) let right = originalStates.1.values.removeAtIndex(0) observer.sendNext((left, right)) } if originalStates.0.isFinished || originalStates.1.isFinished { observer.sendCompleted() } } let onFailed = { observer.sendFailed($0) } let onInterrupted = { observer.sendInterrupted() } disposable += self.observe { event in switch event { case let .Next(value): states.modify { (var states) in states.0.values.append(value) return states } flush() case let .Failed(error): onFailed(error) case .Completed: states.modify { (var states) in states.0.completed = true return states } flush() case .Interrupted: onInterrupted() } } disposable += otherSignal.observe { event in switch event { case let .Next(value): states.modify { (var states) in states.1.values.append(value) return states } flush() case let .Failed(error): onFailed(error) case .Completed: states.modify { (var states) in states.1.completed = true return states } flush() case .Interrupted: onInterrupted() } } return disposable } } /// Applies `operation` to values from `self` with `Success`ful results /// forwarded on the returned signal and `Failure`s sent as `Failed` events. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func attempt(operation: Value -> Result<(), Error>) -> Signal { return attemptMap { value in return operation(value).map { return value } } } /// Applies `operation` to values from `self` with `Success`ful results mapped /// on the returned signal and `Failure`s sent as `Failed` events. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func attemptMap(operation: Value -> Result) -> Signal { return Signal { observer in self.observe { event in switch event { case let .Next(value): operation(value).analysis(ifSuccess: { value in observer.sendNext(value) }, ifFailure: { error in observer.sendFailed(error) }) case let .Failed(error): observer.sendFailed(error) case .Completed: observer.sendCompleted() case .Interrupted: observer.sendInterrupted() } } } } /// Throttle values sent by the receiver, so that at least `interval` /// seconds pass between each, then forwards them on the given scheduler. /// /// If multiple values are received before the interval has elapsed, the /// latest value is the one that will be passed on. /// /// If the input signal terminates while a value is being throttled, that value /// will be discarded and the returned signal will terminate immediately. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func throttle(interval: NSTimeInterval, onScheduler scheduler: DateSchedulerType) -> Signal { precondition(interval >= 0) return Signal { observer in let state: Atomic> = Atomic(ThrottleState()) let schedulerDisposable = SerialDisposable() let disposable = CompositeDisposable() disposable.addDisposable(schedulerDisposable) disposable += self.observe { event in if case let .Next(value) = event { var scheduleDate: NSDate! state.modify { (var state) in state.pendingValue = value let proposedScheduleDate = state.previousDate?.dateByAddingTimeInterval(interval) ?? scheduler.currentDate scheduleDate = proposedScheduleDate.laterDate(scheduler.currentDate) return state } schedulerDisposable.innerDisposable = scheduler.scheduleAfter(scheduleDate) { let previousState = state.modify { (var state) in if state.pendingValue != nil { state.pendingValue = nil state.previousDate = scheduleDate } return state } if let pendingValue = previousState.pendingValue { observer.sendNext(pendingValue) } } } else { schedulerDisposable.innerDisposable = scheduler.schedule { observer.action(event) } } } return disposable } } } private struct ThrottleState { var previousDate: NSDate? = nil var pendingValue: Value? = nil } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal) -> Signal<(A, B), Error> { return a.combineLatestWith(b) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal, _ c: Signal) -> Signal<(A, B, C), Error> { return combineLatest(a, b) .combineLatestWith(c) .map(repack) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal) -> Signal<(A, B, C, D), Error> { return combineLatest(a, b, c) .combineLatestWith(d) .map(repack) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal) -> Signal<(A, B, C, D, E), Error> { return combineLatest(a, b, c, d) .combineLatestWith(e) .map(repack) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal) -> Signal<(A, B, C, D, E, F), Error> { return combineLatest(a, b, c, d, e) .combineLatestWith(f) .map(repack) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal) -> Signal<(A, B, C, D, E, F, G), Error> { return combineLatest(a, b, c, d, e, f) .combineLatestWith(g) .map(repack) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal) -> Signal<(A, B, C, D, E, F, G, H), Error> { return combineLatest(a, b, c, d, e, f, g) .combineLatestWith(h) .map(repack) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal) -> Signal<(A, B, C, D, E, F, G, H, I), Error> { return combineLatest(a, b, c, d, e, f, g, h) .combineLatestWith(i) .map(repack) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal, _ j: Signal) -> Signal<(A, B, C, D, E, F, G, H, I, J), Error> { return combineLatest(a, b, c, d, e, f, g, h, i) .combineLatestWith(j) .map(repack) } /// Combines the values of all the given signals, in the manner described by /// `combineLatestWith`. No events will be sent if the sequence is empty. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func combineLatest>(signals: S) -> Signal<[Value], Error> { var generator = signals.generate() if let first = generator.next() { let initial = first.map { [$0] } return GeneratorSequence(generator).reduce(initial) { signal, next in signal.combineLatestWith(next).map { $0.0 + [$0.1] } } } return .never } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal) -> Signal<(A, B), Error> { return a.zipWith(b) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal, _ c: Signal) -> Signal<(A, B, C), Error> { return zip(a, b) .zipWith(c) .map(repack) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal) -> Signal<(A, B, C, D), Error> { return zip(a, b, c) .zipWith(d) .map(repack) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal) -> Signal<(A, B, C, D, E), Error> { return zip(a, b, c, d) .zipWith(e) .map(repack) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal) -> Signal<(A, B, C, D, E, F), Error> { return zip(a, b, c, d, e) .zipWith(f) .map(repack) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal) -> Signal<(A, B, C, D, E, F, G), Error> { return zip(a, b, c, d, e, f) .zipWith(g) .map(repack) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal) -> Signal<(A, B, C, D, E, F, G, H), Error> { return zip(a, b, c, d, e, f, g) .zipWith(h) .map(repack) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal) -> Signal<(A, B, C, D, E, F, G, H, I), Error> { return zip(a, b, c, d, e, f, g, h) .zipWith(i) .map(repack) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip(a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal, _ j: Signal) -> Signal<(A, B, C, D, E, F, G, H, I, J), Error> { return zip(a, b, c, d, e, f, g, h, i) .zipWith(j) .map(repack) } /// Zips the values of all the given signals, in the manner described by /// `zipWith`. No events will be sent if the sequence is empty. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func zip>(signals: S) -> Signal<[Value], Error> { var generator = signals.generate() if let first = generator.next() { let initial = first.map { [$0] } return GeneratorSequence(generator).reduce(initial) { signal, next in signal.zipWith(next).map { $0.0 + [$0.1] } } } return .never } extension SignalType { /// Forwards events from `self` until `interval`. Then if signal isn't completed yet, /// fails with `error` on `scheduler`. /// /// If the interval is 0, the timeout will be scheduled immediately. The signal /// must complete synchronously (or on a faster scheduler) to avoid the timeout. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func timeoutWithError(error: Error, afterInterval interval: NSTimeInterval, onScheduler scheduler: DateSchedulerType) -> Signal { precondition(interval >= 0) return Signal { observer in let disposable = CompositeDisposable() let date = scheduler.currentDate.dateByAddingTimeInterval(interval) disposable += scheduler.scheduleAfter(date) { observer.sendFailed(error) } disposable += self.observe(observer) return disposable } } } extension SignalType where Error == NoError { /// Promotes a signal that does not generate failures into one that can. /// /// This does not actually cause failures to be generated for the given signal, /// but makes it easier to combine with other signals that may fail; for /// example, with operators like `combineLatestWith`, `zipWith`, `flatten`, etc. @warn_unused_result(message="Did you forget to call `observe` on the signal?") public func promoteErrors(_: F.Type) -> Signal { return Signal { observer in return self.observe { event in switch event { case let .Next(value): observer.sendNext(value) case .Failed: fatalError("NoError is impossible to construct") case .Completed: observer.sendCompleted() case .Interrupted: observer.sendInterrupted() } } } } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/SignalProducer.swift ================================================ import Result /// A SignalProducer creates Signals that can produce values of type `Value` and/or /// fail with errors of type `Error`. If no failure should be possible, NoError /// can be specified for `Error`. /// /// SignalProducers can be used to represent operations or tasks, like network /// requests, where each invocation of start() will create a new underlying /// operation. This ensures that consumers will receive the results, versus a /// plain Signal, where the results might be sent before any observers are /// attached. /// /// Because of the behavior of start(), different Signals created from the /// producer may see a different version of Events. The Events may arrive in a /// different order between Signals, or the stream might be completely /// different! public struct SignalProducer { public typealias ProducedSignal = Signal private let startHandler: (Signal.Observer, CompositeDisposable) -> () /// Initializes a SignalProducer that will emit the same events as the given signal. /// /// If the Disposable returned from start() is disposed or a terminating /// event is sent to the observer, the given signal will be /// disposed. public init(signal: S) { self.init { observer, disposable in disposable += signal.observe(observer) } } /// Initializes a SignalProducer that will invoke the given closure once /// for each invocation of start(). /// /// The events that the closure puts into the given observer will become /// the events sent by the started Signal to its observers. /// /// If the Disposable returned from start() is disposed or a terminating /// event is sent to the observer, the given CompositeDisposable will be /// disposed, at which point work should be interrupted and any temporary /// resources cleaned up. public init(_ startHandler: (Signal.Observer, CompositeDisposable) -> ()) { self.startHandler = startHandler } /// Creates a producer for a Signal that will immediately send one value /// then complete. public init(value: Value) { self.init { observer, disposable in observer.sendNext(value) observer.sendCompleted() } } /// Creates a producer for a Signal that will immediately fail with the /// given error. public init(error: Error) { self.init { observer, disposable in observer.sendFailed(error) } } /// Creates a producer for a Signal that will immediately send one value /// then complete, or immediately fail, depending on the given Result. public init(result: Result) { switch result { case let .Success(value): self.init(value: value) case let .Failure(error): self.init(error: error) } } /// Creates a producer for a Signal that will immediately send the values /// from the given sequence, then complete. public init(values: S) { self.init { observer, disposable in for value in values { observer.sendNext(value) if disposable.disposed { break } } observer.sendCompleted() } } /// A producer for a Signal that will immediately complete without sending /// any values. public static var empty: SignalProducer { return self.init { observer, disposable in observer.sendCompleted() } } /// A producer for a Signal that never sends any events to its observers. public static var never: SignalProducer { return self.init { _ in return } } /// Creates a queue for events that replays them when new signals are /// created from the returned producer. /// /// When values are put into the returned observer (observer), they will be /// added to an internal buffer. If the buffer is already at capacity, /// the earliest (oldest) value will be dropped to make room for the new /// value. /// /// Signals created from the returned producer will stay alive until a /// terminating event is added to the queue. If the queue does not contain /// such an event when the Signal is started, all values sent to the /// returned observer will be automatically forwarded to the Signal’s /// observers until a terminating event is received. /// /// After a terminating event has been added to the queue, the observer /// will not add any further events. This _does not_ count against the /// value capacity so no buffered values will be dropped on termination. public static func buffer(capacity: Int = Int.max) -> (SignalProducer, Signal.Observer) { precondition(capacity >= 0) // This is effectively used as a synchronous mutex, but permitting // limited recursive locking (see below). // // The queue is a "variable" just so we can use its address as the key // and the value for dispatch_queue_set_specific(). var queue = dispatch_queue_create("org.reactivecocoa.ReactiveCocoa.SignalProducer.buffer", DISPATCH_QUEUE_SERIAL) dispatch_queue_set_specific(queue, &queue, &queue, nil) // Used as an atomic variable so we can remove observers without needing // to run on the queue. let state: Atomic> = Atomic(BufferState()) let producer = self.init { observer, disposable in // Assigned to when replay() is invoked synchronously below. var token: RemovalToken? let replay: () -> () = { let originalState = state.modify { (var state) in token = state.observers?.insert(observer) return state } for value in originalState.values { observer.sendNext(value) } if let terminationEvent = originalState.terminationEvent { observer.action(terminationEvent) } } // Prevent other threads from sending events while we're replaying, // but don't deadlock if we're replaying in response to a buffer // event observed elsewhere. // // In other words, this permits limited signal recursion for the // specific case of replaying past events. if dispatch_get_specific(&queue) != nil { replay() } else { dispatch_sync(queue, replay) } if let token = token { disposable.addDisposable { state.modify { (var state) in state.observers?.removeValueForToken(token) return state } } } } let bufferingObserver: Signal.Observer = Observer { event in // Send serially with respect to other senders, and never while // another thread is in the process of replaying. dispatch_sync(queue) { let originalState = state.modify { (var state) in if let value = event.value { state.addValue(value, upToCapacity: capacity) } else { // Disconnect all observers and prevent future // attachments. state.terminationEvent = event state.observers = nil } return state } if let observers = originalState.observers { for observer in observers { observer.action(event) } } } } return (producer, bufferingObserver) } /// Creates a SignalProducer that will attempt the given operation once for /// each invocation of start(). /// /// Upon success, the started signal will send the resulting value then /// complete. Upon failure, the started signal will fail with the error that /// occurred. public static func attempt(operation: () -> Result) -> SignalProducer { return self.init { observer, disposable in operation().analysis(ifSuccess: { value in observer.sendNext(value) observer.sendCompleted() }, ifFailure: { error in observer.sendFailed(error) }) } } /// Creates a Signal from the producer, passes it into the given closure, /// then starts sending events on the Signal when the closure has returned. /// /// The closure will also receive a disposable which can be used to /// interrupt the work associated with the signal and immediately send an /// `Interrupted` event. public func startWithSignal(@noescape setUp: (Signal, Disposable) -> ()) { let (signal, observer) = Signal.pipe() // Disposes of the work associated with the SignalProducer and any // upstream producers. let producerDisposable = CompositeDisposable() // Directly disposed of when start() or startWithSignal() is disposed. let cancelDisposable = ActionDisposable { observer.sendInterrupted() producerDisposable.dispose() } setUp(signal, cancelDisposable) if cancelDisposable.disposed { return } let wrapperObserver: Signal.Observer = Observer { event in observer.action(event) if event.isTerminating { // Dispose only after notifying the Signal, so disposal // logic is consistently the last thing to run. producerDisposable.dispose() } } startHandler(wrapperObserver, producerDisposable) } } private struct BufferState { // All values in the buffer. var values: [Value] = [] // Any terminating event sent to the buffer. // // This will be nil if termination has not occurred. var terminationEvent: Event? // The observers currently attached to the buffered producer, or nil if the // producer was terminated. var observers: Bag.Observer>? = Bag() // Appends a new value to the buffer, trimming it down to the given capacity // if necessary. mutating func addValue(value: Value, upToCapacity capacity: Int) { values.append(value) let overflow = values.count - capacity if overflow > 0 { values.removeRange(0.. { get } /// Creates a Signal from the producer, passes it into the given closure, /// then starts sending events on the Signal when the closure has returned. func startWithSignal(@noescape setUp: (Signal, Disposable) -> ()) } extension SignalProducer: SignalProducerType { public var producer: SignalProducer { return self } } extension SignalProducerType { /// Creates a Signal from the producer, then attaches the given observer to /// the Signal as an observer. /// /// Returns a Disposable which can be used to interrupt the work associated /// with the signal and immediately send an `Interrupted` event. public func start(observer: Signal.Observer = Signal.Observer()) -> Disposable { var disposable: Disposable! startWithSignal { signal, innerDisposable in signal.observe(observer) disposable = innerDisposable } return disposable } /// Convenience override for start(_:) to allow trailing-closure style /// invocations. public func start(observerAction: Signal.Observer.Action) -> Disposable { return start(Observer(observerAction)) } /// Creates a Signal from the producer, then adds exactly one observer to /// the Signal, which will invoke the given callback when `next` events are /// received. /// /// Returns a Disposable which can be used to interrupt the work associated /// with the Signal, and prevent any future callbacks from being invoked. public func startWithNext(next: Value -> ()) -> Disposable { return start(Observer(next: next)) } /// Creates a Signal from the producer, then adds exactly one observer to /// the Signal, which will invoke the given callback when a `completed` event is /// received. /// /// Returns a Disposable which can be used to interrupt the work associated /// with the Signal. public func startWithCompleted(completed: () -> ()) -> Disposable { return start(Observer(completed: completed)) } /// Creates a Signal from the producer, then adds exactly one observer to /// the Signal, which will invoke the given callback when a `failed` event is /// received. /// /// Returns a Disposable which can be used to interrupt the work associated /// with the Signal. public func startWithFailed(failed: Error -> ()) -> Disposable { return start(Observer(failed: failed)) } /// Creates a Signal from the producer, then adds exactly one observer to /// the Signal, which will invoke the given callback when an `interrupted` event is /// received. /// /// Returns a Disposable which can be used to interrupt the work associated /// with the Signal. public func startWithInterrupted(interrupted: () -> ()) -> Disposable { return start(Observer(interrupted: interrupted)) } /// Lifts an unary Signal operator to operate upon SignalProducers instead. /// /// In other words, this will create a new SignalProducer which will apply /// the given Signal operator to _every_ created Signal, just as if the /// operator had been applied to each Signal yielded from start(). @warn_unused_result(message="Did you forget to call `start` on the producer?") public func lift(transform: Signal -> Signal) -> SignalProducer { return SignalProducer { observer, outerDisposable in self.startWithSignal { signal, innerDisposable in outerDisposable.addDisposable(innerDisposable) transform(signal).observe(observer) } } } /// Lifts a binary Signal operator to operate upon SignalProducers instead. /// /// In other words, this will create a new SignalProducer which will apply /// the given Signal operator to _every_ Signal created from the two /// producers, just as if the operator had been applied to each Signal /// yielded from start(). /// /// Note: starting the returned producer will start the receiver of the operator, /// which may not be adviseable for some operators. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func lift(transform: Signal -> Signal -> Signal) -> SignalProducer -> SignalProducer { return liftRight(transform) } /// Right-associative lifting of a binary signal operator over producers. That /// is, the argument producer will be started before the receiver. When both /// producers are synchronous this order can be important depending on the operator /// to generate correct results. @warn_unused_result(message="Did you forget to call `start` on the producer?") private func liftRight(transform: Signal -> Signal -> Signal) -> SignalProducer -> SignalProducer { return { otherProducer in return SignalProducer { observer, outerDisposable in self.startWithSignal { signal, disposable in outerDisposable.addDisposable(disposable) otherProducer.startWithSignal { otherSignal, otherDisposable in outerDisposable.addDisposable(otherDisposable) transform(signal)(otherSignal).observe(observer) } } } } } /// Left-associative lifting of a binary signal operator over producers. That /// is, the receiver will be started before the argument producer. When both /// producers are synchronous this order can be important depending on the operator /// to generate correct results. @warn_unused_result(message="Did you forget to call `start` on the producer?") private func liftLeft(transform: Signal -> Signal -> Signal) -> SignalProducer -> SignalProducer { return { otherProducer in return SignalProducer { observer, outerDisposable in otherProducer.startWithSignal { otherSignal, otherDisposable in outerDisposable.addDisposable(otherDisposable) self.startWithSignal { signal, disposable in outerDisposable.addDisposable(disposable) transform(signal)(otherSignal).observe(observer) } } } } } /// Lifts a binary Signal operator to operate upon a Signal and a SignalProducer instead. /// /// In other words, this will create a new SignalProducer which will apply /// the given Signal operator to _every_ Signal created from the two /// producers, just as if the operator had been applied to each Signal /// yielded from start(). @warn_unused_result(message="Did you forget to call `start` on the producer?") public func lift(transform: Signal -> Signal -> Signal) -> Signal -> SignalProducer { return { otherSignal in return SignalProducer { observer, outerDisposable in self.startWithSignal { signal, disposable in outerDisposable += disposable outerDisposable += transform(signal)(otherSignal).observe(observer) } } } } /// Maps each value in the producer to a new value. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func map(transform: Value -> U) -> SignalProducer { return lift { $0.map(transform) } } /// Maps errors in the producer to a new error. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func mapError(transform: Error -> F) -> SignalProducer { return lift { $0.mapError(transform) } } /// Preserves only the values of the producer that pass the given predicate. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func filter(predicate: Value -> Bool) -> SignalProducer { return lift { $0.filter(predicate) } } /// Returns a producer that will yield the first `count` values from the /// input producer. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func take(count: Int) -> SignalProducer { return lift { $0.take(count) } } /// Returns a signal that will yield an array of values when `signal` completes. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func collect() -> SignalProducer<[Value], Error> { return lift { $0.collect() } } /// Forwards all events onto the given scheduler, instead of whichever /// scheduler they originally arrived upon. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func observeOn(scheduler: SchedulerType) -> SignalProducer { return lift { $0.observeOn(scheduler) } } /// Combines the latest value of the receiver with the latest value from /// the given producer. /// /// The returned producer will not send a value until both inputs have sent at /// least one value each. If either producer is interrupted, the returned producer /// will also be interrupted. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatestWith(otherProducer: SignalProducer) -> SignalProducer<(Value, U), Error> { return liftRight(Signal.combineLatestWith)(otherProducer) } /// Combines the latest value of the receiver with the latest value from /// the given signal. /// /// The returned producer will not send a value until both inputs have sent at /// least one value each. If either input is interrupted, the returned producer /// will also be interrupted. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatestWith(otherSignal: Signal) -> SignalProducer<(Value, U), Error> { return lift(Signal.combineLatestWith)(otherSignal) } /// Delays `Next` and `Completed` events by the given interval, forwarding /// them on the given scheduler. /// /// `Failed` and `Interrupted` events are always scheduled immediately. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func delay(interval: NSTimeInterval, onScheduler scheduler: DateSchedulerType) -> SignalProducer { return lift { $0.delay(interval, onScheduler: scheduler) } } /// Returns a producer that will skip the first `count` values, then forward /// everything afterward. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func skip(count: Int) -> SignalProducer { return lift { $0.skip(count) } } /// Treats all Events from the input producer as plain values, allowing them to be /// manipulated just like any other value. /// /// In other words, this brings Events “into the monad.” /// /// When a Completed or Failed event is received, the resulting producer will send /// the Event itself and then complete. When an Interrupted event is received, /// the resulting producer will send the Event itself and then interrupt. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func materialize() -> SignalProducer, NoError> { return lift { $0.materialize() } } /// Forwards the latest value from `self` whenever `sampler` sends a Next /// event. /// /// If `sampler` fires before a value has been observed on `self`, nothing /// happens. /// /// Returns a producer that will send values from `self`, sampled (possibly /// multiple times) by `sampler`, then complete once both input producers have /// completed, or interrupt if either input producer is interrupted. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func sampleOn(sampler: SignalProducer<(), NoError>) -> SignalProducer { return liftLeft(Signal.sampleOn)(sampler) } /// Forwards the latest value from `self` whenever `sampler` sends a Next /// event. /// /// If `sampler` fires before a value has been observed on `self`, nothing /// happens. /// /// Returns a producer that will send values from `self`, sampled (possibly /// multiple times) by `sampler`, then complete once both inputs have /// completed, or interrupt if either input is interrupted. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func sampleOn(sampler: Signal<(), NoError>) -> SignalProducer { return lift(Signal.sampleOn)(sampler) } /// Forwards events from `self` until `trigger` sends a Next or Completed /// event, at which point the returned producer will complete. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func takeUntil(trigger: SignalProducer<(), NoError>) -> SignalProducer { return liftRight(Signal.takeUntil)(trigger) } /// Forwards events from `self` until `trigger` sends a Next or Completed /// event, at which point the returned producer will complete. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func takeUntil(trigger: Signal<(), NoError>) -> SignalProducer { return lift(Signal.takeUntil)(trigger) } /// Does not forward any values from `self` until `trigger` sends a Next or /// Completed, at which point the returned signal behaves exactly like `signal`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func skipUntil(trigger: SignalProducer<(), NoError>) -> SignalProducer { return liftRight(Signal.skipUntil)(trigger) } /// Does not forward any values from `self` until `trigger` sends a Next or /// Completed, at which point the returned signal behaves exactly like `signal`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func skipUntil(trigger: Signal<(), NoError>) -> SignalProducer { return lift(Signal.skipUntil)(trigger) } /// Forwards events from `self` with history: values of the returned producer /// are a tuple whose first member is the previous value and whose second member /// is the current value. `initial` is supplied as the first member when `self` /// sends its first value. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combinePrevious(initial: Value) -> SignalProducer<(Value, Value), Error> { return lift { $0.combinePrevious(initial) } } /// Like `scan`, but sends only the final value and then immediately completes. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func reduce(initial: U, _ combine: (U, Value) -> U) -> SignalProducer { return lift { $0.reduce(initial, combine) } } /// Aggregates `self`'s values into a single combined value. When `self` emits /// its first value, `combine` is invoked with `initial` as the first argument and /// that emitted value as the second argument. The result is emitted from the /// producer returned from `scan`. That result is then passed to `combine` as the /// first argument when the next value is emitted, and so on. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func scan(initial: U, _ combine: (U, Value) -> U) -> SignalProducer { return lift { $0.scan(initial, combine) } } /// Forwards only those values from `self` which do not pass `isRepeat` with /// respect to the previous value. The first value is always forwarded. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func skipRepeats(isRepeat: (Value, Value) -> Bool) -> SignalProducer { return lift { $0.skipRepeats(isRepeat) } } /// Does not forward any values from `self` until `predicate` returns false, /// at which point the returned signal behaves exactly like `self`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func skipWhile(predicate: Value -> Bool) -> SignalProducer { return lift { $0.skipWhile(predicate) } } /// Forwards events from `self` until `replacement` begins sending events. /// /// Returns a producer which passes through `Next`, `Failed`, and `Interrupted` /// events from `self` until `replacement` sends an event, at which point the /// returned producer will send that event and switch to passing through events /// from `replacement` instead, regardless of whether `self` has sent events /// already. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func takeUntilReplacement(replacement: SignalProducer) -> SignalProducer { return liftRight(Signal.takeUntilReplacement)(replacement) } /// Forwards events from `self` until `replacement` begins sending events. /// /// Returns a producer which passes through `Next`, `Error`, and `Interrupted` /// events from `self` until `replacement` sends an event, at which point the /// returned producer will send that event and switch to passing through events /// from `replacement` instead, regardless of whether `self` has sent events /// already. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func takeUntilReplacement(replacement: Signal) -> SignalProducer { return lift(Signal.takeUntilReplacement)(replacement) } /// Waits until `self` completes and then forwards the final `count` values /// on the returned producer. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func takeLast(count: Int) -> SignalProducer { return lift { $0.takeLast(count) } } /// Forwards any values from `self` until `predicate` returns false, /// at which point the returned producer will complete. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func takeWhile(predicate: Value -> Bool) -> SignalProducer { return lift { $0.takeWhile(predicate) } } /// Zips elements of two producers into pairs. The elements of any Nth pair /// are the Nth elements of the two input producers. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zipWith(otherProducer: SignalProducer) -> SignalProducer<(Value, U), Error> { return liftRight(Signal.zipWith)(otherProducer) } /// Zips elements of this producer and a signal into pairs. The elements of /// any Nth pair are the Nth elements of the two. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zipWith(otherSignal: Signal) -> SignalProducer<(Value, U), Error> { return lift(Signal.zipWith)(otherSignal) } /// Applies `operation` to values from `self` with `Success`ful results /// forwarded on the returned producer and `Failure`s sent as `Failed` events. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func attempt(operation: Value -> Result<(), Error>) -> SignalProducer { return lift { $0.attempt(operation) } } /// Applies `operation` to values from `self` with `Success`ful results mapped /// on the returned producer and `Failure`s sent as `Failed` events. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func attemptMap(operation: Value -> Result) -> SignalProducer { return lift { $0.attemptMap(operation) } } /// Throttle values sent by the receiver, so that at least `interval` /// seconds pass between each, then forwards them on the given scheduler. /// /// If multiple values are received before the interval has elapsed, the /// latest value is the one that will be passed on. /// /// If `self` terminates while a value is being throttled, that value /// will be discarded and the returned producer will terminate immediately. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func throttle(interval: NSTimeInterval, onScheduler scheduler: DateSchedulerType) -> SignalProducer { return lift { $0.throttle(interval, onScheduler: scheduler) } } /// Forwards events from `self` until `interval`. Then if producer isn't completed yet, /// fails with `error` on `scheduler`. /// /// If the interval is 0, the timeout will be scheduled immediately. The producer /// must complete synchronously (or on a faster scheduler) to avoid the timeout. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func timeoutWithError(error: Error, afterInterval interval: NSTimeInterval, onScheduler scheduler: DateSchedulerType) -> SignalProducer { return lift { $0.timeoutWithError(error, afterInterval: interval, onScheduler: scheduler) } } } extension SignalProducerType where Value: OptionalType { /// Unwraps non-`nil` values and forwards them on the returned signal, `nil` /// values are dropped. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func ignoreNil() -> SignalProducer { return lift { $0.ignoreNil() } } } extension SignalProducerType where Value: EventType, Error == NoError { /// The inverse of materialize(), this will translate a signal of `Event` /// _values_ into a signal of those events themselves. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func dematerialize() -> SignalProducer { return lift { $0.dematerialize() } } } extension SignalProducerType where Error == NoError { /// Promotes a producer that does not generate failures into one that can. /// /// This does not actually cause failers to be generated for the given producer, /// but makes it easier to combine with other producers that may fail; for /// example, with operators like `combineLatestWith`, `zipWith`, `flatten`, etc. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func promoteErrors(_: F.Type) -> SignalProducer { return lift { $0.promoteErrors(F) } } } extension SignalProducerType where Value: Equatable { /// Forwards only those values from `self` which are not duplicates of the /// immedately preceding value. The first value is always forwarded. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func skipRepeats() -> SignalProducer { return lift { $0.skipRepeats() } } } /// Creates a repeating timer of the given interval, with a reasonable /// default leeway, sending updates on the given scheduler. /// /// This timer will never complete naturally, so all invocations of start() must /// be disposed to avoid leaks. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func timer(interval: NSTimeInterval, onScheduler scheduler: DateSchedulerType) -> SignalProducer { // Apple's "Power Efficiency Guide for Mac Apps" recommends a leeway of // at least 10% of the timer interval. return timer(interval, onScheduler: scheduler, withLeeway: interval * 0.1) } /// Creates a repeating timer of the given interval, sending updates on the /// given scheduler. /// /// This timer will never complete naturally, so all invocations of start() must /// be disposed to avoid leaks. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func timer(interval: NSTimeInterval, onScheduler scheduler: DateSchedulerType, withLeeway leeway: NSTimeInterval) -> SignalProducer { precondition(interval >= 0) precondition(leeway >= 0) return SignalProducer { observer, compositeDisposable in compositeDisposable += scheduler.scheduleAfter(scheduler.currentDate.dateByAddingTimeInterval(interval), repeatingEvery: interval, withLeeway: leeway) { observer.sendNext(scheduler.currentDate) } } } extension SignalProducerType { /// Injects side effects to be performed upon the specified signal events. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func on(started started: (() -> ())? = nil, event: (Event -> ())? = nil, failed: (Error -> ())? = nil, completed: (() -> ())? = nil, interrupted: (() -> ())? = nil, terminated: (() -> ())? = nil, disposed: (() -> ())? = nil, next: (Value -> ())? = nil) -> SignalProducer { return SignalProducer { observer, compositeDisposable in started?() self.startWithSignal { signal, disposable in compositeDisposable += disposable compositeDisposable += signal .on( event: event, failed: failed, completed: completed, interrupted: interrupted, terminated: terminated, disposed: disposed, next: next ) .observe(observer) } } } /// Starts the returned signal on the given Scheduler. /// /// This implies that any side effects embedded in the producer will be /// performed on the given scheduler as well. /// /// Events may still be sent upon other schedulers—this merely affects where /// the `start()` method is run. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func startOn(scheduler: SchedulerType) -> SignalProducer { return SignalProducer { observer, compositeDisposable in compositeDisposable += scheduler.schedule { self.startWithSignal { signal, signalDisposable in compositeDisposable.addDisposable(signalDisposable) signal.observe(observer) } } } } } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer) -> SignalProducer<(A, B), Error> { return a.combineLatestWith(b) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer) -> SignalProducer<(A, B, C), Error> { return combineLatest(a, b) .combineLatestWith(c) .map(repack) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer) -> SignalProducer<(A, B, C, D), Error> { return combineLatest(a, b, c) .combineLatestWith(d) .map(repack) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer) -> SignalProducer<(A, B, C, D, E), Error> { return combineLatest(a, b, c, d) .combineLatestWith(e) .map(repack) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer) -> SignalProducer<(A, B, C, D, E, F), Error> { return combineLatest(a, b, c, d, e) .combineLatestWith(f) .map(repack) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer) -> SignalProducer<(A, B, C, D, E, F, G), Error> { return combineLatest(a, b, c, d, e, f) .combineLatestWith(g) .map(repack) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer) -> SignalProducer<(A, B, C, D, E, F, G, H), Error> { return combineLatest(a, b, c, d, e, f, g) .combineLatestWith(h) .map(repack) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer) -> SignalProducer<(A, B, C, D, E, F, G, H, I), Error> { return combineLatest(a, b, c, d, e, f, g, h) .combineLatestWith(i) .map(repack) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer, _ j: SignalProducer) -> SignalProducer<(A, B, C, D, E, F, G, H, I, J), Error> { return combineLatest(a, b, c, d, e, f, g, h, i) .combineLatestWith(j) .map(repack) } /// Combines the values of all the given producers, in the manner described by /// `combineLatestWith`. Will return an empty `SignalProducer` if the sequence is empty. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func combineLatest>(producers: S) -> SignalProducer<[Value], Error> { var generator = producers.generate() if let first = generator.next() { let initial = first.map { [$0] } return GeneratorSequence(generator).reduce(initial) { producer, next in producer.combineLatestWith(next).map { $0.0 + [$0.1] } } } return .empty } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer) -> SignalProducer<(A, B), Error> { return a.zipWith(b) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer) -> SignalProducer<(A, B, C), Error> { return zip(a, b) .zipWith(c) .map(repack) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer) -> SignalProducer<(A, B, C, D), Error> { return zip(a, b, c) .zipWith(d) .map(repack) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer) -> SignalProducer<(A, B, C, D, E), Error> { return zip(a, b, c, d) .zipWith(e) .map(repack) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer) -> SignalProducer<(A, B, C, D, E, F), Error> { return zip(a, b, c, d, e) .zipWith(f) .map(repack) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer) -> SignalProducer<(A, B, C, D, E, F, G), Error> { return zip(a, b, c, d, e, f) .zipWith(g) .map(repack) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer) -> SignalProducer<(A, B, C, D, E, F, G, H), Error> { return zip(a, b, c, d, e, f, g) .zipWith(h) .map(repack) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer) -> SignalProducer<(A, B, C, D, E, F, G, H, I), Error> { return zip(a, b, c, d, e, f, g, h) .zipWith(i) .map(repack) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip(a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer, _ j: SignalProducer) -> SignalProducer<(A, B, C, D, E, F, G, H, I, J), Error> { return zip(a, b, c, d, e, f, g, h, i) .zipWith(j) .map(repack) } /// Zips the values of all the given producers, in the manner described by /// `zipWith`. Will return an empty `SignalProducer` if the sequence is empty. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func zip>(producers: S) -> SignalProducer<[Value], Error> { var generator = producers.generate() if let first = generator.next() { let initial = first.map { [$0] } return GeneratorSequence(generator).reduce(initial) { producer, next in producer.zipWith(next).map { $0.0 + [$0.1] } } } return .empty } extension SignalProducerType where Value: SignalProducerType, Error == Value.Error { /// Flattens the inner producers sent upon `producer` (into a single producer of /// values), according to the semantics of the given strategy. /// /// If `producer` or an active inner producer fails, the returned /// producer will forward that failure immediately. /// /// `Interrupted` events on inner producers will be treated like `Completed` /// events on inner producers. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func flatten(strategy: FlattenStrategy) -> SignalProducer { return lift { (signal: Signal) -> Signal in return signal.flatten(strategy) } } } extension SignalProducerType where Value: SignalType, Error == Value.Error { /// Flattens the inner signals sent upon `producer` (into a single producer of /// values), according to the semantics of the given strategy. /// /// If `producer` or an active inner signal emits an error, the returned /// producer will forward that error immediately. /// /// `Interrupted` events on inner signals will be treated like `Completed` /// events on inner signals. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func flatten(strategy: FlattenStrategy) -> SignalProducer { return self.lift { $0.flatten(strategy) } } } extension SignalProducerType { /// Maps each event from `producer` to a new producer, then flattens the /// resulting producers (into a single producer of values), according to the /// semantics of the given strategy. /// /// If `producer` or any of the created producers fail, the returned /// producer will forward that failure immediately. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func flatMap(strategy: FlattenStrategy, transform: Value -> SignalProducer) -> SignalProducer { return map(transform).flatten(strategy) } /// Maps each event from `producer` to a new signal, then flattens the /// resulting signals (into a single producer of values), according to the /// semantics of the given strategy. /// /// If `producer` or any of the created signals emit an error, the returned /// producer will forward that error immediately. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func flatMap(strategy: FlattenStrategy, transform: Value -> Signal) -> SignalProducer { return map(transform).flatten(strategy) } /// Catches any failure that may occur on the input producer, mapping to a new producer /// that starts in its place. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func flatMapError(handler: Error -> SignalProducer) -> SignalProducer { return self.lift { $0.flatMapError(handler) } } /// `concat`s `next` onto `self`. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func concat(next: SignalProducer) -> SignalProducer { return SignalProducer, Error>(values: [self.producer, next]).flatten(.Concat) } } extension SignalProducerType { /// Repeats `self` a total of `count` times. Repeating `1` times results in /// an equivalent signal producer. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func times(count: Int) -> SignalProducer { precondition(count >= 0) if count == 0 { return .empty } else if count == 1 { return producer } return SignalProducer { observer, disposable in let serialDisposable = SerialDisposable() disposable.addDisposable(serialDisposable) func iterate(current: Int) { self.startWithSignal { signal, signalDisposable in serialDisposable.innerDisposable = signalDisposable signal.observe { event in if case .Completed = event { let remainingTimes = current - 1 if remainingTimes > 0 { iterate(remainingTimes) } else { observer.sendCompleted() } } else { observer.action(event) } } } } iterate(count) } } /// Ignores failures up to `count` times. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func retry(count: Int) -> SignalProducer { precondition(count >= 0) if count == 0 { return producer } else { return flatMapError { _ in self.retry(count - 1) } } } /// Waits for completion of `producer`, *then* forwards all events from /// `replacement`. Any failure sent from `producer` is forwarded immediately, in /// which case `replacement` will not be started, and none of its events will be /// be forwarded. All values sent from `producer` are ignored. @warn_unused_result(message="Did you forget to call `start` on the producer?") public func then(replacement: SignalProducer) -> SignalProducer { let relay = SignalProducer { observer, observerDisposable in self.startWithSignal { signal, signalDisposable in observerDisposable.addDisposable(signalDisposable) signal.observe { event in switch event { case let .Failed(error): observer.sendFailed(error) case .Completed: observer.sendCompleted() case .Interrupted: observer.sendInterrupted() case .Next: break } } } } return relay.concat(replacement) } /// Starts the producer, then blocks, waiting for the first value. @warn_unused_result(message="Did you forget to check the result?") public func first() -> Result? { return take(1).single() } /// Starts the producer, then blocks, waiting for events: Next and Completed. /// When a single value or error is sent, the returned `Result` will represent /// those cases. However, when no values are sent, or when more than one value /// is sent, `nil` will be returned. @warn_unused_result(message="Did you forget to check the result?") public func single() -> Result? { let semaphore = dispatch_semaphore_create(0) var result: Result? take(2).start { event in switch event { case let .Next(value): if result != nil { // Move into failure state after recieving another value. result = nil return } result = .Success(value) case let .Failed(error): result = .Failure(error) dispatch_semaphore_signal(semaphore) case .Completed, .Interrupted: dispatch_semaphore_signal(semaphore) } } dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) return result } /// Starts the producer, then blocks, waiting for the last value. @warn_unused_result(message="Did you forget to check the result?") public func last() -> Result? { return takeLast(1).single() } /// Starts the producer, then blocks, waiting for completion. @warn_unused_result(message="Did you forget to check the result?") public func wait() -> Result<(), Error> { return then(SignalProducer<(), Error>(value: ())).last() ?? .Success(()) } } ================================================ FILE: Pods/ReactiveCocoa/ReactiveCocoa/Swift/TupleExtensions.swift ================================================ // // TupleExtensions.swift // ReactiveCocoa // // Created by Justin Spahr-Summers on 2014-12-20. // Copyright (c) 2014 GitHub. All rights reserved. // /// Adds a value into an N-tuple, returning an (N+1)-tuple. /// /// Supports creating tuples up to 10 elements long. internal func repack(t: (A, B), value: C) -> (A, B, C) { return (t.0, t.1, value) } internal func repack(t: (A, B, C), value: D) -> (A, B, C, D) { return (t.0, t.1, t.2, value) } internal func repack(t: (A, B, C, D), value: E) -> (A, B, C, D, E) { return (t.0, t.1, t.2, t.3, value) } internal func repack(t: (A, B, C, D, E), value: F) -> (A, B, C, D, E, F) { return (t.0, t.1, t.2, t.3, t.4, value) } internal func repack(t: (A, B, C, D, E, F), value: G) -> (A, B, C, D, E, F, G) { return (t.0, t.1, t.2, t.3, t.4, t.5, value) } internal func repack(t: (A, B, C, D, E, F, G), value: H) -> (A, B, C, D, E, F, G, H) { return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, value) } internal func repack(t: (A, B, C, D, E, F, G, H), value: I) -> (A, B, C, D, E, F, G, H, I) { return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, t.7, value) } internal func repack(t: (A, B, C, D, E, F, G, H, I), value: J) -> (A, B, C, D, E, F, G, H, I, J) { return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, t.7, t.8, value) } ================================================ FILE: Pods/Result/LICENSE ================================================ The MIT License (MIT) Copyright (c) 2014 Rob Rix Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/Result/README.md ================================================ # Result [![Build Status](https://travis-ci.org/antitypical/Result.svg?branch=master)](https://travis-ci.org/antitypical/Result) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![CocoaPods](https://img.shields.io/cocoapods/v/Result.svg)](https://cocoapods.org/) [![Reference Status](https://www.versioneye.com/objective-c/result/reference_badge.svg?style=flat)](https://www.versioneye.com/objective-c/result/references) This is a Swift µframework providing `Result`. `Result` values are either successful (wrapping `Value`) or failed (wrapping `Error`). This is similar to Swift’s native `Optional` type: `Success` is like `Some`, and `Failure` is like `None` except with an associated `ErrorType` value. The addition of an associated `ErrorType` allows errors to be passed along for logging or displaying to the user. Using this µframework instead of rolling your own `Result` type allows you to easily interface with other frameworks that also use `Result`. ## Use Use `Result` whenever an operation has the possibility of failure. Consider the following example of a function that tries to extract a `String` for a given key from a JSON `Dictionary`. ```swift typealias JSONObject = [String:AnyObject] enum JSONError : ErrorType { case NoSuchKey(String) case TypeMismatch } func stringForKey(json: JSONObject, key: String) -> Result { guard let value = json[key] else { return .Failure(.NoSuchKey(key)) } if let value = value as? String { return .Success(value) } else { return .Failure(.TypeMismatch) } } ``` This function provides a more robust wrapper around the default subscripting provided by `Dictionary`. Rather than return `AnyObject?`, it returns a `Result` that either contains the `String` value for the given key, or an `ErrorType` detailing what went wrong. One simple way to handle a `Result` is to deconstruct it using a `switch` statement. ```swift switch stringForKey(json, key: "email") { case let .Success(email): print("The email is \(email)") case let .Failure(JSONError.NoSuchKey(key)): print("\(key) is not a valid key") case .Failure(JSONError.TypeMismatch): print("Didn't have the right type") } ``` Using a `switch` statement allows powerful pattern matching, and ensures all possible results are covered. Swift 2.0 offers new ways to deconstruct enums like the `if-case` statement, but be wary as such methods do not ensure errors are handled. Other methods available for processing `Result` are detailed in the [API documentation](http://cocoadocs.org/docsets/Result/). ## Result vs. Throws Swift 2.0 introduces error handling via throwing and catching `ErrorType`. `Result` accomplishes the same goal by encapsulating the result instead of hijacking control flow. The `Result` abstraction allows enables powerful functionality such as `map` and `flatMap`, making `Result` more composable than `throw`. Since dealing with APIs that throw is common, you can convert functions such functions into a `Result` by using the `materialize` method. Conversely, a `Result` can be used to throw an error by calling `dematerialize`. [Note: due to compiler issues, `materialize` is not currently available] ## Higher Order Functions `map` and `flatMap` operate the same as `Optional.map` and `Optional.flatMap` except they apply to `Result`. `map` transforms a `Result` into a `Result` of a new type. It does this by taking a function that transforms the `Value` type into a new value. This transformation is only applied in the case of a `Success`. In the case of a `Failure`, the associated error is re-wrapped in the new `Result`. ```swift // transforms a Result to a Result let idResult = intForKey(json, key:"id").map { id in String(id) } ``` Here, the final result is either the id as a `String`, or carries over the `.Failure` from the previous result. `flatMap` is similar to `map` in that in transforms the `Result` into another `Result`. However, the function passed into `flatMap` must return a `Result`. An in depth discussion of `map` and `flatMap` is beyond the scope of this documentation. If you would like a deeper understanding, read about functors and monads. This article is a good place to [start](http://www.javiersoto.me/post/106875422394). ## Integration 1. Add this repository as a submodule and/or [add it to your Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile) if you’re using [carthage](https://github.com/Carthage/Carthage/) to manage your dependencies. 2. Drag `Result.xcodeproj` into your project or workspace. 3. Link your target against `Result.framework`. 4. Application targets should ensure that the framework gets copied into their application bundle. (Framework targets should instead require the application linking them to include Result.) ================================================ FILE: Pods/Result/Result/Result.swift ================================================ // Copyright (c) 2015 Rob Rix. All rights reserved. /// An enum representing either a failure with an explanatory error, or a success with a result value. public enum Result: ResultType, CustomStringConvertible, CustomDebugStringConvertible { case Success(T) case Failure(Error) // MARK: Constructors /// Constructs a success wrapping a `value`. public init(value: T) { self = .Success(value) } /// Constructs a failure wrapping an `error`. public init(error: Error) { self = .Failure(error) } /// Constructs a result from an Optional, failing with `Error` if `nil`. public init(_ value: T?, @autoclosure failWith: () -> Error) { self = value.map(Result.Success) ?? .Failure(failWith()) } /// Constructs a result from a function that uses `throw`, failing with `Error` if throws. public init(@autoclosure _ f: () throws -> T) { self.init(attempt: f) } /// Constructs a result from a function that uses `throw`, failing with `Error` if throws. public init(@noescape attempt f: () throws -> T) { do { self = .Success(try f()) } catch { self = .Failure(error as! Error) } } // MARK: Deconstruction /// Returns the value from `Success` Results or `throw`s the error. public func dematerialize() throws -> T { switch self { case let .Success(value): return value case let .Failure(error): throw error } } /// Case analysis for Result. /// /// Returns the value produced by applying `ifFailure` to `Failure` Results, or `ifSuccess` to `Success` Results. public func analysis(@noescape ifSuccess ifSuccess: T -> Result, @noescape ifFailure: Error -> Result) -> Result { switch self { case let .Success(value): return ifSuccess(value) case let .Failure(value): return ifFailure(value) } } // MARK: Higher-order functions /// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??` public func recover(@autoclosure value: () -> T) -> T { return self.value ?? value() } /// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??` public func recoverWith(@autoclosure result: () -> Result) -> Result { return analysis( ifSuccess: { _ in self }, ifFailure: { _ in result() }) } // MARK: Errors /// The domain for errors constructed by Result. public static var errorDomain: String { return "com.antitypical.Result" } /// The userInfo key for source functions in errors constructed by Result. public static var functionKey: String { return "\(errorDomain).function" } /// The userInfo key for source file paths in errors constructed by Result. public static var fileKey: String { return "\(errorDomain).file" } /// The userInfo key for source file line numbers in errors constructed by Result. public static var lineKey: String { return "\(errorDomain).line" } /// Constructs an error. public static func error(message: String? = nil, function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__) -> NSError { var userInfo: [String: AnyObject] = [ functionKey: function, fileKey: file, lineKey: line, ] if let message = message { userInfo[NSLocalizedDescriptionKey] = message } return NSError(domain: errorDomain, code: 0, userInfo: userInfo) } // MARK: CustomStringConvertible public var description: String { return analysis( ifSuccess: { ".Success(\($0))" }, ifFailure: { ".Failure(\($0))" }) } // MARK: CustomDebugStringConvertible public var debugDescription: String { return description } } /// Returns `true` if `left` and `right` are both `Success`es and their values are equal, or if `left` and `right` are both `Failure`s and their errors are equal. public func == (left: Result, right: Result) -> Bool { if let left = left.value, right = right.value { return left == right } else if let left = left.error, right = right.error { return left == right } return false } /// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values. public func != (left: Result, right: Result) -> Bool { return !(left == right) } /// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits. public func ?? (left: Result, @autoclosure right: () -> T) -> T { return left.recover(right()) } /// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits. public func ?? (left: Result, @autoclosure right: () -> Result) -> Result { return left.recoverWith(right()) } // MARK: - Derive result from failable closure public func materialize(@noescape f: () throws -> T) -> Result { return materialize(try f()) } public func materialize(@autoclosure f: () throws -> T) -> Result { do { return .Success(try f()) } catch { return .Failure(error as NSError) } } // MARK: - Cocoa API conveniences /// Constructs a Result with the result of calling `try` with an error pointer. /// /// This is convenient for wrapping Cocoa API which returns an object or `nil` + an error, by reference. e.g.: /// /// Result.try { NSData(contentsOfURL: URL, options: .DataReadingMapped, error: $0) } public func `try`(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, `try`: NSErrorPointer -> T?) -> Result { var error: NSError? return `try`(&error).map(Result.Success) ?? .Failure(error ?? Result.error(function: function, file: file, line: line)) } /// Constructs a Result with the result of calling `try` with an error pointer. /// /// This is convenient for wrapping Cocoa API which returns a `Bool` + an error, by reference. e.g.: /// /// Result.try { NSFileManager.defaultManager().removeItemAtURL(URL, error: $0) } public func `try`(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, `try`: NSErrorPointer -> Bool) -> Result<(), NSError> { var error: NSError? return `try`(&error) ? .Success(()) : .Failure(error ?? Result<(), NSError>.error(function: function, file: file, line: line)) } // MARK: - Operators infix operator >>- { // Left-associativity so that chaining works like you’d expect, and for consistency with Haskell, Runes, swiftz, etc. associativity left // Higher precedence than function application, but lower than function composition. precedence 100 } /// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors. /// /// This is a synonym for `flatMap`. public func >>- (result: Result, @noescape transform: T -> Result) -> Result { return result.flatMap(transform) } // MARK: - ErrorTypeConvertible conformance /// Make NSError conform to ErrorTypeConvertible extension NSError: ErrorTypeConvertible { public static func errorFromErrorType(error: ErrorType) -> NSError { return error as NSError } } // MARK: - /// An “error” that is impossible to construct. /// /// This can be used to describe `Result`s where failures will never /// be generated. For example, `Result` describes a result that /// contains an `Int`eger and is guaranteed never to be a `Failure`. public enum NoError: ErrorType { } import Foundation ================================================ FILE: Pods/Result/Result/ResultType.swift ================================================ // Copyright (c) 2015 Rob Rix. All rights reserved. /// A type that can represent either failure with an error or success with a result value. public protocol ResultType { typealias Value typealias Error: ErrorType /// Constructs a successful result wrapping a `value`. init(value: Value) /// Constructs a failed result wrapping an `error`. init(error: Error) /// Case analysis for ResultType. /// /// Returns the value produced by appliying `ifFailure` to the error if self represents a failure, or `ifSuccess` to the result value if self represents a success. func analysis(@noescape ifSuccess ifSuccess: Value -> U, @noescape ifFailure: Error -> U) -> U /// Returns the value if self represents a success, `nil` otherwise. /// /// A default implementation is provided by a protocol extension. Conforming types may specialize it. var value: Value? { get } /// Returns the error if self represents a failure, `nil` otherwise. /// /// A default implementation is provided by a protocol extension. Conforming types may specialize it. var error: Error? { get } } public extension ResultType { /// Returns the value if self represents a success, `nil` otherwise. public var value: Value? { return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil }) } /// Returns the error if self represents a failure, `nil` otherwise. public var error: Error? { return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 }) } /// Returns a new Result by mapping `Success`es’ values using `transform`, or re-wrapping `Failure`s’ errors. public func map(@noescape transform: Value -> U) -> Result { return flatMap { .Success(transform($0)) } } /// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors. public func flatMap(@noescape transform: Value -> Result) -> Result { return analysis( ifSuccess: transform, ifFailure: Result.Failure) } /// Returns a new Result by mapping `Failure`'s values using `transform`, or re-wrapping `Success`es’ values. public func mapError(@noescape transform: Error -> Error2) -> Result { return flatMapError { .Failure(transform($0)) } } /// Returns the result of applying `transform` to `Failure`’s errors, or re-wrapping `Success`es’ values. public func flatMapError(@noescape transform: Error -> Result) -> Result { return analysis( ifSuccess: Result.Success, ifFailure: transform) } } /// Protocol used to constrain `tryMap` to `Result`s with compatible `Error`s. public protocol ErrorTypeConvertible: ErrorType { typealias ConvertibleType = Self static func errorFromErrorType(error: ErrorType) -> ConvertibleType } public extension ResultType where Error: ErrorTypeConvertible { /// Returns the result of applying `transform` to `Success`es’ values, or wrapping thrown errors. public func tryMap(@noescape transform: Value throws -> U) -> Result { return flatMap { value in do { return .Success(try transform(value)) } catch { let convertedError = Error.errorFromErrorType(error) as! Error // Revisit this in a future version of Swift. https://twitter.com/jckarter/status/672931114944696321 return .Failure(convertedError) } } } } // MARK: - Operators infix operator &&& { /// Same associativity as &&. associativity left /// Same precedence as &&. precedence 120 } /// Returns a Result with a tuple of `left` and `right` values if both are `Success`es, or re-wrapping the error of the earlier `Failure`. public func &&& (left: L, @autoclosure right: () -> R) -> Result<(L.Value, R.Value), L.Error> { return left.flatMap { left in right().map { right in (left, right) } } } ================================================ FILE: Pods/SDWebImage/LICENSE ================================================ Copyright (c) 2009 Olivier Poitrey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/SDWebImage/README.md ================================================ Web Image ========= [![Build Status](http://img.shields.io/travis/rs/SDWebImage/master.svg?style=flat)](https://travis-ci.org/rs/SDWebImage) [![Pod Version](http://img.shields.io/cocoapods/v/SDWebImage.svg?style=flat)](http://cocoadocs.org/docsets/SDWebImage/) [![Pod Platform](http://img.shields.io/cocoapods/p/SDWebImage.svg?style=flat)](http://cocoadocs.org/docsets/SDWebImage/) [![Pod License](http://img.shields.io/cocoapods/l/SDWebImage.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0.html) [![Dependency Status](https://www.versioneye.com/objective-c/sdwebimage/3.3/badge.svg?style=flat)](https://www.versioneye.com/objective-c/sdwebimage/3.3) [![Reference Status](https://www.versioneye.com/objective-c/sdwebimage/reference_badge.svg?style=flat)](https://www.versioneye.com/objective-c/sdwebimage/references) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/rs/SDWebImage) This library provides a category for UIImageView with support for remote images coming from the web. It provides: - An `UIImageView` category adding web image and cache management to the Cocoa Touch framework - An asynchronous image downloader - An asynchronous memory + disk image caching with automatic cache expiration handling - Animated GIF support - WebP format support - A background image decompression - A guarantee that the same URL won't be downloaded several times - A guarantee that bogus URLs won't be retried again and again - A guarantee that main thread will never be blocked - Performances! - Use GCD and ARC - Arm64 support NOTE: The version 3.0 of SDWebImage isn't fully backward compatible with 2.0 and requires iOS 5.1.1 minimum deployment version. If you need iOS < 5.0 support, please use the last [2.0 version](https://github.com/rs/SDWebImage/tree/2.0-compat). [How is SDWebImage better than X?](https://github.com/rs/SDWebImage/wiki/How-is-SDWebImage-better-than-X%3F) Who Use It ---------- Find out [who uses SDWebImage](https://github.com/rs/SDWebImage/wiki/Who-Uses-SDWebImage) and add your app to the list. How To Use ---------- API documentation is available at [CocoaDocs - SDWebImage](http://cocoadocs.org/docsets/SDWebImage/) ### Using UIImageView+WebCache category with UITableView Just #import the UIImageView+WebCache.h header, and call the sd_setImageWithURL:placeholderImage: method from the tableView:cellForRowAtIndexPath: UITableViewDataSource method. Everything will be handled for you, from async downloads to caching management. ```objective-c #import ... - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *MyIdentifier = @"MyIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease]; } // Here we use the new provided sd_setImageWithURL: method to load the web image [cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]]; cell.textLabel.text = @"My Text"; return cell; } ``` ### Using blocks With blocks, you can be notified about the image download progress and whenever the image retrieval has completed with success or not: ```objective-c // Here we use the new provided sd_setImageWithURL: method to load the web image [cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { ... completion code here ... }]; ``` Note: neither your success nor failure block will be call if your image request is canceled before completion. ### Using SDWebImageManager The SDWebImageManager is the class behind the UIImageView+WebCache category. It ties the asynchronous downloader with the image cache store. You can use this class directly to benefit from web image downloading with caching in another context than a UIView (ie: with Cocoa). Here is a simple example of how to use SDWebImageManager: ```objective-c SDWebImageManager *manager = [SDWebImageManager sharedManager]; [manager downloadImageWithURL:imageURL options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) { // progression tracking code } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (image) { // do something with image } }]; ``` ### Using Asynchronous Image Downloader Independently It's also possible to use the async image downloader independently: ```objective-c SDWebImageDownloader *downloader = [SDWebImageDownloader sharedDownloader]; [downloader downloadImageWithURL:imageURL options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) { // progression tracking code } completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { if (image && finished) { // do something with image } }]; ``` ### Using Asynchronous Image Caching Independently It is also possible to use the async based image cache store independently. SDImageCache maintains a memory cache and an optional disk cache. Disk cache write operations are performed asynchronous so it doesn't add unnecessary latency to the UI. The SDImageCache class provides a singleton instance for convenience but you can create your own instance if you want to create separated cache namespace. To lookup the cache, you use the `queryDiskCacheForKey:done:` method. If the method returns nil, it means the cache doesn't currently own the image. You are thus responsible for generating and caching it. The cache key is an application unique identifier for the image to cache. It is generally the absolute URL of the image. ```objective-c SDImageCache *imageCache = [[SDImageCache alloc] initWithNamespace:@"myNamespace"]; [imageCache queryDiskCacheForKey:myCacheKey done:^(UIImage *image) { // image is not nil if image was found }]; ``` By default SDImageCache will lookup the disk cache if an image can't be found in the memory cache. You can prevent this from happening by calling the alternative method `imageFromMemoryCacheForKey:`. To store an image into the cache, you use the storeImage:forKey: method: ```objective-c [[SDImageCache sharedImageCache] storeImage:myImage forKey:myCacheKey]; ``` By default, the image will be stored in memory cache as well as on disk cache (asynchronously). If you want only the memory cache, use the alternative method storeImage:forKey:toDisk: with a negative third argument. ### Using cache key filter Sometime, you may not want to use the image URL as cache key because part of the URL is dynamic (i.e.: for access control purpose). SDWebImageManager provides a way to set a cache key filter that takes the NSURL as input, and output a cache key NSString. The following example sets a filter in the application delegate that will remove any query-string from the URL before to use it as a cache key: ```objective-c - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { SDWebImageManager.sharedManager.cacheKeyFilter = ^(NSURL *url) { url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path]; return [url absoluteString]; }; // Your app init code... return YES; } ``` Common Problems --------------- ### Using dynamic image size with UITableViewCell UITableView determines the size of the image by the first image set for a cell. If your remote images don't have the same size as your placeholder image, you may experience strange anamorphic scaling issue. The following article gives a way to workaround this issue: [http://www.wrichards.com/blog/2011/11/sdwebimage-fixed-width-cell-images/](http://www.wrichards.com/blog/2011/11/sdwebimage-fixed-width-cell-images/) ### Handle image refresh SDWebImage does very aggressive caching by default. It ignores all kind of caching control header returned by the HTTP server and cache the returned images with no time restriction. It implies your images URLs are static URLs pointing to images that never change. If the pointed image happen to change, some parts of the URL should change accordingly. If you don't control the image server you're using, you may not be able to change the URL when its content is updated. This is the case for Facebook avatar URLs for instance. In such case, you may use the `SDWebImageRefreshCached` flag. This will slightly degrade the performance but will respect the HTTP caching control headers: ``` objective-c [imageView sd_setImageWithURL:[NSURL URLWithString:@"https://graph.facebook.com/olivier.poitrey/picture"] placeholderImage:[UIImage imageNamed:@"avatar-placeholder.png"] options:SDWebImageRefreshCached]; ``` ### Add a progress indicator See this category: https://github.com/JJSaccolo/UIActivityIndicator-for-SDWebImage Installation ------------ There are three ways to use SDWebImage in your project: - using Cocoapods - copying all the files into your project - importing the project as a static library ### Installation with CocoaPods [CocoaPods](http://cocoapods.org/) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries in your projects. See the [Get Started](http://cocoapods.org/#get_started) section for more details. #### Podfile ``` platform :ios, '6.1' pod 'SDWebImage', '~>3.7' ``` If you are using Swift, be sure to add `use_frameworks!` and set your target to iOS 8+: ``` platform :ios, '8.0' use_frameworks! ``` #### Subspecs There are 3 subspecs available now: `Core`, `MapKit` and `WebP` (this means you can install only some of the SDWebImage modules. By default, you get just `Core`, so if you need `WebP`, you need to specify it). Podfile example: ``` pod 'SDWebImage/WebP' ``` ### Installation with Carthage (iOS 8+) [Carthage](https://github.com/Carthage/Carthage) is a lightweight dependency manager for Swift and Objective-C. It leverages CocoaTouch modules and is less invasive than CocoaPods. To install with carthage, follow the instruction on [Carthage](https://github.com/Carthage/Carthage) #### Cartfile ``` github "rs/SDWebImage" ``` #### Usage Swift If you installed using CocoaPods: ``` import SDWebImage ``` If you installed manually: ``` import WebImage ``` Objective-C ``` @import WebImage; ``` ### Installation by cloning the repository In order to gain access to all the files from the repository, you should clone it. ``` git clone --recursive https://github.com/rs/SDWebImage.git ``` ### Add the SDWebImage project to your project - Download and unzip the last version of the framework from the [download page](https://github.com/rs/SDWebImage/releases) - Right-click on the project navigator and select "Add Files to "Your Project": - In the dialog, select SDWebImage.framework: - Check the "Copy items into destination group's folder (if needed)" checkbox ### Add dependencies - In you application project app’s target settings, find the "Build Phases" section and open the "Link Binary With Libraries" block: - Click the "+" button again and select the "ImageIO.framework", this is needed by the progressive download feature: ### Add Linker Flag Open the "Build Settings" tab, in the "Linking" section, locate the "Other Linker Flags" setting and add the "-ObjC" flag: ![Other Linker Flags](http://dl.dropbox.com/u/123346/SDWebImage/10_other_linker_flags.jpg) Alternatively, if this causes compilation problems with frameworks that extend optional libraries, such as Parse, RestKit or opencv2, instead of the -ObjC flag use: ``` -force_load SDWebImage.framework/Versions/Current/SDWebImage ``` If you're using Cocoa Pods and have any frameworks that extend optional libraries, such as Parsen RestKit or opencv2, instead of the -ObjC flag use: ``` -force_load $(TARGET_BUILD_DIR)/libPods.a ``` and this: ``` $(inherited) ``` ### Import headers in your source files In the source files where you need to use the library, import the header file: ```objective-c #import ``` ### Build Project At this point your workspace should build without error. If you are having problem, post to the Issue and the community can help you solve it. Future Enhancements ------------------- - LRU memory cache cleanup instead of reset on memory warning ## Licenses All source code is licensed under the [MIT License](https://raw.github.com/rs/SDWebImage/master/LICENSE). ================================================ FILE: Pods/SDWebImage/SDWebImage/NSData+ImageContentType.h ================================================ // // Created by Fabrice Aneche on 06/01/14. // Copyright (c) 2014 Dailymotion. All rights reserved. // #import @interface NSData (ImageContentType) /** * Compute the content type for an image data * * @param data the input data * * @return the content type as string (i.e. image/jpeg, image/gif) */ + (NSString *)sd_contentTypeForImageData:(NSData *)data; @end @interface NSData (ImageContentTypeDeprecated) + (NSString *)contentTypeForImageData:(NSData *)data __deprecated_msg("Use `sd_contentTypeForImageData:`"); @end ================================================ FILE: Pods/SDWebImage/SDWebImage/NSData+ImageContentType.m ================================================ // // Created by Fabrice Aneche on 06/01/14. // Copyright (c) 2014 Dailymotion. All rights reserved. // #import "NSData+ImageContentType.h" @implementation NSData (ImageContentType) + (NSString *)sd_contentTypeForImageData:(NSData *)data { uint8_t c; [data getBytes:&c length:1]; switch (c) { case 0xFF: return @"image/jpeg"; case 0x89: return @"image/png"; case 0x47: return @"image/gif"; case 0x49: case 0x4D: return @"image/tiff"; case 0x52: // R as RIFF for WEBP if ([data length] < 12) { return nil; } NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding]; if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) { return @"image/webp"; } return nil; } return nil; } @end @implementation NSData (ImageContentTypeDeprecated) + (NSString *)contentTypeForImageData:(NSData *)data { return [self sd_contentTypeForImageData:data]; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDImageCache.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import #import "SDWebImageCompat.h" typedef NS_ENUM(NSInteger, SDImageCacheType) { /** * The image wasn't available the SDWebImage caches, but was downloaded from the web. */ SDImageCacheTypeNone, /** * The image was obtained from the disk cache. */ SDImageCacheTypeDisk, /** * The image was obtained from the memory cache. */ SDImageCacheTypeMemory }; typedef void(^SDWebImageQueryCompletedBlock)(UIImage *image, SDImageCacheType cacheType); typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize); /** * SDImageCache maintains a memory cache and an optional disk cache. Disk cache write operations are performed * asynchronous so it doesn’t add unnecessary latency to the UI. */ @interface SDImageCache : NSObject /** * Decompressing images that are downloaded and cached can improve performance but can consume lot of memory. * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption. */ @property (assign, nonatomic) BOOL shouldDecompressImages; /** * disable iCloud backup [defaults to YES] */ @property (assign, nonatomic) BOOL shouldDisableiCloud; /** * use memory cache [defaults to YES] */ @property (assign, nonatomic) BOOL shouldCacheImagesInMemory; /** * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory. */ @property (assign, nonatomic) NSUInteger maxMemoryCost; /** * The maximum number of objects the cache should hold. */ @property (assign, nonatomic) NSUInteger maxMemoryCountLimit; /** * The maximum length of time to keep an image in the cache, in seconds */ @property (assign, nonatomic) NSInteger maxCacheAge; /** * The maximum size of the cache, in bytes. */ @property (assign, nonatomic) NSUInteger maxCacheSize; /** * Returns global shared cache instance * * @return SDImageCache global instance */ + (SDImageCache *)sharedImageCache; /** * Init a new cache store with a specific namespace * * @param ns The namespace to use for this cache store */ - (id)initWithNamespace:(NSString *)ns; /** * Init a new cache store with a specific namespace and directory * * @param ns The namespace to use for this cache store * @param directory Directory to cache disk images in */ - (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory; -(NSString *)makeDiskCachePath:(NSString*)fullNamespace; /** * Add a read-only cache path to search for images pre-cached by SDImageCache * Useful if you want to bundle pre-loaded images with your app * * @param path The path to use for this read-only cache path */ - (void)addReadOnlyCachePath:(NSString *)path; /** * Store an image into memory and disk cache at the given key. * * @param image The image to store * @param key The unique image cache key, usually it's image absolute URL */ - (void)storeImage:(UIImage *)image forKey:(NSString *)key; /** * Store an image into memory and optionally disk cache at the given key. * * @param image The image to store * @param key The unique image cache key, usually it's image absolute URL * @param toDisk Store the image to disk cache if YES */ - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk; /** * Store an image into memory and optionally disk cache at the given key. * * @param image The image to store * @param recalculate BOOL indicates if imageData can be used or a new data should be constructed from the UIImage * @param imageData The image data as returned by the server, this representation will be used for disk storage * instead of converting the given image object into a storable/compressed image format in order * to save quality and CPU * @param key The unique image cache key, usually it's image absolute URL * @param toDisk Store the image to disk cache if YES */ - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk; /** * Query the disk cache asynchronously. * * @param key The unique key used to store the wanted image */ - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock; /** * Query the memory cache synchronously. * * @param key The unique key used to store the wanted image */ - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key; /** * Query the disk cache synchronously after checking the memory cache. * * @param key The unique key used to store the wanted image */ - (UIImage *)imageFromDiskCacheForKey:(NSString *)key; /** * Remove the image from memory and disk cache synchronously * * @param key The unique image cache key */ - (void)removeImageForKey:(NSString *)key; /** * Remove the image from memory and disk cache asynchronously * * @param key The unique image cache key * @param completion An block that should be executed after the image has been removed (optional) */ - (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion; /** * Remove the image from memory and optionally disk cache asynchronously * * @param key The unique image cache key * @param fromDisk Also remove cache entry from disk if YES */ - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk; /** * Remove the image from memory and optionally disk cache asynchronously * * @param key The unique image cache key * @param fromDisk Also remove cache entry from disk if YES * @param completion An block that should be executed after the image has been removed (optional) */ - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion; /** * Clear all memory cached images */ - (void)clearMemory; /** * Clear all disk cached images. Non-blocking method - returns immediately. * @param completion An block that should be executed after cache expiration completes (optional) */ - (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion; /** * Clear all disk cached images * @see clearDiskOnCompletion: */ - (void)clearDisk; /** * Remove all expired cached image from disk. Non-blocking method - returns immediately. * @param completionBlock An block that should be executed after cache expiration completes (optional) */ - (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock; /** * Remove all expired cached image from disk * @see cleanDiskWithCompletionBlock: */ - (void)cleanDisk; /** * Get the size used by the disk cache */ - (NSUInteger)getSize; /** * Get the number of images in the disk cache */ - (NSUInteger)getDiskCount; /** * Asynchronously calculate the disk cache's size. */ - (void)calculateSizeWithCompletionBlock:(SDWebImageCalculateSizeBlock)completionBlock; /** * Async check if image exists in disk cache already (does not load the image) * * @param key the key describing the url * @param completionBlock the block to be executed when the check is done. * @note the completion block will be always executed on the main queue */ - (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock; /** * Check if image exists in disk cache already (does not load the image) * * @param key the key describing the url * * @return YES if an image exists for the given key */ - (BOOL)diskImageExistsWithKey:(NSString *)key; /** * Get the cache path for a certain key (needs the cache path root folder) * * @param key the key (can be obtained from url using cacheKeyForURL) * @param path the cache path root folder * * @return the cache path */ - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path; /** * Get the default cache path for a certain key * * @param key the key (can be obtained from url using cacheKeyForURL) * * @return the default cache path */ - (NSString *)defaultCachePathForKey:(NSString *)key; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDImageCache.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDImageCache.h" #import "SDWebImageDecoder.h" #import "UIImage+MultiFormat.h" #import // See https://github.com/rs/SDWebImage/pull/1141 for discussion @interface AutoPurgeCache : NSCache @end @implementation AutoPurgeCache - (id)init { self = [super init]; if (self) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeAllObjects) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; } @end static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week // PNG signature bytes and data (below) static unsigned char kPNGSignatureBytes[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; static NSData *kPNGSignatureData = nil; BOOL ImageDataHasPNGPreffix(NSData *data); BOOL ImageDataHasPNGPreffix(NSData *data) { NSUInteger pngSignatureLength = [kPNGSignatureData length]; if ([data length] >= pngSignatureLength) { if ([[data subdataWithRange:NSMakeRange(0, pngSignatureLength)] isEqualToData:kPNGSignatureData]) { return YES; } } return NO; } FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) { return image.size.height * image.size.width * image.scale * image.scale; } @interface SDImageCache () @property (strong, nonatomic) NSCache *memCache; @property (strong, nonatomic) NSString *diskCachePath; @property (strong, nonatomic) NSMutableArray *customPaths; @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t ioQueue; @end @implementation SDImageCache { NSFileManager *_fileManager; } + (SDImageCache *)sharedImageCache { static dispatch_once_t once; static id instance; dispatch_once(&once, ^{ instance = [self new]; }); return instance; } - (id)init { return [self initWithNamespace:@"default"]; } - (id)initWithNamespace:(NSString *)ns { NSString *path = [self makeDiskCachePath:ns]; return [self initWithNamespace:ns diskCacheDirectory:path]; } - (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory { if ((self = [super init])) { NSString *fullNamespace = [@"com.hackemist.SDWebImageCache." stringByAppendingString:ns]; // initialise PNG signature data kPNGSignatureData = [NSData dataWithBytes:kPNGSignatureBytes length:8]; // Create IO serial queue _ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache", DISPATCH_QUEUE_SERIAL); // Init default values _maxCacheAge = kDefaultCacheMaxCacheAge; // Init the memory cache _memCache = [[AutoPurgeCache alloc] init]; _memCache.name = fullNamespace; // Init the disk cache if (directory != nil) { _diskCachePath = [directory stringByAppendingPathComponent:fullNamespace]; } else { NSString *path = [self makeDiskCachePath:ns]; _diskCachePath = path; } // Set decompression to YES _shouldDecompressImages = YES; // memory cache enabled _shouldCacheImagesInMemory = YES; // Disable iCloud _shouldDisableiCloud = YES; dispatch_sync(_ioQueue, ^{ _fileManager = [NSFileManager new]; }); #if TARGET_OS_IPHONE // Subscribe to app events [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearMemory) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cleanDisk) name:UIApplicationWillTerminateNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backgroundCleanDisk) name:UIApplicationDidEnterBackgroundNotification object:nil]; #endif } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; SDDispatchQueueRelease(_ioQueue); } - (void)addReadOnlyCachePath:(NSString *)path { if (!self.customPaths) { self.customPaths = [NSMutableArray new]; } if (![self.customPaths containsObject:path]) { [self.customPaths addObject:path]; } } - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path { NSString *filename = [self cachedFileNameForKey:key]; return [path stringByAppendingPathComponent:filename]; } - (NSString *)defaultCachePathForKey:(NSString *)key { return [self cachePathForKey:key inPath:self.diskCachePath]; } #pragma mark SDImageCache (private) - (NSString *)cachedFileNameForKey:(NSString *)key { const char *str = [key UTF8String]; if (str == NULL) { str = ""; } unsigned char r[CC_MD5_DIGEST_LENGTH]; CC_MD5(str, (CC_LONG)strlen(str), r); NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%@", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15], [[key pathExtension] isEqualToString:@""] ? @"" : [NSString stringWithFormat:@".%@", [key pathExtension]]]; return filename; } #pragma mark ImageCache // Init the disk cache -(NSString *)makeDiskCachePath:(NSString*)fullNamespace{ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); return [paths[0] stringByAppendingPathComponent:fullNamespace]; } - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk { if (!image || !key) { return; } // if memory cache is enabled if (self.shouldCacheImagesInMemory) { NSUInteger cost = SDCacheCostForImage(image); [self.memCache setObject:image forKey:key cost:cost]; } if (toDisk) { dispatch_async(self.ioQueue, ^{ NSData *data = imageData; if (image && (recalculate || !data)) { #if TARGET_OS_IPHONE // We need to determine if the image is a PNG or a JPEG // PNGs are easier to detect because they have a unique signature (http://www.w3.org/TR/PNG-Structure.html) // The first eight bytes of a PNG file always contain the following (decimal) values: // 137 80 78 71 13 10 26 10 // If the imageData is nil (i.e. if trying to save a UIImage directly or the image was transformed on download) // and the image has an alpha channel, we will consider it PNG to avoid losing the transparency int alphaInfo = CGImageGetAlphaInfo(image.CGImage); BOOL hasAlpha = !(alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaNoneSkipFirst || alphaInfo == kCGImageAlphaNoneSkipLast); BOOL imageIsPng = hasAlpha; // But if we have an image data, we will look at the preffix if ([imageData length] >= [kPNGSignatureData length]) { imageIsPng = ImageDataHasPNGPreffix(imageData); } if (imageIsPng) { data = UIImagePNGRepresentation(image); } else { data = UIImageJPEGRepresentation(image, (CGFloat)1.0); } #else data = [NSBitmapImageRep representationOfImageRepsInArray:image.representations usingType: NSJPEGFileType properties:nil]; #endif } if (data) { if (![_fileManager fileExistsAtPath:_diskCachePath]) { [_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; } // get cache Path for image key NSString *cachePathForKey = [self defaultCachePathForKey:key]; // transform to NSUrl NSURL *fileURL = [NSURL fileURLWithPath:cachePathForKey]; [_fileManager createFileAtPath:cachePathForKey contents:data attributes:nil]; // disable iCloud backup if (self.shouldDisableiCloud) { [fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:nil]; } } }); } } - (void)storeImage:(UIImage *)image forKey:(NSString *)key { [self storeImage:image recalculateFromImage:YES imageData:nil forKey:key toDisk:YES]; } - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk { [self storeImage:image recalculateFromImage:YES imageData:nil forKey:key toDisk:toDisk]; } - (BOOL)diskImageExistsWithKey:(NSString *)key { BOOL exists = NO; // this is an exception to access the filemanager on another queue than ioQueue, but we are using the shared instance // from apple docs on NSFileManager: The methods of the shared NSFileManager object can be called from multiple threads safely. exists = [[NSFileManager defaultManager] fileExistsAtPath:[self defaultCachePathForKey:key]]; // fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name // checking the key with and without the extension if (!exists) { exists = [[NSFileManager defaultManager] fileExistsAtPath:[[self defaultCachePathForKey:key] stringByDeletingPathExtension]]; } return exists; } - (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock { dispatch_async(_ioQueue, ^{ BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]]; // fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name // checking the key with and without the extension if (!exists) { exists = [_fileManager fileExistsAtPath:[[self defaultCachePathForKey:key] stringByDeletingPathExtension]]; } if (completionBlock) { dispatch_async(dispatch_get_main_queue(), ^{ completionBlock(exists); }); } }); } - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key { return [self.memCache objectForKey:key]; } - (UIImage *)imageFromDiskCacheForKey:(NSString *)key { // First check the in-memory cache... UIImage *image = [self imageFromMemoryCacheForKey:key]; if (image) { return image; } // Second check the disk cache... UIImage *diskImage = [self diskImageForKey:key]; if (diskImage && self.shouldCacheImagesInMemory) { NSUInteger cost = SDCacheCostForImage(diskImage); [self.memCache setObject:diskImage forKey:key cost:cost]; } return diskImage; } - (NSData *)diskImageDataBySearchingAllPathsForKey:(NSString *)key { NSString *defaultPath = [self defaultCachePathForKey:key]; NSData *data = [NSData dataWithContentsOfFile:defaultPath]; if (data) { return data; } // fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name // checking the key with and without the extension data = [NSData dataWithContentsOfFile:[defaultPath stringByDeletingPathExtension]]; if (data) { return data; } NSArray *customPaths = [self.customPaths copy]; for (NSString *path in customPaths) { NSString *filePath = [self cachePathForKey:key inPath:path]; NSData *imageData = [NSData dataWithContentsOfFile:filePath]; if (imageData) { return imageData; } // fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name // checking the key with and without the extension imageData = [NSData dataWithContentsOfFile:[filePath stringByDeletingPathExtension]]; if (imageData) { return imageData; } } return nil; } - (UIImage *)diskImageForKey:(NSString *)key { NSData *data = [self diskImageDataBySearchingAllPathsForKey:key]; if (data) { UIImage *image = [UIImage sd_imageWithData:data]; image = [self scaledImageForKey:key image:image]; if (self.shouldDecompressImages) { image = [UIImage decodedImageWithImage:image]; } return image; } else { return nil; } } - (UIImage *)scaledImageForKey:(NSString *)key image:(UIImage *)image { return SDScaledImageForKey(key, image); } - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock { if (!doneBlock) { return nil; } if (!key) { doneBlock(nil, SDImageCacheTypeNone); return nil; } // First check the in-memory cache... UIImage *image = [self imageFromMemoryCacheForKey:key]; if (image) { doneBlock(image, SDImageCacheTypeMemory); return nil; } NSOperation *operation = [NSOperation new]; dispatch_async(self.ioQueue, ^{ if (operation.isCancelled) { return; } @autoreleasepool { UIImage *diskImage = [self diskImageForKey:key]; if (diskImage && self.shouldCacheImagesInMemory) { NSUInteger cost = SDCacheCostForImage(diskImage); [self.memCache setObject:diskImage forKey:key cost:cost]; } dispatch_async(dispatch_get_main_queue(), ^{ doneBlock(diskImage, SDImageCacheTypeDisk); }); } }); return operation; } - (void)removeImageForKey:(NSString *)key { [self removeImageForKey:key withCompletion:nil]; } - (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion { [self removeImageForKey:key fromDisk:YES withCompletion:completion]; } - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk { [self removeImageForKey:key fromDisk:fromDisk withCompletion:nil]; } - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion { if (key == nil) { return; } if (self.shouldCacheImagesInMemory) { [self.memCache removeObjectForKey:key]; } if (fromDisk) { dispatch_async(self.ioQueue, ^{ [_fileManager removeItemAtPath:[self defaultCachePathForKey:key] error:nil]; if (completion) { dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); } }); } else if (completion){ completion(); } } - (void)setMaxMemoryCost:(NSUInteger)maxMemoryCost { self.memCache.totalCostLimit = maxMemoryCost; } - (NSUInteger)maxMemoryCost { return self.memCache.totalCostLimit; } - (NSUInteger)maxMemoryCountLimit { return self.memCache.countLimit; } - (void)setMaxMemoryCountLimit:(NSUInteger)maxCountLimit { self.memCache.countLimit = maxCountLimit; } - (void)clearMemory { [self.memCache removeAllObjects]; } - (void)clearDisk { [self clearDiskOnCompletion:nil]; } - (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion { dispatch_async(self.ioQueue, ^{ [_fileManager removeItemAtPath:self.diskCachePath error:nil]; [_fileManager createDirectoryAtPath:self.diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; if (completion) { dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); } }); } - (void)cleanDisk { [self cleanDiskWithCompletionBlock:nil]; } - (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock { dispatch_async(self.ioQueue, ^{ NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES]; NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey]; // This enumerator prefetches useful properties for our cache files. NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURL includingPropertiesForKeys:resourceKeys options:NSDirectoryEnumerationSkipsHiddenFiles errorHandler:NULL]; NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:-self.maxCacheAge]; NSMutableDictionary *cacheFiles = [NSMutableDictionary dictionary]; NSUInteger currentCacheSize = 0; // Enumerate all of the files in the cache directory. This loop has two purposes: // // 1. Removing files that are older than the expiration date. // 2. Storing file attributes for the size-based cleanup pass. NSMutableArray *urlsToDelete = [[NSMutableArray alloc] init]; for (NSURL *fileURL in fileEnumerator) { NSDictionary *resourceValues = [fileURL resourceValuesForKeys:resourceKeys error:NULL]; // Skip directories. if ([resourceValues[NSURLIsDirectoryKey] boolValue]) { continue; } // Remove files that are older than the expiration date; NSDate *modificationDate = resourceValues[NSURLContentModificationDateKey]; if ([[modificationDate laterDate:expirationDate] isEqualToDate:expirationDate]) { [urlsToDelete addObject:fileURL]; continue; } // Store a reference to this file and account for its total size. NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey]; currentCacheSize += [totalAllocatedSize unsignedIntegerValue]; [cacheFiles setObject:resourceValues forKey:fileURL]; } for (NSURL *fileURL in urlsToDelete) { [_fileManager removeItemAtURL:fileURL error:nil]; } // If our remaining disk cache exceeds a configured maximum size, perform a second // size-based cleanup pass. We delete the oldest files first. if (self.maxCacheSize > 0 && currentCacheSize > self.maxCacheSize) { // Target half of our maximum cache size for this cleanup pass. const NSUInteger desiredCacheSize = self.maxCacheSize / 2; // Sort the remaining cache files by their last modification time (oldest first). NSArray *sortedFiles = [cacheFiles keysSortedByValueWithOptions:NSSortConcurrent usingComparator:^NSComparisonResult(id obj1, id obj2) { return [obj1[NSURLContentModificationDateKey] compare:obj2[NSURLContentModificationDateKey]]; }]; // Delete files until we fall below our desired cache size. for (NSURL *fileURL in sortedFiles) { if ([_fileManager removeItemAtURL:fileURL error:nil]) { NSDictionary *resourceValues = cacheFiles[fileURL]; NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey]; currentCacheSize -= [totalAllocatedSize unsignedIntegerValue]; if (currentCacheSize < desiredCacheSize) { break; } } } } if (completionBlock) { dispatch_async(dispatch_get_main_queue(), ^{ completionBlock(); }); } }); } - (void)backgroundCleanDisk { Class UIApplicationClass = NSClassFromString(@"UIApplication"); if(!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) { return; } UIApplication *application = [UIApplication performSelector:@selector(sharedApplication)]; __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ // Clean up any unfinished task business by marking where you // stopped or ending the task outright. [application endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; // Start the long-running task and return immediately. [self cleanDiskWithCompletionBlock:^{ [application endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; } - (NSUInteger)getSize { __block NSUInteger size = 0; dispatch_sync(self.ioQueue, ^{ NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtPath:self.diskCachePath]; for (NSString *fileName in fileEnumerator) { NSString *filePath = [self.diskCachePath stringByAppendingPathComponent:fileName]; NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; size += [attrs fileSize]; } }); return size; } - (NSUInteger)getDiskCount { __block NSUInteger count = 0; dispatch_sync(self.ioQueue, ^{ NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtPath:self.diskCachePath]; count = [[fileEnumerator allObjects] count]; }); return count; } - (void)calculateSizeWithCompletionBlock:(SDWebImageCalculateSizeBlock)completionBlock { NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES]; dispatch_async(self.ioQueue, ^{ NSUInteger fileCount = 0; NSUInteger totalSize = 0; NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURL includingPropertiesForKeys:@[NSFileSize] options:NSDirectoryEnumerationSkipsHiddenFiles errorHandler:NULL]; for (NSURL *fileURL in fileEnumerator) { NSNumber *fileSize; [fileURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:NULL]; totalSize += [fileSize unsignedIntegerValue]; fileCount += 1; } if (completionBlock) { dispatch_async(dispatch_get_main_queue(), ^{ completionBlock(fileCount, totalSize); }); } }); } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageCompat.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * (c) Jamie Pinkham * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import #ifdef __OBJC_GC__ #error SDWebImage does not support Objective-C Garbage Collection #endif #if __IPHONE_OS_VERSION_MIN_REQUIRED != 20000 && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0 #error SDWebImage doesn't support Deployment Target version < 5.0 #endif #if !TARGET_OS_IPHONE #import #ifndef UIImage #define UIImage NSImage #endif #ifndef UIImageView #define UIImageView NSImageView #endif #else #import #endif #ifndef NS_ENUM #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type #endif #ifndef NS_OPTIONS #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type #endif #if OS_OBJECT_USE_OBJC #undef SDDispatchQueueRelease #undef SDDispatchQueueSetterSementics #define SDDispatchQueueRelease(q) #define SDDispatchQueueSetterSementics strong #else #undef SDDispatchQueueRelease #undef SDDispatchQueueSetterSementics #define SDDispatchQueueRelease(q) (dispatch_release(q)) #define SDDispatchQueueSetterSementics assign #endif extern UIImage *SDScaledImageForKey(NSString *key, UIImage *image); typedef void(^SDWebImageNoParamsBlock)(); extern NSString *const SDWebImageErrorDomain; #define dispatch_main_sync_safe(block)\ if ([NSThread isMainThread]) {\ block();\ } else {\ dispatch_sync(dispatch_get_main_queue(), block);\ } #define dispatch_main_async_safe(block)\ if ([NSThread isMainThread]) {\ block();\ } else {\ dispatch_async(dispatch_get_main_queue(), block);\ } ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageCompat.m ================================================ // // SDWebImageCompat.m // SDWebImage // // Created by Olivier Poitrey on 11/12/12. // Copyright (c) 2012 Dailymotion. All rights reserved. // #import "SDWebImageCompat.h" #if !__has_feature(objc_arc) #error SDWebImage is ARC only. Either turn on ARC for the project or use -fobjc-arc flag #endif inline UIImage *SDScaledImageForKey(NSString *key, UIImage *image) { if (!image) { return nil; } if ([image.images count] > 0) { NSMutableArray *scaledImages = [NSMutableArray array]; for (UIImage *tempImage in image.images) { [scaledImages addObject:SDScaledImageForKey(key, tempImage)]; } return [UIImage animatedImageWithImages:scaledImages duration:image.duration]; } else { if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { CGFloat scale = [UIScreen mainScreen].scale; if (key.length >= 8) { NSRange range = [key rangeOfString:@"@2x."]; if (range.location != NSNotFound) { scale = 2.0; } range = [key rangeOfString:@"@3x."]; if (range.location != NSNotFound) { scale = 3.0; } } UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation]; image = scaledImage; } return image; } } NSString *const SDWebImageErrorDomain = @"SDWebImageErrorDomain"; ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageDecoder.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * Created by james on 9/28/11. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import #import "SDWebImageCompat.h" @interface UIImage (ForceDecode) + (UIImage *)decodedImageWithImage:(UIImage *)image; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageDecoder.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * Created by james on 9/28/11. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDWebImageDecoder.h" @implementation UIImage (ForceDecode) + (UIImage *)decodedImageWithImage:(UIImage *)image { // while downloading huge amount of images // autorelease the bitmap context // and all vars to help system to free memory // when there are memory warning. // on iOS7, do not forget to call // [[SDImageCache sharedImageCache] clearMemory]; @autoreleasepool{ // do not decode animated images if (image.images) { return image; } CGImageRef imageRef = image.CGImage; CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef); BOOL anyAlpha = (alpha == kCGImageAlphaFirst || alpha == kCGImageAlphaLast || alpha == kCGImageAlphaPremultipliedFirst || alpha == kCGImageAlphaPremultipliedLast); if (anyAlpha) { return image; } size_t width = CGImageGetWidth(imageRef); size_t height = CGImageGetHeight(imageRef); // current CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(CGImageGetColorSpace(imageRef)); CGColorSpaceRef colorspaceRef = CGImageGetColorSpace(imageRef); bool unsupportedColorSpace = (imageColorSpaceModel == 0 || imageColorSpaceModel == -1 || imageColorSpaceModel == kCGColorSpaceModelCMYK || imageColorSpaceModel == kCGColorSpaceModelIndexed); if (unsupportedColorSpace) colorspaceRef = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(NULL, width, height, CGImageGetBitsPerComponent(imageRef), 0, colorspaceRef, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); // Draw the image into the context and retrieve the new image, which will now have an alpha layer CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(context); UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha scale:image.scale orientation:image.imageOrientation]; if (unsupportedColorSpace) CGColorSpaceRelease(colorspaceRef); CGContextRelease(context); CGImageRelease(imageRefWithAlpha); return imageWithAlpha; } } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageDownloader.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import #import "SDWebImageCompat.h" #import "SDWebImageOperation.h" typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) { SDWebImageDownloaderLowPriority = 1 << 0, SDWebImageDownloaderProgressiveDownload = 1 << 1, /** * By default, request prevent the of NSURLCache. With this flag, NSURLCache * is used with default policies. */ SDWebImageDownloaderUseNSURLCache = 1 << 2, /** * Call completion block with nil image/imageData if the image was read from NSURLCache * (to be combined with `SDWebImageDownloaderUseNSURLCache`). */ SDWebImageDownloaderIgnoreCachedResponse = 1 << 3, /** * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for * extra time in background to let the request finish. If the background task expires the operation will be cancelled. */ SDWebImageDownloaderContinueInBackground = 1 << 4, /** * Handles cookies stored in NSHTTPCookieStore by setting * NSMutableURLRequest.HTTPShouldHandleCookies = YES; */ SDWebImageDownloaderHandleCookies = 1 << 5, /** * Enable to allow untrusted SSL certificates. * Useful for testing purposes. Use with caution in production. */ SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6, /** * Put the image in the high priority queue. */ SDWebImageDownloaderHighPriority = 1 << 7, }; typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) { /** * Default value. All download operations will execute in queue style (first-in-first-out). */ SDWebImageDownloaderFIFOExecutionOrder, /** * All download operations will execute in stack style (last-in-first-out). */ SDWebImageDownloaderLIFOExecutionOrder }; extern NSString *const SDWebImageDownloadStartNotification; extern NSString *const SDWebImageDownloadStopNotification; typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize); typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data, NSError *error, BOOL finished); typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers); /** * Asynchronous downloader dedicated and optimized for image loading. */ @interface SDWebImageDownloader : NSObject /** * Decompressing images that are downloaded and cached can improve performance but can consume lot of memory. * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption. */ @property (assign, nonatomic) BOOL shouldDecompressImages; @property (assign, nonatomic) NSInteger maxConcurrentDownloads; /** * Shows the current amount of downloads that still need to be downloaded */ @property (readonly, nonatomic) NSUInteger currentDownloadCount; /** * The timeout value (in seconds) for the download operation. Default: 15.0. */ @property (assign, nonatomic) NSTimeInterval downloadTimeout; /** * Changes download operations execution order. Default value is `SDWebImageDownloaderFIFOExecutionOrder`. */ @property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder; /** * Singleton method, returns the shared instance * * @return global shared instance of downloader class */ + (SDWebImageDownloader *)sharedDownloader; /** * Set the default URL credential to be set for request operations. */ @property (strong, nonatomic) NSURLCredential *urlCredential; /** * Set username */ @property (strong, nonatomic) NSString *username; /** * Set password */ @property (strong, nonatomic) NSString *password; /** * Set filter to pick headers for downloading image HTTP request. * * This block will be invoked for each downloading image request, returned * NSDictionary will be used as headers in corresponding HTTP request. */ @property (nonatomic, copy) SDWebImageDownloaderHeadersFilterBlock headersFilter; /** * Set a value for a HTTP header to be appended to each download HTTP request. * * @param value The value for the header field. Use `nil` value to remove the header. * @param field The name of the header field to set. */ - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field; /** * Returns the value of the specified HTTP header field. * * @return The value associated with the header field field, or `nil` if there is no corresponding header field. */ - (NSString *)valueForHTTPHeaderField:(NSString *)field; /** * Sets a subclass of `SDWebImageDownloaderOperation` as the default * `NSOperation` to be used each time SDWebImage constructs a request * operation to download an image. * * @param operationClass The subclass of `SDWebImageDownloaderOperation` to set * as default. Passing `nil` will revert to `SDWebImageDownloaderOperation`. */ - (void)setOperationClass:(Class)operationClass; /** * Creates a SDWebImageDownloader async downloader instance with a given URL * * The delegate will be informed when the image is finish downloaded or an error has happen. * * @see SDWebImageDownloaderDelegate * * @param url The URL to the image to download * @param options The options to be used for this download * @param progressBlock A block called repeatedly while the image is downloading * @param completedBlock A block called once the download is completed. * If the download succeeded, the image parameter is set, in case of error, * error parameter is set with the error. The last parameter is always YES * if SDWebImageDownloaderProgressiveDownload isn't use. With the * SDWebImageDownloaderProgressiveDownload option, this block is called * repeatedly with the partial image object and the finished argument set to NO * before to be called a last time with the full image and finished argument * set to YES. In case of error, the finished argument is always YES. * * @return A cancellable SDWebImageOperation */ - (id )downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock; /** * Sets the download queue suspension state */ - (void)setSuspended:(BOOL)suspended; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageDownloader.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDWebImageDownloader.h" #import "SDWebImageDownloaderOperation.h" #import static NSString *const kProgressCallbackKey = @"progress"; static NSString *const kCompletedCallbackKey = @"completed"; @interface SDWebImageDownloader () @property (strong, nonatomic) NSOperationQueue *downloadQueue; @property (weak, nonatomic) NSOperation *lastAddedOperation; @property (assign, nonatomic) Class operationClass; @property (strong, nonatomic) NSMutableDictionary *URLCallbacks; @property (strong, nonatomic) NSMutableDictionary *HTTPHeaders; // This queue is used to serialize the handling of the network responses of all the download operation in a single queue @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; @end @implementation SDWebImageDownloader + (void)initialize { // Bind SDNetworkActivityIndicator if available (download it here: http://github.com/rs/SDNetworkActivityIndicator ) // To use it, just add #import "SDNetworkActivityIndicator.h" in addition to the SDWebImage import if (NSClassFromString(@"SDNetworkActivityIndicator")) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" id activityIndicator = [NSClassFromString(@"SDNetworkActivityIndicator") performSelector:NSSelectorFromString(@"sharedActivityIndicator")]; #pragma clang diagnostic pop // Remove observer in case it was previously added. [[NSNotificationCenter defaultCenter] removeObserver:activityIndicator name:SDWebImageDownloadStartNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:activityIndicator name:SDWebImageDownloadStopNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:activityIndicator selector:NSSelectorFromString(@"startActivity") name:SDWebImageDownloadStartNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:activityIndicator selector:NSSelectorFromString(@"stopActivity") name:SDWebImageDownloadStopNotification object:nil]; } } + (SDWebImageDownloader *)sharedDownloader { static dispatch_once_t once; static id instance; dispatch_once(&once, ^{ instance = [self new]; }); return instance; } - (id)init { if ((self = [super init])) { _operationClass = [SDWebImageDownloaderOperation class]; _shouldDecompressImages = YES; _executionOrder = SDWebImageDownloaderFIFOExecutionOrder; _downloadQueue = [NSOperationQueue new]; _downloadQueue.maxConcurrentOperationCount = 6; _URLCallbacks = [NSMutableDictionary new]; #ifdef SD_WEBP _HTTPHeaders = [@{@"Accept": @"image/webp,image/*;q=0.8"} mutableCopy]; #else _HTTPHeaders = [@{@"Accept": @"image/*;q=0.8"} mutableCopy]; #endif _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT); _downloadTimeout = 15.0; } return self; } - (void)dealloc { [self.downloadQueue cancelAllOperations]; SDDispatchQueueRelease(_barrierQueue); } - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field { if (value) { self.HTTPHeaders[field] = value; } else { [self.HTTPHeaders removeObjectForKey:field]; } } - (NSString *)valueForHTTPHeaderField:(NSString *)field { return self.HTTPHeaders[field]; } - (void)setMaxConcurrentDownloads:(NSInteger)maxConcurrentDownloads { _downloadQueue.maxConcurrentOperationCount = maxConcurrentDownloads; } - (NSUInteger)currentDownloadCount { return _downloadQueue.operationCount; } - (NSInteger)maxConcurrentDownloads { return _downloadQueue.maxConcurrentOperationCount; } - (void)setOperationClass:(Class)operationClass { _operationClass = operationClass ?: [SDWebImageDownloaderOperation class]; } - (id )downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock { __block SDWebImageDownloaderOperation *operation; __weak __typeof(self)wself = self; [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^{ NSTimeInterval timeoutInterval = wself.downloadTimeout; if (timeoutInterval == 0.0) { timeoutInterval = 15.0; } // In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval]; request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies); request.HTTPShouldUsePipelining = YES; if (wself.headersFilter) { request.allHTTPHeaderFields = wself.headersFilter(url, [wself.HTTPHeaders copy]); } else { request.allHTTPHeaderFields = wself.HTTPHeaders; } operation = [[wself.operationClass alloc] initWithRequest:request options:options progress:^(NSInteger receivedSize, NSInteger expectedSize) { SDWebImageDownloader *sself = wself; if (!sself) return; __block NSArray *callbacksForURL; dispatch_sync(sself.barrierQueue, ^{ callbacksForURL = [sself.URLCallbacks[url] copy]; }); for (NSDictionary *callbacks in callbacksForURL) { dispatch_async(dispatch_get_main_queue(), ^{ SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey]; if (callback) callback(receivedSize, expectedSize); }); } } completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { SDWebImageDownloader *sself = wself; if (!sself) return; __block NSArray *callbacksForURL; dispatch_barrier_sync(sself.barrierQueue, ^{ callbacksForURL = [sself.URLCallbacks[url] copy]; if (finished) { [sself.URLCallbacks removeObjectForKey:url]; } }); for (NSDictionary *callbacks in callbacksForURL) { SDWebImageDownloaderCompletedBlock callback = callbacks[kCompletedCallbackKey]; if (callback) callback(image, data, error, finished); } } cancelled:^{ SDWebImageDownloader *sself = wself; if (!sself) return; dispatch_barrier_async(sself.barrierQueue, ^{ [sself.URLCallbacks removeObjectForKey:url]; }); }]; operation.shouldDecompressImages = wself.shouldDecompressImages; if (wself.urlCredential) { operation.credential = wself.urlCredential; } else if (wself.username && wself.password) { operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession]; } if (options & SDWebImageDownloaderHighPriority) { operation.queuePriority = NSOperationQueuePriorityHigh; } else if (options & SDWebImageDownloaderLowPriority) { operation.queuePriority = NSOperationQueuePriorityLow; } [wself.downloadQueue addOperation:operation]; if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) { // Emulate LIFO execution order by systematically adding new operations as last operation's dependency [wself.lastAddedOperation addDependency:operation]; wself.lastAddedOperation = operation; } }]; return operation; } - (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback { // The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data. if (url == nil) { if (completedBlock != nil) { completedBlock(nil, nil, nil, NO); } return; } dispatch_barrier_sync(self.barrierQueue, ^{ BOOL first = NO; if (!self.URLCallbacks[url]) { self.URLCallbacks[url] = [NSMutableArray new]; first = YES; } // Handle single download of simultaneous download request for the same URL NSMutableArray *callbacksForURL = self.URLCallbacks[url]; NSMutableDictionary *callbacks = [NSMutableDictionary new]; if (progressBlock) callbacks[kProgressCallbackKey] = [progressBlock copy]; if (completedBlock) callbacks[kCompletedCallbackKey] = [completedBlock copy]; [callbacksForURL addObject:callbacks]; self.URLCallbacks[url] = callbacksForURL; if (first) { createCallback(); } }); } - (void)setSuspended:(BOOL)suspended { [self.downloadQueue setSuspended:suspended]; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageDownloaderOperation.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import #import "SDWebImageDownloader.h" #import "SDWebImageOperation.h" extern NSString *const SDWebImageDownloadStartNotification; extern NSString *const SDWebImageDownloadReceiveResponseNotification; extern NSString *const SDWebImageDownloadStopNotification; extern NSString *const SDWebImageDownloadFinishNotification; @interface SDWebImageDownloaderOperation : NSOperation /** * The request used by the operation's connection. */ @property (strong, nonatomic, readonly) NSURLRequest *request; @property (assign, nonatomic) BOOL shouldDecompressImages; /** * Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default. * * This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`. */ @property (nonatomic, assign) BOOL shouldUseCredentialStorage; /** * The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`. * * This will be overridden by any shared credentials that exist for the username or password of the request URL, if present. */ @property (nonatomic, strong) NSURLCredential *credential; /** * The SDWebImageDownloaderOptions for the receiver. */ @property (assign, nonatomic, readonly) SDWebImageDownloaderOptions options; /** * The expected size of data. */ @property (assign, nonatomic) NSInteger expectedSize; /** * The response returned by the operation's connection. */ @property (strong, nonatomic) NSURLResponse *response; /** * Initializes a `SDWebImageDownloaderOperation` object * * @see SDWebImageDownloaderOperation * * @param request the URL request * @param options downloader options * @param progressBlock the block executed when a new chunk of data arrives. * @note the progress block is executed on a background queue * @param completedBlock the block executed when the download is done. * @note the completed block is executed on the main queue for success. If errors are found, there is a chance the block will be executed on a background queue * @param cancelBlock the block executed if the download (operation) is cancelled * * @return the initialized instance */ - (id)initWithRequest:(NSURLRequest *)request options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock cancelled:(SDWebImageNoParamsBlock)cancelBlock; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageDownloaderOperation.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDWebImageDownloaderOperation.h" #import "SDWebImageDecoder.h" #import "UIImage+MultiFormat.h" #import #import "SDWebImageManager.h" NSString *const SDWebImageDownloadStartNotification = @"SDWebImageDownloadStartNotification"; NSString *const SDWebImageDownloadReceiveResponseNotification = @"SDWebImageDownloadReceiveResponseNotification"; NSString *const SDWebImageDownloadStopNotification = @"SDWebImageDownloadStopNotification"; NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinishNotification"; @interface SDWebImageDownloaderOperation () @property (copy, nonatomic) SDWebImageDownloaderProgressBlock progressBlock; @property (copy, nonatomic) SDWebImageDownloaderCompletedBlock completedBlock; @property (copy, nonatomic) SDWebImageNoParamsBlock cancelBlock; @property (assign, nonatomic, getter = isExecuting) BOOL executing; @property (assign, nonatomic, getter = isFinished) BOOL finished; @property (strong, nonatomic) NSMutableData *imageData; @property (strong, nonatomic) NSURLConnection *connection; @property (strong, atomic) NSThread *thread; #if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 @property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundTaskId; #endif @end @implementation SDWebImageDownloaderOperation { size_t width, height; UIImageOrientation orientation; BOOL responseFromCached; } @synthesize executing = _executing; @synthesize finished = _finished; - (id)initWithRequest:(NSURLRequest *)request options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock cancelled:(SDWebImageNoParamsBlock)cancelBlock { if ((self = [super init])) { _request = request; _shouldDecompressImages = YES; _shouldUseCredentialStorage = YES; _options = options; _progressBlock = [progressBlock copy]; _completedBlock = [completedBlock copy]; _cancelBlock = [cancelBlock copy]; _executing = NO; _finished = NO; _expectedSize = 0; responseFromCached = YES; // Initially wrong until `connection:willCacheResponse:` is called or not called } return self; } - (void)start { @synchronized (self) { if (self.isCancelled) { self.finished = YES; [self reset]; return; } #if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 Class UIApplicationClass = NSClassFromString(@"UIApplication"); BOOL hasApplication = UIApplicationClass && [UIApplicationClass respondsToSelector:@selector(sharedApplication)]; if (hasApplication && [self shouldContinueWhenAppEntersBackground]) { __weak __typeof__ (self) wself = self; UIApplication * app = [UIApplicationClass performSelector:@selector(sharedApplication)]; self.backgroundTaskId = [app beginBackgroundTaskWithExpirationHandler:^{ __strong __typeof (wself) sself = wself; if (sself) { [sself cancel]; [app endBackgroundTask:sself.backgroundTaskId]; sself.backgroundTaskId = UIBackgroundTaskInvalid; } }]; } #endif self.executing = YES; self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO]; self.thread = [NSThread currentThread]; } [self.connection start]; if (self.connection) { if (self.progressBlock) { self.progressBlock(0, NSURLResponseUnknownLength); } dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStartNotification object:self]; }); if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_5_1) { // Make sure to run the runloop in our background thread so it can process downloaded data // Note: we use a timeout to work around an issue with NSURLConnection cancel under iOS 5 // not waking up the runloop, leading to dead threads (see https://github.com/rs/SDWebImage/issues/466) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); } else { CFRunLoopRun(); } if (!self.isFinished) { [self.connection cancel]; [self connection:self.connection didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorTimedOut userInfo:@{NSURLErrorFailingURLErrorKey : self.request.URL}]]; } } else { if (self.completedBlock) { self.completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Connection can't be initialized"}], YES); } } #if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 Class UIApplicationClass = NSClassFromString(@"UIApplication"); if(!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) { return; } if (self.backgroundTaskId != UIBackgroundTaskInvalid) { UIApplication * app = [UIApplication performSelector:@selector(sharedApplication)]; [app endBackgroundTask:self.backgroundTaskId]; self.backgroundTaskId = UIBackgroundTaskInvalid; } #endif } - (void)cancel { @synchronized (self) { if (self.thread) { [self performSelector:@selector(cancelInternalAndStop) onThread:self.thread withObject:nil waitUntilDone:NO]; } else { [self cancelInternal]; } } } - (void)cancelInternalAndStop { if (self.isFinished) return; [self cancelInternal]; CFRunLoopStop(CFRunLoopGetCurrent()); } - (void)cancelInternal { if (self.isFinished) return; [super cancel]; if (self.cancelBlock) self.cancelBlock(); if (self.connection) { [self.connection cancel]; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self]; }); // As we cancelled the connection, its callback won't be called and thus won't // maintain the isFinished and isExecuting flags. if (self.isExecuting) self.executing = NO; if (!self.isFinished) self.finished = YES; } [self reset]; } - (void)done { self.finished = YES; self.executing = NO; [self reset]; } - (void)reset { self.cancelBlock = nil; self.completedBlock = nil; self.progressBlock = nil; self.connection = nil; self.imageData = nil; self.thread = nil; } - (void)setFinished:(BOOL)finished { [self willChangeValueForKey:@"isFinished"]; _finished = finished; [self didChangeValueForKey:@"isFinished"]; } - (void)setExecuting:(BOOL)executing { [self willChangeValueForKey:@"isExecuting"]; _executing = executing; [self didChangeValueForKey:@"isExecuting"]; } - (BOOL)isConcurrent { return YES; } #pragma mark NSURLConnection (delegate) - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { //'304 Not Modified' is an exceptional one if (![response respondsToSelector:@selector(statusCode)] || ([((NSHTTPURLResponse *)response) statusCode] < 400 && [((NSHTTPURLResponse *)response) statusCode] != 304)) { NSInteger expected = response.expectedContentLength > 0 ? (NSInteger)response.expectedContentLength : 0; self.expectedSize = expected; if (self.progressBlock) { self.progressBlock(0, expected); } self.imageData = [[NSMutableData alloc] initWithCapacity:expected]; self.response = response; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadReceiveResponseNotification object:self]; }); } else { NSUInteger code = [((NSHTTPURLResponse *)response) statusCode]; //This is the case when server returns '304 Not Modified'. It means that remote image is not changed. //In case of 304 we need just cancel the operation and return cached image from the cache. if (code == 304) { [self cancelInternal]; } else { [self.connection cancel]; } dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self]; }); if (self.completedBlock) { self.completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:[((NSHTTPURLResponse *)response) statusCode] userInfo:nil], YES); } CFRunLoopStop(CFRunLoopGetCurrent()); [self done]; } } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [self.imageData appendData:data]; if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0 && self.completedBlock) { // The following code is from http://www.cocoaintheshell.com/2011/05/progressive-images-download-imageio/ // Thanks to the author @Nyx0uf // Get the total bytes downloaded const NSInteger totalSize = self.imageData.length; // Update the data source, we must pass ALL the data, not just the new bytes CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)self.imageData, NULL); if (width + height == 0) { CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); if (properties) { NSInteger orientationValue = -1; CFTypeRef val = CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight); if (val) CFNumberGetValue(val, kCFNumberLongType, &height); val = CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth); if (val) CFNumberGetValue(val, kCFNumberLongType, &width); val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation); if (val) CFNumberGetValue(val, kCFNumberNSIntegerType, &orientationValue); CFRelease(properties); // When we draw to Core Graphics, we lose orientation information, // which means the image below born of initWithCGIImage will be // oriented incorrectly sometimes. (Unlike the image born of initWithData // in connectionDidFinishLoading.) So save it here and pass it on later. orientation = [[self class] orientationFromPropertyValue:(orientationValue == -1 ? 1 : orientationValue)]; } } if (width + height > 0 && totalSize < self.expectedSize) { // Create the image CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); #ifdef TARGET_OS_IPHONE // Workaround for iOS anamorphic image if (partialImageRef) { const size_t partialHeight = CGImageGetHeight(partialImageRef); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); CGColorSpaceRelease(colorSpace); if (bmContext) { CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = partialHeight}, partialImageRef); CGImageRelease(partialImageRef); partialImageRef = CGBitmapContextCreateImage(bmContext); CGContextRelease(bmContext); } else { CGImageRelease(partialImageRef); partialImageRef = nil; } } #endif if (partialImageRef) { UIImage *image = [UIImage imageWithCGImage:partialImageRef scale:1 orientation:orientation]; NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]; UIImage *scaledImage = [self scaledImageForKey:key image:image]; if (self.shouldDecompressImages) { image = [UIImage decodedImageWithImage:scaledImage]; } else { image = scaledImage; } CGImageRelease(partialImageRef); dispatch_main_sync_safe(^{ if (self.completedBlock) { self.completedBlock(image, nil, nil, NO); } }); } } CFRelease(imageSource); } if (self.progressBlock) { self.progressBlock(self.imageData.length, self.expectedSize); } } + (UIImageOrientation)orientationFromPropertyValue:(NSInteger)value { switch (value) { case 1: return UIImageOrientationUp; case 3: return UIImageOrientationDown; case 8: return UIImageOrientationLeft; case 6: return UIImageOrientationRight; case 2: return UIImageOrientationUpMirrored; case 4: return UIImageOrientationDownMirrored; case 5: return UIImageOrientationLeftMirrored; case 7: return UIImageOrientationRightMirrored; default: return UIImageOrientationUp; } } - (UIImage *)scaledImageForKey:(NSString *)key image:(UIImage *)image { return SDScaledImageForKey(key, image); } - (void)connectionDidFinishLoading:(NSURLConnection *)aConnection { SDWebImageDownloaderCompletedBlock completionBlock = self.completedBlock; @synchronized(self) { CFRunLoopStop(CFRunLoopGetCurrent()); self.thread = nil; self.connection = nil; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadFinishNotification object:self]; }); } if (![[NSURLCache sharedURLCache] cachedResponseForRequest:_request]) { responseFromCached = NO; } if (completionBlock) { if (self.options & SDWebImageDownloaderIgnoreCachedResponse && responseFromCached) { completionBlock(nil, nil, nil, YES); } else if (self.imageData) { UIImage *image = [UIImage sd_imageWithData:self.imageData]; NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]; image = [self scaledImageForKey:key image:image]; // Do not force decoding animated GIFs if (!image.images) { if (self.shouldDecompressImages) { image = [UIImage decodedImageWithImage:image]; } } if (CGSizeEqualToSize(image.size, CGSizeZero)) { completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES); } else { completionBlock(image, self.imageData, nil, YES); } } else { completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}], YES); } } self.completionBlock = nil; [self done]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { @synchronized(self) { CFRunLoopStop(CFRunLoopGetCurrent()); self.thread = nil; self.connection = nil; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self]; }); } if (self.completedBlock) { self.completedBlock(nil, nil, error, YES); } self.completionBlock = nil; [self done]; } - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { responseFromCached = NO; // If this method is called, it means the response wasn't read from cache if (self.request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData) { // Prevents caching of responses return nil; } else { return cachedResponse; } } - (BOOL)shouldContinueWhenAppEntersBackground { return self.options & SDWebImageDownloaderContinueInBackground; } - (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection __unused *)connection { return self.shouldUseCredentialStorage; } - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{ if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if (!(self.options & SDWebImageDownloaderAllowInvalidSSLCertificates) && [challenge.sender respondsToSelector:@selector(performDefaultHandlingForAuthenticationChallenge:)]) { [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; } else { NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; } } else { if ([challenge previousFailureCount] == 0) { if (self.credential) { [[challenge sender] useCredential:self.credential forAuthenticationChallenge:challenge]; } else { [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; } } else { [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; } } } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageManager.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDWebImageCompat.h" #import "SDWebImageOperation.h" #import "SDWebImageDownloader.h" #import "SDImageCache.h" typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { /** * By default, when a URL fail to be downloaded, the URL is blacklisted so the library won't keep trying. * This flag disable this blacklisting. */ SDWebImageRetryFailed = 1 << 0, /** * By default, image downloads are started during UI interactions, this flags disable this feature, * leading to delayed download on UIScrollView deceleration for instance. */ SDWebImageLowPriority = 1 << 1, /** * This flag disables on-disk caching */ SDWebImageCacheMemoryOnly = 1 << 2, /** * This flag enables progressive download, the image is displayed progressively during download as a browser would do. * By default, the image is only displayed once completely downloaded. */ SDWebImageProgressiveDownload = 1 << 3, /** * Even if the image is cached, respect the HTTP response cache control, and refresh the image from remote location if needed. * The disk caching will be handled by NSURLCache instead of SDWebImage leading to slight performance degradation. * This option helps deal with images changing behind the same request URL, e.g. Facebook graph api profile pics. * If a cached image is refreshed, the completion block is called once with the cached image and again with the final image. * * Use this flag only if you can't make your URLs static with embedded cache busting parameter. */ SDWebImageRefreshCached = 1 << 4, /** * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for * extra time in background to let the request finish. If the background task expires the operation will be cancelled. */ SDWebImageContinueInBackground = 1 << 5, /** * Handles cookies stored in NSHTTPCookieStore by setting * NSMutableURLRequest.HTTPShouldHandleCookies = YES; */ SDWebImageHandleCookies = 1 << 6, /** * Enable to allow untrusted SSL certificates. * Useful for testing purposes. Use with caution in production. */ SDWebImageAllowInvalidSSLCertificates = 1 << 7, /** * By default, image are loaded in the order they were queued. This flag move them to * the front of the queue and is loaded immediately instead of waiting for the current queue to be loaded (which * could take a while). */ SDWebImageHighPriority = 1 << 8, /** * By default, placeholder images are loaded while the image is loading. This flag will delay the loading * of the placeholder image until after the image has finished loading. */ SDWebImageDelayPlaceholder = 1 << 9, /** * We usually don't call transformDownloadedImage delegate method on animated images, * as most transformation code would mangle it. * Use this flag to transform them anyway. */ SDWebImageTransformAnimatedImage = 1 << 10, /** * By default, image is added to the imageView after download. But in some cases, we want to * have the hand before setting the image (apply a filter or add it with cross-fade animation for instance) * Use this flag if you want to manually set the image in the completion when success */ SDWebImageAvoidAutoSetImage = 1 << 11 }; typedef void(^SDWebImageCompletionBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL); typedef void(^SDWebImageCompletionWithFinishedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL); typedef NSString *(^SDWebImageCacheKeyFilterBlock)(NSURL *url); @class SDWebImageManager; @protocol SDWebImageManagerDelegate @optional /** * Controls which image should be downloaded when the image is not found in the cache. * * @param imageManager The current `SDWebImageManager` * @param imageURL The url of the image to be downloaded * * @return Return NO to prevent the downloading of the image on cache misses. If not implemented, YES is implied. */ - (BOOL)imageManager:(SDWebImageManager *)imageManager shouldDownloadImageForURL:(NSURL *)imageURL; /** * Allows to transform the image immediately after it has been downloaded and just before to cache it on disk and memory. * NOTE: This method is called from a global queue in order to not to block the main thread. * * @param imageManager The current `SDWebImageManager` * @param image The image to transform * @param imageURL The url of the image to transform * * @return The transformed image object. */ - (UIImage *)imageManager:(SDWebImageManager *)imageManager transformDownloadedImage:(UIImage *)image withURL:(NSURL *)imageURL; @end /** * The SDWebImageManager is the class behind the UIImageView+WebCache category and likes. * It ties the asynchronous downloader (SDWebImageDownloader) with the image cache store (SDImageCache). * You can use this class directly to benefit from web image downloading with caching in another context than * a UIView. * * Here is a simple example of how to use SDWebImageManager: * * @code SDWebImageManager *manager = [SDWebImageManager sharedManager]; [manager downloadImageWithURL:imageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (image) { // do something with image } }]; * @endcode */ @interface SDWebImageManager : NSObject @property (weak, nonatomic) id delegate; @property (strong, nonatomic, readonly) SDImageCache *imageCache; @property (strong, nonatomic, readonly) SDWebImageDownloader *imageDownloader; /** * The cache filter is a block used each time SDWebImageManager need to convert an URL into a cache key. This can * be used to remove dynamic part of an image URL. * * The following example sets a filter in the application delegate that will remove any query-string from the * URL before to use it as a cache key: * * @code [[SDWebImageManager sharedManager] setCacheKeyFilter:^(NSURL *url) { url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path]; return [url absoluteString]; }]; * @endcode */ @property (nonatomic, copy) SDWebImageCacheKeyFilterBlock cacheKeyFilter; /** * Returns global SDWebImageManager instance. * * @return SDWebImageManager shared instance */ + (SDWebImageManager *)sharedManager; /** * Downloads the image at the given URL if not present in cache or return the cached version otherwise. * * @param url The URL to the image * @param options A mask to specify options to use for this request * @param progressBlock A block called while image is downloading * @param completedBlock A block called when operation has been completed. * * This parameter is required. * * This block has no return value and takes the requested UIImage as first parameter. * In case of error the image parameter is nil and the second parameter may contain an NSError. * * The third parameter is an `SDImageCacheType` enum indicating if the image was retrieved from the local cache * or from the memory cache or from the network. * * The last parameter is set to NO when the SDWebImageProgressiveDownload option is used and the image is * downloading. This block is thus called repeatedly with a partial image. When image is fully downloaded, the * block is called a last time with the full image and the last parameter set to YES. * * @return Returns an NSObject conforming to SDWebImageOperation. Should be an instance of SDWebImageDownloaderOperation */ - (id )downloadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionWithFinishedBlock)completedBlock; /** * Saves image to cache for given URL * * @param image The image to cache * @param url The URL to the image * */ - (void)saveImageToCache:(UIImage *)image forURL:(NSURL *)url; /** * Cancel all current operations */ - (void)cancelAll; /** * Check one or more operations running */ - (BOOL)isRunning; /** * Check if image has already been cached * * @param url image url * * @return if the image was already cached */ - (BOOL)cachedImageExistsForURL:(NSURL *)url; /** * Check if image has already been cached on disk only * * @param url image url * * @return if the image was already cached (disk only) */ - (BOOL)diskImageExistsForURL:(NSURL *)url; /** * Async check if image has already been cached * * @param url image url * @param completionBlock the block to be executed when the check is finished * * @note the completion block is always executed on the main queue */ - (void)cachedImageExistsForURL:(NSURL *)url completion:(SDWebImageCheckCacheCompletionBlock)completionBlock; /** * Async check if image has already been cached on disk only * * @param url image url * @param completionBlock the block to be executed when the check is finished * * @note the completion block is always executed on the main queue */ - (void)diskImageExistsForURL:(NSURL *)url completion:(SDWebImageCheckCacheCompletionBlock)completionBlock; /** *Return the cache key for a given URL */ - (NSString *)cacheKeyForURL:(NSURL *)url; @end #pragma mark - Deprecated typedef void(^SDWebImageCompletedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType) __deprecated_msg("Block type deprecated. Use `SDWebImageCompletionBlock`"); typedef void(^SDWebImageCompletedWithFinishedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) __deprecated_msg("Block type deprecated. Use `SDWebImageCompletionWithFinishedBlock`"); @interface SDWebImageManager (Deprecated) /** * Downloads the image at the given URL if not present in cache or return the cached version otherwise. * * @deprecated This method has been deprecated. Use `downloadImageWithURL:options:progress:completed:` */ - (id )downloadWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedWithFinishedBlock)completedBlock __deprecated_msg("Method deprecated. Use `downloadImageWithURL:options:progress:completed:`"); @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageManager.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDWebImageManager.h" #import @interface SDWebImageCombinedOperation : NSObject @property (assign, nonatomic, getter = isCancelled) BOOL cancelled; @property (copy, nonatomic) SDWebImageNoParamsBlock cancelBlock; @property (strong, nonatomic) NSOperation *cacheOperation; @end @interface SDWebImageManager () @property (strong, nonatomic, readwrite) SDImageCache *imageCache; @property (strong, nonatomic, readwrite) SDWebImageDownloader *imageDownloader; @property (strong, nonatomic) NSMutableSet *failedURLs; @property (strong, nonatomic) NSMutableArray *runningOperations; @end @implementation SDWebImageManager + (id)sharedManager { static dispatch_once_t once; static id instance; dispatch_once(&once, ^{ instance = [self new]; }); return instance; } - (id)init { if ((self = [super init])) { _imageCache = [self createCache]; _imageDownloader = [SDWebImageDownloader sharedDownloader]; _failedURLs = [NSMutableSet new]; _runningOperations = [NSMutableArray new]; } return self; } - (SDImageCache *)createCache { return [SDImageCache sharedImageCache]; } - (NSString *)cacheKeyForURL:(NSURL *)url { if (self.cacheKeyFilter) { return self.cacheKeyFilter(url); } else { return [url absoluteString]; } } - (BOOL)cachedImageExistsForURL:(NSURL *)url { NSString *key = [self cacheKeyForURL:url]; if ([self.imageCache imageFromMemoryCacheForKey:key] != nil) return YES; return [self.imageCache diskImageExistsWithKey:key]; } - (BOOL)diskImageExistsForURL:(NSURL *)url { NSString *key = [self cacheKeyForURL:url]; return [self.imageCache diskImageExistsWithKey:key]; } - (void)cachedImageExistsForURL:(NSURL *)url completion:(SDWebImageCheckCacheCompletionBlock)completionBlock { NSString *key = [self cacheKeyForURL:url]; BOOL isInMemoryCache = ([self.imageCache imageFromMemoryCacheForKey:key] != nil); if (isInMemoryCache) { // making sure we call the completion block on the main queue dispatch_async(dispatch_get_main_queue(), ^{ if (completionBlock) { completionBlock(YES); } }); return; } [self.imageCache diskImageExistsWithKey:key completion:^(BOOL isInDiskCache) { // the completion block of checkDiskCacheForImageWithKey:completion: is always called on the main queue, no need to further dispatch if (completionBlock) { completionBlock(isInDiskCache); } }]; } - (void)diskImageExistsForURL:(NSURL *)url completion:(SDWebImageCheckCacheCompletionBlock)completionBlock { NSString *key = [self cacheKeyForURL:url]; [self.imageCache diskImageExistsWithKey:key completion:^(BOOL isInDiskCache) { // the completion block of checkDiskCacheForImageWithKey:completion: is always called on the main queue, no need to further dispatch if (completionBlock) { completionBlock(isInDiskCache); } }]; } - (id )downloadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionWithFinishedBlock)completedBlock { // Invoking this method without a completedBlock is pointless NSAssert(completedBlock != nil, @"If you mean to prefetch the image, use -[SDWebImagePrefetcher prefetchURLs] instead"); // Very common mistake is to send the URL using NSString object instead of NSURL. For some strange reason, XCode won't // throw any warning for this type mismatch. Here we failsafe this error by allowing URLs to be passed as NSString. if ([url isKindOfClass:NSString.class]) { url = [NSURL URLWithString:(NSString *)url]; } // Prevents app crashing on argument type error like sending NSNull instead of NSURL if (![url isKindOfClass:NSURL.class]) { url = nil; } __block SDWebImageCombinedOperation *operation = [SDWebImageCombinedOperation new]; __weak SDWebImageCombinedOperation *weakOperation = operation; BOOL isFailedUrl = NO; @synchronized (self.failedURLs) { isFailedUrl = [self.failedURLs containsObject:url]; } if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) { dispatch_main_sync_safe(^{ NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil]; completedBlock(nil, error, SDImageCacheTypeNone, YES, url); }); return operation; } @synchronized (self.runningOperations) { [self.runningOperations addObject:operation]; } NSString *key = [self cacheKeyForURL:url]; operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *image, SDImageCacheType cacheType) { if (operation.isCancelled) { @synchronized (self.runningOperations) { [self.runningOperations removeObject:operation]; } return; } if ((!image || options & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) { if (image && options & SDWebImageRefreshCached) { dispatch_main_sync_safe(^{ // If image was found in the cache but SDWebImageRefreshCached is provided, notify about the cached image // AND try to re-download it in order to let a chance to NSURLCache to refresh it from server. completedBlock(image, nil, cacheType, YES, url); }); } // download if no image or requested to refresh anyway, and download allowed by delegate SDWebImageDownloaderOptions downloaderOptions = 0; if (options & SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority; if (options & SDWebImageProgressiveDownload) downloaderOptions |= SDWebImageDownloaderProgressiveDownload; if (options & SDWebImageRefreshCached) downloaderOptions |= SDWebImageDownloaderUseNSURLCache; if (options & SDWebImageContinueInBackground) downloaderOptions |= SDWebImageDownloaderContinueInBackground; if (options & SDWebImageHandleCookies) downloaderOptions |= SDWebImageDownloaderHandleCookies; if (options & SDWebImageAllowInvalidSSLCertificates) downloaderOptions |= SDWebImageDownloaderAllowInvalidSSLCertificates; if (options & SDWebImageHighPriority) downloaderOptions |= SDWebImageDownloaderHighPriority; if (image && options & SDWebImageRefreshCached) { // force progressive off if image already cached but forced refreshing downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload; // ignore image read from NSURLCache if image if cached but force refreshing downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse; } id subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished) { __strong __typeof(weakOperation) strongOperation = weakOperation; if (!strongOperation || strongOperation.isCancelled) { // Do nothing if the operation was cancelled // See #699 for more details // if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data } else if (error) { dispatch_main_sync_safe(^{ if (strongOperation && !strongOperation.isCancelled) { completedBlock(nil, error, SDImageCacheTypeNone, finished, url); } }); if ( error.code != NSURLErrorNotConnectedToInternet && error.code != NSURLErrorCancelled && error.code != NSURLErrorTimedOut && error.code != NSURLErrorInternationalRoamingOff && error.code != NSURLErrorDataNotAllowed && error.code != NSURLErrorCannotFindHost && error.code != NSURLErrorCannotConnectToHost) { @synchronized (self.failedURLs) { [self.failedURLs addObject:url]; } } } else { if ((options & SDWebImageRetryFailed)) { @synchronized (self.failedURLs) { [self.failedURLs removeObject:url]; } } BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly); if (options & SDWebImageRefreshCached && image && !downloadedImage) { // Image refresh hit the NSURLCache cache, do not call the completion block } else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)]) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url]; if (transformedImage && finished) { BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage]; [self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:(imageWasTransformed ? nil : data) forKey:key toDisk:cacheOnDisk]; } dispatch_main_sync_safe(^{ if (strongOperation && !strongOperation.isCancelled) { completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished, url); } }); }); } else { if (downloadedImage && finished) { [self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:data forKey:key toDisk:cacheOnDisk]; } dispatch_main_sync_safe(^{ if (strongOperation && !strongOperation.isCancelled) { completedBlock(downloadedImage, nil, SDImageCacheTypeNone, finished, url); } }); } } if (finished) { @synchronized (self.runningOperations) { if (strongOperation) { [self.runningOperations removeObject:strongOperation]; } } } }]; operation.cancelBlock = ^{ [subOperation cancel]; @synchronized (self.runningOperations) { __strong __typeof(weakOperation) strongOperation = weakOperation; if (strongOperation) { [self.runningOperations removeObject:strongOperation]; } } }; } else if (image) { dispatch_main_sync_safe(^{ __strong __typeof(weakOperation) strongOperation = weakOperation; if (strongOperation && !strongOperation.isCancelled) { completedBlock(image, nil, cacheType, YES, url); } }); @synchronized (self.runningOperations) { [self.runningOperations removeObject:operation]; } } else { // Image not in cache and download disallowed by delegate dispatch_main_sync_safe(^{ __strong __typeof(weakOperation) strongOperation = weakOperation; if (strongOperation && !weakOperation.isCancelled) { completedBlock(nil, nil, SDImageCacheTypeNone, YES, url); } }); @synchronized (self.runningOperations) { [self.runningOperations removeObject:operation]; } } }]; return operation; } - (void)saveImageToCache:(UIImage *)image forURL:(NSURL *)url { if (image && url) { NSString *key = [self cacheKeyForURL:url]; [self.imageCache storeImage:image forKey:key toDisk:YES]; } } - (void)cancelAll { @synchronized (self.runningOperations) { NSArray *copiedOperations = [self.runningOperations copy]; [copiedOperations makeObjectsPerformSelector:@selector(cancel)]; [self.runningOperations removeObjectsInArray:copiedOperations]; } } - (BOOL)isRunning { BOOL isRunning = NO; @synchronized(self.runningOperations) { isRunning = (self.runningOperations.count > 0); } return isRunning; } @end @implementation SDWebImageCombinedOperation - (void)setCancelBlock:(SDWebImageNoParamsBlock)cancelBlock { // check if the operation is already cancelled, then we just call the cancelBlock if (self.isCancelled) { if (cancelBlock) { cancelBlock(); } _cancelBlock = nil; // don't forget to nil the cancelBlock, otherwise we will get crashes } else { _cancelBlock = [cancelBlock copy]; } } - (void)cancel { self.cancelled = YES; if (self.cacheOperation) { [self.cacheOperation cancel]; self.cacheOperation = nil; } if (self.cancelBlock) { self.cancelBlock(); // TODO: this is a temporary fix to #809. // Until we can figure the exact cause of the crash, going with the ivar instead of the setter // self.cancelBlock = nil; _cancelBlock = nil; } } @end @implementation SDWebImageManager (Deprecated) // deprecated method, uses the non deprecated method // adapter for the completion block - (id )downloadWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedWithFinishedBlock)completedBlock { return [self downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType, finished); } }]; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImageOperation.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import @protocol SDWebImageOperation - (void)cancel; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImagePrefetcher.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import #import "SDWebImageManager.h" @class SDWebImagePrefetcher; @protocol SDWebImagePrefetcherDelegate @optional /** * Called when an image was prefetched. * * @param imagePrefetcher The current image prefetcher * @param imageURL The image url that was prefetched * @param finishedCount The total number of images that were prefetched (successful or not) * @param totalCount The total number of images that were to be prefetched */ - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount; /** * Called when all images are prefetched. * @param imagePrefetcher The current image prefetcher * @param totalCount The total number of images that were prefetched (whether successful or not) * @param skippedCount The total number of images that were skipped */ - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount; @end typedef void(^SDWebImagePrefetcherProgressBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls); typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls); /** * Prefetch some URLs in the cache for future use. Images are downloaded in low priority. */ @interface SDWebImagePrefetcher : NSObject /** * The web image manager */ @property (strong, nonatomic, readonly) SDWebImageManager *manager; /** * Maximum number of URLs to prefetch at the same time. Defaults to 3. */ @property (nonatomic, assign) NSUInteger maxConcurrentDownloads; /** * SDWebImageOptions for prefetcher. Defaults to SDWebImageLowPriority. */ @property (nonatomic, assign) SDWebImageOptions options; /** * Queue options for Prefetcher. Defaults to Main Queue. */ @property (nonatomic, assign) dispatch_queue_t prefetcherQueue; @property (weak, nonatomic) id delegate; /** * Return the global image prefetcher instance. */ + (SDWebImagePrefetcher *)sharedImagePrefetcher; /** * Allows you to instantiate a prefetcher with any arbitrary image manager. */ - (id)initWithImageManager:(SDWebImageManager *)manager; /** * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching, * currently one image is downloaded at a time, * and skips images for failed downloads and proceed to the next image in the list * * @param urls list of URLs to prefetch */ - (void)prefetchURLs:(NSArray *)urls; /** * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching, * currently one image is downloaded at a time, * and skips images for failed downloads and proceed to the next image in the list * * @param urls list of URLs to prefetch * @param progressBlock block to be called when progress updates; * first parameter is the number of completed (successful or not) requests, * second parameter is the total number of images originally requested to be prefetched * @param completionBlock block to be called when prefetching is completed * first param is the number of completed (successful or not) requests, * second parameter is the number of skipped requests */ - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock; /** * Remove and cancel queued list */ - (void)cancelPrefetching; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/SDWebImagePrefetcher.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDWebImagePrefetcher.h" @interface SDWebImagePrefetcher () @property (strong, nonatomic) SDWebImageManager *manager; @property (strong, nonatomic) NSArray *prefetchURLs; @property (assign, nonatomic) NSUInteger requestedCount; @property (assign, nonatomic) NSUInteger skippedCount; @property (assign, nonatomic) NSUInteger finishedCount; @property (assign, nonatomic) NSTimeInterval startedTime; @property (copy, nonatomic) SDWebImagePrefetcherCompletionBlock completionBlock; @property (copy, nonatomic) SDWebImagePrefetcherProgressBlock progressBlock; @end @implementation SDWebImagePrefetcher + (SDWebImagePrefetcher *)sharedImagePrefetcher { static dispatch_once_t once; static id instance; dispatch_once(&once, ^{ instance = [self new]; }); return instance; } - (id)init { return [self initWithImageManager:[SDWebImageManager new]]; } - (id)initWithImageManager:(SDWebImageManager *)manager { if ((self = [super init])) { _manager = manager; _options = SDWebImageLowPriority; _prefetcherQueue = dispatch_get_main_queue(); self.maxConcurrentDownloads = 3; } return self; } - (void)setMaxConcurrentDownloads:(NSUInteger)maxConcurrentDownloads { self.manager.imageDownloader.maxConcurrentDownloads = maxConcurrentDownloads; } - (NSUInteger)maxConcurrentDownloads { return self.manager.imageDownloader.maxConcurrentDownloads; } - (void)startPrefetchingAtIndex:(NSUInteger)index { if (index >= self.prefetchURLs.count) return; self.requestedCount++; [self.manager downloadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (!finished) return; self.finishedCount++; if (image) { if (self.progressBlock) { self.progressBlock(self.finishedCount,[self.prefetchURLs count]); } } else { if (self.progressBlock) { self.progressBlock(self.finishedCount,[self.prefetchURLs count]); } // Add last failed self.skippedCount++; } if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didPrefetchURL:finishedCount:totalCount:)]) { [self.delegate imagePrefetcher:self didPrefetchURL:self.prefetchURLs[index] finishedCount:self.finishedCount totalCount:self.prefetchURLs.count ]; } if (self.prefetchURLs.count > self.requestedCount) { dispatch_async(self.prefetcherQueue, ^{ [self startPrefetchingAtIndex:self.requestedCount]; }); } else if (self.finishedCount == self.requestedCount) { [self reportStatus]; if (self.completionBlock) { self.completionBlock(self.finishedCount, self.skippedCount); self.completionBlock = nil; } self.progressBlock = nil; } }]; } - (void)reportStatus { NSUInteger total = [self.prefetchURLs count]; if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didFinishWithTotalCount:skippedCount:)]) { [self.delegate imagePrefetcher:self didFinishWithTotalCount:(total - self.skippedCount) skippedCount:self.skippedCount ]; } } - (void)prefetchURLs:(NSArray *)urls { [self prefetchURLs:urls progress:nil completed:nil]; } - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock { [self cancelPrefetching]; // Prevent duplicate prefetch request self.startedTime = CFAbsoluteTimeGetCurrent(); self.prefetchURLs = urls; self.completionBlock = completionBlock; self.progressBlock = progressBlock; if (urls.count == 0) { if (completionBlock) { completionBlock(0,0); } } else { // Starts prefetching from the very first image on the list with the max allowed concurrency NSUInteger listCount = self.prefetchURLs.count; for (NSUInteger i = 0; i < self.maxConcurrentDownloads && self.requestedCount < listCount; i++) { [self startPrefetchingAtIndex:i]; } } } - (void)cancelPrefetching { self.prefetchURLs = nil; self.skippedCount = 0; self.requestedCount = 0; self.finishedCount = 0; [self.manager cancelAll]; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIButton+WebCache.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDWebImageCompat.h" #import "SDWebImageManager.h" /** * Integrates SDWebImage async downloading and caching of remote images with UIButtonView. */ @interface UIButton (WebCache) /** * Get the current image URL. */ - (NSURL *)sd_currentImageURL; /** * Get the image URL for a control state. * * @param state Which state you want to know the URL for. The values are described in UIControlState. */ - (NSURL *)sd_imageURLForState:(UIControlState)state; /** * Set the imageView `image` with an `url`. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. */ - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state; /** * Set the imageView `image` with an `url` and a placeholder. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param placeholder The image to be set initially, until the image request finishes. * @see sd_setImageWithURL:placeholderImage:options: */ - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder; /** * Set the imageView `image` with an `url`, placeholder and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param placeholder The image to be set initially, until the image request finishes. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. */ - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options; /** * Set the imageView `image` with an `url`. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the imageView `image` with an `url`, placeholder. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param placeholder The image to be set initially, until the image request finishes. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the imageView `image` with an `url`, placeholder and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param placeholder The image to be set initially, until the image request finishes. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the backgroundImageView `image` with an `url`. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. */ - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state; /** * Set the backgroundImageView `image` with an `url` and a placeholder. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param placeholder The image to be set initially, until the image request finishes. * @see sd_setImageWithURL:placeholderImage:options: */ - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder; /** * Set the backgroundImageView `image` with an `url`, placeholder and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param placeholder The image to be set initially, until the image request finishes. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. */ - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options; /** * Set the backgroundImageView `image` with an `url`. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the backgroundImageView `image` with an `url`, placeholder. * * The download is asynchronous and cached. * * @param url The url for the image. * @param state The state that uses the specified title. The values are described in UIControlState. * @param placeholder The image to be set initially, until the image request finishes. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the backgroundImageView `image` with an `url`, placeholder and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param placeholder The image to be set initially, until the image request finishes. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; /** * Cancel the current image download */ - (void)sd_cancelImageLoadForState:(UIControlState)state; /** * Cancel the current backgroundImage download */ - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state; @end @interface UIButton (WebCacheDeprecated) - (NSURL *)currentImageURL __deprecated_msg("Use `sd_currentImageURL`"); - (NSURL *)imageURLForState:(UIControlState)state __deprecated_msg("Use `sd_imageURLForState:`"); - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:`"); - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:`"); - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:options:`"); - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:completed:`"); - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:completed:`"); - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:options:completed:`"); - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:`"); - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:`"); - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:options:`"); - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:completed:`"); - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:completed:`"); - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:options:completed:`"); - (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelImageLoadForState:`"); - (void)cancelBackgroundImageLoadForState:(UIControlState)state __deprecated_msg("Use `sd_cancelBackgroundImageLoadForState:`"); @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIButton+WebCache.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "UIButton+WebCache.h" #import "objc/runtime.h" #import "UIView+WebCacheOperation.h" static char imageURLStorageKey; @implementation UIButton (WebCache) - (NSURL *)sd_currentImageURL { NSURL *url = self.imageURLStorage[@(self.state)]; if (!url) { url = self.imageURLStorage[@(UIControlStateNormal)]; } return url; } - (NSURL *)sd_imageURLForState:(UIControlState)state { return self.imageURLStorage[@(state)]; } - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state { [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil]; } - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder { [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil]; } - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil]; } - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock]; } - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock]; } - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { [self setImage:placeholder forState:state]; [self sd_cancelImageLoadForState:state]; if (!url) { [self.imageURLStorage removeObjectForKey:@(state)]; dispatch_main_async_safe(^{ if (completedBlock) { NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; completedBlock(nil, error, SDImageCacheTypeNone, url); } }); return; } self.imageURLStorage[@(state)] = url; __weak __typeof(self)wself = self; id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (!wself) return; dispatch_main_sync_safe(^{ __strong UIButton *sself = wself; if (!sself) return; if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) { completedBlock(image, error, cacheType, url); return; } else if (image) { [sself setImage:image forState:state]; } if (completedBlock && finished) { completedBlock(image, error, cacheType, url); } }); }]; [self sd_setImageLoadOperation:operation forState:state]; } - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil]; } - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil]; } - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil]; } - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock]; } - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock]; } - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { [self sd_cancelBackgroundImageLoadForState:state]; [self setBackgroundImage:placeholder forState:state]; if (url) { __weak __typeof(self)wself = self; id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (!wself) return; dispatch_main_sync_safe(^{ __strong UIButton *sself = wself; if (!sself) return; if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) { completedBlock(image, error, cacheType, url); return; } else if (image) { [sself setBackgroundImage:image forState:state]; } if (completedBlock && finished) { completedBlock(image, error, cacheType, url); } }); }]; [self sd_setBackgroundImageLoadOperation:operation forState:state]; } else { dispatch_main_async_safe(^{ NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; if (completedBlock) { completedBlock(nil, error, SDImageCacheTypeNone, url); } }); } } - (void)sd_setImageLoadOperation:(id)operation forState:(UIControlState)state { [self sd_setImageLoadOperation:operation forKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]]; } - (void)sd_cancelImageLoadForState:(UIControlState)state { [self sd_cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]]; } - (void)sd_setBackgroundImageLoadOperation:(id)operation forState:(UIControlState)state { [self sd_setImageLoadOperation:operation forKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]]; } - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state { [self sd_cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]]; } - (NSMutableDictionary *)imageURLStorage { NSMutableDictionary *storage = objc_getAssociatedObject(self, &imageURLStorageKey); if (!storage) { storage = [NSMutableDictionary dictionary]; objc_setAssociatedObject(self, &imageURLStorageKey, storage, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return storage; } @end @implementation UIButton (WebCacheDeprecated) - (NSURL *)currentImageURL { return [self sd_currentImageURL]; } - (NSURL *)imageURLForState:(UIControlState)state { return [self sd_imageURLForState:state]; } - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state { [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil]; } - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder { [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil]; } - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil]; } - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil]; } - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil]; } - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil]; } - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)cancelCurrentImageLoad { // in a backwards compatible manner, cancel for current state [self sd_cancelImageLoadForState:self.state]; } - (void)cancelBackgroundImageLoadForState:(UIControlState)state { [self sd_cancelBackgroundImageLoadForState:state]; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIImage+GIF.h ================================================ // // UIImage+GIF.h // LBGIFImage // // Created by Laurin Brandner on 06.01.12. // Copyright (c) 2012 __MyCompanyName__. All rights reserved. // #import @interface UIImage (GIF) + (UIImage *)sd_animatedGIFNamed:(NSString *)name; + (UIImage *)sd_animatedGIFWithData:(NSData *)data; - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIImage+GIF.m ================================================ // // UIImage+GIF.m // LBGIFImage // // Created by Laurin Brandner on 06.01.12. // Copyright (c) 2012 __MyCompanyName__. All rights reserved. // #import "UIImage+GIF.h" #import @implementation UIImage (GIF) + (UIImage *)sd_animatedGIFWithData:(NSData *)data { if (!data) { return nil; } CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); size_t count = CGImageSourceGetCount(source); UIImage *animatedImage; if (count <= 1) { animatedImage = [[UIImage alloc] initWithData:data]; } else { NSMutableArray *images = [NSMutableArray array]; NSTimeInterval duration = 0.0f; for (size_t i = 0; i < count; i++) { CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); duration += [self sd_frameDurationAtIndex:i source:source]; [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]]; CGImageRelease(image); } if (!duration) { duration = (1.0f / 10.0f) * count; } animatedImage = [UIImage animatedImageWithImages:images duration:duration]; } CFRelease(source); return animatedImage; } + (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source { float frameDuration = 0.1f; CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil); NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties; NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary]; NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime]; if (delayTimeUnclampedProp) { frameDuration = [delayTimeUnclampedProp floatValue]; } else { NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime]; if (delayTimeProp) { frameDuration = [delayTimeProp floatValue]; } } // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify // a duration of <= 10 ms. See and // for more information. if (frameDuration < 0.011f) { frameDuration = 0.100f; } CFRelease(cfFrameProperties); return frameDuration; } + (UIImage *)sd_animatedGIFNamed:(NSString *)name { CGFloat scale = [UIScreen mainScreen].scale; if (scale > 1.0f) { NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"]; NSData *data = [NSData dataWithContentsOfFile:retinaPath]; if (data) { return [UIImage sd_animatedGIFWithData:data]; } NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; data = [NSData dataWithContentsOfFile:path]; if (data) { return [UIImage sd_animatedGIFWithData:data]; } return [UIImage imageNamed:name]; } else { NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; NSData *data = [NSData dataWithContentsOfFile:path]; if (data) { return [UIImage sd_animatedGIFWithData:data]; } return [UIImage imageNamed:name]; } } - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size { if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) { return self; } CGSize scaledSize = size; CGPoint thumbnailPoint = CGPointZero; CGFloat widthFactor = size.width / self.size.width; CGFloat heightFactor = size.height / self.size.height; CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor; scaledSize.width = self.size.width * scaleFactor; scaledSize.height = self.size.height * scaleFactor; if (widthFactor > heightFactor) { thumbnailPoint.y = (size.height - scaledSize.height) * 0.5; } else if (widthFactor < heightFactor) { thumbnailPoint.x = (size.width - scaledSize.width) * 0.5; } NSMutableArray *scaledImages = [NSMutableArray array]; for (UIImage *image in self.images) { UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); [scaledImages addObject:newImage]; UIGraphicsEndImageContext(); } return [UIImage animatedImageWithImages:scaledImages duration:self.duration]; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIImage+MultiFormat.h ================================================ // // UIImage+MultiFormat.h // SDWebImage // // Created by Olivier Poitrey on 07/06/13. // Copyright (c) 2013 Dailymotion. All rights reserved. // #import @interface UIImage (MultiFormat) + (UIImage *)sd_imageWithData:(NSData *)data; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIImage+MultiFormat.m ================================================ // // UIImage+MultiFormat.m // SDWebImage // // Created by Olivier Poitrey on 07/06/13. // Copyright (c) 2013 Dailymotion. All rights reserved. // #import "UIImage+MultiFormat.h" #import "UIImage+GIF.h" #import "NSData+ImageContentType.h" #import #ifdef SD_WEBP #import "UIImage+WebP.h" #endif @implementation UIImage (MultiFormat) + (UIImage *)sd_imageWithData:(NSData *)data { if (!data) { return nil; } UIImage *image; NSString *imageContentType = [NSData sd_contentTypeForImageData:data]; if ([imageContentType isEqualToString:@"image/gif"]) { image = [UIImage sd_animatedGIFWithData:data]; } #ifdef SD_WEBP else if ([imageContentType isEqualToString:@"image/webp"]) { image = [UIImage sd_imageWithWebPData:data]; } #endif else { image = [[UIImage alloc] initWithData:data]; UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data]; if (orientation != UIImageOrientationUp) { image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:orientation]; } } return image; } +(UIImageOrientation)sd_imageOrientationFromImageData:(NSData *)imageData { UIImageOrientation result = UIImageOrientationUp; CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); if (imageSource) { CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); if (properties) { CFTypeRef val; int exifOrientation; val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation); if (val) { CFNumberGetValue(val, kCFNumberIntType, &exifOrientation); result = [self sd_exifOrientationToiOSOrientation:exifOrientation]; } // else - if it's not set it remains at up CFRelease((CFTypeRef) properties); } else { //NSLog(@"NO PROPERTIES, FAIL"); } CFRelease(imageSource); } return result; } #pragma mark EXIF orientation tag converter // Convert an EXIF image orientation to an iOS one. // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation { UIImageOrientation orientation = UIImageOrientationUp; switch (exifOrientation) { case 1: orientation = UIImageOrientationUp; break; case 3: orientation = UIImageOrientationDown; break; case 8: orientation = UIImageOrientationLeft; break; case 6: orientation = UIImageOrientationRight; break; case 2: orientation = UIImageOrientationUpMirrored; break; case 4: orientation = UIImageOrientationDownMirrored; break; case 5: orientation = UIImageOrientationLeftMirrored; break; case 7: orientation = UIImageOrientationRightMirrored; break; default: break; } return orientation; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIImageView+HighlightedWebCache.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import #import "SDWebImageCompat.h" #import "SDWebImageManager.h" /** * Integrates SDWebImage async downloading and caching of remote images with UIImageView for highlighted state. */ @interface UIImageView (HighlightedWebCache) /** * Set the imageView `highlightedImage` with an `url`. * * The download is asynchronous and cached. * * @param url The url for the image. */ - (void)sd_setHighlightedImageWithURL:(NSURL *)url; /** * Set the imageView `highlightedImage` with an `url` and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. */ - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options; /** * Set the imageView `highlightedImage` with an `url`. * * The download is asynchronous and cached. * * @param url The url for the image. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the imageView `highlightedImage` with an `url` and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the imageView `highlightedImage` with an `url` and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. * @param progressBlock A block called while image is downloading * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; /** * Cancel the current download */ - (void)sd_cancelCurrentHighlightedImageLoad; @end @interface UIImageView (HighlightedWebCacheDeprecated) - (void)setHighlightedImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:`"); - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:`"); - (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:completed:`"); - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:completed:`"); - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:progress:completed:`"); - (void)cancelCurrentHighlightedImageLoad __deprecated_msg("Use `sd_cancelCurrentHighlightedImageLoad`"); @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIImageView+HighlightedWebCache.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "UIImageView+HighlightedWebCache.h" #import "UIView+WebCacheOperation.h" #define UIImageViewHighlightedWebCacheOperationKey @"highlightedImage" @implementation UIImageView (HighlightedWebCache) - (void)sd_setHighlightedImageWithURL:(NSURL *)url { [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil]; } - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options { [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil]; } - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:completedBlock]; } - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:completedBlock]; } - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { [self sd_cancelCurrentHighlightedImageLoad]; if (url) { __weak __typeof(self)wself = self; id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (!wself) return; dispatch_main_sync_safe (^ { if (!wself) return; if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) { completedBlock(image, error, cacheType, url); return; } else if (image) { wself.highlightedImage = image; [wself setNeedsLayout]; } if (completedBlock && finished) { completedBlock(image, error, cacheType, url); } }); }]; [self sd_setImageLoadOperation:operation forKey:UIImageViewHighlightedWebCacheOperationKey]; } else { dispatch_main_async_safe(^{ NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; if (completedBlock) { completedBlock(nil, error, SDImageCacheTypeNone, url); } }); } } - (void)sd_cancelCurrentHighlightedImageLoad { [self sd_cancelImageLoadOperationWithKey:UIImageViewHighlightedWebCacheOperationKey]; } @end @implementation UIImageView (HighlightedWebCacheDeprecated) - (void)setHighlightedImageWithURL:(NSURL *)url { [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil]; } - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options { [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil]; } - (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setHighlightedImageWithURL:url options:0 progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)cancelCurrentHighlightedImageLoad { [self sd_cancelCurrentHighlightedImageLoad]; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIImageView+WebCache.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDWebImageCompat.h" #import "SDWebImageManager.h" /** * Integrates SDWebImage async downloading and caching of remote images with UIImageView. * * Usage with a UITableViewCell sub-class: * * @code #import ... - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *MyIdentifier = @"MyIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease]; } // Here we use the provided sd_setImageWithURL: method to load the web image // Ensure you use a placeholder image otherwise cells will be initialized with no image [cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://example.com/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder"]]; cell.textLabel.text = @"My Text"; return cell; } * @endcode */ @interface UIImageView (WebCache) /** * Get the current image URL. * * Note that because of the limitations of categories this property can get out of sync * if you use sd_setImage: directly. */ - (NSURL *)sd_imageURL; /** * Set the imageView `image` with an `url`. * * The download is asynchronous and cached. * * @param url The url for the image. */ - (void)sd_setImageWithURL:(NSURL *)url; /** * Set the imageView `image` with an `url` and a placeholder. * * The download is asynchronous and cached. * * @param url The url for the image. * @param placeholder The image to be set initially, until the image request finishes. * @see sd_setImageWithURL:placeholderImage:options: */ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; /** * Set the imageView `image` with an `url`, placeholder and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param placeholder The image to be set initially, until the image request finishes. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. */ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options; /** * Set the imageView `image` with an `url`. * * The download is asynchronous and cached. * * @param url The url for the image. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the imageView `image` with an `url`, placeholder. * * The download is asynchronous and cached. * * @param url The url for the image. * @param placeholder The image to be set initially, until the image request finishes. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the imageView `image` with an `url`, placeholder and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param placeholder The image to be set initially, until the image request finishes. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the imageView `image` with an `url`, placeholder and custom options. * * The download is asynchronous and cached. * * @param url The url for the image. * @param placeholder The image to be set initially, until the image request finishes. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. * @param progressBlock A block called while image is downloading * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; /** * Set the imageView `image` with an `url` and optionally a placeholder image. * * The download is asynchronous and cached. * * @param url The url for the image. * @param placeholder The image to be set initially, until the image request finishes. * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. * @param progressBlock A block called while image is downloading * @param completedBlock A block called when operation has been completed. This block has no return value * and takes the requested UIImage as first parameter. In case of error the image parameter * is nil and the second parameter may contain an NSError. The third parameter is a Boolean * indicating if the image was retrieved from the local cache or from the network. * The fourth parameter is the original image url. */ - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; /** * Download an array of images and starts them in an animation loop * * @param arrayOfURLs An array of NSURL */ - (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs; /** * Cancel the current download */ - (void)sd_cancelCurrentImageLoad; - (void)sd_cancelCurrentAnimationImagesLoad; /** * Show activity UIActivityIndicatorView */ - (void)setShowActivityIndicatorView:(BOOL)show; /** * set desired UIActivityIndicatorViewStyle * * @param style The style of the UIActivityIndicatorView */ - (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style; @end @interface UIImageView (WebCacheDeprecated) - (NSURL *)imageURL __deprecated_msg("Use `sd_imageURL`"); - (void)setImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:`"); - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:`"); - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options`"); - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:completed:`"); - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:completed:`"); - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:completed:`"); - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:progress:completed:`"); - (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs __deprecated_msg("Use `sd_setAnimationImagesWithURLs:`"); - (void)cancelCurrentArrayLoad __deprecated_msg("Use `sd_cancelCurrentAnimationImagesLoad`"); - (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelCurrentImageLoad`"); @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIImageView+WebCache.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "UIImageView+WebCache.h" #import "objc/runtime.h" #import "UIView+WebCacheOperation.h" static char imageURLKey; static char TAG_ACTIVITY_INDICATOR; static char TAG_ACTIVITY_STYLE; static char TAG_ACTIVITY_SHOW; @implementation UIImageView (WebCache) - (void)sd_setImageWithURL:(NSURL *)url { [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil]; } - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder { [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil]; } - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil]; } - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock]; } - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock]; } - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock]; } - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { [self sd_cancelCurrentImageLoad]; objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC); if (!(options & SDWebImageDelayPlaceholder)) { dispatch_main_async_safe(^{ self.image = placeholder; }); } if (url) { // check if activityView is enabled or not if ([self showActivityIndicatorView]) { [self addActivityIndicator]; } __weak __typeof(self)wself = self; id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { [wself removeActivityIndicator]; if (!wself) return; dispatch_main_sync_safe(^{ if (!wself) return; if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) { completedBlock(image, error, cacheType, url); return; } else if (image) { wself.image = image; [wself setNeedsLayout]; } else { if ((options & SDWebImageDelayPlaceholder)) { wself.image = placeholder; [wself setNeedsLayout]; } } if (completedBlock && finished) { completedBlock(image, error, cacheType, url); } }); }]; [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"]; } else { dispatch_main_async_safe(^{ [self removeActivityIndicator]; if (completedBlock) { NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; completedBlock(nil, error, SDImageCacheTypeNone, url); } }); } } - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url]; UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key]; [self sd_setImageWithURL:url placeholderImage:lastPreviousCachedImage ?: placeholder options:options progress:progressBlock completed:completedBlock]; } - (NSURL *)sd_imageURL { return objc_getAssociatedObject(self, &imageURLKey); } - (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs { [self sd_cancelCurrentAnimationImagesLoad]; __weak __typeof(self)wself = self; NSMutableArray *operationsArray = [[NSMutableArray alloc] init]; for (NSURL *logoImageURL in arrayOfURLs) { id operation = [SDWebImageManager.sharedManager downloadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (!wself) return; dispatch_main_sync_safe(^{ __strong UIImageView *sself = wself; [sself stopAnimating]; if (sself && image) { NSMutableArray *currentImages = [[sself animationImages] mutableCopy]; if (!currentImages) { currentImages = [[NSMutableArray alloc] init]; } [currentImages addObject:image]; sself.animationImages = currentImages; [sself setNeedsLayout]; } [sself startAnimating]; }); }]; [operationsArray addObject:operation]; } [self sd_setImageLoadOperation:[NSArray arrayWithArray:operationsArray] forKey:@"UIImageViewAnimationImages"]; } - (void)sd_cancelCurrentImageLoad { [self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"]; } - (void)sd_cancelCurrentAnimationImagesLoad { [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"]; } #pragma mark - - (UIActivityIndicatorView *)activityIndicator { return (UIActivityIndicatorView *)objc_getAssociatedObject(self, &TAG_ACTIVITY_INDICATOR); } - (void)setActivityIndicator:(UIActivityIndicatorView *)activityIndicator { objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN); } - (void)setShowActivityIndicatorView:(BOOL)show{ objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, [NSNumber numberWithBool:show], OBJC_ASSOCIATION_RETAIN); } - (BOOL)showActivityIndicatorView{ return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue]; } - (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style{ objc_setAssociatedObject(self, &TAG_ACTIVITY_STYLE, [NSNumber numberWithInt:style], OBJC_ASSOCIATION_RETAIN); } - (int)getIndicatorStyle{ return [objc_getAssociatedObject(self, &TAG_ACTIVITY_STYLE) intValue]; } - (void)addActivityIndicator { if (!self.activityIndicator) { self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[self getIndicatorStyle]]; self.activityIndicator.translatesAutoresizingMaskIntoConstraints = NO; dispatch_main_async_safe(^{ [self addSubview:self.activityIndicator]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]]; }); } dispatch_main_async_safe(^{ [self.activityIndicator startAnimating]; }); } - (void)removeActivityIndicator { if (self.activityIndicator) { [self.activityIndicator removeFromSuperview]; self.activityIndicator = nil; } } @end @implementation UIImageView (WebCacheDeprecated) - (NSURL *)imageURL { return [self sd_imageURL]; } - (void)setImageWithURL:(NSURL *)url { [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil]; } - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder { [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil]; } - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil]; } - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock { [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { if (completedBlock) { completedBlock(image, error, cacheType); } }]; } - (void)cancelCurrentArrayLoad { [self sd_cancelCurrentAnimationImagesLoad]; } - (void)cancelCurrentImageLoad { [self sd_cancelCurrentImageLoad]; } - (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs { [self sd_setAnimationImagesWithURLs:arrayOfURLs]; } @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIView+WebCacheOperation.h ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import #import "SDWebImageManager.h" @interface UIView (WebCacheOperation) /** * Set the image load operation (storage in a UIView based dictionary) * * @param operation the operation * @param key key for storing the operation */ - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key; /** * Cancel all operations for the current UIView and key * * @param key key for identifying the operations */ - (void)sd_cancelImageLoadOperationWithKey:(NSString *)key; /** * Just remove the operations corresponding to the current UIView and key without cancelling them * * @param key key for identifying the operations */ - (void)sd_removeImageLoadOperationWithKey:(NSString *)key; @end ================================================ FILE: Pods/SDWebImage/SDWebImage/UIView+WebCacheOperation.m ================================================ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "UIView+WebCacheOperation.h" #import "objc/runtime.h" static char loadOperationKey; @implementation UIView (WebCacheOperation) - (NSMutableDictionary *)operationDictionary { NSMutableDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey); if (operations) { return operations; } operations = [NSMutableDictionary dictionary]; objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return operations; } - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key { [self sd_cancelImageLoadOperationWithKey:key]; NSMutableDictionary *operationDictionary = [self operationDictionary]; [operationDictionary setObject:operation forKey:key]; } - (void)sd_cancelImageLoadOperationWithKey:(NSString *)key { // Cancel in progress downloader from queue NSMutableDictionary *operationDictionary = [self operationDictionary]; id operations = [operationDictionary objectForKey:key]; if (operations) { if ([operations isKindOfClass:[NSArray class]]) { for (id operation in operations) { if (operation) { [operation cancel]; } } } else if ([operations conformsToProtocol:@protocol(SDWebImageOperation)]){ [(id) operations cancel]; } [operationDictionary removeObjectForKey:key]; } } - (void)sd_removeImageLoadOperationWithKey:(NSString *)key { NSMutableDictionary *operationDictionary = [self operationDictionary]; [operationDictionary removeObjectForKey:key]; } @end ================================================ FILE: Pods/SVProgressHUD/LICENSE.txt ================================================ Copyright (c) 2011-2016 Sam Vermette and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. A different license may apply to other resources included in this package, including Freepik Icons. Please consult their respective headers for the terms of their individual licenses. ================================================ FILE: Pods/SVProgressHUD/README.md ================================================ # SVProgressHUD ![Pod Version](https://img.shields.io/cocoapods/v/SVProgressHUD.svg?style=flat) ![Pod License](https://img.shields.io/cocoapods/l/SVProgressHUD.svg?style=flat) ![Pod Platform](https://img.shields.io/cocoapods/p/SVProgressHUD.svg?style=flat) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) `SVProgressHUD` is a clean and easy-to-use HUD meant to display the progress of an ongoing task on iOS and tvOS. ![SVProgressHUD](http://f.cl.ly/items/2G1F1Z0M0k0h2U3V1p39/SVProgressHUD.gif) ## Demo Try `SVProgressHUD` on [Appetize.io](https://appetize.io/app/p8r2cvy8kq74x7q7tjqf5gyatr). ## Installation ### From CocoaPods [CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like `SVProgressHUD` in your projects. First, add the following line to your [Podfile](http://guides.cocoapods.org/using/using-cocoapods.html): ```ruby pod 'SVProgressHUD' ``` If you want to use the latest features of `SVProgressHUD` add `:head`: ```ruby pod 'SVProgressHUD', :head ``` This pulls from the `master` branch directly. We are usually careful about what we push there and this is the version we use ourselves in all of our projects. Second, install `SVProgressHUD` into your project: ```ruby pod install ``` ### Carthage [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. You can install Carthage with [Homebrew](http://brew.sh/) using the following command: ```bash $ brew update $ brew install carthage ``` To integrate `SVProgressHUD` into your Xcode project using Carthage, specify it in your `Cartfile`: ```ogdl github "SVProgressHUD/SVProgressHUD" ``` Run `carthage update` to build the framework and drag the built `SVProgressHUD.framework` (in Carthage/Build/iOS folder) into your Xcode project (Linked Frameworks and Libraries in `Targets`). ### Manually * Drag the `SVProgressHUD/SVProgressHUD` folder into your project. * Take care that `SVProgressHUD.bundle` is added to `Targets->Build Phases->Copy Bundle Resources`. * Add the **QuartzCore** framework to your project. ## Usage (see sample Xcode project in `/Demo`) `SVProgressHUD` is created as a singleton (i.e. it doesn't need to be explicitly allocated and instantiated; you directly call `[SVProgressHUD method]`). **Use `SVProgressHUD` wisely! Only use it if you absolutely need to perform a task before taking the user forward. Bad use case examples: pull to refresh, infinite scrolling, sending message.** Using `SVProgressHUD` in your app will usually look as simple as this (using Grand Central Dispatch): ```objective-c [SVProgressHUD show]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // time-consuming task dispatch_async(dispatch_get_main_queue(), ^{ [SVProgressHUD dismiss]; }); }); ``` ### Showing the HUD You can show the status of indeterminate tasks using one of the following: ```objective-c + (void)show; + (void)showWithStatus:(NSString*)string; ``` If you'd like the HUD to reflect the progress of a task, use one of these: ```objective-c + (void)showProgress:(CGFloat)progress; + (void)showProgress:(CGFloat)progress status:(NSString*)status; ``` ### Dismissing the HUD The HUD can be dismissed using: ```objective-c + (void)dismiss; + (void)dismissWithDelay:(NSTimeInterval)delay; ``` If you'd like to stack HUDs, you can balance out every show call using: ```objective-c + (void)popActivity; ``` The HUD will get dismissed once the `popActivity` calls will match the number of show calls. Or show a confirmation glyph before before getting dismissed a little bit later. The display time depends on the length of the given string (between 0.5 and 5 seconds). ```objective-c + (void)showInfoWithStatus:(NSString *)string; + (void)showSuccessWithStatus:(NSString*)string; + (void)showErrorWithStatus:(NSString *)string; + (void)showImage:(UIImage*)image status:(NSString*)string; ``` ## Customization `SVProgressHUD` can be customized via the following methods: ```objective-c + (void)setDefaultStyle:(SVProgressHUDStyle)style; // default is SVProgressHUDStyleLight + (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType; // default is SVProgressHUDMaskTypeNone + (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type; // default is SVProgressHUDAnimationTypeFlat + (void)setMinimumSize:(CGSize)minimumSize; // default is CGSizeZero, can be used to avoid resizing for a larger message + (void)setRingThickness:(CGFloat)width; // default is 2 pt + (void)setRingRadius:(CGFloat)radius; // default is 18 pt + (void)setRingNoTextRadius:(CGFloat)radius; // default is 24 pt + (void)setCornerRadius:(CGFloat)cornerRadius; // default is 14 pt + (void)setFont:(UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] + (void)setForegroundColor:(UIColor*)color; // default is [UIColor blackColor], only used for SVProgressHUDStyleCustom + (void)setBackgroundColor:(UIColor*)color; // default is [UIColor whiteColor], only used for SVProgressHUDStyleCustom + (void)setInfoImage:(UIImage*)image; // default is the bundled info image provided by Freepik + (void)setSuccessImage:(UIImage*)image; // default is bundled success image from Freepik + (void)setErrorImage:(UIImage*)image; // default is bundled error image from Freepik + (void)setViewForExtension:(UIView*)view; // default is nil, only used if #define SV_APP_EXTENSIONS is set + (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval; // default is 5.0 seconds ``` Additionally `SVProgressHUD` supports the `UIAppearance` protocol for most of the above methods. ### Hint As standard `SVProgressHUD` offers two preconfigured styles: * `SVProgressHUDStyleLight`: White background with black spinner and text * `SVProgressHUDStyleDark`: Black background with white spinner and text If you want to use custom colors with `setForegroundColor` and `setBackgroundColor:` don't forget to set `SVProgressHUDStyleCustom` via `setDefaultStyle:`. ## Notifications `SVProgressHUD` posts four notifications via `NSNotificationCenter` in response to being shown/dismissed: * `SVProgressHUDWillAppearNotification` when the show animation starts * `SVProgressHUDDidAppearNotification` when the show animation completes * `SVProgressHUDWillDisappearNotification` when the dismiss animation starts * `SVProgressHUDDidDisappearNotification` when the dismiss animation completes Each notification passes a `userInfo` dictionary holding the HUD's status string (if any), retrievable via `SVProgressHUDStatusUserInfoKey`. `SVProgressHUD` also posts `SVProgressHUDDidReceiveTouchEventNotification` when users touch on the overall screen or `SVProgressHUDDidTouchDownInsideNotification` when a user touches on the HUD directly. For this notifications `userInfo` is not passed but the object parameter contains the `UIEvent` that related to the touch. ## App Extensions When using `SVProgressHUD` in an App Extension, `#define SV_APP_EXTENSIONS` to avoid using unavailable APIs. Additionally call `setViewForExtension:` from your extensions view controller with `self.view`. ## Contributing to this project If you have feature requests or bug reports, feel free to help out by sending pull requests or by [creating new issues](https://github.com/SVProgressHUD/SVProgressHUD/issues/new). Please take a moment to review the guidelines written by [Nicolas Gallagher](https://github.com/necolas/): * [Bug reports](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#bugs) * [Feature requests](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#features) * [Pull requests](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#pull-requests) ## License `SVProgressHUD` is distributed under the terms and conditions of the [MIT license](https://github.com/SVProgressHUD/SVProgressHUD/blob/master/LICENSE.txt). The success, error and info icons are made by [Freepik](http://www.freepik.com) from [Flaticon](http://www.flaticon.com) and are licensed under [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/). ## Credits `SVProgressHUD` is brought to you by [Sam Vermette](http://samvermette.com), [Tobias Tiemerding](http://tiemerding.com) and [contributors to the project](https://github.com/SVProgressHUD/SVProgressHUD/contributors). If you're using `SVProgressHUD` in your project, attribution would be very appreciated. T ================================================ FILE: Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.h ================================================ // // SVIndefiniteAnimatedView.h // SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD // // Copyright (c) 2014-2016 Guillaume Campagna. All rights reserved. // #import @interface SVIndefiniteAnimatedView : UIView @property (nonatomic, assign) CGFloat strokeThickness; @property (nonatomic, assign) CGFloat radius; @property (nonatomic, strong) UIColor *strokeColor; @end ================================================ FILE: Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.m ================================================ // // SVIndefiniteAnimatedView.m // SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD // // Copyright (c) 2014-2016 Guillaume Campagna. All rights reserved. // #import "SVIndefiniteAnimatedView.h" #import "SVProgressHUD.h" #pragma mark SVIndefiniteAnimatedView @interface SVIndefiniteAnimatedView () @property (nonatomic, strong) CAShapeLayer *indefiniteAnimatedLayer; @end @implementation SVIndefiniteAnimatedView - (void)willMoveToSuperview:(UIView *)newSuperview { if (newSuperview) { [self layoutAnimatedLayer]; } else { [_indefiniteAnimatedLayer removeFromSuperlayer]; _indefiniteAnimatedLayer = nil; } } - (void)layoutAnimatedLayer { CALayer *layer = self.indefiniteAnimatedLayer; [self.layer addSublayer:layer]; CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds); CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds); layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2); } - (CAShapeLayer*)indefiniteAnimatedLayer { if(!_indefiniteAnimatedLayer) { CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); CGRect rect = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat) (M_PI*3/2) endAngle:(CGFloat) (M_PI/2+M_PI*5) clockwise:YES]; _indefiniteAnimatedLayer = [CAShapeLayer layer]; _indefiniteAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; _indefiniteAnimatedLayer.frame = rect; _indefiniteAnimatedLayer.fillColor = [UIColor clearColor].CGColor; _indefiniteAnimatedLayer.strokeColor = self.strokeColor.CGColor; _indefiniteAnimatedLayer.lineWidth = self.strokeThickness; _indefiniteAnimatedLayer.lineCap = kCALineCapRound; _indefiniteAnimatedLayer.lineJoin = kCALineJoinBevel; _indefiniteAnimatedLayer.path = smoothedPath.CGPath; CALayer *maskLayer = [CALayer layer]; NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]]; NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; NSBundle *imageBundle = [NSBundle bundleWithURL:url]; NSString *path = [imageBundle pathForResource:@"angle-mask" ofType:@"png"]; maskLayer.contents = (__bridge id)[[UIImage imageWithContentsOfFile:path] CGImage]; maskLayer.frame = _indefiniteAnimatedLayer.bounds; _indefiniteAnimatedLayer.mask = maskLayer; NSTimeInterval animationDuration = 1; CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; animation.fromValue = (id) 0; animation.toValue = @(M_PI*2); animation.duration = animationDuration; animation.timingFunction = linearCurve; animation.removedOnCompletion = NO; animation.repeatCount = INFINITY; animation.fillMode = kCAFillModeForwards; animation.autoreverses = NO; [_indefiniteAnimatedLayer.mask addAnimation:animation forKey:@"rotate"]; CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; animationGroup.duration = animationDuration; animationGroup.repeatCount = INFINITY; animationGroup.removedOnCompletion = NO; animationGroup.timingFunction = linearCurve; CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; strokeStartAnimation.fromValue = @0.015; strokeStartAnimation.toValue = @0.515; CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; strokeEndAnimation.fromValue = @0.485; strokeEndAnimation.toValue = @0.985; animationGroup.animations = @[strokeStartAnimation, strokeEndAnimation]; [_indefiniteAnimatedLayer addAnimation:animationGroup forKey:@"progress"]; } return _indefiniteAnimatedLayer; } - (void)setFrame:(CGRect)frame { if(!CGRectEqualToRect(frame, super.frame)) { [super setFrame:frame]; if(self.superview) { [self layoutAnimatedLayer]; } } } - (void)setRadius:(CGFloat)radius { if(radius != _radius) { _radius = radius; [_indefiniteAnimatedLayer removeFromSuperlayer]; _indefiniteAnimatedLayer = nil; if(self.superview) { [self layoutAnimatedLayer]; } } } - (void)setStrokeColor:(UIColor *)strokeColor { _strokeColor = strokeColor; _indefiniteAnimatedLayer.strokeColor = strokeColor.CGColor; } - (void)setStrokeThickness:(CGFloat)strokeThickness { _strokeThickness = strokeThickness; _indefiniteAnimatedLayer.lineWidth = _strokeThickness; } - (CGSize)sizeThatFits:(CGSize)size { return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); } @end ================================================ FILE: Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.h ================================================ // // SVProgressHUD.h // SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD // // Copyright (c) 2011-2016 Sam Vermette and contributors. All rights reserved. // #import #import #if __IPHONE_OS_VERSION_MAX_ALLOWED < 70000 #define UI_APPEARANCE_SELECTOR #endif extern NSString * const SVProgressHUDDidReceiveTouchEventNotification; extern NSString * const SVProgressHUDDidTouchDownInsideNotification; extern NSString * const SVProgressHUDWillDisappearNotification; extern NSString * const SVProgressHUDDidDisappearNotification; extern NSString * const SVProgressHUDWillAppearNotification; extern NSString * const SVProgressHUDDidAppearNotification; extern NSString * const SVProgressHUDStatusUserInfoKey; typedef NS_ENUM(NSInteger, SVProgressHUDStyle) { SVProgressHUDStyleLight, // default style, white HUD with black text, HUD background will be blurred on iOS 8 and above SVProgressHUDStyleDark, // black HUD and white text, HUD background will be blurred on iOS 8 and above SVProgressHUDStyleCustom // uses the fore- and background color properties }; typedef NS_ENUM(NSUInteger, SVProgressHUDMaskType) { SVProgressHUDMaskTypeNone = 1, // default mask type, allow user interactions while HUD is displayed SVProgressHUDMaskTypeClear, // don't allow user interactions SVProgressHUDMaskTypeBlack, // don't allow user interactions and dim the UI in the back of the HUD, as on iOS 7 and above SVProgressHUDMaskTypeGradient // don't allow user interactions and dim the UI with a a-la UIAlertView background gradient, as on iOS 6 }; typedef NS_ENUM(NSUInteger, SVProgressHUDAnimationType) { SVProgressHUDAnimationTypeFlat, // default animation type, custom flat animation (indefinite animated ring) SVProgressHUDAnimationTypeNative // iOS native UIActivityIndicatorView }; @interface SVProgressHUD : UIView #pragma mark - Customization @property (assign, nonatomic) SVProgressHUDStyle defaultStyle UI_APPEARANCE_SELECTOR; // default is SVProgressHUDStyleLight @property (assign, nonatomic) SVProgressHUDMaskType defaultMaskType UI_APPEARANCE_SELECTOR; // default is SVProgressHUDMaskTypeNone @property (assign, nonatomic) SVProgressHUDAnimationType defaultAnimationType UI_APPEARANCE_SELECTOR; // default is SVProgressHUDAnimationTypeFlat @property (assign, nonatomic) CGSize minimumSize UI_APPEARANCE_SELECTOR; // default is CGSizeZero, can be used to avoid resizing for a larger message @property (assign, nonatomic) CGFloat ringThickness UI_APPEARANCE_SELECTOR; // default is 2 pt @property (assign, nonatomic) CGFloat ringRadius UI_APPEARANCE_SELECTOR; // default is 18 pt @property (assign, nonatomic) CGFloat ringNoTextRadius UI_APPEARANCE_SELECTOR; // default is 24 pt @property (assign, nonatomic) CGFloat cornerRadius UI_APPEARANCE_SELECTOR; // default is 14 pt @property (strong, nonatomic) UIFont *font UI_APPEARANCE_SELECTOR; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] @property (strong, nonatomic) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; // default is [UIColor whiteColor] @property (strong, nonatomic) UIColor *foregroundColor UI_APPEARANCE_SELECTOR; // default is [UIColor blackColor] @property (strong, nonatomic) UIImage *infoImage UI_APPEARANCE_SELECTOR; // default is the bundled info image provided by Freepik @property (strong, nonatomic) UIImage *successImage UI_APPEARANCE_SELECTOR; // default is the bundled success image provided by Freepik @property (strong, nonatomic) UIImage *errorImage UI_APPEARANCE_SELECTOR; // default is the bundled error image provided by Freepik @property (strong, nonatomic) UIView *viewForExtension UI_APPEARANCE_SELECTOR; // default is nil, only used if #define SV_APP_EXTENSIONS is set @property (assign, nonatomic) NSTimeInterval minimumDismissTimeInterval; // default is 5.0 seconds @property (assign, nonatomic) UIOffset offsetFromCenter UI_APPEARANCE_SELECTOR; // default is 0, 0 + (void)setDefaultStyle:(SVProgressHUDStyle)style; // default is SVProgressHUDStyleLight + (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType; // default is SVProgressHUDMaskTypeNone + (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type; // default is SVProgressHUDAnimationTypeFlat + (void)setMinimumSize:(CGSize)minimumSize; // default is CGSizeZero, can be used to avoid resizing for a larger message + (void)setRingThickness:(CGFloat)ringThickness; // default is 2 pt + (void)setRingRadius:(CGFloat)radius; // default is 18 pt + (void)setRingNoTextRadius:(CGFloat)radius; // default is 24 pt + (void)setCornerRadius:(CGFloat)cornerRadius; // default is 14 pt + (void)setFont:(UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] + (void)setForegroundColor:(UIColor*)color; // default is [UIColor blackColor], only used for SVProgressHUDStyleCustom + (void)setBackgroundColor:(UIColor*)color; // default is [UIColor whiteColor], only used for SVProgressHUDStyleCustom + (void)setInfoImage:(UIImage*)image; // default is the bundled info image provided by Freepik + (void)setSuccessImage:(UIImage*)image; // default is the bundled success image provided by Freepik + (void)setErrorImage:(UIImage*)image; // default is the bundled error image provided by Freepik + (void)setViewForExtension:(UIView*)view; // default is nil, only used if #define SV_APP_EXTENSIONS is set + (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval; // default is 5.0 seconds #pragma mark - Show Methods + (void)show; + (void)showWithMaskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use show and setDefaultMaskType: instead."))); + (void)showWithStatus:(NSString*)status; + (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showWithStatus: and setDefaultMaskType: instead."))); + (void)showProgress:(float)progress; + (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showProgress: and setDefaultMaskType: instead."))); + (void)showProgress:(float)progress status:(NSString*)status; + (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showProgress: and setDefaultMaskType: instead."))); + (void)setStatus:(NSString*)status; // change the HUD loading status while it's showing // stops the activity indicator, shows a glyph + status, and dismisses the HUD a little bit later + (void)showInfoWithStatus:(NSString*)status; + (void)showInfoWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showInfoWithStatus: and setDefaultMaskType: instead."))); + (void)showSuccessWithStatus:(NSString*)status; + (void)showSuccessWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showSuccessWithStatus: and setDefaultMaskType: instead."))); + (void)showErrorWithStatus:(NSString*)status; + (void)showErrorWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showErrorWithStatus: and setDefaultMaskType: instead."))); // shows a image + status, use 28x28 white PNGs + (void)showImage:(UIImage*)image status:(NSString*)status; + (void)showImage:(UIImage*)image status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showImage: and setDefaultMaskType: instead."))); + (void)setOffsetFromCenter:(UIOffset)offset; + (void)resetOffsetFromCenter; + (void)popActivity; // decrease activity count, if activity count == 0 the HUD is dismissed + (void)dismiss; + (void)dismissWithDelay:(NSTimeInterval)delay; + (void)dismissWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay; + (BOOL)isVisible; + (NSTimeInterval)displayDurationForString:(NSString*)string; @end ================================================ FILE: Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.m ================================================ // // SVProgressHUD.h // SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD // // Copyright (c) 2011-2016 Sam Vermette and contributors. All rights reserved. // #if !__has_feature(objc_arc) #error SVProgressHUD is ARC only. Either turn on ARC for the project or use -fobjc-arc flag #endif #import "SVProgressHUD.h" #import "SVIndefiniteAnimatedView.h" #import "SVRadialGradientLayer.h" NSString * const SVProgressHUDDidReceiveTouchEventNotification = @"SVProgressHUDDidReceiveTouchEventNotification"; NSString * const SVProgressHUDDidTouchDownInsideNotification = @"SVProgressHUDDidTouchDownInsideNotification"; NSString * const SVProgressHUDWillDisappearNotification = @"SVProgressHUDWillDisappearNotification"; NSString * const SVProgressHUDDidDisappearNotification = @"SVProgressHUDDidDisappearNotification"; NSString * const SVProgressHUDWillAppearNotification = @"SVProgressHUDWillAppearNotification"; NSString * const SVProgressHUDDidAppearNotification = @"SVProgressHUDDidAppearNotification"; NSString * const SVProgressHUDStatusUserInfoKey = @"SVProgressHUDStatusUserInfoKey"; static const CGFloat SVProgressHUDParallaxDepthPoints = 10; static const CGFloat SVProgressHUDUndefinedProgress = -1; static const CGFloat SVProgressHUDDefaultAnimationDuration = 0.15; @interface SVProgressHUD () @property (nonatomic, strong, readonly) NSTimer *fadeOutTimer; @property (nonatomic, readonly, getter = isClear) BOOL clear; @property (nonatomic, strong) UIControl *overlayView; @property (nonatomic, strong) UIView *hudView; @property (nonatomic, strong) UILabel *statusLabel; @property (nonatomic, strong) UIImageView *imageView; @property (nonatomic, strong) UIView *indefiniteAnimatedView; @property (nonatomic, strong) CALayer *backgroundLayer; @property (nonatomic, readwrite) CGFloat progress; @property (nonatomic, readwrite) NSUInteger activityCount; @property (nonatomic, strong) CAShapeLayer *backgroundRingLayer; @property (nonatomic, strong) CAShapeLayer *ringLayer; @property (nonatomic, readonly) CGFloat visibleKeyboardHeight; - (void)updateHUDFrame; - (void)updateMask; - (void)updateBlurBounds; #if TARGET_OS_IOS - (void)updateMotionEffectForOrientation:(UIInterfaceOrientation)orientation; #endif - (void)updateMotionEffectForXMotionEffectType:(UIInterpolatingMotionEffectType)xMotionEffectType yMotionEffectType:(UIInterpolatingMotionEffectType)yMotionEffectType; - (void)updateViewHierachy; - (void)setStatus:(NSString*)status; - (void)setFadeOutTimer:(NSTimer*)timer; - (void)registerNotifications; - (NSDictionary*)notificationUserInfo; - (void)positionHUD:(NSNotification*)notification; - (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle; - (void)overlayViewDidReceiveTouchEvent:(id)sender forEvent:(UIEvent*)event; - (void)showProgress:(float)progress status:(NSString*)status; - (void)showImage:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration; - (void)showStatus:(NSString *)status; - (void)dismissWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay; - (void)dismiss; - (UIView *)indefiniteAnimatedView; - (CAShapeLayer*)ringLayer; - (CAShapeLayer*)backgroundRingLayer; - (CAShapeLayer*)createRingLayerWithCenter:(CGPoint)center radius:(CGFloat)radius; - (void)cancelRingLayerAnimation; - (void)cancelIndefiniteAnimatedViewAnimation; - (UIColor*)foregroundColorForStyle; - (UIColor*)backgroundColorForStyle; - (UIImage*)image:(UIImage*)image withTintColor:(UIColor*)color; @end @implementation SVProgressHUD { BOOL _isInitializing; } + (SVProgressHUD*)sharedView { static dispatch_once_t once; static SVProgressHUD *sharedView; #if !defined(SV_APP_EXTENSIONS) dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[[UIApplication sharedApplication] delegate] window].bounds]; }); #else dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; }); #endif return sharedView; } #pragma mark - Setters + (void)setStatus:(NSString*)status { [[self sharedView] setStatus:status]; } + (void)setDefaultStyle:(SVProgressHUDStyle)style { [self sharedView].defaultStyle = style; } + (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType { [self sharedView].defaultMaskType = maskType; } + (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type { [self sharedView].defaultAnimationType = type; } + (void)setMinimumSize:(CGSize)minimumSize { [self sharedView].minimumSize = minimumSize; } + (void)setRingThickness:(CGFloat)ringThickness { [self sharedView].ringThickness = ringThickness; } + (void)setRingRadius:(CGFloat)radius { [self sharedView].ringRadius = radius; } + (void)setRingNoTextRadius:(CGFloat)radius { [self sharedView].ringNoTextRadius = radius; } + (void)setCornerRadius:(CGFloat)cornerRadius { [self sharedView].cornerRadius = cornerRadius; } + (void)setFont:(UIFont*)font { [self sharedView].font = font; } + (void)setForegroundColor:(UIColor*)color { [self sharedView].foregroundColor = color; } + (void)setBackgroundColor:(UIColor*)color { [self sharedView].backgroundColor = color; } + (void)setInfoImage:(UIImage*)image { [self sharedView].infoImage = image; } + (void)setSuccessImage:(UIImage *)image { [self sharedView].successImage = image; } + (void)setErrorImage:(UIImage *)image { [self sharedView].errorImage = image; } + (void)setViewForExtension:(UIView *)view { [self sharedView].viewForExtension = view; } + (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval { [self sharedView].minimumDismissTimeInterval = interval; } #pragma mark - Show Methods + (void)show { [self showWithStatus:nil]; } + (void)showWithMaskType:(SVProgressHUDMaskType)maskType { SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; [self setDefaultMaskType:maskType]; [self show]; [self setDefaultMaskType:existingMaskType]; } + (void)showWithStatus:(NSString*)status { [self sharedView]; [self showProgress:SVProgressHUDUndefinedProgress status:status]; } + (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; [self setDefaultMaskType:maskType]; [self showWithStatus:status]; [self setDefaultMaskType:existingMaskType]; } + (void)showProgress:(float)progress { [self showProgress:progress status:nil]; } + (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType { SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; [self setDefaultMaskType:maskType]; [self showProgress:progress]; [self setDefaultMaskType:existingMaskType]; } + (void)showProgress:(float)progress status:(NSString*)status { [[self sharedView] showProgress:progress status:status]; } + (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; [self setDefaultMaskType:maskType]; [self showProgress:progress status:status]; [self setDefaultMaskType:existingMaskType]; } #pragma mark - Show, then automatically dismiss methods + (void)showInfoWithStatus:(NSString*)status { [self showImage:[self sharedView].infoImage status:status]; } + (void)showInfoWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; [self setDefaultMaskType:maskType]; [self showInfoWithStatus:status]; [self setDefaultMaskType:existingMaskType]; } + (void)showSuccessWithStatus:(NSString*)status { [self showImage:[self sharedView].successImage status:status]; } + (void)showSuccessWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; [self setDefaultMaskType:maskType]; [self showSuccessWithStatus:status]; [self setDefaultMaskType:existingMaskType]; } + (void)showErrorWithStatus:(NSString*)status { [self showImage:[self sharedView].errorImage status:status]; } + (void)showErrorWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; [self setDefaultMaskType:maskType]; [self showErrorWithStatus:status]; [self setDefaultMaskType:existingMaskType]; } + (void)showImage:(UIImage*)image status:(NSString*)status { NSTimeInterval displayInterval = [self displayDurationForString:status]; [[self sharedView] showImage:image status:status duration:displayInterval]; } + (void)showImage:(UIImage*)image status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; [self setDefaultMaskType:maskType]; [self showImage:image status:status]; [self setDefaultMaskType:existingMaskType]; } #pragma mark - Dismiss Methods + (void)popActivity { if([self sharedView].activityCount > 0) { [self sharedView].activityCount--; } if([self sharedView].activityCount == 0) { [[self sharedView] dismiss]; } } + (void)dismiss { [self dismissWithDelay:0.0]; } + (void)dismissWithDelay:(NSTimeInterval)delay { [SVProgressHUD dismissWithDuration:SVProgressHUDDefaultAnimationDuration delay:delay]; } + (void)dismissWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay { if([self isVisible]) { [[self sharedView] dismissWithDuration:duration delay:delay]; } } #pragma mark - Offset + (void)setOffsetFromCenter:(UIOffset)offset { [self sharedView].offsetFromCenter = offset; } + (void)resetOffsetFromCenter { [self setOffsetFromCenter:UIOffsetZero]; } #pragma mark - Instance Methods - (instancetype)initWithFrame:(CGRect)frame { if((self = [super initWithFrame:frame])) { _isInitializing = YES; self.userInteractionEnabled = NO; _backgroundColor = [UIColor clearColor]; _foregroundColor = [UIColor blackColor]; self.alpha = 0.0f; self.activityCount = 0; // Set default values _defaultMaskType = SVProgressHUDMaskTypeNone; _defaultStyle = SVProgressHUDStyleLight; _defaultAnimationType = SVProgressHUDAnimationTypeFlat; if ([UIFont respondsToSelector:@selector(preferredFontForTextStyle:)]) { _font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; } else { _font = [UIFont systemFontOfSize:14.0f]; } NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]]; NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; NSBundle *imageBundle = [NSBundle bundleWithURL:url]; UIImage* infoImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"info" ofType:@"png"]]; UIImage* successImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"success" ofType:@"png"]]; UIImage* errorImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"error" ofType:@"png"]]; if ([[UIImage class] instancesRespondToSelector:@selector(imageWithRenderingMode:)]) { _infoImage = [infoImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; _successImage = [successImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; _errorImage = [errorImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; } else { _infoImage = infoImage; _successImage = successImage; _errorImage = errorImage; } _ringThickness = 2.0f; _ringRadius = 18.0f; _ringNoTextRadius = 24.0f; _cornerRadius = 14.0f; _minimumDismissTimeInterval = 5.0; // Accessibility support self.accessibilityIdentifier = @"SVProgressHUD"; self.accessibilityLabel = @"SVProgressHUD"; self.isAccessibilityElement = YES; _isInitializing = NO; } return self; } - (void)updateHUDFrame { // For the beginning use default values, these // might get update if string is too large etc. CGFloat hudWidth = 100.0f; CGFloat hudHeight = 100.0f; CGFloat stringHeightBuffer = 20.0f; CGFloat stringAndContentHeightBuffer = 80.0f; CGRect labelRect = CGRectZero; // Check if an image or progress ring is displayed BOOL imageUsed = (self.imageView.image) && !(self.imageView.hidden); BOOL progressUsed = self.imageView.hidden; // Calculate size of string and update HUD size NSString *string = self.statusLabel.text; if(string) { CGSize constraintSize = CGSizeMake(200.0f, 300.0f); CGRect stringRect; if([string respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) { stringRect = [string boundingRectWithSize:constraintSize options:(NSStringDrawingOptions)(NSStringDrawingUsesFontLeading|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin) attributes:@{NSFontAttributeName: self.statusLabel.font} context:NULL]; } else { CGSize stringSize; if([string respondsToSelector:@selector(sizeWithAttributes:)]) { stringSize = [string sizeWithAttributes:@{NSFontAttributeName:[UIFont fontWithName:self.statusLabel.font.fontName size:self.statusLabel.font.pointSize]}]; } else { #if TARGET_OS_IOS #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated" stringSize = [string sizeWithFont:self.statusLabel.font constrainedToSize:CGSizeMake(200.0f, 300.0f)]; #pragma clang diagnostic pop #endif } stringRect = CGRectMake(0.0f, 0.0f, stringSize.width, stringSize.height); } CGFloat stringWidth = stringRect.size.width; CGFloat stringHeight = ceilf(CGRectGetHeight(stringRect)); if(imageUsed || progressUsed) { hudHeight = stringAndContentHeightBuffer + stringHeight; } else { hudHeight = stringHeightBuffer + stringHeight; } if(stringWidth > hudWidth) { hudWidth = ceilf(stringWidth/2)*2; } CGFloat labelRectY = (imageUsed || progressUsed) ? 68.0f : 9.0f; if(hudHeight > 100.0f) { labelRect = CGRectMake(12.0f, labelRectY, hudWidth, stringHeight); hudWidth += 24.0f; } else { hudWidth += 24.0f; labelRect = CGRectMake(0.0f, labelRectY, hudWidth, stringHeight); } } // Update values on subviews self.hudView.bounds = CGRectMake(0.0f, 0.0f, MAX(self.minimumSize.width, hudWidth), MAX(self.minimumSize.height, hudHeight)); labelRect.size.width += MAX(0, self.minimumSize.width - hudWidth); [self updateBlurBounds]; if(string) { self.imageView.center = CGPointMake(CGRectGetWidth(self.hudView.bounds)/2, 36.0f); } else { self.imageView.center = CGPointMake(CGRectGetWidth(self.hudView.bounds)/2, CGRectGetHeight(self.hudView.bounds)/2); } self.statusLabel.hidden = NO; self.statusLabel.frame = labelRect; // Animate value update [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; if(string) { if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat) { SVIndefiniteAnimatedView *indefiniteAnimationView = (SVIndefiniteAnimatedView *)self.indefiniteAnimatedView; indefiniteAnimationView.radius = self.ringRadius; [indefiniteAnimationView sizeToFit]; } CGPoint center = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), 36.0f); self.indefiniteAnimatedView.center = center; if(self.progress != SVProgressHUDUndefinedProgress) { self.backgroundRingLayer.position = self.ringLayer.position = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), 36.0f); } } else { if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat) { SVIndefiniteAnimatedView *indefiniteAnimationView = (SVIndefiniteAnimatedView *)self.indefiniteAnimatedView; indefiniteAnimationView.radius = self.ringNoTextRadius; [indefiniteAnimationView sizeToFit]; } CGPoint center = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), CGRectGetHeight(self.hudView.bounds)/2); self.indefiniteAnimatedView.center = center; if(self.progress != SVProgressHUDUndefinedProgress) { self.backgroundRingLayer.position = self.ringLayer.position = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), CGRectGetHeight(self.hudView.bounds)/2); } } [CATransaction commit]; } - (void)updateMask { if(self.backgroundLayer) { [self.backgroundLayer removeFromSuperlayer]; self.backgroundLayer = nil; } switch (self.defaultMaskType) { case SVProgressHUDMaskTypeBlack:{ self.backgroundLayer = [CALayer layer]; self.backgroundLayer.frame = self.bounds; self.backgroundLayer.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5].CGColor; [self.backgroundLayer setNeedsDisplay]; [self.layer insertSublayer:self.backgroundLayer atIndex:0]; break; } case SVProgressHUDMaskTypeGradient:{ SVRadialGradientLayer *layer = [SVRadialGradientLayer layer]; self.backgroundLayer = layer; self.backgroundLayer.frame = self.bounds; CGPoint gradientCenter = self.center; gradientCenter.y = (self.bounds.size.height - self.visibleKeyboardHeight)/2; layer.gradientCenter = gradientCenter; [self.backgroundLayer setNeedsDisplay]; [self.layer insertSublayer:self.backgroundLayer atIndex:0]; break; } default: break; } } - (void)updateBlurBounds { #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 if(NSClassFromString(@"UIBlurEffect") && self.defaultStyle != SVProgressHUDStyleCustom) { // Remove background color, else the effect would not work self.hudView.backgroundColor = [UIColor clearColor]; // Remove any old instances of UIVisualEffectViews for (UIView *subview in self.hudView.subviews) { if([subview isKindOfClass:[UIVisualEffectView class]]) { [subview removeFromSuperview]; } } if(self.backgroundColor != [UIColor clearColor]) { // Create blur effect UIBlurEffectStyle blurEffectStyle = self.defaultStyle == SVProgressHUDStyleDark ? UIBlurEffectStyleDark : UIBlurEffectStyleLight; UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:blurEffectStyle]; UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; blurEffectView.autoresizingMask = self.hudView.autoresizingMask; blurEffectView.frame = self.hudView.bounds; // Add vibrancy to the blur effect to make it more vivid UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect]; UIVisualEffectView *vibrancyEffectView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect]; vibrancyEffectView.autoresizingMask = blurEffectView.autoresizingMask; vibrancyEffectView.bounds = blurEffectView.bounds; [blurEffectView.contentView addSubview:vibrancyEffectView]; [self.hudView insertSubview:blurEffectView atIndex:0]; } } #endif } #if TARGET_OS_IOS - (void)updateMotionEffectForOrientation:(UIInterfaceOrientation)orientation { UIInterpolatingMotionEffectType xMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis : UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis; UIInterpolatingMotionEffectType yMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis : UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis; [self updateMotionEffectForXMotionEffectType:xMotionEffectType yMotionEffectType:yMotionEffectType]; } #endif - (void)updateMotionEffectForXMotionEffectType:(UIInterpolatingMotionEffectType)xMotionEffectType yMotionEffectType:(UIInterpolatingMotionEffectType)yMotionEffectType { if([self.hudView respondsToSelector:@selector(addMotionEffect:)]) { UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:xMotionEffectType]; effectX.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints); effectX.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints); UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:yMotionEffectType]; effectY.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints); effectY.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints); UIMotionEffectGroup *effectGroup = [[UIMotionEffectGroup alloc] init]; effectGroup.motionEffects = @[effectX, effectY]; // Clear old motion effect, then add new motion effects self.hudView.motionEffects = @[]; [self.hudView addMotionEffect:effectGroup]; } } - (void)updateViewHierachy { // Add the overlay (e.g. black, gradient) to the application window if necessary if(!self.overlayView.superview) { #if !defined(SV_APP_EXTENSIONS) // Default case: iterate over UIApplication windows NSEnumerator *frontToBackWindows = [UIApplication.sharedApplication.windows reverseObjectEnumerator]; for (UIWindow *window in frontToBackWindows) { BOOL windowOnMainScreen = window.screen == UIScreen.mainScreen; BOOL windowIsVisible = !window.hidden && window.alpha > 0; BOOL windowLevelNormal = window.windowLevel == UIWindowLevelNormal; if(windowOnMainScreen && windowIsVisible && windowLevelNormal) { [window addSubview:self.overlayView]; break; } } #else // If SVProgressHUD ist used inside an app extension add it to the given view if(self.viewForExtension) { [self.viewForExtension addSubview:self.overlayView]; } #endif } else { // The HUD is already on screen, but maybot not in front. Therefore // ensure that overlay will be on top of rootViewController (which may // be changed during runtime). [self.overlayView.superview bringSubviewToFront:self.overlayView]; } // Add self to the overlay view if(!self.superview){ [self.overlayView addSubview:self]; } if(!self.hudView.superview) { [self addSubview:self.hudView]; } } - (void)setStatus:(NSString*)status { self.statusLabel.text = status; [self updateHUDFrame]; } - (void)setFadeOutTimer:(NSTimer*)timer { if(_fadeOutTimer) { [_fadeOutTimer invalidate], _fadeOutTimer = nil; } if(timer) { _fadeOutTimer = timer; } } #pragma mark - Notifications and their handling - (void)registerNotifications { #if TARGET_OS_IOS [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(positionHUD:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; #endif [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(positionHUD:) name:UIApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(positionHUD:) name:UIKeyboardWillHideNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(positionHUD:) name:UIKeyboardDidHideNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(positionHUD:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(positionHUD:) name:UIKeyboardDidShowNotification object:nil]; } - (NSDictionary*)notificationUserInfo{ return (self.statusLabel.text ? @{SVProgressHUDStatusUserInfoKey : self.statusLabel.text} : nil); } - (void)positionHUD:(NSNotification*)notification { CGFloat keyboardHeight = 0.0f; double animationDuration = 0.0; #if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS self.frame = [[[UIApplication sharedApplication] delegate] window].bounds; UIInterfaceOrientation orientation = UIApplication.sharedApplication.statusBarOrientation; #elif !defined(SV_APP_EXTENSIONS) self.frame = [UIApplication sharedApplication].keyWindow.bounds; #else if (self.viewForExtension) { self.frame = self.viewForExtension.frame; } else { self.frame = UIScreen.mainScreen.bounds; } UIInterfaceOrientation orientation = CGRectGetWidth(self.frame) > CGRectGetHeight(self.frame) ? UIInterfaceOrientationLandscapeLeft : UIInterfaceOrientationPortrait; #endif // no transforms applied to window in iOS 8, but only if compiled with iOS 8 sdk as base sdk, otherwise system supports old rotation logic. BOOL ignoreOrientation = NO; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 if([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) { ignoreOrientation = YES; } #endif // Get keyboardHeight in regards to current state if(notification) { NSDictionary* keyboardInfo = [notification userInfo]; CGRect keyboardFrame = [keyboardInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; animationDuration = [keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; if(notification.name == UIKeyboardWillShowNotification || notification.name == UIKeyboardDidShowNotification) { keyboardHeight = CGRectGetWidth(keyboardFrame); #if TARGET_OS_IOS if(ignoreOrientation || UIInterfaceOrientationIsPortrait(orientation)) { keyboardHeight = CGRectGetHeight(keyboardFrame); } #endif } } else { keyboardHeight = self.visibleKeyboardHeight; } // Get the currently active frame of the display (depends on orientation) CGRect orientationFrame = self.bounds; #if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS CGRect statusBarFrame = UIApplication.sharedApplication.statusBarFrame; #else CGRect statusBarFrame = CGRectZero; #endif #if TARGET_OS_IOS if(!ignoreOrientation && UIInterfaceOrientationIsLandscape(orientation)) { float temp = CGRectGetWidth(orientationFrame); orientationFrame.size.width = CGRectGetHeight(orientationFrame); orientationFrame.size.height = temp; temp = CGRectGetWidth(statusBarFrame); statusBarFrame.size.width = CGRectGetHeight(statusBarFrame); statusBarFrame.size.height = temp; } // Update the motion effects in regards to orientation [self updateMotionEffectForOrientation:orientation]; #else [self updateMotionEffectForXMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis yMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; #endif // Calculate available height for display CGFloat activeHeight = CGRectGetHeight(orientationFrame); if(keyboardHeight > 0) { activeHeight += CGRectGetHeight(statusBarFrame)*2; } activeHeight -= keyboardHeight; CGFloat posX = CGRectGetWidth(orientationFrame)/2.0f; CGFloat posY = floorf(activeHeight*0.45f); CGFloat rotateAngle = 0.0; CGPoint newCenter = CGPointMake(posX, posY); // Update posX and posY in regards to orientation #if TARGET_OS_IOS if(!ignoreOrientation) { switch (orientation) { case UIInterfaceOrientationPortraitUpsideDown: rotateAngle = (CGFloat) M_PI; newCenter = CGPointMake(posX, CGRectGetHeight(orientationFrame)-posY); break; case UIInterfaceOrientationLandscapeLeft: rotateAngle = (CGFloat) (-M_PI/2.0f); newCenter = CGPointMake(posY, posX); break; case UIInterfaceOrientationLandscapeRight: rotateAngle = (CGFloat) (M_PI/2.0f); newCenter = CGPointMake(CGRectGetHeight(orientationFrame)-posY, posX); break; default: // Same as UIInterfaceOrientationPortrait rotateAngle = 0.0f; newCenter = CGPointMake(posX, posY); break; } } #endif if(notification) { // Animate update if notification was present __weak SVProgressHUD *weakSelf = self; [UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{ __strong SVProgressHUD *strongSelf = weakSelf; if(strongSelf) { [strongSelf moveToPoint:newCenter rotateAngle:rotateAngle]; [strongSelf.hudView setNeedsDisplay]; } } completion:NULL]; } else { [self moveToPoint:newCenter rotateAngle:rotateAngle]; [self.hudView setNeedsDisplay]; } [self updateMask]; } - (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle { self.hudView.transform = CGAffineTransformMakeRotation(angle); self.hudView.center = CGPointMake(newCenter.x + self.offsetFromCenter.horizontal, newCenter.y + self.offsetFromCenter.vertical); } #pragma mark - Event handling - (void)overlayViewDidReceiveTouchEvent:(id)sender forEvent:(UIEvent*)event { [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidReceiveTouchEventNotification object:self userInfo:[self notificationUserInfo]]; UITouch *touch = event.allTouches.anyObject; CGPoint touchLocation = [touch locationInView:self]; if(CGRectContainsPoint(self.hudView.frame, touchLocation)) { [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidTouchDownInsideNotification object:self userInfo:[self notificationUserInfo]]; } } #pragma mark - Master show/dismiss methods - (void)showProgress:(float)progress status:(NSString*)status { __weak SVProgressHUD *weakSelf = self; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ __strong SVProgressHUD *strongSelf = weakSelf; if(strongSelf){ // Update / Check view hierachy to ensure the HUD is visible [strongSelf updateViewHierachy]; // Reset imageView and fadeout timer if an image is currently displayed strongSelf.imageView.hidden = YES; strongSelf.imageView.image = nil; if(strongSelf.fadeOutTimer) { strongSelf.activityCount = 0; } strongSelf.fadeOutTimer = nil; // Update text and set progress to the given value strongSelf.statusLabel.text = status; strongSelf.progress = progress; // Choose the "right" indicator depending on the progress if(progress >= 0) { // Cancel the indefiniteAnimatedView, then show the ringLayer [strongSelf cancelIndefiniteAnimatedViewAnimation]; // Add ring to HUD and set progress [strongSelf.hudView.layer addSublayer:strongSelf.ringLayer]; [strongSelf.hudView.layer addSublayer:strongSelf.backgroundRingLayer]; strongSelf.ringLayer.strokeEnd = progress; // Updat the activity count if(progress == 0) { strongSelf.activityCount++; } } else { // Cancel the ringLayer animation, then show the indefiniteAnimatedView [strongSelf cancelRingLayerAnimation]; // Add indefiniteAnimatedView to HUD [strongSelf.hudView addSubview:strongSelf.indefiniteAnimatedView]; if([strongSelf.indefiniteAnimatedView respondsToSelector:@selector(startAnimating)]) { [(id)strongSelf.indefiniteAnimatedView startAnimating]; } // Update the activity count strongSelf.activityCount++; } // Show [strongSelf showStatus:status]; } }]; } - (void)showImage:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration { __weak SVProgressHUD *weakSelf = self; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ __strong SVProgressHUD *strongSelf = weakSelf; if(strongSelf){ // Update / Check view hierachy to ensure the HUD is visible [strongSelf updateViewHierachy]; // Reset progress and cancel any running animation strongSelf.progress = SVProgressHUDUndefinedProgress; [strongSelf cancelRingLayerAnimation]; [strongSelf cancelIndefiniteAnimatedViewAnimation]; // Update imageView UIColor *tintColor = strongSelf.foregroundColorForStyle; UIImage *tintedImage = image; if([strongSelf.imageView respondsToSelector:@selector(setTintColor:)]) { if (tintedImage.renderingMode != UIImageRenderingModeAlwaysTemplate) { tintedImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; } strongSelf.imageView.tintColor = tintColor; } else { tintedImage = [strongSelf image:image withTintColor:tintColor]; } strongSelf.imageView.image = tintedImage; strongSelf.imageView.hidden = NO; // Update text strongSelf.statusLabel.text = status; // Show [strongSelf showStatus:status]; // An image will dismissed automatically. Therefore we start a timer // which then will call dismiss after the predefined duration strongSelf.fadeOutTimer = [NSTimer timerWithTimeInterval:duration target:strongSelf selector:@selector(dismiss) userInfo:nil repeats:NO]; [[NSRunLoop mainRunLoop] addTimer:strongSelf.fadeOutTimer forMode:NSRunLoopCommonModes]; } }]; } - (void)showStatus:(NSString *)status { // Update the HUDs frame to the new content and position HUD [self updateHUDFrame]; [self positionHUD:nil]; // Update accesibilty as well as user interaction if(self.defaultMaskType != SVProgressHUDMaskTypeNone) { self.overlayView.userInteractionEnabled = YES; self.accessibilityLabel = status; self.isAccessibilityElement = YES; } else { self.overlayView.userInteractionEnabled = NO; self.hudView.accessibilityLabel = status; self.hudView.isAccessibilityElement = YES; } // Show overlay self.overlayView.backgroundColor = [UIColor clearColor]; // Show if not already visible (depending on alpha) if(self.alpha != 1.0f || self.hudView.alpha != 1.0f) { // Post notification to inform user [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillAppearNotification object:self userInfo:[self notificationUserInfo]]; // Zoom HUD a little to make a nice appear, pop up animation self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 1.3, 1.3); // Set initial values to handle iOS 7 and 8 UIToolbar which not answers well to hierarchy opacity change if(self.isClear) { self.alpha = 1.0f; self.hudView.alpha = 0.0f; } // Animate appearance __weak SVProgressHUD *weakSelf = self; [UIView animateWithDuration:SVProgressHUDDefaultAnimationDuration delay:0 options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState) animations:^{ __strong SVProgressHUD *strongSelf = weakSelf; if(strongSelf) { // Shrink to finish pop up animation strongSelf.hudView.transform = CGAffineTransformScale(strongSelf.hudView.transform, 1/1.3f, 1/1.3f); if(strongSelf.isClear) { // handle iOS 7 and 8 UIToolbar which not answers well to hierarchy opacity change strongSelf.hudView.alpha = 1.0f; } else { strongSelf.alpha = 1.0f; } } } completion:^(BOOL finished) { __strong SVProgressHUD *strongSelf = weakSelf; if(strongSelf) { // Register for notification (e.g. screen rotation) to update the view [strongSelf registerNotifications]; // Post notification to inform user [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidAppearNotification object:strongSelf userInfo:[strongSelf notificationUserInfo]]; } // Update accesibilty UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, status); }]; // Inform iOS to redraw the view hierachy [self setNeedsDisplay]; } } - (void)dismissWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay { // Dismiss if visible (depending on alpha) if(self.alpha != 0.0f || self.hudView.alpha != 0.0f){ // Post notification to inform user [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillDisappearNotification object:nil userInfo:[self notificationUserInfo]]; // Reset activitiy count self.activityCount = 0; // Animate appearance __weak SVProgressHUD *weakSelf = self; void (^animationsBlock)(void) = ^{ __strong SVProgressHUD *strongSelf = weakSelf; if(strongSelf){ strongSelf.hudView.transform = CGAffineTransformScale(self.hudView.transform, 0.8f, 0.8f); if(strongSelf.isClear){ // handle iOS 7 UIToolbar not answer well to hierarchy opacity change strongSelf.hudView.alpha = 0.0f; } else{ strongSelf.alpha = 0.0f; } } }; void (^completionBlock)(void) = ^{ __strong SVProgressHUD *strongSelf = weakSelf; if(strongSelf) { // Clean up view hierachy (overlays) [self.overlayView removeFromSuperview]; [self.hudView removeFromSuperview]; [self removeFromSuperview]; // Remove observer <=> we do not have to handle orientation changes etc. [[NSNotificationCenter defaultCenter] removeObserver:strongSelf]; // Post notification to inform user [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidDisappearNotification object:strongSelf userInfo:[strongSelf notificationUserInfo]]; // Tell the rootViewController to update the StatusBar appearance #if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS UIViewController *rootController = [[UIApplication sharedApplication] keyWindow].rootViewController; if([rootController respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { [rootController setNeedsStatusBarAppearanceUpdate]; } #endif } // Update accesibilty UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); }; if (duration > 0) { [UIView animateWithDuration:duration delay:delay options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) animations:^{ animationsBlock(); } completion:^(BOOL finished) { completionBlock(); }]; } else { animationsBlock(); completionBlock(); } } } - (void)dismiss { [self dismissWithDuration:SVProgressHUDDefaultAnimationDuration delay:0]; } #pragma mark - Ring progress animation - (UIView *)indefiniteAnimatedView { // Get the correct spinner for defaultAnimationType if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat){ // Check if spinner exists and is an object of different class if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[SVIndefiniteAnimatedView class]]){ [_indefiniteAnimatedView removeFromSuperview]; _indefiniteAnimatedView = nil; } if(!_indefiniteAnimatedView){ _indefiniteAnimatedView = [[SVIndefiniteAnimatedView alloc] initWithFrame:CGRectZero]; } // Update styling SVIndefiniteAnimatedView *indefiniteAnimatedView = (SVIndefiniteAnimatedView *)_indefiniteAnimatedView; indefiniteAnimatedView.strokeColor = self.foregroundColorForStyle; indefiniteAnimatedView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; indefiniteAnimatedView.strokeThickness = self.ringThickness; } else { // Check if spinner exists and is an object of different class if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[UIActivityIndicatorView class]]){ [_indefiniteAnimatedView removeFromSuperview]; _indefiniteAnimatedView = nil; } if(!_indefiniteAnimatedView){ _indefiniteAnimatedView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; } // Update styling UIActivityIndicatorView *activityIndicatorView = (UIActivityIndicatorView *)_indefiniteAnimatedView; activityIndicatorView.color = self.foregroundColorForStyle; } [_indefiniteAnimatedView sizeToFit]; return _indefiniteAnimatedView; } - (CAShapeLayer*)ringLayer { if(!_ringLayer) { CGPoint center = CGPointMake(CGRectGetWidth(self.hudView.frame)/2, CGRectGetHeight(self.hudView.frame)/2); _ringLayer = [self createRingLayerWithCenter:center radius:self.ringRadius]; _ringLayer.strokeColor = self.foregroundColorForStyle.CGColor; _ringLayer.lineWidth = self.ringThickness; } return _ringLayer; } - (CAShapeLayer*)backgroundRingLayer { if(!_backgroundRingLayer) { CGPoint center = CGPointMake(CGRectGetWidth(self.hudView.frame)/2, CGRectGetHeight(self.hudView.frame)/2); _backgroundRingLayer = [self createRingLayerWithCenter:center radius:self.ringRadius]; _backgroundRingLayer.strokeEnd = 1; _backgroundRingLayer.strokeColor = [self.foregroundColorForStyle colorWithAlphaComponent:0.1f].CGColor; _backgroundRingLayer.lineWidth = self.ringThickness; } return _backgroundRingLayer; } - (CAShapeLayer*)createRingLayerWithCenter:(CGPoint)center radius:(CGFloat)radius { UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius startAngle:(CGFloat) -M_PI_2 endAngle:(CGFloat) (M_PI + M_PI_2) clockwise:YES]; CAShapeLayer *slice = [CAShapeLayer layer]; slice.contentsScale = [[UIScreen mainScreen] scale]; slice.frame = CGRectMake(center.x-radius, center.y-radius, radius*2, radius*2); slice.fillColor = [UIColor clearColor].CGColor; slice.lineCap = kCALineCapRound; slice.lineJoin = kCALineJoinBevel; slice.path = smoothedPath.CGPath; return slice; } - (void)cancelRingLayerAnimation { // Stop animation [CATransaction begin]; [CATransaction setDisableActions:YES]; [_hudView.layer removeAllAnimations]; _ringLayer.strokeEnd = 0.0f; [CATransaction commit]; // Remove from view [self.ringLayer removeFromSuperlayer]; [self.backgroundRingLayer removeFromSuperlayer]; } - (void)cancelIndefiniteAnimatedViewAnimation { // Stop animation if([self.indefiniteAnimatedView respondsToSelector:@selector(stopAnimating)]) { [(id)self.indefiniteAnimatedView stopAnimating]; } // Remove from view [self.indefiniteAnimatedView removeFromSuperview]; } #pragma mark - Utilities + (BOOL)isVisible { return ([self sharedView].alpha == 1); } #pragma mark - Getters + (NSTimeInterval)displayDurationForString:(NSString*)string { return MIN((float)string.length * 0.06 + 0.5, [self sharedView].minimumDismissTimeInterval); } - (UIColor *)foregroundColorForStyle { if(self.defaultStyle == SVProgressHUDStyleLight) { return [UIColor blackColor]; } else if(self.defaultStyle == SVProgressHUDStyleDark) { return [UIColor whiteColor]; } else { return self.foregroundColor; } } - (UIColor *)backgroundColorForStyle { if(self.defaultStyle == SVProgressHUDStyleLight) { return [UIColor whiteColor]; } else if(self.defaultStyle == SVProgressHUDStyleDark) { return [UIColor blackColor]; } else { return self.backgroundColor; } } - (UIImage*)image:(UIImage*)image withTintColor:(UIColor*)color { CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height); UIGraphicsBeginImageContextWithOptions(rect.size, NO, image.scale); CGContextRef c = UIGraphicsGetCurrentContext(); [image drawInRect:rect]; CGContextSetFillColorWithColor(c, [color CGColor]); CGContextSetBlendMode(c, kCGBlendModeSourceAtop); CGContextFillRect(c, rect); UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return tintedImage; } - (BOOL)isClear { // used for iOS 7 and above return (self.defaultMaskType == SVProgressHUDMaskTypeClear || self.defaultMaskType == SVProgressHUDMaskTypeNone); } - (UIControl*)overlayView { if(!_overlayView) { #if !defined(SV_APP_EXTENSIONS) CGRect windowBounds = [[[UIApplication sharedApplication] delegate] window].bounds; _overlayView = [[UIControl alloc] initWithFrame:windowBounds]; #else _overlayView = [[UIControl alloc] initWithFrame:[UIScreen mainScreen].bounds]; #endif _overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _overlayView.backgroundColor = [UIColor clearColor]; [_overlayView addTarget:self action:@selector(overlayViewDidReceiveTouchEvent:forEvent:) forControlEvents:UIControlEventTouchDown]; } return _overlayView; } - (UIView*)hudView { if(!_hudView) { _hudView = [[UIView alloc] initWithFrame:CGRectZero]; _hudView.layer.cornerRadius = self.cornerRadius; _hudView.layer.masksToBounds = YES; _hudView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin; } _hudView.backgroundColor = self.backgroundColorForStyle; return _hudView; } - (UILabel*)statusLabel { if(!_statusLabel) { _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero]; _statusLabel.backgroundColor = [UIColor clearColor]; _statusLabel.adjustsFontSizeToFitWidth = YES; _statusLabel.textAlignment = NSTextAlignmentCenter; _statusLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; _statusLabel.numberOfLines = 0; } if(!_statusLabel.superview) { [self.hudView addSubview:_statusLabel]; } _statusLabel.textColor = self.foregroundColorForStyle; _statusLabel.font = self.font; return _statusLabel; } - (UIImageView*)imageView { if(!_imageView) { _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 28.0f, 28.0f)]; } if(!_imageView.superview) { [self.hudView addSubview:_imageView]; } return _imageView; } - (CGFloat)visibleKeyboardHeight { #if !defined(SV_APP_EXTENSIONS) UIWindow *keyboardWindow = nil; for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) { if(![[testWindow class] isEqual:[UIWindow class]]) { keyboardWindow = testWindow; break; } } for (__strong UIView *possibleKeyboard in [keyboardWindow subviews]) { if([possibleKeyboard isKindOfClass:NSClassFromString(@"UIPeripheralHostView")] || [possibleKeyboard isKindOfClass:NSClassFromString(@"UIKeyboard")]) { return CGRectGetHeight(possibleKeyboard.bounds); } else if([possibleKeyboard isKindOfClass:NSClassFromString(@"UIInputSetContainerView")]) { for (__strong UIView *possibleKeyboardSubview in [possibleKeyboard subviews]) { if([possibleKeyboardSubview isKindOfClass:NSClassFromString(@"UIInputSetHostView")]) { return CGRectGetHeight(possibleKeyboardSubview.bounds); } } } } #endif return 0; } #pragma mark - UIAppearance Setters - (void)setDefaultStyle:(SVProgressHUDStyle)style { if (!_isInitializing) _defaultStyle = style; } - (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType { if (!_isInitializing) _defaultMaskType = maskType; } - (void)setDefaultAnimationType:(SVProgressHUDAnimationType)animationType { if (!_isInitializing) _defaultAnimationType = animationType; } - (void)setMinimumSize:(CGSize)minimumSize { if (!_isInitializing) _minimumSize = minimumSize; } - (void)setRingThickness:(CGFloat)ringThickness { if (!_isInitializing) _ringThickness = ringThickness; } - (void)setRingRadius:(CGFloat)ringRadius { if (!_isInitializing) _ringRadius = ringRadius; } - (void)setRingNoTextRadius:(CGFloat)ringNoTextRadius { if (!_isInitializing) _ringNoTextRadius = ringNoTextRadius; } - (void)setCornerRadius:(CGFloat)cornerRadius { if (!_isInitializing) _cornerRadius = cornerRadius; } - (void)setFont:(UIFont *)font { if (!_isInitializing) _font = font; } - (void)setBackgroundColor:(UIColor *)color { if (!_isInitializing) _backgroundColor = color; } - (void)setForegroundColor:(UIColor *)color { if (!_isInitializing) _foregroundColor = color; } - (void)setInfoImage:(UIImage*)image { if (!_isInitializing) _infoImage = image; } - (void)setSuccessImage:(UIImage *)image { if (!_isInitializing) _successImage = image; } - (void)setErrorImage:(UIImage *)image { if (!_isInitializing) _errorImage = image; } - (void)setViewForExtension:(UIView *)view { if (!_isInitializing) _viewForExtension = view; } - (void)setOffsetFromCenter:(UIOffset)offset { if (!_isInitializing) _offsetFromCenter = offset; } - (void)setMinimumDismissTimeInterval:(NSTimeInterval)minimumDismissTimeInterval { if (!_isInitializing) _minimumDismissTimeInterval = minimumDismissTimeInterval; } @end ================================================ FILE: Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.h ================================================ // // SVRadialGradientLayer.h // SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD // // Copyright (c) 2014-2016 Tobias Tiemerding. All rights reserved. // #import @interface SVRadialGradientLayer : CALayer @property (nonatomic) CGPoint gradientCenter; @end ================================================ FILE: Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.m ================================================ // // SVRadialGradientLayer.m // SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD // // Copyright (c) 2014-2016 Tobias Tiemerding. All rights reserved. // #import "SVRadialGradientLayer.h" @implementation SVRadialGradientLayer - (void)drawInContext:(CGContextRef)context { size_t locationsCount = 2; CGFloat locations[2] = {0.0f, 1.0f}; CGFloat colors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount); CGColorSpaceRelease(colorSpace); float radius = MIN(self.bounds.size.width , self.bounds.size.height); CGContextDrawRadialGradient (context, gradient, self.gradientCenter, 0, self.gradientCenter, radius, kCGGradientDrawsAfterEndLocation); CGGradientRelease(gradient); } @end ================================================ FILE: Pods/Target Support Files/AFNetworking/AFNetworking-dummy.m ================================================ #import @interface PodsDummy_AFNetworking : NSObject @end @implementation PodsDummy_AFNetworking @end ================================================ FILE: Pods/Target Support Files/AFNetworking/AFNetworking-prefix.pch ================================================ #ifdef __OBJC__ #import #endif #ifndef TARGET_OS_IOS #define TARGET_OS_IOS TARGET_OS_IPHONE #endif #ifndef TARGET_OS_WATCH #define TARGET_OS_WATCH 0 #endif #ifndef TARGET_OS_TV #define TARGET_OS_TV 0 #endif ================================================ FILE: Pods/Target Support Files/AFNetworking/AFNetworking-umbrella.h ================================================ #import #import "AFNetworking.h" #import "AFHTTPSessionManager.h" #import "AFURLSessionManager.h" #import "AFNetworkReachabilityManager.h" #import "AFSecurityPolicy.h" #import "AFURLRequestSerialization.h" #import "AFURLResponseSerialization.h" #import "AFAutoPurgingImageCache.h" #import "AFImageDownloader.h" #import "AFNetworkActivityIndicatorManager.h" #import "UIActivityIndicatorView+AFNetworking.h" #import "UIButton+AFNetworking.h" #import "UIImage+AFNetworking.h" #import "UIImageView+AFNetworking.h" #import "UIKit+AFNetworking.h" #import "UIProgressView+AFNetworking.h" #import "UIRefreshControl+AFNetworking.h" #import "UIWebView+AFNetworking.h" FOUNDATION_EXPORT double AFNetworkingVersionNumber; FOUNDATION_EXPORT const unsigned char AFNetworkingVersionString[]; ================================================ FILE: Pods/Target Support Files/AFNetworking/AFNetworking.modulemap ================================================ framework module AFNetworking { umbrella header "AFNetworking-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/AFNetworking/AFNetworking.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/AFNetworking" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" OTHER_LDFLAGS = -framework "CoreGraphics" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/AFNetworking/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 3.0.4 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/DACircularProgress/DACircularProgress-dummy.m ================================================ #import @interface PodsDummy_DACircularProgress : NSObject @end @implementation PodsDummy_DACircularProgress @end ================================================ FILE: Pods/Target Support Files/DACircularProgress/DACircularProgress-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/DACircularProgress/DACircularProgress-umbrella.h ================================================ #import #import "DACircularProgressView.h" #import "DALabeledCircularProgressView.h" FOUNDATION_EXPORT double DACircularProgressVersionNumber; FOUNDATION_EXPORT const unsigned char DACircularProgressVersionString[]; ================================================ FILE: Pods/Target Support Files/DACircularProgress/DACircularProgress.modulemap ================================================ framework module DACircularProgress { umbrella header "DACircularProgress-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/DACircularProgress/DACircularProgress.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/DACircularProgress" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" OTHER_LDFLAGS = -framework "QuartzCore" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/DACircularProgress/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 2.3.1 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/MJExtension/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 3.0.10 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/MJExtension/MJExtension-dummy.m ================================================ #import @interface PodsDummy_MJExtension : NSObject @end @implementation PodsDummy_MJExtension @end ================================================ FILE: Pods/Target Support Files/MJExtension/MJExtension-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/MJExtension/MJExtension-umbrella.h ================================================ #import #import "MJExtension.h" #import "MJExtensionConst.h" #import "MJFoundation.h" #import "MJProperty.h" #import "MJPropertyKey.h" #import "MJPropertyType.h" #import "NSObject+MJClass.h" #import "NSObject+MJCoding.h" #import "NSObject+MJKeyValue.h" #import "NSObject+MJProperty.h" #import "NSString+MJExtension.h" FOUNDATION_EXPORT double MJExtensionVersionNumber; FOUNDATION_EXPORT const unsigned char MJExtensionVersionString[]; ================================================ FILE: Pods/Target Support Files/MJExtension/MJExtension.modulemap ================================================ framework module MJExtension { umbrella header "MJExtension-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/MJExtension/MJExtension.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MJExtension" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/MJRefresh/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 3.1.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/MJRefresh/MJRefresh-dummy.m ================================================ #import @interface PodsDummy_MJRefresh : NSObject @end @implementation PodsDummy_MJRefresh @end ================================================ FILE: Pods/Target Support Files/MJRefresh/MJRefresh-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/MJRefresh/MJRefresh-umbrella.h ================================================ #import #import "MJRefreshAutoFooter.h" #import "MJRefreshBackFooter.h" #import "MJRefreshComponent.h" #import "MJRefreshFooter.h" #import "MJRefreshHeader.h" #import "MJRefreshAutoGifFooter.h" #import "MJRefreshAutoNormalFooter.h" #import "MJRefreshAutoStateFooter.h" #import "MJRefreshBackGifFooter.h" #import "MJRefreshBackNormalFooter.h" #import "MJRefreshBackStateFooter.h" #import "MJRefreshGifHeader.h" #import "MJRefreshNormalHeader.h" #import "MJRefreshStateHeader.h" #import "MJRefresh.h" #import "MJRefreshConst.h" #import "UIScrollView+MJExtension.h" #import "UIScrollView+MJRefresh.h" #import "UIView+MJExtension.h" FOUNDATION_EXPORT double MJRefreshVersionNumber; FOUNDATION_EXPORT const unsigned char MJRefreshVersionString[]; ================================================ FILE: Pods/Target Support Files/MJRefresh/MJRefresh.modulemap ================================================ framework module MJRefresh { umbrella header "MJRefresh-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/MJRefresh/MJRefresh.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MJRefresh" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/NJKWebViewProgress/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 0.2.3 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/NJKWebViewProgress/NJKWebViewProgress-dummy.m ================================================ #import @interface PodsDummy_NJKWebViewProgress : NSObject @end @implementation PodsDummy_NJKWebViewProgress @end ================================================ FILE: Pods/Target Support Files/NJKWebViewProgress/NJKWebViewProgress-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/NJKWebViewProgress/NJKWebViewProgress-umbrella.h ================================================ #import #import "NJKWebViewProgress.h" #import "NJKWebViewProgressView.h" FOUNDATION_EXPORT double NJKWebViewProgressVersionNumber; FOUNDATION_EXPORT const unsigned char NJKWebViewProgressVersionString[]; ================================================ FILE: Pods/Target Support Files/NJKWebViewProgress/NJKWebViewProgress.modulemap ================================================ framework module NJKWebViewProgress { umbrella header "NJKWebViewProgress-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/NJKWebViewProgress/NJKWebViewProgress.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/NJKWebViewProgress" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/Pods/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 1.0.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/Pods/Pods-acknowledgements.markdown ================================================ # Acknowledgements This application makes use of the following third party libraries: ## AFNetworking Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## DACircularProgress # License ## MIT License Copyright (c) 2013 Daniel Amitay (http://danielamitay.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## MJExtension Copyright (c) 2013-2015 MJExtension (https://github.com/CoderMJLee/MJExtension) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## MJRefresh Copyright (c) 2013-2015 MJRefresh (https://github.com/CoderMJLee/MJRefresh) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## NJKWebViewProgress The MIT License (MIT) Copyright (c) 2013 Satoshi Asano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## ReactiveCocoa **Copyright (c) 2012 - 2015, GitHub, Inc.** **All rights reserved.** Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Result The MIT License (MIT) Copyright (c) 2014 Rob Rix Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## SDWebImage Copyright (c) 2009 Olivier Poitrey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## SVProgressHUD Copyright (c) 2011-2016 Sam Vermette and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. A different license may apply to other resources included in this package, including Freepik Icons. Please consult their respective headers for the terms of their individual licenses. ## UMengSocial Copyright 2011 - 2015 UMeng.com. All rights reserved. Generated by CocoaPods - http://cocoapods.org ================================================ FILE: Pods/Target Support Files/Pods/Pods-acknowledgements.plist ================================================ PreferenceSpecifiers FooterText This application makes use of the following third party libraries: Title Acknowledgements Type PSGroupSpecifier FooterText Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title AFNetworking Type PSGroupSpecifier FooterText # License ## MIT License Copyright (c) 2013 Daniel Amitay (http://danielamitay.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title DACircularProgress Type PSGroupSpecifier FooterText Copyright (c) 2013-2015 MJExtension (https://github.com/CoderMJLee/MJExtension) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title MJExtension Type PSGroupSpecifier FooterText Copyright (c) 2013-2015 MJRefresh (https://github.com/CoderMJLee/MJRefresh) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title MJRefresh Type PSGroupSpecifier FooterText The MIT License (MIT) Copyright (c) 2013 Satoshi Asano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title NJKWebViewProgress Type PSGroupSpecifier FooterText **Copyright (c) 2012 - 2015, GitHub, Inc.** **All rights reserved.** Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title ReactiveCocoa Type PSGroupSpecifier FooterText The MIT License (MIT) Copyright (c) 2014 Rob Rix Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title Result Type PSGroupSpecifier FooterText Copyright (c) 2009 Olivier Poitrey <rs@dailymotion.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title SDWebImage Type PSGroupSpecifier FooterText Copyright (c) 2011-2016 Sam Vermette and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. A different license may apply to other resources included in this package, including Freepik Icons. Please consult their respective headers for the terms of their individual licenses. Title SVProgressHUD Type PSGroupSpecifier FooterText Copyright 2011 - 2015 UMeng.com. All rights reserved. Title UMengSocial Type PSGroupSpecifier FooterText Generated by CocoaPods - http://cocoapods.org Title Type PSGroupSpecifier StringsTable Acknowledgements Title Acknowledgements ================================================ FILE: Pods/Target Support Files/Pods/Pods-dummy.m ================================================ #import @interface PodsDummy_Pods : NSObject @end @implementation PodsDummy_Pods @end ================================================ FILE: Pods/Target Support Files/Pods/Pods-frameworks.sh ================================================ #!/bin/sh set -e echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then local source="${BUILT_PRODUCTS_DIR}/$1" elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" elif [ -r "$1" ]; then local source="$1" fi local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" if [ -L "${source}" ]; then echo "Symlinked..." source="$(readlink "${source}")" fi # use filter instead of exclude so missing patterns dont' throw errors echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" local basename basename="$(basename -s .framework "$1")" binary="${destination}/${basename}.framework/${basename}" if ! [ -r "$binary" ]; then binary="${destination}/${basename}" fi # Strip invalid architectures so "fat" simulator / device frameworks work on device if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then strip_invalid_archs "$binary" fi # Resign the code if required by the build settings to avoid unstable apps code_sign_if_enabled "${destination}/$(basename "$1")" # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then local swift_runtime_libs swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) for lib in $swift_runtime_libs; do echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" code_sign_if_enabled "${destination}/${lib}" done fi } # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then # Use the current code_sign_identitiy echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" fi } # Strip invalid architectures strip_invalid_archs() { binary="$1" # Get architectures for current file archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" stripped="" for arch in $archs; do if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" || exit 1 stripped="$stripped $arch" fi done if [[ "$stripped" ]]; then echo "Stripped $binary of architectures:$stripped" fi } if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "Pods/AFNetworking.framework" install_framework "Pods/DACircularProgress.framework" install_framework "Pods/MJExtension.framework" install_framework "Pods/MJRefresh.framework" install_framework "Pods/NJKWebViewProgress.framework" install_framework "Pods/ReactiveCocoa.framework" install_framework "Pods/Result.framework" install_framework "Pods/SDWebImage.framework" install_framework "Pods/SVProgressHUD.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then install_framework "Pods/AFNetworking.framework" install_framework "Pods/DACircularProgress.framework" install_framework "Pods/MJExtension.framework" install_framework "Pods/MJRefresh.framework" install_framework "Pods/NJKWebViewProgress.framework" install_framework "Pods/ReactiveCocoa.framework" install_framework "Pods/Result.framework" install_framework "Pods/SDWebImage.framework" install_framework "Pods/SVProgressHUD.framework" fi ================================================ FILE: Pods/Target Support Files/Pods/Pods-resources.sh ================================================ #!/bin/sh set -e mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt > "$RESOURCES_TO_COPY" XCASSET_FILES=() realpath() { DIRECTORY="$(cd "${1%/*}" && pwd)" FILENAME="${1##*/}" echo "$DIRECTORY/$FILENAME" } install_resource() { case $1 in *.storyboard) echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" ;; *.xib) echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" ;; *.framework) echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" ;; *.xcdatamodel) echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" ;; *.xcdatamodeld) echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" ;; *.xcmappingmodel) echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" ;; *.xcassets) ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; /*) echo "$1" echo "$1" >> "$RESOURCES_TO_COPY" ;; *) echo "${PODS_ROOT}/$1" echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" ;; esac } if [[ "$CONFIGURATION" == "Debug" ]]; then install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/UMSocialSDKResourcesNew.bundle" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenApi_IOS_Bundle.bundle" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WeiboSDK.bundle" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentDetailController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentInputController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentInputControlleriPad.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMShareEditViewController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMShareEditViewControlleriPad.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSLoginViewController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSnsAccountViewController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSShareListController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/en.lproj" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/zh-Hans.lproj" fi if [[ "$CONFIGURATION" == "Release" ]]; then install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/UMSocialSDKResourcesNew.bundle" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenApi_IOS_Bundle.bundle" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WeiboSDK.bundle" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentDetailController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentInputController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentInputControlleriPad.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMShareEditViewController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMShareEditViewControlleriPad.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSLoginViewController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSnsAccountViewController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSShareListController.xib" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/en.lproj" install_resource "UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/zh-Hans.lproj" fi mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi rm -f "$RESOURCES_TO_COPY" if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] then case "${TARGETED_DEVICE_FAMILY}" in 1,2) TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" ;; 1) TARGET_DEVICE_ARGS="--target-device iphone" ;; 2) TARGET_DEVICE_ARGS="--target-device ipad" ;; *) TARGET_DEVICE_ARGS="--target-device mac" ;; esac # Find all other xcassets (this unfortunately includes those of path pods and other targets). OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) while read line; do if [[ $line != "`realpath $PODS_ROOT`*" ]]; then XCASSET_FILES+=("$line") fi done <<<"$OTHER_XCASSETS" printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi ================================================ FILE: Pods/Target Support Files/Pods/Pods-umbrella.h ================================================ #import FOUNDATION_EXPORT double PodsVersionNumber; FOUNDATION_EXPORT const unsigned char PodsVersionString[]; ================================================ FILE: Pods/Target Support Files/Pods/Pods.debug.xcconfig ================================================ EMBEDDED_CONTENT_CONTAINS_SWIFT = YES FRAMEWORK_SEARCH_PATHS = $(inherited) $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/ $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/ $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' LIBRARY_SEARCH_PATHS = $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/ $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Wechat/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/AlipayShare/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Sina/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Line/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Whatsapp/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Instagram/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Tumblr/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/LaiWang/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/** OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DACircularProgress.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/MJExtension.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/MJRefresh.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NJKWebViewProgress.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/ReactiveCocoa.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Result.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/SDWebImage.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/SVProgressHUD.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/UMengSocial" OTHER_LDFLAGS = $(inherited) -l"APOpenSdk" -l"SocialAlipayShare" -l"SocialFacebook" -l"SocialInstagram" -l"SocialLaiWang" -l"SocialLine" -l"SocialQQ" -l"SocialSina" -l"SocialSinaSSO" -l"SocialTumblr" -l"SocialTwitter" -l"SocialWechat" -l"SocialWhatsapp" -l"UMSocial_Sdk_4.4" -l"UMSocial_Sdk_Comment_4.4" -l"WeChatSDK" -l"WeiboSDK" -l"iconv" -l"sqlite3" -l"stdc++" -l"z" -framework "AFNetworking" -framework "Accounts" -framework "CoreData" -framework "CoreGraphics" -framework "CoreTelephony" -framework "DACircularProgress" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "Fabric" -framework "ImageIO" -framework "MJExtension" -framework "MJRefresh" -framework "MobileCoreServices" -framework "NJKWebViewProgress" -framework "ReactiveCocoa" -framework "Result" -framework "SDWebImage" -framework "SVProgressHUD" -framework "Social" -framework "SystemConfiguration" -framework "TencentOpenAPI" -framework "TwitterCore" -framework "TwitterKit" OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods PODS_ROOT = ${SRCROOT}/Pods ================================================ FILE: Pods/Target Support Files/Pods/Pods.modulemap ================================================ framework module Pods { umbrella header "Pods-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/Pods/Pods.release.xcconfig ================================================ EMBEDDED_CONTENT_CONTAINS_SWIFT = YES FRAMEWORK_SEARCH_PATHS = $(inherited) $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/ $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/ $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' LIBRARY_SEARCH_PATHS = $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/ $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Wechat/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/AlipayShare/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Sina/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Line/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Whatsapp/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Instagram/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Tumblr/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/LaiWang/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/** $(PODS_ROOT)/UmengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/** OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/DACircularProgress.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/MJExtension.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/MJRefresh.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NJKWebViewProgress.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/ReactiveCocoa.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Result.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/SDWebImage.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/SVProgressHUD.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/UMengSocial" OTHER_LDFLAGS = $(inherited) -l"APOpenSdk" -l"SocialAlipayShare" -l"SocialFacebook" -l"SocialInstagram" -l"SocialLaiWang" -l"SocialLine" -l"SocialQQ" -l"SocialSina" -l"SocialSinaSSO" -l"SocialTumblr" -l"SocialTwitter" -l"SocialWechat" -l"SocialWhatsapp" -l"UMSocial_Sdk_4.4" -l"UMSocial_Sdk_Comment_4.4" -l"WeChatSDK" -l"WeiboSDK" -l"iconv" -l"sqlite3" -l"stdc++" -l"z" -framework "AFNetworking" -framework "Accounts" -framework "CoreData" -framework "CoreGraphics" -framework "CoreTelephony" -framework "DACircularProgress" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "Fabric" -framework "ImageIO" -framework "MJExtension" -framework "MJRefresh" -framework "MobileCoreServices" -framework "NJKWebViewProgress" -framework "ReactiveCocoa" -framework "Result" -framework "SDWebImage" -framework "SVProgressHUD" -framework "Social" -framework "SystemConfiguration" -framework "TencentOpenAPI" -framework "TwitterCore" -framework "TwitterKit" OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods PODS_ROOT = ${SRCROOT}/Pods ================================================ FILE: Pods/Target Support Files/ReactiveCocoa/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 4.0.4-alpha-4 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa-dummy.m ================================================ #import @interface PodsDummy_ReactiveCocoa : NSObject @end @implementation PodsDummy_ReactiveCocoa @end ================================================ FILE: Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa-umbrella.h ================================================ #import #import "EXTKeyPathCoding.h" #import "EXTScope.h" #import "metamacros.h" #import "NSArray+RACSequenceAdditions.h" #import "NSData+RACSupport.h" #import "NSDictionary+RACSequenceAdditions.h" #import "NSEnumerator+RACSequenceAdditions.h" #import "NSFileHandle+RACSupport.h" #import "NSIndexSet+RACSequenceAdditions.h" #import "NSInvocation+RACTypeParsing.h" #import "NSNotificationCenter+RACSupport.h" #import "NSObject+RACDeallocating.h" #import "NSObject+RACDescription.h" #import "NSObject+RACKVOWrapper.h" #import "NSObject+RACLifting.h" #import "NSObject+RACPropertySubscribing.h" #import "NSObject+RACSelectorSignal.h" #import "NSOrderedSet+RACSequenceAdditions.h" #import "NSSet+RACSequenceAdditions.h" #import "NSString+RACKeyPathUtilities.h" #import "NSString+RACSequenceAdditions.h" #import "NSString+RACSupport.h" #import "NSURLConnection+RACSupport.h" #import "NSUserDefaults+RACSupport.h" #import "RACArraySequence.h" #import "RACBehaviorSubject.h" #import "RACBlockTrampoline.h" #import "RACChannel.h" #import "RACCommand.h" #import "RACCompoundDisposable.h" #import "RACDelegateProxy.h" #import "RACDisposable.h" #import "RACDynamicPropertySuperclass.h" #import "RACDynamicSequence.h" #import "RACDynamicSignal.h" #import "RACEagerSequence.h" #import "RACErrorSignal.h" #import "RACEvent.h" #import "RACGroupedSignal.h" #import "RACImmediateScheduler.h" #import "RACIndexSetSequence.h" #import "RACKVOChannel.h" #import "RACKVOProxy.h" #import "RACKVOTrampoline.h" #import "RACMulticastConnection.h" #import "RACPassthroughSubscriber.h" #import "RACQueueScheduler+Subclass.h" #import "RACQueueScheduler.h" #import "RACReplaySubject.h" #import "RACReturnSignal.h" #import "RACScheduler+Subclass.h" #import "RACScheduler.h" #import "RACScopedDisposable.h" #import "RACSequence.h" #import "RACSerialDisposable.h" #import "RACSignal+Operations.h" #import "RACSignal.h" #import "RACSignalSequence.h" #import "RACStream.h" #import "RACStringSequence.h" #import "RACSubject.h" #import "RACSubscriber.h" #import "RACSubscriptingAssignmentTrampoline.h" #import "RACSubscriptionScheduler.h" #import "RACTargetQueueScheduler.h" #import "RACTestScheduler.h" #import "RACTuple.h" #import "RACTupleSequence.h" #import "RACUnarySequence.h" #import "RACUnit.h" #import "RACValueTransformer.h" #import "ReactiveCocoa-Bridging-Header.h" #import "ReactiveCocoa.h" #import "MKAnnotationView+RACSignalSupport.h" #import "UIActionSheet+RACSignalSupport.h" #import "UIAlertView+RACSignalSupport.h" #import "UIBarButtonItem+RACCommandSupport.h" #import "UIButton+RACCommandSupport.h" #import "UICollectionReusableView+RACSignalSupport.h" #import "UIControl+RACSignalSupport.h" #import "UIControl+RACSignalSupportPrivate.h" #import "UIDatePicker+RACSignalSupport.h" #import "UIGestureRecognizer+RACSignalSupport.h" #import "UIImagePickerController+RACSignalSupport.h" #import "UIRefreshControl+RACCommandSupport.h" #import "UISegmentedControl+RACSignalSupport.h" #import "UISlider+RACSignalSupport.h" #import "UIStepper+RACSignalSupport.h" #import "UISwitch+RACSignalSupport.h" #import "UITableViewCell+RACSignalSupport.h" #import "UITableViewHeaderFooterView+RACSignalSupport.h" #import "UITextField+RACSignalSupport.h" #import "UITextView+RACSignalSupport.h" #import "RACObjCRuntime.h" FOUNDATION_EXPORT double ReactiveCocoaVersionNumber; FOUNDATION_EXPORT const unsigned char ReactiveCocoaVersionString[]; ================================================ FILE: Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa.modulemap ================================================ framework module ReactiveCocoa { umbrella header "ReactiveCocoa-umbrella.h" export * module * { export * } private header "RACMulticastConnection+Private.h" private header "RACScheduler+Private.h" private header "RACStream+Private.h" private header "RACSubscriber+Private.h" private header "EXTRuntimeExtensions.h" private header "RACEmptySequence.h" private header "RACEmptySignal.h" } ================================================ FILE: Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/ReactiveCocoa" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" OTHER_LDFLAGS = -framework "Foundation" -framework "UIKit" OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/Result/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 1.0.2 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/Result/Result-dummy.m ================================================ #import @interface PodsDummy_Result : NSObject @end @implementation PodsDummy_Result @end ================================================ FILE: Pods/Target Support Files/Result/Result-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/Result/Result-umbrella.h ================================================ #import FOUNDATION_EXPORT double ResultVersionNumber; FOUNDATION_EXPORT const unsigned char ResultVersionString[]; ================================================ FILE: Pods/Target Support Files/Result/Result.modulemap ================================================ framework module Result { umbrella header "Result-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/Result/Result.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Result" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/SDWebImage/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 3.7.5 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/SDWebImage/SDWebImage-dummy.m ================================================ #import @interface PodsDummy_SDWebImage : NSObject @end @implementation PodsDummy_SDWebImage @end ================================================ FILE: Pods/Target Support Files/SDWebImage/SDWebImage-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/SDWebImage/SDWebImage-umbrella.h ================================================ #import #import "NSData+ImageContentType.h" #import "SDImageCache.h" #import "SDWebImageCompat.h" #import "SDWebImageDecoder.h" #import "SDWebImageDownloader.h" #import "SDWebImageDownloaderOperation.h" #import "SDWebImageManager.h" #import "SDWebImageOperation.h" #import "SDWebImagePrefetcher.h" #import "UIButton+WebCache.h" #import "UIImage+GIF.h" #import "UIImage+MultiFormat.h" #import "UIImageView+HighlightedWebCache.h" #import "UIImageView+WebCache.h" #import "UIView+WebCacheOperation.h" FOUNDATION_EXPORT double SDWebImageVersionNumber; FOUNDATION_EXPORT const unsigned char SDWebImageVersionString[]; ================================================ FILE: Pods/Target Support Files/SDWebImage/SDWebImage.modulemap ================================================ framework module SDWebImage { umbrella header "SDWebImage-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/SDWebImage/SDWebImage.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/SDWebImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" OTHER_LDFLAGS = -framework "ImageIO" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/SVProgressHUD/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.cocoapods.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType FMWK CFBundleShortVersionString 2.0-beta8 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass ================================================ FILE: Pods/Target Support Files/SVProgressHUD/SVProgressHUD-dummy.m ================================================ #import @interface PodsDummy_SVProgressHUD : NSObject @end @implementation PodsDummy_SVProgressHUD @end ================================================ FILE: Pods/Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/SVProgressHUD/SVProgressHUD-umbrella.h ================================================ #import #import "SVIndefiniteAnimatedView.h" #import "SVProgressHUD.h" #import "SVRadialGradientLayer.h" FOUNDATION_EXPORT double SVProgressHUDVersionNumber; FOUNDATION_EXPORT const unsigned char SVProgressHUDVersionString[]; ================================================ FILE: Pods/Target Support Files/SVProgressHUD/SVProgressHUD.modulemap ================================================ framework module SVProgressHUD { umbrella header "SVProgressHUD-umbrella.h" export * module * { export * } } ================================================ FILE: Pods/Target Support Files/SVProgressHUD/SVProgressHUD.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/SVProgressHUD" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/UMengSocial" OTHER_LDFLAGS = -framework "QuartzCore" PODS_ROOT = ${SRCROOT} SKIP_INSTALL = YES ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocial.h ================================================ // // UMSocial.h // SocialSDK // // Created by Jiahuan Ye on 13-5-22. // Copyright (c) 2013年 Umeng. All rights reserved. // #import "UMSocialData.h" //分享内容类 #import "UMSocialDataService.h" //分享数据级接口类 #import "UMSocialControllerService.h" //分享界面级接口类 #import "UMSocialControllerServiceComment.h" //评论界面级接口类 #import "UMSocialAccountManager.h" //账户管理,和账户类 #import "UMSocialSnsPlatformManager.h" //平台管理,和平台类 #import "UMSocialSnsService.h" //提供快速分享 #import "UMSocialBar.h" //社会化操作栏 #import "UMSocialConfig.h" //sdk配置类 #import "UMSocialSnsData.h" //区分不同平台设置不同分享内容 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialAccountManager.h ================================================ // // UMSocialAccountManager.h // SocialSDK // // Created by yeahugo on 13-1-15. // Copyright (c) 2013年 Umeng. All rights reserved. // #import #import "UMSocialDataService.h" /** 用户微博账户对象,对象数据从授权账号所对应的微博平台获取 */ @interface UMSocialAccountEntity : NSObject /** 微博平台名称,例如"sina"、"tencent",定义在`UMSocialSnsPlatformManager.h` */ @property (nonatomic, copy) NSString *platformName; /** 用户昵称 */ @property (nonatomic, copy) NSString *userName; /** 用户在微博的id号 */ @property (nonatomic, copy) NSString *usid; /** 用户微博头像的url */ @property (nonatomic, copy) NSString *iconURL; /** 用户授权后得到的accessToken */ @property (nonatomic, copy) NSString *accessToken; /** 用户授权后得到的accessSecret */ @property (nonatomic, copy) NSString *accessSecret; /** 用户微博网址url */ @property (nonatomic, copy) NSString *profileURL; /** 是否首次授权,sdk内使用 */ @property (nonatomic) BOOL isFirstOauth; /** 添加已授权的腾讯微博和qq空间账号,需要用到的openId */ @property (nonatomic, copy) NSString *openId; /** 授权的过期时间 */ @property (nonatomic, retain) NSDate *expirationDate; /** 更新授权时间 */ @property (nonatomic, retain) NSDate *refreshDate; /** 授权到微信用到的refreshToken */ @property (nonatomic, copy) NSString *refreshToken; /** 微信授权完成后得到的unionId */ @property (nonatomic, copy) NSString *unionId; /** 某些平台记录的应用Id */ @property (nonatomic, copy) NSString *appId; /** 授权项 */ @property (nonatomic, copy) NSArray *permissions; /** 非授权项 */ @property (nonatomic, copy) NSArray *dePermissions; /** 初始化方法 @param platformName 微博平台名 @return 初始化对象 */ -(id)initWithPlatformName:(NSString *)platformName; /** 把各属性编码成NSString @return 一个`NSString`对象 */ -(NSString *)description; @end /** 男性用户 */ extern NSString *const UMSCustomAccountGenderMale; /** 女性用户 */ extern NSString *const UMSCustomAccountGenderFeMale; /** 开发者自有账户对象,在app登录或者注册完成之后用用户名来初始化这样的对象,可以指定头像等,然后用`UMSocialAccountManager`来添加到友盟的账户体系上,使用我们的评论列表和个人中心的页面时就会显示自有账号的用户名和头像 */ @interface UMSocialCustomAccount : NSObject /** 用户名 */ @property (nonatomic, copy) NSString *userName; /** 用户id */ @property (nonatomic, copy) NSString *usid; /** 性别 */ @property (nonatomic, copy) NSString *gender; /** 生日 */ @property (nonatomic, retain) NSDate *birthday; /** 个人页面地址 */ @property (nonatomic, copy) NSString *profileUrl; /** 头像url */ @property (nonatomic, copy) NSString *iconUrl; /** 自定义数据 */ @property (nonatomic, retain) NSDictionary *customData; /** 初始化自定义用户 @param userName 用户名 @return 自定义用户对象 */ -(id)initWithUserName:(NSString *)userName; @end /** 账号管理,可以添加开发者应用的自有账号到友盟的账号体系,查询此sns平台是否授权等。 */ @interface UMSocialAccountManager : NSObject /** 存放用户在各个微博平台账户信息的哈希对象,以各个平台名为key,以`UMSocialAccountEntity`对象为value */ +(NSDictionary *)socialAccountDictionary; /** 添加自己获取到的sns账号,必须要有sns用户的usid和accessToken。添加成功后,需要调用`+(void)setSnsAccount:(UMSocialAccountEntity *)snsAccount; `把账户添加到本地缓存。 @param snsAccount 已经授权的sns账号对象 @param completion 回调Block对象 */ +(void)postSnsAccount:(UMSocialAccountEntity *)snsAccount completion:(UMSocialDataServiceCompletion)completion; /** 添加自有账号到友盟的账号体系,一般是用户在使用自有账号登录之后,再利用此方法上传账号,然后利用我们评论和个人中心的接口就会显示自有账号的昵称和头像等信息 @param customAccount 自有账号对象 @param completion 回调Block对象 */ +(void)postCustomAccount:(UMSocialCustomAccount *)customAccount completion:(UMSocialDataServiceCompletion)completion; /** 把自有账号添加到本地账号中 @param snsAccount 已经授权成功的账户对象 */ +(void)setSnsAccount:(UMSocialAccountEntity *)snsAccount; /** 判断是否登录,此登录包括以游客身份登录,如果已经登录评论编辑页面点击发送就不会提示登录。 */ + (BOOL)isLogin; /** 判断是否用sns账号来登录,即绑定一个sns账号作为登录账号,如果是的话,个人中心页面上半部分和评论列表即显示此用户名、头像。 */ + (BOOL)isLoginWithSnsAccount; /** 判断是否授权此sns平台,此方法不包含授权过期的情况,如果要在分享前判断是否授权并且token没有过期,需要用`isOauthAndTokenNotExpired`方法 @param platformType sns平台名,定义在`UMSocialSnsPlatformManager.h` */ + (BOOL)isOauthWithPlatform:(NSString *)platformType; /** 判断此平台是否授权,并且token没有过期 @param platformType sns平台名,定义在`UMSocialSnsPlatformManager.h` */ +(BOOL)isOauthAndTokenNotExpired:(NSString *)platformType; /** 判断是否以游客身份登录。游客身份的过程是用户进入登录页面,并且选以游客身份登录,如果用户选择其他平台登录或者没有进入登录页面都是非游客身份登录。 */ + (BOOL)isLoginWithAnonymous; /** 设置是否已经以游客身份来登录,如果以游客身份登录,评论会显示匿名和使用默认头像,如果没有使用游客身份,会弹出登录界面,选择一个sns平台作为登录账号之后再评论。 */ + (void)setIsLoginWithAnonymous:(BOOL)anonymous; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialBar.h ================================================ // // UMSocialBar.h // SocialSDK // // Created by yeahugo on 13-7-2. // Copyright (c) 2013年 Umeng. All rights reserved. // #import #import "UMSocialSnsPlatformManager.h" #import "UMSocialControllerServiceComment.h" /** 分享 */ extern NSString *const UMSocialShare; /** 喜欢 */ extern NSString *const UMSocialLike; /** 评论 */ extern NSString *const UMSocialComment; /** 个人中心 */ extern NSString *const UMSocialAccount; typedef void (^ClickHandler)(void); /** 代表平台或者功能的按钮 */ @interface UMSocialButton : UIButton /** 点击按钮之后的响应事件 */ @property (nonatomic, copy) ClickHandler clickHandler; /** 当前``对象,此对象可以获取到授权完成,关闭页面等状态,详情看`UMSocialUIDelegate`的定义 */ @property (nonatomic, assign) id socialUIDelegate; /** 按钮名称 */ @property (nonatomic, copy) NSString *buttonName; /** 按钮初始化方法 @param buttonName 按钮类型,可以指定`UMSocialShare`,`UMSocialComment`,`UMSocialLike`、`UMSocialAccount`分别代表分享、评论、喜欢、个人中心 或者`UMShareToSina`、`UMShareToTencent`等代表各个微博平台 @param socialData 数据对象,如果是评论或者喜欢,代表不同的评论、喜欢对象。可以传nil,使用默认数据对象 @param controller 分享编辑页面、评论页面等将弹到的UIViewController对象 */ -(id)initWithButtonName:(NSString *)buttonName socialData:(UMSocialData *)socialData controller:(UIViewController *)controller; /** 按钮初始化方法 @param buttonName 按钮类型,可以指定`UMSocialShare`,`UMSocialComment`,`UMSocialLike`、`UMSocialAccount`分别代表分享、评论、喜欢、个人中心 或者`UMShareToSina`、`UMShareToTencent`等代表各个微博平台 @param controllerService UMSocialControllerService对象,如果是评论或者喜欢,代表不同的评论、喜欢对象。可以传nil,使用默认数据对象 @param controller 分享编辑页面、评论页面等将弹到的UIViewController对象 */ -(id)initWithButtonName:(NSString *)buttonName controllerService:(UMSocialControllerServiceComment *)controllerService controller:(UIViewController *)controller; @end /** 社会化操作栏,默认集成了评论、喜欢、分享、个人中心等功能。 你可以根据你的需求对操作栏上的各个按钮进行定制,方法是修改barButtons数组。 */ @interface UMSocialBar : UIView /** 代表操作栏上所有按钮的数组,数组的元素是UMSocialButton对象。 你可以增加自定义的按钮,例如 ``` UMSocialButton *customButton = [[UMSocialButton alloc] initWithButtonType:@"custom" socialData:nil controller:nil]; customButton.clickHandler = ^(){ NSLog(@"click !!"); }; [customButton setImage:[UIImage imageNamed:@"icon"] forState:UIControlStateNormal]; [_socialBar.barButtons addObject:customButton]; ``` 你可以删除指定的按钮 ``` [_socialBar.barButtons removeObjectAtIndex:1]; ``` 可以修改指定按钮 ``` UMSocialButton *socialButton1 = [_socialBar.barButtons objectAtIndex:1]; socialButton1.clickHandler = ^(){ NSLog(@"click!!"); }; ``` */ @property (nonatomic, retain) NSMutableArray *barButtons; /** `UMSocialData`对象,可以通过该对象设置分享内嵌文字、图片,获取分享数等属性 */ @property (nonatomic, retain) UMSocialData *socialData; /** 当前``对象,此对象可以获取到授权完成,关闭页面等状态,详情看`UMSocialUIDelegate`的定义 */ @property (nonatomic, assign) id socialUIDelegate; /** 初始化方法 @param socialData 标识不同分享对象 @param viewController 分享编辑页面等弹出到的UIViewController对象 */ - (id)initWithUMSocialData:(UMSocialData *)socialData withViewController:(UIViewController *)viewController; /** 更新操作栏的数字 */ - (void)updateButtonNumber; /* 从线上获取分享、评论、喜欢等个数,更新按钮文字 */ - (void)requestUpdateButtonNumber; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialConfig.h ================================================ // // UMSConfigManager.h // SocialSDK // // Created by Jiahuan Ye on 12-9-15. // Copyright (c) umeng.com All rights reserved. // #import #import "UMSocialDataService.h" #ifndef __IPHONE_6_0 typedef enum { UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait), UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft), UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight), UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown), UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown), UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), } UIInterfaceOrientationMask; #endif typedef enum { UMSocialiToastPositionTop = 1000001, //提示位置在屏幕上部 UMSocialiToastPositionBottom, //提示位置在屏幕下部 UMSocialiToastPositionCenter //提示位置在屏幕中间 } UMSocialiToastPosition; /** SDK样式主题 */ typedef enum { UMSocialThemeBlack, //黑色主题 UMSocialThemeWhite //白色主题 } UMSocialTheme; /** 设置分享列表页面的Block类型 @param ref 分享列表绘图所用的CGContext对象 @param backgroundView 分享列表的背景图片 @param label 平台文字 */ typedef void (^UMGridViewConfig)(CGContextRef ref, UIImageView *backgroundView, UILabel *label) ; /** 设置导航栏的样式的Block类型 @param bar 导航栏 @param closeButton 关闭按钮 @param backButton 返回按钮 @param postButton 发送按钮 @param refreshButton 刷新按钮 @param navigationItem 所在UINavigationController的navigationItem,可以改变相应的标题 */ typedef void (^UMNavigationBarConfig)(UINavigationBar *bar, UIButton *closeButton, UIButton *backButton, UIButton *postButton, UIButton *refreshButton, UINavigationItem * navigationItem); /** 设置TableViewCell的样式 @param cell UITableViewCell @param viewControllerType 页面类型 */ typedef void (^UMTableViewCellConfig)(UITableViewCell *cell,UMSViewControllerType viewControllerType); /** SDK设置类,负责改变SDK功能配置 */ @interface UMSocialConfig : NSObject /** 设置显示的sns平台类型 @param platformNames 在`UMSocialSnsPlatformManager.h`定义的UMShareToSina、UMShareToTencent、UMShareToQzone、UMShareToRenren、UMShareToDouban、UMShareToEmail、UMShareToSms组成的NSArray */ + (void)setSnsPlatformNames:(NSArray *)platformNames; /** 设置sdk所有页面需要支持屏幕方向. @param interfaceOrientations 一个bit map(位掩码),ios 6定义的`UIInterfaceOrientationMask` */ + (void)setSupportedInterfaceOrientations:(UIInterfaceOrientationMask)interfaceOrientations; /** 设置社会化组件UI主题,现在有黑色和白色两种 @param theme UI主题 */ + (void) setTheme:(UMSocialTheme)theme; /** 设置分享列表页面,Block对象的形参包括有绘制当前线条的CGContex指针,icon背景视图 例如下面写法 ``` [UMSocialConfig setShareGridViewTheme:^(CGContextRef ref, UIImageView *backgroundView,UILabel *label){ //改变线颜色和线宽 CGContextSetRGBStrokeColor(ref, 0, 0, 0, 1.0); CGContextSetLineWidth(ref, 1.0); //改变背景颜色 backgroundView.backgroundColor = [UIColor blackColor]; //添加背景图片 UIImageView *imageView = [[UIImageView alloc] initWithFrame:backgroundView.frame]; imageView.image = [UIImage imageNamed:@"share_bg.png"]; [backgroundView addSubview:imageView]; backgroundView.backgroundColor = [UIColor clearColor]; //改变文字标题的文字颜色 label.textColor = [UIColor blueColor]; //隐藏文字 label.hidden = YES; }]; ``` @param gridViewConfig 设置分享列表样式的block对象 */ +(void)setShareGridViewTheme:(UMGridViewConfig)gridViewConfig; /** 设置导航栏,包括导航栏的UINavigationBar,返回按钮,关闭按钮,发送按钮,刷新按钮和中间的UINavigationItem的样式 例如下面写法: ``` [UMSocialConfig setNavigationBarConfig:^(UINavigationBar *bar, UIButton *closeButton, UIButton *backButton, UIButton *postButton, UIButton *refreshButton, UINavigationItem * navigationItem){ UIImage * backgroundImage = [UIImage imageNamed:@"UMSocialSDKResourcesNew.bundle/OtherTheme/UMS_nav_bar_bg"]; if ([bar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)]) { [bar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault]; } bar.titleTextAttributes = nil; }]; ``` @param navigationConfig 设置导航栏样式的block对象 navigationConfig 是一个Block对象,传入的参数包括: @param bar 导航栏 @param closeButton 关闭按钮 @param backButton 返回按钮 @param postButton 发送按钮 @param refreshButton 刷新按钮 @param navigationItem 所在UINavigationController的navigationItem,可以改变相应的标题 */ +(void)setNavigationBarConfig:(UMNavigationBarConfig)navigationConfig; /** 设置分享列表页,个人中心页面等的UITableViewCell的样式 @param tableViewCellConfig UITableViewCell的样式配置Block @param cell UITableViewCell @param viewControllerType 页面类型 */ +(void)setTableViewCellConfig:(UMTableViewCellConfig)tableViewCellConfig; /** 设置分享完成时“发送完成”或者分享错误等提示 @param isHidden 是否隐藏该提示 @param toastPosition 提示的位置,可以设置成在屏幕上部、中间、下部 */ +(void)setFinishToastIsHidden:(BOOL)isHidden position:(UMSocialiToastPosition)toastPosition; /** 设置官方微博账号,设置之后可以在授权页面有关注微博的选项,默认勾选,授权之后用户即关注官方微博,仅支持新浪微博和腾讯微博 @param weiboUids 腾讯微博和新浪微博的key分别是`UMShareToSina`和`UMShareToTenc`,值分别是官方微博的uid,例如`[UMSocialConfig setFollowWeiboUids:[NSDictionary dictionaryWithObjectsAndKeys:@"yourSinaUid",UMShareToSina,nil]];` */ + (void)setFollowWeiboUids:(NSDictionary *)weiboUids; /** 设置新增加`UMSocialSnsPlatform`对象 @param snsPlatformArray `UMSocialSnsPlatform`组成的数组对象 */ + (void)addSocialSnsPlatform:(NSArray *)snsPlatformArray; /** 设置页面的背景颜色 @param defaultColor 设置页面背景颜色 */ + (void)setDefaultColor:(UIColor *)defaultColor; /** 设置iPad页面的大小 @param size 页面大小 */ + (void)setBoundsSizeForiPad:(CGSize)size; /** 设置分享编辑页面是否等待完成之后再关闭页面还是立即关闭,如果设置成YES,就是等待分享完成之后再关闭,否则立即关闭。 2.2版本前默认等待分享完成之后再关闭。 2.2版本之后默认设置成立即关闭页面 @param shouldShareSynchronous 是否同步分享 */ + (void)setShouldShareSynchronous:(BOOL)shouldShareSynchronous; /** 设置评论页面是否出现分享按钮,默认出现 */ + (void)setShouldCommentWithShare:(BOOL)shouldCommentWithShare; /** 设置评论页面是否出现分享地理位置信息的按钮,默认出现 */ + (void)setShouldCommentWithLocation:(BOOL)shouldCommentWithLocation; /** Deprecated API, Use [UMSocialConfig showPlatformWhenNotInstall:nil]; 显示所有平台,某些平台例如微信和QQ,需要安装客户端才能分享,若没有安装客户端情况下不显示这些平台 */ //+ (void)showAllPlatform:(BOOL)showAllPlatform; /** Deprecated API, Use [UMSocialConfig hiddenNotInstallPlatforms:nil]; 指定显示没有安装客户端的平台,默认需要客户端的分享平台不显示。 传nil则显示所有平台。 @param showPlatforms 指定要显示的平台 */ + (void)showNotInstallPlatforms:(NSArray *)showPlatforms; /** 隐藏指定没有安装客户端的平台。 @param hiddenPlatforms 指定要隐藏的平台,传nil则隐藏所有没有安装客户端的平台 */ + (void)hiddenNotInstallPlatforms:(NSArray *)hiddenPlatforms; + (UMSocialConfig *)shareInstance; /** deprecated API, Use ''[UMSocialSinaHandler openSSOWithRedirectURL:@"http://sns.whalecloud.com/sina2/callback"];'' 设置是否支持新浪微博SSO,默认不支持 @param supportSinaSSO 设置是否支持新浪微博SSO @param appRedirectUrl 设置授权回调地址,此授权回调地址必须和你在新浪应用后台填写的回调地址一致,否则不能授权 如果在新浪微博后台绑定我们的回调地址“http://sns.whalecloud.com/sina2/callback”,这里可以传nil */ //+ (void)setSupportSinaSSO:(BOOL)supportSinaSSO appRedirectUrl:(NSString *)appRedirectUrl; /** deprecated API, Use ''[UMSocialQQHandler shareToQQWithAppId:@"100424468" url:@"http://www.umeng.com/social"];'' 设置手机QQ的app_Id和微信图文分享用到的url地址 @param app_Id 手机QQ的AppId @param url 手机QQ图文分享web类型,用到的url地址,如果传nil,默认使用http://www.umeng.com/social @param classes 载入QQ互联 SDK,用到的两个类 */ //+ (void)setQQAppId:(NSString *)app_Id url:(NSString *)url importClasses:(NSArray *)classes; /**deprecated API, Use ''[UMSocialQQHandler setSupportQzoneSSO:YES];'' 设置支持Qzone的SSO授权 @param supportQzoneSSO Qzone支持SSO @param classes 载入QQ互联 SDK,用到的两个类 */ //+ (void)setSupportQzoneSSO:(BOOL)supportQzoneSSO importClasses:(NSArray *)classes; /**deprecated API 设置是否使用QQ互联的SDK来分享 @param useQQSDK 是否使用QQ互联的SDK来分享 @param classes 载入QQ互联 SDK,用到的两个类 */ //+ (void)setShareQzoneWithQQSDK:(BOOL)useQQSDK url:(NSString *)urlString importClasses:(NSArray *)classes; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialControllerService.h ================================================ // // UMSocialUIController.h // SocialSDK // // Created by Jiahuan Ye on 12-9-12. // Copyright (c) umeng.com All rights reserved. // #import #import "UMSocialDataService.h" #define kTagSocialIconActionSheet 1013 #define kTagSocialShakeView 1014 @class UMSocialControllerService; /** `UMSocialControllerService`对象用到的一些回调方法,包括分享完成、授权完成、评论完成等事件,和关闭授权页面、分享页面、评论页面等事件。 */ @protocol UMSocialUIDelegate @optional /** 自定义关闭授权页面事件 @param navigationCtroller 关闭当前页面的navigationCtroller对象 */ -(BOOL)closeOauthWebViewController:(UINavigationController *)navigationCtroller socialControllerService:(UMSocialControllerService *)socialControllerService; /** 关闭当前页面之后 @param fromViewControllerType 关闭的页面类型 */ -(void)didCloseUIViewController:(UMSViewControllerType)fromViewControllerType; /** 各个页面执行授权完成、分享完成、或者评论完成时的回调函数 @param response 返回`UMSocialResponseEntity`对象,`UMSocialResponseEntity`里面的viewControllerType属性可以获得页面类型 */ -(void)didFinishGetUMSocialDataInViewController:(UMSocialResponseEntity *)response; /** 点击分享列表页面,之后的回调方法,你可以通过判断不同的分享平台,来设置分享内容。 例如: -(void)didSelectSocialPlatform:(NSString *)platformName withSocialData:(UMSocialData *)socialData { if (platformName == UMShareToSina) { socialData.shareText = @"分享到新浪微博的文字内容"; } else{ socialData.shareText = @"分享到其他平台的文字内容"; } } @param platformName 点击分享平台 @prarm socialData 分享内容 */ -(void)didSelectSocialPlatform:(NSString *)platformName withSocialData:(UMSocialData *)socialData; /** 配置点击分享列表后是否弹出分享内容编辑页面,再弹出分享,默认需要弹出分享编辑页面 @result 设置是否需要弹出分享内容编辑页面,默认需要 */ -(BOOL)isDirectShareInIconActionSheet; @end /** 用此类的方法可以得到分享的有关UI对象,例如分享列表、评论列表、分享编辑页、分享授权页、个人中心页面等。返回都是`UINavigationController`对象,建议把这个对象present到你要添加到的`UIViewController`上 */ @interface UMSocialControllerService : NSObject /** 与`UMSocialControllerService`对象对应的`UMSocialData`对象,可以通过该对象设置分享内嵌文字、图片,获取分享数等属性 */ @property (nonatomic, retain) UMSocialData *socialData; /** 用`UMSocialDataService`对象,可以调用发送微博、评论等数据级的方法 */ @property (nonatomic, readonly) UMSocialDataService *socialDataService; /** 当前返回的`UINavigationController`对象 */ @property (nonatomic, assign) UIViewController *currentViewController; /** 当前返回的`UIViewController`对象 */ @property (nonatomic, assign) UINavigationController *currentNavigationController; /** 当前``对象,此对象可以获取到授权完成,关闭页面等状态,详情看`UMSocialUIDelegate`的定义 */ @property (nonatomic, assign) id socialUIDelegate; /** 当前sns平台名 */ @property (nonatomic, retain) NSString *currentSnsPlatformName; /** 下一个页面类型 */ @property (nonatomic, assign) UMSViewControllerType nextViewController; /** 返回一个以[UMSocialData defaultData]来做初始化参数的`UMSocialControllerService`对象 @return `UMSocialControllerService`的默认初始化对象 */ +(UMSocialControllerService *)defaultControllerService; ///--------------------------------------- /// @name 初始化方法和设置 ///--------------------------------------- /** 初始化一个`UMSocialControllerService`对象 @param socialData `UMSocialData`对象 @return 初始化对象 */ - (id)initWithUMSocialData:(UMSocialData *)socialData; /** 设置分享内容和回调对象 @param shareText 分享内嵌文字 @param shareImage 分享内嵌图片,可以传入UIImage或者NSData类型 @param socialUIDelegate 分享回调对象 */ - (void)setShareText:(NSString *)shareText shareImage:(id)shareImage socialUIDelegate:(id)socialUIDelegate; ///--------------------------------------- /// @name 获得评论列表、分享列表等UINavigationController ///--------------------------------------- /** 得到一个分享列表页面,该列表出现的分享列表可以通过实现`UMSocialConfig`的类方法来自定义 @return `UINavigationController`对象 */ - (UINavigationController *)getSocialShareListController; /** 分享编辑页面 @param platformType 要编辑的微博平台,并支持UMSocialSnsTypeEmail和UMSocialSnsTypeSms返回编辑Email页面和短信页面,不支持邮箱或者短信的设备分别返回nil @return `UINavigationController`对象 */ - (UINavigationController *)getSocialShareEditController:(NSString *)platformType; /** 授权页面,如果你要想得到授权完成之后的事件,你可以实现`UMSocialUIDelegate`里面的`-(void)didCloseUIViewController:(UMSViewControllerType)fromViewControllerType;`方法,当授权关闭页面会调用此方法。另外授权完成之后sdk会自动去取个人账户信息,你可以在回调函数里面去到刚刚授权的微博平台的账户信息。 @param shareToType 要授权的微博平台 @return `UINavigationController`对象 */ - (UINavigationController *)getSocialOauthController:(NSString *)platformType; /** 获取用以sns各平台icon平铺来展示的分享列表页面对象 @param controller 弹出的分享列表页面,点击sns平台icon之后,出现的分享页面或者授权页面所在的UIViewController @return 分享列表页面 */ - (id)getSocialIconActionSheetInController:(UIViewController *)controller; /** 获取各种页面的`UIViewController`对象 @param viewControllerType 页面类型 @param snsName 编辑页面、授权页面等需要的平台名 @return 页面的`UIViewController`对象 */ - (UIViewController *)getSocialViewController:(UMSViewControllerType)viewControllerType withSnsType:(NSString *)snsName; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialControllerServiceComment.h ================================================ // // UMSocialControllerServiceComment.h // SocialSDK // // Created by yeahugo on 12-12-7. // Copyright (c) 2012年 Umeng. All rights reserved. // #import #import "UMSocialControllerService.h" /** 用此类的方法可以得到分享的有关UI对象,例如分享列表、评论列表、分享编辑页、分享授权页、个人中心页面等。返回都是`UINavigationController`对象,建议把这个对象present到你要添加到的`UIViewController`上 */ @interface UMSocialControllerServiceComment : UMSocialControllerService /** 返回一个以[UMSocialData defaultData]来做初始化参数的`UMSocialControllerServiceComment`对象 @return `UMSocialControllerServiceComment`的默认初始化对象 */ +(UMSocialControllerServiceComment *)defaultControllerService; /** 评论列表页面,评论列表页面包括各评论详情、评论编辑 @return `UINavigationController`对象 */ - (UINavigationController *)getSocialCommentListController; /** 得到个人中心页面,该页面包括用户各个微博授权信息和选择的登录账号 @return `UINavigationController`对象 */ - (UINavigationController *)getSocialAccountController; /** sns账号设置页面,该页面包括个人的各个微博授权信息 @return `UINavigationController`对象 */ - (UINavigationController *)getSnsAccountController; /** 登录页面,出现你配置出现的所有sns平台,授权之后设置为sdk的登录账号。使用评论功能时会取此登录账号的昵称和头像。 @return `UINavigationController`对象 */ - (UINavigationController *)getSocialLoginController; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialData.h ================================================ // // UMSocialData.h // SocialSDK // // Created by Jiahuan Ye on 12-9-12. // Copyright (c) umeng.com All rights reserved. // #import #import #import "UMSocialSnsData.h" /** 一个`UMSocialData`对象标识一个分享资源,用一个*identifier*字符串作为标识,你可以为此对象设置分享内嵌文字、分享图片等,可以获取到对应的分享数、评论数。同时`UMSocialData`类方法用来设置appKey和打开log等全局设置。 */ @interface UMSocialData : NSObject ///--------------------------------------- /// @name 对象属性 ///--------------------------------------- /** 标识每个不同`UMSocialData`对象的字符串 */ @property (nonatomic, readonly) NSString *identifier; /** 报表title 不同`UMSocialData`实例的title,在报表中可看到对应分享操作的title */ @property (nonatomic, copy) NSString *title; /** 分享的内嵌文字 */ @property (nonatomic, copy) NSString * shareText; /** 用于用户在评论并分享的时候,该字段内容会自动添加到评论的后面,分享到各个分享平台 */ @property (nonatomic, copy) NSString * commentText; /** 分享的内嵌图片,可以传入`UIImage`或者`NSData`类型 */ @property (nonatomic, retain) id shareImage; /** 用于用户在评论并分享的时候,该字段内容会自动添加到评论中的图片,分享到各个分享平台 */ @property (nonatomic, retain) UIImage * commentImage; /** 保存在本地记录是否喜欢 */ @property (nonatomic, readonly) BOOL isLike; /** 保存在本地的用户微博账户信息,key是微博名,value是自定义的`UMSocialResponseEntity`对象 */ @property (nonatomic, readonly) NSDictionary *socialAccount; /** 分享到微博多媒体资源,包括指定url的图片、音乐、视频 */ @property (nonatomic, retain) UMSocialUrlResource *urlResource; /** 分享到各个微博的扩展设置 */ @property (nonatomic, retain) UMSocialExtConfig *extConfig; ///--------------------------------------- /// @name 对所有对象都起作用的类方法 ///--------------------------------------- /**设置app的友盟appKey,此appKey从友盟网站获取 @param appKey 友盟appKey */ + (void)setAppKey:(NSString *)appKey; /**获取设置的友盟appKey */ + (NSString *)appKey; /** 设置是否打开log输出,默认不打开,如果打开的话可以看到此sdk网络或者其他操作,有利于调试 @param openLog 是否打开log输出 */ + (void)openLog:(BOOL)openLog; /** 获取默认的`UMSocialData`对象,此对象的identifier为"UMSocialDefault" */ + (UMSocialData *)defaultData; ///--------------------------------------- /// @name 对象方法 ///--------------------------------------- /** 初始化一个`UMSocialData`对象 @param identifier 一个`UMSocialData`对象的标识符,相同标识符的`UMSocialData`拥有相同的属性 @return return 初始化的`UMSocialData`对象 */ - (id)initWithIdentifier:(NSString *)identifier; /** 初始化一个`UMSocialData`对象 @param identifier 一个`UMSocialData`对象的标识符,相同标识符的`UMSocialData`拥有相同的属性 @param title 对每个对象的描述,在报表端显示分享、评论等操作对应的title @return return 初始化的`UMSocialData`对象 */ - (id)initWithIdentifier:(NSString *)identifier withTitle:(NSString *)title; /** 获得该对象保存在本地的分享数、评论数或者喜欢数 @param numberType 数目类型,分享、评论、喜欢分别为`UMSNumberShare`、`UMSNumberComment`、`UMSNumberLike` @return 各种动作的数目 */ - (NSInteger)getNumber:(UMSNumberType)numberType; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialDataService.h ================================================ // // UMSocialDataAPI.h // SocialSDK // // Created by Jiahuan Ye on 12-9-13. // Copyright (c) umeng.com All rights reserved. // #import #import "UMSocialData.h" /** 网络请求结果状态码 */ typedef enum { UMSResponseCodeSuccess = 200, //成功 UMSREsponseCodeTokenInvalid = 400, //授权用户token错误 UMSResponseCodeBaned = 505, //用户被封禁 UMSResponseCodeFaild = 510, //发送失败(由于内容不符合要求或者其他原因) UMSResponseCodeArgumentsError = 522, //参数错误,提供的参数不符合要求 UMSResponseCodeEmptyContent = 5007, //发送内容为空 UMSResponseCodeShareRepeated = 5016, //分享内容重复 UMSResponseCodeGetNoUidFromOauth = 5020, //授权之后没有得到用户uid UMSResponseCodeAccessTokenExpired = 5027, //token过期 UMSResponseCodeNetworkError = 5050, //网络错误 UMSResponseCodeGetProfileFailed = 5051, //获取账户失败 UMSResponseCodeCancel = 5052, //用户取消授权 UMSResponseCodeNotLogin = 5053, //用户没有登录 UMSResponseCodeNoApiAuthority = 100031 //QQ空间应用没有在QQ互联平台上申请上传图片到相册的权限 } UMSResponseCode; /** 网络请求类型 */ typedef enum { UMSResponseAddComment = 0, //添加评论 UMSResponseAddLike = 1, //添加喜欢 UMSResponseGetCommentList = 2, //获取评论列表 UMSResponseGetSocialData = 3, //获取social enitity信息 UMSResponseShareToSNS = 4, //分享到一个微博平台 UMSResponseShareToMutilSNS = 5, //分享到多个微博平台 UMSResponseBinding = 6, //绑定一个账户作为登录账户 UMSResponseUnBinding = 7, //解除绑定账户 UMSResponseUnOauth = 8, //解除授权 UMSResponseOauth = 9, //授权 UMSResponseGetAccount = 10, //获取账户信息 UMSResponseGetSnsInfo = 11, //获取sns详细信息 UMSResponseGetFriends = 12, //获取朋友列表 UMSResponseAddFollow = 13, //添加关注 UMSResponseAddCustomAccount = 14, //添加自定义账户 UMSResponseAddSnsAccount = 15, //添加已经授权的账户 UMSResponseGetAppInfo = 16, //获取各个sns绑定app 信息 UMSResponseIsTokenValid = 17, //获取各个微博平台的token是否有效 UMSResponseAnalytics = 18, UMSResponseAddAppInfo = 19 } UMSResponse; /** 页面类型 */ typedef enum{ UMSViewControllerCommentList, //评论列表 UMSViewControllerCommentEdit, //评论编辑页 UMSViewControllerShareList, //分享列表页,包含sdk支持的所有sns平台 UMSViewControllerShareEdit, //分享编辑页 UMSViewControllerAccount, //个人中心页面 UMSViewControllerSnsAccount, //sns账号设置页面 UMSViewControllerLoginAccount, //登录账号页面 UMSViewControllerOauth, //oath授权页面 UMSViewControllerLogin, //登录页面,登录的可选平台为sdk所支持的sns平台 UMSViewControllerFriendList, //好友列表页面 UMSViewControllerActionSheet //icon平铺排列的分享列表页面 }UMSViewControllerType; /** 返回的状态对象,可以通过此对象获取返回类型、返回结果、返回数据等。 */ @interface UMSocialResponseEntity : NSObject /** 代表发送结果,UMSResponseCodeSuccess代表成功,参看上面的定义 */ @property (nonatomic, assign) UMSResponseCode responseCode; /** 数据类型 */ @property (nonatomic, assign) UMSResponse responseType; /** 数据返回`UMViewControllerType`类型,如果是UI的回调函数,表示回调函数所在的页面 */ @property (nonatomic, assign) UMSViewControllerType viewControllerType; /** 错误原因 */ @property (nonatomic, retain) NSString *message; /** 返回数据 */ @property (nonatomic, retain) NSDictionary *data; /** 客户端发送出现的错误 */ @property (nonatomic, retain) NSError *error; /** 把各属性编码成NSString @return 一个`NSString`对象 */ -(NSString *)description; @end /** 进行网络请求之后的回调函数,你可以通过返回的`UMSocialResponseEntity`对象的`responseType`类型来对不同的请求来做处理。 @see `UMSocialResponseEntity.h` */ @protocol UMSocialDataDelegate /** 进行网络请求之后得到的回调方法 @param response 回调返回一个`UMSResponseEntity`对象 */ -(void)didFinishGetUMSocialDataResponse:(UMSocialResponseEntity *)response; @end typedef void (^UMSocialDataServiceCompletion)(UMSocialResponseEntity * response); @class CLLocation; /** 底层数据接口对象,用一个`UMSocialData`来初始化,此对象的方法有在直接发送微博、发送评论等。可以通过`socialData`属性来获取分享数、评论数,设置分享内嵌文字等。 */ @interface UMSocialDataService : NSObject ///--------------------------------------- /// @name 属性 ///--------------------------------------- @property (nonatomic, copy) UMSocialDataServiceCompletion completion; /** 通过`UMSocialData`对象,可以设置分享文字、图片,并获取到分享数、微博账号等属性 */ @property (nonatomic, retain) UMSocialData *socialData; /** 设置实现了``的对象 */ @property (nonatomic, readonly) id socialDataDelegate; ///--------------------------------------- /// @name 对象初始化和设置方法 ///--------------------------------------- /** 返回一个以[UMSocialData defaultData]来做初始化参数的`UMSocialDataService`对象 @return `UMSocialDataService`的默认初始化对象 */ +(UMSocialDataService *)defaultDataService; /** 初始化一个`UMSocialDataService`对象 @param socialData 一个`UMSocialData`对象 @return 初始化对象 */ - (id)initWithUMSocialData:(UMSocialData *)socialData; /*! 设置实现了``的对象, 如果在此视图设置了delegate,离开此视图的时候要设置为nil @param delegate 实现了``的对象 */ - (void)setUMSocialDelegate:(id )delegate; /** 获取微博分享数、评论数等数据 @param completion 获取到数据之后执行的block对象,返回数据放在completion.data */ -(void)requestSocialDataWithCompletion:(UMSocialDataServiceCompletion)completion; /** Deprecated APIs 发送微博内容到多个微博平台 @param platformTypes 分享到的平台,数组的元素是`UMSocialSnsPlatformManager.h`定义的平台名的常量字符串,例如`UMShareToSina`,`UMShareToTencent`等。 @param content 分享的文字内容 @param image 分享的图片 @param location 分享的地理位置信息 @param urlResource 图片、音乐、视频等url资源 @param completion 发送完成执行的block对象 */ - (void)postSNSWithTypes:(NSArray *)platformTypes content:(NSString *)content image:(id)image location:(CLLocation *)location urlResource:(UMSocialUrlResource *)urlResource completion:(UMSocialDataServiceCompletion)completion; /** 发送微博内容到多个微博平台 @param platformTypes 分享到的平台,数组的元素是`UMSocialSnsPlatformManager.h`定义的平台名的常量字符串,例如`UMShareToSina`,`UMShareToTencent`等。 @param content 分享的文字内容 @param image 分享的图片,可以传入UIImage类型或者NSData类型 @param location 分享的地理位置信息 @param urlResource 图片、音乐、视频等url资源 @param completion 发送完成执行的block对象 @param presentedController 如果发送的平台微博只有一个并且没有授权,传入要授权的viewController,将弹出授权页面,进行授权。可以传nil,将不进行授权。 */ - (void)postSNSWithTypes:(NSArray *)platformTypes content:(NSString *)content image:(id)image location:(CLLocation *)location urlResource:(UMSocialUrlResource *)urlResource presentedController:(UIViewController *)presentedController completion:(UMSocialDataServiceCompletion)completion; /** 如果当前`UMSocialData`没有喜欢的话,发送喜欢,否则取消喜欢 @param completion 获取到数据之后执行的block对象 */ - (void)postAddLikeOrCancelWithCompletion:(UMSocialDataServiceCompletion)completion; /** 发送评论 @param content 评论的文字内容 @param completion 获取到数据之后执行的block对象 */ - (void)postCommentWithContent:(NSString *)content completion:(UMSocialDataServiceCompletion)completion; /** 发送评论 @param content 评论的文字内容 @param image 评论并发送到微博的图片 @param templateText 评论并发送到微博跟在微博正文后面用//分隔的文字 @param location 评论的地理位置信息 @param shareToSNS 评论并分享到微博平台,key为微博名,定义在`UMSocialSnsPlatformManager.h`中的`UMShareToSina`等,值为相应的usid @param completion 获取到数据之后执行的block对象 */ -(void)postCommentWithContent:(NSString *)content image:(UIImage *)image templateText:(NSString *)templateText location:(CLLocation *)location shareToSNSWithUsid:(NSDictionary *)shareToSNS completion:(UMSocialDataServiceCompletion)completion; /** 获取评论 @param lastCommentTime 如果要获取最新的评论数,设置为-1,如果获取指定评论,传入评论在这之前的时间戳 @param completion 获取到数据之后执行的block对象,此block对象的形参内带有请求的评论数据 */ - (void)requestCommentList:(long long)lastCommentTime completion:(UMSocialDataServiceCompletion)completion; ///--------------------------------------- /// @name 用户账户信息相关网络请求 ///--------------------------------------- /** 请求获取用户微博账号的数据,获取到的用户数据在回调函数获得,也可以通过已经保存在本地并且更新的`socialData`属性的`socialAccount`属性来获得 @param completion 获取到数据之后执行的block对象,此block对象的形参带啊有请求的用户账号数据 */ - (void)requestSocialAccountWithCompletion:(UMSocialDataServiceCompletion)completion; /** 请求解除授权 @param platformType 要解除授权的微博平台 @param completion 请求之后执行的block对象 */ - (void)requestUnOauthWithType:(NSString *)platformType completion:(UMSocialDataServiceCompletion)completion; /** 请求绑定账号 @param platformType 要绑定账号的微博平台 @param completion 请求之后执行的block对象 */ - (void)requestBindToSnsWithType:(NSString *)platformType completion:(UMSocialDataServiceCompletion)completion; /** 请求解除绑定账号 @param completion 请求之后执行的block对象 */ - (void)requestUnBindToSnsWithCompletion:(UMSocialDataServiceCompletion)completion; /** 请求获取用户微博账号的详细数据,获取返回数据和其他方法一样,在中的`didFinishGetUMSocialDataResponse`返回的`UMSocialResponseEntity`对象,数据部分是`data`属性,为`NSDictionary`类型 @param platformType 要获取微博信息的微博平台 @param completion 请求之后执行的block对象 */ - (void)requestSnsInformation:(NSString *)platformType completion:(UMSocialDataServiceCompletion)completion; /** 请求获取用户微博账号的朋友列表,获取返回数据和其他方法一样,在中的`didFinishGetUMSocialDataResponse`返回的`UMSocialResponseEntity`对象,数据部分是`data`属性,为`NSDictionary`类型 @param platformType 要获取微博信息的微博平台 @param completion 请求之后执行的block对象,block对象的形参内带有请求的好友数据 */ - (void)requestSnsFriends:(NSString *)platformType completion:(UMSocialDataServiceCompletion)completion; /** 请求添加关注 @param platformType 要添加关注的微博平台,目前添加关注功能只支持新浪微博和腾讯微博 @param usids 被关注的usid号 @param completion 请求之后执行的block对象 */ - (void)requestAddFollow:(NSString *)platformType followedUsid:(NSArray *)usids completion:(UMSocialDataServiceCompletion)completion; /** 检测用户在各个开放平台上的token是否有效,失效的情况包括token过期,用户手动解除授权,用户修改密码等情况 @param snsArray 微博平台数组,只支持传入支持授权的平台,包括新浪微博、腾讯微博、QQ空间等。不支持微信等平台。 @return completion 返回结果 */ - (void)requestIsTokenValid:(NSArray *)snsArray completion:(UMSocialDataServiceCompletion)completion; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialSnsData.h ================================================ // // UMSocialSnsData.h // SocialSDK // // Created by yeahugo on 13-11-25. // Copyright (c) 2013年 Umeng. All rights reserved. // #import #import typedef enum{ UMSNumberLike=0, //喜欢 UMSNumberShare, //分享 UMSNumberComment //评论 }UMSNumberType; typedef enum { UMSocialUrlResourceTypeDefault, //无 UMSocialUrlResourceTypeImage, //图片 UMSocialUrlResourceTypeVideo, //视频 UMSocialUrlResourceTypeMusic //音乐 }UMSocialUrlResourceType; /** 分享到微博的多媒体资源,包括指定url的图片、音乐、视频 */ @interface UMSocialUrlResource : NSObject /** url地址 */ @property (nonatomic, copy) NSString *url; /** 资源类型,图片(UMSocialUrlResourceTypeImage)、视频(UMSocialUrlResourceTypeVideo),音乐(UMSocialUrlResourceTypeMusic) */ @property (nonatomic, assign) UMSocialUrlResourceType resourceType; /** 设置url资源类型和url地址 @param resourceType 多媒体资源类型,图片、音乐或者视频 @param urlString url字符串 */ -(void)setResourceType:(UMSocialUrlResourceType)resourceType url:(NSString *)url; /** 初始化对象,指定一种资源和资源URL @param resourceType 多媒体资源类型,图片、音乐或者视频 @param urlString url字符串 */ -(id)initWithSnsResourceType:(UMSocialUrlResourceType)resourceType url:(NSString *)url; @end /** 微信内容类型 */ typedef enum{ UMSocialWXMessageTypeNone, UMSocialWXMessageTypeText, //微信消息文本类型 UMSocialWXMessageTypeImage, //微信消息图片类型 UMSocialWXMessageTypeApp, //微信消息应用类型 UMSocialWXMessageTypeWeb, //微信消息网页类型 UMSocialWXMessageTypeMusic, //微信消息音乐类型 UMSocialWXMessageTypeVideo, //微信消息视频类型 UMSocialWXMessageTypeEmotion, //微信消息表情类型 UMSocialWXMessageTypeOther //微信消息其他多媒体类型 }UMSocialWXMessageType; /** 支付宝消息类型 */ typedef NS_ENUM(NSInteger, UMSocialAlipayMessageType) { UMSocialAlipayMessageTypeNone, UMSocialAlipayMessageTypeText, //支付宝消息文本类型 UMSocialAlipayMessageTypeImage, //支付宝消息图片类型 UMSocialAlipayMessageTypeWeb, //支付宝消息网页类型 }; /** 易信内容类型 */ typedef enum{ UMSocialYXMessageTypeNone, UMSocialYXMessageTypeText, //微信消息文本类型 UMSocialYXMessageTypeImage, //微信消息图片类型 UMSocialYXMessageTypeApp, //微信消息应用类型 UMSocialYXMessageTypeWeb, //微信消息网页类型 UMSocialYXMessageTypeMusic, //微信消息音乐类型 UMSocialYXMessageTypeVideo, //微信消息视频类型 }UMSocialYXMessageType; /** QQ消息类型 */ typedef enum { UMSocialQQMessageTypeDefault, //非纯图片QQ消息 UMSocialQQMessageTypeImage //纯图片QQ消息 }UMSocialQQMessageType; ///--------------------------------------------------------------------------------------- /** 设置分平台对应内容的基类 */ @interface UMSocialSnsData : NSObject /** 平台名 */ @property (nonatomic, copy) NSString *snsName; /** 分享文字 */ @property (nonatomic, copy) NSString *shareText; /** 分享图片 */ @property (nonatomic, retain) id shareImage; /** url资源类型 */ @property (nonatomic, retain) UMSocialUrlResource *urlResource; @end ///--------------------------------------------------------------------------------------- /** 分享到新浪微博数据 */ @interface UMSocialSinaData : UMSocialSnsData @end /** 分享到腾讯微博数据 */ @interface UMSocialTencentData : UMSocialSnsData /** 如果传入音乐的话,腾讯微博可以指定音乐标题 */ @property (nonatomic, copy) NSString *title; /** 如果传入音乐的话,腾讯微博可以指定音乐作者 */ @property (nonatomic, copy) NSString *author; @end /** 分享到QQ空间数据,分享到QQ空间不支持纯图片的消息格式 */ @interface UMSocialQzoneData : UMSocialSnsData /** 分享内容标题 */ @property (nonatomic, copy) NSString *title; /** 应用链接地址 */ @property (nonatomic, copy) NSString *url; @end /** 分享到QQ好友 */ @interface UMSocialQQData : UMSocialSnsData /** 分享到QQ好友的网页消息url */ @property (nonatomic, copy) NSString *url; /** 分享到QQ好友的网页消息标题 */ @property (nonatomic, copy) NSString *title; /** 分享到QQ好友的消息类型 */ @property (nonatomic, assign) UMSocialQQMessageType qqMessageType; @end /** 分享到微信好友 */ @interface UMSocialWechatSessionData : UMSocialSnsData /** 图文分享标题 */ @property (nonatomic, copy) NSString * title; /** 微信消息类型,包括'UMSocialWXMessageTypeText'文字,'UMSocialWXMessageTypeImage'图片,'UMSocialWXMessageTypeApp'应用类型 */ @property (nonatomic, assign) UMSocialWXMessageType wxMessageType; /** 微信网页消息url */ @property (nonatomic, copy) NSString * url; /** App文件数据,该数据发送给微信好友,微信好友需要点击后下载数据,微信终端会回传给第三方程序处理 * @attention 大小不能超过10M */ @property (nonatomic, retain) NSData *fileData; /** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理 * @attention 长度不能超过2K */ @property (nonatomic, copy) NSString *extInfo; @end /** 分享到微信朋友圈 */ @interface UMSocialWechatTimelineData : UMSocialSnsData /** 图文分享标题 */ @property (nonatomic, copy) NSString * title; /** App文件数据,该数据发送给微信好友,微信好友需要点击后下载数据,微信终端会回传给第三方程序处理 * @attention 大小不能超过10M */ @property (nonatomic, retain) NSData *fileData; /** 微信消息类型,包括'UMSocialWXMessageTypeText'文字,'UMSocialWXMessageTypeImage'图片,'UMSocialWXMessageTypeApp'应用类型 */ @property (nonatomic, assign) UMSocialWXMessageType wxMessageType; /** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理 * @attention 长度不能超过2K */ @property (nonatomic, copy) NSString *extInfo; /** 微信网页消息url */ @property (nonatomic, copy) NSString * url; @end /** 分享到微信收藏 */ @interface UMSocialWechatFavorite : UMSocialSnsData /** 图文分享标题 */ @property (nonatomic, copy) NSString * title; /** App文件数据,该数据发送给微信好友,微信好友需要点击后下载数据,微信终端会回传给第三方程序处理 * @attention 大小不能超过10M */ @property (nonatomic, retain) NSData *fileData; /** 微信消息类型,包括'UMSocialWXMessageTypeText'文字,'UMSocialWXMessageTypeImage'图片,'UMSocialWXMessageTypeApp'应用类型 */ @property (nonatomic, assign) UMSocialWXMessageType wxMessageType; /** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理 * @attention 长度不能超过2K */ @property (nonatomic, copy) NSString *extInfo; /** 微信网页消息url */ @property (nonatomic, copy) NSString * url; @end /** 分享到支付宝好友 */ @interface UMSocialAlipaySessionData : UMSocialSnsData /** 图文分享标题 */ @property (nonatomic, copy) NSString * title; /** 支付宝消息类型 */ @property (nonatomic, assign) UMSocialAlipayMessageType alipayMessageType; /** 支付宝网页消息url */ @property (nonatomic, copy) NSString * url; @end /** 分享到人人网数据 */ @interface UMSocialRenrenData : UMSocialSnsData /** 分享内容链接地址 */ @property (nonatomic, copy) NSString *url; /** 应用名称 */ @property (nonatomic, copy) NSString *appName; @end /** 分享到豆瓣 */ @interface UMSocialDoubanData : UMSocialSnsData @end /** 分享到邮箱 */ @interface UMSocialEmailData : UMSocialSnsData /** 邮件标题 */ @property (nonatomic, copy) NSString * title; @end /** 分享到短信 */ @interface UMSocialSmsData : UMSocialSnsData @end /** 分享到Facebook */ @interface UMSocialFacebookData : UMSocialSnsData /** 分享URL标题 */ @property (nonatomic, copy) NSString *title; /** 分享URL描述 */ @property (nonatomic, copy) NSString *linkDescription; /** 分享URL地址 */ @property (nonatomic, copy) NSString *url; @end /** 分享到易信好友 */ @interface UMSocialYXSessionData : UMSocialSnsData /** 易信消息类型 */ @property (nonatomic, assign) UMSocialYXMessageType yxMessageType; /** 分享网页消息的链接地址 */ @property (nonatomic, copy) NSString *url; @end /** 分享到易信朋友圈 */ @interface UMSocialYXTimelineData : UMSocialSnsData /** 易信消息类型 */ @property (nonatomic, assign) UMSocialYXMessageType yxMessageType; /** 分享网页消息的链接地址 */ @property (nonatomic, copy) NSString *url; @end /** 分享到来往好友 */ @interface UMSocialLWSessionData : UMSocialSnsData /** 分享网页消息的链接地址 */ @property (nonatomic, copy) NSString *url; @end /** 分享到来往好友 */ @interface UMSocialLWTimelineData : UMSocialSnsData /** 分享网页消息的链接地址 */ @property (nonatomic, copy) NSString *url; @end /** 分享到Instagram */ @interface UMSocialInstagramData : UMSocialSnsData @end /** 分享到Twitter */ @interface UMSocialTwitterData : UMSocialSnsData @end /** 分享到Tumblr */ @interface UMSocialTumblrData : UMSocialSnsData /** 分享标题 */ @property (nonatomic, copy) NSString *title; /** 分享URL */ @property (nonatomic, copy) NSString *link; /** 分享URL描述 */ @property (nonatomic, copy) NSString *linkDescription; /** 分享tag */ @property (nonatomic, copy) NSArray *tags; @property (nonatomic, copy) NSString *callbackScheme; @end ///--------------------------------------------------------------------------------------- /** 分享到各个平台的扩展设置 */ @interface UMSocialExtConfig : NSObject /** 以各个分享平台名为key,各个品台data为value */ @property (nonatomic, retain) NSDictionary *snsDataDictionary; /** 分享到新浪微博内容 */ @property (nonatomic, retain) UMSocialSinaData *sinaData; /** 分享到腾讯微博内容 */ @property (nonatomic, retain) UMSocialTencentData *tencentData; /** 分享到微信好友内容 */ @property (nonatomic, retain) UMSocialWechatSessionData *wechatSessionData; /** 分享到微信朋友圈内容 */ @property (nonatomic, retain) UMSocialWechatTimelineData *wechatTimelineData; /** 微信收藏 */ @property (nonatomic, retain) UMSocialWechatFavorite * wechatFavoriteData; /** 分享到支付宝好友内容 */ @property (nonatomic, retain) UMSocialAlipaySessionData * alipaySessionData; /** 分享到QQ内容 */ @property (nonatomic, retain) UMSocialQQData *qqData; /** 分享到Qzone内容 */ @property (nonatomic, retain) UMSocialQzoneData * qzoneData; /** 分享到人人网内容 */ @property (nonatomic, retain) UMSocialRenrenData * renrenData; /** 分享到豆瓣内容 */ @property (nonatomic, retain) UMSocialDoubanData * doubanData; /** 分享到邮箱内容 */ @property (nonatomic, retain) UMSocialEmailData *emailData; /** 分享到短信内容 */ @property (nonatomic, retain) UMSocialSmsData *smsData; /** Facebook内容 */ @property (nonatomic, retain) UMSocialFacebookData * facebookData; /** Twitter内容 */ @property (nonatomic, retain) UMSocialTwitterData *twitterData; /** 易信好友 */ @property (nonatomic, retain) UMSocialYXSessionData * yxsessionData; /** 易信朋友圈 */ @property (nonatomic, retain) UMSocialYXTimelineData *yxtimelineData; /** 来往好友 */ @property (nonatomic, retain) UMSocialLWSessionData * lwsessionData; /** 来往朋友圈 */ @property (nonatomic, retain) UMSocialLWTimelineData * lwtimelineData; /** instagram */ @property (nonatomic, retain) UMSocialInstagramData * instagramData; /** tumblr */ @property (nonatomic, retain) UMSocialTumblrData * tumblrData; /** 标题,用于指定微信分享标题,qzone分享的标题和邮件分享的标题。 @attention Deprecated */ @property (nonatomic, copy) NSString *title; /** 分享到微信的消息类型,分别有文字类型,图片类型,app类型(文字和图片都有,点击可以返回app或者到指定url,不过不能全部显示所有文字内容) @attention Deprecated */ @property (nonatomic, assign) UMSocialWXMessageType wxMessageType; /** 微信多媒体资源的分享,详细定义见`WXApiObject.h` @attention Deprecated */ @property (nonatomic, retain) id wxMediaObject; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialSnsPlatformManager.h ================================================ // // UMSocialSnsPlatformManager.h // SocialSDK // // Created by yeahugo on 13-1-15. // Copyright (c) 2013年 Umeng. All rights reserved. // #import #import "UMSocialControllerService.h" /** 新浪微博 */ extern NSString *const UMShareToSina; /** 腾讯微博 */ extern NSString *const UMShareToTencent; /** 人人网 */ extern NSString *const UMShareToRenren; /** 豆瓣 */ extern NSString *const UMShareToDouban; /** QQ空间 */ extern NSString *const UMShareToQzone; /** 邮箱 */ extern NSString *const UMShareToEmail; /** 短信 */ extern NSString *const UMShareToSms; /** 微信好友 */ extern NSString *const UMShareToWechatSession; /** 微信朋友圈 */ extern NSString *const UMShareToWechatTimeline; /** 微信收藏 */ extern NSString *const UMShareToWechatFavorite; /** 支付宝好友 */ extern NSString *const UMShareToAlipaySession; /** 手机QQ */ extern NSString *const UMShareToQQ; /** Facebook */ extern NSString *const UMShareToFacebook; /** Twitter */ extern NSString *const UMShareToTwitter; /** 易信好友 */ extern NSString *const UMShareToYXSession; /** 易信朋友圈 */ extern NSString *const UMShareToYXTimeline; /** 来往好友 */ extern NSString *const UMShareToLWSession; /** 来往朋友圈 */ extern NSString *const UMShareToLWTimeline; /** 分享到Instragram */ extern NSString *const UMShareToInstagram; /** 分享到Whatsapp */ extern NSString *const UMShareToWhatsapp; /** 分享到Line */ extern NSString *const UMShareToLine; /** 分享到Tumblr */ extern NSString *const UMShareToTumblr; /** 分享到Pinterest */ extern NSString *const UMShareToPinterest; /** 分享到KakaoTalk */ extern NSString *const UMShareToKakaoTalk; /** 分享到Flickr */ extern NSString *const UMShareToFlickr; /** 分享平台 */ typedef enum { UMSocialSnsTypeNone = 0, UMSocialSnsTypeQzone = 10, UMSocialSnsTypeSina, //sina weibo UMSocialSnsTypeTenc, //tencent weibo UMSocialSnsTypeRenr, //renren UMSocialSnsTypeDouban, //douban UMSocialSnsTypeWechatSession, UMSocialSnsTypeWechatTimeline, UMSocialSnsTypeWechatFavorite, UMSocialSnsTypeEmail, UMSocialSnsTypeSms, UMSocialSnsTypeMobileQQ, UMSocialSnsTypeFacebook, UMSocialSnsTypeTwitter, UMSocialSnsTypeYiXinSession, UMSocialSnsTypeYiXinTimeline, UMSocialSnsTypeLaiWangSession, UMSocialSnsTypeLaiWangTimeline, UMSocialSnsTypeInstagram, UMSocialSnsTypeWhatsApp, UMSocialSnsTypeLine, UMSocialSnsTypeTumblr, UMSocialSnsTypeKakaoTalk, UMSocialSnsTypeFlickr, UMSocialSnsTypePinterest, UMSocialSnsTypeAlipaySession, UMSocialSnsTypeNew } UMSocialSnsType; @class UMSocialControllerService; /** 定义响应点击平台后的block对象 @param presentingController 点击后弹出的分享页面或者授权页面所在的UIViewController对象 @param socialControllerService 可以用此对象的socialControllerService.socialData可以获取分享内嵌文字、内嵌图片,分享次数等 @param isPresentInController 如果YES代表弹出(present)到当前UIViewController,否则push到UIViewController的navigationController */ typedef void (^UMSocialSnsPlatformClickHandler)(UIViewController *presentingController, UMSocialControllerService * socialControllerService, BOOL isPresentInController); /** 定义响应点击各平台授权登录后的block对象 @param presentingController 点击后弹出的分享页面或者授权页面所在的UIViewController对象 @param socialControllerService 可以用此对象的socialControllerService.socialData可以获取分享内嵌文字、内嵌图片,分享次数等 @param isPresentInController 如果YES代表弹出(present)到当前UIViewController,否则push到UIViewController的navigationController @param completion 授权完成之后的回调对象,返回的response参数表示成功与否和拿到的授权信息 */ typedef void (^UMSocialSnsPlatformLoginHandler)(UIViewController *presentingController, UMSocialControllerService * socialControllerService, BOOL isPresentInController, UMSocialDataServiceCompletion completion); /** Sns平台类,用`platformName`作为标识,指定显示名称、显示的图片,点击之后的响应。 */ @interface UMSocialSnsPlatform : NSObject ///--------------------------------------- /// @name 平台属性 ///--------------------------------------- /** 平台标示符 */ @property (nonatomic, copy) NSString *platformName; /** 显示名称 */ @property (nonatomic, copy) NSString *displayName; /** 登录名称 */ @property (nonatomic, copy) NSString *loginName; /** 分享类型 */ @property (nonatomic, assign) UMSocialSnsType shareToType; /** 大图片的文件名,用于`UMSocialIconActionSheet` */ @property (nonatomic, copy) NSString *bigImageName; /** 小图片的文件名,用于分享列表、登录、个人中心、评论编辑页面等 */ @property (nonatomic, copy) NSString *smallImageName; /** 无色的小图片文件名,用于评论编辑页面显示没有授权状态 */ @property (nonatomic ,copy) NSString *smallImageOffName; /** 处理点击分享事件后的block对象 */ @property(nonatomic, copy) UMSocialSnsPlatformClickHandler snsClickHandler; /** 处理点击登录事件后的block对象 */ @property(nonatomic, copy) UMSocialSnsPlatformLoginHandler loginClickHandler; /** 是否需要登录授权 */ @property(nonatomic, assign) BOOL needLogin; /** 标志是否有webView授权 */ @property(nonatomic, assign) BOOL haveWebViewAuth; /** 初始化方法 @param platformName 作为该对象标识的平台名 */ -(id)initWithPlatformName:(NSString *)platformName; @end /* Sns平台类管理者类 */ @interface UMSocialSnsPlatformManager : NSObject /** sns平台配置数组,此数组由allSnsArray转换,只包含平台名作为元素 */ @property (nonatomic, readonly) NSArray *allSnsValuesArray; /** 该NSDictionary以各个平台名为key,UMSocialPlatform对象为value */ @property (nonatomic, retain) NSDictionary *allSnsPlatformDictionary; /** `UMSocialSnsPlatformManager`的单例方法 @return `UMSocialSnsPlatformManager`的单例对象 */ + (UMSocialSnsPlatformManager *)sharedInstance; /** 根据平台名,返回平台对象 @param platformName sns平台名 @return UMSocialSnsPlatform 平台对象 */ +(UMSocialSnsPlatform *)getSocialPlatformWithName:(NSString *)snsName; /** 根据平台枚举变量,返回平台对象 @param UMSocialSnsType sns平台枚举变量 @return NSString 平台名 */ + (NSString *)getSnsPlatformString:(UMSocialSnsType)socialSnsType; /** 把配置平台的次序号转换成平台名 @param snsIndex 使用的平台顺序,使用的平台配置在UMSocialConfigDelegate,例如`- (NSArray *)shareToPlatforms;`返回的是UMSocialSnsTypeSina和UMSocialSnsTypeTenc,UMSocialSnsTypeSina就是0,UMSocialSnsTypeTenc就是1 @return 平台名字符串 */ +(NSString *)getSnsPlatformStringFromIndex:(NSInteger)snsIndex; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/Header/UMSocialSnsService.h ================================================ // // UMSocialSnsService.h // SocialSDK // // Created by Jiahuan Ye on 13-1-8. // Copyright (c) 2013年 Umeng. All rights reserved. // #import #import @class UMSocialControllerService; /* 自定义的类似iOS6.0中`UIActivityViewController`样式的列表,每个sns平台由对应图片和名称组成。注意:如果你要此控件支持多方向,需要在自己的UIViewController中屏幕旋转的`didRotateFromInterfaceOrientation`调用`UMSocialIconActionSheet`的`setNeedsDisplay`方法,来重新布局。 */ @interface UMSocialIconActionSheet : UIView /** 将自己自下往上弹出来 @param showView 在此父UIView自下往上弹出来的 */ -(void)showInView:(UIView *)showView; /** 将自己移除 */ -(void)dismiss; @end @protocol WXApiDelegate ; @protocol UMSocialUIDelegate; /* 实现快速分享,类方法传入相应的参数,既可以弹出分享列表。现在提供两种列表样式。 */ @interface UMSocialSnsService : NSObject /** 当应用从后台唤起时,应调用此方法,需要完成退出当前登录状态的功能 */ +(void)applicationDidBecomeActive; /** 处理app的URL方法 若除了 UMSocial SDK外,还需要处理其他url,可以针对url的前缀作处理,例如下面写法: if ([url.description hasPrefix:@"xxxx"]) { //你的处理逻辑 } else { return [UMSocialSnsService handleOpenURL:url]; } @param url 传入的url */ +(BOOL)handleOpenURL:(NSURL *)url; /** Deprecated API 处理app的URL方法 @param url 传入的url @return wxApiDelegate 实现微信代理对象 */ +(BOOL)handleOpenURL:(NSURL *)url wxApiDelegate:(id)wxApiDelegate; ///--------------------------------------- /// @name 快速分享 ///--------------------------------------- /** 弹出一个分享列表的UITableViewController @param controller 在该controller弹出分享列表的UIActionSheet @param appKey 友盟appKey @param shareText 分享编辑页面的内嵌文字 @param shareImage 可以传入`UIImage`,或者`NSData`类型,分享内嵌图片,用户可以在编辑页面删除 @param snsNames 你要分享到的sns平台类型,该NSArray值是`UMSocialSnsPlatformManager.h`定义的平台名的字符串常量,有UMShareToSina,UMShareToTencent,UMShareToRenren,UMShareToDouban,UMShareToQzone,UMShareToEmail,UMShareToSms等 @param delegate 实现分享完成后的回调对象,如果不关注分享完成的状态,可以设为nil */ +(void)presentSnsController:(UIViewController *)controller appKey:(NSString *)appKey shareText:(NSString *)shareText shareImage:(id)shareImage shareToSnsNames:(NSArray *)snsNames delegate:(id )delegate; /** 弹出一个分享列表的类似iOS6的UIActivityViewController控件 @param controller 在该controller弹出分享列表的UIActionSheet @param appKey 友盟appKey @param shareText 分享编辑页面的内嵌文字 @param shareImage 分享内嵌图片,用户可以在编辑页面删除 @param snsNames 你要分享到的sns平台类型,该NSArray值是`UMSocialSnsPlatformManager.h`定义的平台名的字符串常量,有UMShareToSina,UMShareToTencent,UMShareToRenren,UMShareToDouban,UMShareToQzone,UMShareToEmail,UMShareToSms等 @param delegate 实现分享完成后的回调对象,如果不关注分享完成的状态,可以设为nil */ +(void)presentSnsIconSheetView:(UIViewController *)controller appKey:(NSString *)appKey shareText:(NSString *)shareText shareImage:(id)shareImage shareToSnsNames:(NSArray *)snsNames delegate:(id )delegate; /** 得到单例对象的类方法 @return `UMSocialSnsService`的单例对象 */ + (UMSocialSnsService *)sharedInstance; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentDetailController.xib ================================================ 1072 12E55 4488.2 1187.39 626.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 3715.3 IBMKMapView IBProxyObject IBUIImageView IBUILabel IBUITextView IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 1298 1298 {320, 167} NO IBCocoaTouchFramework 1312 {{12, 59}, {35, 35}} NO IBCocoaTouchFramework NSImage UMSocialSDKResourcesNew.bundle/Buttons/UMS_User-Avatar-Placeholder 1298 {{86, 210}, {148, 35}} NO YES 7 NO IBCocoaTouchFramework 用户未分享地理位置 1 MC40MTk1OTM3ODczIDAuNDIwNjk2MjY1MyAwLjQzNzUxOTkyOTgAA 3 MQA 1 MCAwIDAgMC44AA 1 10 1 Helvetica Helvetica 0 14 Helvetica 14 16 NO 1288 {{0, 164}, {320, 252}} YES YES IBCocoaTouchFramework 1313 {{61, 136}, {76, 20}} NO YES 7 NO IBCocoaTouchFramework 100 months 2 MC43MDk4MDM5Mzg5IDAuNzEzNzI1NTA3MyAwLjcyOTQxMTc4MDgAA 1 MCAwIDAgMC4yAA 1 10 Helvetica Helvetica 0 12 Helvetica 12 16 NO 1284 {{61, 8}, {240, 128}} YES YES IBCocoaTouchFramework NO Lorem ipsum dolor sit er elit 2 IBCocoaTouchFramework-SevenAndLater 1 13 HelveticaNeue 13 16 {{0, 64}, {320, 416}} 1 MC4yMTU2ODYyNzQ1IDAuMjM5MjE1Njg2MyAwLjI3MDU4ODIzNTMAA NO NO IBCocoaTouchFramework NO commentBackgroundImage 53 commentTextView 61 mapView 49 profileImage 6 timeLabel 47 view 45 delegate 48 0 -1 File's Owner -2 1 8 4 51 9 46 59 UMSCommentDetailController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin UMImageView com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 0 IBCocoaTouchFramework YES com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 YES 3 UMSocialSDKResourcesNew.bundle/Buttons/UMS_User-Avatar-Placeholder {16, 16} 3715.3 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentInputController.xib ================================================ 1072 12E55 4488.2 1187.39 626.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 3715.3 IBMKMapView IBProxyObject IBUIButton IBUIImageView IBUITextView IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 1298 1300 1298 {320, 155} 3 MQA YES YES IBCocoaTouchFramework 2 IBCocoaTouchFramework-SevenAndLater 1 14 HelveticaNeue 14 16 1314 1298 {320, 49} NO IBCocoaTouchFramework -2147482332 {{94, 7}, {30, 30}} NO 4 1001 IBCocoaTouchFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 3 MC41AA NSImage UMSocialSDKResourcesNew.bundle/SnsPlatform/UMS_tencent_off.png 2 15 HelveticaNeue-Bold 15 16 1316 {{0, 5}, {60, 37}} NO IBCocoaTouchFramework 0 0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA -2147482332 {{184, 9}, {30, 30}} NO 4 1001 IBCocoaTouchFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA -2147482332 {{138, 10}, {30, 30}} NO 4 1000 IBCocoaTouchFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMSocialSDKResourcesNew.bundle/SnsPlatform/UMS_sina_off.png -2147482332 {{232, 9}, {30, 30}} NO 4 1002 IBCocoaTouchFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMSocialSDKResourcesNew.bundle/SnsPlatform/UMS_renren_off.png -2147482332 {{278, 9}, {30, 30}} NO 4 1003 IBCocoaTouchFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMSocialSDKResourcesNew.bundle/SnsPlatform/UMS_douban_off.png {{0, 150}, {320, 50}} 3 MQA 2 IBCocoaTouchFramework {320, 200} YES IBCocoaTouchFramework 1292 1292 {{7, 47}, {306, 158}} YES YES IBCocoaTouchFramework NO NO 1316 {{227, 5}, {73, 31}} NO IBCocoaTouchFramework 0 0 取消定位 2 13 HelveticaNeue-Bold 13 16 {{0, 190}, {320, 220}} IBCocoaTouchFramework {{0, 64}, {320, 416}} NO NO IBCocoaTouchFramework NO closeLocationButton 23 commentTextView 21 downView 20 mapView 52 shareToDoubanButton 38 shareToQzoneButton 51 shareToRenrenButton 37 shareToSinaButton 36 shareToTencentButton 35 showLocationButton 27 toolView 30 toolViewImageView 54 upView 43 view 9 delegate 53 0 -1 File's Owner -2 1 4 UpView 3 6 19 49 26 31 32 33 34 18 DownView 14 15 UMSCommentEditController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 0 IBCocoaTouchFramework YES com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 YES 3 {16, 16} {16, 16} {16, 16} {16, 16} 3715.3 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSCommentInputControlleriPad.xib ================================================ 1072 13A603 4514 1265 695.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 3747 IBMKMapView IBProxyObject IBUIButton IBUIImageView IBUITextView IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBIPadFramework IBFirstResponder IBIPadFramework 1306 1314 {533, 221} 1 MSAxIDEAA YES YES IBIPadFramework NO 2 IBIPadFramework-SevenAndLater 1 14 HelveticaNeue 14 16 1314 1306 {533, 44} NO IBIPadFramework 1316 {{40, 0}, {36, 33}} NO IBIPadFramework 0 0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 3 MQA 3 MC41AA 2 15 HelveticaNeue-Bold 15 16 -2147482332 {{275, 7}, {30, 30}} NO 4 1001 IBIPadFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMS_tencent_off.png -2147482332 {{331, 7}, {30, 30}} NO 4 1000 IBIPadFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMS_sina_off.png -2147482332 {{384, 7}, {30, 30}} NO 4 1001 IBIPadFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA -2147482332 {{439, 7}, {30, 30}} NO 4 1002 IBIPadFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMS_renren_off.png -2147482332 {{493, 7}, {30, 30}} NO 4 1003 IBIPadFramework 0 0 10 0.0 10 0.0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMS_douban_off.png -2147482334 {{35, 80}, {460, 250}} YES YES IBIPadFramework 1316 {{439, 45}, {73, 27}} NO IBIPadFramework 0 0 取消定位 2 13 HelveticaNeue-Bold 13 16 {{0, 220}, {533, 44}} YES IBIPadFramework {533, 260} 3 MQA 2 IBIPadFramework NO closeLocationButton 1352 commentTextView 183 mapView 1157 shareToDoubanButton 765 shareToQzoneButton 761 shareToRenrenButton 764 shareToSinaButton 762 shareToTencentButton 763 showLocationButton 801 toolView 857 toolViewImageView 1383 view 191 0 -1 File's Owner -2 87 88 802 1299 705 706 708 709 707 710 1142 1341 UMSCommentEditController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 0 IBIPadFramework YES com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 YES 3 {39, 39} {39, 39} {39, 39} {39, 39} 3747 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSLoginViewController.xib ================================================ 1072 12E55 4488.2 1187.39 626.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 3715.3 IBProxyObject IBUITableView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 1298 {{0, 44}, {320, 436}} 3 MQA YES NO NO IBUIScreenMetrics YES {320, 480} {480, 320} IBCocoaTouchFramework Retina 3.5-inch Full Screen 0 IBCocoaTouchFramework YES 0 YES 44 22 22 NO view 9 dataSource 10 delegate 11 0 -1 File's Owner -2 8 UMSLoginViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 0 IBCocoaTouchFramework YES com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 YES 3 3715.3 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSShareListController.xib ================================================ 1072 12E55 4488.2 1187.39 626.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 3715.3 IBProxyObject IBUITableView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 1298 {{0, 64}, {320, 416}} 3 MQA NO YES NO NO NO IBCocoaTouchFramework NO 0 YES 44 22 22 NO view 5 dataSource 6 delegate 7 0 -1 File's Owner -2 4 UMSShareListController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 0 IBCocoaTouchFramework YES com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 YES 3 3715.3 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMShareEditViewController.xib ================================================ 1072 13A603 4514 1265 695.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 3746 IBProxyObject IBUIButton IBUIImageView IBUILabel IBUITextView IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 1298 1342 {320, 153} 1 MSAxIDEAA YES YES IBCocoaTouchFramework 2 IBCocoaTouchFramework-SevenAndLater 1 14 HelveticaNeue 14 16 1324 1316 {320, 50} 2 MC45MzMzMzMzOTY5IDAuOTMzMzMzMzk2OSAwLjkzMzMzMzM5NjkAA IBCocoaTouchFramework 1316 {{110, 3}, {55, 37}} NO IBCocoaTouchFramework 0 0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 3 MQA 3 MC41AA 2 15 HelveticaNeue-Bold 15 16 1316 {{271, 10}, {42, 21}} NO YES 7 NO IBCocoaTouchFramework Label 3 MC4zMzMzMzMzMzMzAA 0 10 1 17 HelveticaNeue 17 16 1316 {{160, 5}, {58, 35}} NO IBCocoaTouchFramework 0 0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 1297 {{225, 7}, {38, 35}} NO IBCocoaTouchFramework 1313 {{255, 1}, {18, 18}} NO IBCocoaTouchFramework 0 0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMSocialSDKResourcesNew.bundle/Buttons/UMS_delete_image_button_normal -2147482332 {{35, 14}, {60, 20}} _NS:9 {251, 251} NO YES 7 NO IBCocoaTouchFramework 1 MCAwIDAAA darkTextColor 0 1 8 HelveticaNeue 8 16 NO -2147482332 {{5, 10}, {30, 30}} _NS:9 NO IBCocoaTouchFramework 0 0 {{0, 155}, {320, 44}} 3 MQA 2 IBCocoaTouchFramework 1324 {{0, 205}, {320, 211}} IBCocoaTouchFramework 1316 {{0, 208}, {320, 181}} 3 MCAwAA IBCocoaTouchFramework {{0, 64}, {320, 416}} 3 MQA NO NO IBCocoaTouchFramework NO _deleteImageButton 35 _shareImageButton 33 atButton 21 changeAccountBackgroundView 27 changeAccountButton 23 changeAccountView 26 countLabel 13 textView 14 toolBarView 17 toolViewBackgroundImage 18 view 16 followLabel 60r-GO-noj followButton kJT-ao-FBF addFollow: 7 wJu-xn-ETn 0 -1 File's Owner -2 1 4 10 9 19 8 22 32 34 24 25 AaX-8t-GAq 3WK-gL-xa0 UMShareEditViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin UMShareEditViewController UIViewController id id addFollow: id showFriendList id UIButton UIImageView UIButton UIImageView UIButton UIView UILabel UIButton UILabel UITextView UIView UIImageView _deleteImageButton UIButton _shareImageButton UIImageView atButton UIButton changeAccountBackgroundView UIImageView changeAccountButton UIButton changeAccountView UIView countLabel UILabel followButton UIButton followLabel UILabel textView UITextView toolBarView UIView toolViewBackgroundImage UIImageView IBProjectSource ./Classes/UMShareEditViewController.h 0 IBCocoaTouchFramework YES com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 YES 3 UMSocialSDKResourcesNew.bundle/Buttons/UMS_delete_image_button_normal {16, 16} 3746 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMShareEditViewControlleriPad.xib ================================================ 1072 14A389 6245 1343.14 755.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 6238 IBProxyObject IBUIButton IBUIImageView IBUILabel IBUITextView IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBIPadFramework IBFirstResponder IBIPadFramework 1314 1314 {535, 236} 1 MSAxIDEAA YES YES IBIPadFramework NO Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 2 IBIPadFramework-SevenAndLater 1 14 HelveticaNeue 14 16 1318 1314 {550, 47} 2 MC45MzMzMzMzOTY5IDAuOTMzMzMzMzk2OSAwLjkzMzMzMzM5NjkAA NO IBIPadFramework 1316 {{13, 5}, {55, 37}} NO IBIPadFramework 0 0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 3 MQA 3 MC41AA NSImage UMSocialSDKResourcesNew.bundle/Buttons/UMS_umeng_share_at.png 2 15 HelveticaNeue-Bold 15 16 1316 {{471, 13}, {42, 21}} NO YES 7 NO IBIPadFramework Label 3 MC42NjY2NjY2NjY3AA 0 10 1 17 HelveticaNeue 17 16 YES 1316 {{76, 6}, {65, 36}} NO IBIPadFramework 0 0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 1313 {{421, 5}, {37, 37}} NO IBIPadFramework 1313 {{448, 1}, {18, 18}} NO IBIPadFramework 0 0 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA NSImage UMSocialSDKResourcesNew.bundle/Buttons/UMS_delete_image_button_normal {{0, 244}, {550, 47}} 3 MQA 2 IBIPadFramework 1302 {{0, 289}, {550, 217}} IBIPadFramework 1316 {{112, 289}, {309, 135}} 3 MCAwAA IBIPadFramework {540, 506} 3 MQA IBUISimulatedFreeformSizeMetricsSentinel Freeform IBIPadFramework NO _deleteImageButton 511 _shareImageButton 510 atButton 224 changeAccountBackgroundView 506 changeAccountButton 503 changeAccountView 507 countLabel 226 textView 236 toolBarView 223 toolViewBackgroundImage 328 view 316 0 -1 File's Owner -2 202 227 203 207 205 206 502 508 509 504 505 UMShareEditViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin {229, 216} com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin UMShareEditViewController UIViewController id id addFollow: id showFriendList id UIButton UIImageView UIButton UIImageView UIButton UIView UILabel UIButton UILabel UITextView UIView UIImageView _deleteImageButton UIButton _shareImageButton UIImageView atButton UIButton changeAccountBackgroundView UIImageView changeAccountButton UIButton changeAccountView UIView countLabel UILabel followButton UIButton followLabel UILabel textView UITextView toolBarView UIView toolViewBackgroundImage UIImageView IBProjectSource ../SocialSDK/UI/UMShareEditViewController.h UMShareEditViewController id id addFollow: id showFriendList id IBProjectSource ../SocialSDK/UI/UMShareEditViewController.m UIButton UIControl IBFrameworkSource UIKit.framework/Headers/UIButton.h UIControl UIView IBFrameworkSource UIKit.framework/Headers/UIControl.h UIGestureRecognizer NSObject IBFrameworkSource UIKit.framework/Headers/UIGestureRecognizer.h UIImageView UIView IBFrameworkSource UIKit.framework/Headers/UIImageView.h UILabel UIView IBFrameworkSource UIKit.framework/Headers/UILabel.h UIResponder NSObject IBFrameworkSource UIKit.framework/Headers/UIResponder.h UIScrollView UIView IBFrameworkSource UIKit.framework/Headers/UIScrollView.h UISearchBar UIView IBFrameworkSource UIKit.framework/Headers/UISearchBar.h UISearchDisplayController NSObject IBFrameworkSource UIKit.framework/Headers/UISearchDisplayController.h UITextView UIScrollView IBFrameworkSource UIKit.framework/Headers/UITextView.h UIView UIResponder IBFrameworkSource UIKit.framework/Headers/UIView.h UIViewController UIResponder IBFrameworkSource UIKit.framework/Headers/UIViewController.h 0 IBIPadFramework YES com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 YES 3 {16, 16} {16, 16} ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/SocialSDKXib/UMSnsAccountViewController.xib ================================================ 1072 12E55 3084 1187.39 626.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 2083 IBProxyObject IBUIButton IBUIImageView IBUILabel IBUITableView IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 1298 1316 1316 {{20, 0}, {68, 21}} 3 MCAwAA NO YES 7 NO IBCocoaTouchFramework 登录账号 2 MC4zMzMzMzMzNDMzIDAuMzMzMzMzMzQzMyAwLjMzMzMzMzM0MzMAA 1 MCAwIDAAA darkTextColor {0, 0} 0 10 1 15 Helvetica 15 16 1316 {{112, 22}, {90, 89}} NO IBCocoaTouchFramework 1316 {{83, 117}, {149, 21}} NO YES 7 NO IBCocoaTouchFramework 2 MC4zMzMzMzMzNDMzIDAuMzMzMzMzMzQzMyAwLjMzMzMzMzM0MzMAA 0 10 1 1316 {{62, 133}, {197, 31}} NO YES 7 IBCocoaTouchFramework 2 MC4zMzMzMzMzNDMzIDAuMzMzMzMzMzQzMyAwLjMzMzMzMzM0MzMAA 0 10 2 1 1 12 Helvetica 12 16 197 1316 {{112, 141}, {90, 30}} NO IBCocoaTouchFramework 0 0 3 MQA 3 MC41AA {320, 177} IBCocoaTouchFramework 1295 1290 {{0, 20}, {320, 241}} YES IBCocoaTouchFramework NO NO NO NO 1 2 MC45MzMzMzMzOTY5IDAuOTMzMzMzMzk2OSAwLjkzMzMzMzM5NjkAA 0 NO 44 22 22 1332 {{20, 0}, {320, 20}} NO YES 7 NO IBCocoaTouchFramework 分享设置 2 MC40ODIzNTI5NzIgMC40ODIzNTI5NzIgMC40ODIzNTI5NzIAA {0, 0} 0 10 {{0, 179}, {320, 237}} 2 MC45MzMzMzMzOTY5IDAuOTMzMzMzMzk2OSAwLjkzMzMzMzM5NjkAA IBCocoaTouchFramework {{0, 64}, {320, 416}} 3 MQA 2 NO IBUISimulatedFreeformSizeMetricsSentinel Freeform IBCocoaTouchFramework 1298 1320 1316 {{20, 20}, {100, 21}} NO YES 7 NO IBCocoaTouchFramework 分享设置 2 MC42Mjc0NTEwMDI2IDAuNjI3NDUxMDAyNiAwLjYyNzQ1MTAwMjYAA {0, 0} 0 10 1 17 Helvetica 17 16 1298 {{0, 49}, {295, 272}} YES IBCocoaTouchFramework NO NO NO NO 3 MC4zMzMzMzMzMzMzAA 0 NO 44 22 22 {{184, 0}, {384, 300}} 2 MC45MzMzMzMzOTY5IDAuOTMzMzMzMzk2OSAwLjkzMzMzMzM5NjkAA IBCocoaTouchFramework 1320 1316 {{23, 29}, {68, 21}} NO YES 7 NO IBCocoaTouchFramework 登录账号 2 MC42Mjc0NTEwMDI2IDAuNjI3NDUxMDAyNiAwLjYyNzQ1MTAwMjYAA {0, 0} 0 10 1316 {{52, 84}, {90, 89}} NO IBCocoaTouchFramework 1316 {{25, 190}, {145, 21}} NO YES 7 NO IBCocoaTouchFramework 2 MC42Mjc0NTEwMDI2IDAuNjI3NDUxMDAyNiAwLjYyNzQ1MTAwMjYAA 0 10 1 1316 {{23, 230}, {152, 50}} NO YES 7 IBCocoaTouchFramework 2 MC42Mjc0NTEwMDI2IDAuNjI3NDUxMDAyNiAwLjYyNzQ1MTAwMjYAA 0 10 2 1 13 Helvetica 13 16 152 1316 {{52, 218}, {90, 30}} NO IBCocoaTouchFramework 0 0 {180, 300} IBCocoaTouchFramework {{0, 64}, {480, 300}} NO 3 3 IBCocoaTouchFramework NO _landsCandscapeView 42 _loginButton AzY-H8-fDD _loginButtonLand 6Fv-KR-o55 _loginTextLabel 62 _loginTextLabelLand 63 _loginView 58 _loginViewLand 59 _nickNameLabel 46 _nickNameLabelLand 50 _profileImageView 48 _profileImageViewLand 49 _snsTableLable 60 _snsTableLableLand 61 _snsTableView 5 _snsTableViewLand 53 _snsURLLabel 20 _snsURLLabelLand 51 view 41 dataSource 56 delegate 57 dataSource 54 delegate 55 0 -1 File's Owner -2 1 14 8 6 17 8v1-7D-GU9 18 64 4 12 30 65 33 31 32 37 36 35 34 RjH-Tf-mDI UMSnsAccountViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin UMSnsAccountViewController UIViewController UIView UIButton UIButton UILabel UILabel UIView UIView UILabel UILabel UIView UIImageView UIImageView UILabel UILabel UITableView UITableView UILabel UILabel _landsCandscapeView UIView _loginButton UIButton _loginButtonLand UIButton _loginTextLabel UILabel _loginTextLabelLand UILabel _loginView UIView _loginViewLand UIView _nickNameLabel UILabel _nickNameLabelLand UILabel _portraitView UIView _profileImageView UIImageView _profileImageViewLand UIImageView _snsTableLable UILabel _snsTableLableLand UILabel _snsTableView UITableView _snsTableViewLand UITableView _snsURLLabel UILabel _snsURLLabelLand UILabel IBProjectSource ./Classes/UMSnsAccountViewController.h 0 IBCocoaTouchFramework com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 YES 3 2083 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/en.lproj/UMSocialLocalizable.strings ================================================ /* Localizable.strings SocialSDK Created by yeahugo on 13-6-17. Copyright (c) 2013年 Umeng. All rights reserved. */ "button_cancel" = "Cancel"; "button_ok" = "OK"; "button_start" = "Start"; "button_close" = "Close"; "button_back" = "Back"; "button_refresh" = "Refresh"; "label_request_account" = "Getting account data, please wait……"; "oauth_title" = "Authorization"; "oauth_text" = "Connecting to authorization web, please wait……"; "oauth_follow" = "Follow official micro-blog"; "mask_text" = "please wait……"; "oauth_error_title" = "authorise failed"; "oauth_error_message" = "authorise failed, you can try again later"; "oauth_error_not_approved" = "authorise failed, for your app haven't approved or you haven't add your weibo uid to test accounts"; "shareQQ_error" = "Error"; "shareQQ_notInstall" = "Mobile QQ havn't be installed in your device"; "shareQQ_openFail" = "Open Mobile QQ fail"; "shareInstagram_openFail" = "Open Instagram fail"; "shareClient_notInstall" = "Client not installed in your device"; "shareList_title" = "Share To"; "shareEdit_title" = "Share To "; "shareEdit_post" = "Post"; "shareEdit_change_account" = "Change Account"; "shareEdit_post_finish" = "Post Finished"; "shareEdit_post_fail" = "Post Failed"; "shareEdit_posting" = "Posting"; "shareEdit_delete_picture" = "Delete Picture"; "shareEdit_delete_video" = "Delete Video"; "shareEdit_delete_music" = "Delete Music"; "shareEdit_error_not_empty" = "Post content can not be empty"; "shareEdit_error_too_long" = "Post content's length too long"; "shareEdit_error_auth_expired" = "Post failed, for authorization expired"; "shareEdit_error_auth_again" = "authorize again"; "shareEdit_error_text_repeated" = "Text repeated"; "shareEdit_error_user_baned" = "Sorry, you have been banned"; "shareEdit_error_fail" = "Share fail"; "shareEdit_error_no_auth" = "Share fail, for no upload picture authority"; "shareEdit_error_empty_content" = "Share fail, for the content is empty"; "shareEdit_addFollow" = "Follow weibo"; "shareEdit_C" = "符"; "shareEdit_used" = "常"; "shareShake_button" = "Share"; "share_wechat" = "Share to Wechat"; "share_wechat_friend" = "Share to Wechat Friend"; "share_wechat_moments" = "Share to Wechat Moments"; "share_wechat_no_title" = "No Wechat"; "share_wechat_no_message" = "Wechat haven't been install in your device"; "share_facebook_not_login" = "No login Account"; "share_facebook_not_login_message" = "Your account haven't login"; "share_facebook_no_osSupport" = "iOS doesn't support"; "share_facebook_no_osSupport_message" = "The version of your iOS device doesn't support share the that media"; "share_alipay" = "Share to AlipayShare"; "share_alipay_friend" = "Share to AlipayShare friends"; "share_alipay_moments" = "Share to AlipayShare Timeline"; "share_alipay_no_title" = "No Alipay"; "share_alipay_no_message" = "Alipay not installed in device"; "share_alipay_version_not_supported" = "The version of Alipay not supported."; "share_sms_no_osSupport" = "No SMS"; "share_sms_no_osSupport_message" = "The device doesn't support SMS"; "share_email_no_osSupport" = "No email"; "share_email_no_osSupport_message" = "Your email service have been turned off, please turn it on before you share your email"; "login_title" = "Login"; "login_as_tourists" = "Login as tourists"; "login_choose" = "choose your available account"; "commentList_title" = "Comment List"; "commentList_mask_text" = "Requesting comments, please wait……"; "commentList_comment_here" = "Comment here"; "commentDetail_title" = "Detail"; "commentEdit_no_location" = "No Location"; "commentEdit_post_fail" = "Post comment fail"; "commentEdit_post_success" = "Post comment success"; "commentEdit_noLocation_title" = "Location service have been turned off"; "commentEdit_noLocation_message" = "Your device's location service have been turned off, please turn on it before you share your location"; "commentEdit_title" = "New Comment"; "commentEdit_wait" = "Please wait"; "ego_pull_down" = "Pull down, refresh"; "ego_refresh" = "Loose to refresh"; "ego_load_more" = "Loose to load more"; "ego_pull_up" = "Pull up, load more"; "ego_refreshing" = "Refreshing"; "ego_loading_more" = "Loading more"; "loading" = "Loading"; "shareEdit_error_network_fail_message" = "Network Error"; "network_fail_title" = "Network Error"; "network_fail_message" = "The network state of your device is not available."; "account_title" = "User Center"; "account_title_authorize_status" = "authorize status"; "account_label_login_tourist" = "login as tourist"; "account_label_login_account" = "login account"; "account_lable_not_auth" = "not authorized"; "account_lable_have_auth" = "authorized"; "account_title_sns_config" = "sns accounts"; "sina" = "Sina"; "tencent" = "Tencent"; "renren" = "Renren"; "qzone" = "Qzone"; "qq_account" = "QQ Account"; "douban" = "Douban"; "wechat" = "Wechat"; "email" = "Email"; "sms" = "SMS"; "wechat_session" = "Wechat"; "wechat_timeline" = "Moments"; "alipay_session" = "Alipay"; "aliay_circle" = "LifeCircle"; "wechat_favorite" = "Wechat Favorite"; "facebook" = "Facebook"; "twitter" = "Twitter"; "mobile_qq" = "QQ"; "yx_session" = "YiXin"; "yx_timeline" = "YX Moments"; "lw_session" = "LaiWang"; "lw_timeline" = "LW News"; "instagram" = "Instagram"; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_4.4/zh-Hans.lproj/UMSocialLocalizable.strings ================================================ /* Localizable.strings SocialSDK Created by yeahugo on 13-6-17. Copyright (c) 2013年 Umeng. All rights reserved. */ "button_cancel" = "取消"; "button_ok" = "确定"; "button_start" = "开启"; "button_close" = "关闭"; "button_back" = "返回"; "button_refresh" = "刷新"; "label_request_account" = "正在获取账户信息,请稍等..."; "oauth_title" = "授权"; "oauth_text" = "正在连接授权页面,请稍等..."; "mask_text" = "正在获取数据,请稍等..."; "oauth_follow" = "关注官方微博"; "oauth_error_title" = "授权失败"; "oauth_error_message" = "服务器繁忙,授权失败,请稍后再试"; "oauth_error_not_approved" = "由于没有在开放平台添加此账号作为测试账号或者没有通过审核等原因授权失败"; "shareQQ_error" = "抱歉"; "shareQQ_notInstall" = "没有安装手机QQ客户端"; "shareQQ_openFail" = "打开手机QQ失败"; "shareClient_notInstall" = "没有安装客户端"; "shareInstagram_openFail" = "没有安装Instagram客户端"; "shareList_title" = "分享至"; "shareEdit_title" = "分享至"; "shareEdit_post" = "发布"; "shareEdit_change_account" = "切换账号"; "shareEdit_post_finish" = "发送成功"; "shareEdit_post_fail" = "发送失败"; "shareEdit_posting" = "正在发送"; "shareEdit_delete_picture" = "删除图片"; "shareEdit_delete_video" = "删除视频"; "shareEdit_delete_music" = "删除音乐"; "shareEdit_error_not_empty" = "分享内容不能为空"; "shareEdit_error_too_long" = "分享内容长度超出限制"; "shareEdit_error_auth_expired" = "授权过期,分享失败"; "shareEdit_error_auth_again" = "重新授权"; "shareEdit_error_text_repeated" = "内容重复,分享失败"; "shareEdit_error_user_baned" = "对不起,因为违反了用户协议您已被禁言"; "shareEdit_error_fail" = "分享失败"; "shareEdit_error_no_auth" = "无上传图片的权限,分享失败"; "shareEdit_error_empty_content" = "分享内容为空,分享失败"; "shareEdit_addFollow" = "关注官方微博"; "shareEdit_C" = "符"; "shareEdit_used" = "常"; "shareShake_button" = "分享"; "share_wechat" = "分享至微信"; "share_wechat_friend" = "分享至微信好友"; "share_wechat_moments" = "分享至微信朋友圈"; "share_wechat_no_title" = "温馨提示"; "share_wechat_no_message" = "您的设备没有安装微信"; "share_facebook_not_login" = "账号未登录"; "share_facebook_not_login_message" = "账号未登录"; "share_facebook_no_osSupport" = "系统不支持"; "share_facebook_no_osSupport_message" = "您的iOS系统版本过低,不支持分享到该平台"; "share_alipay" = "分享至支付宝"; "share_alipay_friend" = "分享至支付宝好友"; "share_alipay_moments" = "分享至支付宝生活圈"; "share_alipay_no_title" = "温馨提示"; "share_alipay_no_message" = "您的设备没有安装支付宝"; "share_alipay_version_not_supported" = "您的支付宝版本不支持分享"; "share_sms_no_osSupport" = "不支持短信"; "share_sms_no_osSupport_message" = "您的设备不支持短信功能"; "share_email_no_osSupport" = "邮件功能未开启"; "share_email_no_osSupport_message" = "您当前的邮件服务处于未启用状态,请先前往系统设置中配置邮件服务后,再进行分享"; "login_title" = "登录"; "login_as_tourists" = "游客身份"; "login_choose" = "选择已有账号登录"; "commentList_title" = "评论列表"; "commentList_mask_text" = "正在获取评论数据,请稍等..."; "commentList_comment_here" = "在这说点什么..."; "commentDetail_title" = "评论详情"; "commentEdit_no_location" = "取消定位"; "commentEdit_post_fail" = "评论失败"; "commentEdit_post_success" = "评论成功"; "commentEdit_noLocation_title" = "定位服务未开启"; "commentEdit_noLocation_message" = "您当前的定位服务处于关闭状态,或者没有对此应用开启地理位置服务,请先前往系统设置中开启本应用的定位服务,再进行分享"; "commentEdit_title" = "新评论"; "commentEdit_wait" = "评论发送中,请稍等..."; "ego_pull_down" = "下拉刷新"; "ego_pull_up" = "上拉加载更多"; "ego_refreshing" = "正在刷新"; "ego_loading_more" = "正在加载更多"; "ego_refresh" = "松开立即刷新"; "ego_loadmore" = "松开立即加载更多"; "shareEdit_error_network_fail_message" = "网络不给力,发送失败了"; "loading" = " 加载中 "; "network_fail_title" = "温馨提示"; "network_fail_message" = "当前网络不给力"; "account_title" = "个人中心"; "account_title_authorize_status" = "授权信息"; "account_label_login_tourist" = "游客登录"; "account_label_login_account" = "登录账号"; "account_lable_not_auth" = "尚未授权"; "account_lable_have_auth" = "已授权"; "account_title_sns_config" = "分享设置"; "sina" = "微博"; "tencent" = "腾讯微博"; "renren" = "人人网"; "qzone" = "QQ空间"; "qq_account" = "QQ 账号"; "douban" = "豆瓣"; "wechat" = "微信"; "email" = "邮箱"; "sms" = "短信"; "wechat_session" = "微信好友"; "wechat_timeline" = "朋友圈"; "wechat_favorite" = "微信收藏"; "alipay_session" = "支付宝好友"; "aliay_circle" = "生活圈"; "facebook" = "Facebook"; "twitter" = "Twitter"; "mobile_qq" = "QQ"; "yx_session" = "易信"; "yx_timeline" = "易信朋友圈"; "lw_session" = "来往"; "lw_timeline" = "来往动态"; "instagram" = "Instagram"; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/AlipayShare/APOpenAPI.h ================================================ // // APOpenAPI.h // 所有API接口 // // Created by Alipay on 15-4-15. // Copyright (c) 2015年 Alipay. All rights reserved. // #import #import "APOpenAPIObject.h" #pragma mark - APOpenAPIDelegate /*! @brief 接收并处理来自支付宝终端程序的事件消息 * * 接收并处理来自支付宝终端程序的事件消息,期间支付宝界面会切换到第三方应用程序。 * APOpenAPIDelegate 会在handleOpenURL:delegate:中使用并触发。 */ @protocol APOpenAPIDelegate @optional /*! @brief 收到一个来自支付宝的请求,第三方应用程序处理完后调用sendResp向支付宝发送结果 * * 收到一个来自支付宝的请求,异步处理完成后必须调用sendResp发送处理结果给支付宝。 * @param req 具体请求内容 */ -(void) onReq:(APBaseReq*)req; /*! @brief 发送一个sendReq后,收到支付宝的回应 * * 收到一个来自支付宝的处理结果。调用一次sendReq后会收到onResp。 * @param resp具体的回应内容 */ -(void) onResp:(APBaseResp*)resp; @end #pragma mark - APOpenAPI /*! @brief 支付宝API接口函数类 * * 该类封装了支付宝终端SDK的所有接口 */ @interface APOpenAPI : NSObject /*! @brief APOpenAPI的成员函数,向支付宝终端程序注册第三方应用。 * * 需要在每次启动第三方应用程序时调用。第一次调用后,会在支付宝的可用应用列表中出现。 * iOS7及以上系统需要调起一次支付宝才会出现在支付宝的可用应用列表中。 * @attention 请保证在主线程中调用此函数 * @param appid 支付宝开发者ID * @return 成功返回YES,失败返回NO。 */ +(BOOL) registerApp:(NSString *)appid; /*! @brief APOpenAPI的成员函数,向支付宝终端程序注册第三方应用。 * * 需要在每次启动第三方应用程序时调用。第一次调用后,会在支付宝的可用应用列表中出现。 * @see registerApp * @param appid 支付宝开发者ID * @param appdesc 应用附加信息,长度不超过1024字节 * @return 成功返回YES,失败返回NO。 */ +(BOOL) registerApp:(NSString *)appid withDescription:(NSString *)appdesc; /*! @brief 处理支付宝通过URL启动App时传递的数据 * * 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。 * @param url 支付宝启动第三方应用时传递过来的URL * @param delegate APOpenAPIDelegate对象,用来接收支付宝触发的消息。 * @return 成功返回YES,失败返回NO。 */ +(BOOL) handleOpenURL:(NSURL *) url delegate:(id) delegate; /*! @brief 检查支付宝是否已被用户安装 * * @return 支付宝已安装返回YES,未安装返回NO。 */ +(BOOL) isAPAppInstalled; /*! @brief 判断当前支付宝的版本是否支持OpenApi * * @return 支持返回YES,不支持返回NO。 */ +(BOOL) isAPAppSupportOpenApi; /*! @brief 获取支付宝的itunes安装地址 * * @return 支付宝的安装地址字符串。 */ +(NSString *) getAPAppInstallUrl; /*! @brief 获取当前支付宝SDK的版本号 * * @return 返回当前支付宝SDK的版本号 */ +(NSString *) getApiVersion; /*! @brief 打开支付宝 * * @return 成功返回YES,失败返回NO。 */ +(BOOL) openAPApp; /*! @brief 发送请求到支付宝,等待支付宝返回onResp * * 函数调用后,会切换到支付宝的界面。第三方应用程序等待支付宝返回onResp。支付宝在异步处理完成后一定会调用onResp。支持以下类型 * @param req 具体的发送请求,在调用函数后,请自己释放。 * @return 成功返回YES,失败返回NO。 */ +(BOOL) sendReq:(APBaseReq*)req; /*! @brief 收到支付宝onReq的请求,发送对应的应答给支付宝,并切换到支付宝界面 * * 函数调用后,会切换到支付宝的界面。第三方应用程序收到支付宝onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有 * @param resp 具体的应答内容,调用函数后,请自己释放 * @return 成功返回YES,失败返回NO。 */ +(BOOL) sendResp:(APBaseResp*)resp; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/AlipayShare/APOpenAPIObject.h ================================================ // // APOpenAPIObject.h // API对象,包含所有接口和对象数据定义 // // Created by Alipay on 15-4-15. // Copyright (c) 2015年 Alipay. All rights reserved. // #import #import // 错误码 typedef enum { APSuccess = 0, // 成功 APErrCodeCommon = -1, // 通用错误 APErrCodeUserCancel = -2, // 用户取消 APErrCodeSentFail = -3, // 发送失败 APErrCodeAuthDeny = -4, // 授权失败 APErrCodeUnsupport = -5, // 不支持 }APErrorCode; // 分享场景 typedef enum { APSceneSession = 0, // 会话 }APScene; #pragma mark - APBaseReq /*! @brief 该类为支付宝SDK所有请求类的基类 * */ @interface APBaseReq : NSObject /** 请求类型 */ @property (nonatomic, assign) int type; /** AppID,发送请求时第三方程序必须填写 */ @property (nonatomic, retain) NSString* openID; @end #pragma mark - APBaseResp /*! @brief 该类为SDK所有响应类的基类 * */ @interface APBaseResp : NSObject /** 错误码 */ @property (nonatomic, assign) int errCode; /** 错误提示字符串 */ @property (nonatomic, strong) NSString *errStr; /** 响应类型 */ @property (nonatomic, assign) int type; @property (nonatomic, strong) NSString *openID; @end #pragma mark - 发送消息到支付宝 /*! @brief 第三方程序发送消息至支付宝终端程序的消息结构体 * * 第三方程序向支付宝发送信息需要传入SendMessageToAPReq结构体,调用该方法后,支付宝处理完信息会向第三方程序发送一个处理结果。 * @see SendMessageToAPReq */ @class APMediaMessage; @interface APSendMessageToAPReq : APBaseReq // 发送消息的多媒体内容 @property (nonatomic, strong) APMediaMessage* message; @property (nonatomic, assign) APScene scene; @end /*! @brief 支付宝终端向第三方程序返回的SendMessageToAPReq处理结果。 * * 第三方程序向支付宝终端发送SendMessageToAPReq后,支付宝发送回来的处理结果,该结果用SendMessageToAPResp表示。 */ @interface APSendMessageToAPResp : APBaseResp @end #pragma mark - APMediaMessage /*! @brief 多媒体消息结构体 * * 用于支付宝终端和第三方程序之间传递消息的多媒体消息内容 */ @interface APMediaMessage : NSObject // 标题 @property (nonatomic, strong) NSString *title; // 描述内容 @property (nonatomic, strong) NSString *desc; // 缩略图数据 @property (nonatomic, strong) NSData *thumbData; @property (nonatomic, strong) NSString *thumbUrl; // 多媒体对象 @property (nonatomic, strong) id mediaObject; @end // 文本 @interface APShareTextObject : NSObject @property (nonatomic, strong) NSString *text; @end; // 图片 @interface APShareImageObject : NSObject @property (nonatomic, strong) NSData *imageData; @property (nonatomic, strong) NSString *imageUrl; @end; // 网页 @interface APShareWebObject : NSObject @property (nonatomic, strong) NSString *wepageUrl; @end; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/AlipayShare/UMSocialAlipayShareHandler.h ================================================ // // UMSocialAlipayShareHandler.h // SocialSDK // // Created by umeng on 11/4/15. // Copyright © 2015 Umeng. All rights reserved. // #import @interface UMSocialAlipayShareHandler : NSObject /** 设置支付宝AppId @param appId 支付宝appId */ + (void)setAlipayShareAppId:(NSString *)appId; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/FBSDKCoreKit ================================================ [File too large to display: 18.4 MB] ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKAccessToken.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import /*! @abstract Notification indicating that the `currentAccessToken` has changed. @discussion the userInfo dictionary of the notification will contain keys `FBSDKAccessTokenChangeOldKey` and `FBSDKAccessTokenChangeNewKey`. */ FBSDK_EXTERN NSString *const FBSDKAccessTokenDidChangeNotification; /*! @abstract A key in the notification's userInfo that will be set if and only if the user ID changed between the old and new tokens. @discussion Token refreshes can occur automatically with the SDK which do not change the user. If you're only interested in user changes (such as logging out), you should check for the existence of this key. The value is a NSNumber with a boolValue. On a fresh start of the app where the SDK reads in the cached value of an access token, this key will also exist since the access token is moving from a null state (no user) to a non-null state (user). */ FBSDK_EXTERN NSString *const FBSDKAccessTokenDidChangeUserID; /* @abstract key in notification's userInfo object for getting the old token. @discussion If there was no old token, the key will not be present. */ FBSDK_EXTERN NSString *const FBSDKAccessTokenChangeOldKey; /* @abstract key in notification's userInfo object for getting the new token. @discussion If there is no new token, the key will not be present. */ FBSDK_EXTERN NSString *const FBSDKAccessTokenChangeNewKey; /*! @class FBSDKAccessToken @abstract Represents an immutable access token for using Facebook services. */ @interface FBSDKAccessToken : NSObject /*! @abstract Returns the app ID. */ @property (readonly, copy, nonatomic) NSString *appID; /*! @abstract Returns the known declined permissions. */ @property (readonly, copy, nonatomic) NSSet *declinedPermissions; /*! @abstract Returns the expiration date. */ @property (readonly, copy, nonatomic) NSDate *expirationDate; /*! @abstract Returns the known granted permissions. */ @property (readonly, copy, nonatomic) NSSet *permissions; /*! @abstract Returns the date the token was last refreshed. */ @property (readonly, copy, nonatomic) NSDate *refreshDate; /*! @abstract Returns the opaque token string. */ @property (readonly, copy, nonatomic) NSString *tokenString; /*! @abstract Returns the user ID. */ @property (readonly, copy, nonatomic) NSString *userID; - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; /*! @abstract Initializes a new instance. @param tokenString the opaque token string. @param permissions the granted permissions. Note this is converted to NSSet and is only an NSArray for the convenience of literal syntax. @param declinedPermissions the declined permissions. Note this is converted to NSSet and is only an NSArray for the convenience of literal syntax. @param appID the app ID. @param userID the user ID. @param expirationDate the optional expiration date (defaults to distantFuture). @param refreshDate the optional date the token was last refreshed (defaults to today). @discussion This initializer should only be used for advanced apps that manage tokens explicitly. Typical login flows only need to use `FBSDKLoginManager` along with `+currentAccessToken`. */ - (instancetype)initWithTokenString:(NSString *)tokenString permissions:(NSArray *)permissions declinedPermissions:(NSArray *)declinedPermissions appID:(NSString *)appID userID:(NSString *)userID expirationDate:(NSDate *)expirationDate refreshDate:(NSDate *)refreshDate NS_DESIGNATED_INITIALIZER; /*! @abstract Convenience getter to determine if a permission has been granted @param permission The permission to check. */ - (BOOL)hasGranted:(NSString *)permission; /*! @abstract Compares the receiver to another FBSDKAccessToken @param token The other token @return YES if the receiver's values are equal to the other token's values; otherwise NO */ - (BOOL)isEqualToAccessToken:(FBSDKAccessToken *)token; /*! @abstract Returns the "global" access token that represents the currently logged in user. @discussion The `currentAccessToken` is a convenient representation of the token of the current user and is used by other SDK components (like `FBSDKLoginManager`). */ + (FBSDKAccessToken *)currentAccessToken; /*! @abstract Sets the "global" access token that represents the currently logged in user. @param token The access token to set. @discussion This will broadcast a notification and save the token to the app keychain. */ + (void)setCurrentAccessToken:(FBSDKAccessToken *)token; /*! @abstract Refresh the current access token's permission state and extend the token's expiration date, if possible. @param completionHandler an optional callback handler that can surface any errors related to permission refreshing. @discussion On a successful refresh, the currentAccessToken will be updated so you typically only need to observe the `FBSDKAccessTokenDidChangeNotification` notification. If a token is already expired, it cannot be refreshed. */ + (void)refreshCurrentAccessToken:(FBSDKGraphRequestHandler)completionHandler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKAppEvents.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import "FBSDKMacros.h" @class FBSDKAccessToken; @class FBSDKGraphRequest; /*! @abstract NSNotificationCenter name indicating a result of a failed log flush attempt. The posted object will be an NSError instance. */ FBSDK_EXTERN NSString *const FBSDKAppEventsLoggingResultNotification; /*! @abstract optional plist key ("FacebookLoggingOverrideAppID") for setting `loggingOverrideAppID` */ FBSDK_EXTERN NSString *const FBSDKAppEventsOverrideAppIDBundleKey; /*! @typedef NS_ENUM (NSUInteger, FBSDKAppEventsFlushBehavior) @abstract Specifies when `FBSDKAppEvents` sends log events to the server. */ typedef NS_ENUM(NSUInteger, FBSDKAppEventsFlushBehavior) { /*! Flush automatically: periodically (once a minute or every 100 logged events) and always at app reactivation. */ FBSDKAppEventsFlushBehaviorAuto = 0, /*! Only flush when the `flush` method is called. When an app is moved to background/terminated, the events are persisted and re-established at activation, but they will only be written with an explicit call to `flush`. */ FBSDKAppEventsFlushBehaviorExplicitOnly, }; /*! @methodgroup Predefined event names for logging events common to many apps. Logging occurs through the `logEvent` family of methods on `FBSDKAppEvents`. Common event parameters are provided in the `FBSDKAppEventsParameterNames*` constants. */ /*! Log this event when the user has achieved a level in the app. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameAchievedLevel; /*! Log this event when the user has entered their payment info. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameAddedPaymentInfo; /*! Log this event when the user has added an item to their cart. The valueToSum passed to logEvent should be the item's price. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameAddedToCart; /*! Log this event when the user has added an item to their wishlist. The valueToSum passed to logEvent should be the item's price. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameAddedToWishlist; /*! Log this event when a user has completed registration with the app. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameCompletedRegistration; /*! Log this event when the user has completed a tutorial in the app. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameCompletedTutorial; /*! Log this event when the user has entered the checkout process. The valueToSum passed to logEvent should be the total price in the cart. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameInitiatedCheckout; /*! Log this event when the user has rated an item in the app. The valueToSum passed to logEvent should be the numeric rating. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameRated; /*! Log this event when a user has performed a search within the app. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameSearched; /*! Log this event when the user has spent app credits. The valueToSum passed to logEvent should be the number of credits spent. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameSpentCredits; /*! Log this event when the user has unlocked an achievement in the app. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameUnlockedAchievement; /*! Log this event when a user has viewed a form of content in the app. */ FBSDK_EXTERN NSString *const FBSDKAppEventNameViewedContent; /*! @methodgroup Predefined event name parameters for common additional information to accompany events logged through the `logEvent` family of methods on `FBSDKAppEvents`. Common event names are provided in the `FBAppEventName*` constants. */ /*! Parameter key used to specify an ID for the specific piece of content being logged about. Could be an EAN, article identifier, etc., depending on the nature of the app. */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameContentID; /*! Parameter key used to specify a generic content type/family for the logged event, e.g. "music", "photo", "video". Options to use will vary based upon what the app is all about. */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameContentType; /*! Parameter key used to specify currency used with logged event. E.g. "USD", "EUR", "GBP". See ISO-4217 for specific values. One reference for these is . */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameCurrency; /*! Parameter key used to specify a description appropriate to the event being logged. E.g., the name of the achievement unlocked in the `FBAppEventNameAchievementUnlocked` event. */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameDescription; /*! Parameter key used to specify the level achieved in a `FBAppEventNameAchieved` event. */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameLevel; /*! Parameter key used to specify the maximum rating available for the `FBAppEventNameRate` event. E.g., "5" or "10". */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameMaxRatingValue; /*! Parameter key used to specify how many items are being processed for an `FBAppEventNameInitiatedCheckout` or `FBAppEventNamePurchased` event. */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameNumItems; /*! Parameter key used to specify whether payment info is available for the `FBAppEventNameInitiatedCheckout` event. `FBSDKAppEventParameterValueYes` and `FBSDKAppEventParameterValueNo` are good canonical values to use for this parameter. */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNamePaymentInfoAvailable; /*! Parameter key used to specify method user has used to register for the app, e.g., "Facebook", "email", "Twitter", etc */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameRegistrationMethod; /*! Parameter key used to specify the string provided by the user for a search operation. */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameSearchString; /*! Parameter key used to specify whether the activity being logged about was successful or not. `FBSDKAppEventParameterValueYes` and `FBSDKAppEventParameterValueNo` are good canonical values to use for this parameter. */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterNameSuccess; /* @methodgroup Predefined values to assign to event parameters that accompany events logged through the `logEvent` family of methods on `FBSDKAppEvents`. Common event parameters are provided in the `FBSDKAppEventParameterName*` constants. */ /*! Yes-valued parameter value to be used with parameter keys that need a Yes/No value */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterValueYes; /*! No-valued parameter value to be used with parameter keys that need a Yes/No value */ FBSDK_EXTERN NSString *const FBSDKAppEventParameterValueNo; /*! @class FBSDKAppEvents @abstract Client-side event logging for specialized application analytics available through Facebook App Insights and for use with Facebook Ads conversion tracking and optimization. @discussion The `FBSDKAppEvents` static class has a few related roles: + Logging predefined and application-defined events to Facebook App Insights with a numeric value to sum across a large number of events, and an optional set of key/value parameters that define "segments" for this event (e.g., 'purchaserStatus' : 'frequent', or 'gamerLevel' : 'intermediate') + Logging events to later be used for ads optimization around lifetime value. + Methods that control the way in which events are flushed out to the Facebook servers. Here are some important characteristics of the logging mechanism provided by `FBSDKAppEvents`: + Events are not sent immediately when logged. They're cached and flushed out to the Facebook servers in a number of situations: - when an event count threshold is passed (currently 100 logged events). - when a time threshold is passed (currently 15 seconds). - when an app has gone to background and is then brought back to the foreground. + Events will be accumulated when the app is in a disconnected state, and sent when the connection is restored and one of the above 'flush' conditions are met. + The `FBSDKAppEvents` class is thread-safe in that events may be logged from any of the app's threads. + The developer can set the `flushBehavior` on `FBSDKAppEvents` to force the flushing of events to only occur on an explicit call to the `flush` method. + The developer can turn on console debug output for event logging and flushing to the server by using the `FBSDKLoggingBehaviorAppEvents` value in `[FBSettings setLoggingBehavior:]`. Some things to note when logging events: + There is a limit on the number of unique event names an app can use, on the order of 1000. + There is a limit to the number of unique parameter names in the provided parameters that can be used per event, on the order of 25. This is not just for an individual call, but for all invocations for that eventName. + Event names and parameter names (the keys in the NSDictionary) must be between 2 and 40 characters, and must consist of alphanumeric characters, _, -, or spaces. + The length of each parameter value can be no more than on the order of 100 characters. */ @interface FBSDKAppEvents : NSObject /* * Basic event logging */ /*! @abstract Log an event with just an eventName. @param eventName The name of the event to record. Limitations on number of events and name length are given in the `FBSDKAppEvents` documentation. */ + (void)logEvent:(NSString *)eventName; /*! @abstract Log an event with an eventName and a numeric value to be aggregated with other events of this name. @param eventName The name of the event to record. Limitations on number of events and name length are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants. @param valueToSum Amount to be aggregated into all events of this eventName, and App Insights will report the cumulative and average value of this amount. */ + (void)logEvent:(NSString *)eventName valueToSum:(double)valueToSum; /*! @abstract Log an event with an eventName and a set of key/value pairs in the parameters dictionary. Parameter limitations are described above. @param eventName The name of the event to record. Limitations on number of events and name construction are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants. @param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names are provided in `FBSDKAppEventParameterName*` constants. */ + (void)logEvent:(NSString *)eventName parameters:(NSDictionary *)parameters; /*! @abstract Log an event with an eventName, a numeric value to be aggregated with other events of this name, and a set of key/value pairs in the parameters dictionary. @param eventName The name of the event to record. Limitations on number of events and name construction are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants. @param valueToSum Amount to be aggregated into all events of this eventName, and App Insights will report the cumulative and average value of this amount. @param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names are provided in `FBSDKAppEventParameterName*` constants. */ + (void)logEvent:(NSString *)eventName valueToSum:(double)valueToSum parameters:(NSDictionary *)parameters; /*! @abstract Log an event with an eventName, a numeric value to be aggregated with other events of this name, and a set of key/value pairs in the parameters dictionary. Providing session lets the developer target a particular . If nil is provided, then `[FBSession activeSession]` will be used. @param eventName The name of the event to record. Limitations on number of events and name construction are given in the `FBSDKAppEvents` documentation. Common event names are provided in `FBAppEventName*` constants. @param valueToSum Amount to be aggregated into all events of this eventName, and App Insights will report the cumulative and average value of this amount. Note that this is an NSNumber, and a value of `nil` denotes that this event doesn't have a value associated with it for summation. @param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names are provided in `FBSDKAppEventParameterName*` constants. @param accessToken The optional access token to log the event as. */ + (void)logEvent:(NSString *)eventName valueToSum:(NSNumber *)valueToSum parameters:(NSDictionary *)parameters accessToken:(FBSDKAccessToken *)accessToken; /* * Purchase logging */ /*! @abstract Log a purchase of the specified amount, in the specified currency. @param purchaseAmount Purchase amount to be logged, as expressed in the specified currency. This value will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346). @param currency Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for specific values. One reference for these is . @discussion This event immediately triggers a flush of the `FBSDKAppEvents` event queue, unless the `flushBehavior` is set to `FBSDKAppEventsFlushBehaviorExplicitOnly`. */ + (void)logPurchase:(double)purchaseAmount currency:(NSString *)currency; /*! @abstract Log a purchase of the specified amount, in the specified currency, also providing a set of additional characteristics describing the purchase. @param purchaseAmount Purchase amount to be logged, as expressed in the specified currency.This value will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346). @param currency Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for specific values. One reference for these is . @param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names are provided in `FBSDKAppEventParameterName*` constants. @discussion This event immediately triggers a flush of the `FBSDKAppEvents` event queue, unless the `flushBehavior` is set to `FBSDKAppEventsFlushBehaviorExplicitOnly`. */ + (void)logPurchase:(double)purchaseAmount currency:(NSString *)currency parameters:(NSDictionary *)parameters; /*! @abstract Log a purchase of the specified amount, in the specified currency, also providing a set of additional characteristics describing the purchase, as well as an to log to. @param purchaseAmount Purchase amount to be logged, as expressed in the specified currency.This value will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346). @param currency Currency, is denoted as, e.g. "USD", "EUR", "GBP". See ISO-4217 for specific values. One reference for these is . @param parameters Arbitrary parameter dictionary of characteristics. The keys to this dictionary must be NSString's, and the values are expected to be NSString or NSNumber. Limitations on the number of parameters and name construction are given in the `FBSDKAppEvents` documentation. Commonly used parameter names are provided in `FBSDKAppEventParameterName*` constants. @param accessToken The optional access token to log the event as. @discussion This event immediately triggers a flush of the `FBSDKAppEvents` event queue, unless the `flushBehavior` is set to `FBSDKAppEventsFlushBehaviorExplicitOnly`. */ + (void)logPurchase:(double)purchaseAmount currency:(NSString *)currency parameters:(NSDictionary *)parameters accessToken:(FBSDKAccessToken *)accessToken; /*! @abstract Notifies the events system that the app has launched and, when appropriate, logs an "activated app" event. Should typically be placed in the app delegates' `applicationDidBecomeActive:` method. This method also takes care of logging the event indicating the first time this app has been launched, which, among other things, is used to track user acquisition and app install ads conversions. @discussion `activateApp` will not log an event on every app launch, since launches happen every time the app is backgrounded and then foregrounded. "activated app" events will be logged when the app has not been active for more than 60 seconds. This method also causes a "deactivated app" event to be logged when sessions are "completed", and these events are logged with the session length, with an indication of how much time has elapsed between sessions, and with the number of background/foreground interruptions that session had. This data is all visible in your app's App Events Insights. */ + (void)activateApp; /* * Control over event batching/flushing */ /*! @abstract Get the current event flushing behavior specifying when events are sent back to Facebook servers. */ + (FBSDKAppEventsFlushBehavior)flushBehavior; /*! @abstract Set the current event flushing behavior specifying when events are sent back to Facebook servers. @param flushBehavior The desired `FBSDKAppEventsFlushBehavior` to be used. */ + (void)setFlushBehavior:(FBSDKAppEventsFlushBehavior)flushBehavior; /*! @abstract Set the 'override' App ID for App Event logging. @discussion In some cases, apps want to use one Facebook App ID for login and social presence and another for App Event logging. (An example is if multiple apps from the same company share an app ID for login, but want distinct logging.) By default, this value is `nil`, and defers to the `FBSDKAppEventsOverrideAppIDBundleKey` plist value. If that's not set, it defaults to `[FBSDKSettings appID]`. This should be set before any other calls are made to `FBSDKAppEvents`. Thus, you should set it in your application delegate's `application:didFinishLaunchingWithOptions:` delegate. @param appID The Facebook App ID to be used for App Event logging. */ + (void)setLoggingOverrideAppID:(NSString *)appID; /*! @abstract Get the 'override' App ID for App Event logging. @see setLoggingOverrideAppID: */ + (NSString *)loggingOverrideAppID; /*! @abstract Explicitly kick off flushing of events to Facebook. This is an asynchronous method, but it does initiate an immediate kick off. Server failures will be reported through the NotificationCenter with notification ID `FBSDKAppEventsLoggingResultNotification`. */ + (void)flush; /*! @abstract Creates a request representing the Graph API call to retrieve a Custom Audience "third party ID" for the app's Facebook user. Callers will send this ID back to their own servers, collect up a set to create a Facebook Custom Audience with, and then use the resultant Custom Audience to target ads. @param accessToken The access token to use to establish the user's identity for users logged into Facebook through this app. If `nil`, then the `[FBSDKAccessToken currentAccessToken]` is used. @discussion The JSON in the request's response will include an "custom_audience_third_party_id" key/value pair, with the value being the ID retrieved. This ID is an encrypted encoding of the Facebook user's ID and the invoking Facebook app ID. Multiple calls with the same user will return different IDs, thus these IDs cannot be used to correlate behavior across devices or applications, and are only meaningful when sent back to Facebook for creating Custom Audiences. The ID retrieved represents the Facebook user identified in the following way: if the specified access token is valid, the ID will represent the user associated with that token; otherwise the ID will represent the user logged into the native Facebook app on the device. If there is no native Facebook app, no one is logged into it, or the user has opted out at the iOS level from ad tracking, then a `nil` ID will be returned. This method returns `nil` if either the user has opted-out (via iOS) from Ad Tracking, the app itself has limited event usage via the `[FBSDKSettings limitEventAndDataUsage]` flag, or a specific Facebook user cannot be identified. */ + (FBSDKGraphRequest *)requestForCustomAudienceThirdPartyIDWithAccessToken:(FBSDKAccessToken *)accessToken; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKAppLinkResolver.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @class BFTask; // Check if Bolts.framework is available for import #if __has_include() // Import it if it's available # import #else // Otherwise - redeclare BFAppLinkResolving protocol to resolve the problem of missing symbols // Please note: Bolts.framework is still required for AppLink resolving to work, // but this allows FBSDKCoreKit to weakly link Bolts.framework as well as this enables clang modulemaps to work. /*! Implement this protocol to provide an alternate strategy for resolving App Links that may include pre-fetching, caching, or querying for App Link data from an index provided by a service provider. */ @protocol BFAppLinkResolving /*! Asynchronously resolves App Link data for a given URL. @param url The URL to resolve into an App Link. @returns A BFTask that will return a BFAppLink for the given URL. */ - (BFTask *)appLinkFromURLInBackground:(NSURL *)url; @end #endif /*! @class FBSDKAppLinkResolver @abstract Provides an implementation of the BFAppLinkResolving protocol that uses the Facebook App Link Index API to resolve App Links given a URL. It also provides an additional helper method that can resolve multiple App Links in a single call. @discussion Usage of this type requires a client token. See `[FBSDKSettings setClientToken:]` and linking Bolts.framework */ @interface FBSDKAppLinkResolver : NSObject /*! @abstract Asynchronously resolves App Link data for multiple URLs. @param urls An array of NSURLs to resolve into App Links. @returns A BFTask that will return dictionary mapping input NSURLs to their corresponding BFAppLink. @discussion You should set the client token before making this call. See `[FBSDKSettings setClientToken:]` */ - (BFTask *)appLinksFromURLsInBackground:(NSArray *)urls; /*! @abstract Allocates and initializes a new instance of FBSDKAppLinkResolver. */ + (instancetype)resolver; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKAppLinkUtility.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @abstract Describes the callback for fetchDeferredAppLink. @param url the url representing the deferred App Link @param error the error during the request, if any @discussion The url may also have a fb_click_time_utc query parameter that represents when the click occurred that caused the deferred App Link to be created. */ typedef void (^FBSDKDeferredAppLinkHandler)(NSURL *url, NSError *error); /*! @abstract Class containing App Links related utility methods. */ @interface FBSDKAppLinkUtility : NSObject /*! @abstract Call this method from the main thread to fetch deferred applink data if you use Mobile App Engagement Ads (https://developers.facebook.com/docs/ads-for-apps/mobile-app-ads-engagement). This may require a network round trip. If successful, the handler is invoked with the link data (this will only return a valid URL once, and future calls will result in a nil URL value in the callback). @param handler the handler to be invoked if there is deferred App Link data @discussion The handler may contain an NSError instance to capture any errors. In the common case where there simply was no app link data, the NSError instance will be nil. This method should only be called from a location that occurs after any launching URL has been processed (e.g., you should call this method from your application delegate's applicationDidBecomeActive:). */ + (void)fetchDeferredAppLink:(FBSDKDeferredAppLinkHandler)handler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKApplicationDelegate.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @class FBSDKApplicationDelegate @abstract The FBSDKApplicationDelegate is designed to post process the results from Facebook Login or Facebook Dialogs (or any action that requires switching over to the native Facebook app or Safari). @discussion The methods in this class are designed to mirror those in UIApplicationDelegate, and you should call them in the respective methods in your AppDelegate implementation. */ @interface FBSDKApplicationDelegate : NSObject /*! @abstract Gets the singleton instance. */ + (instancetype)sharedInstance; /*! @abstract Call this method from the [UIApplicationDelegate application:openURL:sourceApplication:annotation:] method of the AppDelegate for your app. It should be invoked for the proper processing of responses during interaction with the native Facebook app or Safari as part of SSO authorization flow or Facebook dialogs. @param application The application as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. @param url The URL as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. @param sourceApplication The sourceApplication as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. @param annotation The annotation as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. @return YES if the url was intended for the Facebook SDK, NO if not. */ - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; /*! @abstract Call this method from the [UIApplicationDelegate application:didFinishLaunchingWithOptions:] method of the AppDelegate for your app. It should be invoked for the proper use of the Facebook SDK. @param application The application as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. @param launchOptions The launchOptions as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. @return YES if the url was intended for the Facebook SDK, NO if not. */ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKButton.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @abstract A base class for common SDK buttons. */ @interface FBSDKButton : UIButton @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKConstants.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract The error domain for all errors from FBSDKCoreKit. @discussion Error codes from the SDK in the range 0-99 are reserved for this domain. */ FBSDK_EXTERN NSString *const FBSDKErrorDomain; /*! @typedef NS_ENUM(NSInteger, FBSDKErrorCode) @abstract Error codes for FBSDKErrorDomain. */ typedef NS_ENUM(NSInteger, FBSDKErrorCode) { /*! @abstract Reserved. */ FBSDKReservedErrorCode = 0, /*! @abstract The error code for errors from invalid encryption on incoming encryption URLs. */ FBSDKEncryptionErrorCode, /*! @abstract The error code for errors from invalid arguments to SDK methods. */ FBSDKInvalidArgumentErrorCode, /*! @abstract The error code for unknown errors. */ FBSDKUnknownErrorCode, /*! @abstract A request failed due to a network error. Use NSUnderlyingErrorKey to retrieve the error object from the NSURLConnection for more information. */ FBSDKNetworkErrorCode, /*! @abstract The error code for errors encounted during an App Events flush. */ FBSDKAppEventsFlushErrorCode, /*! @abstract An endpoint that returns a binary response was used with FBSDKGraphRequestConnection. @discussion Endpoints that return image/jpg, etc. should be accessed using NSURLRequest */ FBSDKGraphRequestNonTextMimeTypeReturnedErrorCode, /*! @abstract The operation failed because the server returned an unexpected response. @discussion You can get this error if you are not using the most recent SDK, or you are accessing a version of the Graph API incompatible with the current SDK. */ FBSDKGraphRequestProtocolMismatchErrorCode, /*! @abstract The Graph API returned an error. @discussion See below for useful userInfo keys (beginning with FBSDKGraphRequestError*) */ FBSDKGraphRequestGraphAPIErrorCode, /*! @abstract The specified dialog configuration is not available. @discussion This error may signify that the configuration for the dialogs has not yet been downloaded from the server or that the dialog is unavailable. Subsequent attempts to use the dialog may succeed as the configuration is loaded. */ FBSDKDialogUnavailableErrorCode, /*! @abstract Indicates an operation failed because a required access token was not found. */ FBSDKAccessTokenRequiredErrorCode, /*! @abstract Indicates an app switch (typically for a dialog) failed because the destination app is out of date. */ FBSDKAppVersionUnsupportedErrorCode, /*! @abstract Indicates an app switch to the browser (typically for a dialog) failed. */ FBSDKBrowswerUnavailableErrorCode, }; /*! @typedef NS_ENUM(NSUInteger, FBSDKGraphRequestErrorCategory) @abstract Describes the category of Facebook error. See `FBSDKGraphRequestErrorCategoryKey`. */ typedef NS_ENUM(NSUInteger, FBSDKGraphRequestErrorCategory) { /*! The default error category that is not known to be recoverable. Check `FBSDKLocalizedErrorDescriptionKey` for a user facing message. */ FBSDKGraphRequestErrorCategoryOther = 0, /*! Indicates the error is temporary (such as server throttling). While a recoveryAttempter will be provided with the error instance, the attempt is guaranteed to succeed so you can simply retry the operation if you do not want to present an alert. */ FBSDKGraphRequestErrorCategoryTransient = 1, /*! Indicates the error can be recovered (such as requiring a login). A recoveryAttempter will be provided with the error instance that can take UI action. */ FBSDKGraphRequestErrorCategoryRecoverable = 2 }; /* @methodgroup error userInfo keys */ /*! @abstract The userInfo key for the invalid collection for errors with FBSDKInvalidArgumentErrorCode. @discussion If the invalid argument is a collection, the collection can be found with this key and the individual invalid item can be found with FBSDKErrorArgumentValueKey. */ FBSDK_EXTERN NSString *const FBSDKErrorArgumentCollectionKey; /*! @abstract The userInfo key for the invalid argument name for errors with FBSDKInvalidArgumentErrorCode. */ FBSDK_EXTERN NSString *const FBSDKErrorArgumentNameKey; /*! @abstract The userInfo key for the invalid argument value for errors with FBSDKInvalidArgumentErrorCode. */ FBSDK_EXTERN NSString *const FBSDKErrorArgumentValueKey; /*! @abstract The userInfo key for the message for developers in NSErrors that originate from the SDK. @discussion The developer message will not be localized and is not intended to be presented within the app. */ FBSDK_EXTERN NSString *const FBSDKErrorDeveloperMessageKey; /*! @abstract The userInfo key describing a localized description that can be presented to the user. */ FBSDK_EXTERN NSString *const FBSDKErrorLocalizedDescriptionKey; /*! @abstract The userInfo key describing a localized title that can be presented to the user, used with `FBSDKLocalizedErrorDescriptionKey`. */ FBSDK_EXTERN NSString *const FBSDKErrorLocalizedTitleKey; /* @methodgroup FBSDKGraphRequest error userInfo keys */ /*! @abstract The userInfo key describing the error category, for error recovery purposes. @discussion See `FBSDKGraphErrorRecoveryProcessor` and `[FBSDKGraphRequest disableErrorRecovery]`. */ FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorCategoryKey; /* @abstract The userInfo key for the Graph API error code. */ FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorGraphErrorCode; /* @abstract The userInfo key for the Graph API error subcode. */ FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorGraphErrorSubcode; /* @abstract The userInfo key for the HTTP status code. */ FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorHTTPStatusCodeKey; /* @abstract The userInfo key for the raw JSON response. */ FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorParsedJSONResponseKey; /*! @abstract a formal protocol very similar to the informal protocol NSErrorRecoveryAttempting */ @protocol FBSDKErrorRecoveryAttempting /*! @abstract attempt the recovery @param error the error @param recoveryOptionIndex the selected option index @param delegate the delegate @param didRecoverSelector the callback selector, see discussion. @param contextInfo context info to pass back to callback selector, see discussion. @discussion Given that an error alert has been presented document-modally to the user, and the user has chosen one of the error's recovery options, attempt recovery from the error, and send the selected message to the specified delegate. The option index is an index into the error's array of localized recovery options. The method selected by didRecoverSelector must have the same signature as: - (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo; The value passed for didRecover must be YES if error recovery was completely successful, NO otherwise. */ - (void)attemptRecoveryFromError:(NSError *)error optionIndex:(NSUInteger)recoveryOptionIndex delegate:(id)delegate didRecoverSelector:(SEL)didRecoverSelector contextInfo:(void *)contextInfo; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKCopying.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @abstract Extension protocol for NSCopying that adds the copy method, which is implemented on NSObject. @discussion NSObject implicitly conforms to this protocol. */ @protocol FBSDKCopying /*! @abstract Implemented by NSObject as a convenience to copyWithZone:. @return A copy of the receiver. */ - (id)copy; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKCoreKit.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #define FBSDK_VERSION_STRING @"4.7.0" #define FBSDK_TARGET_PLATFORM_VERSION @"v2.5" ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKGraphErrorRecoveryProcessor.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import "FBSDKConstants.h" @class FBSDKGraphErrorRecoveryProcessor; @class FBSDKGraphRequest; /*! @abstract Defines a delegate for `FBSDKGraphErrorRecoveryProcessor`. */ @protocol FBSDKGraphErrorRecoveryProcessorDelegate /*! @abstract Indicates the error recovery has been attempted. @param processor the processor instance. @param didRecover YES if the recovery was successful. @param error the error that that was attempted to be recovered from. */ - (void)processorDidAttemptRecovery:(FBSDKGraphErrorRecoveryProcessor *)processor didRecover:(BOOL)didRecover error:(NSError *)error; @optional /*! @abstract Indicates the processor is about to process the error. @param processor the processor instance. @param error the error is about to be processed. @discussion return NO if the processor should not process the error. For example, if you want to prevent alerts of localized messages but otherwise perform retries and recoveries, you could return NO for errors where userInfo[FBSDKGraphRequestErrorCategoryKey] equal to FBSDKGraphRequestErrorCategoryOther */ - (BOOL)processorWillProcessError:(FBSDKGraphErrorRecoveryProcessor *)processor error:(NSError *)error; @end /*! @abstract Defines a type that can process Facebook NSErrors with best practices. @discussion Facebook NSErrors can contain FBSDKErrorRecoveryAttempting instances to recover from errors, or localized messages to present to the user. This class will process the instances as follows: 1. If the error is temporary as indicated by FBSDKGraphRequestErrorCategoryKey, assume the recovery succeeded and notify the delegate. 2. If a FBSDKErrorRecoveryAttempting instance is available, display an alert (dispatched to main thread) with the recovery options and call the instance's [ attemptRecoveryFromError:optionIndex:...]. 3. If a FBSDKErrorRecoveryAttempting is not available, check the userInfo for FBSDKLocalizedErrorDescriptionKey and present that in an alert (dispatched to main thread). By default, FBSDKGraphRequests use this type to process errors and retry the request upon a successful recovery. Note that Facebook recovery attempters can present UI or even cause app switches (such as to login). Any such work is dispatched to the main thread (therefore your request handlers may then run on the main thread). Login recovery requires FBSDKLoginKit. Login will use FBSDKLoginBehaviorNative and will prompt the user for all permissions last granted. If any are declined on the new request, the recovery is not successful but the `[FBSDKAccessToken currentAccessToken]` might still have been updated. . */ @interface FBSDKGraphErrorRecoveryProcessor : NSObject /*! @abstract Gets the delegate. Note this is a strong reference, and is nil'ed out after recovery is complete. */ @property (nonatomic, strong, readonly) iddelegate; /*! @abstract Attempts to process the error, return YES if the error can be processed. @param error the error to process. @param request the relateed request that may be reissued. @param delegate the delegate that will be retained until recovery is complete. */ - (BOOL)processError:(NSError *)error request:(FBSDKGraphRequest *)request delegate:(id) delegate; /*! @abstract The callback for FBSDKErrorRecoveryAttempting @param didRecover if the recovery succeeded @param contextInfo unused */ - (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKGraphRequest.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import @class FBSDKAccessToken; /*! @abstract Represents a request to the Facebook Graph API. @discussion `FBSDKGraphRequest` encapsulates the components of a request (the Graph API path, the parameters, error recovery behavior) and should be used in conjunction with `FBSDKGraphRequestConnection` to issue the request. Nearly all Graph APIs require an access token. Unless specified, the `[FBSDKAccessToken currentAccessToken]` is used. Therefore, most requests will require login first (see `FBSDKLoginManager` in FBSDKLoginKit.framework). A `- start` method is provided for convenience for single requests. By default, FBSDKGraphRequest will attempt to recover any errors returned from Facebook. You can disable this via `disableErrorRecovery:`. @see FBSDKGraphErrorRecoveryProcessor */ @interface FBSDKGraphRequest : NSObject /*! @abstract Initializes a new instance that use use `[FBSDKAccessToken currentAccessToken]`. @param graphPath the graph path (e.g., @"me"). @param parameters the optional parameters dictionary. */ - (instancetype)initWithGraphPath:(NSString *)graphPath parameters:(NSDictionary *)parameters; /*! @abstract Initializes a new instance that use use `[FBSDKAccessToken currentAccessToken]`. @param graphPath the graph path (e.g., @"me"). @param parameters the optional parameters dictionary. @param HTTPMethod the optional HTTP method. nil defaults to @"GET". */ - (instancetype)initWithGraphPath:(NSString *)graphPath parameters:(NSDictionary *)parameters HTTPMethod:(NSString *)HTTPMethod; /*! @abstract Initializes a new instance. @param graphPath the graph path (e.g., @"me"). @param parameters the optional parameters dictionary. @param tokenString the token string to use. Specifying nil will cause no token to be used. @param version the optional Graph API version (e.g., @"v2.0"). nil defaults to FBSDK_TARGET_PLATFORM_VERSION. @param HTTPMethod the optional HTTP method (e.g., @"POST"). nil defaults to @"GET". */ - (instancetype)initWithGraphPath:(NSString *)graphPath parameters:(NSDictionary *)parameters tokenString:(NSString *)tokenString version:(NSString *)version HTTPMethod:(NSString *)HTTPMethod NS_DESIGNATED_INITIALIZER; /*! @abstract The request parameters. */ @property (nonatomic, strong, readonly) NSMutableDictionary *parameters; /*! @abstract The access token string used by the request. */ @property (nonatomic, copy, readonly) NSString *tokenString; /*! @abstract The Graph API endpoint to use for the request, for example "me". */ @property (nonatomic, copy, readonly) NSString *graphPath; /*! @abstract The HTTPMethod to use for the request, for example "GET" or "POST". */ @property (nonatomic, copy, readonly) NSString *HTTPMethod; /*! @abstract The Graph API version to use (e.g., "v2.0") */ @property (nonatomic, copy, readonly) NSString *version; /*! @abstract If set, disables the automatic error recovery mechanism. @param disable whether to disable the automatic error recovery mechanism @discussion By default, non-batched FBSDKGraphRequest instances will automatically try to recover from errors by constructing a `FBSDKGraphErrorRecoveryProcessor` instance that re-issues the request on successful recoveries. The re-issued request will call the same handler as the receiver but may occur with a different `FBSDKGraphRequestConnection` instance. This will override [FBSDKSettings setGraphErrorRecoveryDisabled:]. */ - (void)setGraphErrorRecoveryDisabled:(BOOL)disable; /*! @abstract Starts a connection to the Graph API. @param handler The handler block to call when the request completes. */ - (FBSDKGraphRequestConnection *)startWithCompletionHandler:(FBSDKGraphRequestHandler)handler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKGraphRequestConnection.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import @class FBSDKGraphRequest; @class FBSDKGraphRequestConnection; /*! @typedef FBSDKGraphRequestHandler @abstract A block that is passed to addRequest to register for a callback with the results of that request once the connection completes. @discussion Pass a block of this type when calling addRequest. This will be called once the request completes. The call occurs on the UI thread. @param connection The `FBSDKGraphRequestConnection` that sent the request. @param result The result of the request. This is a translation of JSON data to `NSDictionary` and `NSArray` objects. This is nil if there was an error. @param error The `NSError` representing any error that occurred. */ typedef void (^FBSDKGraphRequestHandler)(FBSDKGraphRequestConnection *connection, id result, NSError *error); /*! @protocol @abstract The `FBSDKGraphRequestConnectionDelegate` protocol defines the methods used to receive network activity progress information from a . */ @protocol FBSDKGraphRequestConnectionDelegate @optional /*! @method @abstract Tells the delegate the request connection will begin loading @discussion If the is created using one of the convenience factory methods prefixed with start, the object returned from the convenience method has already begun loading and this method will not be called when the delegate is set. @param connection The request connection that is starting a network request */ - (void)requestConnectionWillBeginLoading:(FBSDKGraphRequestConnection *)connection; /*! @method @abstract Tells the delegate the request connection finished loading @discussion If the request connection completes without a network error occuring then this method is called. Invocation of this method does not indicate success of every made, only that the request connection has no further activity. Use the error argument passed to the FBSDKGraphRequestHandler block to determine success or failure of each . This method is invoked after the completion handler for each . @param connection The request connection that successfully completed a network request */ - (void)requestConnectionDidFinishLoading:(FBSDKGraphRequestConnection *)connection; /*! @method @abstract Tells the delegate the request connection failed with an error @discussion If the request connection fails with a network error then this method is called. The `error` argument specifies why the network connection failed. The `NSError` object passed to the FBSDKGraphRequestHandler block may contain additional information. @param connection The request connection that successfully completed a network request @param error The `NSError` representing the network error that occurred, if any. May be nil in some circumstances. Consult the `NSError` for the for reliable failure information. */ - (void)requestConnection:(FBSDKGraphRequestConnection *)connection didFailWithError:(NSError *)error; /*! @method @abstract Tells the delegate how much data has been sent and is planned to send to the remote host @discussion The byte count arguments refer to the aggregated objects, not a particular . Like `NSURLConnection`, the values may change in unexpected ways if data needs to be resent. @param connection The request connection transmitting data to a remote host @param bytesWritten The number of bytes sent in the last transmission @param totalBytesWritten The total number of bytes sent to the remote host @param totalBytesExpectedToWrite The total number of bytes expected to send to the remote host */ - (void)requestConnection:(FBSDKGraphRequestConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite; @end /*! @class FBSDKGraphRequestConnection @abstract The `FBSDKGraphRequestConnection` represents a single connection to Facebook to service a request. @discussion The request settings are encapsulated in a reusable object. The `FBSDKGraphRequestConnection` object encapsulates the concerns of a single communication e.g. starting a connection, canceling a connection, or batching requests. */ @interface FBSDKGraphRequestConnection : NSObject /*! @abstract The delegate object that receives updates. */ @property (nonatomic, assign) id delegate; /*! @abstract Gets or sets the timeout interval to wait for a response before giving up. */ @property (nonatomic) NSTimeInterval timeout; /*! @abstract The raw response that was returned from the server. (readonly) @discussion This property can be used to inspect HTTP headers that were returned from the server. The property is nil until the request completes. If there was a response then this property will be non-nil during the FBSDKGraphRequestHandler callback. */ @property (nonatomic, retain, readonly) NSHTTPURLResponse *URLResponse; /*! @methodgroup Class methods */ /*! @method @abstract This method sets the default timeout on all FBSDKGraphRequestConnection instances. Defaults to 60 seconds. @param defaultConnectionTimeout The timeout interval. */ + (void)setDefaultConnectionTimeout:(NSTimeInterval)defaultConnectionTimeout; /*! @methodgroup Adding requests */ /*! @method @abstract This method adds an object to this connection. @param request A request to be included in the round-trip when start is called. @param handler A handler to call back when the round-trip completes or times out. @discussion The completion handler is retained until the block is called upon the completion or cancellation of the connection. */ - (void)addRequest:(FBSDKGraphRequest *)request completionHandler:(FBSDKGraphRequestHandler)handler; /*! @method @abstract This method adds an object to this connection. @param request A request to be included in the round-trip when start is called. @param handler A handler to call back when the round-trip completes or times out. The handler will be invoked on the main thread. @param name An optional name for this request. This can be used to feed the results of one request to the input of another in the same `FBSDKGraphRequestConnection` as described in [Graph API Batch Requests]( https://developers.facebook.com/docs/reference/api/batch/ ). @discussion The completion handler is retained until the block is called upon the completion or cancellation of the connection. This request can be named to allow for using the request's response in a subsequent request. */ - (void)addRequest:(FBSDKGraphRequest *)request completionHandler:(FBSDKGraphRequestHandler)handler batchEntryName:(NSString *)name; /*! @method @abstract This method adds an object to this connection. @param request A request to be included in the round-trip when start is called. @param handler A handler to call back when the round-trip completes or times out. @param batchParameters The optional dictionary of parameters to include for this request as described in [Graph API Batch Requests]( https://developers.facebook.com/docs/reference/api/batch/ ). Examples include "depends_on", "name", or "omit_response_on_success". @discussion The completion handler is retained until the block is called upon the completion or cancellation of the connection. This request can be named to allow for using the request's response in a subsequent request. */ - (void)addRequest:(FBSDKGraphRequest *)request completionHandler:(FBSDKGraphRequestHandler)handler batchParameters:(NSDictionary *)batchParameters; /*! @methodgroup Instance methods */ /*! @method @abstract Signals that a connection should be logically terminated as the application is no longer interested in a response. @discussion Synchronously calls any handlers indicating the request was cancelled. Cancel does not guarantee that the request-related processing will cease. It does promise that all handlers will complete before the cancel returns. A call to cancel prior to a start implies a cancellation of all requests associated with the connection. */ - (void)cancel; /*! @method @abstract This method starts a connection with the server and is capable of handling all of the requests that were added to the connection. @discussion By default, a connection is scheduled on the current thread in the default mode when it is created. See `setDelegateQueue:` for other options. This method cannot be called twice for an `FBSDKGraphRequestConnection` instance. */ - (void)start; /*! @abstract Determines the operation queue that is used to call methods on the connection's delegate. @param queue The operation queue to use when calling delegate methods. @discussion By default, a connection is scheduled on the current thread in the default mode when it is created. You cannot reschedule a connection after it has started. This is very similar to `[NSURLConnection setDelegateQueue:]`. */ - (void)setDelegateQueue:(NSOperationQueue *)queue; /*! @method @abstract Overrides the default version for a batch request @discussion The SDK automatically prepends a version part, such as "v2.0" to API paths in order to simplify API versioning for applications. If you want to override the version part while using batch requests on the connection, call this method to set the version for the batch request. @param version This is a string in the form @"v2.0" which will be used for the version part of an API path */ - (void)overrideVersionPartWith:(NSString *)version; @end /*! @abstract The key in the result dictionary for requests to old versions of the Graph API whose response is not a JSON object. @discussion When a request returns a non-JSON response (such as a "true" literal), that response will be wrapped into a dictionary using this const as the key. This only applies for very few Graph API prior to v2.1. */ FBSDK_EXTERN NSString *const FBSDKNonJSONResponseProperty; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKGraphRequestDataAttachment.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @abstract A container class for data attachments so that additional metadata can be provided about the attachment. */ @interface FBSDKGraphRequestDataAttachment : NSObject /*! @abstract Initializes the receiver with the attachment data and metadata. @param data The attachment data (retained, not copied) @param filename The filename for the attachment @param contentType The content type for the attachment */ - (instancetype)initWithData:(NSData *)data filename:(NSString *)filename contentType:(NSString *)contentType NS_DESIGNATED_INITIALIZER; /*! @abstract The content type for the attachment. */ @property (nonatomic, copy, readonly) NSString *contentType; /*! @abstract The attachment data. */ @property (nonatomic, strong, readonly) NSData *data; /*! @abstract The filename for the attachment. */ @property (nonatomic, copy, readonly) NSString *filename; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKMacros.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #ifdef __cplusplus #define FBSDK_EXTERN extern "C" __attribute__((visibility ("default"))) #else #define FBSDK_EXTERN extern __attribute__((visibility ("default"))) #endif #define FBSDK_STATIC_INLINE static inline #define FBSDK_NO_DESIGNATED_INITIALIZER() \ @throw [NSException exceptionWithName:NSInvalidArgumentException \ reason:[NSString stringWithFormat:@"unrecognized selector sent to instance %p", self] \ userInfo:nil] #define FBSDK_NOT_DESIGNATED_INITIALIZER(DESIGNATED_INITIALIZER) \ @throw [NSException exceptionWithName:NSInvalidArgumentException \ reason:[NSString stringWithFormat:@"Please use the designated initializer [%p %@]", \ self, \ NSStringFromSelector(@selector(DESIGNATED_INITIALIZER))] \ userInfo:nil] ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKMutableCopying.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract Extension protocol for NSMutableCopying that adds the mutableCopy method, which is implemented on NSObject. @discussion NSObject implicitly conforms to this protocol. */ @protocol FBSDKMutableCopying /*! @abstract Implemented by NSObject as a convenience to mutableCopyWithZone:. @return A mutable copy of the receiver. */ - (id)mutableCopy; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKProfile.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "FBSDKMacros.h" #import "FBSDKProfilePictureView.h" /*! @abstract Notification indicating that the `currentProfile` has changed. @discussion the userInfo dictionary of the notification will contain keys `FBSDKProfileChangeOldKey` and `FBSDKProfileChangeNewKey`. */ FBSDK_EXTERN NSString *const FBSDKProfileDidChangeNotification; /* @abstract key in notification's userInfo object for getting the old profile. @discussion If there was no old profile, the key will not be present. */ FBSDK_EXTERN NSString *const FBSDKProfileChangeOldKey; /* @abstract key in notification's userInfo object for getting the new profile. @discussion If there is no new profile, the key will not be present. */ FBSDK_EXTERN NSString *const FBSDKProfileChangeNewKey; /*! @abstract Represents an immutable Facebook profile @discussion This class provides a global "currentProfile" instance to more easily add social context to your application. When the profile changes, a notification is posted so that you can update relevant parts of your UI and is persisted to NSUserDefaults. Typically, you will want to call `enableUpdatesOnAccessTokenChange:YES` so that it automatically observes changes to the `[FBSDKAccessToken currentAccessToken]`. You can use this class to build your own `FBSDKProfilePictureView` or in place of typical requests to "/me". */ @interface FBSDKProfile : NSObject /*! @abstract initializes a new instance. @param userID the user ID @param firstName the user's first name @param middleName the user's middle name @param lastName the user's last name @param name the user's complete name @param linkURL the link for this profile @param refreshDate the optional date this profile was fetched. Defaults to [NSDate date]. */ - (instancetype)initWithUserID:(NSString *)userID firstName:(NSString *)firstName middleName:(NSString *)middleName lastName:(NSString *)lastName name:(NSString *)name linkURL:(NSURL *)linkURL refreshDate:(NSDate *)refreshDate NS_DESIGNATED_INITIALIZER; /*! @abstract The user id */ @property (nonatomic, readonly) NSString *userID; /*! @abstract The user's first name */ @property (nonatomic, readonly) NSString *firstName; /*! @abstract The user's middle name */ @property (nonatomic, readonly) NSString *middleName; /*! @abstract The user's last name */ @property (nonatomic, readonly) NSString *lastName; /*! @abstract The user's complete name */ @property (nonatomic, readonly) NSString *name; /*! @abstract A URL to the user's profile. @discussion Consider using Bolts and `FBSDKAppLinkResolver` to resolve this to an app link to link directly to the user's profile in the Facebook app. */ @property (nonatomic, readonly) NSURL *linkURL; /*! @abstract The last time the profile data was fetched. */ @property (nonatomic, readonly) NSDate *refreshDate; /*! @abstract Gets the current FBSDKProfile instance. */ + (FBSDKProfile *)currentProfile; /*! @abstract Sets the current instance and posts the appropriate notification if the profile parameter is different than the receiver. @param profile the profile to set @discussion This persists the profile to NSUserDefaults. */ + (void)setCurrentProfile:(FBSDKProfile *)profile; /*! @abstract Indicates if `currentProfile` will automatically observe `FBSDKAccessTokenDidChangeNotification` notifications @param enable YES is observing @discussion If observing, this class will issue a graph request for public profile data when the current token's userID differs from the current profile. You can observe `FBSDKProfileDidChangeNotification` for when the profile is updated. Note that if `[FBSDKAccessToken currentAccessToken]` is unset, the `currentProfile` instance remains. It's also possible for `currentProfile` to return nil until the data is fetched. */ + (void)enableUpdatesOnAccessTokenChange:(BOOL)enable; /*! @abstract A convenience method for returning a complete `NSURL` for retrieving the user's profile image. @param mode The picture mode @param size The height and width. This will be rounded to integer precision. */ - (NSURL *)imageURLForPictureMode:(FBSDKProfilePictureMode)mode size:(CGSize)size; /*! @abstract A convenience method for returning a Graph API path for retrieving the user's profile image. @deprecated use `imageURLForPictureMode:size:` instead @discussion You can pass this to a `FBSDKGraphRequest` instance to download the image. @param mode The picture mode @param size The height and width. This will be rounded to integer precision. */ - (NSString *)imagePathForPictureMode:(FBSDKProfilePictureMode)mode size:(CGSize)size __attribute__ ((deprecated("use imageURLForPictureMode:size: instead"))); /*! @abstract Returns YES if the profile is equivalent to the receiver. @param profile the profile to compare to. */ - (BOOL)isEqualToProfile:(FBSDKProfile *)profile; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKProfilePictureView.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @typedef FBSDKProfilePictureMode enum @abstract Defines the aspect ratio mode for the source image of the profile picture. */ typedef NS_ENUM(NSUInteger, FBSDKProfilePictureMode) { /*! @abstract A square cropped version of the image will be included in the view. */ FBSDKProfilePictureModeSquare, /*! @abstract The original picture's aspect ratio will be used for the source image in the view. */ FBSDKProfilePictureModeNormal, }; /*! @abstract A view to display a profile picture. */ @interface FBSDKProfilePictureView : UIView /*! @abstract The mode for the receiver to determine the aspect ratio of the source image. */ @property (nonatomic, assign) FBSDKProfilePictureMode pictureMode; /*! @abstract The profile ID to show the picture for. */ @property (nonatomic, copy) NSString *profileID; /*! @abstract Explicitly marks the receiver as needing to update the image. @discussion This method is called whenever any properties that affect the source image are modified, but this can also be used to trigger a manual update of the image if it needs to be re-downloaded. */ - (void)setNeedsImageUpdate; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKSettings.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /* * Constants defining logging behavior. Use with <[FBSDKSettings setLoggingBehavior]>. */ /*! Include access token in logging. */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorAccessTokens; /*! Log performance characteristics */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorPerformanceCharacteristics; /*! Log FBSDKAppEvents interactions */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorAppEvents; /*! Log Informational occurrences */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorInformational; /*! Log cache errors. */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorCacheErrors; /*! Log errors from SDK UI controls */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorUIControlErrors; /*! Log debug warnings from API response, i.e. when friends fields requested, but user_friends permission isn't granted. */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorGraphAPIDebugWarning; /*! Log warnings from API response, i.e. when requested feature will be deprecated in next version of API. Info is the lowest level of severity, using it will result in logging all previously mentioned levels. */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorGraphAPIDebugInfo; /*! Log errors from SDK network requests */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorNetworkRequests; /*! Log errors likely to be preventable by the developer. This is in the default set of enabled logging behaviors. */ FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors; @interface FBSDKSettings : NSObject /*! @abstract Get the Facebook App ID used by the SDK. @discussion If not explicitly set, the default will be read from the application's plist (FacebookAppID). */ + (NSString *)appID; /*! @abstract Set the Facebook App ID to be used by the SDK. @param appID The Facebook App ID to be used by the SDK. */ + (void)setAppID:(NSString *)appID; /*! @abstract Get the default url scheme suffix used for sessions. @discussion If not explicitly set, the default will be read from the application's plist (FacebookUrlSchemeSuffix). */ + (NSString *)appURLSchemeSuffix; /*! @abstract Set the app url scheme suffix used by the SDK. @param appURLSchemeSuffix The url scheme suffix to be used by the SDK. */ + (void)setAppURLSchemeSuffix:(NSString *)appURLSchemeSuffix; /*! @abstract Retrieve the Client Token that has been set via [FBSDKSettings setClientToken]. @discussion If not explicitly set, the default will be read from the application's plist (FacebookClientToken). */ + (NSString *)clientToken; /*! @abstract Sets the Client Token for the Facebook App. @discussion This is needed for certain API calls when made anonymously, without a user-based access token. @param clientToken The Facebook App's "client token", which, for a given appid can be found in the Security section of the Advanced tab of the Facebook App settings found at */ + (void)setClientToken:(NSString *)clientToken; /*! @abstract A convenient way to toggle error recovery for all FBSDKGraphRequest instances created after this is set. @param disableGraphErrorRecovery YES or NO. */ + (void)setGraphErrorRecoveryDisabled:(BOOL)disableGraphErrorRecovery; /*! @abstract Get the Facebook Display Name used by the SDK. @discussion If not explicitly set, the default will be read from the application's plist (FacebookDisplayName). */ + (NSString *)displayName; /*! @abstract Set the default Facebook Display Name to be used by the SDK. @discussion This should match the Display Name that has been set for the app with the corresponding Facebook App ID, in the Facebook App Dashboard. @param displayName The Facebook Display Name to be used by the SDK. */ + (void)setDisplayName:(NSString *)displayName; /*! @abstract Get the Facebook domain part. @discussion If not explicitly set, the default will be read from the application's plist (FacebookDomainPart). */ + (NSString *)facebookDomainPart; /*! @abstract Set the subpart of the Facebook domain. @discussion This can be used to change the Facebook domain (e.g. @"beta") so that requests will be sent to graph.beta.facebook.com @param facebookDomainPart The domain part to be inserted into facebook.com. */ + (void)setFacebookDomainPart:(NSString *)facebookDomainPart; /*! @abstract The quality of JPEG images sent to Facebook from the SDK. @discussion If not explicitly set, the default is 0.9. @see [UIImageJPEGRepresentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIImageJPEGRepresentation) */ + (CGFloat)JPEGCompressionQuality; /*! @abstract Set the quality of JPEG images sent to Facebook from the SDK. @param JPEGCompressionQuality The quality for JPEG images, expressed as a value from 0.0 to 1.0. @see [UIImageJPEGRepresentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIImageJPEGRepresentation) */ + (void)setJPEGCompressionQuality:(CGFloat)JPEGCompressionQuality; /*! @abstract Gets whether data such as that generated through FBSDKAppEvents and sent to Facebook should be restricted from being used for other than analytics and conversions. Defaults to NO. This value is stored on the device and persists across app launches. */ + (BOOL)limitEventAndDataUsage; /*! @abstract Sets whether data such as that generated through FBSDKAppEvents and sent to Facebook should be restricted from being used for other than analytics and conversions. Defaults to NO. This value is stored on the device and persists across app launches. @param limitEventAndDataUsage The desired value. */ + (void)setLimitEventAndDataUsage:(BOOL)limitEventAndDataUsage; /*! @abstract Retrieve the current iOS SDK version. */ + (NSString *)sdkVersion; /*! @abstract Retrieve the current Facebook SDK logging behavior. */ + (NSSet *)loggingBehavior; /*! @abstract Set the current Facebook SDK logging behavior. This should consist of strings defined as constants with FBSDKLoggingBehavior*. @param loggingBehavior A set of strings indicating what information should be logged. If nil is provided, the logging behavior is reset to the default set of enabled behaviors. Set to an empty set in order to disable all logging. @discussion You can also define this via an array in your app plist with key "FacebookLoggingBehavior" or add and remove individual values via enableLoggingBehavior: or disableLogginBehavior: */ + (void)setLoggingBehavior:(NSSet *)loggingBehavior; /*! @abstract Enable a particular Facebook SDK logging behavior. @param loggingBehavior The LoggingBehavior to enable. This should be a string defined as a constant with FBSDKLoggingBehavior*. */ + (void)enableLoggingBehavior:(NSString *)loggingBehavior; /*! @abstract Disable a particular Facebook SDK logging behavior. @param loggingBehavior The LoggingBehavior to disable. This should be a string defined as a constant with FBSDKLoggingBehavior*. */ + (void)disableLoggingBehavior:(NSString *)loggingBehavior; /*! @abstract Set the user defaults key used by legacy token caches. @param tokenInformationKeyName the key used by legacy token caches. @discussion Use this only if you customized FBSessionTokenCachingStrategy in v3.x of the Facebook SDK for iOS. */ + (void)setLegacyUserDefaultTokenInformationKeyName:(NSString *)tokenInformationKeyName; /*! @abstract Get the user defaults key used by legacy token caches. */ + (NSString *)legacyUserDefaultTokenInformationKeyName; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKTestUsersManager.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @class FBSDKAccessToken; /*! @typedef @abstract Callback block for returning an array of FBSDKAccessToken instances (and possibly `NSNull` instances); or an error. */ typedef void (^FBSDKTestUsersManagerRetrieveTestAccountTokensHandler)(NSArray *tokens, NSError *error) ; /*! @typedef @abstract Callback block for removing a test user. */ typedef void (^FBSDKTestUsersManagerRemoveTestAccountHandler)(NSError *error) ; /*! @class FBSDKTestUsersManager @abstract Provides methods for managing test accounts for testing Facebook integration. @discussion Facebook allows developers to create test accounts for testing their applications' Facebook integration (see https://developers.facebook.com/docs/test_users/). This class simplifies use of these accounts for writing tests. It is not designed for use in production application code. This class will make Graph API calls on behalf of your app to manage test accounts and requires an app id and app secret. You will typically use this class to write unit or integration tests. Make sure you NEVER include your app secret in your production app. */ @interface FBSDKTestUsersManager : NSObject /*! @abstract construct or return the shared instance @param appID the Facebook app id @param appSecret the Facebook app secret */ + (instancetype)sharedInstanceForAppID:(NSString *)appID appSecret:(NSString *)appSecret; /*! @abstract retrieve FBSDKAccessToken instances for test accounts with the specific permissions. @param arraysOfPermissions an array of permissions sets, such as @[ [NSSet setWithObject:@"email"], [NSSet setWithObject:@"user_birthday"]] if you needed two test accounts with email and birthday permissions, respectively. You can pass in empty nested sets if you need two arbitrary test accounts. For convenience, passing nil is treated as @[ [NSSet set] ] for fetching a single test user. @param createIfNotFound if YES, new test accounts are created if no test accounts existed that fit the permissions requirement @param handler the callback to invoke which will return an array of `FBAccessTokenData` instances or an `NSError`. If param `createIfNotFound` is NO, the array may contain `[NSNull null]` instances. @discussion If you are requesting test accounts with differing number of permissions, try to order `arrayOfPermissionsArrays` so that the most number of permissions come first to minimize creation of new test accounts. */ - (void)requestTestAccountTokensWithArraysOfPermissions:(NSArray *)arraysOfPermissions createIfNotFound:(BOOL)createIfNotFound completionHandler:(FBSDKTestUsersManagerRetrieveTestAccountTokensHandler)handler; /*! @abstract add a test account with the specified permissions @param permissions the set of permissions, e.g., [NSSet setWithObjects:@"email", @"user_friends"] @param handler the callback handler */ - (void)addTestAccountWithPermissions:(NSSet *)permissions completionHandler:(FBSDKTestUsersManagerRetrieveTestAccountTokensHandler)handler; /*! @abstract remove a test account for the given user id @param userId the user id @param handler the callback handler */ - (void)removeTestAccount:(NSString *)userId completionHandler:(FBSDKTestUsersManagerRemoveTestAccountHandler)handler; /*! @abstract Make two test users friends with each other. @param first the token of the first user @param second the token of the second user @param callback the callback handler */ - (void)makeFriendsWithFirst:(FBSDKAccessToken *)first second:(FBSDKAccessToken *)second callback:(void (^)(NSError *))callback; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Headers/FBSDKUtility.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @abstract Class to contain common utility methods. */ @interface FBSDKUtility : NSObject /*! @abstract Parses a query string into a dictionary. @param queryString The query string value. @return A dictionary with the key/value pairs. */ + (NSDictionary *)dictionaryWithQueryString:(NSString *)queryString; /*! @abstract Constructs a query string from a dictionary. @param dictionary The dictionary with key/value pairs for the query string. @param errorRef If an error occurs, upon return contains an NSError object that describes the problem. @result Query string representation of the parameters. */ + (NSString *)queryStringWithDictionary:(NSDictionary *)dictionary error:(NSError *__autoreleasing *)errorRef; /*! @abstract Decodes a value from an URL. @param value The value to decode. @result The decoded value. */ + (NSString *)URLDecode:(NSString *)value; /*! @abstract Encodes a value for an URL. @param value The value to encode. @result The encoded value. */ + (NSString *)URLEncode:(NSString *)value; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/Modules/module.modulemap ================================================ framework module FBSDKCoreKit { umbrella header "FBSDKCoreKit.h" export * module * { export * } explicit module FBSDKButton { header "FBSDKButton.h" export * } explicit module FBSDKAppLinkResolver { header "FBSDKAppLinkResolver.h" export * } explicit module FBSDKGraphErrorRecoveryProcessor { header "FBSDKGraphErrorRecoveryProcessor.h" export * } explicit module FBSDKGraphRequestDataAttachment { header "FBSDKGraphRequestDataAttachment.h" export * } explicit module FBSDKTestUsersManager { header "FBSDKTestUsersManager.h" export * } } ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKAccessTokenCacheV4.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import "FBSDKAccessToken.h" #import "FBSDKAccessTokenCaching.h" @interface FBSDKAccessTokenCacheV4 : NSObject @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKBridgeAPICrypto.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import "FBSDKBridgeAPIRequest.h" @interface FBSDKBridgeAPICrypto : NSObject + (void)addCipherKeyToQueryParameters:(NSMutableDictionary *)queryParameters; + (NSDictionary *)decryptResponseForRequest:(FBSDKBridgeAPIRequest *)request queryParameters:(NSDictionary *)queryParameters error:(NSError *__autoreleasing *)errorRef; + (void)reset; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKBridgeAPIProtocol.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import "FBSDKBridgeAPIProtocolType.h" @class FBSDKBridgeAPIRequest; FBSDK_EXTERN NSString *const FBSDKBridgeAPIAppIDKey; FBSDK_EXTERN NSString *const FBSDKBridgeAPISchemeSuffixKey; FBSDK_EXTERN NSString *const FBSDKBridgeAPIVersionKey; @protocol FBSDKBridgeAPIProtocol - (NSURL *)requestURLWithActionID:(NSString *)actionID scheme:(NSString *)scheme methodName:(NSString *)methodName methodVersion:(NSString *)methodVersion parameters:(NSDictionary *)parameters error:(NSError *__autoreleasing *)errorRef; - (NSDictionary *)responseParametersForActionID:(NSString *)actionID queryParameters:(NSDictionary *)queryParameters cancelled:(BOOL *)cancelledRef error:(NSError *__autoreleasing *)errorRef; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKBridgeAPIProtocolNativeV1.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import "FBSDKBridgeAPIProtocol.h" typedef struct { __unsafe_unretained NSString *bridgeArgs; __unsafe_unretained NSString *methodArgs; __unsafe_unretained NSString *methodVersion; } FBSDKBridgeAPIProtocolNativeV1OutputKeysStruct; FBSDK_EXTERN const FBSDKBridgeAPIProtocolNativeV1OutputKeysStruct FBSDKBridgeAPIProtocolNativeV1OutputKeys; typedef struct { __unsafe_unretained NSString *actionID; __unsafe_unretained NSString *appIcon; __unsafe_unretained NSString *appName; __unsafe_unretained NSString *sdkVersion; } FBSDKBridgeAPIProtocolNativeV1BridgeParameterOutputKeysStruct; FBSDK_EXTERN const FBSDKBridgeAPIProtocolNativeV1BridgeParameterOutputKeysStruct FBSDKBridgeAPIProtocolNativeV1BridgeParameterOutputKeys; typedef struct { __unsafe_unretained NSString *bridgeArgs; __unsafe_unretained NSString *methodResults; } FBSDKBridgeAPIProtocolNativeV1InputKeysStruct; FBSDK_EXTERN const FBSDKBridgeAPIProtocolNativeV1InputKeysStruct FBSDKBridgeAPIProtocolNativeV1InputKeys; typedef struct { __unsafe_unretained NSString *actionID; __unsafe_unretained NSString *error; } FBSDKBridgeAPIProtocolNativeV1BridgeParameterInputKeysStruct; FBSDK_EXTERN const FBSDKBridgeAPIProtocolNativeV1BridgeParameterInputKeysStruct FBSDKBridgeAPIProtocolNativeV1BridgeParameterInputKeys; @interface FBSDKBridgeAPIProtocolNativeV1 : NSObject - (instancetype)initWithAppScheme:(NSString *)appScheme; - (instancetype)initWithAppScheme:(NSString *)appScheme pasteboard:(UIPasteboard *)pasteboard dataLengthThreshold:(NSUInteger)dataLengthThreshold includeAppIcon:(BOOL)includeAppIcon NS_DESIGNATED_INITIALIZER; @property (nonatomic, copy, readonly) NSString *appScheme; @property (nonatomic, assign, readonly) NSUInteger dataLengthThreshold; @property (nonatomic, assign, readonly) BOOL includeAppIcon; @property (nonatomic, strong, readonly) UIPasteboard *pasteboard; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKBridgeAPIProtocolWebV1.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import "FBSDKBridgeAPIProtocol.h" @interface FBSDKBridgeAPIProtocolWebV1 : NSObject @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKError.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface FBSDKError : NSObject + (NSString *)errorDomain; + (BOOL)errorIsNetworkError:(NSError *)error; + (NSError *)errorWithCode:(NSInteger)code message:(NSString *)message; + (NSError *)errorWithCode:(NSInteger)code message:(NSString *)message underlyingError:(NSError *)underlyingError; + (NSError *)errorWithCode:(NSInteger)code userInfo:(NSDictionary *)userInfo message:(NSString *)message underlyingError:(NSError *)underlyingError; + (NSError *)invalidArgumentErrorWithName:(NSString *)name value:(id)value message:(NSString *)message; + (NSError *)invalidArgumentErrorWithName:(NSString *)name value:(id)value message:(NSString *)message underlyingError:(NSError *)underlyingError; + (NSError *)invalidCollectionErrorWithName:(NSString *)name collection:(id)collection item:(id)item message:(NSString *)message; + (NSError *)invalidCollectionErrorWithName:(NSString *)name collection:(id)collection item:(id)item message:(NSString *)message underlyingError:(NSError *)underlyingError; + (NSError *)requiredArgumentErrorWithName:(NSString *)name message:(NSString *)message; + (NSError *)requiredArgumentErrorWithName:(NSString *)name message:(NSString *)message underlyingError:(NSError *)underlyingError; + (NSError *)unknownErrorWithMessage:(NSString *)message; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKGraphRequestBody.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import @class FBSDKGraphRequestDataAttachment; @class FBSDKLogger; @interface FBSDKGraphRequestBody : NSObject @property (nonatomic, retain, readonly) NSData *data; - (void)appendWithKey:(NSString *)key formValue:(NSString *)value logger:(FBSDKLogger *)logger; - (void)appendWithKey:(NSString *)key imageValue:(UIImage *)image logger:(FBSDKLogger *)logger; - (void)appendWithKey:(NSString *)key dataValue:(NSData *)data logger:(FBSDKLogger *)logger; - (void)appendWithKey:(NSString *)key dataAttachmentValue:(FBSDKGraphRequestDataAttachment *)dataAttachment logger:(FBSDKLogger *)logger; + (NSString *)mimeContentType; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKGraphRequestMetadata.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import // Internal only class to facilitate FBSDKGraphRequest processing, specifically // associating FBSDKGraphRequest and FBSDKGraphRequestHandler instances and necessary // data for retry processing. @interface FBSDKGraphRequestMetadata : NSObject @property (nonatomic, retain) FBSDKGraphRequest *request; @property (nonatomic, copy) FBSDKGraphRequestHandler completionHandler; @property (nonatomic, copy) NSDictionary *batchParameters; - (instancetype)initWithRequest:(FBSDKGraphRequest *)request completionHandler:(FBSDKGraphRequestHandler)handler batchParameters:(NSDictionary *)batchParameters NS_DESIGNATED_INITIALIZER; - (void)invokeCompletionHandlerForConnection:(FBSDKGraphRequestConnection *)connection withResults:(id)results error:(NSError *)error; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKURLConnection.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @class FBSDKURLConnection; typedef void (^FBSDKURLConnectionHandler)(FBSDKURLConnection *connection, NSError *error, NSURLResponse *response, NSData *responseData); @protocol FBSDKURLConnectionDelegate @optional - (void)facebookURLConnection:(FBSDKURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite; @end @interface FBSDKURLConnection : NSObject - (FBSDKURLConnection *)initWithRequest:(NSURLRequest *)request completionHandler:(FBSDKURLConnectionHandler)handler NS_DESIGNATED_INITIALIZER; @property (nonatomic, assign) id delegate; - (void)cancel; - (void)start; - (void)setDelegateQueue:(NSOperationQueue *)queue; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKCoreKit.framework/PrivateHeaders/FBSDKWebDialogView.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @protocol FBSDKWebDialogViewDelegate; @interface FBSDKWebDialogView : UIView @property (nonatomic, assign) id delegate; - (void)loadURL:(NSURL *)URL; - (void)stopLoading; @end @protocol FBSDKWebDialogViewDelegate - (void)webDialogView:(FBSDKWebDialogView *)webDialogView didCompleteWithResults:(NSDictionary *)results; - (void)webDialogView:(FBSDKWebDialogView *)webDialogView didFailWithError:(NSError *)error; - (void)webDialogViewDidCancel:(FBSDKWebDialogView *)webDialogView; - (void)webDialogViewDidFinishLoad:(FBSDKWebDialogView *)webDialogView; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKLoginKit.framework/Headers/FBSDKLoginButton.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import "FBSDKTooltipView.h" @protocol FBSDKLoginButtonDelegate; /*! @typedef NS_ENUM(NSUInteger, FBSDKLoginButtonTooltipBehavior) @abstract Indicates the desired login tooltip behavior. */ typedef NS_ENUM(NSUInteger, FBSDKLoginButtonTooltipBehavior) { /*! The default behavior. The tooltip will only be displayed if the app is eligible (determined by possible server round trip) */ FBSDKLoginButtonTooltipBehaviorAutomatic = 0, /*! Force display of the tooltip (typically for UI testing) */ FBSDKLoginButtonTooltipBehaviorForceDisplay = 1, /*! Force disable. In this case you can still exert more refined control by manually constructing a `FBSDKLoginTooltipView` instance. */ FBSDKLoginButtonTooltipBehaviorDisable = 2 }; /*! @abstract A button that initiates a log in or log out flow upon tapping. @discussion `FBSDKLoginButton` works with `[FBSDKAccessToken currentAccessToken]` to determine what to display, and automatically starts authentication when tapped (i.e., you do not need to manually subscribe action targets). Like `FBSDKLoginManager`, you should make sure your app delegate is connected to `FBSDKApplicationDelegate` in order for the button's delegate to receive messages. `FBSDKLoginButton` has a fixed height, but you may change the width. `initWithFrame:CGRectZero` will size the button to its minimum frame. */ @interface FBSDKLoginButton : FBSDKButton /*! @abstract The default audience to use, if publish permissions are requested at login time. */ @property (assign, nonatomic) FBSDKDefaultAudience defaultAudience; /*! @abstract Gets or sets the delegate. */ @property (weak, nonatomic) IBOutlet id delegate; /*! @abstract Gets or sets the login behavior to use */ @property (assign, nonatomic) FBSDKLoginBehavior loginBehavior; /*! @abstract The publish permissions to request. @discussion Use `defaultAudience` to specify the default audience to publish to. Note this is converted to NSSet and is only an NSArray for the convenience of literal syntax. */ @property (copy, nonatomic) NSArray *publishPermissions; /*! @abstract The read permissions to request. @discussion Note, that if read permissions are specified, then publish permissions should not be specified. This is converted to NSSet and is only an NSArray for the convenience of literal syntax. */ @property (copy, nonatomic) NSArray *readPermissions; /*! @abstract Gets or sets the desired tooltip behavior. */ @property (assign, nonatomic) FBSDKLoginButtonTooltipBehavior tooltipBehavior; /*! @abstract Gets or sets the desired tooltip color style. */ @property (assign, nonatomic) FBSDKTooltipColorStyle tooltipColorStyle; @end /*! @protocol @abstract A delegate for `FBSDKLoginButton` */ @protocol FBSDKLoginButtonDelegate @required /*! @abstract Sent to the delegate when the button was used to login. @param loginButton the sender @param result The results of the login @param error The error (if any) from the login */ - (void) loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error; /*! @abstract Sent to the delegate when the button was used to logout. @param loginButton The button that was clicked. */ - (void)loginButtonDidLogOut:(FBSDKLoginButton *)loginButton; @optional /*! @abstract Sent to the delegate when the button is about to login. @param loginButton the sender @return YES if the login should be allowed to proceed, NO otherwise */ - (BOOL) loginButtonWillLogin:(FBSDKLoginButton *)loginButton; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKLoginKit.framework/Headers/FBSDKLoginConstants.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract The error domain for all errors from FBSDKLoginKit @discussion Error codes from the SDK in the range 300-399 are reserved for this domain. */ FBSDK_EXTERN NSString *const FBSDKLoginErrorDomain; /*! @typedef NS_ENUM(NSInteger, FBSDKLoginErrorCode) @abstract Error codes for FBSDKLoginErrorDomain. */ typedef NS_ENUM(NSInteger, FBSDKLoginErrorCode) { /*! @abstract Reserved. */ FBSDKLoginReservedErrorCode = 300, /*! @abstract The error code for unknown errors. */ FBSDKLoginUnknownErrorCode, /*! @abstract The user's password has changed and must log in again */ FBSDKLoginPasswordChangedErrorCode, /*! @abstract The user must log in to their account on www.facebook.com to restore access */ FBSDKLoginUserCheckpointedErrorCode, /*! @abstract Indicates a failure to request new permissions because the user has changed. */ FBSDKLoginUserMismatchErrorCode, /*! @abstract The user must confirm their account with Facebook before logging in */ FBSDKLoginUnconfirmedUserErrorCode, /*! @abstract The Accounts framework failed without returning an error, indicating the app's slider in the iOS Facebook Settings (device Settings -> Facebook -> App Name) has been disabled. */ FBSDKLoginSystemAccountAppDisabledErrorCode, /*! @abstract An error occurred related to Facebook system Account store */ FBSDKLoginSystemAccountUnavailableErrorCode, /*! @abstract The login response was missing a valid challenge string. */ FBSDKLoginBadChallengeString, }; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKLoginKit.framework/Headers/FBSDKLoginKit.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import #import #import ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKLoginKit.framework/Headers/FBSDKLoginManager.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import @class FBSDKLoginManagerLoginResult; /*! @abstract Describes the call back to the FBSDKLoginManager @param result the result of the authorization @param error the authorization error, if any. */ typedef void (^FBSDKLoginManagerRequestTokenHandler)(FBSDKLoginManagerLoginResult *result, NSError *error); /*! @typedef FBSDKDefaultAudience enum @abstract Passed to open to indicate which default audience to use for sessions that post data to Facebook. @discussion Certain operations such as publishing a status or publishing a photo require an audience. When the user grants an application permission to perform a publish operation, a default audience is selected as the publication ceiling for the application. This enumerated value allows the application to select which audience to ask the user to grant publish permission for. */ typedef NS_ENUM(NSUInteger, FBSDKDefaultAudience) { /*! Indicates that the user's friends are able to see posts made by the application */ FBSDKDefaultAudienceFriends = 0, /*! Indicates that only the user is able to see posts made by the application */ FBSDKDefaultAudienceOnlyMe, /*! Indicates that all Facebook users are able to see posts made by the application */ FBSDKDefaultAudienceEveryone, }; /*! @typedef FBSDKLoginBehavior enum @abstract Passed to the \c FBSDKLoginManager to indicate how Facebook Login should be attempted. @discussion Facebook Login authorizes the application to act on behalf of the user, using the user's Facebook account. Usually a Facebook Login will rely on an account maintained outside of the application, by the native Facebook application, the browser, or perhaps the device itself. This avoids the need for a user to enter their username and password directly, and provides the most secure and lowest friction way for a user to authorize the application to interact with Facebook. The \c FBSDKLoginBehavior enum specifies which log-in methods may be used. The SDK will determine the best behavior based on the current device (such as iOS version). */ typedef NS_ENUM(NSUInteger, FBSDKLoginBehavior) { /*! @abstract This is the default behavior, and indicates logging in through the native Facebook app may be used. The SDK may still use Safari instead. */ FBSDKLoginBehaviorNative = 0, /*! @abstract Attempts log in through the Safari or SFSafariViewController, if available. */ FBSDKLoginBehaviorBrowser, /*! @abstract Attempts log in through the Facebook account currently signed in through the device Settings. @note If the account is not available to the app (either not configured by user or as determined by the SDK) this behavior falls back to \c FBSDKLoginBehaviorNative. */ FBSDKLoginBehaviorSystemAccount, /*! @abstract Attemps log in through a modal \c UIWebView pop up @note This behavior is only available to certain types of apps. Please check the Facebook Platform Policy to verify your app meets the restrictions. */ FBSDKLoginBehaviorWeb, }; /*! @abstract `FBSDKLoginManager` provides methods for logging the user in and out. @discussion `FBSDKLoginManager` works directly with `[FBSDKAccessToken currentAccessToken]` and sets the "currentAccessToken" upon successful authorizations (or sets `nil` in case of `logOut`). You should check `[FBSDKAccessToken currentAccessToken]` before calling logIn* to see if there is a cached token available (typically in your viewDidLoad). If you are managing your own token instances outside of "currentAccessToken", you will need to set "currentAccessToken" before calling logIn* to authorize futher permissions on your tokens. */ @interface FBSDKLoginManager : NSObject /*! @abstract the default audience. @discussion you should set this if you intend to ask for publish permissions. */ @property (assign, nonatomic) FBSDKDefaultAudience defaultAudience; /*! @abstract the login behavior */ @property (assign, nonatomic) FBSDKLoginBehavior loginBehavior; /*! @deprecated use logInWithReadPermissions:fromViewController:handler: instead */ - (void)logInWithReadPermissions:(NSArray *)permissions handler:(FBSDKLoginManagerRequestTokenHandler)handler __attribute__ ((deprecated("use logInWithReadPermissions:fromViewController:handler: instead"))); /*! @deprecated use logInWithPublishPermissions:fromViewController:handler: instead */ - (void)logInWithPublishPermissions:(NSArray *)permissions handler:(FBSDKLoginManagerRequestTokenHandler)handler __attribute__ ((deprecated("use logInWithPublishPermissions:fromViewController:handler: instead"))); /*! @abstract Logs the user in or authorizes additional permissions. @param permissions the optional array of permissions. Note this is converted to NSSet and is only an NSArray for the convenience of literal syntax. @param fromViewController the view controller to present from. If nil, the topmost view controller will be automatically determined as best as possible. @param handler the callback. @discussion Use this method when asking for read permissions. You should only ask for permissions when they are needed and explain the value to the user. You can inspect the result.declinedPermissions to also provide more information to the user if they decline permissions. If `[FBSDKAccessToken currentAccessToken]` is not nil, it will be treated as a reauthorization for that user and will pass the "rerequest" flag to the login dialog. This method will present UI the user. You typically should check if `[FBSDKAccessToken currentAccessToken]` already contains the permissions you need before asking to reduce unnecessary app switching. For example, you could make that check at viewDidLoad. */ - (void)logInWithReadPermissions:(NSArray *)permissions fromViewController:(UIViewController *)fromViewController handler:(FBSDKLoginManagerRequestTokenHandler)handler; /*! @abstract Logs the user in or authorizes additional permissions. @param permissions the optional array of permissions. Note this is converted to NSSet and is only an NSArray for the convenience of literal syntax. @param fromViewController the view controller to present from. If nil, the topmost view controller will be automatically determined as best as possible. @param handler the callback. @discussion Use this method when asking for publish permissions. You should only ask for permissions when they are needed and explain the value to the user. You can inspect the result.declinedPermissions to also provide more information to the user if they decline permissions. If `[FBSDKAccessToken currentAccessToken]` is not nil, it will be treated as a reauthorization for that user and will pass the "rerequest" flag to the login dialog. This method will present UI the user. You typically should check if `[FBSDKAccessToken currentAccessToken]` already contains the permissions you need before asking to reduce unnecessary app switching. For example, you could make that check at viewDidLoad. */ - (void)logInWithPublishPermissions:(NSArray *)permissions fromViewController:(UIViewController *)fromViewController handler:(FBSDKLoginManagerRequestTokenHandler)handler; /*! @abstract Logs the user out @discussion This calls [FBSDKAccessToken setCurrentAccessToken:nil] and [FBSDKProfile setCurrentProfile:nil]. */ - (void)logOut; /*! @method @abstract Issues an asychronous renewCredentialsForAccount call to the device's Facebook account store. @param handler The completion handler to call when the renewal is completed. This can be invoked on an arbitrary thread. @discussion This can be used to explicitly renew account credentials and is provided as a convenience wrapper around `[ACAccountStore renewCredentialsForAccount:completion]`. Note the method will not issue the renewal call if the the Facebook account has not been set on the device, or if access had not been granted to the account (though the handler wil receive an error). If the `[FBSDKAccessToken currentAccessToken]` was from the account store, a succesful renewal will also set a new "currentAccessToken". */ + (void)renewSystemCredentials:(void (^)(ACAccountCredentialRenewResult result, NSError *error))handler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKLoginKit.framework/Headers/FBSDKLoginManagerLoginResult.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @class FBSDKAccessToken; /*! @abstract Describes the result of a login attempt. */ @interface FBSDKLoginManagerLoginResult : NSObject /*! @abstract the access token. */ @property (copy, nonatomic) FBSDKAccessToken *token; /*! @abstract whether the login was cancelled by the user. */ @property (readonly, nonatomic) BOOL isCancelled; /*! @abstract the set of permissions granted by the user in the associated request. @discussion inspect the token's permissions set for a complete list. */ @property (copy, nonatomic) NSSet *grantedPermissions; /*! @abstract the set of permissions declined by the user in the associated request. @discussion inspect the token's permissions set for a complete list. */ @property (copy, nonatomic) NSSet *declinedPermissions; /*! @abstract Initializes a new instance. @param token the access token @param isCancelled whether the login was cancelled by the user @param grantedPermissions the set of granted permissions @param declinedPermissions the set of declined permissions */ - (instancetype)initWithToken:(FBSDKAccessToken *)token isCancelled:(BOOL)isCancelled grantedPermissions:(NSSet *)grantedPermissions declinedPermissions:(NSSet *)declinedPermissions NS_DESIGNATED_INITIALIZER; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKLoginKit.framework/Headers/FBSDKLoginTooltipView.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import @protocol FBSDKLoginTooltipViewDelegate; /*! @class FBSDKLoginTooltipView @abstract Represents a tooltip to be displayed next to a Facebook login button to highlight features for new users. @discussion The `FBSDKLoginButton` may display this view automatically. If you do not use the `FBSDKLoginButton`, you can manually call one of the `present*` methods as appropriate and customize behavior via `FBSDKLoginTooltipViewDelegate` delegate. By default, the `FBSDKLoginTooltipView` is not added to the superview until it is determined the app has migrated to the new login experience. You can override this (e.g., to test the UI layout) by implementing the delegate or setting `forceDisplay` to YES. */ @interface FBSDKLoginTooltipView : FBSDKTooltipView /*! @abstract the delegate */ @property (nonatomic, assign) id delegate; /*! @abstract if set to YES, the view will always be displayed and the delegate's `loginTooltipView:shouldAppear:` will NOT be called. */ @property (nonatomic, assign) BOOL forceDisplay; @end /*! @protocol @abstract The `FBSDKLoginTooltipViewDelegate` protocol defines the methods used to receive event notifications from `FBSDKLoginTooltipView` objects. */ @protocol FBSDKLoginTooltipViewDelegate @optional /*! @abstract Asks the delegate if the tooltip view should appear @param view The tooltip view. @param appIsEligible The value fetched from the server identifying if the app is eligible for the new login experience. @discussion Use this method to customize display behavior. */ - (BOOL)loginTooltipView:(FBSDKLoginTooltipView *)view shouldAppear:(BOOL)appIsEligible; /*! @abstract Tells the delegate the tooltip view will appear, specifically after it's been added to the super view but before the fade in animation. @param view The tooltip view. */ - (void)loginTooltipViewWillAppear:(FBSDKLoginTooltipView *)view; /*! @abstract Tells the delegate the tooltip view will not appear (i.e., was not added to the super view). @param view The tooltip view. */ - (void)loginTooltipViewWillNotAppear:(FBSDKLoginTooltipView *)view; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKLoginKit.framework/Headers/FBSDKTooltipView.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @typedef FBSDKTooltipViewArrowDirection enum @abstract Passed on construction to determine arrow orientation. */ typedef NS_ENUM(NSUInteger, FBSDKTooltipViewArrowDirection) { /*! View is located above given point, arrow is pointing down. */ FBSDKTooltipViewArrowDirectionDown = 0, /*! View is located below given point, arrow is pointing up. */ FBSDKTooltipViewArrowDirectionUp = 1, }; /*! @typedef FBSDKTooltipColorStyle enum @abstract Passed on construction to determine color styling. */ typedef NS_ENUM(NSUInteger, FBSDKTooltipColorStyle) { /*! Light blue background, white text, faded blue close button. */ FBSDKTooltipColorStyleFriendlyBlue = 0, /*! Dark gray background, white text, light gray close button. */ FBSDKTooltipColorStyleNeutralGray = 1, }; /*! @class FBSDKTooltipView @abstract Tooltip bubble with text in it used to display tips for UI elements, with a pointed arrow (to refer to the UI element). @discussion The tooltip fades in and will automatically fade out. See `displayDuration`. */ @interface FBSDKTooltipView : UIView /*! @abstract Gets or sets the amount of time in seconds the tooltip should be displayed. @discussion Set this to zero to make the display permanent until explicitly dismissed. Defaults to six seconds. */ @property (nonatomic, assign) CFTimeInterval displayDuration; /*! @abstract Gets or sets the color style after initialization. @discussion Defaults to value passed to -initWithTagline:message:colorStyle:. */ @property (nonatomic, assign) FBSDKTooltipColorStyle colorStyle; /*! @abstract Gets or sets the message. */ @property (nonatomic, copy) NSString *message; /*! @abstract Gets or sets the optional phrase that comprises the first part of the label (and is highlighted differently). */ @property (nonatomic, copy) NSString *tagline; /*! @abstract Designated initializer. @param tagline First part of the label, that will be highlighted with different color. Can be nil. @param message Main message to display. @param colorStyle Color style to use for tooltip. @discussion If you need to show a tooltip for login, consider using the `FBSDKLoginTooltipView` view. @see FBSDKLoginTooltipView */ - (instancetype)initWithTagline:(NSString *)tagline message:(NSString *)message colorStyle:(FBSDKTooltipColorStyle)colorStyle; /*! @abstract Show tooltip at the top or at the bottom of given view. Tooltip will be added to anchorView.window.rootViewController.view @param anchorView view to show at, must be already added to window view hierarchy, in order to decide where tooltip will be shown. (If there's not enough space at the top of the anchorView in window bounds - tooltip will be shown at the bottom of it) @discussion Use this method to present the tooltip with automatic positioning or use -presentInView:withArrowPosition:direction: for manual positioning If anchorView is nil or has no window - this method does nothing. */ - (void)presentFromView:(UIView *)anchorView; /*! @abstract Adds tooltip to given view, with given position and arrow direction. @param view View to be used as superview. @param arrowPosition Point in view's cordinates, where arrow will be pointing @param arrowDirection whenever arrow should be pointing up (message bubble is below the arrow) or down (message bubble is above the arrow). */ - (void)presentInView:(UIView *)view withArrowPosition:(CGPoint)arrowPosition direction:(FBSDKTooltipViewArrowDirection)arrowDirection; /*! @abstract Remove tooltip manually. @discussion Calling this method isn't necessary - tooltip will dismiss itself automatically after the `displayDuration`. */ - (void)dismiss; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKLoginKit.framework/Modules/module.modulemap ================================================ framework module FBSDKLoginKit { umbrella header "FBSDKLoginKit.h" export * module * { export * } } ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/FBSDKShareKit ================================================ [File too large to display: 12.6 MB] ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKAppGroupAddDialog.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import @protocol FBSDKAppGroupAddDialogDelegate; /*! @abstract A dialog for creating app groups. */ @interface FBSDKAppGroupAddDialog : NSObject /*! @abstract Convenience method to build up an app group dialog with content and a delegate. @param content The content for the app group. @param delegate The receiver's delegate. */ + (instancetype)showWithContent:(FBSDKAppGroupContent *)content delegate:(id)delegate; /*! @abstract The receiver's delegate or nil if it doesn't have a delegate. */ @property (nonatomic, weak) id delegate; /*! @abstract The content for app group. */ @property (nonatomic, copy) FBSDKAppGroupContent *content; /*! @abstract A Boolean value that indicates whether the receiver can initiate an app group dialog. @discussion May return NO if the appropriate Facebook app is not installed and is required or an access token is required but not available. This method does not validate the content on the receiver, so this can be checked before building up the content. @see validateWithError: @result YES if the receiver can share, otherwise NO. */ - (BOOL)canShow; /*! @abstract Begins the app group dialog from the receiver. @result YES if the receiver was able to show the dialog, otherwise NO. */ - (BOOL)show; /*! @abstract Validates the content on the receiver. @param errorRef If an error occurs, upon return contains an NSError object that describes the problem. @return YES if the content is valid, otherwise NO. */ - (BOOL)validateWithError:(NSError *__autoreleasing *)errorRef; @end /*! @abstract A delegate for FBSDKAppGroupAddDialog. @discussion The delegate is notified with the results of the app group request as long as the application has permissions to receive the information. For example, if the person is not signed into the containing app, the shower may not be able to distinguish between completion of an app group request and cancellation. */ @protocol FBSDKAppGroupAddDialogDelegate /*! @abstract Sent to the delegate when the app group request completes without error. @param appGroupAddDialog The FBSDKAppGroupAddDialog that completed. @param results The results from the dialog. This may be nil or empty. */ - (void)appGroupAddDialog:(FBSDKAppGroupAddDialog *)appGroupAddDialog didCompleteWithResults:(NSDictionary *)results; /*! @abstract Sent to the delegate when the app group request encounters an error. @param appGroupAddDialog The FBSDKAppGroupAddDialog that completed. @param error The error. */ - (void)appGroupAddDialog:(FBSDKAppGroupAddDialog *)appGroupAddDialog didFailWithError:(NSError *)error; /*! @abstract Sent to the delegate when the app group dialog is cancelled. @param appGroupAddDialog The FBSDKAppGroupAddDialog that completed. */ - (void)appGroupAddDialogDidCancel:(FBSDKAppGroupAddDialog *)appGroupAddDialog; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKAppGroupContent.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import /*! @typedef NS_ENUM(NSUInteger, FBSDKAppGroupPrivacy) @abstract Specifies the privacy of a group. */ typedef NS_ENUM(NSUInteger, FBSDKAppGroupPrivacy) { /*! Anyone can see the group, who's in it and what members post. */ FBSDKAppGroupPrivacyOpen = 0, /*! Anyone can see the group and who's in it, but only members can see posts. */ FBSDKAppGroupPrivacyClosed, }; /*! @abstract Converts an FBSDKAppGroupPrivacy to an NSString. */ FBSDK_EXTERN NSString *NSStringFromFBSDKAppGroupPrivacy(FBSDKAppGroupPrivacy privacy); /*! @abstract A model for creating an app group. */ @interface FBSDKAppGroupContent : NSObject /*! @abstract The description of the group. */ @property (nonatomic, copy) NSString *groupDescription; /*! @abstract The name of the group. */ @property (nonatomic, copy) NSString *name; /*! @abstract The privacy for the group. */ @property (nonatomic, assign) FBSDKAppGroupPrivacy privacy; /*! @abstract Compares the receiver to another app group content. @param content The other content @return YES if the receiver's values are equal to the other content's values; otherwise NO */ - (BOOL)isEqualToAppGroupContent:(FBSDKAppGroupContent *)content; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKAppGroupJoinDialog.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @protocol FBSDKAppGroupJoinDialogDelegate; /*! @abstract A dialog for joining app groups. */ @interface FBSDKAppGroupJoinDialog : NSObject /*! @abstract Convenience method to build up an app group dialog with content and a delegate. @param groupID The ID for the group. @param delegate The receiver's delegate. */ + (instancetype)showWithGroupID:(NSString *)groupID delegate:(id)delegate; /*! @abstract The receiver's delegate or nil if it doesn't have a delegate. */ @property (nonatomic, weak) id delegate; /*! @abstract The ID for group. */ @property (nonatomic, copy) NSString *groupID; /*! @abstract A Boolean value that indicates whether the receiver can initiate an app group dialog. @discussion May return NO if the appropriate Facebook app is not installed and is required or an access token is required but not available. This method does not validate the content on the receiver, so this can be checked before building up the content. @see validateWithError: @result YES if the receiver can share, otherwise NO. */ - (BOOL)canShow; /*! @abstract Begins the app group dialog from the receiver. @result YES if the receiver was able to show the dialog, otherwise NO. */ - (BOOL)show; /*! @abstract Validates the content on the receiver. @param errorRef If an error occurs, upon return contains an NSError object that describes the problem. @return YES if the content is valid, otherwise NO. */ - (BOOL)validateWithError:(NSError *__autoreleasing *)errorRef; @end /*! @abstract A delegate for FBSDKAppGroupJoinDialog. @discussion The delegate is notified with the results of the app group request as long as the application has permissions to receive the information. For example, if the person is not signed into the containing app, the shower may not be able to distinguish between completion of an app group request and cancellation. */ @protocol FBSDKAppGroupJoinDialogDelegate /*! @abstract Sent to the delegate when the app group request completes without error. @param appGroupJoinDialog The FBSDKAppGroupJoinDialog that completed. @param results The results from the dialog. This may be nil or empty. */ - (void)appGroupJoinDialog:(FBSDKAppGroupJoinDialog *)appGroupJoinDialog didCompleteWithResults:(NSDictionary *)results; /*! @abstract Sent to the delegate when the app group request encounters an error. @param appGroupJoinDialog The FBSDKAppGroupJoinDialog that completed. @param error The error. */ - (void)appGroupJoinDialog:(FBSDKAppGroupJoinDialog *)appGroupJoinDialog didFailWithError:(NSError *)error; /*! @abstract Sent to the delegate when the app group dialog is cancelled. @param appGroupJoinDialog The FBSDKAppGroupJoinDialog that completed. */ - (void)appGroupJoinDialogDidCancel:(FBSDKAppGroupJoinDialog *)appGroupJoinDialog; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKAppInviteContent.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract A model for app invite. */ @interface FBSDKAppInviteContent : NSObject /*! @abstract A URL to a preview image that will be displayed with the app invite @discussion This is optional. If you don't include it a fallback image will be used. */ @property (nonatomic, copy) NSURL *appInvitePreviewImageURL; /*! @abstract An app link target that will be used as a target when the user accept the invite. @discussion This is a requirement. */ @property (nonatomic, copy) NSURL *appLinkURL; /*! @deprecated Use `appInvitePreviewImageURL` instead. */ @property (nonatomic, copy) NSURL *previewImageURL __attribute__ ((deprecated("use appInvitePreviewImageURL instead"))); /*! @abstract Compares the receiver to another app invite content. @param content The other content @return YES if the receiver's values are equal to the other content's values; otherwise NO */ - (BOOL)isEqualToAppInviteContent:(FBSDKAppInviteContent *)content; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKAppInviteDialog.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import @protocol FBSDKAppInviteDialogDelegate; /*! @abstract A dialog for sending App Invites. */ @interface FBSDKAppInviteDialog : NSObject /*! @abstract Convenience method to show a FBSDKAppInviteDialog @param viewController A UIViewController to present the dialog from. @param content The content for the app invite. @param delegate The receiver's delegate. */ + (instancetype)showFromViewController:(UIViewController *)viewController withContent:(FBSDKAppInviteContent *)content delegate:(id)delegate; /*! @deprecated use showFromViewController:withContent:delegate: instead */ + (instancetype)showWithContent:(FBSDKAppInviteContent *)content delegate:(id)delegate __attribute__ ((deprecated("use showFromViewController:withContent:delegate: instead"))); /*! @abstract A UIViewController to present the dialog from. @discussion If not specified, the top most view controller will be automatically determined as best as possible. */ @property (nonatomic, weak) UIViewController *fromViewController; /*! @abstract The receiver's delegate or nil if it doesn't have a delegate. */ @property (nonatomic, weak) id delegate; /*! @abstract The content for app invite. */ @property (nonatomic, copy) FBSDKAppInviteContent *content; /*! @abstract A Boolean value that indicates whether the receiver can initiate an app invite. @discussion May return NO if the appropriate Facebook app is not installed and is required or an access token is required but not available. This method does not validate the content on the receiver, so this can be checked before building up the content. @see validateWithError: @result YES if the receiver can show the dialog, otherwise NO. */ - (BOOL)canShow; /*! @abstract Begins the app invite from the receiver. @result YES if the receiver was able to show the dialog, otherwise NO. */ - (BOOL)show; /*! @abstract Validates the content on the receiver. @param errorRef If an error occurs, upon return contains an NSError object that describes the problem. @return YES if the content is valid, otherwise NO. */ - (BOOL)validateWithError:(NSError *__autoreleasing *)errorRef; @end /*! @abstract A delegate for FBSDKAppInviteDialog. @discussion The delegate is notified with the results of the app invite as long as the application has permissions to receive the information. For example, if the person is not signed into the containing app, the shower may not be able to distinguish between completion of an app invite and cancellation. */ @protocol FBSDKAppInviteDialogDelegate /*! @abstract Sent to the delegate when the app invite completes without error. @param appInviteDialog The FBSDKAppInviteDialog that completed. @param results The results from the dialog. This may be nil or empty. */ - (void)appInviteDialog:(FBSDKAppInviteDialog *)appInviteDialog didCompleteWithResults:(NSDictionary *)results; /*! @abstract Sent to the delegate when the app invite encounters an error. @param appInviteDialog The FBSDKAppInviteDialog that completed. @param error The error. */ - (void)appInviteDialog:(FBSDKAppInviteDialog *)appInviteDialog didFailWithError:(NSError *)error; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKGameRequestContent.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @typedef NS_ENUM(NSUInteger, FBSDKGameRequestActionType) @abstract Additional context about the nature of the request. */ typedef NS_ENUM(NSUInteger, FBSDKGameRequestActionType) { /*! No action type */ FBSDKGameRequestActionTypeNone = 0, /*! Send action type: The user is sending an object to the friends. */ FBSDKGameRequestActionTypeSend, /*! Ask For action type: The user is asking for an object from friends. */ FBSDKGameRequestActionTypeAskFor, /*! Turn action type: It is the turn of the friends to play against the user in a match. (no object) */ FBSDKGameRequestActionTypeTurn, }; /*! @typedef NS_ENUM(NSUInteger, FBSDKGameRequestFilters) @abstract Filter for who can be displayed in the multi-friend selector. */ typedef NS_ENUM(NSUInteger, FBSDKGameRequestFilter) { /*! No filter, all friends can be displayed. */ FBSDKGameRequestFilterNone = 0, /*! Friends using the app can be displayed. */ FBSDKGameRequestFilterAppUsers, /*! Friends not using the app can be displayed. */ FBSDKGameRequestFilterAppNonUsers, }; /*! @abstract A model for a game request. */ @interface FBSDKGameRequestContent : NSObject /*! @abstract Used when defining additional context about the nature of the request. @discussion The parameter 'objectID' is required if the action type is either 'FBSDKGameRequestSendActionType' or 'FBSDKGameRequestAskForActionType'. @seealso objectID */ @property (nonatomic, assign) FBSDKGameRequestActionType actionType; /*! @abstract Compares the receiver to another game request content. @param content The other content @return YES if the receiver's values are equal to the other content's values; otherwise NO */ - (BOOL)isEqualToGameRequestContent:(FBSDKGameRequestContent *)content; /*! @abstract Additional freeform data you may pass for tracking. This will be stored as part of the request objects created. The maximum length is 255 characters. */ @property (nonatomic, copy) NSString *data; /*! @abstract This controls the set of friends someone sees if a multi-friend selector is shown. It is FBSDKGameRequestNoFilter by default, meaning that all friends can be shown. If specify as FBSDKGameRequestAppUsersFilter, only friends who use the app will be shown. On the other hands, use FBSDKGameRequestAppNonUsersFilter to filter only friends who do not use the app. @discussion The parameter name is preserved to be consistent with the counter part on desktop. */ @property (nonatomic, assign) FBSDKGameRequestFilter filters; /*! @abstract A plain-text message to be sent as part of the request. This text will surface in the App Center view of the request, but not on the notification jewel. Required parameter. */ @property (nonatomic, copy) NSString *message; /*! @abstract The Open Graph object ID of the object being sent. @seealso actionType */ @property (nonatomic, copy) NSString *objectID; /*! @abstract An array of user IDs, usernames or invite tokens (NSString) of people to send request. @discussion These may or may not be a friend of the sender. If this is specified by the app, the sender will not have a choice of recipients. If not, the sender will see a multi-friend selector This is equivalent to the "to" parameter when using the web game request dialog. */ @property (nonatomic, copy) NSArray *recipients; /*! @abstract An array of user IDs that will be included in the dialog as the first suggested friends. Cannot be used together with filters. @discussion This is equivalent to the "suggestions" parameter when using the web game request dialog. */ @property (nonatomic, copy) NSArray *recipientSuggestions; /*! @deprecated Use `recipientSuggestions` instead. */ @property (nonatomic, copy) NSArray *suggestions __attribute__ ((deprecated("use recipientSuggestions instead"))); /*! @abstract The title for the dialog. */ @property (nonatomic, copy) NSString *title; /*! @deprecated Use `recipients` instead. */ @property (nonatomic, copy) NSArray *to __attribute__ ((deprecated("use recipients instead"))); @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKGameRequestDialog.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import @protocol FBSDKGameRequestDialogDelegate; /*! @abstract A dialog for sending game requests. */ @interface FBSDKGameRequestDialog : NSObject /*! @abstract Convenience method to build up a game request with content and a delegate. @param content The content for the game request. @param delegate The receiver's delegate. */ + (instancetype)showWithContent:(FBSDKGameRequestContent *)content delegate:(id)delegate; /*! @abstract The receiver's delegate or nil if it doesn't have a delegate. */ @property (nonatomic, weak) id delegate; /*! @abstract The content for game request. */ @property (nonatomic, copy) FBSDKGameRequestContent *content; /*! @abstract Specifies whether frictionless requests are enabled. */ @property (nonatomic, assign) BOOL frictionlessRequestsEnabled; /*! @abstract A Boolean value that indicates whether the receiver can initiate a game request. @discussion May return NO if the appropriate Facebook app is not installed and is required or an access token is required but not available. This method does not validate the content on the receiver, so this can be checked before building up the content. @see validateWithError: @result YES if the receiver can share, otherwise NO. */ - (BOOL)canShow; /*! @abstract Begins the game request from the receiver. @result YES if the receiver was able to show the dialog, otherwise NO. */ - (BOOL)show; /*! @abstract Validates the content on the receiver. @param errorRef If an error occurs, upon return contains an NSError object that describes the problem. @return YES if the content is valid, otherwise NO. */ - (BOOL)validateWithError:(NSError *__autoreleasing *)errorRef; @end /*! @abstract A delegate for FBSDKGameRequestDialog. @discussion The delegate is notified with the results of the game request as long as the application has permissions to receive the information. For example, if the person is not signed into the containing app, the shower may not be able to distinguish between completion of a game request and cancellation. */ @protocol FBSDKGameRequestDialogDelegate /*! @abstract Sent to the delegate when the game request completes without error. @param gameRequestDialog The FBSDKGameRequestDialog that completed. @param results The results from the dialog. This may be nil or empty. */ - (void)gameRequestDialog:(FBSDKGameRequestDialog *)gameRequestDialog didCompleteWithResults:(NSDictionary *)results; /*! @abstract Sent to the delegate when the game request encounters an error. @param gameRequestDialog The FBSDKGameRequestDialog that completed. @param error The error. */ - (void)gameRequestDialog:(FBSDKGameRequestDialog *)gameRequestDialog didFailWithError:(NSError *)error; /*! @abstract Sent to the delegate when the game request dialog is cancelled. @param gameRequestDialog The FBSDKGameRequestDialog that completed. */ - (void)gameRequestDialogDidCancel:(FBSDKGameRequestDialog *)gameRequestDialog; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKLikeButton.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import /*! @abstract A button to like an object. @discussion Tapping the receiver will invoke an API call to the Facebook app through a fast-app-switch that allows the object to be liked. Upon return to the calling app, the view will update with the new state. If the currentAccessToken has "publish_actions" permission and the object is an Open Graph object, then the like can happen seamlessly without the fast-app-switch. */ @interface FBSDKLikeButton : FBSDKButton /*! @abstract If YES, a sound is played when the receiver is toggled. @default YES */ @property (nonatomic, assign, getter = isSoundEnabled) BOOL soundEnabled; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKLikeControl.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import /*! @typedef NS_ENUM (NSUInteger, FBSDKLikeControlAuxiliaryPosition) @abstract Specifies the position of the auxiliary view relative to the like button. */ typedef NS_ENUM(NSUInteger, FBSDKLikeControlAuxiliaryPosition) { /*! The auxiliary view is inline with the like button. */ FBSDKLikeControlAuxiliaryPositionInline, /*! The auxiliary view is above the like button. */ FBSDKLikeControlAuxiliaryPositionTop, /*! The auxiliary view is below the like button. */ FBSDKLikeControlAuxiliaryPositionBottom, }; /*! @abstract Converts an FBSDKLikeControlAuxiliaryPosition to an NSString. */ FBSDK_EXTERN NSString *NSStringFromFBSDKLikeControlAuxiliaryPosition(FBSDKLikeControlAuxiliaryPosition auxiliaryPosition); /*! @typedef NS_ENUM(NSUInteger, FBSDKLikeControlHorizontalAlignment) @abstract Specifies the horizontal alignment for FBSDKLikeControlStyleStandard with FBSDKLikeControlAuxiliaryPositionTop or FBSDKLikeControlAuxiliaryPositionBottom. */ typedef NS_ENUM(NSUInteger, FBSDKLikeControlHorizontalAlignment) { /*! The subviews are left aligned. */ FBSDKLikeControlHorizontalAlignmentLeft, /*! The subviews are center aligned. */ FBSDKLikeControlHorizontalAlignmentCenter, /*! The subviews are right aligned. */ FBSDKLikeControlHorizontalAlignmentRight, }; /*! @abstract Converts an FBSDKLikeControlHorizontalAlignment to an NSString. */ FBSDK_EXTERN NSString *NSStringFromFBSDKLikeControlHorizontalAlignment(FBSDKLikeControlHorizontalAlignment horizontalAlignment); /*! @typedef NS_ENUM (NSUInteger, FBSDKLikeControlStyle) @abstract Specifies the style of a like control. */ typedef NS_ENUM(NSUInteger, FBSDKLikeControlStyle) { /*! Displays the button and the social sentence. */ FBSDKLikeControlStyleStandard = 0, /*! Displays the button and a box that contains the like count. */ FBSDKLikeControlStyleBoxCount, }; /*! @abstract Converts an FBSDKLikeControlStyle to an NSString. */ FBSDK_EXTERN NSString *NSStringFromFBSDKLikeControlStyle(FBSDKLikeControlStyle style); /*! @class FBSDKLikeControl @abstract UI control to like an object in the Facebook graph. @discussion Taps on the like button within this control will invoke an API call to the Facebook app through a fast-app-switch that allows the user to like the object. Upon return to the calling app, the view will update with the new state and send actions for the UIControlEventValueChanged event. */ @interface FBSDKLikeControl : UIControl /*! @abstract The foreground color to use for the content of the receiver. */ @property (nonatomic, strong) UIColor *foregroundColor; /*! @abstract The position for the auxiliary view for the receiver. @see FBSDKLikeControlAuxiliaryPosition */ @property (nonatomic, assign) FBSDKLikeControlAuxiliaryPosition likeControlAuxiliaryPosition; /*! @abstract The text alignment of the social sentence. @discussion This value is only valid for FBSDKLikeControlStyleStandard with FBSDKLikeControlAuxiliaryPositionTop|Bottom. */ @property (nonatomic, assign) FBSDKLikeControlHorizontalAlignment likeControlHorizontalAlignment; /*! @abstract The style to use for the receiver. @see FBSDKLikeControlStyle */ @property (nonatomic, assign) FBSDKLikeControlStyle likeControlStyle; /*! @abstract The preferred maximum width (in points) for autolayout. @discussion This property affects the size of the receiver when layout constraints are applied to it. During layout, if the text extends beyond the width specified by this property, the additional text is flowed to one or more new lines, thereby increasing the height of the receiver. */ @property (nonatomic, assign) CGFloat preferredMaxLayoutWidth; /*! @abstract If YES, a sound is played when the receiver is toggled. @default YES */ @property (nonatomic, assign, getter = isSoundEnabled) BOOL soundEnabled; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKLikeObjectType.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @typedef NS_ENUM (NSUInteger, FBSDKLikeObjectType) @abstract Specifies the type of object referenced by the objectID for likes. */ typedef NS_ENUM(NSUInteger, FBSDKLikeObjectType) { /*! The objectID refers to an unknown object type. */ FBSDKLikeObjectTypeUnknown = 0, /*! The objectID refers to an Open Graph object. */ FBSDKLikeObjectTypeOpenGraph, /*! The objectID refers to an Page object. */ FBSDKLikeObjectTypePage, }; /*! @abstract Converts an FBLikeControlObjectType to an NSString. */ FBSDK_EXTERN NSString *NSStringFromFBSDKLikeObjectType(FBSDKLikeObjectType objectType); ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKLiking.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import /*! @abstract The common interface for components that initiate liking. @see FBSDKLikeButton @see FBSDKLikeControl */ @protocol FBSDKLiking /*! @abstract The objectID for the object to like. @discussion This value may be an Open Graph object ID or a string representation of an URL that describes an Open Graph object. The objects may be public objects, like pages, or objects that are defined by your application. */ @property (nonatomic, copy) NSString *objectID; /*! @abstract The type of object referenced by the objectID. @discussion If the objectType is unknown, the control will determine the objectType by querying the server with the objectID. Specifying a value for the objectType is an optimization that should be used if the type is known by the consumer. Consider setting the objectType if it is known when setting the objectID. */ @property (nonatomic, assign) FBSDKLikeObjectType objectType; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKMessageDialog.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract A dialog for sharing content through Messenger. */ @interface FBSDKMessageDialog : NSObject /*! @abstract Convenience method to show a Message Share Dialog with content and a delegate. @param content The content to be shared. @param delegate The receiver's delegate. */ + (instancetype)showWithContent:(id)content delegate:(id)delegate; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKSendButton.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import /*! @abstract A button to send content through Messenger. @discussion Tapping the receiver will invoke the FBSDKShareDialog with the attached shareContent. If the dialog cannot be shown, the button will be disable. */ @interface FBSDKSendButton : FBSDKButton @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareAPI.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import /*! @abstract A utility class for sharing through the graph API. Using this class requires an access token in [FBSDKAccessToken currentAccessToken] that has been granted the "publish_actions" permission. @discussion FBSDKShareAPI network requests are scheduled on the current run loop in the default run loop mode (like NSURLConnection). If you want to use FBSDKShareAPI in a background thread, you must manage the run loop yourself. */ @interface FBSDKShareAPI : NSObject /*! @abstract Convenience method to build up a share API with content and a delegate. @param content The content to be shared. @param delegate The receiver's delegate. */ + (instancetype)shareWithContent:(id)content delegate:(id)delegate; /*! @abstract The message the person has provided through the custom dialog that will accompany the share content. */ @property (nonatomic, copy) NSString *message; /*! @abstract The graph node to which content should be shared. */ @property (nonatomic, copy) NSString *graphNode; /*! @abstract A Boolean value that indicates whether the receiver can send the share. @discussion May return NO if the appropriate Facebook app is not installed and is required or an access token is required but not available. This method does not validate the content on the receiver, so this can be checked before building up the content. @see [FBSDKSharing validateWithError:] @result YES if the receiver can send, otherwise NO. */ - (BOOL)canShare; /*! @abstract Creates an User Owned Open Graph object without an action. @param openGraphObject The open graph object to create. @discussion Use this method to create an object alone, when an action is not going to be posted with the object. If the object will be used within an action, just put the object in the action and share that as the shareContent and the object will be created in the process. The delegate will be messaged with the results. Also see https://developers.facebook.com/docs/sharing/opengraph/object-api#objectapi-creatinguser @result YES if the receiver was able to send the request to create the object, otherwise NO. */ - (BOOL)createOpenGraphObject:(FBSDKShareOpenGraphObject *)openGraphObject; /*! @abstract Begins the send from the receiver. @result YES if the receiver was able to send the share, otherwise NO. */ - (BOOL)share; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareButton.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import /*! @abstract A button to share content. @discussion Tapping the receiver will invoke the FBSDKShareDialog with the attached shareContent. If the dialog cannot be shown, the button will be disabled. */ @interface FBSDKShareButton : FBSDKButton @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareConstants.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract The error domain for all errors from FBSDKShareKit. @discussion Error codes from the SDK in the range 200-299 are reserved for this domain. */ FBSDK_EXTERN NSString *const FBSDKShareErrorDomain; /*! @typedef NS_ENUM(NSInteger, FBSDKShareErrorCode) @abstract Error codes for FBSDKShareErrorDomain. */ typedef NS_ENUM(NSInteger, FBSDKShareErrorCode) { /*! @abstract Reserved. */ FBSDKShareReservedErrorCode = 200, /*! @abstract The error code for errors from uploading open graph objects. */ FBSDKShareOpenGraphErrorCode, /*! @abstract The error code for when a sharing dialog is not available. @discussion Use the canShare methods to check for this case before calling show. */ FBSDKShareDialogNotAvailableErrorCode, }; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareDialog.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import /*! @abstract A dialog for sharing content on Facebook. */ @interface FBSDKShareDialog : NSObject /*! @abstract Convenience method to show an FBSDKShareDialog with a fromViewController, content and a delegate. @param viewController A UIViewController to present the dialog from, if appropriate. @param content The content to be shared. @param delegate The receiver's delegate. */ + (instancetype)showFromViewController:(UIViewController *)viewController withContent:(id)content delegate:(id)delegate; /*! @abstract A UIViewController to present the dialog from. @discussion If not specified, the top most view controller will be automatically determined as best as possible. */ @property (nonatomic, weak) UIViewController *fromViewController; /*! @abstract The mode with which to display the dialog. @discussion Defaults to FBSDKShareDialogModeAutomatic, which will automatically choose the best available mode. */ @property (nonatomic, assign) FBSDKShareDialogMode mode; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareDialogMode.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @typedef NS_ENUM(NSUInteger, FBSDKShareDialogMode) @abstract Modes for the FBSDKShareDialog. @discussion The automatic mode will progressively check the availability of different modes and open the most appropriate mode for the dialog that is available. */ typedef NS_ENUM(NSUInteger, FBSDKShareDialogMode) { /*! @abstract Acts with the most appropriate mode that is available. */ FBSDKShareDialogModeAutomatic = 0, /*! @Displays the dialog in the main native Facebook app. */ FBSDKShareDialogModeNative, /*! @Displays the dialog in the iOS integrated share sheet. */ FBSDKShareDialogModeShareSheet, /*! @Displays the dialog in Safari. */ FBSDKShareDialogModeBrowser, /*! @Displays the dialog in a UIWebView within the app. */ FBSDKShareDialogModeWeb, /*! @Displays the feed dialog in Safari. */ FBSDKShareDialogModeFeedBrowser, /*! @Displays the feed dialog in a UIWebView within the app. */ FBSDKShareDialogModeFeedWeb, }; /*! @abstract Converts an FBLikeControlObjectType to an NSString. */ FBSDK_EXTERN NSString *NSStringFromFBSDKShareDialogMode(FBSDKShareDialogMode dialogMode); ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareKit.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareLinkContent.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract A model for status and link content to be shared. */ @interface FBSDKShareLinkContent : NSObject /*! @abstract The description of the link. @discussion If not specified, this field is automatically populated by information scraped from the contentURL, typically the title of the page. This value may be discarded for specially handled links (ex: iTunes URLs). @return The description of the link */ @property (nonatomic, copy) NSString *contentDescription; /*! @abstract The title to display for this link. @discussion This value may be discarded for specially handled links (ex: iTunes URLs). @return The link title */ @property (nonatomic, copy) NSString *contentTitle; /*! @abstract The URL of a picture to attach to this content. @return The network URL of an image */ @property (nonatomic, copy) NSURL *imageURL; /*! @abstract Compares the receiver to another link content. @param content The other content @return YES if the receiver's values are equal to the other content's values; otherwise NO */ - (BOOL)isEqualToShareLinkContent:(FBSDKShareLinkContent *)content; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareOpenGraphAction.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import /*! @abstract An Open Graph Action for sharing. @discussion The property keys MUST have namespaces specified on them, such as `og:image`. */ @interface FBSDKShareOpenGraphAction : FBSDKShareOpenGraphValueContainer /*! @abstract Convenience method to build a new action and set the object for the specified key. @param actionType The action type of the receiver @param object The Open Graph object represented by this action @param key The key for the object */ + (instancetype)actionWithType:(NSString *)actionType object:(FBSDKShareOpenGraphObject *)object key:(NSString *)key; /*! @abstract Convenience method to build a new action and set the object for the specified key. @param actionType The action type of the receiver @param objectID The ID of an existing Open Graph object @param key The key for the object */ + (instancetype)actionWithType:(NSString *)actionType objectID:(NSString *)objectID key:(NSString *)key; /*! @abstract Convenience method to build a new action and set the object for the specified key. @param actionType The action type of the receiver @param objectURL The URL to a page that defines the Open Graph object with meta tags @param key The key for the object */ + (instancetype)actionWithType:(NSString *)actionType objectURL:(NSURL *)objectURL key:(NSString *)key; /*! @abstract Gets the action type. @return The action type */ @property (nonatomic, copy) NSString *actionType; /*! @abstract Compares the receiver to another Open Graph Action. @param action The other action @return YES if the receiver's values are equal to the other action's values; otherwise NO */ - (BOOL)isEqualToShareOpenGraphAction:(FBSDKShareOpenGraphAction *)action; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareOpenGraphContent.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import /*! @abstract A model for Open Graph content to be shared. */ @interface FBSDKShareOpenGraphContent : NSObject /*! @abstract Open Graph Action to be shared. @return The action */ @property (nonatomic, copy) FBSDKShareOpenGraphAction *action; /*! @abstract Property name that points to the primary Open Graph Object in the action. @discussion The value that this action points to will be use for rendering the preview for the share. @return The property name for the Open Graph Object in the action */ @property (nonatomic, copy) NSString *previewPropertyName; /*! @abstract Compares the receiver to another Open Graph content. @param content The other content @return YES if the receiver's values are equal to the other content's values; otherwise NO */ - (BOOL)isEqualToShareOpenGraphContent:(FBSDKShareOpenGraphContent *)content; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareOpenGraphObject.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import /*! @abstract An Open Graph Object for sharing. @discussion The property keys MUST have namespaces specified on them, such as `og:image`, and `og:type` is required. See https://developers.facebook.com/docs/sharing/opengraph/object-properties for other properties. You can specify nested namespaces inline to define complex properties. For example, the following code will generate a fitness.course object with a location: FBSDKShareOpenGraphObject *course = [FBSDKShareOpenGraphObject objectWithProperties: @{ @"og:type": @"fitness.course", @"og:title": @"Sample course", @"fitness:metrics:location:latitude": @"41.40338", @"fitness:metrics:location:longitude": @"2.17403", }]; */ @interface FBSDKShareOpenGraphObject : FBSDKShareOpenGraphValueContainer /*! @abstract Convenience method to build a new action and set the object for the specified key. @param properties Properties for the Open Graph object, which will be parsed into the proper models */ + (instancetype)objectWithProperties:(NSDictionary *)properties; /*! @abstract Compares the receiver to another Open Graph Object. @param object The other object @return YES if the receiver's values are equal to the other object's values; otherwise NO */ - (BOOL)isEqualToShareOpenGraphObject:(FBSDKShareOpenGraphObject *)object; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareOpenGraphValueContainer.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @class FBSDKShareOpenGraphObject; @class FBSDKSharePhoto; /*! @abstract Protocol defining operations on open graph actions and objects. @discussion The property keys MUST have namespaces specified on them, such as `og:image`. */ @protocol FBSDKShareOpenGraphValueContaining /*! @abstract Gets an NSArray out of the receiver. @param key The key for the value @return The NSArray value or nil */ - (NSArray *)arrayForKey:(NSString *)key; /*! @abstract Applies a given block object to the entries of the receiver. @param block A block object to operate on entries in the receiver */ - (void)enumerateKeysAndObjectsUsingBlock:(void (^)(NSString *key, id object, BOOL *stop))block; /*! @abstract Returns an enumerator object that lets you access each key in the receiver. @return An enumerator object that lets you access each key in the receiver */ - (NSEnumerator *)keyEnumerator; /*! @abstract Gets an NSNumber out of the receiver. @param key The key for the value @return The NSNumber value or nil */ - (NSNumber *)numberForKey:(NSString *)key; /*! @abstract Returns an enumerator object that lets you access each value in the receiver. @return An enumerator object that lets you access each value in the receiver */ - (NSEnumerator *)objectEnumerator; /*! @abstract Gets an FBSDKShareOpenGraphObject out of the receiver. @param key The key for the value @return The FBSDKShareOpenGraphObject value or nil */ - (FBSDKShareOpenGraphObject *)objectForKey:(NSString *)key; /*! @abstract Enables subscript access to the values in the receiver. @param key The key for the value @return The value */ - (id)objectForKeyedSubscript:(NSString *)key; /*! @abstract Parses properties out of a dictionary into the receiver. @param properties The properties to parse. */ - (void)parseProperties:(NSDictionary *)properties; /*! @abstract Gets an FBSDKSharePhoto out of the receiver. @param key The key for the value @return The FBSDKSharePhoto value or nil */ - (FBSDKSharePhoto *)photoForKey:(NSString *)key; /*! @abstract Removes a value from the receiver for the specified key. @param key The key for the value */ - (void)removeObjectForKey:(NSString *)key; /*! @abstract Sets an NSArray on the receiver. @discussion This method will throw if the array contains any values that is not an NSNumber, NSString, NSURL, FBSDKSharePhoto or FBSDKShareOpenGraphObject. @param array The NSArray value @param key The key for the value */ - (void)setArray:(NSArray *)array forKey:(NSString *)key; /*! @abstract Sets an NSNumber on the receiver. @param number The NSNumber value @param key The key for the value */ - (void)setNumber:(NSNumber *)number forKey:(NSString *)key; /*! @abstract Sets an FBSDKShareOpenGraphObject on the receiver. @param object The FBSDKShareOpenGraphObject value @param key The key for the value */ - (void)setObject:(FBSDKShareOpenGraphObject *)object forKey:(NSString *)key; /*! @abstract Sets an FBSDKSharePhoto on the receiver. @param photo The FBSDKSharePhoto value @param key The key for the value */ - (void)setPhoto:(FBSDKSharePhoto *)photo forKey:(NSString *)key; /*! @abstract Sets an NSString on the receiver. @param string The NSString value @param key The key for the value */ - (void)setString:(NSString *)string forKey:(NSString *)key; /*! @abstract Sets an NSURL on the receiver. @param URL The NSURL value @param key The key for the value */ - (void)setURL:(NSURL *)URL forKey:(NSString *)key; /*! @abstract Gets an NSString out of the receiver. @param key The key for the value @return The NSString value or nil */ - (NSString *)stringForKey:(NSString *)key; /*! @abstract Gets an NSURL out of the receiver. @param key The key for the value @return The NSURL value or nil */ - (NSURL *)URLForKey:(NSString *)key; @end /*! @abstract A base class to container Open Graph values. */ @interface FBSDKShareOpenGraphValueContainer : NSObject @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKSharePhoto.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract A photo for sharing. */ @interface FBSDKSharePhoto : NSObject /*! @abstract Convenience method to build a new photo object with an image. @param image If the photo is resident in memory, this method supplies the data @param userGenerated Specifies whether the photo represented by the receiver was generated by the user or by the application */ + (instancetype)photoWithImage:(UIImage *)image userGenerated:(BOOL)userGenerated; /*! @abstract Convenience method to build a new photo object with an imageURL. @param imageURL The URL to the photo @param userGenerated Specifies whether the photo represented by the receiver was generated by the user or by the application @discussion This method should only be used when adding photo content to open graph stories. For example, if you're trying to share a photo from the web by itself, download the image and use `photoWithImage:userGenerated:` instead. */ + (instancetype)photoWithImageURL:(NSURL *)imageURL userGenerated:(BOOL)userGenerated; /*! @abstract If the photo is resident in memory, this method supplies the data. @return UIImage representation of the photo */ @property (nonatomic, strong) UIImage *image; /*! @abstract The URL to the photo. @return URL that points to a network location or the location of the photo on disk */ @property (nonatomic, copy) NSURL *imageURL; /*! @abstract Specifies whether the photo represented by the receiver was generated by the user or by the application. @return YES if the photo is user-generated, otherwise NO */ @property (nonatomic, assign, getter=isUserGenerated) BOOL userGenerated; /*! @abstract Compares the receiver to another photo. @param photo The other photo @return YES if the receiver's values are equal to the other photo's values; otherwise NO */ - (BOOL)isEqualToSharePhoto:(FBSDKSharePhoto *)photo; /*! @abstract The user generated caption for the photo. Note that the 'caption' must come from * the user, as pre-filled content is forbidden by the Platform Policies (2.3). @return the Photo's caption if exists else returns null. */ @property (nonatomic, copy) NSString *caption; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKSharePhotoContent.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract A model for photo content to be shared. */ @interface FBSDKSharePhotoContent : NSObject /*! @abstract Photos to be shared. @return Array of the photos (FBSDKSharePhoto) */ @property (nonatomic, copy) NSArray *photos; /*! @abstract Compares the receiver to another photo content. @param content The other content @return YES if the receiver's values are equal to the other content's values; otherwise NO */ - (BOOL)isEqualToSharePhotoContent:(FBSDKSharePhotoContent *)content; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareVideo.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract A video for sharing. */ @interface FBSDKShareVideo : NSObject /*! @abstract Convenience method to build a new video object with a videoURL. @param videoURL The URL to the video application */ + (instancetype)videoWithVideoURL:(NSURL *)videoURL; /*! @abstract The file URL to the video. @return URL that points to the location of the video on disk */ @property (nonatomic, copy) NSURL *videoURL; /*! @abstract Compares the receiver to another video. @param video The other video @return YES if the receiver's values are equal to the other video's values; otherwise NO */ - (BOOL)isEqualToShareVideo:(FBSDKShareVideo *)video; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKShareVideoContent.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import #import #import /*! @abstract A model for video content to be shared. */ @interface FBSDKShareVideoContent : NSObject /*! @abstract The photo that represents the video. @return The photo */ @property (nonatomic, copy) FBSDKSharePhoto *previewPhoto; /*! @abstract The video to be shared. @return The video */ @property (nonatomic, copy) FBSDKShareVideo *video; /*! @abstract Compares the receiver to another video content. @param content The other content @return YES if the receiver's values are equal to the other content's values; otherwise NO */ - (BOOL)isEqualToShareVideoContent:(FBSDKShareVideoContent *)content; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKSharing.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import @protocol FBSDKSharingDelegate; /*! @abstract The common interface for components that initiate sharing. @see FBSDKShareDialog @see FBSDKMessageDialog @see FBSDKShareAPI */ @protocol FBSDKSharing /*! @abstract The receiver's delegate or nil if it doesn't have a delegate. */ @property (nonatomic, weak) id delegate; /*! @abstract The content to be shared. */ @property (nonatomic, copy) id shareContent; /*! @abstract A Boolean value that indicates whether the receiver should fail if it finds an error with the share content. @discussion If NO, the sharer will still be displayed without the data that was mis-configured. For example, an invalid placeID specified on the shareContent would produce a data error. */ @property (nonatomic, assign) BOOL shouldFailOnDataError; /*! @abstract Validates the content on the receiver. @param errorRef If an error occurs, upon return contains an NSError object that describes the problem. @return YES if the content is valid, otherwise NO. */ - (BOOL)validateWithError:(NSError **)errorRef; @end /*! @abstract The common interface for dialogs that initiate sharing. */ @protocol FBSDKSharingDialog /*! @abstract A Boolean value that indicates whether the receiver can initiate a share. @discussion May return NO if the appropriate Facebook app is not installed and is required or an access token is required but not available. This method does not validate the content on the receiver, so this can be checked before building up the content. @see [FBSDKSharing validateWithError:] @result YES if the receiver can share, otherwise NO. */ - (BOOL)canShow; /*! @abstract Shows the dialog. @result YES if the receiver was able to begin sharing, otherwise NO. */ - (BOOL)show; @end /*! @abstract A delegate for FBSDKSharing. @discussion The delegate is notified with the results of the sharer as long as the application has permissions to receive the information. For example, if the person is not signed into the containing app, the sharer may not be able to distinguish between completion of a share and cancellation. */ @protocol FBSDKSharingDelegate /*! @abstract Sent to the delegate when the share completes without error or cancellation. @param sharer The FBSDKSharing that completed. @param results The results from the sharer. This may be nil or empty. */ - (void)sharer:(id)sharer didCompleteWithResults:(NSDictionary *)results; /*! @abstract Sent to the delegate when the sharer encounters an error. @param sharer The FBSDKSharing that completed. @param error The error. */ - (void)sharer:(id)sharer didFailWithError:(NSError *)error; /*! @abstract Sent to the delegate when the sharer is cancelled. @param sharer The FBSDKSharing that completed. */ - (void)sharerDidCancel:(id)sharer; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKSharingButton.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract The common interface for sharing buttons. @see FBSDKSendButton @see FBSDKShareButton */ @protocol FBSDKSharingButton /*! @abstract The content to be shared. */ @property (nonatomic, copy) id shareContent; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Headers/FBSDKSharingContent.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import /*! @abstract A base interface for content to be shared. */ @protocol FBSDKSharingContent /*! @abstract URL for the content being shared. @discussion This URL will be checked for all link meta tags for linking in platform specific ways. See documentation for App Links (https://developers.facebook.com/docs/applinks/) @return URL representation of the content link */ @property (nonatomic, copy) NSURL *contentURL; /*! @abstract List of IDs for taggable people to tag with this content. @description See documentation for Taggable Friends (https://developers.facebook.com/docs/graph-api/reference/user/taggable_friends) @return Array of IDs for people to tag (NSString) */ @property (nonatomic, copy) NSArray *peopleIDs; /*! @abstract The ID for a place to tag with this content. @return The ID for the place to tag */ @property (nonatomic, copy) NSString *placeID; /*! @abstract A value to be added to the referrer URL when a person follows a link from this shared content on feed. @return The ref for the content. */ @property (nonatomic, copy) NSString *ref; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/FBSDKShareKit.framework/Modules/module.modulemap ================================================ framework module FBSDKShareKit { umbrella header "FBSDKShareKit.h" export * module * { export * } } ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Facebook/UMSocialFacebookHandler.h ================================================ // // UMSocialFacebookHandler.h // SocialSDK // // Created by yeahugo on 13-12-23. // Copyright (c) 2013年 Umeng. All rights reserved. // #import @interface UMSocialFacebookHandler : NSObject /** 设置facebook应用id,和url地址 @param appID facebook应用ID @param urlString 分享纯文字用到的url地址 */ +(void)setFacebookAppID:(NSString *)appID shareFacebookWithURL:(NSString *)urlString; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Instagram/UMSocialInstagramHandler.h ================================================ // // UMSocialInstragramHandler.h // SocialSDK // // Created by yeahugo on 14-1-8. // Copyright (c) 2014年 Umeng. All rights reserved. // #import #import @interface UMSocialInstagramHandler : NSObject /** 打开分享到Instagram @param isScale 是否等比例缩放,因为分享到instagram,需要传入正方形图片,若等比例缩放则采用传入的color填充周围的空白,若不需要等比例缩放则缩放成正方形 @param color 等比例缩放设置的颜色,设成nil则默认为黑色 @return color */ +(void)openInstagramWithScale:(BOOL)isScale paddingColor:(UIColor *)color; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/LaiWang/UMSocialLaiwangHandler.h ================================================ // // UMSocialLaiwangHandler.h // SocialSDK // // Created by yeahugo on 13-12-23. // Copyright (c) 2013年 Umeng. All rights reserved. // #import @interface UMSocialLaiwangHandler : NSObject /** 设置来往appID,appSecret,description,url @param laiwangAppID 来往AppID @param appSecret 来往appSecret @param description 显示应用来源名称 @param urlString 分享url地址 */ +(void)setLaiwangAppId:(NSString *)laiwangAppId appSecret:(NSString *)appSecret appDescription:(NSString *)description urlStirng:(NSString *)urlString; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Line/UMSocialLineHandler.h ================================================ // // UMSocialLineHandler.h // SocialSDK // // Created by Gavin Ye on 8/21/14. // Copyright (c) 2014 Umeng. All rights reserved. // #import typedef enum { UMSocialLineMessageTypeText, UMSocialLineMessageTypeImage, }UMSocialLineMessageType; @interface UMSocialLineHandler : NSObject +(void)openLineShare:(UMSocialLineMessageType)messageType; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Sina/UMSocialSinaHandler.h ================================================ // // UMSocialSinaHandler.h // SocialSDK // // Created by yeahugo on 14-6-11. // Copyright (c) 2014年 Umeng. All rights reserved. // #import @interface UMSocialSinaHandler : NSObject +(void)openSSOWithRedirectURL:(NSString *)redirectURL; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/UMSocialSinaSSOHandler.h ================================================ // // UMSocialSinaSSOHandler.h // SocialSDK // // Created by Gavin Ye on 3/27/15. // Copyright (c) 2015 Umeng. All rights reserved. // #import /** 使用最新版本的新浪微博官方SDK处理新浪微博SSO授权 */ @interface UMSocialSinaSSOHandler : NSObject /** 设置使用最新新浪微博SDK来处理SSO授权(通过客户端设置appkey进行访问) @param appKey 新浪App Key @param redirectURL 回调URL */ +(void)openNewSinaSSOWithAppKey:(NSString *)appKey RedirectURL:(NSString *)redirectURL; /** 设置使用最新新浪微博SDK来处理SSO授权 @param redirectURL 回调URL */ +(void)openNewSinaSSOWithRedirectURL:(NSString *)redirectURL; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest+WeiboGame.h ================================================ // // WBHttpRequest+WeiboGame.h // WeiboSDK // // Created by insomnia on 15/3/11. // Copyright (c) 2015年 SINA iOS Team. All rights reserved. // #import "WBHttpRequest.h" @interface WBHttpRequest (WeiboGame) /*! @method @abstract 新增游戏对象。 在http://open.weibo.com/wiki/%E6%B8%B8%E6%88%8F%E6%8E%A5%E5%8F%A3 中有关于该接口的细节说明。 @param userID 当前授权用户的uid @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)addGameObject:(NSString*)userID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract 游戏成就对象入库/更新。 在http://open.weibo.com/wiki/%E6%B8%B8%E6%88%8F%E6%8E%A5%E5%8F%A3 中有关于该接口的细节说明。 @param userID 当前授权用户的uid @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)addGameAchievementObject:(NSString*)userID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract 用户获得游戏成就关系入库/更新。 在http://open.weibo.com/wiki/%E6%B8%B8%E6%88%8F%E6%8E%A5%E5%8F%A3 中有关于该接口的细节说明。 @param userID 当前授权用户的uid @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)addGameAchievementGain:(NSString*)userID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract 用户游戏得分关系入库/更新。 在http://open.weibo.com/wiki/%E6%B8%B8%E6%88%8F%E6%8E%A5%E5%8F%A3 中有关于该接口的细节说明。 @param userID 当前授权用户的uid @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)addGameScoreGain:(NSString*)userID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract 读取玩家游戏分数。 在http://open.weibo.com/wiki/%E6%B8%B8%E6%88%8F%E6%8E%A5%E5%8F%A3 中有关于该接口的细节说明。 @param userID 当前授权用户的uid @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)requestForGameScore:(NSString*)userID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract 读取玩家互粉好友游戏分数。 在http://open.weibo.com/wiki/%E6%B8%B8%E6%88%8F%E6%8E%A5%E5%8F%A3 中有关于该接口的细节说明。 @param userID 当前授权用户的uid @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)requestForFriendsGameScore:(NSString*)userID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract 读取玩家获取成就列表。 在http://open.weibo.com/wiki/%E6%B8%B8%E6%88%8F%E6%8E%A5%E5%8F%A3 中有关于该接口的细节说明。 @param userID 当前授权用户的uid @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)requestForGameAchievementGain:(NSString*)userID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest+WeiboShare.h ================================================ // // WBHttpRequest+WeiboShare.h // WeiboSDK // // Created by DannionQiu on 14/10/31. // Copyright (c) 2014年 SINA iOS Team. All rights reserved. // #import "WBHttpRequest.h" @class WBImageObject; @interface WBHttpRequest (WeiboShare) /*! @method @abstract 获得当前授权用户的微博id列表。 @param userID 当前授权用户的uid @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)requestForStatusIDsFromCurrentUser:(NSString*)userID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract 转发微博。转发微博id所对应的微博。 @param statusID 微博id,微博的唯一标识符。 @param text 添加的转发文本,内容不超过140个汉字,不填则默认为“转发微博”。 @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)requestForRepostAStatus:(NSString*)statusID repostText:(NSString*)text withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract 发表一个微博(无图或者带一张图片的微博)。 @param statusText 要发布的微博文本内容,内容不超过140个汉字。 @param imageObject 要上传的图片,仅支持JPEG、GIF、PNG格式,图片大小小于5M。这个参数可为nil。由于只能传一张图片,若imageObject和url都有值,请看@caution。 @param url 图片的URL地址,必须以http开头。这个参数可为nil,由于只能传一张图片,若imageObject和url都有值,请看@caution。 @param accessToken 当前授权用户的accessToken @param otherProperties 一个NSDictionary字典,承载任意想额外添加到请求中的参数。 @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 @caution 注意,如果参数imageObject和url都有值,则发布带有imageObject所对应的图片,忽略url所对应的图片。 */ + (WBHttpRequest *)requestForShareAStatus:(NSString*)statusText contatinsAPicture:(WBImageObject*)imageObject orPictureUrl:(NSString*)url withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest+WeiboToken.h ================================================ // // WBHttpRequest+WeiboToken.h // WeiboSDK // // Created by DannionQiu on 14/11/6. // Copyright (c) 2014年 SINA iOS Team. All rights reserved. // #import "WBHttpRequest.h" @interface WBHttpRequest (WeiboToken) /*! @method @abstract 使用RefreshToken去换取新的身份凭证AccessToken. @discussion 在SSO授权登录后,服务器会下发有效期为7天的refreshToken以及有效期为1天的AccessToken。 当有效期为1天的AccessToken过期时,可以调用该接口带着refreshToken信息区换取新的AccessToken。 @param refreshToken refreshToken @param queue 指定发送请求的NSOperationQueue,如果这个参数为nil,则请求会发送在MainQueue( [NSOperationQueue mainQueue] )中。 @param handler 完成请求后会回调handler,处理完成请求后的逻辑。 */ + (WBHttpRequest *)requestForRenewAccessTokenWithRefreshToken:(NSString*)refreshToken queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest+WeiboUser.h ================================================ // // WBHttpRequest+WeiboUser.h // WeiboSDK // // Created by DannionQiu on 14-9-23. // Copyright (c) 2014年 SINA iOS Team. All rights reserved. // #import "WBHttpRequest.h" @interface WBHttpRequest (WeiboUser) /*! @method @abstract Creates a request representing a Open API call to the "friendships/friends". @discussion Simplifies preparing a request and sending request to retrieve the user's friends. A successful Open API call will return an NSDictionary of objects which contanis an array of objects representing the user's friends. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/friends/en @param currentUserID should be the current User's UserID which has been authorized. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForFriendsListOfUser:(NSString*)currentUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/friends/ids". @discussion Simplifies preparing a request and sending request to retrieve the user's friends' UserID. A successful Open API call will return an NSDictionary of objects which contanis an array of NSString representing the user's friends' UserID. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/friends/ids/en @param currentUserID should be the current User's UserID which has been authorized. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForFriendsUserIDListOfUser:(NSString*)currentUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/friends/in_common". @discussion Simplifies preparing a request and sending request to retrieve the common friends list between two users.. A successful Open API call will return an NSDictionary of objects which contanis an array of objects representing the user's friends. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/friends/in_common/en @param currentUserID should be the current User's UserID which has been authorized. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForCommonFriendsListBetweenUser:(NSString*)currentUserID andUser:(NSString*)anotherUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/friends/bilateral". @discussion Simplifies preparing a request and sending request to retrieve the list of the users that are following the specified user and are being followed by the specified user. A successful Open API call will return an NSDictionary of objects which contanis an array of objects representing the users that are following the specified user and are being followed by the specified user. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/friends/bilateral/en @param currentUserID should be the current User's UserID which has been authorized. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForBilateralFriendsListOfUser:(NSString*)currentUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/followers". @discussion Simplifies preparing a request and sending request to retrieve the user's followers. A successful Open API call will return an NSDictionary of objects which contanis an array of objects representing the user's followers. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/followers/en @param currentUserID should be the current User's UserID which has been authorized. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForFollowersListOfUser:(NSString*)currentUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/followers/ids". @discussion Simplifies preparing a request and sending request to retrieve the user's followers' UserID. A successful Open API call will return an NSDictionary of objects which contanis an array of NSString representing the user's followers' UserID. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/followers/ids/en @param currentUserID should be the current User's UserID which has been authorized. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForFollowersUserIDListOfUser:(NSString*)currentUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/followers/active". @discussion Simplifies preparing a request and sending request to retrieve the active(high quality) followers list of a user. A successful Open API call will return an NSDictionary of objects which contanis an array of objects representing the active(high quality) followers list of a user. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/followers/active/en @param currentUserID should be the current User's UserID which has been authorized. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForActiveFollowersListOfUser:(NSString*)currentUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/friends_chain/followers". @discussion Simplifies preparing a request and sending request to retrieve the users that are being followed by the authenticating user and are following the specified user. A successful Open API call will return an NSDictionary of objects which contanis an array of objects representing the users that are being followed by the authenticating user and are following the specified user. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/friends_chain/followers/en @param currentUserID should be the current User's UserID which has been authorized. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForBilateralFollowersListOfUser:(NSString*)currentUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/show". @discussion Simplifies preparing a request and sending request to retrieve the relationship of two users. A successful Open API call will return an NSDictionary of objects which contanis the relationship of two users. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/show @param targetUserID a User ID @param sourceUserID a User ID @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForFriendshipDetailBetweenTargetUser:(NSString*)targetUserID andSourceUser:(NSString*)sourceUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/create". @discussion Simplifies preparing a request and sending request to Follow a user. A successful Open API call will return an object representing the user to be followed. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/create/en @param theUserToBeFollowed the userID of the user which you want to follow. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForFollowAUser:(NSString*)theUserToBeFollowed withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/destroy". @discussion Simplifies preparing a request and sending request to cancel following a user. A successful Open API call will return an object representing the user to be followed. You can see more details about this API in http://open.weibo.com/wiki/2/friendships/destroy/en @param theUserThatYouDontLike the userID of the user which you want to cancel following. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForCancelFollowAUser:(NSString*)theUserThatYouDontLike withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "friendships/followers/destroy". @discussion Simplifies preparing a request and sending request to remove a follower of the authenticating user. A successful Open API call will return an object representing the user to be followed. this API requires advanced level authorization. You can see more details about advanced level authorization in http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E#scope You can see more details about this API in http://open.weibo.com/wiki/2/friendships/followers/destroy/en @param theUserThatYouDontLike the userID of the follower which you want to remove. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForRemoveFollowerUser:(NSString*)theUserThatYouDontLike withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "messages/invite". @discussion Simplifies preparing a request and sending request to send invitation to a bilateral friend of the authenticating user. A successful Open API call will return an NSDictionary of objects which contanis objects representing sender and receiver and other invitation details. You can see more details about this API in http://open.weibo.com/wiki/2/messages/invite @param theUserThatShouldBeYourBilateralFriend the userID of the follower which you want to remove. @param accessToken The token string. @param text The text content in your invitation message. should not be nil. @param url The url in your invitation message. can be nil. @param logoUrl The logoUrl in your invitation message. can be nil. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForInviteBilateralFriend:(NSString*)theUserThatShouldBeYourBilateralFriend withAccessToken:(NSString*)accessToken inviteText:(NSString*)text inviteUrl:(NSString*)url inviteLogoUrl:(NSString*)logoUrl queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /*! @method @abstract Creates a request representing a Open API call to the "users/show". @discussion Simplifies preparing a request and sending request to retrieve user profile by user ID.. A successful Open API call will return a object representing the user profile by user ID. You can see more details about this API in http://open.weibo.com/wiki/2/users/show/en @param aUserID a User ID. @param accessToken The token string. @param otherProperties Any additional properties for the Open API Request. @param queue specify the queue that you want to send request on, if this param is nil, the request will be start on MainQueue( [NSOperationQueue mainQueue] ). @param handler the comletion block which will be executed after received response from Open API server. */ + (WBHttpRequest *)requestForUserProfile:(NSString*)aUserID withAccessToken:(NSString*)accessToken andOtherProperties:(NSDictionary*)otherProperties queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBHttpRequest.h ================================================ // // WBHttpRequest.h // WeiboSDK // // Created by DannionQiu on 14-9-18. // Copyright (c) 2014年 SINA iOS Team. All rights reserved. // #import #import #pragma mark - WBHttpRequest and WBHttpRequestDelegate @class WBHttpRequest; /** 接收并处理来自微博sdk对于网络请求接口的调用响应 以及openAPI 如inviteFriend、logOutWithToken的请求 */ @protocol WBHttpRequestDelegate /** 收到一个来自微博Http请求的响应 @param response 具体的响应对象 */ @optional - (void)request:(WBHttpRequest *)request didReceiveResponse:(NSURLResponse *)response; /** 收到一个来自微博Http请求失败的响应 @param error 错误信息 */ @optional - (void)request:(WBHttpRequest *)request didFailWithError:(NSError *)error; /** 收到一个来自微博Http请求的网络返回 @param result 请求返回结果 */ @optional - (void)request:(WBHttpRequest *)request didFinishLoadingWithResult:(NSString *)result; /** 收到一个来自微博Http请求的网络返回 @param data 请求返回结果 */ @optional - (void)request:(WBHttpRequest *)request didFinishLoadingWithDataResult:(NSData *)data; /** 收到快速SSO授权的重定向 @param URI */ @optional - (void)request:(WBHttpRequest *)request didReciveRedirectResponseWithURI:(NSURL *)redirectUrl; @end /** 微博封装Http请求的消息结构 */ @interface WBHttpRequest : NSObject { NSURLConnection *connection; NSMutableData *responseData; } /** 用户自定义请求地址URL */ @property (nonatomic, strong) NSString *url; /** 用户自定义请求方式 支持"GET" "POST" */ @property (nonatomic, strong) NSString *httpMethod; /** 用户自定义请求参数字典 */ @property (nonatomic, strong) NSDictionary *params; /** WBHttpRequestDelegate对象,用于接收微博SDK对于发起的接口请求的请求的响应 */ @property (nonatomic, weak) id delegate; /** 用户自定义TAG 用于区分回调Request */ @property (nonatomic, strong) NSString* tag; /** 统一HTTP请求接口 调用此接口后,将发送一个HTTP网络请求 @param url 请求url地址 @param httpMethod 支持"GET" "POST" @param params 向接口传递的参数结构 @param delegate WBHttpRequestDelegate对象,用于接收微博SDK对于发起的接口请求的请求的响应 @param tag 用户自定义TAG,将通过回调WBHttpRequest实例的tag属性返回 */ + (WBHttpRequest *)requestWithURL:(NSString *)url httpMethod:(NSString *)httpMethod params:(NSDictionary *)params delegate:(id)delegate withTag:(NSString *)tag; /** 统一微博Open API HTTP请求接口 调用此接口后,将发送一个HTTP网络请求(用于访问微博open api) @param accessToken 应用获取到的accessToken,用于身份验证 @param url 请求url地址 @param httpMethod 支持"GET" "POST" @param params 向接口传递的参数结构 @param delegate WBHttpRequestDelegate对象,用于接收微博SDK对于发起的接口请求的请求的响应 @param tag 用户自定义TAG,将通过回调WBHttpRequest实例的tag属性返回 */ + (WBHttpRequest *)requestWithAccessToken:(NSString *)accessToken url:(NSString *)url httpMethod:(NSString *)httpMethod params:(NSDictionary *)params delegate:(id)delegate withTag:(NSString *)tag; /** 取消网络请求接口 调用此接口后,将取消当前网络请求,建议同时[WBHttpRequest setDelegate:nil]; 注意:该方法只对使用delegate的request方法有效。无法取消任何使用block的request的网络请求接口。 */ - (void)disconnect; #pragma mark - block extension typedef void (^WBRequestHandler)(WBHttpRequest *httpRequest, id result, NSError *error); /** 统一微博Open API HTTP请求接口 调用此接口后,将发送一个HTTP网络请求(用于访问微博open api) @param url 请求url地址 @param httpMethod 支持"GET" "POST" @param params 向接口传递的参数结构 @param queue 发起请求的NSOperationQueue对象,如queue为nil,则在主线程([NSOperationQueue mainQueue])发起请求。 @param handler 接口请求返回调用的block方法 */ + (WBHttpRequest *)requestWithURL:(NSString *)url httpMethod:(NSString *)httpMethod params:(NSDictionary *)params queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; /** 统一HTTP请求接口 调用此接口后,将发送一个HTTP网络请求 @param url 请求url地址 @param httpMethod 支持"GET" "POST" @param params 向接口传递的参数结构 @param queue 发起请求的NSOperationQueue对象,如queue为nil,则在主线程([NSOperationQueue mainQueue])发起请求。 @param handler 接口请求返回调用的block方法 */ + (WBHttpRequest *)requestWithAccessToken:(NSString *)accessToken url:(NSString *)url httpMethod:(NSString *)httpMethod params:(NSDictionary *)params queue:(NSOperationQueue*)queue withCompletionHandler:(WBRequestHandler)handler; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBSDKBasicButton.h ================================================ // // WBSDKBasicButton.h // WeiboSDK // // Created by DannionQiu on 14/10/24. // Copyright (c) 2014年 SINA iOS Team. All rights reserved. // #import @class WBSDKBasicButton; typedef void (^WBSDKButtonHandler)(WBSDKBasicButton *button, BOOL isSuccess, NSDictionary *resultDict); @interface WBSDKBasicButton : UIButton @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBSDKCommentButton.h ================================================ // // WBSDKCommentButton.h // WeiboSDK // // Created by DannionQiu on 14/10/26. // Copyright (c) 2014年 SINA iOS Team. All rights reserved. // #import "WBSDKBasicButton.h" @interface WBSDKCommentButton : WBSDKBasicButton /** 初始化一个社会化评论按钮 @param frame 按钮的frame值 @param accessToken 用户授权后获取的Token @param keyWord 社会化评论的热点词 @param urlString 社会化评论链接,可传空 @param category 领域ID, 此参数为必选参数。 @param handler 回调函数,当用户点击按钮,进行完与社会化评论组件相关的交互之后,回调的函数。 */ - (id)initWithFrame:(CGRect)frame accessToken:(NSString*)accessToken keyword:(NSString*)keyWord urlString:(NSString*)urlString category:(NSString*)category completionHandler:(WBSDKButtonHandler)handler; @property (nonatomic, strong)NSString* keyWord; @property (nonatomic, strong)NSString* accessToken; @property (nonatomic, strong)NSString* urlString; @property (nonatomic, strong)NSString* category; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WBSDKRelationshipButton.h ================================================ // // WBSDKRelationshipButton.h // WeiboSDK // // Created by DannionQiu on 14/10/26. // Copyright (c) 2014年 SINA iOS Team. All rights reserved. // #import "WBSDKBasicButton.h" enum { WBSDKRelationshipButtonStateFollow, WBSDKRelationshipButtonStateUnfollow }; typedef NSUInteger WBSDKRelationshipButtonState; @interface WBSDKRelationshipButton : WBSDKBasicButton /** 初始化一个关注组件按钮 @param frame 按钮的frame值 @param accessToken 用户授权后获取的Token @param currentUserID 当前用户的uid值 @param followerUserID 希望当前用户加关注的用户uid值 @param handler 回调函数,当用户点击按钮,进行完关注组件相关的交互之后,回调的函数。 */ - (id)initWithFrame:(CGRect)frame accessToken:(NSString*)accessToken currentUser:(NSString*)currentUserID followUser:(NSString*)followerUserID completionHandler:(WBSDKButtonHandler)handler; @property (nonatomic, strong)NSString* accessToken; @property (nonatomic, strong)NSString* currentUserID; @property (nonatomic, strong)NSString* followUserID; @property (nonatomic, assign)WBSDKRelationshipButtonState currentRelationShip; /** 获取最新的关注状态 该方法会调用OpenApi,获取当前用户与目标用户之间的关注状态,并将按钮的状态改变为正确的状态。 */ - (void)checkCurrentRelationship; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WeiboSDK.bundle/others/countryList ================================================ {"香港地区":{"code":"00852","rule":{"mcc":["454"]}},"台湾地区":{"code":"00886","rule":{"mcc":["466"]}},"澳门地区":{"code":"00853","rule":{"mcc":["455"]}},"日本":{"code":"0081","rule":{"mcc":["440","441"]}},"韩国":{"code":"0082","rule":{"mcc":["450"]}},"新加坡":{"code":"0065","rule":{"mcc":["525"]}},"马来西亚":{"code":"0060","rule":{"mcc":["502"]}},"美国":{"code":"001","rule":{"mcc":["310","311","316"]}},"加拿大":{"code":"001","rule":{"mcc":["302"]}},"澳大利亚":{"code":"0061","rule":{"mcc":["505"]}},"英国":{"code":"0044","rule":{"mcc":["234"]}},"法国":{"code":"0033","rule":{"mcc":["208"]}},"俄罗斯":{"code":"007","rule":{"mcc":["250"]}},"印度":{"code":"0091","rule":{"mcc":["404"]}},"泰国":{"code":"0066","rule":{"mcc":["520"]}},"德国":{"code":"0049","rule":{"mcc":["262"]}}} ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WeiboSDK.h ================================================ // // WeiboSDKHeaders.h // WeiboSDKDemo // // Created by Wade Cheng on 4/3/13. // Copyright (c) 2013 SINA iOS Team. All rights reserved. // #import #import #import "WBHttpRequest.h" #import "WBHttpRequest+WeiboUser.h" #import "WBHttpRequest+WeiboShare.h" #import "WBHttpRequest+WeiboToken.h" #import "WBHttpRequest+WeiboGame.h" #import "WBSDKRelationshipButton.h" #import "WBSDKCommentButton.h" typedef NS_ENUM(NSInteger, WeiboSDKResponseStatusCode) { WeiboSDKResponseStatusCodeSuccess = 0,//成功 WeiboSDKResponseStatusCodeUserCancel = -1,//用户取消发送 WeiboSDKResponseStatusCodeSentFail = -2,//发送失败 WeiboSDKResponseStatusCodeAuthDeny = -3,//授权失败 WeiboSDKResponseStatusCodeUserCancelInstall = -4,//用户取消安装微博客户端 WeiboSDKResponseStatusCodePayFail = -5,//支付失败 WeiboSDKResponseStatusCodeShareInSDKFailed = -8,//分享失败 详情见response UserInfo WeiboSDKResponseStatusCodeUnsupport = -99,//不支持的请求 WeiboSDKResponseStatusCodeUnknown = -100, }; @protocol WeiboSDKDelegate; @protocol WBHttpRequestDelegate; @class WBBaseRequest; @class WBBaseResponse; @class WBMessageObject; @class WBImageObject; @class WBBaseMediaObject; @class WBHttpRequest; @class WBOrderObject; /** 微博SDK接口类 */ @interface WeiboSDK : NSObject /** 检查用户是否安装了微博客户端程序 @return 已安装返回YES,未安装返回NO */ + (BOOL)isWeiboAppInstalled; /** 检查用户是否可以通过微博客户端进行分享 @return 可以使用返回YES,不可以使用返回NO */ + (BOOL)isCanShareInWeiboAPP; /** 检查用户是否可以使用微博客户端进行SSO授权 @return 可以使用返回YES,不可以使用返回NO */ + (BOOL)isCanSSOInWeiboApp; /** 打开微博客户端程序 @return 成功打开返回YES,失败返回NO */ + (BOOL)openWeiboApp; /** 获取微博客户端程序的itunes安装地址 @return 微博客户端程序的itunes安装地址 */ + (NSString *)getWeiboAppInstallUrl; /** 获取当前微博客户端程序所支持的SDK最高版本 @return 当前微博客户端程序所支持的SDK最高版本号,返回 nil 表示未安装微博客户端 */ + (NSString *)getWeiboAppSupportMaxSDKVersion __attribute__((deprecated)); /** 获取当前微博SDK的版本号 @return 当前微博SDK的版本号 */ + (NSString *)getSDKVersion; extern NSString * const WeiboSDKGetAidSucessNotification; extern NSString * const WeiboSDKGetAidFailNotification; /** 获取当前微博SDK的aid 返回的aid值可能为 nil ,当值为 nil 时会尝试获取 aid 值。 当获取成功( aid 值变为有效值)时,SDK会发出名为 WeiboSDKGetAidSucessNotification 的通知,通知中带有 aid 值。 当获取失败时,SDK会发出名为 WeiboSDKGetAidFailNotification 的通知,通知中带有 NSError 对象。 @return aid 用于广告的与设备信息相关的标识符 */ + (NSString *)getWeiboAid; /** 向微博客户端程序注册第三方应用 @param appKey 微博开放平台第三方应用appKey @return 注册成功返回YES,失败返回NO */ + (BOOL)registerApp:(NSString *)appKey; /** 处理微博客户端程序通过URL启动第三方应用时传递的数据 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用 @param url 启动第三方应用的URL @param delegate WeiboSDKDelegate对象,用于接收微博触发的消息 @see WeiboSDKDelegate */ + (BOOL)handleOpenURL:(NSURL *)url delegate:(id)delegate; /** 发送请求给微博客户端程序,并切换到微博 请求发送给微博客户端程序之后,微博客户端程序会进行相关的处理,处理完成之后一定会调用 [WeiboSDKDelegate didReceiveWeiboResponse:] 方法将处理结果返回给第三方应用 @param request 具体的发送请求 @see [WeiboSDKDelegate didReceiveWeiboResponse:] @see WBBaseResponse */ + (BOOL)sendRequest:(WBBaseRequest *)request; /** 收到微博客户端程序的请求后,发送对应的应答给微博客户端端程序,并切换到微博 第三方应用收到微博的请求后,异步处理该请求,完成后必须调用该函数将应答返回给微博 @param response 具体的应答内容 @see WBBaseRequest */ + (BOOL)sendResponse:(WBBaseResponse *)response; /** 设置WeiboSDK的调试模式 当开启调试模式时,WeiboSDK会在控制台输出详细的日志信息,开发者可以据此调试自己的程序。默认为 NO @param enabled 开启或关闭WeiboSDK的调试模式 */ + (void)enableDebugMode:(BOOL)enabled; /** 取消授权,登出接口 调用此接口后,token将失效 @param token 第三方应用之前申请的Token @param delegate WBHttpRequestDelegate对象,用于接收微博SDK对于发起的接口请求的请求的响应 @param tag 用户自定义TAG,将通过回调WBHttpRequest实例的tag属性返回 */ + (void)logOutWithToken:(NSString *)token delegate:(id)delegate withTag:(NSString*)tag; /** 邀请好友使用应用 调用此接口后,将发送私信至好友,成功将返回微博标准私信结构 @param data 邀请数据。必须为json字串的形式,必须做URLEncode,采用UTF-8编码。 data参数支持的参数: 参数名称 值的类型 是否必填 说明描述 text string true 要回复的私信文本内容。文本大小必须小于300个汉字。 url string false 邀请点击后跳转链接。默认为当前应用地址。 invite_logo string false 邀请Card展示时的图标地址,大小必须为80px X 80px,仅支持PNG、JPG格式。默认为当前应用logo地址。 @param uid 被邀请人,需为当前用户互粉好友。 @param access_token 第三方应用之前申请的Token @param delegate WBHttpRequestDelegate对象,用于接收微博SDK对于发起的接口请求的请求的响应 @param tag 用户自定义TAG,将通过回调WBHttpRequest实例的tag属性返回 */ + (void)inviteFriend:(NSString* )data withUid:(NSString *)uid withToken:(NSString *)access_token delegate:(id)delegate withTag:(NSString*)tag; /* 第三方调用微博短信注册或者登陆 @param navTitle 为登陆页navigationBar的title,如果为空的话,默认为“验证码登陆” */ + (void)messageRegister:(NSString *)navTitle; @end /** 接收并处理来至微博客户端程序的事件消息 */ @protocol WeiboSDKDelegate /** 收到一个来自微博客户端程序的请求 收到微博的请求后,第三方应用应该按照请求类型进行处理,处理完后必须通过 [WeiboSDK sendResponse:] 将结果回传给微博 @param request 具体的请求对象 */ - (void)didReceiveWeiboRequest:(WBBaseRequest *)request; /** 收到一个来自微博客户端程序的响应 收到微博的响应后,第三方应用可以通过响应类型、响应的数据和 WBBaseResponse.userInfo 中的数据完成自己的功能 @param response 具体的响应对象 */ - (void)didReceiveWeiboResponse:(WBBaseResponse *)response; @end #pragma mark - DataTransferObject and Base Request/Response /** 微博客户端程序和第三方应用之间传输数据信息的基类 */ @interface WBDataTransferObject : NSObject /** 自定义信息字典,用于数据传输过程中存储相关的上下文环境数据 第三方应用给微博客户端程序发送 request 时,可以在 userInfo 中存储请求相关的信息。 @warning userInfo中的数据必须是实现了 `NSCoding` 协议的对象,必须保证能序列化和反序列化 @warning 序列化后的数据不能大于10M */ @property (nonatomic, strong) NSDictionary *userInfo; /** 发送该数据对象的SDK版本号 如果数据对象是自己生成的,则sdkVersion为当前SDK的版本号;如果是接收到的数据对象,则sdkVersion为数据发送方SDK版本号 */ @property (strong, nonatomic, readonly) NSString *sdkVersion; /** 当用户没有安装微博客户端程序时是否提示用户打开微博安装页面 如果设置为YES,当用户未安装微博时会弹出Alert询问用户是否要打开微博App的安装页面。默认为YES */ @property (nonatomic, assign) BOOL shouldOpenWeiboAppInstallPageIfNotInstalled; @end /** 微博SDK所有请求类的基类 */ @interface WBBaseRequest : WBDataTransferObject /** 返回一个 WBBaseRequest 对象 @return 返回一个*自动释放的*WBBaseRequest对象 */ + (id)request; @end /** 微博SDK所有响应类的基类 */ @interface WBBaseResponse : WBDataTransferObject /** 对应的 request 中的自定义信息字典 如果当前 response 是由微博客户端响应给第三方应用的,则 requestUserInfo 中会包含原 request.userInfo 中的所有数据 @see WBBaseRequest.userInfo */ @property (strong, nonatomic, readonly) NSDictionary *requestUserInfo; /** 响应状态码 第三方应用可以通过statusCode判断请求的处理结果 */ @property (nonatomic, assign) WeiboSDKResponseStatusCode statusCode; /** 返回一个 WBBaseResponse 对象 @return 返回一个*自动释放的*WBBaseResponse对象 */ + (id)response; @end #pragma mark - Authorize Request/Response /** 第三方应用向微博客户端请求认证的消息结构 第三方应用向微博客户端申请认证时,需要调用 [WeiboSDK sendRequest:] 函数, 向微博客户端发送一个 WBAuthorizeRequest 的消息结构。 微博客户端处理完后会向第三方应用发送一个结构为 WBAuthorizeResponse 的处理结果。 */ @interface WBAuthorizeRequest : WBBaseRequest /** 微博开放平台第三方应用授权回调页地址,默认为`http://` 参考 http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E#.E5.AE.A2.E6.88.B7.E7.AB.AF.E9.BB.98.E8.AE.A4.E5.9B.9E.E8.B0.83.E9.A1.B5 @warning 必须保证和在微博开放平台应用管理界面配置的“授权回调页”地址一致,如未进行配置则默认为`http://` @warning 不能为空,长度小于1K */ @property (nonatomic, strong) NSString *redirectURI; /** 微博开放平台第三方应用scope,多个scrope用逗号分隔 参考 http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E#scope @warning 长度小于1K */ @property (nonatomic, strong) NSString *scope; /** 当用户没有安装微博客户端或微博客户端过低无法支持SSO的时候是否弹出SDK自带的Webview进行授权 如果设置为YES,当用户没有安装微博客户端或微博客户端过低无法支持SSO的时候会自动弹出SDK自带的Webview进行授权。 如果设置为NO,会根据 shouldOpenWeiboAppInstallPageIfNotInstalled 属性判断是否弹出安装/更新微博的对话框 默认为YES */ @property (nonatomic, assign) BOOL shouldShowWebViewForAuthIfCannotSSO; @end /** 微博客户端处理完第三方应用的认证申请后向第三方应用回送的处理结果 WBAuthorizeResponse 结构中仅包含常用的 userID 、accessToken 和 expirationDate 信息,其他的认证信息(比如部分应用可以获取的 refresh_token 信息)会统一存放到 userInfo 中 */ @interface WBAuthorizeResponse : WBBaseResponse /** 用户ID */ @property (nonatomic, strong) NSString *userID; /** 认证口令 */ @property (nonatomic, strong) NSString *accessToken; /** 认证过期时间 */ @property (nonatomic, strong) NSDate *expirationDate; /** 当认证口令过期时用于换取认证口令的更新口令 */ @property (nonatomic, strong) NSString *refreshToken; @end #pragma mark - ProvideMessageForWeibo Request/Response /** 微博客户端向第三方程序请求提供内容的消息结构 */ @interface WBProvideMessageForWeiboRequest : WBBaseRequest @end /** 微博客户端向第三方应用请求提供内容,第三方应用向微博客户端返回的消息结构 */ @interface WBProvideMessageForWeiboResponse : WBBaseResponse /** 提供给微博客户端的消息 */ @property (nonatomic, strong) WBMessageObject *message; /** 返回一个 WBProvideMessageForWeiboResponse 对象 @param message 需要回送给微博客户端程序的消息对象 @return 返回一个*自动释放的*WBProvideMessageForWeiboResponse对象 */ + (id)responseWithMessage:(WBMessageObject *)message; @end #pragma mark - SendMessageToWeibo Request/Response /** 第三方应用发送消息至微博客户端程序的消息结构体 */ @interface WBSendMessageToWeiboRequest : WBBaseRequest /** 发送给微博客户端的消息 */ @property (nonatomic, strong) WBMessageObject *message; /** 返回一个 WBSendMessageToWeiboRequest 对象 此方法生成对象被[WeiboSDK sendRequest:]会唤起微博客户端的发布器进行分享,如果未安装微博客户端或客户端版本太低 会根据 shouldOpenWeiboAppInstallPageIfNotInstalled 属性判断是否弹出安装/更新微博的对话框 @param message 需要发送给微博客户端的消息对象 @return 返回一个*自动释放的*WBSendMessageToWeiboRequest对象 */ + (id)requestWithMessage:(WBMessageObject *)message; /** 返回一个 WBSendMessageToWeiboRequest 对象 当用户安装了可以支持微博客户端內分享的微博客户端时,会自动唤起微博并分享 当用户没有安装微博客户端或微博客户端过低无法支持通过客户端內分享的时候会自动唤起SDK內微博发布器 @param message 需要发送给微博的消息对象 @param authRequest 授权相关信息,与access_token二者至少有一个不为空,当access_token为空并且需要弹出SDK內发布器时会通过此信息先进行授权后再分享 @param access_token 第三方应用之前申请的Token,当此值不为空并且无法通过客户端分享的时候,会使用此token进行分享。 @return 返回一个*自动释放的*WBSendMessageToWeiboRequest对象 */ + (id)requestWithMessage:(WBMessageObject *)message authInfo:(WBAuthorizeRequest *)authRequest access_token:(NSString *)access_token; @end /** WBSendMessageToWeiboResponse */ @interface WBSendMessageToWeiboResponse : WBBaseResponse /** 可能在分享过程中用户进行了授权操作,当此值不为空时,为用户相应授权信息 */ @property (nonatomic,strong) WBAuthorizeResponse *authResponse; @end #pragma mark - AppRecomend Request/Response /** 第三方应用私信好友推荐app的请求 */ @interface WBSDKAppRecommendRequest : WBBaseRequest /** 返回一个 WBSDKAppRecommendRequest 对象 @param uids 为推荐的好友列表,为空时跳转到用户自选的页面 @param access_token 第三方应用之前申请的Token,当此值不为空并且无法通过客户端分享的时候,会使用此token私信。 @return 返回一个*自动释放的*WBSDKAppRecommendRequest对象 */ + (id)requestWithUIDs:(NSArray *)uids access_token:(NSString *)access_token; /** 私信对象列表 */ @property (nonatomic, strong) NSArray* uids; /** 用于认证的Token */ @property (nonatomic, strong) NSString *access_token; @end /** 第三方应用私信好友推荐app的响应 WBSDKAppRecommendResponse 结构中仅包含常用的 userID 、accessToken 和 expirationDate 信息,其他的认证信息(比如部分应用可以获取的 refresh_token 信息)会统一存放到 userInfo 中 */ @interface WBSDKAppRecommendResponse : WBBaseResponse @property (nonatomic,strong) WBAuthorizeResponse *authResponse; /** 用户ID */ @property (nonatomic, strong) NSString *userID; /** 认证口令 */ @property (nonatomic, strong) NSString *accessToken; /** 认证过期时间 */ @property (nonatomic, strong) NSDate *expirationDate; /** 当认证口令过期时用于换取认证口令的更新口令 */ @property (nonatomic, strong) NSString *refreshToken; @end #pragma mark - Payment Request/Response /** 第三方应用发送消息至微博客户端程序的消息结构体 */ @interface WBPaymentRequest : WBBaseRequest /** 发送给微博客户端的订单 */ @property (nonatomic, strong) WBOrderObject *order; /** 返回一个 WBPaymentRequest 对象 @param message 需要发送给微博客户端程序的消息对象 @return 返回一个*自动释放的*WBSendMessageToWeiboRequest对象 */ + (id)requestWithOrder:(WBOrderObject *)order; @end /** WBPaymentResponse */ @interface WBPaymentResponse : WBBaseResponse /** 支付返回状态码 */ @property (nonatomic, strong) NSString *payStatusCode; /** 支付返回状态信息 */ @property (nonatomic, strong) NSString *payStatusMessage; @end #pragma mark - MessageObject / ImageObject /** 微博客户端程序和第三方应用之间传递的消息结构 一个消息结构由三部分组成:文字、图片和多媒体数据。三部分内容中至少有一项不为空,图片和多媒体数据不能共存。 */ @interface WBMessageObject : NSObject /** 消息的文本内容 @warning 长度小于140个汉字 */ @property (nonatomic, strong) NSString *text; /** 消息的图片内容 @see WBImageObject */ @property (nonatomic, strong) WBImageObject *imageObject; /** 消息的多媒体内容 @see WBBaseMediaObject */ @property (nonatomic, strong) WBBaseMediaObject *mediaObject; /** 返回一个 WBMessageObject 对象 @return 返回一个*自动释放的*WBMessageObject对象 */ + (id)message; @end /** 消息中包含的图片数据对象 */ @interface WBImageObject : NSObject /** 图片真实数据内容 @warning 大小不能超过10M */ @property (nonatomic, strong) NSData *imageData; /** 返回一个 WBImageObject 对象 @return 返回一个*自动释放的*WBImageObject对象 */ + (id)object; /** 返回一个 UIImage 对象 @return 返回一个*自动释放的*UIImage对象 */ - (UIImage *)image; @end #pragma mark - Message Media Objects /** 消息中包含的多媒体数据对象基类 */ @interface WBBaseMediaObject : NSObject /** 对象唯一ID,用于唯一标识一个多媒体内容 当第三方应用分享多媒体内容到微博时,应该将此参数设置为被分享的内容在自己的系统中的唯一标识 @warning 不能为空,长度小于255 */ @property (nonatomic, strong) NSString *objectID; /** 多媒体内容标题 @warning 不能为空且长度小于1k */ @property (nonatomic, strong) NSString *title; /** 多媒体内容描述 @warning 长度小于1k */ @property (nonatomic, strong) NSString *description; /** 多媒体内容缩略图 @warning 大小小于32k */ @property (nonatomic, strong) NSData *thumbnailData; /** 点击多媒体内容之后呼起第三方应用特定页面的scheme @warning 长度小于255 */ @property (nonatomic, strong) NSString *scheme; /** 返回一个 WBBaseMediaObject 对象 @return 返回一个*自动释放的*WBBaseMediaObject对象 */ + (id)object; @end #pragma mark - Message Video Objects /** 消息中包含的视频数据对象 */ @interface WBVideoObject : WBBaseMediaObject /** 视频网页的url @warning 不能为空且长度不能超过255 */ @property (nonatomic, strong) NSString *videoUrl; /** 视频lowband网页的url @warning 长度不能超过255 */ @property (nonatomic, strong) NSString *videoLowBandUrl; /** 视频数据流url @warning 长度不能超过255 */ @property (nonatomic, strong) NSString *videoStreamUrl; /** 视频lowband数据流url @warning 长度不能超过255 */ @property (nonatomic, strong) NSString *videoLowBandStreamUrl; @end #pragma mark - Message Music Objects /** 消息中包含的音乐数据对象 */ @interface WBMusicObject : WBBaseMediaObject /** 音乐网页url地址 @warning 不能为空且长度不能超过255 */ @property (nonatomic, strong) NSString *musicUrl; /** 音乐lowband网页url地址 @warning 长度不能超过255 */ @property (nonatomic, strong) NSString *musicLowBandUrl; /** 音乐数据流url @warning 长度不能超过255 */ @property (nonatomic, strong) NSString *musicStreamUrl; /** 音乐lowband数据流url @warning 长度不能超过255 */ @property (nonatomic, strong) NSString *musicLowBandStreamUrl; @end #pragma mark - Message WebPage Objects /** 消息中包含的网页数据对象 */ @interface WBWebpageObject : WBBaseMediaObject /** 网页的url地址 @warning 不能为空且长度不能超过255 */ @property (nonatomic, strong) NSString *webpageUrl; @end #pragma mark - OrderObject /** 微博客户端程序和第三方应用之间传递的订单结构 */ @interface WBOrderObject : NSObject /** 订单编号 */ @property (nonatomic, strong) NSString *orderString; /** 返回一个 WBOrderObject 对象 @return 返回一个*自动释放的*WBOrderObject对象 */ + (id)order; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/WeiboUser.h ================================================ // // WeiboUser.h // WeiboSDK // // Created by DannionQiu on 14-9-23. // Copyright (c) 2014年 SINA iOS Team. All rights reserved. // #import /*@ You can get the latest WeiboUser field description on http://open.weibo.com/wiki/2/friendships/friends/en . */ @interface WeiboUser : NSObject - (instancetype)initWithDictionary:(NSDictionary*)paraDict; + (instancetype)userWithDictionary:(NSDictionary*)paraDict; // Validate the dictionary to be converted. + (BOOL)isValidForDictionary:(NSDictionary *)dict; - (BOOL)updateWithDictionary:(NSDictionary*)paraDict; @property(readwrite, strong, nonatomic) NSString* userID; @property(readwrite, strong, nonatomic) NSString* userClass; @property(readwrite, strong, nonatomic) NSString* screenName; @property(readwrite, strong, nonatomic) NSString* name; @property(readwrite, strong, nonatomic) NSString* province; @property(readwrite, strong, nonatomic) NSString* city; @property(readwrite, strong, nonatomic) NSString* location; @property(readwrite, strong, nonatomic) NSString* userDescription; @property(readwrite, strong, nonatomic) NSString* url; @property(readwrite, strong, nonatomic) NSString* profileImageUrl; @property(readwrite, strong, nonatomic) NSString* coverImageUrl; @property(readwrite, strong, nonatomic) NSString* coverImageForPhoneUrl; @property(readwrite, strong, nonatomic) NSString* profileUrl; @property(readwrite, strong, nonatomic) NSString* userDomain; @property(readwrite, strong, nonatomic) NSString* weihao; @property(readwrite, strong, nonatomic) NSString* gender; @property(readwrite, strong, nonatomic) NSString* followersCount; @property(readwrite, strong, nonatomic) NSString* friendsCount; @property(readwrite, strong, nonatomic) NSString* pageFriendsCount; @property(readwrite, strong, nonatomic) NSString* statusesCount; @property(readwrite, strong, nonatomic) NSString* favouritesCount; @property(readwrite, strong, nonatomic) NSString* createdTime; @property(readwrite, assign, nonatomic) BOOL isFollowingMe; @property(readwrite, assign, nonatomic) BOOL isFollowingByMe; @property(readwrite, assign, nonatomic) BOOL isAllowAllActMsg; @property(readwrite, assign, nonatomic) BOOL isAllowAllComment; @property(readwrite, assign, nonatomic) BOOL isGeoEnabled; @property(readwrite, assign, nonatomic) BOOL isVerified; @property(readwrite, strong, nonatomic) NSString* verifiedType; @property(readwrite, strong, nonatomic) NSString* remark; @property(readwrite, strong, nonatomic) NSString* statusID; @property(readwrite, strong, nonatomic) NSString* ptype; @property(readwrite, strong, nonatomic) NSString* avatarLargeUrl; @property(readwrite, strong, nonatomic) NSString* avatarHDUrl; @property(readwrite, strong, nonatomic) NSString* verifiedReason; @property(readwrite, strong, nonatomic) NSString* verifiedTrade; @property(readwrite, strong, nonatomic) NSString* verifiedReasonUrl; @property(readwrite, strong, nonatomic) NSString* verifiedSource; @property(readwrite, strong, nonatomic) NSString* verifiedSourceUrl; @property(readwrite, strong, nonatomic) NSString* verifiedState; @property(readwrite, strong, nonatomic) NSString* verifiedLevel; @property(readwrite, strong, nonatomic) NSString* onlineStatus; @property(readwrite, strong, nonatomic) NSString* biFollowersCount; @property(readwrite, strong, nonatomic) NSString* language; @property(readwrite, strong, nonatomic) NSString* star; @property(readwrite, strong, nonatomic) NSString* mbtype; @property(readwrite, strong, nonatomic) NSString* mbrank; @property(readwrite, strong, nonatomic) NSString* block_word; @property(readwrite, strong, nonatomic) NSString* block_app; @property(readwrite, strong, nonatomic) NSString* credit_score; @property(readwrite, strong, nonatomic) NSDictionary* originParaDict; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/SinaSSO/libWeiboSDK.a ================================================ [File too large to display: 11.6 MB] ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/Headers/QQApiInterface.h ================================================ /// /// \file QQApiInterface.h /// \brief QQApi接口简化封装 /// /// Created by Tencent on 12-5-15. /// Copyright (c) 2012年 Tencent. All rights reserved. /// #import #import "QQApiInterfaceObject.h" /** \brief 处理来至QQ的请求及响应的回调协议 */ @protocol QQApiInterfaceDelegate /** 处理来至QQ的请求 */ - (void)onReq:(QQBaseReq *)req; /** 处理来至QQ的响应 */ - (void)onResp:(QQBaseResp *)resp; /** 处理QQ在线状态的回调 */ - (void)isOnlineResponse:(NSDictionary *)response; @end /** \brief 对QQApi的简单封装类 */ @interface QQApiInterface : NSObject /** 处理由手Q唤起的跳转请求 \param url 待处理的url跳转请求 \param delegate 第三方应用用于处理来至QQ请求及响应的委托对象 \return 跳转请求处理结果,YES表示成功处理,NO表示不支持的请求协议或处理失败 */ + (BOOL)handleOpenURL:(NSURL *)url delegate:(id)delegate; /** 向手Q发起分享请求 \param req 分享内容的请求 \return 请求发送结果码 */ + (QQApiSendResultCode)sendReq:(QQBaseReq *)req; /** 向手Q QZone结合版发起分享请求 \note H5分享只支持单张网络图片的传递 \param req 分享内容的请求 \return 请求发送结果码 */ + (QQApiSendResultCode)SendReqToQZone:(QQBaseReq *)req; /** 向手Q 群部落发起分享请求 \note H5分享只支持单张网络图片的传递 \param req 分享内容的请求 \return 请求发送结果码 */ + (QQApiSendResultCode)SendReqToQQGroupTribe:(QQBaseReq *)req; /** 向手Q发送应答消息 \param resp 应答消息 \return 应答发送结果码 */ + (QQApiSendResultCode)sendResp:(QQBaseResp *)resp; /** 检测是否已安装QQ \return 如果QQ已安装则返回YES,否则返回NO */ + (BOOL)isQQInstalled; /** 批量检测QQ号码是否在线 */ + (void)getQQUinOnlineStatues:(NSArray *)QQUins delegate:(id)delegate; /** 检测QQ是否支持API调用 \return 如果当前安装QQ版本支持API调用则返回YES,否则返回NO */ + (BOOL)isQQSupportApi; /** 启动QQ \return 成功返回YES,否则返回NO */ + (BOOL)openQQ; /** 获取QQ下载地址 如果App通过QQApiInterface#isQQInstalledQQApiInterface#isQQSupportApi检测发现QQ没安装或当前版本QQ不支持API调用,可引导用户通过打开此链接下载最新版QQ。 \return iPhoneQQ下载地址 */ + (NSString *)getQQInstallUrl; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/Headers/QQApiInterfaceObject.h ================================================ /// /// \file QQApiInterfaceObject.h /// \brief QQApiInterface所依赖的请求及应答消息对象封装帮助类 /// /// Created by Tencent on 12-5-15. /// Copyright (c) 2012年 Tencent. All rights reserved. /// #ifndef QQApiInterface_QQAPIOBJECT_h #define QQApiInterface_QQAPIOBJECT_h #import typedef enum { EQQAPISENDSUCESS = 0, EQQAPIQQNOTINSTALLED = 1, EQQAPIQQNOTSUPPORTAPI = 2, EQQAPIMESSAGETYPEINVALID = 3, EQQAPIMESSAGECONTENTNULL = 4, EQQAPIMESSAGECONTENTINVALID = 5, EQQAPIAPPNOTREGISTED = 6, EQQAPIAPPSHAREASYNC = 7, EQQAPIQQNOTSUPPORTAPI_WITH_ERRORSHOW = 8, EQQAPISENDFAILD = -1, //qzone分享不支持text类型分享 EQQAPIQZONENOTSUPPORTTEXT = 10000, //qzone分享不支持image类型分享 EQQAPIQZONENOTSUPPORTIMAGE = 10001, } QQApiSendResultCode; #pragma mark - QQApiObject(分享对象类型) // QQApiObject control flags enum { kQQAPICtrlFlagQZoneShareOnStart = 0x01, kQQAPICtrlFlagQZoneShareForbid = 0x02, kQQAPICtrlFlagQQShare = 0x04, kQQAPICtrlFlagQQShareFavorites = 0x08, //收藏 kQQAPICtrlFlagQQShareDataline = 0x10, //数据线 }; // QQApiObject /** \brief 所有在QQ及插件间发送的数据对象的根类。 */ @interface QQApiObject : NSObject @property(nonatomic,retain) NSString* title; ///< 标题,最长128个字符 @property(nonatomic,retain) NSString* description; ///<简要描述,最长512个字符 @property (nonatomic, assign) uint64_t cflag; @end // QQApiResultObject /** \brief 用于请求回应的数据类型。

可能错误码及描述如下:

errorerrorDescription注释
0nil成功
-1param error参数错误
-2group code is invalid该群不在自己的群列表里面
-3upload photo failed上传图片失败
-4user give up the current operation用户放弃当前操作
-5client internal error客户端内部处理错误
*/ @interface QQApiResultObject : QQApiObject @property(nonatomic,retain) NSString* error; ///<错误 @property(nonatomic,retain) NSString* errorDescription; ///<错误描述 @property(nonatomic,retain) NSString* extendInfo; ///<扩展信息 @end // QQApiTextObject /** \brief 文本对象 */ @interface QQApiTextObject : QQApiObject @property(nonatomic,retain)NSString* text; ///<文本内容,必填,最长1536个字符 -(id)initWithText:(NSString*)text; ///<初始化方法 +(id)objectWithText:(NSString*)text;///<工厂方法,获取一个QQApiTextObject对象. @end // QQApiURLObject typedef enum QQApiURLTargetType{ QQApiURLTargetTypeNotSpecified = 0x00, QQApiURLTargetTypeAudio = 0x01, QQApiURLTargetTypeVideo = 0x02, QQApiURLTargetTypeNews = 0x03 }QQApiURLTargetType; /** @brief URL对象类型。 包括URL地址,URL地址所指向的目标类型及预览图像。 */ @interface QQApiURLObject : QQApiObject /** URL地址所指向的目标类型. @note 参见QQApi.h 中的 QQApiURLTargetType 定义. */ @property(nonatomic)QQApiURLTargetType targetContentType; @property(nonatomic,retain)NSURL* url; ///QQApiExtendObject对象 @param data 数据内容 @param previewImageData 用于预览的图片 @param title 标题 @param description 此对象,分享的描述 @return 一个自动释放的QQApiExtendObject实例 */ + (id)objectWithData:(NSData*)data previewImageData:(NSData*)previewImageData title:(NSString*)title description:(NSString*)description; /** helper方法获取一个autorelease的QQApiExtendObject对象 @param data 数据内容 @param previewImageData 用于预览的图片 @param title 标题 @param description 此对象,分享的描述 @param imageDataArray 发送的多张图片队列 @return 一个自动释放的QQApiExtendObject实例 */ + (id)objectWithData:(NSData*)data previewImageData:(NSData*)previewImageData title:(NSString*)title description:(NSString*)description imageDataArray:(NSArray*)imageDataArray; @end // QQApiImageObject /** @brief 图片对象 用于分享图片内容的对象,是一个指定为图片类型的QQApiExtendObject */ @interface QQApiImageObject : QQApiExtendObject @end // QQApiImageArrayForQZoneObject /** @brief 图片对象 用于分享图片到空间,走写说说路径,是一个指定为图片类型的,当图片数组为空时,默认走文本写说说QQApiObject */ @interface QQApiImageArrayForQZoneObject : QQApiObject @property(nonatomic,retain) NSArray* imageDataArray;///图片数组 /** 初始化方法 @param imageDataArray 图片数组 @param title 写说说的内容,可以为空 */ - (id)initWithImageArrayData:(NSArray*)imageDataArray title:(NSString*)title; /** helper方法获取一个autorelease的QQApiExtendObject对象 @param title 写说说的内容,可以为空 @param imageDataArray 发送的多张图片队列 @return 一个自动释放的QQApiExtendObject实例 */ + (id)objectWithimageDataArray:(NSArray*)imageDataArray title:(NSString*)title; @end // QQApiVideoForQZoneObject /** @brief 视频对象 用于分享视频到空间,走写说说路径QQApiObject assetURL可传ALAsset的ALAssetPropertyAssetURL,或者PHAsset的localIdentifier */ @interface QQApiVideoForQZoneObject : QQApiObject @property(nonatomic, retain) NSString *assetURL; - (id)initWithAssetURL:(NSString*)assetURL title:(NSString*)title; + (id)objectWithAssetURL:(NSString*)assetURL title:(NSString*)title; @end // QQApiWebImageObject /** @brief 图片对象 用于分享网络图片内容的对象,是一个指定网络图片url的: 该类型只在2.9.0的h5分享中才支持, 原有的手q分享是不支持该类型的。 */ @interface QQApiWebImageObject : QQApiObject @property(nonatomic, retain) NSURL *previewImageURL; ///<预览图像URL /** 初始化方法 @param previewImageURL 用于预览的图片 @param title 标题 @param description 此对象,分享的描述 */ - (id)initWithPreviewImageURL:(NSURL*)previewImageURL title:(NSString*)title description:(NSString*)description; /** helper方法获取一个autorelease的QQApiWebImageObject对象 @param previewImageURL 用于预览的图片 @param title 标题 @param description 此对象,分享的描述 */ + (id)objectWithPreviewImageURL:(NSURL*)previewImageURL title:(NSString*)title description:(NSString*)description; @end // QQApiGroupTribeImageObject /** @brief 群部落图片对象 用于分享图片内容的对象,是一个指定为图片类型的 可以指定一些其他的附加数据QQApiExtendObject */ @interface QQApiGroupTribeImageObject : QQApiImageObject { NSString *_bid; NSString *_bname; } // 群部落id @property (nonatomic, retain)NSString* bid; // 群部落名称 @property (nonatomic, retain)NSString* bname; @end //QQApiFileObject /** @brief 本地文件对象(暂只支持分享到手机QQ数据线功能) 用于分享文件内容的对象,是一个指定为文件类型的QQApiExtendObject */ @interface QQApiFileObject : QQApiExtendObject { NSString* _fileName; } @property(nonatomic, retain)NSString* fileName; @end // QQApiAudioObject /** @brief 音频URL对象 用于分享目标内容为音频的URL的对象 */ @interface QQApiAudioObject : QQApiURLObject @property (nonatomic, retain) NSURL *flashURL; ///<音频URL地址,最长512个字符 /** 获取一个autorelease的QQApiAudioObject @param url 音频内容的目标URL @param title 分享内容的标题 @param description 分享内容的描述 @param data 分享内容的预览图像 @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE */ +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; /** 获取一个autorelease的QQApiAudioObject @param url 音频内容的目标URL @param title 分享内容的标题 @param description 分享内容的描述 @param previewURL 分享内容的预览图像URL @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE */ +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; @end // QQApiVideoObject /** @brief 视频URL对象 用于分享目标内容为视频的URL的对象 QQApiVideoObject类型的分享,目前在Android和PC QQ上接收消息时,展现有待完善,待手机QQ版本以后更新支持 目前如果要分享视频,推荐使用 QQApiNewsObject 类型 */ @interface QQApiVideoObject : QQApiURLObject @property (nonatomic, retain) NSURL *flashURL; ///<视频URL地址,最长512个字符 /** 获取一个autorelease的QQApiVideoObject @param url 视频内容的目标URL @param title 分享内容的标题 @param description 分享内容的描述 @param data 分享内容的预览图像 @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE */ +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; /** 获取一个autorelease的QQApiVideoObject @param url 视频内容的目标URL @param title 分享内容的标题 @param description 分享内容的描述 @param previewURL 分享内容的预览图像URL @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE */ +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; @end // QQApiNewsObject /** @brief 新闻URL对象 用于分享目标内容为新闻的URL的对象 */ @interface QQApiNewsObject : QQApiURLObject /** 获取一个autorelease的QQApiNewsObject @param url 视频内容的目标URL @param title 分享内容的标题 @param description 分享内容的描述 @param data 分享内容的预览图像 @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE */ +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; /** 获取一个autorelease的QQApiNewsObject @param url 视频内容的目标URL @param title 分享内容的标题 @param description 分享内容的描述 @param previewURL 分享内容的预览图像URL @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE */ +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; @end // QQApiPayObject /** \brief 支付对象 */ @interface QQApiPayObject : QQApiObject @property(nonatomic,retain)NSString* OrderNo; ///<支付订单号,必填 @property(nonatomic,retain)NSString* AppInfo; ///<支付来源信息,必填 -(id)initWithOrderNo:(NSString*)OrderNo AppInfo:(NSString*)AppInfo; ///<初始化方法 +(id)objectWithOrderNo:(NSString*)OrderNo AppInfo:(NSString*)AppInfo;///<工厂方法,获取一个QQApiPayObject对象. @end // QQApiCommonContentObject; /** @brief 通用模板类型对象 用于分享一个固定显示模板的图文混排对象 @note 图片列表和文本列表不能同时为空 */ @interface QQApiCommonContentObject : QQApiObject /** 预定义的界面布局类型 */ @property(nonatomic,assign) unsigned int layoutType; @property(nonatomic,assign) NSData* previewImageData;///<预览图 @property(nonatomic,retain) NSArray* textArray;///<文本列表 @property(nonatomic,retain) NSArray* pictureDataArray;///<图片列表 +(id)objectWithLayoutType:(int)layoutType textArray:(NSArray*)textArray pictureArray:(NSArray*)pictureArray previewImageData:(NSData*)data; /** 将一个NSDictionary对象转化为QQApiCommomContentObject,如果无法转换,则返回空 */ +(id)objectWithDictionary:(NSDictionary*)dic; -(NSDictionary*)toDictionary; @end //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Ad item object definition //////////////////////////////////////////////////////////////////////////////////////////////////////////// /** @brief 广告数据对象 */ @interface QQApiAdItem : NSObject @property(nonatomic,retain) NSString* title; ///<名称 @property(nonatomic,retain) NSString* description;///<描述 @property(nonatomic,retain) NSData* imageData;///<广告图片 @property(nonatomic,retain) NSURL* target;///<广告目标链接 @end // QQApiWPAObject /** \brief 发起WPA对象 */ @interface QQApiWPAObject : QQApiObject @property(nonatomic,retain)NSString* uin; ///<想要对话的QQ号 -(id)initWithUin:(NSString*)uin; ///<初始化方法 +(id)objectWithUin:(NSString*)uin;///<工厂方法,获取一个QQApiWPAObject对象. @end // QQApiAddFriendObject /** \brief 添加好友 */ @interface QQApiAddFriendObject : QQApiObject @property (nonatomic,retain)NSString* openID; @property (nonatomic,retain)NSString* subID; @property (nonatomic,retain)NSString* remark; -(id)initWithOpenID:(NSString*)openID; ///<初始化方法 +(id)objecWithOpenID:(NSString*)openID; ///<工厂方法,获取一个QQApiAddFriendObject对象. @end // QQApiGameConsortiumBindingGroupObject /** \brief 游戏公会绑定群 */ @interface QQApiGameConsortiumBindingGroupObject : QQApiObject @property (nonatomic,retain)NSString* signature; @property (nonatomic,retain)NSString* unionid; @property (nonatomic,retain)NSString* zoneID; @property (nonatomic,retain)NSString* appDisplayName; -(id)initWithGameConsortium:(NSString*)signature unionid:(NSString*)unionid zoneID:(NSString*)zoneID appDisplayName:(NSString*)appDisplayName; ///<初始化方法 +(id)objectWithGameConsortium:(NSString*)signature unionid:(NSString*)unionid zoneID:(NSString*)zoneID appDisplayName:(NSString*)appDisplayName; ///<工厂方法,获取一个QQApiAddFriendObject对象. @end // QQApiGroupChatObject /** \brief 发起群会话对象 */ @interface QQApiGroupChatObject : QQApiObject @property(nonatomic,retain)NSString* groupID; ///<想要对话的群号 -(id)initWithGroup:(NSString*)groupID; ///<初始化方法 +(id)objectWithGroup:(NSString*)groupID;///<工厂方法,获取一个QQApiGroupChatObject对象. @end #pragma mark - QQApi请求消息类型 /** QQApi请求消息类型 */ enum QQApiInterfaceReqType { EGETMESSAGEFROMQQREQTYPE = 0, ///< 手Q -> 第三方应用,请求第三方应用向手Q发送消息 ESENDMESSAGETOQQREQTYPE = 1, ///< 第三方应用 -> 手Q,第三方应用向手Q分享消息 ESHOWMESSAGEFROMQQREQTYPE = 2 ///< 手Q -> 第三方应用,请求第三方应用展现消息中的数据 }; /** QQApi应答消息类型 */ enum QQApiInterfaceRespType { ESHOWMESSAGEFROMQQRESPTYPE = 0, ///< 第三方应用 -> 手Q,第三方应用应答消息展现结果 EGETMESSAGEFROMQQRESPTYPE = 1, ///< 第三方应用 -> 手Q,第三方应用回应发往手Q的消息 ESENDMESSAGETOQQRESPTYPE = 2 ///< 手Q -> 第三方应用,手Q应答处理分享消息的结果 }; /** QQApi请求消息基类 */ @interface QQBaseReq : NSObject /** 请求消息类型,参见\ref QQApiInterfaceReqType */ @property (nonatomic, assign) int type; @end /** QQApi应答消息基类 */ @interface QQBaseResp : NSObject /** 请求处理结果 */ @property (nonatomic, copy) NSString* result; /** 具体错误描述信息 */ @property (nonatomic, copy) NSString* errorDescription; /** 应答消息类型,参见\ref QQApiInterfaceRespType */ @property (nonatomic, assign) int type; /** 扩展信息 */ @property (nonatomic, assign) NSString* extendInfo; @end /** GetMessageFromQQReq请求帮助类 */ @interface GetMessageFromQQReq : QQBaseReq /** 创建一个GetMessageFromQQReq请求实例 */ + (GetMessageFromQQReq *)req; @end /** GetMessageFromQQResp应答帮助类 */ @interface GetMessageFromQQResp : QQBaseResp /** 创建一个GetMessageFromQQResp应答实例 \param message 具体分享消息实例 \return 新创建的GetMessageFromQQResp应答实例 */ + (GetMessageFromQQResp *)respWithContent:(QQApiObject *)message; /** 具体分享消息 */ @property (nonatomic, retain) QQApiObject *message; @end /** SendMessageToQQReq请求帮助类 */ @interface SendMessageToQQReq : QQBaseReq /** 创建一个SendMessageToQQReq请求实例 \param message 具体分享消息实例 \return 新创建的SendMessageToQQReq请求实例 */ + (SendMessageToQQReq *)reqWithContent:(QQApiObject *)message; /** 具体分享消息 */ @property (nonatomic, retain) QQApiObject *message; @end /** SendMessageToQQResp应答帮助类 */ @interface SendMessageToQQResp : QQBaseResp /** 创建一个SendMessageToQQResp应答实例 \param result 请求处理结果 \param errDesp 具体错误描述信息 \param extendInfo 扩展信息 \return 新创建的SendMessageToQQResp应答实例 */ + (SendMessageToQQResp *)respWithResult:(NSString *)result errorDescription:(NSString *)errDesp extendInfo:(NSString*)extendInfo; @end /** ShowMessageFromQQReq请求帮助类 */ @interface ShowMessageFromQQReq : QQBaseReq /** 创建一个ShowMessageFromQQReq请求实例 \param message 具体待展现消息实例 \return 新创建的ShowMessageFromQQReq请求实例 */ + (ShowMessageFromQQReq *)reqWithContent:(QQApiObject *)message; /** 具体待展现消息 */ @property (nonatomic, retain) QQApiObject *message; @end /** ShowMessageFromQQResp应答帮助类 */ @interface ShowMessageFromQQResp : QQBaseResp /** 创建一个ShowMessageFromQQResp应答实例 \param result 展现消息结果 \param errDesp 具体错误描述信息 \return 新创建的ShowMessageFromQQResp应答实例 */ + (ShowMessageFromQQResp *)respWithResult:(NSString *)result errorDescription:(NSString *)errDesp; @end #endif ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/Headers/TencentApiInterface.h ================================================ // // TencentMessage.h // TencentOpenApi_IOS // // Created by qqconnect on 13-5-29. // Copyright (c) 2013年 Tencent. All rights reserved. // #ifndef QQ_OPEN_SDK_LITE #import #import "TencentMessageObject.h" typedef enum { kIphoneQQ, kIphoneQZONE, kThirdApp, } TecnentPlatformType; typedef enum { kTencentApiSuccess, kTencentApiPlatformUninstall, kTencentApiPlatformNotSupport, kTencentApiParamsError, kTencentApiFail, } TencentApiRetCode; @class TencentApiReq; @class TencentApiResp; /** * \brief TencentApiInterface的回调 * * TencentApiInterface的回调接口 * \note v1.0版本只支持腾讯业务拉起第三方请求内容 */ @protocol TencentApiInterfaceDelegate @optional /** * 请求获得内容 当前版本只支持第三方相应腾讯业务请求 */ - (BOOL)onTencentReq:(TencentApiReq *)req; /** * 响应请求答复 当前版本只支持腾讯业务相应第三方的请求答复 */ - (BOOL)onTencentResp:(TencentApiResp *)resp; @end /** * \brief TencentApiInterface的回调 * * TencentApiInterface的调用接口 * \note v1.0版本只支持第三方答复内容 */ @interface TencentApiInterface : NSObject /** * 发送答复返回腾讯业务 * \param resp 答复内容 * \return 返回码 */ + (TencentApiRetCode)sendRespMessageToTencentApp:(TencentApiResp *)resp; /** * 是否可以处理拉起协议 * \param url * \param delegate 指定的回调 * \return 是否是腾讯API认识的消息类型 */ + (BOOL)canOpenURL:(NSURL *)url delegate:(id)delegate; /** * 处理应用拉起协议 * \param url * \param delegate 指定的回调 * \return 是否是腾讯API认识的消息类型 */ + (BOOL)handleOpenURL:(NSURL *)url delegate:(id)delegate; /** * 用户设备是否安装腾讯APP * \param platform 指定的腾讯业务 * \return YES:安装 NO:未安装 */ + (BOOL)isTencentAppInstall:(TecnentPlatformType)platform; /** * 用户设备是否支持调用SDK * \param platform 指定的腾讯业务 * \return YES:支持 NO:不支持 */ + (BOOL)isTencentAppSupportTencentApi:(TecnentPlatformType)platform; @end #endif ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/Headers/TencentMessageObject.h ================================================ // // TencentMessageObject.h // TencentOpenApi_IOS // // Created by qqconnect on 13-5-27. // Copyright (c) 2013年 Tencent. All rights reserved. // #ifndef QQ_OPEN_SDK_LITE #import #import #import "sdkdef.h" #define kTextLimit (1024 * 1024) #define kDataLimit (1024 * 1024 * 10) #define kPreviewDataLimit (1024 * 1024) @class TencentApiReq; @class TencentApiResp; /** * 必填的NSArray型参数 */ typedef NSArray *TCRequiredArray; /** * 必填的NSDictionary型参数 */ typedef NSDictionary *TCRequiredDictionary; /** * 必填的TencentApiReq型参数 */ typedef TencentApiReq *TCRequiredReq; /** * 可选的UIImage类型参数 */ typedef NSData *TCOptionalData; /** * 可选的NSArray型参数 */ typedef NSArray *TCOptionalArray; /** * 可选的TencentApiReq型参数 */ typedef TencentApiReq *TCOptionalReq; /** * TencentReqMessageType 请求类型枚举参数 */ typedef enum { /** TX APP请求内容填充(需要第三方开发者填充完成内容后需要主动调用sendRespMessageToTencentApp)*/ ReqFromTencentAppQueryContent, /** TX APP请求展现内容 (不用调用答复) */ ReqFromTencentAppShowContent, /** 第三方 APP 请求内容 */ ReqFromThirdAppQueryContent, /** 第三方 APP 请求展现内容(类似分享)*/ ReqFromThirdAppShowContent, } TencentReqMessageType; typedef enum { RespFromTencentAppQueryContent, RespFromTencentAppShowContent, RespFromThirdAppQueryContent, RespFromThirdAppShowContent, } TencentRespMessageType; /** * TencentObjVersion 腾讯API消息类型枚举 */ typedef enum { /** 文本类型 */ TencentTextObj, /** 图片类型 */ TencentImageObj, /** 音频类型 */ TencentAudioObj, /** 视频类型 */ TencentVideoObj, /** 图片视频类 */ TencentImageAndVideoObj, } TencentObjVersion; /** * \brief 请求包 * * TencentApiReq用来向其他业务发送请求包 */ @interface TencentApiReq : NSObject /** * 根据序列号生成一个请求包 * \param apiSeq 请求序列号 * \param type 请求类型 * \return tencentApiReq实例 */ + (TencentApiReq *)reqFromSeq:(NSInteger)apiSeq type:(TencentReqMessageType)type; /** 请求类型 */ @property (readonly, assign)TCRequiredInt nMessageType; /** 请求平台 */ @property (readonly, assign)NSInteger nPlatform; /** 请求的SDK版本号 */ @property (readonly, assign)NSInteger nSdkVersion; /** 请求序列号 */ @property (readonly, assign)TCRequiredInt nSeq; /** 第三方的APPID */ @property (nonatomic, retain)TCRequiredStr sAppID; /** 请求内容 TencentBaseMessageObj对象数组 */ @property (nonatomic, retain)TCOptionalArray arrMessage; /** 请求的描述 可以用于告诉对方这个请求的特定场景 */ @property (nonatomic, retain)TCOptionalStr sDescription; @end /** * \brief 答复包 * * TencentApiResp用来向其他业务发送答复包 */ @interface TencentApiResp : NSObject /** * 根据序列号生成一个答复包 * \param req 答复对应的请求包(如果req不是TencentApiReq或者他的子类,会抛出异常) * \return 答复包体 */ + (TencentApiResp *)respFromReq:(TencentApiReq *)req; /** 返回码 */ @property (nonatomic, assign)TCOptionalInt nRetCode; /** 返回消息 */ @property (nonatomic, retain)TCOptionalStr sRetMsg; /** 答复对应的请求包 */ @property (nonatomic, retain)TCOptionalReq objReq; @end /** * \brief 消息体 * * TencentBaseMessageObj 应用之间传递消息体 */ @interface TencentBaseMessageObj : NSObject /** 消息类型 */ @property (nonatomic, assign)NSInteger nVersion; /** 消息描述 */ @property (nonatomic, retain)NSString *sName; /** 消息的扩展信息 主要是可以用来进行一些请求消息体的描述 譬如图片要求的width height 文字的关键字什么的, 也可以不用填写*/ @property (nonatomic, retain)NSDictionary *dictExpandInfo; /** * 消息是否有效 */ - (BOOL)isVaild; @end #pragma mark TencentTextMessage /** * \brief 文本的消息体 * * TencentTextMessageObjV1 应用之间传递的文本消息体 */ @interface TencentTextMessageObjV1 : TencentBaseMessageObj /** * 文本 * \note 文本长度不能超过4096个字 */ @property (nonatomic, retain) NSString *sText; /** * 初始化文本消息 * \param text 文本 * \return 初始化返回的文本消息 */ - (id)initWithText:(NSString *)text; @end #pragma mark TecentImageMessage /** * TencentApiImageSourceType 图片数据类型(请求方对数据类型可能会有限制) */ typedef enum { /** 图片数据是url或二进制数据 */ AllImage, /** 图片数据是url */ UrlImage, /** 图片数据是二进制数据 */ DataImage, }TencentApiImageSourceType; /** * \brief 图片的消息体 * * TencentImageMessageObjV1 应用之间传递的图片消息体 */ @interface TencentImageMessageObjV1 : TencentBaseMessageObj /** * 图片数据 * \note 图片不能大于10M */ @property (nonatomic, retain) NSData *dataImage; /** * 缩略图的数据 * \note 图片不能大于1M */ @property (nonatomic, retain) NSData *dataThumbImage; /** 图片URL */ @property (nonatomic, retain) NSString *sUrl; /** 图片的描述 */ @property (nonatomic, retain) NSString *sDescription; /** 图片的size */ @property (nonatomic, assign) CGSize szImage; /** * 图片来源 * \note TencentApiImageSourceType对应的类型 */ @property (readonly, assign) NSInteger nType; /** * 初始化图片消息 * \param dataImage 图片类型 * \return 初始化返回的图片消息 */ - (id)initWithImageData:(NSData *)dataImage; /** * 初始化图片消息 * \param url 图片url * \return 初始化返回的图片消息 */ - (id)initWithImageUrl:(NSString *)url; /** * 初始化图片消息 * \param type 图片类型 * \return 初始化返回的图片消息 */ - (id)initWithType:(TencentApiImageSourceType)type; @end #pragma mark TencentAudioMessage /** * \brief 音频的消息体 * * TencentAudioMessageObjV1 应用之间传递的音频消息体 */ @interface TencentAudioMessageObjV1 : TencentBaseMessageObj /** 音频URL */ @property (nonatomic, retain) NSString *sUrl; /** * 音频的预览图 * \note图片不能大于1M */ @property (nonatomic, retain) NSData *dataImagePreview; /** 音频的预览图URL */ @property (nonatomic, retain) NSString *sImagePreviewUrl; /** 音频的描述 */ @property (nonatomic, retain) NSString *sDescription; /** * 初始化图片消息 * \param url 音频URL * \return 初始化返回的音频消息 */ - (id)initWithAudioUrl:(NSString *)url; @end #pragma mark TencentVideoMessage /** * TencentApiVideoSourceType 视频数据类型(请求方对数据类型可能会有限制) */ typedef enum { /** 视频来源于本地或网络 */ AllVideo, /** 视频来源于本地 */ LocalVideo, /** 视频来源于网络 */ NetVideo, }TencentApiVideoSourceType; /** * \brief 视频的消息体 * * TencentVideoMessageV1 应用之间传递的视频消息体 */ @interface TencentVideoMessageV1 : TencentBaseMessageObj /** * 视频URL * \note 不能超过1024 */ @property (nonatomic, retain) NSString *sUrl; /** * 视频来源 主要是用来让发起方指定视频的来源 * \note TencentApiVideoSourceType 对应的类型 只读参数 */ @property (readonly, assign) NSInteger nType; /** * 视频的预览图 * \note 图片不能大于1M */ @property (nonatomic, retain) NSData *dataImagePreview; /** 视频的预览图URL */ @property (nonatomic, retain) NSString *sImagePreviewUrl; /** 视频的描述 */ @property (nonatomic, retain) NSString *sDescription; /** * 初始化视频消息 * \param url 视频URL * \param type 视频来源类型 * \return 初始化返回的视频消息 */ - (id)initWithVideoUrl:(NSString *)url type:(TencentApiVideoSourceType)type; /** * 初始化视频消息 * \param type 视频来源类型 * \return 初始化返回的视频消息 */ - (id)initWithType:(TencentApiVideoSourceType)type; @end #pragma mark TencentImageMessageObj /** * \brief 视频图片消息体 * * TencentVideoMessageV1 这是一个扩展的类 是一个图片视频类 * \note 图片视频可以任选一个内容填充 但是注意只能填一个 当有一种类型被填充后 另外一个种类型就无法填充了 */ @interface TencentImageAndVideoMessageObjV1 : TencentBaseMessageObj /** 图片消息 */ @property (nonatomic, retain) TencentImageMessageObjV1 *objImageMessage; /** 视频消息 */ @property (nonatomic, retain) TencentVideoMessageV1 *objVideoMessage; /** * 初始化图片消息 * \param dataImage 图片数据 * \param url 视频url * \return 初始化返回的图片视频消息 */ - (id)initWithMessage:(NSData *)dataImage videoUrl:(NSString *)url; /** * 设置图片 * \param dataImage 图片数据 */ - (void)setDataImage:(NSData *)dataImage; /** * 设置视频 * \param videoUrl 视频URL */ - (void)setVideoUrl:(NSString *)videoUrl; @end #endif ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/Headers/TencentOAuth.h ================================================ /// /// \file TencentOAuth.h /// \brief QQ互联开放平台授权登录及相关开放接口实现类 /// /// Created by Tencent on 12-12-21. /// Copyright (c) 2012年 Tencent. All rights reserved. /// #import #import "sdkdef.h" #import "TencentOAuthObject.h" @protocol TencentSessionDelegate; @protocol TencentLoginDelegate; @protocol TencentApiInterfaceDelegate; @protocol TencentWebViewDelegate; @class TencentApiReq; @class TencentApiResp; typedef enum { kTencentNotAuthorizeState, kTencentSSOAuthorizeState, kTencentWebviewAuthorzieState, } TencentAuthorizeState; typedef enum { kAuthModeClientSideToken, kAuthModeServerSideCode, } TencentAuthMode; #pragma mark - TencentOAuth(授权登录及相关开放接口调用) /** * \brief TencentOpenAPI授权登录及相关开放接口调用 * * TencentOAuth实现授权登录逻辑以及相关开放接口的请求调用 */ @interface TencentOAuth : NSObject { NSMutableDictionary* _apiRequests; NSString* _accessToken; NSDate* _expirationDate; id _sessionDelegate; NSString* _localAppId; NSString* _openId; NSString* _redirectURI; NSArray* _permissions; } /** Access Token凭证,用于后续访问各开放接口 */ @property(nonatomic, copy) NSString* accessToken; /** Access Token的失效期 */ @property(nonatomic, copy) NSDate* expirationDate; /** 已实现的开放接口的回调委托对象 */ @property(nonatomic, assign) id sessionDelegate; /** 第三方应用在开发过程中设置的URLSchema,用于浏览器登录后后跳到第三方应用 */ @property(nonatomic, copy) NSString* localAppId; /** 用户授权登录后对该用户的唯一标识 */ @property(nonatomic, copy) NSString* openId; /** 用户登录成功过后的跳转页面地址 */ @property(nonatomic, copy) NSString* redirectURI; /** 第三方应用在互联开放平台申请的appID */ @property(nonatomic, retain) NSString* appId; /** 主要是互娱的游戏设置uin */ @property(nonatomic, retain) NSString* uin; /** 主要是互娱的游戏设置鉴定票据 */ @property(nonatomic, retain) NSString* skey; /** 登陆透传的数据 */ @property(nonatomic, copy) NSDictionary* passData; /** 授权方式(Client Side Token或者Server Side Code) */ @property(nonatomic, assign) TencentAuthMode authMode; /** * 用来获得当前sdk的版本号 * \return 返回sdk版本号 **/ + (NSString*)sdkVersion; /** * 用来获得当前sdk的小版本号 * \return 返回sdk小版本号 **/ + (NSString*)sdkSubVersion; /** * 用来获得当前sdk的是否精简版 * \return 返回YES表示精简版 **/ + (BOOL)isLiteSDK; /** * 主要是用来帮助判断是否有登陆被发起,但是还没有过返回结果 * \return * kTencentNotAuthorizeState:无授权 * kTencentSSOAuthorizeState:有人发起了sso授权但无返回 * kTencentWebviewAuthorzieState:有人发起了webview授权还未返回 **/ + (TencentAuthorizeState *)authorizeState; /** * 用来获得当前手机qq的版本号 * \return 返回手机qq版本号 **/ + (QQVersion)iphoneQQVersion; /** * 初始化TencentOAuth对象 * \param appId 第三方应用在互联开放平台申请的唯一标识 * \param delegate 第三方应用用于接收请求返回结果的委托对象 * \return 初始化后的授权登录对象 */ - (id)initWithAppId:(NSString *)appId andDelegate:(id)delegate; /** * 判断用户手机上是否安装手机QQ * \return YES:安装 NO:没安装 */ + (BOOL)iphoneQQInstalled; /** * 判断用户手机上的手机QQ是否支持SSO登录 * \return YES:支持 NO:不支持 */ + (BOOL)iphoneQQSupportSSOLogin; /** * 判断用户手机上是否安装手机QZone * \return YES:安装 NO:没安装 */ + (BOOL)iphoneQZoneInstalled; /** * 判断用户手机上的手机QZone是否支持SSO登录 * \return YES:支持 NO:不支持 */ + (BOOL)iphoneQZoneSupportSSOLogin; /** * 登录授权 * * \param permissions 授权信息列 */ - (BOOL)authorize:(NSArray *)permissions; /** * 登录授权 * \param permissions 授权信息列表 * \param bInSafari 是否使用safari进行登录.IOS SDK 1.3版本开始此参数废除 */ - (BOOL)authorize:(NSArray *)permissions inSafari:(BOOL)bInSafari; /** * 登录授权 * \param permissions 授权信息列表 * \param localAppId 应用APPID * \param bInSafari 是否使用safari进行登录.IOS SDK 1.3版本开始此参数废除 */ - (BOOL)authorize:(NSArray *)permissions localAppId:(NSString *)localAppId inSafari:(BOOL)bInSafari; /** * 增量授权,因用户没有授予相应接口调用的权限,需要用户确认是否授权 * \param permissions 需增量授权的信息列表 * \return 增量授权调用是否成功 */ - (BOOL)incrAuthWithPermissions:(NSArray *)permissions; /** * 重新授权,因token废除或失效导致接口调用失败,需用户重新授权 * \param permissions 授权信息列表,同登录授权 * \return 授权调用是否成功 */ - (BOOL)reauthorizeWithPermissions:(NSArray *)permissions; /** * (静态方法)处理应用拉起协议 * \param url 处理被其他应用呼起时的逻辑 * \return 处理结果,YES表示成功,NO表示失败 */ + (BOOL)HandleOpenURL:(NSURL *)url; /** * (静态方法)sdk是否可以处理应用拉起协议 * \param url 处理被其他应用呼起时的逻辑 * \return 处理结果,YES表示可以 NO表示不行 */ + (BOOL)CanHandleOpenURL:(NSURL *)url; /** * (静态方法)获取TencentOAuth调用的上一次错误信息 */ + (NSString *)getLastErrorMsg; /** * 以Server Side Code模式授权登录时,通过此接口获取返回的code值; * 以Client Side Token模式授权登录时,忽略此接口。 */ - (NSString *)getServerSideCode; /** * 退出登录(退出登录后,TecentOAuth失效,需要重新初始化) * \param delegate 第三方应用用于接收请求返回结果的委托对象 */ - (void)logout:(id)delegate; /** * 判断登录态是否有效 * \return 处理结果,YES表示有效,NO表示无效,请用户重新登录授权 */ - (BOOL)isSessionValid; /** * 获取用户个人信息 * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)getUserInfo; /** * SDK内置webview实现定向分享时,第三方应用可以根据应用是否在白名单里来开启该配置开关,默认为关闭; * 在白名单里的应用调用该接口后,即打开sdk内置webview的二级白名单开关(相对与sdk后台的白名单), * 那么在sdk后台白名单校验请求失败的情况下,会继续先尝试采用内置webview进行分享。 */ - (void)openSDKWebViewQQShareEnable; /** * 获取用户QZone相册列表 * \attention 需\ref apply_perm * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)getListAlbum; /** * 获取用户QZone相片列表 * \attention 需\ref apply_perm * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCListPhotoDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)getListPhotoWithParams:(NSMutableDictionary *)params; /** * 分享到QZone * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCAddShareDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)addShareWithParams:(NSMutableDictionary *)params; /** * 上传照片到QZone指定相册 * \attention 需\ref apply_perm * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCUploadPicDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)uploadPicWithParams:(NSMutableDictionary *)params; /** * 在QZone相册中创建一个新的相册 * \attention 需\ref apply_perm * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCAddAlbumDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)addAlbumWithParams:(NSMutableDictionary *)params; /** * 检查是否是QZone某个用户的粉丝 * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCCheckPageFansDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)checkPageFansWithParams:(NSMutableDictionary *)params; /** * 在QZone中发表一篇日志 * \attention 需\ref apply_perm * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCAddOneBlogDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)addOneBlogWithParams:(NSMutableDictionary *)params; /** * 在QZone中发表一条说说 * \attention 需\ref apply_perm * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCAddTopicDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)addTopicWithParams:(NSMutableDictionary *)params; /** * 设置QQ头像 使用默认的效果处理设置头像的界面 * \attention 需\ref apply_perm * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCSetUserHeadpic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)setUserHeadpic:(NSMutableDictionary *)params; /** * 设置QQ头像 会返回设置头像由第三方自己处理界面的弹出方式 * \attention 需\ref apply_perm * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCSetUserHeadpic * \param viewController 设置头像的界面 * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)setUserHeadpic:(NSMutableDictionary *)params andViewController:(UIViewController **)viewController; /** * 获取QQ会员信息(仅包括是否为QQ会员,是否为年费QQ会员) * \attention 需\ref apply_perm * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)getVipInfo; /** * 获取QQ会员详细信息 * \attention 需\ref apply_perm * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)getVipRichInfo; /** * 获取微博好友名称输入提示,即通过字符串查找匹配的微博好友 * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCMatchNickTipsDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)matchNickTips:(NSMutableDictionary *)params; /** * 获取最近的微博好友 * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCGetIntimateFriendsDic * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)getIntimateFriends:(NSMutableDictionary *)params; /** * QZone定向分享,可以@到具体好友,完成后将触发responseDidReceived:forMessage:回调,message:“SendStory” * \param params 参数字典 * \param fopenIdArray 第三方应用预传人好友列表,好友以openid标识 * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)sendStory:(NSMutableDictionary *)params friendList:(NSArray *)fopenIdArray; /** * 发送应用邀请,完成后将触发responseDidReceived:forMessage:回调,message:“AppInvitation” * \param desc 应用的描述文字,不超过35字符,如果为nil或@“”则显示默认描述 * \param imageUrl 应用的图标,如果为nil或者@“”则显示默认图标 * \param source 透传参数,由开发者自定义该参数内容 * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)sendAppInvitationWithDescription:(NSString *)desc imageURL:(NSString *)imageUrl source:(NSString *)source; /** * 发起PK或者发送炫耀,完成后将触发responseDidReceived:forMessage:回调,message:“AppChallenge” * \param receiver 必须指定一位进行PK或者炫耀的好友,填写其OpenID,填写多个OpenID将截取第一个 * \param type 类型,"pk"或者“brag” * \param imageUrl 炫耀/挑战场景图的URL * \param message 炫耀/挑战中的内容描述,不超过50个字符,超过限制则自动截断 * \param source 透传参数,由开发者自定义该参数内容 * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)sendChallenge:(NSString *)receiver type:(NSString *)type imageURL:(NSString *)imageUrl message:(NSString *)message source:(NSString *)source; /** * 赠送或者请求礼物,完成后将触发responseDidReceived:forMessage:回调,message:“AppGiftRequest” * \param receiver 赠送或者请求礼物的好友的OpenID,支持填写多个,OpenID之用","分隔,为nil时将由用户通过好友选择器选择好友 * \param exclude 用户通过好友选择器选择好友场景下,希望排除的好友(不显示在好友选择器) * \param specified 用户通过好友选择器选择好友场景下,希望出现的指定好友 * \param only 是否只显示specified指定的好友 * \param type 类型,"request"或者“freegift” * \param title 免费礼物或请求名称,不超过6个字符 * \param message 礼物或请求的默认赠言,控制在35个汉字以内,超过限制自动截断 * \param imageUrl 请求或礼物配图的URL,如果不传,则默认在弹框中显示应用的icon * \param source 透传参数,由开发者自定义该参数内容 * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 */ - (BOOL)sendGiftRequest:(NSString *)receiver exclude:(NSString *)exclude specified:(NSString *)specified only:(BOOL)only type:(NSString *)type title:(NSString *)title message:(NSString *)message imageURL:(NSString *)imageUrl source:(NSString *)source; /** * 退出指定API调用 * \param userData 用户调用某条API的时候传入的保留参数 * \return 处理结果,YES表示成功 NO表示失败 */ - (BOOL)cancel:(id)userData; /** * CGI类任务创建接口 * \param apiURL CGI请求的URL地址 * \param method CGI请求方式:"GET","POST" * \param params CGI请求参数字典 * \param callback CGI请求结果的回调接口对象 * \return CGI请求任务实例,用于取消任务,返回nil代表任务创建失败 */ - (TCAPIRequest *)cgiRequestWithURL:(NSURL *)apiURL method:(NSString *)method params:(NSDictionary *)params callback:(id)callback; /** * TencentOpenApi发送任务统一接口 * \param request 请求发送的任务 * \param callback 任务发送后的回调地址 */ - (BOOL)sendAPIRequest:(TCAPIRequest *)request callback:(id)callback; - (NSString *)getUserOpenID; @end #pragma mark - TencentLoginDelegate(授权登录回调协议) /** * \brief TencentLoginDelegate iOS Open SDK 1.3 API回调协议 * * 第三方应用实现登录的回调协议 */ @protocol TencentLoginDelegate @required /** * 登录成功后的回调 */ - (void)tencentDidLogin; /** * 登录失败后的回调 * \param cancelled 代表用户是否主动退出登录 */ - (void)tencentDidNotLogin:(BOOL)cancelled; /** * 登录时网络有问题的回调 */ - (void)tencentDidNotNetWork; @optional /** * 登录时权限信息的获得 */ - (NSArray *)getAuthorizedPermissions:(NSArray *)permissions withExtraParams:(NSDictionary *)extraParams; @end #pragma mark - TencentSessionDelegate(开放接口回调协议) /** * \brief TencentSessionDelegate iOS Open SDK 1.3 API回调协议 * * 第三方应用需要实现每条需要调用的API的回调协议 */ @protocol TencentSessionDelegate @optional /** * 退出登录的回调 */ - (void)tencentDidLogout; /** * 因用户未授予相应权限而需要执行增量授权。在用户调用某个api接口时,如果服务器返回操作未被授权,则触发该回调协议接口,由第三方决定是否跳转到增量授权页面,让用户重新授权。 * \param tencentOAuth 登录授权对象。 * \param permissions 需增量授权的权限列表。 * \return 是否仍然回调返回原始的api请求结果。 * \note 不实现该协议接口则默认为不开启增量授权流程。若需要增量授权请调用\ref TencentOAuth#incrAuthWithPermissions: \n注意:增量授权时用户可能会修改登录的帐号 */ - (BOOL)tencentNeedPerformIncrAuth:(TencentOAuth *)tencentOAuth withPermissions:(NSArray *)permissions; /** * [该逻辑未实现]因token失效而需要执行重新登录授权。在用户调用某个api接口时,如果服务器返回token失效,则触发该回调协议接口,由第三方决定是否跳转到登录授权页面,让用户重新授权。 * \param tencentOAuth 登录授权对象。 * \return 是否仍然回调返回原始的api请求结果。 * \note 不实现该协议接口则默认为不开启重新登录授权流程。若需要重新登录授权请调用\ref TencentOAuth#reauthorizeWithPermissions: \n注意:重新登录授权时用户可能会修改登录的帐号 */ - (BOOL)tencentNeedPerformReAuth:(TencentOAuth *)tencentOAuth; /** * 用户通过增量授权流程重新授权登录,token及有效期限等信息已被更新。 * \param tencentOAuth token及有效期限等信息更新后的授权实例对象 * \note 第三方应用需更新已保存的token及有效期限等信息。 */ - (void)tencentDidUpdate:(TencentOAuth *)tencentOAuth; /** * 用户增量授权过程中因取消或网络问题导致授权失败 * \param reason 授权失败原因,具体失败原因参见sdkdef.h文件中\ref UpdateFailType */ - (void)tencentFailedUpdate:(UpdateFailType)reason; /** * 获取用户个人信息回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/getUserInfoResponse.exp success * 错误返回示例: \snippet example/getUserInfoResponse.exp fail */ - (void)getUserInfoResponse:(APIResponse*) response; /** * 获取用户QZone相册列表回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/getListAlbumResponse.exp success * 错误返回示例: \snippet example/getListAlbumResponse.exp fail */ - (void)getListAlbumResponse:(APIResponse*) response; /** * 获取用户QZone相片列表 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/getListPhotoResponse.exp success * 错误返回示例: \snippet example/getListPhotoResponse.exp fail */ - (void)getListPhotoResponse:(APIResponse*) response; /** * 检查是否是QZone某个用户的粉丝回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/checkPageFansResponse.exp success * 错误返回示例: \snippet example/checkPageFansResponse.exp fail */ - (void)checkPageFansResponse:(APIResponse*) response; /** * 分享到QZone回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/addShareResponse.exp success * 错误返回示例: \snippet example/addShareResponse.exp fail */ - (void)addShareResponse:(APIResponse*) response; /** * 在QZone相册中创建一个新的相册回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/addAlbumResponse.exp success * 错误返回示例: \snippet example/addAlbumResponse.exp fail */ - (void)addAlbumResponse:(APIResponse*) response; /** * 上传照片到QZone指定相册回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/uploadPicResponse.exp success * 错误返回示例: \snippet example/uploadPicResponse.exp fail */ - (void)uploadPicResponse:(APIResponse*) response; /** * 在QZone中发表一篇日志回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/addOneBlogResponse.exp success * 错误返回示例: \snippet example/addOneBlogResponse.exp fail */ - (void)addOneBlogResponse:(APIResponse*) response; /** * 在QZone中发表一条说说回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/addTopicResponse.exp success * 错误返回示例: \snippet example/addTopicResponse.exp fail */ - (void)addTopicResponse:(APIResponse*) response; /** * 设置QQ头像回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/setUserHeadpicResponse.exp success * 错误返回示例: \snippet example/setUserHeadpicResponse.exp fail */ - (void)setUserHeadpicResponse:(APIResponse*) response; /** * 获取QQ会员信息回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/getVipInfoResponse.exp success * 错误返回示例: \snippet example/getVipInfoResponse.exp fail */ - (void)getVipInfoResponse:(APIResponse*) response; /** * 获取QQ会员详细信息回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse */ - (void)getVipRichInfoResponse:(APIResponse*) response; /** * 获取微博好友名称输入提示回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/matchNickTipsResponse.exp success * 错误返回示例: \snippet example/matchNickTipsResponse.exp fail */ - (void)matchNickTipsResponse:(APIResponse*) response; /** * 获取最近的微博好友回调 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \remarks 正确返回示例: \snippet example/getIntimateFriendsResponse.exp success * 错误返回示例: \snippet example/getIntimateFriendsResponse.exp fail */ - (void)getIntimateFriendsResponse:(APIResponse*) response; /** * sendStory分享的回调(已废弃,使用responseDidReceived:forMessage:) * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse */ - (void)sendStoryResponse:(APIResponse*) response; /** * 社交API统一回调接口 * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse * \param message 响应的消息,目前支持‘SendStory’,‘AppInvitation’,‘AppChallenge’,‘AppGiftRequest’ */ - (void)responseDidReceived:(APIResponse*)response forMessage:(NSString *)message; /** * post请求的上传进度 * \param tencentOAuth 返回回调的tencentOAuth对象 * \param bytesWritten 本次回调上传的数据字节数 * \param totalBytesWritten 总共已经上传的字节数 * \param totalBytesExpectedToWrite 总共需要上传的字节数 * \param userData 用户自定义数据 */ - (void)tencentOAuth:(TencentOAuth *)tencentOAuth didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite userData:(id)userData; /** * 通知第三方界面需要被关闭 * \param tencentOAuth 返回回调的tencentOAuth对象 * \param viewController 需要关闭的viewController */ - (void)tencentOAuth:(TencentOAuth *)tencentOAuth doCloseViewController:(UIViewController *)viewController; @end #pragma mark - TencentWebViewDelegate(H5登录webview旋转方向回调) /** * \brief TencentWebViewDelegate: H5登录webview旋转方向回调协议 * * 第三方应用可以根据自己APP的旋转方向限制,通过此协议设置 */ @protocol TencentWebViewDelegate @optional - (BOOL) tencentWebViewShouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation; - (NSUInteger) tencentWebViewSupportedInterfaceOrientationsWithWebkit; - (BOOL) tencentWebViewShouldAutorotateWithWebkit; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/Headers/TencentOAuthObject.h ================================================ /// /// \file TencentOAuthObject.h /// 对开放接口的调用提供参数字典封装的辅助类 /// /// Created by Tencent on 12-12-28. /// Copyright (c) 2012年 Tencent. All rights reserved. /// #import #import #import "sdkdef.h" #pragma mark - #pragma mark TCAddTopicDic /** * \brief 发表说说的参数字典定义 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCAddTopicDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * \note 不用释放,返回的对象是自动释放的 */ + (TCAddTopicDic *) dictionary; /** * 发布心情时引用的信息的类型。 * \note 1表示图片; 2表示网页; 3表示视频 */ @property (nonatomic, retain) TCOptionalStr paramRichtype; /** * 发布心情时引用的信息的值。有richtype时必须有richval * * \note * -# 当richtype为图片(即richtype为1,应用场景为发布心情时引用某张图片)时,\n * richval需要传入该图片的相关参数。引用的图片来源分为两种:一种为网站图片,\n * 一种为QQ空间相册中的某张图片。 * - 当引用的图片来自网站,richval包含下列参数的值:\n * | 参数名称 | 是否必须 | 类型 | 描述 | * | ------ | ------- | ------ | ----------------- | * | url | 必须 | string | 网站图片的URL | * | height | 必须 | string | 图片高度,单位: px | * | width | 必须 | string | 图片宽度,单位: px | * \n * 输入时每个值中间用“&”分隔,如下所示:\n * “url=http://qq.com/logo.png&width=25&height=21” * * - 当引用的图片来自QQ空间相册,richval包含下列参数的值。\n * 这些值都需要通过调用相册OpenAPI来获得。参数意义如下:\n * | 参数名称 | 是否必须 | 类型 | 描述 | * | --------- | ------ | ------ | ---------------------------------- | * | albumid | 必须 | string | 图片所属空间相册的ID | * | pictureid | 必须 | string | 图片ID | * | sloc | 必须 | string | 小图ID | * | pictype | | string | 图片类型(JPG = 1;GIF = 2;PNG = 3) | * | picheight | | string | 图片高度,单位: px | * | picwidth | | string | 图片宽度,单位: px | * 输入时每个值中间用逗号分隔,如下所示 :\n * “albumid,pictureid,sloc,pictype,picheight,picwidth” * -# 当richtype为网页(即richtype为2,应用场景为针对某网页发表评论)时,\n * richval需要传入该网页的URL,发表为feeds时,后台会自动将该URL转换为短URL。 * -# 当richtype为视频(即richtype为3,应用场景为针对某视频发表评论)时,\n * richval需要传入该视频的URL,发表为feeds时,后台会对该URL进行解析,\n * 在feeds上显示播放器,视频源及缩略图。 */ @property (nonatomic, retain) TCOptionalStr paramRichval; /** * 发布的心情的内容。 */ @property (nonatomic, retain) TCRequiredStr paramCon; /** * 地址文。例如:广东省深圳市南山区高新科技园腾讯大厦。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 */ @property (nonatomic, retain) TCOptionalStr paramLbs_nm; /** * 经度。-180.0到+180.0,+表示东经。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 */ @property (nonatomic, retain) TCOptionalStr paramLbs_x; /** * 纬度。-90.0到+90.0,+表示北纬。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 */ @property (nonatomic, retain) TCOptionalStr paramLbs_y; /** * 第三方应用的平台类型。 * \note 1表示QQ空间; 2表示腾讯朋友; 3表示腾讯微博平台; 4表示腾讯Q+平台。 */ @property (nonatomic, retain) TCOptionalStr paramThirdSource; @end #pragma mark - #pragma mark TCAddOneBlogDic /** * \brief 发表日志的参数字典定义 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCAddOneBlogDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * \note 不用释放,返回的对象是自动释放的 */ + (TCAddOneBlogDic *) dictionary; /** * 日志标题(纯文本,最大长度128个字节,utf-8编码)。 */ @property (nonatomic, retain) TCRequiredStr paramTitle; /** * content 文章内容(html数据,最大长度100*1024个字节,utf-8编码) */ @property (nonatomic, retain) TCRequiredStr paramContent; @end #pragma mark - #pragma mark TCAddAlbumDic /** * \brief 创建空间相册的参数字典定义 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCAddAlbumDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * * \note 不用释放,返回的对象是自动释放的 */ + (TCAddAlbumDic *) dictionary; /** * albumname 必须 string 相册名 不能超过30个字符。 */ @property (nonatomic, retain) TCRequiredStr paramAlbumname; /** * albumdesc string 相册描述,不能超过200个字符。 */ @property (nonatomic, retain) TCOptionalStr paramAlbumdesc; /** * priv string 相册权限 * * \note 其取值含义为: 1=公开;3=只主人可见; 4=QQ好友可见; 5=问答加密。\n * 不传则相册默认为公开权限。\n * 如果priv取值为5,即相册是问答加密的,则必须包含问题和答案两个参数:\n * - question: 问题,不能超过30个字符。 * - answer: 答案,不能超过30个字符。 */ @property (nonatomic, retain) TCOptionalStr paramPriv; /** * question 问题,不能超过30个字符。 * \note 如果priv取值为5,必须包含这个参数: **/ @property (nonatomic, retain) TCOptionalStr paramQuestion; /** * answer 答案,不能超过30个字符。 * \note 如果priv取值为5,必须包含这个参数: **/ @property (nonatomic, retain) TCOptionalStr paramAnswer; @end #pragma mark - #pragma mark TCUploadPicDic /** * \brief 上传一张照片到QQ空间相册的参数字典定义 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCUploadPicDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * \note 不用释放,返回的对象是自动释放的 */ + (TCUploadPicDic *) dictionary; /** * photodesc string 照片描述,注意照片描述不能超过200个字符。 */ @property (nonatomic, retain) TCOptionalStr paramPhotodesc; /** * string 照片的命名,必须以.jpg, .gif, .png, .jpeg, .bmp此类后缀结尾。 */ @property (nonatomic, retain) TCOptionalStr paramTitle; /** * string 相册id。可不填,不填时则根据“mobile”标识选择默认上传的相册。 */ @property (nonatomic, retain) TCOptionalStr paramAlbumid; /** * 标志位 * * \note 0表示PC,1表示手机。用于当不传相册id时(即albumid为空时)控制是否传到手机相册。\n * -# 如果传1,则当albumid为空时,图片会上传到手机相册; * -# 如果不传或传0,则当albumid为空时,图片会上传到贴图相册; */ @property (nonatomic, assign) TCOptionalStr paramMobile; /** * x string 照片拍摄时的地理位置的经度。请使用原始数据(纯经纬度,0-360)。 */ @property (nonatomic, retain) TCOptionalStr paramX; /** * y string 照片拍摄时的地理位置的纬度。请使用原始数据(纯经纬度,0-360)。 */ @property (nonatomic, retain) TCOptionalStr paramY; /** * picture 必须 string 上传照片的文件名以及图片的内容(在发送请求时,图片内容以二进制数据流的形式发送,见下面的请求示例),注意照片名称不能超过30个字符。 */ @property (nonatomic, retain) TCRequiredImage paramPicture; /** * needfeed int 标识上传照片时是否要发feed * \note(0:不发feed; 1:发feed)。如果不填则默认为发feed。 */ @property (nonatomic, assign)TCOptionalStr paramNeedfeed; /** * successnum int 批量上传照片时,已成功上传的张数,指明上传完成情况。 * \note 单张上传时可以不填,不填则默认为0。 */ @property (nonatomic, assign)TCOptionalStr paramSuccessnum; /** * picnum int 批量上传照片的总张数,如果不填则默认为1。 * \note * - 如果picnum=1,为单张上传,发送单张上传feed; * - 如果picnum>1,为批量上传,发送批量上传feed。 * 批量上传方式:picnum为一次上传照片的张数,successnum初始值为0,每调用一次照片上传接口后递增其值。 * 信息中心中的feed表现形式:批量上传时最新的7张在feed中展示。其中最新上传的一张图片展示为大图,剩下的 * 六张按从新到旧的顺序展示为小图,其他图片不在feed中展示。 */ @property (nonatomic, assign)TCOptionalStr paramPicnum; @end #pragma mark - #pragma mark TCAddShareDic /** * \brief 同步分享到QQ空间,腾讯微博的参数字典定义 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCAddShareDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * * \note 不用释放,返回的对象是自动释放的 */ + (TCAddShareDic *) dictionary; /** * title 必须 string feeds的标题 最长36个中文字,超出部分会被截断。 */ @property (nonatomic, retain) TCRequiredStr paramTitle; /** * url 必须 string 分享所在网页资源的链接,点击后跳转至第三方网页,对应上文接口说明中2的超链接。请以http://开头。 */ @property (nonatomic, retain) TCRequiredStr paramUrl; /** * comment string 用户评论内容,也叫发表分享时的分享理由 禁止使用系统生产的语句进行代替。 * 最长40个中文字,超出部分会被截断。 */ @property (nonatomic, retain) TCOptionalStr paramComment; /** * summary string 所分享的网页资源的摘要内容,或者是网页的概要描述 最长80个中文字,超出部分会被截断。 */ @property (nonatomic, retain) TCOptionalStr paramSummary; /** * images string 所分享的网页资源的代表性图片链接",请以http://开头,长度限制255字符。多张图片以竖线(|)分隔,目前只有第一张图片有效,图片规格100*100为佳。 */ @property (nonatomic, retain) TCOptionalStr paramImages; /** * type string 分享内容的类型。 * * \note 4表示网页;5表示视频(type=5时,必须传入playurl) */ @property (nonatomic, retain) TCOptionalStr paramType; /** * playurl string 长度限制为256字节。仅在type=5的时候有效,表示视频的swf播放地址。 */ @property (nonatomic, retain) TCOptionalStr paramPlayurl; /** * site 必须 string 分享的来源网站名称,请填写网站申请接入时注册的网站名称 */ @property (nonatomic, retain) TCRequiredStr paramSite; /** * fromurl 必须 string 分享的来源网站对应的网站地址url 请以http://开头。 */ @property (nonatomic, retain) TCRequiredStr paramFromurl; /** * nswb string 值为1时,表示分享不默认同步到微博,其他值或者不传此参数表示默认同步到微博。 */ @property (nonatomic, retain) TCOptionalStr paramNswb; @end #pragma mark - #pragma mark TCCheckPageFansDic /** * \brief 验证是否认证空间粉丝tttyttyyyu的参数字典定义 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCCheckPageFansDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * * \note 不用释放,返回的对象是自动释放的 */ + (TCCheckPageFansDic *) dictionary; /** * 表示认证空间的QQ号码 */ @property (nonatomic, retain) TCRequiredStr paramPage_id; @end #pragma mark - #pragma mark TCSetUserHeadpic /** * \brief 设置用户头像 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCSetUserHeadpic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * \note 不用释放,返回的对象是自动释放的 */ + (TCSetUserHeadpic *) dictionary; /** * 设置用户头像的图片 */ @property (nonatomic, retain) TCRequiredImage paramImage; /** * 图片的文件名 */ @property (nonatomic, retain) TCOptionalStr paramFileName; @end #pragma mark - #pragma mark TCListPhotoDic /** * \brief 获取用户QQ空间相册中的照片列表 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCListPhotoDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * * \note 不用释放,返回的对象是自动释放的 */ + (TCListPhotoDic *) dictionary; /** * 表示要获取的照片列表所在的相册ID */ @property (nonatomic, retain) TCRequiredStr paramAlbumid; @end #pragma mark - #pragma mark TCMatchNickTipsDic /** * \brief 微博获取好友输入提示的参数字典定义 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCMatchNickTipsDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * * \note 不用释放,返回的对象是自动释放的 */ + (TCMatchNickTipsDic *) dictionary; /** * 匹配字符串(目前匹配范围为我收听的人) */ @property (nonatomic, retain) TCRequiredStr paramMatch; /** * 请求个数(1-10) */ @property (nonatomic, retain) TCRequiredStr paramReqnum; @end #pragma mark - #pragma mark TCGetIntimateFriendsDic /** * \brief 微博获取最近联系人列表的参数字典定义 * * 可以直接填写相应参数后将对象当作参数传入API中 */ @interface TCGetIntimateFriendsDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * * \note 不用释放,返回的对象是自动释放的 */ + (TCGetIntimateFriendsDic *) dictionary; /** * 请求个数(1-20) */ @property (nonatomic, retain) TCRequiredStr paramReqnum; @end #pragma mark - #pragma mark TCSendStoryDic /** * \brief QQ空间定向分享的参数字典定义 * * 该分享支持@到指定好友,最多支持10个好友。 * 其中第三方应用可预传最多5个指定好友的openid,其余好友由用户自行选择。 * 该分享形式仅提供跳QZone分享和本地Html5分享两种形式。 * sendStroy不支持userData参数 */ @interface TCSendStoryDic : TCAPIRequest /** * 返回一个对象用来进行API参数的填充 * * \note 不用释放,返回的对象是自动释放的 */ + (TCSendStoryDic *) dictionary; /** * 分享的标题 */ @property (nonatomic, retain) TCRequiredStr paramTitle; /** * 故事摘要,最多不超过50个汉字,可以为空 */ @property (nonatomic, retain) TCOptionalStr paramSummary; /** * 默认展示在输入框里的分享理由,最多120个汉字,可以为空 */ @property (nonatomic, retain) TCOptionalStr paramDescription; /** * 图片url */ @property (nonatomic, retain) TCOptionalStr paramPics; /** * 如果不填,则默认为"进入应用" */ @property (nonatomic, retain) TCRequiredStr paramAct; /** * 点击分享的Url */ @property (nonatomic, retain) TCOptionalStr paramShareUrl; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/Headers/WeiBoAPI.h ================================================ // // WeiBoAPI.h // TencentOpenApi_IOS // // Created by qqconnect on 13-6-25. // Copyright (c) 2013年 Tencent. All rights reserved. // #ifndef QQ_OPEN_SDK_LITE #import #import "sdkdef.h" /** 微博相关接口基类 */ @interface WeiBo_baseRequest : TCAPIRequest @end /** * \brief 发表一条微博信息(纯文本)到腾讯微博平台上。 * \note 注意连续两次发布的微博内容不可以重复。 */ @interface WeiBo_add_t_POST : WeiBo_baseRequest /** * 表示要发表的微博内容。 * \note 必须为UTF-8编码,最长为140个汉字,也就是420字节。 * 如果微博内容中有URL,后台会自动将该URL转换为短URL,每个URL折算成11个字节。 * 若在此处@好友,需正确填写好友的微博账号,而非昵称。 */ @property (nonatomic, retain) TCRequiredStr param_content; /** * 用户ip。 * \note 必须正确填写用户侧真实ip,不能为内网ip及以127或255开头的ip,以分析用户所在地。 */ @property (nonatomic, retain) TCOptionalStr param_clientip; /** * 用户所在地理位置的经度。 * \note 为实数,最多支持10位有效数字。有效范围:-180.0到+180.0,+表示东经,默认为0.0。 */ @property (nonatomic, retain) TCOptionalStr param_longitude; /** * 用户所在地理位置的纬度。 * \note 为实数,最多支持10位有效数字。有效范围:-90.0到+90.0,+表示北纬,默认为0.0。 */ @property (nonatomic, retain) TCOptionalStr param_latitude; /** * 容错标志,支持按位操作,默认为0。 * \note 0×2:图片数据大小错误则报错; * 0×4:检查图片格式不支持则报错; * 0×8:上传图片失败则报错; * 0×20:微博内容长度超过140字则报错; * 0:以上错误均做容错处理,即发表普通微博; * 0×2|0×4|0×8|0×20:同旧模式,以上各种情况均报错,不做兼容处理。 * 0x2,0x4,0x8 只对 \ref WeiBo_add_pic_t_POST 有效 */ @property (nonatomic, retain) TCRequiredStr param_compatibleflag; @end /** * \brief 上传一张图片,并发布一条消息到腾讯微博平台上。 * \note 除了图片参数 其他参数参照 \ref WeiBo_add_t_POST */ @interface WeiBo_add_pic_t_POST : WeiBo_add_t_POST /** * 要上传的图片的文件名以及图片的内容 * \note 图片仅支持gif、jpeg、jpg、png、bmp及ico格式 * (所有图片都会重新压缩,gif被重新压缩后不会再有动画效果),图片size小于4M */ @property (nonatomic, retain) TCRequiredImage param_pic; @end #endif ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/Headers/sdkdef.h ================================================ /// /// \file sdkdef.h /// \brief SDK中相关常量定义 /// /// Created by Tencent on 12-12-25. /// Copyright (c) 2012年 Tencent. All rights reserved. /// #import #import /** * \brief 设置sdk的log等级 */ typedef enum { TCOLogLevel_Disabled = -1, // 关闭所有log TCOLogLevel_Error = 0, TCOLogLevel_Warning, TCOLogLevel_Info, TCOLogLevel_Debug, } TCOLogLevel; /** * \brief 手机qq的当前版本 */ typedef enum QQVersion { kQQUninstall, kQQVersion3_0, kQQVersion4_0, //支持sso登陆 kQQVersion4_2_1, //ios7兼容 kQQVersion4_5, //4.5版本,wpa会话 kQQVersion4_6, //4.6版本,sso登陆信令通道切换 kQQVersion4_7, //4.7版本 不确定新支持了什么样的属性 } QQVersion; /** * \brief APIResponse.retCode可能的枚举常量 */ typedef enum { URLREQUEST_SUCCEED = 0, /**< 网络请求成功发送至服务器,并且服务器返回数据格式正确 * \note 这里包括所请求业务操作失败的情况,例如没有授权等原因导致 */ URLREQUEST_FAILED = 1, /**< 网络异常,或服务器返回的数据格式不正确导致无法解析 */ } REPONSE_RESULT; /** * \brief 增量授权失败原因 * * \note 增量授权失败不影响原token的有效性(原token已失效的情况除外) */ typedef enum { kUpdateFailUnknown = 1, ///< 未知原因 kUpdateFailUserCancel, ///< 用户取消 kUpdateFailNetwork, ///< 网络问题 } UpdateFailType; /** * \brief 封装服务器返回的结果 * * APIResponse用于封装所有请求的返回结果,包括错误码、错误信息、原始返回数据以及返回数据的json格式字典 */ @interface APIResponse : NSObject { int _detailRetCode; int _retCode; int _seq; NSString *_errorMsg; NSDictionary *_jsonResponse; NSString *_message; id _userData; } /** * 新增的详细错误码\n * detailRetCode主要用于区分不同的错误情况,参见\ref OpenSDKError */ @property (nonatomic, assign) int detailRetCode; /** * 网络请求是否成功送达服务器,以及服务器返回的数据格式是否正确\n * retCode具体取值可参考\ref REPONSE_RESULT */ @property (nonatomic, assign) int retCode; /** * 网络请求对应的递增序列号,方便内部管理 */ @property (nonatomic, assign) int seq; /** * 错误提示语 */ @property (nonatomic, retain) NSString *errorMsg; /** * 服务器返回数据的json格式字典\n * 字典内具体参数的命名和含义请参考\ref api_spec */ @property (nonatomic, retain) NSDictionary *jsonResponse; /** * 服务器返回的原始数据字符串 */ @property (nonatomic, retain) NSString *message; /** * 用户保留数据 */ @property (nonatomic, retain) id userData; @end /** * 用户自定义的保留字段 */ FOUNDATION_EXTERN NSString * const PARAM_USER_DATA; /** * \name 应用邀请参数字段定义 */ ///@{ /** 应用邀请展示图片url的key */ FOUNDATION_EXTERN NSString * const PARAM_APP_ICON; /** 应用邀请描述文本的key */ FOUNDATION_EXTERN NSString * const PARAM_APP_DESC; /** 应用邀请好友列表的key */ FOUNDATION_EXTERN NSString * const PARAM_APP_INVITED_OPENIDS; ///@} /** * \name sendStory新分享参数字段定义 */ ///@{ /** 预填入接受人列表的key */ FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_RECEIVER; /** 分享feeds标题的key */ FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_TITLE; /** 分享feeds评论内容的key */ FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_COMMENT; /** 分享feeds摘要的key */ FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_SUMMARY; /** 分享feeds展示图片url的key */ FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_IMAGE; /** 分享feeds跳转链接url的key */ FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_URL; /** 分享feeds点击操作默认行为的key */ FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_ACT; ///@} /** * \name 设置头像参数字段定义 */ ///@{ /** 头像图片数据的key */ FOUNDATION_EXTERN NSString * const PARAM_SETUSERHEAD_PIC; /** 头像图片文件名的key */ FOUNDATION_EXTERN NSString * const PARAM_SETUSERHEAD_FILENAME; ///@} /** * \name 服务器返回数据的参数字段定义 */ ///@{ /** 服务器返回码的key */ FOUNDATION_EXTERN NSString * const PARAM_RETCODE; /** 服务器返回错误信息的key */ FOUNDATION_EXTERN NSString * const PARAM_MESSAGE; /** 服务器返回额外数据的key */ FOUNDATION_EXTERN NSString * const PARAM_DATA; ///@} /** * \name 错误信息相关常量定义 */ ///@{ /** 详细错误信息字典中额外信息的key */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyExtraInfo; /** 详细错误信息字典中返回码的key */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyRetCode; /** 详细错误信息字典中错误语句的key */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyMsg; /** 不支持的接口 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUnsupportedAPI; /** 操作成功 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgSuccess; /** 未知错误 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUnknown; /** 用户取消 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUserCancel; /** 请重新登录 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgReLogin; /** 应用没有操作权限 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgOperationDeny; /** 网络异常或没有网络 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgNetwork; /** URL格式或协议错误 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgURL; /** 解析数据出错 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgDataParse; /** 传入参数有误 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgParam; /** 连接超时 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgTimeout; /** 安全问题 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgSecurity; /** 文件读写错误 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgIO; /** 服务器端错误 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgServer; /** 页面错误 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgWebPage; /** 设置头像图片过大 */ FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUserHeadPicLarge; ///@} /** * \brief SDK新增详细错误常量 */ typedef enum { kOpenSDKInvalid = -1, ///< 无效的错误码 kOpenSDKErrorUnsupportedAPI = -2, ///< 不支持的接口 /** * \name CommonErrorCode * 公共错误码 */ ///@{ kOpenSDKErrorSuccess = 0, ///< 成功 kOpenSDKErrorUnknown, ///< 未知错误 kOpenSDKErrorUserCancel, ///< 用户取消 kOpenSDKErrorReLogin, ///< token无效或用户未授权相应权限需要重新登录 kOpenSDKErrorOperationDeny, ///< 第三方应用没有该api操作的权限 ///@} /** * \name NetworkRelatedErrorCode * 网络相关错误码 */ ///@{ kOpenSDKErrorNetwork, ///< 网络错误,网络不通或连接不到服务器 kOpenSDKErrorURL, ///< URL格式或协议错误 kOpenSDKErrorDataParse, ///< 数据解析错误,服务器返回的数据解析出错 kOpenSDKErrorParam, ///< 传入参数错误 kOpenSDKErrorConnTimeout, ///< http连接超时 kOpenSDKErrorSecurity, ///< 安全问题 kOpenSDKErrorIO, ///< 下载和文件IO错误 kOpenSDKErrorServer, ///< 服务器端错误 ///@} /** * \name WebViewRelatedError * webview特有错误 */ ///@{ kOpenSDKErrorWebPage, ///< 页面错误 ///@} /** * \name SetUserHeadRelatedErrorCode * 设置头像自定义错误码段 */ ///@{ kOpenSDKErrorUserHeadPicLarge = 0x010000, ///< 图片过大 设置头像自定义错误码 ///@} } OpenSDKError; /** * \name SDK版本(v1.3)支持的授权列表常量 */ ///@{ /** 发表一条说说到QQ空间(需要申请权限) */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_TOPIC; /** 发表一篇日志到QQ空间(需要申请权限) */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_ONE_BLOG; /** 创建一个QQ空间相册(需要申请权限) */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_ALBUM; /** 上传一张照片到QQ空间相册(需要申请权限) */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_UPLOAD_PIC; /** 获取用户QQ空间相册列表(需要申请权限) */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_LIST_ALBUM; /** 同步分享到QQ空间、腾讯微博 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_SHARE; /** 验证是否认证空间粉丝 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_CHECK_PAGE_FANS; /** 上传图片并发表消息到腾讯微博 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_PIC_T; /** 删除一条微博信息 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_DEL_T; /** 获取一条微博的转播或评论信息列表 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_REPOST_LIST; /** 获取登录用户自己的详细信息 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_INFO; /** 获取其他用户的详细信息 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_OTHER_INFO; /** 获取登录用户的听众列表 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_FANSLIST; /** 获取登录用户的收听列表 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_IDOLLIST; /** 收听腾讯微博上的用户 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_IDOL; /** 取消收听腾讯微博上的用户 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_DEL_IDOL; /** 获取微博中最近at的好友 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_INTIMATE_FRIENDS_WEIBO; /** 获取微博中匹配昵称的好友 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_MATCH_NICK_TIPS_WEIBO; /** 获取会员用户基本信息 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_VIP_INFO; /** 获取会员用户详细信息 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_VIP_RICH_INFO; /** 获取用户信息 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_USER_INFO; /** 移动端获取用户信息 */ FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_SIMPLE_USER_INFO; ///@} /** * \name CGI接口相关参数类型定义 */ ///@{ /** 必填的字符串类型参数 */ typedef NSString *TCRequiredStr; /** 必填的UIImage类型参数 */ typedef UIImage *TCRequiredImage; /** 必填的整型参数 */ typedef NSInteger TCRequiredInt; /** 必填的数字类型 */ typedef NSNumber *TCRequiredNumber; /** 必填的NSData参数 */ typedef NSData *TCRequiredData; /** 可选的字符串类型参数 */ typedef NSString *TCOptionalStr; /** 可选的UIImage类型参数 */ typedef UIImage *TCOptionalImage; /** 可选的整型参数 */ typedef NSInteger TCOptionalInt; /** 可选的数字类型 */ typedef NSNumber *TCOptionalNumber; /** 可选的不定类型参数 */ typedef id TCRequiredId; ///@} /** * \brief CGI请求的参数字典封装辅助基类 * * 将相应属性的值以key-value的形式保存到参数字典中 */ @interface TCAPIRequest : NSMutableDictionary /** CGI请求的URL地址 */ @property (nonatomic, readonly) NSURL *apiURL; /** CGI请求方式:"GET","POST" */ @property (nonatomic, readonly) NSString *method; /** * API参数中的保留字段,可以塞入任意字典支持的类型,再调用完成后会带回给调用方 */ @property (nonatomic, retain) TCRequiredId paramUserData; /** * APIResponse,API的返回结果 */ @property (nonatomic, readonly) APIResponse *response; /** 取消相应的CGI请求任务 */ - (void)cancel; @end @protocol TCAPIRequestDelegate @optional - (void)cgiRequest:(TCAPIRequest *)request didResponse:(APIResponse *)response; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenAPI.framework/TencentOpenAPI ================================================ [File too large to display: 13.0 MB] ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenApi_IOS_Bundle.bundle/ios_open_sdk_2.9.3.2_iphone ================================================ ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/TencentOpenApi_IOS_Bundle.bundle/local.html ================================================ 社交渠道 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/TencentOpenAPI/UMSocialQQHandler.h ================================================ // // UMSocialQQHandler.h // SocialSDK // // Created by yeahugo on 13-8-5. // Copyright (c) 2013年 Umeng. All rights reserved. // #import #import //QQ互联 SDK #import @interface UMSocialQQHandler : NSObject /** 设置分享到手机QQ和QQ空间的应用ID @param appId QQ互联应用Id @param appKey QQ互联应用Key @param url 分享URL链接 */ +(void)setQQWithAppId:(NSString *)appId appKey:(NSString *)appKey url:(NSString *)url; /** 设置在没有安装QQ客户端的情况下,是否支持单独授权到QQ互联 @param supportWebView 是否支持没有安装QQ客户端的情况下,是否支持单独授权 */ +(void)setSupportWebView:(BOOL)supportWebView; /** deprecated API,默认使用Qzone SSO授权 设置QQ空间是否用手机QQ客户端进行SSO授权,默认使用webview授权 @param supportQzoneSSO 是否用手机QQ授权 */ //+ (void)setSupportQzoneSSO:(BOOL)supportQzoneSSO; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Tumblr/UMSocialTumblrHandler.h ================================================ // // UMSocialThumblrHandler.h // SocialSDK // // Created by Gavin Ye on 8/20/14. // Copyright (c) 2014 Umeng. All rights reserved. // #import @interface UMSocialTumblrHandler : NSObject +(void)openTumblr; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/Fabric.framework/Headers/FABAttributes.h ================================================ // // FABAttributes.h // Fabric // // Created by Priyanka Joshi on 3/3/15. // Copyright (c) 2015 Twitter. All rights reserved. // #pragma once #define FAB_UNAVAILABLE(x) __attribute__((unavailable(x))) #if __has_feature(nullability) #define FAB_NONNULL __nonnull #define FAB_NULLABLE __nullable #define FAB_START_NONNULL _Pragma("clang assume_nonnull begin") #define FAB_END_NONNULL _Pragma("clang assume_nonnull end") #else #define FAB_NONNULL #define FAB_NULLABLE #define FAB_START_NONNULL #define FAB_END_NONNULL #endif ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/Fabric.framework/Headers/Fabric.h ================================================ // // Fabric.h // // Copyright (c) 2014 Twitter. All rights reserved. // #import #import "FABAttributes.h" FAB_START_NONNULL /** * Fabric Base. Coordinates configuration and starts all provided kits. */ @interface Fabric : NSObject /** * Initialize Fabric and all provided kits. Call this method within your App Delegate's * `application:didFinishLaunchingWithOptions:` and provide the kits you wish to use. * * For example, in Objective-C: * * `[Fabric with:@[TwitterKit, CrashlyticsKit, MoPubKit]];` * * Swift: * * `Fabric.with([Twitter(), Crashlytics(), MoPub()])` * * Only the first call to this method is honored. Subsequent calls are no-ops. * * @param kits An array of kit instances. Kits may provide a macro such as CrashlyticsKit which can be passed in as array elements in objective-c. * * @return Returns the shared Fabric instance. In most cases this can be ignored. */ + (instancetype)with:(NSArray *)kits; /** * Returns the Fabric singleton object. */ + (instancetype)sharedSDK; /** * This BOOL enables or disables debug logging, such as kit version information. The default value is NO. */ @property (nonatomic, assign) BOOL debug; /** * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance. */ - (id)init FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance."); /** * Returns Fabrics's instance of the specified kit. * * @param klass The class of the kit. * * @return The kit instance of class klass which was provided to with: or nil. */ - (id FAB_NULLABLE)kitForClass:(Class)klass; /** * Returns a dictionary containing the kit configuration info for the provided kit. * The configuration information is parsed from the application's Info.plist. This * method is primarily intended to be used by kits to retrieve their configuration. * * @param kitInstance An instance of the kit whose configuration should be returned. * * @return A dictionary containing kit specific configuration information or nil if none exists. */ - (NSDictionary * FAB_NULLABLE)configurationDictionaryForKit:(id)kitInstance; @end FAB_END_NONNULL ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/Fabric.framework/Info.plist ================================================ BuildMachineOSBuild 13F34 CFBundleDevelopmentRegion en CFBundleExecutable Fabric CFBundleIdentifier io.fabric.sdk.ios CFBundleInfoDictionaryVersion 6.0 CFBundleName Fabric CFBundlePackageType FMWK CFBundleShortVersionString 1.2.8 CFBundleSignature ???? CFBundleSupportedPlatforms iPhoneOS CFBundleVersion 20 DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild 12B411 DTPlatformName iphoneos DTPlatformVersion 8.1 DTSDKBuild 12B411 DTSDKName iphoneos8.1 DTXcode 0611 DTXcodeBuild 6A2008a MinimumOSVersion 5.0 NSHumanReadableCopyright Copyright © 2015 Twitter. All rights reserved. UIDeviceFamily 1 2 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/Fabric.framework/Modules/module.modulemap ================================================ framework module Fabric { umbrella header "Fabric.h" export * module * { export * } } ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Headers/TWTRAPIErrorCode.h ================================================ // // TWTRAPIErrorCode.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import /** * The NSError domain of errors surfaced by the Twitter API. */ FOUNDATION_EXPORT NSString * const TWTRAPIErrorDomain; /** * Error codes surfaced by the Twitter API. * @see https://dev.twitter.com/docs/error-codes-responses */ typedef NS_ENUM(NSUInteger, TWTRAPIErrorCode) { /** * Your call could not be completed as dialed. */ TWTRAPIErrorCodeCouldNotAuthenticate = 32, /** * Corresponds with an HTTP 404 - the specified resource was not found. */ TWTRAPIErrorCodePageNotExist = 34, /** * Not authorized to use this endpoint. */ TWTRAPIErrorCodeNotAuthorizedForEndpoint = 37, /** * Corresponds with an HTTP 403 — the access token being used belongs to a suspended user and they can't complete the action you're trying to take */ TWTRAPIErrorCodeAccountSuspended = 64, /** * Corresponds to a HTTP request to a retired v1-era URL. */ TWTRAPIErrorCodeAPIVersionRetired = 68, /** * The request limit for this resource has been reached for the current rate limit window. */ TWTRAPIErrorCodeRateLimitExceeded = 88, /** * The access token used in the request is incorrect or has expired. Used in API v1.1. */ TWTRAPIErrorCodeInvalidOrExpiredToken = 89, /** * Only SSL connections are allowed in the API, you should update your request to a secure connection. See [how to connect using SSL](https://dev.twitter.com/docs/security/using-ssl). */ TWTRAPIErrorCodeSSLInvalid = 92, /** * Corresponds with an HTTP 503 - Twitter is temporarily over capacity. */ TWTRAPIErrorCodeOverCapacity = 130, /** * Corresponds with an HTTP 500 - An unknown internal error occurred. */ TWTRAPIErrorCodeInternalError = 131, /** * Corresponds with a HTTP 401 - it means that your oauth_timestamp is either ahead or behind our acceptable range. */ TWTRAPIErrorCodeCouldNotAuthenticateTimestampOutOfRange = 135, /** * You have already favorited this status. */ TWTRAPIErrorCodeAlreadyFavorited = 139, /** * Corresponds with HTTP 403 — returned when a user cannot follow another user due to some kind of limit. */ TWTRAPIErrorCodeCannotFollowOverLimit = 161, /** * Corresponds with HTTP 403 — returned when a Tweet cannot be viewed by the authenticating user, usually due to the Tweet's author having protected their Tweets. */ TWTRAPIErrorCodeNotAuthorizedToSeeStatus = 179, /** * Corresponds with HTTP 403 — returned when a Tweet cannot be posted due to the user having no allowance remaining to post. Despite the text in the error message indicating that this error is only returned when a daily limit is reached, this error will be returned whenever a posting limitation has been reached. Posting allowances have roaming windows of time of unspecified duration. */ TWTRAPIErrorCodeOverDailyStatusUpdateLimit = 185, /** * The status text has been Tweeted already by the authenticated account. */ TWTRAPIErrorCodeStatusIsDuplicate = 187, /** * Typically sent with 1.1 responses with HTTP code 400. The method requires authentication but it was not presented or was wholly invalid. */ TWTRAPIErrorCodeBadAuthenticationData = 215, /** * We constantly monitor and adjust our filters to block spam and malicious activity on the Twitter platform. These systems are tuned in real-time. If you get this response our systems have flagged the Tweet or DM as possibly fitting this profile. If you feel that the Tweet or DM you attempted to create was flagged in error, please report the details around that to us by filing a ticket at https://support.twitter.com/forms/platform */ TWTRAPIErrorCodeRequestIsAutomated = 226, /** * Returned as a challenge in xAuth when the user has login verification enabled on their account and needs to be directed to twitter.com to [generate a temporary password](https://twitter.com/settings/applications). */ TWTRAPIErrorCodeUserMustVerifyLogin = 231, /** * "Bad guest token." The token has probably expired. Try calling `-[Twitter logInGuestWithCompletion:]` again later. */ TWTRAPIErrorCodeBadGuestToken = 239, /** * Corresponds to a HTTP request to a retired URL. */ TWTRAPIErrorCodeEndpointRetired = 251, /** * Corresponds with HTTP 403 — returned when the application is restricted from POST, PUT, or DELETE actions. See [How to appeal application suspension and other disciplinary actions](https://support.twitter.com/articles/72585). */ TWTRAPIErrorCodeApplicationCannotPerformWriteAction = 261, /** * Corresponds with HTTP 403. The authenticated user account cannot mute itself. */ TWTRAPIErrorCodeCannotMuteSelf = 271, /** * Corresponds with HTTP 403. The authenticated user account is not muting the account a call is attempting to unmute. */ TWTRAPIErrorCodeCannotMuteSpecifiedUser = 272, /** * You have already retweeted this tweet. */ TWTRAPIErrorCodeAlreadyRetweeted = 327, /** * Returned in API v1.1 when a request cannot be served due to the application's rate limit having been exhausted for the resource. See [Rate Limiting in API v1.1](https://dev.twitter.com/docs/rate-limiting/1.1). */ TWTRAPIErrorCodeTooManyRequests = 429 }; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Headers/TWTRAuthConfig.h ================================================ // // TWTRAuthConfig.h // TwitterKit // // Copyright (c) 2015 Twitter. All rights reserved. // #import /** * Authentication configuration details. Encapsulates credentials required to authenticate a Twitter application. You can obtain your credentials at https://apps.twitter.com/. */ @interface TWTRAuthConfig : NSObject /** * The consumer key of the Twitter application. */ @property (nonatomic, copy, readonly) NSString *consumerKey; /** * The consumer secret of the Twitter application. */ @property (nonatomic, copy, readonly) NSString *consumerSecret; /** * Returns an `TWTRAuthConfig` object initialized by copying the values from the consumer key and consumer secret. * * @param consumerKey The consumer key. * @param consumerSecret The consumer secret. */ - (instancetype)initWithConsumerKey:(NSString *)consumerKey consumerSecret:(NSString *)consumerSecret; /** * Unavailable. Use `initWithConsumerKey:consumerSecret:` instead. */ - (instancetype)init __attribute__((unavailable("Use -initWithConsumerKey:consumerSecret: instead."))); @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Headers/TWTRAuthSession.h ================================================ // // TWTRAuthSession.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import /** * Encapsulates the authorization details of an OAuth Session. */ @protocol TWTRAuthSession @property (nonatomic, readonly, copy) NSString *authToken; @property (nonatomic, readonly, copy) NSString *authTokenSecret; @property (nonatomic, readonly, copy) NSString *userID; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Headers/TWTRConstants.h ================================================ // // TWTRConstants.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import #pragma mark - Error messages /** * The NSError domain of errors surfaced by the Twitter SDK. */ FOUNDATION_EXPORT NSString * const TWTRErrorDomain; /** * Error codes surfaced by the Twitter SDK. */ typedef NS_ENUM(NSInteger, TWTRErrorCode) { /** * Unknown error. */ TWTRErrorCodeUnknown = -1, /** * Authentication has not been set up yet. You must call -[Twitter logInWithCompletion:] or -[Twitter logInGuestWithCompletion:] */ TWTRErrorCodeNoAuthentication = 0, /** * Twitter has not been initialized yet. Call +[Fabric with:@[TwitterKit]] or -[Twitter startWithConsumerKey:consumerSecret:]. */ TWTRErrorCodeNotInitialized = 1, /** * User has declined to grant permission to information such as their email address. */ TWTRErrorCodeUserDeclinedPermission = 2, /** * User has granted permission to their email address but no address is associated with their account. */ TWTRErrorCodeUserHasNoEmailAddress = 3, /** * A resource has been requested by ID, but that ID was not found. */ TWTRErrorCodeInvalidResourceID = 4, /** * A request has been issued for an invalid URL. */ TWTRErrorCodeInvalidURL = 5, /** * Type mismatch in parsing JSON from the Twitter API. */ TWTRErrorCodeMismatchedJSONType = 6, /** * Fail to save to keychain. */ TWTRErrorCodeKeychainSerializationFailure = 7, /** * Fail to save to disk. */ TWTRErrorCodeDiskSerializationError = 8, /** * Error authenticating with the webview. */ TWTRErrorCodeWebViewError = 9, /** * A required parameter is missing. */ TWTRErrorCodeMissingParameter = 10, }; /** * The NSError domain of errors surfaced by the Twitter SDK during the login operation. */ FOUNDATION_EXPORT NSString * const TWTRLogInErrorDomain; /** * Error codes surfaced by the Twitter SDK with the `TWTRLogInErrorDomain` error domain. */ typedef NS_ENUM(NSInteger, TWTRLogInErrorCode) { /** * Unknown error. */ TWTRLogInErrorCodeUnknown = -1, /** * User denied login. */ TWTRLogInErrorCodeDenied = 0, /** * User canceled login. */ TWTRLogInErrorCodeCanceled = 1, /** * No Twitter account found. */ TWTRLogInErrorCodeNoAccounts = 2, /** * Reverse auth with linked account failed. */ TWTRLogInErrorCodeReverseAuthFailed = 3 }; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Headers/TWTRCoreOAuthSigning.h ================================================ // // TWTRCoreOAuthSigning.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import FOUNDATION_EXPORT NSString * const TWTROAuthEchoRequestURLStringKey; FOUNDATION_EXPORT NSString * const TWTROAuthEchoAuthorizationHeaderKey; @protocol TWTRCoreOAuthSigning /** * @name OAuth Echo */ /** * OAuth Echo is a means to securely delegate OAuth authorization to a third party while interacting with an API. * For example, you may wish to verify a user's credentials from your app's server (the third party) rather than your app. * This method provides you with the OAuth signature to add to the third party's request to `URLString`, as well as the formed * URL with the query string to send that request to. * This is equivalent to calling `-URLRequestWithMethod:URL:parameters:error:` and getting the URL and the `Authorization` HTTP header out of the request. * * @param method Request method, GET, POST, PUT, DELETE, etc. * @param URLString The full URL of the Twitter endpoint you plan to send a request to. E.g. https://api.twitter.com/1.1/account/verify_credentials.json * @param parameters Request parameters. * @param error Error in the `TWTRErrorDomain` domain. The code will be `TWTRErrorCodeInvalidURL` if the `URLString`'s host is not api.twitter.com * * @return `nil` if there's an error or a missing required parameter, or a dictionary with the fully formed request URL under `TWTROAuthEchoRequestURLStringKey` (`NSString`), and the `Authorization` header in `TWTROAuthEchoAuthorizationHeaderKey` (`NSString`), to be used to sign the request. * * @see More information about OAuth Echo: https://dev.twitter.com/oauth/echo */ - (NSDictionary *)OAuthEchoHeadersForRequestMethod:(NSString *)method URLString:(NSString *)URLString parameters:(NSDictionary *)parameters error:(NSError **)error __attribute__((nonnull(1, 2))); /** * This method provides you with the OAuth signature, as well as the formed URL with the query string, to send a request to `verify_credentials`. * * @return A dictionary with the fully formed Request URL under `TWTROAuthEchoRequestURLStringKey` (`NSString`), and the `Authorization` header in `TWTROAuthEchoAuthorizationHeaderKey` (`NSString`), to be used to sign the request. * * @see More information about OAuth Echo: https://dev.twitter.com/oauth/echo * @see More information about Verify Credentials: https://dev.twitter.com/rest/reference/get/account/verify_credentials */ - (NSDictionary *)OAuthEchoHeadersToVerifyCredentials; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Headers/TWTRGuestSession.h ================================================ // // TWTRGuestSession.h // TwitterKit // // Created by Joey Carmello on 3/31/15. // Copyright (c) 2015 Twitter. All rights reserved. // #import @class TWTRGuestSession; /** * Completion block called when guest login succeeds or fails. * * @param guestSession A `TWTRGuestSession` containing the OAuth tokens or nil. * @param error Error that will be non nil if the authentication request failed. */ typedef void (^TWTRGuestLogInCompletion)(TWTRGuestSession *guestSession, NSError *error); /** * `TWTRGuestSession` represents a guest session authenticated with the Twitter API. See `TWTRSession` for user sessions. */ @interface TWTRGuestSession : NSObject /** * The bearer access token for guest auth. */ @property (nonatomic, copy, readonly) NSString *accessToken; /** * The guest access token. */ @property (nonatomic, copy, readonly) NSString *guestToken; /** * Returns an `TWTRGuestSession` object initialized by copying the values from the dictionary or nil if the dictionary is missing. * * @param sessionDictionary (required) The dictionary received after successfull authentication from Twitter guest-only authentication. */ - (instancetype)initWithSessionDictionary:(NSDictionary *)sessionDictionary; /** * Unavailable. Use `-initWithSessionDictionary:` instead. */ - (instancetype)init __attribute__((unavailable("Use -initWithSessionDictionary: instead."))); @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Headers/TwitterCore.h ================================================ // // TwitterCore.h // // Copyright (c) 2015 Twitter. All rights reserved. // #if __has_feature(modules) @import CoreData; @import Foundation; @import UIKit; #else #import #import #import #endif #import "TWTRAPIErrorCode.h" #import "TWTRAuthConfig.h" #import "TWTRAuthSession.h" #import "TWTRConstants.h" #import "TWTRCoreOAuthSigning.h" #import "TWTRGuestSession.h" ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Info.plist ================================================ BuildMachineOSBuild 14D136 CFBundleDevelopmentRegion English CFBundleGetInfoString TwitterCore Framework CFBundleIdentifier com.twittercore.sdk.ios CFBundleInfoDictionaryVersion 6.0 CFBundleName TwitterCore CFBundlePackageType FMWK CFBundleShortVersionString 1.8.1 CFBundleSupportedPlatforms iPhoneOS CFBundleVersion 1.8.1 DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild 12F69 DTPlatformName iphoneos DTPlatformVersion 8.3 DTSDKBuild 12F69 DTSDKName iphoneos8.3 DTXcode 0632 DTXcodeBuild 6D2105 MinimumOSVersion 7.0 NSHumanReadableCopyright Copyright 2015 Twitter Inc. UIDeviceFamily 1 2 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterCore.framework/Modules/module.modulemap ================================================ framework module TwitterCore { umbrella header "TwitterCore.h" export * module * { export * } } ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRAPIClient.h ================================================ // // TWTRAPIClient.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import "TWTRDefines.h" NS_ASSUME_NONNULL_BEGIN FOUNDATION_EXPORT NSString * const TWTRTweetsNotLoadedKey; @class TWTRUser; @class TWTRTweet; @class TWTRAuthConfig; @class TWTRGuestSession; @protocol TWTRAuthSession; /** * @name Completion Block Types */ /** * Completion block called when the load user request succeeds or fails. * * @param user The Twitter User. * @param error Error that will be set if the API request failed. */ typedef void (^TWTRLoadUserCompletion)(TWTRUser * __twtr_nullable user, NSError * __twtr_nullable error); /** * Completion block called when the load Tweet request succeeds or fails. * * @param tweet The Twitter Tweet. * @param error Error that will be set if the API request failed. */ typedef void (^TWTRLoadTweetCompletion)(TWTRTweet * __twtr_nullable tweet, NSError * __twtr_nullable error); /** * Completion block called when the load Tweets request succeeds or fails. * * @param tweets Tweets that were successfully retrieved. * @param error Error that will be set if the API request failed. */ typedef void (^TWTRLoadTweetsCompletion)(NSArray * __twtr_nullable tweets, NSError * __twtr_nullable error); /** * Completion block called when the network request succeeds or fails. * * @param response Metadata associated with the response to a URL load request. * @param data Content data of the response. * @param connectionError Error object describing the network error that occurred. */ typedef void (^TWTRNetworkCompletion)(NSURLResponse * __twtr_nullable response, NSData * __twtr_nullable data, NSError * __twtr_nullable connectionError); /** * Completion block called when a JSON request to the Twitter API succeeds or fails. * * @param response Metadata associated with the response to a URL load request. * @param responseObject Content data of the response. * @param error Error object describing the network error that occurred. */ typedef void (^TWTRJSONRequestCompletion)(NSURLResponse * __twtr_nullable response, id __twtr_nullable responseObject, NSError * __twtr_nullable error); /** * Client for consuming the Twitter REST API. Provides methods for common API requests, as well as the ability to create and send custom requests. */ @interface TWTRAPIClient : NSObject /** * @name Initialization */ - (instancetype)init __attribute__((unavailable(("Use one of the other `-init...` methods that allow you to provide signing parameters")))); /** * This method is deprecated since TwitterKit v1.4.0. To get an API client, use the one provided by the `Twitter` class. */ - (instancetype)initWithConsumerKey:(NSString *)consumerKey consumerSecret:(NSString *)consumerSecret __attribute__((deprecated)); /** * @name Making Requests */ /** * Returns a signed URL request. * * @param method Request method, GET, POST, PUT, DELETE, etc. * @param URL Request URL. This is the full Twitter API URL. E.g. https://api.twitter.com/1.1/statuses/user_timeline.json * @param parameters Request parameters. * @param error Error that will be set if there was an error signing the request. */ - (NSURLRequest *)URLRequestWithMethod:(NSString *)method URL:(NSString *)URLString parameters:(NSDictionary *)parameters error:(NSError **)error; /** * Sends a Twitter request. * * @param request The request that will be sent asynchronously. * @param completion Completion block to be called on response. Called on main queue. */ - (void)sendTwitterRequest:(NSURLRequest *)request completion:(TWTRNetworkCompletion)completion; /** * @name Common API Actions */ /** * Loads a Twitter User. * * @param userIDString The Twitter user ID of the desired user. * @param completion Completion block to be called on response. Called on main queue. */ - (void)loadUserWithID:(NSString *)userIDString completion:(TWTRLoadUserCompletion)completion; /** * Loads a single Tweet from the network or cache. * * @param tweetIDString The ID of the desired Tweet. * @param completion Completion bock to be called on response. Called on main queue. */ - (void)loadTweetWithID:(NSString *)tweetIDString completion:(TWTRLoadTweetCompletion)completion; /** * Loads a series of Tweets in a batch. The completion block will be passed an array of zero or more * Tweets that loaded successfully. If some Tweets fail to load the array will contain less Tweets than * number of requested IDs. If any Tweets fail to load, the IDs of the Tweets that did not load will * be provided in the userInfo dictionary property of the error parameter under `TWTRTweetsNotLoadedKey`. * * @param tweetIDStrings An array of Tweet IDs. * @param completion Completion block to be called on response. Called on main queue. */ - (void)loadTweetsWithIDs:(NSArray *)tweetIDStrings completion:(TWTRLoadTweetsCompletion)completion; @end NS_ASSUME_NONNULL_END ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRCollectionTimelineDataSource.h ================================================ // // TWTRCollectionTimelineDataSource.h // TwitterKit // // Created by Steven Hepting on 2/10/15. // Copyright (c) 2015 Twitter. All rights reserved. // #import #import "TWTRTimelineDataSource.h" @class TWTRAPIClient; @interface TWTRCollectionTimelineDataSource : NSObject /** * The number of Tweets to request in each query to the Twitter Timeline API when fetching the next batch of Tweets. */ @property (nonatomic, assign, readonly) NSInteger maxTweetsPerRequest; /** * Convenience initializer. * * @param collectionID (required) The ID of this collection. For example, the ID of this collection: https://twitter.com/TwitterMusic/timelines/393773266801659904 is @"393773266801659904" * * @return An instance of TWTRCollectionTimelineDataSource or nil if any of the required parameters is missing. */ - (instancetype)initWithCollectionID:(NSString *)collectionID APIClient:(TWTRAPIClient *)client __attribute__((nonnull)); /** * Designated initializer setting all supported values for Collection Timeline Data Source. * * @param collectionID (required) The Collection ID value. e.g. @"393773266801659904" * @param apiClient (required) The API client to use for all network requests. * @param maxTweetsPerRequest (optional) Number of Tweets to request per batch. A value of 0 uses the server default. * * @return An instance of TWTRCollectionTimelineDataSource or nil if any of the required parameters are missing. */ - (instancetype)initWithCollectionID:(NSString *)collectionID APIClient:(TWTRAPIClient *)client maxTweetsPerRequest:(NSUInteger)maxTweetsPerRequest __attribute__((nonnull)) NS_DESIGNATED_INITIALIZER; - (instancetype)init __unavailable; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRComposer.h ================================================ // // TWTRComposer.h // TwitterKit // // Copyright (c) 2015 Twitter. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN /** * Possible values for the result parameter of the completionHandler property. */ typedef NS_ENUM(NSInteger, TWTRComposerResult) { /** * The composer is dismissed without sending the Tweet (i.e. the user selects Cancel, or the account is unavailable). */ TWTRComposerResultCancelled, /** * The composer is dismissed and the message is being sent in the background, after the user selects Done. */ TWTRComposerResultDone }; /** * Completion block called when the user finishes composing a Tweet. */ typedef void (^TWTRComposerCompletion)(TWTRComposerResult result); /** * The TWTRComposer class presents a view to the user to compose a Tweet. */ @interface TWTRComposer : NSObject /** * Sets the initial text for the Tweet composition prior to showing it. * * @param text The text to tweet. * * @return This will return NO if the receiver has already been presented (and therefore cannot be changed). */ - (BOOL)setText:(twtr_nullable NSString *)text; /** * Sets an image attachment. * * @param image The image to attach. * * @return This will return NO if the receiver has already been presented (and therefore cannot be changed). */ - (BOOL)setImage:(twtr_nullable UIImage *)image; /** * Adds a URL to the contents of the Tweet message. * * @param url The URL. * * @return This will return NO if the receiver has already been presented (and therefore cannot be changed). */ - (BOOL)setURL:(twtr_nullable NSURL *)url; /** * Presents the composer, with an optional completion handler from the specified view controller. * @param fromController The controller in which to present the composer from. * @param completion completion The completion handler, which has a single parameter indicating whether the user finished or cancelled the Tweet composition. */ - (void)showFromViewController:(UIViewController *)fromController completion:(TWTRComposerCompletion)completion; @end @interface TWTRComposer (TWTRDeprecated) /** * Presents the composer, with an optional completion handler. * * @param completion The completion handler, which has a single parameter indicating whether the user finished or cancelled the Tweet composition. * * @warning This method is deprecated. Use `-showFromViewController:completion:` instead. */ - (void)showWithCompletion:(TWTRComposerCompletion)completion; @end NS_ASSUME_NONNULL_END ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRDefines.h ================================================ // // TWTRDefines.h // // Copyright (c) 2015 Twitter. All rights reserved. // #pragma once #if __has_feature(nullability) #define twtr_nullable nullable #define twtr_nonnull nonnull #define twtr_null_unspecified null_unspecified #define twtr_null_resettable null_resettable #define __twtr_nullable __nullable #define __twtr_nonnull __nonnull #define __twtr_null_unspecified __null_unspecified #else #define twtr_nullable #define twtr_nonnull #define twtr_null_unspecified #define twtr_null_resettable #define __twtr_nullable #define __twtr_nonnull #define __twtr_null_unspecified #endif #ifndef NS_ASSUME_NONNULL_BEGIN #define NS_ASSUME_NONNULL_BEGIN #endif #ifndef NS_ASSUME_NONNULL_END #define NS_ASSUME_NONNULL_END #endif ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRListTimelineDataSource.h ================================================ // // TWTRListTimelineDataSource.h // TwitterKit // // Created by Kang Chen on 6/18/15. // Copyright (c) 2015 Twitter. All rights reserved. // #import #import "TWTRDefines.h" #import "TWTRTimelineDataSource.h" @class TWTRAPIClient; NS_ASSUME_NONNULL_BEGIN /** * Data source representing a list of Tweets. These Tweets are ordered chronologically with the most recent first. * * @see https://dev.twitter.com/rest/reference/get/lists/statuses */ @interface TWTRListTimelineDataSource : NSObject /** * The ID of the list to show Tweets for. Either the `listID` or the `listSlug` and `listOwnerScreenName` are required. */ @property (nonatomic, copy, readonly) NSString *listID; /** * The slug of the list to show Tweets for. Either the `listID` or the `listSlug` and `listOwnerScreenName` are required. */ @property (nonatomic, copy, readonly) NSString *listSlug; /** * Screen name of the owner of the list as specified by the `listSlug`. Either the `listID` or the `listSlug` and `listOwnerScreenName` are required. */ @property (nonatomic, copy, readonly) NSString *listOwnerScreenName; /** * The number of Tweets to request in each query to the Twitter Timeline API when fetching the next batch of Tweets. Will request 30 Tweets by default. Setting this value to 0 will use the server default. */ @property (nonatomic, assign, readonly) NSUInteger maxTweetsPerRequest; /** * Whether to request retweets in the set of Tweets from the server. * * Defaults to YES. */ @property (nonatomic, assign, readonly) BOOL includeRetweets; /** * Convenience initializer. Uses default values for `maxTweetsPerRequest` and `includeRetweets`. * * @param listID (required) The ID of the list. * @param client (required) The API client to use for making network requests. * * @return A full initialized list timeline datasource. */ - (instancetype)initWithListID:(NSString *)listID APIClient:(TWTRAPIClient *)client; /** * Convenience initializer. Uses default values for `maxTweetsPerRequest` and `includeRetweets`. * * @param listSlug (required) The slug of the list. * @param listOwnerScreenName (required) The list owner's screen name. * @param client (required) The API client to use for making network requests. * * @return A full initialized list timeline datasource. */ - (instancetype)initWithListSlug:(NSString *)listSlug listOwnerScreenName:(NSString *)listOwnerScreenName APIClient:(TWTRAPIClient *)client; /** * Designated initializer for creating list timeline data sources taking all parameters. * * @param listID (optional) The ID of the list. Provide either the `listID` or `listSlug` and `listOwnerScreenName`. * @param listSlug (optional) The slug of the list. Provide either the `listID` or `listSlug` and `listOwnerScreenName`. * @param listOwnerScreenName (optional) The list owner's screen name. Provide either the `listID` or `listSlug` and `listOwnerScreenName`. * @param client (required) The API client to use for making networking requests * @param maxTweetsPerRequest (optional) The number of Tweets per batch to request. A value of 0 will use the server default. * @param includeRetweets (optional) Whether retweets should be requested. * * @return A fully initialized list timeline datasource. */ - (instancetype)initWithListID:(NSString * __twtr_nullable)listID listSlug:(NSString * __twtr_nullable)listSlug listOwnerScreenName:(NSString * __twtr_nullable)listOwnerScreenName APIClient:(TWTRAPIClient *)client maxTweetsPerRequest:(NSUInteger)maxTweetsPerRequest includeRetweets:(BOOL)includeRetweets NS_DESIGNATED_INITIALIZER; - (instancetype)init __unavailable; @end NS_ASSUME_NONNULL_END ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRLogInButton.h ================================================ // // TWTRLogInButton.h // TwitterKit // // Copyright (c) 2015 Twitter. All rights reserved. // #import #import "TWTRSession.h" /** * A Button which launches the sign in to Twitter flow when tapped. */ @interface TWTRLogInButton : UIButton /** * The completion block to be called with a `TWTRSession` if successful, * and a `NSError` if logging in failed or was canceled. */ @property (nonatomic, copy) TWTRLogInCompletion logInCompletion; /** * Returns a new log in button which launches Twitter log in when tapped and * calls `completion` when logging in succeeds or fails. * * Internally, this button simply calls `-[Twitter logInWithCompletion:]`. * * @param completion The completion to be called with a `TWTRSession` if successful, * and a `NSError` if logging in failed or was canceled. * @return An initialized `TWTRLogInButton`. */ + (instancetype)buttonWithLogInCompletion:(TWTRLogInCompletion)completion; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTROAuthSigning.h ================================================ // // TWTROAuthSigning.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import @class TWTRAuthConfig; @class TWTRSession; /** * This class provides tools to generate OAuth signatures. */ @interface TWTROAuthSigning : NSObject /** * @name Initialization */ /** * Instantiate a `TWTROAuthSigning` object with the parameters it needs to generate the OAuth signatures. * * @param authConfig (required) Encapsulates credentials required to authenticate a Twitter application. * @param authSession (required) Encapsulated credentials associated with a user session. * * @return An initialized `TWTROAuthSigning` object or nil if any of the parameters are missing. * * @note If you want to generate OAuth Echo headers to verify Digits' credentials, see `DGTOAuthSigning`. * * @see TWTRAuthConfig * @see TWTRSession */ - (instancetype)initWithAuthConfig:(TWTRAuthConfig *)authConfig authSession:(TWTRSession *)authSession NS_DESIGNATED_INITIALIZER; /** * Unavailable. Use `-initWithAuthConfig:authSession:` instead. */ - (instancetype)init __attribute__((unavailable("Use -initWithAuthConfig:authSession: instead."))); @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRSearchTimelineDataSource.h ================================================ // // TWTRSearchTimelineDataSource.h // TwitterKit // // Copyright (c) 2015 Twitter. All rights reserved. // #import #import "TWTRTimelineDataSource.h" @class TWTRAPIClient; /** Data source representing a Search Timeline. Provides TWTRTweet objects to a TWTRTimelineViewController in pages determined by the TWTRTimelineCursor object passed in to the `loadNext:` and `loadPrevious:` methods. ## Search Queries: * `watching now` containing both “watching” and “now”. Default. * `“happy hour”` containing the exact phrase “happy hour”. * `love OR hate` containing either “love” or “hate” (or both). * `beer -root` containing “beer” but not “root”. * `#haiku` containing the hashtag “haiku”. * `from:alexiskold`sent from person “alexiskold”. * `to:techcrunch` sent to person “techcrunch”. * `@mashable` referencing person “mashable”. * `flight :(` containing “flight” and with a negative attitude. * `traffic ?` containing “traffic” and asking a question. * `movie -scary :)`containing “movie”, but not “scary”, and with a positive attitude. * `hilarious filter:links` containing “hilarious” and linking to URL. * `news source:twitterfeed`containing “news” and entered via TwitterFeed * `superhero since:2010-12-27` containing “superhero” and sent since date “2010-12-27” (year-month-day). * `ftw until:2010-12-27` containing “ftw” and sent before the date “2010-12-27”. @see https://dev.twitter.com/rest/public/search Not implemented: `geocode`, `result_type` */ @interface TWTRSearchTimelineDataSource : NSObject /** * The search query. This matches what you would type into https://twitter.com/search */ @property (nonatomic, copy, readonly) NSString *searchQuery; /** * Restricts tweets returned to a given language, specified by its ISO 639-1 code (for example: en, es). Language detection is best-effort. The server defaults to returning Tweets in all languages. * * @see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes */ @property (nonatomic, copy, readonly) NSString *languageCode; /** * The number of Tweets to request in each network request for more Tweets. By default requests 30 tweets. If set to `0` the parameter will not be set on the request and the Twitter API will use the default size for the endpoint. */ @property (nonatomic, assign, readonly) NSUInteger maxTweetsPerRequest; /** * Convenience initializer. Uses default values for `languageCode` and `maxTweetsPerRequest`. * * @param searchQuery (required) The query string that you would type into https://twitter.com/search * @param client (required) An instance of `TWTRAPIClient` with which API calls will be made. * * @return A fully initialized search timeline datasource or `nil` if any of the required parameters are missing. */ - (instancetype)initWithSearchQuery:(NSString *)searchQuery APIClient:(TWTRAPIClient *)client __attribute__((nonnull)); /** * Designated initializer for creating search timeline data sources taking all parameters. * * @param searchQuery (required) The query string that you would type into https://twitter.com/search * @param client (required) An instance of `TWTRAPIClient` with which API calls will be made. * @param languageCode (optional) The ISO 639-1 language code to restrict Tweets to. A `nil` value will not add the parameter to the server request and so use the server default. * @param maxTweetsPerRequest (optional) The number of tweets to request in each query to the Twitter API. A value of 0 will not add to the parameters and thus use the server default. * * @return A fully initialized search timeline datasource or `nil` if any of the required parameters are missing. */ - (instancetype)initWithSearchQuery:(NSString *)searchQuery APIClient:(TWTRAPIClient *)client languageCode:(NSString *)languageCode maxTweetsPerRequest:(NSUInteger)maxTweetsPerRequest __attribute__((nonnull(1,2))) NS_DESIGNATED_INITIALIZER; - (instancetype)init __unavailable; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRSession.h ================================================ // // TWTRSession.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import #import #import /** * TWTRSession represents a user's session authenticated with the Twitter API. */ @interface TWTRSession : NSObject /** * The authorization token. */ @property (nonatomic, copy, readonly) NSString *authToken; /** * The authorization token secret. */ @property (nonatomic, copy, readonly) NSString *authTokenSecret; /** * The username associated with the access token. */ @property (nonatomic, copy, readonly) NSString *userName; /** * The user ID associated with the access token. */ @property (nonatomic, copy, readonly) NSString *userID; /** * Returns an `TWTRSession` object initialized by copying the values from the dictionary or nil if the dictionary is missing. * * @param sessionDictionary (required) The dictionary received after successfull authentication from Twitter OAuth. */ - (instancetype)initWithSessionDictionary:(NSDictionary *)sessionDictionary; /** * Unavailable. Use -initWithSessionDictionary: instead. */ - (instancetype)init __attribute__((unavailable("Use -initWithSessionDictionary: instead."))); @end /** * Completion block called when user login succeeds or fails. * * @param session Contains the OAuth tokens and minimal information associated with the logged in user or nil. * @param error Error that will be non nil if the authentication request failed. */ typedef void (^TWTRLogInCompletion)(TWTRSession *session, NSError *error); ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRShareEmailViewController.h ================================================ // // TWTRShareEmailViewController.h // TwitterKit // // Copyright (c) 2015 Twitter. All rights reserved. // #import /** * A completion block to be called when the user accepts or denies access to their email address. * * @param email The user's email address. This will be nil if the user does not grant access to their email address or your application is not allowed to request email addresses. * @param error An error that details why a user's email address could not be provided. */ typedef void (^TWTRShareEmailCompletion)(NSString *email, NSError *error); /** * The `TWTRShareEmailViewController` class presents a view to the user to request their email address. This is a subclass of `UINavigationController` and must be presented modally. * * @note Using `TWTRShareEmailViewController` requires your application to be whitelisted by Twitter. To request access, please visit https://support.twitter.com/forms/platform. */ @interface TWTRShareEmailViewController : UINavigationController /** * Completion block called when the user accepts or denies access to their email address. */ @property (nonatomic, copy) TWTRShareEmailCompletion completion; /** * Initializer for `TWTRShareEmailViewController`. * * @param completion The completion block called when the user either accepts or denies access to their email address. Called on the main thread. */ - (instancetype)initWithCompletion:(TWTRShareEmailCompletion)completion; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRTimelineDataSource.h ================================================ // // TWTRTimelineDataSource.h // TwitterKit // // Copyright (c) 2015 Twitter. All rights reserved. // #import "TWTRDefines.h" #import "TWTRTimelineType.h" @class TWTRTimelineCursor; NS_ASSUME_NONNULL_BEGIN typedef void (^TWTRLoadTimelineCompletion)(NSArray * __twtr_nullable tweets, TWTRTimelineCursor * __twtr_nullable cursor, NSError *__twtr_nullable error); /** * Responsible for building network parameters for requesting a timeline of Tweets. * * Implementations of this protocol don't need to be thread-safe. All the methods will be invoked on the main thread. */ @protocol TWTRTimelineDataSource /** * Load Tweets before a given position. For time-based timelines this generally * corresponds to Tweets older than a position. * * @param position (optional) The position or Tweet ID before the page * of Tweets to be loaded. * @param completion (required) Invoked with the Tweets and the cursor in case of success, or nil * and an error in case of error. This must be called on the main thread. */ - (void)loadPreviousTweetsBeforePosition:(NSString * __twtr_nullable)position completion:(TWTRLoadTimelineCompletion)completion; /* * The type of the timeline that this data source represents. */ @property (nonatomic, readonly) TWTRTimelineType timelineType; @end NS_ASSUME_NONNULL_END ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRTimelineType.h ================================================ // // TWTRTimelineType.h // TwitterKit // // Created by Steven Hepting on 3/30/15. // Copyright (c) 2015 Twitter. All rights reserved. // /* * Type of timelines that may be loaded and shown to the user. */ typedef NS_ENUM(NSUInteger, TWTRTimelineType) { /* * User Timeline */ TWTRTimelineTypeUser = 1, /* * Search Timeline */ TWTRTimelineTypeSearch, /** * Collection Timeline */ TWTRTimelineTypeCollection, /** * List Timeline */ TWTRTimelineTypeList, }; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRTimelineViewController.h ================================================ // // TWTRTimelineViewController.h // TwitterKit // // Copyright (c) 2015 Twitter. All rights reserved. // #import #import "TWTRTimelineDataSource.h" /** This class is a `UITableViewController` subclass that displays `TWTRTweetTableViewCell` cells. It handles cell-reuse, cell-configuration, and loading more tweets from the given timeline once the last cell is reached. ## Usage Initialize this class with any object that conforms to the `TWTRTimelineDataSource` protocol. We provide two such classes, `TWTRUserTimelineDataSource` and `TWTRSearchTimelineDataSource`. These provide `TWTRTweet` objects to this table view which then configures the instances of `TWTRTweetTableViewCell`. // Create the data source TWTRAPIClient *client = [Twitter sharedInstance].APIClient; TWTRUserTimelineDataSource *dataSource = [[TWTRUserTimelineDataSource alloc] initWithScreenName:@"jack" APIClient:client]; // Create the timeline view controller TWTRTimelineViewController *timeline = [[TWTRTimelineViewController alloc] initWithDataSource:dataSource]; ## Loading More This class loads the first batch of `TWTRTweet` objects from the Twitter API when `viewWillAppear:` is received. It also handles loading more tweets automatically once the last cell has been shown. */ @interface TWTRTimelineViewController : UITableViewController /** Initializes a timeline view controller. Does not start loading tweets until `viewWillAppear:` is called. This method must be used to initialize this class. The `init` method is unavailable. @param dataSource Required. A timeline data source object that conforms to the `TWTRTimelineDataSource` protocol. @return A fully initialized `TWTRTimelineViewController` or nil if the data source is missing. */ - (instancetype)initWithDataSource:(id)dataSource NS_DESIGNATED_INITIALIZER; /** The source of `TWTRTweet` objects for this `TWTRTimelineViewController`. May be set to update the tweets being shown by this table view. Must be set on the main thread. */ @property (nonatomic, strong) id dataSource; - (instancetype)initWithStyle:(UITableViewStyle)style __attribute__((unavailable("Use -initWithDataSource: instead"))); @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRTweet.h ================================================ // // TWTRTweet.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import @class TWTRTweet; @class TWTRUser; /** * `TWTRTweet` is an immutable representation of a Tweet. */ @interface TWTRTweet : NSObject # pragma mark - Properties /** * The ID of the Twitter Tweet. * @warning This represents the id_str field, which could differ from the value of the id field. */ @property (nonatomic, copy, readonly) NSString *tweetID; /** * The date when this Tweet was created. */ @property (nonatomic, copy, readonly) NSDate *createdAt; /** * The text of the Tweet. */ @property (nonatomic, copy, readonly) NSString *text; /** * The Author of the Tweet. */ @property (nonatomic, strong, readonly) TWTRUser *author; /** * The number of times this Tweet was favorited. */ @property (nonatomic, assign, readonly) long long favoriteCount; /** * The number of times this Tweet was retweeted. */ @property (nonatomic, assign, readonly) long long retweetCount; /** * The Tweet this Tweet was a reply to. */ @property (nonatomic, copy, readonly) NSString *inReplyToTweetID; /** * The User ID this Tweet was a reply to. */ @property (nonatomic, copy, readonly) NSString *inReplyToUserID; /** * The screen name of the user this Tweet was a reply to. * @note This doesn't contain the `@` sign before the screen name. */ @property (nonatomic, copy, readonly) NSString *inReplyToScreenName; /** * The permalink URL for this Tweet. * * Suitable for loading in a `UIWebView`, `WKWebView` or passing to Safari: * * `[[UIApplication sharedApplication] openURL:tweet.permalink];` */ @property (nonatomic, copy, readonly) NSURL *permalink; /** * Whether this Tweet was favorited by the authenticated user. * * @warning The value of this property depends on the authenticated user. */ @property (nonatomic, assign, readonly) BOOL isFavorited; /** * Whether this Tweet was retweeted by the authenticated user. * * @warning The value of this property depends on the authenticated user. */ @property (nonatomic, assign, readonly) BOOL isRetweeted; /** * The Tweet ID of the authenticated user's retweet of this Tweet. This will be `nil` if there is no * authenticated user or the user has not retweeted this Tweet. * * @warning The value of this property depends on the authenticated user. */ @property (nonatomic, copy, readonly) NSString *retweetID; /** * The original, fully-hydrated Tweet that was retweeted. This corresponds to the `retweeted_status` API field. * This is `nil` unless `self.isRetweet == YES`. */ @property (nonatomic, strong, readonly) TWTRTweet *retweetedTweet; /** * Indicates whether this Tweet is a retweet of another Tweet. */ @property (nonatomic, assign, readonly) BOOL isRetweet; # pragma mark - Init /** * Creates a TWTRTweet instance from the dictionary of Twitter API JSON response. * * @param dictionary A parsed dictionary of a single Twitter Tweet API JSON response. * @return TWTRTweet instance. */ - (instancetype)initWithJSONDictionary:(NSDictionary *)dictionary; /** * Creates an array of TWTRTweet instances from the array of Twitter API JSON response. * * @param array A parsed array of Tweet API JSON responses. * @return An array of TWTRTweet instances. */ + (NSArray *)tweetsWithJSONArray:(NSArray *)array; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRTweetTableViewCell.h ================================================ // // TWTRTweetTableViewCell.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import @class TWTRTweet; @class TWTRTweetView; /** * A table view cell subclass which displays a Tweet. */ @interface TWTRTweetTableViewCell : UITableViewCell /** * The Tweet view inside this cell. Holds all relevant text and images. */ @property (nonatomic, strong, readonly) TWTRTweetView *tweetView; /** * Configures the existing Tweet view with a Tweet. Updates labels, images, and thumbnails. * * @param tweet The `TWTRTweet` model object for the Tweet to display. */ - (void)configureWithTweet:(TWTRTweet *)tweet; /** * Returns the height calculated using a given width. Usable from a background thread. This is the preferred approach to calculating height for tableview cells. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { TWTRTweet *tweet = self.tweets[indexPath.row]; // Grab the height for this cell CGFloat height = [TWTRTweetTableViewCell heightForTweet:tweet width:CGRectGetWidth(self.view.bounds)]; return height; } * @param width The table view cell width. */ + (CGFloat)heightForTweet:(TWTRTweet *)tweet width:(CGFloat)width; /** DEPRECATED Returns the height calculated using a given width. Generally just for use with prototype cells. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { TWTRTweet *tweet = self.tweets[indexPath.row]; // Grab the height for this cell CGFloat height = [TWTRTweetTableViewCell heightForTweet:tweet width:CGRectGetWidth(self.view.bounds)]; return height; } @deprecated Use +heightForTweet:width: instead. Deprecated in version 1.3.0 @param width The table view cell width. */ - (CGFloat)calculatedHeightForWidth:(CGFloat)width __attribute__((deprecated("Use +heightForTweet:width: instead."))); @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRTweetView.h ================================================ // // TWTRTweetView.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import #import "TWTRTweetViewDelegate.h" @class TWTRTweet; /** * The style for Tweet views. */ typedef NS_ENUM(NSUInteger, TWTRTweetViewStyle) { /** * A full-size Tweet view. Displays images if present. */ TWTRTweetViewStyleRegular, /** * A small Tweet view, primarily designed to be used in table views. */ TWTRTweetViewStyleCompact }; /** * A default combination of colors for Tweet views. */ typedef NS_ENUM(NSUInteger, TWTRTweetViewTheme) { /** * Official light theme. */ TWTRTweetViewThemeLight, /** * Official dark theme. */ TWTRTweetViewThemeDark, }; /** `TWTRTweetView` displays a single Tweet to the user. It handles background taps and other actions displayed to the user. [[[Twitter sharedInstance] APIClient] loadTweetWithID:@"20" completion:^(TWTRTweet *tweet, NSError *error) { if (tweet) { TWTRTweetView *tweetView = [[TWTRTweetView alloc] initWithTweet:tweet]; [self.view addSubview:tweetView]; } else { NSLog(@"Error loading Tweet: %@", [error localizedDescription]); } }]; ## Interaction The `TWTRTweetViewDelegate` is notified: - When the background is tapped. - When a link is selected. - When the share button is tapped. - When the share action completes. ## Usage in UITableView To allow for usage in a `UITableView`, the `configureWithTweet:` method allows configuration of an existing `TWTRTweetView` without having to create a new instance. ## Sizing When using Auto Layout, feel free to set a width or margin on the Tweet view. The height will be calculated automatically. For old-fashioned frame based layout you may use the standard `sizeThatFits:` method to calculate the appropriate height for a given width: // Find the height for a given width (20pts on either side) CGFloat desiredHeight = [tweetView sizeThatFits:CGSizeMake(self.view.frame.size.width - 40, CGFLOAT_MAX)].height; ## UIAppearance You may use UIAppearance proxy objects to style certain aspects of Tweet views before those views are added to the view hierarchy. // Using UIAppearance Proxy [TWTRTweetView appearance].theme = TWTRTweetViewThemeDark; // Setting colors directly [TWTRTweetView appearance].primaryTextColor = [UIColor yellowColor]; [TWTRTweetView appearance].backgroundColor = [UIColor blueColor]; _Note:_ You can't change the theme through an appearance proxy after the view has already been added to the view hierarchy. Direct `theme` property access will work though. */ @interface TWTRTweetView : UIView /** * Background color of the Tweet view and all text labels (fullname, username, Tweet text, timestamp). */ @property (nonatomic, strong) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; /** * Color of Tweet text and full name. */ @property (nonatomic, strong) UIColor *primaryTextColor UI_APPEARANCE_SELECTOR; /** * Color of links in Tweet text. */ @property (nonatomic, strong) UIColor *linkTextColor UI_APPEARANCE_SELECTOR; /** * Set whether the border should be shown. */ @property (nonatomic, assign) BOOL showBorder UI_APPEARANCE_SELECTOR; /** * Setting the theme of the Tweet view will change the color properties accordingly. * * Set to `TWTRTweetViewThemeLight` by default. */ @property (nonatomic, assign) TWTRTweetViewTheme theme UI_APPEARANCE_SELECTOR; /** * The style of the Tweet. i.e. `TWTRTweetViewStyleRegular` or `TWTRTweetViewStyleCompact`. */ @property (nonatomic, assign, readonly) TWTRTweetViewStyle style; /** * The optional delegate to allow presenting a webview with Tweet details. */ @property (nonatomic, weak) IBOutlet id delegate; /** * Convenience initializer to configure a compact style Tweet view. * * @param tweet The Tweet to display. * * @return The fully-configured Tweet view. */ - (instancetype)initWithTweet:(TWTRTweet *)tweet; /** * Designated initializer. Initializes view with both Tweet and style. * * @param tweet The Tweet to display. * @param style The style of the Tweet view (regular or compact). * * @return The fully configured Tweet view. */ - (instancetype)initWithTweet:(TWTRTweet *)tweet style:(TWTRTweetViewStyle)style; /** * Initialization with a frame parameter is not supported. */ - (instancetype)initWithFrame:(CGRect)frame __attribute__((unavailable("Use -initWithTweet: instead"))); /** Find the size that fits into a desired space. This is a system method on UIView but implemented on `TWTRTweetView` TWTRTweetView *tweetView = [[TWTRTweetView alloc] initWithTweet:tweet]; // Make it 280 points wide CGSize desiredSize = [tweetView sizeThatFits:CGSizeMake(280, CGFLOAT_MAX)]; tweetView.frame = CGRectMake(PADDING_X, PADDING_Y, 280, desiredSize.height); [self.view addSubview:tweetView]; @param size The space available. Should generally leave one orientation unconstrained, and the minimum width supported is 200pts. @return The size that will fit into the space available. */ - (CGSize)sizeThatFits:(CGSize)size; /** * Update all images and label text to fully represent the given Tweet. * * @param tweet The Tweet to display. */ - (void)configureWithTweet:(TWTRTweet *)tweet; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRTweetViewDelegate.h ================================================ // // TWTRTweetViewDelegate.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import @class TWTRTweetView; @class TWTRTweet; /** Delegate for `TWTRTweetView` to receive updates on the user interacting with this particular Tweet view. // Create the tweet view TWTRTweetView *tweetView = [[TWTRTweetView alloc] initWithTweet:tweet]; // Set the delegate tweetView.delegate = self; */ @protocol TWTRTweetViewDelegate @optional /** * The tweet view was tapped. Implement to show your own webview if desired using the `permalinkURL` property on the `TWTRTweet` object passed in. * * @param tweetView The Tweet view that was tapped. * @param tweet The Tweet model object being shown. */ - (void)tweetView:(TWTRTweetView *)tweetView didSelectTweet:(TWTRTweet *)tweet; /** * A URL in the text of a tweet was tapped. Implement to show your own webview rather than opening Safari. * * @param tweetView The Tweet view that was tapped. * @param url The URL that was tapped. */ - (void)tweetView:(TWTRTweetView *)tweetView didTapURL:(NSURL *)url; /** * The Tweet view "Share" button was tapped and the `UIActivityViewController` was shown. * * @param tweetView The Tweet view that was tapped. * @param tweet The Tweet model object being shown. */ - (void)tweetView:(TWTRTweetView *)tweetView willShareTweet:(TWTRTweet *)tweet; /** * The share action for a Tweet was completed. * * @param tweetView The Tweet view that was tapped. * @param tweet The Tweet model object being shown. * @param shareType The share action that was completed. (e.g. `UIActivityTypePostToFacebook`, `UIActivityTypePostToTwitter`, or `UIActivityTypeMail`) */ - (void)tweetView:(TWTRTweetView *)tweetView didShareTweet:(TWTRTweet *)tweet withType:(NSString *)shareType; /** * The share action for a Tweet was cancelled. * * @param tweetView The tweet view handling the share action. * @param tweet The tweet model object represented. */ - (void)tweetView:(TWTRTweetView *)tweetView cancelledShareTweet:(TWTRTweet *)tweet; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRUser.h ================================================ // // TWTRUser.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import /** * Represents a user on Twitter. */ @interface TWTRUser : NSObject # pragma mark - Properties /** * The ID of the Twitter User. */ @property (nonatomic, copy, readonly) NSString *userID; /** * The user's name as it appears on their profile. * * @warning This can be modified by the user at any time. */ @property (nonatomic, copy, readonly) NSString *name; /** * The user's username on Twitter. * * @warning This can be modified by the user at any time. */ @property (nonatomic, copy, readonly) NSString *screenName; /** * Whether the user has been verified by Twitter. */ @property (nonatomic, assign, readonly) BOOL isVerified; /** * Whether the user is protected. */ @property (nonatomic, assign, readonly) BOOL isProtected; /** * The HTTPS URL of the user's profile image. */ @property (nonatomic, copy, readonly) NSString *profileImageURL; /** * The URL of a smaller version of the user's profile image. */ @property (nonatomic, copy, readonly) NSString *profileImageMiniURL; /** * The URL of a larger version of the user's profile image. */ @property (nonatomic, copy, readonly) NSString *profileImageLargeURL; /** * The formatted version of the user's `screenName` with the `@` sign for display purposes. */ @property (nonatomic, copy, readonly) NSString *formattedScreenName; # pragma mark - Init /** * Creates a Twitter user object from the dictionary of Twitter API JSON response. * * @param dictionary A parsed dictionary of a single Twitter Tweet API JSON response. * * @return An initialized TWTRUser instance. */ - (instancetype)initWithJSONDictionary:(NSDictionary *)dictionary; /** * Creates an array of Twitter User instances from the array of Twitter API JSON response. * * @param array A parsed array of Twitter User API JSON responses. * * @return An array of initialized TWTRTweet instances. */ + (NSArray *)usersWithJSONArray:(NSArray *)array; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TWTRUserTimelineDataSource.h ================================================ // // TWTRUserTimelineDataSource.h // TwitterKit // // Copyright (c) 2015 Twitter. All rights reserved. // #import #import "TWTRTimelineDataSource.h" @class TWTRAPIClient; /** * This Timeline Data Source provides a list of Tweets roughly consistent with the list on a Users profile page. The difference is that this data source will filter out Tweets that are direct replies to other users by default. * * These Tweets are ordered chronologically with the most recent first. */ @interface TWTRUserTimelineDataSource : NSObject /** * The screen name of the User whose Tweets are being shown. Either the `screenName` or the `userID` are required. */ @property (nonatomic, copy, readonly) NSString *screenName; /** * The userID of the User whose Tweets are being shown. Either the `screenName` or the `userID` are required. */ @property (nonatomic, copy, readonly) NSString *userID; /** * The number of Tweets to request in each query to the Twitter Timeline API when fetching the next batch of Tweets. Will request 30 Tweets by default. Setting this value to 0 will use the server default. */ @property (nonatomic, assign, readonly) NSUInteger maxTweetsPerRequest; /** * Whether to request replies in the set of Tweets from the server. * * Defaults to NO. */ @property (nonatomic, assign, readonly) BOOL includeReplies; /** * Whether to request retweets in the set of Tweets from the server. * * Defaults to YES. */ @property (nonatomic, assign, readonly) BOOL includeRetweets; /** * Convenience initializer. Uses default values for `maxTweetsPerRequest`, `includeReplies` and `includeRetweets`. * * @param screenName (required) The screen name of a Twitter User * @param client (required) The API client to use for making network requests. * * @return A fully initialized user timeline datasource or nil. */ - (instancetype)initWithScreenName:(NSString *)screenName APIClient:(TWTRAPIClient *)client __attribute__((nonnull)); /** * The designated initialzer accepted values for properties. * * @param userID (optional) The user ID of the Twitter User * @param screenName (optional) The screen name of the Twitter User * @param APIClient (required) The API client to use for making network requests. * @param maxTweetsPerRequest (optional) The number of Tweets per batch to request. A value of 0 will use the server default. * @param includeReplies (optional) Whether replies should be requested * @param includeRetweets (optional) Whether retweets should be requested * * @return A fully initialized user timeline datasource or nil. */ - (instancetype)initWithScreenName:(NSString *)screenName userID:(NSString *)userID APIClient:(TWTRAPIClient *)client maxTweetsPerRequest:(NSUInteger)maxTweetsPerRequest includeReplies:(BOOL)includeReplies includeRetweets:(BOOL)includeRetweets __attribute__((nonnull(3))) NS_DESIGNATED_INITIALIZER; - (instancetype)init __unavailable; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/Twitter.h ================================================ // // Twitter.h // // Copyright (c) 2015 Twitter. All rights reserved. // #import #import "TWTRAPIClient.h" #import "TWTRSession.h" /** * The central class of the Twitter Kit. * @note This class can only be used from the main thread. */ @interface Twitter : NSObject /** * Returns the Twitter singleton. * * @return The Twitter singleton. */ + (Twitter *)sharedInstance; /** * Start Twitter with your consumer key and secret. These will override any credentials * present in your applications Info.plist. * * You do not need to call this method unless you wish to provide credentials other than those * in your Info.plist. * * @param consumerKey Your Twitter application's consumer key. * @param consumerSecret Your Twitter application's consumer secret. */ - (void)startWithConsumerKey:(NSString *)consumerKey consumerSecret:(NSString *)consumerSecret; /** * Client for consuming the Twitter REST API. * * This API client is configured with your consumer key and secret if they are available to the Twitter * object (either via initialization of the Twitter instance or your application's Info.plist). * * @warning To make authenticated requests, you need to call `loginWithCompletion:` or `loginGuestWithCompletion:`. */ @property (nonatomic, strong, readonly) TWTRAPIClient *APIClient; /** * The current version of this kit. */ @property (nonatomic, copy, readonly) NSString *version; /** * The Twitter application consumer key. * @deprecated This property is deprecated and will be removed in a later release. Please use `authConfig`. */ @property (nonatomic, copy, readonly) NSString *consumerKey __attribute__((deprecated("Use `authConfig`. This property will be removed in a later release."))); /** * The Twitter application consumer secret. * @deprecated This property is deprecated and will be removed in a later release. Please use `authConfig`. */ @property (nonatomic, copy, readonly) NSString *consumerSecret __attribute__((deprecated("Use `authConfig`. This property will be removed in a later release."))); /** * Authentication configuration details. Encapsulates the `consumerKey` and `consumerSecret` credentials required to authenticate a Twitter application. */ @property (nonatomic, strong, readonly) TWTRAuthConfig *authConfig; /** * @name Authentication */ /** * Triggers user authentication with Twitter. * * This method will present UI to allow the user to log in if there are no saved Twitter login credentials. * * @param completion The completion block will be called after authentication is successful or if there is an error. * @warning This method requires that you have set up your `consumerKey` and `consumerSecret`. */ - (void)logInWithCompletion:(TWTRLogInCompletion)completion; /** * Triggers user authentication with Twitter. Allows the developer to specify the presenting view controller. * * This method will present UI to allow the user to log in if there are no saved Twitter login credentials. * * @param viewController The view controller that will be used to present the authentication view. * @param completion The completion block will be called after authentication is successful or if there is an error. * @warning This method requires that you have set up your `consumerKey` and `consumerSecret`. */ - (void)logInWithViewController:(UIViewController *)viewController completion:(TWTRLogInCompletion)completion; /** * Log in a guest user. This can be used when the user is not a Twitter user. * * This method will not present any UI to the user. * * @param completion The completion block will be called after authentication is successful or if there is an error. * @warning This method requires that you have set up your `consumerKey` and `consumerSecret`. */ - (void)logInGuestWithCompletion:(TWTRGuestLogInCompletion)completion; /** * Triggers user authentication with Twitter given an existing session. * * Use this method if you have already authenticated with Twitter and are migrating to TwitterKit. This * method will verify that the `authToken` and `authTokenSecret` are still valid and log the user in with * the existing credentials. * * @param authToken The existing authToken to use for authentication. * @param authTokenSecret The existing authTokenSecret to use for authentication. * @param completion The completion block will be called after authentication is successful or if there is an error. * @warning This method requires that you have set up your `consumerKey` and `consumerSecret`. */ - (void)logInWithExistingAuthToken:(NSString *)authToken authTokenSecret:(NSString *)authTokenSecret completion:(TWTRLogInCompletion)completion; /** * Returns the current user session or nil if there is no logged in user. * * @return Returns the current user session or nil if there is no logged in user. */ - (TWTRSession *)session; /** * Returns the current guest session or nil if there is no logged in guest. * * @return Returns the current guest session or nil if there is no logged in guest. */ - (TWTRGuestSession *)guestSession; /** * Deletes the local Twitter user session from this app. This will not remove the system Twitter account nor make a network request to invalidate the session. */ - (void)logOut; /** * Deletes the local guest session. Does not make a network request to invalidate the session. */ - (void)logOutGuest; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Headers/TwitterKit.h ================================================ // // TwitterKit.h // // Copyright (c) 2015 Twitter. All rights reserved. // #if __has_feature(modules) @import Accounts; @import Foundation; @import Social; @import UIKit; #else #import #import #import #import #endif #if __IPHONE_OS_VERSION_MIN_REQUIRED < 70000 //#error "TwitterKit doesn't support iOS 6.x and lower. Please, change your minimum deployment target to iOS 7.0" #endif #import #import "Twitter.h" #import "TWTRAPIClient.h" #import "TWTRCollectionTimelineDataSource.h" #import "TWTRComposer.h" #import "TWTRDefines.h" #import "TWTRListTimelineDataSource.h" #import "TWTRLogInButton.h" #import "TWTROAuthSigning.h" #import "TWTRSearchTimelineDataSource.h" #import "TWTRSession.h" #import "TWTRShareEmailViewController.h" #import "TWTRTimelineDataSource.h" #import "TWTRTimelineType.h" #import "TWTRTimelineViewController.h" #import "TWTRTweet.h" #import "TWTRTweetTableViewCell.h" #import "TWTRTweetView.h" #import "TWTRTweetViewDelegate.h" #import "TWTRUser.h" #import "TWTRUserTimelineDataSource.h" #if __has_include() #import #endif /** * `TwitterKit` can be used as an element in the array passed to the `+[Fabric with:]`. */ #define TwitterKit [Twitter sharedInstance] ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Info.plist ================================================ BuildMachineOSBuild 14D136 CFBundleDevelopmentRegion English CFBundleGetInfoString Twitter Kit Framework CFBundleIdentifier com.twitter.sdk.ios CFBundleInfoDictionaryVersion 6.0 CFBundleName TwitterKit CFBundlePackageType FMWK CFBundleShortVersionString 1.8.1 CFBundleSupportedPlatforms iPhoneOS CFBundleVersion 1.8.1 DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild 12F69 DTPlatformName iphoneos DTPlatformVersion 8.3 DTSDKBuild 12F69 DTSDKName iphoneos8.3 DTXcode 0632 DTXcodeBuild 6D2105 MinimumOSVersion 7.0 NSHumanReadableCopyright Copyright 2014 Twitter Inc. UIDeviceFamily 1 2 ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Modules/module.modulemap ================================================ framework module TwitterKit { umbrella header "TwitterKit.h" export * module * { export * } } ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Resources/TwitterKitResources.bundle/en.lproj/Localizable.strings ================================================ /* Label for button to bring up share dialog to share this Tweet in a single Tweet view */ "tw__share_tweet" = "Share Tweet"; /* Subject format used to prefill certain sharing options such as Email includes full name (%1$@) and screenname (%2$@) */ "tw__share_tweet_subject_format" = "Tweet from %1$@ (@%2$@)"; /* Generic share text format used in all sharing options includes screenname (%1$@) and URL to the Tweet (%2$@) */ "tw__share_tweet_generic_template_format" = "Check out @%1$@\'s Tweet: %2$@"; /* Label for Sign in with Twitter button */ "tw__sign_in_with_twitter_button" = "Log in with Twitter"; /* Label Email Share Screen negative button */ "tw__email_share_negative_button" = "Not now"; /* Label Email Share Screen affirmative button */ "tw__email_share_affirmative_button" = "Allow"; /* Heading that appears above the detail message on the share your email screen */ "tw__email_share_heading" = "Share your email address"; /* Detail message that includes the app name and username on the share your email screen */ "tw__email_share_detail_message_format" = "Get updates and other information from %@ when you allow them access to your email on your Twitter account @%@."; /* Fallback string for detail message in case the app name is not available */ "tw__email_share_detail_message_this_app" = "this app"; /* Fallback string for detail message in case the user is not signed in */ "tw__email_share_detail_message_not_signed_in" = "(not signed in)"; /* Label for attributing this Tweet was retweeted by the user %@ */ "tw__tweet_retweeted_by_user" = "Retweeted by %@"; /* Timestamps */ /* Really short abbreviation for days (plural). 5 days would be '5d' */ "TIME_SHORT_DAYS_FORMAT" = "%dd"; /* Really short abbreviation for day (singular). 1 day would be '1d' */ "TIME_SHORT_DAY_FORMAT" = "%dd"; /* Really short abbreviation for hours (plural). 5 hours would be '5h' */ "TIME_SHORT_HOURS_FORMAT" = "%dh"; /* Really short abbreviation for hour (singular). 1 hour would be '1h' */ "TIME_SHORT_HOUR_FORMAT" = "%dh"; /* Really short abbreviation for minutes (plural). 5 minutes would be '5m' */ "TIME_SHORT_MINUTES_FORMAT" = "%dm"; /* Really short abbreviation for minute (singular). 1 minute would be '1m' */ "TIME_SHORT_MINUTE_FORMAT" = "%dm"; /* Really short abbreviation for seconds (plural). 5 seconds would be '5s' */ "TIME_SHORT_SECONDS_FORMAT" = "%ds"; /* Really short abbreviation for second (singular). '1s' */ "TIME_SHORT_SECOND_FORMAT" = "%ds"; /* Accessibility Labels */ /* Text spoken out with VoiceOver when a tweet has an image showing */ "tw__single_image" = "One image attached"; /* Text spoken out with VoiceOver for selecting the profile image on a regular tweet view */ "tw__tweet_profile_accessibility" = "Profile"; /* Text spoken out with VoiceOver for selecting the attached image on a regular tweet view */ "tw__tweet_image_accessibility" = "Attachment"; /* Test String (just for unit tests) */ "tw__test_string" = "Test"; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Versions/A/Resources/TwitterKitResources.bundle/en.lproj/Localizable.strings ================================================ /* Label for button to bring up share dialog to share this Tweet in a single Tweet view */ "tw__share_tweet" = "Share Tweet"; /* Subject format used to prefill certain sharing options such as Email includes full name (%1$@) and screenname (%2$@) */ "tw__share_tweet_subject_format" = "Tweet from %1$@ (@%2$@)"; /* Generic share text format used in all sharing options includes screenname (%1$@) and URL to the Tweet (%2$@) */ "tw__share_tweet_generic_template_format" = "Check out @%1$@\'s Tweet: %2$@"; /* Label for Sign in with Twitter button */ "tw__sign_in_with_twitter_button" = "Log in with Twitter"; /* Label Email Share Screen negative button */ "tw__email_share_negative_button" = "Not now"; /* Label Email Share Screen affirmative button */ "tw__email_share_affirmative_button" = "Allow"; /* Heading that appears above the detail message on the share your email screen */ "tw__email_share_heading" = "Share your email address"; /* Detail message that includes the app name and username on the share your email screen */ "tw__email_share_detail_message_format" = "Get updates and other information from %@ when you allow them access to your email on your Twitter account @%@."; /* Fallback string for detail message in case the app name is not available */ "tw__email_share_detail_message_this_app" = "this app"; /* Fallback string for detail message in case the user is not signed in */ "tw__email_share_detail_message_not_signed_in" = "(not signed in)"; /* Label for attributing this Tweet was retweeted by the user %@ */ "tw__tweet_retweeted_by_user" = "Retweeted by %@"; /* Timestamps */ /* Really short abbreviation for days (plural). 5 days would be '5d' */ "TIME_SHORT_DAYS_FORMAT" = "%dd"; /* Really short abbreviation for day (singular). 1 day would be '1d' */ "TIME_SHORT_DAY_FORMAT" = "%dd"; /* Really short abbreviation for hours (plural). 5 hours would be '5h' */ "TIME_SHORT_HOURS_FORMAT" = "%dh"; /* Really short abbreviation for hour (singular). 1 hour would be '1h' */ "TIME_SHORT_HOUR_FORMAT" = "%dh"; /* Really short abbreviation for minutes (plural). 5 minutes would be '5m' */ "TIME_SHORT_MINUTES_FORMAT" = "%dm"; /* Really short abbreviation for minute (singular). 1 minute would be '1m' */ "TIME_SHORT_MINUTE_FORMAT" = "%dm"; /* Really short abbreviation for seconds (plural). 5 seconds would be '5s' */ "TIME_SHORT_SECONDS_FORMAT" = "%ds"; /* Really short abbreviation for second (singular). '1s' */ "TIME_SHORT_SECOND_FORMAT" = "%ds"; /* Accessibility Labels */ /* Text spoken out with VoiceOver when a tweet has an image showing */ "tw__single_image" = "One image attached"; /* Text spoken out with VoiceOver for selecting the profile image on a regular tweet view */ "tw__tweet_profile_accessibility" = "Profile"; /* Text spoken out with VoiceOver for selecting the attached image on a regular tweet view */ "tw__tweet_image_accessibility" = "Attachment"; /* Test String (just for unit tests) */ "tw__test_string" = "Test"; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/TwitterKit.framework/Versions/Current/Resources/TwitterKitResources.bundle/en.lproj/Localizable.strings ================================================ /* Label for button to bring up share dialog to share this Tweet in a single Tweet view */ "tw__share_tweet" = "Share Tweet"; /* Subject format used to prefill certain sharing options such as Email includes full name (%1$@) and screenname (%2$@) */ "tw__share_tweet_subject_format" = "Tweet from %1$@ (@%2$@)"; /* Generic share text format used in all sharing options includes screenname (%1$@) and URL to the Tweet (%2$@) */ "tw__share_tweet_generic_template_format" = "Check out @%1$@\'s Tweet: %2$@"; /* Label for Sign in with Twitter button */ "tw__sign_in_with_twitter_button" = "Log in with Twitter"; /* Label Email Share Screen negative button */ "tw__email_share_negative_button" = "Not now"; /* Label Email Share Screen affirmative button */ "tw__email_share_affirmative_button" = "Allow"; /* Heading that appears above the detail message on the share your email screen */ "tw__email_share_heading" = "Share your email address"; /* Detail message that includes the app name and username on the share your email screen */ "tw__email_share_detail_message_format" = "Get updates and other information from %@ when you allow them access to your email on your Twitter account @%@."; /* Fallback string for detail message in case the app name is not available */ "tw__email_share_detail_message_this_app" = "this app"; /* Fallback string for detail message in case the user is not signed in */ "tw__email_share_detail_message_not_signed_in" = "(not signed in)"; /* Label for attributing this Tweet was retweeted by the user %@ */ "tw__tweet_retweeted_by_user" = "Retweeted by %@"; /* Timestamps */ /* Really short abbreviation for days (plural). 5 days would be '5d' */ "TIME_SHORT_DAYS_FORMAT" = "%dd"; /* Really short abbreviation for day (singular). 1 day would be '1d' */ "TIME_SHORT_DAY_FORMAT" = "%dd"; /* Really short abbreviation for hours (plural). 5 hours would be '5h' */ "TIME_SHORT_HOURS_FORMAT" = "%dh"; /* Really short abbreviation for hour (singular). 1 hour would be '1h' */ "TIME_SHORT_HOUR_FORMAT" = "%dh"; /* Really short abbreviation for minutes (plural). 5 minutes would be '5m' */ "TIME_SHORT_MINUTES_FORMAT" = "%dm"; /* Really short abbreviation for minute (singular). 1 minute would be '1m' */ "TIME_SHORT_MINUTE_FORMAT" = "%dm"; /* Really short abbreviation for seconds (plural). 5 seconds would be '5s' */ "TIME_SHORT_SECONDS_FORMAT" = "%ds"; /* Really short abbreviation for second (singular). '1s' */ "TIME_SHORT_SECOND_FORMAT" = "%ds"; /* Accessibility Labels */ /* Text spoken out with VoiceOver when a tweet has an image showing */ "tw__single_image" = "One image attached"; /* Text spoken out with VoiceOver for selecting the profile image on a regular tweet view */ "tw__tweet_profile_accessibility" = "Profile"; /* Text spoken out with VoiceOver for selecting the attached image on a regular tweet view */ "tw__tweet_image_accessibility" = "Attachment"; /* Test String (just for unit tests) */ "tw__test_string" = "Test"; ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Twitter/UMSocialTwitterHandler.h ================================================ // // UMSocialTwitterHandler.h // SocialSDK // // Created by yeahugo on 14-1-13. // Copyright (c) 2014年 Umeng. All rights reserved. // #import @interface UMSocialTwitterHandler : NSObject /** 使用友盟提供的方法来分享到twitter */ +(void)openTwitter; /** 设置twitter应用key、secret */ +(void)setTwitterAppKey:(NSString *)appKey withSecret:(NSString *)secret; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Wechat/UMSocialWechatHandler.h ================================================ // // ; // SocialSDK // // Created by yeahugo on 13-8-6. // Copyright (c) 2013年 Umeng. All rights reserved. // #import @interface UMSocialWechatHandler : NSObject /** 设置微信AppId和url地址 @param app_Id 微信应用Id @param url 微信消息url地址 */ + (void)setWXAppId:(NSString *)app_Id appSecret:(NSString *)appSecret url:(NSString *)url; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Wechat/WXApi.h ================================================ // // WXApi.h // 所有Api接口 // // Created by Wechat on 12-2-28. // Copyright (c) 2012年 Tencent. All rights reserved. // #import #import "WXApiObject.h" #pragma mark - WXApiDelegate /*! @brief 接收并处理来自微信终端程序的事件消息 * * 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。 * WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。 */ @protocol WXApiDelegate @optional /*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果 * * 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。 * 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。 * @param req 具体请求内容,是自动释放的 */ -(void) onReq:(BaseReq*)req; /*! @brief 发送一个sendReq后,收到微信的回应 * * 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。 * 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。 * @param resp具体的回应内容,是自动释放的 */ -(void) onResp:(BaseResp*)resp; @end #pragma mark - WXApi /*! @brief 微信Api接口函数类 * * 该类封装了微信终端SDK的所有接口 */ @interface WXApi : NSObject /*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。 * * 需要在每次启动第三方应用程序时调用。第一次调用后,会在微信的可用应用列表中出现。 * iOS7及以上系统需要调起一次微信才会出现在微信的可用应用列表中。 * @attention 请保证在主线程中调用此函数 * @param appid 微信开发者ID * @return 成功返回YES,失败返回NO。 */ +(BOOL) registerApp:(NSString *)appid; /*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。 * * 需要在每次启动第三方应用程序时调用。第一次调用后,会在微信的可用应用列表中出现。 * @see registerApp * @param appid 微信开发者ID * @param appdesc 应用附加信息,长度不超过1024字节 * @return 成功返回YES,失败返回NO。 */ +(BOOL) registerApp:(NSString *)appid withDescription:(NSString *)appdesc; /*! @brief 处理微信通过URL启动App时传递的数据 * * 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。 * @param url 微信启动第三方应用时传递过来的URL * @param delegate WXApiDelegate对象,用来接收微信触发的消息。 * @return 成功返回YES,失败返回NO。 */ +(BOOL) handleOpenURL:(NSURL *) url delegate:(id) delegate; /*! @brief 检查微信是否已被用户安装 * * @return 微信已安装返回YES,未安装返回NO。 */ +(BOOL) isWXAppInstalled; /*! @brief 判断当前微信的版本是否支持OpenApi * * @return 支持返回YES,不支持返回NO。 */ +(BOOL) isWXAppSupportApi; /*! @brief 获取微信的itunes安装地址 * * @return 微信的安装地址字符串。 */ +(NSString *) getWXAppInstallUrl; /*! @brief 获取当前微信SDK的版本号 * * @return 返回当前微信SDK的版本号 */ +(NSString *) getApiVersion; /*! @brief 打开微信 * * @return 成功返回YES,失败返回NO。 */ +(BOOL) openWXApp; /*! @brief 发送请求到微信,等待微信返回onResp * * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型 * SendAuthReq、SendMessageToWXReq、PayReq等。 * @param req 具体的发送请求,在调用函数后,请自己释放。 * @return 成功返回YES,失败返回NO。 */ +(BOOL) sendReq:(BaseReq*)req; /*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp * * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。 * @param req 具体的发送请求,在调用函数后,请自己释放。 * @param viewController 当前界面对象。 * @param delegate WXApiDelegate对象,用来接收微信触发的消息。 * @return 成功返回YES,失败返回NO。 */ +(BOOL) sendAuthReq:(SendAuthReq*) req viewController : (UIViewController*) viewController delegate:(id) delegate; /*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面 * * 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有 * GetMessageFromWXResp、ShowMessageFromWXResp等。 * @param resp 具体的应答内容,调用函数后,请自己释放 * @return 成功返回YES,失败返回NO。 */ +(BOOL) sendResp:(BaseResp*)resp; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Wechat/WXApiObject.h ================================================ // // MMApiObject.h // Api对象,包含所有接口和对象数据定义 // // Created by Wechat on 12-2-28. // Copyright (c) 2012年 Tencent. All rights reserved. // #import #import /*! @brief 错误码 * */ enum WXErrCode { WXSuccess = 0, /**< 成功 */ WXErrCodeCommon = -1, /**< 普通错误类型 */ WXErrCodeUserCancel = -2, /**< 用户点击取消并返回 */ WXErrCodeSentFail = -3, /**< 发送失败 */ WXErrCodeAuthDeny = -4, /**< 授权失败 */ WXErrCodeUnsupport = -5, /**< 微信不支持 */ }; /*! @brief 请求发送场景 * */ enum WXScene { WXSceneSession = 0, /**< 聊天界面 */ WXSceneTimeline = 1, /**< 朋友圈 */ WXSceneFavorite = 2, /**< 收藏 */ }; enum WXAPISupport { WXAPISupportSession = 0, }; /*! @brief 跳转profile类型 * */ enum WXBizProfileType{ WXBizProfileType_Normal = 0, //**< 普通公众号 */ WXBizProfileType_Device = 1, //**< 硬件公众号 */ }; /*! @brief 跳转mp网页类型 * */ enum WXMPWebviewType { WXMPWebviewType_Ad = 0, /**< 广告网页 **/ }; #pragma mark - BaseReq /*! @brief 该类为微信终端SDK所有请求类的基类 * */ @interface BaseReq : NSObject /** 请求类型 */ @property (nonatomic, assign) int type; /** 由用户微信号和AppID组成的唯一标识,发送请求时第三方程序必须填写,用于校验微信用户是否换号登录*/ @property (nonatomic, retain) NSString* openID; @end #pragma mark - BaseResp /*! @brief 该类为微信终端SDK所有响应类的基类 * */ @interface BaseResp : NSObject /** 错误码 */ @property (nonatomic, assign) int errCode; /** 错误提示字符串 */ @property (nonatomic, retain) NSString *errStr; /** 响应类型 */ @property (nonatomic, assign) int type; @end #pragma mark - WXMediaMessage @class WXMediaMessage; /*! @brief 第三方向微信终端发起支付的消息结构体 * * 第三方向微信终端发起支付的消息结构体,微信终端处理后会向第三方返回处理结果 * @see PayResp */ @interface PayReq : BaseReq /** 商家向财付通申请的商家id */ @property (nonatomic, retain) NSString *partnerId; /** 预支付订单 */ @property (nonatomic, retain) NSString *prepayId; /** 随机串,防重发 */ @property (nonatomic, retain) NSString *nonceStr; /** 时间戳,防重发 */ @property (nonatomic, assign) UInt32 timeStamp; /** 商家根据财付通文档填写的数据和签名 */ @property (nonatomic, retain) NSString *package; /** 商家根据微信开放平台文档对数据做的签名 */ @property (nonatomic, retain) NSString *sign; @end #pragma mark - PayResp /*! @brief 微信终端返回给第三方的关于支付结果的结构体 * * 微信终端返回给第三方的关于支付结果的结构体 */ @interface PayResp : BaseResp /** 财付通返回给商家的信息 */ @property (nonatomic, retain) NSString *returnKey; @end #pragma mark - SendAuthReq /*! @brief 第三方程序向微信终端请求认证的消息结构 * * 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数, * 向微信终端发送一个SendAuthReq消息结构。微信终端处理完后会向第三方程序发送一个处理结果。 * @see SendAuthResp */ @interface SendAuthReq : BaseReq /** 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,向微信终端发送一个SendAuthReq消息结构。微信终端处理完后会向第三方程序发送一个处理结果。 * @see SendAuthResp * @note scope字符串长度不能超过1K */ @property (nonatomic, retain) NSString* scope; /** 第三方程序本身用来标识其请求的唯一性,最后跳转回第三方程序时,由微信终端回传。 * @note state字符串长度不能超过1K */ @property (nonatomic, retain) NSString* state; @end #pragma mark - SendAuthResp /*! @brief 微信处理完第三方程序的认证和权限申请后向第三方程序回送的处理结果。 * * 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,向微信终端发送一个SendAuthReq消息结构。 * 微信终端处理完后会向第三方程序发送一个SendAuthResp。 * @see onResp */ @interface SendAuthResp : BaseResp @property (nonatomic, retain) NSString* code; /** 第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传 * @note state字符串长度不能超过1K */ @property (nonatomic, retain) NSString* state; @property (nonatomic, retain) NSString* lang; @property (nonatomic, retain) NSString* country; @end #pragma mark - SendMessageToWXReq /*! @brief 第三方程序发送消息至微信终端程序的消息结构体 * * 第三方程序向微信发送信息需要传入SendMessageToWXReq结构体,信息类型包括文本消息和多媒体消息, * 分别对应于text和message成员。调用该方法后,微信处理完信息会向第三方程序发送一个处理结果。 * @see SendMessageToWXResp */ @interface SendMessageToWXReq : BaseReq /** 发送消息的文本内容 * @note 文本长度必须大于0且小于10K */ @property (nonatomic, retain) NSString* text; /** 发送消息的多媒体内容 * @see WXMediaMessage */ @property (nonatomic, retain) WXMediaMessage* message; /** 发送消息的类型,包括文本消息和多媒体消息两种,两者只能选择其一,不能同时发送文本和多媒体消息 */ @property (nonatomic, assign) BOOL bText; /** 发送的目标场景,可以选择发送到会话(WXSceneSession)或者朋友圈(WXSceneTimeline)。 默认发送到会话。 * @see WXScene */ @property (nonatomic, assign) int scene; @end #pragma mark - SendMessageToWXResp /*! @brief 微信终端向第三方程序返回的SendMessageToWXReq处理结果。 * * 第三方程序向微信终端发送SendMessageToWXReq后,微信发送回来的处理结果,该结果用SendMessageToWXResp表示。 */ @interface SendMessageToWXResp : BaseResp @property(nonatomic, retain) NSString* lang; @property(nonatomic, retain) NSString* country; @end #pragma mark - GetMessageFromWXReq /*! @brief 微信终端向第三方程序请求提供内容的消息结构体。 * * 微信终端向第三方程序请求提供内容,微信终端会向第三方程序发送GetMessageFromWXReq消息结构体, * 需要第三方程序调用sendResp返回一个GetMessageFromWXResp消息结构体。 */ @interface GetMessageFromWXReq : BaseReq @property (nonatomic, retain) NSString* lang; @property (nonatomic, retain) NSString* country; @end #pragma mark - GetMessageFromWXResp /*! @brief 微信终端向第三方程序请求提供内容,第三方程序向微信终端返回的消息结构体。 * * 微信终端向第三方程序请求提供内容,第三方程序调用sendResp向微信终端返回一个GetMessageFromWXResp消息结构体。 */ @interface GetMessageFromWXResp : BaseResp /** 向微信终端提供的文本内容 @note 文本长度必须大于0且小于10K */ @property (nonatomic, retain) NSString* text; /** 向微信终端提供的多媒体内容。 * @see WXMediaMessage */ @property (nonatomic, retain) WXMediaMessage* message; /** 向微信终端提供内容的消息类型,包括文本消息和多媒体消息两种,两者只能选择其一,不能同时发送文本和多媒体消息 */ @property (nonatomic, assign) BOOL bText; @end #pragma mark - ShowMessageFromWXReq /*! @brief 微信通知第三方程序,要求第三方程序显示的消息结构体。 * * 微信需要通知第三方程序显示或处理某些内容时,会向第三方程序发送ShowMessageFromWXReq消息结构体。 * 第三方程序处理完内容后调用sendResp向微信终端发送ShowMessageFromWXResp。 */ @interface ShowMessageFromWXReq : BaseReq /** 微信终端向第三方程序发送的要求第三方程序处理的多媒体内容 * @see WXMediaMessage */ @property (nonatomic, retain) WXMediaMessage* message; @property (nonatomic, retain) NSString* lang; @property (nonatomic, retain) NSString* country; @end #pragma mark - ShowMessageFromWXResp /*! @brief 微信通知第三方程序,要求第三方程序显示或处理某些消息,第三方程序处理完后向微信终端发送的处理结果。 * * 微信需要通知第三方程序显示或处理某些内容时,会向第三方程序发送ShowMessageFromWXReq消息结构体。 * 第三方程序处理完内容后调用sendResp向微信终端发送ShowMessageFromWXResp。 */ @interface ShowMessageFromWXResp : BaseResp @end #pragma mark - LaunchFromWXReq /*! @brief 微信终端打开第三方程序携带的消息结构体 * * 微信向第三方发送的结构体,第三方不需要返回 */ @interface LaunchFromWXReq : BaseReq @property (nonatomic, retain) WXMediaMessage* message; @property (nonatomic, retain) NSString* lang; @property (nonatomic, retain) NSString* country; @end #pragma mark - OpenTempSessionReq /* ! @brief 第三方通知微信,打开临时会话 * * 第三方通知微信,打开临时会话 */ @interface OpenTempSessionReq : BaseReq /** 需要打开的用户名 * @attention 长度不能超过512字节 */ @property (nonatomic, retain) NSString* username; /** 开发者自定义参数,拉起临时会话后会发给开发者后台,可以用于识别场景 * @attention 长度不能超过32位 */ @property (nonatomic, retain) NSString* sessionFrom; @end #pragma mark - OpenTempSessionResp /*! @brief 微信终端向第三方程序返回的OpenTempSessionReq处理结果。 * * 第三方程序向微信终端发送OpenTempSessionReq后,微信发送回来的处理结果,该结果用OpenTempSessionResp表示。 */ @interface OpenTempSessionResp : BaseResp @end #pragma mark - OpenWebviewReq /* ! @brief 第三方通知微信启动内部浏览器,打开指定网页 * * 第三方通知微信启动内部浏览器,打开指定Url对应的网页 */ @interface OpenWebviewReq : BaseReq /** 需要打开的网页对应的Url * @attention 长度不能超过1024 */ @property(nonatomic,retain)NSString* url; @end #pragma mark - OpenWebviewResp /*! @brief 微信终端向第三方程序返回的OpenWebviewReq处理结果 * * 第三方程序向微信终端发送OpenWebviewReq后,微信发送回来的处理结果,该结果用OpenWebviewResp表示 */ @interface OpenWebviewResp : BaseResp @end #pragma mark - OpenRankListReq /* ! @brief 第三方通知微信,打开硬件排行榜 * * 第三方通知微信,打开硬件排行榜 */ @interface OpenRankListReq : BaseReq @end #pragma mark - OpenRanklistResp /*! @brief 微信终端向第三方程序返回的OpenRankListReq处理结果。 * * 第三方程序向微信终端发送OpenRankListReq后,微信发送回来的处理结果,该结果用OpenRankListResp表示。 */ @interface OpenRankListResp : BaseResp @end #pragma mark - JumpToBizProfileReq /* ! @brief 第三方通知微信,打开指定微信号profile页面 * * 第三方通知微信,打开指定微信号profile页面 */ @interface JumpToBizProfileReq : BaseReq /** 跳转到该公众号的profile * @attention 长度不能超过512字节 */ @property (nonatomic, retain) NSString* username; /** 如果用户加了该公众号为好友,extMsg会上传到服务器 * @attention 长度不能超过1024字节 */ @property (nonatomic, retain) NSString* extMsg; /** * 跳转的公众号类型 * @see WXBizProfileType */ @property (nonatomic, assign) int profileType; @end #pragma mark - JumpToBizWebviewReq /* ! @brief 第三方通知微信,打开指定usrname的profile网页版 * */ @interface JumpToBizWebviewReq : BaseReq /** 跳转的网页类型,目前只支持广告页 * @see WXMPWebviewType */ @property(nonatomic, assign) int webType; /** 跳转到该公众号的profile网页版 * @attention 长度不能超过512字节 */ @property(nonatomic, retain) NSString* tousrname; /** 如果用户加了该公众号为好友,extMsg会上传到服务器 * @attention 长度不能超过1024字节 */ @property(nonatomic, retain) NSString* extMsg; @end #pragma mark - WXCardItem @interface WXCardItem : NSObject /** 卡id * @attention 长度不能超过1024字节 */ @property (nonatomic,retain) NSString* cardId; /** ext信息 * @attention 长度不能超过2024字节 * 具体见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94.9F.E6.88.90.E7.AE.97.E6.B3.95 卡券扩展字段cardExt说明 */ @property (nonatomic,retain) NSString* extMsg; /** * @attention 卡的状态,req不需要填。resp:0为未添加,1为已添加。 */ @property (nonatomic,assign) UInt32 cardState; @end; #pragma mark - AddCardToWXCardPackageReq /* ! @brief 请求添加卡券至微信卡包 * */ @interface AddCardToWXCardPackageReq : BaseReq /** 卡列表 * @attention 个数不能超过40个 类型WXCardItem */ @property (nonatomic,retain) NSArray* cardAry; @end #pragma mark - AddCardToWXCardPackageResp /** ! @brief 微信返回第三方添加卡券结果 * */ @interface AddCardToWXCardPackageResp : BaseResp /** 卡列表 * @attention 个数不能超过40个 类型WXCardItem */ @property (nonatomic,retain) NSArray* cardAry; @end #pragma mark - WXMediaMessage /*! @brief 多媒体消息结构体 * * 用于微信终端和第三方程序之间传递消息的多媒体消息内容 */ @interface WXMediaMessage : NSObject +(WXMediaMessage *) message; /** 标题 * @note 长度不能超过512字节 */ @property (nonatomic, retain) NSString *title; /** 描述内容 * @note 长度不能超过1K */ @property (nonatomic, retain) NSString *description; /** 缩略图数据 * @note 大小不能超过32K */ @property (nonatomic, retain) NSData *thumbData; /** * @note 长度不能超过64字节 */ @property (nonatomic, retain) NSString *mediaTagName; /** * */ @property (nonatomic, retain) NSString *messageExt; @property (nonatomic, retain) NSString *messageAction; /** * 多媒体数据对象,可以为WXImageObject,WXMusicObject,WXVideoObject,WXWebpageObject等。 */ @property (nonatomic, retain) id mediaObject; /*! @brief 设置消息缩略图的方法 * * @param image 缩略图 * @note 大小不能超过32K */ - (void) setThumbImage:(UIImage *)image; @end #pragma mark - WXImageObject /*! @brief 多媒体消息中包含的图片数据对象 * * 微信终端和第三方程序之间传递消息中包含的图片数据对象。 * @note imageData和imageUrl成员不能同时为空 * @see WXMediaMessage */ @interface WXImageObject : NSObject /*! @brief 返回一个WXImageObject对象 * * @note 返回的WXImageObject对象是自动释放的 */ +(WXImageObject *) object; /** 图片真实数据内容 * @note 大小不能超过10M */ @property (nonatomic, retain) NSData *imageData; /** 图片url * @note 长度不能超过10K */ @property (nonatomic, retain) NSString *imageUrl; @end #pragma mark - WXMusicObject /*! @brief 多媒体消息中包含的音乐数据对象 * * 微信终端和第三方程序之间传递消息中包含的音乐数据对象。 * @note musicUrl和musicLowBandUrl成员不能同时为空。 * @see WXMediaMessage */ @interface WXMusicObject : NSObject /*! @brief 返回一个WXMusicObject对象 * * @note 返回的WXMusicObject对象是自动释放的 */ +(WXMusicObject *) object; /** 音乐网页的url地址 * @note 长度不能超过10K */ @property (nonatomic, retain) NSString *musicUrl; /** 音乐lowband网页的url地址 * @note 长度不能超过10K */ @property (nonatomic, retain) NSString *musicLowBandUrl; /** 音乐数据url地址 * @note 长度不能超过10K */ @property (nonatomic, retain) NSString *musicDataUrl; /**音乐lowband数据url地址 * @note 长度不能超过10K */ @property (nonatomic, retain) NSString *musicLowBandDataUrl; @end #pragma mark - WXVideoObject /*! @brief 多媒体消息中包含的视频数据对象 * * 微信终端和第三方程序之间传递消息中包含的视频数据对象。 * @note videoUrl和videoLowBandUrl不能同时为空。 * @see WXMediaMessage */ @interface WXVideoObject : NSObject /*! @brief 返回一个WXVideoObject对象 * * @note 返回的WXVideoObject对象是自动释放的 */ +(WXVideoObject *) object; /** 视频网页的url地址 * @note 长度不能超过10K */ @property (nonatomic, retain) NSString *videoUrl; /** 视频lowband网页的url地址 * @note 长度不能超过10K */ @property (nonatomic, retain) NSString *videoLowBandUrl; @end #pragma mark - WXWebpageObject /*! @brief 多媒体消息中包含的网页数据对象 * * 微信终端和第三方程序之间传递消息中包含的网页数据对象。 * @see WXMediaMessage */ @interface WXWebpageObject : NSObject /*! @brief 返回一个WXWebpageObject对象 * * @note 返回的WXWebpageObject对象是自动释放的 */ +(WXWebpageObject *) object; /** 网页的url地址 * @note 不能为空且长度不能超过10K */ @property (nonatomic, retain) NSString *webpageUrl; @end #pragma mark - WXAppExtendObject /*! @brief 多媒体消息中包含的App扩展数据对象 * * 第三方程序向微信终端发送包含WXAppExtendObject的多媒体消息, * 微信需要处理该消息时,会调用该第三方程序来处理多媒体消息内容。 * @note url,extInfo和fileData不能同时为空 * @see WXMediaMessage */ @interface WXAppExtendObject : NSObject /*! @brief 返回一个WXAppExtendObject对象 * * @note 返回的WXAppExtendObject对象是自动释放的 */ +(WXAppExtendObject *) object; /** 若第三方程序不存在,微信终端会打开该url所指的App下载地址 * @note 长度不能超过10K */ @property (nonatomic, retain) NSString *url; /** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理 * @note 长度不能超过2K */ @property (nonatomic, retain) NSString *extInfo; /** App文件数据,该数据发送给微信好友,微信好友需要点击后下载数据,微信终端会回传给第三方程序处理 * @note 大小不能超过10M */ @property (nonatomic, retain) NSData *fileData; @end #pragma mark - WXEmoticonObject /*! @brief 多媒体消息中包含的表情数据对象 * * 微信终端和第三方程序之间传递消息中包含的表情数据对象。 * @see WXMediaMessage */ @interface WXEmoticonObject : NSObject /*! @brief 返回一个WXEmoticonObject对象 * * @note 返回的WXEmoticonObject对象是自动释放的 */ +(WXEmoticonObject *) object; /** 表情真实数据内容 * @note 大小不能超过10M */ @property (nonatomic, retain) NSData *emoticonData; @end #pragma mark - WXFileObject /*! @brief 多媒体消息中包含的文件数据对象 * * @see WXMediaMessage */ @interface WXFileObject : NSObject /*! @brief 返回一个WXFileObject对象 * * @note 返回的WXFileObject对象是自动释放的 */ +(WXFileObject *) object; /** 文件后缀名 * @note 长度不超过64字节 */ @property (nonatomic, retain) NSString *fileExtension; /** 文件真实数据内容 * @note 大小不能超过10M */ @property (nonatomic, retain) NSData *fileData; @end ================================================ FILE: Pods/UMengSocial/Umeng_SDK_Social_iOS_ARM64_4.4/UMSocial_Sdk_Extra_Frameworks/Whatsapp/UMSocialWhatsappHandler.h ================================================ // // UMSocialWhatsappHandler.h // SocialSDK // // Created by Gavin Ye on 8/21/14. // Copyright (c) 2014 Umeng. All rights reserved. // #import typedef enum { UMSocialWhatsappMessageTypeText, UMSocialWhatsappMessageTypeImage, }UMSocialWhatsappMessageType; @interface UMSocialWhatsappHandler : NSObject +(void)openWhatsapp:(UMSocialWhatsappMessageType)messageType; @end ================================================ FILE: README.md ================================================ # XFBaiSiBuDeJie #### 高仿百思不得姐客户端 初次学习使用RAC,还不是怎么熟悉,使用的仍是MVC模式,MVVM还在摸索中... 如果大家觉得还不错,请给颗星星支持下~~~ ## 程序中使用到的库 * `AFNetworking` * `SDWebImage` * `SVProgressHUD` * `MJExtension` * `ReactiveCocoa` * `MJRefresh` * `DACircularProgress` * `NJKWebViewProgress` * `KRVideoPlayerController` ## 完成的功能: * 帖子的显示,包括,声音,视频,段子,图片 * 支持视频、音频的播放 * 登录页面的动画显示 * 帖子的评论显示 * 图片的放大显示 * 网页加载显示 - ![](http://7xoijj.com1.z0.glb.clouddn.com/baisi!!!.gif) ![](http://7xoijj.com1.z0.glb.clouddn.com/baisi%2001.png) ![](http://7xoijj.com1.z0.glb.clouddn.com/baisi%2002.png) ![](http://7xoijj.com1.z0.glb.clouddn.com/baisi%2003.png) ![](http://7xoijj.com1.z0.glb.clouddn.com/baidi%2004.png) ![](http://7xoijj.com1.z0.glb.clouddn.com/baisi%2005.png) ![](http://7xoijj.com1.z0.glb.clouddn.com/baisi%2006.png) ### 程序的还在完善中...如果有什么错误的地方欢迎大家指正,学习交流请Email: ================================================ FILE: Web/Web/AppDelegate.h ================================================ // // AppDelegate.h // Web // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: Web/Web/AppDelegate.m ================================================ // // AppDelegate.m // Web // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // 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. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // 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. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // 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. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ================================================ FILE: Web/Web/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Web/Web/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: Web/Web/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Web/Web/Info.plist ================================================ NSAppTransportSecurity NSAllowsArbitraryLoads CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Web/Web/ViewController.h ================================================ // // ViewController.h // Web // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface ViewController : UIViewController @end ================================================ FILE: Web/Web/ViewController.m ================================================ // // ViewController.m // Web // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. UIWebView *web = [[UIWebView alloc]init]; web.delegate = self; web.frame = self.view.bounds; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://club.eebbk.com/bbkbbs/showtopic/465102/1"]]; [web loadRequest:request]; [self.view addSubview:web]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)webViewDidFinishLoad:(UIWebView *)webView { NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML;"]; if ([html containsString:@"http://club.eebbk.com/bbkbbs/showtopic/"]) { for (int i = 0; i<1000000; i++) { NSMutableArray *arr = [NSMutableArray array]; arr addObject:<#(nonnull id)#> } } NSLog(@"%@",html); } @end ================================================ FILE: Web/Web/main.m ================================================ // // main.m // Web // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: Web/Web.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 65E643951C78423E009E9B6C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 65E643941C78423E009E9B6C /* main.m */; }; 65E643981C78423E009E9B6C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 65E643971C78423E009E9B6C /* AppDelegate.m */; }; 65E6439B1C78423E009E9B6C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65E6439A1C78423E009E9B6C /* ViewController.m */; }; 65E6439E1C78423E009E9B6C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 65E6439C1C78423E009E9B6C /* Main.storyboard */; }; 65E643A01C78423E009E9B6C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 65E6439F1C78423E009E9B6C /* Assets.xcassets */; }; 65E643A31C78423E009E9B6C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 65E643A11C78423E009E9B6C /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 65E643901C78423E009E9B6C /* Web.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Web.app; sourceTree = BUILT_PRODUCTS_DIR; }; 65E643941C78423E009E9B6C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 65E643961C78423E009E9B6C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 65E643971C78423E009E9B6C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 65E643991C78423E009E9B6C /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 65E6439A1C78423E009E9B6C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 65E6439D1C78423E009E9B6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 65E6439F1C78423E009E9B6C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 65E643A21C78423E009E9B6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 65E643A41C78423E009E9B6C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 65E6438D1C78423E009E9B6C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 65E643871C78423E009E9B6C = { isa = PBXGroup; children = ( 65E643921C78423E009E9B6C /* Web */, 65E643911C78423E009E9B6C /* Products */, ); sourceTree = ""; }; 65E643911C78423E009E9B6C /* Products */ = { isa = PBXGroup; children = ( 65E643901C78423E009E9B6C /* Web.app */, ); name = Products; sourceTree = ""; }; 65E643921C78423E009E9B6C /* Web */ = { isa = PBXGroup; children = ( 65E643961C78423E009E9B6C /* AppDelegate.h */, 65E643971C78423E009E9B6C /* AppDelegate.m */, 65E643991C78423E009E9B6C /* ViewController.h */, 65E6439A1C78423E009E9B6C /* ViewController.m */, 65E6439C1C78423E009E9B6C /* Main.storyboard */, 65E6439F1C78423E009E9B6C /* Assets.xcassets */, 65E643A11C78423E009E9B6C /* LaunchScreen.storyboard */, 65E643A41C78423E009E9B6C /* Info.plist */, 65E643931C78423E009E9B6C /* Supporting Files */, ); path = Web; sourceTree = ""; }; 65E643931C78423E009E9B6C /* Supporting Files */ = { isa = PBXGroup; children = ( 65E643941C78423E009E9B6C /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 65E6438F1C78423E009E9B6C /* Web */ = { isa = PBXNativeTarget; buildConfigurationList = 65E643A71C78423E009E9B6C /* Build configuration list for PBXNativeTarget "Web" */; buildPhases = ( 65E6438C1C78423E009E9B6C /* Sources */, 65E6438D1C78423E009E9B6C /* Frameworks */, 65E6438E1C78423E009E9B6C /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Web; productName = Web; productReference = 65E643901C78423E009E9B6C /* Web.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 65E643881C78423E009E9B6C /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0720; ORGANIZATIONNAME = "谢飞"; TargetAttributes = { 65E6438F1C78423E009E9B6C = { CreatedOnToolsVersion = 7.2; DevelopmentTeam = NRZG3Z79NX; }; }; }; buildConfigurationList = 65E6438B1C78423E009E9B6C /* Build configuration list for PBXProject "Web" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 65E643871C78423E009E9B6C; productRefGroup = 65E643911C78423E009E9B6C /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 65E6438F1C78423E009E9B6C /* Web */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 65E6438E1C78423E009E9B6C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 65E643A31C78423E009E9B6C /* LaunchScreen.storyboard in Resources */, 65E643A01C78423E009E9B6C /* Assets.xcassets in Resources */, 65E6439E1C78423E009E9B6C /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 65E6438C1C78423E009E9B6C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 65E6439B1C78423E009E9B6C /* ViewController.m in Sources */, 65E643981C78423E009E9B6C /* AppDelegate.m in Sources */, 65E643951C78423E009E9B6C /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 65E6439C1C78423E009E9B6C /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 65E6439D1C78423E009E9B6C /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 65E643A11C78423E009E9B6C /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 65E643A21C78423E009E9B6C /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 65E643A51C78423E009E9B6C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.2; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 65E643A61C78423E009E9B6C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; 65E643A81C78423E009E9B6C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Web/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.alloc.Web; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 65E643A91C78423E009E9B6C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Web/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.alloc.Web; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 65E6438B1C78423E009E9B6C /* Build configuration list for PBXProject "Web" */ = { isa = XCConfigurationList; buildConfigurations = ( 65E643A51C78423E009E9B6C /* Debug */, 65E643A61C78423E009E9B6C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 65E643A71C78423E009E9B6C /* Build configuration list for PBXNativeTarget "Web" */ = { isa = XCConfigurationList; buildConfigurations = ( 65E643A81C78423E009E9B6C /* Debug */, 65E643A91C78423E009E9B6C /* Release */, ); defaultConfigurationIsVisible = 0; }; /* End XCConfigurationList section */ }; rootObject = 65E643881C78423E009E9B6C /* Project object */; } ================================================ FILE: Web/Web.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Web/Web.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/Web.xcscheme ================================================ ================================================ FILE: Web/Web.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState Web.xcscheme orderHint 0 SuppressBuildableAutocreation 65E6438F1C78423E009E9B6C primary ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "1x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "AppIcon29x29@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "AppIcon29x29@3x.png", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "AppIcon40x40@3x.png", "scale" : "3x" }, { "size" : "57x57", "idiom" : "iphone", "filename" : "AppIcon57x57.png", "scale" : "1x" }, { "size" : "57x57", "idiom" : "iphone", "filename" : "AppIcon57x57@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "AppIcon60x60@2x-1.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "AppIcon60x60@3x-1.png", "scale" : "3x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "AppIcon29x29.png", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "AppIcon40x40~ipad.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "AppIcon40x40@2x.png", "scale" : "2x" }, { "size" : "50x50", "idiom" : "ipad", "filename" : "AppIcon50x50~ipad.png", "scale" : "1x" }, { "size" : "50x50", "idiom" : "ipad", "filename" : "AppIcon50x50@2x~ipad.png", "scale" : "2x" }, { "idiom" : "ipad", "size" : "72x72", "scale" : "1x" }, { "size" : "72x72", "idiom" : "ipad", "filename" : "AppIcon72x72@2x~ipad.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "AppIcon76x76~ipad.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "AppIcon76x76@2x~ipad.png", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" }, { "size" : "60x60", "idiom" : "car", "filename" : "AppIcon60x60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "car", "filename" : "AppIcon60x60@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Brand Assets.launchimage/Contents.json ================================================ { "images" : [ { "extent" : "full-screen", "idiom" : "iphone", "subtype" : "736h", "filename" : "LaunchImage-800-Portrait-736h@3x.png", "minimum-system-version" : "8.0", "orientation" : "portrait", "scale" : "3x" }, { "extent" : "full-screen", "idiom" : "iphone", "subtype" : "667h", "filename" : "LaunchImage-800-667h@2x.png", "minimum-system-version" : "8.0", "orientation" : "portrait", "scale" : "2x" }, { "orientation" : "portrait", "idiom" : "iphone", "extent" : "full-screen", "minimum-system-version" : "7.0", "scale" : "2x" }, { "extent" : "full-screen", "idiom" : "iphone", "subtype" : "retina4", "filename" : "LaunchImage-568h@2x.png", "minimum-system-version" : "7.0", "orientation" : "portrait", "scale" : "2x" }, { "orientation" : "portrait", "idiom" : "iphone", "filename" : "LaunchImage.png", "extent" : "full-screen", "scale" : "1x" }, { "orientation" : "portrait", "idiom" : "iphone", "filename" : "LaunchImage-700@2x.png", "extent" : "full-screen", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/Profile_manIcon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "Profile_manIcon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "Profile_manIcon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "Profile_manIcon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/Profile_womanIcon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "Profile_womanIcon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "Profile_womanIcon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "Profile_womanIcon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment-bar-bg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment-bar-bg.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment-bar-bg@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment-bar-keyboard-click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment-bar-keyboard-click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment-bar-keyboard-click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment-bar-keyboard-click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment-bar-keyboard.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment-bar-keyboard.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment-bar-keyboard@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment-bar-keyboard@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment-bar-record-click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment-bar-record-click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment-bar-record-click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment-bar-record-click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment-bar-record.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment-bar-record.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment-bar-record@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment-bar-record@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment-bar-voice-click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment-bar-voice-click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment-bar-voice-click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment-bar-voice-click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment-bar-voice.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment-bar-voice.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment-bar-voice@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment-bar-voice@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/commentLikeButton.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "commentLikeButton.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "commentLikeButton@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/commentLikeButtonClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "commentLikeButtonClick.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "commentLikeButtonClick@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment_bar_at_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment_bar_at_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment_bar_at_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment_bar_at_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment_bar_at_icon_click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment_bar_at_icon_click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment_bar_at_icon_click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment_bar_at_icon_click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment_nav_item_share_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment_nav_item_share_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment_nav_item_share_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment_nav_item_share_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Comment/comment_nav_item_share_icon_click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "comment_nav_item_share_icon_click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "comment_nav_item_share_icon_click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "comment_nav_item_share_icon_click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/Profile_AddV_authen.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "Profile_AddV_authen.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "Profile_AddV_authen@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "Profile_AddV_authen@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/cell-button-line.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "cell-button-line.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "cell-button-line@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/cell-content-line.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "cell-content-line.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "cell-content-line@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/cellFollowClickIcon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "cellFollowClickIcon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "cellFollowClickIcon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "cellFollowClickIcon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/cellFollowDisableIcon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "cellFollowDisableIcon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "cellFollowDisableIcon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "cellFollowDisableIcon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/cellFollowIcon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "cellFollowIcon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "cellFollowIcon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "cellFollowIcon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/cellmorebtnclick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "cellmorebtnclick.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "cellmorebtnclick@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/cellmorebtnnormal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "cellmorebtnnormal.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "cellmorebtnnormal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/common-gif.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "common-gif.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "common-gif@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/defaultUserIcon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "defaultUserIcon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "defaultUserIcon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "defaultUserIcon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/imageBackground.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "imageBackground.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "imageBackground@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "imageBackground@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellBackground.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellBackground.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellBackground@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellCai.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellCai.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellCai@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellCaiClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellCaiClick.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellCaiClick@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellComment.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellComment.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellComment@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellCommentClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellCommentClick.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellCommentClick@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellDing.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellDing.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellDing@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellDingClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellDingClick.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellDingClick@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellShare.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellShare.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellShare@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/mainCellShareClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mainCellShareClick.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mainCellShareClick@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/playButton.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "playButton.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "playButton@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "playButton@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/playButtonClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "playButtonClick.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "playButtonClick@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "playButtonClick@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/playButtonPause.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "playButtonPause.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "playButtonPause@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "playButtonPause@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/playButtonPlay.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "playButtonPlay.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "playButtonPlay@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "playButtonPlay@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/post_placeholderImage.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "post_placeholderImage.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "post_placeholderImage@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "post_placeholderImage@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/see-big-picture-background.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "see-big-picture-background.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "see-big-picture-background@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/see-big-picture.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "see-big-picture.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "see-big-picture@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "see-big-picture@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/show_image_back_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "show_image_back_icon.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "show_image_back_icon@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "show_image_back_icon@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/tagicon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tagicon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tagicon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tagicon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Essence/video-play.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "video-play.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "video-play@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "video-play@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/FriendTrends/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/FriendTrends/FollowBtnBg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "FollowBtnBg.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "FollowBtnBg@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/FriendTrends/FollowBtnClickBg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "FollowBtnClickBg.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "FollowBtnClickBg@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/FriendTrends/friendsTrend_login.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "friendsTrend_login.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "friendsTrend_login@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/FriendTrends/friendsTrend_login_click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "friendsTrend_login_click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "friendsTrend_login_click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/FriendTrends/header_cry_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "header_cry_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "header_cry_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/loginBtnBg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "loginBtnBg.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "loginBtnBg@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/loginBtnBgClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "loginBtnBgClick.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "loginBtnBgClick@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_QQ_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_QQ_icon.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_QQ_icon@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_QQ_icon@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_QQ_icon_click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_QQ_icon_click.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_QQ_icon_click@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_QQ_icon_click@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_close_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_close_icon.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_close_icon@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_close_icon@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_register_background.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_register_background.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_register_background@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_register_background@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_register_button.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_register_button.png" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_register_button_click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_register_button_click.png" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_register_left_line.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_register_left_line.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_register_left_line@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_register_left_line@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_register_right_line.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_register_right_line.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_register_right_line@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_register_right_line@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_rgister_textfield_bg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_rgister_textfield_bg.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_rgister_textfield_bg@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_rgister_textfield_bg@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_sina_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_sina_icon.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_sina_icon@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_sina_icon@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_sina_icon_click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_sina_icon_click.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_sina_icon_click@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_sina_icon_click@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_tecent_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_tecent_icon.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_tecent_icon@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_tecent_icon@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/LoginRegister/login_tecent_icon_click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "login_tecent_icon_click.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "login_tecent_icon_click@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "login_tecent_icon_click@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-icon-activity.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-icon-activity.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-icon-activity@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-icon-feedback.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-icon-feedback.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-icon-feedback@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-icon-manhua.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-icon-manhua.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-icon-manhua@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-icon-more.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-icon-more.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-icon-more@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-icon-nearby.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-icon-nearby.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-icon-nearby@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-icon-preview.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-icon-preview.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-icon-preview@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-icon-recentHot.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-icon-recentHot.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-icon-recentHot@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-icon-search.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-icon-search.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-icon-search@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-my-post.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-my-post.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-my-post@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine-setting-iconN.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine-setting-iconN.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine-setting-iconN@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "mine-setting-iconN@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine_icon_nearby.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine_icon_nearby.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine_icon_nearby@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine_icon_random.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine_icon_random.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine_icon_random@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/mine_msg_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "mine_msg_icon.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "mine_msg_icon@2x.png" }, { "idiom" : "universal", "scale" : "3x", "filename" : "mine_msg_icon@3x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Me/setup-head-default.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "setup-head-default.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "setup-head-default@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/MainTagSubIcon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "MainTagSubIcon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "MainTagSubIcon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "MainTagSubIcon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/MainTagSubIconClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "MainTagSubIconClick.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "MainTagSubIconClick@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "MainTagSubIconClick@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/MainTitle.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "MainTitle.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "MainTitle@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "MainTitle@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/friendsRecommentIcon-click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "friendsRecommentIcon-click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "friendsRecommentIcon-click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "friendsRecommentIcon-click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/friendsRecommentIcon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "friendsRecommentIcon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "friendsRecommentIcon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "friendsRecommentIcon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/mine-moon-icon-click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mine-moon-icon-click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mine-moon-icon-click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/mine-moon-icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mine-moon-icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mine-moon-icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "mine-moon-icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/mine-setting-icon-click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mine-setting-icon-click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mine-setting-icon-click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "mine-setting-icon-click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/mine-setting-icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mine-setting-icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mine-setting-icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "mine-setting-icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/mine-sun-icon-click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mine-sun-icon-click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mine-sun-icon-click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "mine-sun-icon-click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/mine-sun-icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "mine-sun-icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "mine-sun-icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "mine-sun-icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/nav_coin_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "nav_coin_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "nav_coin_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "nav_coin_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/nav_coin_icon_click.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "nav_coin_icon_click.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "nav_coin_icon_click@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "nav_coin_icon_click@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/navigationButtonReturn.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "navigationButtonReturn.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "navigationButtonReturn@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "navigationButtonReturn@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/navigationButtonReturnClick.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "navigationButtonReturnClick.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "navigationButtonReturnClick@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "navigationButtonReturnClick@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Navigation/navigationbarBackgroundWhite.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "navigationbarBackgroundWhite.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play-voice-bg-select.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play-voice-bg-select.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play-voice-bg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play-voice-bg.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "play-voice-bg@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "play-voice-bg@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play-voice-bgN.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play-voice-bgN.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "play-voice-bgN@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play-voice-icon-0.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play-voice-icon-0.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "play-voice-icon-0@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play-voice-icon-1.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play-voice-icon-1.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "play-voice-icon-1@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play-voice-icon-2.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play-voice-icon-2.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "play-voice-icon-2@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play-voice-icon-3.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play-voice-icon-3.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "play-voice-icon-3@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play-voice-stop.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play-voice-stop.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "play-voice-stop@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "play-voice-stop@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Play/play.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "play.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "play@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "play@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Publish/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Publish/app_slogan.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "app_slogan.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "app_slogan@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "app_slogan@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Publish/publish-audio.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "publish-audio.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "publish-audio@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "publish-audio@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Publish/publish-offline.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "publish-offline.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "publish-offline@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "publish-offline@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Publish/publish-picture.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "publish-picture.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "publish-picture@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "publish-picture@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Publish/publish-review.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "publish-review.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "publish-review@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "publish-review@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Publish/publish-text.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "publish-text.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "publish-text@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "publish-text@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Publish/publish-video.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "publish-video.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "publish-video@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "publish-video@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Pushguide/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Pushguide/pushguidebg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "pushguidebg.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Pushguide/pushguidebot.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "pushguidebot.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "pushguidebot@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "pushguidebot@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Pushguide/pushguidemid.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "pushguidemid.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "pushguidemid@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "pushguidemid@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/Pushguide/pushguidetop.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "pushguidetop.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "pushguidetop@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "pushguidetop@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_essence_click_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_essence_click_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_essence_click_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_essence_click_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "original" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_essence_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_essence_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_essence_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_essence_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "original" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_friendTrends_click_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_friendTrends_click_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_friendTrends_click_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_friendTrends_click_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "original" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_friendTrends_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_friendTrends_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_friendTrends_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_friendTrends_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "original" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_me_click_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_me_click_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_me_click_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_me_click_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "original" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_me_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_me_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_me_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_me_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "original" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_new_click_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_new_click_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_new_click_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_new_click_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "original" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_new_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_new_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_new_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_new_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "original" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_publish_click_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_publish_click_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_publish_click_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_publish_click_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabBar_publish_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabBar_publish_icon.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabBar_publish_icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "tabBar_publish_icon@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/TabBar/tabbar-light.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "tabbar-light.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "tabbar-light@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/kr-Icon/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/kr-Icon/kr-video-player-close.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "filename" : "kr-video-player-close@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "kr-video-player-close@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/kr-Icon/kr-video-player-fullscreen.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "filename" : "kr-video-player-fullscreen@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "kr-video-player-fullscreen@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/kr-Icon/kr-video-player-pause.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "filename" : "kr-video-player-pause@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "kr-video-player-pause@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/kr-Icon/kr-video-player-play.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "filename" : "kr-video-player-play@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "kr-video-player-play@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/kr-Icon/kr-video-player-point.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "filename" : "kr-video-player-point@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "kr-video-player-point@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Assets.xcassets/kr-Icon/kr-video-player-shrinkscreen.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "filename" : "kr-video-player-shrinkscreen@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "kr-video-player-shrinkscreen@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: XFBaiSiBuDeJie/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: XFBaiSiBuDeJie/Base.lproj/Main.storyboard ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/AppDelegate/AppDelegate.h ================================================ // // AppDelegate.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/AppDelegate/AppDelegate.m ================================================ // // AppDelegate.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import "AppDelegate.h" #import "XFTabBarViewController.h" #import "XFGuideView.h" #import "SDWebImageManager.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.window = [[UIWindow alloc]init]; self.window.frame = [UIScreen mainScreen].bounds; self.window.rootViewController = [[XFTabBarViewController alloc]init]; [self.window makeKeyAndVisible]; [self showGuiView]; return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // 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. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // 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. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // 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. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } //当收到Received memory warning.会调用次方法 -(void)applicationDidReceiveMemoryWarning:(UIApplication *)application { SDWebImageManager *mgr = [SDWebImageManager sharedManager]; //取消下载 [mgr cancelAll]; //清空缓存 [mgr.imageCache clearMemory]; } //是否显示引导页 -(void)showGuiView { //获得当前版本号 NSString *currentVersion = [NSBundle mainBundle].infoDictionary[@"CFBundleShortVersionString"]; //沙盒版本号 NSString *lastVersion = [[NSUserDefaults standardUserDefaults] stringForKey:@"CFBundleShortVersionString"]; if (![currentVersion isEqualToString:lastVersion]) { XFGuideView *guideView = [XFGuideView guideView]; guideView.frame = self.window.bounds; [self.window addSubview:guideView]; [[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:@"CFBundleShortVersionString"]; //马上写入沙盒 [[NSUserDefaults standardUserDefaults] synchronize]; } } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/NSString+XFTime.h ================================================ // // NSString+XFTime.h // XFBaiSiBuDeJie // // Created by Fay on 16/3/15. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface NSString (XFTime) + (NSString *)stringWithTime:(NSTimeInterval)time; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/NSString+XFTime.m ================================================ // // NSString+XFTime.m // XFBaiSiBuDeJie // // Created by Fay on 16/3/15. // Copyright © 2016年 谢飞. All rights reserved. // #import "NSString+XFTime.h" @implementation NSString (XFTime) + (NSString *)stringWithTime:(NSTimeInterval)time { NSInteger min = time / 60; NSInteger second = (NSInteger)time % 60; return [NSString stringWithFormat:@"%02ld:%02ld", min, second]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/UIImage+XFCircle.h ================================================ // // UIImage+XFCircle.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/3. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface UIImage (XFCircle) - (UIImage *)circleImage; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/UIImage+XFCircle.m ================================================ // // UIImage+XFCircle.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/3. // Copyright © 2016年 谢飞. All rights reserved. // #import "UIImage+XFCircle.h" @implementation UIImage (XFCircle) - (UIImage *)circleImage { // NO透明 UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0); // 获得上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 添加一个圆 CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); CGContextAddEllipseInRect(ctx, rect); // 裁剪 CGContextClip(ctx); // 将图片画上去 [self drawInRect:rect]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //结束上下文 UIGraphicsEndImageContext(); return image; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/UIImageView+Header.h ================================================ // // UIImageView+Header.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/3. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface UIImageView (Header) - (void)setHeader:(NSString *)url; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/UIImageView+Header.m ================================================ // // UIImageView+Header.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/3. // Copyright © 2016年 谢飞. All rights reserved. // #import "UIImageView+Header.h" #import "UIImageView+WebCache.h" @implementation UIImageView (Header) - (void)setHeader:(NSString *)url { UIImage *placeholder = [[UIImage imageNamed:@"defaultUserIcon"] circleImage]; [self sd_setImageWithURL:[NSURL URLWithString:url] placeholderImage:placeholder completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { self.image = image ? [image circleImage] : placeholder; }]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/UIView+Extension.h ================================================ // // UIView+Extension.h // Weibo // // Created by Fay on 15/9/14. // Copyright (c) 2015年 Fay. All rights reserved. // #import @interface UIView (Extension) @property(nonatomic,assign)CGFloat x; @property(nonatomic,assign)CGFloat y; @property(nonatomic,assign)CGFloat centerX; @property(nonatomic,assign)CGFloat centerY; @property(nonatomic,assign)CGFloat width; @property(nonatomic,assign)CGFloat height; @property(nonatomic,assign)CGSize size; @property(nonatomic,assign)CGPoint origin; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/UIView+Extension.m ================================================ // // UIView+Extension.m // Weibo // // Created by Fay on 15/9/14. // Copyright (c) 2015年 Fay. All rights reserved. // #import "UIView+Extension.h" @implementation UIView (Extension) -(void)setX:(CGFloat)x { CGRect frame = self.frame; frame.origin.x = x; self.frame = frame; } -(CGFloat)x { return self.frame.origin.x; } -(void)setY:(CGFloat)y { CGRect frame = self.frame; frame.origin.y = y; self.frame = frame; } -(CGFloat)y { return self.frame.origin.y; } - (void)setCenterX:(CGFloat)centerX { CGPoint center = self.center; center.x = centerX; self.center = center; } - (CGFloat)centerX { return self.center.x; } - (void)setCenterY:(CGFloat)centerY { CGPoint center = self.center; center.y = centerY; self.center = center; } - (CGFloat)centerY { return self.center.y; } -(void)setWidth:(CGFloat)width { CGRect frame = self.frame; frame.size.width = width; self.frame = frame; } -(CGFloat)width { return self.frame.size.width; } - (void)setHeight:(CGFloat)height { CGRect frame = self.frame; frame.size.height = height; self.frame = frame; } - (CGFloat)height { return self.frame.size.height; } - (void)setSize:(CGSize)size { CGRect frame = self.frame; frame.size = size; self.frame = frame; } - (CGSize)size { return self.frame.size; } - (void)setOrigin:(CGPoint)origin { CGRect frame = self.frame; frame.origin = origin; self.frame = frame; } - (CGPoint)origin { return self.frame.origin; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFMeCell.h ================================================ // // XFMeCell.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/3. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFMeCell : UITableViewCell @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFMeCell.m ================================================ // // XFMeCell.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/3. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFMeCell.h" @interface XFMeCell () @end @implementation XFMeCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.textLabel.textColor = [UIColor darkGrayColor]; self.textLabel.font = [UIFont systemFontOfSize:14]; } return self; } -(void)layoutSubviews { [super layoutSubviews]; if (self.imageView.image == nil) return; self.imageView.width = 26; self.imageView.height = 26; self.imageView.centerY = self.contentView.height * 0.5; self.textLabel.x = CGRectGetMaxX(self.imageView.frame) + 10; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFSquare.h ================================================ // // XFSquare.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFSquare : NSObject /** id */ @property (nonatomic, copy) NSString *id; /** 图片 */ @property (nonatomic, copy) NSString *icon; /** 标题文字 */ @property (nonatomic, copy) NSString *name; /** 链接 */ @property (nonatomic, copy) NSString *url; /** cell高度 */ @property (nonatomic, assign) CGFloat cellHeight; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFSquare.m ================================================ // // XFSquare.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFSquare.h" @implementation XFSquare @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFSquareButton.h ================================================ // // XFSquareButton.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFSquare.h" @interface XFSquareButton : UIButton @property (nonatomic,strong) XFSquare *square; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFSquareButton.m ================================================ // // XFSquareButton.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFSquareButton.h" #import "UIButton+WebCache.h" @implementation XFSquareButton -(instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; self.titleLabel.font = [UIFont systemFontOfSize:14]; self.titleLabel.textAlignment = NSTextAlignmentCenter; //[self setBackgroundImage:[UIImage imageNamed:@"mainCellBackground"] forState:UIControlStateNormal]; } return self; } -(void)layoutSubviews { [super layoutSubviews]; // 调整图片 self.imageView.y = self.height * 0.15; self.imageView.width = self.width * 0.5; self.imageView.height = self.imageView.width; self.imageView.centerX = self.width * 0.5; // 调整文字 self.titleLabel.x = 0; self.titleLabel.y = CGRectGetMaxY(self.imageView.frame); self.titleLabel.width = self.width; self.titleLabel.height = self.height - self.titleLabel.y; } -(void)setSquare:(XFSquare *)square { _square = square; [self setTitle:square.name forState:UIControlStateNormal]; [self sd_setImageWithURL:[NSURL URLWithString:square.icon] forState:UIControlStateNormal]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFSquareCell.h ================================================ // // XFSquareCell.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFSquareCell : UITableViewCell @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFSquareCell.m ================================================ // // XFSquareCell.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFSquareCell.h" #import "XFSquareTool.h" #import "XFSquare.h" #import "XFSquareButton.h" @interface XFSquareCell () @property(nonatomic,strong) UIView *horizenTopLine; @property(nonatomic,strong) UIView *horizenBottomLine; @property(nonatomic,strong) XFSquare *square; @end @implementation XFSquareCell -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { [self createItems]; } return self; } //创建items -(void)createItems { //一共4列 NSInteger maxCols = 4; CGFloat btnW = (SCREEN_WIDTH - 3) / 4; CGFloat btnH = btnW; XFSquareTool *tool = [[XFSquareTool alloc]init]; NSLog(@"1"); [tool getSquareData:^(NSArray *squareItems) { for (NSInteger i = 0; i < squareItems.count; i++) { XFSquareButton *button = [[XFSquareButton alloc]init]; button.square = squareItems[i]; NSInteger col = i % maxCols;//第几列 NSInteger row = i / maxCols;//第几行 CGFloat btnX = col * btnW; CGFloat btnY = row * btnH; button.frame = CGRectMake(btnX, btnY, btnW, btnH); [self.contentView addSubview:button]; } //算出cell的高度 self.height = (squareItems.count + maxCols - 1)/maxCols * btnH; [self setNeedsDisplay]; NSLog(@"2"); }]; NSLog(@"3"); } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFSquareTool.h ================================================ // // XFSquareTool.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFSquareTool : NSObject /** * 回去广场方块数据 * * @param block 回调 */ -(void)getSquareData:(void(^)(id json))block; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Category/XFSquareTool.m ================================================ // // XFSquareTool.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFSquareTool.h" #import "HttpTool.h" #import "MJExtension.h" #import "AFNetworking.h" #import "XFSquare.h" @implementation XFSquareTool -(void)getSquareData:(void (^)(id))block { // 参数 NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"a"] = @"square"; params[@"c"] = @"topic"; [HttpTool get:BaseURL parameters:params success:^(id json) { NSArray *squareArray = [XFSquare mj_objectArrayWithKeyValuesArray:json[@"square_list"]]; block(squareArray); } failure:^(NSError *error) { nil; }]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFConcernViewController.h ================================================ // // XFConcernViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFConcernViewController : UIViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFConcernViewController.m ================================================ // // XFConcernViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFConcernViewController.h" #import "XFRecommendViewController.h" #import "XFLoginViewController.h" @interface XFConcernViewController () @property (nonatomic,strong) UIButton *recommandBtn; @end @implementation XFConcernViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.view.backgroundColor = BackgroundColor; [self setupNavBar]; } - (IBAction)loginBtn:(UIButton *)sender { XFLoginViewController *loginVc = [[XFLoginViewController alloc]init]; [self presentViewController:loginVc animated:YES completion:nil]; } - (IBAction)registerBtn:(UIButton *)sender { XFLoginViewController *loginVc = [[XFLoginViewController alloc]init]; [self presentViewController:loginVc animated:YES completion:nil]; } //设置导航条 - (void)setupNavBar { self.navigationItem.title = @"我的关注"; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:self.recommandBtn]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (UIButton *)recommandBtn { if (_recommandBtn == nil) { _recommandBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [_recommandBtn setBackgroundImage:[UIImage imageNamed:@"friendsRecommentIcon"] forState:UIControlStateNormal]; [_recommandBtn setBackgroundImage:[UIImage imageNamed:@"friendsRecommentIcon-click"] forState:UIControlStateHighlighted]; _recommandBtn.size = _recommandBtn.currentBackgroundImage.size; [[_recommandBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { XFRecommendViewController *rcVc = [[XFRecommendViewController alloc]init]; [self.navigationController pushViewController:rcVc animated:YES]; }]; } return _recommandBtn; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFConcernViewController.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFLoginViewController.h ================================================ // // XFLoginViewController.h // // // Created by 谢飞 on 16/2/20. // // #import @interface XFLoginViewController : UIViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFLoginViewController.m ================================================ // // XFLoginViewController.m // // // Created by 谢飞 on 16/2/20. // // #import "XFLoginViewController.h" #import @interface XFLoginViewController () @property (weak, nonatomic) IBOutlet UIButton *closeBtn; @property (weak, nonatomic) IBOutlet UIButton *QQBtn; @property (weak, nonatomic) IBOutlet UIButton *sinaBtn; @property (weak, nonatomic) IBOutlet UIButton *tencentBtn; @property (weak, nonatomic) IBOutlet UIButton *loginBtn; @property (weak, nonatomic) IBOutlet UIButton *forgetBtn; @property (weak, nonatomic) IBOutlet UIView *textView; @property (weak, nonatomic) IBOutlet UILabel *quickBtn; @property (weak, nonatomic) IBOutlet UIButton *registerBtn; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *leftlineWidth; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *rightlineWidth; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *topConstraint; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *textLeft; @end @implementation XFLoginViewController - (void)viewDidLoad { [super viewDidLoad]; self.topConstraint.constant = -250; self.leftlineWidth.constant = 0; self.rightlineWidth.constant = 0; self.forgetBtn.layer.mask = [[CALayer alloc]init]; self.quickBtn.layer.mask = [[CALayer alloc]init]; self.registerBtn.layer.mask = [[CALayer alloc]init]; } //注册按钮 - (IBAction)registerBtn:(UIButton *)sender { if (self.textLeft.constant == 0) { // 显示注册界面 self.textLeft.constant = - self.view.width; sender.selected = YES; } else { // 显示登录界面 self.textLeft.constant = 0; sender.selected = NO; } [UIView animateWithDuration:0.25 animations:^{ [self.view layoutIfNeeded]; }]; } //需要的动画 -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [UIView animateWithDuration:1.0 animations:^{ self.closeBtn.transform = CGAffineTransformMakeRotation(M_PI); }]; self.topConstraint.constant = 40; self.leftlineWidth.constant = 103; self.rightlineWidth.constant = 103; [UIView animateWithDuration:1.0 delay:0.5 usingSpringWithDamping:0.3 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ [self.view layoutIfNeeded]; } completion:^(BOOL finished) { //忘记密码动画 [self setupAnimationWithStartRect:CGRectMake(0, 0, 0, CGRectGetHeight(self.forgetBtn.frame)) endRect:CGRectMake(0, 0, CGRectGetWidth(self.forgetBtn.frame), CGRectGetHeight(self.forgetBtn.frame)) object:self.forgetBtn duration:0.5]; //注册按钮动画 [self setupAnimationWithStartRect:CGRectMake(-(CGRectGetWidth(self.registerBtn.frame)), 0, 0, CGRectGetHeight(self.registerBtn.frame)) endRect:CGRectMake(0, 0, CGRectGetWidth(self.registerBtn.frame), CGRectGetHeight(self.registerBtn.frame)) object:self.registerBtn duration:0.5]; }]; //快速登录动画 [self setupAnimationWithStartRect:CGRectMake(self.quickBtn.width/2, 0, 0, CGRectGetHeight(self.quickBtn.frame)) endRect:CGRectMake(0, 0, CGRectGetWidth(self.quickBtn.frame), CGRectGetHeight(self.quickBtn.frame)) object:self.quickBtn duration:0.5]; [UIView animateWithDuration:0.1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:10 options:UIViewAnimationOptionCurveLinear animations:^{ self.QQBtn.transform = CGAffineTransformMakeScale(0.01, 0.01); self.sinaBtn.transform = CGAffineTransformMakeScale(0.01, 0.01); self.tencentBtn.transform = CGAffineTransformMakeScale(0.01, 0.01); } completion:^(BOOL finished) { [UIView animateWithDuration:1 delay:1.5 usingSpringWithDamping:0.4 initialSpringVelocity:10 options:UIViewAnimationOptionCurveLinear animations:^{ self.QQBtn.transform = CGAffineTransformIdentity; self.sinaBtn.transform = CGAffineTransformIdentity; self.tencentBtn.transform = CGAffineTransformIdentity; } completion:nil]; }]; } //设置动画 -(void)setupAnimationWithStartRect:(CGRect)startRect endRect:(CGRect)endRect object:(UIView *)view duration:(NSTimeInterval)duration { UIBezierPath *beginPath = [UIBezierPath bezierPathWithRect:startRect]; UIBezierPath *endPath = [UIBezierPath bezierPathWithRect:endRect]; CAShapeLayer *quickMask = [[CAShapeLayer alloc]init]; quickMask.path = endPath.CGPath; quickMask.fillColor = [UIColor whiteColor].CGColor; view.layer.mask = quickMask; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"]; animation.duration = duration; animation.beginTime = CACurrentMediaTime(); animation.fromValue = (__bridge id _Nullable)(beginPath.CGPath); animation.toValue = (__bridge id _Nullable)(endPath.CGPath); [quickMask addAnimation:animation forKey:@"path"]; } //关闭控制器 - (IBAction)close:(UIButton *)sender { [self dismissViewControllerAnimated:YES completion:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFLoginViewController.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFRecommendViewController.h ================================================ // // XFRecommendViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFRecommendViewController : UIViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFRecommendViewController.m ================================================ // // XFRecommendViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFRecommendViewController.h" #import "XFRcommandDataTool.h" #import "XFCategoryModel.h" #import "XFCategoryCell.h" #import "XFMainTableCell.h" #import "MJRefresh.h" #import "SVProgressHUD.h" static NSString *const categoryID = @"category"; static NSString *const mainID = @"main"; @interface XFRecommendViewController () @property (nonatomic,weak) IBOutlet UITableView *categoryTable; @property (nonatomic,weak) IBOutlet UITableView *mainTable; @property (nonatomic,strong) XFRcommandDataTool *tool; @property (nonatomic,strong) NSArray *categoryArray; @property (nonatomic,strong) NSMutableArray *mainTableArray; @property (nonatomic,assign) NSInteger page; @end @implementation XFRecommendViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"推荐关注"; self.view.backgroundColor = BackgroundColor; self.automaticallyAdjustsScrollViewInsets = NO; [self setupTableView]; [self setupRefreshView]; //获得侧边数据 [self.tool getCategoryData:^(id json) { self.categoryArray = json; [self.categoryTable reloadData]; }]; } //设置tableView -(void)setupTableView { self.categoryTable.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); self.mainTable.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); self.mainTable.rowHeight = 70; self.categoryTable.backgroundColor = BackgroundColor; //去掉不要的cell self.categoryTable.tableFooterView = [[UIView alloc]init]; //注册tableView [self.categoryTable registerNib:[UINib nibWithNibName:@"XFCategoryCell" bundle:nil] forCellReuseIdentifier:categoryID]; [self.mainTable registerNib:[UINib nibWithNibName:@"XFMainTableCell" bundle:nil] forCellReuseIdentifier:mainID]; } -(void)setupRefreshView { self.mainTable.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNew)]; [self.mainTable.mj_header beginRefreshing]; self.mainTable.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMore)]; self.mainTable.mj_footer.hidden = YES; } //加载最新数据 -(void)loadNew { self.page = 1; [self.mainTableArray removeAllObjects]; XFCategoryModel *model = self.categoryArray[self.categoryTable. indexPathForSelectedRow.row]; [self.tool getMainDataWithID:@(model.id) block:^(id json) { self.mainTableArray = json; model.users = json; [self.mainTable reloadData]; [self.mainTable.mj_header endRefreshing]; }]; } //加载更多数据 -(void)loadMore { self.page += 1; XFCategoryModel *model = self.categoryArray[self.categoryTable. indexPathForSelectedRow.row]; [self.tool getMainDataWithID:@(model.id) currentPage:self.page block:^(id json) { [self.mainTableArray addObjectsFromArray:json]; [self.mainTable reloadData]; [self.mainTable.mj_footer endRefreshing]; }]; } #pragma mark - UITableViewDelegate -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self.mainTable.mj_header beginRefreshing]; XFCategoryModel *model = self.categoryArray[indexPath.row]; [self.tool getMainDataWithID:@(model.id) block:^(id json) { self.mainTableArray = json; [self.mainTable reloadData]; [self.mainTable.mj_header endRefreshing]; }]; } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (tableView == self.categoryTable) { return self.categoryArray.count; } return self.mainTableArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (tableView == self.categoryTable) { XFCategoryCell *cell = [tableView dequeueReusableCellWithIdentifier:categoryID]; cell.model = self.categoryArray[indexPath.row]; [self.categoryTable selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop]; return cell; } else { XFMainTableCell *cell = [tableView dequeueReusableCellWithIdentifier:mainID]; cell.model = self.mainTableArray[indexPath.row]; return cell; } } #pragma mark - getter and setter - (XFRcommandDataTool *)tool{ if (_tool == nil) { _tool = [[XFRcommandDataTool alloc]init]; } return _tool; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Controller/XFRecommendViewController.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Model/XFCategoryModel.h ================================================ // // XFCategoryModel.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFCategoryModel : NSObject @property (nonatomic,assign) NSInteger id; @property (nonatomic,strong) NSString *name; @property (nonatomic,assign) NSInteger count; /** 用于缓存下载下来的对应类别数据 */ @property (nonatomic, strong) NSMutableArray *users; @property (nonatomic, assign) NSInteger total; @property (nonatomic, assign) NSInteger currentPage; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Model/XFCategoryModel.m ================================================ // // XFCategoryModel.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFCategoryModel.h" @implementation XFCategoryModel @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Model/XFMainTableModel.h ================================================ // // XFMainTableModel.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/19. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFMainTableModel : NSObject @property (nonatomic, assign) NSInteger uid; @property (nonatomic, copy) NSString *screen_name; @property (nonatomic, assign) NSInteger fans_count; @property (nonatomic, assign) NSInteger tiezi_count; @property (nonatomic, copy) NSString *header; @property (nonatomic, assign,getter=isVip) BOOL is_vip; /** 用于存放右边表格下载好的数据 */ @property (nonatomic, strong) NSMutableArray *users; @property (nonatomic, assign) NSInteger total; @property (nonatomic, assign) NSInteger currentPage; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Model/XFMainTableModel.m ================================================ // // XFMainTableModel.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/19. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFMainTableModel.h" @implementation XFMainTableModel //-(BOOL)isVip { // if ([self.is_vip isEqualToString:@"true"]) { // return YES; // } // return NO; //} @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Tool/XFRcommandDataTool.h ================================================ // // XFRcommandDataTool.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFRcommandDataTool : NSObject /** * 获取左边栏数据 * * @param block 回调 */ -(void)getCategoryData:(void(^)(id json))block; /** * 获取右边栏数据,用于刷新数据,无需页码参数 * * @param Id 选中的ID * @param block 回调 */ -(void)getMainDataWithID:(NSNumber *)Id block:(void (^)(id json))block; /** * 用于右边栏数据用于加载更多 * * @param Id 选中ID * @param currentPage 当前页码 * @param block 回调 */ -(void)getMainDataWithID:(NSNumber *)Id currentPage:(NSInteger)currentPage block:(void (^)(id json))block; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/Tool/XFRcommandDataTool.m ================================================ // // XFRcommandDataTool.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFRcommandDataTool.h" #import "HttpTool.h" #import "MJExtension.h" #import "XFCategoryModel.h" #import "XFMainTableModel.h" #import "SVProgressHUD.h" static NSString *const categoryUrl = @"http://api.budejie.com/api/api_open.php"; @implementation XFRcommandDataTool -(void)getCategoryData:(void (^)(id))block { NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"a"] = @"category"; parameters[@"c"] = @"subscribe"; [HttpTool get:categoryUrl parameters:parameters success:^(id json) { NSArray *listArray = [XFCategoryModel mj_objectArrayWithKeyValuesArray:json[@"list"]]; block(listArray); } failure:^(NSError *error) { [SVProgressHUD showErrorWithStatus:@"加载失败..."]; nil; }]; } -(void)getMainDataWithID:(NSNumber *)Id block:(void (^)(id json))block { NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"a"] = @"list"; parameters[@"c"] = @"subscribe"; parameters[@"category_id"] = Id; [HttpTool get:categoryUrl parameters:parameters success:^(id json) { NSMutableArray *mainArray = [XFMainTableModel mj_objectArrayWithKeyValuesArray:json[@"list"]]; block(mainArray); } failure:^(NSError *error) { [SVProgressHUD showErrorWithStatus:@"加载失败..."]; nil; }]; } -(void)getMainDataWithID:(NSNumber *)Id currentPage:(NSInteger)currentPage block:(void (^)(id))block { NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"a"] = @"list"; parameters[@"c"] = @"subscribe"; parameters[@"category_id"] = Id; parameters[@"page"] = @(currentPage); [HttpTool get:categoryUrl parameters:parameters success:^(id json) { NSMutableArray *mainArray = [XFMainTableModel mj_objectArrayWithKeyValuesArray:json[@"list"]]; block(mainArray); } failure:^(NSError *error) { [SVProgressHUD showErrorWithStatus:@"加载失败..."]; nil; }]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/View/XFCategoryCell.h ================================================ // // XFCategoryCell.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/19. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFCategoryModel.h" @interface XFCategoryCell : UITableViewCell @property (nonatomic,strong) XFCategoryModel *model; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/View/XFCategoryCell.m ================================================ // // XFCategoryCell.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/19. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFCategoryCell.h" @interface XFCategoryCell () @end @implementation XFCategoryCell - (void)awakeFromNib { // Initialization code self.backgroundColor = [UIColor clearColor]; self.textLabel.textColor = [UIColor grayColor]; UIView *selectedView = [[UIView alloc]initWithFrame:self.frame]; UIView *selectedIndicator = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 5, self.height+1)]; selectedIndicator.backgroundColor = GLOBALCOLOR(219, 21, 26,1); [selectedView addSubview:selectedIndicator]; self.selectedBackgroundView = selectedView; self.selectedBackgroundView.backgroundColor = GLOBALCOLOR(245, 245, 245, 1);; self.textLabel.highlightedTextColor = GLOBALCOLOR(219, 21, 26,1); } -(void)setModel:(XFCategoryModel *)model { _model = model; self.textLabel.text = model.name; self.textLabel.font = [UIFont systemFontOfSize:15]; self.textLabel.textAlignment = NSTextAlignmentCenter; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/View/XFCategoryCell.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/View/XFMainTableCell.h ================================================ // // XFMainTableCell.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/19. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFMainTableModel.h" @interface XFMainTableCell : UITableViewCell @property (nonatomic, strong) XFMainTableModel *model; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/View/XFMainTableCell.m ================================================ // // XFMainTableCell.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/19. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFMainTableCell.h" #import "UIImageView+WebCache.h" @interface XFMainTableCell () @property (weak, nonatomic) IBOutlet UIImageView *avatar; @property (weak, nonatomic) IBOutlet UILabel *name; @property (weak, nonatomic) IBOutlet UILabel *concernCount; @property (weak, nonatomic) IBOutlet UIView *separator; @end @implementation XFMainTableCell - (void)awakeFromNib { // Initialization code } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } -(void)setModel:(XFMainTableModel *)model { _model = model; if (model.isVip) { self.name.textColor = [UIColor redColor]; } self.avatar.layer.cornerRadius = 21; self.avatar.clipsToBounds = YES; [self.avatar sd_setImageWithURL:[NSURL URLWithString:model.header] placeholderImage:[UIImage imageNamed:@"defaultUserIcon"]]; self.name.text = model.screen_name; self.concernCount.text = [NSString stringWithFormat:@"%zd人关注",model.fans_count]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/View/XFMainTableCell.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/View/XFTextfield.h ================================================ // // XFTextfield.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFTextfield : UITextField @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Concern/View/XFTextfield.m ================================================ // // XFTextfield.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFTextfield.h" @implementation XFTextfield //成为第一响应者就会调用 -(BOOL)becomeFirstResponder { [super becomeFirstResponder]; // 修改占位文字颜色 [self setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"]; return YES; } //放弃第一响应者就会调用 -(BOOL)resignFirstResponder { [super resignFirstResponder]; // 修改占位文字颜色 [self setValue:[UIColor grayColor] forKeyPath:@"_placeholderLabel.textColor"]; return YES; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFAllViewController.h ================================================ // // XFAllViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFAllViewController : UITableViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFAllViewController.m ================================================ // // XFAllViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFAllViewController.h" #import "XFTopicCell.h" #import "XFModuleDataTool.h" #import "MJRefresh.h" #import "XFCommentViewController.h" #import "XFLatestViewController.h" static NSString *const CellID = @"topic"; @interface XFAllViewController() @property (nonatomic,strong) XFModuleDataTool *tool; @property (nonatomic,strong) NSMutableArray *topicFrames; /** 当前页码 */ @property (nonatomic, assign) NSInteger page; /** 当加载下一页数据时需要的参数 */ @property (nonatomic, copy) NSString *maxtime; @end @implementation XFAllViewController - (void)viewDidLoad { [super viewDidLoad]; [self settableView]; [self setRefresh]; [self enterComment]; } //评论按钮 -(void)enterComment { [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"commentClick" object:nil] subscribeNext:^(NSNotification *noti) { XFTopicFrame *topicFrame = noti.userInfo[@"topicFrame"]; XFCommentViewController * commentVC = [[XFCommentViewController alloc]init]; commentVC.topicFrame = topicFrame; [self.navigationController pushViewController:commentVC animated:YES]; }]; } //设置刷新控件 -(void)setRefresh { self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(getNewData)]; //自动改变透明度 self.tableView.mj_header.automaticallyChangeAlpha = YES; [self.tableView.mj_header beginRefreshing]; self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(getMoreData)]; } #pragma mark - a参数 - (NSString *)parameterA { return [self.parentViewController isKindOfClass:[XFLatestViewController class]] ? @"newlist" : @"list"; } //获取最新数据 -(void)getNewData { self.page = 0;//清空 [self.topicFrames removeAllObjects]; @weakify(self) [self.tool getDataWithArrayType:TopicTypeAll parameterA:self.parameterA block:^(id json, NSString *maxtime) { @strongify(self) for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [self.topicFrames addObject:topicFrame]; } self.maxtime = maxtime; [self.tableView reloadData]; [self.tableView.mj_header endRefreshing]; }]; } //获取更多数据 -(void)getMoreData { //计算页码 NSInteger page = self.page+1; @weakify(self) [self.tool getDataWithMaxtime:self.maxtime page:@(page) TopicType:TopicTypeAll parameterA:self.parameterA block:^(id json,NSString *maxtime) { @strongify(self) NSMutableArray *newArray = [NSMutableArray array]; for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [newArray addObject:topicFrame]; } [self.topicFrames addObjectsFromArray:newArray]; [self.tableView reloadData]; self.page = page; self.maxtime = maxtime; [self.tableView.mj_footer endRefreshing]; }]; } //设置tableView -(void)settableView{ self.view.backgroundColor = BackgroundColor; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView registerNib:[UINib nibWithNibName:@"XFTopicCell" bundle:nil] forCellReuseIdentifier:CellID]; } -(void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicFrame *topicFrame = self.topicFrames[indexPath.row]; XFCommentViewController * commentVC = [[XFCommentViewController alloc]init]; commentVC.topicFrame = topicFrame; [self.navigationController pushViewController:commentVC animated:YES]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.topicFrames.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID]; cell.topicFrame = self.topicFrames[indexPath.row]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { //计算文字高度 XFTopicFrame *topicFrame = self.topicFrames[indexPath.row]; return topicFrame.cellHeight; } #pragma mark - getter and setter - (XFModuleDataTool *)tool{ if (_tool == nil) { _tool = [[XFModuleDataTool alloc]init]; } return _tool; } - (NSMutableArray *)topicFrames{ if (_topicFrames == nil) { _topicFrames = [NSMutableArray array]; } return _topicFrames; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFCommentViewController.h ================================================ // // XFCommentViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/1. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFTopicModel.h" #import "XFTopicFrame.h" @interface XFCommentViewController : UIViewController @property (nonatomic, strong) XFTopicFrame *topicFrame; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFCommentViewController.m ================================================ // // XFCommentViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/1. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFCommentViewController.h" #import "XFCommentCell.h" #import "XFModuleDataTool.h" #import "MJRefresh.h" #import "XFTopicCell.h" static NSString *const cellID = @"comment"; @interface XFCommentViewController () @property (weak,nonatomic) IBOutlet NSLayoutConstraint *bottomConstrain; @property (weak,nonatomic) IBOutlet UITableView *tableView; @property (strong,nonatomic) UIButton *naviRightBtn; @property (nonatomic,strong) XFModuleDataTool *tool; @property (nonatomic,strong) NSMutableArray *hotComments; @property (nonatomic,strong) NSMutableArray *lastestComments; @property (nonatomic,assign) NSInteger page; @end @implementation XFCommentViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. //[self getNewData]; [self keyboardChange]; [self setRefresh]; [self setupHeader]; [self setNaviBar]; [self setTableView]; } //设置头部的cell -(void)setupHeader { UIView *header = [[UIView alloc]init]; XFTopicCell *cell = [XFTopicCell cell]; cell.topicFrame = self.topicFrame; cell.size = CGSizeMake(SCREEN_WIDTH, self.topicFrame.cellHeight); [header addSubview:cell]; header.height = self.topicFrame.cellHeight + 10; self.tableView.tableHeaderView = header; } //设置导航 -(void)setNaviBar { self.title = @"评论"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:self.naviRightBtn]; } //设置tableView -(void)setTableView { self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XFCommentCell class]) bundle:nil] forCellReuseIdentifier:cellID]; } //设置刷新控件 -(void)setRefresh { self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(getNewData)]; //自动改变透明度 self.tableView.mj_header.automaticallyChangeAlpha = YES; [self.tableView.mj_header beginRefreshing]; self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(getMoreData)]; } //拿到最新数据 -(void)getNewData { self.page = 1; [self.tool getCommentsWithID:self.topicFrame.topic.ID block:^(NSMutableArray *hotComments, NSMutableArray *lastestComments) { self.hotComments = hotComments; self.lastestComments = lastestComments; [self.tableView reloadData]; [self.tableView.mj_header endRefreshing]; }]; [self.tableView.mj_header endRefreshing]; } //获得更多数据 -(void)getMoreData { self.page += 1; XFCommentModel *comment = [self.lastestComments lastObject]; [self.tool getCommentsWithID:self.topicFrame.topic.ID page:self.page lastcid:comment.ID block:^(id json,NSInteger total) { NSMutableArray *array = [NSMutableArray array]; for (XFCommentModel *comment in json) { [array addObject:comment]; } [self.lastestComments addObjectsFromArray:array]; [self.tableView reloadData]; if (self.lastestComments.count >= total) { // 全部加载完毕 [self.tableView.mj_footer endRefreshingWithNoMoreData]; } else { // 结束刷新状态 [self.tableView.mj_footer endRefreshing]; } }]; } //监听键盘的改变 -(void)keyboardChange { [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillChangeFrameNotification object:nil] subscribeNext:^(NSNotification *noti) { //弹出时间 CGFloat animaDuration = [noti.userInfo [UIKeyboardAnimationDurationUserInfoKey] doubleValue]; //拿到键盘弹出的frame CGRect frame = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; self.bottomConstrain.constant = SCREEN_HEIGHT - frame.origin.y; [UIView animateWithDuration:animaDuration animations:^{ [self.view layoutIfNeeded]; }]; }]; } /** * 返回第section组的所有评论数组 */ - (NSArray *)commentsInSection:(NSInteger)section { if (section == 0) { return self.hotComments.count ? self.hotComments : self.lastestComments; } return self.lastestComments; } - (XFCommentModel *)commentInIndexPath:(NSIndexPath *)indexPath { return [self commentsInSection:indexPath.section][indexPath.row]; } //移除通知 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - UITableViewDelegate -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { XFCommentModel *comment = [self commentInIndexPath:indexPath]; return comment.cellHeight; } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //创建menu菜单 UIMenuController *menu = [UIMenuController sharedMenuController]; if (menu.isMenuVisible) { [menu setMenuVisible:NO animated:YES]; }else { //取出点的那一行 XFCommentCell *cell = (XFCommentCell *)[tableView cellForRowAtIndexPath:indexPath]; //成为第一响应者 [cell becomeFirstResponder]; UIMenuItem *ding = [[UIMenuItem alloc]initWithTitle:@"顶" action:@selector(ding:)]; UIMenuItem *replay = [[UIMenuItem alloc]initWithTitle:@"回复" action:@selector(replay:)]; UIMenuItem *report = [[UIMenuItem alloc]initWithTitle:@"举报" action:@selector(report:)]; UIMenuItem *copy = [[UIMenuItem alloc]initWithTitle:@"复制" action:@selector(copyText:)]; menu.menuItems = @[ding,replay,report,copy]; CGRect cellRect = CGRectMake(0, cell.height / 2, cell.width, cell.height / 2); [menu setTargetRect:cellRect inView:cell]; [menu setMenuVisible:YES animated:YES]; } } -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES]; //让键盘退出 [self.view endEditing:YES]; } -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { NSInteger hotCount = self.hotComments.count; if (section == 0) { return hotCount ? @"最热评论" : @"最新评论"; } else { return @"最新评论"; } } #pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { NSInteger hotCount = self.hotComments.count; NSInteger latestCount = self.lastestComments.count; if (hotCount) return 2; if (latestCount) return 1; return 0; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSInteger hotCount = self.hotComments.count; NSInteger latestCount = self.lastestComments.count; if (section == 0) { return hotCount ? hotCount : latestCount; } return latestCount; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XFCommentCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; cell.comment = [self commentInIndexPath:indexPath]; return cell; } #pragma mark - MenuItem处理 - (void)ding:(UIMenuController *)menu {//顶 NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; NSLog(@"%s %@", __func__, indexPath); } - (void)replay:(UIMenuController *)menu {//回复 NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; NSLog(@"%s %@", __func__, indexPath); } - (void)report:(UIMenuController *)menu {//举报 NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; NSLog(@"%s %@", __func__, indexPath); } - (void)copyText:(UIMenuController *)menu {//复制 NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; UIPasteboard *paste = [UIPasteboard generalPasteboard]; paste.string = [self commentInIndexPath:indexPath].content; } #pragma mark - getter and setter - (UIButton *)naviRightBtn{ if (_naviRightBtn == nil) { _naviRightBtn = [[UIButton alloc]init]; [_naviRightBtn setBackgroundImage:[UIImage imageNamed:@"comment_nav_item_share_icon"] forState:UIControlStateNormal]; [_naviRightBtn setBackgroundImage:[UIImage imageNamed:@"comment_nav_item_share_icon_click"] forState:UIControlStateHighlighted]; [_naviRightBtn sizeToFit]; } return _naviRightBtn; } - (XFModuleDataTool *)tool{ if (_tool == nil) { _tool = [[XFModuleDataTool alloc]init]; } return _tool; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFCommentViewController.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFDetailPictureController.h ================================================ // // XFDetailPictureController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/27. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFTopicModel.h" @interface XFDetailPictureController : UIViewController @property (nonatomic,strong) XFTopicModel *topic; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFDetailPictureController.m ================================================ // // XFDetailPictureController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/27. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFDetailPictureController.h" #import "UIImageView+WebCache.h" #import "SVProgressHUD.h" #import "DALabeledCircularProgressView.h" @interface XFDetailPictureController () @property (nonatomic,strong) UIButton *saveBtn; @property (nonatomic,strong) UIButton *shareBtn; @property (nonatomic,strong) UIButton *commentBtn; @property (nonatomic,strong) UIButton *backBtn; @property (nonatomic,strong) UIView *backgroundView; @property (nonatomic,strong) UIScrollView *scrollView; @property (nonatomic,strong) UIImageView *imageView; @property (nonatomic,strong) DALabeledCircularProgressView *progressView; @end @implementation XFDetailPictureController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self initialViews]; [self loadImgae]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } //加载图片 -(void)loadImgae { [self.imageView sd_setImageWithPreviousCachedImageWithURL:[NSURL URLWithString:self.topic.large_image] placeholderImage:nil options:SDWebImageProgressiveDownload progress:^(NSInteger receivedSize, NSInteger expectedSize) { CGFloat progress = 1.0 * receivedSize / expectedSize; self.progressView.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",progress*100]; [self.progressView setProgress:progress animated:YES]; } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { self.progressView.hidden = YES; }]; } //初始化控件 -(void)initialViews { [self.view addSubview:self.scrollView]; [self.scrollView addSubview:self.imageView]; [self.scrollView addSubview:self.backBtn]; [self.scrollView addSubview:self.saveBtn]; [self.scrollView addSubview:self.shareBtn]; [self.scrollView addSubview:self.commentBtn]; [self.scrollView addSubview:self.progressView]; } -(void)back { [self dismissViewControllerAnimated:YES completion:nil]; } //保存图片 -(void)saveImageBtn { if(self.imageView.image != nil) { UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); }else{ [SVProgressHUD showErrorWithStatus:@"加载失败..."]; } } - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { if (error) { [SVProgressHUD showErrorWithStatus:@"保存失败"]; }else{ [SVProgressHUD showSuccessWithStatus:@"保存成功"]; } } #pragma mark - getter and setter - (UIButton *)backBtn{ if (_backBtn == nil) { _backBtn = [[UIButton alloc]init]; [_backBtn setBackgroundImage:[UIImage imageNamed:@"show_image_back_icon"] forState:UIControlStateNormal]; _backBtn.x = 20; _backBtn.y = 30; [[_backBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { [self dismissViewControllerAnimated:YES completion:nil]; }]; [_backBtn sizeToFit]; } return _backBtn; } - (UIButton *)shareBtn{ if (_shareBtn == nil) { _shareBtn = [[UIButton alloc]init]; [_shareBtn setImage:[UIImage imageNamed:@"mainCellShare"] forState:UIControlStateNormal]; NSString *sharnCount = [NSString stringWithFormat:@"%ld",(long)self.topic.repost]; [_shareBtn setTitle:sharnCount forState:UIControlStateNormal]; _shareBtn.titleLabel.font = [UIFont systemFontOfSize:14]; _shareBtn.x = SCREEN_WIDTH - 120; _shareBtn.y = SCREEN_HEIGHT - 35; [_shareBtn sizeToFit]; } return _shareBtn; } - (UIButton *)commentBtn{ if (_commentBtn == nil) { _commentBtn = [[UIButton alloc]init]; [_commentBtn setImage:[UIImage imageNamed:@"mainCellComment"] forState:UIControlStateNormal]; NSString *commentCount = [NSString stringWithFormat:@"%ld",(long)self.topic.comment]; [_commentBtn setTitle:commentCount forState:UIControlStateNormal]; _commentBtn.titleLabel.font = [UIFont systemFontOfSize:14]; _commentBtn.x = SCREEN_WIDTH - 60; _commentBtn.y = SCREEN_HEIGHT - 35; [_commentBtn sizeToFit]; } return _commentBtn; } - (UIButton *)saveBtn{ if (_saveBtn == nil) { _saveBtn = [[UIButton alloc]init]; [_saveBtn setTitle:@"保存" forState:UIControlStateNormal]; _saveBtn.titleLabel.font = [UIFont systemFontOfSize:13]; _saveBtn.x = 25; _saveBtn.y = SCREEN_HEIGHT - 35; [_saveBtn sizeToFit]; [[_saveBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { [self saveImageBtn]; }]; } return _saveBtn; } - (UIScrollView *)scrollView{ if (_scrollView == nil) { _scrollView = [[UIScrollView alloc]init]; _scrollView.frame = SCREEN_FRAME; _scrollView.backgroundColor = [UIColor blackColor]; } return _scrollView; } - (UIImageView *)imageView{ if (_imageView == nil) { _imageView = [[UIImageView alloc]init]; _imageView.userInteractionEnabled = YES; [_imageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(back)]]; CGFloat picW = SCREEN_WIDTH; CGFloat picH = picW * self.topic.height / self.topic.width; if (picH > SCREEN_HEIGHT) { // 图片显示高度超过一个屏幕, 需要滚动查看 _imageView.frame = CGRectMake(0, 0, picW, picH); self.scrollView.contentSize = CGSizeMake(0, picH); } else { _imageView.size = CGSizeMake(picW, picH); _imageView.centerY = SCREEN_HEIGHT * 0.5; } } return _imageView; } - (DALabeledCircularProgressView *)progressView{ if (_progressView == nil) { _progressView = [[DALabeledCircularProgressView alloc]init]; _progressView.size = CGSizeMake(100, 100); _progressView.centerY = SCREEN_HEIGHT / 2; _progressView.centerX = SCREEN_WIDTH / 2; _progressView.progressLabel.textColor = [UIColor whiteColor]; _progressView.roundedCorners = 3; } return _progressView; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFEssenceViewController.h ================================================ // // XFEssenceViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFEssenceViewController : UIViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFEssenceViewController.m ================================================ // // XFEssenceViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFEssenceViewController.h" #import "XFConcernViewController.h" #import "XFAllViewController.h" #import "XFVideoViewController.h" #import "XFPictrueViewController.h" #import "XFTalkViewController.h" #import "XFVocieViewController.h" #import "ReactiveCocoa.h" @interface XFEssenceViewController () @property (nonatomic,strong) UIButton *naviLeftBtn; @property (nonatomic,strong) UIView *titleView; @property (nonatomic,strong) UIView *btnIndicator; @property (nonatomic, weak) UIButton *seletedBtn; @property (nonatomic,strong) UIScrollView *scrollview; @end @implementation XFEssenceViewController - (void)viewDidLoad { [super viewDidLoad]; self.automaticallyAdjustsScrollViewInsets = NO; self.view.backgroundColor = BackgroundColor; [self setNaviBar]; [self setupChildViewControllers]; [self.view addSubview:self.scrollview]; [self.view addSubview:self.titleView]; [self setupTitleBtn]; [self.titleView addSubview:self.btnIndicator]; } //设置子控制器 -(void)setupChildViewControllers { XFAllViewController *allVc = [[XFAllViewController alloc]init]; [self addChildViewController:allVc]; XFVideoViewController *videoVc = [[XFVideoViewController alloc]init]; [self addChildViewController:videoVc]; XFPictrueViewController *picVc = [[XFPictrueViewController alloc]init]; [self addChildViewController:picVc]; XFVocieViewController *voiceVc = [[XFVocieViewController alloc]init]; [self addChildViewController:voiceVc]; XFTalkViewController *talkVc = [[XFTalkViewController alloc]init]; [self addChildViewController:talkVc]; } //设置导航栏 -(void)setNaviBar { self.navigationItem.titleView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"MainTitle"]]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:self.naviLeftBtn]; } //设置titleView按钮 -(void)setupTitleBtn { NSArray *titles = @[@"推荐",@"视频",@"图片",@"声音",@"段子"]; NSInteger count = titles.count; CGFloat btnH = self.titleView.height - 2; CGFloat btnW = self.titleView.width / count; CGFloat btnY = 0; for (NSInteger i = 0; i @interface XFPictrueViewController : UITableViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFPictrueViewController.m ================================================ // // XFPictrueViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFPictrueViewController.h" #import "XFTopicCell.h" #import "XFModuleDataTool.h" #import "MJRefresh.h" #import "XFCommentViewController.h" #import "XFLatestViewController.h" static NSString *const CellID = @"topic"; @interface XFPictrueViewController() @property (nonatomic,strong) XFModuleDataTool *tool; @property (nonatomic,strong) NSMutableArray *topicFrames; /** 当前页码 */ @property (nonatomic, assign) NSInteger page; /** 当加载下一页数据时需要的参数 */ @property (nonatomic, copy) NSString *maxtime; @end @implementation XFPictrueViewController - (void)viewDidLoad { [super viewDidLoad]; [self settableView]; [self setRefresh]; } //设置刷新控件 -(void)setRefresh { self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(getNewData)]; //自动改变透明度 self.tableView.mj_header.automaticallyChangeAlpha = YES; [self.tableView.mj_header beginRefreshing]; self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(getMoreData)]; } #pragma mark - a参数 - (NSString *)parameterA { return [self.parentViewController isKindOfClass:[XFLatestViewController class]] ? @"newlist" : @"list"; } //获取最新数据 -(void)getNewData { self.page = 0;//清空 [self.topicFrames removeAllObjects]; @weakify(self) [self.tool getDataWithArrayType:TopicTypePicture parameterA:self.parameterA block:^(id json, NSString *maxtime) { @strongify(self) for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [self.topicFrames addObject:topicFrame]; } self.maxtime = maxtime; [self.tableView reloadData]; [self.tableView.mj_header endRefreshing]; }]; } //获取更多数据 -(void)getMoreData { //计算页码 NSInteger page = self.page+1; @weakify(self) [self.tool getDataWithMaxtime:self.maxtime page:@(page) TopicType:TopicTypePicture parameterA:self.parameterA block:^(id json,NSString *maxtime) { @strongify(self) NSMutableArray *newArray = [NSMutableArray array]; for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [newArray addObject:topicFrame]; } [self.topicFrames addObjectsFromArray:newArray]; [self.tableView reloadData]; self.page = page; self.maxtime = maxtime; [self.tableView.mj_footer endRefreshing]; }]; } //设置tableView -(void)settableView{ self.view.backgroundColor = BackgroundColor; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView registerNib:[UINib nibWithNibName:@"XFTopicCell" bundle:nil] forCellReuseIdentifier:CellID]; } #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicFrame *topicFrame = self.topicFrames[indexPath.row]; XFCommentViewController * commentVC = [[XFCommentViewController alloc]init]; commentVC.topicFrame = topicFrame; [self.navigationController pushViewController:commentVC animated:YES]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.topicFrames.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID]; cell.topicFrame = self.topicFrames[indexPath.row]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { //计算文字高度 XFTopicFrame *topicFrame = self.topicFrames[indexPath.row]; return topicFrame.cellHeight; } #pragma mark - getter and setter - (XFModuleDataTool *)tool{ if (_tool == nil) { _tool = [[XFModuleDataTool alloc]init]; } return _tool; } - (NSMutableArray *)topicFrames{ if (_topicFrames == nil) { _topicFrames = [NSMutableArray array]; } return _topicFrames; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFTalkViewController.h ================================================ // // XFTalkViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFTalkViewController : UITableViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFTalkViewController.m ================================================ // // XFTalkViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFTalkViewController.h" #import "XFTopicCell.h" #import "XFTopicModel.h" #import "XFModuleDataTool.h" #import "MJRefresh.h" #import "XFCommentViewController.h" #import "XFLatestViewController.h" static NSString *const CellID = @"topic"; @interface XFTalkViewController () @property (nonatomic,strong) XFModuleDataTool *tool; @property (nonatomic,strong) NSMutableArray *topicsFrame; /** 当前页码 */ @property (nonatomic, assign) NSInteger page; /** 当加载下一页数据时需要的参数 */ @property (nonatomic, copy) NSString *maxtime; @end @implementation XFTalkViewController - (void)viewDidLoad { [super viewDidLoad]; [self settableView]; [self setRefresh]; } //设置刷新控件 -(void)setRefresh { self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(getNewData)]; //自动改变透明度 self.tableView.mj_header.automaticallyChangeAlpha = YES; [self.tableView.mj_header beginRefreshing]; self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(getMoreData)]; } #pragma mark - a参数 - (NSString *)parameterA { return [self.parentViewController isKindOfClass:[XFLatestViewController class]] ? @"newlist" : @"list"; } //获取最新数据 -(void)getNewData { self.page = 0;//清空 [self.topicsFrame removeAllObjects]; @weakify(self) [self.tool getDataWithArrayType:TopicTypeTalk parameterA:self.parameterA block:^(id json, NSString *maxtime) { @strongify(self) for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [self.topicsFrame addObject:topicFrame]; } self.maxtime = maxtime; [self.tableView reloadData]; [self.tableView.mj_header endRefreshing]; }]; } //获取更多数据 -(void)getMoreData { //计算页码 NSInteger page = self.page+1; @weakify(self) [self.tool getDataWithMaxtime:self.maxtime page:@(page) TopicType:TopicTypeTalk parameterA:self.parameterA block:^(id json,NSString *maxtime) { @strongify(self) NSMutableArray *newFrames = [NSMutableArray array]; for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [newFrames addObject:topicFrame]; } [self.topicsFrame addObjectsFromArray:newFrames]; [self.tableView reloadData]; self.page = page; self.maxtime = maxtime; [self.tableView.mj_footer endRefreshing]; }]; } //设置tableView -(void)settableView{ self.view.backgroundColor = BackgroundColor; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView registerNib:[UINib nibWithNibName:@"XFTopicCell" bundle:nil] forCellReuseIdentifier:CellID]; } #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicFrame *topicFrame = self.topicsFrame[indexPath.row]; XFCommentViewController * commentVC = [[XFCommentViewController alloc]init]; commentVC.topicFrame = topicFrame; [self.navigationController pushViewController:commentVC animated:YES]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.topicsFrame.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID]; cell.topicFrame = self.topicsFrame[indexPath.row]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { //取出frame模型 XFTopicFrame *topicFrame = self.topicsFrame[indexPath.row]; return topicFrame.cellHeight; } #pragma mark - getter and setter - (XFModuleDataTool *)tool{ if (_tool == nil) { _tool = [[XFModuleDataTool alloc]init]; } return _tool; } - (NSMutableArray *)topicsFrame{ if (_topicsFrame == nil) { _topicsFrame = [NSMutableArray array]; } return _topicsFrame; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFVideoViewController.h ================================================ // // XFVideoViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFVideoViewController : UITableViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFVideoViewController.m ================================================ // // XFVideoViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFVideoViewController.h" #import "XFTopicCell.h" #import "XFModuleDataTool.h" #import "MJRefresh.h" #import "XFCommentViewController.h" #import "XFLatestViewController.h" #import "XFContentVideoView.h" #import #import "KRVideoPlayerController.h" static NSString *const CellID = @"topic"; @interface XFVideoViewController() @property (nonatomic,strong) XFModuleDataTool *tool; @property (nonatomic,strong) NSMutableArray *topicFrames; @property (nonatomic, strong) KRVideoPlayerController *videoController; /** 当前页码 */ @property (nonatomic, assign) NSInteger page; /** 当加载下一页数据时需要的参数 */ @property (nonatomic, copy) NSString *maxtime; @end @implementation XFVideoViewController - (void)viewDidLoad { [super viewDidLoad]; [self settableView]; [self setRefresh]; [self setupPlayBtnNotification]; } //添加播放按钮通知 -(void)setupPlayBtnNotification { [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"playVideo" object:nil] subscribeNext:^(NSNotification *noti) { XFTopicModel *topic = noti.userInfo[@"Video"]; [self playVideoWithURL:[NSURL URLWithString:topic.videouri]]; }]; } //设置刷新控件 -(void)setRefresh { self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(getNewData)]; //自动改变透明度 self.tableView.mj_header.automaticallyChangeAlpha = YES; [self.tableView.mj_header beginRefreshing]; self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(getMoreData)]; } #pragma mark - a参数 - (NSString *)parameterA { return [self.parentViewController isKindOfClass:[XFLatestViewController class]] ? @"newlist" : @"list"; } //获取最新数据 -(void)getNewData { self.page = 0;//清空 [self.topicFrames removeAllObjects]; @weakify(self) [self.tool getDataWithArrayType:TopicTypeVideo parameterA:self.parameterA block:^(id json, NSString *maxtime) { @strongify(self) for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [self.topicFrames addObject:topicFrame]; } self.maxtime = maxtime; [self.tableView reloadData]; [self.tableView.mj_header endRefreshing]; }]; } //获取更多数据 -(void)getMoreData { //计算页码 NSInteger page = self.page+1; @weakify(self) [self.tool getDataWithMaxtime:self.maxtime page:@(page) TopicType:TopicTypeVideo parameterA:self.parameterA block:^(id json,NSString *maxtime) { @strongify(self) NSMutableArray *newArray = [NSMutableArray array]; for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [newArray addObject:topicFrame]; } [self.topicFrames addObjectsFromArray:newArray]; [self.tableView reloadData]; self.page = page; self.maxtime = maxtime; [self.tableView.mj_footer endRefreshing]; }]; } //设置tableView -(void)settableView{ self.view.backgroundColor = BackgroundColor; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView registerNib:[UINib nibWithNibName:@"XFTopicCell" bundle:nil] forCellReuseIdentifier:CellID]; } -(void)dealloc { [[NSNotificationCenter defaultCenter]removeObserver:self]; } #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicFrame *topicFrame = self.topicFrames[indexPath.row]; XFCommentViewController * commentVC = [[XFCommentViewController alloc]init]; commentVC.topicFrame = topicFrame; [self.navigationController pushViewController:commentVC animated:YES]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.topicFrames.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID]; cell.topicFrame = self.topicFrames[indexPath.row]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { //计算文字高度 XFTopicFrame *topicFrame = self.topicFrames[indexPath.row]; return topicFrame.cellHeight; } #pragma mark - getter and setter - (XFModuleDataTool *)tool{ if (_tool == nil) { _tool = [[XFModuleDataTool alloc]init]; } return _tool; } - (NSMutableArray *)topicFrames{ if (_topicFrames == nil) { _topicFrames = [NSMutableArray array]; } return _topicFrames; } - (void)playVideoWithURL:(NSURL *)url { if (!self.videoController) { self.videoController = [[KRVideoPlayerController alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_WIDTH*(9.0/16.0))]; __weak typeof(self)weakSelf = self; [self.videoController setDimissCompleteBlock:^{ weakSelf.videoController = nil; }]; [self.videoController showInWindow]; } self.videoController.contentURL = url; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFVocieViewController.h ================================================ // // XFVocieViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFVocieViewController : UITableViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Controller/XFVocieViewController.m ================================================ // // XFVocieViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFVocieViewController.h" #import "XFTopicCell.h" #import "XFModuleDataTool.h" #import "MJRefresh.h" #import "XFCommentViewController.h" #import "XFLatestViewController.h" static NSString *const CellID = @"topic"; @interface XFVocieViewController() @property (nonatomic,strong) XFModuleDataTool *tool; @property (nonatomic,strong) NSMutableArray *topicFrames; /** 当前页码 */ @property (nonatomic, assign) NSInteger page; /** 当加载下一页数据时需要的参数 */ @property (nonatomic, copy) NSString *maxtime; @end @implementation XFVocieViewController - (void)viewDidLoad { [super viewDidLoad]; [self settableView]; [self setRefresh]; } //设置刷新控件 -(void)setRefresh { self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(getNewData)]; //自动改变透明度 self.tableView.mj_header.automaticallyChangeAlpha = YES; [self.tableView.mj_header beginRefreshing]; self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(getMoreData)]; } #pragma mark - a参数 - (NSString *)parameterA { return [self.parentViewController isKindOfClass:[XFLatestViewController class]] ? @"newlist" : @"list"; } //获取最新数据 -(void)getNewData { self.page = 0;//清空 [self.topicFrames removeAllObjects]; @weakify(self) [self.tool getDataWithArrayType:TopicTypeVoice parameterA:self.parameterA block:^(id json, NSString *maxtime) { @strongify(self) for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [self.topicFrames addObject:topicFrame]; } self.maxtime = maxtime; [self.tableView reloadData]; [self.tableView.mj_header endRefreshing]; }]; } //获取更多数据 -(void)getMoreData { //计算页码 NSInteger page = self.page+1; @weakify(self) [self.tool getDataWithMaxtime:self.maxtime page:@(page) TopicType:TopicTypeVoice parameterA:self.parameterA block:^(id json,NSString *maxtime) { @strongify(self) NSMutableArray *newArray = [NSMutableArray array]; for (XFTopicModel *topic in json) { XFTopicFrame *topicFrame = [[XFTopicFrame alloc]init]; topicFrame.topic = topic; [newArray addObject:topicFrame]; } [self.topicFrames addObjectsFromArray:newArray]; [self.tableView reloadData]; self.page = page; self.maxtime = maxtime; [self.tableView.mj_footer endRefreshing]; }]; } //设置tableView -(void)settableView{ self.view.backgroundColor = BackgroundColor; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView registerNib:[UINib nibWithNibName:@"XFTopicCell" bundle:nil] forCellReuseIdentifier:CellID]; } #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicFrame *topicFrame = self.topicFrames[indexPath.row]; XFCommentViewController * commentVC = [[XFCommentViewController alloc]init]; commentVC.topicFrame = topicFrame; [self.navigationController pushViewController:commentVC animated:YES]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.topicFrames.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XFTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID]; cell.topicFrame = self.topicFrames[indexPath.row]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { //计算文字高度 XFTopicFrame *topicFrame = self.topicFrames[indexPath.row]; return topicFrame.cellHeight; } #pragma mark - getter and setter - (XFModuleDataTool *)tool{ if (_tool == nil) { _tool = [[XFModuleDataTool alloc]init]; } return _tool; } - (NSMutableArray *)topicFrames{ if (_topicFrames == nil) { _topicFrames = [NSMutableArray array]; } return _topicFrames; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Model/XFCommentModel.h ================================================ // // XFCommentModel.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/29. // Copyright © 2016年 谢飞. All rights reserved. // #import @class XFUserModel; @interface XFCommentModel : NSObject /** id */ @property (nonatomic, copy) NSString *ID; /** 音频文件的时长 */ @property (nonatomic, assign) NSInteger voicetime; /** 音频文件的路径 */ @property (nonatomic, copy) NSString *voiceuri; /** 评论的文字内容 */ @property (nonatomic, copy) NSString *content; /** 被点赞的数量 */ @property (nonatomic, assign) NSInteger like_count; /** 用户 */ @property (nonatomic, strong) XFUserModel *user; /** 有声音时的行高 */ @property (nonatomic,assign) CGFloat cellHeight; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Model/XFCommentModel.m ================================================ // // XFCommentModel.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/29. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFCommentModel.h" #import "MJExtension.h" @implementation XFCommentModel + (NSDictionary *)replacedKeyFromPropertyName { return @{ @"ID" : @"id" }; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Model/XFTopicFrame.h ================================================ // // XFTopicFrame.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/24. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFTopicModel.h" @interface XFTopicFrame : NSObject @property (nonatomic,strong)XFTopicModel *topic; @property (assign, nonatomic) CGFloat cellHeight; @property (assign, nonatomic) CGRect contentViewFrame;//图片或视频或声音内容尺寸 @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Model/XFTopicFrame.m ================================================ // // XFTopicFrame.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/24. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFTopicFrame.h" #import "XFUserModel.h" static CGFloat avatarMaxY = 50; static CGFloat inset = 10; static CGFloat toolBarHeight = 50; static CGFloat textX = 14; static CGFloat topCmtH = 20; @implementation XFTopicFrame -(void)setTopic:(XFTopicModel *)topic { _topic = topic; CGFloat textW = SCREEN_WIDTH - 28; CGFloat textH = [topic.text boundingRectWithSize:CGSizeMake(textW , MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil].size.height; //最大的Y值 CGFloat maxY = avatarMaxY + inset*2 + textH ; if (topic.type != TopicTypeTalk) { CGFloat contentViewX = textX; CGFloat contentViewY = maxY; CGFloat contentViewW = textW; CGFloat widthScale = topic.width / contentViewW; CGFloat contentViewH = topic.height / widthScale; if (topic.type == TopicTypeVideo && contentViewH > 250) { contentViewH = 250; topic.bigImage = YES; }if (contentViewH > 1500) { contentViewH = 300; topic.bigImage = YES; } self.contentViewFrame = CGRectMake(contentViewX, contentViewY, contentViewW, contentViewH); maxY = contentViewY + contentViewH + inset; } //如果有热门评论 if(topic.top_cmt){ NSString *content = [NSString stringWithFormat:@"%@ : %@", topic.top_cmt.user.username, topic.top_cmt.content]; CGFloat topcmtContentH = [content boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:13]} context:nil].size.height; maxY = topcmtContentH + topCmtH + maxY + inset; } //设置cell的高度 self.cellHeight = maxY + toolBarHeight; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Model/XFTopicModel.h ================================================ // // XFTopicModel.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/22. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFCommentModel.h" @interface XFTopicModel : NSObject /** id */ @property (nonatomic, copy) NSString *ID; /** 昵称 */ @property (nonatomic, copy) NSString *name; /** 头像 */ @property (nonatomic, copy) NSString *profile_image; /** 发帖时间 */ @property (nonatomic, copy) NSString *created_at; /** 文字内容 */ @property (nonatomic, copy) NSString *text; /** 顶的数量 */ @property (nonatomic, assign) NSInteger ding; /** 踩的数量 */ @property (nonatomic, assign) NSInteger cai; /** 转发的数量 */ @property (nonatomic, assign) NSInteger repost; /** 评论的数量 */ @property (nonatomic, assign) NSInteger comment; //内容类型 @property (nonatomic, assign) TopicType type; /** 最热评论(数组放的是Comment模型) */ @property (nonatomic, strong) XFCommentModel *top_cmt; /** 小图片*/ @property (nonatomic, copy) NSString *small_image; /** 中图片*/ @property (nonatomic, copy) NSString *middle_image; /** 大图片 */ @property (nonatomic, copy) NSString *large_image; /** 是否为gif图片 */ @property (assign, nonatomic) BOOL is_gif; /** 视频或图片类型帖子的宽度 */ @property (assign, nonatomic) CGFloat width; /** 视频或图片类型帖子的高度 */ @property (assign, nonatomic) CGFloat height; /** 音频的时长 */ @property (assign, nonatomic) NSInteger voicetime; /** 播放次数 */ @property (assign, nonatomic) NSInteger playcount; /** 音频的播放地址 */ @property (copy, nonatomic) NSString *voiceuri; /** 视频的播放地址 */ @property (copy, nonatomic) NSString *videouri; /** 视频的时长 */ @property (assign, nonatomic) NSInteger videotime; /****** 是否为大图 ******/ @property (assign, nonatomic, getter=isBigImage) BOOL bigImage; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Model/XFTopicModel.m ================================================ // // XFTopicModel.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/22. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFTopicModel.h" #import "MJExtension.h" #import "XFCommentModel.h" @implementation XFTopicModel + (NSDictionary *)replacedKeyFromPropertyName { return @{ @"small_image" : @"image0", @"large_image" : @"image1", @"middle_image" : @"image2", @"ID" : @"id", @"top_cmt" : @"top_cmt[0]" }; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Model/XFUserModel.h ================================================ // // XFUserModel.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/29. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFUserModel : NSObject @property (nonatomic, copy) NSString *username; @property (nonatomic, copy) NSString *sex; @property (nonatomic, copy) NSString *profile_image; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Model/XFUserModel.m ================================================ // // XFUserModel.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/29. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFUserModel.h" @implementation XFUserModel @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Tool/XFModuleDataTool.h ================================================ // // XFModuleDataTool.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/22. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFModuleDataTool : NSObject /** * 首次刷新(不需要传页码) * * @param block 回调 */ -(void)getDataWithArrayType:(TopicType)type parameterA:(NSString *)parameterA block:(void (^)(id json,id param))block; /** * 加载更多数据(需要传页码) * * @param maxtime 参数 * @param page 页码 * @param block 回调 */ -(void)getDataWithMaxtime:(NSString *)maxtime page:(NSNumber *)page TopicType:(TopicType)type parameterA:(NSString *)parameterA block:(void (^)(id json,id param))block; /** * 加载最新的评论(最热和最新评论) * * @param ID ID * @param block 回调 */ -(void)getCommentsWithID:(NSString *)ID block:(void (^)(id json1,id json2))block; /** * 加载更多最新评论 * * @param ID ID * @param page 页码 * @param lastcid 上次id * @param block 回调 */ -(void)getCommentsWithID:(NSString *)ID page:(NSInteger)page lastcid:(NSString *)lastcid block:(void (^)(id json,NSInteger total))block; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/Tool/XFModuleDataTool.m ================================================ // // XFModuleDataTool.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/22. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFModuleDataTool.h" #import "HttpTool.h" #import "MJExtension.h" #import "XFTopicModel.h" #import "XFCommentModel.h" #import "XFLatestViewController.h" @implementation XFModuleDataTool -(void)getDataWithArrayType:(TopicType)type parameterA:(NSString *)parameterA block:(void (^)(id json,id param))block { // 参数 NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"a"] = parameterA; params[@"c"] = @"data"; params[@"type"] = @(type); [HttpTool get:BaseURL parameters:params success:^(id json) { NSArray *talekArray = [XFTopicModel mj_objectArrayWithKeyValuesArray:json[@"list"]]; NSString *maxTime = json[@"info"][@"maxtime"]; block(talekArray,maxTime); } failure:^(NSError *error) { nil; }]; } -(void)getDataWithMaxtime:(NSString *)maxtime page:(NSNumber *)page TopicType:(TopicType)type parameterA:(NSString *)parameterA block:(void (^)(id json,id param))block { // 参数 NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"a"] = parameterA; params[@"c"] = @"data"; params[@"type"] = @(type); params[@"page"] = page; params[@"maxtime"] = maxtime; [HttpTool get:BaseURL parameters:params success:^(id json) { NSArray *talkMoreArray = [XFTopicModel mj_objectArrayWithKeyValuesArray:json[@"list"]]; NSString *maxTime = json[@"info"][@"maxtime"]; block(talkMoreArray,maxTime); } failure:^(NSError *error) { nil; }]; } -(void)getCommentsWithID:(NSString *)ID block:(void (^)(id, id))block { // 参数 NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"a"] = @"dataList"; params[@"c"] = @"comment"; params[@"data_id"] = ID; params[@"hot"] = @"1"; [HttpTool get:BaseURL parameters:params success:^(id json) { // 如果没有数据 if (![json isKindOfClass:[NSDictionary class]]) { return; } //最热评论 NSArray *hotCommentArray = [XFCommentModel mj_objectArrayWithKeyValuesArray:json[@"hot"]]; //最新评论 NSArray *lastestCommentArray = [XFCommentModel mj_objectArrayWithKeyValuesArray:json[@"data"]]; block(hotCommentArray,lastestCommentArray); } failure:^(NSError *error) { nil; }]; } -(void)getCommentsWithID:(NSString *)ID page:(NSInteger)page lastcid:(NSString *)lastcid block:(void (^)(id, NSInteger))block{ // 参数 NSMutableDictionary *params = [NSMutableDictionary dictionary]; params[@"a"] = @"dataList"; params[@"c"] = @"comment"; params[@"data_id"] = ID; params[@"page"] = @(page); params[@"lastcid"] = lastcid; [HttpTool get:BaseURL parameters:params success:^(id json) { // 如果没有数据没有数据 if (![json isKindOfClass:[NSDictionary class]]) { return; } //最热评论 NSArray *moreCommentArray = [XFCommentModel mj_objectArrayWithKeyValuesArray:json[@"data"]]; NSInteger total = [json[@"total"] integerValue]; block(moreCommentArray,total); } failure:^(NSError *error) { nil; }]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFCommentCell.h ================================================ // // XFCommentCell.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/1. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFCommentModel.h" @interface XFCommentCell : UITableViewCell @property (nonatomic, strong) XFCommentModel *comment; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFCommentCell.m ================================================ // // XFCommentCell.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/1. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFCommentCell.h" #import "UIImageView+WebCache.h" #import "XFUserModel.h" @interface XFCommentCell() @property (weak, nonatomic) IBOutlet UIImageView *avartar; @property (weak, nonatomic) IBOutlet UIImageView *sex; @property (weak, nonatomic) IBOutlet UILabel *name; @property (weak, nonatomic) IBOutlet UILabel *content; @property (weak, nonatomic) IBOutlet UILabel *like; @property (weak, nonatomic) IBOutlet UIButton *playBtn; @end @implementation XFCommentCell - (void)awakeFromNib { // Initialization code } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } //使cell一定成为第一响应者 - (BOOL)canBecomeFirstResponder { return YES; } //支持的方法 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { return NO; } -(void)setComment:(XFCommentModel *)comment { _comment = comment; [self.avartar setHeader:comment.user.profile_image]; self.sex.image = [comment.user.sex isEqualToString:@"m"] ? [UIImage imageNamed:@"Profile_manIcon"] : [UIImage imageNamed:@"Profile_womanIcon"]; if (comment.voiceuri.length) { self.playBtn.hidden = NO; [self.playBtn setTitle:[NSString stringWithFormat:@"%ld''", comment.voicetime] forState:UIControlStateNormal]; } else { self.playBtn.hidden = YES; } self.content.text = comment.content; self.name.text = comment.user.username; self.like.text = [NSString stringWithFormat:@"%ld", (long)comment.like_count]; CGFloat commentH = [self.content.text boundingRectWithSize:CGSizeMake(204, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil].size.height; comment.cellHeight = 50 + commentH; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFCommentCell.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentPictureView.h ================================================ // // XFContentPictureView.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/23. // Copyright © 2016年 谢飞. All rights reserved. // #import @class XFTopicModel; @interface XFContentPictureView : UIView @property (nonatomic,strong) XFTopicModel *topic; + (instancetype)pictureView; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentPictureView.m ================================================ // // XFContentPictureView.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/23. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFContentPictureView.h" #import "UIImageView+WebCache.h" #import "DALabeledCircularProgressView.h" #import "XFTopicModel.h" #import "UIImageView+WebCache.h" #import "XFDetailPictureController.h" @interface XFContentPictureView () @property (weak, nonatomic) IBOutlet UIImageView *gifView; @property (weak, nonatomic) IBOutlet UIButton *bigPicBtn; @property (weak, nonatomic) IBOutlet UIImageView *baisiView; @property (weak, nonatomic) IBOutlet DALabeledCircularProgressView *progrssView; @property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @implementation XFContentPictureView +(instancetype)pictureView { return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject]; } - (void)awakeFromNib { self.autoresizingMask = UIViewAutoresizingNone; // 给图片添加监听器 self.imageView.userInteractionEnabled = YES; [self.imageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showPicture)]]; } -(void)showPicture { XFDetailPictureController *showPicVc = [[XFDetailPictureController alloc]init]; showPicVc.topic = self.topic; [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:showPicVc animated:YES completion:nil]; } -(void)setTopic:(XFTopicModel *)topic { _topic = topic; [self.progrssView setProgress:0.0 animated:NO]; [self.imageView sd_setImageWithURL:[NSURL URLWithString:topic.middle_image] placeholderImage:nil options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) { self.bigPicBtn.hidden = YES; self.baisiView.hidden = NO; CGFloat progress = 1.0 * receivedSize / expectedSize; self.progrssView.hidden = NO; self.progrssView.progressLabel.textColor = [UIColor whiteColor]; self.progrssView.roundedCorners = 3; self.progrssView.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",progress*100]; [self.progrssView setProgress:progress animated:YES]; } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { self.progrssView.hidden = YES; self.baisiView.hidden = YES; //判断是不是大图 if (topic.isBigImage) { //如果是的话,则截出图片的最上方铺满contentView // 开启图形上下文 UIGraphicsBeginImageContextWithOptions(self.imageView.size, YES, 0.0); // 将下载完的image对象绘制到图形上下文 CGFloat width = self.imageView.width; CGFloat height = width * image.size.height / image.size.width; [image drawInRect:CGRectMake(0, 0, width, height)]; // 获得图片 self.imageView.image = UIGraphicsGetImageFromCurrentImageContext(); // 结束图形上下文 UIGraphicsEndImageContext(); self.bigPicBtn.hidden = NO; } else { self.imageView.contentMode = UIViewContentModeScaleToFill; self.bigPicBtn.hidden = YES; } }]; self.gifView.hidden = ![topic.middle_image.pathExtension.lowercaseString isEqualToString:@"gif"]; } - (IBAction)bigBtn:(UIButton *)sender { [self showPicture]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentPictureView.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentVideoView.h ================================================ // // XFContentVideoView.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/24. // Copyright © 2016年 谢飞. All rights reserved. // #import @class XFTopicModel; @interface XFContentVideoView : UIView @property (nonatomic, strong) XFTopicModel *topic; +(instancetype)videoView; - (void)reset; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentVideoView.m ================================================ // // XFContentVideoView.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/24. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFContentVideoView.h" #import "XFDetailPictureController.h" #import "UIImageView+WebCache.h" #import #import "KRVideoPlayerController.h" @interface XFContentVideoView () @property (weak, nonatomic) IBOutlet UIImageView *imageView; @property (weak, nonatomic) IBOutlet UILabel *playCount; @property (weak, nonatomic) IBOutlet UILabel *playTime; @property (weak, nonatomic) IBOutlet UIButton *playBtn; @property (nonatomic, strong) KRVideoPlayerController *videoController; @end @implementation XFContentVideoView - (void)awakeFromNib { self.autoresizingMask = UIViewAutoresizingNone; self.imageView.userInteractionEnabled = YES; [self.imageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showPicture)]]; } +(instancetype)videoView { return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject]; } -(void)showPicture { XFDetailPictureController *showPicVc = [[XFDetailPictureController alloc]init]; showPicVc.topic = self.topic; [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:showPicVc animated:YES completion:nil]; } -(void)setTopic:(XFTopicModel *)topic { _topic = topic; self.playCount.text = [NSString stringWithFormat:@"%ld播放",(long)topic.playcount]; [self.imageView sd_setImageWithURL:[NSURL URLWithString:topic.middle_image]]; self.playTime.text = [NSString stringWithFormat:@"%02ld:%02ld", topic.videotime / 60, topic.videotime % 60]; } //播放按钮 - (IBAction)playBtn:(UIButton *)sender { [self playVideoWithURL:[NSURL URLWithString:self.topic.videouri]]; [self addSubview:self.videoController.view]; } - (void)playVideoWithURL:(NSURL *)url { if (!self.videoController) { self.videoController = [[KRVideoPlayerController alloc] initWithFrame:self.imageView.bounds]; __weak typeof(self)weakSelf = self; [self.videoController setDimissCompleteBlock:^{ weakSelf.videoController = nil; }]; } self.videoController.contentURL = url; } //停止视频的播放 - (void)reset { [self.videoController dismiss]; self.videoController = nil; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentVideoView.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentVoiceView.h ================================================ // // XFContentVoiceView.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/24. // Copyright © 2016年 谢飞. All rights reserved. // #import @class XFTopicModel; @interface XFContentVoiceView : UIView @property (nonatomic,strong) XFTopicModel *topic; +(instancetype)voiceView; -(void)reset; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentVoiceView.m ================================================ // // XFContentVoiceView.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/24. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFContentVoiceView.h" #import "XFDetailPictureController.h" #import "UIImageView+WebCache.h" #import #import #import "XFVociePlayerController.h" @interface XFContentVoiceView () @property (weak, nonatomic) IBOutlet UILabel *playCount; @property (weak, nonatomic) IBOutlet UILabel *playTime; @property (weak, nonatomic) IBOutlet UIButton *playBtn; @property (weak, nonatomic) IBOutlet UIImageView *imageView; @property (nonatomic,strong) XFVociePlayerController *voicePlayer; @end @implementation XFContentVoiceView - (void)awakeFromNib { self.autoresizingMask = UIViewAutoresizingNone; // 给图片添加监听器 self.imageView.userInteractionEnabled = YES; [self.imageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showPicture)]]; } +(instancetype)voiceView { return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject]; } -(void)showPicture { XFDetailPictureController *showPicVc = [[XFDetailPictureController alloc]init]; showPicVc.topic = self.topic; [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:showPicVc animated:YES completion:nil]; } -(void)setTopic:(XFTopicModel *)topic { _topic = topic; self.playCount.text = [NSString stringWithFormat:@"%ld播放",(long)topic.playcount]; [self.imageView sd_setImageWithURL:[NSURL URLWithString:topic.middle_image]]; self.playTime.text = [NSString stringWithFormat:@"%02ld:%02ld", topic.voicetime / 60, topic.voicetime % 60]; } //播放按钮 - (IBAction)playBtn:(UIButton *)sender { self.playBtn.hidden = YES; self.voicePlayer = [[XFVociePlayerController alloc]initWithNibName:@"XFVociePlayerController" bundle:nil]; self.voicePlayer.url = self.topic.voiceuri; self.voicePlayer.totalTime = self.topic.voicetime; self.voicePlayer.view.width = self.imageView.width; self.voicePlayer.view.y = self.imageView.height - self.voicePlayer.view.height; [self addSubview:self.voicePlayer.view]; } //重置 -(void)reset { [self.voicePlayer dismiss]; [self.voicePlayer.view removeFromSuperview]; self.voicePlayer = nil; self.playBtn.hidden = NO; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFContentVoiceView.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFTopicCell.h ================================================ // // XFTalkCell.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/22. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFTopicFrame.h" @interface XFTopicCell : UITableViewCell @property (nonatomic, strong) XFTopicFrame *topicFrame; + (instancetype)cell; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFTopicCell.m ================================================ // // XFTalkCell.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/22. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFTopicCell.h" #import "UIImageView+WebCache.h" #import "XFContentPictureView.h" #import "XFContentVideoView.h" #import "XFContentVoiceView.h" #import "XFUserModel.h" #import "XFCommentViewController.h" @interface XFTopicCell () @property (weak,nonatomic) IBOutlet UIImageView *avatar; @property (weak,nonatomic) IBOutlet UILabel *name; @property (weak,nonatomic) IBOutlet UILabel *creat_time; @property (weak,nonatomic) IBOutlet UIButton *dingBtn; @property (weak,nonatomic) IBOutlet UIButton *caiBtn; @property (weak,nonatomic) IBOutlet UIButton *shareBtn; @property (weak,nonatomic) IBOutlet UIButton *commenBtn; @property (weak,nonatomic) IBOutlet UILabel *text; @property (weak,nonatomic) IBOutlet UILabel *topCmtContentText; @property (weak,nonatomic) IBOutlet UIView *topCmtView; @property (strong,nonatomic) XFContentPictureView *pictureView; @property (strong,nonatomic) XFContentVideoView *videoView; @property (strong,nonatomic) XFContentVoiceView *voiceView; @end @implementation XFTopicCell // 从队列里面复用时调用 - (void)prepareForReuse { [super prepareForReuse]; [_videoView reset]; [_voiceView reset]; } + (instancetype)cell { return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] firstObject]; } -(void)setTopicFrame:(XFTopicFrame *)topicFrame { _topicFrame = topicFrame; XFTopicModel *topic = topicFrame.topic; [self.avatar setHeader:topic.profile_image]; self.name.text = topic.name; self.creat_time.text = topic.created_at; self.text.text = topic.text; [self.dingBtn setTitle:[NSString stringWithFormat:@"%ld",topic.ding] forState:UIControlStateNormal]; [self.caiBtn setTitle:[NSString stringWithFormat:@"%ld",topic.cai] forState:UIControlStateNormal]; [self.shareBtn setTitle:[NSString stringWithFormat:@"%ld",topic.repost] forState:UIControlStateNormal]; [self.commenBtn setTitle:[NSString stringWithFormat:@"%ld",topic.comment] forState:UIControlStateNormal]; // 处理最热评论 if (topic.top_cmt) { self.topCmtView.hidden = NO; self.topCmtContentText.text = [NSString stringWithFormat:@"%@ : %@", topic.top_cmt.user.username, topic.top_cmt.content]; } else { self.topCmtView.hidden = YES; } if (topic.type == TopicTypePicture) { self.pictureView.topic = topic; self.pictureView.frame = topicFrame.contentViewFrame; self.pictureView.hidden = NO; self.voiceView.hidden = YES; self.videoView.hidden = YES; } else if (topic.type == TopicTypeVideo) { self.videoView.topic = topic; self.videoView.frame = topicFrame.contentViewFrame; self.videoView.hidden = NO; self.pictureView.hidden = YES; self.voiceView.hidden = YES; } else if (topic.type == TopicTypeVoice) { self.voiceView.topic = topic; self.voiceView.frame = topicFrame.contentViewFrame; self.voiceView.hidden = NO; self.pictureView.hidden = YES; self.videoView.hidden = YES; } else { self.pictureView.hidden = YES; self.videoView.hidden = YES; self.voiceView.hidden = YES; } } //重新设置尺寸 -(void)setFrame:(CGRect)frame { CGFloat inset = 10; frame.size.height -= inset; frame.origin.y += inset; [super setFrame:frame]; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { } -(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { } //更多按钮 - (IBAction)moreBtn:(UIButton *)sender { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; UIAlertAction *save = [UIAlertAction actionWithTitle:@"收藏" style:UIAlertActionStyleDefault handler:nil]; UIAlertAction *report = [UIAlertAction actionWithTitle:@"举报" style:UIAlertActionStyleDefault handler:nil]; [alertController addAction:report]; [alertController addAction:cancel]; [alertController addAction:save]; [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil]; } //评论按钮 - (IBAction)commentBtn:(UIButton *)sender { NSDictionary *dic = [NSDictionary dictionaryWithObject:self.topicFrame forKey:@"topicFrame"]; [[NSNotificationCenter defaultCenter] postNotificationName:@"commentClick" object:nil userInfo:dic]; } -(void)dealloc { [[NSNotificationCenter defaultCenter]removeObserver:self forKeyPath:@"topicFrame"]; } #pragma mark - getter and setter - (XFContentPictureView *)pictureView { if (!_pictureView) { _pictureView = [XFContentPictureView pictureView]; [self.contentView addSubview:_pictureView]; } return _pictureView; } -(XFContentVideoView *)videoView { if (!_videoView) { _videoView = [XFContentVideoView videoView]; [self.contentView addSubview:_videoView]; } return _videoView; } - (XFContentVoiceView *)voiceView { if (!_voiceView) { _voiceView = [XFContentVoiceView voiceView]; [self.contentView addSubview:_voiceView]; } return _voiceView; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Essence/View/XFTopicCell.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Latest/Controller/XFLatestViewController.h ================================================ // // XFLatestViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "XFEssenceViewController.h" @interface XFLatestViewController : XFEssenceViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Latest/Controller/XFLatestViewController.m ================================================ // // XFLatestViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFLatestViewController.h" @interface XFLatestViewController () @end @implementation XFLatestViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/KRVideoPlayerController/KRVideoPlayerControlView.h ================================================ // // KRVideoPlayerControlView.h // KRKit // // Created by aidenluo on 5/23/15. // Copyright (c) 2015 36kr. All rights reserved. // #import @interface KRVideoPlayerControlView : UIView @property (nonatomic, strong, readonly) UIView *topBar; @property (nonatomic, strong, readonly) UIView *bottomBar; @property (nonatomic, strong, readonly) UIButton *playButton; @property (nonatomic, strong, readonly) UIButton *pauseButton; @property (nonatomic, strong, readonly) UIButton *fullScreenButton; @property (nonatomic, strong, readonly) UIButton *shrinkScreenButton; @property (nonatomic, strong, readonly) UISlider *progressSlider; @property (nonatomic, strong, readonly) UIButton *closeButton; @property (nonatomic, strong, readonly) UILabel *timeLabel; @property (nonatomic, strong, readonly) UIActivityIndicatorView *indicatorView; - (void)animateHide; - (void)animateShow; - (void)autoFadeOutControlBar; - (void)cancelAutoFadeOutControlBar; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/KRVideoPlayerController/KRVideoPlayerControlView.m ================================================ // // KRVideoPlayerControlView.m // KRKit // // Created by aidenluo on 5/23/15. // Copyright (c) 2015 36kr. All rights reserved. // #import "KRVideoPlayerControlView.h" static const CGFloat kVideoControlBarHeight = 40.0; static const CGFloat kVideoControlAnimationTimeinterval = 0.3; static const CGFloat kVideoControlTimeLabelFontSize = 10.0; static const CGFloat kVideoControlBarAutoFadeOutTimeinterval = 5.0; @interface KRVideoPlayerControlView () @property (nonatomic, strong) UIView *topBar; @property (nonatomic, strong) UIView *bottomBar; @property (nonatomic, strong) UIButton *playButton; @property (nonatomic, strong) UIButton *pauseButton; @property (nonatomic, strong) UIButton *fullScreenButton; @property (nonatomic, strong) UIButton *shrinkScreenButton; @property (nonatomic, strong) UISlider *progressSlider; @property (nonatomic, strong) UIButton *closeButton; @property (nonatomic, strong) UILabel *timeLabel; @property (nonatomic, assign) BOOL isBarShowing; @property (nonatomic, strong) UIActivityIndicatorView *indicatorView; @end @implementation KRVideoPlayerControlView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor clearColor]; [self addSubview:self.topBar]; [self.topBar addSubview:self.closeButton]; [self addSubview:self.bottomBar]; [self.bottomBar addSubview:self.playButton]; [self.bottomBar addSubview:self.pauseButton]; self.pauseButton.hidden = YES; [self.bottomBar addSubview:self.fullScreenButton]; [self.bottomBar addSubview:self.shrinkScreenButton]; self.shrinkScreenButton.hidden = YES; [self.bottomBar addSubview:self.progressSlider]; [self.bottomBar addSubview:self.timeLabel]; [self addSubview:self.indicatorView]; UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap:)]; [self addGestureRecognizer:tapGesture]; } return self; } - (void)layoutSubviews { [super layoutSubviews]; self.topBar.frame = CGRectMake(CGRectGetMinX(self.bounds), CGRectGetMinY(self.bounds), CGRectGetMaxX(self.bounds), kVideoControlBarHeight); self.closeButton.frame = CGRectMake(CGRectGetMaxX(self.bounds) - CGRectGetMaxX(self.closeButton.bounds), CGRectGetMinX(self.bounds), CGRectGetMaxX(self.closeButton.bounds), CGRectGetMaxY(self.closeButton.bounds)); self.bottomBar.frame = CGRectMake(CGRectGetMinX(self.bounds), CGRectGetMaxY(self.bounds) - kVideoControlBarHeight, CGRectGetMaxX(self.bounds), kVideoControlBarHeight); self.playButton.frame = CGRectMake(CGRectGetMinX(self.bottomBar.bounds), CGRectGetMaxY(self.bottomBar.bounds)/2 - CGRectGetMaxY(self.playButton.bounds)/2, CGRectGetMaxX(self.playButton.bounds), CGRectGetMaxY(self.playButton.bounds)); self.pauseButton.frame = self.playButton.frame; self.fullScreenButton.frame = CGRectMake(CGRectGetMaxX(self.bottomBar.bounds) - CGRectGetMaxX(self.fullScreenButton.bounds), CGRectGetMaxY(self.bottomBar.bounds)/2 - CGRectGetMaxY(self.fullScreenButton.bounds)/2, CGRectGetMaxX(self.fullScreenButton.bounds), CGRectGetMaxY(self.fullScreenButton.bounds)); self.shrinkScreenButton.frame = self.fullScreenButton.frame; self.progressSlider.frame = CGRectMake(CGRectGetMaxX(self.playButton.bounds), CGRectGetMaxY(self.bottomBar.bounds)/2 - CGRectGetMaxY(self.progressSlider.bounds)/2, CGRectGetMaxX(self.bounds) - CGRectGetMaxX(self.playButton.bounds) - CGRectGetMaxX(self.fullScreenButton.bounds), CGRectGetMaxY(self.progressSlider.bounds)); self.timeLabel.frame = CGRectMake(CGRectGetMidX(self.progressSlider.frame), CGRectGetMaxY(self.progressSlider.frame) + 2, CGRectGetMidX(self.progressSlider.frame), CGRectGetMaxY(self.timeLabel.bounds)); self.indicatorView.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); } - (void)didMoveToSuperview { [super didMoveToSuperview]; self.isBarShowing = YES; } - (void)animateHide { if (!self.isBarShowing) { return; } [UIView animateWithDuration:kVideoControlAnimationTimeinterval animations:^{ self.topBar.alpha = 0.0; self.bottomBar.alpha = 0.0; } completion:^(BOOL finished) { self.isBarShowing = NO; }]; } - (void)animateShow { if (self.isBarShowing) { return; } [UIView animateWithDuration:kVideoControlAnimationTimeinterval animations:^{ self.topBar.alpha = 1.0; self.bottomBar.alpha = 1.0; } completion:^(BOOL finished) { self.isBarShowing = YES; [self autoFadeOutControlBar]; }]; } - (void)autoFadeOutControlBar { if (!self.isBarShowing) { return; } [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(animateHide) object:nil]; [self performSelector:@selector(animateHide) withObject:nil afterDelay:kVideoControlBarAutoFadeOutTimeinterval]; } - (void)cancelAutoFadeOutControlBar { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(animateHide) object:nil]; } - (void)onTap:(UITapGestureRecognizer *)gesture { if (gesture.state == UIGestureRecognizerStateRecognized) { if (self.isBarShowing) { [self animateHide]; } else { [self animateShow]; } } } #pragma mark - Property - (UIView *)topBar { if (!_topBar) { _topBar = [UIView new]; _topBar.backgroundColor = [UIColor clearColor]; } return _topBar; } - (UIView *)bottomBar { if (!_bottomBar) { _bottomBar = [UIView new]; _bottomBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3]; } return _bottomBar; } - (UIButton *)playButton { if (!_playButton) { _playButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_playButton setImage:[UIImage imageNamed:[self videoImageName:@"kr-video-player-play"]] forState:UIControlStateNormal]; _playButton.bounds = CGRectMake(0, 0, kVideoControlBarHeight, kVideoControlBarHeight); } return _playButton; } - (UIButton *)pauseButton { if (!_pauseButton) { _pauseButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_pauseButton setImage:[UIImage imageNamed:[self videoImageName:@"kr-video-player-pause"]] forState:UIControlStateNormal]; _pauseButton.bounds = CGRectMake(0, 0, kVideoControlBarHeight, kVideoControlBarHeight); } return _pauseButton; } - (UIButton *)fullScreenButton { if (!_fullScreenButton) { _fullScreenButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_fullScreenButton setImage:[UIImage imageNamed:[self videoImageName:@"kr-video-player-fullscreen"]] forState:UIControlStateNormal]; _fullScreenButton.bounds = CGRectMake(0, 0, kVideoControlBarHeight, kVideoControlBarHeight); } return _fullScreenButton; } - (UIButton *)shrinkScreenButton { if (!_shrinkScreenButton) { _shrinkScreenButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_shrinkScreenButton setImage:[UIImage imageNamed:[self videoImageName:@"kr-video-player-shrinkscreen"]] forState:UIControlStateNormal]; _shrinkScreenButton.bounds = CGRectMake(0, 0, kVideoControlBarHeight, kVideoControlBarHeight); } return _shrinkScreenButton; } - (UISlider *)progressSlider { if (!_progressSlider) { _progressSlider = [[UISlider alloc] init]; [_progressSlider setThumbImage:[UIImage imageNamed:[self videoImageName:@"kr-video-player-point"]] forState:UIControlStateNormal]; [_progressSlider setMinimumTrackTintColor:[UIColor whiteColor]]; [_progressSlider setMaximumTrackTintColor:[UIColor lightGrayColor]]; _progressSlider.value = 0.f; _progressSlider.continuous = YES; } return _progressSlider; } - (UIButton *)closeButton { if (!_closeButton) { _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_closeButton setImage:[UIImage imageNamed:[self videoImageName:@"kr-video-player-close"]] forState:UIControlStateNormal]; _closeButton.bounds = CGRectMake(0, 0, kVideoControlBarHeight, kVideoControlBarHeight); } return _closeButton; } - (UILabel *)timeLabel { if (!_timeLabel) { _timeLabel = [UILabel new]; _timeLabel.backgroundColor = [UIColor clearColor]; _timeLabel.font = [UIFont systemFontOfSize:kVideoControlTimeLabelFontSize]; _timeLabel.textColor = [UIColor whiteColor]; _timeLabel.textAlignment = NSTextAlignmentRight; _timeLabel.bounds = CGRectMake(0, 0, kVideoControlTimeLabelFontSize, kVideoControlTimeLabelFontSize); } return _timeLabel; } - (UIActivityIndicatorView *)indicatorView { if (!_indicatorView) { _indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; [_indicatorView stopAnimating]; } return _indicatorView; } #pragma mark - Private Method - (NSString *)videoImageName:(NSString *)name { if (name) { NSString *path = [NSString stringWithFormat:@"%@",name]; return path; } return nil; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/KRVideoPlayerController/KRVideoPlayerController.h ================================================ // // KRVideoPlayerController.h // KRKit // // Created by aidenluo on 5/23/15. // Copyright (c) 2015 36kr. All rights reserved. // @import MediaPlayer; @interface KRVideoPlayerController : MPMoviePlayerController @property (nonatomic, copy)void(^dimissCompleteBlock)(void); @property (nonatomic, assign) CGRect frame; - (instancetype)initWithFrame:(CGRect)frame; - (void)showInWindow; - (void)dismiss; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/KRVideoPlayerController/KRVideoPlayerController.m ================================================ // // KRVideoPlayerController.m // KRKit // // Created by aidenluo on 5/23/15. // Copyright (c) 2015 36kr. All rights reserved. // #import "KRVideoPlayerController.h" #import "KRVideoPlayerControlView.h" static const CGFloat kVideoPlayerControllerAnimationTimeinterval = 0.3f; @interface KRVideoPlayerController () @property (nonatomic, strong) KRVideoPlayerControlView *videoControl; @property (nonatomic, strong) UIView *movieBackgroundView; @property (nonatomic, assign) BOOL isFullscreenMode; @property (nonatomic, assign) CGRect originFrame; @property (nonatomic, strong) NSTimer *durationTimer; @property (nonatomic, strong) UIView *originView; @end @implementation KRVideoPlayerController - (void)dealloc { [self cancelObserver]; } - (instancetype)initWithFrame:(CGRect)frame { self = [super init]; if (self) { self.view.frame = frame; self.view.backgroundColor = [UIColor blackColor]; self.controlStyle = MPMovieControlStyleNone; [self.view addSubview:self.videoControl]; self.videoControl.frame = self.view.bounds; [self configObserver]; [self configControlAction]; } return self; } #pragma mark - Override Method - (void)setContentURL:(NSURL *)contentURL { [self stop]; [super setContentURL:contentURL]; [self play]; } #pragma mark - Publick Method - (void)showInWindow { UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; if (!keyWindow) { keyWindow = [[[UIApplication sharedApplication] windows] firstObject]; } [keyWindow addSubview:self.view]; self.view.alpha = 0.0; [UIView animateWithDuration:kVideoPlayerControllerAnimationTimeinterval animations:^{ self.view.alpha = 1.0; } completion:^(BOOL finished) { }]; [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade]; } - (void)dismiss { [self stop]; [self stopDurationTimer]; [UIView animateWithDuration:kVideoPlayerControllerAnimationTimeinterval animations:^{ self.view.alpha = 0.0; } completion:^(BOOL finished) { [self.view removeFromSuperview]; if (self.dimissCompleteBlock) { self.dimissCompleteBlock(); } }]; [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade]; } #pragma mark - Private Method - (void)configObserver { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMPMoviePlayerPlaybackStateDidChangeNotification) name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMPMoviePlayerLoadStateDidChangeNotification) name:MPMoviePlayerLoadStateDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMPMoviePlayerReadyForDisplayDidChangeNotification) name:MPMoviePlayerReadyForDisplayDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMPMovieDurationAvailableNotification) name:MPMovieDurationAvailableNotification object:nil]; } - (void)cancelObserver { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)configControlAction { [self.videoControl.playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside]; [self.videoControl.pauseButton addTarget:self action:@selector(pauseButtonClick) forControlEvents:UIControlEventTouchUpInside]; [self.videoControl.closeButton addTarget:self action:@selector(closeButtonClick) forControlEvents:UIControlEventTouchUpInside]; [self.videoControl.fullScreenButton addTarget:self action:@selector(fullScreenButtonClick) forControlEvents:UIControlEventTouchUpInside]; [self.videoControl.shrinkScreenButton addTarget:self action:@selector(shrinkScreenButtonClick) forControlEvents:UIControlEventTouchUpInside]; [self.videoControl.progressSlider addTarget:self action:@selector(progressSliderValueChanged:) forControlEvents:UIControlEventValueChanged]; [self.videoControl.progressSlider addTarget:self action:@selector(progressSliderTouchBegan:) forControlEvents:UIControlEventTouchDown]; [self.videoControl.progressSlider addTarget:self action:@selector(progressSliderTouchEnded:) forControlEvents:UIControlEventTouchUpInside]; [self.videoControl.progressSlider addTarget:self action:@selector(progressSliderTouchEnded:) forControlEvents:UIControlEventTouchUpOutside]; [self setProgressSliderMaxMinValues]; [self monitorVideoPlayback]; } - (void)onMPMoviePlayerPlaybackStateDidChangeNotification { if (self.playbackState == MPMoviePlaybackStatePlaying) { self.videoControl.pauseButton.hidden = NO; self.videoControl.playButton.hidden = YES; [self startDurationTimer]; [self.videoControl.indicatorView stopAnimating]; [self.videoControl autoFadeOutControlBar]; } else { self.videoControl.pauseButton.hidden = YES; self.videoControl.playButton.hidden = NO; [self stopDurationTimer]; if (self.playbackState == MPMoviePlaybackStateStopped) { [self.videoControl animateShow]; } } } - (void)onMPMoviePlayerLoadStateDidChangeNotification { if (self.loadState & MPMovieLoadStateStalled) { [self.videoControl.indicatorView startAnimating]; } } - (void)onMPMoviePlayerReadyForDisplayDidChangeNotification { } - (void)onMPMovieDurationAvailableNotification { [self setProgressSliderMaxMinValues]; } - (void)playButtonClick { [self play]; self.videoControl.playButton.hidden = YES; self.videoControl.pauseButton.hidden = NO; } - (void)pauseButtonClick { [self pause]; self.videoControl.playButton.hidden = NO; self.videoControl.pauseButton.hidden = YES; } - (void)closeButtonClick { [self dismiss]; } - (void)fullScreenButtonClick { if (self.isFullscreenMode) { return; } self.originFrame = self.view.frame; CGFloat height = [[UIScreen mainScreen] bounds].size.width; CGFloat width = [[UIScreen mainScreen] bounds].size.height; CGRect frame = CGRectMake((height - width) / 2, (width - height) / 2, width, height); UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; if (!keyWindow) { keyWindow = [[[UIApplication sharedApplication] windows] firstObject]; } self.originView = self.view.superview; [keyWindow addSubview:self.view]; [UIView animateWithDuration:0.3f animations:^{ self.frame = frame; [self.view setTransform:CGAffineTransformMakeRotation(M_PI_2)]; } completion:^(BOOL finished) { self.isFullscreenMode = YES; self.videoControl.fullScreenButton.hidden = YES; self.videoControl.shrinkScreenButton.hidden = NO; }]; } - (void)shrinkScreenButtonClick { if (!self.isFullscreenMode) { return; } [self.originView addSubview:self.view]; [UIView animateWithDuration:0.2f animations:^{ [self.view setTransform:CGAffineTransformIdentity]; self.frame = self.originFrame; } completion:^(BOOL finished) { self.isFullscreenMode = NO; self.videoControl.fullScreenButton.hidden = NO; self.videoControl.shrinkScreenButton.hidden = YES; }]; } - (void)setProgressSliderMaxMinValues { CGFloat duration = self.duration; self.videoControl.progressSlider.minimumValue = 0.f; self.videoControl.progressSlider.maximumValue = duration; } - (void)progressSliderTouchBegan:(UISlider *)slider { [self pause]; [self.videoControl cancelAutoFadeOutControlBar]; } - (void)progressSliderTouchEnded:(UISlider *)slider { [self setCurrentPlaybackTime:floor(slider.value)]; [self play]; [self.videoControl autoFadeOutControlBar]; } - (void)progressSliderValueChanged:(UISlider *)slider { double currentTime = floor(slider.value); double totalTime = floor(self.duration); [self setTimeLabelValues:currentTime totalTime:totalTime]; } - (void)monitorVideoPlayback { double currentTime = floor(self.currentPlaybackTime); double totalTime = floor(self.duration); [self setTimeLabelValues:currentTime totalTime:totalTime]; self.videoControl.progressSlider.value = ceil(currentTime); } - (void)setTimeLabelValues:(double)currentTime totalTime:(double)totalTime { double minutesElapsed = floor(currentTime / 60.0); double secondsElapsed = fmod(currentTime, 60.0); NSString *timeElapsedString = [NSString stringWithFormat:@"%02.0f:%02.0f", minutesElapsed, secondsElapsed]; double minutesRemaining = floor(totalTime / 60.0);; double secondsRemaining = floor(fmod(totalTime, 60.0));; NSString *timeRmainingString = [NSString stringWithFormat:@"%02.0f:%02.0f", minutesRemaining, secondsRemaining]; self.videoControl.timeLabel.text = [NSString stringWithFormat:@"%@/%@",timeElapsedString,timeRmainingString]; } - (void)startDurationTimer { self.durationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(monitorVideoPlayback) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:self.durationTimer forMode:NSDefaultRunLoopMode]; } - (void)stopDurationTimer { [self.durationTimer invalidate]; } - (void)fadeDismissControl { [self.videoControl animateHide]; } #pragma mark - Property - (KRVideoPlayerControlView *)videoControl { if (!_videoControl) { _videoControl = [[KRVideoPlayerControlView alloc] init]; } return _videoControl; } - (UIView *)movieBackgroundView { if (!_movieBackgroundView) { _movieBackgroundView = [UIView new]; _movieBackgroundView.alpha = 0.0; _movieBackgroundView.backgroundColor = [UIColor blackColor]; } return _movieBackgroundView; } - (void)setFrame:(CGRect)frame { [self.view setFrame:frame]; [self.videoControl setFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; [self.videoControl setNeedsLayout]; [self.videoControl layoutIfNeeded]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/KRVideoPlayerController/XFVociePlayerController.h ================================================ // // XFVociePlayerController.h // XFBaiSiBuDeJie // // Created by Fay on 16/3/15. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFVociePlayerController : UIViewController @property (nonatomic,copy) NSString *url; @property (nonatomic,assign) NSInteger totalTime; -(void)dismiss; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/KRVideoPlayerController/XFVociePlayerController.m ================================================ // // XFVociePlayerController.m // XFBaiSiBuDeJie // // Created by Fay on 16/3/15. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFVociePlayerController.h" #import "NSString+XFTime.h" @interface XFVociePlayerController () @property (weak, nonatomic) IBOutlet UIButton *playBtn; @property (weak, nonatomic) IBOutlet UILabel *restTime; @property (weak, nonatomic) IBOutlet UILabel *playTime; @property (weak, nonatomic) IBOutlet UISlider *progress; //播放器 @property (nonatomic,strong)MPMoviePlayerController *player; /** 进度的Timer */ @property (nonatomic, strong) NSTimer *progressTimer; //slider 事件处理 - (IBAction)startSlide; - (IBAction)sliderValueChange; - (IBAction)endSlide; - (IBAction)sliderClick:(UITapGestureRecognizer *)sender; //暂停 - (IBAction)pause; @end @implementation XFVociePlayerController -(void)viewDidLoad { [self.progress setThumbImage:[UIImage imageNamed:@"kr-video-player-point"] forState:UIControlStateNormal]; [self startPlayingMusic]; self.playTime.text = [NSString stringWithTime:self.totalTime]; _player = [[MPMoviePlayerController alloc]initWithContentURL:[NSURL URLWithString:self.url]]; [self.player play]; } //开始播放音乐 - (void)startPlayingMusic { [self removeProgressTimer]; [self addProgressTimer]; } //添加定时器 - (void)addProgressTimer { [self updateProgressInfo]; self.progressTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateProgressInfo) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:self.progressTimer forMode:NSRunLoopCommonModes]; } #pragma mark - 更新进度的界面 - (void)updateProgressInfo { // 1.设置当前的播放时间 self.restTime.text = [NSString stringWithTime:self.player.currentPlaybackTime]; // 2.更新滑块的位置 self.progress.value = self.player.currentPlaybackTime / self.player.duration; } #pragma mark - Slider的事件处理 - (IBAction)startSlide { [self removeProgressTimer]; } - (IBAction)sliderValueChange { // 设置当前播放的时间Label self.restTime.text = [NSString stringWithTime:self.player.duration * self.progress.value]; } - (IBAction)endSlide { // 1.设置歌曲的播放时间 self.player.currentPlaybackTime = self.progress.value * self.player.duration; // 2.添加定时器 [self addProgressTimer]; } - (IBAction)sliderClick:(UITapGestureRecognizer *)sender { // 1.获取点击的位置 CGPoint point = [sender locationInView:sender.view]; // 2.获取点击的在slider长度中占据的比例 CGFloat ratio = point.x / self.progress.bounds.size.width; // 3.改变歌曲播放的时间 self.player.currentPlaybackTime = ratio * self.player.duration; // 4.更新进度信息 [self updateProgressInfo]; } //暂停 - (IBAction)pause { self.playBtn.selected = !self.playBtn.selected; if (self.playBtn.selected) { [self.player pause]; [self removeProgressTimer]; } else { [self.player play]; [self addProgressTimer]; } } //移除定时器 - (void)removeProgressTimer { [self.progressTimer invalidate]; self.progressTimer = nil; } -(void)dismiss { [self removeProgressTimer]; [self.player stop]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/KRVideoPlayerController/XFVociePlayerController.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/Tool/HttpTool.h ================================================ // // HttpTool.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface HttpTool : NSObject +(void)get:(NSString *)url parameters:(NSDictionary *)parameters success:(void (^)(id json))success failure:(void (^)(NSError *error))failure; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Lib/Tool/HttpTool.m ================================================ // // HttpTool.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import "HttpTool.h" #import "AFNetworking.h" @implementation HttpTool +(void)get:(NSString *)url parameters:(NSDictionary *)parameters success:(void (^)(id json))success failure:(void (^)(NSError *error))failure { //显示状态栏的网络指示器 [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; AFHTTPSessionManager *mgr = [self manager]; //设置加载时间 mgr.requestSerializer.timeoutInterval = 10.0f; [mgr GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) { nil; } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; success(responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; failure(error); }]; } + (AFHTTPSessionManager *)manager { static AFHTTPSessionManager *manager = nil; if (manager == nil) { manager = [AFHTTPSessionManager manager]; } return manager; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Main/Controller/XFNavigationController.h ================================================ // // XFNavigationController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFNavigationController : UINavigationController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Main/Controller/XFNavigationController.m ================================================ // // XFNavigationController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/18. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFNavigationController.h" @interface XFNavigationController() @property (nonatomic,strong) UIButton *backBtn; @end @interface XFNavigationController () @end @implementation XFNavigationController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } //只初始化一次 + (void)initialize { UIImage *background = [UIImage imageNamed:@"navigationbarBackgroundWhite"]; //设置导航条 UINavigationBar *bar = [UINavigationBar appearance]; [bar setBackgroundImage:background forBarMetrics:UIBarMetricsDefault]; [bar setTitleTextAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:20]}]; } //拦截push进来的控制器 -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{ if (self.childViewControllers.count) { viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:self.backBtn]; viewController.hidesBottomBarWhenPushed = YES; } //如果在控制器有设置,就可以让后面设置的按钮可以覆盖它 [super pushViewController:viewController animated:animated]; } - (UIButton *)backBtn{ if (_backBtn == nil) { _backBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [_backBtn setImage:[UIImage imageNamed:@"navigationButtonReturn"] forState:UIControlStateNormal]; [_backBtn setImage:[UIImage imageNamed:@"navigationButtonReturnClick"] forState:UIControlStateHighlighted]; [_backBtn setTitle:@"返回" forState:UIControlStateNormal]; [_backBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_backBtn setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted]; _backBtn.titleLabel.font = [UIFont systemFontOfSize:15]; _backBtn.contentEdgeInsets = UIEdgeInsetsMake(0, -5, 0, 0); [_backBtn sizeToFit]; [[_backBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { [self popViewControllerAnimated:YES]; }]; } return _backBtn; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Main/Controller/XFTabBarViewController.h ================================================ // // XFTabBarViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFTabBarViewController : UITabBarController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Main/Controller/XFTabBarViewController.m ================================================ // // XFTabBarViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFTabBarViewController.h" #import "XFConcernViewController.h" #import "XFEssenceViewController.h" #import "XFLatestViewController.h" #import "XFMeViewController.h" #import "XFTabBar.h" #import "XFNavigationController.h" @interface XFTabBarViewController () @end @implementation XFTabBarViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self initialControllers]; //替换系统tabbar [self setValue:[[XFTabBar alloc] init] forKeyPath:@"tabBar"]; } //初始化子控制器 -(void)initialControllers { [self setupController:[[XFEssenceViewController alloc]init] image:@"tabBar_essence_icon" selectedImage:@"tabBar_essence_click_icon" title:@"精华"]; [self setupController:[[XFLatestViewController alloc]init] image:@"tabBar_new_icon" selectedImage:@"tabBar_new_click_icon" title:@"最新"]; [self setupController:[[XFConcernViewController alloc]init] image:@"tabBar_friendTrends_icon" selectedImage:@"tabBar_friendTrends_click_icon" title:@"关注"]; [self setupController:[[XFMeViewController alloc]init] image:@"tabBar_me_icon" selectedImage:@"tabBar_me_click_icon" title:@"我"]; } //设置控制器 -(void)setupController:(UIViewController *)childVc image:(NSString *)image selectedImage:(NSString *)selectedImage title:(NSString *)title { UIViewController *viewVc = childVc; viewVc.tabBarItem.image = [UIImage imageNamed:image]; viewVc.tabBarItem.selectedImage = [UIImage imageNamed:selectedImage]; viewVc.tabBarItem.title = title; XFNavigationController *navi = [[XFNavigationController alloc]initWithRootViewController:viewVc]; [self addChildViewController:navi]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Main/View/XFPublishView.h ================================================ // // XFPublishView.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/25. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFPublishView : UIView +(instancetype)publishView; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Main/View/XFPublishView.m ================================================ // // XFPublishView.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/25. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFPublishView.h" #import "XFShowWordBtn.h" @interface XFPublishView () @property (weak, nonatomic) IBOutlet NSLayoutConstraint *slogaTop; @end @implementation XFPublishView +(instancetype)publishView { return [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject]; } -(void)awakeFromNib { NSArray *images = @[@"publish-video", @"publish-picture", @"publish-text", @"publish-audio", @"publish-review", @"publish-offline"]; NSArray *titles = @[@"发视频", @"发图片", @"发段子", @"发声音", @"审帖", @"发链接"]; NSInteger maxCols = 3; CGFloat buttonW = 70; CGFloat buttonH = 100; CGFloat startY = SCREEN_HEIGHT*0.4; CGFloat startX = 20; CGFloat margin = (SCREEN_WIDTH - 2*startX - maxCols*buttonW) / 2; for (NSInteger i = 0; i ================================================ FILE: XFBaiSiBuDeJie/Classes/Main/View/XFTabBar.h ================================================ // // XFTabBar.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFTabBar : UITabBar @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Main/View/XFTabBar.m ================================================ // // XFTabBar.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFTabBar.h" #import "XFPublishView.h" @interface XFTabBar () @property (nonatomic,strong) UIButton *publishBtn; @end @implementation XFTabBar -(instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { //设置tabbar的文字颜色 UITabBarItem *appearance = [UITabBarItem appearance]; [appearance setTitleTextAttributes:@{ NSForegroundColorAttributeName : [UIColor darkGrayColor]} forState:UIControlStateSelected]; [self setBackgroundImage:[UIImage imageNamed:@"tabbar-light"]]; UIButton *publishBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [publishBtn setBackgroundImage:[UIImage imageNamed:@"tabBar_publish_icon"] forState:UIControlStateNormal]; [publishBtn setBackgroundImage:[UIImage imageNamed:@"tabBar_publish_click_icon"] forState:UIControlStateHighlighted]; publishBtn.size = publishBtn.currentBackgroundImage.size; [[publishBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { XFPublishView *publishView = [XFPublishView publishView]; publishView.frame = SCREEN_FRAME; UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; [keyWindow addSubview:publishView]; }]; self.publishBtn = publishBtn; [self addSubview:_publishBtn]; } return self; } //重新设置按钮的位置 -(void)layoutSubviews { [super layoutSubviews]; CGFloat width = self.width; CGFloat height = self.height; NSInteger index = 0; CGFloat btnW = width / 5; CGFloat btnH = height; CGFloat btnY = 0; //发布按钮位置 self.publishBtn.center = CGPointMake(width/2, height/2); //遍历取出按钮 for (UIView *view in self.subviews) { if (![view isKindOfClass:[UIControl class]] || view == self.publishBtn) continue; { CGFloat btnX = (index > 1 ? (index +1) : index) *btnW; view.frame = CGRectMake(btnX, btnY, btnW, btnH); index++; } } } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Me/Controller/XFMeViewController.h ================================================ // // XFMeViewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFMeViewController : UIViewController @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Me/Controller/XFMeViewController.m ================================================ // // XFMeViewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFMeViewController.h" #import "XFMeCell.h" #import "XFSquareCell.h" #import "XFSquare.h" #import "XFSquareTool.h" #import "XFSquareFooterView.h" static NSString *const meCellID = @"me"; static NSString *const squareCellID = @"square"; @interface XFMeViewController () @property (nonatomic,strong) UIButton *moonBtn; @property (nonatomic,strong) UIButton *settingBtn; @property (nonatomic,strong) XFSquareTool *tool; @property (nonatomic,strong) UIButton *btnRight; @property (nonatomic,strong) UIButton *btnLeft; @property (nonatomic,strong) UIView *verticalLine; @property (nonatomic,strong) UITableView *tableView; @end @implementation XFMeViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self setNaviItems]; [self setupTableView]; } //设置tableView -(void)setupTableView { [self.view addSubview:self.tableView]; // 设置背景色 self.tableView.backgroundColor = BackgroundColor; [self.tableView registerClass:[XFMeCell class] forCellReuseIdentifier:meCellID]; [self.tableView registerClass:[XFSquareCell class] forCellReuseIdentifier:squareCellID]; // 调整header和footer self.tableView.sectionHeaderHeight = 0; self.tableView.sectionFooterHeight = 10; // 调整inset self.tableView.contentInset = UIEdgeInsetsMake(-25, 0, 0, 0); self.tableView.tableFooterView = [[XFSquareFooterView alloc]init]; //frame 刚开始是0 [[RACObserve(self.tableView.tableFooterView, frame) distinctUntilChanged] subscribeNext:^(id x) { self.tableView.tableFooterView = self.tableView.tableFooterView; }]; } //设置导航按钮 -(void)setNaviItems { self.title = @"我的"; self.navigationItem.rightBarButtonItems = @[ [[UIBarButtonItem alloc]initWithCustomView:self.settingBtn], [[UIBarButtonItem alloc]initWithCustomView:self.moonBtn] ]; } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 1; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 3; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { XFMeCell *cell = [tableView dequeueReusableCellWithIdentifier:meCellID]; if (indexPath.section == 0) { cell.imageView.image = [UIImage imageNamed:@"setup-head-default"]; cell.textLabel.text = @"登录/注册"; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } else if (indexPath.section == 1) { cell.textLabel.text = @"离线下载"; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } else if (indexPath.section == 2) { [cell addSubview:self.btnLeft]; [cell addSubview:self.btnRight]; [cell addSubview:self.verticalLine]; } return cell; } #pragma mark - getter and setter - (UIButton *)moonBtn{ if (_moonBtn == nil) { _moonBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [_moonBtn setBackgroundImage:[UIImage imageNamed:@"mine-moon-icon"] forState:UIControlStateNormal]; [_moonBtn setBackgroundImage:[UIImage imageNamed:@"mine-moon-icon-click"] forState:UIControlStateHighlighted]; _moonBtn.size = _moonBtn.currentBackgroundImage.size; } return _moonBtn; } - (UIButton *)settingBtn{ if (_settingBtn == nil) { _settingBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [_settingBtn setBackgroundImage:[UIImage imageNamed:@"mine-setting-icon"] forState:UIControlStateNormal]; [_settingBtn setBackgroundImage:[UIImage imageNamed:@"mine-setting-icon-click"] forState:UIControlStateHighlighted]; _settingBtn.size = _settingBtn.currentBackgroundImage.size; } return _settingBtn; } - (UIButton *)btnLeft{ if (_btnLeft == nil) { _btnLeft = [[UIButton alloc]init]; _btnLeft.frame = CGRectMake(0, 0, SCREEN_WIDTH/2, 44); [_btnLeft setTitle:@"#自拍#" forState:UIControlStateNormal]; _btnLeft.titleLabel.font = [UIFont systemFontOfSize:15]; [_btnLeft setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal]; [[_btnLeft rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { }]; } return _btnLeft; } - (UIButton *)btnRight{ if (_btnRight == nil) { _btnRight = [[UIButton alloc]init]; _btnRight.frame = CGRectMake(SCREEN_WIDTH/2, 0,SCREEN_WIDTH/2, 44); [_btnRight setTitle:@"#我是段子手#" forState:UIControlStateNormal]; _btnRight.titleLabel.font = [UIFont systemFontOfSize:15]; [_btnRight setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal]; [[_btnRight rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) { }]; } return _btnRight; } - (UIView *)verticalLine{ if (_verticalLine == nil) { _verticalLine = [[UIView alloc]init]; _verticalLine.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.3]; _verticalLine.frame = CGRectMake(SCREEN_WIDTH/2, 2, 0.5, 40); } return _verticalLine; } - (UITableView *)tableView{ if (_tableView == nil) { _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) style:UITableViewStyleGrouped]; _tableView.showsVerticalScrollIndicator = NO; _tableView.dataSource = self; } return _tableView; } - (XFSquareTool *)tool{ if (_tool == nil) { _tool = [[XFSquareTool alloc]init]; } return _tool; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Me/Controller/XFWebviewController.h ================================================ // // XFWebviewController.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFWebviewController : UIViewController @property (nonatomic, copy) NSString *url; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Me/Controller/XFWebviewController.m ================================================ // // XFWebviewController.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFWebviewController.h" #import "NJKWebViewProgressView.h" #import "NJKWebViewProgress.h" @interface XFWebviewController () @property (nonatomic,strong)NJKWebViewProgress *progressProxy; @property (nonatomic,strong)NJKWebViewProgressView *progressView; @property (nonatomic,strong)UIWebView *webView; @end @implementation XFWebviewController -(void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.webView]; [self.webView addSubview:self.progressView]; } #pragma mark - NJKWebViewProgressDelegate -(void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress { [self.progressView setProgress:progress animated:NO]; } - (NJKWebViewProgress *)progressProxy{ if (_progressProxy == nil) { _progressProxy = [[NJKWebViewProgress alloc]init]; _progressProxy.webViewProxyDelegate = self; _progressProxy.progressDelegate = self; } return _progressProxy; } - (UIWebView *)webView{ if (_webView == nil) { _webView = [[UIWebView alloc]init]; _webView.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); [_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.url]]]; _webView.delegate = self.progressProxy; } return _webView; } - (NJKWebViewProgressView *)progressView{ if (_progressView == nil) { _progressView = [[NJKWebViewProgressView alloc]init]; _progressView.frame = CGRectMake(0, 64, SCREEN_WIDTH, 2); [_progressView setProgress:0 animated:NO]; } return _progressView; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Me/View/XFSquareFooterView.h ================================================ // // XFSquareFooterView.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFSquareFooterView : UIView @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Me/View/XFSquareFooterView.m ================================================ // // XFSquareFooterView.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/3/4. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFSquareFooterView.h" #import "XFSquareTool.h" #import "XFSquareButton.h" #import "XFWebviewController.h" @implementation XFSquareFooterView -(instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor whiteColor]; [self createItems]; } return self; } //创建按钮 -(void)createItems { //一共4列 NSInteger maxCols = 4; CGFloat btnW = SCREEN_WIDTH / 4; CGFloat btnH = btnW; XFSquareTool *tool = [[XFSquareTool alloc]init]; NSLog(@"1"); [tool getSquareData:^(NSArray *squareItems) { for (NSInteger i = 0; i < squareItems.count; i++) { XFSquareButton *button = [[XFSquareButton alloc]init]; button.square = squareItems[i]; NSInteger col = i % maxCols;//第几列 NSInteger row = i / maxCols;//第几行 CGFloat btnX = col * btnW; CGFloat btnY = row * btnH; button.frame = CGRectMake(btnX, btnY, btnW, btnH); [self addSubview:button]; [[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(XFSquareButton *button) { if (![button.square.url hasPrefix:@"http"]) return; XFWebviewController *web = [[XFWebviewController alloc]init]; web.url = button.square.url; web.title = button.square.name; // 取出当前的导航控制器 UITabBarController *tabBarVc = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController; UINavigationController *nav = (UINavigationController *)tabBarVc.selectedViewController; [nav pushViewController:web animated:YES]; }]; } //算出footer的高度 self.height = (squareItems.count + maxCols - 1)/maxCols * btnH; [self setNeedsDisplay]; }]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Other/PrefixHeader.pch ================================================ // // PrefixHeader.pch // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #ifndef PrefixHeader_pch #define PrefixHeader_pch #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height #define SCREEN_FRAME [UIScreen mainScreen].bounds #define GLOBALCOLOR(r,g,b,a) [UIColor colorWithRed:r/255.f green:g/255.f blue:b/255.f alpha:1] //背景色 #define BackgroundColor GLOBALCOLOR(229, 229, 229,1) #define BaseURL @"http://api.budejie.com/api/api_open.php" #import "ReactiveCocoa.h" #import "UIView+Extension.h" #import "UIImage+XFCircle.h" #import "UIImageView+Header.h" typedef NS_ENUM(NSUInteger, TopicType) { TopicTypeAll = 1, // 全部 TopicTypePicture = 10, // 图片 TopicTypeTalk = 29, // 段子 TopicTypeVoice = 31, // 声音 TopicTypeVideo = 41 // 视频 }; #endif /* PrefixHeader_pch */ ================================================ FILE: XFBaiSiBuDeJie/Classes/Other/View/XFGuideView.h ================================================ // // XFGuideView.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFGuideView : UIView + (instancetype)guideView; @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Other/View/XFGuideView.m ================================================ // // XFGuideView.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/21. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFGuideView.h" @implementation XFGuideView +(instancetype)guideView { return [[[NSBundle mainBundle]loadNibNamed:@"XFGuideView" owner:self options:nil] lastObject]; } - (IBAction)closeBtn:(UIButton *)sender { [self removeFromSuperview]; } @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Other/View/XFGuideView.xib ================================================ ================================================ FILE: XFBaiSiBuDeJie/Classes/Other/View/XFShowWordBtn.h ================================================ // // XFShowWordBtn.h // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import @interface XFShowWordBtn : UIButton @end ================================================ FILE: XFBaiSiBuDeJie/Classes/Other/View/XFShowWordBtn.m ================================================ // // XFShowWordBtn.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/20. // Copyright © 2016年 谢飞. All rights reserved. // #import "XFShowWordBtn.h" @implementation XFShowWordBtn - (void)awakeFromNib { self.titleLabel.textAlignment = NSTextAlignmentCenter; } -(void)layoutSubviews { [super layoutSubviews]; // 调整图片 self.imageView.x = 0; self.imageView.y = 0; self.imageView.width = self.width; self.imageView.height = self.imageView.width; //调整文字 self.titleLabel.x = 0; self.titleLabel.y = self.imageView.height + 5; self.titleLabel.width = self.width; self.titleLabel.height = self.height - self.imageView.height; } @end ================================================ FILE: XFBaiSiBuDeJie/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS NSAppTransportSecurity NSAllowsArbitraryLoads UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait ================================================ FILE: XFBaiSiBuDeJie/main.m ================================================ // // main.m // XFBaiSiBuDeJie // // Created by 谢飞 on 16/2/17. // Copyright © 2016年 谢飞. All rights reserved. // #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: XFBaiSiBuDeJie.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 650742731C8570720069A37A /* XFCommentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 650742711C8570720069A37A /* XFCommentViewController.m */; }; 650742741C8570720069A37A /* XFCommentViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 650742721C8570720069A37A /* XFCommentViewController.xib */; }; 650742781C8580BA0069A37A /* XFCommentCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 650742761C8580BA0069A37A /* XFCommentCell.m */; }; 650742791C8580BA0069A37A /* XFCommentCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 650742771C8580BA0069A37A /* XFCommentCell.xib */; }; 6525F16A1C982E46006BCD89 /* NSString+XFTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 6525F1691C982E46006BCD89 /* NSString+XFTime.m */; }; 6525F16E1C991641006BCD89 /* HttpTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 6525F16D1C991641006BCD89 /* HttpTool.m */; }; 6525F1721C991650006BCD89 /* XFVociePlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6525F1701C991650006BCD89 /* XFVociePlayerController.m */; }; 6525F1731C991650006BCD89 /* XFVociePlayerController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6525F1711C991650006BCD89 /* XFVociePlayerController.xib */; }; 652CB2711C78E1B20027B71B /* XFGuideView.m in Sources */ = {isa = PBXBuildFile; fileRef = 652CB2701C78E1B20027B71B /* XFGuideView.m */; }; 652CB2731C78E1C00027B71B /* XFGuideView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 652CB2721C78E1C00027B71B /* XFGuideView.xib */; }; 65752E301C7C9E120005CCB2 /* XFContentPictureView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65752E2F1C7C9E120005CCB2 /* XFContentPictureView.m */; }; 65752E321C7C9E3F0005CCB2 /* XFContentPictureView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65752E311C7C9E3F0005CCB2 /* XFContentPictureView.xib */; }; 65752E351C7D8F7C0005CCB2 /* XFTopicFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 65752E341C7D8F7C0005CCB2 /* XFTopicFrame.m */; }; 65752E381C7D9DBC0005CCB2 /* XFContentVoiceView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65752E371C7D9DBC0005CCB2 /* XFContentVoiceView.m */; }; 65752E3B1C7D9DCD0005CCB2 /* XFContentVideoView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65752E3A1C7D9DCD0005CCB2 /* XFContentVideoView.m */; }; 657E659C1C89DBD2005D6D8E /* XFWebviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 657E659B1C89DBD2005D6D8E /* XFWebviewController.m */; }; 65A2845B1C79956800D8031B /* XFVocieViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A2845A1C79956800D8031B /* XFVocieViewController.m */; }; 65A2845E1C79957D00D8031B /* XFPictrueViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A2845D1C79957D00D8031B /* XFPictrueViewController.m */; }; 65A284611C79958800D8031B /* XFVideoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A284601C79958800D8031B /* XFVideoViewController.m */; }; 65A284641C7995BD00D8031B /* XFTalkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A284631C7995BD00D8031B /* XFTalkViewController.m */; }; 65A284671C799A9400D8031B /* XFAllViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A284661C799A9400D8031B /* XFAllViewController.m */; }; 65A2846A1C7B2DE500D8031B /* XFModuleDataTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A284691C7B2DE500D8031B /* XFModuleDataTool.m */; }; 65A2846D1C7B33E700D8031B /* XFTopicModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A2846C1C7B33E700D8031B /* XFTopicModel.m */; }; 65A284711C7B355D00D8031B /* XFTopicCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A2846F1C7B355D00D8031B /* XFTopicCell.m */; }; 65A284721C7B355D00D8031B /* XFTopicCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65A284701C7B355D00D8031B /* XFTopicCell.xib */; }; 65A2AB4E1C8F01B500BF2B8F /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65A2AB4A1C8EE2FA00BF2B8F /* AVFoundation.framework */; }; 65A2AB4F1C8F01BE00BF2B8F /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65A2AB481C8EC99F00BF2B8F /* MediaPlayer.framework */; }; 65A2AB5E1C8FF15700BF2B8F /* KRVideoPlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A2AB5B1C8FF15700BF2B8F /* KRVideoPlayerController.m */; }; 65A2AB5F1C8FF15700BF2B8F /* KRVideoPlayerControlView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65A2AB5D1C8FF15700BF2B8F /* KRVideoPlayerControlView.m */; }; 65A2AB611C91A8C700BF2B8F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65A2AB601C91A8C700BF2B8F /* AudioToolbox.framework */; }; 65AD116E1C83208300E994F1 /* XFContentVoiceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65AD116D1C83208300E994F1 /* XFContentVoiceView.xib */; }; 65AD11731C833C0C00E994F1 /* XFContentVideoView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65AD11721C833C0C00E994F1 /* XFContentVideoView.xib */; }; 65AD11761C8362C700E994F1 /* XFUserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11751C8362C700E994F1 /* XFUserModel.m */; }; 65AD11791C8362D300E994F1 /* XFCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11781C8362D300E994F1 /* XFCommentModel.m */; }; 65AD11941C84D18600E994F1 /* XFConcernViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65AD11811C84D18600E994F1 /* XFConcernViewController.xib */; }; 65AD11951C84D18600E994F1 /* XFRecommendViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11831C84D18600E994F1 /* XFRecommendViewController.m */; }; 65AD11961C84D18600E994F1 /* XFRecommendViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65AD11841C84D18600E994F1 /* XFRecommendViewController.xib */; }; 65AD11971C84D18600E994F1 /* XFCategoryModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11871C84D18600E994F1 /* XFCategoryModel.m */; }; 65AD11981C84D18600E994F1 /* XFMainTableModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11891C84D18600E994F1 /* XFMainTableModel.m */; }; 65AD11991C84D18700E994F1 /* XFRcommandDataTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD118C1C84D18600E994F1 /* XFRcommandDataTool.m */; }; 65AD119A1C84D18700E994F1 /* XFCategoryCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD118F1C84D18600E994F1 /* XFCategoryCell.m */; }; 65AD119B1C84D18700E994F1 /* XFCategoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65AD11901C84D18600E994F1 /* XFCategoryCell.xib */; }; 65AD119C1C84D18700E994F1 /* XFMainTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11921C84D18600E994F1 /* XFMainTableCell.m */; }; 65AD119D1C84D18700E994F1 /* XFMainTableCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65AD11931C84D18600E994F1 /* XFMainTableCell.xib */; }; 65AD11A01C84D1CB00E994F1 /* XFConcernViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD119F1C84D1CB00E994F1 /* XFConcernViewController.m */; }; 65AD11A41C84D1F500E994F1 /* XFLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11A21C84D1F500E994F1 /* XFLoginViewController.m */; }; 65AD11A51C84D1F500E994F1 /* XFLoginViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65AD11A31C84D1F500E994F1 /* XFLoginViewController.xib */; }; 65AD11A81C84D23500E994F1 /* XFTextfield.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11A71C84D23500E994F1 /* XFTextfield.m */; }; 65AD11AB1C84D26C00E994F1 /* XFShowWordBtn.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11AA1C84D26C00E994F1 /* XFShowWordBtn.m */; }; 65AD11BB1C84D32F00E994F1 /* XFNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11B21C84D32F00E994F1 /* XFNavigationController.m */; }; 65AD11BC1C84D32F00E994F1 /* XFTabBarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11B41C84D32F00E994F1 /* XFTabBarViewController.m */; }; 65AD11BD1C84D32F00E994F1 /* XFPublishView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11B71C84D32F00E994F1 /* XFPublishView.m */; }; 65AD11BE1C84D32F00E994F1 /* XFPublishView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65AD11B81C84D32F00E994F1 /* XFPublishView.xib */; }; 65AD11BF1C84D32F00E994F1 /* XFTabBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 65AD11BA1C84D32F00E994F1 /* XFTabBar.m */; }; 65EA75901C74AB4C0017DB20 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EA758F1C74AB4C0017DB20 /* main.m */; }; 65EA75991C74AB4C0017DB20 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 65EA75971C74AB4C0017DB20 /* Main.storyboard */; }; 65EA759B1C74AB4C0017DB20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 65EA759A1C74AB4C0017DB20 /* Assets.xcassets */; }; 65EA759E1C74AB4C0017DB20 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 65EA759C1C74AB4C0017DB20 /* LaunchScreen.storyboard */; }; 65EA76181C74C18A0017DB20 /* XFEssenceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EA76011C74C18A0017DB20 /* XFEssenceViewController.m */; }; 65EA76191C74C18A0017DB20 /* XFLatestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EA76081C74C18A0017DB20 /* XFLatestViewController.m */; }; 65EA761B1C74C18A0017DB20 /* XFMeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EA76121C74C18A0017DB20 /* XFMeViewController.m */; }; 65EA761E1C74C1A70017DB20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EA761D1C74C1A70017DB20 /* AppDelegate.m */; }; 65EA762A1C74C54E0017DB20 /* UIView+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EA76291C74C54E0017DB20 /* UIView+Extension.m */; }; 65FAABB71C8155A700A3C971 /* XFDetailPictureController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FAABB61C8155A700A3C971 /* XFDetailPictureController.m */; }; 65FE4B3A1C8884B900A4BA45 /* UIImageView+Header.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FE4B391C8884B900A4BA45 /* UIImageView+Header.m */; }; 65FE4B3D1C88850600A4BA45 /* UIImage+XFCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FE4B3C1C88850600A4BA45 /* UIImage+XFCircle.m */; }; 65FE4B401C888BBA00A4BA45 /* XFMeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FE4B3F1C888BBA00A4BA45 /* XFMeCell.m */; }; 65FE4B461C896C4500A4BA45 /* XFSquareCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FE4B451C896C4500A4BA45 /* XFSquareCell.m */; }; 65FE4B491C896D1400A4BA45 /* XFSquare.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FE4B481C896D1400A4BA45 /* XFSquare.m */; }; 65FE4B4C1C896D4700A4BA45 /* XFSquareTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FE4B4B1C896D4700A4BA45 /* XFSquareTool.m */; }; 65FE4B4F1C897F1900A4BA45 /* XFSquareButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FE4B4E1C897F1900A4BA45 /* XFSquareButton.m */; }; 65FE4B911C89D2FF00A4BA45 /* XFSquareFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 65FE4B901C89D2FF00A4BA45 /* XFSquareFooterView.m */; }; 9F1B78C58CDAEB38BB9F5CEA /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF97E68F796933B40822AB81 /* Pods.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 650742701C8570720069A37A /* XFCommentViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFCommentViewController.h; sourceTree = ""; }; 650742711C8570720069A37A /* XFCommentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFCommentViewController.m; sourceTree = ""; }; 650742721C8570720069A37A /* XFCommentViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFCommentViewController.xib; sourceTree = ""; }; 650742751C8580BA0069A37A /* XFCommentCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFCommentCell.h; sourceTree = ""; }; 650742761C8580BA0069A37A /* XFCommentCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFCommentCell.m; sourceTree = ""; }; 650742771C8580BA0069A37A /* XFCommentCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFCommentCell.xib; sourceTree = ""; }; 6525F1681C982E46006BCD89 /* NSString+XFTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+XFTime.h"; sourceTree = ""; }; 6525F1691C982E46006BCD89 /* NSString+XFTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+XFTime.m"; sourceTree = ""; }; 6525F16C1C991641006BCD89 /* HttpTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpTool.h; sourceTree = ""; }; 6525F16D1C991641006BCD89 /* HttpTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpTool.m; sourceTree = ""; }; 6525F16F1C991650006BCD89 /* XFVociePlayerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFVociePlayerController.h; sourceTree = ""; }; 6525F1701C991650006BCD89 /* XFVociePlayerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFVociePlayerController.m; sourceTree = ""; }; 6525F1711C991650006BCD89 /* XFVociePlayerController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFVociePlayerController.xib; sourceTree = ""; }; 652CB26F1C78E1B20027B71B /* XFGuideView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFGuideView.h; sourceTree = ""; }; 652CB2701C78E1B20027B71B /* XFGuideView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFGuideView.m; sourceTree = ""; }; 652CB2721C78E1C00027B71B /* XFGuideView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFGuideView.xib; sourceTree = ""; }; 65752E2E1C7C9E120005CCB2 /* XFContentPictureView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFContentPictureView.h; sourceTree = ""; }; 65752E2F1C7C9E120005CCB2 /* XFContentPictureView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFContentPictureView.m; sourceTree = ""; }; 65752E311C7C9E3F0005CCB2 /* XFContentPictureView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFContentPictureView.xib; sourceTree = ""; }; 65752E331C7D8F7C0005CCB2 /* XFTopicFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFTopicFrame.h; sourceTree = ""; }; 65752E341C7D8F7C0005CCB2 /* XFTopicFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFTopicFrame.m; sourceTree = ""; }; 65752E361C7D9DBC0005CCB2 /* XFContentVoiceView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFContentVoiceView.h; sourceTree = ""; }; 65752E371C7D9DBC0005CCB2 /* XFContentVoiceView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFContentVoiceView.m; sourceTree = ""; }; 65752E391C7D9DCD0005CCB2 /* XFContentVideoView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFContentVideoView.h; sourceTree = ""; }; 65752E3A1C7D9DCD0005CCB2 /* XFContentVideoView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFContentVideoView.m; sourceTree = ""; }; 657E659A1C89DBD2005D6D8E /* XFWebviewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFWebviewController.h; sourceTree = ""; }; 657E659B1C89DBD2005D6D8E /* XFWebviewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFWebviewController.m; sourceTree = ""; }; 65A284591C79956800D8031B /* XFVocieViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFVocieViewController.h; sourceTree = ""; }; 65A2845A1C79956800D8031B /* XFVocieViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFVocieViewController.m; sourceTree = ""; }; 65A2845C1C79957D00D8031B /* XFPictrueViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFPictrueViewController.h; sourceTree = ""; }; 65A2845D1C79957D00D8031B /* XFPictrueViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFPictrueViewController.m; sourceTree = ""; }; 65A2845F1C79958800D8031B /* XFVideoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFVideoViewController.h; sourceTree = ""; }; 65A284601C79958800D8031B /* XFVideoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFVideoViewController.m; sourceTree = ""; }; 65A284621C7995BD00D8031B /* XFTalkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFTalkViewController.h; sourceTree = ""; }; 65A284631C7995BD00D8031B /* XFTalkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFTalkViewController.m; sourceTree = ""; }; 65A284651C799A9400D8031B /* XFAllViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFAllViewController.h; sourceTree = ""; }; 65A284661C799A9400D8031B /* XFAllViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFAllViewController.m; sourceTree = ""; }; 65A284681C7B2DE500D8031B /* XFModuleDataTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFModuleDataTool.h; sourceTree = ""; }; 65A284691C7B2DE500D8031B /* XFModuleDataTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFModuleDataTool.m; sourceTree = ""; }; 65A2846B1C7B33E700D8031B /* XFTopicModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFTopicModel.h; sourceTree = ""; }; 65A2846C1C7B33E700D8031B /* XFTopicModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFTopicModel.m; sourceTree = ""; }; 65A2846E1C7B355D00D8031B /* XFTopicCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFTopicCell.h; sourceTree = ""; }; 65A2846F1C7B355D00D8031B /* XFTopicCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFTopicCell.m; sourceTree = ""; }; 65A284701C7B355D00D8031B /* XFTopicCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFTopicCell.xib; sourceTree = ""; }; 65A2AB481C8EC99F00BF2B8F /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; 65A2AB4A1C8EE2FA00BF2B8F /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 65A2AB4C1C8EE31A00BF2B8F /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; 65A2AB5A1C8FF15700BF2B8F /* KRVideoPlayerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRVideoPlayerController.h; sourceTree = ""; }; 65A2AB5B1C8FF15700BF2B8F /* KRVideoPlayerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRVideoPlayerController.m; sourceTree = ""; }; 65A2AB5C1C8FF15700BF2B8F /* KRVideoPlayerControlView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRVideoPlayerControlView.h; sourceTree = ""; }; 65A2AB5D1C8FF15700BF2B8F /* KRVideoPlayerControlView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRVideoPlayerControlView.m; sourceTree = ""; }; 65A2AB601C91A8C700BF2B8F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 65AD116D1C83208300E994F1 /* XFContentVoiceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFContentVoiceView.xib; sourceTree = ""; }; 65AD11721C833C0C00E994F1 /* XFContentVideoView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFContentVideoView.xib; sourceTree = ""; }; 65AD11741C8362C700E994F1 /* XFUserModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFUserModel.h; sourceTree = ""; }; 65AD11751C8362C700E994F1 /* XFUserModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFUserModel.m; sourceTree = ""; }; 65AD11771C8362D300E994F1 /* XFCommentModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFCommentModel.h; sourceTree = ""; }; 65AD11781C8362D300E994F1 /* XFCommentModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFCommentModel.m; sourceTree = ""; }; 65AD11811C84D18600E994F1 /* XFConcernViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFConcernViewController.xib; sourceTree = ""; }; 65AD11821C84D18600E994F1 /* XFRecommendViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFRecommendViewController.h; sourceTree = ""; }; 65AD11831C84D18600E994F1 /* XFRecommendViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFRecommendViewController.m; sourceTree = ""; }; 65AD11841C84D18600E994F1 /* XFRecommendViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFRecommendViewController.xib; sourceTree = ""; }; 65AD11861C84D18600E994F1 /* XFCategoryModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFCategoryModel.h; sourceTree = ""; }; 65AD11871C84D18600E994F1 /* XFCategoryModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFCategoryModel.m; sourceTree = ""; }; 65AD11881C84D18600E994F1 /* XFMainTableModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFMainTableModel.h; sourceTree = ""; }; 65AD11891C84D18600E994F1 /* XFMainTableModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFMainTableModel.m; sourceTree = ""; }; 65AD118B1C84D18600E994F1 /* XFRcommandDataTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFRcommandDataTool.h; sourceTree = ""; }; 65AD118C1C84D18600E994F1 /* XFRcommandDataTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFRcommandDataTool.m; sourceTree = ""; }; 65AD118E1C84D18600E994F1 /* XFCategoryCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFCategoryCell.h; sourceTree = ""; }; 65AD118F1C84D18600E994F1 /* XFCategoryCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFCategoryCell.m; sourceTree = ""; }; 65AD11901C84D18600E994F1 /* XFCategoryCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFCategoryCell.xib; sourceTree = ""; }; 65AD11911C84D18600E994F1 /* XFMainTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFMainTableCell.h; sourceTree = ""; }; 65AD11921C84D18600E994F1 /* XFMainTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFMainTableCell.m; sourceTree = ""; }; 65AD11931C84D18600E994F1 /* XFMainTableCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFMainTableCell.xib; sourceTree = ""; }; 65AD119E1C84D1CB00E994F1 /* XFConcernViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFConcernViewController.h; sourceTree = ""; }; 65AD119F1C84D1CB00E994F1 /* XFConcernViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFConcernViewController.m; sourceTree = ""; }; 65AD11A11C84D1F500E994F1 /* XFLoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFLoginViewController.h; sourceTree = ""; }; 65AD11A21C84D1F500E994F1 /* XFLoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFLoginViewController.m; sourceTree = ""; }; 65AD11A31C84D1F500E994F1 /* XFLoginViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFLoginViewController.xib; sourceTree = ""; }; 65AD11A61C84D23500E994F1 /* XFTextfield.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFTextfield.h; sourceTree = ""; }; 65AD11A71C84D23500E994F1 /* XFTextfield.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFTextfield.m; sourceTree = ""; }; 65AD11A91C84D26C00E994F1 /* XFShowWordBtn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFShowWordBtn.h; sourceTree = ""; }; 65AD11AA1C84D26C00E994F1 /* XFShowWordBtn.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFShowWordBtn.m; sourceTree = ""; }; 65AD11B11C84D32F00E994F1 /* XFNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFNavigationController.h; sourceTree = ""; }; 65AD11B21C84D32F00E994F1 /* XFNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFNavigationController.m; sourceTree = ""; }; 65AD11B31C84D32F00E994F1 /* XFTabBarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFTabBarViewController.h; sourceTree = ""; }; 65AD11B41C84D32F00E994F1 /* XFTabBarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFTabBarViewController.m; sourceTree = ""; }; 65AD11B61C84D32F00E994F1 /* XFPublishView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFPublishView.h; sourceTree = ""; }; 65AD11B71C84D32F00E994F1 /* XFPublishView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFPublishView.m; sourceTree = ""; }; 65AD11B81C84D32F00E994F1 /* XFPublishView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XFPublishView.xib; sourceTree = ""; }; 65AD11B91C84D32F00E994F1 /* XFTabBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFTabBar.h; sourceTree = ""; }; 65AD11BA1C84D32F00E994F1 /* XFTabBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFTabBar.m; sourceTree = ""; }; 65EA758B1C74AB4C0017DB20 /* XFBaiSiBuDeJie.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XFBaiSiBuDeJie.app; sourceTree = BUILT_PRODUCTS_DIR; }; 65EA758F1C74AB4C0017DB20 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 65EA75981C74AB4C0017DB20 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 65EA759A1C74AB4C0017DB20 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 65EA759D1C74AB4C0017DB20 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 65EA759F1C74AB4C0017DB20 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65EA76001C74C18A0017DB20 /* XFEssenceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFEssenceViewController.h; sourceTree = ""; }; 65EA76011C74C18A0017DB20 /* XFEssenceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFEssenceViewController.m; sourceTree = ""; }; 65EA76071C74C18A0017DB20 /* XFLatestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFLatestViewController.h; sourceTree = ""; }; 65EA76081C74C18A0017DB20 /* XFLatestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFLatestViewController.m; sourceTree = ""; }; 65EA76111C74C18A0017DB20 /* XFMeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFMeViewController.h; sourceTree = ""; }; 65EA76121C74C18A0017DB20 /* XFMeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFMeViewController.m; sourceTree = ""; }; 65EA761C1C74C1A70017DB20 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 65EA761D1C74C1A70017DB20 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 65EA76281C74C54E0017DB20 /* UIView+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Extension.h"; sourceTree = ""; }; 65EA76291C74C54E0017DB20 /* UIView+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Extension.m"; sourceTree = ""; }; 65EA762B1C74C5840017DB20 /* PrefixHeader.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrefixHeader.pch; sourceTree = ""; }; 65FAABB51C8155A700A3C971 /* XFDetailPictureController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFDetailPictureController.h; sourceTree = ""; }; 65FAABB61C8155A700A3C971 /* XFDetailPictureController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFDetailPictureController.m; sourceTree = ""; }; 65FE4B381C8884B900A4BA45 /* UIImageView+Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+Header.h"; sourceTree = ""; }; 65FE4B391C8884B900A4BA45 /* UIImageView+Header.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+Header.m"; sourceTree = ""; }; 65FE4B3B1C88850600A4BA45 /* UIImage+XFCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+XFCircle.h"; sourceTree = ""; }; 65FE4B3C1C88850600A4BA45 /* UIImage+XFCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+XFCircle.m"; sourceTree = ""; }; 65FE4B3E1C888BBA00A4BA45 /* XFMeCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XFMeCell.h; path = XFBaiSiBuDeJie/Classes/Category/XFMeCell.h; sourceTree = SOURCE_ROOT; }; 65FE4B3F1C888BBA00A4BA45 /* XFMeCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XFMeCell.m; path = XFBaiSiBuDeJie/Classes/Category/XFMeCell.m; sourceTree = SOURCE_ROOT; }; 65FE4B441C896C4500A4BA45 /* XFSquareCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XFSquareCell.h; path = XFBaiSiBuDeJie/Classes/Category/XFSquareCell.h; sourceTree = SOURCE_ROOT; }; 65FE4B451C896C4500A4BA45 /* XFSquareCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XFSquareCell.m; path = XFBaiSiBuDeJie/Classes/Category/XFSquareCell.m; sourceTree = SOURCE_ROOT; }; 65FE4B471C896D1400A4BA45 /* XFSquare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XFSquare.h; path = XFBaiSiBuDeJie/Classes/Category/XFSquare.h; sourceTree = SOURCE_ROOT; }; 65FE4B481C896D1400A4BA45 /* XFSquare.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XFSquare.m; path = XFBaiSiBuDeJie/Classes/Category/XFSquare.m; sourceTree = SOURCE_ROOT; }; 65FE4B4A1C896D4700A4BA45 /* XFSquareTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XFSquareTool.h; path = XFBaiSiBuDeJie/Classes/Category/XFSquareTool.h; sourceTree = SOURCE_ROOT; }; 65FE4B4B1C896D4700A4BA45 /* XFSquareTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XFSquareTool.m; path = XFBaiSiBuDeJie/Classes/Category/XFSquareTool.m; sourceTree = SOURCE_ROOT; }; 65FE4B4D1C897F1900A4BA45 /* XFSquareButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XFSquareButton.h; path = XFBaiSiBuDeJie/Classes/Category/XFSquareButton.h; sourceTree = SOURCE_ROOT; }; 65FE4B4E1C897F1900A4BA45 /* XFSquareButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XFSquareButton.m; path = XFBaiSiBuDeJie/Classes/Category/XFSquareButton.m; sourceTree = SOURCE_ROOT; }; 65FE4B8F1C89D2FF00A4BA45 /* XFSquareFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFSquareFooterView.h; sourceTree = ""; }; 65FE4B901C89D2FF00A4BA45 /* XFSquareFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XFSquareFooterView.m; sourceTree = ""; }; 93C111E3628DDD5B6A1F02D9 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; E95CFFAFAF3A502F07AE5DD2 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; FF97E68F796933B40822AB81 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 65EA75881C74AB4C0017DB20 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 65A2AB611C91A8C700BF2B8F /* AudioToolbox.framework in Frameworks */, 65A2AB4F1C8F01BE00BF2B8F /* MediaPlayer.framework in Frameworks */, 65A2AB4E1C8F01B500BF2B8F /* AVFoundation.framework in Frameworks */, 9F1B78C58CDAEB38BB9F5CEA /* Pods.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 4C2E2ACE3CE0AB82CF3D16E7 /* Pods */ = { isa = PBXGroup; children = ( 93C111E3628DDD5B6A1F02D9 /* Pods.debug.xcconfig */, E95CFFAFAF3A502F07AE5DD2 /* Pods.release.xcconfig */, ); name = Pods; sourceTree = ""; }; 6525F16B1C991641006BCD89 /* Tool */ = { isa = PBXGroup; children = ( 6525F16C1C991641006BCD89 /* HttpTool.h */, 6525F16D1C991641006BCD89 /* HttpTool.m */, ); path = Tool; sourceTree = ""; }; 652CB26D1C78E1830027B71B /* Controller */ = { isa = PBXGroup; children = ( ); path = Controller; sourceTree = ""; }; 652CB26E1C78E1830027B71B /* View */ = { isa = PBXGroup; children = ( 65AD11A91C84D26C00E994F1 /* XFShowWordBtn.h */, 65AD11AA1C84D26C00E994F1 /* XFShowWordBtn.m */, 652CB26F1C78E1B20027B71B /* XFGuideView.h */, 652CB2701C78E1B20027B71B /* XFGuideView.m */, 652CB2721C78E1C00027B71B /* XFGuideView.xib */, ); path = View; sourceTree = ""; }; 65A2AB591C8FF15700BF2B8F /* KRVideoPlayerController */ = { isa = PBXGroup; children = ( 6525F16F1C991650006BCD89 /* XFVociePlayerController.h */, 6525F1701C991650006BCD89 /* XFVociePlayerController.m */, 6525F1711C991650006BCD89 /* XFVociePlayerController.xib */, 65A2AB5A1C8FF15700BF2B8F /* KRVideoPlayerController.h */, 65A2AB5B1C8FF15700BF2B8F /* KRVideoPlayerController.m */, 65A2AB5C1C8FF15700BF2B8F /* KRVideoPlayerControlView.h */, 65A2AB5D1C8FF15700BF2B8F /* KRVideoPlayerControlView.m */, ); path = KRVideoPlayerController; sourceTree = ""; }; 65AD11801C84D18600E994F1 /* Controller */ = { isa = PBXGroup; children = ( 65AD119E1C84D1CB00E994F1 /* XFConcernViewController.h */, 65AD119F1C84D1CB00E994F1 /* XFConcernViewController.m */, 65AD11811C84D18600E994F1 /* XFConcernViewController.xib */, 65AD11821C84D18600E994F1 /* XFRecommendViewController.h */, 65AD11831C84D18600E994F1 /* XFRecommendViewController.m */, 65AD11841C84D18600E994F1 /* XFRecommendViewController.xib */, 65AD11A11C84D1F500E994F1 /* XFLoginViewController.h */, 65AD11A21C84D1F500E994F1 /* XFLoginViewController.m */, 65AD11A31C84D1F500E994F1 /* XFLoginViewController.xib */, ); path = Controller; sourceTree = ""; }; 65AD11851C84D18600E994F1 /* Model */ = { isa = PBXGroup; children = ( 65AD11861C84D18600E994F1 /* XFCategoryModel.h */, 65AD11871C84D18600E994F1 /* XFCategoryModel.m */, 65AD11881C84D18600E994F1 /* XFMainTableModel.h */, 65AD11891C84D18600E994F1 /* XFMainTableModel.m */, ); path = Model; sourceTree = ""; }; 65AD118A1C84D18600E994F1 /* Tool */ = { isa = PBXGroup; children = ( 65AD118B1C84D18600E994F1 /* XFRcommandDataTool.h */, 65AD118C1C84D18600E994F1 /* XFRcommandDataTool.m */, ); path = Tool; sourceTree = ""; }; 65AD118D1C84D18600E994F1 /* View */ = { isa = PBXGroup; children = ( 65AD11A61C84D23500E994F1 /* XFTextfield.h */, 65AD11A71C84D23500E994F1 /* XFTextfield.m */, 65AD118E1C84D18600E994F1 /* XFCategoryCell.h */, 65AD118F1C84D18600E994F1 /* XFCategoryCell.m */, 65AD11901C84D18600E994F1 /* XFCategoryCell.xib */, 65AD11911C84D18600E994F1 /* XFMainTableCell.h */, 65AD11921C84D18600E994F1 /* XFMainTableCell.m */, 65AD11931C84D18600E994F1 /* XFMainTableCell.xib */, ); path = View; sourceTree = ""; }; 65AD11AC1C84D2B300E994F1 /* Lib */ = { isa = PBXGroup; children = ( 6525F16B1C991641006BCD89 /* Tool */, 65A2AB591C8FF15700BF2B8F /* KRVideoPlayerController */, ); path = Lib; sourceTree = ""; }; 65AD11B01C84D32F00E994F1 /* Controller */ = { isa = PBXGroup; children = ( 65AD11B11C84D32F00E994F1 /* XFNavigationController.h */, 65AD11B21C84D32F00E994F1 /* XFNavigationController.m */, 65AD11B31C84D32F00E994F1 /* XFTabBarViewController.h */, 65AD11B41C84D32F00E994F1 /* XFTabBarViewController.m */, ); path = Controller; sourceTree = ""; }; 65AD11B51C84D32F00E994F1 /* View */ = { isa = PBXGroup; children = ( 65AD11B61C84D32F00E994F1 /* XFPublishView.h */, 65AD11B71C84D32F00E994F1 /* XFPublishView.m */, 65AD11B81C84D32F00E994F1 /* XFPublishView.xib */, 65AD11B91C84D32F00E994F1 /* XFTabBar.h */, 65AD11BA1C84D32F00E994F1 /* XFTabBar.m */, ); path = View; sourceTree = ""; }; 65EA75821C74AB4C0017DB20 = { isa = PBXGroup; children = ( 65EA758D1C74AB4C0017DB20 /* XFBaiSiBuDeJie */, 65EA758C1C74AB4C0017DB20 /* Products */, 4C2E2ACE3CE0AB82CF3D16E7 /* Pods */, A665137DCAB793132FF0FD7E /* Frameworks */, ); sourceTree = ""; }; 65EA758C1C74AB4C0017DB20 /* Products */ = { isa = PBXGroup; children = ( 65EA758B1C74AB4C0017DB20 /* XFBaiSiBuDeJie.app */, ); name = Products; sourceTree = ""; }; 65EA758D1C74AB4C0017DB20 /* XFBaiSiBuDeJie */ = { isa = PBXGroup; children = ( 65EA75F41C74C18A0017DB20 /* Classes */, 65EA758E1C74AB4C0017DB20 /* Supporting Files */, ); path = XFBaiSiBuDeJie; sourceTree = ""; }; 65EA758E1C74AB4C0017DB20 /* Supporting Files */ = { isa = PBXGroup; children = ( 65EA759A1C74AB4C0017DB20 /* Assets.xcassets */, 65EA75971C74AB4C0017DB20 /* Main.storyboard */, 65EA759C1C74AB4C0017DB20 /* LaunchScreen.storyboard */, 65EA759F1C74AB4C0017DB20 /* Info.plist */, 65EA758F1C74AB4C0017DB20 /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; 65EA75F41C74C18A0017DB20 /* Classes */ = { isa = PBXGroup; children = ( 65EA75F51C74C18A0017DB20 /* AppDelegate */, 65EA75F61C74C18A0017DB20 /* Category */, 65EA75F71C74C18A0017DB20 /* Concern */, 65EA75FE1C74C18A0017DB20 /* Essence */, 65EA76051C74C18A0017DB20 /* Latest */, 65EA760C1C74C18A0017DB20 /* Main */, 65EA760F1C74C18A0017DB20 /* Me */, 65AD11AC1C84D2B300E994F1 /* Lib */, 65EA76161C74C18A0017DB20 /* Other */, ); path = Classes; sourceTree = ""; }; 65EA75F51C74C18A0017DB20 /* AppDelegate */ = { isa = PBXGroup; children = ( 65EA761C1C74C1A70017DB20 /* AppDelegate.h */, 65EA761D1C74C1A70017DB20 /* AppDelegate.m */, ); path = AppDelegate; sourceTree = ""; }; 65EA75F61C74C18A0017DB20 /* Category */ = { isa = PBXGroup; children = ( 65EA76281C74C54E0017DB20 /* UIView+Extension.h */, 65EA76291C74C54E0017DB20 /* UIView+Extension.m */, 65FE4B3B1C88850600A4BA45 /* UIImage+XFCircle.h */, 65FE4B3C1C88850600A4BA45 /* UIImage+XFCircle.m */, 65FE4B381C8884B900A4BA45 /* UIImageView+Header.h */, 65FE4B391C8884B900A4BA45 /* UIImageView+Header.m */, 6525F1681C982E46006BCD89 /* NSString+XFTime.h */, 6525F1691C982E46006BCD89 /* NSString+XFTime.m */, ); path = Category; sourceTree = ""; }; 65EA75F71C74C18A0017DB20 /* Concern */ = { isa = PBXGroup; children = ( 65AD11801C84D18600E994F1 /* Controller */, 65AD11851C84D18600E994F1 /* Model */, 65AD118A1C84D18600E994F1 /* Tool */, 65AD118D1C84D18600E994F1 /* View */, ); path = Concern; sourceTree = ""; }; 65EA75FE1C74C18A0017DB20 /* Essence */ = { isa = PBXGroup; children = ( 65EA75FF1C74C18A0017DB20 /* Controller */, 65EA76021C74C18A0017DB20 /* Model */, 65EA76031C74C18A0017DB20 /* Tool */, 65EA76041C74C18A0017DB20 /* View */, ); path = Essence; sourceTree = ""; }; 65EA75FF1C74C18A0017DB20 /* Controller */ = { isa = PBXGroup; children = ( 65EA76001C74C18A0017DB20 /* XFEssenceViewController.h */, 65EA76011C74C18A0017DB20 /* XFEssenceViewController.m */, 65A284591C79956800D8031B /* XFVocieViewController.h */, 65A2845A1C79956800D8031B /* XFVocieViewController.m */, 65A2845C1C79957D00D8031B /* XFPictrueViewController.h */, 65A2845D1C79957D00D8031B /* XFPictrueViewController.m */, 65A2845F1C79958800D8031B /* XFVideoViewController.h */, 65A284601C79958800D8031B /* XFVideoViewController.m */, 65A284621C7995BD00D8031B /* XFTalkViewController.h */, 65A284631C7995BD00D8031B /* XFTalkViewController.m */, 65A284651C799A9400D8031B /* XFAllViewController.h */, 65A284661C799A9400D8031B /* XFAllViewController.m */, 65FAABB51C8155A700A3C971 /* XFDetailPictureController.h */, 65FAABB61C8155A700A3C971 /* XFDetailPictureController.m */, 650742701C8570720069A37A /* XFCommentViewController.h */, 650742711C8570720069A37A /* XFCommentViewController.m */, 650742721C8570720069A37A /* XFCommentViewController.xib */, ); path = Controller; sourceTree = ""; }; 65EA76021C74C18A0017DB20 /* Model */ = { isa = PBXGroup; children = ( 65A2846B1C7B33E700D8031B /* XFTopicModel.h */, 65A2846C1C7B33E700D8031B /* XFTopicModel.m */, 65752E331C7D8F7C0005CCB2 /* XFTopicFrame.h */, 65752E341C7D8F7C0005CCB2 /* XFTopicFrame.m */, 65AD11741C8362C700E994F1 /* XFUserModel.h */, 65AD11751C8362C700E994F1 /* XFUserModel.m */, 65AD11771C8362D300E994F1 /* XFCommentModel.h */, 65AD11781C8362D300E994F1 /* XFCommentModel.m */, ); path = Model; sourceTree = ""; }; 65EA76031C74C18A0017DB20 /* Tool */ = { isa = PBXGroup; children = ( 65A284681C7B2DE500D8031B /* XFModuleDataTool.h */, 65A284691C7B2DE500D8031B /* XFModuleDataTool.m */, ); path = Tool; sourceTree = ""; }; 65EA76041C74C18A0017DB20 /* View */ = { isa = PBXGroup; children = ( 65A2846E1C7B355D00D8031B /* XFTopicCell.h */, 65A2846F1C7B355D00D8031B /* XFTopicCell.m */, 65A284701C7B355D00D8031B /* XFTopicCell.xib */, 65752E2E1C7C9E120005CCB2 /* XFContentPictureView.h */, 65752E2F1C7C9E120005CCB2 /* XFContentPictureView.m */, 65752E311C7C9E3F0005CCB2 /* XFContentPictureView.xib */, 65752E361C7D9DBC0005CCB2 /* XFContentVoiceView.h */, 65752E371C7D9DBC0005CCB2 /* XFContentVoiceView.m */, 65AD116D1C83208300E994F1 /* XFContentVoiceView.xib */, 65752E391C7D9DCD0005CCB2 /* XFContentVideoView.h */, 65752E3A1C7D9DCD0005CCB2 /* XFContentVideoView.m */, 65AD11721C833C0C00E994F1 /* XFContentVideoView.xib */, 650742751C8580BA0069A37A /* XFCommentCell.h */, 650742761C8580BA0069A37A /* XFCommentCell.m */, 650742771C8580BA0069A37A /* XFCommentCell.xib */, ); path = View; sourceTree = ""; }; 65EA76051C74C18A0017DB20 /* Latest */ = { isa = PBXGroup; children = ( 65EA76061C74C18A0017DB20 /* Controller */, 65EA76091C74C18A0017DB20 /* Model */, 65EA760A1C74C18A0017DB20 /* Tool */, 65EA760B1C74C18A0017DB20 /* View */, ); path = Latest; sourceTree = ""; }; 65EA76061C74C18A0017DB20 /* Controller */ = { isa = PBXGroup; children = ( 65EA76071C74C18A0017DB20 /* XFLatestViewController.h */, 65EA76081C74C18A0017DB20 /* XFLatestViewController.m */, ); path = Controller; sourceTree = ""; }; 65EA76091C74C18A0017DB20 /* Model */ = { isa = PBXGroup; children = ( ); path = Model; sourceTree = ""; }; 65EA760A1C74C18A0017DB20 /* Tool */ = { isa = PBXGroup; children = ( ); path = Tool; sourceTree = ""; }; 65EA760B1C74C18A0017DB20 /* View */ = { isa = PBXGroup; children = ( ); path = View; sourceTree = ""; }; 65EA760C1C74C18A0017DB20 /* Main */ = { isa = PBXGroup; children = ( 65AD11B01C84D32F00E994F1 /* Controller */, 65AD11B51C84D32F00E994F1 /* View */, ); path = Main; sourceTree = ""; }; 65EA760F1C74C18A0017DB20 /* Me */ = { isa = PBXGroup; children = ( 65EA76101C74C18A0017DB20 /* Controller */, 65EA76131C74C18A0017DB20 /* Model */, 65EA76141C74C18A0017DB20 /* Tool */, 65EA76151C74C18A0017DB20 /* View */, ); path = Me; sourceTree = ""; }; 65EA76101C74C18A0017DB20 /* Controller */ = { isa = PBXGroup; children = ( 65EA76111C74C18A0017DB20 /* XFMeViewController.h */, 65EA76121C74C18A0017DB20 /* XFMeViewController.m */, 657E659A1C89DBD2005D6D8E /* XFWebviewController.h */, 657E659B1C89DBD2005D6D8E /* XFWebviewController.m */, ); path = Controller; sourceTree = ""; }; 65EA76131C74C18A0017DB20 /* Model */ = { isa = PBXGroup; children = ( 65FE4B471C896D1400A4BA45 /* XFSquare.h */, 65FE4B481C896D1400A4BA45 /* XFSquare.m */, ); path = Model; sourceTree = ""; }; 65EA76141C74C18A0017DB20 /* Tool */ = { isa = PBXGroup; children = ( 65FE4B4A1C896D4700A4BA45 /* XFSquareTool.h */, 65FE4B4B1C896D4700A4BA45 /* XFSquareTool.m */, ); path = Tool; sourceTree = ""; }; 65EA76151C74C18A0017DB20 /* View */ = { isa = PBXGroup; children = ( 65FE4B3E1C888BBA00A4BA45 /* XFMeCell.h */, 65FE4B3F1C888BBA00A4BA45 /* XFMeCell.m */, 65FE4B441C896C4500A4BA45 /* XFSquareCell.h */, 65FE4B451C896C4500A4BA45 /* XFSquareCell.m */, 65FE4B4D1C897F1900A4BA45 /* XFSquareButton.h */, 65FE4B4E1C897F1900A4BA45 /* XFSquareButton.m */, 65FE4B8F1C89D2FF00A4BA45 /* XFSquareFooterView.h */, 65FE4B901C89D2FF00A4BA45 /* XFSquareFooterView.m */, ); path = View; sourceTree = ""; }; 65EA76161C74C18A0017DB20 /* Other */ = { isa = PBXGroup; children = ( 652CB26D1C78E1830027B71B /* Controller */, 652CB26E1C78E1830027B71B /* View */, 65EA762B1C74C5840017DB20 /* PrefixHeader.pch */, ); path = Other; sourceTree = ""; }; A665137DCAB793132FF0FD7E /* Frameworks */ = { isa = PBXGroup; children = ( 65A2AB601C91A8C700BF2B8F /* AudioToolbox.framework */, 65A2AB4C1C8EE31A00BF2B8F /* CoreMedia.framework */, 65A2AB4A1C8EE2FA00BF2B8F /* AVFoundation.framework */, 65A2AB481C8EC99F00BF2B8F /* MediaPlayer.framework */, FF97E68F796933B40822AB81 /* Pods.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 65EA758A1C74AB4C0017DB20 /* XFBaiSiBuDeJie */ = { isa = PBXNativeTarget; buildConfigurationList = 65EA75A21C74AB4C0017DB20 /* Build configuration list for PBXNativeTarget "XFBaiSiBuDeJie" */; buildPhases = ( E20EAC8FA180FBF4795EEC3C /* Check Pods Manifest.lock */, 65EA75871C74AB4C0017DB20 /* Sources */, 65EA75881C74AB4C0017DB20 /* Frameworks */, 65EA75891C74AB4C0017DB20 /* Resources */, 5C537EFD111F11B589F9EB49 /* Embed Pods Frameworks */, 36DC7830B24B1E15B1629FA1 /* Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = XFBaiSiBuDeJie; productName = XFBaiSiBuDeJie; productReference = 65EA758B1C74AB4C0017DB20 /* XFBaiSiBuDeJie.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 65EA75831C74AB4C0017DB20 /* Project object */ = { isa = PBXProject; attributes = { CLASSPREFIX = XF; LastUpgradeCheck = 0720; ORGANIZATIONNAME = "谢飞"; TargetAttributes = { 65EA758A1C74AB4C0017DB20 = { CreatedOnToolsVersion = 7.2; DevelopmentTeam = NRZG3Z79NX; }; }; }; buildConfigurationList = 65EA75861C74AB4C0017DB20 /* Build configuration list for PBXProject "XFBaiSiBuDeJie" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 65EA75821C74AB4C0017DB20; productRefGroup = 65EA758C1C74AB4C0017DB20 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 65EA758A1C74AB4C0017DB20 /* XFBaiSiBuDeJie */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 65EA75891C74AB4C0017DB20 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 65752E321C7C9E3F0005CCB2 /* XFContentPictureView.xib in Resources */, 65AD119D1C84D18700E994F1 /* XFMainTableCell.xib in Resources */, 65AD11941C84D18600E994F1 /* XFConcernViewController.xib in Resources */, 650742791C8580BA0069A37A /* XFCommentCell.xib in Resources */, 65A284721C7B355D00D8031B /* XFTopicCell.xib in Resources */, 65AD11731C833C0C00E994F1 /* XFContentVideoView.xib in Resources */, 65AD11961C84D18600E994F1 /* XFRecommendViewController.xib in Resources */, 650742741C8570720069A37A /* XFCommentViewController.xib in Resources */, 65AD11BE1C84D32F00E994F1 /* XFPublishView.xib in Resources */, 65EA759E1C74AB4C0017DB20 /* LaunchScreen.storyboard in Resources */, 6525F1731C991650006BCD89 /* XFVociePlayerController.xib in Resources */, 652CB2731C78E1C00027B71B /* XFGuideView.xib in Resources */, 65AD116E1C83208300E994F1 /* XFContentVoiceView.xib in Resources */, 65AD11A51C84D1F500E994F1 /* XFLoginViewController.xib in Resources */, 65EA759B1C74AB4C0017DB20 /* Assets.xcassets in Resources */, 65EA75991C74AB4C0017DB20 /* Main.storyboard in Resources */, 65AD119B1C84D18700E994F1 /* XFCategoryCell.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 36DC7830B24B1E15B1629FA1 /* Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; showEnvVarsInLog = 0; }; 5C537EFD111F11B589F9EB49 /* Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; E20EAC8FA180FBF4795EEC3C /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 65EA75871C74AB4C0017DB20 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 65EA762A1C74C54E0017DB20 /* UIView+Extension.m in Sources */, 65AD119A1C84D18700E994F1 /* XFCategoryCell.m in Sources */, 65EA75901C74AB4C0017DB20 /* main.m in Sources */, 65FE4B401C888BBA00A4BA45 /* XFMeCell.m in Sources */, 65EA76191C74C18A0017DB20 /* XFLatestViewController.m in Sources */, 650742731C8570720069A37A /* XFCommentViewController.m in Sources */, 65AD11A81C84D23500E994F1 /* XFTextfield.m in Sources */, 65A2846A1C7B2DE500D8031B /* XFModuleDataTool.m in Sources */, 650742781C8580BA0069A37A /* XFCommentCell.m in Sources */, 652CB2711C78E1B20027B71B /* XFGuideView.m in Sources */, 65FE4B911C89D2FF00A4BA45 /* XFSquareFooterView.m in Sources */, 6525F16A1C982E46006BCD89 /* NSString+XFTime.m in Sources */, 65A284641C7995BD00D8031B /* XFTalkViewController.m in Sources */, 65A284611C79958800D8031B /* XFVideoViewController.m in Sources */, 65AD11BF1C84D32F00E994F1 /* XFTabBar.m in Sources */, 65FAABB71C8155A700A3C971 /* XFDetailPictureController.m in Sources */, 65AD11951C84D18600E994F1 /* XFRecommendViewController.m in Sources */, 65A284671C799A9400D8031B /* XFAllViewController.m in Sources */, 65FE4B491C896D1400A4BA45 /* XFSquare.m in Sources */, 65752E3B1C7D9DCD0005CCB2 /* XFContentVideoView.m in Sources */, 65A2845E1C79957D00D8031B /* XFPictrueViewController.m in Sources */, 65A284711C7B355D00D8031B /* XFTopicCell.m in Sources */, 65EA76181C74C18A0017DB20 /* XFEssenceViewController.m in Sources */, 65AD11AB1C84D26C00E994F1 /* XFShowWordBtn.m in Sources */, 65AD11791C8362D300E994F1 /* XFCommentModel.m in Sources */, 6525F1721C991650006BCD89 /* XFVociePlayerController.m in Sources */, 65EA761B1C74C18A0017DB20 /* XFMeViewController.m in Sources */, 65FE4B461C896C4500A4BA45 /* XFSquareCell.m in Sources */, 65AD11BB1C84D32F00E994F1 /* XFNavigationController.m in Sources */, 65FE4B4C1C896D4700A4BA45 /* XFSquareTool.m in Sources */, 65752E301C7C9E120005CCB2 /* XFContentPictureView.m in Sources */, 6525F16E1C991641006BCD89 /* HttpTool.m in Sources */, 65AD11BD1C84D32F00E994F1 /* XFPublishView.m in Sources */, 65FE4B4F1C897F1900A4BA45 /* XFSquareButton.m in Sources */, 65AD11A01C84D1CB00E994F1 /* XFConcernViewController.m in Sources */, 65A2AB5E1C8FF15700BF2B8F /* KRVideoPlayerController.m in Sources */, 65EA761E1C74C1A70017DB20 /* AppDelegate.m in Sources */, 65FE4B3D1C88850600A4BA45 /* UIImage+XFCircle.m in Sources */, 65AD11BC1C84D32F00E994F1 /* XFTabBarViewController.m in Sources */, 65752E351C7D8F7C0005CCB2 /* XFTopicFrame.m in Sources */, 65FE4B3A1C8884B900A4BA45 /* UIImageView+Header.m in Sources */, 65AD11A41C84D1F500E994F1 /* XFLoginViewController.m in Sources */, 65AD11991C84D18700E994F1 /* XFRcommandDataTool.m in Sources */, 65752E381C7D9DBC0005CCB2 /* XFContentVoiceView.m in Sources */, 65AD11761C8362C700E994F1 /* XFUserModel.m in Sources */, 65A2846D1C7B33E700D8031B /* XFTopicModel.m in Sources */, 657E659C1C89DBD2005D6D8E /* XFWebviewController.m in Sources */, 65AD11981C84D18600E994F1 /* XFMainTableModel.m in Sources */, 65A2845B1C79956800D8031B /* XFVocieViewController.m in Sources */, 65AD11971C84D18600E994F1 /* XFCategoryModel.m in Sources */, 65A2AB5F1C8FF15700BF2B8F /* KRVideoPlayerControlView.m in Sources */, 65AD119C1C84D18700E994F1 /* XFMainTableCell.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 65EA75971C74AB4C0017DB20 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 65EA75981C74AB4C0017DB20 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 65EA759C1C74AB4C0017DB20 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 65EA759D1C74AB4C0017DB20 /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 65EA75A01C74AB4C0017DB20 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.2; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 65EA75A11C74AB4C0017DB20 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; 65EA75A31C74AB4C0017DB20 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 93C111E3628DDD5B6A1F02D9 /* Pods.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Brand Assets"; GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREFIX_HEADER = "$(SRCROOT)/XFBaiSiBuDeJie/Classes/Other/PrefixHeader.pch"; INFOPLIST_FILE = XFBaiSiBuDeJie/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/XFBaiSiBuDeJie/Classes/Lib/VoiceConvert/opencore-amrnb", "$(PROJECT_DIR)/XFBaiSiBuDeJie/Classes/Lib/VoiceConvert/opencore-amrwb", ); PRODUCT_BUNDLE_IDENTIFIER = com.alloc.XFBaiSiBuDeJie; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 65EA75A41C74AB4C0017DB20 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = E95CFFAFAF3A502F07AE5DD2 /* Pods.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Brand Assets"; GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREFIX_HEADER = "$(SRCROOT)/XFBaiSiBuDeJie/Classes/Other/PrefixHeader.pch"; INFOPLIST_FILE = XFBaiSiBuDeJie/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/XFBaiSiBuDeJie/Classes/Lib/VoiceConvert/opencore-amrnb", "$(PROJECT_DIR)/XFBaiSiBuDeJie/Classes/Lib/VoiceConvert/opencore-amrwb", ); PRODUCT_BUNDLE_IDENTIFIER = com.alloc.XFBaiSiBuDeJie; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 65EA75861C74AB4C0017DB20 /* Build configuration list for PBXProject "XFBaiSiBuDeJie" */ = { isa = XCConfigurationList; buildConfigurations = ( 65EA75A01C74AB4C0017DB20 /* Debug */, 65EA75A11C74AB4C0017DB20 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 65EA75A21C74AB4C0017DB20 /* Build configuration list for PBXNativeTarget "XFBaiSiBuDeJie" */ = { isa = XCConfigurationList; buildConfigurations = ( 65EA75A31C74AB4C0017DB20 /* Debug */, 65EA75A41C74AB4C0017DB20 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 65EA75831C74AB4C0017DB20 /* Project object */; } ================================================ FILE: XFBaiSiBuDeJie.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: XFBaiSiBuDeJie.xcodeproj/xcuserdata/FAY.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist ================================================ ================================================ FILE: XFBaiSiBuDeJie.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/XFBaiSiBuDeJie.xcscheme ================================================ ================================================ FILE: XFBaiSiBuDeJie.xcodeproj/xcuserdata/FAY.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState XFBaiSiBuDeJie.xcscheme orderHint 0 SuppressBuildableAutocreation 65EA758A1C74AB4C0017DB20 primary ================================================ FILE: XFBaiSiBuDeJie.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: XFBaiSiBuDeJie.xcworkspace/xcuserdata/FAY.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist ================================================