iOS开发ObjectC内存管理

iOS Object-C辣鸡代码生成器-Python编写 本文件用于iOS object-c生成辣鸡代码,使用Python编写的工具。可以根据自己想要的内容进行修改。 立即下载

iOS开发ObjectC内存管理

我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是由系统自己管理的,放在栈上)。如果一个对象创建并使用后没有得到及时释放那么就会占用大量内存。其他高级语言如C#、Java都是通过垃圾回收来(GC)解决这个问题的,但在OjbC中并没有类似的垃圾回收机制,因此它的内存管理就需要由开发人员手动维护。今天将着重介绍ObjC内存管理。

引用计数器

在Xcode4.2及之后的版本中由于引入了ARC(Automatic Reference Counting)机制,程序编译时Xcode可以自动给你的代码添加内存释放代码,如果编写手动释放代码Xcode会报错,因此在今天的内容中如果你使用的是Xcode4.2之后的版本(相信现在朋友们用的版本都比这个要高),必手动关闭ARC,这样才有助于你理解ObjC的内存回收机制。

ObjC中的内存管理机制跟C语言中指针的内容是同样重要的,要开发一个程序并不难。但是优秀的程序则更测重于内存管理,它们往往占用内存更少,运行更加流畅。虽然在新版Xcode引入了ARC,但是很多时候它并不能完全解决你的问题。在Xcode中关闭ARC:项目属性—Build Settings–搜索“garbage”找到Objective-C Automatic Reference Counting设置为No即可。

内存管理原理

在ObjC中没有垃圾回收机制,那么ObjC中内存又是如何管理的呢?其实在ObjC中内存的管理是依赖对象引用计数器来进行的:在ObjC中每个对象内部都有一个与之对应的整数(retainCount),叫“引用计数器”,当一个对象在创建之后它的引用计数器为1,当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上加1(ObjC中调用一个对象的方法就是给这个对象发送一个消息),当调用这个对象的release方法之后它的引用计数器减1,如果一个对象的引用计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。

下面通过一个简单的例子看一下引用计数器的知识:
Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject

#pragma mark - 属性
@property (nonatomic,retain) NSString *name;
@property (nonatomic,assign) int age;

@end

Person.m

#import "Person.h"

@implementation Person

#pragma mark 重写dealloc方法,在这个方法中通常进行对象释放操作
-(void)dealloc{
    NSLog(@"dealloc method.");
    [_name release];//释放setter方法泄露的实例变量,即使没有赋值,由于_name是空指针也不会出错
    [super dealloc];//注意最后一定要调用父类的dealloc方法(两个目的:一是父
    类可能有其他引用对象需要释放;二是:当前对象真正的释放操作是在super的de
    alloc中完成的)
}

- (void)setName:(NSString *)name
{
    if(_name != name)//首先判断要赋值的变量和当前成员变量是不是同一个变量
    {
        [_name release];//释放之前的对象
        _name = [name retain];//赋值时重新retain
    }
}

- (instancetype)initWithName:(NSString *)name
                         age:(int)age
{
    self = [super init];
    if(self)
    {
        _name = name;
        _age = age;
    }
    return  self;
}
+ (id)personWithName:(NSString *)name
                 age:(int)age
{
    Person *person = [[Person alloc] initWithName:name
    age:age];
    return [person autorelease];//[p autorelease]是最完美的解决方案,既不会内存泄露,也不会产生野指针。
}

@end

main.m

#import <Foundation/Foundation.h>
#import "Person.h"

void Test1(){
    Person *person=[[Person alloc]init]; //调用alloc,引用计数器+1
    person.name=@"Kenshin";
    person.age=28;

    NSLog(@"retainCount=%lu",[person retainCount]);
    //结果:retainCount=1

    [peron release];
    //结果:调用Person的 dealloc method.



    //上面调用过release方法,person指向的对象就会被销毁,但是此时变量person中还存放着Person对象的地址,
    //如果不设置person=nil,则person就是一个野指针,它指向的内存已经不属于这个程序,因此是很危险的
    person=nil;
    //如果不设置person=nil,此时如果再调用对象release会报错,但是如果此时person已经是空指针了,
    //则在ObjC中给空指针发送消息是不会报错的
    [person release];
}

