美文网首页程序员iOS零碎知识
【IOS读书笔记】ProgrammingWithObjectiv

【IOS读书笔记】ProgrammingWithObjectiv

作者: 纳达丶无忌 | 来源:发表于2016-04-26 20:20 被阅读111次

    1. 面向对象I

    这里不会像从0开始学OC一样逐步解释面向对象的基本概念,只说一下一些独特之处。

    1.1.定义类属性
    @property NSString *fullName;
    

    自定义getter名称,自定义只读属性

    @property (readonly, getter=isFinished) BOOL finished;
    

    如果执行somePerson.firstName仍然是调用的getter方法

    1.2.合成
    @implementation YourClass
    @synthesize propertyName = instanceVariableName;  //指定为instanceVariableName
    或者
    @synthesize propertyName  //指定为propertyName
    或者不写   //指定为_propertyName
    ...
    @end
    

    此处synthesize的作用只是重新指定名称而已,不加也会有getter setter

    1.3.属性配置
    @property(nonatomic,retain) UIWindow *window;
    

    其中参数主要分为三个维度,每个维度可以有一个值:

    • 读写属性: (readwrite 默认/readonly)
    • setter语意:(assign/retain/copy) NSFloat,NSInteger只能用assign,否则报错
    • 原子性: (atomic 默认/nonatomic)

    强弱:(strong 默认/weak) 强引用、若引用,主要用于arc的垃圾回收,如果一个对象有被强引用则不能被回收。对某一小部分类,如NSTextView无法被申明为weak(历史原因),要用unsafe_unretained关键字代替。
    强弱不是一个维度,其本质是setter语意的维度,其中
    strong == retain,weak == assign。
    验证:如果标示为 (strong, copy)则xcode报错如下:


    77BA93B9-3A32-488B-B388-600BA53AA7E9.png

    各参数意义如下:

    readwrite: 产生setter\getter方法
    readonly: 只产生简单的getter,没有setter。
    assign: 默认类型,setter方法直接赋值,而不进行retain操作
    对基础数据类型 (例如NSInteger,CGFloat)和C数据类型(int, float, double, char, 等) 适用简单数据类型
    retain: setter方法对参数进行release旧值,再retain新值。
    copy: setter方法进行Copy操作,与retain一样
    retain 是指针拷贝,copy 是内容拷贝。
    nonatomic: 禁止多线程,变量保护,提高性能

    一般使用场景:

    //基本属性用assign
    @property (assign, nonatomic) NSInteger unit_id;
    //类属性用copy
    @property (copy,  nonatomic) NSString* name;
    //重要的线程安全类
    @property (retain,  atomic) ThreadSafeClass* instance;
    //待添加
    
    1.4 如何比较两个类
    //== 是否指向同一个对象
    if (aPerson == bPerson){
    }
    //isEqual 是否相同
    if ([firstPerson isEqual:secondPerson]) {  
        // firstPerson is identical to secondPerson 方法由NSObject提供
    }
    
    //比较大小
    //the basic Foundation types, like NSNumber, NSString and NSDate, provide a compare: method:
    if ([someDate compare:anotherDate] == NSOrderedAscending) {
        // someDate is earlier than anotherDate
    }
    

    2.特有语法

    简单列举Category, Extension等OC特有的编程结构使用方法

    2.1 Category

    典型使用场景:

    #import "XYZPerson+XYZPersonNameDisplayAdditions.h"
    @implementation SomeObject
    - (void)someMethod {
        XYZPerson *person = [[XYZPerson alloc] initWithFirstName:@"John" lastName:@"Doe"];
        XYZShoutingPerson *shoutingPerson = [[XYZShoutingPerson alloc] initWithFirstName:@"Monica"
     lastName:@"Robinson"];
        NSLog(@"The two people are %@ and %@",[person lastNameFirstNameString], [shoutingPerson lastNameFirstNameString]);
    
    }
    @end
    

    只要import XYZPerson+XYZPersonNameDisplayAdditions.h,就可以在其他的类的实例调用新增方法。
    需要注意:category中不能增加property,如果需要,那么要使用继承或者扩展来是实现。

    2.2 Extension

    中文名:扩展

    @interface ClassName ()
    @end
    

    扩展即匿名的分类,并且在扩展中可以添加自定义的属性。

    3.数据类型

    OC中的数据类型主要分为以下几类:

    • C原始类型:
      int float double char
    • OC原始类型:
      NSInteger NSFloat 是int,float的宏定义,做了优化
    • 结构体:
    typedef struct {
                 int id,
                 float height,
                 unsigned char flag
    
    }MyTestStruct;
    

    在View框架中能看到大量的常用结构体如CGPoint CGRect CGSize等

    • Foundation对象:
      NSNumber NSString NSRange NSValue
      其中NSValue作用是封装一个结构体,为了给比如NSArray之类的集合类使用,代码如下:
    struct MyIntegerFloatStruct aStruct;
    aStruct.i = 42;
    aStruct.f = 3.14;
    
    NSValue *structValue = [NSValue value:&aStruct
                             withObjCType:@encode(MyIntegerFloatStruct)];
    
    • enum
      枚举使用的地方都可以用int。而枚举类型常用于有限可选的项,表达更有语义的场景。定义方式如下:


      11919918-3B06-4270-8CB9-7DB3B1A7998B.png

      上述定义自动将第一个值设为0,之后是1,2,3...

    4.集合

    集合在所有语言的学习中都是重中之重,从数据结构知识中可以知道,无非有这么几种集合:Array, Stack,Queue, Set, Map(Java中认为map不是集合), Tree 等。
    Foundation为我们提供了常用的集合实现,主要有:
    NSArray, NSSet and NSDictionary.
    他们都是不可变对象,相当于Java中的final。如要使用可变对象,都有对应的NSMutableArrayNSMutableDictionary等。

    4.1 NSArray

    Objective-C的数组比C++,Java的数组强大在于,NSArray保存的对象可以是不同的对象

    初始化:
    由于 arrayWithObjects: 和 initWithObjects: 方法都采用了以 nil 结束且数量可变的参数,所以您 必须包括 nil 并将其作为最后一个值。

    NSArray *someArray =
    [NSArray arrayWithObjects:someObject, someString, someNumber, someValue, nil];
    

    这里的对象不能为nil
    存在性

    if ([someArray containsObject:someString]) 
    

    这个Array相当于java的ArrayList

    排序

    NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
    NSArray *sortedStrings =
                 [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];
    

    默认是immutable
    还有NSMutableArray,后者有add,replace,remove功能:

    [array addObject:...] : 向可变数组尾部添加数据对象。
    [array addObjectsFromArray:..] :向可变数组尾部添加一个数组对象。
    [array removeObject:(id)] :删除数组中指定元素,根据对象isEqual消息判断。
    [array removeObjectAtIndex:(NSUInteger)]:删除数组中指定脚标索引的数据。
    
    4.2 NSDictionary

    只能用NSString作key

    //字面量定义(官方推荐使用)
    NSDictionary *dictionary = @{
       @"anObject" : someObject,
    @"helloString" : @"Hello, World!",
    @"magicNumber" : @42,
         @"aValue" : someValue
    };
    //get方法1
    dictionary[@"magicNumber"];
    //get方法2
    NSNumber *storedNumber = [dictionary objectForKey:@"magicNumber"];
    
    4.3 NSNull

    NSNull
    是一个工厂类,有方法null

    //用于在collection中添加“空”元素。
    NSArray *array = @[ @"string", @42, [NSNull null] ];
    //判断时采用
    if (object == [NSNull null]) {
    

    Tips: nil,Nil,NULL和NSNull 的区别:
    从语言角度,NULL是c语言的产物,适用于任何指针
    int * pointerA = NULL

    OC语言中nil,和Nil代表空指针,即一个目标为空。
    nil的目标指实例,如
    ClassA * instanceA = nil;
    而Nil目标是类
    Class* ClassA = Nil;
    然而实际上nil和Nil是可以混用的。

    NSNull和之前的作用都不同,他是一个真正的类,这个类出现的作用是『标记』

    AD15468E-8714-4ED8-B864-06DAA8635A65.png
    唯一的类方法是返回一个NSNull的实例,是一个工厂方法。但不是单例工厂。
    这个类的实际作用是在NSArray等集合类中占位,代表这个位置为空。因为如果设为nil,在循环的时候就认为集合已经到头了,是无法实现如
    *NSArray array = @[ @"string", @42, [NSNull null],@42 ];

    这时候判断也要这么进行:
    if ([array objectAtIndex:1] == [NSNull null])

    4.4 迭代
    for (int index = 0; index < count; index++) {
    
    for (id eachObject in array) {
    //反向迭代器
    for (id eachObject in [array reverseObjectEnumerator]) {
    
    

    5 Block

    总的来说和函数比较像。

    1. 可以实现js中的高阶函数,作为变量传给function
    2. 可以保存和调用block所在域的变量
      下面说说主要的几个用法:

    1.用于回调:

    //例子1 
    //此处就是一个回调函数的用法,使用了block来作为回调传入进去。那为什么不能用另一个函数的@selector?
    [task beginTaskWithCallbackBlock:^{
            [self hideProgressIndicator];
    }];
    
    //解释:看看task的该方法定义:
    - (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock;
    //是因为从定义上可以更明确(要传入void,void的类型)
    
    
    
    
    //例子2
    - (void)doSomethingWithBlock:(void (^)(double, double))block {
        ...
        block(21.0, 2.0);
    }
    
    //约定:一般来讲有block参数的函数要把block类型放在最后一个入参,如
    - (void)beginTaskWithName:(NSString *)name completion:(void(^)(void))callback;
    

    2.除了回调,还有一个用法是用于迭代,如:

    NSArray *array = ...[array enumerateObjectsUsingBlock:^ (id obj, NSUInteger idx, BOOL *stop) {
    
        NSLog(@"Object at index %lu is %@", idx, obj);
    }];
    //以及并发版本的迭代:
    [array enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^ (id obj, NSUInteger idx, BOOL *stop) {
    
    ... }];
    

    3.用于并发任务(Operation Queue \ GCD)

    // Operation Queue
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        ...
    }];
    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    [mainQueue addOperation:operation];
    
    //GCD:
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{ NSLog(@"Block for asynchronous execution");
    
    });
    

    相关文章

      网友评论

        本文标题:【IOS读书笔记】ProgrammingWithObjectiv

        本文链接:https://www.haomeiwen.com/subject/ygzqrttx.html