PART 5

本文介绍了Swift中的指定构造函数与便利构造函数的区别,探讨了OC与Swift中构造函数的不同之处。同时,深入解析了UICollectionView自定义约束实现方法,包括UICollectionViewLayout的重要方法及其实现细节。

便利构造函数

既然要说便利构造函数(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记)

内容概要:本文详细介绍了一个基于Java和Vue的联邦学习隐私保护推荐系统的设计与实现。系统采用联邦学习架构,使用户数据在本地完成模型训练,仅上传加密后的模型参数或梯度,通过中心服务器进行联邦平均聚合,从而实现数据隐私保护与协同建模的双重目标。项目涵盖完整的系统架构设计,包括本地模型训练、中心参数聚合、安全通信、前后端解耦、推荐算法插件化等模块,并结合差分隐私与同态加密等技术强化安全性。同时,系统通过Vue前端实现用户行为采集与个性化推荐展示,Java后端支撑高并发服务与日志处理,形成“本地训练—参数上传—全局聚合—模型下发—个性化微调”的完整闭环。文中还提供了关键模块的代码示例,如特征提取、模型聚合、加密上传等,增强了项目的可实施性与工程参考价值。 适合人群:具备一定Java和Vue开发基础,熟悉Spring Boot、RESTful API、分布式系统或机器学习相关技术,从事推荐系统、隐私计算或全栈开发方向的研发人员。 使用场景及目标:①学习联邦学习在推荐系统中的工程落地方法;②掌握隐私保护机制(如加密传输、差分隐私)与模型聚合技术的集成;③构建高安全、可扩展的分布式推荐系统原型;④实现前后端协同的个性化推荐闭环系统。 阅读建议:建议结合代码示例深入理解联邦学习流程,重点关注本地训练与全局聚合的协同逻辑,同时可基于项目架构进行算法替换与功能扩展,适用于科研验证与工业级系统原型开发。
源码来自:https://pan.quark.cn/s/a4b39357ea24 遗传算法 - 简书 遗传算法的理论是根据达尔文进化论而设计出来的算法: 人类是朝着好的方向(最优解)进化,进化过程中,会自动选择优良基因,淘汰劣等基因。 遗传算法(英语:genetic algorithm (GA) )是计算数学中用于解决最佳化的搜索算法,是进化算法的一种。 进化算法最初是借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传、突变、自然选择、杂交等。 搜索算法的共同特征为: 首先组成一组候选解 依据某些适应性条件测算这些候选解的适应度 根据适应度保留某些候选解,放弃其他候选解 对保留的候选解进行某些操作,生成新的候选解 遗传算法流程 遗传算法的一般步骤 my_fitness函数 评估每条染色体所对应个体的适应度 升序排列适应度评估值,选出 前 parent_number 个 个体作为 待选 parent 种群(适应度函数的值越小越好) 从 待选 parent 种群 中随机选择 2 个个体作为父方和母方。 抽取父母双方的染色体,进行交叉,产生 2 个子代。 (交叉概率) 对子代(parent + 生成的 child)的染色体进行变异。 (变异概率) 重复3,4,5步骤,直到新种群(parentnumber + childnumber)的产生。 循环以上步骤直至找到满意的解。 名词解释 交叉概率:两个个体进行交配的概率。 例如,交配概率为0.8,则80%的“夫妻”会生育后代。 变异概率:所有的基因中发生变异的占总体的比例。 GA函数 适应度函数 适应度函数由解决的问题决定。 举一个平方和的例子。 简单的平方和问题 求函数的最小值,其中每个变量的取值区间都是 [-1, ...
<think>好的,我现在需要帮助用户查找关于PLCopen Part 5的技术规范和实现方法。首先,我得回忆一下PLCopen的相关知识。PLCopen是一个专注于工业自动化编程标准的组织,他们的标准帮助统一不同厂商的PLC编程,提高兼容性。用户提到的Part 5可能属于运动控制规范的一部分,因为之前提到的引用[3]提到了PLCopen的运动控制规范。 接下来,用户提供的引用中有三个相关的引用。引用[1]提到OPC UA为PLC推荐了配套规范,包括DI和PLCopen NodeSets。引用[2]关于EtherCAT和CiA402规范,涉及运动控制的状态机和参数映射。引用[3]则详细说明PLCopen的运动控制规范的优势,如遵循行业标准、优化算法和易集成性。 现在需要确定PLCopen Part 5的具体内容。根据PLCopen官网的信息,Part 5属于运动控制规范的一部分,可能涉及协调运动和轴组控制。比如,Part 4是运动控制基础,Part 5可能更高级。需要确认每个部分的具体内容,可能需要查阅官网或技术文档。 用户需要技术规范和实现方法。规范方面,应该建议查阅PLCopen官网的文档,特别是Part 5的PDF。实现方法方面,可能需要参考OPC UA的配套规范,比如引用[1]提到的NodeSets,以及结合运动控制器的实现,如引用[3]提到的算法和集成方法。另外,引用[2]中的CiA402规范可能与轴控制相关,可能和Part 5的轴组协调有关联。 还需要考虑用户可能的实际应用场景,比如他们可能在开发多轴协调运动的系统,需要了解如何通过PLCopen的标准来实现。这时候,实现方法可能涉及使用支持Part 5的软件库,比如CODESYS或TwinCAT,这些平台通常遵循PLCopen规范,并提供相应的函数块和接口。 最后,生成相关问题时要围绕Part 5的细节、与其他部分的关系、具体实现案例以及相关技术如OPC UA和EtherCAT的结合应用。确保问题能引导用户深入理解Part 5的应用和实现。</think>### 关于PLCopen Part 5的技术规范与实现方法 PLCopen Part 5是PLCopen组织发布的运动控制规范中的一部分,主要涉及**运动控制的功能模块与标准化接口**。以下是其核心内容和实现方法的分析: --- #### **1. PLCopen Part 5 的核心内容** PLCopen运动控制规范分为多个部分,Part 5重点围绕**轴组协同控制**和**复杂运动轨迹规划**展开,具体包括: - **轴组同步控制**:定义多轴协同运动的接口和状态管理,例如机械臂的轨迹插补、多轴联动等[^3]。 - **标准化功能块**:如`MC_GroupMove`(轴组运动)、`MC_CamIn`(电子凸轮同步)等,支持复杂运动逻辑的编程[^3]。 - **参数映射与数据交换**:通过过程数据对象(PDO)实现与伺服驱动器的实时通信,符合CiA402规范(如引用[2]中提到的EtherCAT运动控制器)[^2]。 --- #### **2. 实现方法** **步骤1:规范文档获取** - 从[PLCopen官网](https://www.plcopen.org/)下载Part 5的PDF文档,明确功能块定义、状态机流程及接口要求。 **步骤2:开发工具选择** - 使用支持PLCopen规范的编程平台,例如: - **CODESYS**:内置PLCopen Part 4(基础运动控制)和Part 5(高级协同控制)的函数库。 - **TwinCAT(Beckhoff)**:通过EtherCAT实现实时轴组控制,支持CiA402与PLCopen的集成[^2][^3]。 **步骤3:功能块应用示例** ```pascal // 使用PLCopen功能块实现轴组同步 PROGRAM Main VAR AxisGroup: MC_GROUP; Command: MC_GroupMove; END_VAR Command(AxisGroup:=AxisGroup, Position:=100, Velocity:=50); ``` 此代码片段展示了如何调用轴组运动功能块,控制多轴同步移动到目标位置。 --- #### **3. 与OPC UA的集成** PLCopen Part 5的实现常结合OPC UA信息模型(如引用[1]提到的PLCopen NodeSets),通过以下方式提升兼容性: - **标准化节点**:将轴组控制参数(如位置、速度)映射到OPC UA地址空间,实现跨平台数据交互[^1]。 - **状态机同步**:通过OPC UA服务实时监控轴组状态(如`StateMachineType`节点)。 --- #### **4. 典型应用场景** - **包装机械**:多轴协同控制实现高速贴标。 - **半导体设备**:精密定位与轨迹插补,如晶圆搬运机械臂。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值