[iOS] remove date selection from booking filters

This commit is contained in:
Aleksey Belousov 2020-07-16 11:27:31 +03:00 committed by Alexander Boriskov
parent 180ff4ceb0
commit 4f1a581840
136 changed files with 8680 additions and 12014 deletions

View file

@ -66,7 +66,6 @@
3406FA191C6E0D8F00E9FAD2 /* MWMMapDownloadDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3406FA171C6E0D8F00E9FAD2 /* MWMMapDownloadDialog.xib */; };
340708651F2905A500029ECC /* NavigationInfoArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340708631F2905A500029ECC /* NavigationInfoArea.swift */; };
340708781F2B5D6C00029ECC /* DimBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340708761F2B5D6C00029ECC /* DimBackground.swift */; };
3409D50B1FC6D8D2000F9B3E /* FilterCheckCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409D5091FC6D8D2000F9B3E /* FilterCheckCell.swift */; };
340B33C61F3AEFDB00A8C1B4 /* MWMRouter+RouteManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 340B33C41F3AEFDB00A8C1B4 /* MWMRouter+RouteManager.mm */; };
340E1EEC1E2F614400CE49BF /* Authorization.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 340E1EE41E2F614400CE49BF /* Authorization.storyboard */; };
340E1EEF1E2F614400CE49BF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 340E1EE51E2F614400CE49BF /* LaunchScreen.storyboard */; };
@ -1026,7 +1025,6 @@
340837121B7243CE00B5C185 /* MWMActivityViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMActivityViewController.mm; sourceTree = "<group>"; };
340837141B72451A00B5C185 /* MWMShareActivityItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMShareActivityItem.h; sourceTree = "<group>"; };
340837151B72451A00B5C185 /* MWMShareActivityItem.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMShareActivityItem.mm; sourceTree = "<group>"; };
3409D5091FC6D8D2000F9B3E /* FilterCheckCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCheckCell.swift; sourceTree = "<group>"; };
340B33C41F3AEFDB00A8C1B4 /* MWMRouter+RouteManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "MWMRouter+RouteManager.mm"; sourceTree = "<group>"; };
340DC82B1C4E72C700EAA2CC /* liboauthcpp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liboauthcpp.a; path = "../../../omim-xcode-build/Debug/liboauthcpp.a"; sourceTree = "<group>"; };
340E1EE41E2F614400CE49BF /* Authorization.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Authorization.storyboard; sourceTree = "<group>"; };
@ -2319,7 +2317,7 @@
name = Products;
sourceTree = "<group>";
};
29B97314FDCFA39411CA2CEA /* Maps */ = {
29B97314FDCFA39411CA2CEA = {
isa = PBXGroup;
children = (
47AEF83F2231249E00D20538 /* categories_brands.txt */,
@ -4754,7 +4752,6 @@
F6E2FCE51E097B9F0083EBEC /* Filters */ = {
isa = PBXGroup;
children = (
3409D5091FC6D8D2000F9B3E /* FilterCheckCell.swift */,
F63AF5111EA6250F00A1DB98 /* FilterCollectionHolderCell.swift */,
F63AF50D1EA6215100A1DB98 /* FilterPriceCategoryCell.swift */,
F63AF5091EA6213F00A1DB98 /* FilterRatingCell.swift */,
@ -5072,7 +5069,7 @@
"en-GB",
el,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* Maps */;
mainGroup = 29B97314FDCFA39411CA2CEA;
productRefGroup = 19C28FACFE9D520D11CA2CBB /* Products */;
projectDirPath = "";
projectRoot = "";
@ -5351,7 +5348,6 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-MAPS.ME/Pods-MAPS.ME-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework",
"${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework",
"${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework",
"${BUILT_PRODUCTS_DIR}/Flurry-iOS-SDK/Flurry_iOS_SDK.framework",
@ -5362,7 +5358,6 @@
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ActionSheetPicker_3_0.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flurry_iOS_SDK.framework",
@ -5797,7 +5792,6 @@
99CB34CD236B054B001D28AD /* DeepLinkInfoRouter.swift in Sources */,
99CB34B72369E188001D28AD /* WelcomeRouter.swift in Sources */,
99CB34CC236B054B001D28AD /* DeepLinkInfoPresenter.swift in Sources */,
3409D50B1FC6D8D2000F9B3E /* FilterCheckCell.swift in Sources */,
47E3C72121108E9F008B3B27 /* BookmarksLoadedViewController.swift in Sources */,
3472B5CB200F43EF00DC6CD5 /* BackgroundFetchScheduler.swift in Sources */,
471BBD942130390F00EB17C9 /* TutorialViewController.swift in Sources */,

View file

@ -10,7 +10,6 @@ target 'MAPS.ME' do
pod 'AppsFlyerFramework', '4.9.0'
pod 'Pushwoosh', '5.16.0'
pod 'ActionSheetPicker-3.0', '2.3.0'
pod 'FBSDKCoreKit', '5.15.1'
pod 'FBSDKLoginKit', '5.15.1'
pod 'Flurry-iOS-SDK/FlurrySDK', '10.1'

View file

@ -1,5 +1,4 @@
PODS:
- ActionSheetPicker-3.0 (2.3.0)
- AppsFlyerFramework (4.9.0)
- FBAudienceNetwork (5.6.0):
- FBSDKCoreKit/Basics (>= 5.6.0)
@ -38,8 +37,7 @@ PODS:
- FirebaseCoreDiagnosticsInterop (~> 1.2)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
- FirebaseCoreDiagnostics (1.3.0):
- FirebaseCoreDiagnosticsInterop (~> 1.2)
- FirebaseCoreDiagnostics (1.4.0):
- GoogleDataTransportCCTSupport (~> 3.1)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
@ -66,27 +64,27 @@ PODS:
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (~> 1.30905.0)
- GoogleDataTransport (6.2.1)
- GoogleDataTransportCCTSupport (3.1.0):
- GoogleDataTransportCCTSupport (3.2.0):
- GoogleDataTransport (~> 6.1)
- nanopb (~> 1.30905.0)
- GoogleUtilities/AppDelegateSwizzler (6.6.0):
- GoogleUtilities/AppDelegateSwizzler (6.7.1):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (6.6.0):
- GoogleUtilities/Environment (6.7.1):
- PromisesObjC (~> 1.2)
- GoogleUtilities/Logger (6.6.0):
- GoogleUtilities/Logger (6.7.1):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (6.6.0):
- GoogleUtilities/MethodSwizzler (6.7.1):
- GoogleUtilities/Logger
- GoogleUtilities/Network (6.6.0):
- GoogleUtilities/Network (6.7.1):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (6.6.0)"
- GoogleUtilities/Reachability (6.6.0):
- "GoogleUtilities/NSData+zlib (6.7.1)"
- GoogleUtilities/Reachability (6.7.1):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (6.6.0):
- GoogleUtilities/UserDefaults (6.7.1):
- GoogleUtilities/Logger
- MoPub-FacebookAudienceNetwork-Adapters (5.6.0.0):
- MoPub-FacebookAudienceNetwork-Adapters/MoPub (= 5.6.0.0)
@ -112,13 +110,12 @@ PODS:
- nanopb/encode (= 1.30905.0)
- nanopb/decode (1.30905.0)
- nanopb/encode (1.30905.0)
- PromisesObjC (1.2.8)
- PromisesObjC (1.2.9)
- Pushwoosh (5.16.0):
- Pushwoosh/Core (= 5.16.0)
- Pushwoosh/Core (5.16.0)
DEPENDENCIES:
- ActionSheetPicker-3.0 (= 2.3.0)
- AppsFlyerFramework (= 4.9.0)
- FBSDKCoreKit (= 5.15.1)
- FBSDKLoginKit (= 5.15.1)
@ -131,7 +128,6 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- ActionSheetPicker-3.0
- AppsFlyerFramework
- FBAudienceNetwork
- FBSDKCoreKit
@ -156,7 +152,6 @@ SPEC REPOS:
- Pushwoosh
SPEC CHECKSUMS:
ActionSheetPicker-3.0: eef157d75e151f255c5333d26656c7fbfe905a51
AppsFlyerFramework: f57e5d590ad3124d3e594a76032a181bc91ec6cd
FBAudienceNetwork: 1ea63543665445a3a5b4a059e8210a343b6ab3c1
FBSDKCoreKit: 1d5acf7c9d7a2f92bb1a242dc60cae5b7adb91df
@ -165,21 +160,21 @@ SPEC CHECKSUMS:
FirebaseAnalytics: 96634d356482d4f3af8fe459a0ebf19a99c71b75
FirebaseAnalyticsInterop: 3f86269c38ae41f47afeb43ebf32a001f58fcdae
FirebaseCore: f42e5e5f382cdcf6b617ed737bf6c871a6947b17
FirebaseCoreDiagnostics: 4a773a47bd83bbd5a9b1ccf1ce7caa8b2d535e67
FirebaseCoreDiagnostics: 4505e4d4009b1d93f605088ee7d7764d5f0d1c84
FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850
FirebaseCrashlytics: a87cce5746d3335995bd18b1b60d073cd05a6920
FirebaseInstallations: 6f5f680e65dc374397a483c32d1799ba822a395b
Flurry-iOS-SDK: be6bfad47f3b3c15a38b5e396935ef74512f1c38
GoogleAppMeasurement: 67458367830514fb20fd9e233496f1eef9d90185
GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020
GoogleDataTransportCCTSupport: d70a561f7d236af529fee598835caad5e25f6d3d
GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1
GoogleDataTransportCCTSupport: 489c1265d2c85b68187a83a911913d190012158d
GoogleUtilities: e121a3867449ce16b0e35ddf1797ea7a389ffdf2
MoPub-FacebookAudienceNetwork-Adapters: 3cec249235d12e3fec9a01bf559d608fa3ec05e1
mopub-ios-sdk: 3d65133b95b6498aa871a66818a11a5ba307e565
nanopb: c43f40fadfe79e8b8db116583945847910cbabc9
PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6
PromisesObjC: b48e0338dbbac2207e611750777895f7a5811b75
Pushwoosh: 6cba171e52f3f7b8ccd280f492a5831deac2f594
PODFILE CHECKSUM: 18f4e3a3de30ca73d4725a3e49f8c60205ad2306
PODFILE CHECKSUM: c3f8758a04bfcf497d7cf4a86726c990ae127e6a
COCOAPODS: 1.8.3
COCOAPODS: 1.9.3

View file

@ -1,24 +0,0 @@
Copyright (c) 2011, Tim Cinel (see AUTHORS)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,126 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class SWActionSheet;
#define SuppressPerformSelectorLeakWarning(Stuff) \
do { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \
Stuff; \
_Pragma("clang diagnostic pop") \
} while (0)
typedef NS_ENUM(NSInteger, ActionType) {
ActionTypeValue,
ActionTypeSelector,
ActionTypeBlock
};
typedef NS_ENUM(NSInteger, TapAction) {
TapActionNone,
TapActionSuccess,
TapActionCancel
};
typedef void (^ActionBlock)(void);
static NSString *const kButtonValue = @"buttonValue";
static NSString *const kButtonTitle = @"buttonTitle";
static NSString *const kActionType = @"buttonAction";
static NSString *const kActionTarget = @"buttonActionTarget";
@interface AbstractActionSheetPicker : NSObject <UIPopoverControllerDelegate>
@property(nonatomic, strong) SWActionSheet *actionSheet;
@property (nonatomic) UIWindowLevel windowLevel;
@property(nonatomic, assign) NSInteger tag;
@property(nonatomic, assign) int borderWidth;
@property(nonatomic, strong) UIToolbar *toolbar;
@property(nonatomic, copy) NSString *title;
@property(nonatomic, strong) UIView *pickerView;
@property(nonatomic, readonly) CGSize viewSize;
@property(nonatomic, strong) NSMutableArray *customButtons;
@property(nonatomic, assign) BOOL hideCancel; // show or hide cancel button.
@property(nonatomic, assign) CGRect presentFromRect;
@property(nonatomic) NSDictionary *titleTextAttributes; // default is nil. Used to specify Title Label attributes.
@property(nonatomic) NSAttributedString *attributedTitle; // default is nil. If titleTextAttributes not nil this value ignored.
@property(nonatomic) NSMutableDictionary *pickerTextAttributes; // default with a NSMutableParagraphStyle to set label align center. Used to specify Picker Label attributes.
@property(nonatomic) UIColor *pickerBackgroundColor;
@property(nonatomic) UIColor *toolbarBackgroundColor;
@property(nonatomic, strong) UIColor *toolbarButtonsColor;
@property(nonatomic) NSNumber *pickerBlurRadius;
@property(nonatomic, retain) Class popoverBackgroundViewClass; //allow popover customization on iPad
@property(nonatomic) UIInterfaceOrientationMask supportedInterfaceOrientations; // You can set your own supportedInterfaceOrientations value to prevent dismissing picker in some special cases.
@property(nonatomic) TapAction tapDismissAction; // Specify, which action should be fired in case of tapping outside of the picker (on top darkened side). Default is TapActionNone.
@property(nonatomic) BOOL popoverDisabled; // Disable popover behavior on iPad
- (void)setTextColor:(UIColor *)textColor;
// For subclasses.
- (instancetype)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin;
// Present the ActionSheetPicker
- (void)showActionSheetPicker;
// For subclasses. This is used to send a message to the target upon a successful selection and dismissal of the picker (i.e. not canceled).
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin;
// For subclasses. This is an optional message upon cancelation of the picker.
- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin;
// For subclasses. This returns a configured picker view. Subclasses should autorelease.
- (UIView *)configuredPickerView;
// Adds custom buttons to the left of the UIToolbar that select specified values
- (void)addCustomButtonWithTitle:(NSString *)title value:(id)value;
// Adds custom buttons to the left of the UIToolbar that implement specified block
- (void)addCustomButtonWithTitle:(NSString *)title actionBlock:(ActionBlock)block;
// Adds custom buttons to the left of the UIToolbar that implement specified selector
- (void)addCustomButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector;
//For subclasses. This responds to a custom button being pressed.
- (IBAction)customButtonPressed:(id)sender;
// Allow the user to specify a custom cancel button
- (void)setCancelButton:(UIBarButtonItem *)button;
// Allow the user to specify a custom done button
- (void)setDoneButton:(UIBarButtonItem *)button;
// Hide picker programmatically
- (void)hidePickerWithCancelAction;
@end

View file

@ -1,804 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "AbstractActionSheetPicker.h"
#import "SWActionSheet.h"
#import <objc/message.h>
#import <sys/utsname.h>
CG_INLINE BOOL isIPhone4() {
struct utsname systemInfo;
uname(&systemInfo);
NSString *modelName = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
return ([modelName rangeOfString:@"iPhone3"].location != NSNotFound);
}
#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
#define IS_IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
#define DEVICE_ORIENTATION [UIDevice currentDevice].orientation
// UIInterfaceOrientationMask vs. UIInterfaceOrientation
// As far as I know, a function like this isn't available in the API. I derived this from the enum def for
// UIInterfaceOrientationMask.
#define OrientationMaskSupportsOrientation(mask, orientation) ((mask & (1 << orientation)) != 0)
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
@interface MyPopoverController : UIPopoverController <UIAdaptivePresentationControllerDelegate>
@end
@implementation MyPopoverController
+ (BOOL)canShowPopover {
if (IS_IPAD) {
if ([UITraitCollection class]) {
UITraitCollection *traits = [UIApplication sharedApplication].keyWindow.traitCollection;
if (traits.horizontalSizeClass == UIUserInterfaceSizeClassCompact)
return NO;
}
return YES;
}
return NO;
}
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection {
return UIModalPresentationNone;
}
@end
#else
@interface MyPopoverController:UIPopoverController
@end
@implementation MyPopoverController
+(BOOL)canShowPopover {
return IS_IPAD;
}
@end
#endif
@interface AbstractActionSheetPicker () <UIGestureRecognizerDelegate>
@property(nonatomic, strong) UIBarButtonItem *barButtonItem;
@property(nonatomic, strong) UIBarButtonItem *doneBarButtonItem;
@property(nonatomic, strong) UIBarButtonItem *cancelBarButtonItem;
@property(nonatomic, strong) UIView *containerView;
@property(nonatomic, unsafe_unretained) id target;
@property(nonatomic, assign) SEL successAction;
@property(nonatomic, assign) SEL cancelAction;
@property(nonatomic, strong) UIPopoverController *popOverController;
@property(nonatomic, strong) CIFilter *filter;
@property(nonatomic, strong) CIContext *context;
@property(nonatomic, strong) NSObject *selfReference;
- (void)presentPickerForView:(UIView *)aView;
- (void)configureAndPresentPopoverForView:(UIView *)aView;
- (void)configureAndPresentActionSheetForView:(UIView *)aView;
- (void)presentActionSheet:(SWActionSheet *)actionSheet;
- (void)presentPopover:(UIPopoverController *)popover;
- (void)dismissPicker;
- (BOOL)isViewPortrait;
- (BOOL)isValidOrigin:(id)origin;
- (id)storedOrigin;
- (UIToolbar *)createPickerToolbarWithTitle:(NSString *)aTitle;
- (UIBarButtonItem *)createButtonWithType:(UIBarButtonSystemItem)type target:(id)target action:(SEL)buttonAction;
- (IBAction)actionPickerDone:(id)sender;
- (IBAction)actionPickerCancel:(id)sender;
@end
@implementation AbstractActionSheetPicker
#pragma mark - Abstract Implementation
- (instancetype)init {
self = [super init];
if (self) {
self.windowLevel = UIWindowLevelAlert;
self.presentFromRect = CGRectZero;
self.popoverBackgroundViewClass = nil;
self.popoverDisabled = NO;
#pragma clang diagnostic push
#pragma ide diagnostic ignored "UnavailableInDeploymentTarget"
if ([UIApplication instancesRespondToSelector:@selector(supportedInterfaceOrientationsForWindow:)])
self.supportedInterfaceOrientations = (UIInterfaceOrientationMask) [[UIApplication sharedApplication]
supportedInterfaceOrientationsForWindow:
[UIApplication sharedApplication].keyWindow];
else {
self.supportedInterfaceOrientations = UIInterfaceOrientationMaskAllButUpsideDown;
if (IS_IPAD)
self.supportedInterfaceOrientations |= (1 << UIInterfaceOrientationPortraitUpsideDown);
}
#pragma clang diagnostic pop
UIBarButtonItem *sysDoneButton = [self createButtonWithType:UIBarButtonSystemItemDone target:self
action:@selector(actionPickerDone:)];
UIBarButtonItem *sysCancelButton = [self createButtonWithType:UIBarButtonSystemItemCancel target:self
action:@selector(actionPickerCancel:)];
[self setCancelBarButtonItem:sysCancelButton];
[self setDoneBarButtonItem:sysDoneButton];
self.tapDismissAction = TapActionNone;
//allows us to use this without needing to store a reference in calling class
self.selfReference = self;
NSMutableParagraphStyle *labelParagraphStyle = [[NSMutableParagraphStyle alloc] init];
labelParagraphStyle.alignment = NSTextAlignmentCenter;
self.pickerTextAttributes = [@{NSParagraphStyleAttributeName : labelParagraphStyle} mutableCopy];
self.context = [CIContext contextWithOptions:nil];
self.filter = [CIFilter filterWithName:@"CIGaussianBlur"];
}
return self;
}
- (void)setTextColor:(UIColor *)textColor {
if (self.pickerTextAttributes) {
self.pickerTextAttributes[NSForegroundColorAttributeName] = textColor;
} else {
self.pickerTextAttributes = [@{NSForegroundColorAttributeName : [UIColor whiteColor]} mutableCopy];
}
}
- (instancetype)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin {
self = [self init];
if (self) {
self.target = target;
self.successAction = successAction;
self.cancelAction = cancelActionOrNil;
if ([origin isKindOfClass:[UIBarButtonItem class]])
self.barButtonItem = origin;
else if ([origin isKindOfClass:[UIView class]])
self.containerView = origin;
else
NSAssert(NO, @"Invalid origin provided to ActionSheetPicker ( %@ )", origin);
}
return self;
}
- (void)dealloc {
//need to clear picker delegates and datasources, otherwise they may call this object after it's gone
if ([self.pickerView respondsToSelector:@selector(setDelegate:)])
[self.pickerView performSelector:@selector(setDelegate:) withObject:nil];
if ([self.pickerView respondsToSelector:@selector(setDataSource:)])
[self.pickerView performSelector:@selector(setDataSource:) withObject:nil];
if ([self.pickerView respondsToSelector:@selector(removeTarget:action:forControlEvents:)])
[((UIControl *) self.pickerView) removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
self.target = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (UIView *)configuredPickerView {
NSAssert(NO, @"This is an abstract class, you must use a subclass of AbstractActionSheetPicker (like ActionSheetStringPicker)");
return nil;
}
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin {
NSAssert(NO, @"This is an abstract class, you must use a subclass of AbstractActionSheetPicker (like ActionSheetStringPicker)");
}
- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin {
if (target && cancelAction && [target respondsToSelector:cancelAction]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:cancelAction withObject:origin];
#pragma clang diagnostic pop
}
}
#pragma mark - Actions
- (void)showActionSheetPicker {
UIView *masterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.viewSize.width, 260)];
// to fix bug, appeared only on iPhone 4 Device: https://github.com/skywinder/ActionSheetPicker-3.0/issues/5
if (isIPhone4()) {
masterView.backgroundColor = [UIColor colorWithRed:0.97 green:0.97 blue:0.97 alpha:1.0];
}
self.toolbar = [self createPickerToolbarWithTitle:self.title];
[masterView addSubview:self.toolbar];
//ios7 picker draws a darkened alpha-only region on the first and last 8 pixels horizontally, but blurs the rest of its background. To make the whole popup appear to be edge-to-edge, we have to add blurring to the remaining left and right edges.
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
CGRect rect = CGRectMake(0, self.toolbar.frame.origin.y, _borderWidth, masterView.frame.size.height - self.toolbar.frame.origin.y);
UIToolbar *leftEdge = [[UIToolbar alloc] initWithFrame:rect];
rect.origin.x = masterView.frame.size.width - _borderWidth;
UIToolbar *rightEdge = [[UIToolbar alloc] initWithFrame:rect];
#pragma clang diagnostic push
#pragma ide diagnostic ignored "UnavailableInDeploymentTarget"
leftEdge.barTintColor = rightEdge.barTintColor = self.toolbar.barTintColor;
#pragma clang diagnostic pop
[masterView insertSubview:leftEdge atIndex:0];
[masterView insertSubview:rightEdge atIndex:0];
}
self.pickerView = [self configuredPickerView];
NSAssert(_pickerView != NULL, @"Picker view failed to instantiate, perhaps you have invalid component data.");
// toolbar hidden remove the toolbar frame and update pickerview frame
if (self.toolbar.hidden) {
int halfWidth = (int) (_borderWidth * 0.5f);
masterView.frame = CGRectMake(0, 0, self.viewSize.width, 220);
self.pickerView.frame = CGRectMake(0, halfWidth, self.viewSize.width, 220 - halfWidth);
}
[masterView addSubview:_pickerView];
if ((![MyPopoverController canShowPopover] || self.popoverDisabled) && !self.pickerBackgroundColor && !self.toolbarBackgroundColor && [self.pickerBlurRadius intValue] > 0) {
[self blurPickerBackground];
} else {
[self presentPickerForView:masterView];
}
#pragma clang diagnostic push
#pragma ide diagnostic ignored "UnavailableInDeploymentTarget"
{
switch (self.tapDismissAction) {
case TapActionNone:
break;
case TapActionSuccess: {
// add tap dismiss action
self.actionSheet.window.userInteractionEnabled = YES;
UITapGestureRecognizer *tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionPickerDone:)];
tapAction.delegate = self;
[self.actionSheet.window addGestureRecognizer:tapAction];
break;
}
case TapActionCancel: {
// add tap dismiss action
self.actionSheet.window.userInteractionEnabled = YES;
UITapGestureRecognizer *tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionPickerCancel:)];
tapAction.delegate = self;
[self.actionSheet.window addGestureRecognizer:tapAction];
break;
}
};
}
#pragma clang diagnostic pop
}
- (IBAction)actionPickerDone:(id)sender {
[self notifyTarget:self.target didSucceedWithAction:self.successAction origin:[self storedOrigin]];
[self dismissPicker];
}
- (IBAction)actionPickerCancel:(id)sender {
[self notifyTarget:self.target didCancelWithAction:self.cancelAction origin:[self storedOrigin]];
[self dismissPicker];
}
- (void)dismissPicker {
#if __IPHONE_4_1 <= __IPHONE_OS_VERSION_MAX_ALLOWED
if (self.actionSheet)
#else
if (self.actionSheet && [self.actionSheet isVisible])
#endif
[_actionSheet dismissWithClickedButtonIndex:0 animated:YES];
else if (self.popOverController && self.popOverController.popoverVisible)
[_popOverController dismissPopoverAnimated:YES];
self.actionSheet = nil;
self.popOverController = nil;
self.selfReference = nil;
}
#pragma mark - Custom Buttons
- (NSMutableArray *)customButtons {
if (!_customButtons) {
_customButtons = [[NSMutableArray alloc] init];
}
return _customButtons;
}
- (void)addCustomButtonWithTitle:(NSString *)title value:(id)value {
if (!title)
title = @"";
if (!value)
value = @0;
NSDictionary *buttonDetails = @{
kButtonTitle : title,
kActionType : @(ActionTypeValue),
kButtonValue : value
};
[self.customButtons addObject:buttonDetails];
}
- (void)addCustomButtonWithTitle:(NSString *)title actionBlock:(ActionBlock)block {
if (!title)
title = @"";
if (!block)
block = (^{
});
NSDictionary *buttonDetails = @{
kButtonTitle : title,
kActionType : @(ActionTypeBlock),
kButtonValue : [block copy]
};
[self.customButtons addObject:buttonDetails];
}
- (void)addCustomButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector {
if (!title)
title = @"";
if (!target)
target = [NSNull null];
NSDictionary *buttonDetails = @{
kButtonTitle : title,
kActionType : @(ActionTypeSelector),
kActionTarget : target,
kButtonValue : [NSValue valueWithPointer:selector]
};
[self.customButtons addObject:buttonDetails];
}
- (IBAction)customButtonPressed:(id)sender {
UIBarButtonItem *button = (UIBarButtonItem *) sender;
NSInteger index = button.tag;
NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %ld, custom button count: %lu", (long) index, (unsigned long) self.customButtons.count);
NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index];
NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid");
ActionType actionType = (ActionType) [buttonDetails[kActionType] integerValue];
switch (actionType) {
case ActionTypeValue: {
NSAssert([self.pickerView respondsToSelector:@
selector(selectRow:inComponent:animated:)], @"customButtonPressed not overridden, cannot interact with subclassed pickerView");
NSInteger buttonValue = [buttonDetails[kButtonValue] integerValue];
UIPickerView *picker = (UIPickerView *) self.pickerView;
NSAssert(picker != NULL, @"PickerView is invalid");
[picker selectRow:buttonValue inComponent:0 animated:YES];
if ([self respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)]) {
void (*objc_msgSendTyped)(id target, SEL _cmd, id pickerView, NSInteger row, NSInteger component) = (void *) objc_msgSend; // sending Integers as params
objc_msgSendTyped(self, @selector(pickerView:didSelectRow:inComponent:), picker, buttonValue, 0);
}
break;
}
case ActionTypeBlock: {
ActionBlock actionBlock = buttonDetails[kButtonValue];
[self dismissPicker];
if (actionBlock)
actionBlock();
break;
}
case ActionTypeSelector: {
SEL selector = [buttonDetails[kButtonValue] pointerValue];
id target = buttonDetails[kActionTarget];
[self dismissPicker];
if (target && [target respondsToSelector:selector]) {
SuppressPerformSelectorLeakWarning (
[target performSelector:selector];
);
}
break;
}
default:
NSAssert(false, @"Unknown action type");
break;
}
}
// Allow the user to specify a custom cancel button
- (void)setCancelButton:(UIBarButtonItem *)button {
if (!button) {
self.hideCancel = YES;
return;
}
if ([button.customView isKindOfClass:[UIButton class]]) {
UIButton *uiButton = (UIButton *) button.customView;
[uiButton addTarget:self action:@selector(actionPickerCancel:) forControlEvents:UIControlEventTouchUpInside];
}
else {
[button setTarget:self];
[button setAction:@selector(actionPickerCancel:)];
}
self.cancelBarButtonItem = button;
}
// Allow the user to specify a custom done button
- (void)setDoneButton:(UIBarButtonItem *)button {
if ([button.customView isKindOfClass:[UIButton class]]) {
UIButton *uiButton = (UIButton *) button.customView;
[button setAction:@selector(actionPickerDone:)];
[uiButton addTarget:self action:@selector(actionPickerDone:) forControlEvents:UIControlEventTouchUpInside];
}
else {
[button setTarget:self];
[button setAction:@selector(actionPickerDone:)];
}
[button setTarget:self];
[button setAction:@selector(actionPickerDone:)];
self.doneBarButtonItem = button;
}
- (void)hidePickerWithCancelAction {
[self actionPickerCancel:nil];
}
- (UIToolbar *)createPickerToolbarWithTitle:(NSString *)title {
CGRect frame = CGRectMake(0, 0, self.viewSize.width, 44);
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:frame];
pickerToolbar.barStyle = (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) ? UIBarStyleDefault : UIBarStyleBlackTranslucent;
pickerToolbar.barTintColor = self.toolbarBackgroundColor;
pickerToolbar.tintColor = self.toolbarButtonsColor;
NSMutableArray *barItems = [[NSMutableArray alloc] init];
if (!self.hideCancel) {
[barItems addObject:self.cancelBarButtonItem];
}
NSInteger index = 0;
for (NSDictionary *buttonDetails in self.customButtons) {
NSString *buttonTitle = buttonDetails[kButtonTitle];
UIBarButtonItem *button;
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
button = [[UIBarButtonItem alloc] initWithTitle:buttonTitle style:UIBarButtonItemStylePlain
target:self action:@selector(customButtonPressed:)];
}
else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
button = [[UIBarButtonItem alloc] initWithTitle:buttonTitle style:UIBarButtonItemStyleBordered
target:self action:@selector(customButtonPressed:)];
#pragma clang diagnostic pop
}
button.tag = index;
[barItems addObject:button];
index++;
}
UIBarButtonItem *flexSpace = [self createButtonWithType:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[barItems addObject:flexSpace];
if (title) {
UIBarButtonItem *labelButton;
labelButton = [self createToolbarLabelWithTitle:title titleTextAttributes:self.titleTextAttributes andAttributedTitle:self.attributedTitle];
[barItems addObject:labelButton];
[barItems addObject:flexSpace];
}
[barItems addObject:self.doneBarButtonItem];
[pickerToolbar setItems:barItems animated:NO];
[pickerToolbar layoutIfNeeded];
return pickerToolbar;
}
- (UIBarButtonItem *)createToolbarLabelWithTitle:(NSString *)aTitle
titleTextAttributes:(NSDictionary *)titleTextAttributes
andAttributedTitle:(NSAttributedString *)attributedTitle {
UILabel *toolBarItemLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 180, 30)];
[toolBarItemLabel setTextAlignment:NSTextAlignmentCenter];
[toolBarItemLabel setBackgroundColor:[UIColor clearColor]];
CGFloat strikeWidth;
CGSize textSize;
if (titleTextAttributes) {
toolBarItemLabel.attributedText = [[NSAttributedString alloc] initWithString:aTitle attributes:titleTextAttributes];
textSize = toolBarItemLabel.attributedText.size;
} else if (attributedTitle) {
toolBarItemLabel.attributedText = attributedTitle;
textSize = toolBarItemLabel.attributedText.size;
}
else {
[toolBarItemLabel setTextColor:(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) ? [UIColor blackColor] : [UIColor whiteColor]];
[toolBarItemLabel setFont:[UIFont boldSystemFontOfSize:16]];
toolBarItemLabel.text = aTitle;
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
#pragma clang diagnostic push
#pragma ide diagnostic ignored "UnavailableInDeploymentTarget"
textSize = [[toolBarItemLabel text] sizeWithAttributes:@{NSFontAttributeName : [toolBarItemLabel font]}];
#pragma clang diagnostic pop
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
textSize = [[toolBarItemLabel text] sizeWithFont:[toolBarItemLabel font]];
#pragma clang diagnostic pop
}
}
strikeWidth = textSize.width;
if (strikeWidth < 180) {
[toolBarItemLabel sizeToFit];
}
UIBarButtonItem *buttonLabel = [[UIBarButtonItem alloc] initWithCustomView:toolBarItemLabel];
return buttonLabel;
}
- (UIBarButtonItem *)createButtonWithType:(UIBarButtonSystemItem)type target:(id)target action:(SEL)buttonAction {
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:type target:target
action:buttonAction];
return barButton;
}
#pragma mark - Custom Color
- (void)setPickerBackgroundColor:(UIColor *)backgroundColor {
_pickerBackgroundColor = backgroundColor;
_actionSheet.bgView.backgroundColor = backgroundColor;
}
#pragma mark - Picker blur effect
- (void)blurPickerBackground {
UIWindow *window = [UIApplication sharedApplication].delegate.window;
UIViewController *rootViewController = window.rootViewController;
UIView *masterView = self.pickerView.superview;
self.pickerView.backgroundColor = [UIColor clearColor];
masterView.backgroundColor = [UIColor clearColor];
// Get the snapshot
UIGraphicsBeginImageContext(rootViewController.view.bounds.size);
[rootViewController.view drawViewHierarchyInRect:rootViewController.view.bounds afterScreenUpdates:NO];
UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self presentPickerForView:masterView];
// Crop the snapshot to match picker frame
CIImage *image = [CIImage imageWithCGImage:[backgroundImage CGImage]];
[self.filter setValue:image forKey:kCIInputImageKey];
[self.filter setValue:self.pickerBlurRadius forKey:kCIInputRadiusKey];
CGRect blurFrame = [rootViewController.view convertRect:self.pickerView.frame fromView:masterView];
// CoreImage coordinate system and UIKit coordinate system differs, so we need to adjust the frame
blurFrame.origin.y = - (blurFrame.origin.y - rootViewController.view.frame.size.height) - blurFrame.size.height;
CGImageRef imageRef = [self.context createCGImage:self.filter.outputImage fromRect:blurFrame];
UIImageView *blurredImageView = [[UIImageView alloc] initWithFrame:self.pickerView.frame];
blurredImageView.image = [UIImage imageWithCGImage:imageRef];
blurredImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[masterView addSubview:blurredImageView];
[masterView sendSubviewToBack:blurredImageView];
CGImageRelease(imageRef);
}
#pragma mark - Utilities and Accessors
- (CGSize)viewSize {
if (IS_IPAD) {
if (!self.popoverDisabled && [MyPopoverController canShowPopover])
return CGSizeMake(320, 320);
return [UIApplication sharedApplication].keyWindow.bounds.size;
}
#if defined(__IPHONE_8_0)
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
//iOS 7.1 or earlier
if ([self isViewPortrait])
return CGSizeMake(320, IS_WIDESCREEN ? 568 : 480);
return CGSizeMake(IS_WIDESCREEN ? 568 : 480, 320);
} else {
//iOS 8 or later
return [[UIScreen mainScreen] bounds].size;
}
#else
if ( [self isViewPortrait] )
return CGSizeMake(320 , IS_WIDESCREEN ? 568 : 480);
return CGSizeMake(IS_WIDESCREEN ? 568 : 480, 320);
#endif
}
- (BOOL)isViewPortrait {
return UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation);
}
- (BOOL)isValidOrigin:(id)origin {
if (!origin)
return NO;
BOOL isButton = [origin isKindOfClass:[UIBarButtonItem class]];
BOOL isView = [origin isKindOfClass:[UIView class]];
return (isButton || isView);
}
- (id)storedOrigin {
if (self.barButtonItem)
return self.barButtonItem;
return self.containerView;
}
#pragma mark - Popovers and ActionSheets
- (void)presentPickerForView:(UIView *)aView {
self.presentFromRect = aView.frame;
if (!self.popoverDisabled && [MyPopoverController canShowPopover])
[self configureAndPresentPopoverForView:aView];
else
[self configureAndPresentActionSheetForView:aView];
}
- (void)configureAndPresentActionSheetForView:(UIView *)aView {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
_actionSheet = [[SWActionSheet alloc] initWithView:aView windowLevel:self.windowLevel];
if (self.pickerBackgroundColor) {
_actionSheet.bgView.backgroundColor = self.pickerBackgroundColor;
}
[self presentActionSheet:_actionSheet];
// Use beginAnimations for a smoother popup animation, otherwise the UIActionSheet pops into view
[UIView beginAnimations:nil context:nil];
// _actionSheet.bounds = CGRectMake(0, 0, self.viewSize.width, sheetHeight);
[UIView commitAnimations];
}
- (void)didRotate:(NSNotification *)notification {
if (OrientationMaskSupportsOrientation(self.supportedInterfaceOrientations, DEVICE_ORIENTATION))
[self dismissPicker];
}
- (void)presentActionSheet:(SWActionSheet *)actionSheet {
NSParameterAssert(actionSheet != NULL);
if (self.barButtonItem)
[actionSheet showFromBarButtonItem:_barButtonItem animated:YES];
else
[actionSheet showInContainerView];
}
- (void)configureAndPresentPopoverForView:(UIView *)aView {
UIViewController *viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
viewController.view = aView;
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
#pragma clang diagnostic push
#pragma ide diagnostic ignored "UnavailableInDeploymentTarget"
viewController.preferredContentSize = aView.frame.size;
#pragma clang diagnostic pop
}
else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
viewController.contentSizeForViewInPopover = viewController.view.frame.size;
#pragma clang diagnostic pop
}
_popOverController = [[MyPopoverController alloc] initWithContentViewController:viewController];
_popOverController.delegate = self;
if (self.pickerBackgroundColor) {
self.popOverController.backgroundColor = self.pickerBackgroundColor;
}
if (self.popoverBackgroundViewClass) {
[self.popOverController setPopoverBackgroundViewClass:self.popoverBackgroundViewClass];
}
[self presentPopover:_popOverController];
}
- (void)presentPopover:(UIPopoverController *)popover {
NSParameterAssert(popover != NULL);
if (self.barButtonItem) {
if (_containerView != nil) {
[popover presentPopoverFromRect:CGRectMake(_containerView.frame.size.width / 2.f, 0.f, 0, 0) inView:_containerView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
} else {
[popover presentPopoverFromBarButtonItem:_barButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
return;
}
else if ((self.containerView)) {
dispatch_async(dispatch_get_main_queue(), ^{
[popover presentPopoverFromRect:_containerView.bounds inView:_containerView
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
});
return;
}
// Unfortunately, things go to hell whenever you try to present a popover from a table view cell. These are failsafes.
UIView *origin = nil;
CGRect presentRect = CGRectZero;
@try {
origin = (_containerView.superview ? _containerView.superview : _containerView);
presentRect = origin.bounds;
dispatch_async(dispatch_get_main_queue(), ^{
[popover presentPopoverFromRect:presentRect inView:origin
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
});
}
@catch (NSException *exception) {
origin = [[[[UIApplication sharedApplication] keyWindow] rootViewController] view];
presentRect = CGRectMake(origin.center.x, origin.center.y, 1, 1);
dispatch_async(dispatch_get_main_queue(), ^{
[popover presentPopoverFromRect:presentRect inView:origin
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
});
}
}
#pragma mark - Popoverdelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
switch (self.tapDismissAction) {
case TapActionSuccess: {
[self notifyTarget:self.target didSucceedWithAction:self.successAction origin:self.storedOrigin];
break;
}
case TapActionNone:
case TapActionCancel: {
[self notifyTarget:self.target didCancelWithAction:self.cancelAction origin:self.storedOrigin];
break;
}
};
}
#pragma mark UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
CGPoint location = [gestureRecognizer locationInView:self.toolbar];
return !CGRectContainsPoint(self.toolbar.bounds, location);
}
@end

View file

@ -1,37 +0,0 @@
//
// ActionSheetPicker.h
// ActionSheetPicker
//
// Created by on 13/03/2012.
// Copyright (c) 2012 Club 15CC. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AbstractActionSheetPicker.h"
#import "ActionSheetCustomPickerDelegate.h"
@interface ActionSheetCustomPicker : AbstractActionSheetPicker
{
}
/////////////////////////////////////////////////////////////////////////
#pragma mark - Properties
/////////////////////////////////////////////////////////////////////////
@property(nonatomic, strong) id <ActionSheetCustomPickerDelegate> delegate;
/////////////////////////////////////////////////////////////////////////
#pragma mark - Init Methods
/////////////////////////////////////////////////////////////////////////
/** Designated init */
- (instancetype)initWithTitle:(NSString *)title delegate:(id <ActionSheetCustomPickerDelegate>)delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin;
- (instancetype)initWithTitle:(NSString *)title delegate:(id <ActionSheetCustomPickerDelegate>)delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections;
/** Convenience class method for creating an launched */
+ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id <ActionSheetCustomPickerDelegate>)delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin;
+ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id <ActionSheetCustomPickerDelegate>)delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections;
@end

View file

@ -1,125 +0,0 @@
//
// ActionSheetPicker.m
// ActionSheetPicker
//
// Created by on 13/03/2012.
// Copyright (c) 2012 Club 15CC. All rights reserved.
//
#import "ActionSheetCustomPicker.h"
@interface ActionSheetCustomPicker ()
@property(nonatomic, strong) NSArray *initialSelections;
@end
@implementation ActionSheetCustomPicker
/////////////////////////////////////////////////////////////////////////
#pragma mark - Init
/////////////////////////////////////////////////////////////////////////
- (instancetype)initWithTitle:(NSString *)title delegate:(id <ActionSheetCustomPickerDelegate>)delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin
{
return [self initWithTitle:title delegate:delegate
showCancelButton:showCancelButton origin:origin
initialSelections:nil];
}
+ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id <ActionSheetCustomPickerDelegate>)delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin
{
return [self showPickerWithTitle:title delegate:delegate showCancelButton:showCancelButton origin:origin
initialSelections:nil ];
}
- (instancetype)initWithTitle:(NSString *)title delegate:(id <ActionSheetCustomPickerDelegate>)delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections
{
if ( self = [self initWithTarget:nil successAction:nil cancelAction:nil origin:origin] )
{
self.title = title;
self.hideCancel = !showCancelButton;
NSAssert(delegate, @"Delegate can't be nil");
_delegate = delegate;
if (initialSelections)
self.initialSelections = [[NSArray alloc] initWithArray:initialSelections];
}
return self;
}
/////////////////////////////////////////////////////////////////////////
+ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id <ActionSheetCustomPickerDelegate>)delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections
{
ActionSheetCustomPicker *picker = [[ActionSheetCustomPicker alloc] initWithTitle:title delegate:delegate
showCancelButton:showCancelButton origin:origin
initialSelections:initialSelections];
[picker showActionSheetPicker];
return picker;
}
/////////////////////////////////////////////////////////////////////////
#pragma mark - AbstractActionSheetPicker fulfilment
/////////////////////////////////////////////////////////////////////////
- (UIView *)configuredPickerView
{
CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216);
UIPickerView *pv = [[UIPickerView alloc] initWithFrame:pickerFrame];
self.pickerView = pv;
// Default to our delegate being the picker's delegate and datasource
pv.delegate = _delegate;
pv.dataSource = _delegate;
pv.showsSelectionIndicator = YES;
if ( self.initialSelections )
{
NSAssert(pv.numberOfComponents == self.initialSelections.count, @"Number of sections not match");
for (NSUInteger i = 0; i < [self.initialSelections count]; i++)
{
NSInteger row = [(NSNumber *) self.initialSelections[i] integerValue];
NSAssert([pv numberOfRowsInComponent:i] > row, @"Number of sections not match");
[pv selectRow:row inComponent:i animated:NO];
// Strangely, the above selectRow:inComponent:animated: will not call
// pickerView:didSelectRow:inComponent: automatically, so we manually call it.
[pv reloadAllComponents];
}
}
// Allow the delegate to override and set additional configs
//to backward compatibility:
if ( [_delegate respondsToSelector:@selector(actionSheetPicker:configurePickerView:)] )
{
[_delegate actionSheetPicker:self configurePickerView:pv];
}
return pv;
}
/////////////////////////////////////////////////////////////////////////
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin
{
// Ignore parent args and just notify the delegate
if ( [_delegate respondsToSelector:@selector(actionSheetPickerDidSucceed:origin:)] )
{
[_delegate actionSheetPickerDidSucceed:self origin:origin];
}
}
/////////////////////////////////////////////////////////////////////////
- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin
{
// Ignore parent args and just notify the delegate
if ( [_delegate respondsToSelector:@selector(actionSheetPickerDidCancel:origin:)] )
{
[_delegate actionSheetPickerDidCancel:self origin:origin];
}
}
@end

