1、ARC 中lifetime修饰词
- 默认是__strong。只要对象还有强引用,该对象“活着”
- __weak不保留对象,只是简单引用。weak对象将被设置nil,当对象没有任何强引用的时候。
- __unsafe_unretained 不保留对象,只是简单引用。但是不设置为nil,当对象没有任何强引用得时候。如果对象被销毁,__unsafe_unretained的对象将会野指针。
- __autoreleasing 用于标识id*的引用参数,或者需要自动释放的返回的对象。
2、什么是ARC?
- Automatic Reference Counting,自动引用计数
- 在工程中使用ARC非常简单:只需要像往常那样编写代码,只不过永远不写retain,release和 autorelease三个关键字就好~这是ARC的基本原则。
- ARC与其他语言的”垃圾回收”机制不同。ARC:编译器特性;“垃圾回收”运行时特性
[更多的了解ARC(http://blog.csdn.net/kaitiren/article/details/17219957)
3、ARC判断准则
只要没有强指针指向对象,对象就会被释放。
注意:当使用ARC的时候,暂时忘记“引用计数器”,因为判断标准变了。
4、何为强弱指针
- __strong:强指针,所有的指针默认就是强指针
- __weak:弱指针
5、lifetime修饰词在实际中的运用
void Fun1()
{
// 内存没有被使用时立即释放
{
// 默认是__strong
Student *stu=[[Student alloc] init];
stu.name=@"李四";
}
// 此处stu为局部变量在栈区,花括号关闭释放,同时内存没有强指针指向,内
//存即释放
}
void Fun2()
{
{
// 弱指针指向内存空间,根据ARC判断准则只要没有强指针指向对象,对象就会
//释放 ,弱指针当然留不住内存,内存立即释放,当然,这样做没有什么意义,
//只是说明一下只有强指针指向对象,对象才不释放
__weak Student *stu=[[Student alloc] init];
stu.name=@"李四";
}
}
void Fun3()
{
// 有强指针指向对象不会立即释放内存
Student *stu;
{
Student *stu1=[[Student alloc] init];
stu1.name=@"李四";
stu=stu1;
// 现在对象被stu1和stu强指针指向
}
//花括号关闭,stu1释放,不过还有stu强指针指向,不能释放
int i=0;
i++;
}
//stu也释放,现在对象没有强指针指向,立即释放
void Fun4()
{
__weak Student *stu;
{
Student *stu1=[[Student alloc] init];
stu1.name=@"李四";
stu=stu1;
}
// 此处释放内存
int i=0;
i++;
}
void Fun5()
{
{
// 返回野指针 不安全 会概率性崩溃同时,内存立即释放
//不同于弱指针,内存释放,弱指针立即等于nil;
//而野指针值不变,不过内存释放了
__unsafe_unretained Student *stu=[Student new];
}
}
void Fun6()
{
@autoreleasepool {
{
// 超过 自动释放池 释放内存
__autoreleasing Student *stu=[Student new];
stu.name=@"test";
}
}
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
Fun4();
}
return 0;
}
6、ARC下循环引用问题
person.h
@interface Person : NSObject
//dog是strong 强指针
@property (nonatomic,strong) Dog *dog;
@end
person.m
@class Person;
@interface Dog : NSObject
//狗的主人 也是strong 强指针
@property (nonatomic,strong) Person *owner; @end
main.m
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [Person new];
Dog *d = [Dog new]; p.dog=d;
d.owner=p;
}
return 0;
}
运行结束会发现person和dog都无法释放
解决方案
循环引入的对象中其中一个对象设置为strong 另一个设置为weak
7、ARC下@property参数
- strong : 用于OC对象, 相当于MRC中的retain
- weak : 用于OC对象, 相当于MRC中的assign,不过释放时,weak变自动=nil,assign不能
- assign : 用于基本数据类型, 跟MRC中的assign一样
- copy: 一般用于NSString, 跟MRC中的copy一样
在ARC情况下解决”循环retain”的问题:@property一边用strong,一边用weak。
在MRC情况下解决”循环retain”的问题:@property一边用retain,一边用assign(可见第7天总结)。
分类(Category)
1、类别概念
- Category有很多种翻译: 分类 ,类别 ,类目,范畴 (一般叫分类)
- Category是OC特有的语法, 其他语言没有的语法(类似于C#语言中的”扩展方法”和”partial” 关键字)
2、类别的作用
- 在不修改原有的类的基础上增加新的方法
- 一个庞大的类可以分模块开发
- 一个庞大的类可以由多个人来编写,更有利于团队合作
3、类目的局限性
- 无法向类中添加新的实例变量。类别没有位置容纳实例变量
- 名称冲突,即类别中得方法与现有的方法重名。当发生名称冲突时,类别具有更高的优先级。你得类别方法将完全取代初始方法,从而无法再使用初始方法。有些编程人员在自己的类别方法中增加一个前缀,以确保不发生名称冲突。
4、类目的作用
- 第一,将类的实现分散到不同文件或者不同框架中
- 第二,创建对私有方法的前向引用
- 第三,向对象添加非正式协议
首先来看一个例子
student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
-(void) test;
@end
@interface Student (Student1)
-(void ) test1;
@end
@interface Student (Student2)
-(void) test2;
@end
@interface Student (Student3)
-(void) test3;
@end
student.m
#import "Student.h"
@implementation Student
-(void)test{
NSLog(@"test");
}
@end
student+student1.m
#import "Student.h"
@implementation Student (Student1)
-(void)test1{
NSLog(@"test1");
}
@end
student+student2.m
#import "Student.h"
@implementation Student (Student2)
-(void)test2{
NSLog(@"test2");
}
@end
student+student3.m
#import "Student.h"
@implementation Student (Student3)
-(void)test3{
NSLog(@"test3");
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu=[Student new];
[stu test];
[stu test1];
[stu test2];
[stu test3];
}
return 0;
}
注意观察,只有一个。h文件。
1个.h文件对应多个.m文件
另外下面是今天自己做的作业,大家参考下
NSString+MyStringCategory.h
#import <Foundation/Foundation.h>
@interface NSString (MyStringCategory)
/**
* 字符串首字母大写的方法
*
* @return NSString类实例
*/
-(NSString *)Capitalized;
/**
* 单词首字母大写的方法
*
* @return 一个NSString实例
*/
-(NSString *) capitalized;
@end
NSString+MyStringCategory.m
#import "NSString+MyStringCategory.h"
@implementation NSString (MyStringCategory)
-(NSString *)Capitalized{
char a=[self characterAtIndex:0];
char b=a-32;
NSString *s1=[NSString stringWithFormat:@"%c",a];
NSString *s2=[NSString stringWithFormat:@"%c",b];
NSMutableString *str=[NSMutableString stringWithString:self];
NSRange range={0,1};
if (a>=97&&a<122) {
[str replaceOccurrencesOfString:s1 withString:s2 options:NSLiteralSearch range:range ];
}
return str;
}
-(NSString *) capitalized{
NSString *str=[NSString stringWithString:self.capitalizedString];
return str;
}
@end