#import <Foundation/Foundation.h>

@interface Test : NSObject
/**
* 默认的就是__strong,这里只是做示范,实际使用时,不用写。
*
* @param obj <#obj description#>
*/
- (void)setObject:(id __strong)obj;
@end
#import "Test.h"
@interface Test(){ id __strong obj_; /** 默认的就是__strong,这里只是做示范,实际使用时,不用写。*/ }
@end
@implementation Test - (void)setObject:(id)obj{ //设置成员变量的值
obj_ = obj;
} @end

ARC的学习

使用ARC时,id类型和对象类型上必须加上所有权修饰符,所有权修饰符分为下面四种,一.是__strong,强引用(id类型和对象类型默认的就是这个修饰符,如成员变量,所有前面什么也不加,就是__strong)

是__weak弱引用,一般不会持有对象。三.是__unsafe_unretained修饰符。 四. 是__autoreleasing修饰符。

一.   __strong 的使用

特点

1.强引用,会持有对象,但会造成两个类或对象之前互相引用,造成循环引用。

2.超出作用域,强引用失效,会被释放。

3. 栗子1,循环引用,循环引用的重点就是最后引用的的那个对象是否为空,如果持有的对象已经废弃了,那个引用还存在,说明内存泄漏了,不能合理的翻译该对象。

   id  test1 = [[Test alloc] init];     /**test1 持有对象A的强引用*/
id test2 = [[Test alloc] init]; /**test2 持有对象B的强引用*/ [test1 setObject:test2]; /**Test对象A的成员变量obj_持有Test对象B的强引用,此时持有Test对象B的强引用为Test对象A的成员变量obj_和test2*/
[test2 setObject:test1]; /**Test对象B的成员变量obj_持有Test对象A的强引用,此时持有Test对象A的强引用为Test对象A的成员变量obj_和test1*/ /**1.因为test1变量超出作用域时,强引用会失效,会自动释放Test对象A*/
/**2.因为test2变量超出作用域时,强引用会失效,会自动释放Test对象B*/
/**3.此时持有Test对象A的强引用变量为Test对象B的成员变量obj_*/
/**4.此时持有Test对象B的强引用变量为Test对象A的成员变量obj_*/
/**5.发生内存泄漏*/

3.什么是内存泄漏?

/**内存泄漏是应当废弃的对象,在赶出自己的生命周期后继续存在*/

4.自己持有自己,不会造成内存泄漏,因为超出其生命周期时,会正常释放。

   id  test0 = [[Test alloc] init];

    [test0 setObject:test0];

5. 如何避免内存泄漏

二. __weak的使用

特点

1.避免循环引用

2.当一个对象对使用弱引用时,若对象被废弃时,该对象会被置为空

3.不支持iOS4及以下和OS X Snow Leopard

#if 0  //强引用的话,最终obj1还会持有对象。
id obj1 = nil; //默认的是用__strong修饰
{
id obj0 = [[NSObject alloc] init];
obj1 = obj0; /**强引用持有obj0*/ NSLog(@"obj1=%@,obj0=%@",obj1,obj0); //打印结果, obj1=<NSObject: 0x7fbcf3417220>,obj0=<NSObject: 0x7fbcf3417220>
}
/**obj0已经被废弃了,但obj1还持有它*/
NSLog(@"强引用超出作用域被废弃后obj1=%@",obj1); // 弱引用超出作用域被废弃后obj1=<NSObject: 0x7fbcf3417220> #endif
#if 0 //弱引用的话,最终obj1为nil id __weak obj1 = nil; //默认的是用__strong修饰,现在这里弱引用这个对象,并不持有它 { id obj0 = [[NSObject alloc] init]; obj1 = obj0; NSLog(@"obj1=%@,obj0=%@",obj1,obj0); //打印结果, obj1=<NSObject: 0x7fbcf3417220>,obj0=<NSObject: 0x7fbcf3417220> } NSLog(@"弱引用超出作用域被废弃后obj1=%@",obj1); // 打印结果,弱引用超出作用域被废弃后obj1=(null) #endif

三.  __unsafe_unretained的使用

特点

1.当使用iOS4及以下和OS X Snow Leopard时,会用到__unsafe_unretained,主要目的是在iOS4及以下和OS X Snow Leopard中代替__weak的。