View file

@ -1,39 +0,0 @@
//
// ActionSheetPickerDelegate.h
// ActionSheetPicker
//
// Created by on 13/03/2012.
// Copyright (c) 2012 Club 15CC. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AbstractActionSheetPicker.h"
@protocol ActionSheetCustomPickerDelegate <UIPickerViewDelegate, UIPickerViewDataSource>
@optional
/**
Allow the delegate to override default settings for the picker
Allows for instance, ability to set separate delegates and data sources as well as GUI settings on the UIPickerView
If not defined and explicily overridden then this class will be the delegate and dataSource.
*/
- (void)configurePickerView:(UIPickerView *)pickerView DEPRECATED_MSG_ATTRIBUTE("use -actionSheetPicker:configurePickerView: instead.");
- (void)actionSheetPicker:(AbstractActionSheetPicker *)actionSheetPicker configurePickerView:(UIPickerView *)pickerView;
/**
Success callback
\param actionSheetPicker .pickerView property accesses the picker. Requires a cast to UIView subclass for the picker
\param origin The entity which launched the ActionSheetPicker
*/
- (void)actionSheetPickerDidSucceed:(AbstractActionSheetPicker *)actionSheetPicker origin:(id)origin;
/** Cancel callback. See actionSheetPickerDidSuccess:origin: */
- (void)actionSheetPickerDidCancel:(AbstractActionSheetPicker *)actionSheetPicker origin:(id)origin;
@required
@end