void Test2(){
    Person *person=[[Person alloc]init];
    person.name=@"Kenshin";
    person.age=28;

    NSLog(@"retainCount=%lu",[person retainCount]);
    //结果:retainCount=1

    [person retain];//引用计数器+1
    NSLog(@"retainCount=%lu",[person retainCount]);
    //结果:retainCount=2

    [person release];//调用1次release引用计数器-1
    NSLog(@"retainCount=%lu",[person retainCount]);
    //结果:retainCount=1
    [person release];
    //结果:调用Person的 dealloc method.
    person=nil;


}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Test1();
        Test2();
    }
    return 0;
}

在上面的代码中我们可以通过dealloc方法来查看是否一个对象已经被回收,如果没有被回收则有可能造成内存泄露。dealloc 才是释放内存方法, 永远不要手动调用这个方法, 系统会再引用计数为0的时候, 自动调用。手动管理内存有时候并不容易,因为对象的引用有时候是错综复杂的,对象之间可能互相交叉引用,此时需要遵循一个法则:谁创建,谁释放。如果一个对象被释放之后,那么最后引用它的变量我们手动设置为nil,否则可能造成野指针错误,而且需要注意在ObjC中给空对象发送消息是不会引起错误的。

野指针错误形式在Xcode中通常表现为:Thread 1:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)错误。因为你访问了一块已经不属于你的内存。

注意setter方法、dealloc方法以及便利构造器的实现。
dealloc方法:

-(void)dealloc{
    NSLog(@"dealloc method.");
    [_name release];
    //因为age为int类型,并不在堆区开辟内存,因此不用对age进行内存管理
    [super dealloc];
}

在Person对象在释放的时候,需要将属性的setter方法创建是的实例变量给释放,否则属性所指向的内存引用计数不-1,会出现内存泄露,如果没有赋值,由于该属性是空指针也不会出错。注意最后一定要调用父类的dealloc方法(两个目的:一是父类可能有其他引用对象需要释放;二是:当前对象真正的释放操作是在super的dealloc中完成的)。

setter方法:

//setter方法1
- (void)setName:(NSString *)name
{
    _name = name;
}

//setter方法2
- (void)setName:(NSString *)name
{
    if(_name != name)//首先判断要赋值的变量和当前成员变量是不是同一个变量
    {
        [_name release];//释放之前的对象
        _name = [name retain];//赋值时重新retain
    }
}

仔细考虑两种setter方法的不同,在setter方法1中直接将_name指向name,那么_name之前所指的内存的引用计数不会-1,_name新指向的内存的引用计数不会+1,内存管理出错!使用方法2就不会出现内存泄露。
便利构造器:

+ (id)personWithName:(NSString *)name
                 age:(int)age
{
    Person *person = [[Person alloc] initWithName:name
    age:age];
    return [person autorelease];
}

在便利构造器中,由于使用了alloc方法,对象的引用计数会+1,因此需要对对象使用release方法,但如果在方法里面就调用release方法,在return person时会crash,因此使用return [person autorelease]是最完美的解决方案,既不会内存泄露,也不会产生野指针。

自动释放池

在ObjC中也有一种内存自动释放的机制叫做“自动引用计数”(或“自动释放池”),与C#、Java不同的是,这只是一种半自动的机制,有些操作还是需要我们手动设置的。自动内存释放使用@autoreleasepool关键字声明一个代码块,如果一个对象在初始化时调用了autorelease方法,那么当代码块执行完之后,在块中调用过autorelease方法的对象都会自动调用一次release方法,上文中便利构造器中就使用到了autorelase方法。这样一来就起到了自动释放的作用,同时对象的销毁过程也得到了延迟(统一调用release方法)。

autorelease方法:未来的某一时刻引用计数减1。如果内存之前引用计数为4,autorelease之后仍然为4,未来某个时刻会变为3。何时-1,取决于autoreleasepool。

NSAutoreleasePool *pool= [[NSAutoreleasePool alloc]init];
Person *person = [[Person alloc]init];//retainCount为1
[person  retain];//retainCount为2
[person autorelease];//retainCount为2,未来的某个时刻释放
[pool release];//此时 autorelease的对象引用计数-1
NSLog(@”%d”,[person retainCount]);//打印结果为1

