object


重点知识
Engadget(瘾科技)
StackOverFlow(栈溢出)
Code4Apprespon
魏先宇的程序人生
第一周
快捷键: Alt+上方向键 跳到最上面  Alt+下方向键 跳到最下面
        Alt+左方向键 跳到最左面   Alt+右方向键 跳到最右面
        Alt+shift+方向键  可以批量复制内容,在按方向键可以删除行
        command+鼠标  纵向复制内容
userInteractionEnabled  控件的交互性;
类的三大特性 :工程名:首字母一定要大写,如果名字包含多个单词,则每个单词的首字母都要大写。
方法名:  命名规则和属性名(变量名)相同,第一个单词的首字母小写,以后的每个单词的首字母都要大写。

#import<>  #import关键字,导入工具   <> 代表导入是系统的工具类的头文件    “” 代表导入的是自己的类的头文件

@"" 代表OC中的字符串

逻辑运算 &(与) |(或) !(非)
&& 并且   || 或者   ! 非 !YES = NO  !NO = YES

对于c的函数,非void类型都要使用return return后面的代码都不再执行
Control reaches end of non-void function
控制到达了非空方法的末尾    表示此方法需要有返回值。必须使用return。


.h  header  头文件   作用只是做类的声明,做属性的声明,不做赋值,做方法的声明,不做实现。  方法分为-实例方法和+类方法。 在类方法中是不允许访问属性(instance variable 实例变量)
.m  main      主文件  实现文件  作用:.h不做了,我来做。 方法的实现和属性的赋值(属性的赋值是放在方法中完成)。
非ARC下)对于一个方法,在.h未声明,但是在.m中已经实现,则仍然可以调用。

执行类中的方法: OC调用方法都使用 [ ]
+(eat)   1 导入People头文件
2 调用+eat方法    [类名  类方法的方法名];
-(eat) 1 导入头文件     
2 创建对象  People *p = [People alloc];
3 对象调用实例方法  [对象名 方法名];

Log 日志     %d  %lld % i  %f
 %@ 对象类型(指针类型)
 NSLog(@"=====%@",p2);   =====<People: 0x100200960>
  %p 输出指针保存的内存地址 pointer 指针   
 NSLog(@"=====%p",p2);   =====0x1002063d0

声明多个参数的方法:
- (int)sum:(int)value1 withSecond:(int)value2;
//方法类型 (返回值类型)方法名部分1(参数1类型)参数1名 方法名部分2(参数2类型)参数2名....


属性用来使用 (设置属性值,获得属性值)
案例:设置一个人的年龄,并且设置之后获得设置后的年龄值。
只能通过方法访问属性值。
对于对象打点调用属性,所调用的set和get的方法的方法名是固定的:age属性: setAge    age
set 和get方法
————————
对象调用set和get方法
————————
set 和get方法
对象名.属性名(代替调用set和get的方法的一种简易写方法)
————————
@property+@synthesize(属性的声明和实现,代替属性set和get方法)
对象名.属性名
————————
同种类型的属性声明可以写在一起,用逗号分隔。
@property float height,weight;
@property int age;
@property bool sex;
@synthesize height,age,sex,weight;
如果类中存在属性的set和get方法,则对属性设置值和获得值时,可以使用两种方式:
1 对象调用set和get方法
2 对象打点调用属性 对象名.属性名
对象打点调用属性的本质调用属性的set和get方法。

在.h中声明的属性变量,在.m中的任何一个方法中都可以使用(+方法除外),这个属性变量一般叫做 全局变量。
全局变量(属性) 局部变量(某个方法中定义的变量)
局部变量会覆盖全局变量(变量名相同)

NSString  字符串类    声明变量 *
默认是nil ,在控制台上输出的是(null),指针指向的地址是0x0.
nil是一个对象指针为空,Nil是一个类指针为空,NULL是基本数据类型为空。
NSString 类型 共有的只有NSString,不共有*。
@property NSString *name,*name1;

内存管理  ARC  Automatic Reference Counting
                                    自动            引用            计数
Xcode 5.x 默认创建工程 支持ARC
关闭ARC: Building Setting ---搜索:auto---Objective-C 把ARC改成NO  /  gar 把ARC改成NO
(非ARC下)在.m中已经实现但在.h中未声明的方法仍然可以调用。

继承的特性:子类继承父类,会继承父类 所有的 属性和方法。

self 本类的对象    super 父类的对象


重写的init方法。
目的:把属性的初始化工作直接写在了init方法中。
自定义的initWithXX方法。
目的:可以对对象的属性进行赋值

强制类型转换 :       (转换后的类型)需要转换的变量
float a = 3.14;    int b  = (int)a
强制类型转换只能转换指针类型,不能转换它的对象类型

People *p = [[People alloc] init];
p完成初始化之后再赋给p,那么这时的指针指向的对象就已经是完成初始化之后的对象。
init方法是完成系统最基本的初始化工作,比如优化内存等。
重写的init方法就能替代多参完成属性赋值的初始化操作。
+alloc  -init  是NSObject的方法    People : NSObject

id OC中的弱类型 强 可以接收任意类型,一般接收对象类型(*)
alloc和init方法返回值类型都是id的原因是这里返回值不能是固定的类型(People*),任何NSObject的子类People调用alloc或init方法时都返回该类的对象,并且使用People类的指针接收。

- (id)init
{
self = [super init];
如果父类初始化成功,则完成 自己的初始化工作。
    if (self)  //    if (self != nil)
    {
 //      initialize code
        age = 18;
        sex = YES;
        [self eat];
    }
  //  最后返回的self ,不仅完成了父类的初始化工作,而且也完成自己的初始化工作。
    return self;
}

设置自己飞机的移动
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    //获得touch事件
    UITouch* touch = [touches anyObject];
    //根据touch事件获得点的坐标
    CGPoint point = [touch locationInView:self.window];
    if (CGRectContainsPoint(myPlane.frame, point))
    {
        myPlane.center = point;
    }
}

让键盘下去的方法:
1.[_loginPassWordTxt addTarget:self action:@selector(keyBoardLeave) forControlEvents:UIControlEventEditingDidEndOnExit]; 下面实现 keyBoLeave 方法时可以什么都不写
2.-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //当前view结束编辑
    [self.view endEditing:YES];
    //当textField失去焦点的时候,键盘也会下去
    3.//[_userNameTxt resignFirstResponder];
}


局部变量的生命周期 从声明开始到方法的结束

for循环语句中    可以定义 static  静态变量  它只会被初始化一次    会保存在内存里面的 静态存储区

i++ i是先使用,后++    ++i  i是先++,后使用


控件 窗口小部件(组件)  手机软件中的按钮,标签等,,
UI  UserInterface   用户接口界面
1.标签 显示文字   2.按钮  点击用于触发事件      
3. 文本框  输入文字        

AppDelegate 应用程序代理类    入口类
入口类中的didFinishLaunching 入口方法 相当于代替了main方法。

CGRect (数据类型)  结构体
typedef(类型定义)    struct   CGRect   CGRect;
typedef  a   b    用b代替a

