├── .idea
├── .name
├── vcs.xml
├── modules.xml
├── JCAlert.iml
├── misc.xml
└── workspace.xml
├── JCAlertController
├── Assets.xcassets
│ ├── Contents.json
│ ├── alert.imageset
│ │ ├── alert@2x.png
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── RootVC.h
├── ViewController.h
├── JCAlertController
│ ├── ButtonItem
│ │ ├── JCAlertButtonItem.m
│ │ └── JCAlertButtonItem.h
│ ├── Category
│ │ ├── UIWindow+JCBlur.h
│ │ ├── UIColor+JCHightlightedColor.h
│ │ ├── UIImage+JCColor2Image.h
│ │ ├── NSAttributedString+JCCalculateSize.h
│ │ ├── UIImage+JCColor2Image.m
│ │ ├── UIColor+JCHightlightedColor.m
│ │ ├── NSAttributedString+JCCalculateSize.m
│ │ └── UIWindow+JCBlur.m
│ ├── AlertView
│ │ ├── JCAlertView.h
│ │ └── JCAlertView.m
│ ├── JCPresentQueue
│ │ ├── UIViewController+JCPresentQueue.h
│ │ ├── JCPresentController.h
│ │ ├── JCPresentController.m
│ │ └── UIViewController+JCPresentQueue.m
│ ├── JCAlertController.h
│ ├── Style
│ │ ├── JCAlertStyle.h
│ │ └── JCAlertStyle.m
│ └── JCAlertController.m
├── NormalVCForPresentation.h
├── AppDelegate.h
├── main.m
├── NSObject+BlockSEL.h
├── NormalVCForPresentation.m
├── NSObject+BlockSEL.m
├── Info.plist
├── Base.lproj
│ └── LaunchScreen.storyboard
├── RootVC.m
├── AppDelegate.m
└── ViewController.m
├── JCAlertController.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── JCAlertController.podspec
├── JCAlertControllerTests
├── Info.plist
└── JCAlertControllerTests.m
├── JCAlertControllerUITests
├── Info.plist
└── JCAlertControllerUITests.m
├── LICENSE
├── .gitignore
├── README_CN.md
└── README.md
/.idea/.name:
--------------------------------------------------------------------------------
1 | JCAlert
--------------------------------------------------------------------------------
/JCAlertController/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/JCAlertController/Assets.xcassets/alert.imageset/alert@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RichDaddyCashMany/JCAlertController/HEAD/JCAlertController/Assets.xcassets/alert.imageset/alert@2x.png
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/JCAlertController.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/JCAlertController/RootVC.h:
--------------------------------------------------------------------------------
1 | //
2 | // TestVC.h
3 | // JCAlertController
4 | //
5 | // Created by weiping.lii on 29/03/2018.
6 | // Copyright © 2018 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface RootVC : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/JCAlert.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/JCAlertController/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/8.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UITableViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/ButtonItem/JCAlertButtonItem.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertButtonItem.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "JCAlertButtonItem.h"
10 |
11 | @implementation JCAlertButtonItem
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/JCAlertController/NormalVCForPresentation.h:
--------------------------------------------------------------------------------
1 | //
2 | // NormalVCForPresentation.h
3 | // JCAlertController
4 | //
5 | // Created by weiping.lii on 30/03/2018.
6 | // Copyright © 2018 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NormalVCForPresentation : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/JCAlertController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Category/UIWindow+JCBlur.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIWindow+blur.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIWindow (blur)
12 |
13 | - (UIImageView *)blurScreenshot;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/JCAlertController/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/8.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
17 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Category/UIColor+JCHightlightedColor.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+JCHightlightedColor.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/6.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIColor (JCHightlightedColor)
12 |
13 | - (UIColor *)hightlightedColor;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Category/UIImage+JCColor2Image.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+JCColor2Image.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (JCColor2Image)
12 |
13 | +(UIImage *)createImageWithColor:(UIColor *)color;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/JCAlertController/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/8.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Category/NSAttributedString+JCCalculateSize.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSAttributedString+JCCalculateSize.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSAttributedString (JCCalculateSize)
12 |
13 | - (CGSize)sizeWithMaxWidth:(CGFloat)maxWidth;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/JCAlertController/Assets.xcassets/alert.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "alert@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/ButtonItem/JCAlertButtonItem.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertButtonItem.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "JCAlertStyle.h"
11 |
12 | @interface JCAlertButtonItem : NSObject
13 |
14 | @property (nonatomic, copy) NSString *title;
15 | @property (nonatomic, copy) void (^clicked)(void);
16 | @property (nonatomic) JCButtonType type;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/JCAlertController/NSObject+BlockSEL.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+BlockSEL.h
3 | //
4 | //
5 | // Created by HJaycee on 2017/4/28.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | @param weakSelf 方便使用,用来打破循环引用。使用时需要改成实际类型,否则没有代码提示.
13 | @param arg 事件默认传递的对象,比如`NSNotification`,`UIButton`。
14 | */
15 | typedef void (^callback)(id weakSelf, id arg);
16 |
17 | @interface NSObject (BlockSEL)
18 |
19 | /**
20 | 用block来代替selector
21 | */
22 | - (SEL)selectorBlock:(callback)block;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/JCAlertController.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "JCAlertController"
3 | s.version = "3.0.4"
4 | s.summary = "A replacement of UIAlertController"
5 | s.homepage = "https://github.com/HJaycee/JCAlertController"
6 | s.license = "MIT"
7 | s.author = { "HJaycee" => "huangxisu@gmail.com" }
8 | s.platform = :ios, "7.0"
9 | s.source = { :git => "https://github.com/HJaycee/JCAlertController.git", :tag => s.version }
10 | s.source_files = "JCAlertController/JCAlertController/**/*.{h,m}"
11 | s.frameworks = 'Accelerate'
12 | s.requires_arc = true
13 | end
14 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/JCAlertControllerTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/JCAlertControllerUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/AlertView/JCAlertView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertController.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/1.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "JCAlertStyle.h"
11 |
12 | @protocol JCAlertViewDelegate
13 |
14 | - (void)alertButtonClicked:(void(^)(void))clicked;
15 |
16 | @end
17 |
18 | @interface JCAlertView : UIView
19 |
20 | @property (nonatomic, copy) NSString *title;
21 | @property (nonatomic, copy) NSString *message;
22 | @property (nonatomic, strong) UIView *contentView;
23 | @property (nonatomic, strong) NSArray *buttonItems;
24 | @property (nonatomic, strong) JCAlertStyle *style;
25 |
26 | @property (nonatomic, weak) id delegate;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Category/UIImage+JCColor2Image.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+JCColor2Image.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "UIImage+JCColor2Image.h"
10 |
11 | @implementation UIImage (JCJCColor2Image)
12 |
13 | + (UIImage *)createImageWithColor:(UIColor *)color {
14 | CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
15 | UIGraphicsBeginImageContext(rect.size);
16 | CGContextRef context = UIGraphicsGetCurrentContext();
17 | CGContextSetFillColorWithColor(context, [color CGColor]);
18 | CGContextFillRect(context, rect);
19 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
20 | UIGraphicsEndImageContext();
21 | return theImage;
22 | }
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/JCAlertController/NormalVCForPresentation.m:
--------------------------------------------------------------------------------
1 | //
2 | // NormalVCForPresentation.m
3 | // JCAlertController
4 | //
5 | // Created by weiping.lii on 30/03/2018.
6 | // Copyright © 2018 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "NormalVCForPresentation.h"
10 |
11 | @interface NormalVCForPresentation ()
12 |
13 | @end
14 |
15 | @implementation NormalVCForPresentation
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 |
20 | UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"Dismiss" style:UIBarButtonItemStyleDone target:self action:@selector(onDismiss)];
21 | self.navigationItem.leftBarButtonItem = item;
22 | self.view.backgroundColor = [UIColor whiteColor];
23 | }
24 |
25 | - (void)onDismiss {
26 | [self dismissViewControllerAnimated:YES completion:nil];
27 | }
28 |
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Category/UIColor+JCHightlightedColor.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+JCHightlightedColor.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/6.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "UIColor+JCHightlightedColor.h"
10 |
11 | #define deepValue 10
12 |
13 | @implementation UIColor (JCHightlightedColor)
14 |
15 | - (UIColor *)hightlightedColor {
16 | const CGFloat *components = CGColorGetComponents(self.CGColor);
17 |
18 | CGFloat r = components[0];
19 | CGFloat g = components[1];
20 | CGFloat b = components[2];
21 |
22 | r = r * 255 - deepValue >= 0 ? r * 255 - deepValue : 0;
23 | g = g * 255 - deepValue >= 0 ? g * 255 - deepValue : 0;
24 | b = b * 255 - deepValue >= 0 ? b * 255 - deepValue : 0;
25 |
26 | return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:components[3]];
27 | }
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Category/NSAttributedString+JCCalculateSize.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSAttributedString+JCCalculateSize.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "NSAttributedString+JCCalculateSize.h"
10 |
11 | @implementation NSAttributedString (JCCalculateSize)
12 |
13 | - (CGSize)sizeWithMaxWidth:(CGFloat)maxWidth {
14 | if ([self length] > 0) {
15 | CGRect textRect = [self
16 | boundingRectWithSize:CGSizeMake(maxWidth, MAXFLOAT)
17 | options:(NSStringDrawingUsesLineFragmentOrigin |
18 | NSStringDrawingUsesFontLeading)
19 | context:nil];
20 | return CGSizeMake(ceilf(textRect.size.width), ceilf(textRect.size.height));
21 | } else {
22 | return CGSizeZero;
23 | }}
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/JCAlertController/NSObject+BlockSEL.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+BlockSEL.m
3 | //
4 | //
5 | // Created by HJaycee on 2017/4/28.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "NSObject+BlockSEL.h"
10 | #import
11 |
12 | @implementation NSObject (BlockSEL)
13 |
14 | - (SEL)selectorBlock:(void (^)(id, id))block {
15 | if (!block) {
16 | [NSException raise:@"block can not be nil" format:@"%@ selectorBlock error", self];
17 | }
18 | NSString *selName = [NSString stringWithFormat:@"selector_%p:", block];
19 | SEL sel = NSSelectorFromString(selName);
20 | class_addMethod([self class], sel, (IMP)selectorImp, "v@:@");
21 | objc_setAssociatedObject(self, sel, block, OBJC_ASSOCIATION_COPY_NONATOMIC);
22 | return sel;
23 | }
24 |
25 | static void selectorImp(id self, SEL _cmd, id arg) {
26 | callback block = objc_getAssociatedObject(self, _cmd);
27 | __weak typeof(self) weakSelf = self;
28 | if (block) {
29 | block(weakSelf, arg);
30 | }
31 | }
32 |
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/JCAlertController/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "size" : "1024x1024",
46 | "scale" : "1x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/JCAlertControllerTests/JCAlertControllerTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertControllerTests.m
3 | // JCAlertControllerTests
4 | //
5 | // Created by HJaycee on 2017/4/8.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface JCAlertControllerTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation JCAlertControllerTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013-2015 MJRefresh (https://github.com/HJaycee/JCAlertController)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/JCPresentQueue/UIViewController+JCPresentQueue.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController+JCPresentQueue.h
3 | // JCPresentController
4 | //
5 | // Created by HJaycee on 2017/4/4.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | extern NSString * const JCPresentControllersAllDismissedNotification;
12 |
13 | typedef NS_OPTIONS (NSUInteger, JCPresentType) {
14 | JCPresentTypeLIFO = 0, // last in, first out
15 | JCPresentTypeFIFO // first in, last out
16 | };
17 |
18 | @interface UIViewController (JCPresentQueue)
19 |
20 | /**
21 | Present any controller with LIFO or FIFO.
22 | Choose one to use, dont't use LIFO and FIFO two together.
23 |
24 | @param controller any controller inherits in UIViewController
25 | @param presentType JCPresentTypeLIFO or JCPresentTypeFIFO
26 | @param presentCompletion callback if presented
27 | @param dismissCompletion callback if dismissed
28 | */
29 | - (void)jc_presentViewController:(UIViewController *)controller presentType:(JCPresentType)presentType presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion;
30 |
31 | @end
32 |
33 |
--------------------------------------------------------------------------------
/JCAlertController/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/JCPresentQueue/JCPresentController.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCPresentController.h
3 | // JCPresentController
4 | //
5 | // Created by HJaycee on 2018/5/3.
6 | // Copyright © 2018年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface JCPresentController : NSObject
12 |
13 | /**
14 | overlayWindow's default windowLevel is UIWindowLevelNormal, you can modify it
15 |
16 | @param windowLevel windowLevel
17 | */
18 | + (void)setOverlayWindowLevel:(UIWindowLevel)windowLevel;
19 |
20 | /**
21 | viewControllers will be presented like LIFO
22 |
23 | @param viewController viewControllerToPresent
24 | @param presentCompletion be performed after present
25 | @param dismissCompletion be performed after dismiss
26 | */
27 | + (void)presentViewControllerLIFO:(UIViewController *)viewController presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion;
28 |
29 | /**
30 | viewControllers will be presented like FIFO
31 |
32 | @param viewController viewControllerToPresent
33 | @param presentCompletion be performed after present
34 | @param dismissCompletion be performed after dismiss
35 | */
36 | + (void)presentViewControllerFIFO:(UIViewController *)viewController presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion;
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/JCAlertControllerUITests/JCAlertControllerUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertControllerUITests.m
3 | // JCAlertControllerUITests
4 | //
5 | // Created by HJaycee on 2017/4/8.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface JCAlertControllerUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation JCAlertControllerUITests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 |
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 |
22 | // In UI tests it is usually best to stop immediately when a failure occurs.
23 | self.continueAfterFailure = NO;
24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
25 | [[[XCUIApplication alloc] init] launch];
26 |
27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | [super tearDown];
33 | }
34 |
35 | - (void)testExample {
36 | // Use recording to get started writing UI tests.
37 | // Use XCTAssert and related functions to verify your tests produce the correct results.
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | # CocoaPods
32 | #
33 | # We recommend against adding the Pods directory to your .gitignore. However
34 | # you should judge for yourself, the pros and cons are mentioned at:
35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
36 | #
37 | # Pods/
38 |
39 | # Carthage
40 | #
41 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
42 | # Carthage/Checkouts
43 |
44 | Carthage/Build
45 |
46 | # fastlane
47 | #
48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
49 | # screenshots whenever they are needed.
50 | # For more information about the recommended setup visit:
51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
52 |
53 | fastlane/report.xml
54 | fastlane/Preview.html
55 | fastlane/screenshots
56 | fastlane/test_output
57 |
58 | # Code Injection
59 | #
60 | # After new code Injection tools there's a generated folder /iOSInjectionProject
61 | # https://github.com/johnno1962/injectionforxcode
62 |
63 | iOSInjectionProject/
64 |
--------------------------------------------------------------------------------
/JCAlertController/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/JCAlertController/RootVC.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestVC.m
3 | // JCAlertController
4 | //
5 | // Created by weiping.lii on 29/03/2018.
6 | // Copyright © 2018 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "RootVC.h"
10 | #import "ViewController.h"
11 |
12 | @interface RootVC ()
13 |
14 | @property (strong, nonatomic) UIButton *pushButton;
15 | @property (strong, nonatomic) UIButton *presentButton;
16 |
17 | @end
18 |
19 | @implementation RootVC
20 |
21 | - (void)viewDidLoad {
22 | [super viewDidLoad];
23 | self.view.backgroundColor = [UIColor whiteColor];
24 |
25 | [self.view addSubview:self.pushButton];
26 | [self.view addSubview:self.presentButton];
27 |
28 | self.pushButton.frame = CGRectMake(50, 200, 100, 50);
29 | self.presentButton.frame = CGRectMake(50, 300, 100, 50);
30 | }
31 |
32 | - (void)onPushButtonClicked:(UIButton *)button {
33 | ViewController *vc = [ViewController new];
34 | [self.navigationController pushViewController:vc animated:YES];
35 | }
36 |
37 | - (void)onPresentButtonClicked:(UIButton *)button {
38 | ViewController *vc = [ViewController new];
39 | [self presentViewController:vc animated:YES completion:nil];
40 | }
41 |
42 | - (UIButton *)pushButton {
43 | if (!_pushButton) {
44 | _pushButton = [UIButton buttonWithType:UIButtonTypeCustom];
45 | [_pushButton setTitle:@"Push" forState:UIControlStateNormal];
46 | _pushButton.backgroundColor = [UIColor blackColor];
47 | [_pushButton addTarget:self action:@selector(onPushButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
48 | }
49 | return _pushButton;
50 | }
51 |
52 | - (UIButton *)presentButton {
53 | if (!_presentButton) {
54 | _presentButton = [UIButton buttonWithType:UIButtonTypeCustom];
55 | [_presentButton setTitle:@"Present" forState:UIControlStateNormal];
56 | _presentButton.backgroundColor = [UIColor blackColor];
57 | [_presentButton addTarget:self action:@selector(onPresentButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
58 | }
59 | return _presentButton;
60 | }
61 |
62 |
63 | @end
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/JCAlertController/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/6.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "ViewController.h"
11 | #import "RootVC.h"
12 | #import "UIViewController+JCPresentQueue.h"
13 |
14 | @interface AppDelegate ()
15 |
16 | @end
17 |
18 | @implementation AppDelegate
19 |
20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
21 | // Override point for customization after application launch.
22 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
23 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[RootVC new]];
24 | self.window.rootViewController = nav;
25 | [self.window makeKeyAndVisible];
26 | return YES;
27 | }
28 |
29 | - (void)applicationWillResignActive:(UIApplication *)application {
30 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
31 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
32 | }
33 |
34 |
35 | - (void)applicationDidEnterBackground:(UIApplication *)application {
36 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
38 | }
39 |
40 |
41 | - (void)applicationWillEnterForeground:(UIApplication *)application {
42 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
43 | }
44 |
45 |
46 | - (void)applicationDidBecomeActive:(UIApplication *)application {
47 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
48 | }
49 |
50 |
51 | - (void)applicationWillTerminate:(UIApplication *)application {
52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
53 | }
54 |
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/JCAlertController.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertController.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/3/31.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "JCPresentController.h"
11 | #import "JCAlertStyle.h"
12 |
13 | /**
14 | Same level with UIAlertController.
15 | Use method 'jc_presentViewController...' in 'UIViewController+JCPresentQueue.h',It accouts with FIFO or LIFO.
16 | Use +[JCAlertStyle styleWithType:JCAlertType] to change the style of alertView.
17 | */
18 | @interface JCAlertController : UIViewController
19 |
20 | /**
21 | Class method to create 'JCAlertController' instance
22 | The alertView is composed of title, message and buttons
23 | */
24 | + (instancetype)alertWithTitle:(NSString *)title message:(NSString *)message;
25 |
26 | /**
27 | The alertView is composed of title, contentView and buttons
28 | */
29 | + (instancetype)alertWithTitle:(NSString *)title contentView:(UIView *)contentView;
30 |
31 | /**
32 | Add a button on alertView with title and action
33 | */
34 | - (void)addButtonWithTitle:(NSString *)title type:(JCButtonType)type clicked:(void (^)(void))clicked;
35 |
36 | @end
37 |
38 | @interface JCAlertController (keyboardHandle)
39 |
40 | /**
41 | Monitor keyboard showed state
42 |
43 | @param showed callback after keyboard showed
44 | */
45 | - (void)monitorKeyboardShowed:(void(^)(CGFloat alertHeight, CGFloat keyboardHeight))showed;
46 |
47 | /**
48 | Monitor keyboard hided state
49 |
50 | @param hided callback after keyboard hided
51 | */
52 | - (void)monitorKeyboardHided:(void(^)(void))hided;
53 |
54 | /**
55 | Move alertView to new centerY to avoid the keyboard
56 |
57 | @param centerY centerY
58 | @param animated is animated
59 | */
60 | - (void)moveAlertViewToCenterY:(CGFloat)centerY animated:(BOOL)animated;
61 |
62 | /**
63 | Move alertView to center of screen
64 |
65 | @param animated is animated
66 | */
67 | - (void)moveAlertViewToScreenCenterAnimated:(BOOL)animated;
68 |
69 | @end
70 |
71 | @interface JCAlertController (Deprecated)
72 |
73 | /**
74 | It's too waste time to pass parameter `type` each time.
75 | */
76 | + (instancetype)alertWithTitle:(NSString *)title message:(NSString *)message type:(JCAlertType)type NS_DEPRECATED_IOS(2.0, 6.0, "Use + (instancetype)alertWithTitle:(NSString *)title message:(NSString *)message; please!");
77 | + (instancetype)alertWithTitle:(NSString *)title contentView:(UIView *)contentView type:(JCAlertType)type NS_DEPRECATED_IOS(2.0, 6.0, "Use + (instancetype)alertWithTitle:(NSString *)title contentView:(UIView *)contentView; please!");
78 | - (instancetype)initWithTitle:(NSString *)title message:(NSString *)message type:(JCAlertType)type NS_DEPRECATED_IOS(2.0, 6.0, "Use + (instancetype)alertWithTitle:(NSString *)title message:(NSString *)message; please!");
79 | - (instancetype)initWithTitle:(NSString *)title contentView:(UIView *)contentView type:(JCAlertType)type NS_DEPRECATED_IOS(2.0, 6.0, "Use + (instancetype)alertWithTitle:(NSString *)title contentView:(UIView *)contentView; please!");
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/JCPresentQueue/JCPresentController.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCPresentController.m
3 | // JCPresentController
4 | //
5 | // Created by HJaycee on 2018/5/3.
6 | // Copyright © 2018年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "JCPresentController.h"
10 | #import "UIViewController+JCPresentQueue.h"
11 |
12 | @interface JCPresentWindow : UIWindow
13 | @end
14 |
15 | @implementation JCPresentWindow
16 | @end
17 |
18 | @interface JCPresentRootController : UIViewController
19 | @end
20 |
21 | @implementation JCPresentRootController
22 | @end
23 |
24 | @interface JCPresentQueueManager : NSObject
25 |
26 | @property (nonatomic) UIWindow *overlayWindow;
27 | @property (nonatomic) UIWindowLevel overLayWindowLevel;
28 | + (instancetype)shareManager;
29 |
30 | @end
31 |
32 | @implementation JCPresentQueueManager
33 |
34 | + (instancetype)shareManager {
35 | static JCPresentQueueManager *manager;
36 | static dispatch_once_t onceToken;
37 | dispatch_once(&onceToken, ^{
38 | manager = [JCPresentQueueManager new];
39 | });
40 | return manager;
41 | }
42 |
43 | - (UIWindow *)overlayWindow {
44 | if (!_overlayWindow) {
45 | JCPresentRootController *rootViewController = [JCPresentRootController new];
46 | rootViewController.view.backgroundColor = [UIColor clearColor];
47 | _overlayWindow = [[JCPresentWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
48 | _overlayWindow.backgroundColor = [UIColor clearColor];
49 | _overlayWindow.windowLevel = self.overLayWindowLevel;
50 | _overlayWindow.rootViewController = rootViewController;
51 | _overlayWindow.hidden = NO;
52 | [_overlayWindow makeKeyAndVisible];
53 | }
54 | return _overlayWindow;
55 | }
56 |
57 | @end
58 |
59 | @implementation JCPresentController
60 |
61 | + (void)load {
62 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAllControllersDismissed) name:JCPresentControllersAllDismissedNotification object:nil];
63 | }
64 |
65 | + (void)setOverlayWindowLevel:(UIWindowLevel)windowLevel {
66 | [JCPresentQueueManager shareManager].overLayWindowLevel = windowLevel;
67 | }
68 |
69 | + (void)presentViewControllerLIFO:(UIViewController *)viewController presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion {
70 | [self presentViewController:viewController presentType:JCPresentTypeLIFO presentCompletion:presentCompletion dismissCompletion:dismissCompletion];
71 | }
72 |
73 | + (void)presentViewControllerFIFO:(UIViewController *)viewController presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion {
74 | [self presentViewController:viewController presentType:JCPresentTypeFIFO presentCompletion:presentCompletion dismissCompletion:dismissCompletion];
75 | }
76 |
77 | + (void)presentViewController:(UIViewController *)viewController presentType:(JCPresentType)presentType presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion {
78 | [[JCPresentQueueManager shareManager].overlayWindow.rootViewController jc_presentViewController:viewController presentType:presentType presentCompletion:^{
79 | if (presentCompletion) {
80 | presentCompletion();
81 | }
82 | } dismissCompletion:^{
83 | if (dismissCompletion) {
84 | dismissCompletion();
85 | }
86 | }];
87 | }
88 |
89 | + (void)onAllControllersDismissed {
90 | [JCPresentQueueManager shareManager].overlayWindow.hidden = YES;
91 | [JCPresentQueueManager shareManager].overlayWindow = nil;
92 | }
93 |
94 | @end
95 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Style/JCAlertStyle.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertStyle.h
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "UIColor+JCHightlightedColor.h"
11 |
12 | typedef NS_OPTIONS (NSUInteger, JCButtonType){
13 | JCButtonTypeNormal = 0,
14 | JCButtonTypeCancel,
15 | JCButtonTypeWarning
16 | };
17 |
18 | @interface JCAlertStyleAlertView : NSObject
19 | @property (nonatomic) CGFloat width;
20 | @property (nonatomic) CGFloat maxHeight;
21 | @property (nonatomic, strong) UIColor *backgroundColor;
22 | @property (nonatomic) CGFloat cornerRadius;
23 | @end
24 |
25 | @interface JCAlertStyleBackground : NSObject
26 | @property (nonatomic) BOOL blur;
27 | @property (nonatomic) BOOL canDismiss; // dismissed with touched the bg
28 | @property (nonatomic) float alpha;
29 | @end
30 |
31 | @interface JCAlertStyleTitle : NSObject
32 | @property (nonatomic) UIEdgeInsets insets;
33 | @property (nonatomic) UIEdgeInsets onlyTitleInsets;
34 | @property (nonatomic) CGFloat minHeight;
35 | @property (nonatomic, strong) UIFont *font;
36 | @property (nonatomic, strong) UIColor *textColor;
37 | @property (nonatomic, strong) UIColor *backgroundColor;
38 | @property (assign, nonatomic) NSTextAlignment textAlignment;
39 | @end
40 |
41 | @interface JCAlertStyleButton : NSObject
42 | @property (nonatomic) CGFloat height;
43 | @property (nonatomic, strong) UIFont *font;
44 | @property (nonatomic, strong) UIColor *textColor;
45 | @property (nonatomic, strong) UIColor *backgroundColor;
46 | @property (nonatomic, strong) UIColor *highlightTextColor;
47 | @property (nonatomic, strong) UIColor *highlightBackgroundColor;
48 | @end
49 |
50 | @interface JCAlertStyleButtonNormal : JCAlertStyleButton
51 | @end
52 |
53 | @interface JCAlertStyleButtonCancel : JCAlertStyleButton
54 | @end
55 |
56 | @interface JCAlertStyleButtonWarning : JCAlertStyleButton
57 | @end
58 |
59 | @interface JCAlertStyleContent : NSObject
60 | @property (nonatomic) UIEdgeInsets insets;
61 | @property (nonatomic) UIEdgeInsets onlyMessageInsets;
62 | @property (nonatomic) CGFloat minHeight;
63 | @property (nonatomic, strong) UIFont *font;
64 | @property (nonatomic, strong) UIColor *textColor;
65 | @property (nonatomic, strong) UIColor *backgroundColor;
66 | @property (assign, nonatomic) NSTextAlignment textAlignment;
67 | @end
68 |
69 | @interface JCAlertStyleSeparator : NSObject
70 | @property (nonatomic) CGFloat width;
71 | @property (nonatomic, strong) UIColor *color;
72 | @end
73 |
74 | @interface JCAlertStyle : NSObject
75 |
76 | @property (nonatomic, strong) JCAlertStyleAlertView *alertView;
77 | @property (nonatomic, strong) JCAlertStyleBackground *background;
78 | @property (nonatomic, strong) JCAlertStyleTitle *title;
79 | @property (nonatomic, strong) JCAlertStyleContent *content;
80 | @property (nonatomic, strong) JCAlertStyleButtonNormal *buttonNormal;
81 | @property (nonatomic, strong) JCAlertStyleButtonCancel *buttonCancel;
82 | @property (nonatomic, strong) JCAlertStyleButtonWarning *buttonWarning;
83 | @property (nonatomic, strong) JCAlertStyleSeparator *separator;
84 |
85 | + (instancetype)shareStyle;
86 |
87 | @end
88 |
89 | @interface JCAlertStyle (Deprecated)
90 |
91 | typedef NS_OPTIONS (NSUInteger, JCAlertType){
92 | JCAlertTypeNormal NS_ENUM_DEPRECATED_IOS(2.0, 6.0, "No longer support") = 0,
93 | JCAlertTypeTitleOnly NS_ENUM_DEPRECATED_IOS(2.0, 6.0, "No longer support"),
94 | JCAlertTypeContentOnly NS_ENUM_DEPRECATED_IOS(2.0, 6.0, "No longer support"),
95 | JCAlertTypeCustom NS_ENUM_DEPRECATED_IOS(2.0, 6.0, "No longer support")
96 | };
97 |
98 | + (JCAlertStyle *)styleWithType:(JCAlertType)type NS_DEPRECATED_IOS(2.0, 6.0, "Use + (instancetype)alertWithTitle:(NSString *)title message:(NSString *)message; please!");
99 |
100 | @end
101 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Category/UIWindow+JCBlur.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIWindow+blur.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "UIWindow+JCBlur.h"
10 | #import
11 |
12 | @implementation UIWindow (JCBlur)
13 |
14 | - (UIImageView *)blurScreenshot {
15 | UIGraphicsBeginImageContext(self.frame.size);
16 | [self.layer renderInContext:UIGraphicsGetCurrentContext()];
17 | UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
18 | UIGraphicsEndImageContext();
19 |
20 | UIImage *originalImage = viewImage;
21 |
22 | CGFloat blurRadius = 4;
23 | UIColor *tintColor = [UIColor clearColor];
24 | CGFloat saturationDeltaFactor = 1;
25 | UIImage *maskImage = nil;
26 |
27 | CGRect imageRect = { CGPointZero, originalImage.size };
28 | UIImage *effectImage = originalImage;
29 |
30 | BOOL hasBlur = blurRadius > __FLT_EPSILON__;
31 | BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
32 | if (hasBlur || hasSaturationChange) {
33 | UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, [[UIScreen mainScreen] scale]);
34 | CGContextRef effectInContext = UIGraphicsGetCurrentContext();
35 | CGContextScaleCTM(effectInContext, 1.0, -1.0);
36 | CGContextTranslateCTM(effectInContext, 0, -originalImage.size.height);
37 | CGContextDrawImage(effectInContext, imageRect, originalImage.CGImage);
38 |
39 | vImage_Buffer effectInBuffer;
40 | effectInBuffer.data = CGBitmapContextGetData(effectInContext);
41 | effectInBuffer.width = CGBitmapContextGetWidth(effectInContext);
42 | effectInBuffer.height = CGBitmapContextGetHeight(effectInContext);
43 | effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);
44 |
45 | UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, [[UIScreen mainScreen] scale]);
46 | CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
47 | vImage_Buffer effectOutBuffer;
48 | effectOutBuffer.data = CGBitmapContextGetData(effectOutContext);
49 | effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext);
50 | effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext);
51 | effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);
52 |
53 | if (hasBlur) {
54 | CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
55 | uint32_t radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
56 | if (radius % 2 != 1) {
57 | radius += 1;
58 | }
59 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
60 | vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
61 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
62 | }
63 | BOOL effectImageBuffersAreSwapped = NO;
64 | if (hasSaturationChange) {
65 | CGFloat s = saturationDeltaFactor;
66 | CGFloat floatingPointSaturationMatrix[] = {
67 | 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0,
68 | 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0,
69 | 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0,
70 | 0, 0, 0, 1,
71 | };
72 | const int32_t divisor = 256;
73 | NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
74 | int16_t saturationMatrix[matrixSize];
75 | for (NSUInteger i = 0; i < matrixSize; ++i) {
76 | saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
77 | }
78 | if (hasBlur) {
79 | vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
80 | effectImageBuffersAreSwapped = YES;
81 | }
82 | else {
83 | vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
84 | }
85 | }
86 | if (!effectImageBuffersAreSwapped)
87 | effectImage = UIGraphicsGetImageFromCurrentImageContext();
88 | UIGraphicsEndImageContext();
89 |
90 | if (effectImageBuffersAreSwapped)
91 | effectImage = UIGraphicsGetImageFromCurrentImageContext();
92 | UIGraphicsEndImageContext();
93 | }
94 |
95 | UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, [[UIScreen mainScreen] scale]);
96 | CGContextRef outputContext = UIGraphicsGetCurrentContext();
97 | CGContextScaleCTM(outputContext, 1.0, -1.0);
98 | CGContextTranslateCTM(outputContext, 0, -originalImage.size.height);
99 |
100 | CGContextDrawImage(outputContext, imageRect, originalImage.CGImage);
101 |
102 | if (hasBlur) {
103 | CGContextSaveGState(outputContext);
104 | if (maskImage) {
105 | CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
106 | }
107 | CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
108 | CGContextRestoreGState(outputContext);
109 | }
110 |
111 | if (tintColor) {
112 | CGContextSaveGState(outputContext);
113 | CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
114 | CGContextFillRect(outputContext, imageRect);
115 | CGContextRestoreGState(outputContext);
116 | }
117 |
118 | UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
119 | UIGraphicsEndImageContext();
120 |
121 | return [[UIImageView alloc] initWithImage:outputImage];
122 | }
123 |
124 | @end
125 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/Style/JCAlertStyle.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertStyle.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/5.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "JCAlertStyle.h"
10 |
11 | #define JCColor(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0]
12 | #define JCDefaultTextColor JCColor(0,0,0)
13 |
14 | @interface JCAlertStyleCache : NSObject
15 |
16 | @property (nonatomic, strong) JCAlertStyle *styleNormal;
17 | @property (nonatomic, strong) JCAlertStyle *styleTitleOnly;
18 | @property (nonatomic, strong) JCAlertStyle *styleContentOnly;
19 |
20 | @end
21 |
22 | @implementation JCAlertStyleCache
23 | @end
24 |
25 | @implementation JCAlertStyleAlertView @end
26 | @implementation JCAlertStyleBackground @end
27 | @implementation JCAlertStyleTitle @end
28 | @implementation JCAlertStyleContent @end
29 | @implementation JCAlertStyleButton @end
30 | @implementation JCAlertStyleButtonNormal @end
31 | @implementation JCAlertStyleButtonCancel @end
32 | @implementation JCAlertStyleButtonWarning @end
33 | @implementation JCAlertStyleSeparator @end
34 |
35 | @implementation JCAlertStyle
36 |
37 | + (instancetype)shareStyle {
38 | static JCAlertStyle *style = nil;
39 | static dispatch_once_t onceToken;
40 | dispatch_once(&onceToken, ^{
41 | style = [JCAlertStyle new];
42 | // default
43 | [style useDefaultStyle];
44 | });
45 | return style;
46 | }
47 |
48 | + (JCAlertStyle *)styleWithType:(JCAlertType)type {
49 | static JCAlertStyleCache *cache = nil;
50 | static dispatch_once_t onceToken;
51 | dispatch_once(&onceToken, ^{
52 | cache = [JCAlertStyleCache new];
53 | cache.styleNormal = [[JCAlertStyle alloc] initWithType:JCAlertTypeNormal];
54 | cache.styleTitleOnly = [[JCAlertStyle alloc] initWithType:JCAlertTypeTitleOnly];
55 | cache.styleContentOnly = [[JCAlertStyle alloc] initWithType:JCAlertTypeContentOnly];
56 | });
57 |
58 | if (type == JCAlertTypeNormal) {
59 | return cache.styleNormal;
60 | } else if (type == JCAlertTypeTitleOnly) {
61 | return cache.styleTitleOnly;
62 | } else {
63 | return cache.styleContentOnly;
64 | }
65 | }
66 |
67 | #pragma clang diagnostic push
68 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
69 |
70 | - (instancetype)initWithType:(JCAlertType)type {
71 | if (self = [super init]) {
72 | [self useDefaultStyle];
73 |
74 | if (type == JCAlertTypeTitleOnly) {
75 | [self useTitleOnlyStyle];
76 | } else if (type == JCAlertTypeContentOnly) {
77 | [self useContentOnlyStyle];
78 | }
79 | }
80 | return self;
81 | }
82 |
83 | #pragma clang diagnostic pop
84 |
85 | - (void)useDefaultStyle {
86 | JCAlertStyleBackground *background = [JCAlertStyleBackground new];
87 | background.blur = NO;
88 | background.canDismiss = NO;
89 | background.alpha = 0.3;
90 |
91 | JCAlertStyleAlertView *alertView = [JCAlertStyleAlertView new];
92 | alertView.width = [UIScreen mainScreen].bounds.size.width == 320 ? 260 : 280;
93 | alertView.maxHeight = [UIScreen mainScreen].bounds.size.height - 120;
94 | alertView.backgroundColor = [UIColor whiteColor];
95 | alertView.cornerRadius = 8;
96 |
97 | JCAlertStyleTitle *title = [JCAlertStyleTitle new];
98 | title.insets = UIEdgeInsetsMake(10, 10, 10, 10);
99 | title.onlyTitleInsets = UIEdgeInsetsMake(28, 20, 28, 20);
100 | title.font = [UIFont boldSystemFontOfSize:17];
101 | title.textColor = JCDefaultTextColor;
102 | title.backgroundColor = [UIColor whiteColor];
103 | title.textAlignment = NSTextAlignmentCenter;
104 |
105 | JCAlertStyleContent *content = [JCAlertStyleContent new];
106 | content.insets = UIEdgeInsetsMake(5, 10, 15, 10);
107 | content.onlyMessageInsets = UIEdgeInsetsMake(28, 20, 28, 20);
108 | content.font = [UIFont systemFontOfSize:15];
109 | content.textColor = JCDefaultTextColor;
110 | content.backgroundColor = [UIColor whiteColor];
111 | content.textAlignment = NSTextAlignmentCenter;
112 |
113 | JCAlertStyleButtonNormal *buttonNormal = [JCAlertStyleButtonNormal new];
114 | buttonNormal.height = 44;
115 | buttonNormal.font = [UIFont systemFontOfSize:17];
116 | buttonNormal.textColor = JCDefaultTextColor;
117 | buttonNormal.backgroundColor = [UIColor whiteColor];
118 | buttonNormal.highlightTextColor = JCDefaultTextColor;
119 | buttonNormal.highlightBackgroundColor = JCColor(224, 224, 224);
120 |
121 | JCAlertStyleButtonCancel *buttonCancel = [JCAlertStyleButtonCancel new];
122 | buttonCancel.height = 44;
123 | buttonCancel.font = [UIFont systemFontOfSize:17];
124 | buttonCancel.textColor = JCDefaultTextColor;
125 | buttonCancel.backgroundColor = [UIColor whiteColor];
126 | buttonCancel.highlightTextColor = JCDefaultTextColor;
127 | buttonCancel.highlightBackgroundColor = JCColor(224, 224, 224);
128 |
129 | JCAlertStyleButtonWarning *buttonWarning = [JCAlertStyleButtonWarning new];
130 | buttonWarning.height = 44;
131 | buttonWarning.font = [UIFont systemFontOfSize:17];
132 | buttonWarning.textColor = JCColor(248, 59, 50);
133 | buttonWarning.backgroundColor = [UIColor whiteColor];
134 | buttonWarning.highlightTextColor = JCColor(248, 59, 50);
135 | buttonWarning.highlightBackgroundColor = JCColor(224, 224, 224);
136 |
137 | JCAlertStyleSeparator *separator = [JCAlertStyleSeparator new];
138 | separator.width = 0.5;
139 | separator.color = JCColor(200, 200, 205);
140 |
141 | self.background = background;
142 | self.alertView = alertView;
143 | self.title = title;
144 | self.content = content;
145 | self.buttonNormal = buttonNormal;
146 | self.buttonCancel = buttonCancel;
147 | self.buttonWarning = buttonWarning;
148 | self.separator = separator;
149 | }
150 |
151 | - (void)useTitleOnlyStyle {
152 | self.title.insets = UIEdgeInsetsMake(28, 20, 28, 20);
153 | }
154 |
155 | - (void)useContentOnlyStyle {
156 | self.content.insets = UIEdgeInsetsMake(28, 20, 28, 20);
157 | }
158 |
159 | @end
160 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
37 |
38 |
39 | true
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | 1446598579909
110 |
111 | 1446598579909
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### [English](https://github.com/HJaycee/JCAlertController) | [中文](https://github.com/HJaycee/JCAlertController/blob/master/README_CN.md)
4 |
5 | JCAlertController继承于UIViewController,可以作为替代UIAlertController的弹窗库,使用简单,可自定义程度高。
6 |
7 |
8 | | 比较 |队列管理 | 自定义样式 | 自定义view | 最低支持系统 |
9 | | :----: | :----: | :----: | :----: | :----: |
10 | | JCAlertController | 支持 | 简单 | 简单 | iOS 7|
11 | | UIAlertController | 不支持 | 复杂 | 复杂 | iOS 8|
12 |
13 |
14 | * 支持队列管理
15 | * 支持自定义样式
16 | * 支持自定义contentView
17 |
18 | ## 什么是队列管理 ?
19 | 请看下面的伪代码:
20 |
21 | ```objc
22 | [self presentWithFIFO:alert1];
23 | [self presentWithFIFO:alert2];
24 | [self presentWithFIFO:alert3];
25 | ```
26 | 结果:
27 | alert1`第一个`显示, 被用户关闭后, alert2`第二个`显示, 被用户关闭后, alert3`第三个`显示
28 | 就像这样: `alert1` >> `alert2` >> `alert3`
29 |
30 | ```objc
31 | [self presentWithLIFO:alert1];
32 | [self presentWithLIFO:alert2];
33 | [self presentWithLIFO:alert3];
34 | ```
35 | 结果:
36 | alert3`第一个`显示, 被用户关闭后, alert2`第二个`显示, 被用户关闭后, alert1`第三个`显示
37 | 就像这样 `alert3` >> `alert2` >> `alert1`
38 |
39 | >Present顺序由 [JCPresentQueue](https://github.com/HJaycee/JCPresentQueue)管理,支持cocoapods导入。你可以用它来自动管理任何`UIAlertController`库的弹出顺序。
40 | >如果你已经导入了[JCAlertController](https://github.com/HJaycee/JCAlertController)就不用再导入[JCPresentQueue](https://github.com/HJaycee/JCPresentQueue)了。
41 |
42 | ## 预览
43 |
44 | #### 默认样式(标题和内容都有)
45 |
46 |
47 | #### 默认样式(只有标题)
48 |
49 |
50 | #### 默认样式(只有内容)
51 |
52 |
53 |
54 | #### 默认样式 (超长文字)
55 |
56 |
57 | #### 自定义样式
58 |
59 |
60 | #### 自定义View
61 |
62 |
63 | #### 自定义View+键盘处理
64 |
65 |
66 | #### 自定义View+富文本
67 |
68 |
69 |
70 | ## 文件结构
71 |
72 | ```objc
73 | .
74 | |____.DS_Store
75 | |____AlertView
76 | | |____JCAlertView.h
77 | | |____JCAlertView.m
78 | |____ButtonItem
79 | | |____JCAlertButtonItem.h
80 | | |____JCAlertButtonItem.m
81 | |____Category
82 | | |____NSAttributedString+JCCalculateSize.h
83 | | |____NSAttributedString+JCCalculateSize.m
84 | | |____UIColor+JCHightlightedColor.h
85 | | |____UIColor+JCHightlightedColor.m
86 | | |____UIImage+JCColor2Image.h
87 | | |____UIImage+JCColor2Image.m
88 | | |____UIViewController+JCPresentQueue.h // present category
89 | | |____UIViewController+JCPresentQueue.m
90 | | |____UIWindow+JCBlur.h
91 | | |____UIWindow+JCBlur.m
92 | |____JCAlertController.h // import this
93 | |____JCAlertController.m
94 | |____Style
95 | | |____JCAlertStyle.h
96 | | |____JCAlertStyle.m
97 | | |____JCAlertStyleAlertView.h
98 | | |____JCAlertStyleAlertView.m
99 | | |____JCAlertStyleBackground.h
100 | | |____JCAlertStyleBackground.m
101 | | |____JCAlertStyleButton.h
102 | | |____JCAlertStyleButton.m
103 | | |____JCAlertStyleButtonCancel.h
104 | | |____JCAlertStyleButtonCancel.m
105 | | |____JCAlertStyleButtonNormal.h
106 | | |____JCAlertStyleButtonNormal.m
107 | | |____JCAlertStyleButtonWarning.h
108 | | |____JCAlertStyleButtonWarning.m
109 | | |____JCAlertStyleContent.h
110 | | |____JCAlertStyleContent.m
111 | | |____JCAlertStyleSeparator.h
112 | | |____JCAlertStyleSeparator.m
113 | | |____JCAlertStyleTitle.h
114 | | |____JCAlertStyleTitle.m
115 | ```
116 |
117 | ## 使用CocoaPods集成
118 |
119 | step 1
120 | ```objc
121 | platform :ios, '7.0'
122 | target 'your target' do
123 | pod 'JCAlertController'
124 | end
125 | ```
126 |
127 | step 2
128 | ```objc
129 | #import "JCAlertController.h"
130 | ```
131 |
132 | ## 如何使用
133 |
134 | ```objc
135 | // LIFO: alert3 >> alert2 >> alert1
136 | for (int i = 1; i<4; i++) {
137 | JCAlertController *alert = [JCAlertController alertWithTitle:[NSString stringWithFormat:@"alert%zi", i] message:nil];
138 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
139 | [self jc_presentViewController:alert presentCompletion:nil dismissCompletion:nil];
140 | }
141 | ```
142 |
143 |
144 | ## Contact me
145 |
146 | E-mail: hjaycee@163.com
147 | Blog: http://www.jianshu.com/u/8bde69945e50
148 |
149 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### [English](https://github.com/HJaycee/JCAlertController) | [中文](https://github.com/HJaycee/JCAlertController/blob/master/README_CN.md)
4 |
5 | `JCAlertController` is `same level` with `UIAlertController`.
6 | It is `inherited` from `UIViewController` too.
7 | It supports managing presented controllers with `FIFO` or `LIFO`.
8 |
9 |
10 | | Compare | Present Queue | Custom Style | Custom View | Minimum iOS Target |
11 | | :----: | :----: | :----: | :----: | :----: |
12 | | JCAlertController | support | simple | simple | iOS 7|
13 | | UIAlertController | not support| difficult | difficult | iOS 8|
14 |
15 |
16 | * support present queue
17 | * support custom style
18 | * support custom contentView
19 |
20 | ## What is present queue ?
21 | Look at the flowing code:
22 |
23 | ```objc
24 | [self presentWithFIFO:alert1];
25 | [self presentWithFIFO:alert2];
26 | [self presentWithFIFO:alert3];
27 | ```
28 | Result:
29 | alert1 shows `first`, after dismissed by user, alert2 shows `second`, after dismissed by user, alert3 shows `third`.
30 | like this: `alert1` >> `alert2` >> `alert3`
31 |
32 | ```objc
33 | [self presentWithLIFO:alert1];
34 | [self presentWithLIFO:alert2];
35 | [self presentWithLIFO:alert3];
36 | ```
37 | Result:
38 | alert3 shows `first`, after dismissed by user, alert2 shows `second`, after dismissed by user, alert1 shows `third`.
39 | like this `alert3` >> `alert2` >> `alert1`
40 |
41 | Present queue is powered by [JCPresentQueue](https://github.com/HJaycee/JCPresentQueue). It supports cocoapods too.
42 |
43 | ## Preview
44 |
45 | #### normal style
46 |
47 |
48 | #### normal style(title only)
49 |
50 |
51 | #### normal style(content only)
52 |
53 |
54 |
55 | #### normal style (words oveflow)
56 |
57 |
58 | #### custom style
59 |
60 |
61 | #### custom contentView
62 |
63 |
64 | #### custom contentView and keyboard handle
65 |
66 |
67 | #### custom contentView and attributedstring
68 |
69 |
70 |
71 | ## Struct
72 |
73 | ```objc
74 | .
75 | |____.DS_Store
76 | |____AlertView
77 | | |____JCAlertView.h
78 | | |____JCAlertView.m
79 | |____ButtonItem
80 | | |____JCAlertButtonItem.h
81 | | |____JCAlertButtonItem.m
82 | |____Category
83 | | |____NSAttributedString+JCCalculateSize.h
84 | | |____NSAttributedString+JCCalculateSize.m
85 | | |____UIColor+JCHightlightedColor.h
86 | | |____UIColor+JCHightlightedColor.m
87 | | |____UIImage+JCColor2Image.h
88 | | |____UIImage+JCColor2Image.m
89 | | |____UIViewController+JCPresentQueue.h // present category
90 | | |____UIViewController+JCPresentQueue.m
91 | | |____UIWindow+JCBlur.h
92 | | |____UIWindow+JCBlur.m
93 | |____JCAlertController.h // import this
94 | |____JCAlertController.m
95 | |____Style
96 | | |____JCAlertStyle.h
97 | | |____JCAlertStyle.m
98 | | |____JCAlertStyleAlertView.h
99 | | |____JCAlertStyleAlertView.m
100 | | |____JCAlertStyleBackground.h
101 | | |____JCAlertStyleBackground.m
102 | | |____JCAlertStyleButton.h
103 | | |____JCAlertStyleButton.m
104 | | |____JCAlertStyleButtonCancel.h
105 | | |____JCAlertStyleButtonCancel.m
106 | | |____JCAlertStyleButtonNormal.h
107 | | |____JCAlertStyleButtonNormal.m
108 | | |____JCAlertStyleButtonWarning.h
109 | | |____JCAlertStyleButtonWarning.m
110 | | |____JCAlertStyleContent.h
111 | | |____JCAlertStyleContent.m
112 | | |____JCAlertStyleSeparator.h
113 | | |____JCAlertStyleSeparator.m
114 | | |____JCAlertStyleTitle.h
115 | | |____JCAlertStyleTitle.m
116 | ```
117 |
118 | ## Installation with CocoaPods
119 |
120 | step 1
121 | ```objc
122 | platform :ios, '7.0'
123 | target 'your target' do
124 | pod 'JCAlertController'
125 | end
126 | ```
127 |
128 | step 2
129 | ```objc
130 | #import "JCAlertController.h"
131 | ```
132 |
133 | ## Usage
134 |
135 | ```objc
136 | // LIFO: alert3 >> alert2 >> alert1
137 | for (int i = 1; i<4; i++) {
138 | JCAlertController *alert = [JCAlertController alertWithTitle:[NSString stringWithFormat:@"alert%zi", i] message:nil];
139 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
140 | [self jc_presentViewController:alert presentCompletion:nil dismissCompletion:nil];
141 | }
142 | ```
143 |
144 | ## Contact me
145 |
146 | E-mail: hjaycee@163.com
147 | Blog: http://www.jianshu.com/u/8bde69945e50
148 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/JCPresentQueue/UIViewController+JCPresentQueue.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController+JCPresentQueue.m
3 | // JCPresentController
4 | //
5 | // Created by HJaycee on 2017/4/4.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "UIViewController+JCPresentQueue.h"
10 | #import
11 |
12 | NSString * const JCPresentControllersAllDismissedNotification = @"JCPresentControllersAllDismissedNotification";
13 |
14 | static NSMutableArray *_stackControllers;
15 | static NSOperationQueue *_operationQueue;
16 | static dispatch_queue_t _jc_present_queue;
17 |
18 | @implementation UIViewController (JCPresentQueue)
19 |
20 | + (void)load {
21 | SEL oldSel = @selector(viewDidDisappear:);
22 | SEL newSel = @selector(jc_viewDidDisappear:);
23 | Method oldMethod = class_getInstanceMethod([self class], oldSel);
24 | Method newMethod = class_getInstanceMethod([self class], newSel);
25 |
26 | BOOL didAddMethod = class_addMethod(self, oldSel, method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
27 | if (didAddMethod) {
28 | class_replaceMethod(self, newSel, method_getImplementation(oldMethod), method_getTypeEncoding(oldMethod));
29 | } else {
30 | method_exchangeImplementations(oldMethod, newMethod);
31 | }
32 |
33 | _stackControllers = ({
34 | static NSMutableArray *stackControllers = nil;
35 | static dispatch_once_t onceToken;
36 | dispatch_once(&onceToken, ^{
37 | stackControllers = [NSMutableArray array];
38 | });
39 | stackControllers;
40 | });
41 |
42 | _operationQueue = ({
43 | static NSOperationQueue *operationQueue = nil;
44 | static dispatch_once_t onceToken;
45 | dispatch_once(&onceToken, ^{
46 | _jc_present_queue = dispatch_queue_create("jc_present_queue", DISPATCH_QUEUE_SERIAL);
47 | operationQueue = [NSOperationQueue new];
48 | operationQueue.underlyingQueue = _jc_present_queue;
49 | });
50 | operationQueue;
51 | });
52 | }
53 |
54 | - (void)jc_viewDidDisappear:(BOOL)animated {
55 | [self jc_viewDidDisappear:animated];
56 |
57 | if ([self getDeallocCompletion] && ![self isTemporarilyDismissed]) {
58 | [self getDeallocCompletion]();
59 | }
60 | }
61 |
62 | - (void)setDeallocCompletion:(void (^)(void))completion {
63 | objc_setAssociatedObject(self, @selector(getDeallocCompletion), completion, OBJC_ASSOCIATION_COPY_NONATOMIC);
64 | }
65 |
66 | - (void (^)(void))getDeallocCompletion {
67 | return objc_getAssociatedObject(self, _cmd);
68 | }
69 |
70 | - (void)setDismissCompletion:(void (^)(void))completion {
71 | objc_setAssociatedObject(self, @selector(getDismissCompletion), completion, OBJC_ASSOCIATION_COPY_NONATOMIC);
72 | }
73 |
74 | - (void (^)(void))getDismissCompletion {
75 | return objc_getAssociatedObject(self, _cmd);
76 | }
77 |
78 | - (void)setPresentCompletion:(void (^)(void))completion {
79 | objc_setAssociatedObject(self, @selector(getPresentCompletion), completion, OBJC_ASSOCIATION_COPY_NONATOMIC);
80 | }
81 |
82 | - (void (^)(void))getPresentCompletion {
83 | return objc_getAssociatedObject(self, _cmd);
84 | }
85 |
86 | - (void)setCurrentPresentType:(JCPresentType)presentType {
87 | objc_setAssociatedObject(self, @selector(getCurrentPresentType), @(presentType), OBJC_ASSOCIATION_COPY_NONATOMIC);
88 | }
89 |
90 | - (JCPresentType)getCurrentPresentType {
91 | NSNumber *type = objc_getAssociatedObject(self, _cmd);
92 | return [type integerValue];
93 | }
94 |
95 | - (void)setTemporarilyDismissed:(BOOL)temporarilyDismissed {
96 | objc_setAssociatedObject(self, @selector(isTemporarilyDismissed), @(temporarilyDismissed), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
97 | }
98 |
99 | - (BOOL)isTemporarilyDismissed {
100 | NSNumber *num = objc_getAssociatedObject(self, _cmd);
101 | return [num boolValue];
102 | }
103 |
104 | - (void)setDismissing:(BOOL)dismissing {
105 | objc_setAssociatedObject(self, @selector(isDismissing), @(dismissing), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
106 | }
107 |
108 | - (BOOL)isDismissing {
109 | NSNumber *num = objc_getAssociatedObject(self, _cmd);
110 | return [num boolValue];
111 | }
112 |
113 | - (void)jc_presentViewController:(UIViewController *)controller presentType:(JCPresentType)presentType presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion {
114 | if ([_operationQueue operations].count > 0 && presentType != [self getCurrentPresentType]) {
115 | [NSException raise:@"This is dangerous." format:@"%@'s present queue is confused. Dont't use LIFO and FIFO two together.", self];
116 | }
117 | [self setCurrentPresentType:presentType];
118 |
119 | if (presentType == JCPresentTypeLIFO) {
120 | [self lifoPresentViewController:controller presentCompletion:presentCompletion dismissCompletion:dismissCompletion];
121 | } else {
122 | [self fifoPresentViewController:controller presentCompletion:presentCompletion dismissCompletion:dismissCompletion];
123 | }
124 | }
125 |
126 | #pragma mark - present controller with LIFO
127 | - (void)lifoPresentViewController:(UIViewController *)controller presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion {
128 |
129 | dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
130 |
131 | // put in stack
132 | NSMutableArray *stackControllers = _stackControllers;
133 | if (![stackControllers containsObject:controller]) {
134 | [stackControllers addObject:controller];
135 | }
136 |
137 | NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
138 | __weak typeof(controller) weakController = controller;
139 | [controller setPresentCompletion:presentCompletion];
140 | [controller setDismissCompletion:dismissCompletion];
141 | [controller setDeallocCompletion:^{
142 | if (dismissCompletion) {
143 | dismissCompletion();
144 | }
145 |
146 | // fetch new next controller if exists, because button action after dismiss completion
147 | [weakController setDismissing:YES];
148 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
149 | [weakController setDismissing:NO];
150 | // if the dismiss controller is the last one
151 | if (stackControllers.lastObject == weakController) {
152 | [stackControllers removeObject:weakController];
153 |
154 | // is there any previous controllers
155 | if (stackControllers.count > 0) {
156 | UIViewController *preController = [stackControllers lastObject];
157 | [self lifoPresentViewController:preController presentCompletion:[preController getPresentCompletion] dismissCompletion:[preController getDismissCompletion]];
158 | } else {
159 | [[NSNotificationCenter defaultCenter] postNotificationName:JCPresentControllersAllDismissedNotification object:nil];
160 | }
161 | } else {
162 | NSUInteger index = [stackControllers indexOfObject:weakController];
163 | [stackControllers removeObject:weakController];
164 |
165 | // is there any next controllers
166 | NSArray *nextControllers = [stackControllers objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(index, stackControllers.count - index)]];
167 | for (UIViewController *nextController in nextControllers) {
168 | [self lifoPresentViewController:nextController presentCompletion:[nextController getPresentCompletion] dismissCompletion:[nextController getDismissCompletion]];
169 | }
170 | }
171 | });
172 | }];
173 |
174 | // if the previous controller is dismissing, wait it's completion
175 | if (stackControllers.count > 1) {
176 | for (UIViewController *preController in stackControllers) {
177 | if ([preController isDismissing]) {
178 | return ;
179 | }
180 | }
181 | }
182 |
183 | // present a new controller before dismissing the presented controller if exists
184 | dispatch_async(dispatch_get_main_queue(), ^{
185 | if (self.presentedViewController) {
186 | [self.presentedViewController temporarilyDismissViewControllerAnimated:YES completion:^{
187 | [self presentViewController:controller animated:YES completion:^{
188 | dispatch_semaphore_signal(semaphore);
189 | }];
190 | }];
191 | } else {
192 | [self presentViewController:controller animated:YES completion:^{
193 | dispatch_semaphore_signal(semaphore);
194 | if (presentCompletion) {
195 | presentCompletion();
196 | }
197 | }];
198 | }
199 | });
200 |
201 | dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
202 | }];
203 |
204 | // put in queue
205 | if (_operationQueue.operations.lastObject) {
206 | [operation addDependency:_operationQueue.operations.lastObject];
207 | }
208 | [_operationQueue addOperation:operation];
209 | }
210 |
211 | // dismiss controller temporarily
212 | - (void)temporarilyDismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion {
213 | [self setTemporarilyDismissed:YES];
214 | [self dismissViewControllerAnimated:flag completion:^{
215 | [self setTemporarilyDismissed:NO];
216 | if (completion) {
217 | completion();
218 | }
219 | }];
220 | }
221 |
222 | #pragma mark - present controller with FIFO
223 | - (void)fifoPresentViewController:(UIViewController *)controller presentCompletion:(void (^)(void))presentCompletion dismissCompletion:(void (^)(void))dismissCompletion {
224 | dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
225 | NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
226 | [controller setDeallocCompletion:^{
227 | if (dismissCompletion) {
228 | dismissCompletion();
229 | }
230 |
231 | if (_operationQueue.operations.count <= 1) {
232 | [[NSNotificationCenter defaultCenter] postNotificationName:JCPresentControllersAllDismissedNotification object:nil];
233 | }
234 |
235 | // got to next operation
236 | dispatch_semaphore_signal(semaphore);
237 | }];
238 | dispatch_async(dispatch_get_main_queue(), ^{
239 | [self presentViewController:controller animated:YES completion:presentCompletion];
240 | });
241 | dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
242 | }];
243 |
244 | // put in queue
245 | if (_operationQueue.operations.lastObject) {
246 | [operation addDependency:_operationQueue.operations.lastObject];
247 | }
248 | [_operationQueue addOperation:operation];
249 | }
250 |
251 | @end
252 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/JCAlertController.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertController.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/3/31.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "JCAlertController.h"
10 | #import "JCAlertView.h"
11 | #import "UIWindow+JCBlur.h"
12 | #import "JCAlertStyle.h"
13 | #import "NSAttributedString+JCCalculateSize.h"
14 | #import "JCAlertButtonItem.h"
15 |
16 | @interface JCAlertController ()
17 |
18 | @property (nonatomic, strong) UIImageView *blurView;
19 | @property (nonatomic, strong) UIButton *coverView;
20 | @property (nonatomic, strong) JCAlertView *alertView;
21 |
22 | @end
23 |
24 | #pragma mark - transitionAnimation
25 |
26 | @interface JCDimissAnimation : NSObject
27 | @end
28 |
29 | @implementation JCDimissAnimation
30 |
31 | - (NSTimeInterval)transitionDuration:(id)transitionContext {
32 | return 0.2;
33 | }
34 |
35 | - (void)animateTransition:(id)transitionContext {
36 | JCAlertController *alertController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
37 |
38 | NSTimeInterval duration = [self transitionDuration:transitionContext];
39 |
40 | [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
41 | alertController.coverView.alpha = 0;
42 | alertController.blurView.alpha = 0;
43 | alertController.alertView.alpha = 0;
44 | } completion:^(BOOL finished) {
45 | [alertController.view removeFromSuperview];
46 | [transitionContext completeTransition:YES];
47 | }];
48 |
49 | [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
50 | alertController.alertView.transform = CGAffineTransformMakeScale(0.7, 0.7);
51 | } completion:^(BOOL finished) {
52 | alertController.alertView.transform = CGAffineTransformIdentity;
53 | }];
54 | }
55 |
56 | @end
57 |
58 | @interface JCPresentAnimation : NSObject
59 | @end
60 |
61 | @implementation JCPresentAnimation
62 |
63 | - (NSTimeInterval)transitionDuration:(id)transitionContext {
64 | return 0.4;
65 | }
66 |
67 | - (void)animateTransition:(id)transitionContext {
68 | JCAlertController *alertController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
69 |
70 | [[transitionContext containerView] addSubview:alertController.view];
71 |
72 | NSTimeInterval duration = [self transitionDuration:transitionContext];
73 |
74 | alertController.blurView.alpha = 0;
75 | alertController.coverView.alpha = 0;
76 | alertController.alertView.alpha = 1;
77 | alertController.alertView.transform = CGAffineTransformMakeScale(0.4, 0.4);
78 |
79 | [UIView animateWithDuration:duration / 2 animations:^{
80 | alertController.coverView.alpha = alertController.alertView.style.background.alpha;
81 | }];
82 |
83 | [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
84 | alertController.blurView.alpha = 1;
85 | } completion:nil];
86 |
87 | [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:20 options:UIViewAnimationOptionAllowUserInteraction animations:^{
88 | alertController.alertView.transform = CGAffineTransformIdentity;
89 | } completion:^(BOOL finished) {
90 | [transitionContext completeTransition:YES];
91 | }];
92 | }
93 |
94 | @end
95 |
96 | @interface JCAlertController ()
97 |
98 | @property (nonatomic, copy) NSString *alertTitle;
99 | @property (nonatomic, copy) NSString *alertMessage;
100 | @property (nonatomic, strong) UIView *contentView;
101 | @property (nonatomic, strong) NSMutableArray *buttonItems;
102 | @property (nonatomic, strong) JCAlertStyle *style;
103 | @property (nonatomic, copy) void(^keyboardShowed)(CGFloat alertHeight, CGFloat keyboardHeight);
104 | @property (nonatomic, copy) void(^keyboardHided)(void);
105 |
106 | @end
107 |
108 | @implementation JCAlertController
109 |
110 | #pragma clang diagnostic push
111 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
112 |
113 | + (instancetype)alertWithTitle:(NSString *)title message:(NSString *)message {
114 | return [self alertWithTitle:title message:message type:0];
115 | }
116 |
117 | + (instancetype)alertWithTitle:(NSString *)title contentView:(UIView *)contentView {
118 | return [self alertWithTitle:title contentView:contentView type:0];
119 | }
120 |
121 | #pragma clang diagnostic pop
122 |
123 | + (instancetype)alertWithTitle:(NSString *)title message:(NSString *)message type:(JCAlertType)type {
124 | return [[self alloc] initWithTitle:title message:message type:type];
125 | }
126 |
127 | + (instancetype)alertWithTitle:(NSString *)title contentView:(UIView *)contentView type:(JCAlertType)type {
128 | return [[self alloc] initWithTitle:title contentView:contentView type:type];
129 | }
130 |
131 | - (instancetype)initWithTitle:(NSString *)title message:(NSString *)message type:(JCAlertType)type{
132 | if (self = [super init]) {
133 | self.modalPresentationStyle = UIModalPresentationCustom;
134 | self.transitioningDelegate = self;
135 | self.alertTitle = title;
136 | self.alertMessage = message;
137 | self.style = [JCAlertStyle shareStyle];
138 |
139 | if (self.alertTitle.length == 0 && self.alertMessage.length == 0) {
140 | [NSException raise:@"can not show" format:@"%@: need title or message at least one", self];
141 | }
142 | }
143 | return self;
144 | }
145 |
146 | - (instancetype)initWithTitle:(NSString *)title contentView:(UIView *)contentView type:(JCAlertType)type {
147 | if (self = [super init]) {
148 | self.modalPresentationStyle = UIModalPresentationCustom;
149 | self.transitioningDelegate = self;
150 | self.alertTitle = title;
151 | self.contentView = contentView;
152 | self.style = [JCAlertStyle shareStyle];
153 |
154 | if (self.alertTitle.length == 0 && contentView.frame.size.width != self.style.alertView.width) {
155 | [NSException raise:@"can not show" format:@"%@: title is empty or contentView's width is not equal to alertView's width", self];
156 | }
157 | }
158 | return self;
159 | }
160 |
161 | - (void)monitorKeyboardShowed:(void(^)(CGFloat alertHeight, CGFloat keyboardHeight))showed {
162 | self.keyboardShowed = showed;
163 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardShow:) name:UIKeyboardWillShowNotification object:nil];
164 | }
165 |
166 | - (void)monitorKeyboardHided:(void(^)(void))hided {
167 | self.keyboardHided = hided;
168 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHide) name:UIKeyboardWillHideNotification object:nil];
169 | }
170 |
171 | - (void)keyboardShow:(NSNotification *)notification {
172 | CGRect keyBoardRect = [[[notification userInfo]objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
173 |
174 | if (self.keyboardShowed) {
175 | self.keyboardShowed(self.alertView.frame.size.height, keyBoardRect.size.height);
176 | }
177 | }
178 |
179 | - (void)keyboardHide {
180 | if (self.keyboardHided) {
181 | self.keyboardHided();
182 | }
183 | }
184 |
185 | - (void)dealloc {
186 | [[NSNotificationCenter defaultCenter] removeObserver:self];
187 | }
188 |
189 | - (void)moveAlertViewToCenterY:(CGFloat)centerY animated:(BOOL)animated {
190 | [UIView animateWithDuration:animated ? 0.25 : 0 animations:^{
191 | self.alertView.center = CGPointMake(self.alertView.center.x, centerY);
192 | }];
193 | }
194 |
195 | - (void)moveAlertViewToScreenCenterAnimated:(BOOL)animated {
196 | [self moveAlertViewToCenterY:[UIScreen mainScreen].bounds.size.height / 2 animated:animated];
197 | }
198 |
199 | - (NSMutableArray *)buttonItems {
200 | if (!_buttonItems) {
201 | _buttonItems = [NSMutableArray arrayWithCapacity:2];
202 | }
203 | return _buttonItems;
204 | }
205 |
206 | - (void)addButtonWithTitle:(NSString *)title type:(JCButtonType)type clicked:(void (^)(void))clicked {
207 | if (self.buttonItems.count >= 2) {
208 | [NSException raise:@"You can add 2 buttons at most" format:@"%@: already has %zi buttons", self, self.buttonItems.count];
209 | }
210 |
211 | JCAlertButtonItem *item = [JCAlertButtonItem new];
212 | item.title = title;
213 | item.type = type;
214 | item.clicked = clicked;
215 | [self.buttonItems addObject:item];
216 | }
217 |
218 | - (void)viewDidLoad {
219 | [super viewDidLoad];
220 |
221 | [self setupBlurView];
222 | [self setupAlphaCoverView];
223 | [self setupAlertView];
224 | }
225 |
226 | - (void)setupBlurView {
227 | if (self.style.background.blur) {
228 | // check the window
229 | NSArray* reversedWindows = [[[UIApplication sharedApplication].windows reverseObjectEnumerator] allObjects];
230 | for (UIWindow *window in reversedWindows) {
231 | if ([NSStringFromClass([window class]) isEqualToString:@"UIWindow"] && CGRectEqualToRect(window.frame, [UIScreen mainScreen].bounds)) {
232 | self.blurView = [window blurScreenshot];
233 | [self.view addSubview:self.blurView];
234 | break;
235 | }
236 | }
237 | }
238 | }
239 |
240 | - (void)setupAlphaCoverView {
241 | self.coverView = [[UIButton alloc] initWithFrame:[UIScreen mainScreen].bounds];
242 | self.coverView.backgroundColor = [UIColor colorWithRed:5/255.0 green:0 blue:10/255.0 alpha:1.0];
243 | [self.view addSubview:self.coverView];
244 | if (self.style.background.canDismiss) {
245 | [self.coverView addTarget:self action:@selector(dismissViewController) forControlEvents:UIControlEventTouchUpInside];
246 | }
247 | }
248 |
249 | - (void)setupAlertView {
250 | self.alertView = [JCAlertView new];
251 | self.alertView.title = self.alertTitle;
252 | self.alertView.message = self.alertMessage;
253 | self.alertView.contentView = self.contentView;
254 | self.alertView.buttonItems = self.buttonItems;
255 | self.alertView.style = self.style;
256 | self.alertView.backgroundColor = self.style.alertView.backgroundColor;
257 | self.alertView.delegate = self;
258 | [self.view addSubview:self.alertView];
259 | }
260 |
261 | - (void)dismissViewController {
262 | [self dismissViewControllerAnimated:YES completion:nil];
263 | }
264 |
265 | #pragma mark - transtionAnimation
266 | - (id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
267 | return [JCPresentAnimation new];
268 | }
269 |
270 | - (id)animationControllerForDismissedController:(UIViewController *)dismissed {
271 | return [JCDimissAnimation new];
272 | }
273 |
274 | #pragma mark - JCAlertViewDelegate
275 | - (void)alertButtonClicked:(void (^)(void))clicked {
276 | [self dismissViewControllerAnimated:YES completion:^{
277 | if (clicked) {
278 | clicked();
279 | }
280 | }];
281 | }
282 |
283 | @end
284 |
--------------------------------------------------------------------------------
/JCAlertController/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/6.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "JCAlertController.h"
11 | #import "NSObject+BlockSEL.h" // just used in demo
12 | #import "UIViewController+JCPresentQueue.h"
13 | #import "NormalVCForPresentation.h"
14 |
15 | #define identifier @"identifier"
16 | #define longTitle @"I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title I am title "
17 | #define longMessage @"I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content I am content "
18 |
19 | @interface ViewController ()
20 |
21 | @property (nonatomic, strong) NSArray *dataSource;
22 |
23 | @end
24 |
25 | @implementation ViewController
26 |
27 | - (void)viewDidLoad {
28 | [super viewDidLoad];
29 | // Do any additional setup after loading the view, typically from a nib.
30 |
31 | self.title = @"JCAlertController";
32 |
33 | self.dataSource = @[
34 | @{@"Normal Style":@[@"only title",@"only content",@"title and content both",@"title words overflow",@"content words overflow"]},
35 | @{@"Custom Style":@[@"change JCAlertTypeCustom"]},
36 | @{@"Present Queue":@[@"JCAlertController LIFO",
37 | @"JCAlertController FIFO",
38 | @"UIAlertController LIFO",
39 | @"UIAlertController FIFO",
40 | @"UIAlertController default"]},
41 | @{@"Custom ContentView":@[@"contentView",@"contentView and keyboard handle",@"contentView and attributed string"]},
42 | @{@"FIFO View Hierarchy test":@[@"pop/dismiss self when alert dismissed"]},
43 | @{@"LIFO View Hierarchy test":@[@"pop/dismiss self when alert dismissed", @"present another controller when first alert dismissed"]}];
44 |
45 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:identifier];
46 | [self.tableView reloadData];
47 |
48 | // default is UIWindowLevelNormal
49 | [JCPresentController setOverlayWindowLevel:UIWindowLevelAlert + 1];
50 | }
51 |
52 | #pragma mark - TableView delegate/datasource
53 |
54 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
55 | return self.dataSource.count;
56 | }
57 |
58 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
59 | NSDictionary *dict = self.dataSource[section];
60 | NSArray *array = [dict.allValues firstObject];
61 | return array.count;
62 | }
63 |
64 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
65 | NSDictionary *dict = self.dataSource[section];
66 | return dict.allKeys.firstObject;
67 | }
68 |
69 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
70 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
71 | NSDictionary *dict = self.dataSource[indexPath.section];
72 | NSArray *array = [dict.allValues firstObject];
73 | cell.textLabel.text = array[indexPath.row];
74 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
75 | return cell;
76 | }
77 |
78 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
79 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
80 |
81 | if (indexPath.section == 0) {
82 | if (indexPath.row == 0) {
83 | [self onlyTitle];
84 | } else if (indexPath.row == 1) {
85 | [self onlyContent];
86 | } else if (indexPath.row == 2) {
87 | [self titleAndContentBoth];
88 | } else if (indexPath.row == 3) {
89 | [self titleWordsOverflow];
90 | } else if (indexPath.row == 4) {
91 | [self contentWordsOverflow];
92 | }
93 | }
94 |
95 | if (indexPath.section == 1) {
96 | [self customStyle];
97 | }
98 |
99 | if (indexPath.section == 2) {
100 | if (indexPath.row == 0) {
101 | [self JCAlertControllerLIFO];
102 | } else if (indexPath.row == 1) {
103 | [self JCAlertControllerFIFO];
104 | } else if (indexPath.row == 2){
105 | [self UIAlertControllerLIFO];
106 | } else if (indexPath.row == 3) {
107 | [self UIAlertControllerFIFO];
108 | } else {
109 | [self UIAlertControllerDefault];
110 | }
111 | }
112 |
113 | if (indexPath.section == 3) {
114 | if (indexPath.row == 0) {
115 | [self customView];
116 | } else if (indexPath.row == 1) {
117 | [self customViewAndHandleKeyboard];
118 | } else {
119 | [self customViewAndAttributedString];
120 | }
121 | }
122 |
123 | if (indexPath.section == 4) {
124 | if (indexPath.row == 0) {
125 | [self popOrDismissSelfWhenAlertDismissedFIFO];
126 | }
127 | }
128 |
129 | if (indexPath.section == 5) {
130 | if (indexPath.row == 0) {
131 | [self popOrDismissSelfWhenAlertDismissedLIFO];
132 | } else if (indexPath.row == 1) {
133 | [self presentOtherVCWhenLastAlertDismissed];
134 | }
135 | }
136 | }
137 |
138 |
139 | #pragma mark - Methods
140 |
141 | - (void)onlyTitle {
142 | JCAlertController *alert = [JCAlertController alertWithTitle:@"I am title" message:nil];
143 | [alert addButtonWithTitle:@"Cancel" type:JCButtonTypeCancel clicked:^{
144 | NSLog(@"Cancel button clicked");
145 | }];
146 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:^{
147 | NSLog(@"OK button clicked");
148 | }];
149 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:^{
150 | NSLog(@"present completion");
151 | } dismissCompletion:^{
152 | NSLog(@"dismiss completion");
153 | }];
154 | }
155 |
156 | - (void)onlyContent {
157 | JCAlertController *alert = [JCAlertController alertWithTitle:nil message:@"I am content"];
158 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
159 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
160 | }
161 |
162 | - (void)titleAndContentBoth {
163 | JCAlertController *alert = [JCAlertController alertWithTitle:@"JCAlertController" message:@"Support custom Style.\nSupport custom View.\nSupport presented with LIFO."];
164 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
165 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
166 | }
167 |
168 | - (void)titleWordsOverflow {
169 | JCAlertController *alert = [JCAlertController alertWithTitle:longTitle message:nil];
170 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
171 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
172 | }
173 |
174 | - (void)contentWordsOverflow {
175 | JCAlertController *alert = [JCAlertController alertWithTitle:@"I am title" message:longMessage];
176 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
177 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
178 | }
179 |
180 | - (void)customStyle {
181 | // See all properties in JCAlertStyle
182 | JCAlertStyle *style = [JCAlertStyle shareStyle];
183 |
184 | style.background.blur = YES;
185 | style.background.alpha = 0.65;
186 | style.background.canDismiss = YES;
187 |
188 | style.alertView.cornerRadius = 4;
189 |
190 | style.title.backgroundColor = [UIColor colorWithRed:251/255.0 green:2/255.0 blue:19/255.0 alpha:1.0];
191 | style.title.textColor = [UIColor whiteColor];
192 |
193 | style.content.backgroundColor = [UIColor colorWithRed:251/255.0 green:2/255.0 blue:19/255.0 alpha:1.0];
194 | style.content.textColor = [UIColor whiteColor];
195 | style.content.insets = UIEdgeInsetsMake(20, 20, 40, 20);
196 |
197 | style.buttonNormal.textColor = [UIColor colorWithRed:248/255.0 green:59/255.0 blue:50/255.0 alpha:1.0];
198 | style.buttonNormal.highlightTextColor = [style.buttonNormal.textColor hightlightedColor];
199 | style.buttonNormal.backgroundColor = [UIColor whiteColor];
200 | style.buttonNormal.highlightBackgroundColor = [UIColor whiteColor];
201 |
202 | JCAlertController *alert = [JCAlertController alertWithTitle:@"I am title" message:@"I am content"];
203 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
204 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
205 | }
206 |
207 | - (void)JCAlertControllerLIFO {
208 | // LIFO: alert3 >> alert2 >> alert1
209 | for (int i = 1; i<4; i++) {
210 | JCAlertController *alert = [JCAlertController alertWithTitle:[NSString stringWithFormat:@"alert%i", i] message:nil];
211 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
212 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
213 | }
214 | }
215 |
216 | - (void)JCAlertControllerFIFO {
217 | // FIFO alert1 >> alert2 >> alert3
218 | for (int i = 1; i<4; i++) {
219 | JCAlertController *alert = [JCAlertController alertWithTitle:[NSString stringWithFormat:@"alert%i", i] message:nil];
220 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
221 | [JCPresentController presentViewControllerFIFO:alert presentCompletion:nil dismissCompletion:nil];
222 | }
223 | }
224 |
225 | - (void)UIAlertControllerLIFO {
226 | // LIFO: alert3 >> alert2 >> alert1
227 | for (int i = 1; i<4; i++) {
228 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"alert%i", i] message:nil preferredStyle:UIAlertControllerStyleAlert];
229 | UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:nil];
230 | [alert addAction:alertAction];
231 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
232 | }
233 | }
234 |
235 | - (void)UIAlertControllerFIFO {
236 | // FIFO: alert1 >> alert2 >> alert3
237 | for (int i = 1; i<4; i++) {
238 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"alert%i", i] message:nil preferredStyle:UIAlertControllerStyleAlert];
239 | UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:nil];
240 | [alert addAction:alertAction];
241 | [JCPresentController presentViewControllerFIFO:alert presentCompletion:nil dismissCompletion:nil];
242 | }
243 | }
244 |
245 | - (void)UIAlertControllerDefault {
246 | // Only show one alert and log error msg.
247 | for (int i = 1; i<4; i++) {
248 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"alert%i", i] message:nil preferredStyle:UIAlertControllerStyleAlert];
249 | UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:nil];
250 | [alert addAction:alertAction];
251 | [self presentViewController:alert animated:YES completion:nil];
252 | }
253 | }
254 |
255 |
256 | - (void)popOrDismissSelfWhenAlertDismissedFIFO {
257 | JCAlertController *alert = [JCAlertController alertWithTitle:@"pop/dismiss self in completion" message:nil];
258 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
259 | __weak typeof(self) weakSelf = self;
260 | [JCPresentController presentViewControllerFIFO:alert presentCompletion:nil dismissCompletion:^(void){
261 | if (weakSelf.navigationController) {
262 | [weakSelf.navigationController popViewControllerAnimated:YES];
263 | } else {
264 | [weakSelf dismissViewControllerAnimated:YES completion:nil];
265 | }
266 | }];
267 | for (int i = 1; i<4; i++) {
268 | JCAlertController *alert = [JCAlertController alertWithTitle:[NSString stringWithFormat:@"alert%i", i] message:nil];
269 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
270 | [JCPresentController presentViewControllerFIFO:alert presentCompletion:nil dismissCompletion:nil];
271 | }
272 | }
273 |
274 | - (void)popOrDismissSelfWhenAlertDismissedLIFO {
275 | for (int i = 1; i<4; i++) {
276 | JCAlertController *alert = [JCAlertController alertWithTitle:[NSString stringWithFormat:@"alert%i", i] message:nil];
277 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
278 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
279 | }
280 | JCAlertController *alert = [JCAlertController alertWithTitle:@"pop/dismiss self in completion" message:nil];
281 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
282 | __weak typeof(self) weakSelf = self;
283 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:^(void){
284 | if (weakSelf.presentingViewController) {
285 | [weakSelf dismissViewControllerAnimated:YES completion:nil];
286 | } else {
287 | [weakSelf.navigationController popViewControllerAnimated:YES];
288 | }
289 | }];
290 | }
291 |
292 | - (void)presentOtherVCWhenLastAlertDismissed {
293 | for (int i = 1; i<4; i++) {
294 | JCAlertController *alert = [JCAlertController alertWithTitle:[NSString stringWithFormat:@"alert%i", i] message:nil];
295 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
296 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
297 | }
298 | JCAlertController *alert = [JCAlertController alertWithTitle:@"present a nav in completion" message:nil];
299 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
300 | __weak typeof(self) weakSelf = self;
301 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:^(void){
302 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[NormalVCForPresentation new]];
303 | [weakSelf presentViewController:nav animated:YES completion:nil];
304 | }];
305 | }
306 |
307 | #pragma mark -
308 |
309 | - (void)customView {
310 | // without title and button
311 |
312 | // setup a contentView
313 | CGFloat width = [JCAlertStyle shareStyle].alertView.width;
314 | UIImageView *contentView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, width, width * 0.623)];
315 | contentView.image = [UIImage imageNamed:@"alert"];
316 | contentView.userInteractionEnabled = YES;
317 |
318 | // pass the contentView
319 | JCAlertController *alert = [JCAlertController alertWithTitle:nil contentView:contentView];
320 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
321 |
322 | // avoid retain circle
323 | __weak JCAlertController *weakAlert = alert;
324 |
325 | // add gesture to dismiss alert
326 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:[self selectorBlock:^(id weakSelf, id arg) {
327 | [weakAlert dismissViewControllerAnimated:YES completion:nil];
328 | }]];
329 | [contentView addGestureRecognizer:tap];
330 | }
331 |
332 | - (void)customViewAndHandleKeyboard {
333 | // without title
334 |
335 | CGFloat width = [JCAlertStyle shareStyle].alertView.width;
336 |
337 | // setup contentView with a textField inside
338 | UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, width - 20, 26)];
339 | textField.backgroundColor = [UIColor colorWithRed:241/255.0 green:241/255.0 blue:241/255.0 alpha:1.0];
340 | textField.layer.cornerRadius = 2;
341 | textField.clipsToBounds = YES;
342 | textField.center = CGPointMake(width / 2, 30);
343 | textField.secureTextEntry = YES;
344 | textField.textAlignment = NSTextAlignmentCenter;
345 | [textField becomeFirstResponder];
346 |
347 | UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 60)];
348 | contentView.backgroundColor = [UIColor whiteColor];
349 | [contentView addSubview:textField];
350 |
351 | // pass the contentView
352 | JCAlertController *alert = [JCAlertController alertWithTitle:@"Enter password please" contentView:contentView];
353 | [alert addButtonWithTitle:@"Confirm" type:JCButtonTypeNormal clicked:^{
354 | NSLog(@"You inputed:%@", textField.text);
355 | [textField resignFirstResponder];
356 | }];
357 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:^{
358 | [textField becomeFirstResponder];
359 | } dismissCompletion:nil];
360 |
361 | // avoid retain circle
362 | __weak typeof(JCAlertController *) weakalert = alert;
363 |
364 | // callback after keyboard shows
365 | [alert monitorKeyboardShowed:^(CGFloat alertHeight, CGFloat keyboardHeight) {
366 | [weakalert moveAlertViewToCenterY:alertHeight / 2 + 120 animated:YES];
367 | }];
368 | // callback after keyboard hides
369 | [alert monitorKeyboardHided:^{
370 | [weakalert moveAlertViewToScreenCenterAnimated:YES];
371 | }];
372 | }
373 |
374 | - (void)customViewAndAttributedString {
375 | // without title
376 | CGFloat width = [JCAlertStyle shareStyle].alertView.width;
377 | UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, width, 100)];
378 | label.backgroundColor = [UIColor whiteColor];
379 | label.textAlignment = NSTextAlignmentCenter;
380 | NSMutableAttributedString *AttributedStr = [[NSMutableAttributedString alloc]initWithString:@"Hello"];
381 | [AttributedStr addAttribute:NSForegroundColorAttributeName value:[UIColor orangeColor] range:NSMakeRange(0, 2)];
382 | [AttributedStr addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(2, 3)];
383 | label.attributedText = AttributedStr;
384 |
385 | JCAlertController *alert = [JCAlertController alertWithTitle:nil contentView:label];
386 | [alert addButtonWithTitle:@"OK" type:JCButtonTypeNormal clicked:nil];
387 | [JCPresentController presentViewControllerLIFO:alert presentCompletion:nil dismissCompletion:nil];
388 | }
389 |
390 | @end
391 |
--------------------------------------------------------------------------------
/JCAlertController/JCAlertController/AlertView/JCAlertView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCAlertController.m
3 | // JCAlertController
4 | //
5 | // Created by HJaycee on 2017/4/1.
6 | // Copyright © 2017年 HJaycee. All rights reserved.
7 | //
8 |
9 | #import "JCAlertView.h"
10 | #import "NSAttributedString+JCCalculateSize.h"
11 | #import "JCAlertButtonItem.h"
12 | #import "UIImage+JCColor2Image.h"
13 |
14 | @interface JCAlertView ()
15 |
16 | @property (nonatomic) CGFloat buttonHeight;
17 | @property (nonatomic, weak) UIButton *leftBtn;
18 | @property (nonatomic, weak) UIButton *rightBtn;
19 |
20 | @end
21 |
22 | @implementation JCAlertView
23 |
24 | - (void)willMoveToSuperview:(UIView *)newSuperview {
25 | [super willMoveToSuperview:newSuperview];
26 |
27 | self.backgroundColor = [UIColor clearColor];
28 |
29 | JCAlertStyle *style = self.style;
30 |
31 | UIEdgeInsets titleInsets = style.title.insets;
32 | if (self.title && self.title.length > 0 && (!self.message || self.message.length == 0) && !self.contentView) {
33 | titleInsets = style.title.onlyTitleInsets;
34 | }
35 |
36 | UIEdgeInsets messageInsets = style.content.insets;
37 | if (self.message && self.message.length > 0 && (!self.title || self.title.length == 0)) {
38 | messageInsets = style.content.onlyMessageInsets;
39 | }
40 |
41 | // button height
42 | self.buttonHeight = self.buttonItems.count > 0 ? style.buttonNormal.height : 0;
43 |
44 | // cal title height
45 | CGFloat titleHeight = 0;
46 | CGSize titleSize = CGSizeZero;
47 | if (self.title.length > 0) {
48 | NSAttributedString *titleStr = [[NSAttributedString alloc] initWithString:self.title attributes:@{NSFontAttributeName:style.title.font}];
49 | titleSize = [titleStr sizeWithMaxWidth:style.alertView.width - titleInsets.left - titleInsets.right];
50 | titleHeight = titleSize.height + titleInsets.top + titleInsets.bottom;
51 | }
52 |
53 | // title one line height
54 | NSAttributedString *titleChar = [[NSAttributedString alloc] initWithString:@" " attributes:@{NSFontAttributeName:style.title.font}];
55 | CGFloat titleCharHeight = [titleChar sizeWithMaxWidth:self.frame.size.width].height;
56 |
57 | // if has contentView
58 | if (self.contentView) {
59 | CGFloat totalHeight = titleHeight + self.contentView.frame.size.height + self.buttonHeight;
60 | CGFloat alertHeight = totalHeight > self.style.alertView.maxHeight ? self.style.alertView.maxHeight : totalHeight;
61 | self.frame = CGRectMake(0, 0, style.alertView.width, alertHeight);
62 |
63 | if (titleHeight > 0) {
64 | if (titleSize.height <= titleCharHeight) { // show in center
65 | UILabel *titleView = [[UILabel alloc] initWithFrame:CGRectIntegral(CGRectMake(titleInsets.left, titleInsets.top, style.alertView.width - titleInsets.left - titleInsets.right, titleCharHeight))];
66 | titleView.text = self.title;
67 | titleView.font = style.title.font;
68 | titleView.textColor = style.title.textColor;
69 | titleView.backgroundColor = [UIColor clearColor];
70 | titleView.textAlignment = style.title.textAlignment;
71 |
72 | UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, style.alertView.width, titleHeight)];
73 | bgView.backgroundColor = style.title.backgroundColor;
74 | [bgView addSubview:titleView];
75 |
76 | [self addSubview:bgView];
77 | } else { // break line use textview
78 | UITextView *titleView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, style.alertView.width, titleHeight)];
79 | titleView.textContainerInset = titleInsets;
80 | titleView.text = self.title;
81 | titleView.font = style.title.font;
82 | titleView.textColor = style.title.textColor;
83 | titleView.backgroundColor = style.title.backgroundColor;
84 | titleView.editable = NO;
85 | titleView.selectable = NO;
86 | titleView.scrollEnabled = YES;
87 | titleView.textAlignment = style.title.textAlignment;
88 | // because contentsize.height < frame.size.height
89 | if (titleView.frame.size.height < titleView.contentSize.height) {
90 | CGRect newF = titleView.frame;
91 | newF.size.height = titleView.contentSize.height;
92 | titleView.frame = newF;
93 | }
94 | titleView.scrollEnabled = NO;
95 | [self addSubview:titleView];
96 | }
97 | }
98 |
99 | CGRect contentFrame = self.contentView.frame;
100 | contentFrame.origin.y = titleHeight;
101 |
102 | CGFloat maxContentHeight = self.style.alertView.maxHeight - titleHeight - self.buttonHeight;
103 | if (CGRectGetHeight(contentFrame) > maxContentHeight) {
104 | CGRect scrollFrame = contentFrame;
105 | scrollFrame.size.height = maxContentHeight;
106 | UIScrollView *contentScrollView = [[UIScrollView alloc] initWithFrame:scrollFrame];
107 | contentScrollView.contentSize = contentFrame.size;
108 | contentScrollView.backgroundColor = self.style.alertView.backgroundColor;
109 | [contentScrollView addSubview:self.contentView];
110 | [self addSubview:contentScrollView];
111 | } else {
112 | self.contentView.frame = contentFrame;
113 | [self addSubview:self.contentView];
114 | }
115 |
116 | [self setupButton];
117 |
118 | if (titleHeight + self.buttonHeight > 0) {
119 | self.layer.cornerRadius = style.alertView.cornerRadius;
120 | if (self.layer.cornerRadius > 0) {
121 | self.clipsToBounds = YES;
122 | }
123 | }
124 |
125 | self.center = newSuperview.center;
126 | return;
127 | }
128 |
129 | // title height than max
130 | CGFloat maxUnstretchTitleHeight = style.alertView.maxHeight - self.buttonHeight;
131 |
132 | // cal content height
133 | CGFloat contentHeight = 0;
134 | CGSize contentSize = CGSizeZero;
135 | if (self.message.length > 0) {
136 | NSAttributedString *contentStr = [[NSAttributedString alloc] initWithString:self.message attributes:@{NSFontAttributeName:style.content.font}];
137 | contentSize = [contentStr sizeWithMaxWidth:style.alertView.width - messageInsets.left - messageInsets.right];
138 | contentHeight = contentSize.height + messageInsets.top + messageInsets.bottom;
139 | }
140 |
141 | // content one line height
142 | NSAttributedString *contentChar = [[NSAttributedString alloc] initWithString:@" " attributes:@{NSFontAttributeName:style.content.font}];
143 | CGFloat contentCharHeight = [contentChar sizeWithMaxWidth:self.frame.size.width].height;
144 |
145 | // give alert frame
146 | if (titleHeight + contentHeight + self.buttonHeight > style.alertView.maxHeight) {
147 | self.frame = CGRectMake(0, 0, style.alertView.width, style.alertView.maxHeight);
148 | } else {
149 | self.frame = CGRectMake(0, 0, style.alertView.width, titleHeight + contentHeight + self.buttonHeight);
150 | }
151 |
152 | // layout
153 | if (titleHeight + contentHeight + self.buttonHeight < style.alertView.maxHeight) { // in max height
154 | if (titleHeight > 0) {
155 | if (titleSize.height <= titleCharHeight) { // show in center
156 | UILabel *titleView = [[UILabel alloc] initWithFrame:CGRectIntegral(CGRectMake(titleInsets.left, titleInsets.top, style.alertView.width - titleInsets.left - titleInsets.right, titleCharHeight))];
157 | titleView.text = self.title;
158 | titleView.font = style.title.font;
159 | titleView.textColor = style.title.textColor;
160 | titleView.backgroundColor = [UIColor clearColor];
161 | titleView.textAlignment = style.title.textAlignment;
162 |
163 | UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, style.alertView.width, titleHeight)];
164 | bgView.backgroundColor = style.title.backgroundColor;
165 | [bgView addSubview:titleView];
166 |
167 | [self addSubview:bgView];
168 | } else {
169 | UITextView *titleView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, style.alertView.width, titleHeight)];
170 | titleView.text = self.title;
171 | titleView.font = style.title.font;
172 | titleView.textContainerInset = titleInsets;
173 | titleView.textColor = style.title.textColor;
174 | titleView.backgroundColor = style.title.backgroundColor;
175 | titleView.editable = NO;
176 | titleView.selectable = NO;
177 | titleView.scrollEnabled = YES;
178 | titleView.textAlignment = style.title.textAlignment;
179 | // because contentsize.height < frame.size.height
180 | if (titleView.frame.size.height < titleView.contentSize.height) {
181 | CGRect newF = titleView.frame;
182 | newF.size.height = titleView.contentSize.height;
183 | titleView.frame = newF;
184 | }
185 | titleView.scrollEnabled = NO;
186 | [self addSubview:titleView];
187 | }
188 | }
189 |
190 | if (contentHeight > 0) {
191 | if (contentSize.height <= contentCharHeight) {
192 | UILabel *contentView = [[UILabel alloc] initWithFrame:CGRectMake(messageInsets.left, messageInsets.top, style.alertView.width - messageInsets.left - messageInsets.right, contentCharHeight)];
193 | contentView.text = self.message;
194 | contentView.font = style.content.font;
195 | contentView.textColor = style.content.textColor;
196 | contentView.backgroundColor = [UIColor clearColor];
197 | contentView.textAlignment = style.content.textAlignment;
198 |
199 | UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, titleHeight, style.alertView.width, contentHeight)];
200 | bgView.backgroundColor = style.content.backgroundColor;
201 | [bgView addSubview:contentView];
202 |
203 | [self addSubview:bgView];
204 | } else {
205 | UITextView *contentView = [[UITextView alloc] initWithFrame:CGRectMake(0, titleHeight, style.alertView.width, contentHeight)];
206 | contentView.textContainerInset = messageInsets;
207 | contentView.text = self.message;
208 | contentView.font = style.content.font;
209 | contentView.textColor = style.content.textColor;
210 | contentView.backgroundColor = style.content.backgroundColor;
211 | contentView.editable = NO;
212 | contentView.selectable = NO;
213 | contentView.scrollEnabled = YES;
214 | contentView.textAlignment = style.content.textAlignment;
215 | // because contentsize.height < frame.size.height
216 | if (contentView.frame.size.height < contentView.contentSize.height) {
217 | CGRect newF = contentView.frame;
218 | newF.size.height = contentView.contentSize.height;
219 | contentView.frame = newF;
220 | }
221 | contentView.scrollEnabled = NO;
222 | [self addSubview:contentView];
223 | }
224 | }
225 |
226 | [self setupButton];
227 | } else {
228 | if (titleHeight > maxUnstretchTitleHeight) { // title scrollable
229 | UITextView *titleView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, style.alertView.width, maxUnstretchTitleHeight)];
230 | titleView.textContainerInset = titleInsets;
231 | titleView.text = self.title;
232 | titleView.font = style.title.font;
233 | titleView.textColor = style.title.textColor;
234 | titleView.backgroundColor = style.title.backgroundColor;
235 | titleView.editable = NO;
236 | titleView.selectable = NO;
237 | titleView.textAlignment = style.title.textAlignment;
238 | [self addSubview:titleView];
239 |
240 | [self setupButton];
241 | } else { // content scrollable
242 | if (titleHeight > 0) {
243 | if (titleSize.height <= titleCharHeight) { // show in center
244 | UILabel *titleView = [[UILabel alloc] initWithFrame:CGRectIntegral(CGRectMake(titleInsets.left, titleInsets.top, style.alertView.width - titleInsets.left - titleInsets.right, titleCharHeight))];
245 | titleView.text = self.title;
246 | titleView.font = style.title.font;
247 | titleView.textColor = style.title.textColor;
248 | titleView.backgroundColor = [UIColor clearColor];
249 | titleView.textAlignment = style.title.textAlignment;
250 |
251 | UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, style.alertView.width, titleHeight)];
252 | bgView.backgroundColor = style.title.backgroundColor;
253 | [bgView addSubview:titleView];
254 |
255 | [self addSubview:bgView];
256 | } else {
257 | UITextView *titleView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, style.alertView.width, titleHeight)];
258 | titleView.textContainerInset = titleInsets;
259 | titleView.text = self.title;
260 | titleView.font = style.title.font;
261 | titleView.textColor = style.title.textColor;
262 | titleView.backgroundColor = style.title.backgroundColor;
263 | titleView.editable = NO;
264 | titleView.selectable = NO;
265 | titleView.scrollEnabled = YES;
266 | titleView.textAlignment = style.title.textAlignment;
267 | // because contentsize.height < frame.size.height
268 | if (titleView.frame.size.height < titleView.contentSize.height) {
269 | CGRect newF = titleView.frame;
270 | newF.size.height = titleView.contentSize.height;
271 | titleView.frame = newF;
272 | }
273 | titleView.scrollEnabled = NO;
274 | [self addSubview:titleView];
275 | }
276 | }
277 |
278 | UITextView *contentView = [[UITextView alloc] initWithFrame:CGRectMake(0, titleHeight, style.alertView.width, maxUnstretchTitleHeight - titleHeight)];
279 | contentView.textContainerInset = messageInsets;
280 | contentView.text = self.message;
281 | contentView.font = style.content.font;
282 | contentView.textColor = style.content.textColor;
283 | contentView.backgroundColor = style.content.backgroundColor;
284 | contentView.editable = NO;
285 | contentView.selectable = NO;
286 | contentView.scrollEnabled = YES;
287 | contentView.textAlignment = style.content.textAlignment;
288 | [self addSubview:contentView];
289 |
290 | [self setupButton];
291 | }
292 | }
293 |
294 | self.layer.cornerRadius = style.alertView.cornerRadius;
295 | if (self.layer.cornerRadius > 0) {
296 | self.clipsToBounds = YES;
297 | }
298 |
299 | self.center = newSuperview.center;
300 | }
301 |
302 | - (void)setupButton {
303 | if (self.buttonHeight > 0) {
304 | JCAlertStyle *style = self.style;;
305 | if (self.buttonItems.count > 1) {
306 | JCAlertButtonItem *leftItem = self.buttonItems[0];
307 | JCAlertStyleButton *styleButton = style.buttonNormal;
308 | if (leftItem.type == JCButtonTypeCancel) {
309 | styleButton = style.buttonCancel;
310 | } else if (leftItem.type == JCButtonTypeWarning) {
311 | styleButton = style.buttonWarning;
312 | }
313 | CGFloat alertHeight = (self.frame.size.height > self.style.alertView.maxHeight) ? self.style.alertView.maxHeight : self.frame.size.height;
314 | UIButton *leftBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, alertHeight - self.buttonHeight, style.alertView.width / 2, self.buttonHeight)];
315 | leftBtn.userInteractionEnabled = NO;
316 | [leftBtn setTitle:leftItem.title forState:UIControlStateNormal];
317 | [leftBtn setTitleColor:styleButton.textColor forState:UIControlStateNormal];
318 | [leftBtn setTitleColor:styleButton.highlightTextColor forState:UIControlStateHighlighted];
319 | [leftBtn setBackgroundImage:[UIImage createImageWithColor:styleButton.backgroundColor] forState:UIControlStateNormal];
320 | [leftBtn setBackgroundImage:[UIImage createImageWithColor:styleButton.highlightBackgroundColor] forState:UIControlStateHighlighted];
321 | leftBtn.titleLabel.font = styleButton.font;
322 | [self addSubview:leftBtn];
323 | self.leftBtn = leftBtn;
324 |
325 | JCAlertButtonItem *rightItem = self.buttonItems[1];
326 | styleButton = style.buttonNormal;
327 | if (rightItem.type == JCButtonTypeCancel) {
328 | styleButton = style.buttonCancel;
329 | } else if (rightItem.type == JCButtonTypeWarning) {
330 | styleButton = style.buttonWarning;
331 | }
332 | UIButton *rightBtn = [[UIButton alloc] initWithFrame:CGRectMake(style.alertView.width / 2, alertHeight - self.buttonHeight, style.alertView.width / 2, self.buttonHeight)];
333 | rightBtn.userInteractionEnabled = NO;
334 | [rightBtn setTitle:rightItem.title forState:UIControlStateNormal];
335 | [rightBtn setTitleColor:styleButton.textColor forState:UIControlStateNormal];
336 | [rightBtn setTitleColor:styleButton.highlightTextColor forState:UIControlStateHighlighted];
337 | [rightBtn setBackgroundImage:[UIImage createImageWithColor:styleButton.backgroundColor] forState:UIControlStateNormal];
338 | [rightBtn setBackgroundImage:[UIImage createImageWithColor:styleButton.highlightBackgroundColor] forState:UIControlStateHighlighted];
339 | rightBtn.titleLabel.font = styleButton.font;
340 | [self addSubview:rightBtn];
341 | self.rightBtn = rightBtn;
342 |
343 | UIView *separator = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - self.buttonHeight, style.alertView.width, style.separator.width)];
344 | separator.backgroundColor = style.separator.color;
345 | [self addSubview:separator];
346 |
347 | UIView *separator1 = [[UIView alloc] initWithFrame:CGRectMake(style.alertView.width / 2, self.frame.size.height - self.buttonHeight, style.separator.width, styleButton.height)];
348 | separator1.backgroundColor = style.separator.color;
349 | [self addSubview:separator1];
350 | } else {
351 | JCAlertButtonItem *item = self.buttonItems[0];
352 | JCAlertStyleButton *styleButton = style.buttonNormal;
353 | if (item.type == JCButtonTypeCancel) {
354 | styleButton = style.buttonCancel;
355 | } else if (item.type == JCButtonTypeWarning) {
356 | styleButton = style.buttonWarning;
357 | }
358 | CGFloat alertHeight = (self.frame.size.height > self.style.alertView.maxHeight) ? self.style.alertView.maxHeight : self.frame.size.height;
359 | UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, alertHeight - self.buttonHeight, style.alertView.width, self.buttonHeight)];
360 | btn.userInteractionEnabled = NO;
361 | [btn setTitle:item.title forState:UIControlStateNormal];
362 | [btn setTitleColor:styleButton.textColor forState:UIControlStateNormal];
363 | [btn setTitleColor:styleButton.highlightTextColor forState:UIControlStateHighlighted];
364 | [btn setBackgroundImage:[UIImage createImageWithColor:styleButton.backgroundColor] forState:UIControlStateNormal];
365 | [btn setBackgroundImage:[UIImage createImageWithColor:styleButton.highlightBackgroundColor] forState:UIControlStateHighlighted];
366 | btn.titleLabel.font = styleButton.font;
367 | [self addSubview:btn];
368 | self.leftBtn = btn;
369 |
370 | UIView *separator = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - self.buttonHeight, style.alertView.width, style.separator.width)];
371 | separator.backgroundColor = style.separator.color;
372 | [self addSubview:separator];
373 | }
374 | }
375 | }
376 |
377 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
378 | UITouch *touch = [[touches allObjects] lastObject];
379 | CGPoint originPoint = [touch locationInView:self];
380 |
381 | [self handleTouch:originPoint insideLeft:^{
382 | self.leftBtn.highlighted = YES;
383 | self.rightBtn.highlighted = NO;
384 | } insideRight:^{
385 | self.rightBtn.highlighted = YES;
386 | self.leftBtn.highlighted = NO;
387 | } neither:^{
388 | self.rightBtn.highlighted = NO;
389 | self.leftBtn.highlighted = NO;
390 | }];
391 | }
392 |
393 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
394 | UITouch *touch = [[touches allObjects] lastObject];
395 | CGPoint originPoint = [touch locationInView:self];
396 |
397 | [self handleTouch:originPoint insideLeft:^{
398 | [self leftBtnClick];
399 | } insideRight:^{
400 | [self rightBtnClick];
401 | } neither:nil];
402 | }
403 |
404 | - (void)handleTouch:(CGPoint)originPoint insideLeft:(void(^)(void))insideLeft insideRight:(void(^)(void))insideRight neither:(void(^)(void))neither {
405 | CGPoint point = [self convertPoint:originPoint toView:self.leftBtn];
406 | if (point.x > 0 && point.y > 0 && point.x <= self.leftBtn.frame.size.width && point.y <= self.leftBtn.frame.size.height) {
407 | insideLeft();
408 | } else {
409 | point = [self convertPoint:originPoint toView:self.rightBtn];
410 | if (point.x > 0 && point.y > 0 && point.x <= self.rightBtn.frame.size.width && point.y <= self.rightBtn.frame.size.height) {
411 | insideRight();
412 | } else {
413 | if (neither) {
414 | neither();
415 | }
416 | }
417 | }
418 | }
419 |
420 | - (void)leftBtnClick {
421 | JCAlertButtonItem *item = self.buttonItems[0];
422 | [self notifyDelegateWithClicked:item.clicked];
423 | }
424 |
425 | - (void)rightBtnClick {
426 | JCAlertButtonItem *item = self.buttonItems[1];
427 | [self notifyDelegateWithClicked:item.clicked];
428 | }
429 |
430 | - (void)notifyDelegateWithClicked:(void(^)(void))clicked {
431 | if ([self.delegate respondsToSelector:@selector(alertButtonClicked:)]) {
432 | [self.delegate alertButtonClicked:clicked];
433 | }
434 | }
435 |
436 | @end
437 |
--------------------------------------------------------------------------------
/JCAlertController.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 0306AD681ECC6032008705B4 /* NSObject+BlockSEL.m in Sources */ = {isa = PBXBuildFile; fileRef = 0306AD671ECC6032008705B4 /* NSObject+BlockSEL.m */; };
11 | 030C7A971E9CF3C200B822C1 /* JCAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 030C7A711E9CF3C200B822C1 /* JCAlertView.m */; };
12 | 030C7A981E9CF3C200B822C1 /* JCAlertButtonItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 030C7A741E9CF3C200B822C1 /* JCAlertButtonItem.m */; };
13 | 030C7A991E9CF3C200B822C1 /* NSAttributedString+JCCalculateSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 030C7A771E9CF3C200B822C1 /* NSAttributedString+JCCalculateSize.m */; };
14 | 030C7A9A1E9CF3C200B822C1 /* UIColor+JCHightlightedColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 030C7A791E9CF3C200B822C1 /* UIColor+JCHightlightedColor.m */; };
15 | 030C7A9B1E9CF3C200B822C1 /* UIImage+JCColor2Image.m in Sources */ = {isa = PBXBuildFile; fileRef = 030C7A7B1E9CF3C200B822C1 /* UIImage+JCColor2Image.m */; };
16 | 030C7A9D1E9CF3C200B822C1 /* UIWindow+JCBlur.m in Sources */ = {isa = PBXBuildFile; fileRef = 030C7A7F1E9CF3C200B822C1 /* UIWindow+JCBlur.m */; };
17 | 030C7A9E1E9CF3C200B822C1 /* JCAlertController.m in Sources */ = {isa = PBXBuildFile; fileRef = 030C7A811E9CF3C200B822C1 /* JCAlertController.m */; };
18 | 030C7A9F1E9CF3C200B822C1 /* JCAlertStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 030C7A841E9CF3C200B822C1 /* JCAlertStyle.m */; };
19 | 034A70C520A4195F007A61D6 /* JCPresentController.m in Sources */ = {isa = PBXBuildFile; fileRef = 034A70C220A4195F007A61D6 /* JCPresentController.m */; };
20 | 034A70C620A4195F007A61D6 /* UIViewController+JCPresentQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 034A70C320A4195F007A61D6 /* UIViewController+JCPresentQueue.m */; };
21 | 03A99E141E98066B009BC03D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 03A99E131E98066B009BC03D /* main.m */; };
22 | 03A99E171E98066B009BC03D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 03A99E161E98066B009BC03D /* AppDelegate.m */; };
23 | 03A99E1A1E98066B009BC03D /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 03A99E191E98066B009BC03D /* ViewController.m */; };
24 | 03A99E1F1E98066B009BC03D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 03A99E1E1E98066B009BC03D /* Assets.xcassets */; };
25 | 03A99E221E98066B009BC03D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 03A99E201E98066B009BC03D /* LaunchScreen.storyboard */; };
26 | 03A99E2D1E98066B009BC03D /* JCAlertControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 03A99E2C1E98066B009BC03D /* JCAlertControllerTests.m */; };
27 | 03A99E381E98066B009BC03D /* JCAlertControllerUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 03A99E371E98066B009BC03D /* JCAlertControllerUITests.m */; };
28 | F872B58C206CCFAF003456A2 /* RootVC.m in Sources */ = {isa = PBXBuildFile; fileRef = F872B58B206CCFAF003456A2 /* RootVC.m */; };
29 | F872B595206E3F92003456A2 /* NormalVCForPresentation.m in Sources */ = {isa = PBXBuildFile; fileRef = F872B594206E3F92003456A2 /* NormalVCForPresentation.m */; };
30 | /* End PBXBuildFile section */
31 |
32 | /* Begin PBXContainerItemProxy section */
33 | 03A99E291E98066B009BC03D /* PBXContainerItemProxy */ = {
34 | isa = PBXContainerItemProxy;
35 | containerPortal = 03A99E071E98066B009BC03D /* Project object */;
36 | proxyType = 1;
37 | remoteGlobalIDString = 03A99E0E1E98066B009BC03D;
38 | remoteInfo = JCAlertController;
39 | };
40 | 03A99E341E98066B009BC03D /* PBXContainerItemProxy */ = {
41 | isa = PBXContainerItemProxy;
42 | containerPortal = 03A99E071E98066B009BC03D /* Project object */;
43 | proxyType = 1;
44 | remoteGlobalIDString = 03A99E0E1E98066B009BC03D;
45 | remoteInfo = JCAlertController;
46 | };
47 | /* End PBXContainerItemProxy section */
48 |
49 | /* Begin PBXFileReference section */
50 | 0306AD661ECC6032008705B4 /* NSObject+BlockSEL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+BlockSEL.h"; sourceTree = ""; };
51 | 0306AD671ECC6032008705B4 /* NSObject+BlockSEL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+BlockSEL.m"; sourceTree = ""; };
52 | 030C7A701E9CF3C200B822C1 /* JCAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JCAlertView.h; sourceTree = ""; };
53 | 030C7A711E9CF3C200B822C1 /* JCAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JCAlertView.m; sourceTree = ""; };
54 | 030C7A731E9CF3C200B822C1 /* JCAlertButtonItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JCAlertButtonItem.h; sourceTree = ""; };
55 | 030C7A741E9CF3C200B822C1 /* JCAlertButtonItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JCAlertButtonItem.m; sourceTree = ""; };
56 | 030C7A761E9CF3C200B822C1 /* NSAttributedString+JCCalculateSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSAttributedString+JCCalculateSize.h"; sourceTree = ""; };
57 | 030C7A771E9CF3C200B822C1 /* NSAttributedString+JCCalculateSize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSAttributedString+JCCalculateSize.m"; sourceTree = ""; };
58 | 030C7A781E9CF3C200B822C1 /* UIColor+JCHightlightedColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+JCHightlightedColor.h"; sourceTree = ""; };
59 | 030C7A791E9CF3C200B822C1 /* UIColor+JCHightlightedColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+JCHightlightedColor.m"; sourceTree = ""; };
60 | 030C7A7A1E9CF3C200B822C1 /* UIImage+JCColor2Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+JCColor2Image.h"; sourceTree = ""; };
61 | 030C7A7B1E9CF3C200B822C1 /* UIImage+JCColor2Image.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+JCColor2Image.m"; sourceTree = ""; };
62 | 030C7A7E1E9CF3C200B822C1 /* UIWindow+JCBlur.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIWindow+JCBlur.h"; sourceTree = ""; };
63 | 030C7A7F1E9CF3C200B822C1 /* UIWindow+JCBlur.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIWindow+JCBlur.m"; sourceTree = ""; };
64 | 030C7A801E9CF3C200B822C1 /* JCAlertController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JCAlertController.h; sourceTree = ""; };
65 | 030C7A811E9CF3C200B822C1 /* JCAlertController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JCAlertController.m; sourceTree = ""; };
66 | 030C7A831E9CF3C200B822C1 /* JCAlertStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JCAlertStyle.h; sourceTree = ""; };
67 | 030C7A841E9CF3C200B822C1 /* JCAlertStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JCAlertStyle.m; sourceTree = ""; };
68 | 034A70C120A4195F007A61D6 /* UIViewController+JCPresentQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+JCPresentQueue.h"; sourceTree = ""; };
69 | 034A70C220A4195F007A61D6 /* JCPresentController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JCPresentController.m; sourceTree = ""; };
70 | 034A70C320A4195F007A61D6 /* UIViewController+JCPresentQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+JCPresentQueue.m"; sourceTree = ""; };
71 | 034A70C420A4195F007A61D6 /* JCPresentController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JCPresentController.h; sourceTree = ""; };
72 | 03A99E0F1E98066B009BC03D /* JCAlertController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JCAlertController.app; sourceTree = BUILT_PRODUCTS_DIR; };
73 | 03A99E131E98066B009BC03D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
74 | 03A99E151E98066B009BC03D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
75 | 03A99E161E98066B009BC03D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
76 | 03A99E181E98066B009BC03D /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
77 | 03A99E191E98066B009BC03D /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
78 | 03A99E1E1E98066B009BC03D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
79 | 03A99E211E98066B009BC03D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
80 | 03A99E231E98066B009BC03D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
81 | 03A99E281E98066B009BC03D /* JCAlertControllerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JCAlertControllerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
82 | 03A99E2C1E98066B009BC03D /* JCAlertControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JCAlertControllerTests.m; sourceTree = ""; };
83 | 03A99E2E1E98066B009BC03D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
84 | 03A99E331E98066B009BC03D /* JCAlertControllerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JCAlertControllerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
85 | 03A99E371E98066B009BC03D /* JCAlertControllerUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JCAlertControllerUITests.m; sourceTree = ""; };
86 | 03A99E391E98066B009BC03D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
87 | F872B58A206CCFAF003456A2 /* RootVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RootVC.h; sourceTree = ""; };
88 | F872B58B206CCFAF003456A2 /* RootVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RootVC.m; sourceTree = ""; };
89 | F872B593206E3F92003456A2 /* NormalVCForPresentation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NormalVCForPresentation.h; sourceTree = ""; };
90 | F872B594206E3F92003456A2 /* NormalVCForPresentation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NormalVCForPresentation.m; sourceTree = ""; };
91 | /* End PBXFileReference section */
92 |
93 | /* Begin PBXFrameworksBuildPhase section */
94 | 03A99E0C1E98066B009BC03D /* Frameworks */ = {
95 | isa = PBXFrameworksBuildPhase;
96 | buildActionMask = 2147483647;
97 | files = (
98 | );
99 | runOnlyForDeploymentPostprocessing = 0;
100 | };
101 | 03A99E251E98066B009BC03D /* Frameworks */ = {
102 | isa = PBXFrameworksBuildPhase;
103 | buildActionMask = 2147483647;
104 | files = (
105 | );
106 | runOnlyForDeploymentPostprocessing = 0;
107 | };
108 | 03A99E301E98066B009BC03D /* Frameworks */ = {
109 | isa = PBXFrameworksBuildPhase;
110 | buildActionMask = 2147483647;
111 | files = (
112 | );
113 | runOnlyForDeploymentPostprocessing = 0;
114 | };
115 | /* End PBXFrameworksBuildPhase section */
116 |
117 | /* Begin PBXGroup section */
118 | 030C7A6E1E9CF3C200B822C1 /* JCAlertController */ = {
119 | isa = PBXGroup;
120 | children = (
121 | 030C7A801E9CF3C200B822C1 /* JCAlertController.h */,
122 | 030C7A811E9CF3C200B822C1 /* JCAlertController.m */,
123 | 034A70C020A4195F007A61D6 /* JCPresentQueue */,
124 | 030C7A6F1E9CF3C200B822C1 /* AlertView */,
125 | 030C7A721E9CF3C200B822C1 /* ButtonItem */,
126 | 030C7A751E9CF3C200B822C1 /* Category */,
127 | 030C7A821E9CF3C200B822C1 /* Style */,
128 | );
129 | path = JCAlertController;
130 | sourceTree = "";
131 | };
132 | 030C7A6F1E9CF3C200B822C1 /* AlertView */ = {
133 | isa = PBXGroup;
134 | children = (
135 | 030C7A701E9CF3C200B822C1 /* JCAlertView.h */,
136 | 030C7A711E9CF3C200B822C1 /* JCAlertView.m */,
137 | );
138 | path = AlertView;
139 | sourceTree = "";
140 | };
141 | 030C7A721E9CF3C200B822C1 /* ButtonItem */ = {
142 | isa = PBXGroup;
143 | children = (
144 | 030C7A731E9CF3C200B822C1 /* JCAlertButtonItem.h */,
145 | 030C7A741E9CF3C200B822C1 /* JCAlertButtonItem.m */,
146 | );
147 | path = ButtonItem;
148 | sourceTree = "";
149 | };
150 | 030C7A751E9CF3C200B822C1 /* Category */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 030C7A761E9CF3C200B822C1 /* NSAttributedString+JCCalculateSize.h */,
154 | 030C7A771E9CF3C200B822C1 /* NSAttributedString+JCCalculateSize.m */,
155 | 030C7A781E9CF3C200B822C1 /* UIColor+JCHightlightedColor.h */,
156 | 030C7A791E9CF3C200B822C1 /* UIColor+JCHightlightedColor.m */,
157 | 030C7A7A1E9CF3C200B822C1 /* UIImage+JCColor2Image.h */,
158 | 030C7A7B1E9CF3C200B822C1 /* UIImage+JCColor2Image.m */,
159 | 030C7A7E1E9CF3C200B822C1 /* UIWindow+JCBlur.h */,
160 | 030C7A7F1E9CF3C200B822C1 /* UIWindow+JCBlur.m */,
161 | );
162 | path = Category;
163 | sourceTree = "";
164 | };
165 | 030C7A821E9CF3C200B822C1 /* Style */ = {
166 | isa = PBXGroup;
167 | children = (
168 | 030C7A831E9CF3C200B822C1 /* JCAlertStyle.h */,
169 | 030C7A841E9CF3C200B822C1 /* JCAlertStyle.m */,
170 | );
171 | path = Style;
172 | sourceTree = "";
173 | };
174 | 034A70C020A4195F007A61D6 /* JCPresentQueue */ = {
175 | isa = PBXGroup;
176 | children = (
177 | 034A70C420A4195F007A61D6 /* JCPresentController.h */,
178 | 034A70C220A4195F007A61D6 /* JCPresentController.m */,
179 | 034A70C120A4195F007A61D6 /* UIViewController+JCPresentQueue.h */,
180 | 034A70C320A4195F007A61D6 /* UIViewController+JCPresentQueue.m */,
181 | );
182 | path = JCPresentQueue;
183 | sourceTree = "";
184 | };
185 | 03A99E061E98066B009BC03D = {
186 | isa = PBXGroup;
187 | children = (
188 | 03A99E111E98066B009BC03D /* JCAlertController */,
189 | 03A99E2B1E98066B009BC03D /* JCAlertControllerTests */,
190 | 03A99E361E98066B009BC03D /* JCAlertControllerUITests */,
191 | 03A99E101E98066B009BC03D /* Products */,
192 | );
193 | sourceTree = "";
194 | };
195 | 03A99E101E98066B009BC03D /* Products */ = {
196 | isa = PBXGroup;
197 | children = (
198 | 03A99E0F1E98066B009BC03D /* JCAlertController.app */,
199 | 03A99E281E98066B009BC03D /* JCAlertControllerTests.xctest */,
200 | 03A99E331E98066B009BC03D /* JCAlertControllerUITests.xctest */,
201 | );
202 | name = Products;
203 | sourceTree = "";
204 | };
205 | 03A99E111E98066B009BC03D /* JCAlertController */ = {
206 | isa = PBXGroup;
207 | children = (
208 | 030C7A6E1E9CF3C200B822C1 /* JCAlertController */,
209 | 03A99E151E98066B009BC03D /* AppDelegate.h */,
210 | 03A99E161E98066B009BC03D /* AppDelegate.m */,
211 | 0306AD661ECC6032008705B4 /* NSObject+BlockSEL.h */,
212 | 0306AD671ECC6032008705B4 /* NSObject+BlockSEL.m */,
213 | F872B58A206CCFAF003456A2 /* RootVC.h */,
214 | F872B58B206CCFAF003456A2 /* RootVC.m */,
215 | 03A99E181E98066B009BC03D /* ViewController.h */,
216 | 03A99E191E98066B009BC03D /* ViewController.m */,
217 | F872B593206E3F92003456A2 /* NormalVCForPresentation.h */,
218 | F872B594206E3F92003456A2 /* NormalVCForPresentation.m */,
219 | 03A99E1E1E98066B009BC03D /* Assets.xcassets */,
220 | 03A99E201E98066B009BC03D /* LaunchScreen.storyboard */,
221 | 03A99E231E98066B009BC03D /* Info.plist */,
222 | 03A99E121E98066B009BC03D /* Supporting Files */,
223 | );
224 | path = JCAlertController;
225 | sourceTree = "";
226 | };
227 | 03A99E121E98066B009BC03D /* Supporting Files */ = {
228 | isa = PBXGroup;
229 | children = (
230 | 03A99E131E98066B009BC03D /* main.m */,
231 | );
232 | name = "Supporting Files";
233 | sourceTree = "";
234 | };
235 | 03A99E2B1E98066B009BC03D /* JCAlertControllerTests */ = {
236 | isa = PBXGroup;
237 | children = (
238 | 03A99E2C1E98066B009BC03D /* JCAlertControllerTests.m */,
239 | 03A99E2E1E98066B009BC03D /* Info.plist */,
240 | );
241 | path = JCAlertControllerTests;
242 | sourceTree = "";
243 | };
244 | 03A99E361E98066B009BC03D /* JCAlertControllerUITests */ = {
245 | isa = PBXGroup;
246 | children = (
247 | 03A99E371E98066B009BC03D /* JCAlertControllerUITests.m */,
248 | 03A99E391E98066B009BC03D /* Info.plist */,
249 | );
250 | path = JCAlertControllerUITests;
251 | sourceTree = "";
252 | };
253 | /* End PBXGroup section */
254 |
255 | /* Begin PBXNativeTarget section */
256 | 03A99E0E1E98066B009BC03D /* JCAlertController */ = {
257 | isa = PBXNativeTarget;
258 | buildConfigurationList = 03A99E3C1E98066B009BC03D /* Build configuration list for PBXNativeTarget "JCAlertController" */;
259 | buildPhases = (
260 | 03A99E0B1E98066B009BC03D /* Sources */,
261 | 03A99E0C1E98066B009BC03D /* Frameworks */,
262 | 03A99E0D1E98066B009BC03D /* Resources */,
263 | );
264 | buildRules = (
265 | );
266 | dependencies = (
267 | );
268 | name = JCAlertController;
269 | productName = JCAlertController;
270 | productReference = 03A99E0F1E98066B009BC03D /* JCAlertController.app */;
271 | productType = "com.apple.product-type.application";
272 | };
273 | 03A99E271E98066B009BC03D /* JCAlertControllerTests */ = {
274 | isa = PBXNativeTarget;
275 | buildConfigurationList = 03A99E3F1E98066B009BC03D /* Build configuration list for PBXNativeTarget "JCAlertControllerTests" */;
276 | buildPhases = (
277 | 03A99E241E98066B009BC03D /* Sources */,
278 | 03A99E251E98066B009BC03D /* Frameworks */,
279 | 03A99E261E98066B009BC03D /* Resources */,
280 | );
281 | buildRules = (
282 | );
283 | dependencies = (
284 | 03A99E2A1E98066B009BC03D /* PBXTargetDependency */,
285 | );
286 | name = JCAlertControllerTests;
287 | productName = JCAlertControllerTests;
288 | productReference = 03A99E281E98066B009BC03D /* JCAlertControllerTests.xctest */;
289 | productType = "com.apple.product-type.bundle.unit-test";
290 | };
291 | 03A99E321E98066B009BC03D /* JCAlertControllerUITests */ = {
292 | isa = PBXNativeTarget;
293 | buildConfigurationList = 03A99E421E98066B009BC03D /* Build configuration list for PBXNativeTarget "JCAlertControllerUITests" */;
294 | buildPhases = (
295 | 03A99E2F1E98066B009BC03D /* Sources */,
296 | 03A99E301E98066B009BC03D /* Frameworks */,
297 | 03A99E311E98066B009BC03D /* Resources */,
298 | );
299 | buildRules = (
300 | );
301 | dependencies = (
302 | 03A99E351E98066B009BC03D /* PBXTargetDependency */,
303 | );
304 | name = JCAlertControllerUITests;
305 | productName = JCAlertControllerUITests;
306 | productReference = 03A99E331E98066B009BC03D /* JCAlertControllerUITests.xctest */;
307 | productType = "com.apple.product-type.bundle.ui-testing";
308 | };
309 | /* End PBXNativeTarget section */
310 |
311 | /* Begin PBXProject section */
312 | 03A99E071E98066B009BC03D /* Project object */ = {
313 | isa = PBXProject;
314 | attributes = {
315 | LastUpgradeCheck = 0820;
316 | ORGANIZATIONNAME = HJaycee;
317 | TargetAttributes = {
318 | 03A99E0E1E98066B009BC03D = {
319 | CreatedOnToolsVersion = 8.2.1;
320 | DevelopmentTeam = 7L64JRM966;
321 | ProvisioningStyle = Automatic;
322 | };
323 | 03A99E271E98066B009BC03D = {
324 | CreatedOnToolsVersion = 8.2.1;
325 | ProvisioningStyle = Automatic;
326 | TestTargetID = 03A99E0E1E98066B009BC03D;
327 | };
328 | 03A99E321E98066B009BC03D = {
329 | CreatedOnToolsVersion = 8.2.1;
330 | ProvisioningStyle = Automatic;
331 | TestTargetID = 03A99E0E1E98066B009BC03D;
332 | };
333 | };
334 | };
335 | buildConfigurationList = 03A99E0A1E98066B009BC03D /* Build configuration list for PBXProject "JCAlertController" */;
336 | compatibilityVersion = "Xcode 3.2";
337 | developmentRegion = English;
338 | hasScannedForEncodings = 0;
339 | knownRegions = (
340 | en,
341 | Base,
342 | );
343 | mainGroup = 03A99E061E98066B009BC03D;
344 | productRefGroup = 03A99E101E98066B009BC03D /* Products */;
345 | projectDirPath = "";
346 | projectRoot = "";
347 | targets = (
348 | 03A99E0E1E98066B009BC03D /* JCAlertController */,
349 | 03A99E271E98066B009BC03D /* JCAlertControllerTests */,
350 | 03A99E321E98066B009BC03D /* JCAlertControllerUITests */,
351 | );
352 | };
353 | /* End PBXProject section */
354 |
355 | /* Begin PBXResourcesBuildPhase section */
356 | 03A99E0D1E98066B009BC03D /* Resources */ = {
357 | isa = PBXResourcesBuildPhase;
358 | buildActionMask = 2147483647;
359 | files = (
360 | 03A99E221E98066B009BC03D /* LaunchScreen.storyboard in Resources */,
361 | 03A99E1F1E98066B009BC03D /* Assets.xcassets in Resources */,
362 | );
363 | runOnlyForDeploymentPostprocessing = 0;
364 | };
365 | 03A99E261E98066B009BC03D /* Resources */ = {
366 | isa = PBXResourcesBuildPhase;
367 | buildActionMask = 2147483647;
368 | files = (
369 | );
370 | runOnlyForDeploymentPostprocessing = 0;
371 | };
372 | 03A99E311E98066B009BC03D /* Resources */ = {
373 | isa = PBXResourcesBuildPhase;
374 | buildActionMask = 2147483647;
375 | files = (
376 | );
377 | runOnlyForDeploymentPostprocessing = 0;
378 | };
379 | /* End PBXResourcesBuildPhase section */
380 |
381 | /* Begin PBXSourcesBuildPhase section */
382 | 03A99E0B1E98066B009BC03D /* Sources */ = {
383 | isa = PBXSourcesBuildPhase;
384 | buildActionMask = 2147483647;
385 | files = (
386 | 030C7A971E9CF3C200B822C1 /* JCAlertView.m in Sources */,
387 | 030C7A9E1E9CF3C200B822C1 /* JCAlertController.m in Sources */,
388 | 03A99E1A1E98066B009BC03D /* ViewController.m in Sources */,
389 | 0306AD681ECC6032008705B4 /* NSObject+BlockSEL.m in Sources */,
390 | 030C7A9F1E9CF3C200B822C1 /* JCAlertStyle.m in Sources */,
391 | 034A70C620A4195F007A61D6 /* UIViewController+JCPresentQueue.m in Sources */,
392 | 030C7A991E9CF3C200B822C1 /* NSAttributedString+JCCalculateSize.m in Sources */,
393 | 030C7A981E9CF3C200B822C1 /* JCAlertButtonItem.m in Sources */,
394 | 03A99E171E98066B009BC03D /* AppDelegate.m in Sources */,
395 | 03A99E141E98066B009BC03D /* main.m in Sources */,
396 | F872B58C206CCFAF003456A2 /* RootVC.m in Sources */,
397 | 030C7A9A1E9CF3C200B822C1 /* UIColor+JCHightlightedColor.m in Sources */,
398 | 030C7A9B1E9CF3C200B822C1 /* UIImage+JCColor2Image.m in Sources */,
399 | 034A70C520A4195F007A61D6 /* JCPresentController.m in Sources */,
400 | F872B595206E3F92003456A2 /* NormalVCForPresentation.m in Sources */,
401 | 030C7A9D1E9CF3C200B822C1 /* UIWindow+JCBlur.m in Sources */,
402 | );
403 | runOnlyForDeploymentPostprocessing = 0;
404 | };
405 | 03A99E241E98066B009BC03D /* Sources */ = {
406 | isa = PBXSourcesBuildPhase;
407 | buildActionMask = 2147483647;
408 | files = (
409 | 03A99E2D1E98066B009BC03D /* JCAlertControllerTests.m in Sources */,
410 | );
411 | runOnlyForDeploymentPostprocessing = 0;
412 | };
413 | 03A99E2F1E98066B009BC03D /* Sources */ = {
414 | isa = PBXSourcesBuildPhase;
415 | buildActionMask = 2147483647;
416 | files = (
417 | 03A99E381E98066B009BC03D /* JCAlertControllerUITests.m in Sources */,
418 | );
419 | runOnlyForDeploymentPostprocessing = 0;
420 | };
421 | /* End PBXSourcesBuildPhase section */
422 |
423 | /* Begin PBXTargetDependency section */
424 | 03A99E2A1E98066B009BC03D /* PBXTargetDependency */ = {
425 | isa = PBXTargetDependency;
426 | target = 03A99E0E1E98066B009BC03D /* JCAlertController */;
427 | targetProxy = 03A99E291E98066B009BC03D /* PBXContainerItemProxy */;
428 | };
429 | 03A99E351E98066B009BC03D /* PBXTargetDependency */ = {
430 | isa = PBXTargetDependency;
431 | target = 03A99E0E1E98066B009BC03D /* JCAlertController */;
432 | targetProxy = 03A99E341E98066B009BC03D /* PBXContainerItemProxy */;
433 | };
434 | /* End PBXTargetDependency section */
435 |
436 | /* Begin PBXVariantGroup section */
437 | 03A99E201E98066B009BC03D /* LaunchScreen.storyboard */ = {
438 | isa = PBXVariantGroup;
439 | children = (
440 | 03A99E211E98066B009BC03D /* Base */,
441 | );
442 | name = LaunchScreen.storyboard;
443 | sourceTree = "";
444 | };
445 | /* End PBXVariantGroup section */
446 |
447 | /* Begin XCBuildConfiguration section */
448 | 03A99E3A1E98066B009BC03D /* Debug */ = {
449 | isa = XCBuildConfiguration;
450 | buildSettings = {
451 | ALWAYS_SEARCH_USER_PATHS = NO;
452 | CLANG_ANALYZER_NONNULL = YES;
453 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
454 | CLANG_CXX_LIBRARY = "libc++";
455 | CLANG_ENABLE_MODULES = YES;
456 | CLANG_ENABLE_OBJC_ARC = YES;
457 | CLANG_WARN_BOOL_CONVERSION = YES;
458 | CLANG_WARN_CONSTANT_CONVERSION = YES;
459 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
460 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
461 | CLANG_WARN_EMPTY_BODY = YES;
462 | CLANG_WARN_ENUM_CONVERSION = YES;
463 | CLANG_WARN_INFINITE_RECURSION = YES;
464 | CLANG_WARN_INT_CONVERSION = YES;
465 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
466 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
467 | CLANG_WARN_UNREACHABLE_CODE = YES;
468 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
469 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
470 | COPY_PHASE_STRIP = NO;
471 | DEBUG_INFORMATION_FORMAT = dwarf;
472 | ENABLE_STRICT_OBJC_MSGSEND = YES;
473 | ENABLE_TESTABILITY = YES;
474 | GCC_C_LANGUAGE_STANDARD = gnu99;
475 | GCC_DYNAMIC_NO_PIC = NO;
476 | GCC_NO_COMMON_BLOCKS = YES;
477 | GCC_OPTIMIZATION_LEVEL = 0;
478 | GCC_PREPROCESSOR_DEFINITIONS = (
479 | "DEBUG=1",
480 | "$(inherited)",
481 | );
482 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
483 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
484 | GCC_WARN_UNDECLARED_SELECTOR = YES;
485 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
486 | GCC_WARN_UNUSED_FUNCTION = YES;
487 | GCC_WARN_UNUSED_VARIABLE = YES;
488 | IPHONEOS_DEPLOYMENT_TARGET = 10.2;
489 | MTL_ENABLE_DEBUG_INFO = YES;
490 | ONLY_ACTIVE_ARCH = YES;
491 | SDKROOT = iphoneos;
492 | };
493 | name = Debug;
494 | };
495 | 03A99E3B1E98066B009BC03D /* Release */ = {
496 | isa = XCBuildConfiguration;
497 | buildSettings = {
498 | ALWAYS_SEARCH_USER_PATHS = NO;
499 | CLANG_ANALYZER_NONNULL = YES;
500 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
501 | CLANG_CXX_LIBRARY = "libc++";
502 | CLANG_ENABLE_MODULES = YES;
503 | CLANG_ENABLE_OBJC_ARC = YES;
504 | CLANG_WARN_BOOL_CONVERSION = YES;
505 | CLANG_WARN_CONSTANT_CONVERSION = YES;
506 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
507 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
508 | CLANG_WARN_EMPTY_BODY = YES;
509 | CLANG_WARN_ENUM_CONVERSION = YES;
510 | CLANG_WARN_INFINITE_RECURSION = YES;
511 | CLANG_WARN_INT_CONVERSION = YES;
512 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
513 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
514 | CLANG_WARN_UNREACHABLE_CODE = YES;
515 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
516 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
517 | COPY_PHASE_STRIP = NO;
518 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
519 | ENABLE_NS_ASSERTIONS = NO;
520 | ENABLE_STRICT_OBJC_MSGSEND = YES;
521 | GCC_C_LANGUAGE_STANDARD = gnu99;
522 | GCC_NO_COMMON_BLOCKS = YES;
523 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
524 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
525 | GCC_WARN_UNDECLARED_SELECTOR = YES;
526 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
527 | GCC_WARN_UNUSED_FUNCTION = YES;
528 | GCC_WARN_UNUSED_VARIABLE = YES;
529 | IPHONEOS_DEPLOYMENT_TARGET = 10.2;
530 | MTL_ENABLE_DEBUG_INFO = NO;
531 | SDKROOT = iphoneos;
532 | VALIDATE_PRODUCT = YES;
533 | };
534 | name = Release;
535 | };
536 | 03A99E3D1E98066B009BC03D /* Debug */ = {
537 | isa = XCBuildConfiguration;
538 | buildSettings = {
539 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
540 | DEVELOPMENT_TEAM = 7L64JRM966;
541 | INFOPLIST_FILE = JCAlertController/Info.plist;
542 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
543 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
544 | PRODUCT_BUNDLE_IDENTIFIER = com.HJaycee.JCAlertController;
545 | PRODUCT_NAME = "$(TARGET_NAME)";
546 | };
547 | name = Debug;
548 | };
549 | 03A99E3E1E98066B009BC03D /* Release */ = {
550 | isa = XCBuildConfiguration;
551 | buildSettings = {
552 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
553 | DEVELOPMENT_TEAM = 7L64JRM966;
554 | INFOPLIST_FILE = JCAlertController/Info.plist;
555 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
556 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
557 | PRODUCT_BUNDLE_IDENTIFIER = com.HJaycee.JCAlertController;
558 | PRODUCT_NAME = "$(TARGET_NAME)";
559 | };
560 | name = Release;
561 | };
562 | 03A99E401E98066B009BC03D /* Debug */ = {
563 | isa = XCBuildConfiguration;
564 | buildSettings = {
565 | BUNDLE_LOADER = "$(TEST_HOST)";
566 | INFOPLIST_FILE = JCAlertControllerTests/Info.plist;
567 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
568 | PRODUCT_BUNDLE_IDENTIFIER = com.HJaycee.JCAlertControllerTests;
569 | PRODUCT_NAME = "$(TARGET_NAME)";
570 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JCAlertController.app/JCAlertController";
571 | };
572 | name = Debug;
573 | };
574 | 03A99E411E98066B009BC03D /* Release */ = {
575 | isa = XCBuildConfiguration;
576 | buildSettings = {
577 | BUNDLE_LOADER = "$(TEST_HOST)";
578 | INFOPLIST_FILE = JCAlertControllerTests/Info.plist;
579 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
580 | PRODUCT_BUNDLE_IDENTIFIER = com.HJaycee.JCAlertControllerTests;
581 | PRODUCT_NAME = "$(TARGET_NAME)";
582 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JCAlertController.app/JCAlertController";
583 | };
584 | name = Release;
585 | };
586 | 03A99E431E98066B009BC03D /* Debug */ = {
587 | isa = XCBuildConfiguration;
588 | buildSettings = {
589 | INFOPLIST_FILE = JCAlertControllerUITests/Info.plist;
590 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
591 | PRODUCT_BUNDLE_IDENTIFIER = com.HJaycee.JCAlertControllerUITests;
592 | PRODUCT_NAME = "$(TARGET_NAME)";
593 | TEST_TARGET_NAME = JCAlertController;
594 | };
595 | name = Debug;
596 | };
597 | 03A99E441E98066B009BC03D /* Release */ = {
598 | isa = XCBuildConfiguration;
599 | buildSettings = {
600 | INFOPLIST_FILE = JCAlertControllerUITests/Info.plist;
601 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
602 | PRODUCT_BUNDLE_IDENTIFIER = com.HJaycee.JCAlertControllerUITests;
603 | PRODUCT_NAME = "$(TARGET_NAME)";
604 | TEST_TARGET_NAME = JCAlertController;
605 | };
606 | name = Release;
607 | };
608 | /* End XCBuildConfiguration section */
609 |
610 | /* Begin XCConfigurationList section */
611 | 03A99E0A1E98066B009BC03D /* Build configuration list for PBXProject "JCAlertController" */ = {
612 | isa = XCConfigurationList;
613 | buildConfigurations = (
614 | 03A99E3A1E98066B009BC03D /* Debug */,
615 | 03A99E3B1E98066B009BC03D /* Release */,
616 | );
617 | defaultConfigurationIsVisible = 0;
618 | defaultConfigurationName = Release;
619 | };
620 | 03A99E3C1E98066B009BC03D /* Build configuration list for PBXNativeTarget "JCAlertController" */ = {
621 | isa = XCConfigurationList;
622 | buildConfigurations = (
623 | 03A99E3D1E98066B009BC03D /* Debug */,
624 | 03A99E3E1E98066B009BC03D /* Release */,
625 | );
626 | defaultConfigurationIsVisible = 0;
627 | defaultConfigurationName = Release;
628 | };
629 | 03A99E3F1E98066B009BC03D /* Build configuration list for PBXNativeTarget "JCAlertControllerTests" */ = {
630 | isa = XCConfigurationList;
631 | buildConfigurations = (
632 | 03A99E401E98066B009BC03D /* Debug */,
633 | 03A99E411E98066B009BC03D /* Release */,
634 | );
635 | defaultConfigurationIsVisible = 0;
636 | defaultConfigurationName = Release;
637 | };
638 | 03A99E421E98066B009BC03D /* Build configuration list for PBXNativeTarget "JCAlertControllerUITests" */ = {
639 | isa = XCConfigurationList;
640 | buildConfigurations = (
641 | 03A99E431E98066B009BC03D /* Debug */,
642 | 03A99E441E98066B009BC03D /* Release */,
643 | );
644 | defaultConfigurationIsVisible = 0;
645 | defaultConfigurationName = Release;
646 | };
647 | /* End XCConfigurationList section */
648 | };
649 | rootObject = 03A99E071E98066B009BC03D /* Project object */;
650 | }
651 |
--------------------------------------------------------------------------------