View file

@ -1,95 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "AbstractActionSheetPicker.h"
@class ActionSheetDatePicker;
typedef void(^ActionDateDoneBlock)(ActionSheetDatePicker *picker, id selectedDate, id origin); //selectedDate is NSDate or NSNumber for "UIDatePickerModeCountDownTimer"
typedef void(^ActionDateCancelBlock)(ActionSheetDatePicker *picker);
@interface ActionSheetDatePicker : AbstractActionSheetPicker
@property (nonatomic, retain) NSDate *minimumDate; // specify min/max date range. default is nil. When min > max, the values are ignored. Ignored in countdown timer mode
@property (nonatomic, retain) NSDate *maximumDate; // default is nil
@property (nonatomic) NSInteger minuteInterval; // display minutes wheel with interval. interval must be evenly divided into 60. default is 1. min is 1, max is 30
@property (nonatomic, retain) NSLocale *locale; // default is [NSLocale currentLocale]. setting nil returns to default
@property (nonatomic, copy) NSCalendar *calendar; // default is [NSCalendar currentCalendar]. setting nil returns to default
@property (nonatomic, retain) NSTimeZone *timeZone; // default is nil. use current time zone or time zone from calendar
@property (nonatomic, assign) NSTimeInterval countDownDuration; // for UIDatePickerModeCountDownTimer, ignored otherwise. default is 0.0. limit is 23:59 (86,399 seconds). value being set is div 60 (drops remaining seconds).
@property (nonatomic, copy) ActionDateDoneBlock onActionSheetDone;
@property (nonatomic, copy) ActionDateCancelBlock onActionSheetCancel;
+ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin;
+ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction;
+ (instancetype)showPickerWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate
minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate
target:(id)target action:(SEL)action origin:(id)origin;
+ (instancetype)showPickerWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode
selectedDate:(NSDate *)selectedDate
doneBlock:(ActionDateDoneBlock)doneBlock
cancelBlock:(ActionDateCancelBlock)cancelBlock
origin:(UIView*)view;
+ (instancetype)showPickerWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode
selectedDate:(NSDate *)selectedDate
minimumDate:(NSDate *)minimumDate
maximumDate:(NSDate *)maximumDate
doneBlock:(ActionDateDoneBlock)doneBlock
cancelBlock:(ActionDateCancelBlock)cancelBlock
origin:(UIView*)view;
- (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin;
- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action origin:(id)origin;
- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction;
- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action cancelAction:(SEL)cancelAction origin:(id)origin;
- (instancetype)initWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode
selectedDate:(NSDate *)selectedDate
doneBlock:(ActionDateDoneBlock)doneBlock
cancelBlock:(ActionDateCancelBlock)cancelBlock
origin:(UIView*)view;
- (void)eventForDatePicker:(id)sender;
@end

View file

@ -1,272 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "ActionSheetDatePicker.h"
#import <objc/message.h>
@interface ActionSheetDatePicker()
@property (nonatomic, assign) UIDatePickerMode datePickerMode;
@property (nonatomic, strong) NSDate *selectedDate;
@end
@implementation ActionSheetDatePicker
+ (instancetype)showPickerWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate
target:(id)target action:(SEL)action origin:(id)origin {
ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin];
[picker showActionSheetPicker];
return picker;
}
+ (instancetype)showPickerWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate
target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction {
ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin cancelAction:cancelAction];
[picker showActionSheetPicker];
return picker;
}
+ (instancetype)showPickerWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate
minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate
target:(id)target action:(SEL)action origin:(id)origin {
ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin];
[picker setMinimumDate:minimumDate];
[picker setMaximumDate:maximumDate];
[picker showActionSheetPicker];
return picker;
}
+ (instancetype)showPickerWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode
selectedDate:(NSDate *)selectedDate
doneBlock:(ActionDateDoneBlock)doneBlock
cancelBlock:(ActionDateCancelBlock)cancelBlock
origin:(UIView*)view
{
ActionSheetDatePicker* picker = [[ActionSheetDatePicker alloc] initWithTitle:title
datePickerMode:datePickerMode
selectedDate:selectedDate
doneBlock:doneBlock
cancelBlock:cancelBlock
origin:view];
[picker showActionSheetPicker];
return picker;
}
+ (instancetype)showPickerWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode
selectedDate:(NSDate *)selectedDate
minimumDate:(NSDate *)minimumDate
maximumDate:(NSDate *)maximumDate
doneBlock:(ActionDateDoneBlock)doneBlock
cancelBlock:(ActionDateCancelBlock)cancelBlock
origin:(UIView*)view
{
ActionSheetDatePicker* picker = [[ActionSheetDatePicker alloc] initWithTitle:title
datePickerMode:datePickerMode
selectedDate:selectedDate
doneBlock:doneBlock
cancelBlock:cancelBlock
origin:view];
[picker setMinimumDate:minimumDate];
[picker setMaximumDate:maximumDate];
[picker showActionSheetPicker];
return picker;
}
- (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin
{
self = [self initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin cancelAction:nil];
return self;
}
- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action origin:(id)origin
{
self = [self initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin cancelAction:nil];
self.minimumDate = minimumDate;
self.maximumDate = maximumDate;
return self;
}
- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction
{
self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin];
if (self) {
self.title = title;
self.datePickerMode = datePickerMode;
self.selectedDate = selectedDate;
}
return self;
}
- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action cancelAction:(SEL)cancelAction origin:(id)origin
{
self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin];
if (self) {
self.title = title;
self.datePickerMode = datePickerMode;
self.selectedDate = selectedDate;
self.minimumDate = minimumDate;
self.maximumDate = maximumDate;
}
return self;
}
- (instancetype)initWithTitle:(NSString *)title
datePickerMode:(UIDatePickerMode)datePickerMode
selectedDate:(NSDate *)selectedDate
doneBlock:(ActionDateDoneBlock)doneBlock
cancelBlock:(ActionDateCancelBlock)cancelBlock
origin:(UIView*)origin
{
self = [self initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:nil action:nil origin:origin];
if (self) {
self.onActionSheetDone = doneBlock;
self.onActionSheetCancel = cancelBlock;
}
return self;
}
- (UIView *)configuredPickerView {
CGRect datePickerFrame = CGRectMake(0, 40, self.viewSize.width, 216);
UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:datePickerFrame];
datePicker.datePickerMode = self.datePickerMode;
datePicker.maximumDate = self.maximumDate;
datePicker.minimumDate = self.minimumDate;
datePicker.minuteInterval = self.minuteInterval;
datePicker.calendar = self.calendar;
datePicker.timeZone = self.timeZone;
datePicker.locale = self.locale;
// if datepicker is set with a date in countDownMode then
// 1h is added to the initial countdown
if (self.datePickerMode == UIDatePickerModeCountDownTimer) {
datePicker.countDownDuration = self.countDownDuration;
// Due to a bug in UIDatePicker, countDownDuration needs to be set asynchronously
// more info: http://stackoverflow.com/a/20204317/1161723
dispatch_async(dispatch_get_main_queue(), ^{
datePicker.countDownDuration = self.countDownDuration;
});
} else {
[datePicker setDate:self.selectedDate animated:NO];
}
[datePicker addTarget:self action:@selector(eventForDatePicker:) forControlEvents:UIControlEventValueChanged];
//need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing (not used in this picker, but just in case somebody uses this as a template for another picker)
self.pickerView = datePicker;
return datePicker;
}
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)action origin:(id)origin
{
if (self.onActionSheetDone)
{
if (self.datePickerMode == UIDatePickerModeCountDownTimer)
self.onActionSheetDone(self, @(((UIDatePicker *)self.pickerView).countDownDuration), origin);
else
self.onActionSheetDone(self, self.selectedDate, origin);
return;
}
else if ([target respondsToSelector:action])
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
if (self.datePickerMode == UIDatePickerModeCountDownTimer) {
[target performSelector:action withObject:@(((UIDatePicker *)self.pickerView).countDownDuration) withObject:origin];
} else {
[target performSelector:action withObject:self.selectedDate withObject:origin];
}
#pragma clang diagnostic pop
else
NSAssert(NO, @"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(action));
}
- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin
{
if (self.onActionSheetCancel)
{
self.onActionSheetCancel(self);
return;
}
else
if ( target && cancelAction && [target respondsToSelector:cancelAction] )
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:cancelAction withObject:origin];
#pragma clang diagnostic pop
}
}
- (void)eventForDatePicker:(id)sender
{
if (!sender || ![sender isKindOfClass:[UIDatePicker class]])
return;
UIDatePicker *datePicker = (UIDatePicker *)sender;
self.selectedDate = datePicker.date;
self.countDownDuration = datePicker.countDownDuration;
}
- (void)customButtonPressed:(id)sender {
UIBarButtonItem *button = (UIBarButtonItem*)sender;
NSInteger index = button.tag;
NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %zd, custom button count: %zd", index, self.customButtons.count);
NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index];
NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid");
ActionType actionType = (ActionType) [buttonDetails[kActionType] integerValue];
switch (actionType) {
case ActionTypeValue: {
NSAssert([self.pickerView respondsToSelector:@selector(setDate:animated:)], @"Bad pickerView for ActionSheetDatePicker, doesn't respond to setDate:animated:");
NSDate *itemValue = buttonDetails[kButtonValue];
UIDatePicker *picker = (UIDatePicker *)self.pickerView;
if (self.datePickerMode != UIDatePickerModeCountDownTimer)
{
[picker setDate:itemValue animated:YES];
[self eventForDatePicker:picker];
}
break;
}
case ActionTypeBlock:
case ActionTypeSelector:
[super customButtonPressed:sender];
break;
default:
NSAssert(false, @"Unknown action type");
break;
}
}
@end

View file

@ -1,39 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "AbstractActionSheetPicker.h"
#import "DistancePickerView.h"
@interface ActionSheetDistancePicker : AbstractActionSheetPicker <UIPickerViewDelegate, UIPickerViewDataSource>
+ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin;
- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin;
+ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction;
- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction;
@end

View file