#if 1 //__unsafe_unretained的话,最终会抛出异常或恰巧正常运行。
id __unsafe_unretained obj1 = nil; //默认的是用__strong修饰,现在这里弱引用这个对象,并不持有它
{
id obj0 = [[NSObject alloc] init];
obj1 = obj0; NSLog(@"obj1=%@,obj0=%@",obj1,obj0); //打印结果, obj1=<NSObject: 0x7fbcf3417220>,obj0=<NSObject: 0x7fbcf3417220>
}
NSLog(@"__unsafe_unretained超出作用域被废弃后obj1=%@",obj1); //objc1表示变量的对象,已经被废弃(悬垂指针)!错误访问!,也就是说,最后一行的NSLog只是碰巧正常运行而已,虽然访问了已经废弃的对象,但应用程序在个别情况下 #endif

四. __autoreleasing 的使用,在ARC中不允许使用autorelease和自动释放池pool,但autorelease是真实存在的。

arc下有效的方法

@autoreleasepool {
id __autoreleasing obj = [[NSObject alloc] init]; //obj,超出释放池之后会被自动释放
}

相当于mrc下的NSAutoreleasePool

#if 0

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    //如obj,要做耗时操作,如加载大量图片等等

     id  obj = [[NSObject alloc] init];

     [objc autorelease];

    [pool drain];

#endif

除alloc/new/copy/mutableCopy创建的对象不会注册的aureleasePool外,其他的都会注册到,如__weak,其他情况即为“取得非自己生成持有的对象”,这些务必牢记,为了在使用参数取得对象时,贯彻内存管理的思考方式,我们要将参数声明附有__autorelease的修饰符指针

//***__strong修饰符和__weak修饰符类似于C++中的智能指针,std::shared_ptr和weak::shared_ptr,前者也是强引用,后者也是避免循环引用***//

不要显式调用dealloc,如【self dealloc】,下面是可行的

//------------------------ARC下内存管理规则,不能使用或不推荐使用的-----------------------//

1.对象变量不能作为C语言的结构体成员,

 struct data{
// NSMutableArray *array; //成员变量,因为这是Objective-c中故有的对象,所以不能作为成员变量。
NSMutableArray __unsafe_unretained *array; // 这样的话可以在Objective中使用,但__unsafe_unretained不属于内存管理的对象,所以会造成内存泄漏。
NSInteger name;
}data1,data2; //data1,data2是变量名
data1.name = ;
data2.name = ;
NSLog(@"结构体打印%ld,%ld",data1.name,data2.name);
//2.显式转换id与void*的转换, 通过 __bridge 可以显式转换id与void*的转换
id obj = [[NSObject alloc] init];
void *p =(__bridge void *)obj;
id obje = (__bridge id)p;

__bridge 还有两种转换,__bridge_retained(使用后对象还存在相当于retain),__bridge_transfer(使用后对象被释放,相当于release),ARC中不推荐使用

但这样是可以转换,其安全性与__unsafe_unretained类似甚至会更低,如果管理者不注意赋值对象的所有者就会因悬垂指针而导致程序崩溃

//*** 悬垂指针 :指向曾经存在的对象,但该对象已经不再存在了,此类指针称为悬垂指针。结果未定义,往往导致程序错误,而且难以检测。***/

