您的位置:首页 > 移动开发 > IOS开发

iOS 开发笔记

2015-12-17 22:08 579 查看
学习了IOS开发,就可以编写运行在iPhone上/ipad的应用程序和游戏
IOS开发的准备:
1.OC语言
2.Xcode
3.Mac OS X
调试设备(可选):真机测试
开发者证书(可选):在APPstore申请
第一个IOS程序运行过程:
1.每一个应用程序都有属于自己的UIWindow,UIWindow继承自UIView
2.UIView面临的问题
1>谁来控制器UIView之间的切换?
2>谁来管理UIView的生命周期?
3>谁来给UIView装配数据?
4>谁来监听UIView的事件?
答案都是:控制器(UIViewController)
ios的设计采取了MVC模式
IOS的运行过程原理:
1.首先执行main函数
2.执行UIApplicationMain函数
3.UIApplicationMain函数内部
1>创建一个UIApplication实例.这个
UIApplication对象是单粒的,一个IOS程序对应一个UIApplication对象
2>UIApplication对象是应用程序的象征
3>开启一个消息循环(main loop),用来监听用户的操作
4>再创建一个UIApplication的delegate对象,负责监听UIApplication的生命周期
5>当UIApplication的生命周期发送改变时,会给代理delegate发送不同消息
*当第一次运行程序时候:
didFinishLaunchingWithOptions(加载完毕)->
applicationDidBecomeActive(获取焦点)
*当点击home键时候:
applicationWillResignActive(失去焦点)->
applicationDidEnterBackground(进入后台)
*当再次点击应用图标重新进入应用时候:
applicationWillEnterForeground(进入前台)->
applicationDidBecomeActive(获取焦点)

UIApplication函数的参数:
*第四个参数用来指定UIApplication的代理
*第三个参数用来指定UIApplication的代理的类名或者子类,如果为nil,就默认为nil

1iOS开发概述:
开发iOS程序的步骤:
(1)搭建界面;
(2)监听事件;(连线)
(3)编写代码
0519
iOS系统架构:基于UNIX。分为4个层次:
核心操作系统层(最底层)Core OS
核心服务层 Core Services
媒体层 Media
可触摸层 Cocoa Touch

company identifier 公司标示符,反向域名
正向域名:www.baidu.com 用来表示一台网络主机
反向域名:cn.itCast. 用来标示产品的
bundle identifier产品唯一标示符
bundle ID=公司反向域名+产品
注意点:在模拟器上只能有一个唯一的标示符;
在APPStore上所有应用程序Bundle ID是唯一的(不支持中文,如果是上架产品,需要修改)

UIView:屏幕上能看得见摸的着的东西,翻译叫做视图\控件\组件
每一个UIView都是一个容器,能容纳其他UIView。
父控件和子控件:
UIButton,UILabel,UITextField都继承UIView。
UIViewController是UIView的大管家,通过程序代码处理。工作:
(1)UIView的创建,显示和销毁;
(2)UIView跟用户的交互;
(3)监听UIView内部的事件;
UIViewController 是负责程序的控制;UIView是负责界面的显示的。
IBAction和IBOutlet:
IBAction原名是Interface Builder,用来操作建立关系,本质就是一个void,
只有返回值声明为IBAction方法,才能跟storyboard控件进行连线。
IBOutlet用来和界面上元素建立关系,用来获得修改界面控件属性.
退出键盘的方式:
1resignFirstResponder
2endEditing

如何修改控件状态:
每一个UI控件都是一个对象;每一个UI控件都有自己的位置和尺寸,有自己的父控件和子控件;
修改UI控件的状态,其实就是修改控件对象的属性;
所有的UI控件最终都继承自UIView,UI控件的
公共属性都定义在UIView中。
UIKit坐标系:坐标系原点在左上角,x值向右正向延伸,Y值向下正向延伸。
UIView的常见属性:
@property(nonatomic,readonly)UIView *superview;
获得自己的父控件对象
@property(nonatomic,readonly,copy)NSArray *subviews;
获得自己的所有子控件对象
@property(nonatomic)NSInteger tag;
控件的ID(标识),父控件可以通过tag找到对应的子控件
@property(nonatomic)CGAffineTransform transform;
控件的形变属性(旋转,缩放,平移等属性)
UIView的常见方法:
-(void)addSubview:(UIView *)view;
-(void)removeFromSubview;
-(UIView *)viewWithTag:(NSInteger)tag;

去除autolayout:如果发现通过代码无法修改控件的位置或者尺寸时。

UIButton的状态:normal;highlighted;disabled。
通过修改控件的frame属性就可以修改控件在屏幕的位置尺寸。
实现简单动画:
头尾式:[UIView beginAnimations:nil context:nil];
[UIView commitAnimations];
Block式:[UIView animateWithDuration:0.5 animations:^{

}];
修改控件的位置:(frame)
frame.origin(CGRect)
center (CGPoint)
修改控件的尺寸:(size)
frame.size
bounds.size
transforms属性:可以修改控件位移(位置尺寸),缩放,旋转
4>.h & .m
.h 是程序接口,对外提供方法声明
.m 是程序的实现,负责方法的具体实现
注意:在OC中,不允许直接修改对象的结构体属性的成员;
允许修改对象的结构体属性。
UIView常见属性:
@property(nonatomic)CGRect frame;父控件原点,定义控件位置和大小
@property(nonatomic)CGRect bounds;自己左上角为原点,定义控件的大小(神奇)
@property(nonatomic)CGPoint center;父控件原点,定义控件的位置

有时候连线连不了,需要将Xcode退一下就可以了。
要想提示高亮状态的颜色必须把type的system改为custom;normal改为highlighted。
1定义属性
2创建属性对应的控件,添加到视图
3监听按钮的点击事件

懒加载:在需要’的时候在实例化加载在内存中
@property1setter和getter 2带下划线的成员变量
怎么懒加载?重写一个getter方法

0522
-(void)dealloc
{
//对象被销毁,系统会自动调用
}
1. @property的参数说明
========================================
ARC是苹果为了简化程序员对内存的管理,推出的一套内存管理机制
使用ARC机制,对象的申请和释放工作会在运行时,由编译器自动在代码中添加retain和release
1> strong:强指针引用的对象,在生命周期内不会被系统释放
在OC中,对象默认都是强指针
2> weak:弱指针引用的对象,系统会立即释放
弱指针可以指向其他已经被强指针引用的对象
ARC中的@property参数使用小结:
1> 控件用weak 相当于MRC的assign
2> 属性对象用strong(如:NSArray *DataList)相当于MRC的retain
3> 非对象类型用assign 相当于MRC的assign
4> 字符串NSString用copy 相当于MRC的copy
提示:在纯手码实现界面布局时,如果通过懒加载处理界面控件,需要使用strong强指针
2. 运行循环
========================================
在iOS的应用程序中,应用程序启动之后,系统即会创建一个运行循环监听用户的交互。
runloop的演示:
创建新的项目;osx,application,commandLineTool.(Foundation框架)
程序运行启动——>等待用户输入——><——处理用户输入
以下代码其本质是在运行循环中注册一个监听事件
[button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
当运行循环检测到button的UIControlEventTouchUpInside事件时,会给视图控制器(self)发送一个click消息。

1. 开发前的思路
========================================
1> 从mainBundle中加载Plist
2> 按照plist中的数据数量先确定各个appView的大小和位置
3> 使用代码创建appView中的子控件,并显示内容

3. 关于UIButton的一些补充
========================================
3.1 按钮的类型
在iOS的控件中,只有UIButton提供了类方法,可以在实例化按钮时指定按钮的不同类型。
UIButtonTypeCustom和[[UIButton alloc] init]是等价的
3.2 修改按钮字体
在UIButton中定义有两个readonly的属性:
1> titleLabel
2> imageView
@property中readonly表示不允许修改这两个属性的指针地址,但是可以修改其属性

注意:由于按钮的字体大小是所有状态共用的,因此可以通过
button.titleLabel.font= [UIFont systemFontOfSize:14.0];
修改按钮标签文本的字体大小
但是不能使用以下代码设置按钮标签的文本内容
button.titleLabel.text = @"下载";
因为按钮标签的文本内容是跟按钮的状态向关的

4. 动画
========================================
4.1 首尾式动画
如果只是修改控件的属性,使用首尾式动画还是比较方便的,但是如果需要在动画完成后做后续处理,就不是那么方便了
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
// 修改属性的动画代码
// ......
[UIView commitAnimations];

4.2 块动画
块动画相对来说比较灵活,尤为重要的是能够将动画相关的代码编写在一起,便于代码的阅读和理解
[UIView animateWithDuration:2.0 animations:^{
// 修改控件属性动画
label.alpha = 0.0;
} completion:^(BOOL finished) {
// 删除控件
[label removeFromSuperview];
}];

5. ***************************
*******************************
在点击supportingFiles新建plist文件(iOS-resource-propertyList)建立好array,dictionary,string
在viewController.m文件中:
1 在懒加载中通过mainBundle加载plist文件;获得全路径
2 根据全路径加载数据;
3 字典转模型;
4 赋值数据
5 返回数据
#pragma mark -懒加载
-(NSArray *)heros
{
if(_heros == nil){

//获得全路径
NSString *fullPath = [[NSBundle mainBundle]pathForResource:@“heros
” ofType:@“plist”;
//根据全路径加载数据
NSArray *dictArray = [NSArray arrayWithContentsOfFile:fullPath];

//字典转模型
NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictArray.count];
for(NSDictionary *dict in dictArray){
NJHero *hero = [NJHero heroWithDict:dict];
[models addObject:hero];
}
//赋值数据
_heros = [models copy];

}
//返回数据
return _heros;
}

在viewController.M文件中再建议一个类,继承NSOject。
在类.h中,写入如下方法
模型应该提供一个可以传入字典参数的构造方法(字典转模型的过程最好封装在模型内部)
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)xxxWithDict:(NSDictionary *)dict;
在类.m中实现方法:
- (instancetype)initWithDict:(NSDictionary *)dict{
if(self = [super init]){
[self setValueForKeysWithDictionary:dict];

}

return self;
}
+ (instancetype)xxxWithDict:(NSDictionary *)dict{

return [[self alloc]initWithDict:dict];
}

