Tag: uicollectionview

GCD在UICollectionView上的强大功能滚动

所以我从最近2年开始使用objC,从最近4个月开始使用Swift 3。 因为这是我的第一个博客,所以这个问题对我来说很难解决。 在尝试了多个stackOverFlow线程之后,在搜索了数百篇博客之后,我终于找到了解决方案。 就是这样 问题: 考虑一个具有UICollectionView作为情节提要的IBOutlet的视图控制器。 它将解析后的JSON响应对象用作数据源数组。 因此JSON结构非常庞大,就像我们的数据源一样。 看一下下面的UI截图: 所以UICollectionView具有问题和答案的结构,因为标题显示了问题,而单元格是可用于相应答案的多个答案。 单元格包含一个UIImageView和UILabel作为描述。 用户必须至少选择一个单元格作为一个问题的答案,否则,UICollectionView将滚动到特定的索引单元格。 为了存储选定的答案,我为选定的索引维护了[[IndexPath]]。 这样我就可以知道用户选择了哪个值,并将此数组用于cellForItem以显示所选答案。 滚动到特定索引单元格的代码: 现在,最关键的部分是我花了很多天来弄清楚的。 在单击下一个按钮时,UICollectionView应该可以平滑滚动到相应的索引单元,但是在滚动时会被切碎。 我不得不点按两次按钮三下才能到达该特定的索引单元格。 调试: 所以,首先我可能是因为分层。 因为我是CALayer 与所选单元格接壤以突出显示特定单元格。 但是即使去除分层后,问题仍然存在。 其次,我认为这一定是有可能发生的,因为我没有正确地缓存图像 ,所以一定是因为这个原因,但是即使在调试代码后,我仍然知道这不是问题,这是不同的。 花了很多时间后,我有了使用XCode的工具来了解问题的想法。 因此,使用仪器后,我开始获得清晰的图像。 当我单击按钮进行验证时,我的应用程序没有足够的内存。 即我的整个主线程因执行该特定任务而被阻塞。 当我在主线程上进行分层,图像下载以及UICollectionView的滚动时,主线程被100%的workLoad使用。 解: 因此,为了解决这个问题,我创建了一个VC中的另一个线程,在我的viewDidLoad 中将 QoS指定为.userInteractive 。 因此,上面的代码所做的只是创建另一个线程并从主线程共享工作负载,以便更好地响应主线程。 现在,主线程只有两个任务可以执行:渲染边框和显示图像。 当我们使用此scrollDispatchQueue滚动到相应的索引时,单击下一步按钮时,现在不会出现UICollectionView滚动的斩波。 在解决这个问题的过程中,我非常想解决这个问题,但是现在终于解决了,并且知道我们可以使用GCD在多线程中发挥什么作用。 所以希望这个博客能在以后迅速帮助像我这样的新手3 3 因为这是我的第一个博客,请忽略是否有错字。 欢迎对此发表评论或提供任何帮助,或针对相应问题提出其他建议。 真的很高兴知道。 感谢您的阅读,祝您编程愉快。

访问iPhone照片库对象

