UIViewController---汇总
2015-12-21 13:32
609 查看
UIWindow、UILabel、UIColor、UIScreen、UIViewController、UIView、UIControl、UIButton、IBOutlet、IBAction、UIStepper、 UISlider、 UISwitch、UITextField、UIAlertView、UIActionSheet、UINavigationController、UIBarButtonItem、UIImageView、UIScrollView、UIPageContro、UITableView、UITableViewController、UITableViewCell、UITabBarController、NSTimer、UICollectionViewController、UISegmentedControl ======================================================================= 在类内的init…方法中、get、set方法中,用_xxx实例变量。其他地方的访问都用self.属性 内存管理修饰: copy:NSString,block copy:将对象的拷贝赋给引用,拷贝完的是不可变的。 为什么用copy? NSString类型的特点就是内容不可变的,但是给NSString赋值时,可以将NSMutableString赋过来,可能就会有其他持有MutableString的引用修改了这个字符串,结果你再用NSString访问字符串时就会发现,本来不可变的字符串在不知情的情况下被改变了。所以为了避免这种情况,就是用copy将内容复制成不可变之后再给NSString 使用copy会更安全,但内存会被占用,一般情况下用strong不影响程序运行 strong:除NSString以外的引用类型 完全的拥有对象,引用计数器+1 assign:基本数据类型、结构体、枚举 ========================================================================== 一、调试 0.警告 尽量一个警告都不要有 1.错误 1)红色提示 编译过不去的原因大部分是语法,检查括号的匹配,变量名称,作用域范围 2)编译可以通过,可以运行 a。运行过程中程序崩溃 在debug区域的右侧,观察提示信息,信息的最上面会说明出错的类及方法的位置,然后找“reason”单词,看后面的提示 b。运行过程中没有问题,但是结果与期待不符 2.问题的解决方法 2.1 核心理念:掌控每一步中变量的变化 使用debug工具,下断点,逐行跟踪程序的运行,查看每一行代码运行时,各个变量内存放的数据是否与期待存储的数据相一致,如果某一行代码执行后,发现变量中存储的值与期待不符,那么基本上原因就找到了,然后根据变量的整个赋值、运算过程再来分析为什么数据不符,解决了无数据或数据有误的情况后,程序基本就正常运行了。 2.2 下断点位置的选择 变量被改变之前的位置以及变量被改变之后的位置 3工具的使用 3.1 遇到断点停下来后,debug区域的三角按钮,点击后,程序继续自动 运行;如果后续运行中遇到了下一个断点,则停下来;如果后续运行中没有断点了,那么程序自动运行完才停下来 3.2 step over:将一个方法整体作为执行的一步,一次性执行完,但,如果方法中有断点,则会进断点。进入断点后,可以通过点击三角号或step out都可以回到进入方法前的那个位置 3.3 step into:可以进入方法的内部,继续逐行跟踪代码的执行过程 3.4 step out:在方法内部中调试时,如果不想再继续跟踪,可以通过点击此按钮,快速回到进入该方法的那个位置 3.5 调试过程中,如果想快速略过一段循环的话,可以在循环的后面添加断点,然后点击三角号,就会不再跟踪循环的过程,而快速执行到下一个断点的位置 ============================================================================= User Interface UIKit 知识点 一、UIWindow 今天的目标: 写出第一个iOS的程序,在界面上显示“Hello World” 1.如何新建一个工程 iOS—>Single View Application—>工程名、保存位置 2.运行App 点击三角符号或使用快捷键(Command + R) 快捷键:Command+B 只是编译,不是运行 3.工程的文件组成 4.应用程序是如何运行起来的? 1)main方法 int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } UIApplicationMain()全局函数,一共做了三件事: a)根据第三个参数创建应用程序类的实例(nil默认UIApplication 系统默认) b)根据第四个参数创建应用程序代理类的实例 (Application Delegate代理 自己任意创建的类,遵守了协议才可以成为代理类) c)启动事件循环 d)在代理类的didFinishLaunchingWithOptions:方法中编写启动程序后的界面创建及显示 5.UIWindow 1)是什么 是界面显示的根本对象,要想出现显示的内容,那么一定是先创建window的实例 2)作用是什么? 是界面要显示的内容的父容器,在window的上面添加其他显示的内容 6.frame 1)是什么 是CGRect类型的结构体 2)描述了控件在父容器中的位置和大小 CGRect{ CGPoint origin, CGSize size } CGPoint{ CGFloat x, CGFloat y } CGSize{ CGFloat width, CGFloat height } 3)如何创建结构体的变量? 使用全局函数 xxxMake(); CGRect —> CGRectMake(x,y,width,height) CGPoint -> CGPointMake(x,y); CGSize -> CGSizeMake(width,height); 例: AppDelegate.m #import "AppDelegate.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //应用程序启动后,第一个要执行动作的时机点,可以做第一个要出现的界面的设置 //1.创建window的实例 self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];//读屏幕的大小 //2.设置window的背景色 self.window.backgroundColor = [UIColor whiteColor]; //3.创建并添加显示文本信息的标签 UILabel *label = [[UILabel alloc]init]; label.frame = CGRectMake(100, 150, 200, 40); label.text = @"Hello World"; [self.window addSubview:label];//子试图添加到界面 //4.设置窗口可见(显示) [self.window makeKeyAndVisible]; return YES; } ================================================================================================= 知识点 二、应用程序设计理念:视图控制器(UIViewController)、视图(UIView) *利用视图控制器(底层)管理视图(外观),一对一 1.视图的作用:负责显示的外观 2.视图控制器的作用:创建界面、管理视图的生命周期 3.UIViewController的UIView关系:系统的UIViewController中天生自带一个视图,UIView通过self.view属性来访问控制器自带的这个视图 4.viewDidLoad方法:创建视图时会自动调用,而且只被调用一次,有关视图的初始化工作都会放在这个方法中 5.使用VC的步骤: step1:编写一个类,继承自UIViewController step2:重写类中的viewDidLoad方法,创建界面内容 step3:在didFinishLaunching方法中,创建window的实例,创建vc的实例,将vc设置为window的rootViewController(根vc),显示window 1.创建控制器 AppDelegate.m #import "AppDelegate.h" #import "MyViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window=[[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; self.window.backgroundColor=[UIColor greenColor]; //1.创建控制器的实例 myVC自带一个视图 MyViewController* myVC=[[MyViewController alloc]init]; //2.将控制器设置为window的根视图控制器 self.window.rootViewController=myVC; [self.window makeKeyAndVisible]; return YES; } 2.视图控制器viewDidLoad方法 1).控制器拥有对其自带的视图的生命周期(创建--->销毁)管理权 2).在视图的生命周期的第一个阶段就是执行viewDidLoad方法 3).作用:用于创建视图,如:初始化界面、创建界面的显示元素 4).特点:在整个生命周期中,只会被执行一次 例: MyViewController.m (自己创建的类,继承了UIViewController父类方法,并重写了viewDidLoad方法) #import "MyViewController.h" @interface MyViewController () @end @implementation MyViewController //控制器拥有对其自带的视图的生命周期(创建--->销毁)管理权 //在视图的生命周期的第一个阶段就是执行viewDidLoad方法 //作用:用于创建视图,如:初始化界面、创建界面的显示元素 //特点:在整个生命周期中,只会被执行一次 - (void)viewDidLoad { [super viewDidLoad]; //设计view UILabel* label=[[UILabel alloc]init]; label.frame=CGRectMake(110, 200, 100, 40); label.text=@"HelloWlord"; //添加到控制器自带的那个视图里面 [self.view addSubview:label]; } @end ========================================================================================================================== 知识点 三、视图(UIView)与控件(UIControl) 1.UIView类 1.什么是视图 看得见的都是视图 2.什么是控件 一种特殊的视图,都是UIControl的子类,不仅具有一定的显示外观,还能响应高级事件,与用户交互。严格意义上UILabel不是控件,因为label不能响应用户交互事件。 3 术语的理解: 视图:一个大一点的显示区域,里面可以容纳控件,做容器讲 控件:容器中包含的子元素 2.UILabel标签 1. 是什么? 静态文本内容的展示控件 2.label属性 1)text:显示文本的内容 2)font:显示文本的字体 3)numberOfLines:默认为1,显示的最大行数,0表示无上限 4) lineBreakMode:换行模式, 省略头或尾 NSLineBreakByTruncatingHead, /* Truncate at head of line: "...wxyz" */ NSLineBreakByTruncatingTail, /* Truncate at tail of line: "abcd..." */ NSLineBreakByTruncatingMiddle /* Truncate middle of line: "ab...yz" 5)adjustsFontSizeToWidth:是否调整字体大小适应控件宽度 yes; 6) textColor:设置文本的颜色 例: MyViewController.m - (void)viewDidLoad { [super viewDidLoad]; //设计view UILabel* label=[[UILabel alloc]init]; label.frame=CGRectMake(110, 200, 100, 60); //设置字体颜色 label.textColor=[UIColor whiteColor]; //设置最大显示行数 label.numberOfLines=2; //设置标签内容的字体 label.font=[UIFont systemFontOfSize:20]; //设置换行模式 label.lineBreakMode=NSLineBreakByTruncatingHead; //调整字体大小 //label.adjustsFontSizeToFitWidth=YES; label.text=@"HelloWlord HelloWlord HelloWlord"; //添加到控制器自带的那个视图里面 [self.view addSubview:label]; } 3.UIButton按钮 1.什么是按钮? 可以与用户交互,能够点击的一种控件 2.创建方式 工厂方法创建,使用系统模式 3.常用属性 1)frame :按钮大小 2)backgroundColor:按钮背景色 3)setBackgroundImage:按钮背景图 1.点击images.xcassets文件,将要添加的图片拖拉进文本框,左边框修改图片名字 2.点击下方Show Slicing按钮 3.在下方进行缩小放大操作 4.点击图片中Start Slicing按钮进行裁剪,再点击中间按钮 5.九切片:横3线:1线范围不变,1-2线之间复制,2-3线裁剪省掉,3线不变 6.将照片名字添加到程序 [button setBackgroundImage:[UIImage imageNamed:@"bg"]forState:UIControlStateNormal]; 4)tintColor:按钮字体颜色 5) setTitle:点击按钮的状态 UIControlStateNormal = 0, 正常按下 UIControlStateHighlighted = 1 << 0, 长按状态 UIControlStateDisabled = 1 << 1, UIControlStateSelected = 1 << 2, 4.添加事件 ***点一次按钮,执行调用一次方法 addTarget:为按钮添加响应事件,即点击按钮时需实现的功能 参数: 1.target:让当前控制器对象成为处理响应的对象 2.action:处理事件的对象所使用的方法 3.events:添加对按钮的什么事件的处理 [button addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside]; 例: MyViewController.m #import "MyViewController.h" @interface MyViewController () @property(nonatomic,strong)UILabel *label;//设置全局变量 @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; //使用工厂方法创建button对象 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; //设置frame属性 button.frame = CGRectMake(100, 200, 100, 40); //设置按钮上的文字 [button setTitle:@"OK" forState:UIControlStateNormal]; [button setTitle:@"KO" forState:UIControlStateHighlighted]; //设置按钮的背景色 //button.backgroundColor = [UIColor lightGrayColor]; //设置按钮的背景图 [button setBackgroundImage:[UIImage imageNamed:@"bg"] forState:UIControlStateNormal]; //设置按钮的图片 //[button setImage:[UIImage imageNamed:@"wifi"] forState:UIControlStateNormal]; //为按钮添加响应事件 //target:让当前控制器对象成为处理响应的对象 //action:处理事件的对象所使用的方法 //events:添加对按钮的什么事件的处理 [button addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside]; //添加按钮到视图中 [self.view addSubview:button]; //添加一个UILable UILabel *label = [[UILabel alloc]init]; self.label = label; label.frame = CGRectMake(110, 50, 100, 40); label.text = @"Hello World"; [self.view addSubview:label]; } //处理事件的对象所使用的方法 -(void)click { self.label.text = @"Hello Kitty"; //NSLog(@"click....."); } @end AppDelegate.h @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window=[[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; self.window.backgroundColor=[UIColor whiteColor]; MyViewController* vc=[[MyViewController alloc]init]; self.window.rootViewController=vc; [self.window makeKeyAndVisible]; return YES; } 作业: 2.做一个小的应用 界面中有一个按钮,每次按下按钮,界面多一个UILabel 要求: 1)label之间间隔10个点的距离 2)所有label和屏幕左边距离20个点 3)所有label宽280,高20 4)每个Label的内容进行叠加(Hello,HelloWorld,HelloWorldWorld,......) #import "MyViewController.h" @interface MyViewController () //@property(nonatomic,strong)UILabel* label; @property(nonatomic,assign)int y; @property(nonatomic,strong)NSMutableString* str; @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; UIButton* button=[UIButton buttonWithType:UIButtonTypeSystem]; button.frame=CGRectMake(130, 40, 60, 20); button.backgroundColor=[UIColor yellowColor]; button.tintColor=[UIColor redColor]; [button setTitle:@"on" forState:UIControlStateNormal]; [button setTitle:@"off" forState:UIControlStateHighlighted]; //响应事件 [button addTarget:self action:@selector(show) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; self.y=100;//初始化 self.str=[[NSMutableString alloc]initWithString:@"Hello"];//初始化 } -(void)show{ UILabel* label=[[UILabel alloc]init]; label.backgroundColor=[UIColor greenColor]; label.text=self.str; label.frame=CGRectMake(20, self.y, 280, 20); label.adjustsFontSizeToFitWidth=YES; label.textColor=[UIColor redColor]; [self.view addSubview:label]; //只改变当前使用的值,出了范围就是改变后的值 self.y+=30; [self.str appendString:@"Wlord"]; } @end ======================================================================================================================= 知识点 四、interface Builder(简称 IB) 界面构建器 1.interface Builder 设置界面 1.1 是什么? 一个可视化的界面编辑工具软件,在xcode4之后整合到了xcode中 1.2 作用? 通过可视化的界面设置,能够少写或不写代码而完成界面的设计,从而减少在控制器的viewDidLoad中写的大量有关创建控件及设置属性的代码 1.3 工作原理 将界面所需控件的设置保存到xib文件中,在创建控制器实例的时候,系统会根据指定的xib文件来自动创建视图中的各个控件的实例、设置实例的属性,将其用于对控制器自带的视图的初始化中。所以,在创建控制器实例时,需要使用initWithNibName方法来指定有关视图的配置需要加载的文件是哪一个 MyViewController* vc=[[MyViewController alloc]initWithNibName:@"MyViewController" bundle:nil];//参数1:文件名 参数2:nil通常 1.4 所需文件 XxxxYyyy.h XxxxYyyy.m XxxxYyyy.xib (xml interface builder) 2. IBOutlet,IBAction 由于控制器的视图中所需的控件都由系统根据xib文件自动创建完成,所以view已经对这些控件对象是strong强引用了,但是,此时控制器无法访问系统创建的这些控件,于是需要通过特殊的方法来获取系统创建的这些对象的引用。 1.1使用方式 1. 如果,是对IB中的对象添加属性访问,让控件成为一个外界可以访问的输出口,则通过连线的方式,使其成为控制其的IBOutlet属性 @property (weak, nonatomic) IBOutlet UILabel *infolabel;//通过连线后生成的属性(Ctrl+鼠标左键) 2.如果,是对IB中的对象添加事件的响应,则通过连线的方式,为控件添加IBAction行为事件 添加连线的方式: a。打开拆分视图,左边为xib文件,右边为xib对应的控制器m文件 b。选中控件,按下control c。在控件上按下鼠标左键,拖拽到右侧的指定位置 d。如果是添加输出口,则拖拽到扩展中 @property (weak, nonatomic) IBOutlet UILabel *valueLabel; e。如果是添加action,则拖拽到类的实现中,change方法 - (IBAction)changeValue:(UIStepper *)sender { } 1.2 action的参数 在为控件添加事件响应时,可以添加一个参数,默认为id类型,代表的是发生事件的源头是哪个控件,或者说本次事件的发送者是谁 在需要用到这个参数来区分连到同一个方法上的多个控件的时候,可以在连线时,选择type参数,设置为具体的某种控件类型,不需要再在方法内进行类型转换了。 例: 三个button控制一个label,并且将button的内容赋给label。只需将三个button都连线到一个方法当中。 - (IBAction)click:(UIButton *)sender { self.infolabel.text=[sender titleForState:UIControlStateNormal]; } 1.3 使用IB连线时的注意事项 如果对IB中的控件连线后,又删除,那么此时删掉的只是代码中的变量或方法,并没有删掉界面中控件记录的连线,一定要在xib中,选中控件,右键,查看绑定的线有几条,将不需要的连线删掉,才不会出错。 ================================================================================= 知识点 五、基础控件(UIStepper UISlider UISwitch UITextField ) 1.UIStepper 步进控件 精确掌握 1.重要属性: .value 初始值 .maximumValue 最大值 .minimumValue 最小值 .stepValue 间隔 2.常用事件: value Changed事件:当数值改变时触发 2 .UISlider 滑块控件 快速滑动的方式得到一个可变数值 1.重要属性: .value 2.重要事件: value Changed事件:当数值改变时触发 //显示滑块控件的初始值 self.sliderLabel.text = [NSString stringWithFormat:@"%.2lf",self.slider.value]; 例:三个滑块控件控制一个label的渐变色,红、绿、蓝 #import "ColorViewController.h" @interface ColorViewController () @property (weak, nonatomic) IBOutlet UISlider *redSlider; @property (weak, nonatomic) IBOutlet UISlider *greenSlider;//连接控件生成属性 @property (weak, nonatomic) IBOutlet UISlider *blueSlider; @property (weak, nonatomic) IBOutlet UILabel *label; @end @implementation ColorViewController - (void)viewDidLoad { [super viewDidLoad]; self.label.backgroundColor = [UIColor colorWithRed:self.redSlider.value green:self.greenSlider.value blue:self.blueSlider.value alpha:1]; } - (IBAction)changeRedColor:(UISlider *)sender { self.label.backgroundColor = [UIColor colorWithRed:self.redSlider.value green:self.greenSlider.value blue:self.blueSlider.value alpha:1];//三个控件共用一个方法,赋给label } @end 3. UISwitch 开关控件 1.重要属性: .on (BOOL) 获取或设置开关的状态 .enabled(BOOL) 获取或设置控件是否可用 //修改switch状态 [self.switchControl setOn:NO animated:YES]; //设置switch不可用 self.switchControl.enabled = NO; 2.重要的事件: valueChanged事件 例:两个开关。主控制辅,主开,则辅可以开关。主关,则辅不可操作 - (IBAction)mainSwitchChanged:(UISwitch *)sender { //根据当前sender的状态来决定下面的switch的状态 [self.otherSwitch setOn:sender.on animated:YES]; //下面的switch能不能用,取决于sender的状态 //sender 如果为YES,enabled为YES //sender 如果为NO,enabled为NO self.otherSwitch.enabled = sender.on; } 4.UITextField 文本框控件 4.1 是什么? 是单行的文本输入框,支持用户的输入 4.2 属性 .text 获取或设置文本框内的文本 … … 4.3 系统弹出的键盘 第一响应者:当用户触摸界面时,系统会根据手指触摸的位置层层定位到具体的控件,如果,本次触点在文本框控件的区域内,那么文本框就负责对本次的触碰事件进行响应,由于文本框比较特殊,所以系统自动将文本框设置为响应事件的第一关,并且自动弹出键盘。 插播: 当用户点击屏幕后,首先开启的是查找hit-View的过程。从window开始,给所有直接子视图发hit-Test的消息,直到某一个控件没有子视图了,并且这个触点在这个子视图中,则返回这个控件,于是hit-View找到了 找到hit-View后,view则成为了需要第一个为这个事件提供响应的对象,如果,该对象没有提供事件响应,则该事件对象会向视图的父视图继续传递,如果父视图依然没有提供响应,则继续向上传递,直到传递到UIApplication对象,依然没有处理的话,则抛弃该事件。这个过程叫做响应者链。 4.4 如何关闭键盘 方法一:让键盘放弃第一响应者的身份即可 [self.textField resignFirstResponder]; 方法二:让键盘所在的父视图结束编辑状态 [self.view endEditing:YES]; 4.5什么时候关闭键盘呢?(关闭键盘的时机) 时机一:点击键盘右下角的按键 选择Did End On Exit事件 为文本框添加一个 事件 时机二:点击屏幕的空白部分 重写控制器的touchesBegan:withEvent:方法 (不用连接方法) 例: #import "MyViewController.h" @interface MyViewController () @property (weak, nonatomic) IBOutlet UITextField *textField; @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; //self.textField.text = @"xxxxxxx"; } - (IBAction)openKeyboard:(UIButton *)sender { //让文本框成为第一响应者 [self.textField becomeFirstResponder]; } - (IBAction)closeKeyboard:(UIButton *)sender { //方式一:让文本框放弃第一响应者的身份 //[self.textField resignFirstResponder]; //方式二:让文本框的父视图放弃编辑状态 [self.view endEditing:YES]; } //时机一:点击键盘右下角的按键,该事件触发 键盘收起 - (IBAction)tapReturn:(UITextField *)sender { //[sender resignFirstResponder]; [self.view endEditing:YES]; } //时机二:点击空白屏幕 键盘收起 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self.view endEditing:YES]; } 作业: 1.界面如下: [输入框][发送按钮] 1)当点击发送按钮后,界面上会出现一个UILabel,内容就是输入框中的内容,此时要求,收起键盘,清空输入框 2)当用户点击键盘右下角的按键时,功能和1相同 3)label本身设置为宽280,高40,距离左边20个点 4)多个label不能重合 #import "MyViewController.h" @interface MyViewController () //发送按钮 @property (weak, nonatomic) IBOutlet UIButton *sendButton; //文本框 @property (weak, nonatomic) IBOutlet UITextField *textField; @property(nonatomic,assign)float y; @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; //设置按钮属性 self.sendButton.backgroundColor=[UIColor redColor]; self.y=100; } //点击发送按钮,响应事件 - (IBAction)openKeyBound:(UIButton *)sender { UILabel*label=[[UILabel alloc]init]; label.frame=CGRectMake(20, self.y, 280, 40); NSLog(@"%@",self.textField.text); label.text=self.textField.text; [self.view addSubview:label]; self.y+=60; [self.view endEditing:YES]; self.textField.text=nil; } //点击左下角收起键盘 - (IBAction)tapReturn:(UITextField *)sender { UILabel*label=[[UILabel alloc]init]; label.frame=CGRectMake(20, self.y, 280, 40); NSLog(@"%@",self.textField.text); label.text=self.textField.text; [self.view addSubview:label]; self.y+=60; [self.view endEditing:YES]; self.textField.text=nil; [self.view endEditing:YES]; } 2.界面如下: [输入框 账号] [输入框 密码] [登录 按钮] [UILabel 显示当前状态(登录后显示用户名,没登录显示未登录)] 1)用户输入完用户名和密码后,点击登录,判断是否可以登录,如果登录成功,label上显示当前用户的用户名,如果没有登录,显示未登录 2)当用户没有填写用户名和密码时,点击登录,提供用户输入用户名和密码 3)第一个textField支持Next功能,第二是Done #import "MyViewController.h" @interface MyViewController () @property (weak, nonatomic) IBOutlet UITextField *textUse;//文本框1连线 @property (weak, nonatomic) IBOutlet UITextField *textPassword;//文本框2连线 @property (weak, nonatomic) IBOutlet UILabel *labelShow;//显示登陆成功的连线 @property (weak, nonatomic) IBOutlet UILabel *label;//显示输入有误的连线 @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)buttonValue:(UIButton *)sender { if ([self.textUse.text isEqualToString:@"fcp"]&&[self.textPassword.text isEqualToString:@"123"]) { self.labelShow.text=@"fcp用户登陆成功"; self.label.text=@""; }else{ self.label.text=@"用户名或密码错误"; self.labelShow.text=@"未登录"; } [self.view endEditing:YES]; self.textUse.text=nil; self.textPassword.text=nil; } //实现next功能 - (IBAction)frist:(UITextField *)sender { //文本框1连线,实现点回车到next功能 [self.textPassword becomeFirstResponder]; } - (IBAction)done:(UITextField *)sender { [self.view endEditing:YES]; } @end ===================================================================== 知识点 六、UIAlertView、UIActionSheet 1.UIAlertView(警告框) 1.1 创建警告框,设置样式 - (IBAction)alertView:(UIButton *)sender {//创建button按钮 //创建警告框的实例 //UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"警告" message:@"提示信息message" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; //如有多个otherButtonTitles,先显示otherButtonTitles。otherButtonTitles有一个,cancelButtonTitle在左边 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"警告" message:@"提示信息message" delegate:nil cancelButtonTitle:@"NO" otherButtonTitles:@"YES",nil]; //显示警告框 [alert show];//系统自带show方法 } 1.2创建有提示信息输入的警告框 - (IBAction)alertViewInput:(id)sender { //创建警告框 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"title" message:@"enter your login info" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; //设置警告框的样式 alert.alertViewStyle = UIAlertViewStylePlainTextInput; //显示警告框 [alert show]; } 1.3创建有提示信息输入的警告框 UIAlertViewStyleDefault UIAlertViewStyleSecureTextInput,//单行密码形式 UIAlertViewStylePlainTextInput, //单行正常形式 UIAlertViewStyleLoginAndPasswordInput//用户名和密码 alert.alertViewStyle = UIAlertViewStylePlainTextInput; 1.4 如何获取用户在警告框上的选择——委托 a)什么是委托: 一个对象(对象A)让另一个对象(对象B)帮它做事情(发消息)。 b)委托协议: 是委托方要求代理方所符合的规则,这些规则对应的就是一组方法,并且每个方法的第一个参数都是委托方的引用,每个方法的名称用于描述方法的执行时机 c)设置控制器实例成为alertView的代理方的步骤 1)控制器遵守协议//委托方定义协议的名称要求"委托方name+Delegate" 2)控制器实现协议中的方法//要想成为代理方,必须满足委托方定义的协议 //第一个参数永远是委托方的引用,点进协议直接复制 3)在创建UIAlertView时设定控制器实例为代理方法 例:通过输入用户名和密码信息,点击按钮。取出用户名和密码 /*1.设置控制器成为警告框的代理,需要控制器(代理方)遵守协议*/ @interface AlertViewController ()<UIAlertViewDelegate> @end @implementation AlertViewController - (IBAction)alertViewDelegate:(id)sender { //3.设置了警告框的代理方为当前控制器实例,于是,当用户点击了警告框上的某个按钮时该动作的处理就交给了控制器实例来响应 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"title" message:@"your choice" delegate:self cancelButtonTitle:@"NO" otherButtonTitles:@"YES",nil]; //self alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput; [alert show]; } /*2.设置控制器成为警告框的代理,实现协议中的方法选择哪个方法实现,根据不同的方法对应的执行时机可以从方法名判断发消息的时机。 方法的第一个参数一定是委托方的引用 */ - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { //目标:当点击YES按钮时,在控制器打印输入的用户名和密码 if (alertView.cancelButtonIndex != buttonIndex) { //获取用户名 NSString *loginName = [alertView textFieldAtIndex:0].text; //获取密码 NSString *pwd = [alertView textFieldAtIndex:1].text; NSLog(@"name:%@ , pwd:%@",loginName,pwd); } 结果: name:ggfg , pwd:sgg 1.5 如何区分用户点击的按钮 在 -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex方法中,第二个参数为点击的按钮的索引,可以使用以下几种方法进行判断 方法一:直接判断索引值区分不同的按钮 方法二:根据索引值获取按钮的title,进行区分 方法三:判断索引是否是cancelButtonIndex进行区分 //根据点击的按钮的索引获取点击的按钮的标题 NSString *title = [alertView buttonTitleAtIndex:buttonIndex]; 方法1:判断标题来区分不同的动作 if ([title isEqualToString:@"YES"]) { // NSLog(@"点击了YES按钮");//根据点击了按钮OK执行的动作 }else{ // NSLog(@"点击了NO按钮"); } 方法3:也可以通过判断是不是cancel按钮的索引 //来判断是否点击了cancel按钮 if (alertView.cancelButtonIndex == buttonIndex) { // NSLog(@"点击了NO按钮"); } }    1.6 如何获取alertView中输入框内的文本 利用alertView的textFieldAtIndex:方法,获得不同索引位置上的文本框,然后反问text属性即可 NSString *pwd = [alertView textFieldAtIndex:1].text; 2.UIActionSheet(操作表) 2.1 创建操作表 //创建actionSheet的实例 UIActionSheet *sheet = [[UIActionSheet alloc]initWithTitle:nil delegate:self cancelButtonTitle:@"cancel" destructiveButtonTitle:@"destructive" otherButtonTitles:@"微博",@"微信",@"朋友圈", nil]; //显示actionSheet [sheet showInView:self.view]; 2.2 判断用户点击的不同的按钮 a)需要控制器实例遵守协议 b)需要控制器实现协议中的方法 #import "ActionSheetViewController.h" @interface ActionSheetViewController ()<UIActionSheetDelegate>//遵守协议 @end - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { //区分点击的按钮 //NSLog(@"%d",buttonIndex);//获取按钮标题对应的值 //获取按钮上的标题 //NSLog(@"%@",[actionSheet buttonTitleAtIndex:buttonIndex]); if (actionSheet.cancelButtonIndex == buttonIndex) { //....点击了cancel } if (actionSheet.destructiveButtonIndex == buttonIndex) { //....点击了有破坏性的那个危险按钮 } }  ===================================================================== 知识点 七、MVC 界面开发 1.什么是设计模式 mvc只是其中一种,对某一类具体问题,总结出来的一套最优的解决方案 1.MVC: 1.Model(模型) View(视图)Controller(控制器) 的缩写 Model:程序中处理数据逻辑 (数据存储、业务逻辑、多线程、网络传输、文件存储) View:程序中处理数据显示 Controller:View和Model的媒介 2.优点: 1.耦合性低 2.重用性高 3.可维护性高 (结构清晰、可重用、方便维护) ***1.对引用数据类型,在保证在第一次访问改属性时,数组空间被创建出来。所以就得重写属性get和set方法: //重写suit属性的set方法 -(void)setSuit:(NSString *)suit{ if ([[Card allSuit]containsObject:suit]) {Card类,+(NSArray*)allSuit; _suit=suit; } } //重写cardInfo属性的get方法 -(NSString*)cardInfo{ _cardInfo=[self.suit stringByAppendingString:self.rank]; return _cardInfo; } //保证在第一次访问改属性时,数组空间被创建出来 -(NSMutableArray *)allCards{ if (!_allCards) { _allCards=[NSMutableArray array]; } return _allCards; } **2.随机数 随机数从0开始的一个无符号正整数 unsigned int index=arc4random()%52 0-51 特点:不需要设置随机算子 **3.lazy loading懒加载 例: MVC案例(重在体会) 里程碑1: 能够随机出12张纸牌,将纸牌信息显示到界面上 里程碑2: 根据用户选中的纸牌,进行判断,生成新的结果,将结果显示到界面上 里程碑3: 再根据游戏规则统计分数 创建文件夹model: Card.h #import <Foundation/Foundation.h> /* 用于描述一张纸牌 属性: 花色,大小,牌面信息,朝向,是否匹配 方法: 无 */ @interface Card : NSObject @property(nonatomic,strong)NSString *suit;//花色 @property(nonatomic,strong)NSString *rank;//大小 @property(nonatomic,strong,readonly)NSString *cardInfo; @property(nonatomic,getter=isFaceUp)BOOL faceUp; @property(nonatomic,getter=isMatched)BOOL matched; -(instancetype)initWithSuit:(NSString *)suit andRank:(NSString *)rank; +(NSArray *)allSuit; +(NSArray *)allRank; @end Card.m #import "Card.h" @interface Card () @property(nonatomic,strong,readwrite)NSString *cardInfo; @end @implementation Card //重写suit属性的set方法 - (void)setSuit:(NSString *)suit{ if ([[Card allSuit] containsObject:suit]) { _suit = suit; } } //重写rank属性的set方法 - (void)setRank:(NSString *)rank{ if ([[Card allRank] containsObject:rank]) { _rank = rank; } } //重写cardInfo属性的get方法 - (NSString *)cardInfo{ _cardInfo = [self.suit stringByAppendingString:self.rank]; return _cardInfo; } - (instancetype)initWithSuit:(NSString *)suit andRank:(NSString *)rank{ self = [super init]; if (self) { self.suit = suit; self.rank = rank; self.faceUp = NO; self.matched = NO; } return self; } + (NSArray *)allSuit { return @[@"♠️",@"❤️",@"♣️",@"♦️"]; } + (NSArray *)allRank { return @[@"A",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"J",@"Q",@"K"]; } @end Poker.h #import <Foundation/Foundation.h> /*用于描述一副扑克牌,能够容纳52张纸牌对象*/ @interface Poker : NSObject @property(nonatomic,strong)NSMutableArray *allCards; @end Poker.m #import "Poker.h" #import "Card.h" @implementation Poker //重写allCards属性的get方法 //保证在第一次访问该属性时,数组空间被创建出来 - (NSMutableArray *)allCards{ if (!_allCards) { _allCards = [NSMutableArray array]; } return _allCards; } -(id)init{ self = [super init]; if (self) { //创建52张纸牌对象,并放入到allCards中 for (NSString *suit in [Card allSuit]) { for (NSString *rank in [Card allRank]) { Card *card = [[Card alloc]initWithSuit:suit andRank:rank]; [self.allCards addObject:card]; } } } return self; } @end Poker.h #import <Foundation/Foundation.h> #import "Poker.h" /* 用于描述游戏类,存储游戏的数据, 及对数据的处理逻辑 */ @interface Game : NSObject @property(nonatomic,strong)NSMutableArray *randomCards; @property(nonatomic)NSInteger score; -(instancetype)initWithCountCard:(NSInteger)count inPoker:(Poker *)poker; -(void)tapCardAtIndex:(NSInteger)index; @end Poker.m #import "Game.h" #import "Card.h" @implementation Game - (NSMutableArray *)randomCards{ if (!_randomCards) { _randomCards = [NSMutableArray array]; } return _randomCards; } -(instancetype)initWithCountCard:(NSInteger)count inPoker:(Poker *)poker{ self = [super init]; if (self) { //根据指定的count作为随机的次数 //从poker中随机一张牌,将牌放入到randomCards for (NSInteger i=0; i<count; i++) { //使用随机函数得到一个0-51的下标 unsigned int index = arc4random()%poker.allCards.count; //从poker中找到随机位置对应的牌 Card *card = poker.allCards[index]; //将牌从poker中移除 [poker.allCards removeObject:card]; //记录牌到randomCards中 [self.randomCards addObject:card]; } self.score=0; } return self; } /* 1.获取index位置上的card对象 2.如果card面儿朝上,则修改为面儿朝下 3.如果card面儿朝下,首先修改为面儿朝上 将card与数组中其他的(已经朝上并且还没有被matched)牌进行比对 4.比对的原则: 如果两张牌的花色相同,则两张牌被matched 如果两张牌的大小相同,则两张牌被matched 否则,将被比对的牌翻回背面即可 */ - (void)tapCardAtIndex:(NSInteger)index{ Card *card = self.randomCards[index]; if (card.isFaceUp) { card.faceUp = NO; }else{ card.faceUp = YES; for (NSInteger i=0;i<self.randomCards.count;i++) { if (i != index) { Card *otherCard = self.randomCards[i]; if (otherCard.isFaceUp && !otherCard.isMatched) { //比对花色 if ([card.suit isEqualToString:otherCard.suit]) { card.matched = YES; otherCard.matched = YES; self.score+=1; }else if([card.rank isEqualToString:otherCard.rank]){ card.matched = YES; otherCard.matched = YES; self.score+=4; }else{ otherCard.faceUp = NO; } } } } } } @end GameViewController.h 继承ViewController的控制器 GameViewController.m #import "GameViewController.h" #import "Game.h" #import "Poker.h" #import "Card.h" @interface GameViewController () @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *buttons; //构成游戏而增加的属性 @property(nonatomic,strong)Game *game; @property(nonatomic,strong)Poker *poker; @property (weak, nonatomic) IBOutlet UILabel *scoreLabel; @end @implementation GameViewController //通过重写属性的get方法,实现lazy loading - (Poker *)poker{ if (!_poker) { _poker = [[Poker alloc]init]; } return _poker; } - (void)viewDidLoad { [super viewDidLoad]; self.game = [[Game alloc]initWithCountCard:self.buttons.count inPoker:self.poker]; [self updateCard]; self.scoreLabel.text=@"0"; } //更新Model中的牌信息到界面上 -(void)updateCard{ //遍历每一个按钮,根据按钮的坐标找到位置相同的随机的纸牌,并显示 for (NSUInteger index = 0; index<self.buttons.count; index++) { //获取该位置的纸牌对象 Card *card = self.game.randomCards[index]; UIButton *button = self.buttons[index]; [button setTitle:[self titleForCard:card] forState:UIControlStateNormal]; [button setBackgroundImage:[UIImage imageNamed:[self imageNameForCard:card]]forState:UIControlStateNormal]; button.enabled = !card.isMatched; } //更新分数标签 self.scoreLabel.text=[NSString stringWithFormat:@"%d",self.game.score]; } //根据纸牌信息返回按钮上要显示的文字 -(NSString *)titleForCard:(Card *)card{ return card.isFaceUp?card.cardInfo:@""; } //根据纸牌信息返回按钮上要显示的图片 -(NSString *)imageNameForCard:(Card *)card{ return card.isFaceUp?@"cardfront.png":@"cardback.png"; } - (IBAction)chooseCard:(UIButton *)sender { NSInteger index = [self.buttons indexOfObject:sender]; //将索引值传递给Model [self.game tapCardAtIndex:index]; //更新界面 [self updateCard]; } @end AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "GameViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; GameViewController *vc = [[GameViewController alloc]initWithNibName:@"GameViewController" bundle:nil]; self.window.rootViewController = vc; [self.window makeKeyAndVisible]; return YES; }  ================================================================================================================ 知识点 八、多MVC开发 ( 多界面开发) 1.多MVC 每一个界面的显示都是一套独立的MVC,由于应用程序需要多个界面,所以构成了多套MVC。 注意:其中C和V是绑在一起的,但是M由于实现了程序中的数据存储以及业务逻辑,是与C和V分开的一套体系,所以多套C+V组合,可以共用一个M。但是,不允许v的共用,每一个c都有自己的v,不能因为要切换界面,而让某一个c抛弃自己带的v,换别的c下面的v。 1.1 多界面的切换 原理:更换了c就实现了更换了v 1.2 如何实现c的更换? 方向:从controlA —> 推出controlB [controlA presentViewController:] 方向:A推出B之后,想从B再回到A [controlB dismissViewController:]; 例: 创建两个控制器类A和B,每个类的xib界面拉入一个button按钮,然后添加方法。 功能:点击A界面的按钮回到B界面。点击B界面按钮返回到A 界面 FristViewController.h FristViewController.m #import "FristViewController.h" #import "SecondViewController.h" @interface FristViewController () @end @implementation FristViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)gotoSecondView:(id)sender {//A界面的方法 //创建要推出的vc的实例 SecondViewController* secondVc=[[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil]; //从当前控制器下方推出新的vc [self presentViewController:secondVc animated:YES completion:nil]; } SecondViewController.h SecondViewController.m #import "SecondViewController.h" @interface SecondViewController () @end @implementation SecondViewController - (void)viewDidLoad { [super viewDidLoad]; } //返回到第一个界面 - (IBAction)goBack:(id)sender {//B界面的方法 [self dismissViewControllerAnimated:YES completion:nil]; } @end 2.界面之间的正向传值 2.1 什么是正向传值: 当从控制器A推出新的控制器B的时候,A将界面中接受的数据同时也传给了B,由B进行展示或处理的过程 2.2 如何实现正向传值: step1:为控制器B增加公开的属性用于接收外界传入的值 step2:控制器A为了推出B,会创建B的实例,创建完实例后,在推出之前,将要传递的属于存到B公开的属性中即可 step3:推出的控制器B在viewWillAppear中将数据展示到界面中 例: 控制器A界面的内容可以传到B界面显示 FristViewController.h FristViewController.m #import "FristViewController.h" #import "SecondViewController.h" @interface FristViewController () @property (weak, nonatomic) IBOutlet UILabel *textField;//界面1中的文字信息属性 连线A中的 @end @implementation FristViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)gotoSecondView:(id)sender {//A界面的方法 //创建要推出的vc的实例 SecondViewController* secondVc=[[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil]; //将文本框的值赋到的secondVc公开属性中 secondVc.content=self.textField.text; //从当前控制器下方推出新的vc [self presentViewController:secondVc animated:YES completion:nil]; } SecondViewController.h #import <UIKit/UIKit.h> @interface SecondViewController : UIViewController @property(nonatomic,strong)NSString*content; //公开属性 @end SecondViewController.m #import "SecondViewController.h" @interface SecondViewController () @property (weak, nonatomic) IBOutlet UILabel *label;//界面2的文本属性 连线B界面中的label @end @implementation SecondViewController //创建视图时被执行一次 - (void)viewDidLoad { [super viewDidLoad]; self.label.text=self.content; } //视图显示之前被执行,可以执行多次 -(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; //显示公开的属性 self.label.text=self.content; } //返回到第一个界面 - (IBAction)goBack:(id)sender {//B界面的方法 [self dismissViewControllerAnimated:YES completion:nil]; } @end 3.界面之间的反向传值 3.1 什么是反向传值 ? 从A推出了B之后,当从B返回到(dismiss)推出它的A时,传递了数据回来,由A进行显示的过程 3.2 如何实现 step1:B中公开一个可以接收A引用的属性aVC step2:A中公开一个可以接收返回数据的属性message step3:A推出B之前,将自己的引用传给B step4:B在dismiss之前,将要返回的数据传给持有的A的引用中公开的message属性 step5:在A的viewWillAppear中,显示message的内容 例: B界面的内容返回到A界面 1.方法一:缺点耦合度太高 AViewController.h #import <UIKit/UIKit.h> @interface AViewController : UIViewController @property(nonatomic,strong)NSString *message;公开属性 @end AViewController.m #import "AViewController.h" #import "BViewController.h" @interface AViewController () @property (weak, nonatomic) IBOutlet UILabel *label; 连线label,显示返回的值 @end @implementation AViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; //呈现界面之前将message内的数据显示到标签上 self.label.text = self.message; } - (IBAction)gotoBViewController:(id)sender { BViewController *bVC = [[BViewController alloc]initWithNibName:@"BViewController" bundle:nil]; //将当前控制器(A)引用传给B bVC.aVC = self; [self presentViewController:bVC animated:YES completion:nil]; } @end BViewController.h #import <UIKit/UIKit.h> #import "AViewController.h" @interface BViewController : UIViewController //公开一个属性,存放A的引用 @property(nonatomic,strong)AViewController *aVC; @end BViewController.m #import "BViewController.h" @interface BViewController () @property (weak, nonatomic) IBOutlet UITextField *textField; 连线文本框,B界面输入的内容 @end @implementation BViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)goback:(id)sender { self.aVC.message = self.textField.text; [self dismissViewControllerAnimated:YES completion:nil]; } @end 2.方法二: 4.使用 委托 实现 反向传值 委托方:推出的B 代理方:推出B的那个A 委托方要做的三件事: .h文件 a。定义协议1)协议名称 : 类名+Delegate 2)方法的第一个参数一定是委托方自己 3)方法名尽量体现发消息的时机 .h文件 b。添加delegate属性 @property(nonatomic,weak)id<BViewControllerDelegate> delegate; .m文件c。选择合适的时机给代理发消息 代理方要做的三件事: a。遵守协议 b。实现方法 c。将自己设置为代理方 AViewController.h AViewController.m #import "AViewController.h" #import "BViewController.h" //代理方要做的三件事 //1.遵守协议 @interface AViewController ()<BViewControllerDelegate> @property (weak, nonatomic) IBOutlet UILabel *label; @end @implementation AViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)gotoB:(id)sender { BViewController *bVC = [[BViewController alloc]initWithNibName:@"BViewController" bundle:nil]; //3.将自己设置为bVC的代理方 bVC.delegate = self; [self presentViewController:bVC animated:YES completion:nil]; } //2.实现方法 - (void)bViewController:(BViewController *)bVC inputFinishedWithMessage:(NSString *)message{ self.label.text = message; } BViewController.h #import <UIKit/UIKit.h> @class BViewController; //1.定义协议 /* 要点: 1)协议名称 : 类名+Delegate 2)方法的第一个参数一定是委托方自己 3)方法名尽量体现发消息的时机 */ @protocol BViewControllerDelegate <NSObject> -(void)bViewController:(BViewController *)bVC inputFinishedWithMessage:(NSString *)message; @end @interface BViewController : UIViewController //2.添加一个公开的delegate属性 @property(nonatomic,weak)id<BViewControllerDelegate> delegate; @end BViewController.m #import "BViewController.h" @interface BViewController () @property (weak, nonatomic) IBOutlet UITextField *textField; @end @implementation BViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)goBack:(id)sender { //3.合适的时机,给代理方发消息 [self.delegate bViewController:self inputFinishedWithMessage:self.textField.text]; [self dismissViewControllerAnimated:YES completion:nil]; } @end 作业: 1.作业1参考图片 homework1.png 2.星座运程App a。界面1:有一个按钮“请选择您的星座”,用户点击后,跳转到第二个界面 b。界面2:有12个星座(可以做成12个按钮)可选,选定后,返回到第一个界面 c。界面1:显示选择的那个星座的运程 AViewController.h AViewController.m #import "AViewController.h" #import "StarViewController.h" @interface AViewController ()<StarViewControllerDelegate> @property (weak, nonatomic) IBOutlet UILabel *resultLabel;连线返回值label的属性 @end @implementation AViewController - (void)starViewController:(StarViewController *)sVC chooseStarWithMessage:(NSString *)mes{ self.resultLabel.text = mes; } - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)chooseStar:(id)sender {连线按钮的点击方法 StarViewController *svc = [[StarViewController alloc]initWithNibName:@"StarViewController" bundle:nil]; svc.delegate = self; [self presentViewController:svc animated:YES completion:nil]; } @end StarViewController.h #import <UIKit/UIKit.h> @class StarViewController; @protocol StarViewControllerDelegate <NSObject> -(void)starViewController:(StarViewController *)sVC chooseStarWithMessage:(NSString *)mes; @end @interface StarViewController : UIViewController @property(nonatomic,weak)id<StarViewControllerDelegate> delegate; @end StarViewController.m #import "StarViewController.h" @interface StarViewController () @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *buttons; 连线建立4个星座的属性 @property(nonatomic,strong)NSArray *array; @end @implementation StarViewController //重写array属性的get方法 - (NSArray *)array{ if (!_array) { _array = @[@"恭喜发财",@"万事如意",@"顺风顺水",@"新年快乐"]; } return _array; } - (IBAction)chooseStar:(UIButton *)sender { 连线建立4个星座的方法 NSInteger index = [self.buttons indexOfObject:sender]; [self.delegate starViewController:self chooseStarWithMessage:self.array[index]]; [self dismissViewControllerAnimated:YES completion:nil]; } 3.文本创建器 a。界面1:有一个按钮“创建文本”,点击后进入到界面2 b。界面2: x:[TextField] width:[TextField] y:[TextField] height:[TextField] text:[TextField] 【确定按钮】 当用户点击确认按钮后,返回到界面1 c。界面1:根据用户刚才的输入,创建一个UILabel对象,label的frame根据刚才的输入确定,label的内容也是根据输入确定,将label加入到界面1中 FirstViewController.h FirstViewController.m #import "FirstViewController.h" #import "SecondViewController.h" @interface FirstViewController ()<SecondViewControllerDelegate> @property(nonatomic,assign)NSInteger x; @property(nonatomic,assign)NSInteger y; @property(nonatomic,assign)NSInteger w; @property(nonatomic,assign)NSInteger h; @end @implementation FirstViewController -(void)secondViewController:(SecondViewController *)secondVC sendX:(NSString *)x sendY:(NSString *)y sendWidth:(NSString *)width sendHeight:(NSString *)height sendTextField:(NSString *)textField{ self.x=[x intValue] ; self.y=[y intValue] ; self.w=[width intValue] ; self.h=[height intValue] ; UILabel* label=[[UILabel alloc]initWithFrame:CGRectMake(self.x, self.y, self.w, self.h)]; label.text=textField; [self.view addSubview:label]; } - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)gotoSecond:(UIButton *)sender { 连线创建文本按钮 SecondViewController* second = [[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil]; second.delegate = self; [self presentViewController:second animated:YES completion:nil]; } @end SecondViewController.h c#import <UIKit/UIKit.h> @class SecondViewController; @protocol SecondViewControllerDelegate <NSObject> -(void)secondViewController:(SecondViewController*)secondVC sendX:(NSString*)x sendY:(NSString*)y sendWidth:(NSString*)width sendHeight:(NSString*)height sendTextField:(NSString*)textField; @end @interface SecondViewController : UIViewController @property(nonatomic,weak)id<SecondViewControllerDelegate> delegate; @end SecondViewController.m #import "SecondViewController.h" @interface SecondViewController () @property (weak, nonatomic) IBOutlet UITextField *x; @property (weak, nonatomic) IBOutlet UITextField *width; @property (weak, nonatomic) IBOutlet UITextField *y; @property (weak, nonatomic) IBOutlet UITextField *height; @property (weak, nonatomic) IBOutlet UITextField *textField; 连线5个文本框 @end @implementation SecondViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)goBack:(UIButton *)sender { 连线确定按钮 [self.delegate secondViewController:self sendX:self.x.text sendY:self.y.text sendWidth:self.width.text sendHeight:self.height.text sendTextField:self.textField.text]; [self dismissViewControllerAnimated:YES completion:nil]; } @end ========================================================================= 知识点 九、UINavigationController(导航控制器) 1.UINavigationControlle 1.1 是什么? 继承自UIViewController,依然是一种控制器,但是,这种控制器没有具体的view,是管理控制器的控制器 1.2 优点? 能够管理和控制VC的走向,比present方式更清晰 1.3 如何使用? step1:创建UINavigationController的实例 step2:创建一个具体的vc实例,并将这个vc设置为UINavigationController的根视图控制器 step3:设置navigationController为window的根视图控制器 step4:想推出新的vc时,可以使用pushViewController的方法 step5:想回退到上一个vc时,可以不写代码;或者是使用popViewController的方法 1.4 内部原理 1)navi内部有一个可以存储多个vc的数组,就是self.navigationController.viewControllers属性;并且这个数组使用“栈”的方式来管理数据。“栈”的特点:先进后出,后进先出。 2)navi必须 有一个根视图控制器作为第一个展示的vc 3)push出一个新的vc时,就是往栈属性中入栈一个vc对象,新的vc入栈之前显示的那个vc不会被释放 4)pop现有vc时,才是将这个vc释放掉 5)不能pop根vc 例: A界面退出B,B返回A AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "AViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window=[[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; AViewController* aVC=[[AViewController alloc]initWithNibName:@"AViewController" bundle:nil]; //创建导航控制器的实例 UINavigationController*navi=[[UINavigationController alloc]initWithRootViewController:aVC]; //将navi设置为window的跟视图 self.window.rootViewController=navi; [self.window makeKeyAndVisible]; return YES; } AViewController.h AViewController.m #import "AViewController.h" #import "BViewController.h" @interface AViewController () @end @implementation AViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)gotoB:(id)sender { BViewController* bVC=[[BViewController alloc]initWithNibName:@"BViewController" bundle:nil]; [self.navigationController pushViewController:bVC animated:YES];//通过navigationController属性退出B界面 } @end BViewController.h BViewController.m #import "BViewController.h" @interface BViewController () @end @implementation BViewController - (void)viewDidLoad { [super viewDidLoad]; } //返回(也可以不写,通过navigationController自带的back返回) - (IBAction)goback:(id)sender { [self.navigationController popViewControllerAnimated:YES]; } @end 2.配置导航栏 只针对当前的界面 1.访问导航栏:self.navigationItem 2.导航栏包含三部分: 1)左侧的按钮区域 self.navigationItem.leftBarButtonItem/s self.navigationItem.leftBarButtonItem=r;方法同右侧 2)中间的title self.title = @“”; 中间title部分:在viewDidLoad中配置导航栏标题,在哪个界面显示就配置的哪个界面的标题栏 - (void)viewDidLoad { [super viewDidLoad]; //配置导航栏标题 self.title=@"A界面"; } 3)右侧的按钮区域 self.navigationItem.rightBarButtonItem/s - (void)viewDidLoad { [super viewDidLoad]; //配置导航栏标题 self.title=@"A界面"; //配置导航栏右侧按钮内容 UIBarButtonItem* r=[[UIBarButtonItem alloc]initWithTitle:@"下一个" style:UIBarButtonItemStyleDone target:self action:@selector(gotoB:)]; //self.navigationItem.rightBarButtonItem=r; UIBarButtonItem* r2=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:nil action:nil];//系统自带显示图标 搜索 self.navigationItem.rightBarButtonItems=@[r,r2]; 4)按钮的类型:UIBarButtonItem类型 可以使用initWithTitle。。方法创建自定义 文本内容的按钮 可以使用initWithBarButtonSystemItem…方法创建系统定义好的,有固定外观的按钮 3.配置工具栏 默认是全局的 1. 访问工具栏:self.toolBarItem 2.工具栏中加载的也是UIBarButtonItem类型的按钮 3.将默认隐藏的工具栏显示出来,默认是隐藏 self.navigationController.toolbarHidden = NO; 1)只在一个界面显示,其他界面隐藏 ( 需要在其他界面加上self.navigationController.toolbarHidden = YES;) //和显示有关,和创建没有关系 -(void)viewWillAppear:(BOOL)animated{ //将默认隐藏的工具栏显示出来 self.navigationController.toolbarHidden = NO; } 2)设置推出bvc时,底部区域所有bar隐藏 (其他界面不需要修改) 在需要设置导航的界面,通过viewDidLoad方法显示出来,然后在创建推出其它界面时隐藏bvc.hidesBottomBarWhenPushed=YES; - (IBAction)gotoBViewController:(id)sender { BViewController *bvc = [[BViewController alloc]initWithNibName:@"BViewController" bundle:nil]; //设置推出bvc时,底部区域隐藏 bvc.hidesBottomBarWhenPushed=YES; [self.navigationController pushViewController: bvc animated:YES]; } 4.特效按钮:木棍(固定的) 调整工具栏的距离,一般放在最左、最右。可以设置宽度width UIBarButtonSystemItemFixedSpace 5.特效按钮:弹簧(随着之间的距离自动调整) 放在两个对象之间 例:暂停,前进,后退按钮显示在工具栏中。 - (void)viewDidLoad { [super viewDidLoad]; //将默认隐藏的工具栏显示出来 self.navigationController.toolbarHidden = NO; //配置工具栏 UIBarButtonItem *item1 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:nil action:nil]; UIBarButtonItem *item2 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target:nil action:nil]; UIBarButtonItem *item3 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFastForward target:nil action:nil]; //特效按钮:木棍 UIBarButtonItem *item4 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; item4.width = 40; //特效按钮:弹簧 UIBarButtonItem *item5 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; self.toolbarItems = @[item4,item2,item5,item1,item5,item3,item4]; } @end 4.多个导航之间切换 是当前界面的导航跳转到另一个界面的导航,导航与导航之间的切换(从下面推出)。此时就不用push 和pop 来推出和返回了(从左面推出) 1.推出时修改为: UINavigationController*navi2=[[UINavigationController alloc]initWithRootViewController:bvc]; [self.navigationController presentViewController:navi2 animated:YES completion:nil]; 2.返回到推出的界面 [self.navigationController dismissViewControllerAnimated:YES completion:nil]; 小结:导航控制器可以设置的属性的作用于范围 属性: .title .navigationItem.leftBarButtonItem/s .navigationItem.rightBarButtonItem/s .toolbarItems 以上四个属性的设置只负责当前所属的vc 属性: .navigationController.toolbarHidden 设置后,针对导航控制器管理的所有vc都生效 *** 问:在不同的vc中都可以访问self.navigationController,那么是同一个导航控制器吗? 答:是   推出的界面, =============================================================================== 知识点 十、UIImageView 1.数据类型:NSString —>UILabel 显示 UIImage—>UIImageView 显示 2. 如何使用 #import "MyViewController.h" @interface MyViewController () @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; //创建图片 UIImage *image = [UIImage imageNamed:@"Elephant.jpg"];//图片名称 //创建图片控件,此时imageView的尺寸和创建时使用的图片的尺寸一样大 UIImageView *imageView = [[UIImageView alloc]initWithImage:image]; //设置图片view的frame imageView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);//一定要设置尺寸,不然不会显示 //设置imageView为圆角 imageView.layer.cornerRadius = 30; imageView.layer.masksToBounds = YES; //设置图片view的内容显示方式 imageView.contentMode = UIViewContentModeScaleAspectFit; //将图片控件添加到视图中 [self.view addSubview:imageView]; } @end 3.拥有属性 1.属性: contentMode用于设置view内容显示的方式 1)UIViewContentModeScaleToFill: 修改宽高比,适应imageView的区域大小,图片会被拉伸,不留白边 2)UIViewContentModeScaleAspectFit: 维持宽高比不变的情况下,将整张图片可见,由于图片的宽高比和设置的imageView的frame的宽高比如果不协调的话,可能会留白边儿。 3)UIViewContentModeScaleAspectFill: 保持宽高比不变的情况下,将imageView所占的区域填满,所以只会显示图片的一部分,不会留白 2.属性: layer.cornerRadius设置圆角的半径 layer.masksToBounds开启按边缘遮罩 =========================================================================== 知识点 十一、UIScrollView 1 .作用: 在有限的区域内,显示更多的数据或图片 2 .本质: 管理view的view,scrollView本身没有任何的外观,依靠添加到scrollView中的其他视图来完成界面的显示 3 .如何使用 //imageView尺寸比较大,与图片一样大 UIImageView* iV=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Elephant.jpg"]]; UIScrollView*sV=[[UIScrollView alloc]init];//创建scrollView的实例 sV.frame=CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);//设置scrollView的frame [sV addSubview:iV];//将图片控件添加到scrollView中 [self.view addSubview:sV]; //将滚动视图添加的view中 4.重要的属性: .frame 设置scrollView用多大的窗口来显示内容 .contentSize设置了可滚动的区域的大小 .contentOffset设置frame定点与内容的左顶点的偏移坐标 .contentInset设置内容与边界之间的上、左、下、右的距离 其他属性: .bounces 是否可以边缘弹跳 .showsHorizontalScrollIndicator .showsVerticalScrollIndicator .indicatorStyle 1. //设置scrollView可滚动查看的内容的区域大小 scrollView.contentSize = imageView.frame.size; //设置滚动视图不可以弹跳 scrollView.bounces = NO; //设置水平滚动条是否显示 scrollView.showsHorizontalScrollIndicator = NO; //设置竖直滚动条是否显示 scrollView.showsVerticalScrollIndicator = NO; //设置滚动条颜色 scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite; 2.//设置导航框,点击移动按钮,便可以跳到图片的设定范围 self.title = @"scrollView"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"移动" style:UIBarButtonItemStyleDone target:self action:@selector(move)]; -(void)move{ self.sV.contentOffset=CGPointMake(1000, 1000); self.sV.contentInset = UIEdgeInsetsMake(300, 300, 300, 300); } 5.如何实现滚动视图内容的缩放 step1:设置滚动内容缩放的最大比率 step2:设置滚动内容缩放的最小比率 step3:回答问题,说明scrollView里面的哪个子视图需要缩放 //设置最大比率 scrollView.maximumZoomScale = 1; CGFloat xScale = scrollView.frame.size.width/imageView.frame.size.width; CGFloat yScale = scrollView.frame.size.height/imageView.frame.size.height; //设置最小比率 scrollView.minimumZoomScale = MIN(xScale, yScale); //设置当前控制器为scrollView的代理 scrollView.delegate = self; **需遵守协议@interface MyViewController ()<UIScrollViewDelegate> //返回要缩放的视图 遵守协议 - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{ return self.imageView; } 6.UIPageControl 界面下方小圆点 //创建pageControl UIPageControl *pageControl = [[UIPageControl alloc]init]; pageControl.frame = CGRectMake(0, self.view.frame.size.height-20-30, self.view.frame.size.width, 30); pageControl.numberOfPages = self.imageNames.count; //设置圆点的颜色 pageControl.pageIndicatorTintColor = [UIColor whiteColor]; //设置被选中的圆点的颜色 pageControl.currentPageIndicatorTintColor = [UIColor redColor]; //关闭用户交互功能 pageControl.userInteractionEnabled = NO; [self.view addSubview:pageControl]; 作业: 1.视力检查器 a。界面1:程序开始时,有一个检查视力的字母”E”一个Label显示E,font属性比较大.=[UIFont systemFontOfSize:100],界面下方有两个按钮,分别是看的清,看不清 b。点击看的清,则推出第二个界面,第二个界面和第一个界面几乎一样,唯一不同的时E变小了,大小变成95 c。点击看的清,继续推出第三个界面,E的字体继续变小,90 。。。 85 。。。 80.。。 d。直到用户点击了看不清,告诉他,视力是多少 要求:必须是使用UINavigationController来控制vc的跳转,每次应该推出新的vc对象,而不是修改原来的vc对象 AppDelegate.h #import <UIKit/UIKit.h> @interface EViewController : UIViewController @property(nonatomic)CGFloat fontSize;//公开的属性,字母的大小 @end AppDelegate.m #import "AppDelegate.h" #import "EViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; EViewController *evc = [[EViewController alloc]initWithNibName:@"EViewController" bundle:nil]; evc.fontSize = 100.0; UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:evc]; self.window.rootViewController = navi; [self.window makeKeyAndVisible]; return YES; } EViewController.h EViewController.m #import "EViewController.h" @interface EViewController () @property (weak, nonatomic) IBOutlet UILabel *label; @end @implementation EViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = [NSString stringWithFormat:@"%f",self.fontSize]; self.label.font = [UIFont systemFontOfSize:self.fontSize]; } - (IBAction)canSee:(id)sender { if ((self.fontSize-5)<0) { UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:@"视力太好了" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; [alert show]; return; } EViewController *evc = [[EViewController alloc]initWithNibName:@"EViewController" bundle:nil]; evc.fontSize = self.fontSize-10; [self.navigationController pushViewController:evc animated:YES]; } - (IBAction)cannotSee:(id)sender { NSString *mes = [NSString stringWithFormat:@"视力是:%f",self.fontSize/100]; UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:mes delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; [alert show]; } @end 2. 完成scrollView 对图片的缩放 3.试做如 homework.png的效果图 要求:四张图片拼接,通过滑动屏幕显示出来,同时手机下方有圆形按钮,随着滑动图片显示原点位置,同时在滑动到第四张图片时,添加一个按钮,点击按钮响应事件 WelcomeViewController.h WelcomeViewController.m #import "AppDelegate.h" #import "WelcomeViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; WelcomeViewController *vc = [[WelcomeViewController alloc]initWithNibName:@"WelcomeViewController" bundle:nil]; self.window.rootViewController = vc; [self.window makeKeyAndVisible]; return YES; } WelcomeViewController.h #import <UIKit/UIKit.h> @interface WelcomeViewController : UIViewController //图片的名称 @property(nonatomic,strong)NSArray *imageNames; @end WelcomeViewController.m #import "WelcomeViewController.h" @interface WelcomeViewController ()<UIScrollViewDelegate> @property(nonatomic,strong)UIPageControl *pageControl; @end @implementation WelcomeViewController //重写初始化方法 - (NSArray *)imageNames{ if (!_imageNames) { _imageNames = @[@"welcome1.png",@"welcome2.png",@"welcome3.png",@"welcome4.png"]; } return _imageNames; } - (void)viewDidLoad { [super viewDidLoad]; UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:self.view.frame]; //设置contentSize 大小:手机屏幕宽*4(图片的个数) scrollView.contentSize = CGSizeMake(scrollView.frame.size.width*self.imageNames.count, scrollView.frame.size.height); //将所有图片以子视图的方式添加到scrollView中 for (NSInteger i=0; i<self.imageNames.count; i++) { UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:self.imageNames[i]]]; //创建一个frame变量,并赋值 CGRect imageFrame = CGRectZero; imageFrame.size = scrollView.frame.size; imageFrame.origin.y = 0; imageFrame.origin.x = i*scrollView.frame.size.width; //将设置到好的frame变量给image imageView.frame = imageFrame; [scrollView addSubview:imageView]; } //配置scrollView //设置整页滚动 scrollView.pagingEnabled = YES; //设置边缘不弹跳 scrollView.bounces = NO; //设置水平滚动条不显示 scrollView.showsHorizontalScrollIndicator =NO; //设置scrollView的代理 scrollView.delegate = self; [self.view addSubview:scrollView]; //创建pageControl UIPageControl *pageControl = [[UIPageControl alloc]init]; self.pageControl = pageControl; pageControl.frame = CGRectMake(0, self.view.frame.size.height-20-30, self.view.frame.size.width, 30); pageControl.numberOfPages = self.imageNames.count; //设置圆点的颜色 pageControl.pageIndicatorTintColor = [UIColor whiteColor]; //设置被选中的圆点的颜色 pageControl.currentPageIndicatorTintColor = [UIColor redColor]; //关闭用户交互功能 pageControl.userInteractionEnabled = NO; [self.view addSubview:pageControl]; //为最后一屏添加按钮 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; button.frame = CGRectMake(scrollView.frame.size.width*(self.imageNames.count-1), 0, scrollView.frame.size.width, scrollView.frame.size.height); //为按钮添加点击事件 [button addTarget:self action:@selector(enterApp) forControlEvents:UIControlEventTouchUpInside]; [scrollView addSubview:button]; } //委托代理 - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ // 获取移动的偏移定点坐标 CGPoint offSet = scrollView.contentOffset; //根据坐标算出滚动到第几屏的位置下标 NSInteger index = offSet.x/scrollView.frame.size.width; self.pageControl.currentPage=index; } -(void)enterApp{ NSLog(@"........."); } @end =========================================================================== 知识点 十二、表视图 1.UITableView(表视图) 1.1 什么是表视图? 类型是:UITableView类 表现形式:以一列多行的列表形式来展示数据的视图 表视图的样式:普通表视图(Plain) 分组表视图(Group) 1.2 表视图包含的部分? +UITableView +TableHeaderView +section1(分区) +sectionHeader +UITableViewCell (行、单元格) +sectionFooter +section2(分区) +TableFooterView 其中,表头、尾,分区头、尾可以根据需要选择的设置,但是在设定表格式,单元格是必须被设置的 1.3 如何使用UITableView表视图? step1:创建tableView的实例,设置frame,以子视图的形式添加到self.view中 step2:设置tableView的dataSource代理和delegate代理为当前控制器 step3:设置控制器遵守UITableViewDataSource和UITableViewDelegate协议 step4:实现dataSource协议中的三个方法用于设定表格展示的外观 方法1:用于设定整个表格有几个分区 方法2:用于设定每个分区有几行 方法3:用于设定每个行是什么样子 step5:实现delegate协议中的一个方法用于设定表格可以对用户的点击某一行的动作的响应 注:以上协议,dataSource协议必须遵守及实现方法2和方法3,方法1有默认的设置,可以根据需要修改;delegate协议在需要响应用户点击动作时再遵守和实现方法;另,实现表视图的过程可以简称为3问1答;3问指的是实现datasource协议中的三个方法,1答指的是实现delegate协议中的一个方法 MyViewController.h #import <UIKit/UIKit.h> @interface MyViewController : UIViewController//继承自UIViewController @end MyViewController.m #import "MyViewController.h" @interface MyViewController ()<UITableViewDataSource,UITableViewDelegate> @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; //创建UITableView的实例 UITableView *tableView = [[UITableView alloc]initWithFrame:self.view.frame]; //设置表视图的数据源代理 tableView.dataSource = self; //设置表视图的代理 tableView.delegate = self; //将表视图添加到view中 [self.view addSubview:tableView]; } //问1:表格有几个分区 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } //问2:每个分区有几行 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 10; } //问3:每一行什么样 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [[UITableViewCell alloc]init]; cell.textLabel.text = @"Hello World"; return cell; } //答1:点击某一行后的响应 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSLog(@"....."); } AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "MyViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; MyViewController *vc = [[MyViewController alloc]initWithNibName:@"MyViewController" bundle:nil]; self.window.rootViewController = vc; [self.window makeKeyAndVisible]; return YES; } 2.表视图控制器(UITableIViewController) 2.1 是什么? 一种专门配置表视图的控制器 2.2特点? a)继承自UITableViewController b)已经遵守了UITableViewDataSource和UITableViewDelegate协议 c)该控制器自带的视图已经是UITableView类型的了,并且可以借助于self.tableView属性来访问自带的这个表视图 d)控制器已经成为了自带的表视图的数据源代理对象和代理对象 2.3 使用 创建表视图时,可以继承自UITableViewController,设置代理、遵守协议这些设置就都不需要单独完成了,只需要将关注点放在三问一答上即可。 MyTableViewController.h #import <UIKit/UIKit.h> @interface MyTableViewController : UITableViewController//继承自UITableViewController @end MyTableViewController.m #import "MyTableViewController.h" #import "DetailViewController.h" @interface MyTableViewController () @end @implementation MyTableViewController #pragma mark - 视图的生命周期 //方便从窗口快速定位到方法查看 - (void)viewDidLoad { [super viewDidLoad]; self.title = @"表格"; } #pragma mark - dataSource协议 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 10; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc]init]; cell.textLabel.text = @"Hello Kitty"; return cell; } #pragma mark - Table view delegate //一答 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; [self.navigationController pushViewController:detailViewController animated:YES]; } @end DetailViewController.h DetailViewController.m AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "MyTableViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; MyTableViewController *tvc = [[MyTableViewController alloc]initWithNibName:@"MyTableViewController" bundle:nil]; UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:tvc]; self.window.rootViewController = navi; [self.window makeKeyAndVisible]; return YES; } 3.多分区的UITableView(表视图) 3.1 NSIndexPath 该类型描述的是一种路径,为了定位一个单元格的位置,需要两个值,一个是分区号,一个是在分区内的行号;分区号的排序规则从0开始,单元格在每一个分区内的排序规则也是从0开始。 属性: .section 记录的是分区号 .row 记录的是行在某一个分区内的行号 MyTableViewController.h #import <UIKit/UIKit.h> @interface MyTableViewController : UITableViewController @end MyTableViewController.m - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 3; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section//分区号 { //第一个分区有三行 if (section==0) { return 3; }else if (section==1){//第二个分区有两行 return 2; }else{ return 4; } } /**/ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc]init]; //每个区 if (indexPath.section==0) {//第一个区 if (indexPath.row==0) {//第一行 cell.textLabel.text=@"hello"; }else{ cell.textLabel.text=@"Hello"; } }else if (indexPath.section==1){//第二个分区所有行的内容 cell.textLabel.text=@"hello wlord"; }else{ cell.textLabel.text=@"hello kity"; } return cell; } 3.2表头视图、表尾视图内容 一个表格中,只能有一个表头和表尾视图 通过以下两个属性进行设置: .tableView.tableHeaderView .tableView.tableFooterView - (void)viewDidLoad { [super viewDidLoad]; //表头视图 可以在表头视图添加标签、文本框、按钮等 UIView* headerView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)]; UILabel* label=[[UILabel alloc]initWithFrame:CGRectMake(100, 10, 100, 50)];//标签在视图中的位置 label.backgroundColor=[UIColor greenColor]; label.textAlignment=NSTextAlignmentCenter;//标签上的文字居中 label.text=@"header"; [headerView addSubview:label];//将标签添加到表视图 self.tableView.tableHeaderView=headerView; //self.tableView.tableFooterView=headerView; 表尾视图 } 3.3 分区头、分区尾内容 一个表格中,可以有多个分区头和分区尾,通过回答问题的方式进行设定;分区头和分区尾可以设置为简单的字符串描述,也可以设置复杂的UIView 1)第一种设定方法 //表头视图、表尾视图 -(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ if (section==0) { return @"title1";//第一个分区表视图的表头内容 }else if(section==1){ return @"title2"; }else{ return @"title3"; } } 2)第二种设定方法 -(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ //可以添加文本框、标签等 } ======================================================================================================== 4.UITableViewCell 单元格 4.1是什么? 系统定义的单元格类型,表格中的每一个都是一个UITableViewCell的实例 4.2单元格具有系统提供的默认的样式 不同的演示,对于系统默认提供的三个视图具有不同的摆放方式 四种样式: UITableViewCellStyleDefault (imageView和textLabel在最左边,不显示detailTextLabel) UITableViewCellStyleValue1 (imageView和textLabel在最左边,detailTextLabel在最右边) UITableViewCellStyleValue2 (textLabel和detailTextLabel在一行,前边空几格,不显示图片) UITableViewCellStyleSubtitle (imageView最左边,detailTextLabel在textLabel的下方) 4.3单元格具有系统提供的默认的组成视图 .textLabel 标题标签 .detailTextLabel 详情标签 .imageView 图片视图 //每行的内容 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; cell.textLabel.text=@"title"; cell.detailTextLabel.text=@"title2";//详细的内容 cell.imageView.image=[UIImage imageNamed:@"wifi.png"]; return cell; } 4.4设置单元格行高 //设置单元格行高 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 70; } 5.单元格的重用 5.1 什么是单元格的重用? 将完整超出屏幕的单元格存到队列中,屏幕一旦出现空白区域,需要单元格来填充时,先去队列中按照指定的标示图来试着取,看有没有已经用完并存在队列中的单元格,有,就拿来修改值后重新加到界面中,从队列中取不出已用完的单元格时,则新建 5.2 如何实现单元格的重用? 前提:超出屏幕的单元格由系统自动窜到队列中 具体做的内容:在回答每行内容什么样的时候,先尝试着从队列中取单元格对象,取的结果有两种,要么取到,拿来继续用,要么取不到可重用的,那么自己新建即可 ***注意:存到队列中的单元格可以有多种多样的,所以每一种进入队列的单元格都需要指定给一个标示,去队列中取单元格时,要说明按哪种标示来找一样的对象 方法一:从队列中取cell对象,自己判断是否取到了cell,没有取到时,自己用代码创建cell对象 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //重复用单元格 UITableViewCell* cell=[tableView dequeueReusableCellWithIdentifier:@"abc"]; if (cell==nil) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"abc"]; } cell.textLabel.text=@"hello"; return cell; } 方法二:viewDidLoad中提在注册单元格的类型,然后从队列中取出cell对象后,就算没有取到可重用的单元格,系统也会按照注册的cell样式创建新的cell对象 - (void)viewDidLoad { [super viewDidLoad]; //注册单元格 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"abc"]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //重复用单元格 UITableViewCell* cell=[tableView dequeueReusableCellWithIdentifier:@"abc"]; cell.textLabel.text=@"hello"; return cell; } 5.3如何进行表格的刷新,在原有的基础上添加 方法一:整体刷新 [self.tableView reloadData]; 方法二:局部刷新 //从第四行开始刷新 局部刷新 最后一行 NSIndexPath* newIndexPath=[NSIndexPath indexPathForRow:self.citys.count-1 inSection:0]; [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationTop]; 6.三问一答中的一答 6.1 推出简单的VC来显示数据详情 【Demo3_SimpleVC】 数据结构: + City : NSObject +name : NSString +population : NSInteger 要求: a。有一组城市信息,以tableView的形式来展示所有城市的列表 b。选中某一个城市后,推出新的普通vc,显示选中的城市名称和城市的人口数 CityTableViewController.h #import <UIKit/UIKit.h> @interface CityTableViewController : UITableViewController @end CityTableViewController.m #import "CityTableViewController.h" #import "City.h" #import "DetailViewController.h" @interface CityTableViewController () @property(nonatomic,strong)NSArray *citys; @end @implementation CityTableViewController //重写get方法 - (NSArray *)citys{ if (!_citys) { _citys = [City demoData]; } return _citys; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"城市列表"; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.citys.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } //根据row,去数组中取到city对象 City *city = self.citys[indexPath.row]; cell.textLabel.text = city.name; return cell; } #pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; //根据行号找到选中的城市对象 City *city = self.citys[indexPath.row]; //将city传给推出的vc来显示 detailViewController.city = city; [self.navigationController pushViewController:detailViewController animated:YES]; } @end DetailViewController.h #import <UIKit/UIKit.h> #import "City.h" @interface DetailViewController : UIViewController @property(nonatomic,strong)City *city; @end DetailViewController.m #import "DetailViewController.h" @interface DetailViewController () @property (weak, nonatomic) IBOutlet UILabel *nameLabel; 连线 @property (weak, nonatomic) IBOutlet UILabel *populationLabel; @end @implementation DetailViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"城市详情"; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; self.nameLabel.text = self.city.name; self.populationLabel.text = [NSString stringWithFormat:@"%d万",self.city.population]; } @end City.h #import <Foundation/Foundation.h> @interface City : NSObject @property(nonatomic,strong)NSString *name; @property(nonatomic)NSInteger population; -(instancetype)initWithName:(NSString *)name andPopulation:(NSInteger)population; +(NSArray *)demoData; @end City.m #import "City.h" @implementation City -(instancetype)initWithName:(NSString *)name andPopulation:(NSInteger)population{ self = [super init]; if (self) { self.name = name; self.population = population; } return self; } + (NSArray *)demoData{ City *t1 = [[City alloc]initWithName:@"北京" andPopulation:1000]; City *t2 = [[City alloc]initWithName:@"上海" andPopulation:900]; City *t3 = [[City alloc]initWithName:@"广州" andPopulation:800]; City *t4 = [[City alloc]initWithName:@"深圳" andPopulation:700]; return @[t1,t2,t3,t4]; } @end 6.2 推出tableView来显示子数据 【Demo4_TableVC】 数据结构: + City : NSObject +name : NSString +population : NSInteger +areas(区域) : NSArray (NSString) 例如: City: name:北京 population:1000 areas: @[@“东城区”,@“西城区”,@“朝阳区”] 要求: a。有一组城市信息,以tableView的形式来展示所有城市的列表 b。选中某一个城市后,推出新的tableVC,显示选中的城市的所有areas信息 City.h #import <Foundation/Foundation.h> @interface City : NSObject @property(nonatomic,strong)NSString *name; @property(nonatomic)NSInteger population; @property(nonatomic,strong)NSArray *areas;//地区 -(instancetype)initWithName:(NSString *)name andPopulation:(NSInteger)population; +(NSArray *)demoData; @end City.m #import "City.h" @implementation City -(instancetype)initWithName:(NSString *)name andPopulation:(NSInteger)population{ self = [super init]; if (self) { self.name = name; self.population = population; } return self; } + (NSArray *)demoData{ City *t1 = [[City alloc]initWithName:@"北京" andPopulation:1000]; t1.areas = @[@"东城区",@"西城区",@"海淀区"]; City *t2 = [[City alloc]initWithName:@"上海" andPopulation:900]; t2.areas = @[@"浦东区",@"静安区",@"徐汇区"]; City *t3 = [[City alloc]initWithName:@"广州" andPopulation:800]; t3.areas = @[@"白云区",@"越秀区",@"天河区"]; City *t4 = [[City alloc]initWithName:@"深圳" andPopulation:700]; t4.areas = @[@"未知区",@"未知2区"]; return @[t1,t2,t3,t4]; } @end CityTableViewController.h CityTableViewController.m 同上 DetailViewController.h #import <UIKit/UIKit.h> #import "City.h" @interface DetailViewController : UITableViewController ***继承 @property(nonatomic,strong)City *city; @end DetailViewController.m #import "DetailViewController.h" @interface DetailViewController () @end @implementation DetailViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = self.city.name; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.city.areas.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; cell.textLabel.text = self.city.areas[indexPath.row]; return cell; } 6.3 使用多分区来显示子数据 【Demo5_MutilSection】 数据结构: + City : NSObject +name : NSString +population : NSInteger +areas(区域) : NSArray (NSString) 例如: City: name:北京 population:1000 areas: @[@“东城区”,@“西城区”,@“朝阳区”] 要求: a。使用一个tableView的多分区展示城市名称及子地区名称 b。每个分区的头,显示城市名称 c。每个分区的尾,显示城市的人口 d。分区内的多行显示城市的所有areas City.h City.m 同上 CityTableViewController.h CityTableViewController.m #import "CityTableViewController.h" #import "City.h" @interface CityTableViewController () @property(nonatomic,strong)NSArray *citys; @end @implementation CityTableViewController - (NSArray *)citys{ if (!_citys) { _citys = [City demoData]; } return _citys; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"城市列表"; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { //有几个城市就是几个分区 return self.citys.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { //每个城市的子地区有几个,那么该分区就有几行 City *city = self.citys[section]; return city.areas.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } //根据section找到对应的city City *city = self.citys[indexPath.section]; cell.textLabel.text = city.areas[indexPath.row]; return cell; } //设置section头 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ City *city = self.citys[section]; return city.name; } //设置section尾 -(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{ City *city = self.citys[section]; return [NSString stringWithFormat:@"人口数:%d万",city.population]; } @end 6.4 向TableView中添加一行数据 数据模型: + City : NSObject +name : NSString +population : NSInteger 要求: a。第一个界面使用tableView展示所有的城市信息 b。城市名称在单元格的左侧显示 c。城市的人口在单元格的右侧显示 d。在导航栏的右上角有一个加号按钮,点击这个加号后,推出一个新的普通vc e。在推出的界面2中,包含两个文本框,一个用于输入新的城市名称,一个用于输入该城市的人口数 f。界面2中下方有一个保存按钮,点击保存按钮后,返回到界面1,并且将在界面2中输入的数据回传到界面1,保存在界面1中用于存放所有城市信息的数组中 g。同时,更新表格,显示增加完城市信息后的新数据(注:如何刷新整个表格?[ self.tableView reloadData];) TRCity.h #import <Foundation/Foundation.h> @interface TRCity : NSObject @property(nonatomic,strong)NSString* name; @property(nonatomic)NSInteger population; -(instancetype)initWithName:(NSString*)name andPopulation:(NSInteger)population; +(NSMutableArray*)cityArrays; @end TRCity.m #import "TRCity.h" @implementation TRCity -(instancetype)initWithName:(NSString*)name andPopulation:(NSInteger)population{ if ([super init]) { self.name=name; self.population=population; } return self; } +(NSMutableArray*)cityArrays{ TRCity* c1=[[TRCity alloc]initWithName:@"北京" andPopulation:1000]; TRCity* c2=[[TRCity alloc]initWithName:@"上海" andPopulation:800]; TRCity* c3=[[TRCity alloc]initWithName:@"广州" andPopulation:600]; return [@[c1,c2,c3]mutableCopy]; } @end CityTableViewController.h #import <UIKit/UIKit.h> @interface CityTableViewController : UITableViewController @end CityTableViewController.m #import "CityTableViewController.h" #import "TRCity.h" #import "MyViewController.h" @interface CityTableViewController ()<MyViewControllerDelegate> @property(nonatomic,strong)NSMutableArray* citys; //@property(nonatomic,strong)NSMutableArray*message; @end @implementation CityTableViewController -(NSMutableArray*)citys{ if (!_citys) { _citys=[TRCity cityArrays]; } return _citys; } //添加导航栏配置 - (void)viewDidLoad { [super viewDidLoad]; self.title=@"城市列表"; UIBarButtonItem* r=[[UIBarButtonItem alloc]initWithBarButtonSystemItem: target:self action:@selector(gotoNewVC)]; self.navigationItem.rightBarButtonItem=r; } //点击加号切换到的界面 -(void)gotoNewVC{ MyViewController* myVC=[[MyViewController alloc]initWithNibName:@"MyViewController" bundle:nil]; [self.navigationController pushViewController:myVC animated:YES ]; myVC.delegate=self; } //实现方法 -(void)myViewController:(MyViewController *)mVC gobackMessage:(NSArray *)message{ //self.citys=message; TRCity* city=[[TRCity alloc]init]; city.name=message[0]; city.population=[message[1] integerValue]; [self.citys addObject:city]; //刷新表格 从原有的刷新 //[ self.tableView reloadData]; //从第四行开始刷新 局部刷新 NSIndexPath* newIndexPath=[NSIndexPath indexPathForRow:self.citys.count-1 inSection:0]; [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.citys.count; } /**/ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell==nil) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; } TRCity* city=self.citys[indexPath.row]; cell.textLabel.text=city.name; cell.detailTextLabel.text=[NSString stringWithFormat:@"人口:%d",city.population]; return cell; } MyViewController.h #import <UIKit/UIKit.h> //定义协议 @class MyViewController; @protocol MyViewControllerDelegate <NSObject> -(void)myViewController:(MyViewController*)mVC gobackMessage:(NSArray*)message; @end @interface MyViewController : UIViewController @property(nonatomic,weak)id<MyViewControllerDelegate>delegate; @end MyViewController.m #import "MyViewController.h" @interface MyViewController () @property (weak, nonatomic) IBOutlet UITextField *name; 连线文本框 @property (weak, nonatomic) IBOutlet UITextField *population; @property(nonatomic,strong)NSArray* city; @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)returnCS:(UITextField *)sender { [self.view endEditing:YES]; } - (IBAction)returnRK:(UITextField *)sender { [self.view endEditing:YES]; } //点击保存按钮返回到界面1 - (IBAction)goBackCIty:(UIButton *)sender { NSString* str=self.name.text; NSString*str2=self.population.text; self.city=@[str,str2]; [self.delegate myViewController:self gobackMessage:self.city]; [self.navigationController popToRootViewControllerAnimated:YES]; } @end 7.表格的编辑模式 1.1 什么是表格的编辑模式? 在表格上可以进行cell的删除、增加、移动的操作 1.2 如何实现数据的编辑(删除、增加) 实现步骤: a。启动表格的编辑模式:通过修改tableView的editing属性即可 b。回答 两问一答 三个问题 问1:哪些行可以进入编辑模式 问2:行处于何种编辑模式 答1:点击编辑按钮后要做的响应 1.3 实现数据删除或增加时,一定是先改数据模型,然后再刷新界面 例: 1).启用编辑模式两种方法 - (void)viewDidLoad { [super viewDidLoad]; self.title = @"联系人"; ****//创建启用编辑按钮的方式一 //self.navigationItem.rightBarButtonItem = self.editButtonItem; ****//创建启用编辑按钮的方式二 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"编辑" style:UIBarButtonItemStyleDone target:self action:@selector(tableBeginEditing)]; } -(void)tableBeginEditing{ //self.tableView.editing = YES; //启动表格的编辑模式 [self.tableView setEditing:!self.tableView.editing animated:YES]; //修改右侧按钮上的显示文字 if (self.tableView.editing) { [self.navigationItem.rightBarButtonItem setTitle:@"完成"]; }else { [self.navigationItem.rightBarButtonItem setTitle:@"编辑"]; } } 2).利用启用编辑模式进行删除、添加 MyTableViewController.h MyTableViewController.m #import "MyTableViewController.h" @interface MyTableViewController () @property(nonatomic,strong)NSMutableArray *names; @end @implementation MyTableViewController - (NSMutableArray *)names{ if (!_names) { _names = [@[@"张三",@"李四",@"王五",@"赵六"] mutableCopy]; } return _names; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"联系人"; //创建启用编辑按钮的方式一 //self.navigationItem.rightBarButtonItem = self.editButtonItem; //创建启用编辑按钮的方式二 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"编辑" style:UIBarButtonItemStyleDone target:self action:@selector(tableBeginEditing)]; } -(void)tableBeginEditing{ //self.tableView.editing = YES; //启动表格的编辑模式 [self.tableView setEditing:!self.tableView.editing animated:YES]; //修改右侧按钮上的显示文字 if (self.tableView.editing) { [self.navigationItem.rightBarButtonItem setTitle:@"完成"]; }else { [self.navigationItem.rightBarButtonItem setTitle:@"编辑"]; } } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.names.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } cell.textLabel.text = self.names[indexPath.row]; return cell; } #pragma mark - table editing //问1:该行是否可以进入编辑模式 -(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{ return YES; } //问2:该行使用什么编辑样式 -(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{ if (indexPath.row == self.names.count-1){ return UITableViewCellEditingStyleInsert; }else{ return UITableViewCellEditingStyleDelete; } } //答1:确定编辑动作后的响应 -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ //如果提交的编辑样式是删除动作时 if (editingStyle == UITableViewCellEditingStyleDelete) { 删除模式 //1.根据选择的行的位置,修改数据模型 [self.names removeObjectAtIndex:indexPath.row]; //2.刷新tableView [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft]; }else if(editingStyle == UITableViewCellEditingStyleInsert){ 添加模式 //1.修改数据模型 [self.names addObject:@"test"]; //2.刷新tableView NSIndexPath *newPath = [NSIndexPath indexPathForRow:self.names.count-1 inSection:0]; [self.tableView insertRowsAtIndexPaths:@[newPath] withRowAnimation:UITableViewRowAnimationRight]; } } @end 1.4 实现数据的移动 //移动 //一问 -(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{ return YES; } //一答 -(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{ //建立模型 //获取要移动的数据对象 NSString* str=[self.names objectAtIndex:sourceIndexPath.row]; //将数据从数组中移除 [self.names removeObjectAtIndex:sourceIndexPath.row]; //按照新的坐标位置,将对象在插入回数组中 [self.names insertObject:str atIndex:destinationIndexPath.row]; } 8. 单元格的contentView内容视图 UITableViewCell继承自UIView,其中又包含了左右两个区域,其中左侧用于显示内容的区域叫做内容视图,想访问这个区域,可以通过cell.contentView属性即可 a)系统为内容视图提供了默认的三个控件 .textLabel .detailTextLabel .imageView b)可以自定义内容视图 [cell.contentView addSubView:xxx] MyTableViewController.h MyTableViewController.m #import "MyTableViewController.h" @interface MyTableViewController () @property(nonatomic,strong)NSArray *citys; @end @implementation MyTableViewController - (NSArray *)citys{ if (!_citys) { _citys = @[@"北京",@"上海",@"广州",@"深圳",@"杭州",@"苏州",@"厦门",@"天津",@"重庆",@"呼和浩特",@"郑州",@"乌鲁木齐",@"拉萨",@"xx",@"yy",@"zz",@"mm",@"nn",@"qq",@"aa",]; } return _citys; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.citys.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" ]; UILabel *label = nil; //经过一些步骤,label指向一个对象 if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 60)]; label.font = [UIFont systemFontOfSize:22]; label.shadowColor = [UIColor redColor]; label.shadowOffset = CGSizeMake(2, 2); label.textAlignment = NSTextAlignmentCenter; //为label添加一个容器内的对象标识 label.tag = 1; [cell.contentView addSubview:label]; }else{ //获取cell中已经添加了的那个label label = (UILabel *)[cell.contentView viewWithTag:1]; } label.text = self.citys[indexPath.row]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 60; } @end 9.单元格的accessoryView(辅助视图) a)使用系统提供的辅助视图样式 cell.accessoryType UITableViewCellAccessoryCheckmark:对勾 UITableViewCellAccessoryDisclosureIndicator:大于号 UITableViewCellAccessoryDetailButton:圆圈i UITableViewCellAccessoryDetailDisclosureButton:圆圈i+大于号 注意:包含detail按钮时,cell可以有两种不同的单击事件的响应。 点击圆圈i部分:响应accessoryButtonTapped:方法 点击圆圈i以外的部分:响应didSelectRowAtIndexPath: 如: cell.accessoryType = UITableViewCellAccessoryDetailButton; b)自定义辅助视图 cell.accessoryView = [UIButton] 如:cell.accessoryView = [[UISwitch alloc]init]; MyTableViewController.h MyTableViewController.m #import "MyTableViewController.h" @interface MyTableViewController () @end @implementation MyTableViewController - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 5; } static NSString *cellIdentifier = @"cell"; - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell==nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; } if (indexPath.row == 2) { //系统定义的辅助视图样式 cell.accessoryType = UITableViewCellAccessoryDetailButton; //自定义辅助视图样式 }else if (indexPath.row == 3) { cell.accessoryView = [[UISwitch alloc]init]; }else if(indexPath.row == 1){ UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setTitle:@"验证码" forState:UIControlStateNormal]; button.frame = CGRectMake(0, 0, 100, 40); cell.accessoryView = button; } cell.textLabel.text = @"Hello World"; return cell; } //一响应 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSLog(@"didSelectRowAtIndexPath"); } //响应用户点击圆圈i (Detail按钮) -(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{ NSLog(@"...."); } @end 10. 自定义单元格 1.预备: 根据要显示的结果,分析底层的数据模型,创建模型类,cell类是模型类的一种显示外观 2.实现步骤: step1:编写一个类,继承自UITableViewCell 勾选xib //step2:创建可以进行界面设置的xib文件,设计界面 //step3:将xib文件与自己编写的Cell类关联起来 step4:将xib中设计的各个可被修改的控件进行连线,且要变成公开的属性 step5:创建表格,回答第三问时,不再创建UITableViewCell的实例,而是创建我们自己编写的cell类的实例,返回即可。 News.h #import <Foundation/Foundation.h> @interface News : NSObject @property(nonatomic,strong)NSString *title; @property(nonatomic,strong)NSString *newsImageName; @property(nonatomic)NSUInteger commentNumber; -(instancetype)initWithTitle:(NSString *)title andImageName:(NSString *)imageName andCommentNumber:(NSUInteger)number; +(NSArray *)demoData; @end News.m #import "News.h" @implementation News -(instancetype)initWithTitle:(NSString *)title andImageName:(NSString *)imageName andCommentNumber:(NSUInteger)number{ self = [super init]; if (self) { self.title = title; self.newsImageName = imageName; self.commentNumber = number; } return self; } + (NSArray *)demoData{ News *n1 = [[News alloc]initWithTitle:@"xxx" andImageName:@"icon40.png" andCommentNumber:200]; News *n2 = [[News alloc]initWithTitle:@"yyyyyyy" andImageName:@"icon40.png" andCommentNumber:100]; News *n3 = [[News alloc]initWithTitle:@"zzzzzzz" andImageName:@"icon40.png" andCommentNumber:20]; News *n4 = [[News alloc]initWithTitle:@"mmmmmm" andImageName:@"icon40.png" andCommentNumber:0]; return @[n1,n2,n3,n4]; } @end NewsCell.h #import <UIKit/UIKit.h> @interface NewsCell : UITableViewCell //继承自 @property (weak, nonatomic) IBOutlet UIImageView *newsImageView; @property (weak, nonatomic) IBOutlet UILabel *title; @property (weak, nonatomic) IBOutlet UILabel *commentNumberLabel; @end NewsCell.m #import "NewsCell.h" @implementation NewsCell @end NewsTableViewController.h #import <UIKit/UIKit.h> @interface NewsTableViewController : UITableViewController @property(nonatomic,strong)NSArray *allNews; @end NewsTableViewController.m #import "NewsTableViewController.h" #import "News.h" #import "NewsCell.h" @interface NewsTableViewController () @end @implementation NewsTableViewController static NSString *cellIdentifier = @"cell"; - (void)viewDidLoad { [super viewDidLoad]; //注册NewsCell类型,重用时由系统创建指定的类型 //由于自定义的cell类带有xib文件 //所以注册时使用nib方法,说明,如果系统 //帮助创建cell对象,则根据指定的xib文件来创建 [self.tableView registerNib:[UINib nibWithNibName:@"NewsCell" bundle:nil] forCellReuseIdentifier:cellIdentifier]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.allNews.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NewsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; //按下标找到新闻对象 News *news = self.allNews[indexPath.row]; cell.title.text = news.title; cell.newsImageView.image = [UIImage imageNamed:news.newsImageName]; cell.commentNumberLabel.text = [NSString stringWithFormat:@"%d",news.commentNumber]; return cell; } //设置行高 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 60; } @end 作业: 见下发的资源包   1.qq音乐的配置界面 MyTableViewController.h MyTableViewController.m #import "MyTableViewController.h" @interface MyTableViewController () @end @implementation MyTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.title=@"更多"; UIView* headeView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 70)]; UILabel* label1=[[UILabel alloc]initWithFrame:CGRectMake(15, 40, 80, 30)]; label1.text=@"关注 3"; UILabel* label2=[[UILabel alloc]initWithFrame:CGRectMake(130, 40, 160, 30)]; label2.text=@"粉丝 0"; UILabel* label3=[[UILabel alloc]initWithFrame:CGRectMake(240, 40, 240, 30)]; label3.text=@"动态 0"; UILabel* label4=[[UILabel alloc]initWithFrame:CGRectMake(240, 20, 240, 20)]; label4.text=@"我的绿钻"; label4.textColor=[UIColor greenColor]; [headeView addSubview:label1]; [headeView addSubview:label2]; [headeView addSubview:label3]; [headeView addSubview:label4]; UILabel* label5=[[UILabel alloc]initWithFrame:CGRectMake(60, 10, 90, 30)]; label5.text=@"傻丫头"; [headeView addSubview:label5]; //照片 UIImage* image=[UIImage imageNamed:@"header.png"]; UIImageView* imageView=[[UIImageView alloc]initWithImage:image]; imageView.frame=CGRectMake(10, 0, 40, 40); [headeView addSubview:imageView]; imageView.layer.cornerRadius=20; imageView.layer.masksToBounds=YES; self.tableView.tableHeaderView=headeView; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 3; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section==0) { return 4; }else if (section==1){ return 3; }else{ return 1; } } /**/ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell==nil) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; } cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator; if (indexPath.section==0) { if (indexPath.row==0) { cell.textLabel.text=@"我的绿钻"; }else if (indexPath.row==1){ cell.textLabel.text=@"免流量服务"; cell.detailTextLabel.text=@"在线听歌免流量费"; }else if (indexPath.row==2){ cell.textLabel.text=@"QPlay与车载互联"; cell.detailTextLabel.text=@"开启"; }else{ cell.textLabel.text=@"笛音传歌"; cell.detailTextLabel.text=@"声波传送,一触即发"; } }else if (indexPath.section==1){ if (indexPath.row==0) { cell.textLabel.text=@"设置"; }else if (indexPath.row==1){ cell.textLabel.text=@"定时关闭"; //设置辅视图 cell.accessoryView=[[UISwitch alloc]init]; }else if (indexPath.row==2){ cell.textLabel.text=@"关于QQ音乐"; } }else{ cell.textLabel.text=@"退出登录"; cell.textLabel.textColor=[UIColor redColor]; // cell.textLabel.textAlignment=NSTextAlignmentCenter; } return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 40; } -(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ return @" "; } 2.新闻客户端的首页,新闻展示 News.h #import <Foundation/Foundation.h> @interface News : NSObject @property(nonatomic,strong) NSString *title; @property(nonatomic,strong) NSString *newsImageName; @property(nonatomic) NSUInteger commentNumber; -(instancetype)initWithTitle:(NSString*)title andImageName:(NSString*)imageName andCommentNumber:(NSUInteger)commentNumber; +(NSArray *)demoData; @end News.m #import "News.h" @implementation News -(instancetype)initWithTitle:(NSString*)title andImageName:(NSString*)imageName andCommentNumber:(NSUInteger)commentNumber{ self = [super init]; if (self) { self.title = title; self.newsImageName = imageName; self.commentNumber = commentNumber; } return self; } + (NSArray *)demoData{ News *n1 = [[News alloc]initWithTitle:@"联通被曝高危漏洞 或致用户通话记录等信息泄露" andImageName:@"n1.png" andCommentNumber:186]; News *n2 = [[News alloc]initWithTitle:@"CES2015回顾:民用无人机来袭 中国公司占主导" andImageName:@"n2.png" andCommentNumber:17]; News *n3 = [[News alloc]initWithTitle:@"中企征战CES:难寻颠覆性产品 未打通海外品牌渠道" andImageName:@"n3.png" andCommentNumber:17]; News *n4 = [[News alloc]initWithTitle:@"老话重提:“专车”是否是黑车?被查合不合法" andImageName:@"n4.png" andCommentNumber:178]; News *n5 = [[News alloc]initWithTitle:@"马云告诫员工千万别碰京东:京东将会成悲剧" andImageName:@"n5.png" andCommentNumber:4374]; News *n6 = [[News alloc]initWithTitle:@"三星Q4营业利润47亿美元超预期:内存芯片需求利好" andImageName:@"n6.png" andCommentNumber:6]; News *n7 = [[News alloc]initWithTitle:@"索尼宣布PS4国行版延期上市 或因被举报不锁区" andImageName:@"n7.png" andCommentNumber:0]; News *n8 = [[News alloc]initWithTitle:@"微众银行开业前夕推“信用付”临时核心系统过度" andImageName:@"n8.png" andCommentNumber:4]; return @[n1,n2,n3,n4,n5,n6,n7,n8]; } @end MyCell.xib  MyCell.h #import <UIKit/UIKit.h> @interface MyCell : UITableViewCell @property (weak, nonatomic) IBOutlet UIImageView *newsImageView; 与上图连线 @property (weak, nonatomic) IBOutlet UILabel *titleLabel; @property (weak, nonatomic) IBOutlet UILabel *commentNumberLabel; @end MyCell.m NewsViewController.h #import <UIKit/UIKit.h> @interface NewsViewController : UITableViewController @property(nonatomic,strong)NSArray *allNews; @end NewsViewController.m #import "NewsViewController.h" #import "News.h" #import "MyCell.h" @interface NewsViewController ()<UIScrollViewDelegate> @property(nonatomic,strong) UIScrollView *scrollView; @property(nonatomic,strong) NSArray *labels;; @end @implementation NewsViewController static NSString *cellIdentifier = @"cell"; -(NSArray*)allNews{ if (!_allNews) { _allNews=[News demoData]; } return _allNews; } - (void)viewDidLoad { [super viewDidLoad]; [self.tableView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellReuseIdentifier:cellIdentifier]; self.scrollView=[[UIScrollView alloc]init]; self.scrollView.frame=CGRectMake(0, 0, self.view.frame.size.width, 30); self.scrollView.contentSize=CGSizeMake(610, 30); self.scrollView.showsHorizontalScrollIndicator=NO; self.scrollView.delegate=self; UILabel *titleLabel1=[[UILabel alloc]initWithFrame:CGRectMake(55, 00,100, 30)]; titleLabel1.text=@"体育"; UILabel *titleLabel2=[[UILabel alloc]initWithFrame:CGRectMake(155, 00, 100, 30)]; titleLabel2.text=@"非新闻"; UILabel *titleLabel3=[[UILabel alloc]initWithFrame:CGRectMake(255, 00, 100, 30)]; titleLabel3.text=@"科技"; UILabel *titleLabel4=[[UILabel alloc]initWithFrame:CGRectMake(355, 00, 100, 30)]; titleLabel4.text=@"军事"; UILabel *titleLabel5=[[UILabel alloc]initWithFrame:CGRectMake(455, 00, 100, 30)]; titleLabel5.text=@"历史"; self.labels=@[titleLabel1,titleLabel2,titleLabel3,titleLabel4,titleLabel5]; for (UILabel *label in self.labels) { label.textAlignment=NSTextAlignmentCenter; [self.scrollView addSubview:label]; } self.scrollView.bounces=NO; self.navigationItem.titleView=self.scrollView; self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:nil]; self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemReply target:self action:nil]; UIView *tableHeader=[[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 180)]; UIImageView *headerView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 180)]; headerView.image=[UIImage imageNamed:@"header.png"]; [tableHeader addSubview:headerView]; self.tableView.tableHeaderView=tableHeader; self.tableView.showsVerticalScrollIndicator=NO; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.allNews.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { MyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; News *news = self.allNews[indexPath.row]; cell.titleLabel.text=news.title; cell.newsImageView.image = [UIImage imageNamed:news.newsImageName]; cell.commentNumberLabel.text = [NSString stringWithFormat:@"%d",news.commentNumber]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 100; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ CGPoint offSet=self.scrollView.contentOffset; for (int i=0; i<self.labels.count; i++) { if (i==(int)offSet.x/80) { UILabel* label=self.labels[i]; [label setTextColor:[UIColor redColor]]; } else { UILabel* label=self.labels[i]; [label setTextColor:[UIColor blackColor]]; } } [self.navigationItem.titleView setNeedsDisplay]; } 作业: 1.照片查看器 在一个TableView中列出所有照片的缩小图、照片名称和拍摄的位置。当用户点击某一行时,推出一个vc,在此vc中显示大的图片,大的图片允许缩放。 Pictures.h #import <Foundation/Foundation.h> @interface Pictures : NSObject @property(nonatomic,strong)NSString *name; -(instancetype)initWithName:(NSString *)name; +(NSArray *)DemoData; @end Pictures.m #import "Pictures.h" @implementation Pictures -(instancetype)initWithName:(NSString *)name { if (self = [super init]) { self.name = name; } return self; } +(NSArray *)DemoData { Pictures *p1 = [[Pictures alloc]initWithName:@"welcome1.PNG"]; Pictures *p2 = [[Pictures alloc]initWithName:@"welcome2.PNG"]; Pictures *p3 = [[Pictures alloc]initWithName:@"welcome3.PNG"]; Pictures *p4 = [[Pictures alloc]initWithName:@"welcome4.PNG"]; return @[p1,p2,p3,p4]; } @end MyTableViewController.h MyTableViewController.m #import "MyTableViewController.h" #import "DetailViewController.h" @interface MyTableViewController () @property(nonatomic,strong)NSArray *pictures; @end @implementation MyTableViewController -(NSArray *)pictures { if (!_pictures) { _pictures = [Pictures DemoData]; } return _pictures; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.pictures.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"]; cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"]; } Pictures *picture = self.pictures[indexPath.row]; if (indexPath.row == 0) { cell.textLabel.text =picture.name; cell.detailTextLabel.text = @"achao"; cell.imageView.image = [UIImage imageNamed:picture.name]; }else if (indexPath.row == 1) { cell.textLabel.text =picture.name; cell.detailTextLabel.text = @"achao"; cell.imageView.image = [UIImage imageNamed:picture.name]; }else if (indexPath.row == 2) { cell.textLabel.text =picture.name; cell.detailTextLabel.text = @"achao"; cell.imageView.image = [UIImage imageNamed:picture.name]; }else if (indexPath.row == 3) { cell.textLabel.text =picture.name; cell.detailTextLabel.text = @"achao"; cell.imageView.image = [UIImage imageNamed:picture.name]; } return cell; } #pragma mark - Table view delegate // In a xib-based application, navigation from a table can be handled in -tableView:didSelectRowAtIndexPath: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; // Pass the selected object to the new view controller. Pictures *picture = self.pictures[indexPath.row]; detailViewController.picture = picture; // Push the view controller. [self.navigationController pushViewController:detailViewController animated:YES]; } @end DetailViewController.h #import <UIKit/UIKit.h> #import "Pictures.h" @interface DetailViewController : UIViewController @property(nonatomic,strong)Pictures *picture; @end DetailViewController.m #import "DetailViewController.h" #import "Pictures.h" @interface DetailViewController ()<UIScrollViewDelegate> @property(nonatomic,strong)UIScrollView *scrollView; @property(nonatomic,strong)UIImageView *imageView; @end @implementation DetailViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; } -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; NSString *name = self.picture.name; NSLog(@"->%@",name); UIImage *image= [UIImage imageNamed:name]; UIImageView *imageView = [[UIImageView alloc]initWithImage:image]; //imageView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); imageView.contentMode = UIViewContentModeScaleAspectFit; self.imageView = imageView; UIScrollView *scrollView = [[UIScrollView alloc]init]; self.scrollView = scrollView; scrollView.contentSize = imageView.frame.size; scrollView.contentMode = UIViewContentModeScaleAspectFit; scrollView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); scrollView.maximumZoomScale = 1; CGFloat xScale = scrollView.frame.size.width/imageView.frame.size.width; CGFloat yScale = scrollView.frame.size.height/imageView.frame.size.height; scrollView.minimumZoomScale = MIN(xScale, yScale); scrollView.delegate = self; [scrollView addSubview:imageView]; [self.view addSubview:scrollView]; } -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return self.imageView; } AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "MyTableViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; MyTableViewController *myVC = [[MyTableViewController alloc]initWithNibName:@"MyTableViewController" bundle:nil]; UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:myVC]; self.window.rootViewController = navi; [self.window makeKeyAndVisible]; return YES; } 1.静态表格 行数不变的表格 实现方式: 方法一:代码方式 特点:使用大量的if else 进行界面的硬编码 注意:静态表格中的数据依然是可变的 User.h #import <Foundation/Foundation.h> @interface User : NSObject @property(nonatomic,strong)NSString *weChatNumber; @property(nonatomic,strong)NSString *qqNumber; @property(nonatomic,strong)NSString *phoneNumber; @property(nonatomic,strong)NSString *email; @end User.m 空 SafeViewController.h SafeViewController.m #import "SafeViewController.h" @interface SafeViewController () @end @implementation SafeViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"账号与安全"; //设置导航栏的背景色 self.navigationController.navigationBar.barTintColor = [UIColor grayColor]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == 0) { return 1; }else{ return 3; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = nil; switch (indexPath.section) { case 0://分区0 cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; cell.textLabel.text = @"微信号"; cell.detailTextLabel.text = self.user.weChatNumber; break; case 1://分区1 if (indexPath.row == 0) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; cell.textLabel.text = @"QQ号"; cell.detailTextLabel.text = self.user.qqNumber; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; }else if(indexPath.row == 1){ cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; cell.textLabel.text = @"手机号"; cell.detailTextLabel.text = self.user.phoneNumber; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; }else{ cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; cell.textLabel.text = @"邮箱"; cell.detailTextLabel.text = self.user.email; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } break; default: break; } return cell; } AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "SafeViewController.h" #import "User.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; User *user = [[User alloc]init]; user.weChatNumber = @"chat-num"; user.qqNumber = @"1234567"; user.phoneNumber = @"18600xxxx"; user.email = @"tom@tarena.com.cn"; SafeViewController *vc = [[SafeViewController alloc]initWithNibName:@"SafeViewController" bundle:nil]; vc.user = user; UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:vc]; self.window.rootViewController = navi; [self.window makeKeyAndVisible]; return YES; } 结果:  方法二:xib方法 实现思路:在xib中将静态表格中的每一行都通过拖拽一个对象来进行设计,系统会自动创建xib中包含的所有的控件对象,但是,默认每一个xib文件只能有一个根元素被控制器加载,其他拖拽后并由系统创建了的对象,可以通过将这个对象连线到控制器中成为属性再访问。 【Demo2_StaticTable_Xib】 SettingViewController.h SettingViewController.m #import "SettingViewController.h" @interface SettingViewController ()  @property (strong, nonatomic) IBOutlet UIView *headerView; 连线 @property (strong, nonatomic) IBOutlet UITableViewCell *greenDimand; @property (strong, nonatomic) IBOutlet UITableViewCell *freeMode; @property (strong, nonatomic) IBOutlet UITableViewCell *settingClose; @property (strong, nonatomic) IBOutlet UITableViewCell *exit; @end @implementation SettingViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"更多"; self.tableView.tableHeaderView = self.headerView; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 3; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { case 0: return 2; case 1: return 1; case 2: return 1; default: return 0; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = nil; switch (indexPath.section) { case 0: if (indexPath.row == 0 ) { //根据分区号和行号,cell指向不同的对象,然后返回 cell = self.greenDimand; }else{ cell = self.freeMode; } break; case 1: cell = self.settingClose; break; case 2: cell = self.exit; break; } return cell; } 2.动态表格 数据行是不固定的 核心理念:创建完TableView之后,设置tableView的dataSource和delegate对象,只要符合协议的对象都可以设置为代理方法 选择一:让当前控制器遵守协议,然后成为tableView的代理 选择二:自己编写类,遵守协议,然后创建类的对象,设置为tableView的代理 方法一: tableView.dataSource和tableView.delegate两个代理交给两个类处理,不用当前控制器处理。两个类需遵守协议UITableViewDataSource和UITableViewDelegate,当前控制器需创建两个类的实例化,才能将其成为代理方 ViewController.xib 添加Table View控件,修改大小,连线代理, ViewController.h 控制器 #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end ViewController.m #import "ViewController.h" #import "TRTableDateSource.h" #import "TRTableDalegate.h" @interface ViewController () @property(nonatomic,strong)TRTableDateSource* tableDateSource; @property(nonatomic,strong)TRTableDalegate* tableDalegate; @end @implementation ViewController //重写get方法 -(TRTableDateSource *)tableDateSource{ if (!_tableDateSource) { _tableDateSource=[[TRTableDateSource alloc]init]; } return _tableDateSource; } -(TRTableDalegate *)tableDalegate{ if (!_tableDalegate) { _tableDalegate=[[TRTableDalegate alloc]init]; } return _tableDalegate; } //UITableView继承UIScrollView - (void)viewDidLoad { [super viewDidLoad]; UITableView* tableView=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain]; tableView.dataSource=self.tableDateSource; tableView.delegate=self.tableDalegate; [self.view addSubview:tableView]; } @end TRTableDateSource.h #import <Foundation/Foundation.h> @interface TRTableDateSource : NSObject<UITableViewDataSource>//遵守协议 @end TRTableDateSource.m #import "TRTableDateSource.h" //数据源 @implementation TRTableDateSource -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 10; } -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell* cell=[tableView dequeueReusableCellWithIdentifier:@"cell" ]; if (cell==nil) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } cell.textLabel.text=@"hello"; return cell; } @end TRTableDalegate.h #import <Foundation/Foundation.h> @interface TRTableDalegate : NSObject<UITableViewDelegate>//遵守协议 @end TRTableDalegate.m #import "TRTableDalegate.h"//代理响应 @implementation TRTableDalegate -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSLog(@"..."); } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 100; } @end AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "ViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window=[[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; ViewController* cV=[[ViewController alloc]initWithNibName:@"ViewController" bundle:nil]; self.window.rootViewController=cV; [self.window makeKeyAndVisible]; return YES; } 方法2: 需求:在一个普通vc的视图上有两个tableView,上面的tableView从资源库中拖拽,用于显示5行Hello World;下面的tableView使用代码创建,用于显示7行Hello Kitty;当前控制器对象同时是这两个tableView的dataSource和delegate TRViewController.h TRViewController.m #import "TRViewController.h" @interface TRViewController ()<UITableViewDataSource,UITableViewDelegate> @property(nonatomic,strong)UITableView* codeTableView;//手写代码 @property (weak, nonatomic) IBOutlet UITableView *xibTableView;//通过xib创建,就可以省了viewDidLoad中的4步 @end @implementation TRViewController - (void)viewDidLoad { [super viewDidLoad]; self.codeTableView=[[UITableView alloc]initWithFrame:CGRectMake(0, 220, self.view.frame.size.width, 250)]; self.codeTableView.dataSource=self; self.codeTableView.delegate=self; [self.view addSubview:self.codeTableView]; } -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ if (tableView==self.xibTableView) { return 5; }else{ return 7; } } -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell* cell=[tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell==nil) { if (tableView==self.xibTableView) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; }else{ cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"]; } } if (tableView==self.xibTableView) { cell.textLabel.text=@"HelloWord"; }else{ cell.textLabel.text=@"HelloKitty"; cell.detailTextLabel.text=@"miao"; } return cell; } @end 结果:  练习: 展示地区名称,层级未知,取决于数据模型 北京 东城 西城 朝阳 潘家园 松榆路 建业苑 一层 六层 达内 第一教室 第二教室 达内对面 麦当劳 海淀 上海 徐汇 静安 +AreaTableViewController +areas: Area( 元素类型:Area) +Area +name:NSString +subAreas:NSArray +[Item]:Area +name:NSString +subAreas:NSArray +[Item]:Arear …… Area.h #import <Foundation/Foundation.h> @interface Area : NSObject @property(nonatomic,strong)NSString *name; @property(nonatomic,strong)NSArray *subAreas; -(instancetype)initWithName:(NSString *)name; +(Area *)demoData; @end Area.m #import "Area.h" @implementation Area - (instancetype)initWithName:(NSString *)name{ self = [super init]; if (self) { self.name = name; } return self; } + (Area *)demoData{ Area *a0 = [[Area alloc]initWithName:@"城市"]; Area *a1 = [[Area alloc]initWithName:@"北京"]; Area *a2 = [[Area alloc]initWithName:@"上海"]; Area *a11 = [[Area alloc]initWithName:@"东城"]; Area *a12 = [[Area alloc]initWithName:@"西城"]; Area *a13 = [[Area alloc]initWithName:@"朝阳"]; Area *a14 = [[Area alloc]initWithName:@"徐汇"]; Area *a15 = [[Area alloc]initWithName:@"静安"]; Area *a21 = [[Area alloc]initWithName:@"潘家园"]; Area *a22 = [[Area alloc]initWithName:@"松榆路"]; Area *a23 = [[Area alloc]initWithName:@"麦当劳"]; Area *a31 = [[Area alloc]initWithName:@"建业苑"]; Area *a41 = [[Area alloc]initWithName:@"一楼"]; Area *a42 = [[Area alloc]initWithName:@"六楼"]; Area *a51 = [[Area alloc]initWithName:@"达内"]; Area *a61 = [[Area alloc]initWithName:@"第一教室"]; Area *a62= [[Area alloc]initWithName:@"第二教室"]; a51.subAreas = @[a61,a62]; a42.subAreas = @[a51]; a31.subAreas=@[a41,a42]; a22.subAreas = @[a31]; a13.subAreas = @[a21,a22,a23]; a1.subAreas = @[a11,a12,a13]; a2.subAreas = @[a14,a15]; a0.subAreas = @[a1,a2]; return a0; } @end AreaTableViewController.h #import <UIKit/UIKit.h> #import "Area.h" @interface AreaTableViewController : UITableViewController //每一个控制器实例对应的界面都是用来显示 //一个area的实例 //将area显示到表视图中 @property(nonatomic,strong)Area *area; @end AreaTableViewController.m #import "AreaTableViewController.h" @interface AreaTableViewController () @end @implementation AreaTableViewController - (void)viewDidLoad { [super viewDidLoad]; //1.area实例的name放在导航栏的标题位置 self.title = self.area.name; } /* 表格显示的是:area中的所有子地区对象的名字 */ #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.area.subAreas.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } //每一个单元格用于显示area的一个子地区信息 Area *subArea = self.area.subAreas[indexPath.row]; cell.textLabel.text = subArea.name; if (subArea.subAreas!=nil) { //如果有子地区,显示大于号做提示 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; }else{ //如果没有子地区,修改行的默认选中样式 //在选中后不出现灰色的背景 cell.selectionStyle = UITableViewCellSelectionStyleNone; } return cell; } //点击某一行之后推出新的界面,推出的界面与当前界面显示样式相同的,只是数据不同 //而已,选中一个节点,其实代表的选中依然是一个Area的实例,所以在推出新的界面时,将选中的Area实例 //作为参数传过去,由推出的界面负责显示 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ //获取选中的节点对应的Area实例 Area *subArea = self.area.subAreas[indexPath.row]; if (subArea.subAreas!=nil) { //创建新的控制器实例 AreaTableViewController *tVC = [[AreaTableViewController alloc]initWithNibName:@"AreaTableViewController" bundle:nil]; tVC.area = subArea; //推出新的控制器 [self.navigationController pushViewController:tVC animated:YES]; } } @end AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "Area.h" #import "AreaTableViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; AreaTableViewController *tvc = [[AreaTableViewController alloc]initWithNibName:@"AreaTableViewController" bundle:nil]; Area *area = [Area demoData]; tvc.area = area; UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:tvc]; self.window.rootViewController = navi; [self.window makeKeyAndVisible]; return YES; } ======================================================================================================================== 知识点 十三、UITabBarController标签控制器 1.是什么? 与navigationController很像,也是管理控制器的控制器。 tabBarController没有完整的界面外观,靠管理其它的vc来完成界面的显示。 管理方式横向并列方式的,navigation倾向于垂直深入式的管理vc。 1.如何使用? step1:将tabBarController管理的多个vc实例化出具体的对象 step2:将多个vc存到tabBar控制器中 1.1创建 #import "AppDelegate.h" #import "AViewController.h" #import "BViewController.h" #import "CViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; AViewController *avc = [[AViewController alloc]initWithNibName:@"AViewController" bundle:nil]; BViewController *bvc = [[BViewController alloc]initWithNibName:@"BViewController" bundle:nil]; CViewController *cvc = [[CViewController alloc]initWithNibName:@"CViewController" bundle:nil]; // 创建tabBar的实例 UITabBarController *tabVC = [[UITabBarController alloc]init]; //设置颜色 tabVC.tabBar.tintColor = [UIColor redColor]; //设置tabBar的代理 tabVC.delegate = self; // 将多个vc放到tabBar中 tabVC.viewControllers = @[avc,bvc,cvc]; self.window.rootViewController = tabVC; [self.window makeKeyAndVisible]; return YES; } 1.2设置 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { //配置文字 self.title = @"AVC"; //self.tabBarItem.title = @"AVC"; //配置图片 self.tabBarItem.image =[UIImage imageNamed:@"line_bell"]; self.tabBarItem.selectedImage = [UIImage imageNamed:@"full_bell"]; self.tabBarItem.badgeValue = @"2";//配置徽章 } return self; } 1. tabBar的配置 .tabBarItem.title 文字 .tabBarItem.image 不点击时是 空心图片 .tabBarItem.selectedImage 点击的时候是 实心图片 .tabBarItem.badgeValue 徽章 tabBarController.tabBar.tintColor 颜色 tabBarController.selectedIndex 可读可写的属性,用于获取或设置tabBar中激活的vc的下标 2.响应用户选中某vc事件: - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController 4.tabBarController与navigationController的配合 原则: a。多引导性控制器共存时,tabBar是整体最外层的管理者,navigation被tabBar管理的一个分支控制器 b。显示第一屏时,tabBar可以看见,在某一个具体 的vc中推出新vc时,tabBar处于隐藏状态。只有回到顶级vc时,tabBar区域才可见 c。推出新vc时,隐藏底部各种bar的方法: vc.hidesBottomBarWhenPushed = YES; 例: AppDelegate.h #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate,UITabBarControllerDelegate> //遵守协议 @property (strong, nonatomic) UIWindow *window; @end AppDelegate.m #import "AppDelegate.h" #import "AViewController.h" #import "BViewController.h" #import "CViewController.h" @implementation AppDelegate - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{ NSInteger index = tabBarController.selectedIndex; NSLog(@"%d",index); //选中tab中的某一个项后触发 //viewController.tabBarItem.badgeValue = nil; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; AViewController *avc = [[AViewController alloc]initWithNibName:@"AViewController" bundle:nil]; UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:avc]; BViewController *bvc = [[BViewController alloc]initWithNibName:@"BViewController" bundle:nil]; CViewController *cvc = [[CViewController alloc]initWithNibName:@"CViewController" bundle:nil]; // 创建tabBar的实例 UITabBarController *tabVC = [[UITabBarController alloc]init]; //设置颜色 tabVC.tabBar.tintColor = [UIColor redColor]; //设置tabBar的代理 tabVC.delegate = self; // 将多个vc放到tabBar中 tabVC.viewControllers = @[navi,bvc,cvc]; self.window.rootViewController = tabVC; [self.window makeKeyAndVisible]; return YES; } AViewController.h AViewController.m #import "AViewController.h" #import "OtherViewController.h" @interface AViewController () @end @implementation AViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { //配置文字 self.title = @"AVC"; //self.tabBarItem.title = @"AVC"; //配置图片 self.tabBarItem.image =[UIImage imageNamed:@"line_bell"]; self.tabBarItem.selectedImage = [UIImage imageNamed:@"full_bell"]; self.tabBarItem.badgeValue = @"2";//配置徽章 } return self; } - (void)viewDidLoad { [super viewDidLoad]; //配置导航的右侧按钮 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(gotoOther:)]; } -(void)gotoOther:(UIBarButtonItem *)barButton{ //推出otherVC OtherViewController *ovc = [[OtherViewController alloc]initWithNibName:@"OtherViewController" bundle:nil]; //推出时,隐藏底部区域 ovc.hidesBottomBarWhenPushed = YES; [self.navigationController pushViewController:ovc animated:YES]; } //点击按钮,跳到第三个界面 - (IBAction)gotoCVC:(id)sender { self.tabBarController.selectedIndex = 2; 连线按钮 } @end 想要哪个界面显示,就配置哪个界面 BViewController.h BViewController.m CViewController.h CViewController.m OtherViewController.h OtherViewController.m  知识点 十四、其它控件 1. SegmentedControl 分段控件 SegmentedControl 分段控件 属性: selectedSegmentIndex 选中的分段按钮的下标 事件: valueChanged事件 SegViewController.h SegViewController.m #import "SegViewController.h" @interface SegViewController () @property(nonatomic,strong)NSArray *headerImageNames; @property (weak, nonatomic) IBOutlet UIImageView *headerImageView; 连线属性如下图 @property (weak, nonatomic) IBOutlet UISegmentedControl *segmented; @end @implementation SegViewController - (NSArray *)headerImageNames{ if (!_headerImageNames) { _headerImageNames =@[@"Brad Cox.png",@"Dennis Ritchie.png",@"Ray.png"]; } return _headerImageNames; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = @"分段"; self.tabBarItem.image = [UIImage imageNamed:@"line_ball"]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.titleView = self.segmented; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [self changeHeaderImage:self.segmented]; } - (IBAction)changeHeaderImage:(UISegmentedControl *)sender { //选择的segmented中的按钮的索引 NSInteger index = sender.selectedSegmentIndex; self.headerImageView.image = [UIImage imageNamed:self.headerImageNames[index]]; } @end  2. Activity Indicator 活动指示器 IndicatorViewController.h IndicatorViewController.m #import "IndicatorViewController.h" @interface IndicatorViewController () @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicator; @property (weak, nonatomic) IBOutlet UIProgressView *progressView; @end @implementation IndicatorViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title=@"指示器"; self.tabBarItem.image = [UIImage imageNamed:@"line_cart"]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.progressView.progress = 0; } - (IBAction)changeIndicator:(UIButton *)sender { //根据指示器的状态来决定是转动还是停止转动 if (self.indicator.isAnimating) { [self.indicator stopAnimating]; }else{ [self.indicator startAnimating]; } } - (IBAction)beginDownload:(id)sender { //启动一个计时器,每隔一段时间自动的执行动作 //使用sheduledTime。。。方法创建的计时器 //不需要启动已经开始工作 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(changeProgress:) userInfo:nil repeats:YES]; } -(void)changeProgress:(NSTimer *)timer{ //修改进度条的进度 self.progressView.progress+=0.1; if (self.progressView.progress >= 0.5) { 范围判断比较好 // 停止计时器 [timer invalidate]; } } @end  3. Progress View 进度条 4. Date Picker DateViewController.h DateViewController.m #import "DateViewController.h" @interface DateViewController () @property (weak, nonatomic) IBOutlet UIDatePicker *datePicker;连线 @property (weak, nonatomic) IBOutlet UILabel *dateLabel; @end @implementation DateViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = @"时间"; self.tabBarItem.image = [UIImage imageNamed:@"line_paint"]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. } - (IBAction)showDate:(UIButton *)sender { NSDate *date = self.datePicker.date; NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; NSString *dateString = [formatter stringFromDate:date]; self.dateLabel.text = dateString; } @end   5. Picker View 重要属性: date 获取选中后的时间对象 一般需要转换成指定的格式: NSDate *date = self.datePicker.date; NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; NSString *dateString = [formatter stringFromDate:date]; PickerViewController.h PickerViewController.m #import "PickerViewController.h" @interface PickerViewController ()<UIPickerViewDataSource,UIPickerViewDelegate> @property(nonatomic,strong)NSArray *fromCity; @property(nonatomic,strong)NSArray *toCity; @end @implementation PickerViewController - (NSArray *)fromCity{ if (!_fromCity) { _fromCity = @[@"北京",@"上海",@"广州",@"深圳"]; } return _fromCity; } - (NSArray *)toCity{ if (!_toCity) { _toCity = @[@"杭州",@"苏州"]; } return _toCity; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = @"picker view"; self.tabBarItem.image = [UIImage imageNamed:@"line_map"]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - UIPickerView DataSource //控件有几列 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ return 2; } //列中有几行 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ if (component == 0) { return self.fromCity.count; }else{ return self.toCity.count; } } #pragma mark - UIPickerView Delegate - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{ if (component == 0) { return self.fromCity[row]; }else{ return self.toCity[row]; } } @end  RelationPickerViewController.h RelationPickerViewController.m #import "RelationPickerViewController.h" @interface RelationPickerViewController ()<UIPickerViewDataSource,UIPickerViewDelegate> @property(nonatomic,strong)NSDictionary *dictionaryCitys; @property(nonatomic,strong)NSArray *allCityName; @property(nonatomic,strong)NSArray *allAreaName; @end @implementation RelationPickerViewController - (NSDictionary *)dictionaryCitys{ if (!_dictionaryCitys) { _dictionaryCitys = @{ @"北京":@[@"东城",@"西城",@"海淀"], @"上海":@[@"徐汇",@"静安",@"浦东"], @"广州":@[@"白云",@"越秀",@"天河"] }; } return _dictionaryCitys; } - (NSArray *)allCityName{ if (!_allCityName) { _allCityName = self.dictionaryCitys.allKeys; } return _allCityName; } - (NSArray *)allAreaName{ if (!_allAreaName) { _allAreaName = [self.dictionaryCitys objectForKey:self.allCityName[0]]; } return _allAreaName; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = @"地址"; self.tabBarItem.image = [ UIImage imageNamed:@"line_umbrella"]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; } -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ return 2; } -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ if (component==0) { return self.allCityName.count; }else{ return self.allAreaName.count; } } -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{ if (component==0) { return self.allCityName[row]; }else{ return self.allAreaName[row]; } } -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{ if (component == 0) { //1.获取第一列中选中的值 NSString *cityName = self.allCityName[row]; //2.根据第一列的值做key,找到对应的子地区 self.allAreaName = [self.dictionaryCitys objectForKey:cityName]; [pickerView reloadComponent:1]; // 修改第二列第一行为选中的值 [pickerView selectRow:0 inComponent:1 animated:YES]; } } @end  总: AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "SegViewController.h" #import "IndicatorViewController.h" #import "DateViewController.h" #import "PickerViewController.h" #import "RelationPickerViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; SegViewController *segVC = [[SegViewController alloc]initWithNibName:@"SegViewController" bundle:nil]; UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:segVC]; IndicatorViewController *indicatorVC = [[IndicatorViewController alloc]initWithNibName:@"IndicatorViewController" bundle:nil]; DateViewController *dateVC = [[DateViewController alloc]initWithNibName:@"DateViewController" bundle:nil]; PickerViewController *pVC = [[PickerViewController alloc]initWithNibName:@"PickerViewController" bundle:nil]; RelationPickerViewController *rVC = [[RelationPickerViewController alloc]initWithNibName:@"RelationPickerViewController" bundle:nil]; UITabBarController *tabVC = [[UITabBarController alloc]init]; tabVC.viewControllers = @[navi,indicatorVC,dateVC,pVC,rVC]; self.window.rootViewController = tabVC; [self.window makeKeyAndVisible]; return YES; } 3.iOS8中的警告框和操作表 3.1 创建 UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title"message:@"messsage"preferredStyle:UIAlertControllerStyleAlert]; 3.2 添加动作 UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style: UIAlertActionStyleCancel handler:^(UIAlertAction *action) { NSLog(@"Cancel");}]; [alertController addAction:cancelAction]; 3.3 添加文本框 [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {textField.secureTextEntry = YES;}]; 3.4 推出显示警告框 [self presentViewController:alertController animated:YES completion:nil]; 例:ios6 AlertViewController.h AlertViewController.m #import "AlertViewController.h" @interface AlertViewController () @end @implementation AlertViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. } - (IBAction)showAlerView:(id)sender { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"title" message:@"mes" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *action = [UIAlertAction actionWithTitle:@"YES" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { UITextField *t = (UITextField *)alertController.textFields[0]; NSLog(@"%@",t.text); }]; [alertController addAction:action]; [alertController addTextFieldWithConfigurationHandler:nil]; [self presentViewController:alertController animated:YES completion:nil]; } ======================================================================================== 知识点 十四、故事板Storyboard 1.Storyboard 故事板 1.1 为什么需要故事板 因为在使用xib文件制作界面时存在以下两个问题: a。多个xib之间表达的界面的层级关系,以及界面的行进关系无法在第一时间准确把握 b。代码中会有大量的创建目标控制器,类似于initWithNibName这样的代码,一旦有任何改动,那么所有initWithNibName就都需要修改,行进路线发生变动 基于以上两个问题,希望能够将app看成一个整体,能够清晰的表达界面的行进路线,以及对各个控制器的创建工作能够进行统一管理,于是,从iOS5以后,推出了故事板技术来代替xib 1.2 什么是故事板 一个特殊的文件,后缀是storyBoard,本质上还是一个xml文件,用于记录在应用中,各个界面的行进路线,能够以图形化的方式设计界面,并且对于其中使用到的控制器能够自动的创建对象。 故事板是从应用的整体角度来进行设计产品,并且将一部分创建工作实现了编码最大化的自动化。 1.3 故事板的简单使用 【Demo1_StoryBoard】 a。程序启动时的流程 在工程的配置文件中首先要配置Main Interface为故事板,然后在故事板中再设置起始场景,然后启动工程,第一个展示的界面对应的控制器实例就由故事板来自动创建了 b。场景 (Scene) 指的是故事板中的一个节点。节点中可以包含 控制器、第一响应者、出口以及该场景的过渡(Segue) c。设计界面 设计方法:与使用xib时没有区别 连线动作:没有区别 连线输出口:没有区别 重点需要注意的是:一旦需要对场景中的vc进行编码时,一定要单独创建一个没有xib文件的控制器器类,并且将故事板中的场景中的vc与创建的控制器类绑定在一起 如何绑定:选中 场景,点击第三个检查器,选择class属性,后面的下拉框,找到对应的控制器类即可 1.4 使用storyBoard配置各种控制器 a。导航 Editor—>Embed in—>导航/标签 b。标签 c。表格 设置表格的步骤: 1)选中表视图后,设置表格是static(静态)还是dynamic(动态)的 2)选中表视图中的 Prototype Cell(原型单元格),在第四个检查其中修改为自定义单元格或者是4种基本样式中的某一个中类型 3)一定要为Prototype Cell设置identifier,因为这一次的设置相当于原来在viewDidLoad中写的regist。。。注册单元格的代码 4)为表视图绑定自己创建的继承自UITableViewController的类,回答三问一答 5)其中,viewDidLoad中已经不需要使用regist方法来注册单元格了,在第三问中,只需要直接从队列中按照在storyBoard中设置的identifier来dequeu单元格即可。 注意: 1。identifier区分大小写 2。deque单元格时,可以使用带有forIndexPath参数的那个方法了 1.5 UITableView在故事板中的使用【Demo1】 a。静态表格的配置 实现步骤: 从资源库中添加表格控制器,在第四个检查器中,设置第一个Content为Static Cell 修改Prototype 属性的值为0 设置section属性 (分区) 设置style属性为group 逐一选中各个Section设置头和cell的数目 逐一选中Cell,设置样式 新建一个类,继承自UITableViewController,在故事板中选中控制器,修改第三个检查器中的class属性,将自定义的类与场景关联起来 ****删除新建的类中,有关生成表格的三问一答的代码 ****如果需要对静态表格中的控件,赋动态值,可以在拆分视图下,将控件连线到类中,然后在viewWillAppear:事件中为控件赋值  b。动态表格的配置 1)系统原型 实现步骤: 从资源库中添加表格控制器 设置表格的Prototype 的个数为1 选中Prototype Cell,在检查器中,设置该原型的style及identifier 创建一个类,继承自UITableViewController 将类与故事板中的控制器绑定 在类中回答三问,其中,单元格不需要注册,回答第三问时,直接按照属性栏中设置的identifier去队列中取单元格即可 2)自定义原型 实现步骤: 从资源库中拖拽一个TableVC 添加一个单元格原型view 设定该原型的style为Custom 设定该原型的identifier 设计cell的内容 新建一个类,继承自UITableViewCell 选中原型cell,第三个检查器,设定class为新建的类 拆分视图中,将原型cell中的各个控件连线到类中,作为公开的输出口 新建一个类,继承自UITableViewController,并与故事板中的vc绑定 回答第三个问题时,从队列中按照原型的identifier取出自定义的cell类的实例,并返回 3)混合原型 实现步骤: 在故事板中添加tableVC后,设定Prototype Cell的个数为2 为每一个Prototype Cell设定identifier 在tableVC绑定的自定义类中,回答三问一答 其中,第三问,生成单元格时,可以根据生成的单元格的位置及设定的规律,取队列中,按照不同的identifier来取不同原型的单元格,然后返回 News.h #import <Foundation/Foundation.h> @interface News : NSObject @property(nonatomic,strong) NSString *title; @property(nonatomic,strong) NSString *newsImageName; @property(nonatomic) NSUInteger commentNumber; -(instancetype)initWithTitle:(NSString*)title andImageName:(NSString*)imageName andCommentNumber:(NSUInteger)commentNumber; +(NSArray *)demoData; @end News.M #import "News.h" @implementation News -(instancetype)initWithTitle:(NSString*)title andImageName:(NSString*)imageName andCommentNumber:(NSUInteger)commentNumber{ self = [super init]; if (self) { self.title = title; self.newsImageName = imageName; self.commentNumber = commentNumber; } return self; } + (NSArray *)demoData{ News *n1 = [[News alloc]initWithTitle:@"联通被曝高危漏洞 或致用户通话记录等信息泄露" andImageName:@"n1.png" andCommentNumber:186]; News *n2 = [[News alloc]initWithTitle:@"CES2015回顾:民用无人机来袭 中国公司占主导" andImageName:@"n2.png" andCommentNumber:17]; News *n3 = [[News alloc]initWithTitle:@"中企征战CES:难寻颠覆性产品 未打通海外品牌渠道" andImageName:@"n3.png" andCommentNumber:17]; News *n4 = [[News alloc]initWithTitle:@"老话重提:“专车”是否是黑车?被查合不合法" andImageName:@"n4.png" andCommentNumber:178]; News *n5 = [[News alloc]initWithTitle:@"马云告诫员工千万别碰京东:京东将会成悲剧" andImageName:@"n5.png" andCommentNumber:4374]; News *n6 = [[News alloc]initWithTitle:@"三星Q4营业利润47亿美元超预期:内存芯片需求利好" andImageName:@"n6.png" andCommentNumber:6]; News *n7 = [[News alloc]initWithTitle:@"索尼宣布PS4国行版延期上市 或因被举报不锁区" andImageName:@"n7.png" andCommentNumber:0]; News *n8 = [[News alloc]initWithTitle:@"微众银行开业前夕推“信用付”临时核心系统过度" andImageName:@"n8.png" andCommentNumber:4]; return @[n1,n2,n3,n4,n5,n6,n7,n8]; } @end NewsCell.h #import <UIKit/UIKit.h> 连线自定义的内容 @interface NewsCell : UITableViewCell @property (weak, nonatomic) IBOutlet UIImageView *newsImageVIew; @property (weak, nonatomic) IBOutlet UILabel *newsTitleLabel; @property (weak, nonatomic) IBOutlet UILabel *newsCountLabel; @end NewsCell.M MutilProtoViewController.h MutilProtoViewController.m #import "MutilProtoViewController.h" #import "News.h" #import "NewsCell.h" @interface MutilProtoViewController () @property(nonatomic,strong)NSArray *allNews; @end @implementation MutilProtoViewController - (NSArray *)allNews{ if (!_allNews) { _allNews = [News demoData]; } return _allNews; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.allNews.count*2; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row % 2) { NewsCell *newsCell = [tableView dequeueReusableCellWithIdentifier:@"Cell2" forIndexPath:indexPath]; //按照行号找到数据 //得到的标号是: 0 1 2 3 4 5 //实际的行号是: 1 3 5 7 9 11 News *news = self.allNews[indexPath.row/2]; //将新闻实体的各个属性设置到cell中 newsCell.newsImageVIew.image = [UIImage imageNamed:news.newsImageName]; newsCell.newsTitleLabel.text = news.title; newsCell.newsCountLabel.text = [NSString stringWithFormat:@"%d",news.commentNumber]; return newsCell; }else{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell1" forIndexPath:indexPath]; cell.textLabel.text = @"订单详情"; return cell; } } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ if (indexPath.row%2) { return 100; }else{ return 44; } }  1.6跳转 【Demo2_Goto_OtherVC】 从一个场景跳转到另一个场景(从一个vc跳转到另一个vc)的过程 实现方式: 方式一:Segue 不需要编写代码,通过连线的方式来实现 实现步骤: 选中原始vc,按住control,按左键,拖拽到目标vc,弹出菜单后,根据跳转的需要选择push或model即可 方式二: 从一个vc跳转到故事板中的另一个独立的vc 实现步骤: 选中故事板中的vc,第三个检查器中,设定vc的Storyboard ID 在要执行跳转的事件中编写代码 获取控制器所在的故事板对象 self.storyboard 故事板发送消息instantiateViewControllerWithIdentifier:@"SomeVC" 其中,参数填写为vc的storyboard ID即可 然后,推出该控制器实例 - (IBAction)gotoSomeVC:(UIButton *)sender { //找到故事板创建的vc实例 SomeViewController *someVC = [self.storyboard instantiateViewControllerWithIdentifier:@"SomeVC"]; //推出新vc [self.navigationController pushViewController:someVC animated:YES]; } 方式三:跳转到独立的xib 实现方式:同以前的跳转方式,使用initWithNibName方法创建vc的实例后,推出即可 - (IBAction)gotoOtherVC:(UIButton *)sender { //根据xib的名字创建vc OtherViewController *otherVC = [[OtherViewController alloc]initWithNibName:@"OtherViewController" bundle:nil]; //推出新vc [self.navigationController pushViewController:otherVC animated:YES]; } 1.7 传值 1.7.1 正向传值:从AVC跳转到BVC时,AVC传数据给BVC的过程 实现思路: a。BVC要有公开的属性接收数据 b。AVC在跳转到BVC之前,获取到BVC的引用,就可以为空开的属性赋值,完成正向传值了 c.segue.destinationViewController实现跳转 AViewController.h AViewController.m #import "AViewController.h" #import "BViewController.h" @interface AViewController () @property (weak, nonatomic) IBOutlet UITextField *textFiled; 连线文本框 @end @implementation AViewController - (void)viewDidLoad { [super viewDidLoad]; } //在跳转到BVC的Segue发生之前 //获取跳转到的目标vc也就是BVC的控制权 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if ([segue.identifier isEqualToString:@"segueToBVC"]) { 跳转线 //通过segue对象获取到目标vc BViewController *bvc = segue.destinationViewController; bvc.codeString = self.textFiled.text; } } BViewController.h #import <UIKit/UIKit.h> @interface BViewController : UIViewController @property(nonatomic,strong)NSString *codeString; @end BViewController.m #import "BViewController.h" @interface BViewController () @property (weak, nonatomic) IBOutlet UILabel *codeLabel; @end @implementation BViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear:(BOOL)animated { self.codeLabel.text = self.codeString; } @end 1.7.2 反向传值:从AVC跳转到BVC后,BVC返回AVC的过程中给AVC传值的过程 实现思路: a。BVC是委托方,做三件事(定义协议,添加delegate属性,合适的时机发消息) b。AVC是代理方,做三件事(遵守协议,实现方法,设置BVC的delegate为self) **注意:设置BVC的delegate为self时应考虑segue方法,使用如下 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if ([segue.identifier isEqualToString:@"segueGotoDVC"]) { DViewController *dvc = segue.destinationViewController; dvc.delegate = self; } } =========================================================== 知识点 十五、UICollectionViewController 1.1 是什么? 可以控制视图,以多行多列的形式展示数据的一种控制器。是从UITableViewController演变而来,所以在使用上与表视图很像。(从iOS6开始支持) 1.2 与表视图相比的相同点 UITableViewController .tableView (UITableView) .dataSource (id<UITableViewDataSource>) .delegate(id<UITableViewDelegate>) 每一行的类型是:UITableViewCell 加载数据:实现三问一答即可(有几个分区,每个分区多少行,每一行什么样) UICollectionViewController .collectionView (UICollectionView) .dataSource(id<UICollectionViewDataSource>) .delegate(id<UICollectionViewDelegate>) 每一个项的类型:UICollectionViewCell 加载数据:实现三问一答即可(有几个分区,每个分区多少item,每一个项什么样) 1.3与tableView相比不同点 a。tableViewCell默认自带了三个显示内容的控件(imageView,textLabel,detailLabel),并且这三个控件的摆放位置也有系统定义好的四种样式,而collectionViewCell没有任何事先由系统定义的用于显示内容的控件,只有能访问的这样几个属性:backgroundColor、backgroundView、contentView b。tableViewCell的排布顺序是系统提前定义好的,都是严格的按照从上到下,依次排布,也就是每一个cell的坐标,在指定了行高以后,都有系统计算完成并显示;collectionView没有固定的item的排布规则,需要自定义,这是需要一个特殊的叫做布局类(UICollectionViewLayout)来辅助CollectionView完成每一个item的显示位置的设定,系统只提供了一种布局类,从UICollectionViewLayout派生出来的,叫做流式布局UICollectionFlowLayout,这种系统定义的布局类的布局特点是:一行排满后,自动换行, 1.4UICollectionViewController的基本使用 1.1Code 纯代码的方式【Demo1_CollectionView_Code】 a。Cell的简单样式 + 系统的流式布局 UICollectionViewCell + UICollectionViewFlowLayout b。Cell的简单样式 + 自定义的流式布局 UICollectionViewCell+MyFlowLayout c。自定义Cell + 自定义的流式布局 MyCell + MyFlowLayout AppDelegate.h AppDelegate.m #import "AppDelegate.h" #import "MyCollectionViewController.h" #import "MyFlowLayout.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]]; //创建一个默认的流式布局类的对象 //UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init]; MyFlowLayout *layout = [[MyFlowLayout alloc]init]; MyCollectionViewController *vc = [[MyCollectionViewController alloc]initWithCollectionViewLayout:layout]; self.window.rootViewController = vc; [self.window makeKeyAndVisible]; return YES; } MyCell.h #import <UIKit/UIKit.h> @interface MyCell : UICollectionViewCell @property(nonatomic,strong)UIImageView *bgImageView; @property(nonatomic,strong)UILabel *label; @end MyCell.m #import "MyCell.h" @implementation MyCell - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; //设置图片视图为cell的背景视图 self.backgroundView = self.bgImageView; self.label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; self.label.textAlignment = NSTextAlignmentCenter; self.label.font = [UIFont boldSystemFontOfSize:30]; //将标签添加到cell的内容视图中 [self.contentView addSubview:self.label]; } return self; } @end MyFlowLayout.h #import <UIKit/UIKit.h> @interface MyFlowLayout : UICollectionViewFlowLayout @end MyFlowLayout.m #import "MyFlowLayout.h" @implementation MyFlowLayout - (id)init { self = [super init]; if (self) { // 流式布局的自定义设置 self.itemSize = CGSizeMake(80, 80); self.minimumLineSpacing = 10; self.minimumInteritemSpacing = 10; self.sectionInset = UIEdgeInsetsMake(154, 30, 154, 30); self.scrollDirection = UICollectionViewScrollDirectionHorizontal; } return self; } @end MyCollectionViewController.h #import <UIKit/UIKit.h> @interface MyCollectionViewController : UICollectionViewController @end MyCollectionViewController.m #import "MyCollectionViewController.h" #import "MyCell.h" @interface MyCollectionViewController () @end @implementation MyCollectionViewController static NSString *reuseIdentifier=@"MyCell"; - (void)viewDidLoad { [super viewDidLoad]; //注册CollectionViewCell [self.collectionView registerClass:[MyCell class] forCellWithReuseIdentifier:reuseIdentifier]; } // 三问 // 第一问:多少个分区 -(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 3; } // 第二问:每个分区多少个项 -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return 9; } // 第三问:每个项什么样 -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // 从队列中按标识取cell MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; // 设置自定义cell的背景图和标签的内容 cell.bgImageView.image = [UIImage imageNamed:@"f.png"]; cell.label.text = [NSString stringWithFormat:@"%d",indexPath.row]; // 设置cell // cell.backgroundColor = [UIColor whiteColor]; // UILabel *label = (UILabel *)[cell.contentView viewWithTag:1]; // if (label == nil) { // label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, cell.bounds.size.width, cell.bounds.size.height)]; // label.font = [UIFont boldSystemFontOfSize:26]; // label.textAlignment = NSTextAlignmentCenter; // //为label添加tag值 // label.tag = 1; // [cell.contentView addSubview:label]; // } // label.text = [NSString stringWithFormat:@"%d",indexPath.row]; // // 返回cell return cell; } 水平滚动显示 竖直滚动显示   1.2 Xib 方式 1).主要就是xib中创建的UICollectionViewController,如果是自动义的布局需在xib的右侧区域与创建的类相连接,并且需注意注册时应该使用nibWithNibName,如: - (void)viewDidLoad { [super viewDidLoad]; //注册cell //[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier]; [self.collectionView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellWithReuseIdentifier:reuseIdentifier]; }  ***上边的图片是在xib中刚开始创建的时候并没有与控制器连接,需通过黄色的方框与控制器连接,并通过第五个检查器连线设置代理 2).并且注意MyFlowLayout.m中要初始化方法需使用- (id)initWithCoder:(NSCoder *)aDecoder{来设置布局大小,滚动方向等 - (id)initWithCoder:(NSCoder *)aDecoder{ self = [super initWithCoder:aDecoder]; if (self) { self.itemSize = CGSizeMake(60, 60); self.minimumInteritemSpacing = 10; self.minimumLineSpacing = 10; self.sectionInset = UIEdgeInsetsMake(100, 25, 100, 25); self.scrollDirection = UICollectionViewScrollDirectionVertical; } return self; } 3).而MyCell.h类中的单元格内容的设置不需要手写代码了,只需在xib中设置,然后公开属性连线即可(需注意此类创建不自带xib,需自己重新创建,User Interface—>Empty—>next—>起名字,与类名前缀起的一样即可,并添加单元格,在单元格里添加图片和label即可,将class与自己创建的类关联起来) 1.3 Storyboard方式 1).故事板中导入UICollectionViewController控制器,全部选中,并将自己创建的类相关联, 2)只选中view,设置自定义和格式,并与创建的类MyFlowLayout相关联,滚动方向及显示大小都通过自己创建的类来设置 3)选中故事板中的cell与自己创建的类相关联class,自己创建的cell类在公开属性中与故事板中创建的模型连接属性即可  2.使用UICollectionViewController实现复杂布局 2.1 自定义的复杂的流式布局实现水平移动时的缩放 MyFlowLayout.h MyFlowLayout.m #import "MyFlowLayout.h" @implementation MyFlowLayout -(id)init { self = [super init]; if (self) { self.itemSize = CGSizeMake(200, 200); self.scrollDirection = UICollectionViewScrollDirectionHorizontal; self.sectionInset = UIEdgeInsetsMake(60, 0, 60, 0); self.minimumLineSpacing = 100; } return self; } -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{ return YES; } 必须使用这个方法进行缩放 -(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{ NSArray *array = [super layoutAttributesForElementsInRect:rect]; //创建可视化的矩形区域 CGRect visiabelRect = CGRectZero; visiabelRect.origin = self.collectionView.contentOffset; visiabelRect.size = self.collectionView.bounds.size; //可视化矩形区域的中心点x CGFloat visiableRectCenterX = CGRectGetMidX(visiabelRect); //依次获取系统指定的矩形区域中的每一个item //的中心点坐标 //将可视化区域的中心点与item的中心点进行 //比对,根据两个中心点的距离产生一个变化的 //比率,并将该比率作为item的缩放比率即可 for (UICollectionViewLayoutAttributes *attributes in array) { //获取每一个item的中心点 CGFloat itemCenterX = attributes.center.x; //计算两个中心点的距离 CGFloat distance = visiableRectCenterX - itemCenterX; //设定两个中心点的距离在200以内时 //才针对item做放大缩小的操作 if (ABS(distance) < 200) { //根据distance的大小产生一个变化的zoomFator缩放因子 CGFloat zoomFactor = 1 + 0.5*(1-ABS(distance/200.0)); attributes.transform3D = CATransform3DMakeScale(zoomFactor, zoomFactor, 1); } } return array; } @end 2.2 自定义的不规则布局 补充: 1.frame属性描述的是,视图在父视图中的位置及所占的区域大小 2.bounds属性描述的是,视图本身的大小 3.屏幕:3.5 宽 320 高480 屏幕:4 宽 320 高568 练习: 水平滚动的 三页九宫格 垂直滚动的 三页九宫格 九宫格间距较紧密,居中显示 水平滚动:(4寸) itemSize:80 X 80 itemSpacing:10 lineSpacing:10 sectionInset:top:[568 - (80*3+10*2)]/2=154 left:[320 - (80*3+10*2)]/2= 30 总结: 如果要利用UICollectionViewController来设计界面,需要创建3个类来实现此功能 MyCollectionViewController.h MyCollectionViewController.m 此类中主要用于实现三问一答,继承自UICollectionViewController用来创建表格的基本模式,几个分区,几列以及表格的显示内容(需注意:表格的内容需在viewDidLoad中注册才能创建),实现表格的重用 MyFlowLayout.h MyFlowLayout.m 此类中主要是为了布局,继承自UICollectionViewFlowLayout重写初始化方法,设置显示的大小,项目间的距离、行高、以及水平滚动还是竖直滚动,以及与屏幕的上下左右的间距。 self.itemSize 设置每个单元格的大小 self.scrollDirection 设置水平滚动还是竖直滚动 self.sectionInset 设置距离屏幕上下左右的距离 self.minimumLineSpacing 设置行间距 self.minimumInteritemSpacing 设置项目之间的距离 MyCell.h MyCell.m 此类中主要用来设置单元格的内容,继承自UICollectionViewCell在.h文件中设置一个公开的属性,与MyCollectionViewController联系,一般情况下设置图片背景和标签,在initWithFrame方法中设置。 如: - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; self.backgroundView = self.bgImageView; //边框线条宽度 self.contentView.layer.borderWidth = 1.0f; //边框的颜色 self.contentView.layer.borderColor = [UIColor whiteColor].CGColor; } return self; } =========================================================================================================
相关文章推荐
- ueditor的配置和使用
- IOS UI总结
- iOS 通过storyboard设置UIView或者其他layer图层的圆角
- 努比亚 Z5 mini刷机包 omni4.4.2改动V4.0 自用版 精简 MIUI特效
- IOS7 UI设计的十大准则
- 为NGUI panel 添加 sorting layer
- NGUI学习笔记
- [leetcdoe] 51. N-Queens 解题报告.
- NGUI制作显示tooltip需要注意的地方
- iOS9 UI Tests探索笔记
- NGUI -- UIWidget
- NGUI -- UIRect
- IOS UIScrollView注意要点(AutoLayout情况)
- [hdoj试题]Buildings
- Finished with Non Zero Exit Value 3
- 优化UITableViewCell高度计算的那些事
- StringBuffer和StringBuild区别
- this android sdk requires ADT version 23
- [Java开发之路](4)String、StringBuffer与StringBuilder详解
- UITableViewCell 滑动删除