• JDiPad项目runtime的使用分析


    首先,项目有点老 但是运行还是没有问题的。其中很多地方到了runtime,同时也看到了 早期的开发人员 基本没用pod 第三方也很少用,除了微信登录,整个项目还没看到集成的第三方SDK。然后慢慢梳理 其中关于runtime的用法。

    项目较老,很多地方还是使用MRC 

    @property (nonatomic, retain) IBOutlet UIWindow *window;

    @property (nonatomic, retain) JDMainViewController *mainViewCtrl;

    @property (nonatomic, retain) NSURL *LaunchOptionsURL;

    @property (nonatomic, assign) BOOL isOpenFromUrl;

    @property (nonatomic, retain) NSString  *level;

    @property (nonatomic, retain) NSString  *catelogyId;

    @property (nonatomic, retain) NSString  *lastTitle;

    @property (nonatomic, assign) int       preSelectTabbarItem;

    @property (nonatomic, assign) int       currentTabbaarItem;

    @property (nonatomic, assign) int       n360buyCellSelectIndex_;

    @property (nonatomic, retain) NSMutableArray *catelogyFirstLeveData;

    @property (nonatomic, assign) BOOL isLoadProduct;

    @property (nonatomic, retain) NSMutableArray *catelogyArray;

    @property (nonatomic, retain) BarcodeController * barCode;

    我们先回顾下 assigin retain copy 的区别

    一、assign属性

      当数据类型为int、float等原生类型时,可以使用assign,否则可能导致内存泄露。例如当使用malloc分配了一块内存,并把它的地址赋值给了指针a,后来如果希望指针b也共享这块内存,于是讲a赋值给(assgin)b。这时就用到了assgin,此时a和b指向同一块内存。但是现在问题出现了,当a不再需要这块内存时,能都直接释放呢?肯定是不能的,因为a并不知道b是否还在使用这块内存,如果a释放了,那么b在使用这块内存的时候引起程序crash掉。

    二、retain属性

      retain属性就是为了解决上述问题而提出的,使用了引用计数(reference counting),还是上面那个例子,我们给那块内存设一个引用计数,当内存呗分配并且赋值给a时,引用计数是1.当把a赋值给b时引用计数增加到2.这时如果a不再使用这块内存,它只需要把引用计数减1,表明自己不再拥有这块内存。b不再使用这块内存时也把引用计数减1.当引用计数变为0的时候,代表该内存不再被任何指针所引用,系统可以直接释放掉。此时系统自动调用dealloc函数,内存被回收。

    三、copy属性

      copy是你不希望a和b共享一块内存时会使用到。a和b各自有自己的内存。

    ios提供了copy和mutablecopy方法,顾名思义,copy就是复制了一个imutable的对象,而mutablecopy就是复制了一个mutable的对象。以下将举几个例子来说明。

    1、系统的非容器类对象:这里指的是NSString、NSNumber等等一类的对象。

    NSString *string = @"origion";
    NSString *stringCopy = [string copy];
    NSMutableString *stringMCopy = [string mutableCopy];
    [stringMCopy appendString:@"!!"];

    查看内存可以发现,string和stringCopy指向的是同一块内存区域(又叫apple弱引用weak reference),此时stringCopy的引用计数和string的一样都为2。而stringMCopy则是我们所说的真正意义上的复制,系统为其分配了新内存,但指针所指向的字符串还是和string所指的一样。

    再看下面的例子:

    复制代码
    NSMutableString *string = [NSMutableString stringWithString: @"origion"];
    NSString *stringCopy = [string copy];
     NSMutableString *mStringCopy = [string copy];
    NSMutableString *stringMCopy = [string mutableCopy];
    [mStringCopy appendString:@"mm"];//error
    [string appendString:@" origion!"];
    [stringMCopy appendString:@"!!"];
    复制代码

    以上四个NSString对象所分配的内存都是不一样的。但是对于mStringCopy其实是个imutable对象,所以上述会报错。
    对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。

    2、系统的容器类对象:指NSArray,NSDictionary等。对于容器类本身,上面讨论的结论也是适用的,需要探讨的是复制后容器内对象的变化。

    复制代码
    //copy返回不可变对象,mutablecopy返回可变对象
    NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];
    NSArray *arrayCopy1 = [array1 copy];
    //arrayCopy1是和array同一个NSArray对象(指向相同的对象),包括array里面的元素也是指向相同的指针
    NSLog(@"array1 retain count: %d",[array1 retainCount]);
    NSLog(@"array1 retain count: %d",[arrayCopy1 retainCount]);
    NSMutableArray *mArrayCopy1 = [array1 mutableCopy];
     //mArrayCopy1是array1的可变副本,指向的对象和array1不同,但是其中的元素和array1中的元素指向的是同一个对象。mArrayCopy1还可以修改自己的对象
    [mArrayCopy1 addObject:@"de"];
    [mArrayCopy1 removeObjectAtIndex:0];
    复制代码

    array1和arrayCopy1是指针复制,而mArrayCopy1是对象复制,mArrayCopy1还可以改变期内的元素:删除或添加。但是注意的是,容器内的元素内容都是指针复制。
    下面用另一个例子来测试一下。

    复制代码
    NSArray *mArray1 = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
    NSArray *mArrayCopy2 = [mArray1 copy];
    NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);
    NSMutableArray *mArrayMCopy1 = [mArray1 mutableCopy];
    NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);
     //mArrayCopy2,mArrayMCopy1和mArray1指向的都是不一样的对象,但是其中的元素都是一样的对象——同一个指针
     //一下做测试
     NSMutableString *testString = [mArray1 objectAtIndex:0];
     //testString = @"1a1";//这样会改变testString的指针,其实是将@“1a1”临时对象赋给了testString
    [testString appendString:@" tail"];//这样以上三个数组的首元素都被改变了
    复制代码

    由此可见,对于容器而言,其元素对象始终是指针复制。如果需要元素对象也是对象复制,就需要实现深拷贝。

    一、#import与#include

    #import不会引起交叉编译的问题。因为在Objective-C中会存在C/C++和Object-C混编的问题,如果用#include引入头文件,会导致交叉编译。

    二、#import<>与#import""

    在实际运用中都是某个框架里的.#import <Three20/Three20.h><>通常指向的是一个目录#import ""则直接是文件名。

    三条基本原则:

    1、当你使用 new、alloc 或 copy 创建对象时,对象的 count retain 到 1。你一定要负责把这个对象 release 或 autolease 掉。这样当它的生命周期结束时,它才能清空。

    2、当你使用其他方法获得一个对象时,你可以认为它已经 retain 了一个 count,并且 autolease 掉了。你不用考虑和它相关的清理问题。但是如果你想保留这个对象,那么你需要 retain 它,并且要确保之后你 release 了这个对象。

    3、如果你 retain 一个对象,你最终总是需要 release 或者 autolease 它。

    @property和
    @synthesize

    当定义了一系列的变量时,需要写很多的getter和setter方法,而且它们的形式都是差不多的,所以Xcode提供了@property和@synthesize属性,@property用在 .h 头文件中用作声明,@synthesize用在.m 文件中用于实现。
    在X-code4.5以前,在.h中声明完属性之后,如:
    @property(nonatomic,assign) int age;
    @property(nonatomic,assign) NSString *name;
    需要在.m中写上
    @synthesize int age;
    @synthesize NSString *name;
    系统会自动去实现setter和getter方法

    而在X-code4.5之后,@synthesize就不需要再写了,系统会直接去实现setter和getter方法。
    另外,声明完property属性之后,会自动生成下划线,如_age、_name;如果不想要下划线,那么就可以使用@synthesize去修饰,例如,在.m中写@synthesize age;那么_age就会变成age

    // 加载启动广告图

    //- (void)loadStartADView

    //{

    //    // 启动时的广告图

    //    JDStartLoadingViewController *startVC = [[JDStartLoadingViewController alloc] init];

    //    [startVC addTarget:self action:@selector(didFinishSetup)];

    //    window.rootViewController = startVC;

    //    [startVC release];

    //}

    根据分析,程序用的开发是2010年末或2011年初 开始, 一直更新 到2016年末 如此长时间的项目,也许是大公司特有的。毕竟听说如今使用的QQ优化了好多年也还有一半是MRC。注意的是Xcode 4.1及其以前版本没有ARC,

    //  Created by steven sun on 1/11/11.

    //  Copyright 2011 __MyCompanyName__. All rights reserved.

    为了方便项目的正常使用,我去掉一些广告,修改了rootViewController,注销了一些runtime 

    runtime 哦,终于到正题了 ,我们先欣赏下他的view,太多了,我截取了一部分,分了好多板块,甚至很多版本,包括自定义的IM 和 分享,当然还有自己的支付库

     

  • 相关阅读:
    努力努力,我假期要练琴学css
    在遇到困难时我们都会想要是这一切不曾发生该多好,可现实并不以我们的意志为转移,我们所能做的就是去克服...
    寒假学习目标~
    平安夜&&圣诞节
    you are the ont that we would like to trust and ca...
    Happy New Year!PR升3啦!
    呵呵,Merry Christmas & Happy New Year!
    使用Rx Framework实现XAML中的物体拖动
    MVVM绑定多层级数据到TreeView并设置项目展开
    Entity framework中EntityFunctions.CreateDateTime方法的闰年闰月bug
  • 原文地址:https://www.cnblogs.com/tangyuanby2/p/6442506.html
Copyright © 2020-2023  润新知