NSAutoreleasePool *pool= [[NSAutoreleasePool alloc]init];和[pool release];就像一对括号,[xxx autorelease];必须写在两者之间。
[xxx autorelease];出现在了两者之间,pool就会把接收autorelease的对象给保存起来(以栈的方式,把对象压入栈)
当[pool release];的时候,pool会向之前保存的对象逐一发送release消息(对象出栈,越晚autorelease的对象,越早接收release消息)。
在iOS5之后,不再推荐使用NSAutoreleasePool类,使用@autoreleasepool{}替代。
之前写在NSAutoreleasePool *pool= [[NSAutoreleasePool alloc]init];和[pool release];之间的代码,需要写在@autoreleasepool{}的大括号里。
出了大括号,自动释放池才向各个对象发送release消息。

Person *person = [[Person alloc] init];
    @autoreleasepool {
        [person retain];/* 引用计数+1 , 为:2 */

        [person autorelease];
        NSLog(@"%ld",[person retainCount]);/* autorelease 引用计数不是立即 -1, 在未来的某个时刻 -1 */
    }
    NSLog(@"%ld",[person retainCount]);/* 离开autorelease 释放池之后, 引用计数-1 */

对于自动释放池简单总结一下:
autorelease方法不会改变对象的引用计数器,只是将这个对象放到自动释放池中;
自动释放池实质是当自动释放池销毁后调用对象的release方法,不一定就能销毁对象(例如如果一个对象的引用计数器>1则此时就无法销毁);
由于自动释放池最后统一销毁对象,因此如果一个操作比较占用内存(对象比较多或者对象占用资源比较多),最好不要放到自动释放池或者考虑放到多个自动释放池;
ObjC中类库中的静态方法一般都不需要手动释放,内部已经调用了autorelease方法。

Word中 Go to endnote 出现闪退问题解决办法 阅读详情

相关推荐

Nornir自动化简单介绍-网络设备信息收集

作为网工,学会通过执行脚本,可以自动化的完成日常一些设备相关配置或信息收集等工作,可以说是事半功倍。 Nornir就是这样一个自动化网络运维工具。按照官网上的说明: Nornir是用python编写的自动化框架,可与python一起使用。Nornir旨在通过提供一个纯Python框架来解决这些问题。 详细参考: Github GitHub - nornir-automation/nornir: Pluggable multi-threaded framework with inventory .

Gun&rose 7806

object-c 垃圾回收机制

垃圾回收 在Objective-C 2.0中引入了垃圾回收机制(自动管理内存),在工程设置里设置Objective-C Garbage Collection为Required[-fobjc-gc-only]就可以使用垃圾回收机制。 启用垃圾回收机制后,通常的内存管理命令都变成了空操作指令,不执行任何操作。 Objective-C的垃圾回收机制是一种继承性的垃圾回收器,垃圾回收器定期...

349

Material Studio 2024安装避坑指南:从证书配置到权限设置的完整解决方案

本文详细解析了Material Studio 2024的安装流程,从环境准备到权限优化的完整解决方案。针对证书配置、系统权限和计算服务等常见问题,提供了12个关键风险点的避坑指南,帮助科研工作者高效完成安装,提升材料模拟工作的效率。

moon9的博客 774

iOS Objective-C 中是否支持垃圾回收机制

//联系人:石虎  QQ: 1224614774昵称:嗡嘛呢叭咪哄 一、OC 回收机制概念 1.OC是支持垃圾回收机制的(Garbage collection简称GC), 2.macOS开发中是支持的,但是iOS中,是不支持GC的。 3.iOS开发只支持手动内存管理和ARC,Mac开发支持GC垃圾回收机制, 18.8之后弃用了GC, 对剑使用ARC 4.iOS开发是

石虎 3625

避坑指南:QT Creator报Unknown module(s) in QT: serialport的5种解决方法

本文详细解析了Qt Creator报'Unknown module(s) in QT: serialport'错误的5种解决方法,包括检查Qt版本兼容性、安装缺失组件、配置Kit环境等。针对Windows和Linux平台提供具体操作步骤,帮助开发者快速解决串口通信模块问题,提升开发效率。

weixin_29197051的博客 157

Matlab2021a破解版安装与激活实战教程(含详细步骤截图)

本文详细介绍了MATLAB R2021a的正版安装流程与核心功能优化,包括系统要求、安装步骤、性能调优及深度学习工具箱的应用。通过实战教程和代码示例,帮助用户高效搭建开发环境并掌握关键技术,特别适合工程计算与科学研究的专业人士。

vvv99的博客 461

iOS为什么选择了Object-C?