如果想确定一个控件的位置,要么使用frame,要么使用bounds+center,仅仅设置bounds,那么默认center为(0,0),这样只会显示此控件的1/4(右下半)。

device  真机调试
3.5 inch iPhone4 4s     4 inch iPhone 5 5c 5s SE  4.7 inch iPhone 6 6s  5.5 inch iPhone 6s  6sp
ipad1,2  1024 * 768   9.7寸
ipad3 ,4  2048 * 1536
ipad mini 1024 * 768    7.9寸
ipad mini (retina)2048 * 1536
ipad air (ipad 5) 2048 * 1536 9.7寸

ipad模拟器:      1024*768
iphone 3.5inch   320* 480
iphone 4inch      320*568
iphone 4.7inch   375*667

iphone 5.5inch   540*960


第二周

Lab.textAlignment = NSTextAlignmentCenter;  设置字体居中
TextField.placeholder = @"请输入密码";   设置隐藏编辑字符
TextField.secureTextEntry = YES;   设置是否安全键入
TextField.borderStyle = UITextBorderStyleRoundedRect;  设置边框样式  border  边角
TextField.clearButtonMode = UITextFieldViewModeAlways;      设置清除文本框
[t addTarget:self action:@selector(XX) forControlEvents:UIControlEventEditingDidEndOnExit];    设置return键取消键盘
是否允许剪切    earth.clipsToBounds=YES;
这个值设置长宽高的一半  earth.layer.cornerRadius=20;

字符串判断是否相等  isEqualToString

去掉字符串中的空格和空白
str = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]

返回参数字符串在原字符串中的位置和长度
//返回值是NSRange,类似于CGRect,CGPoint
//NSRange有两个属性,location,length
//location,参数字符串的第一个字符在原字符串中的位置
//length,参数字符串的长度
//如果原字符串不包含参数字符串,返回的NSRange的location的值为NSNotFound
if ([urlString rangeOfString:@"code"].location == NSNotFound) {};

//substringToIndex,截取字符串,从0开始,到index结束
//substringFromIndex,截取字符串,从index开始,到末尾结束
//substringWithRange,截取字符串,从location开始,长度为length
 textView.text = [resultString substringToIndex:10];

#define  宏定义    分为 常量宏  函数宏


IBAction 绑定方法  IBOutlet  关键字 关联对象   (xib中在.h文件中写的)

如果xib文件被修改后 需手动加载xib文件 调用 [ ]initWithNibName:@“”……

获取window的方式
1. UIWindow *window = [UIApplication sharedApplication].keyWindow;
2. AppDelegate * app =[UIApplication sharedApplication].delegate;
UIWindow *window = app.window;
3. NSArray *array = [UIApplication sharedApplication].Windows;
UIWindow *window = [array objectAtIndex : 0 ];
部分可用 self.view.window

字符串拼接来找图片的图片名  (格式化字符串)
NSString* imageName = [NSString stringWithFormat:@"Fire%d.gif",i];
根据图片名找图片放到fire的imageView上  
fire.image = [UIImage imageNamed:imageName];

让定时器方法不再等待第一个时间差   [Timer fire];
暂时关闭定时器  [timer setFireDate:[NSDate distantFuture]];
再开启定时器   [timer setFireDate:[NSDate distantPast]];
永久关闭定时器  [timer invalidate];  timer = nil;

输出一个对象的CGRect , CGPoint ,CGSize :
NSLog(@"%@",NSStringFromCGRect(CGRect rect));
NSLog(@"%@",NSStringFromCGPoint(CGPoint point));
NSLog(@"%@",NSStringFromCGSize(CGSize size));

//输出字节数
    NSLog(@"int---%lu",sizeof(int));
    NSLog(@"long---%lu",sizeof(long));


第三周

开辟线程的两种方法
//开辟分线程的时候,绑定一个方法,让这个方法在分线程里面执行.
[NSThread detachNewThreadSelector:@selector(new) toTarget:self withObject:nil];
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(new) object:nil];     通过alloc 方法开辟线程  需要去调用start方法 [thread start];

解决多个线程同时访问一个数据(类比 多个卖票点同时卖一张火车票),
1.NSLock 加线程锁,  
//    _lock = [[NSLock alloc] init];
//    [_lock lock];
    线程队列执行
//    [_lock unlock];
2,线程同步块  @synchronized(self)

分线程中不能开启 Timer
分线程中不会执行UI的更新,要回到主线程去更新  [self performSelectorOnMainThread:(SEL) withObject:(id) waitUntilDone:(BOOL)];
waitUntilDone:   为yes 让分线程等待,直接去主线程中执行,执行完毕后继续执行当前的分线程
为NO, 分线程执行结束再去执行主线程
当前线程休眠  [NSThread sleepForTimeInterval:(NSTimeInterval)];
[Thread MainThread];       [Thread currentThread];    //判断当前线程是否为主线程,返回值为 BOOL类型    [NSThread isMainThread];

12.31号 :// 获取URL地址上的data 方法 是一个同步的方法
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/e4dde71190ef76c666af095f9e16fdfaaf516741.jpg"]];

//perform 执行, 在主线程中执行一个方法,可以传一个参数给这个方法
// 拿到数据之后 回到主线程刷新UI  分线程不能刷新UI
    [self performSelectorOnMainThread:@selector(setImageViev:) withObject:data waitUntilDone:YES];

3,操作队列:
//用操作队列可以解决线程同步的问题,如果有多个操作的话,每个操作随机先执行,执行完一个操作之后才去执行另外一个操作,不会出现一个数据同时被多个操作访问的情况.
    
    // 创建一个操作 绑定相应的方法,当把操作添加到操作队列中时 操作绑定的方法就会自动执行了
     // 创建一个操作队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
     // 1,系统提供的操作
    // 调用操作
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomeThing) object:nil];
     // 把操作添加到操作队列中
    [queue addOperation:operation1];


设置导航栏标题
第一种
self.title = @"setting";
第二种
self.navigationItem.title = @"1111";
第三种    
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
lab.text = @"111222";
lab.backgroundColor = [UIColor redColor];
self.navigationItem.titleView = lab;

设置导航栏右边按钮选项
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(buttonClick:)];
self.navigationItem.rightBarButtonItems = rightButton ;

跳转到下一个界面
1. SecondViewController *secondVC = [[SecondViewController alloc] init];
  [self.navigationController pushViewController:secondVC animated:YES];
2.模态弹出
 SecondViewController *secondVC = [[SecondViewController alloc] init];
[self.navigationController presentViewController:secondVC animated:YES completion:nil];
(如果使用模态弹出,此时没有导航栏且ViewController 不会被加载到导航控制器中,那么就不能使用pop方法)                  若想返回上一个界面,要使用
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
    //模态弹出的样式( 非全屏 formSheet,pageSheet)
    vc.modalPresentationStyle = UIModalPresentationFormSheet;
        //模态弹出的动画方式
    vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;