@ -1,207 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "ActionSheetDistancePicker.h"
#import <objc/message.h>
@interface ActionSheetDistancePicker()
@property (nonatomic, strong) NSString *bigUnitString;
@property (nonatomic, assign) NSInteger selectedBigUnit;
@property (nonatomic, assign) NSInteger bigUnitMax;
@property (nonatomic, assign) NSInteger bigUnitDigits;
@property (nonatomic, strong) NSString *smallUnitString;
@property (nonatomic, assign) NSInteger selectedSmallUnit;
@property (nonatomic, assign) NSInteger smallUnitMax;
@property (nonatomic, assign) NSInteger smallUnitDigits;
@end
@implementation ActionSheetDistancePicker
+ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin {
ActionSheetDistancePicker *picker = [[ActionSheetDistancePicker alloc] initWithTitle:title bigUnitString:bigUnitString bigUnitMax:bigUnitMax selectedBigUnit:selectedBigUnit smallUnitString:smallUnitString smallUnitMax:smallUnitMax selectedSmallUnit:selectedSmallUnit target:target action:action origin:origin];
[picker showActionSheetPicker];
return picker;
}
- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin {
self = [super initWithTarget:target successAction:action cancelAction:nil origin:origin];
if (self) {
self.title = title;
self.bigUnitString = bigUnitString;
self.bigUnitMax = bigUnitMax;
self.selectedBigUnit = selectedBigUnit;
self.smallUnitString = smallUnitString;
self.smallUnitMax = smallUnitMax;
self.selectedSmallUnit = selectedSmallUnit;
self.bigUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.bigUnitMax] length];
self.smallUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.smallUnitMax] length];
}
return self;
}
+ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction
{
ActionSheetDistancePicker *picker = [[ActionSheetDistancePicker alloc] initWithTitle:title bigUnitString:bigUnitString bigUnitMax:bigUnitMax selectedBigUnit:selectedBigUnit smallUnitString:smallUnitString smallUnitMax:smallUnitMax selectedSmallUnit:selectedSmallUnit target:target action:action origin:origin cancelAction:cancelAction];
[picker showActionSheetPicker];
return picker;
}
- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction
{
self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin];
if (self) {
self.title = title;
self.bigUnitString = bigUnitString;
self.bigUnitMax = bigUnitMax;
self.selectedBigUnit = selectedBigUnit;
self.smallUnitString = smallUnitString;
self.smallUnitMax = smallUnitMax;
self.selectedSmallUnit = selectedSmallUnit;
self.bigUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.bigUnitMax] length];
self.smallUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.smallUnitMax] length];
}
return self;
}
- (UIView *)configuredPickerView {
CGRect distancePickerFrame = CGRectMake(0, 40, self.viewSize.width, 216);
DistancePickerView *picker = [[DistancePickerView alloc] initWithFrame:distancePickerFrame];
picker.delegate = self;
picker.dataSource = self;
picker.showsSelectionIndicator = YES;
// [picker addLabel:self.bigUnitString forComponent:(NSUInteger) (self.bigUnitDigits - 1) forLongestString:nil];
// [picker addLabel:self.smallUnitString forComponent:(NSUInteger) (self.bigUnitDigits + self.smallUnitDigits - 1)
// forLongestString:nil];
NSInteger unitSubtract = 0;
NSInteger currentDigit = 0;
for (int i = 0; i < self.bigUnitDigits; ++i) {
NSInteger factor = (int)pow((double)10, (double)(self.bigUnitDigits - (i+1)));
currentDigit = (( self.selectedBigUnit - unitSubtract ) / factor ) ;
[picker selectRow:currentDigit inComponent:i animated:NO];
unitSubtract += currentDigit * factor;
}
unitSubtract = 0;
for (NSInteger i = self.bigUnitDigits + 1; i < self.bigUnitDigits + self.smallUnitDigits + 1; ++i) {
NSInteger factor = (int)pow((double)10, (double)(self.bigUnitDigits + self.smallUnitDigits + 1 - (i+1)));
currentDigit = (( self.selectedSmallUnit - unitSubtract ) / factor ) ;
[picker selectRow:currentDigit inComponent:i animated:NO];
unitSubtract += currentDigit * factor;
}
//need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing
self.pickerView = picker;
return picker;
}
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)action origin:(id)origin {
NSInteger bigUnits = 0;
NSInteger smallUnits = 0;
DistancePickerView *picker = (DistancePickerView *)self.pickerView;
for (int i = 0; i < self.bigUnitDigits; ++i)
bigUnits += [picker selectedRowInComponent:i] * (int)pow((double)10, (double)(self.bigUnitDigits - (i + 1)));
for (NSInteger i = self.bigUnitDigits + 1; i < self.bigUnitDigits + self.smallUnitDigits + 1; ++i)
smallUnits += [picker selectedRowInComponent:i] * (int)pow((double)10, (double)((picker.numberOfComponents - i - 2)));
//sending three objects, so can't use performSelector:
if ([target respondsToSelector:action])
{
void (*response)(id, SEL, id, id,id) = (void (*)(id, SEL, id, id,id)) objc_msgSend;
response(target, action, @(bigUnits), @(smallUnits), origin);
}
else
NSAssert(NO, @"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(action));
}
#pragma mark -
#pragma mark UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return self.bigUnitDigits + self.smallUnitDigits + 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
//for labels
if (component == self.bigUnitDigits || component == self.bigUnitDigits + self.smallUnitDigits + 1)
return 1;
if (component + 1 <= self.bigUnitDigits) {
if (component == 0)
return self.bigUnitMax / (int)pow((double)10, (double)(self.bigUnitDigits - 1)) + 1;
return 10;
}
if (component == self.bigUnitDigits + 1)
return self.smallUnitMax / (int)pow((double)10, (double)(self.smallUnitDigits - 1)) + 1;
return 10;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
CGFloat totalWidth = pickerView.frame.size.width - 30;
CGFloat otherSize = (totalWidth )/(self.bigUnitDigits + self.smallUnitDigits + 2);
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, otherSize, 30)];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont boldSystemFontOfSize:20];
if ( component == self.bigUnitDigits )
{
label.text = self.bigUnitString;
return label;
}
else if ( component == self.bigUnitDigits + self.smallUnitDigits + 1 )
{
label.text = self.smallUnitString;
return label;
}
label.font = [UIFont systemFontOfSize:20];
label.text = [NSString stringWithFormat:@"%li", (long)row];
return label;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
CGFloat totalWidth = pickerView.frame.size.width - 30;
CGFloat otherSize = (totalWidth )/(self.bigUnitDigits + self.smallUnitDigits + 2);
return otherSize;
}
- (void)customButtonPressed:(id)sender {
NSLog(@"Not implemented. If you get around to it, please contribute back to the project :)");
}
@end

View file

@ -1,63 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "AbstractActionSheetPicker.h"
@class ActionSheetLocalePicker;
typedef void(^ActionLocaleDoneBlock)(ActionSheetLocalePicker *picker, NSTimeZone * selectedValue);
typedef void(^ActionLocaleCancelBlock)(ActionSheetLocalePicker *picker);
static const float firstColumnWidth = 100.0f;
static const float secondColumnWidth = 160.0f;
@interface ActionSheetLocalePicker : AbstractActionSheetPicker <UIPickerViewDelegate, UIPickerViewDataSource>
/**
* Create and display an action sheet picker.
*
* @param title Title label for picker
* @param index is used to establish the initially selected row;
* @param target must not be empty. It should respond to "onSuccess" actions.
* @param successAction successAction
* @param cancelActionOrNil cancelAction
* @param origin must not be empty. It can be either an originating container view or a UIBarButtonItem to use with a popover arrow.
*
* @return return instance of picker
*/
+ (instancetype)showPickerWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin;
// Create an action sheet picker, but don't display until a subsequent call to "showActionPicker". Receiver must release the picker when ready. */
- (instancetype)initWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin;
+ (instancetype)showPickerWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index doneBlock:(ActionLocaleDoneBlock)doneBlock cancelBlock:(ActionLocaleCancelBlock)cancelBlock origin:(id)origin;
- (instancetype)initWithTitle:(NSString *)title initialSelection:(NSTimeZone *)timeZone doneBlock:(ActionLocaleDoneBlock)doneBlock cancelBlock:(ActionLocaleCancelBlock)cancelBlockOrNil origin:(id)origin;
@property (nonatomic, copy) ActionLocaleDoneBlock onActionSheetDone;
@property (nonatomic, copy) ActionLocaleCancelBlock onActionSheetCancel;
@end

View file

@ -1,408 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "ActionSheetLocalePicker.h"
@interface ActionSheetLocalePicker()
//@property (nonatomic,strong) NSArray *data;
//@property (nonatomic,assign) NSInteger selectedIndex;
@property(nonatomic, strong) NSTimeZone *initialTimeZone;
@property (nonatomic, strong) NSString *selectedContinent;
@property (nonatomic, strong) NSString *selectedCity;
@property(nonatomic, strong) NSMutableDictionary *continentsAndCityDictionary;
@property(nonatomic, strong) NSMutableArray *continents;
@end
@implementation ActionSheetLocalePicker
+ (instancetype)showPickerWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index doneBlock:(ActionLocaleDoneBlock)doneBlock cancelBlock:(ActionLocaleCancelBlock)cancelBlockOrNil origin:(id)origin
{
ActionSheetLocalePicker * picker = [[ActionSheetLocalePicker alloc] initWithTitle:title initialSelection:index doneBlock:doneBlock cancelBlock:cancelBlockOrNil origin:origin];
[picker showActionSheetPicker];
return picker;
}
- (instancetype)initWithTitle:(NSString *)title initialSelection:(NSTimeZone *)timeZone doneBlock:(ActionLocaleDoneBlock)doneBlock cancelBlock:(ActionLocaleCancelBlock)cancelBlockOrNil origin:(id)origin
{
self = [self initWithTitle:title initialSelection:timeZone target:nil successAction:nil cancelAction:nil origin:origin];
if (self) {
self.onActionSheetDone = doneBlock;
self.onActionSheetCancel = cancelBlockOrNil;
}
return self;
}
+ (instancetype)showPickerWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin
{
ActionSheetLocalePicker *picker = [[ActionSheetLocalePicker alloc] initWithTitle:title initialSelection:index target:target successAction:successAction cancelAction:cancelActionOrNil origin:origin];
[picker showActionSheetPicker];
return picker;
}
- (instancetype)initWithTitle:(NSString *)title initialSelection:(NSTimeZone *)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin
{
self = [self initWithTarget:target successAction:successAction cancelAction:cancelActionOrNil origin:origin];
if (self) {
self.initialTimeZone = index;
self.title = title;
}
return self;
}
- (UIView *)configuredPickerView {
[self fillContinentsAndCities];
[self setSelectedRows];
CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216);
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.showsSelectionIndicator = YES;
[self selectCurrentLocale:pickerView];
//need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing
self.pickerView = pickerView;
return pickerView;
}
- (void)selectCurrentLocale:(UIPickerView *)pickerView
{
NSUInteger rowContinent = [_continents indexOfObject:self.selectedContinent];
NSUInteger rowCity = [[self getCitiesByContinent:self.selectedContinent] indexOfObject:self.selectedCity];
if ((rowContinent != NSNotFound) && (rowCity != NSNotFound)) // to fix some crashes from prev versions http://crashes.to/s/ecb0f15ce49
{
[pickerView selectRow:rowContinent inComponent:0 animated:YES];
[pickerView reloadComponent:1];
[pickerView selectRow:rowCity inComponent:1 animated:YES];
}
else
{
[pickerView selectRow:0 inComponent:0 animated:YES];
[pickerView selectRow:0 inComponent:1 animated:YES];
}
}
-(void)fillContinentsAndCities
{
NSArray *timeZones = [NSTimeZone knownTimeZoneNames];
NSMutableDictionary *continentsDict = [[NSMutableDictionary alloc] init];
_continents= [[NSMutableArray alloc] init];
[timeZones enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
if ( [obj isKindOfClass:[NSString class]] )
{
NSString *string = (NSString *) obj;
NSArray *array = [string componentsSeparatedByString:@"/"];
if ( [array count] == 2)
{
if ( continentsDict[array[0]] ) //if continent exists
{
NSMutableArray *citys = continentsDict[array[0]];
[citys addObject:array[1]];
}
else //it's new continent
{
NSMutableArray *mutableArray = [@[array[1]] mutableCopy];
continentsDict[array[0]] = mutableArray;
[_continents addObject:array[0]];
}
}
else if (array.count == 3)
{
NSString *string0 = array[0];
NSString *string1 = array[1];
NSString *string2 = array[2];
NSString *string3 = [string1 stringByAppendingFormat:@"/%@", string2];
if ( continentsDict[string0] ) //if continent exists
{
NSMutableArray *citys = continentsDict[string0];
[citys addObject:string3];
}
else //it's new continent
{
NSMutableArray *mutableArray = [@[string3] mutableCopy];
continentsDict[string0] = mutableArray;
[_continents addObject:string0];
}
}
}
}];
self.continentsAndCityDictionary = continentsDict;
};
- (void)setSelectedRows
{
NSString *string;
if (self.initialTimeZone)
string = self.initialTimeZone.name;
else
string = [[NSTimeZone localTimeZone] name];
NSArray *array = [string componentsSeparatedByString:@"/"];
if (array.count == 1)
{
// Unknown time zone - appeared only in travis builds.
self.selectedContinent = _continents[0];
self.selectedCity = [self getCitiesByContinent:self.selectedContinent][0];
}
else if (array.count == 2)
{
self.selectedContinent = array[0];
self.selectedCity = array[1];
}
else
{
assert(NO);
}
}
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin {
NSString *timeZoneId = [NSString stringWithFormat:@"%@/%@", self.selectedContinent, self.selectedCity];
NSTimeZone *timeZone = [[NSTimeZone alloc] initWithName:timeZoneId];
if (self.onActionSheetDone) {
_onActionSheetDone(self, timeZone);
return;
}
else if (target && [target respondsToSelector:successAction]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:successAction withObject:timeZone withObject:origin];
#pragma clang diagnostic pop
return;
}
NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(successAction));
}
- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin {
if (self.onActionSheetCancel) {
_onActionSheetCancel(self);
return;
}
else if (target && cancelAction && [target respondsToSelector:cancelAction]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:cancelAction withObject:origin];
#pragma clang diagnostic pop
}
}
#pragma mark - UIPickerViewDelegate / DataSource
//
//- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
// id obj = [self.data objectAtIndex:(NSUInteger) row];
//
// // return the object if it is already a NSString,
// // otherwise, return the description, just like the toString() method in Java
// // else, return nil to prevent exception
//
// if ([obj isKindOfClass:[NSString class]])
// return obj;
//
// if ([obj respondsToSelector:@selector(description)])
// return [obj performSelector:@selector(description)];
//
// return nil;
//}
//
/////////////////////////////////////////////////////////////////////////
#pragma mark - UIPickerViewDataSource Implementation
/////////////////////////////////////////////////////////////////////////
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
// Returns
switch (component) {
case 0: return [_continents count];
case 1: return [[self getCitiesByContinent:self.selectedContinent] count];
default:break;
}
return 0;
}
/////////////////////////////////////////////////////////////////////////
#pragma mark UIPickerViewDelegate Implementation
/////////////////////////////////////////////////////////////////////////
// returns width of column and height of row for each component.
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
switch (component) {
case 0: return firstColumnWidth;
case 1: return secondColumnWidth;
default:break;
}
return 0;
}
- (UIView *)pickerView:(UIPickerView *)pickerView
viewForRow:(NSInteger)row
forComponent:(NSInteger)component
reusingView:(UIView *)view {
UILabel *pickerLabel = (UILabel *)view;
if (pickerLabel == nil) {
CGRect frame = CGRectZero;
switch (component) {
case 0: frame = CGRectMake(0.0, 0.0, firstColumnWidth, 32);
break;
case 1:
frame = CGRectMake(0.0, 0.0, secondColumnWidth, 32);
break;
default:
assert(NO);
break;
}
pickerLabel = [[UILabel alloc] initWithFrame:frame];
[pickerLabel setTextAlignment:NSTextAlignmentCenter];
if ([pickerLabel respondsToSelector:@selector(setMinimumScaleFactor:)])
[pickerLabel setMinimumScaleFactor:0.5];
[pickerLabel setAdjustsFontSizeToFitWidth:YES];
[pickerLabel setBackgroundColor:[UIColor clearColor]];
[pickerLabel setFont:[UIFont systemFontOfSize:20]];
}
NSString *text;
switch (component) {
case 0: text = (self.continents)[(NSUInteger) row];
break;
case 1:
{
NSString *cityTitle = [self getCitiesByContinent:self.selectedContinent][(NSUInteger) row];
NSString *timeZoneId = [NSString stringWithFormat:@"%@/%@", self.selectedContinent, cityTitle];
NSTimeZone *timeZone = [[NSTimeZone alloc] initWithName:timeZoneId];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:@"z"];
text = [cityTitle stringByAppendingString:[NSString stringWithFormat: @" (%@)", [dateFormatter stringFromDate:[NSDate date]]]];
break;
}
default:break;
}
[pickerLabel setText:text];
return pickerLabel;
}
/////////////////////////////////////////////////////////////////////////
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
switch (component) {
case 0:
{
self.selectedContinent = (self.continents)[(NSUInteger) row];
[pickerView reloadComponent:1];
self.selectedCity = [self getCitiesByContinent:self.selectedContinent][(NSUInteger) [pickerView selectedRowInComponent:1]];
return;
}
case 1:
self.selectedCity = [self getCitiesByContinent:self.selectedContinent][(NSUInteger) row];
return;
default:break;
}
}
-(NSMutableArray *)getCitiesByContinent:(NSString *)continent
{
NSMutableArray *citiesIncontinent = _continentsAndCityDictionary[continent];
return citiesIncontinent;
};
- (void)customButtonPressed:(id)sender {
UIBarButtonItem *button = (UIBarButtonItem*)sender;
NSInteger index = button.tag;
NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %ld, custom button count: %lu", (long)index, (unsigned long)self.customButtons.count);
NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index];
NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid");
ActionType actionType = (ActionType) [buttonDetails[kActionType] intValue];
switch (actionType) {
case ActionTypeValue: {
id itemValue = buttonDetails[kButtonValue];
if ( [itemValue isKindOfClass:[NSTimeZone class]] )
{
NSTimeZone *timeZone = (NSTimeZone *) itemValue;
self.initialTimeZone = timeZone;
[self setSelectedRows];
[self selectCurrentLocale:(UIPickerView *) self.pickerView];
}
break;
}
case ActionTypeBlock:
case ActionTypeSelector:
[super customButtonPressed:sender];
break;
default:
NSAssert(false, @"Unknown action type");
break;
}
}
@end

View file

@ -1,65 +0,0 @@
//
// ActionSheetMultipleStringPicker.h
// CoreActionSheetPicker
//
// Created by Alejandro on 21/07/15.
// Copyright (c) 2015 Petr Korolev. All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "AbstractActionSheetPicker.h"
@class ActionSheetMultipleStringPicker;
typedef void(^ActionMultipleStringDoneBlock)(ActionSheetMultipleStringPicker *picker, NSArray *selectedIndexes, id selectedValues);
typedef void(^ActionMultipleStringCancelBlock)(ActionSheetMultipleStringPicker *picker);
@interface ActionSheetMultipleStringPicker : AbstractActionSheetPicker <UIPickerViewDelegate, UIPickerViewDataSource>
/**
* Create and display an action sheet picker.
*
* @param title Title label for picker
* @param data is an array of strings to use for the picker's available selection choices
* @param indexes is used to establish the initially selected row;
* @param target must not be empty. It should respond to "onSuccess" actions.
* @param successAction successAction
* @param cancelActionOrNil cancelAction
* @param origin must not be empty. It can be either an originating container view or a UIBarButtonItem to use with a popover arrow.
*
* @return return instance of picker
*/
+ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin;
// Create an action sheet picker, but don't display until a subsequent call to "showActionPicker". Receiver must release the picker when ready. */
- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin;
+ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlock origin:(id)origin;
- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin;
@property (nonatomic, copy) ActionMultipleStringDoneBlock onActionSheetDone;
@property (nonatomic, copy) ActionMultipleStringCancelBlock onActionSheetCancel;
@end

View file