***************************
*******************************
5.2 instancetype & id
1> instancetype在类型表示上,跟id一样,可以表示任何对象类型
2> instancetype只能用在返回值类型上,不能像id一样用在参数类型上
3> instancetype比id多一个好处:编译器会检测instancetype的真实类型

5.3 在模型中添加readonly属性
// 定义属性时,会生成getter&setter方法,还会生成一个带下划线的成员变量
// 而如果是readonly属性,则只会生成getter方法,同时没有成员变量
@property (nonatomic, strong, readonly) UIImage *image;

@interface LFAppInfo()
{
UIImage *_imageABC;
}
- (UIImage *)image
{
if (!_imageABC) {
_imageABC = [UIImage imageNamed:self.icon];
}
return _imageABC;
}
在模型中合理地使用只读属性,可以进一步降低代码的耦合度。

5.4 使用数据模型的好处:
*** 调用方不用关心模型内部的任何处理细节!
5.1 字典转模型的好处:
1> 降低代码的耦合度
2> 所有字典转模型部分的代码统一集中在一处处理,降低代码出错的几率
3> 在程序中直接使用模型的属性操作,提高编码效率

6. XIB
========================================
Xib文件可以用来描述某一块局部的UI界面
Xib文件的加载:
方法1NSArray *objs = [NSBundle mainBundle] loadNibNamed:@“AppView”owner:nil options:nil];
方法2UINib *nib = [UINib nibWithNibName:@“AppView”bundle:[NSBundle mainBundle]];
NSArray *objs = [nib instantiateWithOwner:nil options:nil];

XIB & Storyboard
相同点:
1> 都用来描述软件界面
2> 都用Interface Builder工具来编辑
不同点
1> Xib是轻量级的,用来描述局部的UI界面
2> Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系

7. View的封装思路
========================================
1> 如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部子控件的创建屏蔽起来,不让外界关心
2> 外界可以传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应的数据

MVC:
controller(控制中心,大管家)

Model(数据模型,数据) View(视图,显示数据)
特征:
View上面显示什么东西,取决于Model
只要Model数据改了,View的显示状态会跟着更改
Controller负责初始化Model,并将Model传递给View去解析展示

UILabel的常见设置:
@property(nonatomic,copy)NSString *text;
@property(nonatomic,retain)UIFont *font;
@property(nonatomic,retain)UIColor *color;
@property(nonatomic)NSTextAlignment textAlignment;
UIFont:
创建方法:
+(UIFont *)systemFontOfSize:(CGFloat)fontSize;系统默认字体

+(UIFont *)boldSystemFontOfSize:(CGFloat)fontSize;粗体