返回到上一个界面
[self.navigationController popViewControllerAnimated:YES];
返回到根视图界面
[self.navigationController popToRootViewControllerAnimated:YES];
返回到指定视图界面
(获取导航器中的所有导航控制器)     NSArray *array = self.navigationController.viewControllers;
[self.navigationController popToViewController:[array objectAtIndex:0] animated:YES];

在一个数组中插入数组
NSMutableArray *array1 = [NSMutableArray arrayWithObjects: @"one", @"two", @"three", @"four", nil];
NSArray *newAdditions = [NSArray arrayWithObjects: @"a", @"b", nil];
NSMutableIndexSet *indexes = [NSMutableIndexSet indexSetWithIndex:1];[indexes addIndex:3];
//  indexes   1  3
[array1 insertObjects:newAdditions atIndexes:indexes];
NSLog(@"array: %@", array)
// Output: array: (one, a, two, b, three, four)

 替换多个索引值的对象
(NSIndexSet *) 索引
[arr replaceObjectsAtIndexes:(NSIndexSet *) withObjects:(NSArray *)];


从第二界面回到第一界面时 此时viewdidload方法不再执行,因为视图已经加载过了
此时需要重写viewWillAppear(视图将要显示)
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
     NSLog(@"从第二个页面得到的内容  %@",self.fromSecondText);
//    把第二界面的内容赋值给text1
    text1.text = self.fromSecondText;
}

判断从数组中取的对象是否是( )类型的对象用 iskindOfClass

ScrollView.contentSize (容量大小)
设置水平竖直方向的标示符
scrollView.showsHorizontalScrollIndicator = YES;
scrollView.showsVerticalScrollIndicator = YES;
设置是否可以分页
scrollView.pagingEnabled = YES;
设置是否回弹
scrollView.bounces = YES;
设置偏移量  (向左为正  向右为负)
scrollView.contentOffset = CGPointMake(30, 0);
设置拖动过程中水平或者垂直方向能否被锁定
scrollView.directionalLockEnabled = YES;
设置 scrollView 四个边界的预留空白区域
scrollView.contentInset = UIEdgeInsetsMake(40, 40, 0, 0);
ScrollView中实现图片的缩放
设置它的最大放大比例(长和宽)
  _scrollView.maximumZoomScale = 4;
  _scrollView.minimumZoomScale = 0.25;
 返回需要缩放的 View,这个 View 必须是 scrollview 的子 View,实现了这个方法,scrollview 就可以实现缩放了。  如果使用了 scrollView 的缩放功能,就不能再用它的滑动效果,否则会乱。
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return _imageView;
}
当 scrollView 已经缩放时的回调
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
  //_imageView.center = self.view.center;(缩小的时候可以用)
    if (scrollView.zoomScale<1)
    {
        float width = _scrollView.frame.size.width*(1-scrollView.zoomScale)/2;
        float height = _scrollView.frame.size.height*(1-scrollView.zoomScale)/2;
        scrollView.contentInset = UIEdgeInsetsMake(height, width, 0, 0);
    }
}


PageControl.numberOfPages  设置页数(几个点)
PageControl.currentPage  当前的页数

系统 tabBar的选项
 pay.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemRecents tag:1];
若要给它换图片,用
pay.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"pay" image:[UIImage imageNamed:@"1"] selectedImage:[UIImage imageNamed:@"1"]];
给tabBar 设置多个视图控制器
NSArray *vcArray = @[nav1,nav2,nav3,nav4,five,six];
tabBarController.viewControllers = vcArray;
设置当前选中的索引
tabBarController.selectedIndex = 0;
 1.创建多个视图控制器
 2.创建UITabBarController的实例
 3.把UITabBarController的对象做为根视图添加到window上
 4.将所有的视图控制器添加到tabbar上
 5.设置tabbar中的item

设置样式
toolBar.barStyle = UIBarStyleDefault;
UIBarButtonItem *barButton1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:Nil];
设置BarButtonItem 之间的固定空间
UIBarButtonItem *FixedSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:Nil];
宽度  FixedSpace.width  = 20;  
NSArray *itemArray = @[FixedSpace,barButton2,FixedSpace,barButton3];
[toolBar setItems:itemArray animated:YES];

ActionSheet 中的按钮是从上到下来按顺序设置索引值的
AlertView 中的按钮中“取消”的索引值是0,其他的按顺序设置

若要使用系统的代理方法,要在.h 文件声明类的后面加上<UI XXX Delegate>

第四周

代理
如果一个页面以及上面的内容会在不同的时候出现,此时可以把这个相同的东西封装到一个类当中, 若此页面出现的时候需要调用一些方法,此时为了区分它们,我们可以在封装类的头文件中声明一个 id 类型的对象(delegate),并在@end 下面用@protocol声明此对象的方法(此方法的实现内容在具体出现的页面中实现),让其在需要用的时候调用。
@end
@protocol XXXDelgate <NSObject>
@optional
- (void)myView:(UIView *)myView clickedButtonAtIndex:(NSInteger)buttonIndex;
@end

继承于 UIView的类所创造的对象可以打点调用 hidden 设置为 YES 让其隐藏。

数据源   pickerView.dataSource = self;   有两个必须实现的方法
代理   pickerView.delegate = self;
[pickerView selectedRowInComponent:0]; 获得第0区的第Row行
刷新第一个区  [pickerView reloadComponent:1];
选中第1区的第0行[pickerView selectRow:0 inComponent:1 animated:YES];

#pragma mark  杂注

设置样式
datePicker.datePickerMode = UIDatePickerModeDateAndTime;
获取picker的时间
NSDate *date = picker.date;
创建时间格式化器
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
 设置date的格式
[dateFormatter setDateFormat:@"yyyy-MMMM-dd-EEE-aa"];
把时间转换成字符串
NSString *dateString = [dateFormatter stringFromDate:date];
yy: 年的后2位   yyyy: 完整年  
MM: 月,显示为1-12  MMM: 月,显示为英文月份简写,如Jan  MMMM: 月,显示为英文月份全称,如Janualy
dd: 日,2位数表示,如02  d: 日,1-2位显示,如 2
EEE: 简写星期几,如Sun  EEEE: 全写星期几,如Sunday
aa: 上下午,AM/PM
H: 时,24小时制,0-23
K:时,12小时制,0-11
m: 分,1-2位  mm: 分,2位
s: 秒,1-2位  ss: 秒,2位  S: 毫秒
Z:  时区
常用日期结构:
yyyy-MM-dd HH:mm:ss.SSS
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd
MM dd yyyy    

第五周

获取标题宽度
width = button.titleLabel.frame.size.width;
UIFont *font = [UIFont systemFontOfSize:17];
CGSize size = [@"百度" sizeWithFont:font];

webView  网页视图
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[self.view addSubview:_webView];   
//    创建 链接
NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
//  创建请求
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
//    加载请求
[_webView loadRequest:request];

不能深度赋值
应该这样:CGRect rect = rainImage.frame;
        rect.origin.y = 305;
        rainImage.frame = rect;

如果把 Image 盖在 button 上面,在 image 上点击 button 效果还会被触发,如果是把 View 盖在上面,button 效果不会被触发。