公众号"码农翻身"注: 本文是《Android为什么选择了Java》的姐妹篇。地球人都知道,iOS 最初的开发语言是Object-C (当然现在Swift流行起来了), ...

码农翻身 821

AIO-1126-JD4(RV1126)蓝牙通讯(BLE)

AIO-1126-JD4采用了正基科技推出的一款集成WiFi、蓝牙功能的模组AP6236,支持高速(HS)功能的蓝牙 4.0,集成了 1.5 类功率放大器(PA),并支持低功耗蓝牙(BLE)。提到正基就不得不提下博通。博通和正基是芯片技术与模块制造方面的合作关系,正基科技是中国台湾的公司,在无线通信模块领域有一定的市场份额,博通则是全球领先的有线和无线通信半导体公司。正基把包含博通关键IP的核心芯片和自家的射频部分等封装在一起,即SIP(System In Package)。

w1820020635的博客 1123

iOS - 代码查看控制台打印内存使用情况:

1.先导入: #import 2.写此方法.单位为兆(M)。 void report_memory(void) { struct task_basic_info info; mach_msg_type_number_t size = sizeof(info); kern_return_t kernr = task_info(mach_task_self(), TAS

ifziv 3149

FAST-LIVO2 源码精读(一):系统总览——从 LIO 到 LIVO 的多传感器融合架构

本文是「FAST-LIVO2 激光-惯性-视觉里程计源码精读」专栏的开篇。全专栏共 18 篇,锚定香港大学 MaRS 实验室 2025 年 1 月开源的官方代码,逐模块剖析这套登上 T-RO’24 的多传感器融合系统。开篇先建立全局认知:FAST-LIVO2 所要解决的问题、整体框架的构成,以及源码主线的数据流动。

PX4-SLAM-PNC 598

(BS ISO 11898-1:2015)CAN_FD 总线协议详解1- 基本概念描述

本文对can总线协议做了详细的讲解,can协议里面的每一个知识点都做了详细且举一反三的论述,读了本文可以不用读can协议了。

zhangziranzm的博客 2314

objectC 内存管理

介绍objectc中内存管理 内存管理是objectc的核心部分,一个好的objectc程序员必须对它的内存管理机制有很好的理解并付诸于代码的实现上。糟糕的内存管理会引起以下两点致命问题 1. 无尽的使用内存不进行适当的释放导致内存泄露程序崩溃 2. 内存管理不当使程序中引用非法的内存取到非法数据或程序直接崩溃 ios开发内存管理这部分内容分成以下几部分来进行阐述 一  Obje

jacky_jin的专栏 829

基于YOLOv11的建筑图纸物体检测系统设计与实现

包含多种建筑平面图,标注了墙体、门窗等元素:CAD格式的建筑图纸数据集:专门针对建筑元素的标注数据集自定义数据集:使用LabelImg等工具自行标注的建筑图纸本文以FloorPlanDataset为基础,结合部分自定义标注数据构建混合数据集。wall (墙体)door (门)window (窗)stair (楼梯)furniture (家具)text (文字标注)dimension (尺寸标注)column (柱子)

YOLO 536

douyin-ios-objectc性能优化:如何实现流畅的视频列表滚动体验

在移动应用开发中,视频列表的流畅滚动体验直接影响用户留存率。douyin-ios-objectc作为抖音iOS平台的Objective-C实现,其视频列表性能优化方案具有重要参考价值。本文将从单元格复用、图片加载优化、预加载策略三个维度,解析如何打造60fps的丝滑滚动体验。 ## 核心优化策略一:单元格复用机制 抖音视频列表采用全屏垂直滑动布局,每个视频占据一整个屏幕高度。这种设计对内存管理

gitblog_00024的博客 476

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

[ObjectC]Objective-C内存管理之---属性修饰词