+(UIFont *)italicSystemFontOfSize:(CGFloat)fontSize;斜体
UIButton的常见设置:
-(void)setTitle:(NSString *)title forState:(UIControlState)state;
-(void)setTitleColor:(UIColor *)color forState:(UIControlState)state;
-(void)setImage:(UIImage *)image forState:(UIControlState)state;
-(void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;
//设置按钮的文字字体
btn.titleLabel.font = [UIFont systemFontOfSize:13];

//获得按钮的文字
-(NSString *)titleForState:(UIControlState)state;
-(UIColor *)titleColorForState:(UIControlState)state;
-(UIImage *)imageForState:(UIControlState)state;
-(UIImage *)backgroundImageForState:(UIControlState)state;
新建
shift + cmd + n 新建项目
cmd + n 新建文件

视图
option + cmd + 回车 打开助理编辑器
cmd + 回车 显示主窗口
cmd + 0 导航窗口
option + cmd + 0 工具窗口

在.m & .h之间切换 control + cmd + 上/下
按照浏览文件的前后顺序切换 control + cmd + 左右

查看头文件 control + cmd + j
切换到对应的函数 control + 6 支持智能输入,注意输入法

运行
cmd + r 运行
cmd + . 停止
cmd + b 编译
cmd + shift + b 静态内存分析编译,可以检查程序结构上是否存在内存泄露

排版
control + i 将选中按钮重新缩进
cmd + ] 向右增加缩进
cmd + [ 向左减少缩进
cmd + / 注释/取消注释,提示:取消注释时,注释双斜线必须在行首
cmd + 向上 到文件开始位置
cmd + 向下 到文件末尾位置

.png格式的图片都是直接拖Applicon;
.jpg格式的图片放在Supporting Files。
序列帧动画,就是让一组图片一张一张顺序播放。

git的使用:
newBranch (不想改变破坏原来的版本,新建一个分支看看是否适合)
switch to branch 切换分支(查看原来的版本)
Merge from Branch 将原来版本和分支整合起来

0526
UIScrollView的基本使用:
1将需要展示的内容添加到UIScrollView
2设置UIScrollView的contentSize属性,告诉尺寸,也就是滚动范围
UIScrollView无法滚动的解决办法:
原因:没有设置contentSize;
scrollEnabled = NO
没有接收到触摸事件:userInteractionEnabled = NO
没有取消autolayout功能
UIScrollView的代理
前提能够监听UIScrollView的整个滚动过程
就是给它设置一个代理对象,通过代理通知滚动过程

UIScrollView和delegate的通信:
发送信息就是调用方法
1UIScrollView开始拖拽,调用scrollViewWillBeginDragging:方法通知delegate
2滚动某个位置,调用scrollViewDidScroll:方法
3停止拖拽,调用scrollViewDidEndDragging:willDecelerate:方法
称为delegate的条件:
遵守UIScrollViewDelegate协议,然后实现协议中的方法就可以了

UIScrollView和控制器:
一般设置UIScrollView所在控制器为UIScrollView的delegate
有2种方法:
通过代码
self.scrollView.delegate = self;
通过storyboard托线
UIScrollView的常见属性
@property(nonatomic)CGPoint contentOffset;//滚动位置
@property(nonatomic)CGSize contentSize;//滚动范围
@property(nonatomic)UIEdgeInsets contentInset;//设置滚动控件的四周增加额外的滚动区域

其他属性:
@property(nonatomic)BOOL bounces;//是否需要弹簧效果
@property(nonatomic,getter = isScrollEnabled)BOOL scrollEnabled;//是否能滚动
@property(nonatomic)BOOL showsHorizontalScrollIndicator;//是否显示水平滚动条
@property(nonatomic)BOOL showsVerticalScrollIndicator;

缩放
//用户使用捏合手势调用
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
缩放实现步骤:
1设置UIScrollView的id<UIScrollViewDelegate>delegate对象
2设置minimumZoomScale:缩放最小比例
3设置maximumZoomScale:放大的最大比例
4让代理对象实现下面方法,返回需要缩放的视图控件
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
跟缩放相关的其他代理方法:
//缩放完毕
-(void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view;
//正在缩放
-(void)scrollViewDidZoom:(UIScrollView *)scrollView;
分页:
pageEnabled属性设置YES,分页展示
UIPageControl的属性:

//一共多少页
@property(nonatomic)NSInteger numberOfPages;
//当前显示的页码
@property(nonatomic)NSInteger currentPage;
//只有一页时,是否需要隐藏页码显示器
@property(nonatomic)BOOL hidesForSinglePage;
//其他页码显示的颜色
@property(nonatomic,retain)UIColor *pageIndicatorTintColor;
//当前页码显示器的颜色
@property(nonatomic,retain)UIColor *currentPageIndicatorTintColor;

NSTimer:
定时器
在制定时间执行指定任务;每隔一段时间执行指定的任务
//开启定时任务
+(NSTimer *)scheduledTimerWithTimeInterval:(NSTimerInterval)ti
target:(id)aTarget
selector(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)yesOrNo;

//停止定时器工作
-(void)invalidate;

0524
状态栏:
设置状态栏的样式
(UIStatusBarStyle)preferredStatusBarStyle;
设置状态栏的可见性
-(BOOL)prefersStatusBarHidden;
Retina屏幕:就是高清视网膜屏幕
苹果4/4s 3.5inch 640*960
苹果5/5c/5s 4inch 640*1136
UIButton获得当前状态下文字,文字颜色,图片。
@property(nonatomic,readonly,retain)NSString *currentTitle;

0527
UITableview基本使用
实现表格数据展示,继承自UIScrollview,支持垂直滚动
如何展示数据
UITableView需要一个数据源(dataSource)来显示数据,任意类型对象
UITableView会向数据源查询一共有多少行数据以及每一行显示什么数据等
没有设置数据源的UITableView只是个空壳
凡是遵守<UITableViewDataSource>协议的OC对象,都可以是UITableView的数据源
分为两种格式:plain,group
1设置数据源
2向数据源查询有多少组,每组有多少行,每行有显示什么对象
3头标题和尾部标题的设置
控制状态栏是否显示:返回YES代表隐藏状态栏,NO相反
-(BOOL)prefersStatusBarHidden

tableView和数据源(先调用数据源才有下面方法)
//一共有多少组数据
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
//每一组有多少行数据
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//每一行显示什么内容
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath;

cell的简介:
UITableView的每一行都是一个UITableViewCell,通过dataSource的tableView:cellForRowAtIndexPath
:方法来初始化每一行
UITableViewCell内部有个默认子实图:contentView,它是UITableViewCell的父视图,显示辅助视图
辅助指示视图的作用是显示一个表示动作的图标,通过设置UITableViewCell的accessoryType来显示,
默认是UITableViewCellAccessoryNone
***还可以通过cell的accessoryView的属性自定义辅助指示视图(如往右边放一个开关)
UITableViewCell的contentView:
contentView下默认有3个子视图
其中2个是UILabel(通过UITableViewCell的textLabel和detailTextLabel属性访问)
第3个是UIImageView(通过UITableViewCell的imageView属性访问)
UITableViewCell还有一个UITableViewCellStyle属性,决定使用contentView的哪些子视图还有位置等

cell的重用原理:
当滚动列表时,部分UITableViewCell会移出窗口,UITableView会将窗口外的UITableViewCell放入一个对象池中
,等待重用。当UITableView要求dataSource返回UITableViewCell时,datasource会先查看这个对象池,
如果池中又未使用的UITableViewCell,dataSource会用新的数据配置这个UITableViewCell,然后返回给UITableView,重新显示到窗口中,从而避免创建新对象
自定义UITableViewCell时候,可能得到错误。怎么解决?
UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell
的时候传入特定字符串标识来设置reuseIdentifier,当UITableView要求dataSource返回UITableViewCell时,
先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有就重用,没有就传入这个字符串标识
来初始化一个UITableViewCell对象

cell的重用代码:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath
{
//定义一个cell的标识
static NSString *ID = @“MJCell”;
//从缓存池取出cell
UITableViewCell *cell = [tableview dequeueReusabelcellWithIdentifier:ID];
//如果缓存池没有cell
if(cell == nil){
cell = [UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:ID];

}

//设置数据

//返回cell
return cell;

}

cell的常见属性
设置cell的辅助视图:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
设置cell的背景颜色属性:默认状态下
cell.backgroundColor = [UIColor redColor];
//通过把backgroundColor和backgroundView都可以设置cell的背景'
不过后者比前者优先级高,颜色会覆盖前者颜色。
UIView*view=[[UIView alloc] init];
view.backgroundColor = [UIColor blueColor];
cell.backgroundView = view;
设置cell的选中状态背景的属性:
UIView*view=[[UIView alloc] init];
view.backgroundColor = [UIColor purpleColor];
cell.selectedBackgroundView = view;

tableview的常见属性(利用代码,不用storyboard)
(1)创建一个tableview
UITableview *tableview =[ [tableview alloc]init];
(2)设置数据源
tableView.datasource = self;
(3)添加tableview到view
[self.view addSubview:tableview];
(4)设置分割线样式
tableView.separatorStyle = UITableViewCellSeparatorStylenone;
(5)设置分割线颜色
24bit颜色(R,G,B);32bit颜色(A,R,G,B)
tableView.separatorColor = [UIColor colorWithRed:0/255.0 green:255/255.0 blue:0/255.0 alpha:255/255.0];
(6)设置tableview的头部尾部视图,不用设置宽度,默认和tableview宽度一样
tableView.tableHeaderView =[UIButton buttonWithType:UIButtonTypeContact add];
tableView.tableFooterView =[[UISwitch alloc] init];

Delegate的使用场合:
1对象A内部发生了一些事情,想通知对象B
2对象B想监听对象A内部发生了什么事情
3对象A想在自己的方法内部调用对象B的某个方法,并且对象A不能对对象B有耦合依赖
4对象A想传递数据给对象B
。。。。结果:对象B是对象A的代理。
使用delegate的步骤:
1搞清楚谁是谁的代理
2定义代理协议,协议名称的命名规范:控件类名 + delegate
3定义代理方法:
》代理方法一般定义为@optional
》代理方法名都以控件名开头
》代理方法至少有1个参数,将控件本身传递出去
4设置代理对象
》代理对象遵守协议
》代理对象实现协议里面该实现的方法
5在恰当时候调用代理对象的代理方法,通知代理发生了什么事情

自定义cell:
在系统自带中,cell中只有两个lable,一个image,满足不了需求,可以自定义cell
有2种方式:1通过纯代码 2通过xib(每个cell都相同时候用xib)

****通过xib步骤自定义cell(iOS-USER interface-empty-next-名称XXXCell-creatre)
往xib里面拖拽所需要的控件,通过xib来描述一个cell;需要绑定一个ID标识
****使用xib封装一个cell的步骤:
1新建一个xib文件描述一个view/cell的内部结构
2新建一个自定义的类
3新建类的类名最好跟xib文件名保持一致
4将xib控件和自定义的.m文件进行连线
5提供一个类方法返回一个创建好的自定义cell
6提供一个模型属性让外界传递模型数据
7重写模型属性的setter方法,在这里将模型数据展示到对应的子控件上面

*****通过纯代码自定义cell(cell的高度不一致)
1新建一个继承自UITableViewCell的类
2重写initWithStyle:reuseIdentifier:方法
》添加所有需要显示的子控件(不需要设置子控件的数据和frame,子控件要添加到contentView中)
》进行子控件一次性的属性设置
3提供2个模型
》数据模型:存放文字数据\图片数据
》frame模型:存放数据模型\所有子控件的frame\cell的高度
4cell拥有一个frame模型
5重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame
6frame模型数据的初始化以及采用懒加载的方式(只加载一次)

控件通过xib或者storyboard创建控件时候调用
-(void)awakeFromNib{
}
协议可选的optional。
协议名称:控件名称+delegate
协议方法名称:控件名称去掉前缀+含义
协议方法中将自己控件传出去的目的是发布用于区分哪个空间触发类该方法

UITextField:
通过UITextFiel的代理方法能够监听键盘最右下角按钮的点击
//称为UITextField的代理
self.textField.delegate = self;
//遵守协议,实现代理方法
-(BOOL)textFieldShouldReturn:(UITextField *)textField;
//在UITextField左边放一个view
self.textField,leftView = [[UIView alloc]initWithFrame:CGRectMake(0,0,8,0)];
self.textField.leftViewMode = UITextFieldViewModeAlways;

数据独立:
iOS—》Cocoa Touch —>OC class
新建一个继承NSObject的类,建立一个模型保存数据
1创建模型
2将模型添加到数组中
3返回数组

取出对应的组模型
返回对应组行的数据
设置要显示的数据

**注意点:当每一行的cell的高度不一致时候就使用代理方法设置cell的高度

#warning待续,接着写(很好的作用)

如:
-(CGFloat)tableView:(UITableView *)tableView hightForRowAtIndexPath:(NSIndexPath *)indexPath;
1.tableView的刷新
1> 数据刷新的总体步骤
* 修改模型数据
* 刷新表格(刷新界面)

2> 刷新表格(刷新界面)的方法
* 全局刷新(每一行都会重新刷新)
- (void)reloadData;

* 局部刷新(使用前提: 刷新前后, 模型数据的个数不变)
- (void)reloadRows:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

* 局部删除(使用前提: 模型数据减少的个数 == indexPaths的长度)
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

2.@property属性的用法
* weak(assign) : 代理\UI控件
* strong(retain) : 其他对象(除代理\UI控件\字符串以外的对象)
* copy : 字符串
* assign : 非对象类型(基本数据类型int\float\BOOL\枚举\结构体)

0530
通知机制:
通知中心(NSNotificationCenter)
每一个应用APP都有一个通知中心实例,负责协助不同对象之间的消息通信
任何一个对象都可以向通知中心发布通知,描述自己在做什么。

通知发布者 通知接收者
某个对象A ——发布通知—————>通知中心 observer1
某个对象D————————> observer2
通知包含的3个属性:
-(NSString *)name;//通知名称
-(id)object;//通知发布者
-(NSDictionary *)userInfo;//一些额外的信息(通知发布者传递给通知接收者的信息内容)
初始化一个通知对象:
1+(instancetype)notificationWithName:(NSString *)aName object:(id)anObject;
2+(instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:
(NSDictionary *)aUserInfo;
3-(instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;
发布通知:
//发布通知,可以设置通知名称,通知发布者,额外信息
1-(void)postNotification:(NSNotification *)notification;
//发布一个名称为aName的通知,anObject为这个通知的发布者
2-(void)postNotificationName:(NSString *)aName object:(id)anObject;
//发布一个名称为aName的通知,anObject为这个通知的发布者,aUserInfo为额外信息
3-(void)postNotificationWithName:(NSString *)aName object:(id)anObject userInfo:
(NSDictionary *)aUserInfo;

注册通知监听器:
1-(void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName
object:(id)anObject;
observer:谁要接收这个通知
aSelector:收到通知后,回调监听器方法,并把通知对象当做参数传入
aName:通知名称
anObject:通知发布者
2
-(id)addObserverForName:(NSString *)name object:(id)obj queue:
(NSOperationQueue *)queue usingBlock:(void(^)(NSNotification *note))block;
name:通知名称
obj:通知发布者
block:收到对应通知后,回调这个block
queue:决定block在哪个操作队列执行,传nil,默认在当前操作队列同步执行
取消注册通知监听器:
-(void)removeObserver:(id)observer;
-(void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
一般在监听器销毁之前取消注册:
-(void)dealloc{
[super dealloc];//非ARC中需要调用
[[NSNotificationCenter defaultCenter]removeObserver:self];

}

UIDevice通知:
UIDevice类提供了一个单例对象,代表设备,获取设备信息,如电池状态,设备类型,设备系统
通过[UIDevice currentDevice]可以获取这个单粒对象
UIDevice对象发布通知的名称常量:
UIDeviceOrientationDidChangeNotification//设备旋转

键盘通知:
UIKeyboardWillShowNotification//键盘即将显示
UIKeyboardDidShowNotification//键盘显示完毕
UIKeyboardWillHideNotification//
UIKeyboardDidHideNotification
UIKeyboardWillChangeFrameNotification//键盘位置尺寸即将发生改变
UIKeyboardDidChangeFrameNotification

UIKeyboardFrameBeginUserInfoKey//键盘刚开始的frame
UIKeyboardFrameEndUserInfoKey
UIKeyboardAnimationDurationUserInfoKey//键盘动画的时间
UIKeyboardAnimationCurveUserInfoKey//键盘动画的执行节奏

通知和代理的选择:
共同点:利用通知和代理都能完成对象之间的通信
不同点:
代理:一对一关系
通知:多对多关系

0603
pickerview 和tableview一样,也有数据源,不过需要用代理来显示数据,不是由数据源显示
tableview设置高度时候有两种方法:一种是属性。(每行高度一样)一种是代理
pickerView只有代理一种方法

一.UIPickerView
1.UIPickerView的常见属性
// 数据源(用来告诉UIPickerView有多少列多少行)
@property(nonatomic,assign) id<UIPickerViewDataSource> dataSource;
// 代理(用来告诉UIPickerView每1列的每1行显示什么内容,监听UIPickerView的选择)
@property(nonatomic,assign) id<UIPickerViewDelegate> delegate;
// 是否要显示选中的指示器
@property(nonatomic) BOOL showsSelectionIndicator;
// 一共有多少列
@property(nonatomic,readonly) NSInteger numberOfComponents;

2.UIPickerView的常见方法
// 重新刷新所有列
- (void)reloadAllComponents;
// 重新刷新第component列
- (void)reloadComponent:(NSInteger)component;

// 主动选中第component列的第row行
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;

// 获得第component列的当前选中的行号
- (NSInteger)selectedRowInComponent:(NSInteger)component;

3.数据源方法(UIPickerViewDataSource)
// 一共有多少列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
// 第component列一共有多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;

4.代理方法(UIPickerViewDelegate)
// 第component列的宽度是多少
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;
// 第component列的行高是多少
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component;

// 第component列第row行显示什么文字
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;

// 第component列第row行显示怎样的view(内容)
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;

// 选中了pickerView的第component列第row行
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;

二.UIDatePicker
1.常见属性
// datePicker的显示模式
@property (nonatomic) UIDatePickerMode datePickerMode;
// 显示的区域语言
@property (nonatomic, retain) NSLocale *locale;

2.监听UIDatePicker的选择
* 因为UIDatePicker继承自UIControl,所以通过addTarget:...监听

Info.pilst常见的设置,是在Supporting files文件夹
pch文件也就是Supporting files的头文件,可以被所有源文件访问和使用
pch的常见使用:1用来定义一些全局的宏
2用来导入一些全局都能用到的文件
3用来自定义log
--objc--这个宏,只要在.M或者.MM才定义这个宏
在开发中有两个阶段:
1开发调试阶段:是需要打印LOG调试程序,系统定义一个叫做BEBUG的宏
2发布阶段:不需要打印LOG,因为LOG很占用资源并且用户看不懂
因此,自定义LOG就诞生了。
更简单的就是自动解开自动加:
在pch文件中
#ifdef BEBUG
#define Log(...) NSLog(__VA_ARGS__)
#else
#define Log(..)
#endif
当去公司的时候,做的第一件事就是观察公司自定义的LOG

UIApplication:
应用程序有一个openURL的强大功能。统一资源定位符,
用来唯一 的表示一个资源。表示一个资源地址
URL:协议头://主机地址/资源路径
网络资源:http://www.baidu.com/images/20140603/abc.png
本地资源:file:///users/apple/desktop/abc.png
http://ios.itcast.cn

UIApplication和delegate
所有移动操作系统都有个致命的缺点:app很容易受到打扰。
delegate可处理的事件包括:
1应用程序的生命周期事件(如程序启动和关闭)
2系统事件(如来电)
3内存警告
............
iOS程序的启动过程(没有storyboard)
1打开程序,执行main函数;
2执行UIApplicationMain函数;(创建UIApplication对象,创建UIApplication的delegate对象)
3delegate对象开始处理监听系统事件(没有storyboard)
*程序启动完毕时候会调用代理的application:didFinishlauchingwithoptions:方法
*在application:didFinishlauchingwithoptions:方法中创建UIWindow
*创建和设置UIWindow的rootviewController
*显示窗口

iOS程序的启动过程(有storyboard)
1打开程序,执行main函数;
2执行UIApplicationMain函数;(创建UIApplication对象,创建UIApplication的delegate对象)
3根据Info.plist获得主要storyboard的文件名,加载最主要的storyboard(有storyboard)
*创建UIWindow
*创建和设置UIWindow的rootviewController
*显示窗口
分析:UIApplicationMain函数会根据principalClassname创建UIApplicationMain
对象,根据delegateClassname创建一个delegate对象,并将delegate对象
赋值给UIApplication对象中的delegate属性;
然后建立程序的main runloop(事件循环),进行事件处理(在程序完毕后调用delegate对象
的application:didFinishlaunchingwithoptions:方法 )//通知代理
最后程序正常退出时UIApplicationMain函数才返回。
argc:系统或者用户传入的参数 个数;
argv:系统或者用户传入的实际参数。
int main (int argc, char * argv[]){
}
这个函数做了哪些事情?
1根据传入的第三个参数创建UIAoolication对象
2根据传入的第四个参数产生UIApplication对象的代理
3设置刚刚创建出来的代理对象为UIApplication的代理
4开启一个事件的循环,死循环,UIApplicationmain永远不会返还

UIWindow
是一种特殊的UIView,一个app只会有一个UIWindow
ios程序启动完毕后,创建第一个视图控件就是UIWindow,接着创建控制器的view,
最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了。
一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow,没有它,就看不见
UI界面了。

主窗口和次窗口的区别:
在iOS7以前,只有主窗口可以输入内容;
在iOS7以后,主窗口和次窗口都可以显示输入内容

控制器的多种创建方式:
1通过storyboard,(加载storyboard;创建storyboard箭头指向的控制器/或者通过唯一标示符)
2直接创建
NJViewController *nj =[ [NJViewController alloc]init];
3指定xib文件来创建
NJViewController *nj =[ [NJViewController alloc]initWithNibName :"NJViewController" bundle:nil];

控制器view的创建方式:
1//通过alloc init创建,会自动创一个空白的view做为控制器的view(没有storyboard和xib)
NJViewController *vc =[ [NJViewController alloc]init];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];

2有storyboard的情况下创建
//通过storyboard,会根据storyboard中箭头指向控制器view的描述创建控制器的view
加载storyboard:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@""test bundle:nil];
UIViewController *vc = [storyboard instantiateInitialViewController];==
//UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"two"];
self.window.rootviewController = vc;
[self.window makeKeyAndVisible];
注意:如果有重写控制器loadview方法,就不会创建storyboard描述中的view,
,而是创建一个空白的view来作为控制器的view。

3通过指定xib创建
先设置一个view;根据xib描述的view来创建控制器的view
NJViewController *VC=[ [NJViewController alloc]initWithNibname:@“one” bundle:nil];
self.window.rootviewController = vc;
[self.window makeKeyandvisible];

4有同名xib创建,xib名称和控制器的名称相同
会自动找到同名xib中描述的view作为控制器的view
NJViewController *VC=[[ [NJViewController alloc]init];
self.window.rootviewController = vc;
[self.window makeKeyandvisible];

5有同名xib去掉controller情况下
会自动找到该xib的view作为控制器的view
NJViewController *VC=[[ [NJViewController alloc]init];
self.window.rootviewController = vc;
[self.window makeKeyandvisible];

6重写控制器loadview方法,就不会去加载创建同名去掉controller的xib和同名的xib
,而是创建一个空白的view来作为控制器的view
-(void)loadView{
self.view =[ [UIView alloc ]init];
}

最优先级方法,什么时候调用loadview方法就什么时候加载控制器的view
// 当控制器需要显示控制器的view的时候就会调用loadView
// 可以在loadView方法中创建view给控制器
// 该方法一般用于自定义控制器的view

控制器view的延迟加载---懒加载
可以用isViewloaded方法判断一个UIViewController的view
是否已被加载;
控制器的view加载完毕(也就是loadView方法完毕后)就会调用viewDidload方法

多控制器:父控制器,子控制器
管理控制器的特殊的控制器:
UINavigationController 和 UITabBarController

UINavigationController使用步骤:
1初始化UINavigationController
2设置UIWindow的rootController为UINavigationController
3根据具体情况,通过push方法添加对应个数的子控制器
UINavigationController是通过栈的形式来管理子控制器先进后出
UINavigationController的view结构:导航条;导航控制器的view;栈顶控制器的view;
显示在导航控制器上的view永远是栈顶控制器的view
返回就会将放在栈里面的控制器一个一个销毁,然后控制器的view也会跟着慢慢销毁
nav.viewController;//导航控制器的栈等效 nav.childviewController;

添加子控制器到导航控制器上:4种方法
1[nav.childviewController:one ];
2[nav pushviewController:one animated:YES];
3nav.viewControllers=@[one];赋值
4UINavigationController *nav =[[ UINavigationController alloc]initwithrootviewController:one];

怎么获取栈顶的控制器?方法
nav.topviewController;

移除当前栈顶控制器?方法
[self.navigationController popToViewController animated:YES];

怎么从最栈顶控制器回到最初的控制器?方法
[self.navigationController popTorootviewController animated:YES];

//zhi要传入栈的某一个控制器就好跳转到指定控制器 方法
[self.navigationController popToviewController:two animated:YES];

总结:一个导航控制器只有一个导航条,也就是说所有的子控制器都公用一个导航条
导航条上显示的内容和栈顶控制器有关,所有导航条上显示什么内容由栈顶控制器决定
怎么控制当前控制器对应的导航条显示的内容?方法
-(void)viewDidLoad(){
[super viewDidLoad];
self.navigationItem.title=@"";
}
注意导航条上显示的内容特例:导航条上的返回按钮的文字是由上一个控制器决定的

修改返回按钮显示的内容方法:
self .navigationItem.backBarButtonItem =[ [UIButtonItem alloc ]initWith
tittle:@"返回" styleBarbuttonItemstylepliantarget:nil action:bil] ;

控制器生命周期:
过时方法:(面试时候经常会问看你是否有经验)
//控制器即将销毁的时候调用
-(void)viewWillunload{
[super viewWillunload];
}
//控制器即将销毁的时候调用
-(void)viewDidunload{
[super viewDidunload];
}
接收到内存警告的时候调用
-(void)didreceivememoryWarning{
[super didreceivememoryWarning];
}
当系统出现内存警告的时候怎么处理?
首先,当系统出现memory warning的时候会调用didreceivememoryWarning这个方法,接着判断
是否有is there a view ?如果控制器有view就判断是否能销毁?怎么判断它是否能被销毁?控制器的view不在UIwindow上可以销毁,
然后会调用viewWillunload方法来即将释放控制器的view,接下会释放控制器的view,released the view,
再调用viewdidunload方法之后控制器的view已经被销毁了,但是数据还在,一般在viewwillunload清空不需要的数据,
当调用完这个方法之后,控制器的view和不需要的数据都被销毁了。
需要再次显示这个控制器的view?
loadView——>viewDidLoad——>viewWillAppear——>viewDidAppear——>
viewWillDisappear——>viewDiddisappear——>didReceivememoryWarning
——>viewWillUnload——>销毁view——>viewDidUnload——>(重复加载)loadView

0604
控制器的值传递:
顺传和逆传
顺传:从A到C;采取perform方法,取出目标控制器
逆传:从C到A;让A成为C的代理,设置数据模型方法
除了push之外,还有另外一种控制器的切换方式,那就是Modal
任何控制器都能通过Modal形式展示,最底面钻出来
注意点:如果一个控制器的视图是以模态形式展现出来的,可以调用该控制器
以及该控制器的子控制器让控制器消失。
如果控制器之间的关系比较紧密用UINavigationController;
如果控制器之间的关系不是很紧密用Modal。

数据存储:
1plist属性列表(plist通过XML来保存数据),本质是XML,只存储系统自带的一些类如dictionary,array等
2preference(偏好设置/NSUserDefaults)
3键值归档(NSCoding/NSKeyedArchiver)
4SQLite3数据库
5Core Data

应用沙盒:
模拟器应用沙盒的根路径在:/Users/apple/Library/Application Support/iPone
Simulator/7.0/Applications
layer:是属于应用程序包,压缩包,不能存储任何东西
Documents:把重要文件存储在这里,持久化,会备份;
tep:保存临时数据;
Library/Caches:存储体积大,不需要备份的非重要数据;
Library/preference:存储应用的所有偏好设置。(系统自动放)
1XML属性列表(plist)归档(plist通过XML来保存数据)注意:不能保存自定义对象
获取应用程序沙盒目录方法:
NSString *home = NSHomeDictionary( ) ;
//动态获取数据
NSString *path =[NSSearchpathfordirectoriesindomains(NSdocumentdirectory,NSUserdomainmask,YES)lastobject];
//拼接文件路径
NSString *path = [doc stringByAppendingPathComponent:@"abc.plist”];

2偏好设置是专门用来保存应用程序的配置信息,一般情况下不用偏好设置中保存
其他数据,如果利用系统的偏好设置来存储数据,默认就是存储在preference文件夹下面
偏好设置会将所有数据保存到同一个文件中。本质是plist,不能保存普通对象

3文件归档:NSKeyedArchiver归档(NSCoding)保存自定义对象
如果想自定义对象保存到文件必须实现NSCoding协议,在协议中写清楚要存储哪些对象的属性
创建对象;
获取文件途径;
将自定义对象保存在文件中;
然后实现严格coding协议;
以什么方式保存就以什么方式读取。

0606
1.UISwitch
* UISwitch继承自UIControl,因此也能像UIButton一样监听一些事件,比如状态改变事件
* UISwitch可以通过拖线监听状态改变
* UISwitch可以通过addTarget:...方法监听状态改变
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
// 其中controlEvents参数传递的是:UIControlEventValueChanged(值改变事件)

2.监听文本框的文字改变
* 一个文本输入框的文字发生改变时,文本输入框会发出一个UITextFieldTextDidChangeNotification通知
* 因此通过监听通知来监听文本输入框的文字改变
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:textField];
// textField文本输入框的文字改变了,就会调用self的textChange方法

UIKit框架学习完毕**********

0607
Quartz2D来自Core Graphics 框架,纯C语言
Quartz 2D价值:自定义view/控件
注意自定义view的时候要重写initWithframe方法和initWithcoder方法。

图形上下文Graphics Context:是一个CGContextRef类型的数据
作用:
1 保存绘图信息(起点终点),绘图状态(颜色,线宽,线段顶部);
2 决定绘制的输出的目标

图形上下文有5种类型:window;layer;printer;PDF; Bitmap
如果在drawRect方法调用GraphicsGetcurrent Context方法获取
出来的就是layer的上下文。

画图的步骤:
获取上下文;
绘制图形;
渲染图形到layer上。

CGContextRef ctx = UIGraphicsgetcurrent Context;获取上下文
保存上下文图形
CGContextSaveGetState(ctx);
还原图形上下文
CGContextRestoreGetState(ctx);
rotate旋转;scale缩放;translate平移
图片剪切clip

自定义view的步骤:
1 新建一个类,继承UIView
2 实现-(void)drawRect:(CGRect)rect方法,然后在这个方法中
》 获取上下文;
》 绘制图形;
》利用上下文将绘制内容渲染显示到view上

drawRect:方法什么时候调用?
当view第一次显示到屏幕上时候调用;
调用view的setNeedsDisplay或者setNeedsDisplayInRect:时

Quartz2D的内存管理:
1有copy和create需要释放;
2retain了一个对象,不再使用需要release;
3使用Quartz2D的函数来指定retain和release对象
4也可以使用Core Foundation的CGRetain和CGRelease

KVC\KVO

KVC:键值编码 通过字符串更改对象属性,方法是valueForKey:和setValue:ForKey:
支持键路径key path,属性访问
KVO:键值监听
监听某个对象的属性

0609
如何创建一个Bitmap的上下文?
UIGraphicsBeginImageContextWithoptions(CGSize size,BOOL opaque,CGFloat scale);
步骤:
1 加载图片;
2 创建bitmap的上下文;
3 获取上下文;
4 绘图;
5 渲染;
6 获取生成的图片;
7 显示生成的图片到imageview;
8 保存绘制好的图片到文件中

水印的作用:图片从哪来的?主要是一些网站为了版权问题,广告而添加的
实现方式:利用Quartz2D,图片水印,文字水印

0610
swift的基本使用:在Xcode6以上使用
不需要main函数;不需要分号;支持多行注释嵌套多行注释;

常量和变量:
用let来声明常量;用var来声明变量;
常量和变量的命名:基本上可以用任何你喜欢的字符作为常量和变量
表情是一种特殊的Unicode字符
注意点:不能包含数学符号;不能包含箭头;不能包含非法无效的Unicode字符;
不能是关键字;不能包含横线,制表符;不能以数字开头;不能是单独一个下划线
数据类型:
常用的有Int,Float,Double,Bool,String,Character,Array,Dictionary
数据类型的首字母都是大写的。
如何指定?在常量和变量名后面加上冒号和类型名称
整数:分为2种,有符号和无符号
整数的最值:number.min/max;
整数的4种表示形式:十进制:没有前缀;
二进制:以0b为前缀;八进制:以0o为前缀;十六进制:0x为前缀
类型别名:typealias 和typed 一样的用法
浮点数:double和float可以使用十进制和十六进制表示

事件传递:
从父控件传递自控件;
触摸事件不能接受的三种情况:
1隐藏;透明度为0;不接受用户交互。

响应者链条:由很多响应者链接在一起组合起来的一个链条;
什么是响应者?继承自Responder的对象;
上一个响应者:默认做法是将事件顺着响应者链条传递给上一个响应者;
如何判断当前响应者的上一个响应者是谁?
1判断当前响应者是否是控制器的view,如果是上一个响应者就是控制器的view;
2如果不是控制器的view,上一个响应者就是父控件。
一次完整触摸事件的传递相应的过程:
UIApplication,UIWindow,递归找到最适合处理的事件的控件,控件调用
touches方法,判断是否实现touches方法,没有实现默认将事件传递给上一个响应者,找到上一个响应者
响应者链条有什么用?
可以让一个触摸事件发生的时候让多个响应者同时相应该事件

0612
CALayer的基本使用
UIView之所以你显示在屏幕上,完全是因为它内部的图层(CALayer对象)
创建UIView对象时候,UIView内部会自动创建一个图层
如果
CALayer是定义在QuartzCore框架;可以跨平台。iOS和MAC OS X使用
UIColor,UIImage是定义在UIKit框架;不能,只能在iOS使用
CGImageRef,CGColorRef两种数据类型定义在CoreGraphics框架。可以

UIView可以处理用户的触摸事件,多一种功能,而CALayer不可以。
CALayer性能更高一些。

CALayer的属性:
宽度和高度
位置
描点
背景颜色
形变属性

CALayer的重要属性:position和anchorPoint(锚点)
用来设置CALayer在父层中的位置,以左上角为原点;
锚点绝对CALayer身上的那个点会在position属性所指的位置,以自己的
左上角为原点。

动画:
CAAnimation是所有动画对象的父类,不能直接使用,
CAPropertyAnimation是CAAnimation的子类,也是抽象类,要想创建动画对象,使用它的两个子类
:CABasicAnimation(从一个数值变到另一个数值)和CAKeyframeAnimation(使用一个NSArray保存这些数值)
CAAnimationGroup也是CAAnimation的子类,可以保存一组动画效果。
CATransition也是CAAnimation的子类,用于做专场动画,提供移出屏幕和移入屏幕的动画效果

UIView动画:首尾式动画
block式动画
UIImageView的帧动画

*******创建核心动画(Core Animation)
1.1告诉系统执行什么动画;
1.2保存执行之后的状态
1.2.1执行之后不删除动画
1.2.2执行总监保存最新的状态
1.3设置动画时间
2添加核心动画
3设置动画类型
4平移,缩放,旋转
***关键帧动画:CAKeyframeAnimation
***转场动画:CATransitionCA
***组动画:AnimationGroup

0620
真机调试:
必须购买苹果开发者账号。个人:99美元,可以进行真机调试,将开发好的程序发布APPStore
发布到APPStore会进行最少一个礼拜的应用程序审核
企业:299美元可以真机调试,不能把开发好的程序发布APPStore,直接将打开好的程序发布到网站上(非苹果网站)

真机调试的主要步骤:
1登陆开发者主页
>1.1登录开发者主页
http://developer.apple.com/membercenter/index.action
>1.2管理证书(前提:得花99¥或299¥加入开发者计划)

2生成cer证书:cer是一个跟电脑相关联的证书文件,让电脑具备真机调试的功能
》2.1添加cer证书
》2.2利用钥匙串生成cer签名请求文件
》2.3选择cer签名请求文件,生成并且下载cer证书

3添加APP ID:调试哪些app?
》3.1添加App ID
》3.2App ID的描述和所调试应用的Bundle ID

4注册真机设备:哪台设备需要做真机调试?
>4.1添加真机设备
》4.2利用Xcode查看真机设备的唯一标识(插上USB数据线)
》4.3填写设备名称和唯一标识

5生成MobileProvision文件:结合2,3,4生成一个手机规定文件
》5.1添加MobileProvision文件
》5.2选择App ID
>5.3选择cer证书
》5.4选择真机设备
》5.5填写MobileProvision文件名
》5.6下载MobileProvision文件

6导入cer,MobileProvision文件
苹果网站:developer.apple.com\cn
》6.1最终会得到2个文件:
cer文件:让电脑具备真机调试的功能
MobileProvision文件:哪台设备,哪些APP,哪台电脑需要做真机测试?
》6.2双击导入cer文件(可以打开钥匙串确认证书是否有效)
》6.3双击导入MobileProvision文件(打开Xcode,链接好真机)
》6.4打开任意程序,选择真机设别,点击运行

7替换旧的调试证书
有时候需要把项目里面配置的旧调试证书换掉

0623/0624
多线程:
进程含义:系统中正在运行的一个应用程序
每个进程都是独立的,互不干扰。
(通过活动监视器可以查看Mac系统所开启的进程)
线程的含义:1个进程要想执行任务,必须得有线程
线程是进程的基本执行单元,一个进程(程序)所有任务都在线程中执行
线程的串行:1个线程中任务的执行是串行的,按顺序一个一个的执行多项任务
同一时间内,1个线程只能执行1个任务。
多线程的含义:1个进程可以开启多条线程每条线程可以并行(同时)执行不同的任务
(进程相当于车间;线程相当于车间工人)

多线程的原理:
1同一时间,CPU只能处理1条线程,只要1条线程在工作
2多线程并发(同时)执行,其实是CPU快速的在多线程之间调度(切换)
3如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象
思考:如果线程非常非常多,会发生什么情况?
CPU在N多线程之间调度,CPU会累死,消耗大量的CPU资源
每条线程被调度在的频次会降低,线程执行效率降低
多线程的优缺点:
能适当提高程序的执行效率;能适当提高资源利用率。
缺点:开启线程需要占用一定的内存的空间;
线程越多,CPU在调度线程上的开销就越大;
程序设计更加复杂:比如线程之间的通信,多线程的数据共享

多线程在ios开发中的应用:
什么是主线程:(UI线程)一个IOS程序运行之后,默认会开启1条线程,成为主线程或者UI线程
主线程的作用:
1显示或者刷新UI界面;
2处理UI事件;
主线程的使用注意:别将比较耗时的操作放到主线程中
//获得当前线程
NSThread current = [NSThread currentThread] ;
耗时操作的执行:将耗时操作放在子线程,后台线程,非主线程

iOS中多线程的实现方案:
pthread (posix):是一套适用的多线程的API,适用于Unix,Linux,Window等系统,跨平台,可移植,使用难度大
线程生命周期是程序员管理,几乎不使用,C语言
NSThread:更加面向对象,简单易用,可直接操作线程对象,OC语言。偶尔使用,程序员管理生命周期
GCD:替代NSThread等线程技术,充分利用设备的多核,C语言,经常使用,自动管理生命周期
NSOperation:基于GCD,比GCD多了一些更简单实用功能,使用面向对象,OC语言,经常使用,自动管理生命周期

NSThread:
一个NSThread对象就代表一条线程
1创建线程(先创建后启动):
NSThread *thread = [NSThread alloc ]initWithTarget:self selector:@selector(run) object:nil];
线程启动:[thread start];
线程一启动,就会在线程thread中执行self的run方法

其他创建线程的方式:(优缺点)
//创建线程后自动启动线程
[NSThread detachNewThreadSelector:@selector (run) toTarget:self withObject:nil];
//隐式创建并启动线程
[self performSelectorInBackground:@selector(run) withObject:nil];

主线程的相关用法:
+(NSThread *)mainThread;
-(BOOL)isMainThread;
+(BOOL)isMainThread;

线程的调度优先级:
+(double)threadPriority;
+(BOOL)setThreadPriority:(double)p;
-(double)threadPriority;
-(BOOL)setThreadPriority:(double)p;
调度优先级取值范围是0.0~1.0,默认0.5,值越大,优先级越高。
线程的名字:
-(void)setName:(NSString *)n;
-(NSString *)name;

线程的状态:
新建—start—>就绪—CPU调度当前线程或者CPU调度其他线程—>运行
——>阻塞(还有死亡状态)——>就绪

控制线程状态:
启动线程;
-(void)start;

阻塞线程;
+(void)sleepUntilDate:(NSDate *)date;
+(void)sleepForTimeInterval:(NSTimeInterval)ti;

强制停止线程(exit)一旦线程死亡了就不能再次开启任务
+(void)exit;

多线程的安全隐患:
1 1块资源可能被多个线程共享,发生数据错乱

多线程安全隐患解决:互斥锁(使用前提多条线程抢夺同一块资源)
互斥锁使用格式:
@synchronized(锁对象){//需要锁定的代码}

互斥锁的优缺点:能有效防止因线程抢夺资源造成的数据安全问题;
需要消耗大量 的CPU资源

相关专业术语:线程同步。意思是多条线程按顺序的执行任务,互斥锁就是使用了线程同步技术

原子和非原子属性:
1 atomic,原子属性,为setter方法加锁;
加锁原理:
@property(assign,atomic)int age;
-(void)setAge:(int)age
{
@synchronized(self){
_age = age;
}

}
2 nonatomic,非原子属性,不会为setter方法枷锁

原子和非原子属性非选择:
atomic。线程安全,需要消耗大量资源;
nonatomic,非线程安全,适合内存小的移动设备

iOS开发建议:
1所有属性都声明为nonatomic
2尽量避免多线程抢夺同一块资源
3尽量将加锁,资源抢夺的业务逻辑交给服务端处理,减少移动客户端的压力

线程间的通信:
在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信
体现:
1个线程传递数据给另外1个线程;
在1个线程中执行完待定任务后,转到另外一个线程继续执行任务

线程间通信常用方法:

-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

-(void)performSelector:(SEL)aSelector OnThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

在子线程中通过联网下载图片,然后回到主线程显示图片
通信交互过程:主线程(添加UIImageview,显示图片),
子线程(下载图片,下载完毕)

下载图片的方法:在本地应用图片下载是:UIImage *image = [UIImage imageNamed:@“”];
从网络上的图片下载:UIImage *image = [[UIImage imageWithData:(NSData *)];

2GCD:
Grand Central Dispatch,译为牛逼的中枢调度器
纯C语言,提供非常强大的函数

优势:1是苹果公司为多核的并行运算提出的解决方案
2自动利用更多的CPU内核
3自动管理线程的生命周期
4程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

GCD的核心和概念:任务和队列
任务:执行什么操作
队列:用来存放任务

GCD使用就2个步骤:
1 定制任务;
2 将任务添加到队列中
遵循FIFO原则:先进先出,后进后出

有2个函数执行任务:
同步方式:
dispatch_sync( dispatch_queue_t queue , dispatch_block_t block);两个参数
queue:队列;
block:任务

异步方式:
dispatch_async( dispatch_queue_t queue , dispatch_block_t block);两个参数

区别:
同步:在当前线程中;
异步:在另外一条线程中

GCD队列的类型:
1并发队列 让多个任务并发执行,并发功能只有在异步才能执行
2串行队列 让任务一个接着一个执行

注意:同步和异步决定了要不要开启新线程
同步:在当前线程执行任务,不具备开启新线程的能力
异步:在新的线程执行任务,具备开启新线程的能力

并发和串行决定了任务的执行方式:
并发:多个任务并发同时执行
串行:一个任务执行完毕,再执行下一个任务

并发队列:
//获得全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT,//队列的优先级
0);

串行队列:2种途径
1使用dispatch_queue_create函数创建
2使用主队列
dispatch_queue_t queue = dispatch_get_main_queue();

线程间通信实例:(异步并发队列中通信)
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//执行耗时的异步操作。。
dispatch_async( dispatch_get_main_queue(),^{
//回到主线程,执行UI刷新操作

});

});

延时执行:
2种方式
1调用NSObject方法

[self performSelector:@selector(run) withObject:nil afterDelay:2.0];

2使用GCD函数

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2.0 *
NSEC_PER_SEC)),dispatch_get_main_queue(),^{

//2秒后异步执行这里的代码

})

一次性代码:
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
//只执行1次的代码

})