UITableView
设置分割线的颜色 tableView.separatorColor
实现表的数据源方法
下面黄色部分可以相互代替(写在 tableView 的创建后面)
给 tableview 的 ReuseIdentifier 注册一个 cell类,当 tableview 找不到可以重用的 cell 时,就会自动创建一个这种类型的 cell
[_table registerClass:[UITableViewCell class]  forCellReuseIdentifier:@"cell"];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"cell";
    //    在队列中查询有没有可以重用的单元格
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    //    如果没有单元格 就去创建新的单元格
    if (!cell)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    return cell;
}
如果是自定义表加载 xib 时,要用
if (!cell)
    {
        //手动加载xib文件
        NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:Nil options:Nil];
         //强转
        cell = (CustomCell *)[array objectAtIndex:0];
    }

自定义区头后一定要记得设置区头和区尾的高度
// 设置索引标题
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    return _array;
}
// 完成编辑
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    (此方法写上以后向右划定单元格会出现删除按钮,移除单元格的方法也就写在这个方法里面)
}

//设置是否可以移动
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}
//改变数据
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    找到sourceIndexPath所在的位置(区、行)并把它从当前的数组中移除,然后把                                  sourceIndexPath加入到destinationIndexPath所在的位置(区、行),完成操作后一定要刷新表
}
刷新表的两种方法:
1.[_tableView reloadData];
2.  NSIndexSet  索引集合 把将要改变的区加入到索引集合中  NSMutableIndexSet  可变的索引集合
 NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSetWithIndex:section];
[_tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationFade];
第二种方法比较高效
刷新表的时候,表的数据源方法和代理方法都要重新执行一次

Rotation 旋转
顺时针旋转90
Button.transform = CGAffineTransformMakeRotation(M_PI_2);
transform默认为CGAffineTransformIdentity

//    获取最后一行的索引
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_messageArray.count - 1 inSection:0];
//    _tableView滑动
    [_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

//    自适应高度
    CGRect rect = [contentText boundingRectWithSize:CGSizeMake(160, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:17]} context:Nil];

UIImage *old = _whoSay ?[UIImage imageNamed:@"bubbleSelf"]:[UIImage imageNamed:@"bubble"];
UIImage *image = [old stretchableImageWithLeftCapWidth:10 topCapHeight:10];
imageView.image = image;

第六周

NSNumber 能够把基本类型的数据包装成一个对象,此对象可以存进数组。
    _sectionOpenArray = [[NSMutableArray alloc]initWithObjects:[NSNumber numberWithBool:NO], [NSNumber numberWithBool:NO],[NSNumber numberWithBool:NO],nil];
利用 NSNumber 实现 BOOL 值的转换来改变tableView 中区的打开与关闭
[_sectionOpenArray replaceObjectAtIndex:button.tag withObject:[NSNumber numberWithBool:![[_sectionOpenArray objectAtIndex:button.tag] boolValue]]];

设置 alert 的样式,不同样式上面的 textfield 数量和类型不同
    alert.alertViewStyle = UIAlertViewStylePlainTextInput;
    [alert textFieldAtIndex:0].placeholder = @"用户名";

用 alert 在 tableView 中添加一个分组
if (alertView.tag == 100)
   {
      //首先在好友数组中添加一个新的数组,用来存放这个区的好友
      [_friendArray addObject:[NSMutableArray arrayWithCapacity:0]];
      //然后再分组名称数组中添加这个新分组的名字
      NSString *name = [alertView textFieldAtIndex:0].text;
      [_sectionNameArray addObject:name];
      //最后在控制打开关闭的数组中给这个新区添加一个 NSnumber,用来标记它的打开状态
      [_sectionOpenArray addObject:[NSNumber numberWithBool:NO]];
      [_table reloadData];
   }

//从 iOS7 开始,状态栏和 navigationBar 与 viewController 合为一体(ViewController 的 View 左上角从屏幕左上角开始),为了保证 tableview 或者 scrollView 顶部的内容不被 navigationBar 挡住,ViewController回自动给自身上的 scrollerView 顶部添加64的 inset,如果不需要这个 inset,automaticallyAdjustsScrollViewInsets设置为 NO 即可。
    self.automaticallyAdjustsScrollViewInsets = NO;
    _table.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);

    //刷新控制器
    UIRefreshControl *control = [[UIRefreshControl alloc] init];
    //设置菊花颜色
    control.tintColor = [UIColor redColor];
    //设置下拉刷新标题
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"下拉刷新"];
    [str setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:20],NSFontAttributeName,[UIColor redColor],NSForegroundColorAttributeName, nil] range:NSMakeRange(0, 4)];
    control.attributedTitle = str;
    //把刷新控制器和tableViewController结合
    self.refreshControl = control;

    //停止下拉刷新的转动动画
    [self.refreshControl endRefreshing];

为什么要管理内存?
计算机的内存是有限的,如果我们需要使用一个对象,会在内存中创建这个对象,内存使用量就会越来越多,如果只创建,不去释放,那么就会造成内存撑爆。所以,我们在使用一个对象时创建,不再使用这个对象时,要把它释放。

不同语言管理内存的方式
Java:全自动内存管理:Java 运行时,每隔一段时间就会自动检查内存当中的所有对象,当发现不再使用的对象时,就会把这个对象从内存中释放。这个功能叫做 Java 垃圾回收机制。这种内存管理机制使用方便,但是运行效率低。
C++:全手动内存管理:当需要使用一个对象时创建,确定不再使用这个对象时,手动把它释放掉。这种内存管理机制使用麻烦,但是运行效率高。
OC:通过引用计数来管理内存(半自动管理内存):对象的引用计数就是标记当前有多少个其他对象正在使用这个对象。当其他对象需要使用这个对象时,要把这个对象的引用计数加1,当某个其他对象不再使用这个对象时,要把这个对象引用计数减1。一旦某个对象的引用计数为0,那么它就会被系统释放掉。

*全局指针需要在dealloc中release。 *局部指针需要在方法结束前release
super dealloc目的是释放掉父类的全局指针指向的对象。
super dealloc必须写在最后,因为要先释放自己的全局属性,再释放父类的全局属性
通过alloc,new,copy创建出来的对象,引用计数为1 其他的方式创建的对象,都是延迟释放的。   new就相当于alloc+init
retain方法使一个对象引用计数+1    release方法使一个对象引用计数-1
如果一个指针指向了一个对象,那么这个指针指向另外一个对象时,需要先把之前指向的对象release一次。否则就会导致内存泄露。
*引用计数管理原则:谁创建,谁释放,谁使用,谁管理。
alloc的数量+retain的数量=release的数量

把对象放进数组后,数组会对这个对象的引用计数+1
当数组移除某个对象时,这个对象的引用计数-1
当数组将要被释放时,会对这个内部的所有对象release一次。

当一个视图添加到父视图上时,父视图会对这个视图引用计数+1
当一个视图将要被释放时,会对自己的所有子视图release一次。

用buttonWithType创建的button,addSubview之后不需要release

alertView show之后会导致alert引用计数增加。 alertView show之后立刻release

模态弹出一个vc之后,vc的引用计数会增加。  vc模态弹出或者push之后立刻release

