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方法。

OpenFOAM-多孔介质模型(porous media) 文章目录一、多孔介质(porous media)二、使用步骤1.达西定律2.Darcy-Forchheimer3.OpenFOAM fvOptions4.paraview动画每帧显示时间(Annotate Time)5.参考内容总结 一、多孔介质(porous media) 在流体力学中,流体流经多孔介质是指流体流经多孔介质时的行为方式,如海绵或木材,或使用沙子或其他多孔材料过滤水。 我们将展示如何设置多孔层,并使用OpenFOAM模拟流体通过该介质。 二、使用步骤 1.达西定律 达西定律最初是由达西通. 阅读详情

相关推荐

从零完成 STM32 + ESP-01S + 云服务器 TCP 通信测试

STM32 通过 USART3 控制 ESP-01S 接入手机 2.4 GHz 热点,随后连接公网云服务器 8.152.204.86:9002。云端在同一 TCP 连接中连续收到 seq=1~6 的测试报文,5 个发送间隔平均约 5.4 秒,说明本次 TCP 上行链路已经打通。

weixin_51387720的博客 312

object-c 垃圾回收机制

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

349

老司机避坑指南:UC3842自举驱动电路发热严重?这样选C39/C37电容值最稳

本文针对UC3842自举驱动电路发热严重的问题,深入剖析了驱动波形边沿速度与损耗的矛盾根源。通过实测数据与热成像分析,重点阐述了关键电容C39/C37的选型策略,提供了从经验公式到量化计算的优化方法,帮助工程师在发热与效率间找到最佳平衡点,并探讨了分立方案与专用驱动IC的适用场景。

lambda的博客 747

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

银河麒麟V10开机卡Logo?别慌,手把手教你进单用户模式修复(附详细命令)

本文详细解析银河麒麟V10操作系统启动时卡Logo的故障原因,并提供进入单用户模式的完整解决方案。通过GRUB引导菜单修改启动参数,执行文件系统检查、图形服务修复等关键命令,帮助用户快速恢复系统正常运行,适用于运维人员和普通用户应对紧急启动问题。

weixin_30522183的博客 392

置顶必读(1) | 《YOLOv26实战:从入门到深度优化》专栏导读与完整目录导航(持续更新中)

🏆 本文收录于 《YOLOv26实战:从入门到深度优化》 专栏。 本专栏系统梳理并持续复现 YOLOv26 官方特性、核心改进、多任务支持、部署优化与行业落地,内容坚持 持续更新 + 深度拆解 + 工程落地导向,不仅讲“怎么用”,更讲“为什么这样设计、如何真正落地到项目中”。

**My Coding Family** 9万+

iOS为什么选择了Object-C?

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

码农翻身 821

光斑定位 - MATLAB实现

光斑定位是一种常见的图像处理任务,它涉及到在图像中准确定位光斑或亮点的位置。在本篇文章中,我们将使用MATLAB来实现光斑定位的算法,并提供相应的源代码。希望本文提供的MATLAB代码和步骤能够帮助您实现光斑定位任务。通过这些代码,您可以在MATLAB环境中轻松地定位光斑,并在图像上进行可视化展示。这样,我们就完成了光斑定位算法的MATLAB实现。通过以上步骤,我们可以得到一个在光斑位置上标记的图像,从而实现了光斑的准确定位。光斑定位 - MATLAB实现。

qq_39605374的博客 764

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

AgentScope Java 2.0 项目实战:从零构建企业级自主Coding Agent

本文基于 AgentScope Java 框架,完整拆解两个生产级 AI Agent 项目的从零开发全过程。其一是企业级自主编码机器人(agentscope-codingagent),支持 Issue→PR 自动实现、PR Code Review、Docker 沙箱隔离执行与多通道接入;其二是个人 AI 助手管理平台(agentscope-paw),采用 Spring Boot + React 全栈架构,支持多 Agent、技能市场与多 IM 通道。

program哲学 839

SAP 系统和银行系统通过 SM2 加密算法进行集成

SM2 是基于椭圆曲线离散对数问题(ECDLP)的一种公钥密码算法。椭圆曲线加密的核心原理,是利用了一个数学难题:在椭圆曲线群上,已知曲线上两点的运算结果,逆向推导出这两个点的具体信息是非常困难的。这样的复杂度使得基于椭圆曲线的密码体制比传统的 RSA 更加难以破解。在 SM2 加密中,公钥和私钥的生成与传统的椭圆曲线加密类似。选择一个椭圆曲线和一个基点 P。使用私钥 d,计算公钥 P’ = d * P。私钥 d 保密,而公钥 P’ 可公开分发,用于加密数据。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1212

objectC 内存管理

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

jacky_jin的专栏 829

华为OD机试 - 文件存储系统的排序 - 深度优先搜索dfs(Java 双机位C卷 200分)

华为OD机试 双机位C卷题库疯狂收录中,刷题。

学Java,找哪吒 719

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

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

gitblog_00024的博客 476

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

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

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

超越 1008

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

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

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

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

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

转载大神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、付费专栏及课程。

余额充值