//使用异步函数往并发队列中添加任务,开启多条线程
//使用异步函数往串行队列中添加任务,开启1条线程

//使用同步函数往并发队列中添加任务,不会开启新线程
//使用同步函数往串行队列中添加任务,不会开启新线程

注意:凡是函数各种带有create,copy,new,retain等字眼,都需要进行release
GCD的数据类型在ARC环境下不需要再做release
CF(core Foundation)的数据类型在ARC环境下还要进行release
******主队列是GCD自带的一种特殊的串行队列,任务放主线程执行,不管是放在同步还是异步都不会开启新的线程
主队列使用同步函数任务无法执行。

GCD其他用法队列组:
有这么一种需求:首先分别异步执行2个耗时的操作,其次等2各异步操作都执行完毕再回到主线程执行操作
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
^{

//执行1个耗时的异步操作

});

dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
^{
//执行1个耗时的异步操作

});
dispatch_group_notify(group,dispatch_get_main_queue(),^{

//回到主线程执行操作

});

单例模式(保证这个类永远只有一个对象):ARC和非ARC的实现
设计模式:多年软件开发,总结出来的一套经验、方法、工具
永远只放一次内存,alloc负责分配内存
好处:方便控制实例个数,节约系统资源

宏是放在头文件里面的
可以使用宏判断是否为ARC环境:(兼容)
#if __has_feature(objc_arc)
//ARC
#else
//MRC
#endif