背景: 我正在构建一个iPhone应用程序(XCode 9.2,iOS 11+),在该应用程序中,用户可以选择照片库图像作为笔记记录过程的一部分。 主要问题是,当他们回到笔记中时,如果将其与图像相关联,则必须从照片库中加载这些图像。 我不想将每个图像都转换为持久数据的数据对象,因为它们已经存在于设备中。 仅参考图像并在需要时显示它会容易得多。 本教程将介绍: •如何访问照片库和选择对象 •存储有关该对象的照片资产元数据 •以后通过使用存储的元数据检索对象 完成后,应用程序应如下运行: 我们在这里所做的是让我们的应用程序知道,当我们请求用户允许其照片库显示我们提供的文本消息时。 链接到照片框架 苹果有一个非常强大的框架来处理照片资产,称为照片。 我们将需要将此包含在我们的项目中。 返回项目导航器,然后单击顶部的项目图标,这会将项目设置加载到主要内容区域。 在顶部将出现几个导航选项,选择Build Phases。 与info.plist一样,“构建阶段”将具有多个选项,这些三角形的右上角指向三角形。 单击“将二进制文件与库链接”旁边的一个以显示其属性。 该区域允许您向应用程序中添加框架和库。 单击+图标,将显示一个弹出框,显示可用的框架。 开始在文本字段中输入“ 照片” ,列表将随着您输入的内容进行调整以显示匹配项。 选择Photos.framework选项,然后单击“添加”按钮以将其包括在项目中。 将UI元素添加到情节提要 现在,我们已经配置了应用程序,可以添加一些UI元素,以便我们可以从用户的设备中选择并显示照片。 返回到项目浏览器,然后选择Main.storyboard文件。 这将在内容区域显示应用程序的主故事板。 如果“ 实用程序”面板未打开,则显示它,并从按钮的下一行中选择“ 对象库” 。 使用下面的过滤文本字段或滚动浏览对象列表,选择一个UIButton并将其拖动到视图控制器顶部附近。 您可以根据需要在此处调整大小。 使用属性检查器将标题设置为“ 显示库”,您还可以在此处编辑按钮的字体,文本颜色和背景颜色。 使用另一个UIButton重复此过程,将其均匀放置在第一个按钮的右侧,将标题设置为Show Images。 第一个按钮将用于显示照片库,第二个按钮将用于在UICollectionView中查看选定的图像。 再次滚动浏览对象库,然后选择UICollectionView 。 选择它并将其拖到情节提要板上,将其放在按钮下方。 将UI元素连接到ViewController 通过单击右上角的Show Assistant Editor按钮来显示Assistant Editor 。 确保在助手编辑器中选择了ViewController文件。 在情节提要中,控制单击添加的UIButton。 将显示一个选择弹出窗口,选择“ 引用出口” […]

MVVM实现UICollectionView的方法-第4部分

单元中的用户交互。 如果您对示例项目感兴趣,那么PowerTools是一个小框架,我正在构建这些框架,应用这些文章中介绍的所有策略,然后在您的计算机上进行尝试,只需在bash终端上尝试PowerTools 。 在这里您可以找到以前的部分: 第1部分-使您的内容独立 第2部分-增强ViewModel和单元的可重用性 第3部分-使用UICollectionFlowLayout的单元格大小 互动,滚动和委派 正如我们在第3部分中所看到的,UICollectionViewDelegate与UICollectionViewDataSource一起埋在我们的DataSource类中。 这是因为UICollectionViewDelegate具有很多功能: 定义单元格的大小 响应用户与单元的交互 是UICollectionView的UIScrollViewDelegate 吗? 但是通常我想分别定义和管理那些行为,以遵守单一责任原则。 为此,我应用了Jesse Squires在本文中描述的技术,在数据源上定义了两个委托:InteractionDelegate和UIScrollViewDelegate。 所有这些方法都将代理给委托,可以单独实现这些委托并将行为注入到DataSource中。 我的假设是:ViewController,您将在迭代呈现的业务资源上呈现劣势。 如果为真,则每个项目都有一个要呈现的特定UIViewController或定义该项目需要呈现哪个UIViewController的相关逻辑。 同时, UIViewControllers需要定义上下文,通常这些信息不依赖业务资源,而是直接从UIViewController到UIViewController 。 基于这些假设,我可以定义一个Builder,他是唯一知道如何构造目标UIViewController的Builder 。 它将包含与构建UIViewController所需的业务资源相关的所有信息,并从工厂接收要注入的上下文。 带有字符串的示例构建器。 我定义了在应用程序级别在PowerTools框架中通用的Context ,通常将其用于依赖注入。 Factory是一个协议,因此可以从需要它的每个对象中实现它,并将上下文注入到Builder中,因此一切都是类型安全的。 在PowerTools中声明的AbstractFactory 观看AbstractFactory的实现,我们可以看到一个新的接口,该接口以前从未知道过,但是它的名称应该很清楚: BuilderContainer。 这是启用类型擦除的层: 很简单,但是像个魔术 类型擦除是一个复杂的论点,如果您有兴趣深入了解,建议您从NatashaTheRobot的本文开始。 FastForward,这是我在ItemViewModels中应用typeErasure的方式: ItemViewModel如何将构建器传递到其交互工厂 此代码段中的重要部分是ColorItemViewModel扩展,其余的仅用于提供有关正在应用的内容的上下文。 因此,现在我们只需要将Interaction委托绑定到AbstractFactory即可使其像黑魔法一样工作,并且要做到这一点,使用条件扩展的解决方案非常简单: 合并AbstractFactory行为的InteractionDelegate条件扩展 结论 我大量使用这些模式来增强应用程序中的代码可重用性和责任封装,因此,如果您发现此提示很方便或有增强的想法,请提示我或向PowerTools提出拉取请求

