美文网首页程序员
熟悉Objective-C <一>

熟悉Objective-C <一>

作者: 那是一阵清风_徐来 | 来源:发表于2018-01-20 20:24 被阅读11次
    MARK: - 了解Objective-C 语言起源

    Objective-C 为C语言添加了 面向对象 的的特性
    Objective-C是一门 动态绑定 的消息结构,也就是说运行时才会检查对象类型。接到消息之后,究竟应该执行何种代码,由运行期环境而非编译器来决定

    //总结:
    //1、对象所占用的内存 总是分配在 堆空间 中
    //2、对象是分配在栈上的
    //3、class 是引用类型、struct是值类型()
    - (void)test01
    {
        // 1、someString变量 指向 NSString的指针,对象所占用的内存 总是分配在 堆空间 中
        NSString *someString = @"the string";
        
        // 2、anotherString变量 指向 同一块地址,并不拷贝改对象,只是这两个变量会同时指向此对象
        NSString *anotherString = someString;  //*** 浅拷贝 ***
        
        NSLog(@"someString 内存地址:%p,someString = %@",someString,someString);
        //0x10e1f2088 the string
        
        NSLog(@"anotherString 内存地址:%p,anotherString = %@",anotherString,anotherString);
        //0x10e1f2088 the string
        
        //  3、
        someString = @"the string is change";
        
        NSLog(@"someString 内存地址:%p,someString = %@",someString,someString);
        //0x10e1f20e8 the string is change  //内存地址不一样,字面量重新创建一个字符串对象
        
        NSLog(@"anotherString 内存地址:%p,anotherString = %@",anotherString,anotherString);
        //0x10e1f2088 the string
    
        
        //**************
        
        MObject *m1 = [[MObject alloc] init];
        m1.name = @"jack";
        
        MObject *m2 = m1;
        NSLog(@"m1 的内存地址:%@,m1 = %@",m1,m1.name);    //0x6000000076f0   jack
        NSLog(@"m2 的内存地址:%@,m2 = %@",m2,m2.name);    //0x6000000076f0   jack
    
        m2.name = @"rose";
        NSLog(@"m1 的内存地址:%@,m1 = %@",m1,m1.name);    //0x6000000076f0   rose
        NSLog(@"m2 的内存地址:%@,m2 = %@",m2,m2.name);    //0x6000000076f0   rose
    
    }
    
    MARK: - 了解Objective-C 命名规范
    // 用系统方法举例子
    - (void)example
    {
        
        // 驼峰命名法
        // 以小写字母开头,其后每个单词首字母大写,而且前面通常还有两三那个前缀字母(自定义方法的生活,可以用于区别与系统的方法)
        // 但方法名不能太长,必须言简意赅
        NSString *text = @"this is text";
        NSString *newText = [text stringByReplacingOccurrencesOfString:@"text"
                                                            withString:@"textString"];
        NSLog(@"newText = %@",newText);
    }
    
    - (void)majqNamedForMethodTest
    {
        // 1、用于创建新的MPeson对象,方法名清晰的描述了返回值的类型
        MPeson *p = [MPeson person];
        
        // 获取p 的名字,这个方法只有一个词,实际上name 也是一个字符串属性
        // 如果此方法命名StringName 就不好,string 一词多余
        NSString *temVar = [p name];
        NSLog(@"temVar = %@",temVar);
    
        // 2、如果方法的返回值是新创建的,那么方法名的首个单词应该是返回值的类型,除非前面有修饰语,但是string 不能简写成str
        [p stringBookNameByShoping];
        
        // 3、应该把参数类型的名词放在参数前面
        [p runWithFriend:nil name:@"jack"];
        
        // 4、BOOl 属性应加is前缀,如果某方法返回非属性的Bool值,那么应该根据其功能,选用has或者is 当前缀
        [p hasPet];
        BOOL temVar01 = [p isMillionaire];
        BOOL temVar02 = p.isMillionaire;
        NSLog(@"temVar01 = %d temVar02 = %d",temVar01,temVar02);
    
        NSString *text = @"http://www.baidu.com";
        [text hasPrefix:@"http"];
        [text isEqualToString:@"http://www.taobao.com"];
        
    }
    
    - (void)majqNamedForClasstest
    {
        // 1、应该为类与协议的名称加上前缀,以避免命名空间(nameSpace)冲突
        // MPeson、NSArray、NSMutableArray
        
        
        // 2、向 命名方法那么驼峰命名
        
        // 3、*****命名方式应该协调一致*****
        // 3.1 如果要从其他框架中继承子类,那么务必遵守其命名管理
        // UIView  -->  MView
        
        // 3.2 如果创建自定义的委托协议,则其名字中应该包含委托发起方的名称,后面再跟上 Delegate
    }
    
    MARK: - 在类的头文件中尽量少引用其他头文件

    查看下面代码:

    #import <Foundation/Foundation.h>
    
    // 注意:***
    #import "MajqNetworkFetcher.h"
    // 注意:***
    
    @interface MObject : NSObject
    
    @property(nonatomic,copy)NSString *name;
    
    @property(nonatomic,strong)MajqNetworkFetcher *fetcher;
    
    @end
    
    

    // 注意:***
    // MObject 添加属性fetcher时,常见的方法就是导入#import "MajqNetworkFetcher.h" 头问题
    // 这种方法可行,但是不够优雅
    // 因为编译的时候,MObject 不需要知道MajqNetworkFetcher类的全部细节,只需要知道有一个类名叫MajqNetworkFetcher 就好
    // 所以,有个办法告诉编译器:@class MajqNetworkFetcher;
    // 这叫 "向前声明"

    #import <Foundation/Foundation.h>
    
    // 注意:***
    // MObject 添加属性fetcher时,常见的方法就是导入#import "MajqNetworkFetcher.h" 头问题
    // 这种方法可行,但是不够优雅
    // 因为编译的时候,MObject 不需要知道MajqNetworkFetcher类的全部细节,只需要知道有一个类名叫MajqNetworkFetcher 就好
    // 所以,有个办法告诉编译器:@class MajqNetworkFetcher;
    // 这叫 "向前声明"
    #import "MajqNetworkFetcher.h"
    @class MajqNetworkFetcher;
    // 注意:***
    
    @interface MObject : NSObject
    
    @property(nonatomic,copy)NSString *name;
    
    @property(nonatomic,strong)MajqNetworkFetcher *fetcher;
    
    @end
    
    这样做的好处就是:

    将头文件的时机尽量延后,只在确有需要的时候引入,这样做可以:
    减少类的使用者所需引入的头文件数量,从而减少 编译时间

    在实际开发过程中,我们可以这样去处理,但是,这样做也许会遇到一些问题:
    比如说: @protocol

    要声明你写的类遵守某个 协议@protocol,那么该协议必须要有完整的定义,且不能使用 向前声明 (向前声明@class 只能告诉编译器有某个协议,而此时编译器却要知道该协议中定义的方法)

    那么怎么做呢??

    通常做法是:

    #import "MajqDataModel.h"
    // 导入头文件
    #import "MajqNetworkFetcher.h"
    @interface MajqDataModel () <MajqNetworkFetcherDelegate>
    
    @end
    
    @implementation MajqDataModel
    

    上面这种做法 没毛病,导入头文件 #import "MajqNetworkFetcher.h" 这个是在所难免的;
    鉴于此,最好把协议 单独放在一个头文件中;
    而要是把 MajqNetworkFetcherDelegate 放在 #import "MajqNetworkFetcher.h" 中,则只有引入头文件 #import "MajqNetworkFetcher.h" ,那么就会引入该头文件的所以内容

    当然 这样做 有时候还是会有缺陷的,比如 委托协议,协议只有与接受协议委托的类放在一起定义才有意义
    这个就不做具体的介绍,有时间在补充...

    相关文章

      网友评论

        本文标题:熟悉Objective-C <一>

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