在ARC中这样写单例模式:定义一个类,AudioTool
在.h中写一个方法:
+(instancetype)shareAudioTool;

//在.m中保留一个全局的static的实例
定义全局变量(整个程序运行过程,只有1份)
static id _instance;

//初始化,加载资源一次
-(id)init
{
if(self = [super init]){
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
//加载资源

});

return self;
}

重写控制内存方法,创建唯一的实例:alloc分配内存1次
+(id)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{

_instance = [super allocWithZone:zone];

});

return _instance;
}

提供一个类方法让外界访问唯一的实例:
+(instancetype)sharedAudioTool
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
_instance = [[self alloc]init];

});

return _instance;
}

//实现copyWithZone:方法

+(id)copyWithZone:(struct _NSZone *)zone
{
return _instance;//返回对象,不能返回类如self

}

非ARC这样写单例模式的代码:
和上面一样只是多了一些方法:
//实现内存管理方法:
-(oneway void)release{}//用在MAC上,分布式对象
-(id)autorelease{return _instance;}
-(id)retain{return _instance;}
-(NSUInteger)retainCount{return 1;}

单例模式的作用:保证程序运行过一个类只有一个实例,该实例易于供外界访问
方便控制实例个数,节约系统资源
使用场合:在整个应用程序,共享一份资源
单例模式在ARC和MRC环境写法不同,需要编写2套不同的代码