Objective C中的ARC的修饰符的使用---- 学习笔记九的更多相关文章

  1. Java 中的 protected 访问修饰符你真的了解吗?

    protected Java 中的 protected 访问修饰符 总结 在同一个包中,类中 protected 或 default 修饰的属性或方法可以在类外被其对象 (实例) 外部访问,也可以被子 ...

  2. iOS中copy和strong修饰符的区别

    iOS中copy和strong修饰符的区别 //用copys修饰的生成的都是不可变的对象 ,如果调用可变类型方法的直接报错 @property(nonatomic,copy)NSString * cp ...

  3. 《挑战30天C++入门极限》入门教程:C++中的const限定修饰符

        入门教程:C++中的const限定修饰符 const修饰符可以把对象转变成常数对象,什么意思呢? 意思就是说利用const进行修饰的变量的值在程序的任意位置将不能再被修改,就如同常数一样使用! ...

  4. Java语言中的访问权限修饰符

    一个Java应用有很多类,但是有些类,并不希望被其他类使用.每个类中都有数据成员和方法成员,但是并不是每个数据和方法,都允许在其他类中调用.如何能做到访问控制呢?就需要使用访问权限修饰符. Java语 ...

  5. 人工智能中小样本问题相关的系列模型演变及学习笔记(二):生成对抗网络 GAN

    [说在前面]本人博客新手一枚,象牙塔的老白,职业场的小白.以下内容仅为个人见解,欢迎批评指正,不喜勿喷![握手][握手] [再啰嗦一下]本文衔接上一个随笔:人工智能中小样本问题相关的系列模型演变及学习 ...

  6. 正则表达式preg_replace中危险的/e修饰符带来的安全漏洞问题

    mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit]) /e 修饰符使 preg_rep ...

  7. C#中的默认访问修饰符

    1.命名空间下的元素的默认访问修饰符 public : 同一程序集的其他任何代码或引用该程序集的其他程序集都可以访问该类型或成员.internal : 同一程序集中的任何代码都可以访问该类型或成员,但 ...

  8. JAVA中静态修饰符static的学习(初学)

    静态修饰符static,用于修饰类中的成员变量和成员函数. 用static修饰的成员变量也可叫做类变量. 什么时候使用静态 什么时候定义静态成员变量?     当对象中出现共享数据时,将该数据定义为静 ...

  9. 理解C语言中几个常见修饰符

    写在前面 今天下午一个同事问「register」关键字是什么作用?噢,你说的是「register」啊,它的作用是……脑袋突然断片儿,我擦,啥意思来着,这么熟悉的陌生感.做C语言开发时间也不短了,不过好 ...

随机推荐

  1. js 与JQuery显示及隐藏方法

    虽然以后两种方式都能让文本信息隐藏和显示 第一种文本隐藏以后还是会占居位置, 第二种则不会占位置. <p id="p1">这是一段文本.</p> <i ...

  2. C++11之std::function和std::bind

    std::function是可调用对象的包装器,它最重要的功能是实现延时调用: #include "stdafx.h" #include<iostream>// std ...

  3. 转载:《TypeScript 中文入门教程》 11、声明合并

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 TypeScript有一些独特的概念,有的是因为我们需要描述JavaScript ...

  4. 简单Java类与XML之间的转换

    需要的jar包:xmlpull_1_0_5.jar,xstream-1.4.1.jar) 1.工具类XstreamUtil package com.learn.util; import com.tho ...

  5. UML简单例子

    平时最常用到的UML图包括:用例图.类图.序列图.状态图. 用例图 主要是描述系统具有的一个功能单元.通常包含角色和用例.角色通常表示为一个系统用户,用例通常表示为系统具有的一个功能.通过用例图我们可 ...

  6. Java基础学习总结 -- 多线程的实现

    目录: 继承Thread类 start()方法实现多线程的原理 实现Runnable接口 Thread类 与 Runnable接口 的联系与区别 多线程的实现方法: 继承Thread类 实现Runna ...

  7. 【grunt整合版】30分钟学会使用grunt打包前端代码

    grunt 是一套前端自动化工具,一个基于nodeJs的命令行工具,一般用于:① 压缩文件② 合并文件③ 简单语法检查 对于其他用法,我还不太清楚,我们这里简单介绍下grunt的压缩.合并文件,初学, ...

  8. 前端HTML规范

    HTML规范 - 整体结构 文件应以“<!DOCTYPE ......>”首行顶格开始,推荐使用“<!DOCTYPE html>”. 必须申明文档的编码charset,且与文件 ...

  9. jquery-懒加载技术(简称lazyload)

    第一:lazyLoad简介及作用 网站性能优化的插件,提高用户体验. 页面如果有很多图片的时候,当你滚动到相应的行时,当前行的图片才即时加载的,这样子的话页面在打开只加可视区域的图片,而其它隐藏的图片 ...

  10. 关于web页面性能测量指标与建议

    首先看一个图: 注:右图在我们工作中经常用到 我们专注的web性能指标有那些? 1.页面加载时间 从页面开始加载到页面onload事件触发的时间.一般来说onload触发代表着直接通过HTML引用的C ...