首先,项目有点老 但是运行还是没有问题的。其中很多地方到了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 和 分享,当然还有自己的支付库

 

 

posted on 2017-02-25 19:14  ZOYOO  阅读(232)  评论(0编辑  收藏  举报