字符串处理相关

字符串处理

认识字符串NSString

  • NSString 是一个Unicode编码、16位字符的字符序列
  • NSString 被定义为类,引用类型,拷贝时具有引用语义
  • 初始化方法:字面量初始化、初始化器、工厂方法。
  • NSString拥有恒定性,所有的操作无法更改字符串本身,如有更改,都是返回新值的形式
  • NSString 拥有共享机制,引用计数管理对其有特殊的管理规则。

%p表示地址

NSMutalbeString

  • NSMutableString具有可变性,NSString具有恒定性。
  • NSMutableString是NSString的子类。
  • NSMutableString不具有共享机制,NSString具有共享机制。
  • NSMutableString并不是在原有内存上直接增长,而是重新分配一个更大或更小的缓存容量存放字符。

NSString 常用操作

  • NSString:
    • 访问字符串:获取字符串字符、字符串长度、字面量、大小写转换。
    • 查询字符串:定位子串、是否包含子串、查询字符集
    • 其他操作:比较字符串、替换字符串、分解字符串。
  • NSMutableString
    • 添加字符串
    • 删除字符串
    • 修改字符串

集合类型

认识数组

  • 数组是一个有序的元素序列,支持随机存取。索引从0开始,索引访问越界会抛出运行时异常。注意与C语言数组不同。
  • NSArray的元素定义为class,引用类型,拷贝时具有引用语义
  • NSArray的元素必须是对象,即NSObject的子类
    • 如为基本数值类型,须用NSNumber封装为对象类型后,才能放入数组中。
    • 如为C语言结构类型,须用NSValue封装为对象类型后,才能放入数组中。
    • 数组元素可以是不同对象类型,可能会有类型不安全。
  • NSArray具有常量性:长度和元素指针都不能更改。但指针指向的对象内部可以更改。

常用操作

  • 数组遍历
    • 最快 -- Fast Enumeration,直接访问内存,优化索引检查,快5-10倍
    • 较慢 -- NSEnumerator遍历:索引检查+动态消息调用
    • 最慢 -- For 循环访问:索引检查+动态消息调用
  • 数组查找
    • indexOfObject 查找是否存在“值相等”的对象(类型需要实现isEqual)
    • indexOfObjectIdenticalTo查找是否存在“指针相等”的对象
  • 数组排序
    *不改变原数组(常量性),返回新数组。

使用NSMutableArray

  • NSMutableArray支持更改数组长度和元素指针。为NSArray子类。
  • NSMutableArray初始化后,会分配一个缓存容量capacity,一般大于实际元素数量,当元素长度增加时,如实际需求大于capacity,其capacity会以近似二倍的方式指数增长。伴随代价:
    • 分配新的堆内存 2*capacity
    • 将原来堆内存上的元素拷贝到新内存
    • 释放原来的堆内存
  • 最佳实践:估计好capacity,预先分配一定容量,避免以后增长
  • 尽量避免使用insertObject:atIndex;和removeObjectAtIndex;等操作,因为会改变数组元素序列,涉及大量内存拷贝操作,代价高。(假如我有这种需要呢?)

认识Set

  • NSSet是一个无序的集合,其存储的对象不能重复

  • NSSet被定义为class,引用类型,拷贝时具有引用语义

  • 常量集合NSSet,可变集合:NSMutableSet:

    • 常量性:长度和元素指针都不能改变。但指针指向的对象内部可以更改。
    • 创建NSMutableSet时用initWithCapacity提前设置capacity
  • 支持Fast Enumeration和NSEnumerator遍历,前者较快。

认识Dictionary

  • NSDictionary是一个存储key-value的无序集合,key唯一,value可重复
  • NSDictionary被定义为class,引用类型,拷贝时具有引用语义。
  • 常量集合NSDictionary,可编辑和:NSMutableDictionary:
    • 常量性:长度和元素指针都不能更改。但指针指向的对象内部可以更改。
    • 创建NSMutableDictionary时用initWithCapacity提前设置capacity
  • 支持Fast Enumeration和NSEnumerator遍历,前者较快。

自动技术引用ARC

  • 自动引用计数(Automatic Reference Counting)是Objective-C默认的内存管理机制,其针对堆上的对象,由编译器自动生成操作引用计数的指令(retain或release),来管理对象的创建与释放。
  • 那些对象受ARC管理:
    • OC对象指针
    • Block指针
    • 使用attribute((NSObject))定义的typedef
  • 那些对象不受ARC管理:
    • 值类型(简单值类型,c语言struct)
    • 使用其他方式分配的堆对象(如使用malloc分配)
    • 非内存资源