3NSOperation基本使用:
作用:配合NSOperation和NSOperationQueue也能实现多项线程编程
具体步骤:
1将需要执行的操作封装到一个NSOperation对象
2将NSOperation对象添加到NSOperationQueue中
3系统会自动将NSOperationQueue中的NSOperation取出来
4将取出的NSOperation封装的操作放到一条新线程中执行

NSOperation的子类:
NSOperation是个抽象类。并不具备封装操作的能力,必须使用它的子类
子类方式有3种:
1NSInvocationOperation
2NSBlockOperation
3自定义子类继承NSOperation,实现内部相应的方法

1NSInvocationOperation:
//创建NSInvocationOperation对象
-(id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
//调用start方法开始执行操作
-(void)start;
注意:调用start方法不会开启新线程执行操作,而是在当前线程同步执行操作
只有将NSOperation放到一个NSOperationQueue才会异步执行操作

2NSBlockOperation
//创建NSBlockOperation对象
+(id)blockOperationWithBlock:(void(^)(void))block;
//通过addExecutionBlock:方法添加更多的操作
-(void)addExecutionBlock:(void(^)(void))block;
注意:只要NSBlockOperation封装的操作数>1,就会异步执行操作

3NSOperation
NSOperation可以调用start方法来执行任务,但是默认是同步执行。如果将NSOperation添加到NSOperationQueue中,系统会自动异步执行。
添加操作到NSOperationQueue中:
-(void)addOperation:(NSOperation *)op;

-(void)addOperationWithBlock:(void (^)(void))block;

最大并发数:
同时执行的任务数
相关方法:
-(NSInteger)maxConcurrentOperationCount;
-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;

队列的取消,暂停,恢复
//取消队列的所有操作
-(void)cancelAllOperation;
//暂停和恢复队列:
-(void)setSuspended:(BOOL)b;
-(BOOL)isSuspended;//YES代表暂停,NO代表恢复

操作优先级:
改变操作的执行顺序
-(NSOperationQueuePriority)queuePriority;
-(void)setQueuePriority:(NSOperationQueuePriority)p;

操作依赖:设置依赖来保证执行顺序
可以在不同的队列的NSOperation之间创建依赖关系,不能相互依赖
操作的监听:
自定义NSOperation:
自定义NSOperation下载图片思路:
图片的URL:http://abc.png

怎么保证一个URL图片不重复下载?
SDWebImage框架用来下载图片,下载一个dng文件搜索WDWebImage这个框架
如果公司做的项目需要下载图片的话可以下载SDWebImage框架来使用
重点掌握NSOperationQueue;设置依赖;最大并发数设置;自定义NSOperation的基本流程

自定义NSOperation:
1重写=(void)main方法,在里面实现想执行的任务
注意:自己要创建自动释放池,如果是异步操作,无法访问主线程的自动释放池,通过-(BOOL)isCanceled方法检测操作释放被取消,对取消做出响应

总结多线程:
多线程
1.NSThread
1> 开线程的几种方式
* 先创建,后启动
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];

