IOS简洁的试图控制器

//英文不好,好好学习


在IOS项目里,View controller经常是最大的文件,它们通常包含一些非必须的代码。View controller几乎总是代码中最少可以重用的。我们将关注一些技术使你的View controller瘦下来,使代码可以重用,把代码移动到更适当的地方。


分离数据源和其它特性       


一个使你的View controller瘦下来非常有效的手段是把UITableViewDataSource部分移动到你自己的类中。如果你不止一次的这样做,你将看到它的模式和可重用的类。

例如,在我们的示例项目中,类PhotosViewController中有以下的方法:

# pragma mark Pragma 


- (Photo*)photoAtIndexPath:(NSIndexPath*)indexPath {

    return photos[(NSUInteger)indexPath.row];

}


- (NSInteger)tableView:(UITableView*)tableView 

 numberOfRowsInSection:(NSInteger)section {

    return photos.count;

}


- (UITableViewCell*)tableView:(UITableView*)tableView 

        cellForRowAtIndexPath:(NSIndexPath*)indexPath {

    PhotoCell* cell = [tableView dequeueReusableCellWithIdentifier:PhotoCellIdentifier 

                                                      forIndexPath:indexPath];

    Photo* photo = [self photoAtIndexPath:indexPath];

    cell.label.text = photo.name;

    return cell;

}

很多的代码是关于数组的,还有一些只是关于photos由view controller管理。让我尝试着把array相关的代码移动到我们自己的class中。我们使用block去配置cell,但它也有可能是委托,只是根据你自己去选择的。

@implementationArrayDataSource


- (id)itemAtIndexPath:(NSIndexPath*)indexPath {

    return items[(NSUInteger)indexPath.row];

}


- (NSInteger)tableView:(UITableView*)tableView 

 numberOfRowsInSection:(NSInteger)section {

    return items.count;

}


- (UITableViewCell*)tableView:(UITableView*)tableView 

        cellForRowAtIndexPath:(NSIndexPath*)indexPath {

    id cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier

                                              forIndexPath:indexPath];

    id item = [self itemAtIndexPath:indexPath];

    configureCellBlock(cell,item);

    return cell;

}


@end


这三个方法在你自己的view controller中可以运行,而相反你可以创建一个这个类的实例并且把它设置成为tableview的数据源。

void (^configureCell)(PhotoCell*, Photo*) = ^(PhotoCell* cell, Photo* photo) {

   cell.label.text = photo.name;

};

photosArrayDataSource = [[ArrayDataSource alloc] initWithItems:photos

                                                cellIdentifier:PhotoCellIdentifier

                                            configureCellBlock:configureCell];

self.tableView.dataSource = photosArrayDataSource;


现在,您不用去担心把index path映射到你数组中相应的位置,每当您想在tableview中展示array中的数据,您可以重用这段代码。您也可以实现额外的方法,例如tableView:commitEditingStyle:forRowAtIndexPath:共享这些代码在你的view controller中。


一个好的方面,我们可以单独测试这个类,再也不用担心再写一次,同样的规则你可以应用到其他的东西上不只是array。


一个应用我们让它在这一年工作,我们大量的使用Core Data,我们创建了一个相似的类,但不是依靠一个数组,它依赖一个读取数据的控制器。它实现了所有的动画更新,做节头和删除数据的逻辑。你可以创建一个实例,给它一个获取的数据的请求再用一个block去配置cell。


此外,这种方法也可以扩展到其他的协议。最明显的是UICollectionViewDataSource。这给了你极大的灵活性。如果在开发中的某一刻你决定用UICollectionView替代UITableVIew,你几乎不用改变view controller中的任何东西,你只需要让你的数据支持这两种协议。


把逻辑域移动到Model


下面是一段实例代码,用于查找一个用户活动优先级的列表:

- (void)loadPriorities {

  NSDate* now = [NSDate date];

  NSString* formatString = @"startDate <= %@ AND endDate >= %@";

  NSPredicate* predicate = [NSPredicate predicateWithFormat:formatString, now, now];

  NSSet* priorities = [self.user.priorities filteredSetUsingPredicate:predicate];

  self.priorities = [priorities allObjects];

}

然而,把他移动到我们类的类别中它将变得更简洁,然后我们将在这个view controller中看到:

- (void)loadPriorities {

  self.priorities = [user currentPriorities];

}

在 User+Extensions.m:

- (NSArray*)currentPriorities {

  NSDate* now = [NSDate date];

  NSString* formatString = @"startDate <= %@ AND endDate >= %@";

  NSPredicate* predicate = [NSPredicate predicateWithFormat:formatString, now, now];

  return [[self.priorities filteredSetUsingPredicate:predicate] allObjects];

}

一些代码移动到模型中不是那么的简单,但是它明显的跟modol中的代码有关联,因此,我们可以用Store:


创建一个Store类


在我们的第一个实例中,我们一些代码是从文件中加载数据并解析它。这些代码在我们的view controller中:

- (void)readArchive {

    NSBundle* bundle = [NSBundle bundleForClass:[selfclass]];

    NSURL *archiveURL = [bundle URLForResource:@"photodata"

                                 withExtension:@"bin"];

    NSAssert(archiveURL != nil, @"Unable to find archive in bundle.");

    NSData *data = [NSData dataWithContentsOfURL:archiveURL

                                         options:0

                                           error:NULL];

    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];

    _users = [unarchiver decodeObjectOfClass:[NSArrayclass] forKey:@"users"];

    _photos = [unarchiver decodeObjectOfClass:[NSArrayclass] forKey:@"photos"];

    [unarchiver finishDecoding];

}

View controller不需要知道这些,我们创建一个Store来做这些。通过把它分离出去,我们可以重用这些代码,分别测试

,保持我们view controller简洁。Store可以关注数据加载、缓存、设置数据库堆栈。Store也经常会被服务层或存储调用。


移动网络服务到数据层


这和上面的主题非常相似:不要把网络服务逻辑放在你的view controller。相反,把它封装到不同的类。你的view controler可以调用这个类提供的方法附带一个回调(例如,一个finish block)。你可以把所有处理缓存和错误的放在这个类,这是一件很棒的事情。


移动View代码到View层


创建复杂结构层次的视图不应该放在view controller。你可以用interface builder 或者把views封装到UIView的子类。例如,如果你创建一个日期选择控制器,把它放到一个DatePickerView比直接把所有的东西都在view controller创建更有意义。此外,它可以增加代码的可重用性和使代码简洁。

如果你喜欢用Interface Builder,你可以在Interface Builder中做这些工作。有些人认为你只能把它给View controller用,但是你亦可以加载独立的nib文件与你自定义的视图,在我们的实例app,我们创建一个PhotoCell.Xib,它包含一个photo cell的布局:



正如我们看到的,我们在视图上创建属性,把他们连接到特定的子view,这个技术对于自定义子试图来说非常的方便。


讨论

一个view controller经常会和其它的view controller、数据、视图相互通讯。这正是一个controller应该做的,我们尽可能用最少的代码去实现。

有很多好的技术对于controller和model的通讯(比如KVO和读取结果控制器),然而,controller之间的通讯往往有点儿不大清楚。

我们经常遇到一个问题,一个cotroller有一些状态和其它很多的controller通讯,把它变成一个单独的实例在视图之间传递,所有的controller观察和修改该状态。这样的好处是所有的在一个地方,我们不会陷入一个代理回调。


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
应用背景为变电站电力巡检,基于YOLO v4算法模型对常见电力巡检目标进行检测,并充分利用Ascend310提供的DVPP等硬件支持能力来完成流媒体的传输、处理等任务,并对系统性能做出一定的优化。.zip深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值