引用计数管理

  • 新创建(使用alloc, new, copy等)一个引用类型对象,引用计数为1
  • 对象引用计数增1--retain操作
    • 将对象引用赋值给其他变量或常量
    • 将对象引用赋值给其他属性或实例变量
    • 将对象传递给函数参数,或者返回值
    • 将对象加入集合中
  • 对象引用计数减1--release操作
    • 将局部变量或全局变量赋值为nil或其他值
    • 将属性赋值为nil或其他值
    • 实例属性所在的对象被释放
    • 参数或局部变量离开函数
    • 将对象从集合中删除
  • 引用计数变为0时,内存自动被释放。

自动释放池(Autorelease Pool)

  • release会导致对象立即释放。如果频繁对对象进行release,可能会造成琐碎的内存管理负担。autorelease可以将release的调用延迟到自动释放池被释放时。
  • 推荐使用自动释放池(Autorelease Pool)Block,当其结束时,所有接受autorelease消息的对象就会被立即释放(即发送release消息)
  • AppKit和UIKit框架在处理每一次事件循环迭代时,都会将其放入一个Autorelease Pool中。大多数情况,无需程序员干预。

什么时候需要手工管理Autorelease Pool

  • 编写的程序不基于UI框架,如命令行程序。
  • 在循环中创建大量临时对象,需要更早地释放,避免临时对象聚集导致内存峰值过大。
  • 在主线程之外创建新的线程,在线程开始执行出,需要创建自己的Autorelease Pool
  • 可以签到使用Autorelease Pool

类型合同:协议

认识协议Protocol

  • 协议:类型的合同约定,只描述外部接口,不提供具体实现
  • 协议可以包含以下成员:
    • 属性
    • 实例方法
    • 类方法
    • 初始化器-不常用
    • 析构器 - 不常用
  • 协议中无法包含实例变量成员
  • 协议中定义的属性本质上是访问器方法,编译器不会合成实例变量。

使用协议

  • 一个类遵守协议,需要实现协议约定的所有@required成员
    • 协议中的属性项目须在实现类的.h文件中声明(编译器合成实例变量需要)。
  • 注意编译警告信息:
    • 遵守协议后却没有实现必选协议方法时,会出现警告提示。
    • 协议类型变量被赋值非协议类型对象时,会出现警告提示。
  • 协议本质上是一种类型,可以作为声明类型,但不能创建实例。
  • 检查协议类型
    • 使用conformsToProtocol:检查对象是否实现了协议

更多协议形式

  • 协议继承
    • 一个协议可以继承一个或多个协议
    • 实现子协议的类型,也必须实现父协议中约定的成员
  • 协议组合
    • 可以使用protocol来组合多个协议
    • 实现组合协议的类型,必须实现组合协议中的每一个协议
  • 可选协议
    • 协议的某些成员可以定义为optional,不必实现。

了解常用协议

  • NSObject:包含对象的常用操作,相等、字符串表示、哈希
  • NSCopying:支持赋值的类型必须遵守该协议
  • NSMutableCopying:在NSCopying协议的基础上,支持赋值数据的可变性。
  • NSFastEnumeration:实现快速枚举for-in的类型采用。
  • NSCoding协议:支持将对线图进行编码/解码以支持对象序列化。

类别 Category

  • 类别支持在没有源代码的情况下,基于某些特定的场合,为一个类增加功能。

  • 可以添加

    • 类方法
    • 实例方法
    • 重写基类方法
  • 不能添加

    • 属性
    • 实例变量 (相当于更改类的内存模型)
    • 已存在的同名方法
  • 命名规范

    • 文件名:类名+扩展方法,如:NSString+Drawing.h/.m

扩展 Extension

  • 扩展支持在编译时、有类的源代码的前提下,向类添加功能。可以将扩展看做匿名的类别。
  • 接口定义在.m文件中@implementation钱声明,实现代码仍然在@implementation内实现。
  • 扩展支持添加一下成员:
    • 添加属性
    • 添加实例成员
    • 添加类方法
    • 添加实例方法
    • 改写属性的读写属性

使用扩展

  • 扩展实现的成员都只能在.m实现文件内部访问,在类外不可以直接访问。
  • 扩展的主要用途在于信息隐藏,隐藏一些外部无需访问、而内部实现又需要使用的属性、方法:
    • 类的主接口主要用于“对类外公开”的接口
    • 类的扩展接口用于“对类内可见”的接口。

你可能感兴趣的:(字符串处理相关)