* 直接启动
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
[self performSelectorInBackground:@selector(run) withObject:nil];

2> 其他用法
NSThread *current = [NSThread currentThread];
+ (NSThread *)mainThread; // 获得主线程

3> 线程间通信
performSelectorOnMainThread.....

2.GCD(重点)
1> 队列的类型
* 并发队列
获得全局的并发队列: dispatch_get_global_queue

* 串行队列
a.自己创建
dispatch_queue_create

b.主队列
dispatch_get_main_queue

2> 执行任务的方法类型
* 同步(sync)执行
* 异步(async)执行

3> 了解队列和方法的配合使用

4> 线程间通信
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行耗时的异步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执行UI刷新操作
});
});

5> 其他用法
dispatch_once
dispatch_after
dispatch_group_async\dispatch_group_notify

3.NSOperation
1> 基本使用
NSInvocationOperation
NSBlockOperation

2> NSOperationQueue(重点)
* 最大并发数设置
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

* 设置依赖(面试题)
[operationB addDependency:operationA]; // 操作B依赖于操作A

3> 自定义Operation(了解基本流程)

4> 如何解决一张图片(一个url)重复下载的问题(面试题)

0626-0701
网络编程:
必须掌握的基本概念:
1客户端(移动应用)Client

2服务器(后端)server

3请求 request

4响应 response

服务器:
分为远程服务器(外网正式服务器)如:www.baidu.com(访问的是外网的服务器)
使用阶段:应用上线后使用的服务器
使用人群:供全体用户使用
速度:服务器性能,用户的网速

本地服务器(也叫内网,测试服务器)
使用阶段:应用处于开发测试阶段
使用人群:供公司内部开发人员,测试人员使用
速度:局域网,速度飞快

访问本地服务器的主机地址:3种写法
127.0.0.1:每一台机器内置的IP地址,机器本身(也是网卡IP地址)所有电脑和手机都有这个IP地址
localhost:等价于第一种情况
交换机\路由器的IP地址192.168.5.102:真机测试一定使用,而且真机和服务器都得在同一个局域网

如何访问本地服务器?
IP地址+端口+资源路径
如:192.168.5.102:8080/MJServer/
服务器的用处:提供登录接口;提供资源

URL:Uniform Resource Locator统一资源定位符
通过1个URL,能找到互联网唯一的1个资源,URL就是资源的地址,位置

URL的基本格式 = 协议://主机地址(huo域名)/路径
如:http://ios.itcast.cn/ios/images/contenet_25.jpg
http://www.baidu.com/img/bdlogo.gif

URL常见协议:协议不一样,访问资源的方式就不一样
HTTP 超文本传输协议(什么东西都可以访问) 最常用访问远程网络资源,格式http://
File 访问本地计算机上的资源,格式:File://(不加主机地址)
mailTo访问电子邮件地址 格式是mailTo:
FTP访问共享主机的文件资源,格式是ftp://

HTTP协议的作用:遵守HTTP协议
1全称是Hypertet transfer Protocol,超文本传输协议
规定客户端和服务器之间的数据传输格式
让客户端和服务器能有效地进行数据沟通
HTTP的特点:简单快速;灵活;使用非连续

HTTP的完整通信过程:
1请求:客户端向服务器索要数据
2响应:服务器返回客户端相应的数据

****HTTP的通信过程——请求
请求:客户端向服务器索要数据