Swift中的回调– TableView和CollectionView的实际示例

您非常喜欢某件东西,因此您始终希望围绕它。 所有程序员都沉迷于某种东西,如果您是iOS开发者,那么当您被介绍到UITableView和/或UICollectionView ,您将UICollectionView 。 当您使用UIScrollView危险时,您会更加爱他们(我是说😢)。 我已经看到程序员非常喜欢某些数据结构(即enum , struct ),以至于他们只能思考。 这种爱带来了一些在别的事情的帮助下做某事的非常酷的技巧。 因此,在开始快速讨论之前,让我更新前面提到的报价, 您非常喜欢UITableView和/或UICollectionView ,以至于即使是简单的输入FORM看起来也UICollectionView 。 请参阅此非常简单的表单以获取用户输入。 它具有一些文本字段和一些标题标签。 可以使用UIScrollView在本地UIViewController轻松设计和维护(适用于较小的屏幕)。 但是,如果您喜欢TableView,那么您会发现它也可以很容易地实现。 我认为它具有一些明显的优势 。 但是让我们看看这怎么可能是一个实施问题。 表单的设计和表示形式与自定义单元格类完全没有问题,但是问题是如何将数据从custom cell对象传输到TableViewController对象。 我将通过图表显示。 现在,可以通过多种方式将输入文本返回给Parent ViewController 。 我们可以使用protocol声明, Notification userInfo等来实现。但是今天,我将讨论一种通过回调函数完成此操作的巧妙方法。 现在,在各种平台和语言中以各种方式定义了回调。 简单地说,回调会将某些内容返回给调用方。 它可以返回值,引用,函数或返回自身。 好的好的。 我说话太多了。 让我们看一些代码。 假设这是一个自定义UITableViewCell类 由名为UserController的UITableViewController实例化。 我们可以在控制器中UITableViewDataSource cellForRowAtIndexPath方法中执行此操作。 让cell = tableView.dequeueReusableCell(withIdentifier:“ singleTfCell”,for:indexPath)为! SingleTfTableViewCell cell.staticLbl.text =“公司” cell.inputTf.text = company ///如果表单处于编辑用户信息模式 返回单元 我们知道。 来吧,已经显示了回调!! 是的,我要去。 […]

动态架构和集合视图

