1、ARC与非ARC项目的互转
- 选择项目中的Targets,选中你所要操作的Target,选Build Phases,在其中Complie Sources中选择需要ARC的文件双击,并在输入框中输入:-fobjc-arc,
- 如果不要ARC则输入:-fno-objc-arc
2、ARC的判断准则:
只要没有强指针指向对象,对象就会被释放。
3、指针分类:
(1)强指针:默认的情况下,所有的指针都是强指针,关键字strong
(2)弱指针:_ _weak关键字修饰的指针
声明一个弱指针如下:
__weak Person *p;
ARC中,只要弱指针指向的对象不在了,就直接把弱指针做清空操作。
__weak Person *p=[[Person alloc] init];//不合理,对象一创建出来就被释放掉,对象释放掉后,ARC把指针自动清零。
ARC中在property处不再使用retain,而是使用strong,在dealloc中不需要再[super dealloc]。
@property(nonatomic,strong)Dog *dog;// 意味着生成的成员变量_dog是一个强指针,相当于以前的retain。如果换成是弱指针,则换成weak,不需要加_ _。
4、ARC的特点总结:
(1)不允许调用release,retain,retainCount
(2)不允许重写dealloc,但是不允许调用[super dealloc]
(3)@property的参数:
Strong:相当于原来的retain(适用于OC对象类型),成员变量是强指针
Weak:相当于原来的assign,(适用于oc对象类型),成员变量是弱指针
Assign:适用于非OC对象类型(基础类型)
5、类目category
为什么不用继承
继承有两个问题:- 第一个问题:继承的前提是这个类可以被继承,因为在Java中有些类是不允许继承的,定义成final类,同样的OC中也是有不可以继承的类
- 第二个问题:这个类可以被继承,但是继承我们知道是侵入性的,就是我可能只是想实现一个功能,但是继承之后,子类就会把父类的所有功能(属性和方法)都继承了,这个代价太大了。没必要
类目的局限性
- 第一,无法向类中添加新的实例变量。类别没有位置容纳实例变量。
- 第二,名称冲突,即类别中得方法与现有的方法重名。当发生名称冲突时,类别具有更高的优先级。你得类别方法将完全取代初始方法,从而无法再使用初始方法。有些编程人员在自己的类别方法中增加一个前缀,以确保不发生名称冲突。
类目的作用
主要用于3个目的:- 第一,将类的实现分散到不同文件或者不同框架中。
- 第二,创建对私有方法的前向引用。
- 第三,向对象添加非正式协议。
来看一个例子:
// Student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
-(void)test;
@end
@interface Student (Student_)
-(void)test1;
@end
@interface Student (Student__)
-(void)test2;
@end
// Student.m
#import "Student.h"
@implementation Student
-(void)test{
NSLog(@"test1");
}
@end
// Student+Student_.m
#import "Student.h"
@implementation Student (Student_)
-(void)test1{
NSLog(@"test2");
}
@end
// Student+Student__.m
#import "Student.h"
@implementation Student (Student__)
-(void)test2{
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];
}
return 0;
}
//注意上例中多个.m对应了一个.h
-
-
-
之前的ARC要是有什么不明白的还可以看一下下面这个例子
#import <Foundation/Foundation.h>
#import "Student.h"
void Fun1()
{
// 内存没有被使用时立即释放
{
// 默认是__strong
__strong Student *stu=[[Student alloc] init];
stu.name=@"test1";
}
// 此处释放内存
}
void Fun2()
{
{
// 在这行已经释放了 弱引用
__weak Student *stu=[[Student alloc] init];
stu.name=@"test2";
}
}
void Fun3()
{
// 强引用对象被使用不会立即释放内存
Student *stu;
{
Student *stu1=[[Student alloc] init];
stu1.name=@"test3";
stu=stu1;
// 如果加入这句代码 超过} 就释放内存
// 如果不加入这句代码 在函数结束是释放
// stu=nil;
}
int i=0;
i++;
}
void Fun4()
{
__weak Student *stu;
{
Student *stu1=[[Student alloc] init];
stu1.name=@"test4";
stu=stu1;
// stu=nil;
}
// 此处释放内存
int i=0;
i++;
}
void Fun5()
{
{
// 返回野指针 不安全 会概率性崩溃
__unsafe_unretained Student *stu=[Student new];
//此处释放
int i=0;
}
}
void Fun6()
{
@autoreleasepool {
{
// 超过 自动释放池 释放内存
__autoreleasing Student *stu=[Student new];
stu.name=@"test6";
}
}
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
Fun1();
Fun2();
Fun3();
Fun4();
Fun5();
Fun6();
}
return 0;
}
-
-
-
下面附上今天的作业:
/**
*
*作业:为NSString类添加一个首字母大写的方法
*/
#import <Foundation/Foundation.h>
#import "NSString+Mycapital.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *str1=@"abcdef";//新建一个字符串str1
NSLog(@"%@",[str1 mycapital]);//调用自己的首字母大写方法并打印
}
return 0;
}
//
// NSString+Mycapital.h
#import <Foundation/Foundation.h>
@interface NSString (Mycapital)
-(NSString *)mycapital;
@end
//
// NSString+Mycapital.m
#import "NSString+Mycapital.h"
@implementation NSString (Mycapital)
-(NSString *)mycapital{
//提取字符串的首字符
char temp=[self characterAtIndex:0];
//进行首字符是否是小写字符的判断
if (temp<=122&&temp>=97) {
//判断通过则将temp转成大写
temp=temp-32;
//将大写字符储存在cap中
NSString *cap=[NSString stringWithFormat:@"%c",temp];
//设置首字符的范围
NSRange range=NSMakeRange(0, 1);
//将原字符串中得第一个字符改为cap中得字符,并返回
return [self stringByReplacingCharactersInRange:range withString:cap];
}else{
//首字母不是小写是打印日志信息,并返回本身值
NSLog(@"首字符不是小写字母");
return self;
}
}
@end
/**
* 为NSMutableArray类添加一个reverse 翻转的方法
*/
//main.m
#import <Foundation/Foundation.h>
#import "NSMutableArray+Myreverse.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableArray *marr=[NSMutableArray arrayWithObjects:@"a",@"b",@"c",@"d", nil];//新建一个可变数组
[marr Myreverse];//调用自己的翻转翻转方法进行操作
NSLog(@"%@",marr);//打印数组
}
return 0;
}
//
// NSMutableArray+Myreverse.h
#import <Foundation/Foundation.h>
/**
* NSMutableArray的新类目
*/
@interface NSMutableArray (Myreverse)
//声明自己的翻转方法
-(void)Myreverse;
@end
//
// NSMutableArray+Myreverse.m
#import "NSMutableArray+Myreverse.h"
@implementation NSMutableArray (Myreverse)
-(void)Myreverse{
//从数组下标0开始循环到数组元素数量的一半
for (int i=0; i<(self.count)/2; i++) {
//声明一个id类型的临时变量temp
id temp;
//将当前循环位于的元素值赋给temp
temp=[self objectAtIndex:i];
//将当前循环位置的值用它翻转对应位置的值代替
[self replaceObjectAtIndex:i withObject:[self objectAtIndex:self.count-i-1]];
//将当前循环位置所对应位置的值用temp中的代替
[self replaceObjectAtIndex:self.count-i-1 withObject:temp];
}
}
@end
-15.8.10
-15.8.12