HTTP协议规定:客户端向服务器请求需要包含以下内容:
请求行:包含请求方法,请求资源路径,HTTP协议版本 如GET/MJServer/resource/images/1.jpg HTTP/1.1
请求头:包含对客户端的环境描述,客户端请求的主机地址等信息如下
Host:客户端想访问的服务器主机地址如192.168.1.105:8080
User-Agent:客户端类型,软件环境(pc端还是移动端?)
Accept:客户端接收的数据类型 text/html,*/*
Accept-language:客户端语言环境 zh-cn
Accept-Encoding:客户端支持的数据压缩格式 gzip
请求体:客户端发给服务器的具体数据 比如文件数据

*****HTTP的通信过程——响应
响应:服务器返回客户端相应的数据

HTTP协议规定,1个完整的HTTP响应包含以下内容:
状态行:包含了HTTP协议版本,状态码,状态英文名称 HTTP/1.1 200 OK
响应头:包含了对服务器的描述,对返回数据的描述
server:服务器的类型 Apache-Coyote/1.1
content-Type:返回数据的类型 image/jpeg
content-Length:返回数据的长度 56811字节
Date:响应的时间 Mon,23 Jun 2014 12:54:52 GMT
实体内容:服务器返回客户端的具体数据 比如文件数据

HTTP通信过程:

请求行,请求头,请求体
客户端 ————————————> 服务器
<———————————
状态行,响应头,实体内容

常见响应状态码:
200:OK 请求成功
400:Bad Request 客户端请求语法错误,服务器无法解析
404:Not Found 服务器无法根据客户端的请求找到资源
500:Internal Server Error 服务器内部错误,无法完成请求

发送HTTP请求的方法有8种:GET(查),POST(改),PUT(增),DELETE(删)。。。。。

GET和POST对比:
区别在数据传递上
GET:在请求URL后面以?的形式跟上发给服务器的参数,多个参数之间用&隔开
POST:发给服务器的参数全部放在请求体中

GET和POST的选择:
如果要传输大量数据,比如文件上传,只能用POST请求
GET的安全性比POST差些,如果包含机密或者敏感信息,用POST
如果仅仅是索取数据(数据查询)用GET
如果是增加,修改,删除数据,用POST

iOS中发送HTTP请求的方案:
1NSURLConnection
2NSURLSession
3CFNetwork
4第三方框架:ASIHttpRequest(已经停止更新);AFNetworking
ASI和AFN架构对比:ASI性能比较好

NSURLConnection常用类:
(NSURLConnection-GET请求:请求行,请求头,没有请求体,由于苹果帮我们弄好了前两者,所所以我们只要写URL)
NSURL:请求地址
NSURLRequest:代表一个请求
NSURLConnection:负责发送请求,建立客户端和服务器的链接
发送NSURLrequest的数据给服务器,并收集来自服务器的响应数据

NSURLConnection的使用步骤:
1创建NSURL对象,设置请求路径
2传入NSURL创建一个NSURLRequest对象,设置请求头和请求体(iOS中的请求头和请求体一般不用设置,苹果原生自带)
3使用NSURLConnection发送NSURLRequest

NSURLConnection发送请求:
同步请求(一直在等服务器给数据,在当前线程也就是主线程)不建议使用
+(NSData *)sendSynchronousRequest:(NSURLRequest *)request
returningResponse:(NSURLResponse **)response error:(NSError **)error;

异步请求分为2种:
block回调//当请求结束时候调用(请求超时/请求失败)
+(void)sendSynchronousRequest:(NSURLRequest *)request
queue:(NSOperationQueue*)queue
completionHandler:(void(^)(NSURLResponse* response,NSData*data,NSError* connectionError))
handler;

代理:
-(id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate;
+(NSURLConnection*)connectionWithRequest:(NSURLRequest*)request delegate:(id)delegate;
-(id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately;
-(void)start;//异步请求
称为NSURLConnection的代理,遵守NSURLConnectionDataDelegate协议

NSURLConnectionDelegate:(遵守协议,还要实现4种办法)
//开始接收到服务器响应时调用 初始化数据
-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response;
//接收到服务器返回 的数据时调用 收集数据
-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data;

//服务器返回的数据完全接收完毕后调用 处理服务器所有数据
-(void)connectionDidFinishLoading:(NSURLConnection*)connection;
//请求出错时调用 请求超时/断网/网速慢
-(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error;

NSMutableURLRequest:
常用设置有:timeoutInterval 请求超时等待时间
-(void)setTimeoutInterval:(NSTimeInterval)seconds;
HTTPMethod 请求方法
-(void)setHTTPMethod:(NSString*)method;
HTTPBody 请求体
-(void)setHTTPBody:(NSData*)data;
设置请求头
-(void)setValue:(NSString*)value forHTTPHeaderField:(NSString*)field;

创建GET和POST请求
创建GET请求

NSString *urlStr = [NSString stringWithFormat:@“http://192.168.1.102:8080/MJServer/login?username=123&pwd=123”,username,pwd];
NSURL *url = [NSURL urlWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//发送请求(异步请求)

创建POST请求
//设置请求路径
NSString *urlStr = [@“http://192.168.1.102:8080/MJServer/login“;
NSURL *url = [NSURL urlWithString:urlStr];
//创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @“POST”;
//请求体
NSString *bodyStr = @“username=123&pwd=123”;
request.HTTPBody = [bodyStr dataUsingEncoding:NSUTF8StringEncoding];

提交用户的隐私数据
一定要使用post请求提交用户的隐私数据;GET请求的所有参数都之直接暴露在URL中

数据安全:post请求提交用户的隐私数据还不能完全解决安全问题
可以利用Charles设置代理服务器软件,拦截网络请求,利用Charles能得知大部分公司APP数据来源和数据格式
下载地址:http://www.charlesproxy.com/download
提交用户的隐私数据用暗文
常见的加密算法:
MD5\SHA\DES\3DES\RC2和RC4\RSA\IDEA\DSA\AES

MD5:Message Digest Algorithm5,译为消息摘要算法第5版
对输入信息生成唯一的128位散列值(32个字符串)
MD5特点:根据输出值不能得出原始明文,其过程是不可逆的
输入两个不同的明文不会得到相同的输出值
应用:MD5解密网站:http://www.cmd5.com
MD5已经不再是绝对安全了,要稍微改进
MD5改进:
加盐,就是在密码加一字符串
先加先加密,后乱序

JSON和XML(服务器为什么返回JSON,是为了规范)
JSON是一种数据格式,用于用户交互
一般服务器返回客户端的数据,一般是JSN格式或者XML格式
NSJSON解析方案:有四种
JSONKit;第三方框架(性能好)
SBJSON;第三方框架(性能较好)
TouchJSON;第三方框架(性能差)
苹果原生:NSJSONSerialization(性能最好)用这个
NSJSONSerialization常见方法
JSON数据转换OC对象
+(id)JSONObjectWithData:(NSData*)data options:(NSJSONReadingOptions)opt error:(NSError*)error;

//OC对象转换JSON数据
+(NSData*)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError*)error;

XML格式:
Extensible Markup Language 译为可扩展标记语言
跟JSON一样,也是常用的一种用于交互的数据格式
一般叫XML文档(XML Document)
XML语法:
组成部分:文档声明;元素(Element),包含开始标签和结束标签;属性(Attribute)
同一份数据,既可以用JSON来表示;也可以用XML来表示
JSON体积小于XML。

XML的解析
XML的解析方式:
DOM:一次性将整个XML文档加载进内存,适合解析小文件
SAX:从根元素开始,按顺序一个元素一个元素往下解析,适合解析大文件

iOS中XML解析手段:
苹果原生
1NSXMLParser:SAX方式解析使用简单;
第三方框架:
2libxml2:纯C语言,默认包含在iOS SDK中国,同时支持DOM和SAX方式解析
3GDataXML:DOM方式解析,由google开发,基于libxml2,需要做配置:1导入libxml2库 2设置libxml2的头文件搜索路径
GDataXML的使用:
GDataXMLDocument:代表整个文档
GDataXMLElement:代表文档中的每个元素

XML解析方式的选择建议:
大文件:NSXMLParser,libxml2
小文件:GDataXML

文件上传下载:
小文件下载:
1直接用NSData的+(id)dataWithContentsOfURL:(NSURL*)url;

2利用NSURLConnection发送一个HTTP请求下载
3如果是下载图片,可以利用SDWebImage框架

网络编程总结:
HTTP协议
1.面试题: 聊一下HTTP协议(协议的完整的通信过程)

2.通信过程
1> 请求
* 客户端 --> 服务器
* 请求的内容
a. 请求行(请求方法\HTTP协议\请求资源路径)
b. 请求头(描述客户端的信息)
c. 请求体(POST请求才需要有, 存放具体数据)

2> 响应
* 服务器 --> 客户端
* 响应的内容
a. 状态行(响应行, 状态码)
b. 响应头(服务器信息, 返回数据的类型, 返回数据的长度)
c. 实体内容(响应体, 返回给客户端的具体内容)

3.HTTP请求的方法
1> GET(不需要请求体)
* 参数都拼接在URL后面
* 参数有限制

2> POST
* 参数都在请求体
* 参数没有限制

4.iOS中发送GET\POST请求的手段
1> NSURLConnection
* 发送一个同步请求
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;

* 发送一个异步请求
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
queue:(NSOperationQueue*) queue
completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler;

* 代理的方法(异步)
[NSURLConnection connectionWithRequest:request delegate:self];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];

NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[conn start];

ASI和AFN的区别:
1性能
ASI基于底层的CFNetwork框架
AFN基于NSURLConnection
运行性能:ASI>AFN
2处理服务器数据
1>AFN
根据服务器返回数据进行自动解析
*服务器返回的是JSON数据,自动转换为NSDictionary或NSArray
*服务器返回的是XML数据,自动转换为NSXMLParser

2>ASI
并没有对服务器数据进行解析,直接返回NSData二进制数据

3处理请求过程
AFN:success和failure两个block
ASI:有三种方式处理请求过程(代理、SEL、block)

ASI的特色:
1缓存
2下载和上传
*轻松监听请求进度
*轻松实现断点下载
3提供很多扩展接口(比如做数据压缩)
*ASIDataCompressor.h
*ASIDataDecompressor.h
4ASIHttPRequest继承自NSOperation
*能用队列统一管理所有请求
*请求之间能依赖
5ASINetworkQueue
*统一管理所有请求
*监听所有请求的开始或失败或完毕
AFN的特色:
1使用简单
2自带网络监控功能

643055886@qq.com
ios4762450

*****新浪微博
一项目之大,从哪里开始做起?
1项目组
》移动开发组(移动iOS和安卓)
》服务器(web)开发组(我发什么给你,你传什么给我?)
移动开发组———接口文档(沟通)———服务器开发组
》产品需求组
》测试组
》美工组
2项目文档
》需求文档
》接口文档
》开发文档
》产品文档
3项目架构
》UI界面层
》业务类层
》网络处理层
》工具类层
4分配任务
》按照功能和模块来分
》按照项目架构的层次分
二、项目里面的用户微博数据从何而来?
新浪的开发数据
》新浪已经开发了用户的部分数据
》新浪已经向开发者提供数据接口
》开发者微博客户端发送HTTP请求到新浪的服务器,即可获得数据
三、项目里面的UI素材从何而来?
》正规的公司里面都会有专业的美工来切图
》如果没有美工切图,可以暂用别人项目的素材
》从网上下载新浪的ipa安装包
》解压ipa包,取出里面的UI素材
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: