UI基础知识汇总
iOS的坐标系
原点是屏幕的左上角,各机型取值范围如下表所述:
![](https://img.haomeiwen.com/i1447833/1aa54b5d8c7004cd.png)
UIView 视图的类(略讲)
@property(nonatomic) CGRect frame; 尺寸
@property(nonatomic,copy) UIColor *backgroundColor 背景色
@property(nonatomic) CGPoint center; 中心点位置
@property(nonatomic)CGFloat alpha; 透明度
@property(nonatomic,getter=isHidden) BOOL hidden; 是否掩藏
@property(nonatomic) BOOL clipsToBounds; 超出父视图是否显示
@property(nonatomic,readonly) UIView *superview; 父视图
@property(nonatomic,readonly,copy) NSArray *subviews; 子视图
- (void)addSubview:(UIView *)view; 添加视图
UILabel父类为UIView,标签,用于展示文字,用户不可以对文字进行编辑
@property(nonatomic,copy) NSString *text; //设置显示的文字
@property(nonatomic,retain) UIFont *font; //设置文字的字体 封装的时候可以用宏定义
@property(nonatomic) NSTextAlignment textAlignment; //设置文字的对齐方式
@property(nonatomic,retain) UIColor *textColor; //设置文字的字体颜色
@property(nonatomic,retain) UIColor *shadowColor; //设置阴影颜色
@property(nonatomic) CGSize shadowOffset; //设置阴影的偏移量(相对原来文字的偏移量)
@property(nonatomic) NSLineBreakMode lineBreakMode; //设置文字的换行方式
NSLineBreakByCharWrapping label中比较精确的设置文字的一种换行方式
@property(nonatomic) NSInteger numberOfLines; //设置文字显示的行数, numberOfLines =0 不限制行数,默认UILabel只显示一行文字
UIFont 字体的类
systemFontOfSize 系统字体样式,并设置字号,默认字号为17
NSArray *familyArray = [UIFont familyNames];//拿到字体族的数组,数组中是字体族的名称
for (NSString *familyName in familyArray) { //根据字体族的名称,拿到字体的名称
NSArray *names = [UIFont fontNamesForFamilyName:familyName];
for (NSString *fontName in names) { NSLog(@"fontName:%@",fontName); }
}
UIButton&NSTime&UIImageView
UIButton是一个视图类,继承自UIControl 间接继承自UIView,凡是UIControl子类可以接收触发事件。UIButton用于创建一个按钮,添加点击事件开发中注意的事情:把我们的button 尽量写的够大,可以=看起来不那么大,这样做的好处是方便用户点击.
常见的三种状态:
1、UIControlStateNormal 正常状态
2、UIControlStateHighlighted 高亮状态
3、UIControlStateSelected 选中状态(设置btn.selected)//大部分用在同意协议和不同意协议 btn.selected=yes,就是被选中状态常用方法
- (void)setTitle:(NSString *)title forState:(UIControlState)state;//设置title和title的颜色
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;//设置前景图 用的是填充方式的第二种
- (void)setImage:(UIImage *)image forState:(UIControlState)state; //设置背景图片
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;//给button添加方法
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
补充:
1、png格式的图片支持镂空,iOS应用中绝大多数素材都是PNG格式
2、设置视图的标记,通过标记可以找到视图(From UIView) [self.view viewWithTag:xxx];
定时器NSTimer
常用方法
1、+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
timer创建方法是类方法,自动释放,离开当前函数就有释放的危险,但是如果添加为成员变量,就在dealloc释放了timer创建就启动,停止就销毁。第一个参数,表示时间间隔;target是接收消息的对象;selector是消息;user info传nil;repeats如果添NO,定时器,只工作一次,添YES,每xx秒,发送action给self一次。
2、- (void)invalidate;@property (copy) NSDate *fireDate;
此函数标示定时器启动时间,使用[NSDate distantFuture]放在未来是停止,[NSDate distantPast])放在过去就是开始
UIImage和UIImageView
【注】UIImage和UIImageView的关系,近似于NSString和UILabel的关系。
一.UIImage的取图方式
1、通过图片姓名获取图片+ (UIImage *)imageNamed:(NSString *)name; //会将图片读到内存中因此imageNamed的优点是当加载时会缓存图片到本地。所以当图片会频繁的使用时,那么用imageNamed的方法会比较好。
2、根据图片的路径获取图片 ,不会把图片读到内存中,先获得图片在App包内的路径NSString *path=[[NSBundle mainBundle]pathForResource:@"DOVE 1" ofType:@"png"]+ (UIImage *)imageWithContentsOfFile:(NSString *)path;imageWithContentsOfFile:仅加载图片,图像数据不会缓存。因此对于较大的图片以及使用情况较少时,那就可以用该方法,降低内存消耗
二.图片视图的基本使用常用属性:
@property(nonatomic,retain) UIImage *image; //设置静态图片
三.imageView中的图片
方法先创建图片视图UIImageView *imageView =[[UIImageView alloc]initWithFrame:CGRectMake(xx, xx, xx, xx)];
imageView.image=[UIImage imageNamed:@“图片的名称”];
@property(nonatomic)UIViewContentMode contentMode;// default 取值: UIViewContentModeScaleToFill 拉伸填满,缺省; UIViewContentModeScaleAspectFit 按比例填充; UIViewContentModeScaleAspectFill 按比例填满
四.图片视图的动画效果
这个一般和+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo 放在一起用。
imageView.animationImages = array;//设置动画图片数组
imageView.animationDuration = 1.5;//设置动画时间,是全部图片切换一次的时间
imageView.animationRepeatCount = 0;//设置动画重复次数,设为0是无限次
[imageView startAnimating];//启动动画[imageView stopAnimating];//停止动画
UIView
UIView是所有视图的父类,UIView的属性和方法,就是所有视图的属性和方法 UILabel、Unbutton、UITextField、UIImageView的父类都是UIView
一.关于坐标系的属性和方法
@property(nonatomic) CGRect frame;
@property(nonatomic) CGRect bounds;
@property(nonatomic) CGPoint center;
@property(nonatomic) CGAffinesTransform transform; frame: 该view在父view坐标系统中的位置和大小。(参照点是,父亲的坐标系统) bounds:该view在本地坐标系统中的位置和大小。(参照点是,本地坐标系统,就相当于ViewB自己的坐标系统,以0,0点为起点) center:该view的中心点在父view坐标系统中的位置和大小。(参照物是,父亲的坐标系统)我个人认为,bounds稍微有点费解,稍不留神,想的多了,就会绕进去。每个view都有一个本地坐标系统。这个坐标系统作用比较重要,比如触 摸的回调函数中的UITouch里面的>坐标值都是参照这个本地坐标系统的坐标。当然bounds这个属性也是参照这个本地坐标系统来的。其实本地 坐标系统的关键就是要知道的它的原点(0,0)在什么位置(这个位置又是相对于上层的view的本地坐标系统而言的,当然最上面的一层view就是 window它的本地坐标系统原点就是屏幕的左上角了)。通过修改view的bounds属性可以修改本地坐标系统的原点位置。所以,我个人认为,bounds影响到子view的位置和大小
二、Transform 属性
UIView有个transform的属性,通过设置该属性,我们可以实现调整该view在其superView中的大小和位置,具体来说,Transform(变化矩阵)是一种3×3的矩阵,通过这个矩阵我们可以对一个坐标系统进行缩放,平移,旋转以及这两者的任意组着操作。而且矩阵的操作不具备交换律,即矩阵的操作的顺序不同会导致不同的结果。
常用的三种实现选中的方式:
1、view.transform=CGAffineTransformScale(view.transform, 0.5, 0.5); // 实现的是放大和缩小,两个浮点数,表示变形后和变形前横纵坐标的百分比
2、view.transform=CGAffineTransformRotate(view.transform, 0.2); //实现的是旋转角度变形(旋转形变),单位是弧度2*PI是一周 参数是一个浮点数,表示弧度 顺时针为
3、view.transform=CGAffineTransformTranslate(view.transform, 20, 20); //实现的是平移
由此可以发现屏幕旋转其实就是通过view的矩阵变化实现,当设备监测到旋转的时候,会通知当前程序,当前程序再通知程序中的window,window会通知它的rootViewController的,rootViewController对其view的transform进行设置,最终完成旋转。
另:frame bounds center transform 四个属性相互关联,改变其中一个,另三个也会改变。
【注】bounds origin部分是用来修改当前视图的原点坐标即左上角一点坐标,修改了这个坐标,影响的是子视图的位置。
三、关于父子视图关系的属性和方法
【注】任何视图,都可以添加到另一个视图上面,但是每个视图只能有一个父视图。也就是说一个子视图被添加到另一个视图上,会从原父视图上脱离。
【注】子视图的坐标是相对于父视图的。以父视图左上角一点为原点,缺省原点为(0,0)点。
移动父视图,因为子视图的位置是相对的,所以会一起移动。修改父视图坐标,子视图跟着动, 父视图隐藏,子视图一起隐藏。子视图的实际透明度,是父视图透明度X子视图透明度 。默认超出父视图的部分是可见的。父视图可以设置,边界裁剪,即裁减掉超出当前视图的子视图。
@property(nonatomic,readonly) UIView *superview;//拿到当前视图的父视图
@property(nonatomic,readonly,copy) NSArray *subviews;//这个方法是获取的子视图,以数组的形式返回 NSArray *array=self.view.subviews; subViews这个数组中的顺序是按照子视图的层次排的,最下面的子视图就是第0个元素,最上面的子视图就是最后一个元素
四.关于同父视图的子视图的层次关系
[view bringSubviewToFront:redLabel]; //传入子视图地址,将子视图拿到最上层
[view sendSubviewToBack:yellowLabel];//将子视图放到最下面
[view insertSubview:blueLabel atIndex:0];//将某个子视图,插入到某一层,这个方法中,如果subview不是view的子视图,则会添加为子视图,如果已经是子视图,则会改变层次
[view insertSubview:redLabel aboveSubview:yellowLabel]; //同上
[view insertSubview:redLabel belowSubview:subviews[1]]; //同上
[view exchangeSubviewAtIndex:0 withSubviewAtIndex:2];//交换两个子视图层次
Δ五.层次与事件接收
1.父视图不能接收事件,则子视图无法接受事件。
2.子视图超出父视图的部分,不能接收事件
3.同一个父视图下,最上面的视图,首先遭遇事件,如果能够响应,就不向下传递事件。如果不能响应,事件向下传递。
六、UIView动画
【注】UIView动画只能修改关于坐标系的属性,以及色彩和透明度。
第一种动画设置方法
[UIView beginAnimations:nil context:nil];//启动UIView动画
[UIView setAnimationDelay:0]; //设置延迟启动
[UIView setAnimationDuration:10];//设置动画时间
[UIView setAnimationDelegate:self];//设置代理
[UIView setAnimationDidStopSelector:@selector(stopAnimation)];//设置回调方法
[UIView commitAnimations];//设置完毕,启动动画
第二种动画设置方法
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations//+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion //+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
UITextFiled
文本输入框,用于用户输入文本信息(类似于C scanf)的UI视图
一.基础属性方法,下面列出属性方法的在工程中相关函数
textField.borderStyle=UITextBorderStyleRoundedRect; //设置边框样式 UITextBorderStyleNone 没有 ; UITextBorderStyleLine 线状边框 ; UITextBorderStyleBezel 直角立体矩形(底座) ; UITextBorderStyleRoundedRect 圆角矩形
textField.text = @"用户名"; //设置文字
textField.textColor = [UIColor blueColor]; //设置文字颜色
textField.textAlignment = NSTextAlignmentLeft; //设置文字的对齐方式
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; //设置文字的垂直对齐方式
textField.font = [UIFont systemFontOfSize:20]; //设置文字的字体
textField.placeholder = @"请输入用户名"; //设置占位符
textField.secureTextEntry = NO;//设置密文显示
textField.clearButtonMode = UITextFieldViewModeAlways; //设置clearButton模式 UITextFieldViewModeNever, 永不显示 ; UITextFieldViewModeWhileEditing, 当编辑时 ; UITextFieldViewModeUnlessEditing, 除了编辑时 ; UITextFieldViewModeAlways, 永远显示
textField.leftView = leftView; textField.rightView = rightView; //设置左右视图设置左右视图的显示模式 textField.leftViewMode = UITextFieldViewModeAlways; textField.rightViewMode = UITextFieldViewModeAlways;
BOOL ret = textField.isEditing; //判断textField是否处于编辑模式
textField.clearsOnBeginEditing = YES;/*关于设置键盘样式*/ //设置进入编辑状态,立即清空文字
textField.keyboardType = UIKeyboardTypeDefault; //设置弹出的键盘样式
UIKeyboardTypeDefault, 默认样式,可以输入一切字符;
UIKeyboardTypeASCIICapable, 可以输入ASCII码表上的所有字符即英文键盘;
UIKeyboardTypeNumbersAndPunctuation, 可以输入数字和字符的键盘,就是手提电话键盘
UIKeyboardTypeURL, 适合输入网址的键盘
UIKeyboardTypeNumberPad, 纯粹数字键盘
UIKeyboardTypePhonePad, 座机电话键盘
UIKeyboardTypeNamePhonePad, 默认键盘,点击123会弹出数字键盘
UIKeyboardTypeEmailAddress, 适合输入email的键盘
UIKeyboardTypeDecimalPad, 有小数点的数字键盘
UIKeyboardTypeTwitter, 适合输入推特地址的键盘
UIKeyboardTypeWebSearch, 适合输入网址地址的键盘
二、设置键盘的return键样式
只有键盘样式为default生效 textField.returnKeyType = UIReturnKeyNext; // UIReturnKeyDefault, 返回 // UIReturnKeyGo, 前往 // UIReturnKeyGoogle, 搜索 // UIReturnKeyJoin, 加入 // UIReturnKeyNext, 下一项 // UIReturnKeyRoute, 路线 // UIReturnKeySearch, 搜索 // UIReturnKeySend, 发送 // UIReturnKeyYahoo, 搜索 // UIReturnKeyDone, 完成 // UIReturnKeyEmergencyCall, 紧急电话9、设置键盘的色彩 textField.keyboardAppearance = UIKeyboardAppearanceDefault; // UIKeyboardAppearanceDefault, 默认,根据设置的键盘不同,不同 // UIKeyboardAppearanceDark iOS7生效,深色 // UIKeyboardAppearanceLight iOS7生效,浅色 // UIKeyboardAppearanceAlert = UIKeyboardAppearanceDark,10、设置大写提示,只是用于英语 textField.autocapitalizationType = UITextAutocapitalizationTypeNone; // UITextAutocapitalizationTypeNone, 不大写 // UITextAutocapitalizationTypeWords, 单词首字符大写 // UITextAutocapitalizationTypeSentences, 句子首字符大写 // UITextAutocapitalizationTypeAllCharacters, 全部字符大写 11、设置自动纠错,适用于英文 textField.autocorrectionType = UITextAutocorrectionTypeNo; // UITextAutocorrectionTypeDefault, 默认,按照在设置里进行的设置 // UITextAutocorrectionTypeNo, 不纠错 // UITextAutocorrectionTypeYes, 纠错12、设置弹出自定义键盘 UIView * keyboardView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 200)]; //只有视图的高生效 textField.inputView = keyboardView; 13、设置弹出自定制二级键盘 textField.inputAccessoryView = label;14、becomeFirstResponder 成为第一响应者 resignFirstResponder取消第一响应二.协议中的方法- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField; //当textField将要开始被编辑,会委托代理调用这个方法- (void)textFieldDidBeginEditing:(UITextField *)textField; //当textField已经开始被编辑,会委托代理调用这个方法- (BOOL)textFieldShouldEndEditing:(UITextField *)textField; //当textField将要结束被编辑,会委托代理调用这个方法- (void)textFieldDidEndEditing:(UITextField *)textField; //当textField已经结束被编辑,会委托代理调用这个方法- (BOOL)textFieldShouldReturn:(UITextField *)textField; //当keyBoard上return键被点击,委托代理调用这个方法Δ三.监听键盘的收起和弹出//拿到通知中心NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];//添加通知中心监听的通知- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;//UIKeyboardWillShowNotification; 键盘将要出现时发送通知//UIKeyboardDidShowNotification; 键盘已经出现时发送通知//UIKeyboardWillHideNotification; 键盘将要隐藏时发送通知//UIKeyboardDidHideNotification;键盘已经隐藏时发送通知//去除通知 //去除需要当前对象响应的通知 [[NSNotificationCenter defaultCenter] removeObserver:self];备注://取出键盘的信息NSDictionary * userInfo = notification.userInfo;// NSLog(@"%@", userInfo);NSTimeInterval duration = [userInfo[@"UIKeyboardAnimationDurationUserInfoKey"] floatValue];UIKeyboardAnimationDurationUserInfoKey 拿到键盘弹出时间【调试程序Bug】不知名的崩溃方法1:按照程序的执行顺序,打断点,找崩溃位置方法2:设置全局断点1)进入断点窗口2)单击Add Symbolic Breakpoint..., 输入-[NSException raise],然后按Done键。3)单击Add Symbolic Breakpoint..., 输入objc_exception_throw,然后按Done键。
UIViewController视图控制器
【MVC模式】
【注】iOS程序采用MVC设计模式为基础设计模式。即一个程序个构成,由模型,视图,控制器构成。模型(Model):非UI部分,数据的储存与管理;视图(View):UI部分,用于显示界面,与用户交互,包括接收触发事件,显示数据内容;控制器(Controller):本身不显示,用于管理视图,将视图部分,和模型部分链接起来。原则上视图不直接访问数据。
【注】使用MVC架构,视图不直接访问数据,可以便于修改,降低开发和维护成本。
【视图控制器】
一.生命周期
所谓这里的生命周期,指视图控制被加载后,首先调用的方法,其次调用的方法,到销毁时调用的方法。视图控制对象通过alloc和init来创建,但是视图控制对象不会在创建的那一刻就马上创建相应的视图,而是等到需要使用的时候才通过调用loadView来创建,这样的做法能提高内存的使用率。
![](http://upload-images.jianshu.io/upload_images/1447833-ea174aee1d823689.png)
二.模态视图控制器
切换是当前视图控制器,弹出形式是模态视图控制器 ,基本上系统封装具有特殊功能的视图都用的是模态化。
SecondViewController * svc = [[SecondViewController alloc] init];
void (^block)(void) = ^(void){NSLog(@"已经弹出了模态视图"); }; //弹出模态视图
[self presentViewController:svc animated:YES completion:block]; //当前显示的视图控制器,是被screen保留的,所以,如果MRC,弹出svc后,就可以在这里release svc。
[self dismissViewControllerAnimated:NO completion:nil];//关闭模态视图控制器,只有当前视图控制器确实是模态视图控制器,才能调用这个方法
三.容器视图控制器
【注】一般来讲视图控制器分为两种:普通视图控制器:管理一个页面的视图,和模型关联容器视图控制器:本身不显示,管理其他的视图控制器导航控制器标签栏控制器,称之为容器视图控制。
UINavigationController导航控制器
【注】导航控制器,是UIKit框架提供的一个容器视图控制器,用于切换拥有明确层次关系的视图。即由一级视图切换到二级视图,而不是平级视图间的切换。
【注】导航中视图控制器的层次结构,称为栈结构。(栈:先进的后出,后进的先出,叫做栈。 出栈:pop 入栈:push。队列:先进的先出,后进的后出,叫队列)
一.基本视图控制器切换
1、通过导航弹出
[self.navigationController pushViewController:svc animated:YES]; //返回上一级视图控制器
[self.navigationController popViewControllerAnimated:YES]; //返回跟视图控制器(这里指同一个导航的跟视图控制器)
[self.navigationController popToRootViewControllerAnimated:YES]; //返回栈中的根视图控制器 它的操作等同于:1.找到当前栈中的视图控制器 NSArray * array = self.navigationController.viewControllers; 2.取出需要的视图控制器 UIViewController * vc = array[0];3.pop到该视图控制器 [self.navigationController popToViewController:vc animated:YES];
self.navigationController.viewControllers 里面装了我们容器里面的所有视图,数组里面的顺序就是UINavigationController(容器)里面的顺序。
2、在AppDelegate代理中必须要写的
self.window=[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor=[UIColor clearColor];
[self.window makeKeyAndVisible];
FirstViewController *fvc=[[FirstViewController alloc]init];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:fvc]; self.window.rootViewController=nav;
注意:代理和block的反向传值。if(string.length>0)判断是否为空字符串;if(string)判断是否为空,扣号里值为真,因为还是是字符串
#define KWS(weakSelf) _weak _typeof(&*self)weakSelf=self //block 把强强引用转化成弱引用, 在代码中用block 反向传值可能会出现报警
【注】导航控制器发生作用,有三个类共同作用UINavigationController,本身并不显示无需定制;UINavigationBar,属于导航控制器(子对象),需要定制UINavigationItem,显示到导航条上,属于每个导航中的视图控制器,每个视图控制器有自己的BarItem,需要每个页面单独定制。
1.UINavigationBar (导航条,普通视图控件,父类为UIView)
每个导航控制器有且只有一个导航条,所有的视图控制器共用一个导航条。导航控制器中的导航条高度固定44。
(1).拿到导航条的方法:self.navigationController.navigationBar
(2).设置导航条的风格:self.navigationController.navigationBar.barStyleUIBarStyleDefault // 默认下面三中iOS7之后几乎一致 UIBarStyleBlack、UIBarStyleBlackOpaque、UIBarStyleBlackTranslucent 设置导航条的风格样式会波及到状态栏
(3).设置导航条的背景图片:- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics //UIBarMetricsDefault 对应iPhone竖屏(人像模式) ;UIBarMetricsLandscapePhone 对应iPhone横屏(风景模式)
(4).是否隐藏导航条:@property(nonatomic,getter=isNavigationBarHidden) BOOL navigationBarHidden;
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated
加动画的注意:图片严格遵守屏幕宽*44的尺寸,贴图不会波及到状态栏,而且状态栏会自动呈现出最初的样式
2.定制NavigationItem
NavigationItem是加载在UINavigationBar上的,每个页面单独定制自己的Item。
(1).设置导航条上显示的标题视图,会将视图自动居中显示,在外部设置x,y无效果self.navigationItem.titleViewself.navigationItem.title
(2)UIBarButtonItem
1、通过初始化标题的方法UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"左侧" style:UIBarButtonItemStylePlain target:self action:@selector(leftItemClicked:)];
UIBarButtonItemStylePlain (iOS7中将Item的圆角矩形和边框全部去掉了)
2、用系统提供的样式初始化得到UIBarButtonItem的对象UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(rightItemClicked:)];
3、开发中最常用的创建UIBarButtonItem的方法(这个一定要会)UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithCustomView:customBtn];
(3)显示在导航条的左侧和右侧self.navigationItem.leftBarButtonItem,设置左侧1个视图self.navigationItem.leftBarButtonItems 设置左侧1组视图,数组的元素必须是UIBarButtonItem的对象self.navigationItem.rightBarButtonItem 设置右侧1个视图self.navigationItem.rightBarButtonItems 设置右侧1组视图,数组的元素必须是UIBarButtonItem的对象注意:当我们用leftBarButtonItem覆盖掉系统原本的返回上级界面的按钮,这个时候,UINavigationController的测滑是不能用的。
3.定制ToolBar(工具条)//每个导航控制器,还配备了工具条(44坐标高),默认隐藏【注】toolBar属于NavigationController,一个导航控制器,只有一个
【注】toolBarItems属于每个视图控制器,每个视图控制器单独定制。
(1)拿到导航控制器中工具栏的方法self.navigationController.toolbarHidden=NOself.navigationController.toolbar
(2)设置工具栏的背景图片- (void)setBackgroundImage:(UIImage *)backgroundImage forToolbarPosition:(UIBarPosition)topOrBottom barMetrics:(UIBarMetrics)barMetrics
(3)self.toolbarItems 设置底部,数组中每个元素必需是UIBarButtonItem
注意:开发中,底部工具栏往往自己通过UIView+UIButton定制。
再注意:视图控制器的title属性能同时为navigationItem.title和tabBarItem.title赋值
二.视图控制器间传值(面试题)
【及时性】ΔΔ代理传值、Block传值、Δ通知传值(以后说)
【非及时性】全局变量传值 (只能是基础数据类型)、单例传值(传递对象数据)、文件传值(最慢)、存数据库。
例子:1、我们会把用户信息放到单例里面,当我们需要用户的信息的时候,直接从单例里面取。
三.NSUserDefaults的使用(沙盒保存基本数据的方法)
1、介绍:单例,每个应用程序有且只有一个NSUserDefaults对象,本质是应用程序特定路径下的一个plist文件
2、用途:用于实现数据持久化存储,存储数据量相对较小的数据(比如:用户名,密码。或者程序的一些设置信息等)
3、只能存储基本数据类型:(NSString,NSArray,NSDictionary,NSData,NSDate,bool,NSURL,NSNumber),NSArray,NSDictionary 中的元素也必须是基本数据类型(比如 :NSArray中是字符串,能够写入到UserDefaults,NSArray中是视图控制器对象,则此array不能写入)
4、用法 :
(1)NSUserDefaults *defaluts = [NSUserDefaults standardUserDefaults];//拿到单例
(2)- (void)setObject:(id)value forKey:(NSString *)defaultName;//向NSUserDefaults,写入数据(内存)
(3)- (void)removeObjectForKey:(NSString *)defaultName;//删除NSUserDefaults中的对应数据
(4)- (id)objectForKey:(NSString *)defaultName;//从UserDefaults中读取数据,如果从来没写入过数据,读到的为空
(5)[defaluts synchronize];//将数据同步给应用程序(执行真正写入plist的操作)
注意:第二个方法和第三个方法执行完之后,一定要执行第5个方法
UITabBarController 分栏控制器/标签栏控制器
【注】标签栏控制器,是UIKit框架提供的一个容器视图控制器,用于切换相同级别的兄弟视图控制器。iOS允许将导航控制器添加到标签栏控制器中进行管理(事实上这种结构非常常见),但原则上,不推荐将分栏控制器添加到导航控制器中进行管理,导航栏控制器放在标签栏控制器里面
一、UITabBarItem简介:UITabBarItem(标签栏项),视图控制器通过tabBarItem属性来定制标签栏项的显示。
1、呈现在标签栏(UITabBar)上方法:
(1).xxx.tabBarItem.image 设置标签栏项的图片;
(2).xxx.tabBarItem.selectedImage 设置标签栏项的选中图片;
(3).xxx.tabBarItem.title 设置标签栏项的title5)xxx.tabBarItem.badgeValue 设置标签栏项的徽标,用于提示用户
(4).xxx.tabBarItem.titlePositionAdjustment设置标题偏移量 正为下为右 负是上是左创建
2、UITabBarItem的方法
(1).[[UITabBarItem alloc] initWithTitle:title image:image1 tag:100];
(2).[[UITabBarItem alloc]initWithTitle:title image:image selectedImage:selectImage];根据title、image、selectedImage创建UITabBarItem
(3).[[UITabBarItem alloc] initWithTabBarSystemItem:xxx tag:0] 根据系统样式去创建UITabBarItem
二、UITabBarController的方法
(1).UITabBarController *tabController = [[UITabBarController alloc] init] 创建一个标签栏控制器
(2).tabController.viewControllers = controllers;
1、viewControllers 数组,数组中的元素必须是视图控制器的对象
2、视图控制器对象的显示顺序(左到右)与在数组中的顺序一致
3、各个视图控制器是并列的关系,彼此互相独立,点击不同tabBarItem,切换不同的视图控制器的视图
4、当viewControllers中视图控制器的对象多于5个的时候,会自动创建一个标题为more的标签栏项,对应的为moreNavigationController的导航控制器的对象,第5个以及5以后的视图控制器会通过列表的形式呈现在moreNavigationController中
5、tabController.moreNavigationController 获取到我们的moreNavigationController
6、tabController.selectedIndex通过下标的方式指定被选中的视图控制器
7、tabController.selectedViewController通过指定被选中的视图控制器的方式
三、协议方法 UITabBarControllerDelegate
1、- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewControllertabBar将要切换到某个子视图控制器,返回YES允许,返回NO不许,第二个参数是被选的视图控制器
2、- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewControllertabBar已经切换到某个子视图控制器,第二个参数是被选的视图控制器
3、- (void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray *)viewControllers当more中,将要编辑视图控制器顺序
4、- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed当more中,将要结束编辑视图控制器顺序
5、- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed当more中,已经结束编辑视图控制器顺序重要
四.自制TabViewController
自制TabViewController第一步NSMutableArray *controllers=[[NSMutableArray alloc]init];//通过数组的形式来创建视图,并且 运用Class class=NSClassFromString([NSString stringWithFormat:@“xxxx”,xxx]);来找数组中的对象,然后初始化视图控件UIViewController *vc=[[class alloc]init];然后把数组中的视图对象赋值给vc,然后把vc添加到开始自己初始化的可变数组中去NSMutableArray *controllers=[[NSMutableArray alloc]init]; NSArray *nameArray=@[@"界面一",@"界面二",@"界面三",@"界面四",@"界面五”];如果视图控件不需要标题,这个数组可以不需要,把相关的去掉就可以了 。 for (NSInteger i=0; i=0) { UIButton *btn=(UIButton *)[self.view viewWithTag:100+index]; [self btnClick:btn]; }else{ //我们认为这个数据不合理,就把值改为0,改成默认的第一个 [defaults setObject:@"0" forKey:@"index"]; [defaults synchronize]; }这个是存,一般是在button的点击方法中NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults]; [defaults setObject:[NSString stringWithFormat:@"%ld",btn.tag-100] forKey:@"index"]; [defaults synchronize];
补充:1、 button.titleEdgeInsets = UIEdgeInsetsMake(30, -25, 0, 0);设置button文字偏移,让开图片,四个值是相对于之前文字的上左下右的距离2、button.imageEdgeInsets = UIEdgeInsetsMake(5, 12, 15, 12);设置图片偏移,让开文字3、button.adjustsImageWhenHighlighted = NO;设置点击不闪烁4、viewWithTag这个方法是深度遍历,也就是说,不仅能找到self.view的子视图,也能找到子视图的子视图 。什么是单例?对于app来说有很多界面,这些功能来说都是同一个人来做的,需要获取用户信息是一个人打开的,主要用来传值点赞是代理写的,视图之间的传值。
其他控件与手势
【其他控件】
1、UISlider 滑块控件介绍:继承自UIControl,为事件驱动型控件,高度固定23,frame设置高度无效果方法:
1)@property(nonatomic) CGRect frame;设置滑块的尺寸
2)@property(nonatomic) float maximumValue设置滑块的最大值,默认值(0.0 1.0)
3)@property(nonatomic) float minimumValue设置滑块的最小值
4)@property(nonatomic) float value设置滑块最初显示的数值,滑动滑块,伴随的value值的改变
5)@property(nonatomic,getter=isContinuous) BOOL continuous控制滑块的值是否时时变化,默认为YES
6)- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents给滑块添加方法
7)UIControlEventValueChanged 当控件的值发生变化时所对应的事件
2、UISegmentedControl 分段选取器介绍:事件驱动型控件,分段选取器会根据文字内容给一个合适的size
1)- (id)initWithItems:(NSArray *)items;初始化传递进去的NSArray里面放置字符串或图片
2)@property(nonatomic) CGRect frame;不要忘记设置frame
3)@property(nonatomic) NSInteger selectedSegmentIndex;设置哪个分段处于选中状态,不设置此属性,任何分段都处于非选中状态
4)- (void)insertSegmentWithTitle:(NSString *)title atIndex:(NSUInteger)segment animated:(BOOL)animated向分段选取器指定的位置插入标题
5)- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents给分段选取器添加方法
6)- (NSString *)titleForSegmentAtIndex:(NSUInteger)segment根据分段的下标,拿到分段的标题
3、UIStepper 步进器介绍:固定的size (94*27), 事件驱动型控件
1)@property(nonatomic) double maximumValue设置最大值
2)@property(nonatomic) double minimumValue设置最小值
3)@property(nonatomic) double stepValue设置步长 (默认值为1 必须>0)(+一次增加的值/-一次减少的值)
4)@property(nonatomic,getter=isContinuous) BOOL continuous设置长按是否连续响应事件
5)- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents给步进器添加方法
4、UIProgressView 进度条介绍:进度条,普通视图控件,高度固定9
1)@property(nonatomic) float progress进度条的进度属性(默认为0,0.0-1.0),值大于1,进度条一直处于满格状态
5、UISwitch 开关介绍:开关控件,事件驱动型控件,固定size(79*27),frame更改size无效
1)、@property(nonatomic,getter=isOn) BOOL on控制开关的开闭(YES 开)
2)、- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents添加事件
6、UIActivityIndicatorView 加载等待提示控件介绍:加载等待提示控件,控件的size固定
1)、- (id)initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyle)style初始化的时候,设定风格样式
2)、@property(nonatomic) CGPoint center一般设置中心点为view的中心点
3)、- (void)startAnimating;让提示控件转动4)- (void)stopAnimating;让提示控件停止转动
7、UIAlertView 介绍:(视图控件-警告框)
1)- (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString*)cancelButtonTitle otherButtonTitles:(NSString*)otherButtonTitles, ...初始化举例:UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@“xxx” message:@"xxx" delegate:self cancelButtonTitle:@"0" otherButtonTitles:@"1",@"2",nil];
2)- (void)show;显示警告框,同时将alert托管给应用程序
3)- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 当点击警告框上的按钮时,触发此方法,buttonIndex 按钮在警告框上的位置
8、UIActionSheet 介绍:动作表单
1)- (instancetype)initWithTitle:(NSString*)title delegate:(id)delegate cancelButtonTitle:(NSString*)cancelButtonTitle destructiveButtonTitle:(NSString*)destructiveButtonTitle otherButtonTitles:(NSString*)otherButtonTitles, ...初始化举例:UIActionSheet *atSheet=[[UIActionSheet alloc] initWithTitle:@“xxxx” delegate:self cancelButtonTitle:@"x" destructiveButtonTitle:nil otherButtonTitles:@"0",@"1",@"...",@"x-1",nil];
2)- (void)showInView:(UIView *)view;;在view上显示动作表单
3)- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 当点击动作表单上的按钮时,触发此方法,buttonIndex 按钮在动作表单上的位置上面两种方法放在一起用 如下-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
【手势】
一.触摸类UITouch通过触摸类,我们可以实现各式的自定义手势
二.手势类 UIGestureRecognizer介绍:UIGestureRecognizer 所有手势的父类
1)@property(nonatomic,readonly) UIView *view;获取到被添加手势的视图
2)- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;设置某某手势在otherGestureRecognizer手势之后响应 双击优先响应 也是other
3)@property(nonatomic,assign)iddelegate;设置代理UIView的一个常用方法-(void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer用这个方法给UIView及子类添加手势
1、UITapGestureRecognizer 点击手势
1)- (id)initWithTarget:(id)target action:(SEL)action当满足这个手势之后,让谁去调用这个方法
2)@property(nonatomic)NSUInteger numberOfTapsRequired;设置点击次数
3)@property(nonatomic)NSUInteger numberOfTouchesRequired;设置需要多少个手指点击
2、UILongPressGestureRecognizer 长按手势
1)- (id)initWithTarget:(id)target action:(SEL)action当满足这个手势之后,让谁去调用这个方法
2)@property (nonatomic)NSUInteger numberOfTouchesRequired设置几根手指生效
3)@property (nonatomic) CFTimeInterval minimumPressDuration;设置最小长按时间
3、UIPanGestureRecognizer 移动手势
1)- (id)initWithTarget:(id)target action:(SEL)action当满足这个手势之后,让谁去调用这个方法
2)@property (nonatomic)NSUInteger minimumNumberOfTouches;设置最小手指数
3)@property (nonatomic)NSUInteger maximumNumberOfTouches;设置最大手指数
4)- (CGPoint)translationInView:(UIView *)view;相对于View,拖动时偏移的坐标
4、UISwipeGestureRecognizer 清扫手势
1)- (id)initWithTarget:(id)target action:(SEL)action当满足这个手势之后,让谁去调用这个方法
2)@property(nonatomic) UISwipeGestureRecognizerDirection direction设置这个滑动手势要监听哪个方向,即监听滑向哪边,一个手势,只监听一种方向
3)@property(nonatomic)NSUInteger numberOfTouchesRequired;设置需要几根手指滑动
5、UIPinchGestureRecognizer 缩放手势
1)- (id)initWithTarget:(id)target action:(SEL)action当满足这个手势之后,让谁去调用这个方法
2)@property (nonatomic)CGFloat scale;缩放比例
6、UIRotationGestureRecognizer 旋转手势
1)- (id)initWithTarget:(id)target action:(SEL)action当满足这个手势之后,让谁去调用这个方法
2)@property (nonatomic)CGFloat rotation;旋转的角度
三.手势的四种常用状态state
刚开始生效UIGestureRecognizerStateBegan,
每次移动UIGestureRecognizerStateChanged,
手势结束UIGestureRecognizerStateEnded,
手势被取消UIGestureRecognizerStateCancelled,
四、手势的代理方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer//返回值表示能否两个手势混搭补充:从给定的大图中切出指定矩形区域的小图CGImageRef imageRef = CGImageCreateWithImageInRect(image1.CGImage, rect);UIImage *image = [UIImage imageWithCGImage:imageRef];
UIScrollView/滚动视图
【注】滚动视图(UIScrollView)和表格视图(UITableView)是UI知识体系中,最重要的两个控件。滚动视图本身不显示,或者只显示一个背景,主要负责子视图的滚动和翻页。是一个没有文字的TextView。多用于图片的显示,或者布局的更改(如,弹出键盘时,可以使用滚动视图,来操作布局向上滚动)
【注】UIScrollView常用有四个子类,UITextView,UITableView,UICollectionView,UIWebView
前言:
1)导航控制器结合UIScrollView使用,需要将此属性设置为NO,来消除对UIScrollView的影响self.automaticallyAdjustsScrollViewInsets = NO;
2)添加到scrollView上的视图可以叫内容视图[scrollView addSubview:imageView];
一.基本属性方法
1)@property(nonatomic)CGSize contentSize; 设置内容视图的滚动区域,contentSize一般设置成内容视图的大小,或者是多个内容视图的size和 contentSize 比scrollView本身的size大时,scrollView才有滚动效果
2)@property(nonatomic) BOOL showsHorizontalScrollIndicator 横向滚动条是否显示,默认是YES
3)@property(nonatomic) BOOL showsVerticalScrollIndicator 纵向滚动条是否显示,默认是YES
4)@property(nonatomic)BOOL bounces 是否有边界回弹效果
5)@property(nonatomic)CGPoint contentOffset 内容视图左上角的点为坐标原点,scrollView的起始点与内容视图左上角的点(内容视图的起始点)的偏移量
6)@property(nonatomic,getter=isPagingEnabled) BOOL pagingEnabled 设置scrollView的分页属性,会将内容视图进行分页计算,每页大小与scrollView的size一致
7)@property(nonatomic) CGFloat maximumZoomScale 设置内容视图的最大缩放系数
8)@property(nonatomic) CGFloat minimumZoomScale 设置内容视图的最小缩放系数
注意:7)和8)两条属性需要和- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{}结合使用。
二.协议方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{// NSLog(@"已经滑动的时候调用这个方法!contofset一直在变:(%f:%f)",scrollView.contentOffset.x,scrollView.contentOffset.y);}//在滚动的时候调用这个方法,而且是时时调用
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ NSLog(@"刚开始拖拽的时候调用这个方法!");}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ NSLog(@"结束拖拽的时候调用");}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{ NSLog(@"将要结束拖拽的时候调用这个方法,第一个参数是scrollView,第二个参数是加速度,第三个参数是预定停留点");}
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{ NSLog(@"将要开始减速的时候,调用这个方法");}//一定得有减速的过程,将要减速的时候,调用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ NSLog(@"结束减速过程之后,调用的方法");}//已经结束滑动的时候调用
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{ NSLog(@"已经结束滑动的时候调用");}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{ return [scrollView.subviews objectAtIndex:0];}//这个方法很重要,而且当我们设置属性pagingEnabled=YES,就一定会调用这个方法
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view{ NSLog(@"将要缩放的时候,调用的方法");}//返回缩放的视图
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{ NSLog(@"结束缩放的时候,调用的方法。第一参数是ScrollView,第二个参数是被缩放的视图,第三个参数是缩放的比例");}
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView{ NSLog(@"我要上去了"); return YES;}//点击状态栏的时候调用,当返回YES的时候,就是让scrollView回到顶部,当返回NO的时候,就不能回到顶部
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView{ NSLog(@"我上来了!");}//已经到顶部的时候,调用这个方法
三.UIPageControl和广告栏(照片墙)
1)@property(nonatomic) NSInteger numberOfPages;设置总页数
2)@property(nonatomic) NSInteger currentPage;设置当前页,页数从0开始
3)@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;userInteractionEnabled 视图的用户交互属性,设置为NO后,视图无法响应用户的交互行为
4)@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor设置当前点的颜色
5)@property(nonatomic,retain) UIColor *pageIndicatorTintColor设置其它点的颜色
UITableView/表格视图
【知识点】【TableView使用】【TableView定制】【Cell定制】
1.UITableView的结构
【注】UITableView派生自UIScrollView
【注】UITableView的结构如下背景是滚动视图每个横向的表格称为Cell(UITableViewCell)<注>每个cell既可以存储数据,也可以接受选中的事件,我们可以选中某个cell时,下拉列表,也可以选中某个cell时,推出新的页面。在编辑模式下还可以选中多个cell,批量删除等。
<注>通过自定义cell,更可以在cell上添加任何需要的视图。多个cell可以进行分组管理
【注】UITableView的cell复用UITableView只会添加所需的一定数量的cell,仅仅比同屏显示的cell多一点,当tableView滚动时,重复使用这些cell,刷新内容。
【注】UITableView具有编辑状态和普通状态两种模式。很多属性方法都只在某一种模式下生效
2.UITableView的基本属性和常用方法基本属性:
1)@property (nonatomic) UITableViewCellSeparatorStyle separatorStyle设置分割线的样式
2)@property (nonatomic, retain) UIColor *separatorColor设置分割线的颜色
3)@property (nonatomic, retain) UIView *tableHeaderView整个tableView的头部
4)@property (nonatomic, retain) UIView *tableFooterView
整个tableView的底部常用方法:
1)- (void)reloadData; 刷新tabView的数据
2)- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation刷新tabView某个section的数据,第二个参数是动画类型
3)- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation删除行 第一个参数是数组,数组里面每个元素是要删除的cell的位置,第二个参数是删除时候的动画
4)- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;删除组 第一个参数是NSIndexSet包装后,组的位置,第二个参数是删除时的动画[NSIndexSet indexSetWithIndex:indexPath.section]
5)- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; 插入行 第一个元素是一个数组,数组里面每个元素都是要插入行的位置;第二个元素是动画效果
6)- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation 插入组
7)- (void)setEditing:(BOOL)editing animated:(BOOL)animated 设置tabView是否处于编辑状态
3.UITableViewCell的基本属性
1)@property (nonatomic, retain)UIView *selectedBackgroundView设置cell选取后的背景视图
2)@property (nonatomic) UITableViewCellSelectionStyle selectionStyle设置cell被选取后的样式3)@property (nonatomic) UITableViewCellAccessoryType accessoryType设置右边图标的样式UITableViewCellAccessoryDisclosureIndicator 是箭头
4.UITableView的协议
(1)设置Cell
1)- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 设置每组里面有多少行,大部分的情况都是只有一组
2)-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath设置cell的高度 默认高度44
3)- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath返回cell
(2)section
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 设置有多少组,默认是1
(3)header
1、 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section设置section头部的标题
2、-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 设置头部section的高度
3、-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 当我们头部的样式不满足我们要求的时候,我们需要自己去定义个View
(4)Footer
1、- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section设置section底部的标题
2、-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section 设置section底部的高度
3、-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section 当我们底部的样式不满足我们要求的时候,我们需要自己去定义个View
(5)选择
1)- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 选中tableView中的某一行时,触发此方法
2)- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated 通过tableView设置某一行,自动反选,反选的代理方法不再被调用
3)- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath 某一行被反选时,触发此方法
5.UITableView的cell编辑与移动(1)下面是关于编辑的方法(4个) 仅在编辑模式生效
1)- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 返回某一行,return YES允许被编辑, return NO 不能被编辑
2)- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath 返回某一行的编辑状态 UITableViewCellEditingStyleInsert 插入 UITableViewCellEditingStyleDelete 删除
3)- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath 返回删除时右侧按钮的文字
4)- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 真正开始编辑,如果是insert,点击+就调用,如果delete,必须点击右侧字体才调用
(2)关于移动cell的方法 仅在编辑模式下生效
1)- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath 返回某一行可不可以移动
2)- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath 当移动cell时调用,只有实现了这个方法,才能移动cell
6.UITableViewController
7.设置tabView的索引
1)- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView 返回值为一组索引标题(一组字符串)
2)- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index title 被选中的索引标题 index 索引标题在索引中的位置(在索引标题数组中的下标) 返回值为要指向的分区下标
8、UISearchDisplayController和UISearchBar
1) UISearchBar 正常创建,然后赋值给tableHeaderView
2) UISearchDisplayController
1、- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController创建搜索控制器,传入一个搜索条,点击搜索条,可以触发搜索vc的搜索模式,搜索模式作用在self上
2、@property(nonatomic,assign)idsearchResultsDataSource
3、@property(nonatomic,assign)idsearchResultsDelegate
9.cell的定制
1)-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 重写这个方法,第一参数是样式,第二个参数是标识
2)- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier;这个方法是用来提前注册cell,可以让在编译器创建cell之前知道创建哪种类型的cell,效率高 第一个参数:cell的class 第二个参数是标识
3)- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath这个方法根据cell的标识和cell的位置取出cell,一定是和提前注册一起使用,当队列中没有的cell的时候,会自动帮你创建cell注意:提前注册手写cell,一定是上面三个方法都用到
4)UINib *nib=[UINib nibWithNibName:@"BookCell" bundle:nil]根据cell的名字创建UINib
5)[_tableView registerNib:nib forCellReuseIdentifier:@"BookCell"]; 提前注册xib写的cell注意:提前注册定制的cell,这两个方法和第3个方法一起用
10.通过XIB进行Cell定制【三大注意事项】
1.必须确保Xib文件关联类是自定义的cell类
2.必须确保Xib文件中只有一个cell
3.必须手动拷贝Cell的唯一ID,否则不能复用
补充:[[UIDevice currentDevice].systemVersion floatValue]获取系统版本号
UICollectionView/表格视图
1.介绍 集合视图,iOS6之后出现的视图控件,与UITableView类似,最大的特点是可以对cell实现灵活的布局 UICollectionView 使用的cell为UICollectionViewCell
注意:self.automaticallyAdjustsScrollViewInsets = NO;
2.UICollectionViewFlowLayout
介绍:UICollectionViewFlowLayout 系统提供的,能够实现cell的网格布局UICollectionViewFlowLayout的父类是UICollectionViewLayout,UICollectionViewLayout 集合视图的布局类,是一个抽象基类
1)@property (nonatomic) UICollectionViewScrollDirection scrollDirection设置collectionView的方向UICollectionViewScrollDirectionVertical 竖直 UICollectionViewScrollDirectionHorizontal 水平
2)@property (nonatomic) CGFloat minimumLineSpacing;设置横向的最小间隔
3)@property (nonatomic) CGFloat minimumInteritemSpacing;设置纵向的最小间隔
注意:如果CollectionView垂直滚动,横向的最小间隔能直接生效;纵向的最小间隔由实际间隔需要根据item的size 和edgesInsets的值来调节
3.UICollectionView 基本方法和属性
1)- (id)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout利用布局对象,实现集合视图的初始化
2)@property (nonatomic, assign) iddelegate设置代理 UICollectionViewDelegateFlowLayout
3)@property (nonatomic, assign) iddataSource;设置代理 UICollectionViewDataSource4.UICollectionView 代理方法cell的方法
4)- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath指定每一个item的大小
5)- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section一个section 有多少个Item(cell)
6)- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath返回Cell
(1)Cell的注册方法
- (void)registerNib:(UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier
- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier
(2)Cell取出的方式
- (id)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath通过重用标识符和indexPath到UICollectionView的重用队列中获取cell对象,因为已经提前注册了cell,如果获取不到cell对象,UICollectionView会根据注册的cell样式,自动创建cell对象
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPathcell被选中的时候调用的方法section的方法
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView设置组的个数
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section 设置顶部view的高度。如果垂直滚动,view的width与集合视图一致,需要设置高度
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section设置底部view的高度
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath通过此方法为section的headerView和footerView赋值
(1)注册方法
- (void)registerClass:(Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier; 注册的种类UICollectionElementKindSectionHeader 设置sectionHeaderViewUICollectionElementKindSectionFooter 设置SectionFooterView
(2)取出的方式
- (id)dequeueReusableSupplementaryViewOfKind:(NSString*)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath通过此方法为section的headerView和footerView赋值 用下面方法判断是header还是footer[kind isEqualToString:UICollectionElementKindSectionHeader]cell整体边距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section描述的是所有cell相对于另一个视图上、左、下、右的距离
补充:[[UIDevice currentDevice].systemVersion floatValue]获取系统版本号
GET请求和数据下载、JSON解析
【知识点】
一. 数据的网络请求
【注】大多数APP都是依托于服务器的,由服务器负责数据的管理交互,分发,筛选等等。APP做的事情就是发送请求,接收数据。当然有些请求也可以伴随数据的上传。
请求(Request):APP客户端发送给服务器的数据,根据服务器协议,通知服务器,要求服务器做出数据的筛选,管理或分发。
响应(Respond):服务器接收到APP的请求,会回馈响应。响应包括TCP稳定链接的建立,以及数据的传输。
【注】网络数据传输的常用协议,有TCP和UDP。(了解)
TCP:首先建立稳定的传输链接,保证传输数据,正确稳定,序列正常,适合传输文件
UDP:不建立链接,发送方发送数据后,对数据不再负责,快速,但是容易造成丢包,序列紊乱和后发先至,适合即时通讯,或者广播消息。举例:淘宝, QQ, 微信,传视频等
【注】数据的请求协议:手机应用开发的绝大多数数据请求协议都是使用http(超文本传输协议)。
主要使用的请求:<1>Post请求:请求数据不裸露,适合向服务器上传文件等大数据。
<2>get请求:最常用的app数据请求模式,通过裸露的传参方式,将我们请求的数据发送给服务端,服务端解析http协议,根据参数管理,筛选,分发数据,并作出相应响应。用于下载数据。
【注】数据格式JSon(很多,很简单)和Xml(很少,很困难)在移动APP当中,服务器发送过来的数据,都是字符串,有两种格式JSon和Xml.将JSon格式的数据提取出来,保存到数据模型中的过程,称为JSon解析.将Xml格式的数据提取出来,保存到数据模型中的过程,称为Xml解析
【注】一般客户端流程,发送请求 -> 等待响应 -> 建立链接 ->下载数据 -> 解析数据 -> 存入数据模型 -> mvc 显示到UI
二.网络数据的下载AFNetworking初步介绍:AFNetWorking2.0是目前最受开发欢迎的第三方网络框架,里面不但封装了最基本的NSURLConnection 而且还封装了iOS7之后的NSURLSession向下兼容到iOS6,arc+block 不用添加任何其他库依赖,json的数据,能自动解析(NSJSONSerialization)
1)AFHTTPRequestOperationManager *manager=[AFHTTPRequestOperationManager manager];拿到数据请求的管理类
2)manager.responseSerializer.acceptableContentTypes=[NSSet setWithObject:@"application/json”];告诉manager,需要解析的数据类型(服务端下发给客户端的数据是什么类型的)
application/json是json数据 text/xml是xml数据
3)manager.responseSerializer=[AFHTTPResponseSerializer serializer]; 将一个新的解析对象 AFHTTPResponseSerializer 赋值过去,数据不会再被自动解析
1、对json数据的Get请求
- (AFHTTPRequestOperation *)GET:(NSString *)URLString parameters:(id)parameters success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
三. JSON解析[核心和重点]
<1>Json数据的格式{}中表示一个字典[]中表示一个数组key: value 表示一个键值对"string" 表示一个字符串, 表示并列数据
<2> 如何解析
四. SDWebImage异步下载图片知识
补充kvc:
key-value-coding 键值编码,kvc 是oc动态语法结构一种使用形式,主要是用来进行赋值取值操作,所有NSObject类型的对象都支持KVC,点语法是特殊的一种kvc。把value赋值给一个叫name的属性 ,程序内部:查找是否有setName方法,有直接赋值,没有就继续查找_name,有就赋值,没有就查找属性名为name的属性。KVC最常用的方法,可以根据字典中的key对model里面的值赋值。(习惯用法:当使用时保持key和属性的名字一致)例如:
[_stuModel setValuesForKeysWithDictionary:dic];
NSDictionary *dic=@{@"name":@"佐罗",@"sex":@"男",@"friends":@[@"xx.xx",@"xxx.xxx"],@"height":@"186"}; //当没有找到set方法,_属性,属性的时候,它会在model里面找setValue:forUndefinedKey: 如果我们没有重写,程序就会崩溃在model的.m文件中重写-(void)setValue:(id)value forUndefinedKey:(NSString *)key{ //可以不写打印,写了可以提示自己 NSLog(@"UndefinedKey:%@",key);}程序就不会崩溃了
补充 kvo:
key-value-observer 键值观察,用来观察使用kvc的对象的属性,常用来观察属性值的变化
第一参数:设置观察者
第二个参数:观察哪个属性
第三个参数:观察的属性的哪种变化
第四个参数写nil
1、通知中心 每个应用程序有且只有一个通知中心的对象(单例),可以理解为广播站。任何对象都可以通过通知中心发送广播,任何对象都可以通过通知中心注册成为某条广播的观察者(具有接收/收听某条广播能力的对象)
1)添加观察者[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(xxx) name:@“message” object:nil];在通知中心注册self为@“message”广播的观察者,一旦有其他对象发送这条广播,self就能接收到并触发@selector(xxx)方法
2)移除观察者[[NSNotificationCenter defaultCenter] removeObserver:self name:@“message” object:nil];在通知中心移除self对@“message”的观察
3)发送通知[[NSNotificationCenter defaultCenter] postNotificationName:@“message” object:nil userInfo:dic];对象通过通知中心发送消息,dic的消息会被传到观察者中
2、视频 MPMoviePlayerViewController介绍:
MPMoviePlayerViewController是视频播放器的控制器(能够播放mp4、avi、mov格式的视频,支持本地和远程视频的播放)
1)#import此framework中带有视频播放器
2) 创建的方法_playController=[[MPMoviePlayerViewController alloc]initWithContentURL:url];
3) 设置资源类型_playController.moviePlayer.movieSourceType视频资源分为普通的文件资源,还有流媒体格式(.m3u8)的视频资源,moviePlayer属性为视频播放器,指定播放的资源的类型
4) 要用模态化的方式呈现
5)[_playController.moviePlayer play];
注意:在用的时候,通过点击done按钮后,销毁_playController步骤:
1)[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playBack) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];在通知中心注册self为MPMoviePlayerPlaybackDidFinishNotification广播的观察者,一旦有其他对象发送这条广播,self就能接收到并触发playBack方法点击done按钮->视频播放器会自动通过通知中心发送MPMoviePlayerPlaybackDidFinishNotification这条广播
2)实现playBack方法[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];在通知中心移除self对MPMoviePlayerPlaybackDidFinishNotification广播的观察(不要忘记) //停掉播放器 [_playController.moviePlayer stop]; //销毁playController _playController = nil;
3、音频 AVAudioPlayer介绍:
AVAudioPlayer是音频播放器
1)#import带有音频播放器的framework
2) _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];本地的资源路径生成url用fileURLWithPath
3)_audioPlayer.delegate设置代理
4)[_audioPlayer prepareToPlay];对音频资源进行预加载
5)[_audioPlayer play];播放音频
6)[_audioPlayer stop];停止播放音频
代理方法
1)- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;当成功播放完成一首歌后,调用此方法
4、相机和相册 UIImagePickerController介绍:UIImagePickerController用来获取拍照和相册库资源
1)UIImagePickerController *picker = [[UIImagePickerController alloc] init];创建
2)@property(nonatomic) UIImagePickerControllerSourceType sourceType;通过UIImagePickerController 来获取拍照和相册库资源UIImagePickerControllerSourceTypePhotoLibrary,相册UIImagePickerControllerSourceTypeCamera, 相机UIImagePickerControllerSourceTypeSavedPhotosAlbum 图册
3)@property(nonatomic,assign) iddelegate
4)@property(nonatomic)BOOL allowsEditing 是否允许对图片、视频资源进行后续处理
5)通过模态化的方式呈现到程序中代理方法
1)+ (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType;用来判断是否可以调用相机或者相册,sourceType是下面的UIImagePickerControllerSourceType
2)- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;点击picker上的cancel按钮时,触发的方法,里面picker需要dismiss
3)- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info点击choose按钮触发的方法,info 带有选中资源的信息
1、NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];判断选中的资源的类型[mediaType isEqualToString:(NSString *)kUTTypeImage]注意需要#import//此framework中带有系统预置的多媒体常量参数
2、UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];通过字典获取选中的图片APP之间的跳转所用的函数在第一界面鞋写在需要跳转的或者btn点击下 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:encodeString]];并且在targets中info 找到 URLtypes 做一个标记 跳转传值的话需要用到函数app一个代理方法- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{ ((ViewController*)self.window.rootViewController).label.text=string;}有时搜索框不能搜索中文 我们需要把中文转化成 万国码方法如下将字符串的中文转码NSString * string=@"yxl://你好"; NSString * encodeString=[string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; //将转码后的字符串转回来 NSString * string=[url.absoluteString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
地图一、iOS系统自带定位,用CLLocationManager就可以轻松的实现定位的操作,获得的是一组经纬度。
1、导入CoreLocation.framework框架
2、定义属性 CLLocationManager *_locationManager
3、@property(assign, nonatomic) iddelegate;
4、@property(assign, nonatomic) CLLocationDistance distanceFilter;
设置过滤器的距离
5、@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;
设置精确度,位置服务大量消耗电池电量,下面罗列优先级别从上而下:
6、ios8.0之后请求授权,需要在plist文件中添加字段
NSLocationWhenInUseUsageDescription 值为YES请求定位的用户授权
requestWhenInUseAuthorization 只有应用在使用的时候允许授权
requestAlwaysAuthorization 在任何时候都需要授权,如果要在后台定位,需要有一个明确的提示,告诉用户,你的应用会在后台定位,电池会加快消耗
[_locationManager requestWhenInUseAuthorization];
7、- (void)startUpdatingLocation;
开启位置服务
8、-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
当位置发生变化时调用这个方法
9 、-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
当定位失败的时候调用这个方法
CLLocation的属性CLLocationCoordinate2D中包含了经度longitude 纬度latitude
二、根据上面得到的经纬度可以获取相应的身份、城市、街道等信息。
1、CLGeocoder *geocoder=[[CLGeocoder alloc]init];
CLGeocoder类中有几个方法,一个是把经纬度转化成大家能看懂的信息,比如:city,county,街道等等
2、- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;
根据经纬度反向地理编译出地址信息
CLPlacemark有很多属性,thoroughfare获取街道,locality获取城市,administrativeArea,获取省(直辖市).......
测试地址:经度:121.487237,纬度:31.380998
多线程
1、进程和线程
1)、什么是进程
进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。
2)、什么是线程
1个进程要想执行任务,必需得有线程(每1个进程至少要有1条线程);线程是进程的基本单元,一个进程(程序)的所有任务都在线程中执行。
比如使用酷狗播放音乐、使用迅雷下载电影,都需要在线程中执行
3)、线程的串行
1个线程中任务的执行是串行的。如果要在这个线程中执行多个任务,那么智能一个一个地按顺序执行这些任务,也就是说,在同一时间内,一个线程只能执行一个任务
2、多线程
1)、什么是多线程
1个进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务
2)、多线程的原理
同一时间,CPU只能处理1条线程,只有1条线程在工作(执行)。多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换)。CPU调度线程的速度足够快,就造成了多线程并发执行的假像。
3、多线程的优缺点
优点:1、能适当提高程序的执行效率
2、能适当提高资源利用率(CPU、内存利用率)
缺点:1、开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能。
2、线程越多,CPU在调度线程上的开销就越大(如果有N条多线程,cpu会在N多线程之间调度,CPU会累死,消耗大量的CPU资源,每条线程被调度执行的频次会降低,线程的执行效率就下降了)
3、程序设计更加复杂:比如线程之间的通信,多线程的数据共享
4、多线程在iOS开发中的应用
主线程:一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”
主线程的主要作用:显示\刷新UI界面、处理UI事件
主线程的使用注意:别将比较耗时的操作放在主线程中。耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验(见代码事例:BlockingMainThread)
5、线程的实现
iOS中实现线程的可行方式有:
pthread 底层的C线程库(不考虑)
NSThread Objective-C的线程类
NSOperationQueue 线程池/线程队列
GCD 使用Block语法的线程池/线程队列
6、NSThread Objective-C的线程类
1)、创建线程,并自动执行
[NSThread detachNewThreadSelector:@selector(doSomeThing) toTarget:self withObject:nil];
2)、创建线程,不自动执行
[[NSThread alloc] initWithTarget:self selector:@selector(doSomeThing) object:nil];
3)、设置线程名
thread.name = @"另一个线程";
4)、执行线程
[thread start];
5)、函数内获取当前线程
[NSThread currentThread];
6)、获取主线程
[NSThread mainThread];
7)、线程休眠
[NSThread sleepForTimeInterval:1.0f]; // 休眠几秒
[NSThread sleepUntilDate:date]; // 休眠到指定时间
8)、线程退出
[NSThread exit];
9)、线程通信
[self performSelector:@selector(function) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
7、NSOperationQueue 线程池/线程队列(内部实现是GCD)
1)、NSInvocationOperation
1、创建操作对象,封装要执行的任务
NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
2、执行操作
[operation start];
2)、NSBlockOperation子类
1、创建NSBlockOperation操作对象
NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
}];
2、添加操作
[operation addExecutionBlock:^{
}];
3、开启执行操作
[operation start];
3)、NSOperationQueue
添加操作到NSOperationQueue中,自动执行操作,自动开启线程 1、创建NSOperationQueue
[[NSOperationQueue alloc] init];
2、设置最大并发数
queue.maxConcurrentOperationCount = 1;
3、添加任务到队列里
[queue addOperation:blockOperation];
4、让队列里面,所有的Operation都取消
[queue cancelAllOperations];
5、获取当前线程对列
[NSOperationQueue currentQueue]
6、获取主线程对列
[NSOperationQueue mainQueue]
7、添加任务间的依赖关系,前者依赖于后者的完成,也就是后者执行完,前者才能执行,依赖关系需要放在添加到队列之前设置
[invocation addDependency:blockOperation];
8、GCD 使用Block语法的线程池/线程队列
介绍:全称是Grand Central Dispatch,纯C语言,提供了非常多强大的函数
优势:1、GCD是苹果公司为多核的并行运算提出的解决方案
2、GCD会自动利用更多的CPU内核(比如双核、四核)
3、GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程),程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
术语补充:
1、同步和异步决定了要不要开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力
2、并发和串行决定了任务的执行方式
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
获得串行队列:
1、使用dispatch_queue_create函数创建串行队列
dispatch_queue_t queue=dispatch_queue_create("sjl", NULL);
第一个参数队列名称,第二个参数用NUKLL即可
2、使用主队列(跟主线程相关的队列)
主队列是GCD自带的一种特殊的串行队列,放在主队列中的任务,都会放到主线程中执行
获得并发队列:
1、GCD默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建
dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
第一个参数,是全局并发队列的优先级
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台添加同步任务
第二个参数,写0即可
用同步的方式执行任务 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
参数说明:
queue:队列
block:任务
用异步的方式执行任务 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
9、线程锁
- (NSString *)md5:(NSString *)str
{
const char *cStr = [str UTF8String];
unsigned char result[16];
CC_MD5(cStr, (CC_LONG)strlen(cStr), result); // This is the md5 call
return [NSString stringWithFormat:
@"XXXXXXXXXXXXXXXX", // 小写 x 表示输出的是小写 MD5 ,大写 X 表示输出的是大写 MD5
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
];
}