OC基础语法(六)---内存管理(二)

本文详细介绍了iOS开发中的ARC内存管理特性,包括其原理、优势、判断准则、指针类型、循环引用解决方法以及如何使用Block进行代码保存与执行。同时,还探讨了协议在iOS开发中的应用,包括其基本用途、声明方式、注意事项等。



一、ARC

简介:ARC是自ios 5 之后增加的新特性,完全消除了手动管理内存的繁琐,编译器会自动在适当的地方插入retain、release、autorelease语句。你完全不需要担心内存,因为编译器为你处理了一切。

ARC 是编译器特性吗,而不是ios运行时的特性,它也不是类似于其他语言中的垃圾收集器。因为ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化

ARC判断准则:只要没有强指针指向的对象,就会释放对象。

指针分两种:

1.强指针:默认所有实例变量和局部变量都是Strong指针;

2.弱指针指向的对象被回收后,弱指针会自动变为nil指针,不会引发野指针

          错误

ARC特点:

1.不能调用release、retain、autorelease、retainCount

2.可以重写dealloc,但是不能调用[super dealloc]

3.@property参数:

  *strong:成员变量是强指针(适用于OC对象);

  *weak:成员变量是弱指针(适用于OC对象);

  *assign:适用于非OC对象类型;

4.以前的retain改为strong。

    ARC循环引用解决方案:一端用strong;一端用weak。     

二、Block

作用:用来保存一段代码。苹果官方建议尽量多用block。在多线程、异步

      任务、集合遍历、集合排序、动画转场用的很多。

block标志: ^ .

block和函数很相像:

1.可以保存代码;

2.有返回值;

3.有形式参数;

4.调用方法一样。

注:block还可以作为函数参数或者函数的返回值。

block定义:

int (^MySum)(int, int) = ^(int a, int b

{

       return a+b;

     };

     定义了一个MySumblocks对象,它带有两个int参数,返回int。等式右边就是blocks的具体实现.

调用block: int c = MySum(10,11);

    Block可以访问局部变量,但是不能修改。

    int sum 10;

   int (^MyBlock)(int) = ^(int num) 

   {

                sum++;//编译报错

                return num * sum;

    };

    如果要修改就要加关键字:__block

     __block int sum 10;

Block和指向函数的指针的比较:

    1.定义函数指针:

    int (*myFn)();

     定义Block

    int (^MyBlocks)(int,int);

    2.调用函数指针:

    (*myFn)(10, 20);

      调用Block

    MyBlocks(10, 20);

使用typedef定义block类型:(参考typedef指向函数的指针)

(1)typedef int(^MyBlock)(int,int);

MyBlock sumBlock = ^(int a,int b)

{  return a+b; };

(2)MyBlock minusBlock;

       minusBlock = ^(int a,int b) 

      {  return a-b;  };

三、protocol(协议)

基本用途:

1.可以用来声明一大堆方法(不能声明成员变量);

2.只要某个类遵守了这个协议,就相当于拥有这个协议中所有的方法声明;

3.只要父类遵守了某个协议,就相当于子类也遵守了。

 

协议的声明类似于类接口的声明,有一点不同的是,协议没有父类,并且不能定义成员变量

下面的例子演示了只有一个方法的协议的声明:

@protocol MyProtocol

//@required/@optional

- (void)myProtocolMethod;

@end

协议中的方法声明的关键字:(主要是为了方便程序员之间的交流)

1.@required(默认):要求实现,如果没有实现,会有警告;

2.@optional:不要求实现,怎样都不会有警告。   

协议是多个类共享的一个方法列表,协议中列出的方法没有相应的实现。如果一个类采用MyProtocol协议,则必须实现名为myProtocolMethod 的方法

通过在@interface 行的一对尖括号<...>内列出协议名称,可以告知编译器你正在采用一个协议。这项协议的名称放在类名和它的父类名称之后,

如下所示:

@interface AddressBook: NSObject <myProtocol>

这说明, AddressBook 是父类为AddressBook 的对象,并且它遵守myProtocolMethod 协议在AddressBook 的实现部分,编译器期望找到定义的myProtocolMethod 方法。

如果采用多项协议,只需把它们都列在尖括号中,用逗号分开:

@interface AddressBook: NSObject < myProtocol , yourProtocol >

以上代码告知编译器AddressBook 类采用myProtocolMethod 和yourProtocolMethod 协议。这次,编译器将期望在AddressBook 的实现部分看到为这些协议列出的所有方法的实现。

有关协议的注意事项:

A、如果一个类遵守某项协议,那么它的子类也遵守该协议。

B、协议不引用任何类,它是无类的(classless)。任何类都可以遵守某项协议。

C、限制对象类型:

   通过在类型名称之后的尖括号中添加协议名称,可以借助编译器的帮助来检  

   查变量的一致性,如下:

   id <Drawing> currentObject;

   这告知编译器currentObject 将包含遵守Drawing 协议的对象。如果向 currentObject 指派静态类型的对象,这个对象不遵守Drawing 协议,编译器将给出warning。

   再次提到id 类型,如果向currentObject 指派一个id 变量,不会产生这条消息,因为编译器不知道存储在id 变量中的对象是否遵守Drawing 协议。

D、如果这个变量保存的对象遵守多项协议,则可以列出多项协议,如下:

   id <Drawing, Drawing 1> currentObject;

E、协议间的遵守:例如:

   @protocol Drawing3D <Drawing>

   说明Drawing3D 协议也采用了Drawing 协议。因此采用Drawing3D 协议的类都必须实现此协议列出的方法,以及Drawing 协议的方法。

   基协议:任何协议都要遵守基协议。

   基类遵守了基协议,所有类继承基类,也遵守基协议。

F、分类也可以采用一项协议,如:

@interface Fraction (stuff) <NSCopying, NSCoding>

此处,Fraction 拥有一个分类stuff,这个分类采用了NSCopying 和NSCoding 协议。

注:1.@property中声明的属性也可做一个遵守协议的限制:

      @property  (nonatomic,strong)类名<协议名>  *属性名;

    2. 协议可定义在单独的.h文件中,也可定义在类中:

      (1)如果这个协议只用在某个类中,应该把协议定义在类中;

      (2)如果这个协议用在很多个类中,应该把协议定义在单独.h文件中。

    另外:分类可定义在单独的.h文件中,也可以定义在原来类中,一般都定义在.h文件中,定义在原来文件中的分类,只要求看懂代码。

四、练习

代理模型设计:

Person.h:

#import <Foundation/Foundation.h>

#import "TiketDelegate.h"

@interface Person : NSobject <TiketDelegate>

- (void)BuyTiket;

@property(nonatomic,retain) id<TiketDelegate> delegate;

@end

Person.m:

#import "Person.h"

@implementation Person

- (void)BuyTiket

{

  double monkey = [_delegata tiketMonkey];

  int number = [_delegate tiketNumber];

  NSLog(@"找到一个代理,询问票价是:%f,剩余张数是:%d",monkey,number);

}

- (void)dealloc

{

   [_delegate release];

   [super dealloc];

}

@end 

TiketDelegante.h:

     #import <Foundation/Foundation.h>

    @protocol TiketDelegate <NSobject>

     @required

     - (double)tiketMonkey;

 

    - (int)tiketNumber;

@end

Agent.h:

     #import <Foundation/Foundation.h>

     #import "TiketDelegate.h"

     @implementation Agent : NSobject <TiketDelegate>

@end

Agent.m:

#import "Agent.h"

@implementation Agent

- (double)TiketMonkey

{

  return 100;

- (int)TiketNumber

{

  return 10;

}

@end

main.m:

#import <Foudation/Foundation.h>

#import "Person.h"

#impiort "Agent.h"

int main()

{

  @autoreleasepool{

   Person *p = [[[Person alloc] init] autorelease];

   Agent *a = [[[Agent alloc] init] autorelease];

 

   p.delegate = a;

   [p BuyTiket];

                 }



(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值