PART 5

news/2024/11/18 1:30:32/

便利构造函数

既然要说便利构造函数(Convenience Initializer)就不得不先提起指定构造函数(Designated Initializer)。前者是Swift特有的概念,后者是OCSwift共有的初始化对象的方式,形如:

//OC
- (instancetype)initWithXXXX {if (self = [super init]) {}return self;
}
//Swift
init(....) {//属性的初始化super.init()
}

需要明确注意的是:OC中,初始化的对象需要显示返回,并且当前对象属性的初始化需要在父类初始化后进行。而在Swift中,以上过程恰恰相反。(指定构造器中)

指定构造器正常情况下都会创建对象,而便利构造器会根据条件判断创建对象与否,对于不合理调用构造函数就可以做到减小内存开销问题。便利构造器本身不负责对象的创建,这就要求其内部必须调用当前类的指定构造器来实例化对象。所以如果要在便利构造函数中使用当前对象的属性,就需要在调用指定构造函数之后。此外,还可用extension给类扩展一个便利构造函数简化对象的创建。

NSString属性为什么用copy关键字

要说明这个观点的必要性就先说明为什么不用strongretain。它们两者都是增加原对象的引用计数,来达到持有该对象的目的。在类的关系能正确对应的情况下,即NSString对象 -> NSString类型的属性。对,当遇上NSMutableString时,情况就变糟糕了。此时使用strong或者retain,当原对象改变了之后,属性引用的对象也会随之改变。

copy是不可变的复制。针对于不可变对象,此时的复制只是浅复制。如NSArray、NSDictionary、NSString、NSSet。此时针对于被复制的对象本身,使用strongretain也不会有什么问题。当被复制的对象是可变时,复制后虽然会产生新的对象,但集合内部的元素只是增加了它的引用计数而已,元素本身没有被复制。使用LLDBexpression判断元素相等,你会得到肯定的结果。就效率和安全性来说,使用copy是毫无疑问的。

UICollectionView自定义约束实现

系统提供了一个约束来为UICollectionView实现流式布局——UICollectionViewFlowLayout,也就是网格布局。这能满足一些场景的需求,如果你想要更灵活的玩耍UICollectionView,你就需要自定义约束类来添加各种有意思的约束,这个类是UICollectionViewLayout,你需要实现如下几个方法:

// 开始时调用的方法,每次只执行一次,准备工作,不执行任何布局。一般在该方法中设定一些必要的layout的结构和初始需要的参数等。以下用官方提供的圆形布局作为讲解参考
// 调用顺序:1
- (void)prepareLayout {// 保证约束实例能正常工作[super prepareLayout];// UICollectionViewLayout持有使用它布局的UICollectionView实例CGSize size = self.collectionView.frame.size;// 获得当前单元格的数量_cellCount = [self.collectionView numberOfItemsInSection:0];// 圆环的圆心_center = CGPointMake(size.width / 2.0, size.height / 2.0);// 以UICollectionView宽高中较小值的2.5分之一作为圆环的半径_radius = MIN(size.width, size.height) / 2.5;
}// 确定collection应该占据的尺寸。注意这里的尺寸不是指可视部分的尺寸,而应该是所有内容所占的尺寸。collectionView是scrollView的子类,因此需要这个尺寸来配置滚动行为。在这个例子中,不需要滚动,就直接返回视图的尺寸。
// 2
- (CGSize)collectionViewContentSize {// NSLog(@"%f", self.collectionView.frame.size.height);return self.collectionView.frame.size;
}// 指定CGRect范围内的单元格大小和位置
// 3
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {NSMutableArray *attributes = [NSMutableArray array];// rect表示的是UICollectionView所有内容所占的矩形区域的尺寸,即在CollectionViewContentSize设定的尺寸for (NSInteger i = 0; i < _cellCount; i++) {NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];[attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];}return attributes;
}// 返回UICollectionViewLayoutAttributes控制指定的单元格大小和位置。
// 4
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];// cosf, sinf分别表示余弦函数,正弦函数attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);attributes.center = CGPointMake(_center.x + _radius * cosf(2 * M_PI * indexPath.item / _cellCount), _center.y + _radius * sinf(2 * M_PI *indexPath.item / _cellCount));return attributes;
}// 当单元格动态开始显示出来时自动调用该方法(实例化对单元格添加的约束)
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {// 设置item最初的约束,系统会以动画的形式让item完成最终的约束UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];attributes.alpha = 0.0;attributes.center = CGPointMake(_center.x, _center.y);return attributes;}// 当单元格消失的时候自动调用
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {// 设置item消失后的约束,与开始相反,系统以动画形式让item从现在的约束过渡到消失后指定的约束UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];attributes.alpha = 0.0;attributes.center = CGPointMake(_center.x, _center.y);attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);return attributes;
}

哈希表

关于哈希表(hash table)的概述或者定义这里就不阐述了,因为这样的文章比比皆是,这里主要记录一些哈希表的特性以及在iOS中如何让自定义对象可哈希化。

特性

众所周知的是objc中的字典的底层实现就是哈希表,而它在数据结构上的表现与数组是类似的,即内存空间都是连续的,它的每一元素被称为箱(bin),箱中装的就是键值对。

因此它也具有快速查找的能力,在理想的哈希函数中,无论数据体量有多大,它的一次查询操作的时间复杂度均是O(1)。它实际上会将字典中使用键(key)来找值转换成在数组中使用下标来查找值,所以这里就涉及到如果将键映射成索引下标。

其实,这个过程在理解上很简单:根据指定的规则,以给定的键来计算哈希值(hash value)h,这会是一个数量类型的值。它在哈希表中的位置会通过下面这个等式算出:

// n为哈希表中元素的个数
location = h % n

这个location就相当于数组中元素的下标。

因此就不难得出,发生键值对冲突的原因:相同的键被插入到同一哈希表中。在objc中使用字符串作为键时,发生这种情况的话,后者的插入将会无效,即结果只保留前者。一种名叫拉链法的解决方案是将属于同一箱子的键值对依次排列形成链表。

在正常情况下一个箱子中就只会有一个键值对,即负载因子(load factor:等于键值对总数除于箱子数)为1。负载因子越大表示哈希表越满,越容易发生冲突,效率就越低。一般程序语言中会设置一个阈值,当负载因子大于这个值时,哈希表会自动扩容。此时所有键值对的存放位置都可能发生改变,这个过程叫做重哈希(rehash)。此时由于需要分配新的内存空间,并将之前的键值对赋值到新的内存中,性能会明显下降。因此指定容量创建字典是个很好的决策。

自定义对象哈希化

覆写类的这两个方法:

- (BOOL)isEqual:(id)object {
    //自定义键的判等条件
}- (NSUInteger)hash {
    //尽可能保证哈希值的唯一
}

一个判等的参考示例是这样的:

- (BOOL)isEqual:(id)object {if (!object) {return NO;}if (self == object) {return YES;}if (![object isKindOfClass:[XXX class]]) {return NO;}return [self isEqualToXXX:(XXX *)object];
}- (BOOL)isEqualToXXX:(XXX *)object {//判等条件
}

这样做了之后,你的自定义对象就可以作为字典的键了。

(于2017-8-8记)


http://www.ppmy.cn/news/131477.html

相关文章

EPEL

1. EPEL EPEL(http://fedoraproject.org/wiki/EPEL) 是由 Fedora 社区打造&#xff0c;为 RHEL 及衍生发行版如 CentOS、Scientific Linux 等提供高质量软件包的项目。 详见&#xff1a;http://fedoraproject.org/wiki/EPEL/zh-cn&#xff08;官方 中文&#xff09; or https:…

[原创] STM32 USB CDC 虚拟多串口

creep 该用户从未签到 61 主题 1995 帖子 26 蝴蝶豆版主 最后登录 2018-10-19 发消息 电梯直达 楼主 发表于 2017-9-28 22:30:04 | 只看该作者 |只看大图 本帖最后由 creep 于 2017-9-28 22:37 编辑 之前一直使用STM32的CDC虚拟串口和上位机进行数据通信&#xff0c…

面对裁员潮,程序员如何安身立命

互联网企业正在降本增效。关注【融云全球互联网通信云】了解更多 最切身的体会来自大厂不绝于耳的“毕业”之声。最直接的原因是增速不再的营收、利润和流量&#xff0c;这在刚告一段落的财报季中显露无疑。 不太乐观的财报折射出的&#xff0c;是近乎饱和的市场渗透率&#xf…

stm32数据传输流程学习笔记

转自&#xff1a;http://www.eeworld.com.cn/mcu/article_2016121632400_2.html 这里主要讲设备端&#xff0c;因为我们的代码是做USB设备用的。 我们需要必须要定义了USB中断。起始在STM32的中断向量表中给USB两个中断&#xff0c;我们可以在stm32f10x.h中找到这两个中断&am…

STM32学习笔记之USB数据接收和发送流程分析

既然学习了USB&#xff0c;那就必须的搞懂USB设备与USB主机数据是怎么通讯的。这里主要讲设备端&#xff0c;因为我们的代码是做USB设备用的。 我们需要必须要定义了USB中断。起始在STM32的中断向量表中给USB两个中断&#xff0c;我们可以在stm32f10x.h中找到这两个中断&#x…

epplus word html,EPPlus简介

简介&#xff1a;Epplus是一个使用Open Office XML(Xlsx)文件格式&#xff0c;能读写Excel 2007/2010文件的开源组件 功效&#xff1a;支持对excel文档的汇入汇出&#xff0c;图表(excel自带的图表基本都可以实现)的列印 使用&#xff1a;首先应该下载Epplus的dll文件 1.添加dl…

USRP RFNoC image 开发示例

本文内容、所用开发板、配件等仅限与研发和学习使用&#xff0c;如有侵权&#xff0c;请联系我们进行删除&#xff01; 目录 一、概要 二、实验环境 1. 软件环境 2. 硬件设备 三、Adding an FFT BLOCK 1. 修改 x310_rfnoc_image_core.yml 文件 2. rfnoc_image_builder …

STM32 USB数据接收与数据发送过程

既然学习了USB&#xff0c;那就必须的搞懂USB设备与USB主机数据是怎么通讯的。这里主要讲设备端&#xff0c;因为我们的代码是做USB设备用的。 我们需要必须要定义了USB中断。起始在STM32的中断向量表中给USB两个中断&#xff0c;我们可以在stm32f10x.h中找到这两个中断&#…