*如果property为retain(copy)形式,当打点调用赋值时,会先对之指向的对象release一次,再对新指向的对象retain(copy)一次

对于对象的set方法,需要先对之前的对象release一次,然后对新的对象retain一次

对于全局的timer一般需要在界面消失的时候停止,而不是dealloc中停止,因为timer如果不停止,那么timer的target就不会释放。dealloc就不会执行。
NSTimer只要还在执行,即使引用计数为0,也不会被释放,直到timer停止才可能被释放。

UIImage的imageNamed方法虽然是延迟release的,但是并不会在事件循环结束的时候release。

delegate的property要用assign描述,否则会导致循环引用,最后两个对象都释放不掉

//用storyboard设计的viewController需要用UIStoryboard加载
    UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    ViewController *vc = [board instantiateInitialViewController];

单例类
1、单例类只有一个实例(对象)
2、单例类必须提供一个获得这个唯一实例的方法
3、单例类能够自动创建这个唯一的实例
自定义单例类
static Singleton *__singleton = nil;
+(Singleton *)defaultSingleton{
    
        //为了防止多个线程同时判断单例是否存在,从而导致同时创建单例。判断的时候必须加线程同步。
    @synchronized(self){
        if (!__singleton) {
            __singleton = [[Singleton alloc] init];
        }
    }
    return __singleton;
}
//为了防止人为创建单例类,重写alloc方法。
+ (id)alloc{
        //dispatch_once 的block中的代码当程序运行后只会被执行一次。
        //单例类的创建最好用dispatch_once。
        //使用dispatch_once就不需要再进行判断,也不需要关心线程同步。
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        __singleton = [super alloc];
    });
    return __singleton;
}

通知是 iOS中的一种调用机制,当发送通知时,不需要关心谁来接收,需要接收这个通知的对象需要自己去监听这个通知。
 通知和代理的区别:相同之处,都可以实现回调,都可以传参。不同之处,代理只能一对一调用,而且必须明确代理对象,通知可以实现多对多调用,而且不需要关心通知的接收者;代理的协议方法可以有返回值,但是通知的调用方法不能加返回值。

UIApplication就是单例类,我们使用的时候没有alloc 而是通过sharedApplication找到单例对象[UIApplication sharedApplication]
NSNotificationCenter是单例类。通知中心类似于广播站,发送任何通知都必须通过通知中心发送。
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//字典,也是一种对象的容器,和数组不同的是,数组中的对象按照顺序存储,而字典中的对象按照键值对存储。
NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:color,@"color", nil];
//NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:color,@"color", nil];
//postNotification,发送一个通知
//第一个参数name是发送的通知的名字,用来区分不同的通知。
//第二个参数object是通知的发送者,一般都写self
//第三个参数是通知的参数,用来传参.
[center postNotificationName:@"changeColor" object:self userInfo:dic];

//addObserver添加一个监听者(让某个对象可以接收通知)。
        //第一个参数observer就是添加的监听者,就是让哪个对象去接受通知
        //第二个参数selector当监听者收到通知时调用的方法。
        //第三个参数name,监听的通知名字,只监听哪个通知。
        //第四个参数object,限定通知来源(只接受某个对象发的通知),如果不限定,写成nil
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveChangeColorNotification:) name:@"changeColor" object:nil];

- (void)receiveChangeColorNotification:(NSNotification *)noti
{
//当收到通知时调用方法会传过来一个NSNotification类型的参数,这个参数包含了name,object,和userInfo。
    self.view.backgroundColor = [noti.userInfo objectForKey:@"color"];
}
removeObserver取消所有的通知监听。
*当一个对象将要被释放时,如果这个对象注册有监听通知,那么在释放前(也就是dealloc中)必须取消所有的监听,否则就会导致程序崩溃
[[NSNotificationCenter defaultCenter] removeObserver:self];

- (void)introduceSelf
{
    NSLog(@"%@",self);
}
//description方法用来设置NSLog这个对象时输出的内容。如果不设置,默认输出为内存地址
- (NSString *)description
{
    return [NSString stringWithFormat:@"我叫%@,今年%d岁,性别%@",_name,_age,_sex?@"男":@"女"];
}


