zoukankan      html  css  js  c++  java
  • 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];













  • 相关阅读:
    cocos2d-x系列笔记技巧篇(2)---关于CREATE_FUNC宏的用法
    Cocos2d-x开源、跨平台的游戏引擎
    Asp.Net Core 文件上传处理
    Asp.Net Core获取当前上下文对象
    Asp.Net Core 视图整理(一)
    SVG渲染顺序及z轴显示问题(zIndex)
    JavaScript Screen对象
    Javascript 对象(object)合并
    SVG.Js事件示例,简单绑定拖动操作
    SVG 文字居中整理
  • 原文地址:https://www.cnblogs.com/hero11223/p/5508204.html
Copyright © 2011-2022 走看看