├── MultipleSelectedWindow ├── MultipleSelectedWindow.xcodeproj │ ├── xcuserdata │ │ └── liushuo.xcuserdatad │ │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── MultipleSelectedWindow.xcscheme │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── liushuo.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── project.pbxproj └── MultipleSelectedWindow │ ├── ViewController.h │ ├── SureMultipleSelectedWindow │ ├── SureConditionModel.m │ ├── SureConditionModel.h │ ├── SureHeaderCollectionReusableView.h │ ├── SureHeaderCollectionReusableView.m │ ├── SureFooterCollectionReusableView.h │ ├── SureConditionCollectionViewCell.h │ ├── SureMultipleSelectedWindow.h │ ├── SureFooterCollectionReusableView.m │ ├── SureConditionCollectionViewCell.m │ ├── SureConditionCollectionViewCell.xib │ ├── SureHeaderCollectionReusableView.xib │ ├── SureFooterCollectionReusableView.xib │ └── SureMultipleSelectedWindow.m │ ├── AppDelegate.h │ ├── main.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── ViewController.m │ ├── Info.plist │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ └── AppDelegate.m └── README.md /MultipleSelectedWindow/MultipleSelectedWindow.xcodeproj/xcuserdata/liushuo.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow.xcodeproj/project.xcworkspace/xcuserdata/liushuo.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSure/MultipleSelectedWindow/HEAD/MultipleSelectedWindow/MultipleSelectedWindow.xcodeproj/project.xcworkspace/xcuserdata/liushuo.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureConditionModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SureConditionModel.m 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import "SureConditionModel.h" 10 | 11 | @implementation SureConditionModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. 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 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureConditionModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SureConditionModel.h 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SureConditionModel : NSObject 12 | @property (nonatomic, assign) BOOL isSelected; 13 | @property (nonatomic, copy) NSString *title; 14 | @end 15 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureHeaderCollectionReusableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SureHeaderCollectionReusableView.h 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SureHeaderCollectionReusableView : UICollectionReusableView 12 | @property (weak, nonatomic) IBOutlet UILabel *titleLabel; 13 | @end 14 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureHeaderCollectionReusableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SureHeaderCollectionReusableView.m 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import "SureHeaderCollectionReusableView.h" 10 | 11 | @implementation SureHeaderCollectionReusableView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureFooterCollectionReusableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SureFooterCollectionReusableView.h 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SureFooterCollectionReusableView : UICollectionReusableView 12 | @property (nonatomic, copy) void(^confirmBlock)(void); 13 | @property (nonatomic, copy) void(^cancelBlock)(void); 14 | @end 15 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureConditionCollectionViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SureConditionCollectionViewCell.h 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SureConditionModel.h" 11 | @interface SureConditionCollectionViewCell : UICollectionViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *conditionLabel; 14 | - (void)loadDataFromModel:(SureConditionModel*)model; 15 | @end 16 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureMultipleSelectedWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // SureMultipleSelectedWindow.h 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SureMultipleSelectedWindow : UIView 12 | 13 | @property (nonatomic, copy) void(^selectedBlock)(NSArray*); 14 | 15 | + (void)showWindowWithTitle:(NSString*)title 16 | selectedConditions:(NSArray*)conditions 17 | defaultSelectedConditions:(NSArray*)selectedConditions 18 | selectedBlock:(void(^)(NSArray *selectedArr))block; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow.xcodeproj/xcuserdata/liushuo.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MultipleSelectedWindow.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 88AB28581E0D1EF400165626 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureFooterCollectionReusableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SureFooterCollectionReusableView.m 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import "SureFooterCollectionReusableView.h" 10 | 11 | @implementation SureFooterCollectionReusableView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | } 17 | - (IBAction)confirmClick:(id)sender { 18 | if (self.confirmBlock) { 19 | self.confirmBlock(); 20 | } 21 | } 22 | - (IBAction)cancelClick:(id)sender { 23 | if (self.cancelBlock) { 24 | self.cancelBlock(); 25 | } 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "SureConditionModel.h" 11 | #import "SureMultipleSelectedWindow.h" 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view, typically from a nib. 21 | } 22 | 23 | - (IBAction)buttonClick:(id)sender { 24 | [SureMultipleSelectedWindow showWindowWithTitle:@"多选弹窗" selectedConditions:@[@"我",@"是",@"卖报的",@"小画家",@"Sure"] defaultSelectedConditions:@[@"我",@"小画家",@"Sure"] selectedBlock:^(NSArray *selectedArr) { 25 | NSLog(@"%@",selectedArr); 26 | for (SureConditionModel *model in selectedArr) { 27 | NSLog(@"选中[%@]",model.title); 28 | } 29 | }]; 30 | } 31 | 32 | - (void)didReceiveMemoryWarning { 33 | [super didReceiveMemoryWarning]; 34 | // Dispose of any resources that can be recreated. 35 | } 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/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 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureConditionCollectionViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SureConditionCollectionViewCell.m 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import "SureConditionCollectionViewCell.h" 10 | #define SureQuickSetRed [UIColor \ 11 | colorWithRed:236.0/255.0 \ 12 | green:73.0/255.0 \ 13 | blue:73.0/255.0 \ 14 | alpha:1.0] 15 | #define SureQuickSetWhite [UIColor \ 16 | colorWithRed:245.0/255.0 \ 17 | green:245.0/255.0 \ 18 | blue:245.0/255.0 \ 19 | alpha:1.0] 20 | @implementation SureConditionCollectionViewCell 21 | 22 | - (void)loadDataFromModel:(SureConditionModel *)model { 23 | _conditionLabel.text = model.title; 24 | if (model.isSelected) { 25 | _conditionLabel.backgroundColor = SureQuickSetRed; 26 | _conditionLabel.textColor = [UIColor whiteColor]; 27 | _conditionLabel.font = [UIFont boldSystemFontOfSize:15.0]; 28 | self.layer.borderColor = [UIColor clearColor].CGColor; 29 | self.layer.borderWidth = .0; 30 | } else { 31 | _conditionLabel.backgroundColor = SureQuickSetWhite; 32 | _conditionLabel.textColor = [UIColor darkGrayColor]; 33 | _conditionLabel.font = [UIFont systemFontOfSize:15.0]; 34 | self.layer.borderColor = [UIColor lightGrayColor].CGColor; 35 | self.layer.borderWidth = .5; 36 | } 37 | } 38 | 39 | - (void)awakeFromNib { 40 | [super awakeFromNib]; 41 | // Initialization code 42 | self.layer.borderColor = [UIColor lightGrayColor].CGColor; 43 | self.layer.cornerRadius = 20; 44 | self.layer.borderWidth = .5; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/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 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // 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. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureConditionCollectionViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureHeaderCollectionReusableView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow.xcodeproj/xcuserdata/liushuo.xcuserdatad/xcschemes/MultipleSelectedWindow.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureFooterCollectionReusableView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 29 | 39 | 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MultipleSelectedWindow 2 | ######前言 3 | 本文为iOS自定义视图封装《一劳永逸》系列的第三期,旨在提供封装思路,结果固然重要,但理解过程才最好。授人以鱼不如授人以渔。⚠️文章旨在帮助封装程度较低的朋友们,大神可无视,勿喷。 4 | ######历史文章链接列表: 5 | - [一劳永逸,iOS引导蒙版封装流程](http://www.jianshu.com/p/dfc3ecdd5810) 6 | - [一劳永逸,iOS网页视图控制器封装流程](http://www.jianshu.com/p/553424763585) 7 | 8 | ######正文 9 | 最近更新项目需求,需要封装一款多选弹窗视图,故将封装流程进行分享,效果图如下: 10 | ![多选弹窗.png](http://upload-images.jianshu.io/upload_images/1767950-0309c825d4a55ce5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 11 | 12 | 对于弹窗视图,大体由两个视图进行搭建,一为蒙版视图(maskView)二为内容视图(contentView)。maskView通常设定一定的透明度允许用户交互点击取消弹窗操作,需要注意的是不要maskView做为contentView的子视图,因改变父视图透明度会影响子视图,因此maskView与contentView均需添加在弹窗视图self上,保证兄弟视图关系,这里不再赘述。对于contentView,因需求变动不大,本文直接采用collectionView作为内容视图,标题与决策按钮以组头组尾视图进行展示。 13 | ``` 14 | - (void)createUI { 15 | [self addSubview:self.maskView]; 16 | [self addSubview:self.collectionView]; 17 | } 18 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 19 | [self removeFromSuperview]; 20 | } 21 | ``` 22 | 接下来我们解决首要问题,即collectionView多选操作,既然tableView具有多选功能,那么collectionView为什么不呢?对于collectionView的多选功能的使用场景还是很多的,比如本例多选弹窗、自定义相册功能等。 23 | 接下来简单讲述下collectionView实现多选功能的实现,以下为部分核心代码。 24 | 25 | ⚠️collectionView开启多选功能,需将属性allowsMultipleSelection置为YES 26 | ``` 27 | _collectionView.allowsMultipleSelection = YES; 28 | ``` 29 | 接下来我们需要准备两个数据源,分别存储全部选项与选中选项,命名为dataArr与selectedArr 30 | ``` 31 | @property (nonatomic, strong) NSMutableArray *dataArr; 32 | @property (nonatomic, strong) NSMutableArray *selectedArr; 33 | ``` 34 | 为了防止复用问题的出现,我们需要存储每个item的选中状态,这里选择创建数据模型进行实现。 35 | ``` 36 | #import 37 | 38 | @interface SureConditionModel : NSObject 39 | @property (nonatomic, assign) BOOL isSelected;//是否选中 默认为NO 40 | @property (nonatomic, copy) NSString *title;//选中item标题 41 | @end 42 | ``` 43 | 接下来对collectionView布局时,我们即可通过数据模型中提供的数据进行布局 44 | ``` 45 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 46 | SureConditionCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CONDITION" forIndexPath:indexPath]; 47 | SureConditionModel *model = _dataArr[indexPath.item]; 48 | [cell loadDataFromModel:model]; 49 | return cell; 50 | } 51 | ``` 52 | ``` 53 | @implementation SureConditionCollectionViewCell 54 | 55 | - (void)loadDataFromModel:(SureConditionModel *)model { 56 | _conditionLabel.text = model.title; 57 | if (model.isSelected) { 58 | _conditionLabel.backgroundColor = SureQuickSetRed; 59 | _conditionLabel.textColor = [UIColor whiteColor]; 60 | _conditionLabel.font = [UIFont boldSystemFontOfSize:15.0]; 61 | } else { 62 | _conditionLabel.backgroundColor = SureQuickSetWhite; 63 | _conditionLabel.textColor = [UIColor darkGrayColor]; 64 | _conditionLabel.font = [UIFont systemFontOfSize:15.0]; 65 | } 66 | } 67 | ``` 68 | 在这里简单的更改了选中文字的背景颜色、字体颜色和字体,如有其他需求也可进行更改。 69 | 接下来我们实现collectionView选中与取消选中的代理方法即可,这里需要取得当前选中或取消选中的item对应的数据模型,并对其选中属性进行置反操作。然后进行添加或删除操作,选中与取消选中的最终结果都存储在selectedArr中。 70 | ``` 71 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 72 | [self selectedOrDeselectedItemAtIndexPath:indexPath]; 73 | } 74 | 75 | - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath { 76 | [self selectedOrDeselectedItemAtIndexPath:indexPath]; 77 | } 78 | 79 | - (void)selectedOrDeselectedItemAtIndexPath:(NSIndexPath*)indexPath { 80 | SureConditionModel *model = _dataArr[indexPath.item]; 81 | model.isSelected = !model.isSelected; 82 | [_collectionView reloadItemsAtIndexPaths:@[indexPath]]; 83 | if (model.isSelected) { 84 | if (![_selectedArr containsObject:model]) { 85 | [_selectedArr addObject:model]; 86 | } 87 | } else { 88 | if ([_selectedArr containsObject:model]) { 89 | [_selectedArr removeObject:model]; 90 | }; 91 | } 92 | } 93 | ``` 94 | 执行上述操作,我们即可简单实现collectionView的多选功能。 95 | 96 | 接下来需要解决的问题为随选项个数动态调节collectionView高度的问题。即简单实现自适应内容高度。 97 | 98 | 因此我们需要获取collectionView的行数,但API中并没有给予。楼主通过数据源除列数获取行数,然后判断是否有余数进行++操作进行解决,如有更好的方式请评论指出,多谢。 99 | ``` 100 | NSInteger rows = window.dataArr.count / 2; 101 | if (window.dataArr.count % 2 != 0) { 102 | rows++; 103 | } 104 | ``` 105 | 既然UI上的操作基本考虑完成,接下里即需获取所选中选项并进行回调。因确认与取消按钮布局在collectionView的组尾上,因此我们需要回调传递所选选项,使用Block、代理等均可。 106 | ``` 107 | - (UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 108 | if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { 109 | SureHeaderCollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"HEADER" forIndexPath:indexPath]; 110 | headerView.titleLabel.text = _title; 111 | return headerView; 112 | } else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) { 113 | SureFooterCollectionReusableView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"FOOTER" forIndexPath:indexPath]; 114 | __weak typeof(self) weakself = self; 115 | [footerView setConfirmBlock:^{ 116 | __strong typeof(self) stongself = weakself; 117 | if (stongself.selectedBlock) { 118 | stongself.selectedBlock(stongself.selectedArr); 119 | } 120 | [stongself removeFromSuperview]; 121 | }]; 122 | 123 | [footerView setCancelBlock:^{ 124 | __strong typeof(self) stongself = weakself; 125 | [stongself removeFromSuperview]; 126 | }]; 127 | return footerView; 128 | } else { 129 | return [[UICollectionReusableView alloc]init]; 130 | } 131 | } 132 | ``` 133 | 最后即为最重要的外漏方法问题,前几篇文章提过,为了降低代码耦合度,尽量外漏简易的方法,使其他开发人员可快速使用。并且在对象方法与类方法之间通常选择类方法进行实现。 134 | 135 | 考虑本文需求,既然为自定义View,因此数据获取一定不要放在View中,因此我们需要传入所有可选择数据,对于可选择数据可能具有默认选项,我们也可进行提供,最后最重要的为选中结果,我们需要将用户所选中的信息进行回调传递。 136 | 137 | 最终的结果如下,部分代码已省略,可前往demo查看。 138 | ``` 139 | + (void)showWindowWithTitle:(NSString*)title 140 | selectedConditions:(NSArray*)conditions 141 | defaultSelectedConditions:(NSArray*)SelectedConditions 142 | selectedBlock:(void(^)(NSArray *selectedArr))block; 143 | ``` 144 | ``` 145 | + (void)showWindowWithTitle:(NSString*)title 146 | selectedConditions:(NSArray*)conditions 147 | defaultSelectedConditions:(NSArray*)SelectedConditions 148 | selectedBlock:(void(^)(NSArray *selectedArr))block{ 149 | SureMultipleSelectedWindow *window = [[SureMultipleSelectedWindow alloc]initWithFrame:[UIScreen mainScreen].bounds]; 150 | [[UIApplication sharedApplication].keyWindow addSubview:window]; 151 | //数据接收处理 152 | window.selectedBlock = block; 153 | //显示调节 154 | } 155 | ``` 156 | 调用方式如下 157 | ``` 158 | [SureMultipleSelectedWindow showWindowWithTitle:@"多选弹窗" 159 | selectedConditions:@[@"我",@"是",@"卖报的",@"小画家",@"Sure"] defaultSelectedIndex:3 160 | selectedBlock:^(NSArray *selectedArr) { 161 | NSLog(@"%@",selectedArr); 162 | }]; 163 | ``` 164 | 至此多选弹窗即封装完毕。 165 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow/SureMultipleSelectedWindow/SureMultipleSelectedWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // SureMultipleSelectedWindow.m 3 | // MultipleSelectedWindow 4 | // 5 | // Created by 刘硕 on 2016/12/23. 6 | // Copyright © 2016年 刘硕. All rights reserved. 7 | // 8 | 9 | #import "SureMultipleSelectedWindow.h" 10 | #import "SureConditionModel.h" 11 | #import "SureConditionCollectionViewCell.h" 12 | #import "SureHeaderCollectionReusableView.h" 13 | #import "SureFooterCollectionReusableView.h" 14 | #define SPACE 40.0 15 | #define WINDOW_WIDTH ([UIScreen mainScreen].bounds.size.width - (SPACE * 2)) 16 | #define WINDOW_HEIGHT ([UIScreen mainScreen].bounds.size.height - (SPACE * 2)) 17 | #define ITEM_SIZE ((WINDOW_WIDTH / 2) - 15) 18 | @interface SureMultipleSelectedWindow () 19 | @property (nonatomic, strong) UIView *maskView; 20 | @property (nonatomic, strong) UICollectionView *collectionView; 21 | @property (nonatomic, strong) NSMutableArray *dataArr; 22 | @property (nonatomic, strong) NSMutableArray *selectedArr; 23 | @property (nonatomic, copy) NSString *title; 24 | @property (nonatomic, assign) NSInteger defaultIndex; 25 | @end 26 | 27 | @implementation SureMultipleSelectedWindow 28 | 29 | + (void)showWindowWithTitle:(NSString*)title 30 | selectedConditions:(NSArray*)conditions 31 | defaultSelectedConditions:(NSArray*)selectedConditions 32 | selectedBlock:(void(^)(NSArray *selectedArr))block{ 33 | SureMultipleSelectedWindow *window = [[SureMultipleSelectedWindow alloc]initWithFrame:[UIScreen mainScreen].bounds]; 34 | window.title = title; 35 | [[UIApplication sharedApplication].keyWindow addSubview:window]; 36 | 37 | for (NSInteger i = 0; i < conditions.count; i++) { 38 | SureConditionModel *model = [[SureConditionModel alloc]init]; 39 | if ([selectedConditions containsObject:conditions[i]]) { 40 | model.isSelected = YES; 41 | [window.selectedArr addObject:model]; 42 | } else { 43 | model.isSelected = NO; 44 | } 45 | model.title = conditions[i]; 46 | [window.dataArr addObject:model]; 47 | } 48 | 49 | NSInteger rows = window.dataArr.count / 2; 50 | if (window.dataArr.count % 2 != 0) { 51 | rows++; 52 | } 53 | window.collectionView.frame = CGRectMake(0, 0, WINDOW_WIDTH, rows * 40 + ((rows - 1) * 5) + 100); 54 | if (window.collectionView.frame.size.height >= WINDOW_HEIGHT) { 55 | window.collectionView.frame = CGRectMake(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 56 | } 57 | 58 | window.collectionView.center = window.center; 59 | window.collectionView.transform = CGAffineTransformConcat(CGAffineTransformIdentity, 60 | CGAffineTransformMakeScale(1.1f, 1.1f)); 61 | [UIView animateWithDuration:.2 animations:^{ 62 | window.collectionView.transform = CGAffineTransformConcat(CGAffineTransformIdentity, 63 | CGAffineTransformMakeScale(1.0f, 1.0f)); 64 | }]; 65 | 66 | window.selectedBlock = block; 67 | } 68 | 69 | - (instancetype)initWithFrame:(CGRect)frame { 70 | if (self = [super initWithFrame:frame]) { 71 | [self initData]; 72 | } 73 | return self; 74 | } 75 | 76 | - (void)layoutSubviews { 77 | [super layoutSubviews]; 78 | [self createUI]; 79 | } 80 | 81 | - (void)initData { 82 | _selectedArr = [[NSMutableArray alloc]init]; 83 | _dataArr = [[NSMutableArray alloc]init]; 84 | } 85 | 86 | - (void)createUI { 87 | [self addSubview:self.maskView]; 88 | [self addSubview:self.collectionView]; 89 | } 90 | 91 | - (UIView*)maskView { 92 | if (!_maskView) { 93 | _maskView = [[UIView alloc]initWithFrame:self.bounds]; 94 | _maskView.backgroundColor = [UIColor blackColor]; 95 | _maskView.alpha = .8; 96 | } 97 | return _maskView; 98 | } 99 | 100 | - (UICollectionView*)collectionView { 101 | if (!_collectionView) { 102 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init]; 103 | layout.itemSize = CGSizeMake(ITEM_SIZE, 40); 104 | layout.headerReferenceSize = CGSizeMake(WINDOW_WIDTH, 50); 105 | layout.footerReferenceSize = CGSizeMake(WINDOW_WIDTH, 50); 106 | layout.minimumLineSpacing = 5; 107 | _collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, WINDOW_WIDTH, 0) collectionViewLayout:layout]; 108 | _collectionView.delegate = self; 109 | _collectionView.dataSource = self; 110 | _collectionView.allowsMultipleSelection = YES; 111 | _collectionView.bounces = NO; 112 | _collectionView.backgroundColor = [UIColor whiteColor]; 113 | _collectionView.layer.borderColor = [UIColor groupTableViewBackgroundColor].CGColor; 114 | _collectionView.layer.borderWidth = .5; 115 | _collectionView.layer.cornerRadius = 10.0; 116 | [_collectionView registerNib:[UINib nibWithNibName:@"SureConditionCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"CONDITION"]; 117 | [_collectionView registerNib:[UINib nibWithNibName:@"SureHeaderCollectionReusableView" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HEADER"]; 118 | [_collectionView registerNib:[UINib nibWithNibName:@"SureFooterCollectionReusableView" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"FOOTER"]; 119 | } 120 | return _collectionView; 121 | } 122 | 123 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 124 | return _dataArr.count; 125 | } 126 | 127 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 128 | SureConditionCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CONDITION" forIndexPath:indexPath]; 129 | SureConditionModel *model = _dataArr[indexPath.item]; 130 | [cell loadDataFromModel:model]; 131 | return cell; 132 | } 133 | 134 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { 135 | return UIEdgeInsetsMake(0, 10, 0, 10); 136 | } 137 | 138 | - (UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 139 | if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { 140 | SureHeaderCollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"HEADER" forIndexPath:indexPath]; 141 | headerView.titleLabel.text = _title; 142 | return headerView; 143 | } else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) { 144 | SureFooterCollectionReusableView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"FOOTER" forIndexPath:indexPath]; 145 | __weak typeof(self) weakself = self; 146 | [footerView setConfirmBlock:^{ 147 | __strong typeof(self) stongself = weakself; 148 | if (stongself.selectedBlock) { 149 | stongself.selectedBlock(stongself.selectedArr); 150 | } 151 | [stongself removeFromSuperview]; 152 | }]; 153 | 154 | [footerView setCancelBlock:^{ 155 | __strong typeof(self) stongself = weakself; 156 | [stongself removeFromSuperview]; 157 | }]; 158 | return footerView; 159 | } else { 160 | return [[UICollectionReusableView alloc]init]; 161 | } 162 | } 163 | 164 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 165 | [self selectedOrDeselectedItemAtIndexPath:indexPath]; 166 | } 167 | 168 | - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath { 169 | [self selectedOrDeselectedItemAtIndexPath:indexPath]; 170 | } 171 | 172 | - (void)selectedOrDeselectedItemAtIndexPath:(NSIndexPath*)indexPath { 173 | SureConditionModel *model = _dataArr[indexPath.item]; 174 | model.isSelected = !model.isSelected; 175 | [_collectionView reloadItemsAtIndexPaths:@[indexPath]]; 176 | if (model.isSelected) { 177 | if (![_selectedArr containsObject:model]) { 178 | [_selectedArr addObject:model]; 179 | } 180 | } else { 181 | if ([_selectedArr containsObject:model]) { 182 | [_selectedArr removeObject:model]; 183 | }; 184 | } 185 | } 186 | 187 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 188 | [self removeFromSuperview]; 189 | } 190 | 191 | - (void)dealloc { 192 | 193 | } 194 | 195 | /* 196 | // Only override drawRect: if you perform custom drawing. 197 | // An empty implementation adversely affects performance during animation. 198 | - (void)drawRect:(CGRect)rect { 199 | // Drawing code 200 | } 201 | */ 202 | 203 | @end 204 | -------------------------------------------------------------------------------- /MultipleSelectedWindow/MultipleSelectedWindow.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 887B91A91E16349F006C5652 /* SureConditionCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 887B919D1E16349F006C5652 /* SureConditionCollectionViewCell.m */; }; 11 | 887B91AA1E16349F006C5652 /* SureConditionCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 887B919E1E16349F006C5652 /* SureConditionCollectionViewCell.xib */; }; 12 | 887B91AB1E16349F006C5652 /* SureConditionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 887B91A01E16349F006C5652 /* SureConditionModel.m */; }; 13 | 887B91AC1E16349F006C5652 /* SureFooterCollectionReusableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 887B91A21E16349F006C5652 /* SureFooterCollectionReusableView.m */; }; 14 | 887B91AD1E16349F006C5652 /* SureFooterCollectionReusableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 887B91A31E16349F006C5652 /* SureFooterCollectionReusableView.xib */; }; 15 | 887B91AE1E16349F006C5652 /* SureHeaderCollectionReusableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 887B91A51E16349F006C5652 /* SureHeaderCollectionReusableView.m */; }; 16 | 887B91AF1E16349F006C5652 /* SureHeaderCollectionReusableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 887B91A61E16349F006C5652 /* SureHeaderCollectionReusableView.xib */; }; 17 | 887B91B01E16349F006C5652 /* SureMultipleSelectedWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 887B91A81E16349F006C5652 /* SureMultipleSelectedWindow.m */; }; 18 | 88AB285E1E0D1EF400165626 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 88AB285D1E0D1EF400165626 /* main.m */; }; 19 | 88AB28611E0D1EF400165626 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 88AB28601E0D1EF400165626 /* AppDelegate.m */; }; 20 | 88AB28641E0D1EF400165626 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 88AB28631E0D1EF400165626 /* ViewController.m */; }; 21 | 88AB28671E0D1EF400165626 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88AB28651E0D1EF400165626 /* Main.storyboard */; }; 22 | 88AB28691E0D1EF400165626 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88AB28681E0D1EF400165626 /* Assets.xcassets */; }; 23 | 88AB286C1E0D1EF400165626 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88AB286A1E0D1EF400165626 /* LaunchScreen.storyboard */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 887B919C1E16349F006C5652 /* SureConditionCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SureConditionCollectionViewCell.h; sourceTree = ""; }; 28 | 887B919D1E16349F006C5652 /* SureConditionCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SureConditionCollectionViewCell.m; sourceTree = ""; }; 29 | 887B919E1E16349F006C5652 /* SureConditionCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SureConditionCollectionViewCell.xib; sourceTree = ""; }; 30 | 887B919F1E16349F006C5652 /* SureConditionModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SureConditionModel.h; sourceTree = ""; }; 31 | 887B91A01E16349F006C5652 /* SureConditionModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SureConditionModel.m; sourceTree = ""; }; 32 | 887B91A11E16349F006C5652 /* SureFooterCollectionReusableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SureFooterCollectionReusableView.h; sourceTree = ""; }; 33 | 887B91A21E16349F006C5652 /* SureFooterCollectionReusableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SureFooterCollectionReusableView.m; sourceTree = ""; }; 34 | 887B91A31E16349F006C5652 /* SureFooterCollectionReusableView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SureFooterCollectionReusableView.xib; sourceTree = ""; }; 35 | 887B91A41E16349F006C5652 /* SureHeaderCollectionReusableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SureHeaderCollectionReusableView.h; sourceTree = ""; }; 36 | 887B91A51E16349F006C5652 /* SureHeaderCollectionReusableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SureHeaderCollectionReusableView.m; sourceTree = ""; }; 37 | 887B91A61E16349F006C5652 /* SureHeaderCollectionReusableView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SureHeaderCollectionReusableView.xib; sourceTree = ""; }; 38 | 887B91A71E16349F006C5652 /* SureMultipleSelectedWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SureMultipleSelectedWindow.h; sourceTree = ""; }; 39 | 887B91A81E16349F006C5652 /* SureMultipleSelectedWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SureMultipleSelectedWindow.m; sourceTree = ""; }; 40 | 88AB28591E0D1EF400165626 /* MultipleSelectedWindow.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MultipleSelectedWindow.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 88AB285D1E0D1EF400165626 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 42 | 88AB285F1E0D1EF400165626 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 43 | 88AB28601E0D1EF400165626 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 44 | 88AB28621E0D1EF400165626 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 45 | 88AB28631E0D1EF400165626 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 46 | 88AB28661E0D1EF400165626 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 47 | 88AB28681E0D1EF400165626 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 48 | 88AB286B1E0D1EF400165626 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 49 | 88AB286D1E0D1EF400165626 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | 88AB28561E0D1EF400165626 /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXFrameworksBuildPhase section */ 61 | 62 | /* Begin PBXGroup section */ 63 | 887B919B1E16349F006C5652 /* SureMultipleSelectedWindow */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 887B91A71E16349F006C5652 /* SureMultipleSelectedWindow.h */, 67 | 887B91A81E16349F006C5652 /* SureMultipleSelectedWindow.m */, 68 | 887B919C1E16349F006C5652 /* SureConditionCollectionViewCell.h */, 69 | 887B919D1E16349F006C5652 /* SureConditionCollectionViewCell.m */, 70 | 887B919E1E16349F006C5652 /* SureConditionCollectionViewCell.xib */, 71 | 887B919F1E16349F006C5652 /* SureConditionModel.h */, 72 | 887B91A01E16349F006C5652 /* SureConditionModel.m */, 73 | 887B91A11E16349F006C5652 /* SureFooterCollectionReusableView.h */, 74 | 887B91A21E16349F006C5652 /* SureFooterCollectionReusableView.m */, 75 | 887B91A31E16349F006C5652 /* SureFooterCollectionReusableView.xib */, 76 | 887B91A41E16349F006C5652 /* SureHeaderCollectionReusableView.h */, 77 | 887B91A51E16349F006C5652 /* SureHeaderCollectionReusableView.m */, 78 | 887B91A61E16349F006C5652 /* SureHeaderCollectionReusableView.xib */, 79 | ); 80 | path = SureMultipleSelectedWindow; 81 | sourceTree = ""; 82 | }; 83 | 88AB28501E0D1EF400165626 = { 84 | isa = PBXGroup; 85 | children = ( 86 | 88AB285B1E0D1EF400165626 /* MultipleSelectedWindow */, 87 | 88AB285A1E0D1EF400165626 /* Products */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | 88AB285A1E0D1EF400165626 /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 88AB28591E0D1EF400165626 /* MultipleSelectedWindow.app */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 88AB285B1E0D1EF400165626 /* MultipleSelectedWindow */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 887B919B1E16349F006C5652 /* SureMultipleSelectedWindow */, 103 | 88AB285F1E0D1EF400165626 /* AppDelegate.h */, 104 | 88AB28601E0D1EF400165626 /* AppDelegate.m */, 105 | 88AB28621E0D1EF400165626 /* ViewController.h */, 106 | 88AB28631E0D1EF400165626 /* ViewController.m */, 107 | 88AB28651E0D1EF400165626 /* Main.storyboard */, 108 | 88AB28681E0D1EF400165626 /* Assets.xcassets */, 109 | 88AB286A1E0D1EF400165626 /* LaunchScreen.storyboard */, 110 | 88AB286D1E0D1EF400165626 /* Info.plist */, 111 | 88AB285C1E0D1EF400165626 /* Supporting Files */, 112 | ); 113 | path = MultipleSelectedWindow; 114 | sourceTree = ""; 115 | }; 116 | 88AB285C1E0D1EF400165626 /* Supporting Files */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 88AB285D1E0D1EF400165626 /* main.m */, 120 | ); 121 | name = "Supporting Files"; 122 | sourceTree = ""; 123 | }; 124 | /* End PBXGroup section */ 125 | 126 | /* Begin PBXNativeTarget section */ 127 | 88AB28581E0D1EF400165626 /* MultipleSelectedWindow */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 88AB28701E0D1EF400165626 /* Build configuration list for PBXNativeTarget "MultipleSelectedWindow" */; 130 | buildPhases = ( 131 | 88AB28551E0D1EF400165626 /* Sources */, 132 | 88AB28561E0D1EF400165626 /* Frameworks */, 133 | 88AB28571E0D1EF400165626 /* Resources */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | ); 139 | name = MultipleSelectedWindow; 140 | productName = MultipleSelectedWindow; 141 | productReference = 88AB28591E0D1EF400165626 /* MultipleSelectedWindow.app */; 142 | productType = "com.apple.product-type.application"; 143 | }; 144 | /* End PBXNativeTarget section */ 145 | 146 | /* Begin PBXProject section */ 147 | 88AB28511E0D1EF400165626 /* Project object */ = { 148 | isa = PBXProject; 149 | attributes = { 150 | CLASSPREFIX = Sure; 151 | LastUpgradeCheck = 0800; 152 | ORGANIZATIONNAME = "刘硕"; 153 | TargetAttributes = { 154 | 88AB28581E0D1EF400165626 = { 155 | CreatedOnToolsVersion = 8.0; 156 | ProvisioningStyle = Automatic; 157 | }; 158 | }; 159 | }; 160 | buildConfigurationList = 88AB28541E0D1EF400165626 /* Build configuration list for PBXProject "MultipleSelectedWindow" */; 161 | compatibilityVersion = "Xcode 3.2"; 162 | developmentRegion = English; 163 | hasScannedForEncodings = 0; 164 | knownRegions = ( 165 | en, 166 | Base, 167 | ); 168 | mainGroup = 88AB28501E0D1EF400165626; 169 | productRefGroup = 88AB285A1E0D1EF400165626 /* Products */; 170 | projectDirPath = ""; 171 | projectRoot = ""; 172 | targets = ( 173 | 88AB28581E0D1EF400165626 /* MultipleSelectedWindow */, 174 | ); 175 | }; 176 | /* End PBXProject section */ 177 | 178 | /* Begin PBXResourcesBuildPhase section */ 179 | 88AB28571E0D1EF400165626 /* Resources */ = { 180 | isa = PBXResourcesBuildPhase; 181 | buildActionMask = 2147483647; 182 | files = ( 183 | 88AB286C1E0D1EF400165626 /* LaunchScreen.storyboard in Resources */, 184 | 887B91AF1E16349F006C5652 /* SureHeaderCollectionReusableView.xib in Resources */, 185 | 88AB28691E0D1EF400165626 /* Assets.xcassets in Resources */, 186 | 887B91AD1E16349F006C5652 /* SureFooterCollectionReusableView.xib in Resources */, 187 | 88AB28671E0D1EF400165626 /* Main.storyboard in Resources */, 188 | 887B91AA1E16349F006C5652 /* SureConditionCollectionViewCell.xib in Resources */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | /* End PBXResourcesBuildPhase section */ 193 | 194 | /* Begin PBXSourcesBuildPhase section */ 195 | 88AB28551E0D1EF400165626 /* Sources */ = { 196 | isa = PBXSourcesBuildPhase; 197 | buildActionMask = 2147483647; 198 | files = ( 199 | 887B91AB1E16349F006C5652 /* SureConditionModel.m in Sources */, 200 | 887B91A91E16349F006C5652 /* SureConditionCollectionViewCell.m in Sources */, 201 | 88AB28641E0D1EF400165626 /* ViewController.m in Sources */, 202 | 88AB28611E0D1EF400165626 /* AppDelegate.m in Sources */, 203 | 887B91AE1E16349F006C5652 /* SureHeaderCollectionReusableView.m in Sources */, 204 | 887B91AC1E16349F006C5652 /* SureFooterCollectionReusableView.m in Sources */, 205 | 88AB285E1E0D1EF400165626 /* main.m in Sources */, 206 | 887B91B01E16349F006C5652 /* SureMultipleSelectedWindow.m in Sources */, 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | }; 210 | /* End PBXSourcesBuildPhase section */ 211 | 212 | /* Begin PBXVariantGroup section */ 213 | 88AB28651E0D1EF400165626 /* Main.storyboard */ = { 214 | isa = PBXVariantGroup; 215 | children = ( 216 | 88AB28661E0D1EF400165626 /* Base */, 217 | ); 218 | name = Main.storyboard; 219 | sourceTree = ""; 220 | }; 221 | 88AB286A1E0D1EF400165626 /* LaunchScreen.storyboard */ = { 222 | isa = PBXVariantGroup; 223 | children = ( 224 | 88AB286B1E0D1EF400165626 /* Base */, 225 | ); 226 | name = LaunchScreen.storyboard; 227 | sourceTree = ""; 228 | }; 229 | /* End PBXVariantGroup section */ 230 | 231 | /* Begin XCBuildConfiguration section */ 232 | 88AB286E1E0D1EF400165626 /* Debug */ = { 233 | isa = XCBuildConfiguration; 234 | buildSettings = { 235 | ALWAYS_SEARCH_USER_PATHS = NO; 236 | CLANG_ANALYZER_NONNULL = YES; 237 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 238 | CLANG_CXX_LIBRARY = "libc++"; 239 | CLANG_ENABLE_MODULES = YES; 240 | CLANG_ENABLE_OBJC_ARC = YES; 241 | CLANG_WARN_BOOL_CONVERSION = YES; 242 | CLANG_WARN_CONSTANT_CONVERSION = YES; 243 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 244 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 245 | CLANG_WARN_EMPTY_BODY = YES; 246 | CLANG_WARN_ENUM_CONVERSION = YES; 247 | CLANG_WARN_INFINITE_RECURSION = YES; 248 | CLANG_WARN_INT_CONVERSION = YES; 249 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 250 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 251 | CLANG_WARN_UNREACHABLE_CODE = YES; 252 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 253 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 254 | COPY_PHASE_STRIP = NO; 255 | DEBUG_INFORMATION_FORMAT = dwarf; 256 | ENABLE_STRICT_OBJC_MSGSEND = YES; 257 | ENABLE_TESTABILITY = YES; 258 | GCC_C_LANGUAGE_STANDARD = gnu99; 259 | GCC_DYNAMIC_NO_PIC = NO; 260 | GCC_NO_COMMON_BLOCKS = YES; 261 | GCC_OPTIMIZATION_LEVEL = 0; 262 | GCC_PREPROCESSOR_DEFINITIONS = ( 263 | "DEBUG=1", 264 | "$(inherited)", 265 | ); 266 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 267 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 268 | GCC_WARN_UNDECLARED_SELECTOR = YES; 269 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 270 | GCC_WARN_UNUSED_FUNCTION = YES; 271 | GCC_WARN_UNUSED_VARIABLE = YES; 272 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 273 | MTL_ENABLE_DEBUG_INFO = YES; 274 | ONLY_ACTIVE_ARCH = YES; 275 | SDKROOT = iphoneos; 276 | }; 277 | name = Debug; 278 | }; 279 | 88AB286F1E0D1EF400165626 /* Release */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | ALWAYS_SEARCH_USER_PATHS = NO; 283 | CLANG_ANALYZER_NONNULL = YES; 284 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 285 | CLANG_CXX_LIBRARY = "libc++"; 286 | CLANG_ENABLE_MODULES = YES; 287 | CLANG_ENABLE_OBJC_ARC = YES; 288 | CLANG_WARN_BOOL_CONVERSION = YES; 289 | CLANG_WARN_CONSTANT_CONVERSION = YES; 290 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 291 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 292 | CLANG_WARN_EMPTY_BODY = YES; 293 | CLANG_WARN_ENUM_CONVERSION = YES; 294 | CLANG_WARN_INFINITE_RECURSION = YES; 295 | CLANG_WARN_INT_CONVERSION = YES; 296 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 297 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 298 | CLANG_WARN_UNREACHABLE_CODE = YES; 299 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 300 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 301 | COPY_PHASE_STRIP = NO; 302 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 303 | ENABLE_NS_ASSERTIONS = NO; 304 | ENABLE_STRICT_OBJC_MSGSEND = YES; 305 | GCC_C_LANGUAGE_STANDARD = gnu99; 306 | GCC_NO_COMMON_BLOCKS = YES; 307 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 308 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 309 | GCC_WARN_UNDECLARED_SELECTOR = YES; 310 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 311 | GCC_WARN_UNUSED_FUNCTION = YES; 312 | GCC_WARN_UNUSED_VARIABLE = YES; 313 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 314 | MTL_ENABLE_DEBUG_INFO = NO; 315 | SDKROOT = iphoneos; 316 | VALIDATE_PRODUCT = YES; 317 | }; 318 | name = Release; 319 | }; 320 | 88AB28711E0D1EF400165626 /* Debug */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 324 | INFOPLIST_FILE = MultipleSelectedWindow/Info.plist; 325 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 326 | PRODUCT_BUNDLE_IDENTIFIER = com.Sure.MultipleSelectedWindow; 327 | PRODUCT_NAME = "$(TARGET_NAME)"; 328 | }; 329 | name = Debug; 330 | }; 331 | 88AB28721E0D1EF400165626 /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 335 | INFOPLIST_FILE = MultipleSelectedWindow/Info.plist; 336 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 337 | PRODUCT_BUNDLE_IDENTIFIER = com.Sure.MultipleSelectedWindow; 338 | PRODUCT_NAME = "$(TARGET_NAME)"; 339 | }; 340 | name = Release; 341 | }; 342 | /* End XCBuildConfiguration section */ 343 | 344 | /* Begin XCConfigurationList section */ 345 | 88AB28541E0D1EF400165626 /* Build configuration list for PBXProject "MultipleSelectedWindow" */ = { 346 | isa = XCConfigurationList; 347 | buildConfigurations = ( 348 | 88AB286E1E0D1EF400165626 /* Debug */, 349 | 88AB286F1E0D1EF400165626 /* Release */, 350 | ); 351 | defaultConfigurationIsVisible = 0; 352 | defaultConfigurationName = Release; 353 | }; 354 | 88AB28701E0D1EF400165626 /* Build configuration list for PBXNativeTarget "MultipleSelectedWindow" */ = { 355 | isa = XCConfigurationList; 356 | buildConfigurations = ( 357 | 88AB28711E0D1EF400165626 /* Debug */, 358 | 88AB28721E0D1EF400165626 /* Release */, 359 | ); 360 | defaultConfigurationIsVisible = 0; 361 | defaultConfigurationName = Release; 362 | }; 363 | /* End XCConfigurationList section */ 364 | }; 365 | rootObject = 88AB28511E0D1EF400165626 /* Project object */; 366 | } 367 | --------------------------------------------------------------------------------