@ -1,225 +0,0 @@
//
// ActionSheetMultipleStringPicker.m
// CoreActionSheetPicker
//
// Created by Alejandro on 21/07/15.
// Copyright (c) 2015 Petr Korolev. All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "ActionSheetMultipleStringPicker.h"
@interface ActionSheetMultipleStringPicker()
@property (nonatomic,strong) NSArray *data; //Array of string arrays :)
@property (nonatomic,strong) NSArray *initialSelection;
@end
@implementation ActionSheetMultipleStringPicker
+ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin {
ActionSheetMultipleStringPicker * picker = [[ActionSheetMultipleStringPicker alloc] initWithTitle:title rows:strings initialSelection:indexes doneBlock:doneBlock cancelBlock:cancelBlockOrNil origin:origin];
[picker showActionSheetPicker];
return picker;
}
- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin {
self = [self initWithTitle:title rows:strings initialSelection:indexes target:nil successAction:nil cancelAction:nil origin:origin];
if (self) {
self.onActionSheetDone = doneBlock;
self.onActionSheetCancel = cancelBlockOrNil;
}
return self;
}
+ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin {
ActionSheetMultipleStringPicker *picker = [[ActionSheetMultipleStringPicker alloc] initWithTitle:title rows:data initialSelection:indexes target:target successAction:successAction cancelAction:cancelActionOrNil origin:origin];
[picker showActionSheetPicker];
return picker;
}
- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin {
self = [self initWithTarget:target successAction:successAction cancelAction:cancelActionOrNil origin:origin];
if (self) {
self.data = data;
self.initialSelection = indexes;
self.title = title;
}
return self;
}
- (UIView *)configuredPickerView {
if (!self.data)
return nil;
CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216);
UIPickerView *stringPicker = [[UIPickerView alloc] initWithFrame:pickerFrame];
stringPicker.delegate = self;
stringPicker.dataSource = self;
[self performInitialSelectionInPickerView:stringPicker];
if (self.data.count == 0) {
stringPicker.showsSelectionIndicator = NO;
stringPicker.userInteractionEnabled = NO;
} else {
stringPicker.showsSelectionIndicator = YES;
stringPicker.userInteractionEnabled = YES;
}
//need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing
self.pickerView = stringPicker;
return stringPicker;
}
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin {
if (self.onActionSheetDone) {
_onActionSheetDone(self, [self selectedIndexes], [self selection]);
return;
}
else if (target && [target respondsToSelector:successAction]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:successAction withObject:self.selectedIndexes withObject:origin];
#pragma clang diagnostic pop
return;
}
NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker and done block is nil.", object_getClassName(target), sel_getName(successAction));
}
- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin {
if (self.onActionSheetCancel) {
_onActionSheetCancel(self);
return;
}
else if (target && cancelAction && [target respondsToSelector:cancelAction]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:cancelAction withObject:origin];
#pragma clang diagnostic pop
}
}
#pragma mark - UIPickerViewDelegate / DataSource
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return [self.data count];
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return ((NSArray *)self.data[component]).count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
id obj = (self.data)[(NSUInteger) row];
// return the object if it is already a NSString,
// otherwise, return the description, just like the toString() method in Java
// else, return nil to prevent exception
if ([obj isKindOfClass:[NSString class]])
return obj;
if ([obj respondsToSelector:@selector(description)])
return [obj performSelector:@selector(description)];
return nil;
}
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
id obj = (self.data)[component][(NSUInteger) row];
// return the object if it is already a NSString,
// otherwise, return the description, just like the toString() method in Java
// else, return nil to prevent exception
if ([obj isKindOfClass:[NSString class]])
return [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes];
if ([obj respondsToSelector:@selector(description)])
return [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes];
return nil;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *pickerLabel = (UILabel *)view;
if (pickerLabel == nil) {
pickerLabel = [[UILabel alloc] init];
}
id obj = (self.data)[component][row];
NSAttributedString *attributeTitle = nil;
// use the object if it is already a NSString,
// otherwise, use the description, just like the toString() method in Java
// else, use String with no text to ensure this delegate do not return a nil value.
if ([obj isKindOfClass:[NSString class]])
attributeTitle = [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes];
if ([obj respondsToSelector:@selector(description)])
attributeTitle = [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes];
if (attributeTitle == nil) {
attributeTitle = [[NSAttributedString alloc] initWithString:@"" attributes:self.pickerTextAttributes];
}
pickerLabel.attributedText = attributeTitle;
return pickerLabel;
}
- (void)performInitialSelectionInPickerView:(UIPickerView *)pickerView {
for (int i = 0; i < self.selectedIndexes.count; i++) {
NSInteger row = [(NSNumber *)self.initialSelection[i] integerValue];
[pickerView selectRow:row inComponent:i animated:NO];
}
}
- (NSArray *)selection {
NSMutableArray * array = [NSMutableArray array];
for (int i = 0; i < self.data.count; i++) {
id object = self.data[i][[(UIPickerView *)self.pickerView selectedRowInComponent:(NSInteger)i]];
[array addObject: object];
}
return [array copy];
}
- (NSArray *)selectedIndexes {
NSMutableArray * indexes = [NSMutableArray array];
for (int i = 0; i < self.data.count; i++) {
NSNumber *index = [NSNumber numberWithInteger:[(UIPickerView *)self.pickerView selectedRowInComponent:(NSInteger)i]];
[indexes addObject: index];
}
return [indexes copy];
}
//- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
// return pickerView.frame.size.width - 30;
//}
@end

View file

@ -1,35 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "ActionSheetCustomPickerDelegate.h"
#import "AbstractActionSheetPicker.h"
#import "ActionSheetCustomPicker.h"
#import "ActionSheetDatePicker.h"
#import "ActionSheetDistancePicker.h"
#import "ActionSheetLocalePicker.h"
#import "ActionSheetStringPicker.h"
#import "ActionSheetMultipleStringPicker.h"

View file

@ -1,62 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "AbstractActionSheetPicker.h"
@class ActionSheetStringPicker;
typedef void(^ActionStringDoneBlock)(ActionSheetStringPicker *picker, NSInteger selectedIndex, id selectedValue);
typedef void(^ActionStringCancelBlock)(ActionSheetStringPicker *picker);
@interface ActionSheetStringPicker : AbstractActionSheetPicker <UIPickerViewDelegate, UIPickerViewDataSource>
/**
* Create and display an action sheet picker.
*
* @param title Title label for picker
* @param data is an array of strings to use for the picker's available selection choices
* @param index is used to establish the initially selected row;
* @param target must not be empty. It should respond to "onSuccess" actions.
* @param successAction successAction
* @param cancelActionOrNil cancelAction
* @param origin must not be empty. It can be either an originating container view or a UIBarButtonItem to use with a popover arrow.
*
* @return return instance of picker
*/
+ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSInteger)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin;
// Create an action sheet picker, but don't display until a subsequent call to "showActionPicker". Receiver must release the picker when ready. */
- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSInteger)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin;
+ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSInteger)index doneBlock:(ActionStringDoneBlock)doneBlock cancelBlock:(ActionStringCancelBlock)cancelBlock origin:(id)origin;
- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSInteger)index doneBlock:(ActionStringDoneBlock)doneBlock cancelBlock:(ActionStringCancelBlock)cancelBlockOrNil origin:(id)origin;
@property (nonatomic, copy) ActionStringDoneBlock onActionSheetDone;
@property (nonatomic, copy) ActionStringCancelBlock onActionSheetCancel;
@end

View file

@ -1,195 +0,0 @@
//
//Copyright (c) 2011, Tim Cinel
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//* Redistributions of source code must retain the above copyright
//notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright
//notice, this list of conditions and the following disclaimer in the
//documentation and/or other materials provided with the distribution.
//* Neither the name of the <organization> nor the
//names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "ActionSheetStringPicker.h"
@interface ActionSheetStringPicker()
@property (nonatomic,strong) NSArray *data;
@property (nonatomic,assign) NSInteger selectedIndex;
@end
@implementation ActionSheetStringPicker
+ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSInteger)index doneBlock:(ActionStringDoneBlock)doneBlock cancelBlock:(ActionStringCancelBlock)cancelBlockOrNil origin:(id)origin {
ActionSheetStringPicker * picker = [[ActionSheetStringPicker alloc] initWithTitle:title rows:strings initialSelection:index doneBlock:doneBlock cancelBlock:cancelBlockOrNil origin:origin];
[picker showActionSheetPicker];
return picker;
}
- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSInteger)index doneBlock:(ActionStringDoneBlock)doneBlock cancelBlock:(ActionStringCancelBlock)cancelBlockOrNil origin:(id)origin {
self = [self initWithTitle:title rows:strings initialSelection:index target:nil successAction:nil cancelAction:nil origin:origin];
if (self) {
self.onActionSheetDone = doneBlock;
self.onActionSheetCancel = cancelBlockOrNil;
}
return self;
}
+ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSInteger)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin {
ActionSheetStringPicker *picker = [[ActionSheetStringPicker alloc] initWithTitle:title rows:data initialSelection:index target:target successAction:successAction cancelAction:cancelActionOrNil origin:origin];
[picker showActionSheetPicker];
return picker;
}
- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSInteger)index target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin {
self = [self initWithTarget:target successAction:successAction cancelAction:cancelActionOrNil origin:origin];
if (self) {
self.data = data;
self.selectedIndex = index;
self.title = title;
}
return self;
}
- (UIView *)configuredPickerView {
if (!self.data)
return nil;
CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216);
UIPickerView *stringPicker = [[UIPickerView alloc] initWithFrame:pickerFrame];
stringPicker.delegate = self;
stringPicker.dataSource = self;
[stringPicker selectRow:self.selectedIndex inComponent:0 animated:NO];
if (self.data.count == 0) {
stringPicker.showsSelectionIndicator = NO;
stringPicker.userInteractionEnabled = NO;
} else {
stringPicker.showsSelectionIndicator = YES;
stringPicker.userInteractionEnabled = YES;
}
//need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing
self.pickerView = stringPicker;
return stringPicker;
}
- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin {
if (self.onActionSheetDone) {
id selectedObject = (self.data.count > 0) ? (self.data)[(NSUInteger) self.selectedIndex] : nil;
_onActionSheetDone(self, self.selectedIndex, selectedObject);
return;
}
else if (target && [target respondsToSelector:successAction]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:successAction withObject:@(self.selectedIndex) withObject:origin];
#pragma clang diagnostic pop
return;
}
NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker and done block is nil.", object_getClassName(target), sel_getName(successAction));
}
- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin {
if (self.onActionSheetCancel) {
_onActionSheetCancel(self);
return;
}
else if (target && cancelAction && [target respondsToSelector:cancelAction]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:cancelAction withObject:origin];
#pragma clang diagnostic pop
}
}
#pragma mark - UIPickerViewDelegate / DataSource
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
self.selectedIndex = row;
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return self.data.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
id obj = (self.data)[(NSUInteger) row];
// return the object if it is already a NSString,
// otherwise, return the description, just like the toString() method in Java
// else, return nil to prevent exception
if ([obj isKindOfClass:[NSString class]])
return obj;
if ([obj respondsToSelector:@selector(description)])
return [obj performSelector:@selector(description)];
return nil;
}
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
id obj = (self.data)[(NSUInteger) row];
// return the object if it is already a NSString,
// otherwise, return the description, just like the toString() method in Java
// else, return nil to prevent exception
if ([obj isKindOfClass:[NSString class]])
return [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes];
if ([obj respondsToSelector:@selector(description)])
return [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes];
return nil;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *pickerLabel = (UILabel *)view;
if (pickerLabel == nil) {
pickerLabel = [[UILabel alloc] init];
}
id obj = (self.data)[(NSUInteger) row];
NSAttributedString *attributeTitle = nil;
// use the object if it is already a NSString,
// otherwise, use the description, just like the toString() method in Java
// else, use String with no text to ensure this delegate do not return a nil value.
if ([obj isKindOfClass:[NSString class]])
attributeTitle = [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes];
if ([obj respondsToSelector:@selector(description)])
attributeTitle = [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes];
if (attributeTitle == nil) {
attributeTitle = [[NSAttributedString alloc] initWithString:@"" attributes:self.pickerTextAttributes];
}
pickerLabel.attributedText = attributeTitle;
return pickerLabel;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return pickerView.frame.size.width - 30;
}
@end

View file

@ -1,21 +0,0 @@
//
// DistancePickerView.h
//
// Created by Evan on 12/27/10.
// Copyright 2010 NCPTT. All rights reserved.
//
// Adapted from LabeledPickerView by Kåre Morstøl (NotTooBad Software).
// This file only Copyright (c) 2009 Kåre Morstøl (NotTooBad Software).
// This file only under the Eclipse public license v1.0
// http://www.eclipse.org/legal/epl-v10.html
#import <UIKit/UIKit.h>
@interface DistancePickerView : UIPickerView {
NSMutableDictionary *labels;
}
- (void) addLabel:(NSString *)labeltext forComponent:(NSUInteger)component forLongestString:(NSString *)longestString;
- (void) updateLabel:(NSString *)labeltext forComponent:(NSUInteger)component;
@end

View file

@ -1,208 +0,0 @@
//
// DistancePickerView.m
//
// Created by Evan on 12/27/10.
// Copyright 2010 NCPTT. All rights reserved.
//
// Adapted from LabeledPickerView by Kåre Morstøl (NotTooBad Software).
// This file only Copyright (c) 2009 Kåre Morstøl (NotTooBad Software).
// This file only under the Eclipse public license v1.0
// http://www.eclipse.org/legal/epl-v10.html
#import "DistancePickerView.h"
@implementation DistancePickerView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if ( self )
{
labels = [[NSMutableDictionary alloc] initWithCapacity:2];
}
return self;
}
- (void)addLabel:(NSString *)labeltext forComponent:(NSUInteger)component forLongestString:(NSString *)longestString
{
labels[@(component)] = labeltext;
NSString *keyName = [NSString stringWithFormat:@"%@_%ld", @"longestString", (unsigned long)component];
if ( !longestString )
{
longestString = labeltext;
}
labels[keyName] = longestString;
}
- (void)updateLabel:(NSString *)labeltext forComponent:(NSUInteger)component
{
UILabel *theLabel = (UILabel *) [self viewWithTag:component + 1];
// Update label if it doesnt match current label
if ( ![theLabel.text isEqualToString:labeltext] )
{
NSString *keyName = [NSString stringWithFormat:@"%@_%ld", @"longestString", (unsigned long)component];
NSString *longestString = labels[keyName];
// Update label array with our new string value
[self addLabel:labeltext forComponent:component forLongestString:longestString];
// change label during fade out/in
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.75];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
theLabel.alpha = 0.00;
theLabel.text = labeltext;
theLabel.alpha = 1.00;
[UIView commitAnimations];
}
}
/**
Adds the labels to the view, below the selection indicator glass.
The labels are aligned to the right side of the wheel.
The delegate is responsible for providing enough width for both the value and the label.
*/
- (void)didMoveToWindow
{
// exit if view is removed from the window or there are no labels.
if ( !self.window || [labels count] == 0 )
return;
UIFont *labelfont = [UIFont boldSystemFontOfSize:20];
// find the width of all the wheels combined
CGFloat widthofwheels = 0;
for (int i = 0; i < self.numberOfComponents; i++)
{
widthofwheels += [self rowSizeForComponent:i].width;
}
// find the left side of the first wheel.
// seems like a misnomer, but that will soon be corrected.
CGFloat rightsideofwheel = (self.frame.size.width - widthofwheels) / 2;
// cycle through all wheels
for (int component = 0; component < self.numberOfComponents; component++)
{
// find the right side of the wheel
rightsideofwheel += [self rowSizeForComponent:component].width;
// get the text for the label.
// move on to the next if there is no label for this wheel.
NSString *text = labels[@(component)];
if ( text )
{
// set up the frame for the label using our longestString length
NSString *keyName = [NSString stringWithFormat:@"%@_%@", @"longestString",
@(component)];
NSString *longestString = labels[keyName];
CGRect frame;
if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
{
#pragma clang diagnostic push
#pragma ide diagnostic ignored "UnavailableInDeploymentTarget"
frame.size = [longestString sizeWithAttributes:
@{NSFontAttributeName :
labelfont}];
#pragma clang diagnostic pop
}
else
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
frame.size = [longestString sizeWithFont:labelfont];
#pragma clang diagnostic pop
}
// center it vertically
frame.origin.y = (CGFloat) ((self.frame.size.height / 2.f) - (frame.size.height / 2.f) - 0.5f);
// align it to the right side of the wheel, with a margin.
// use a smaller margin for the rightmost wheel.
frame.origin.x = rightsideofwheel - frame.size.width - (component == self.numberOfComponents - 1 ? 5 : 7);
// set up the label. If label already exists, just get a reference to it
BOOL addlabelView = NO;
UILabel *label = (UILabel *) [self viewWithTag:component + 1];
if ( !label )
{
label = [[UILabel alloc] initWithFrame:frame];
addlabelView = YES;
}
label.text = text;
label.font = labelfont;
label.backgroundColor = [UIColor clearColor];
label.shadowColor = [UIColor whiteColor];
label.shadowOffset = CGSizeMake(0, 1);
// Tag cannot be 0 so just increment component number to esnure we get a positive
// NB update/remove Label methods are aware of this incrementation!
label.tag = component + 1;
if ( addlabelView )
{
/*
and now for the tricky bit: adding the label to the view.
kind of a hack to be honest, might stop working if Apple decides to
change the inner workings of the UIPickerView.
*/
if ( self.showsSelectionIndicator )
{
// if this is the last wheel, add label as the third view from the top
if ( component == self.numberOfComponents - 1 ) if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
{
UIView *o = [self.subviews[0] subviews][[[self.subviews[0] subviews] count] - 1];
UIView *subview = [o subviews][2];
UIView *view = [(subview.subviews)[0] subviews][1];
[self insertSubview:label aboveSubview:view];
}
else
{
[self insertSubview:label atIndex:[self.subviews count] - 3];
}
// otherwise add label as the 5th, 10th, 15th etc view from the top
else
{
if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
{
[self insertSubview:label
aboveSubview:[self.subviews[0] subviews][(NSUInteger) component]];
}
else
{
[self insertSubview:label aboveSubview:(self.subviews)[(NSUInteger) (5 * (component + 1))]];
}
}
} else
// there is no selection indicator, so just add it to the top
[self addSubview:label];
}
if ( [self.delegate respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)] )
[self.delegate pickerView:self didSelectRow:[self selectedRowInComponent:component]
inComponent:component];
}
}
}
@end

View file

@ -1,19 +0,0 @@
//
// Created by Petr Korolev on 11/08/14.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface SWActionSheet : UIView
@property(nonatomic, strong) UIView *bgView;
- (void)dismissWithClickedButtonIndex:(int)i animated:(BOOL)animated;
- (void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;
- (instancetype)initWithView:(UIView *)view windowLevel:(UIWindowLevel)windowLevel;
- (void)showInContainerView;
@end

View file

@ -1,223 +0,0 @@
//
// Created by Petr Korolev on 11/08/14.
//
#import "SWActionSheet.h"
static const float delay = 0.f;
static const float duration = .25f;
static const enum UIViewAnimationOptions options = UIViewAnimationOptionCurveEaseIn;
@interface SWActionSheetVC : UIViewController
@property (nonatomic, retain) SWActionSheet *actionSheet;
@end
@interface SWActionSheet ()
{
UIWindow *SWActionSheetWindow;
}
@property (nonatomic, assign) BOOL presented;
@property (nonatomic) UIWindowLevel windowLevel;
- (void)configureFrameForBounds:(CGRect)bounds;
- (void)showInContainerViewAnimated:(BOOL)animated;
@end
@implementation SWActionSheet
{
UIView *view;
UIView *_bgView;
}
- (void)dismissWithClickedButtonIndex:(int)i animated:(BOOL)animated
{
CGPoint fadeOutToPoint = CGPointMake(view.center.x,
self.center.y + CGRectGetHeight(view.frame));
// Window of app
//UIWindow *appWindow = [UIApplication sharedApplication].windows.firstObject;
// Actions
void (^actions)(void) = ^{
self.center = fadeOutToPoint;
self.backgroundColor = [UIColor colorWithWhite:0.f alpha:0.0f];
};
void (^completion)(BOOL) = ^(BOOL finished) {
// if (![appWindow isKeyWindow])
// [appWindow makeKeyAndVisible];
[self destroyWindow];
[self removeFromSuperview];
};
// Do actions animated or not
if (animated) {
[UIView animateWithDuration:duration delay:delay options:options animations:actions completion:completion];
} else {
actions();
completion(YES);
}
self.presented = NO;
}
- (void)destroyWindow
{
if (SWActionSheetWindow)
{
[self actionSheetContainer].actionSheet = nil;
SWActionSheetWindow.hidden = YES;
if ([SWActionSheetWindow isKeyWindow])
[SWActionSheetWindow resignFirstResponder];
SWActionSheetWindow.rootViewController = nil;
SWActionSheetWindow = nil;
}
}
- (UIWindow *)window
{
if ( SWActionSheetWindow )
{
return SWActionSheetWindow;
}
else
{
return SWActionSheetWindow = ({
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.windowLevel = self.windowLevel;
window.backgroundColor = [UIColor clearColor];
window.rootViewController = [SWActionSheetVC new];
window;
});
}
}
- (SWActionSheetVC *)actionSheetContainer
{
return (SWActionSheetVC *) [self window].rootViewController;
}
- (instancetype)initWithView:(UIView *)aView windowLevel:(UIWindowLevel)windowLevel
{
if ((self = [super init]))
{
view = aView;
_windowLevel = windowLevel;
self.backgroundColor = [UIColor colorWithWhite:0.f alpha:0.0f];
_bgView = [UIView new];
_bgView.backgroundColor = [UIColor colorWithRed:247.f/255.f green:247.f/255.f blue:247.f/255.f alpha:1.0f];
[self addSubview:_bgView];
[self addSubview:view];
}
return self;
}
- (void)configureFrameForBounds:(CGRect)bounds
{
self.frame = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height + view.bounds.size.height);
view.frame = CGRectMake(view.bounds.origin.x, bounds.size.height, view.bounds.size.width, view.bounds.size.height);
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
_bgView.frame = view.frame;
_bgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
- (void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated
{
[self showInContainerView];
}
- (void)showInContainerView
{
// Make sheet window visible and active
UIWindow *sheetWindow = [self window];
if (![sheetWindow isKeyWindow])
[sheetWindow makeKeyAndVisible];
sheetWindow.hidden = NO;
// Put our ActionSheet in Container (it will be presented as soon as possible)
self.actionSheetContainer.actionSheet = self;
}
- (void)showInContainerViewAnimated:(BOOL)animated
{
CGPoint toPoint;
CGFloat y = self.center.y - CGRectGetHeight(view.frame);
toPoint = CGPointMake(self.center.x, y);
// Present actions
void (^animations)(void) = ^{
self.center = toPoint;
self.backgroundColor = [UIColor colorWithWhite:0.f alpha:0.5f];
};
// Present sheet
if (animated)
[UIView animateWithDuration:duration delay:delay options:options animations:animations completion:nil];
else
animations();
self.presented = YES;
}
@end
#pragma mark - SWActionSheet Container
@implementation SWActionSheetVC
- (UIStatusBarStyle)preferredStatusBarStyle {
return [UIApplication sharedApplication].statusBarStyle;
}
- (void)setActionSheet:(SWActionSheet *)actionSheet
{
// Prevent processing one action sheet twice
if (_actionSheet == actionSheet)
return;
// Dissmiss previous action sheet if it presented
if (_actionSheet.presented)
[_actionSheet dismissWithClickedButtonIndex:0 animated:YES];
// Remember new action sheet
_actionSheet = actionSheet;
// Present new action sheet
[self presentActionSheetAnimated:YES];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self presentActionSheetAnimated:YES];
}
- (void)presentActionSheetAnimated:(BOOL)animated
{
// New action sheet will be presented only when view controller will be loaded
if (_actionSheet && [self isViewLoaded] && !_actionSheet.presented)
{
[_actionSheet configureFrameForBounds:self.view.bounds];
_actionSheet.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:_actionSheet];
[_actionSheet showInContainerViewAnimated:animated];
}
}
- (BOOL)prefersStatusBarHidden {
return [UIApplication sharedApplication].statusBarHidden;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return NO;
}
// iOS6 support
// ---
- (BOOL)shouldAutorotate
{
return YES;
}
@end