//UIApplicationDidEnterBackgroundNotification应用程序已经进入后台的通知。
//UITextFieldTextDidChangeNotification输入框中内容改变时的通知
//UIKeyboardWillChangeFrameNotification键盘的frame将要发生改变的通知
NSValue能够把结构体封装成对象,就可以放入数组或字典。
    NSValue *value = [noti.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
        //获得键盘的坐标
    CGRect rect = [value CGRectValue];
        //获得动画时间
    float duration = [[noti.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
    int curve = [[noti.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];

数据的存储
沙盒:在存储器中一块独立的空间,这个空间中存储了一个应用,以及这个应用的数据,那么这块空间就叫做这个应用的沙盒。
沙盒运行模式:应用程序在运行时,对硬盘的操作权限仅限于自己沙盒内部,不能对沙盒外部的空间进行直接操作。
沙盒内部有4个文件夹, Documents,library,tmp,app  Documents 存储应用的文档文件,对于开发者最常用.      library 存储应用设置或配置的相关信息,也存储一些系统数据,提供给系统使用,一般情况下不在这个文件夹下存储文件.        tmp 临时文件夹,用来存储一些临时文件      app 应用资源文件夹,存储应用所需要的所有资源,此文件夹只能读,不能修改.  

1.使用NSUserDefaults存储数据
    // NSUserDefaults 用户数据存储器,常用来存储和一些用户信息或用户设置有关的一些数据
    // NSUserDefaults 单例类
    NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
    // NSUserDefaults 类似字典,但不是字典,它可以存对象,还可以存基本类型.
    [user setObject:name forKey:@"name"];
    [user setInteger:age forKey:@"age"];
    [user setBool:sex forKey:@"sex"];
    // NSUserDefaults 修改后必须立刻同步一次(存储到硬盘),否则修改无效.
    [user synchronize];
    // NSUserDefaults 中的内容存储在沙盒下 library 文件夹中
从 NSUserDefaults 中读取数据
    NSString *name = [[NSUserDefaults standardUserDefaults] objectForKey:@"name"];
    int age = [[NSUserDefaults standardUserDefaults] integerForKey:@"age"];
    BOOL sex = [[NSUserDefaults standardUserDefaults] boolForKey:@"sex"];
    _name.text = name;
    _age.text = [NSString stringWithFormat:@"%d",age];
    _sexControl.selectedSegmentIndex = sex;

2.使用数组存储数据
    NSArray *array = [[NSArray alloc]initWithObjects:name,_age.text,sex?@"男":@"女", nil];
    //Directory (计算机文件或程序)的目录
    //Appending 附加 添加 贴上   Component 构成 成分  
    //NSHomeDirectory()找到当前应用的沙盒路径。
    //stringByAppendingPathComponent当一个路径后追加路径。
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/abc.xml"];
    //writeToFile 把数据存入文件,第一个参数是路径名,第二个参数是是否原子性(是否使用临时文件存储).
    [array writeToFile:path atomically:NO];
    [array release];
    //文件名的后缀和文件内容没有关系,后缀仅仅是标记了这个文件的类型,也就是这个文件应该用什么工具去打开.
从文件当中读取数组.
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/abc.xml"];
    NSArray *array = [[NSArray alloc]initWithContentsOfFile:path];
    _name.text = [array objectAtIndex:0];
    _age.text = [array objectAtIndex:1];
    _sexControl.selectedSegmentIndex = [[array objectAtIndex:2] isEqualToString:@"男"]?0:1;
//判断某个文件是否存在
[[NSFileManager defaultManager]fileExistsAtPath:directoryPath]

//创建一个文件夹
 [[NSFileManager defaultManager ] createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];

//创建一个文件
[[NSFileManager defaultManager]createFileAtPath:filePath contents:nil attributes:nil];

3.使用字符串拼接存储数据
    NSString *string = [NSString stringWithFormat:@"%@|%@|%@",name,_age.text,sex?@"女":@"男"];
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/string.txt"];
    //把字符串存入文件,第一个参数是存储路径,第二个参数是原子性,第三个参数是编码方式,iOS 的默认编码方式是 UTF8编码,第四个参数是如果写入失败,失败的原因.
    [string writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:nil];
3.
     NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/string.txt"];
    NSString *string  = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    //按照某个字符串分割成一个长字符串,得到一个数组,数组中就是分割成的若干个字符串.
    NSArray *arr = [string componentsSeparatedByString:@"|"];
    _name.text = [arr objectAtIndex:0];
    _age.text = [arr objectAtIndex:1];
    _sexControl.selectedSegmentIndex = [[arr objectAtIndex:2] isEqualToString:@"男"]?0:1;
    [string release];

NSUserDefaults只能存系统自带的数据类,例如NSArray,NSString,int,BOOL等,自定义的类不能存。
NSArray(NSDictionary)只有当存储的对象都是系统自带的数据类时,才可以writeToFile,如果数组中存有自定义类,那么就不能writeToFile.
NSData数据类,存储了一段二进制数据。NSDate可以直接存入文件
    //对于自定义类,如果想存入文件,必须先转化为二进制数据。这个转化的过程叫做对象序列化。
    //只有实现了NSCoding协议,这个类才能被转化为二进制数据
    //NSKeyedArchiver编码器,能够把实现了NSCoding协议的对象编码成二进制数据.
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:p];
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/data.plist"];
    [data writeToFile:path atomically:NO];
从文件中读取NSData
  NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/data.plist"];
  NSData *data = [NSData dataWithContentsOfFile:path];
  //NSKeyedUnarchiver解码器,能够把二进制数据还原成原来的对象。
  People *p = [NSKeyedUnarchiver unarchiveObjectWithData:data];
  _nameField.text = p.name;
  _ageField.text = [NSString stringWithFormat:@"%d",p.age];
  _sexControl.selectedSegmentIndex = p.sex;

实现 NSCoding 协议(先在.h 文件中用<NSCoding>在想要实现的类后追加)
    //编码方法。
- (void)encodeWithCoder:(NSCoder *)aCoder{
        //如果父类也遵守NSCoding协议,需要先调用super encodeWithCoder
        //在编码方法中,把需要编码的数挨个进行编码
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInt:_age forKey:@"age"];
    [aCoder encodeBool:_sex forKey:@"sex"];
}

    //解码方法。
- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
        //在解码方法中,对编码过的属性逐一解码
    if (self) {
        _name = [[aDecoder decodeObjectForKey:@"name"] copy];
        _age = [aDecoder decodeIntForKey:@"age"];
        _sex = [aDecoder decodeBoolForKey:@"sex"];
    }
    return self;
}

指针本身也是个变量,也需要占用内存,所以指针本身也有内存地址。
     // NSString **str;两个星的指针叫做双指针,也就是指向指针的指针(指向指针的内存地址)。
&取地址符,获得一个指针的内存地址
     //NSString **dString = &string;
/方法传参时如果要传递一个指针,那么不能直接写这个指针,因为写成指针实际传递的是这个指针指向的对象,所以如果要传递指针,参数必须写成指向这个指针的指针。

//  NSFileManager  文件管理器,对文件进行删除,移动,复制,剪切等操作。
        //NSFileManager也是单例类
    NSFileManager *manager = [NSFileManager defaultManager];
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/string.txt"];
    NSError *err = nil;
        //删除一个文件,如果删除失败,输出失败的原因
    if (![manager removeItemAtPath:path error:&err]) {
        NSLog(@"%@",err);
    }

/创建文件夹
    NSFileManager *manager = [NSFileManager defaultManager];
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/abc/123"];
        //withIntermediateDirectories是否自动创建路径中不存在的文件夹。
    [manager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];

//查看文件属性
- (IBAction)checkFileAttribute:(UIButton *)sender
{
    NSFileManager *manager = [NSFileManager defaultManager];
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/string.txt"];
    NSDictionary *dic = [manager attributesOfItemAtPath:path error:nil];
    NSLog(@"%@",dic);
}

UIImagePickerController  图片选择器
把图片转化成data的
    NSData *data = UIImageJPEGRepresentation(_imageView.image, 0.5);
//图片可编辑
        controller.allowsEditing = YES;

第七周

//FMDB是对sqlite3的封装,内部使用的也是sqlite3,所以要使用FMDB,需要先导入sqlite3库
//FMDatabase数据库操作类,可以打开或创建一个数据库文件。
    FMDatabase          *_db;
//打开或创建一个数据库文件
    _db = [[FMDatabase alloc]initWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Documents/data.sqlite"]];
    //打开数据库
    [_db open];
    //在这个数据库中创建一张表  executeUpdate 执行一条修改语句
    [_db executeUpdate:@"CREATE TABLE IF NOT EXISTS people(peopleID INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,phone TEXT)"];
    //FMResultSet 结果集,查询出来的数据有可能很多条,所以放在了一个结果集中
    FMResultSet *set = [_db executeQuery:@"SELECT * FROM people"];
    //next 方法前往下一条记录,如果存在下一条记录返回 YES,不存在返回 NO.存在这条记录的话,把此记录封装成 people 对象,装进数组.(通过 while 循环遍历结果集)
    while ([set next])
    {
        People *p = [[People alloc]init];
        p.name = [set stringForColumn:@"name"];
        p.peopleID = [set intForColumn:@"peopleID"];
        p.phone = [set stringForColumn:@"phone"];
        [_array addObject:p];
        [p release];
    }
    [set close];
    //关闭数据库
    [_db close];

//把新添加的人写入数据库
    [_db open];
    //FMDB中 SQL 语句的占位符(?)只能用 NSString 替代,不能用 int
    [_db executeUpdate:@"INSERT INTO people(name,phone)VALUES(?,?)",p.name,p.phone];
    //SELECT MAX(peopleID) 搜索表中最大的peopleID,
    FMResultSet *set = [_db executeQuery:@"SELECT MAX(peopleID) FROM people"];
    [set next];
    int maxID = [set intForColumnIndex:0];
    p.peopleID = maxID;

//执行删除操作时,要先从数据库中删除
    People *p = [_array objectAtIndex:indexPath.row];
    [_db open];
    [_db executeUpdate:@"DELETE FROM people WHERE peopleID=?",[NSString stringWithFormat:@"%d",p.peopleID]];
    [_db close];

/*----这两个方法配套使用,是 UIViewController 的方法*/
- (BOOL)shouldAutorotate{
    return YES;
}
    //设置支持的屏幕方向
- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}
/*----_________________*/

获取屏幕的旋转角度
 UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
设置标签的旋转(到的)角度
 lab.transform = CGAffineTransformMakeRotation( 270 * M_PI/180);

第八周

通讯
是客户端与服务器之间的通信
服务器(客户端):1.安装了服务器(客户端)软件的电脑    2.服务器(客户端)软件

IP 地址:Internet protocol 网络传输协议的逻辑地址
IPv4 地址是由4个  0到255  的数字组成
互联网中一台计算机发出的数据通过 IP 地址才能把数据准确的发送到另外一台计算机

域名,俗称网址,为了方便记忆和输入,进行通信时,不直接使用 IP 地址,而是使用域名.

DNS 服务:域名解析服务,能够把域名解析为 IP 地址

MAC地址:Media Access Control  接入互联网计算机的物理地址或网卡地址 通过物理地址识别主机

端口号: 是计算机与外界通讯交流的出口。   物理接口,协议端口    192.169.0.1:80 冒号后面的就是端口号
在计算机上运行的软件如果需要上网,就必须有一个端口号,用来区分网络返回的数据用于哪个软件。范围0-65535。一些号被特定的使用如:用于网络的80端口,用于FTP服务的21端口。

HTML:Hyper Text Mark-up Language 超文本标记语言,用来设计一个网页,任何网页的实质都是 html 标签对.

URL:唯一资源标识符.(链接地址) 代表一个资源的位置。可以是网络上的,可以是本地的。

http协议: 超文本传输协议
http传输 以报文形式传输,  分为请求报文和响应报文
请求报文分为请求行,请求头,和请求体。  
请求行:请求方式(GET,POST)空格 IP 地址后的url 空格 http 版本
回车         
请求头:contentLength = 0    connection = “close”
回车
回车
请求体:请求内容,可以为空也可以传数据

telnet localhost 8080
GET /MyServer/ HTTP/1.0

Host=localhost
Connection=close   

//把接收到服务器返回的data类型的数据 转换成String类型的数据
NSString *str = [[NSString alloc] initWithData:_buffer encoding:NSUTF8StringEncoding];
    NSLog(@"str  %@",str);

响应报文
1.响应行:HTTP 版本 响应状态码(2XX 正常响应 4XX 异常响应)
GET 请求:把请求的参数写在请求的 url 之后,在 url 最后加?然后后面写参数,参数与参数之间用&分割(url?XXX=XXX&XXX=XXX)
GET请求参数长度受限,而且不安全.

POST 请求:把参数写在请求体中,这种请求方式相对安全.

JSON数据
[]表示数组
{}表示字典

[{name:张三,qq:123,sign:我今年5岁了},{name:李四,qq:333,sign:我捡了100块}]

OAuth 2.0认证过程
1.客户端从新浪微博请求一个认证界面,然后将这个认证界面呈现给用户。
2.用户在认证界面填写完账号密码并点确定时,认证界面会把账号密码直接发送给新浪微博(不通过客户端)。
3.新浪微博验证用户输入的账号密码,如果输入正确,新浪微博回交给客户端一个 code。
4.客户端拿到 code 之后,用 code 去请求 token。
token 就是这个用户的通行证。

在当前时间的基础上加上一个时间
NSDate *date = [[NSDate date] dateByAddingTimeInterval:expires.doubleValue]

//dateWithTimeIntervalSinceNow
//于现在相隔多少秒的一个时间
//正数,多少秒后,负数,多少面前
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:[expires intValue]];