iOS经典面试题总结--内存管理 : 分别写一个setter方法用于完成@property (nonatomic,retain)NSString *name和@property (nonatomic,copy) NSString *name -(void)setName:(NSString *)name { [name retain]; [_name release];

超越 1008

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IOS开发学习笔记(一)——ObjectC语言快速入门

需要学习IOS开发,首先需要掌握的是ObjectC语言。由于我之前接触过多年的C/C++和Java,所以很多地方我只需要理解ObjectC和他们的不同即可。当然为了能够系统的学习,建议您还是仔细学习一遍ObjectC语言,我这里并不会讲述太多原理方面的内容,只会尽量将实际编码中需要注意的内容列出: 基本的关键字,类似于for/case/switch等等,大家都是差不多的;“@”标识符标识

「行到水穷处,坐看云起时」 4960

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

转载大神IOS开发系列【4】--ObjectC语言之基础知识

转载自:http://www.cnblogs.com/kenshincui/p/3861300.html 概览 前面我们已经用了几章内容进行C语言介绍,当然要通过几篇文章完整的介绍C语言的知识是不太现实的,例如C语言的文件操作、内存申请等我们都没有重点介绍,当然核心知识点基本都已经提到了,后面有时间我们会继续扩充。今天我们正式开始学习Objective-C,以后简称“ObjC”,O

yuxikuo_1的专栏 602

IOS基础:IOS及ObjectC基础知识

@import url(http://www.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); 1 变量声明 变量的声明与C语言一样,在变量名前加类型名 以下这些数据类型是从C语言中直接拿来使用的: int n; unsigned int n; c...

weixin_30243533的博客 176

IOS开发系列—Objective-C之内存管理详解

2014-07-26 17:10 by KenshinCui, 29403 阅读, 22 评论, 收藏,  编辑 概述 我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是由系统自己管理的,放在栈上)。如果一个对象创建并使用后没有得到及时释放那么就会占用大量内存。其他高级语言如C#、Java都是通

li唱的专栏 804

iOS开发核心语言Objective C —— 所有知识点总结

1. OC中主要开发在什么平台上的应用程序? 答:可以使用OC开发Mac OS X平台和iOS平台的应用程序 2. OC中新增关键字大部分是以什么开头? 答:OC中新增关键字大部分是以@开头 3. OC中新增加了那些数据类型? 答:Block类型 指针类型(Class, id类型) 空类型 特殊类型(SEL, nil) 4. 面向对象特性是什么? 答:继承性,封装性,多态性

求知若渴,虚心若愚,努力前行,未来可期。 5571

douyin-ios-objectc UITableView多视频源自动播放的5个关键步骤

抖音iOS Object-C版作为一款流行的短视频应用,其核心功能之一就是在UITableView中实现多视频源的自动播放。本文将详细介绍实现这一功能的5个关键步骤,帮助开发者快速掌握相关技术要点。 ### 1. 视频播放器核心组件构建 首先需要构建一个高效的视频播放器核心组件。在项目中,`AVPlayerManager`和`AVPlayerView`是实现视频播放的关键类,它们位于`Douyi

gitblog_00143的博客 451

Objective-C_内存管理(一)

一、内存管理的⽅式大家都去过图书馆,而图书馆里的书是可以借出的。我们来设想这样一个场景,大家都去借书,但是从来没有人去还书,那么最后,这个图书馆会因为无书可借而倒闭,每个人都没法再使用图书馆。计算机也是这样,当程序运行结束时,操作系统将回收其占用的资源。但是,只要程序运行就会占用资源,如果不进行清理已经不用的资源,资源最终将被耗尽,程序将崩溃。学会内存管理我们就明白什么时候由你释放对象,什么时候你不

谁见过风的专栏 1038

ios学习--Object-C中的内存管理

免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作! 注:本教程由北方和我本人合作翻译。 教程截图: 当我检查其他开发人员的代码时,似乎最常见的错误总是围绕在以Object-C中的内存管理为中心。如果您使用的语言是java或

yanfangjin的专栏 2033

json到objectc互转的类,自动枚举类属性

给个主先类,所有的model类型只要继承,声明属性即可,会自动具有json objectc的转化功能 注意:后台是java的springmvc框架,前台用的时asihttprequest库和SBJson库 子类的属性不需要写dealloc方法,主先类会自动释放对象。 调用initWithDictonary:(NSDictionary *)dict 可以将json转化成需要的model类

仰望星空 1796

JAVA转IOS开发指南

一. object c及其他基本概念: 1) Object -C使用#import代替#include 2) Object -C预设文件后缀名是.m, Object c++的后缀是.mm 3) 类的声明和定义:    声明: @interface Class: Parent  { }    @end    实现:   Implementation以@implement

qaz13177_58_的专栏 3731
上一篇: iOS开发调用短信、邮件、通讯录等应用
下一篇: iOS开发TTS技术即文本转语音
mengjun_win
博客等级 码龄11年 8粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值