View file

@ -1,230 +0,0 @@
[![Version](http://img.shields.io/cocoapods/v/ActionSheetPicker-3.0.svg)](http://cocoadocs.org/docsets/ActionSheetPicker-3.0)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Build Status](https://travis-ci.org/skywinder/ActionSheetPicker-3.0.svg?branch=master)](https://travis-ci.org/skywinder/ActionSheetPicker-3.0)
[![Issues](http://img.shields.io/github/issues/skywinder/ActionSheetPicker-3.0.svg)](https://github.com/skywinder/ActionSheetPicker-3.0/issues?state=open)
[![License](https://img.shields.io/cocoapods/l/ActionSheetPicker-3.0.svg)](http://cocoadocs.org/docsets/ActionSheetPicker-3.0)
[![Platform](https://img.shields.io/cocoapods/p/ActionSheetPicker-3.0.svg)](http://cocoadocs.org/docsets/ActionSheetPicker-3.0)
ActionSheetPicker-3.0
==================
- [Overview](#overview)
- [Benefits](#benefits)
- [QuickStart](#quickstart)
- [Basic Usage](#basic-usage)
- [Installation](#installation)
- [Example Projects](#example-projects)
- [Screenshots](#screenshots)
- [Apps using this library](#apps-using-this-library)
- [Maintainer and Contributor](#maintainer-and-contributor)
- [Credits](#credits)
- [Contributing](#contributing)
Please welcome: **ActionSheetPicker-3.0**!
`pod 'ActionSheetPicker-3.0', '~> 2.3.0'` (**iOS 5.1.1-9.x** compatible!)
##ActionSheetPicker = UIPickerView + UIActionSheet ##
![Animation](Screenshots/example.gif)
Well, that's how it started. Now, the following is more accurate:
* _**iPhone/iPod** ActionSheetPicker = ActionSheetPicker = A Picker + UIActionSheet_
* _**iPad** ActionSheetPicker = A Picker + UIPopoverController_
## Overview ##
Easily present an ActionSheet with a PickerView, allowing user to select from a number of immutable options.
### Benefits ##
* Spawn pickers with convenience function - delegate or reference
not required. Just provide a target/action callback.
* Add buttons to UIToolbar for quick selection (see ActionSheetDatePicker below)
* Delegate protocol available for more control
* Universal (iPhone/iPod/iPad)
## QuickStart
There are 4 distinct picker view options: `ActionSheetStringPicker`, `ActionSheetDistancePicker`, `ActionSheetDatePicker`, and `ActionSheetCustomPicker`. We'll focus here on how to use the `ActionSheetStringPicker` since it's most likely the one you want to use.
### Basic Usage ##
**For detailed info about customisations, please look [BASIC USAGE](https://github.com/skywinder/ActionSheetPicker-3.0/blob/master/BASIC-USAGE.md)**
- Custom buttons view
- Custom buttons callbacks
- Action by clicking outside of the picker
- Background color and blur effect
- Other customisations
**For detailed examples, please check [Example Projects](#example-projects) in this repo.**
#### `Swift:`
```swift
ActionSheetMultipleStringPicker.show(withTitle: "Multiple String Picker", rows: [
["One", "Two", "A lot"],
["Many", "Many more", "Infinite"]
], initialSelection: [2, 2], doneBlock: {
picker, indexes, values in
print("values = \(values)")
print("indexes = \(indexes)")
print("picker = \(picker)")
return
}, cancel: { ActionMultipleStringCancelBlock in return }, origin: sender)
```
#### `Objective-C:`
```obj-c
// Inside a IBAction method:
// Create an array of strings you want to show in the picker:
NSArray *colors = [NSArray arrayWithObjects:@"Red", @"Green", @"Blue", @"Orange", nil];
[ActionSheetStringPicker showPickerWithTitle:@"Select a Color"
rows:colors
initialSelection:0
doneBlock:^(ActionSheetStringPicker *picker, NSInteger selectedIndex, id selectedValue) {
NSLog(@"Picker: %@, Index: %@, value: %@",
picker, selectedIndex, selectedValue);
}
cancelBlock:^(ActionSheetStringPicker *picker) {
NSLog(@"Block Picker Canceled");
}
origin:sender];
// You can also use self.view if you don't have a sender
```
##Installation##
### CocoaPods
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects.
You can install it with the following command:
```bash
$ gem install cocoapods
```
To integrate ActionSheetPicker-3.0 into your Xcode project using CocoaPods, specify it in your `Podfile`:
```ruby
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
pod 'ActionSheetPicker-3.0'
```
Then, run the following command:
```bash
$ pod install
```
### Import to project
To import pod you should add string:
- For `Obj-c` projects:
```obj-c
#import "ActionSheetPicker.h"
```
- For `Swift` projects:
```swift
import ActionSheetPicker_3_0
```
### Carthage
Carthage is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application.
You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
```bash
$ brew update
$ brew install carthage
```
To integrate ActionSheetPicker-3.0 into your Xcode project using Carthage, specify it in your `Cartfile`:
```ogdl
github "skywinder/ActionSheetPicker-3.0"
```
### Manually
If you prefer not to use either of the aforementioned dependency managers, you can integrate ActionSheetPicker-3.0 into your project manually.
The "old school" way is manually add to your project all from [Pickers](/Pickers) folder.
### Embedded Framework
- Add ActionSheetPicker-3.0 as a [submodule](http://git-scm.com/docs/git-submodule) by opening the Terminal, `cd`-ing into your top-level project directory, and entering the following command:
```bash
$ git submodule add https://github.com/skywinder/ActionSheetPicker-3.0.git
```
- Open the `ActionSheetPicker-3.0` folder, and drag `CoreActionSheetPicker.xcodeproj` into the file navigator of your app project.
- In Xcode, navigate to the target configuration window by clicking on the blue project icon, and selecting the application target under the "Targets" heading in the sidebar.
- Ensure that the deployment target of CoreActionSheetPicker.framework matches that of the application target.
- In the tab bar at the top of that window, open the "Build Phases" panel.
- Expand the "Target Dependencies" group, and add `CoreActionSheetPicker.framework`.
- Click on the `+` button at the top left of the panel and select "New Copy Files Phase". Rename this new phase to "Copy Frameworks", set the "Destination" to "Frameworks", and add `CoreActionSheetPicker.framework`.
## Example Projects##
`open ActionSheetPicker-3.0.xcworkspace`
Here is 4 projects:
- **CoreActionSheetPicker** - all picker files combined in one Framework. (available since `iOS 8`)
- **ActionSheetPicker** - modern and descriptive Obj-C project with many examples.
- **Swift-Example** - example, written on Swift. (only with basic 3 Pickers examples, for all examples please run `ActionSheetPicker` project)
- **ActionSheetPicker-iOS6-7** - iOS 6 and 7 comparable project. or to run only this project `open Example-for-and-6/ActionSheetPicker.xcodeproj`
## Screenshots
![ActionSheetPicker](https://raw.githubusercontent.com/skywinder/ActionSheetPicker-3.0/master/Screenshots/string.png "ActionSheetPicker")
![ActionSheetDatePicker](https://raw.githubusercontent.com/skywinder/ActionSheetPicker-3.0/master/Screenshots/date.png "ActionSheetDatePicker")
![ActionSheetDatePicker](https://raw.githubusercontent.com/Jack-s/ActionSheetPicker-3.0/master/Screenshots/time.png "ActionSheetDatePicker")
![CustomButtons](https://raw.githubusercontent.com/skywinder/ActionSheetPicker-3.0/master/Screenshots/custom.png "CustomButtons")
![iPad Support](https://raw.githubusercontent.com/skywinder/ActionSheetPicker-3.0/master/Screenshots/ipad.png "iPad Support")
## [Apps using this library](https://github.com/skywinder/ActionSheetPicker-3.0/wiki/Apps-using-ActionSheetPicker-3.0)
If you've used this project in a live app, please let me know! Nothing makes me happier than seeing someone else take my work and go wild with it.
*If you are using `ActionSheetPicker-3.0` in your app or know of an app that uses it, please add it to [this] (https://github.com/skywinder/ActionSheetPicker-3.0/wiki/Apps-using-ActionSheetPicker-3.0) list.*
## Maintainer and Contributor
- [Petr Korolev](http://github.com/skywinder) (update to iOS 7 and iOS 8, implementing new pickers, community support)
## Credits
- ActionSheetPicker was originally created by [Tim Cinel](http://github.com/TimCinel) ([@TimCinel](http://twitter.com/TimCinel)) Since the [Tim's repo](https://github.com/TimCinel/ActionSheetPicker) is not support iOS 7+, I forked from his repo and implement iOS 7-8 support, and also bunch of UI fixes, crash-fixes and different customisation abilities.
- And most of all, thanks to ActionSheetPicker-3.0's [growing list of contributors](https://github.com/skywinder/ActionSheetPicker-3.0/graphs/contributors).
## Contributing
1. Create an issue to discuss about your idea
2. Fork it (https://github.com/skywinder/ActionSheetPicker-3.0/fork)
3. Create your feature branch (`git checkout -b my-new-feature`)
4. Commit your changes (`git commit -am 'Add some feature'`)
5. Push to the branch (`git push origin my-new-feature`)
6. Create a new Pull Request
**Bug reports, feature requests, patches, well-wishes, and rap demo tapes are always welcome.**
[![Analytics](https://ga-beacon.appspot.com/UA-52127948-3/ActionSheetPicker-3.0/readme)](https://ga-beacon.appspot.com/UA-52127948-3/ActionSheetPicker-3.0/readme)

View file

@ -26,8 +26,8 @@
#import <GoogleUtilities/GULHeartbeatDateStorage.h>
#import <GoogleUtilities/GULLogger.h>
#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h>
#import <FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h>
#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h"
#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h"
#import <nanopb/pb.h>
#import <nanopb/pb_decode.h>

View file

@ -0,0 +1,61 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** If present, is a BOOL wrapped in an NSNumber. */
#define kFIRCDIsDataCollectionDefaultEnabledKey @"FIRCDIsDataCollectionDefaultEnabledKey"
/** If present, is an int32_t wrapped in an NSNumber. */
#define kFIRCDConfigurationTypeKey @"FIRCDConfigurationTypeKey"
/** If present, is an NSString. */
#define kFIRCDSdkNameKey @"FIRCDSdkNameKey"
/** If present, is an NSString. */
#define kFIRCDSdkVersionKey @"FIRCDSdkVersionKey"
/** If present, is an int32_t wrapped in an NSNumber. */
#define kFIRCDllAppsCountKey @"FIRCDllAppsCountKey"
/** If present, is an NSString. */
#define kFIRCDGoogleAppIDKey @"FIRCDGoogleAppIDKey"
/** If present, is an NSString. */
#define kFIRCDBundleIDKey @"FIRCDBundleID"
/** If present, is a BOOL wrapped in an NSNumber. */
#define kFIRCDUsingOptionsFromDefaultPlistKey @"FIRCDUsingOptionsFromDefaultPlistKey"
/** If present, is an NSString. */
#define kFIRCDLibraryVersionIDKey @"FIRCDLibraryVersionIDKey"
/** If present, is an NSString. */
#define kFIRCDFirebaseUserAgentKey @"FIRCDFirebaseUserAgentKey"
/** Defines the interface of a data object needed to log diagnostics data. */
@protocol FIRCoreDiagnosticsData <NSObject>
@required
/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */
@property(nonatomic) NSDictionary<NSString *, id> *diagnosticObjects;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,34 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRCoreDiagnosticsData.h"
NS_ASSUME_NONNULL_BEGIN
/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */
@protocol FIRCoreDiagnosticsInterop <NSObject>
/** Sends the given diagnostics data.
*
* @param diagnosticsData The diagnostics data object to send.
*/
+ (void)sendDiagnosticsData:(id<FIRCoreDiagnosticsData>)diagnosticsData;
@end
NS_ASSUME_NONNULL_END

View file

@ -2,14 +2,20 @@
[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![Actions Status][gh-abtesting-badge]][gh-actions]
[![Actions Status][gh-auth-badge]][gh-actions]
[![Actions Status][gh-core-badge]][gh-actions]
[![Actions Status][gh-crashlytics-badge]][gh-actions]
[![Actions Status][gh-database-badge]][gh-actions]
[![Actions Status][gh-datatransport-badge]][gh-actions]
[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
[![Actions Status][gh-firebasepod-badge]][gh-actions]
[![Actions Status][gh-firestore-badge]][gh-actions]
[![Actions Status][gh-functions-badge]][gh-actions]
[![Actions Status][gh-inappmessaging-badge]][gh-actions]
[![Actions Status][gh-interop-badge]][gh-actions]
[![Actions Status][gh-messaging-badge]][gh-actions]
[![Actions Status][gh-remoteconfig-badge]][gh-actions]
[![Actions Status][gh-storage-badge]][gh-actions]
[![Actions Status][gh-symbolcollision-badge]][gh-actions]
[![Actions Status][gh-zip-badge]][gh-actions]
@ -92,7 +98,7 @@ Instructions for installing binary frameworks via
To develop Firebase software in this repository, ensure that you have at least
the following software:
* Xcode 10.1 (or later)
* Xcode 10.3 (or later)
* CocoaPods 1.7.2 (or later)
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See
See [AddNewPod.md](AddNewPod.md).
### Managing Headers and Imports
See [HeadersImports.md](HeadersImports.md).
### Code Formatting
To ensure that the code is formatted consistently, run the script
@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
To run the Database Integration tests, make your database authentication rules
[public](https://firebase.google.com/docs/database/security/quickstart).
The Firebase Database Integration tests can be run against a locally running Database Emulator
or against a production instance.
To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
running the integration test.
To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to
[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
running.
### Firebase Storage
@ -274,14 +292,20 @@ Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg

View file

@ -31,7 +31,7 @@
#import <nanopb/pb_decode.h>
#import <nanopb/pb_encode.h>
#import "GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h"
#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h"
#pragma mark - General purpose encoders
@ -145,6 +145,11 @@ gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCOREvent *event) {
length:networkConnectionInfoData.length];
logEvent.has_network_connection_info = 1;
}
NSNumber *eventCode = event.eventCode;
if (eventCode != nil) {
logEvent.has_event_code = 1;
logEvent.event_code = [eventCode intValue];
}
}
NSError *error;
NSData *extensionBytes;

View file

@ -23,7 +23,7 @@
#import <GoogleDataTransport/GDTCORTargets.h>
#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h"
#import "GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h"
#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h"
const static int64_t kMillisPerDay = 8.64e+7;

View file

@ -0,0 +1,236 @@
/*
* Copyright 2020 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h"
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
NSString *const GDTCCTNeedsNetworkConnectionInfo = @"needs_network_connection_info";
NSString *const GDTCCTNetworkConnectionInfo = @"network_connection_info";
NSString *const GDTCCTEventCodeInfo = @"event_code_info";
@implementation GDTCOREvent (GDTCCTSupport)
- (void)setNeedsNetworkConnectionInfoPopulated:(BOOL)needsNetworkConnectionInfoPopulated {
if (!needsNetworkConnectionInfoPopulated) {
if (!self.customBytes) {
return;
}
// Make sure we don't destroy the eventCode data, if any is present.
@try {
NSError *error;
NSMutableDictionary *bytesDict =
[[NSJSONSerialization JSONObjectWithData:self.customBytes options:0
error:&error] mutableCopy];
if (error) {
GDTCORLogDebug(@"Error when setting an event's event_code: %@", error);
return;
}
NSNumber *eventCode = bytesDict[GDTCCTEventCodeInfo];
if (eventCode != nil) {
self.customBytes =
[NSJSONSerialization dataWithJSONObject:@{GDTCCTEventCodeInfo : eventCode}
options:0
error:&error];
}
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@",
exception);
}
} else {
@try {
NSError *error;
NSMutableDictionary *bytesDict;
if (self.customBytes) {
bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes
options:0
error:&error] mutableCopy];
if (error) {
GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error);
return;
}
} else {
bytesDict = [[NSMutableDictionary alloc] init];
}
[bytesDict setObject:@YES forKey:GDTCCTNeedsNetworkConnectionInfo];
self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error];
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@",
exception);
}
}
}
- (BOOL)needsNetworkConnectionInfoPopulated {
if (self.customBytes) {
@try {
NSError *error;
NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes
options:0
error:&error];
return bytesDict && !error && [bytesDict[GDTCCTNeedsNetworkConnectionInfo] boolValue];
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when checking the event for needs_network_connection_info: %@",
exception);
}
}
return NO;
}
- (void)setNetworkConnectionInfoData:(NSData *)networkConnectionInfoData {
@try {
NSError *error;
NSString *dataString = [networkConnectionInfoData base64EncodedStringWithOptions:0];
if (dataString != nil) {
NSMutableDictionary *bytesDict;
if (self.customBytes) {
bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes
options:0
error:&error] mutableCopy];
if (error) {
GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error);
return;
}
} else {
bytesDict = [[NSMutableDictionary alloc] init];
}
[bytesDict setObject:dataString forKey:GDTCCTNetworkConnectionInfo];
self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error];
if (error) {
self.customBytes = nil;
GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error);
}
}
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", exception);
}
}
- (nullable NSData *)networkConnectionInfoData {
if (self.customBytes) {
@try {
NSError *error;
NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes
options:0
error:&error];
NSString *base64Data = bytesDict[GDTCCTNetworkConnectionInfo];
NSData *networkConnectionInfoData = [[NSData alloc] initWithBase64EncodedString:base64Data
options:0];
if (error) {
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error);
return nil;
} else {
return networkConnectionInfoData;
}
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception);
}
}
return nil;
}
- (NSNumber *)eventCode {
if (self.customBytes) {
@try {
NSError *error;
NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes
options:0
error:&error];
NSString *eventCodeString = bytesDict[GDTCCTEventCodeInfo];
if (!eventCodeString) {
return nil;
}
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *eventCode = [formatter numberFromString:eventCodeString];
if (error) {
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error);
return nil;
} else {
return eventCode;
}
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when getting an event's event_code: %@", exception);
}
}
return nil;
}
- (void)setEventCode:(NSNumber *)eventCode {
if (eventCode == nil) {
if (!self.customBytes) {
return;
}
NSError *error;
NSMutableDictionary *bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes
options:0
error:&error] mutableCopy];
if (error) {
GDTCORLogDebug(@"Error when setting an event's event_code: %@", error);
return;
}
[bytesDict removeObjectForKey:GDTCCTEventCodeInfo];
self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error];
if (error) {
self.customBytes = nil;
GDTCORLogDebug(@"Error when setting an event's event_code: %@", error);
return;
}
return;
}
@try {
NSMutableDictionary *bytesDict;
NSError *error;
if (self.customBytes) {
bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes options:0
error:&error] mutableCopy];
if (error) {
GDTCORLogDebug(@"Error when setting an event's event_code: %@", error);
return;
}
} else {
bytesDict = [[NSMutableDictionary alloc] init];
}
NSString *eventCodeString = [eventCode stringValue];
if (eventCodeString == nil) {
return;
}
[bytesDict setObject:eventCodeString forKey:GDTCCTEventCodeInfo];
self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error];
if (error) {
self.customBytes = nil;
GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error);
return;
}
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception);
}
}
@end

View file

@ -1,102 +0,0 @@
/*
* Copyright 2020 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "GDTCCTLibrary/Private/GDTCOREvent+NetworkConnectionInfo.h"
#import <GoogleDataTransport/GDTCORConsoleLogger.h>
NSString *const GDTCCTNeedsNetworkConnectionInfo = @"needs_network_connection_info";
NSString *const GDTCCTNetworkConnectionInfo = @"network_connection_info";
@implementation GDTCOREvent (CCTNetworkConnectionInfo)
- (void)setNeedsNetworkConnectionInfoPopulated:(BOOL)needsNetworkConnectionInfoPopulated {
if (!needsNetworkConnectionInfoPopulated) {
self.customBytes = nil;
} else {
@try {
NSError *error;
self.customBytes =
[NSJSONSerialization dataWithJSONObject:@{GDTCCTNeedsNetworkConnectionInfo : @YES}
options:0
error:&error];
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@",
exception);
}
}
}
- (BOOL)needsNetworkConnectionInfoPopulated {
if (self.customBytes) {
@try {
NSError *error;
NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes
options:0
error:&error];
return bytesDict && !error && [bytesDict[GDTCCTNeedsNetworkConnectionInfo] boolValue];
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when checking the event for needs_network_connection_info: %@",
exception);
}
}
return NO;
}
- (void)setNetworkConnectionInfoData:(NSData *)networkConnectionInfoData {
@try {
NSError *error;
NSString *dataString = [networkConnectionInfoData base64EncodedStringWithOptions:0];
if (dataString) {
self.customBytes =
[NSJSONSerialization dataWithJSONObject:@{GDTCCTNetworkConnectionInfo : dataString}
options:0
error:&error];
if (error) {
self.customBytes = nil;
GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error);
}
}
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", exception);
}
}
- (nullable NSData *)networkConnectionInfoData {
if (self.customBytes) {
@try {
NSError *error;
NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes
options:0
error:&error];
NSString *base64Data = bytesDict[GDTCCTNetworkConnectionInfo];
NSData *networkConnectionInfoData = [[NSData alloc] initWithBase64EncodedString:base64Data
options:0];
if (error) {
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error);
return nil;
} else {
return networkConnectionInfoData;
}
} @catch (NSException *exception) {
GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception);
}
}
return nil;
}
@end

View file

@ -30,7 +30,7 @@ FOUNDATION_EXPORT NSString *const GDTCCTNetworkConnectionInfo;
/** A category that uses the customBytes property of a GDTCOREvent to store network connection info.
*/
@interface GDTCOREvent (CCTNetworkConnectionInfo)
@interface GDTCOREvent (GDTCCTSupport)
/** If YES, needs the network connection info field set during prioritization.
* @note Uses the GDTCOREvent customBytes property.
@ -42,6 +42,10 @@ FOUNDATION_EXPORT NSString *const GDTCCTNetworkConnectionInfo;
*/
@property(nullable, nonatomic) NSData *networkConnectionInfoData;
/** Code that identifies the event to be sent to the CCT backend.
*/
@property(nullable, nonatomic) NSNumber *eventCode;
@end
NS_ASSUME_NONNULL_END

View file

@ -2,14 +2,20 @@
[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![Actions Status][gh-abtesting-badge]][gh-actions]
[![Actions Status][gh-auth-badge]][gh-actions]
[![Actions Status][gh-core-badge]][gh-actions]
[![Actions Status][gh-crashlytics-badge]][gh-actions]
[![Actions Status][gh-database-badge]][gh-actions]
[![Actions Status][gh-datatransport-badge]][gh-actions]
[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
[![Actions Status][gh-firebasepod-badge]][gh-actions]
[![Actions Status][gh-firestore-badge]][gh-actions]
[![Actions Status][gh-functions-badge]][gh-actions]
[![Actions Status][gh-inappmessaging-badge]][gh-actions]
[![Actions Status][gh-interop-badge]][gh-actions]
[![Actions Status][gh-messaging-badge]][gh-actions]
[![Actions Status][gh-remoteconfig-badge]][gh-actions]
[![Actions Status][gh-storage-badge]][gh-actions]
[![Actions Status][gh-symbolcollision-badge]][gh-actions]
[![Actions Status][gh-zip-badge]][gh-actions]
@ -92,7 +98,7 @@ Instructions for installing binary frameworks via
To develop Firebase software in this repository, ensure that you have at least
the following software:
* Xcode 10.1 (or later)
* Xcode 10.3 (or later)
* CocoaPods 1.7.2 (or later)
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
@ -123,6 +129,10 @@ Firestore has a self contained Xcode project. See
See [AddNewPod.md](AddNewPod.md).
### Managing Headers and Imports
See [HeadersImports.md](HeadersImports.md).
### Code Formatting
To ensure that the code is formatted consistently, run the script
@ -185,8 +195,16 @@ building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
To run the Database Integration tests, make your database authentication rules
[public](https://firebase.google.com/docs/database/security/quickstart).
The Firebase Database Integration tests can be run against a locally running Database Emulator
or against a production instance.
To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
running the integration test.
To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to
[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
running.
### Firebase Storage
@ -274,14 +292,20 @@ Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg

View file

@ -14,12 +14,12 @@
#import <TargetConditionals.h>
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
#import <GoogleUtilities/GULLogger.h>
#import <GoogleUtilities/GULMutableDictionary.h>
#import "GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h"
#import "GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h"
#import "GoogleUtilities/Common/GULLoggerCodes.h"
#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h"
#import "GoogleUtilities/Logger/Private/GULLogger.h"
#import "GoogleUtilities/Network/Private/GULMutableDictionary.h"
#import <objc/runtime.h>
@ -37,12 +37,8 @@ typedef void (*GULRealHandleEventsForBackgroundURLSessionIMP)(
id, SEL, GULApplication *, NSString *, void (^)());
#pragma clang diagnostic pop
// This is needed to for the library to be warning free on iOS versions < 8.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
typedef BOOL (*GULRealContinueUserActivityIMP)(
id, SEL, GULApplication *, NSUserActivity *, void (^)(NSArray *restorableObjects));
#pragma clang diagnostic pop
typedef void (*GULRealDidRegisterForRemoteNotificationsIMP)(id, SEL, GULApplication *, NSData *);
@ -53,14 +49,10 @@ typedef void (*GULRealDidFailToRegisterForRemoteNotificationsIMP)(id,
typedef void (*GULRealDidReceiveRemoteNotificationIMP)(id, SEL, GULApplication *, NSDictionary *);
// TODO: Since we don't support iOS 7 anymore, see if we can remove the check below.
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
#if !TARGET_OS_WATCH && !TARGET_OS_OSX
typedef void (*GULRealDidReceiveRemoteNotificationWithCompletionIMP)(
id, SEL, GULApplication *, NSDictionary *, void (^)(UIBackgroundFetchResult));
#pragma clang diagnostic pop
#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH
#endif // !TARGET_OS_WATCH && !TARGET_OS_OSX
typedef void (^GULAppDelegateInterceptorCallback)(id<GULApplicationDelegate>);
@ -519,28 +511,26 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken;
storeDestinationImplementationTo:realImplementationsBySelector];
// For application:didReceiveRemoteNotification:fetchCompletionHandler:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH
if ([GULAppEnvironmentUtil isIOS7OrHigher]) {
SEL didReceiveRemoteNotificationWithCompletionSEL =
NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL);
SEL didReceiveRemoteNotificationWithCompletionDonorSEL =
@selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:);
if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) {
// Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if
// the original AppDelegate implements it.
// This fixes a bug if an app only implements application:didReceiveRemoteNotification:
// (if we add the method with completion, iOS sees that one exists and does not call
// the method without the completion, which in this case is the only one the app implements).
#if !TARGET_OS_WATCH && !TARGET_OS_OSX
SEL didReceiveRemoteNotificationWithCompletionSEL =
NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL);
SEL didReceiveRemoteNotificationWithCompletionDonorSEL =
@selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:);
if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) {
// Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if
// the original AppDelegate implements it.
// This fixes a bug if an app only implements application:didReceiveRemoteNotification:
// (if we add the method with completion, iOS sees that one exists and does not call
// the method without the completion, which in this case is the only one the app implements).
[self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL
implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL
fromClass:[GULAppDelegateSwizzler class]
toClass:appDelegateSubClass
realClass:realClass
storeDestinationImplementationTo:realImplementationsBySelector];
}
[self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL
implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL
fromClass:[GULAppDelegateSwizzler class]
toClass:appDelegateSubClass
realClass:realClass
storeDestinationImplementationTo:realImplementationsBySelector];
}
#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH
#endif // !TARGET_OS_WATCH && !TARGET_OS_OSX
}
/// We have to do this to invalidate the cache that caches the original respondsToSelector of
@ -799,9 +789,6 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken;
#pragma mark - [Donor Methods] User Activities overridden handler methods
// This is needed to for the library to be warning free on iOS versions < 8.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
- (BOOL)application:(GULApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
@ -828,7 +815,6 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken;
}
return returnedValue;
}
#pragma clang diagnostic pop
#pragma mark - [Donor Methods] Remote Notifications
@ -885,9 +871,7 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken;
}
}
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
#if !TARGET_OS_WATCH && !TARGET_OS_OSX
- (void)application:(GULApplication *)application
donor_didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
@ -917,8 +901,7 @@ static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken;
completionHandler);
}
}
#pragma clang diagnostic pop
#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH
#endif // !TARGET_OS_WATCH && !TARGET_OS_OSX
- (void)application:(GULApplication *)application
donor_didReceiveRemoteNotification:(NSDictionary *)userInfo {

View file

@ -15,8 +15,8 @@
*/
#import <Foundation/Foundation.h>
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
#import <GoogleUtilities/GULMutableDictionary.h>
#import "GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h"
#import "GoogleUtilities/Network/Private/GULMutableDictionary.h"
@class GULApplication;

View file

@ -16,7 +16,11 @@
#import <Foundation/Foundation.h>
#if SWIFT_PACKAGE
#import "GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h"
#else
#import <GoogleUtilities/GULApplication.h>
#endif
NS_ASSUME_NONNULL_BEGIN

View file

@ -14,16 +14,20 @@
* limitations under the License.
*/
#import <GoogleUtilities/GULHeartbeatDateStorage.h>
#import <GoogleUtilities/GULSecureCoding.h>
#import "GoogleUtilities/Environment/Private/GULHeartbeatDateStorage.h"
#import "GoogleUtilities/Environment/Private/GULSecureCoding.h"
@interface GULHeartbeatDateStorage ()
/** The storage to store the date of the last sent heartbeat. */
@property(nonatomic, readonly) NSFileCoordinator *fileCoordinator;
/** The name of the file that stores heartbeat information. */
@property(nonatomic, readonly) NSString *fileName;
@end
@implementation GULHeartbeatDateStorage
@synthesize fileURL = _fileURL;
- (instancetype)initWithFileName:(NSString *)fileName {
if (fileName == nil) {
return nil;
@ -32,13 +36,23 @@
self = [super init];
if (self) {
_fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
NSURL *directoryURL = [[self class] directoryPathURL];
[[self class] checkAndCreateDirectory:directoryURL fileCoordinator:_fileCoordinator];
_fileURL = [directoryURL URLByAppendingPathComponent:fileName];
_fileName = fileName;
}
return self;
}
/** Lazy getter for fileURL
* @return fileURL where heartbeat information is stored.
*/
- (NSURL *)fileURL {
if (!_fileURL) {
NSURL *directoryURL = [[self class] directoryPathURL];
[[self class] checkAndCreateDirectory:directoryURL fileCoordinator:_fileCoordinator];
_fileURL = [directoryURL URLByAppendingPathComponent:_fileName];
}
return _fileURL;
}
/** Returns the URL path of the Application Support folder.
* @return the URL path of Application Support.
*/

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#import "GoogleUtilities/Environment/Public/GULSecureCoding.h"
#import "GoogleUtilities/Environment/Private/GULSecureCoding.h"
NSString *const kGULSecureCodingError = @"GULSecureCodingError";

View file

@ -41,6 +41,7 @@
+ (BOOL)isAppExtension;
/// @return Returns @YES when is run on iOS version greater or equal to 7.0
+ (BOOL)isIOS7OrHigher;
+ (BOOL)isIOS7OrHigher DEPRECATED_MSG_ATTRIBUTE(
"Always `YES` because only iOS 8 and higher supported. The method will be removed.");
@end

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
#import <GoogleUtilities/GULKeychainStorage.h>
#import "GoogleUtilities/Environment/Private/GULKeychainStorage.h"
#import <Security/Security.h>
#if __has_include(<FBLPromises/FBLPromises.h>)
@ -23,8 +23,8 @@
#import "FBLPromises.h"
#endif
#import <GoogleUtilities/GULKeychainUtils.h>
#import <GoogleUtilities/GULSecureCoding.h>
#import "GoogleUtilities/Environment/Private/GULKeychainUtils.h"
#import "GoogleUtilities/Environment/Private/GULSecureCoding.h"
@interface GULKeychainStorage ()
@property(nonatomic, readonly) dispatch_queue_t keychainQueue;

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
#import <GoogleUtilities/GULKeychainUtils.h>
#import "GoogleUtilities/Environment/Private/GULKeychainUtils.h"
NSString *const kGULKeychainUtilsErrorDomain = @"com.gul.keychain.ErrorDomain";

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#import "GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h"
#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h"
#import <Foundation/Foundation.h>
#import <dlfcn.h>
@ -187,17 +187,10 @@ static BOOL HasEmbeddedMobileProvision() {
![enableSandboxCheck boolValue]) {
return NO;
}
// The #else is for pre Xcode 9 where @available is not yet implemented.
#if __has_builtin(__builtin_available)
if (@available(iOS 7.0, *)) {
#else
if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) {
#endif
NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL;
NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent;
return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName];
}
return NO;
NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL;
NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent;
return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName];
}
+ (BOOL)isSimulator {
@ -253,15 +246,7 @@ static BOOL HasEmbeddedMobileProvision() {
}
+ (BOOL)isIOS7OrHigher {
#if __has_builtin(__builtin_available)
if (@available(iOS 7.0, *)) {
#else
if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) {
#endif
return YES;
}
return NO;
return YES;
}
@end

View file

@ -12,12 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if SWIFT_PACKAGE
// Need to import the public header here, since the module won't exist yet.
// Restructure the GULLogger headers for Firebase 7.
#import "GoogleUtilities/Logger/Public/GULLoggerLevel.h"
#endif
#import "GoogleUtilities/Logger/Private/GULLogger.h"
#include <asl.h>
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
#import <GoogleUtilities/GULLoggerLevel.h>
#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h"
#import "GoogleUtilities/Logger/Public/GULLoggerLevel.h"
/// ASL client facility name used by GULLogger.
const char *kGULLoggerASLClientFacilityName = "com.google.utilities.logger";

View file

@ -16,7 +16,11 @@
#import <Foundation/Foundation.h>
#if SWIFT_PACKAGE
@import GoogleUtilities_Logger;
#else
#import <GoogleUtilities/GULLoggerLevel.h>
#endif
NS_ASSUME_NONNULL_BEGIN

View file

@ -17,8 +17,8 @@
#import <objc/runtime.h>
#ifdef DEBUG
#import <GoogleUtilities/GULLogger.h>
#import "GoogleUtilities/Common/GULLoggerCodes.h"
#import "GoogleUtilities/Logger/Private/GULLogger.h"
static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/MethodSwizzler]";
#endif

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#import "GoogleUtilities/NSData+zlib/GULNSData+zlib.h"
#import "GoogleUtilities/NSData+zlib/Public/GULNSData+zlib.h"
#import <zlib.h>

View file

@ -0,0 +1,22 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// An umbrella header, for any other libraries in this repo to access Firebase Public and Private
// headers. Any package manager complexity should be handled here.
#if SWIFT_PACKAGE
@import GoogleUtilities_NSData;
#else
#import <GoogleUtilities/GULNSData+zlib.h>
#endif

View file

@ -15,11 +15,11 @@
#import "GoogleUtilities/Network/Private/GULNetwork.h"
#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h"
#import <GoogleUtilities/GULLogger.h>
#import <GoogleUtilities/GULNSData+zlib.h>
#import <GoogleUtilities/GULReachabilityChecker.h>
#import "GoogleUtilities/Logger/Private/GULLogger.h"
#import "GoogleUtilities/NSData+zlib/Private/GULNSDataInternal.h"
#import "GoogleUtilities/Network/Private/GULMutableDictionary.h"
#import "GoogleUtilities/Network/Private/GULNetworkConstants.h"
#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h"
/// Constant string for request header Content-Encoding.
static NSString *const kGULNetworkContentCompressionKey = @"Content-Encoding";

View file

@ -16,7 +16,7 @@
#import "GoogleUtilities/Network/Private/GULNetworkURLSession.h"
#import <GoogleUtilities/GULLogger.h>
#import "GoogleUtilities/Logger/Private/GULLogger.h"
#import "GoogleUtilities/Network/Private/GULMutableDictionary.h"
#import "GoogleUtilities/Network/Private/GULNetworkConstants.h"
#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h"

View file

@ -16,9 +16,9 @@
#import <Foundation/Foundation.h>
#import "GULNetworkConstants.h"
#import "GULNetworkLoggerProtocol.h"
#import "GULNetworkURLSession.h"
#import "GoogleUtilities/Network/Private/GULNetworkConstants.h"
#import "GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h"
#import "GoogleUtilities/Network/Private/GULNetworkURLSession.h"
/// Delegate protocol for GULNetwork events.
@protocol GULNetworkReachabilityDelegate

View file

@ -15,7 +15,7 @@
*/
#import <Foundation/Foundation.h>
#import <GoogleUtilities/GULLogger.h>
#import "GoogleUtilities/Logger/Private/GULLogger.h"
/// Error codes in Firebase Network error domain.
/// Note: these error codes should never change. It would make it harder to decode the errors if

View file

@ -16,9 +16,9 @@
#import <Foundation/Foundation.h>
#import <GoogleUtilities/GULLoggerLevel.h>
#import "GoogleUtilities/Logger/Private/GULLogger.h"
#import "GULNetworkMessageCode.h"
#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h"
/// The log levels used by GULNetworkLogger.
typedef NS_ENUM(NSInteger, GULNetworkLogLevel) {

View file

@ -16,7 +16,7 @@
#import <Foundation/Foundation.h>
#import "GULNetworkLoggerProtocol.h"
#import "GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h"
NS_ASSUME_NONNULL_BEGIN

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
#import <GoogleUtilities/GULReachabilityChecker.h>
#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h"
#if !TARGET_OS_WATCH
typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator,
const char *host);

View file

@ -18,8 +18,8 @@
#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h"
#import "GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h"
#import <GoogleUtilities/GULLogger.h>
#import <GoogleUtilities/GULReachabilityChecker.h>
#import "GoogleUtilities/Logger/Private/GULLogger.h"
#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h"
static GULLoggerService kGULLoggerReachability = @"[GULReachability]";
#if !TARGET_OS_WATCH

View file

@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#import "TargetConditionals.h"
#import <TargetConditionals.h>
#import <GoogleUtilities/GULAppDelegateSwizzler.h>
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
#import <GoogleUtilities/GULLogger.h>
#import <GoogleUtilities/GULMutableDictionary.h>
#import <GoogleUtilities/GULSceneDelegateSwizzler.h>
#import "GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h"
#import "GoogleUtilities/Common/GULLoggerCodes.h"
#import "GoogleUtilities/Environment/Private/GULAppEnvironmentUtil.h"
#import "GoogleUtilities/Logger/Private/GULLogger.h"
#import "GoogleUtilities/Network/Private/GULMutableDictionary.h"
#import "GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h"
#import "GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h"
#import <objc/runtime.h>

View file

@ -15,8 +15,8 @@
*/
#import <Foundation/Foundation.h>
#import <GoogleUtilities/GULMutableDictionary.h>
#import <GoogleUtilities/GULSceneDelegateSwizzler.h>
#import "GoogleUtilities/Network/Private/GULMutableDictionary.h"
#import "GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h"
NS_ASSUME_NONNULL_BEGIN

View file

@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#import "Private/GULUserDefaults.h"
#import "GoogleUtilities/UserDefaults/Private/GULUserDefaults.h"
#import <GoogleUtilities/GULLogger.h>
#import "GoogleUtilities/Logger/Private/GULLogger.h"
NS_ASSUME_NONNULL_BEGIN

View file

@ -1,18 +1,29 @@
# Firebase iOS Open Source Development
[![Actions Status][gh-auth-badge]][gh-actions]
[![Actions Status][gh-core-badge]][gh-actions]
[![Actions Status][gh-datatransport-badge]][gh-actions]
[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
[![Actions Status][gh-firebasepod-badge]][gh-actions]
[![Actions Status][gh-firestore-badge]][gh-actions]
[![Actions Status][gh-interop-badge]][gh-actions]
[![Actions Status][gh-messaging-badge]][gh-actions]
[![Actions Status][gh-storage-badge]][gh-actions]
[![Actions Status][gh-symbolcollision-badge]][gh-actions]
[![Actions Status][gh-zip-badge]][gh-actions]
[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase)
This repository contains all Firebase iOS SDK source except FirebaseAnalytics,
[![Actions Status][gh-abtesting-badge]][gh-actions]
[![Actions Status][gh-auth-badge]][gh-actions]
[![Actions Status][gh-core-badge]][gh-actions]
[![Actions Status][gh-crashlytics-badge]][gh-actions]
[![Actions Status][gh-database-badge]][gh-actions]
[![Actions Status][gh-datatransport-badge]][gh-actions]
[![Actions Status][gh-dynamiclinks-badge]][gh-actions]
[![Actions Status][gh-firebasepod-badge]][gh-actions]
[![Actions Status][gh-firestore-badge]][gh-actions]
[![Actions Status][gh-functions-badge]][gh-actions]
[![Actions Status][gh-inappmessaging-badge]][gh-actions]
[![Actions Status][gh-interop-badge]][gh-actions]
[![Actions Status][gh-messaging-badge]][gh-actions]
[![Actions Status][gh-remoteconfig-badge]][gh-actions]
[![Actions Status][gh-storage-badge]][gh-actions]
[![Actions Status][gh-symbolcollision-badge]][gh-actions]
[![Actions Status][gh-zip-badge]][gh-actions]
[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk)
# Firebase Apple Open Source Development
This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics,
FirebasePerformance, and FirebaseML.
The repository also includes GoogleUtilities source. The
@ -87,7 +98,7 @@ Instructions for installing binary frameworks via
To develop Firebase software in this repository, ensure that you have at least
the following software:
* Xcode 10.1 (or later)
* Xcode 10.3 (or later)
* CocoaPods 1.7.2 (or later)
* [CocoaPods generate](https://github.com/square/cocoapods-generate)
@ -118,6 +129,10 @@ Firestore has a self contained Xcode project. See
See [AddNewPod.md](AddNewPod.md).
### Managing Headers and Imports
See [HeadersImports.md](HeadersImports.md).
### Code Formatting
To ensure that the code is formatted consistently, run the script
@ -125,21 +140,13 @@ To ensure that the code is formatted consistently, run the script
before creating a PR.
Travis will verify that any code changes are done in a style compliant way. Install
`clang-format` and `swiftformat`.
These commands will get the right versions:
`clang-format` and `swiftformat`:
```
brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb
brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb
brew install clang-format
brew install swiftformat
```
Note: if you already have a newer version of these installed you may need to
`brew switch` to this version.
To update this section, find the versions of clang-format and swiftformat.rb to
match the versions in the CI failure logs
[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula).
### Running Unit Tests
Select a scheme and press Command-u to build a component and run its unit tests.
@ -162,12 +169,7 @@ files without real values, but can be replaced with real plist files. To get you
2. Create a new Firebase project, if you don't already have one
3. For each sample app you want to test, create a new Firebase app with the sample app's bundle
identifier (e.g. `com.google.Database-Example`)
4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file
(e.g. in [Example/Database/App/](Example/Database/App/));
Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require
special Apple capabilities, and you will have to change the sample app to use a unique bundle
identifier that you can control in your own Apple Developer account.
4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project.
## Specific Component Instructions
See the sections below for any special instructions for those components.
@ -180,8 +182,16 @@ building and running the FirebaseAuth pod along with various samples and tests.
### Firebase Database
To run the Database Integration tests, make your database authentication rules
[public](https://firebase.google.com/docs/database/security/quickstart).
The Firebase Database Integration tests can be run against a locally running Database Emulator
or against a production instance.
To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before
running the integration test.
To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to
`FirebaseDatabase/Tests/Resources/GoogleService-Info.plist`. Your Security Rule must be set to
[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are
running.
### Firebase Storage
@ -269,14 +279,20 @@ Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).
[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions
[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg
[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg
[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg
[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg
[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg
[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg
[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg
[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg
[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg
[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg
[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg
[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg
[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg
[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg
[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg
[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg
[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg

View file

@ -1,5 +1,4 @@
PODS:
- ActionSheetPicker-3.0 (2.3.0)
- AppsFlyerFramework (4.9.0)
- FBAudienceNetwork (5.6.0):
- FBSDKCoreKit/Basics (>= 5.6.0)
@ -38,8 +37,7 @@ PODS:
- FirebaseCoreDiagnosticsInterop (~> 1.2)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
- FirebaseCoreDiagnostics (1.3.0):
- FirebaseCoreDiagnosticsInterop (~> 1.2)
- FirebaseCoreDiagnostics (1.4.0):
- GoogleDataTransportCCTSupport (~> 3.1)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
@ -66,27 +64,27 @@ PODS:
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (~> 1.30905.0)
- GoogleDataTransport (6.2.1)
- GoogleDataTransportCCTSupport (3.1.0):
- GoogleDataTransportCCTSupport (3.2.0):
- GoogleDataTransport (~> 6.1)
- nanopb (~> 1.30905.0)
- GoogleUtilities/AppDelegateSwizzler (6.6.0):
- GoogleUtilities/AppDelegateSwizzler (6.7.1):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (6.6.0):
- GoogleUtilities/Environment (6.7.1):
- PromisesObjC (~> 1.2)
- GoogleUtilities/Logger (6.6.0):
- GoogleUtilities/Logger (6.7.1):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (6.6.0):
- GoogleUtilities/MethodSwizzler (6.7.1):
- GoogleUtilities/Logger
- GoogleUtilities/Network (6.6.0):
- GoogleUtilities/Network (6.7.1):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (6.6.0)"
- GoogleUtilities/Reachability (6.6.0):
- "GoogleUtilities/NSData+zlib (6.7.1)"
- GoogleUtilities/Reachability (6.7.1):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (6.6.0):
- GoogleUtilities/UserDefaults (6.7.1):
- GoogleUtilities/Logger
- MoPub-FacebookAudienceNetwork-Adapters (5.6.0.0):
- MoPub-FacebookAudienceNetwork-Adapters/MoPub (= 5.6.0.0)
@ -112,13 +110,12 @@ PODS:
- nanopb/encode (= 1.30905.0)
- nanopb/decode (1.30905.0)
- nanopb/encode (1.30905.0)
- PromisesObjC (1.2.8)
- PromisesObjC (1.2.9)
- Pushwoosh (5.16.0):
- Pushwoosh/Core (= 5.16.0)
- Pushwoosh/Core (5.16.0)
DEPENDENCIES:
- ActionSheetPicker-3.0 (= 2.3.0)
- AppsFlyerFramework (= 4.9.0)
- FBSDKCoreKit (= 5.15.1)
- FBSDKLoginKit (= 5.15.1)
@ -131,7 +128,6 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- ActionSheetPicker-3.0
- AppsFlyerFramework
- FBAudienceNetwork
- FBSDKCoreKit
@ -156,7 +152,6 @@ SPEC REPOS:
- Pushwoosh
SPEC CHECKSUMS:
ActionSheetPicker-3.0: eef157d75e151f255c5333d26656c7fbfe905a51
AppsFlyerFramework: f57e5d590ad3124d3e594a76032a181bc91ec6cd
FBAudienceNetwork: 1ea63543665445a3a5b4a059e8210a343b6ab3c1
FBSDKCoreKit: 1d5acf7c9d7a2f92bb1a242dc60cae5b7adb91df
@ -165,21 +160,21 @@ SPEC CHECKSUMS:
FirebaseAnalytics: 96634d356482d4f3af8fe459a0ebf19a99c71b75
FirebaseAnalyticsInterop: 3f86269c38ae41f47afeb43ebf32a001f58fcdae
FirebaseCore: f42e5e5f382cdcf6b617ed737bf6c871a6947b17
FirebaseCoreDiagnostics: 4a773a47bd83bbd5a9b1ccf1ce7caa8b2d535e67
FirebaseCoreDiagnostics: 4505e4d4009b1d93f605088ee7d7764d5f0d1c84
FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850
FirebaseCrashlytics: a87cce5746d3335995bd18b1b60d073cd05a6920
FirebaseInstallations: 6f5f680e65dc374397a483c32d1799ba822a395b
Flurry-iOS-SDK: be6bfad47f3b3c15a38b5e396935ef74512f1c38
GoogleAppMeasurement: 67458367830514fb20fd9e233496f1eef9d90185
GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020
GoogleDataTransportCCTSupport: d70a561f7d236af529fee598835caad5e25f6d3d
GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1
GoogleDataTransportCCTSupport: 489c1265d2c85b68187a83a911913d190012158d
GoogleUtilities: e121a3867449ce16b0e35ddf1797ea7a389ffdf2
MoPub-FacebookAudienceNetwork-Adapters: 3cec249235d12e3fec9a01bf559d608fa3ec05e1
mopub-ios-sdk: 3d65133b95b6498aa871a66818a11a5ba307e565
nanopb: c43f40fadfe79e8b8db116583945847910cbabc9
PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6
PromisesObjC: b48e0338dbbac2207e611750777895f7a5811b75
Pushwoosh: 6cba171e52f3f7b8ccd280f492a5831deac2f594
PODFILE CHECKSUM: 18f4e3a3de30ca73d4725a3e49f8c60205ad2306
PODFILE CHECKSUM: c3f8758a04bfcf497d7cf4a86726c990ae127e6a
COCOAPODS: 1.8.3
COCOAPODS: 1.9.3

File diff suppressed because it is too large Load diff

View file

@ -40,7 +40,6 @@ BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) {
@dynamic isPending;
@dynamic isFulfilled;
@dynamic isRejected;
@dynamic pendingObjects;
@dynamic value;
@dynamic error;

View file

@ -191,14 +191,16 @@ static dispatch_queue_t gFBLPromiseDefaultDispatchQueue;
}
}
- (NSMutableSet *__nullable)pendingObjects {
- (void)addPendingObject:(id)object {
NSParameterAssert(object);
@synchronized(self) {
if (_state == FBLPromiseStatePending) {
if (!_pendingObjects) {
_pendingObjects = [[NSMutableSet alloc] init];
}
[_pendingObjects addObject:object];
}
return _pendingObjects;
}
}

View file

@ -40,12 +40,6 @@ FOUNDATION_EXTERN BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) NS_
@property(nonatomic, readonly) BOOL isFulfilled NS_REFINED_FOR_SWIFT;
@property(nonatomic, readonly) BOOL isRejected NS_REFINED_FOR_SWIFT;
/**
Set of arbitrary objects to keep strongly while the promise is pending.
Becomes nil after the promise has been resolved.
*/
@property(nonatomic, readonly, nullable) NSMutableSet *pendingObjects NS_REFINED_FOR_SWIFT;
/**
Value the promise was fulfilled with.
Can be nil if the promise is still pending, was resolved with nil or after it has been rejected.

View file

@ -57,6 +57,17 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
@end
@interface FBLPromise<Value>()
/**
Adds an object to the set of pending objects to keep strongly while the promise is pending.
Used by the Swift wrappers to keep them alive until the underlying ObjC promise is resolved.
@param object An object to add.
*/
- (void)addPendingObject:(id)object NS_REFINED_FOR_SWIFT;
@end

View file

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.3.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View file

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_ActionSheetPicker_3_0 : NSObject
@end
@implementation PodsDummy_ActionSheetPicker_3_0
@end

View file

@ -1,12 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif

View file

@ -1,27 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#import "AbstractActionSheetPicker.h"
#import "ActionSheetCustomPicker.h"
#import "ActionSheetCustomPickerDelegate.h"
#import "ActionSheetDatePicker.h"
#import "ActionSheetDistancePicker.h"
#import "ActionSheetLocalePicker.h"
#import "ActionSheetMultipleStringPicker.h"
#import "ActionSheetPicker.h"
#import "ActionSheetStringPicker.h"
#import "DistancePickerView.h"
#import "SWActionSheet.h"
FOUNDATION_EXPORT double ActionSheetPicker_3_0VersionNumber;
FOUNDATION_EXPORT const unsigned char ActionSheetPicker_3_0VersionString[];

View file

@ -1,6 +0,0 @@
framework module ActionSheetPicker_3_0 {
umbrella header "ActionSheetPicker-3.0-umbrella.h"
export *
module * { export * }
}

View file

@ -0,0 +1,11 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AppsFlyerFramework
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AppsFlyerFramework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "AdSupport" -framework "CoreTelephony" -framework "Security" -framework "SystemConfiguration" -framework "iAd"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/AppsFlyerFramework
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,11 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AppsFlyerFramework
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AppsFlyerFramework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "AdSupport" -framework "CoreTelephony" -framework "Security" -framework "SystemConfiguration" -framework "iAd"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/AppsFlyerFramework
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,11 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBAudienceNetwork
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit" "${PODS_ROOT}/FBAudienceNetwork/Static"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"c++" -l"xml2" -framework "AVFoundation" -framework "AudioToolbox" -framework "CoreGraphics" -framework "CoreImage" -framework "CoreMedia" -framework "Foundation" -framework "Security" -framework "StoreKit" -framework "UIKit" -weak_framework "Accelerate" -weak_framework "Accounts" -weak_framework "AdSupport" -weak_framework "AudioToolbox" -weak_framework "CFNetwork" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "CoreMotion" -weak_framework "CoreTelephony" -weak_framework "Foundation" -weak_framework "LocalAuthentication" -weak_framework "QuartzCore" -weak_framework "SafariServices" -weak_framework "Security" -weak_framework "Social" -weak_framework "SystemConfiguration" -weak_framework "UIKit" -weak_framework "VideoToolbox" -weak_framework "WebKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBAudienceNetwork
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,11 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBAudienceNetwork
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit" "${PODS_ROOT}/FBAudienceNetwork/Static"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"c++" -l"xml2" -framework "AVFoundation" -framework "AudioToolbox" -framework "CoreGraphics" -framework "CoreImage" -framework "CoreMedia" -framework "Foundation" -framework "Security" -framework "StoreKit" -framework "UIKit" -weak_framework "Accelerate" -weak_framework "Accounts" -weak_framework "AdSupport" -weak_framework "AudioToolbox" -weak_framework "CFNetwork" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "CoreMotion" -weak_framework "CoreTelephony" -weak_framework "Foundation" -weak_framework "LocalAuthentication" -weak_framework "QuartzCore" -weak_framework "SafariServices" -weak_framework "Security" -weak_framework "Social" -weak_framework "SystemConfiguration" -weak_framework "UIKit" -weak_framework "VideoToolbox" -weak_framework "WebKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBAudienceNetwork
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,10 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) FBSDKCOCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"c++" -l"stdc++" -l"z" -weak_framework "Accelerate" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSDKCoreKit
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,10 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) FBSDKCOCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"c++" -l"stdc++" -l"z" -weak_framework "Accelerate" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSDKCoreKit
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,11 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSDKLoginKit
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -weak_framework "Accelerate" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSDKLoginKit
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,11 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSDKLoginKit
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -weak_framework "Accelerate" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSDKLoginKit
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,12 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCrashlytics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public"
OTHER_LDFLAGS = $(inherited) -framework "StoreKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,12 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCrashlytics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public"
OTHER_LDFLAGS = $(inherited) -framework "StoreKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,12 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public"
OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,12 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public"
OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,10 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalyticsInterop
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseAnalyticsInterop" "${PODS_ROOT}/Headers/Public"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalyticsInterop
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,10 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalyticsInterop
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseAnalyticsInterop" "${PODS_ROOT}/Headers/Public"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalyticsInterop
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,13 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb"
GCC_C_LANGUAGE_STANDARD = c99
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.7.2 Firebase_VERSION=6.26.0
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}"
OTHER_CFLAGS = $(inherited) -fno-autolink
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,13 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb"
GCC_C_LANGUAGE_STANDARD = c99
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.7.2 Firebase_VERSION=6.26.0
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}"
OTHER_CFLAGS = $(inherited) -fno-autolink
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.3.0</string>
<string>1.4.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View file

@ -11,6 +11,8 @@
#endif
#import "firebasecore.nanopb.h"
#import "FIRCoreDiagnosticsData.h"
#import "FIRCoreDiagnosticsInterop.h"
FOUNDATION_EXPORT double FirebaseCoreDiagnosticsVersionNumber;
FOUNDATION_EXPORT const unsigned char FirebaseCoreDiagnosticsVersionString[];

View file

@ -0,0 +1,14 @@
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb"
GCC_C_LANGUAGE_STANDARD = c99
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
GCC_TREAT_WARNINGS_AS_ERRORS = YES
HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" "${PODS_TARGET_SRCROOT}/Firebase/CoreDiagnostics/"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnostics
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,14 @@
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb"
GCC_C_LANGUAGE_STANDARD = c99
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
GCC_TREAT_WARNINGS_AS_ERRORS = YES
HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" "${PODS_TARGET_SRCROOT}/Firebase/CoreDiagnostics/"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnostics
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,10 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnosticsInterop
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseCoreDiagnosticsInterop" "${PODS_ROOT}/Headers/Public"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnosticsInterop
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,10 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnosticsInterop
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseCoreDiagnosticsInterop" "${PODS_ROOT}/Headers/Public"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnosticsInterop
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View file

@ -0,0 +1,13 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCrashlytics
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb"
GCC_C_LANGUAGE_STANDARD = c99
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 DISPLAY_VERSION=4.1.1 CLS_SDK_NAME="Crashlytics iOS SDK" PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public"
OTHER_LD_FLAGS = $(inherited) -sectcreate __TEXT __info_plist
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCrashlytics
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

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