在本文中,我将主要讨论UICollectionView,但它也将与UITableView一起使用。 主要问题 UICollectionView的最大问题之一是单元,控制器和模型之间的依赖关系。 如果架构不好,则所有内容都在控制器中,很难更改任何内容。 但是,UICollectionView的目标是显示具有不同设计和数据的UICollectionViewCell。 解 解决方案之一是使用MVVM软件架构模式,如果您不知道它是什么,可以在此处学习一些技巧。 让我们看一个具体的示例,该示例说明并显示如何解决上面看到的问题。 该项目显示一个简单的集合视图,该视图显示具有不同设计的电影列表和一些广告。 ($$$$) 您可以在此处找到该项目。 建筑 如您所见,这里不仅包含ViewController和单元,而且由于每个类的职责也将更加清楚! 我将逐一解释每个班级的责任。 视图模型 这个ViewModel的目的是通过遵守UICollectionViewDataSource协议来告诉控制器它必须显示什么以及何时必须通过ViewModelDelegate显示它。 在我们的项目中,ViewModel将提供要显示在UICollectionView中的项目列表。 视图模型的简单实现示例 首先,我们调用viewModelDidStartLoad委托方法以在屏幕上显示加载程序或任何内容。 然后,我们添加项目并调用viewModelDidLoad委托方法以刷新屏幕。 ViewController 通常,每个控制器都有一个ViewModel。 惰性变量viewModel:ViewModel = ViewModel(委托:self) ViewController实现UICollectionViewDelegate和自定义ViewModelDelegate 。 ViewModelDelegate实现的示例 当数据准备好显示时,此类必须遍历所有项并将它们注册到collectionView中,如您所见: 通过项目在集合视图上注册单元格 CellItem 每个项目都处理一个单元格,并且必须遵守协议CellItem。 单元项协议 如您在上面看到的,该项目必须: 知道重用标识符 了解XIB来加载单元 配置单元(显示数据) 知道细胞的大小 将单元格注册到集合视图 通常, register和cellNib方法总是相同的,因此我们可以创建协议的扩展以具有默认实现。 MovieCellItem 让我们看一个带有MovieCellItem的更具体的例子。 在此类中,我们有一种类型可以帮助我们加载特定的XIB,但是CellItem协议的实现非常简单。 如果您必须处理单元内部的特定交互,则最好在项目中进行。 例如,该项目可以是单元格拥有的UITextField的委托,并通过特定协议,数据块或您喜欢的任何数据将数据直接传递到ViewController或ViewModel 。 细胞 细胞几乎什么都不做! 它们仅具有IBOutlet,并可以根据需要在aakeakeNib()或prepareForReuse()方法中自定义设计。 MovieCell类:UICollectionViewCell { @IBOutlet弱var imageView:UIImageView! @IBOutlet弱var […]

UICollectionView使用具有不同高度的单元格

允许您更改像元高度大小的组件 我参加了一个项目,被要求构建一个界面来显示一些卡片,这些卡片具有特定的功能,它们具有不同的大小。 一位同事带来了一个天才的解决方案,我很喜欢它,我花了一些时间来理解它,因此我决定使用cocoapod来构建组件以使其变得更容易。 怎么运行的 为了简化说明,UICollectionView允许开发人员自定义如何在屏幕上构建每个单元格,这可以通过UICollectionViewLayout类实现,如果您想进一步了解它,请在GitHub链接的末尾查看文件UICustomCollectionViewLayout.swift 。文章。 如果您只想在项目中使用它,请将pod’hkAlium ‘添加到您的podfile中,或仅将UICustomCollectionViewLayout.swift文件复制到您的项目中(请参阅文章最后的Github链接) 。 实施委托 在视图控制器中,必须实现CustomLayoutDelegate ,此方法返回每个单元格的高度大小,与标准UICollectionView方法非常相似。 请参见下面的代码段: 完整的代码示例。 有关它的更多信息并访问完整的示例项目,请转到下面的GitHub链接: heuristisk / hkAlium hkAlium –具有不同单元大小的 UICollectionView github.com 希望它对您有帮助,祝您好运!

UICollectionView:如何轻松处理更新

使用CollectionViews或TableViews时,困难的部分是需要添加,删除,移动某些单元格或更新其内容时。 使用装饰视图时甚至更多。 介绍 查看以下两个数组: let old = [“ A”,“ B”] let new = [“ B”,“ C”] 这些数组之间的差异非常容易计算: Deleted:[0] //旧数组中的索引 已移动:[(从:1,至:0)] 插入的:[1] //在新数组中的索引 重新加载:[] 要计算此差异,我们使用一个键比较两个数组,在这种情况下,这是数组中的值。 使用key,我们可以计算move , delete和inserts 。 删除了位置0的键A 钥匙B从位置1移到位置0 键C插入位置1 当我们要计算两个数组之间的重载索引时,它变得更加复杂。 我们还需要一个key和一个值。 如果值更改,我们需要重新加载该项目。 let old = [(键:“ A”,值:0),(键:“ B”,值:0)] let new = [(键:“ C”,值:0),(键:“ B”,值:1)] 差异的结果: 已删除:[0] //键A已删除 感动:[] 插入:[0] //插入键C 重新加载:[1] // B的值已更改 […]

如何创建自定义可移动UITableViewCell / UICollectionViewCell。

难度等级:容易 在本教程中,您将学习如何通过长按手势来制作可移动的表格视图单元格。 您可以在我的github页面上找到相同的教程。 bhaveshtandel17 / MovableTableViewCell MovableTableViewCell –在本教程中,您将学习如何通过长按手势来移动表格视图单元格。 github.com 怎么做? 添加UILongGestureRecognizer 处理UIGestureRecognizerState.began 处理UIGestureRecognizerState.changed 让我们开始吧!! 🎉

iOS TableView使用Swift预取数据源

Apple引入了用于在iOS 10中预取UITableView和UICollectionView的 API。这是有关如何实现UITableViewDataSourcePrefetching协议的简短故事。 总览 为了实现预取,我们向视图控制器确认了UITableViewDataSourcePrefetching协议,就像UITableViewDataSource和UITableViewDelegate一样 。 这使表视图的数据源可以在调用tableView(_:cellForRowAt 🙂数据源方法之前开始为单元格加载数据。 入门 将视图控制器设置为表视图预取数据源 tableView.prefetchDataSource =自我 在tableView(_:prefetchRowsAt :)的实现中,初始化指定索引路径中单元格所需的数据的异步加载。 func tableView(_ tableView:UITableView,prefetchRowsAt indexPaths:[IndexPath]){ 用于indexPaths中的indexPath { 警卫让_ = loadingOperations [indexPath]否则{返回} 如果让dataLoader = dataStore.loadPhoto(at:indexPath.row){ loadingQueue.addOperation(dataLoader) loadingOperations [indexPath] = dataLoader } } } 当表视图通知您tableView(_:cancelPrefetchingForRowsAt 🙂方法不再需要数据时,取消挂起的数据加载操作 func tableView(_ tableView:UITableView,cancelPrefetchingForRowsAt indexPaths:[IndexPath]){ 用于indexPaths中的indexPath { 如果让dataLoader = loadingOperations [indexPath] { dataLoader.cancel() loadingOperations.removeValue(forKey:indexPath) } } } 异步加载数据 与tableView(_:cellForRowAt […]

UICollectionView具有在iOS 9和10中使用自动布局自动调整单元格大小的功能

警告!!! :使用基本SDK> = iOS 12进行构建时不起作用 在开发iOS应用时。 您通常会遇到一个使用垂直卡片设计的应用程序,如下面的屏幕截图所示。 如果您熟悉iOS Apps开发。 您将知道有2种选择。 使用UITableView或UICollectionView。 在本教程中,我将使用UICollectionView,因为它比UITableView具有更高的可伸缩性,并且您可以在iPad中采用多列。 在WWDC 2016视频会议219:iOS 10中UICollectionView的新增功能。苹果表示,从下面的屏幕快照中收集视图单元格大小有3种方法 在本教程中,我们将使用方法1 自动布局 。 开始吧 首先设置您的视图控制器和UICollectionView。 将您的UICollectionView出口命名为viewController的4面的“ collectionView”引脚约束 由于我们将不会在情节提要中使用集合视图单元格(我们将使用nib代替),因此我们将集合视图中的项目数设置为0,并确保“布局”为“流”,因为我们将使用集合视图流布局来制作单元格自动调整大小。 接下来,创建一个用于收集视图单元格的类及其xib。 在本教程中,我们将其命名为Cell.swift和Cell.xib 别忘了将nib注册为viewDidLoad中的单元。 我们还将UICollectionViewFlowLayout的EstimateItemSize设置为(1,1),因为当设置了估算项的大小时,flowLayout将通过自动布局使用自动调整大小(这是常见的陷阱)。 现在是时候在Cell.xib中设计单元格了,如果您将单元格大小设置为想要的最大宽度(对于5.5英寸的屏幕,> 414则是安全的),如果将宽度设置得太小,应用程序将在运行时崩溃(例如。您将宽度设置为350,它将在5.5英寸的屏幕上崩溃),并为其增加一些高度(请注意,此尺寸仅用于设计时) 将UIView用作容器,以便所有视图将单元格的第4针固定到单元格。 接下来,我们如下设计单元。 确保最底部的视图和最右侧的销钉固定到容器视图。 这是单元自动调整大小所必需的。 然后我们制作单元类的出口 为容器视图宽度创建约束,并为单元格类创建出口 然后设置内容视图宽度约束,以使其与您在情节提要中设置的从笔尖减去集合视图插图中唤醒时的屏幕尺寸匹配。 我们还设置了self.contentView.translatesAutoresizingMaskIntoConstraints = false,以防止Xcode为不需要的单元格的宽度和高度生成自动布局约束。 现在,我们应该像往常一样通过将数据源添加到集合视图中进行测试并运行 示例项目在这里:https://github.com/tttsunny/CollectionViewAutoSizingTest