比较两个时间的大小 NSOrderedDescending降序 说明前者比后者大
[date compare:nowDate] == NSOrderedDescending

//实现断点下载,首先要获取已经下载的文件的大小。
 NSDictionary *att = [[NSFileManager defaultManager] attributesOfItemAtPath:[self filePath] error:nil];
 unsigned long long size = [att fileSize];
//*当继续下载时,应该告诉服务器,客户端已经下载好了一部分数据,只需要把下载好的数据后面的数据传输过来即可。
//*请求头中Range代表下载的范围,从总数据的第几个字节之后开始下载就写成xx-
[request addValue:[NSString stringWithFormat:@"bytes=%qu-",size] forHTTPHeaderField:@"Range"];

上传文件或图片时,要用到固定的HeaderField   
[request addValue:@"multipart/form-data" forHTTPHeaderField:@"Content-Type"];

//UIImagePNGRepresentation把一个UIImage转成png格式的 NSData。
//UIImageJPEGRepresentation把一个UIImage转成jpg格式的 NSData。
//0.7是压缩比例,把图片压缩后转成DATA
NSData *data =  UIImageJPEGRepresentation(_imageView.image, 0.7);
//把需要上传的数据放入请求体
[request setHTTPBody:data];

unsigned long long size = [att fileSize];
 //告诉服务器上传的文件的大小
 [request addValue:[NSString stringWithFormat:@"%qu",size] forHTTPHeaderField:@"Content-Length"];
 //生成一个文件的输入流
    NSInputStream *stream = [NSInputStream inputStreamWithFileAtPath:path];
 //当上传大文件时,为了节省内存,不直接把所有数据都读入内存,而是使用数据流一点一点读取。
 //设置请求体的输入流
 [request setHTTPBodyStream:stream];

第十周


//自定义类型   在#import 下,@interface 上 定义以后,在本类中后者就可以代替前者使用
typedef int myInt;
typedef NSString String;
//定义一个block类型
typedef int (^myBlock)(int a,int b) ;


//block不能使用局部变量,可以使用全局变量,如果block中需要使用局部变量,需要在定义的变量前+ __block
//局部变量在block中只读。而且,是一次性赋值(把c的值copy到block中,以后c的值改变,并不会影响到block中的c)
//全局变量,__block变量,static变量,在block中引用的话,引用的是变量,而不是变量的值,也就是说,引用之后,变量发生改变的话,block中的值也会发生变化

//如果属于某个对象的block当中又使用到了这个对象,就会造成循环引用(对象和block的循环引用),导致最后对象释放不掉,所以,当属于某个对象的block使用这个对象时,应该再定义一个__block的指针指向这个对象,在block中使用__block指针。
//如果是ARC,用__weak
__block SecondVC *safeSelf = self;
    self.block = ^{
        safeSelf.view.backgroundColor = [UIColor redColor];
    };

//全局的block(在栈内存中的block)需要对block块内局部变量的引用计数+1(块内全局变量不变)。
//某些情况下,不能使block的对象引用计数增加,那么在这个指针前+__block。
__block NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"123", nil];
//局部的 block 块内对象的引用计数均不变
    self.block = ^{
        [array addObject:@"222"];
        [_array addObject:@"222"];
    };

//GCD中使用线程队列实现多线程。
  //我们可以在一个线程队列中加入一段代码,线程队列就会执行这个段代码。
  //dispatch_queue_t 线程队列,
  //dispatch_queue_create函数,创建一个新的线程队列,其中第一个参数是线程队列的标签(名字)。第二个参数是队列的类型。
  //线程队列分为串行队列和并行队列,如果要创建串行队列,第二个参数写DISPATCH_QUEUE_SERIAL,并行队列写DISPATCH_QUEUE_CONCURRENT。
 dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);

  //虽然并行队列也可以创建,但是一般不去创建并行队列,而是找到系统自带的global并行队列使用。
 dispatch_queue_t tQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//dispatch_sync在线程队列中同步执行一个block
//同步执行,相当于waitUntilDone,当前代码先停止,直到分线程的block中的代码执行完毕,当前线程才继续往下执行。
//异步执行,开启一个分线程后,当前线程不去等待分线程执行完毕,直接往下执行。
dispatch_async(concurrentQueue, ^{
    NSLog(@"%@",[NSThread currentThread]);
    [NSThread sleepForTimeInterval:1];
});

//dispatch_get_main_queue获得主线程队列,主线程只有一个,所以,主线程是串行队列。
        dispatch_queue_t mainQueue =  dispatch_get_main_queue();
        //把刷新UI的代码放在主线程中执行
        dispatch_async(mainQueue, ^{
            _imageView.image = image;
        });
    });

//dispatch_suspend暂停一个线程队列,暂停之后,正在执行的block还会继续执行,这个block执行完之后,后面的block不会继续执行。      dispatch_suspend(_queue);
//dispatch_resume继续一个线程队列,继续之后,队列中的block会继续执行。
    dispatch_resume(_queue);

//创建出来的线程队列用完之后需要release
    dispatch_release(queue);

//dispatch_semaphore_t 线程信号量,dispatch_semaphore_create创建一个信号量,参数为初始信号量。
    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
//dispatch_semaphore_signal给某个信号量发送一个信号,作用是使这个信号量+1.       
    dispatch_semaphore_signal(sem);
 //dispatch_semaphore_wait等待信号量(等待信号量大于0),当信号量等于0时,当前线程会在这一行代码等待,直到sem信号的信号量大于0,当信号量大于0时,当前线程会对信号量-1,然后继续往下执行。
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

//设置一个信号量,信号量的值就是最大并发数。
    dispatch_semaphore_t sema = dispatch_semaphore_create(10);
-使用semaphore设置并发队列的最大并发数-
        //创建一个并发队列
    dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        //每当向队列中加入一个block时,先让线程等待,信号量足够时(大于0),线程执行,否则线程等待。
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        //code
        //code
        //code
        //code
            //当block执行完毕时,给信号量发送信号,使信号量+1
        dispatch_semaphore_signal(sema);
    });

//dispatch_after延迟执行一个block
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"3秒之前点击了button");
    });

//NSOperationQueue,操作队列。
     NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
//maxConcurrentOperationCount设置队列的最大并发数,当把最大并发数设置为1时,这个队列就相当于串行队列。
     queue.maxConcurrentOperationCount = 10;

//addOperationWithBlock把一个block封装成NSOperation,然后把这个operation放进操作队列中执行。
    [queue addOperationWithBlock:^{
        NSLog(@"%d",[NSThread isMainThread]);
          //currentQueue得到当前线程所在的操作队列。
        NSOperationQueue *qu = [NSOperationQueue currentQueue];
          //mainQueue得到主线程操作队列
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    }];

第十一周

    //setApplicationIconBadgeNumber设置应用程序icon的角标
    //申请推送权限,IOS8开始,需要申请推送权限,才能显示icon角标
    [[UIApplication sharedApplication] registerUserNotificationSettings:nil];
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:3];
    //badgeValue属性,角标。
    self.navigationController.tabBarItem.badgeValue = nil;

    frame是相对于父类的坐标系,bounds 是相对于自己的坐标系

字符串的逆转
NSString *str = @"a,b,c,d";
    NSMutableString *newStr = [[NSMutableString alloc]initWithCapacity:0];
    @autoreleasepool {
        for (int i = str.length-1; i>=0; i--)
        {
            [newStr appendString:[NSString stringWithFormat:@"%c",[str characterAtIndex:i]]];
        }
    }
    NSLog(@"%@",newStr);


//在图片边缘添加一个像素的透明区域,去图片锯齿
    CGRect imageRrect = CGRectMake(0, 0,_imageView.frame.size.width, _imageView.frame.size.height);
    UIGraphicsBeginImageContext(imageRrect.size);
    [_imageView.image drawInRect:CGRectMake(1,1,_imageView.frame.size.width-2,_imageView.frame.size.height-2)];
    _imageView.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();



2015.1.13
手势 touch时间 核心动画
/*iOS学习笔记之QuartzCore框架
 iOS编程给用户视觉反馈其实都是通过QuartzCore框架来进行的,说白了,所有用户最终看到的显示界面都是图层合成的结果,而图层即是QuartzCore中的CALayer。
 通常我们所说的视图即UIView,并不是直接显示在屏幕上,而是在创建视图对象的时候视图对象会自动创建一个层,而视图对象把要显示的东西绘制在层上,待到需要显示时硬件将所有的层拷贝,然后按Z轴的高低合成最终的显示结果。
 CALayer本质上是一块包含一幅位图的缓冲区,由视图创建的层为隐式层,而手动创建的层称为显示层。
 如果要在iOS上能够有良好的用户体验,动画的过渡效果是必不可少的,而所有的动画效果都是通过CAAnimation类的子类(CAAnimation是抽象类)来完成的。CAAnimation类的子类包括了 CAAnimationGroup,CAPropertyAnimation,CATransition,而CAPropertyAniamtion(同为抽象类)也衍生了CABasicAnimation和CAKeyframeAnimation。用UIView的animation实现的动画本质上也是通过CALayer来实现的,iOS系统中CALayer的很多属性都是隐含有动画效果的,如果不想要隐式动画或者想要显示动画效果,都可以通过CATransaction来设置是否显示动画效果。同时,在CATransaction内可同时修改多个属性,然后再一并同时渲染,另外CATransaction还是可嵌套的。
 CABasicAnimation是一个最多只能有两个关键帧的动画,而 CAKeyframeAnimation除了可含有多个关键帧,而且还可以修改每个关键帧的速度。
 CATransition能够为层提供移出以及移入屏幕的效果。苹果提供的所有动画类型在http://iphonedevwiki.net/index.php/CATransition这里有介绍,但是api只开放了其中的四种,当然你可以调用未公开的api,但是假如苹果以后出于安全还是什么原因调整接口的话,就不一定能用了,所以最好还是不要调用私有api,况且还有许多可以替代的方法,例如 @"flip”,@"pageCurl”这些type是属于未公开的,

//成为第一响应者
 [self becomeFirstResponder];













原文地址:https://www.cnblogs.com/hero11223/p/5508204.html