Tag: swift

RxSwift中的TableView –第2部分

如果您还没有阅读上一部分,可以在这里获得。 在上一个中,我们讨论了如何设置具有一个部分和单元格类型的TableView。 在本文中,我们将讨论如何设置具有单元格类型的多节的TableView。 为什么我要为多节类型撰写另一篇文章? 我们看到了使用一个节和一个单元格处理TableView的过程很简单,但是如果我们要使用单元格类型来处理多个节,则应该安装RxDataSources并在此库的帮助下管理TableView。 因此,我决定另写一篇文章,介绍如何使用RxDataSources处理TableView。 在这一部分中,我们将设置具有多个节和单元格类型的TableView。 像上一部分一样,我在这里在Github上创建了一个简单的项目。 我在该项目中使用了MVVM设计模式。 安装吊舱 像以前一样,我们有RxSwift和RxCocoa,但是还应该添加一个Pod。 这是RxDataSources。 像以前一样,我们有三个独立的层。 模型 我们为两种不同的细胞类型创建两种不同的模型。 第一个模型是具有两个属性的学生。 您可以在下面看到TableViewSection和TableViewItem。 我们迅速使用Enum的功能并创建这两种类型。 像上一篇文章一样,我们创建了SectionOfStudent类型的发布主题。 就像我之前说过的,我们需要两个参数用于RxDataSources的SectionModel。 其中之一是TableViewItem,因此我们将创建项目并将其附加到TableViewItem数组中。 之后,我们创建SectionOfStudent (SectionModel的类型别名)对象,并为itemType传递item和main(TableViewSection代表section类型)项。 SectionOfStudent(model:.main,项目:subItems) 最后,我们将SectionOfStudent放入数组中,然后调用发布主题的onNext() 。 我们将SectionOfStudent放在数组中的原因是我们可能希望拥有更多的Sections类型。 请参见下面的代码: 感谢您阅读本文,如果喜欢,请与他人分享😊。 我正在等待在评论部分中看到您的评论或推荐。

在iOS 11和Swift 4中拖放表格视图单元格

在IOS 11中,UITableView添加了一些专门的API,用于将tableView行从一个tableView拖放到另一个tableView。 对于拖放,我们需要实现委托UITableViewDragDelegate和UITableViewDropDelegate。 UITableView和UICollectionView都具有拖放API(协议)。 对于UICollectionView,可以按照本教程进行操作。 这些代表完全独立,我们可以根据需要使用任何一个代表进行拖放。 两者都适用于拖放。 注意:-请注意, iPhone和iPad均支持拖放功能,在iPad上,不同应用程序,同一应用程序和同一屏幕之间可使用拖放功能,但在iPhone中,仅可在相似屏幕上使用拖放功能。 通过使用CollectionViewDataSource和CollectionViewDelegate方法在同一屏幕上创建带有两个tableView的基础项目。 您可以从此处下载基础项目。 现在,我们开始拖放代理,以将tableView行从FirstTableView移至SecondTableView。 为了回调UITableViewDragDelegate,我们需要在viewDidLoad()方法中设置.dragDelegate 。 覆盖func viewDidLoad(){ super.viewDidLoad() self.topTableView.dragDelegate =自我 } 为了启用拖动吸引力,我们需要设置表格视图的dragInteractionEnabled属性。 在viewDidLoad方法中启用此属性。 此属性的默认值在iPad上为true,在iPhone上为false。 self.topTableView.dragInteractionEnabled = true 在UITableViewDragDelegate中,只有一个必需的方法 itemForBeginning用于支持拖动项。 tableView(_:itemsForBeginning:at 🙂 ->提供项目以开始与给定indexPath相关的拖动。 如果返回一个空数组,则拖动会话将不会开始。 NSItemProvider UIDragItem NSItemProvider- >通过使用此类,您可以创建数据或文件的对象,以便在拖放期间在进程之间传送数据或文件。 UIDragItem- >从一个位置拖动到另一个位置的基础数据项的表示。 扩展ViewController:UITableViewDragDelegate { func tableView(_ tableView:UITableView,itemsForBeginning会话:UIDragSession,在indexPath:IndexPath)-> [UIDragItem] { 让dragItem = self.dragItem(forPhotoAt:indexPath) 返回[dragItem] } ///辅助方法 私人功能dragItem(forPhotoAt indexPath:IndexPath)-> UIDragItem { […]

iOS黑暗主题

显然,如果我们计划支持更多主题,则我们必须选择其他数据类型(例如,您可以选择Integer类型并创建带有所有主题的枚举类型)。 另外,我还创建了一个简单的帮助程序类来获取/保存设置。 我有一个动作连接到Dark mode开关。 现在,当用户更改主题时,我们可以在应用程序中的任何地方捕获该通知。 基本控制器 当然,如果我们在每个视图中分别捕获通知,那将不是最佳选择。 我们可以在这里创建基本控制器类并自定义大多数内容。 当我们在视图中有特定的东西时,我们可以重写方法之一: enableDarkMode或disableDarkMode 。 表格视图的基本控制器。 用于视图的基本控制器。 现在,当用户更改主题时,我们的通知将捕获到我们的基本控制器之一中,并且应用程序正在更改视图样式。 您可以在GitHub存储库中检查整个解决方案: 姆恰楚斯基/ vcoin 通过在GitHub上创建一个帐户为vcoin开发做出贡献。 github.com 我希望这可以帮助你!

在Swift中避免原始痴迷

确保您的代码代表要解决的问题称为域建模 ,这是软件工艺的重要组成部分。 这意味着您应该创建代表问题的类( 或结构! ),而不是使用字典或元组之类的结构来存储信息。 创建这些域概念的好处是,您可以创建更丰富的API,并减少开发人员理解一段代码所花费的精力。 领域建模的反面-使用基元表示复杂的想法-被称为基元痴迷,是一种代码味道。 例如,通过将网站存储为String来表示网站的URL。 与String相比,URL具有更多信息和特定属性(例如,方案,查询参数,协议),并且通过将其存储为字符串,您将无法在没有其他代码的情况下访问这些特定于URL项(域概念)。 作为域建模的一部分,您要针对两件事: 使代码尽可能说明性,而无需文档 充当其自己的文档的代码是软件开发的重要内容之一。 如果代码以这种方式进行自我记录,则说明文档将永远不会过时,因为它是代码本身的一部分。 您不必每次更改代码都记得要更新文档,这很容易忽略。 防止以对业务无济于事的方式滥用您的代码 好的代码经常被忽略的一件事是,它很难做错事情。 需要URL的函数应将URL作为参数,而不是字符串。 如果该函数的用户可以传递String可能会更容易,但该函数现在必须确保String实际上也是URL。 通过强迫用户执行此操作,您将给他们带来一些负担,同时还可以防止他们不仅滥用您的API,而且可以滥用它。 让我们专注于这段代码,看看如何更好地对此建模: func showDetailsForEmail(withId:String){ //推送新的视图控制器 } 使用类型别名 typealias是一个关键字(在Objective-C和Swift中都可用),用于显示代码中的其他内容可以轻松表示的位置: typealias EmailId =字符串 func showDetailsForEmail(withId:EmailId){ //推送新的视图控制器 } Typealiases很好地解释了在这种情况下可以使用什么,它们满足了第一个目标(使您的代码更具解释性)。 在这里,通过查看功能签名,您可以看到发送到该功能才能使其正常工作所需的内容-电子邮件的ID。 以前,当函数只需要一个String ,该字符串应代表什么以及如何创建一个字符串就不太明显了。 将一个完全不相关的String传递给方法,这太容易了,这不是您想要的。 不幸的是,类型别名未能满足第二个要求-防止滥用API。 类型别名是另一个对象的“昵称”。 它们不是单独的类型,因此不会阻止在其位置使用“昵称”类型。 即使上面的函数需要一个EmailId ,您仍然可以在其位置传递一个String (或什至其他类型的别名): typealias EmailId =字符串 typealias SMSId =字符串 func showDetailsForEmail(withId:EmailId){ //推送新的视图控制器 } 让smsOne:SMSId […]

建立我的第一个iOS游戏

两个星期前的星期天晚上,我无事可做。 因此,我开始谷歌搜索一些iOS教程,并登陆了Ray Wenderlich制作的这本令人惊叹的视频教程。 对于像我这样的初学者来说,这非常令人兴奋且易于遵循。 我之前曾研究过Swift文档,但很容易感到无聊。 😝 在该教程中,您将通过构建一些名为Bull’s Eye的简单游戏来学习iOS开发的基础。 它会生成一个介于1到100之间的随机数。然后,它会向用户提出挑战,要求估算滑块并将其尽可能靠近该随机数。 距离越近,分数越高。 很简单 您可以在我的Github存储库中检出完整的项目:risan / bullseye-ios。 基本数据类型 Swift提供了几种基本数据类型,以下是我到目前为止使用的一些类型: Int :对于正数或负数(例如-12或-12 ); Float :十进制数字(例如3.14或-0.123 ); Double :双精度浮点数-比Float精确得多; 布尔值:布尔值( true或false ); Character :对于单个字符(例如A , b或& ); 和 String :字符的集合(例如Hello World )。 使用整数 Swift还提供了其他几种用于处理整数的数据类型: UInt Int的无符号版本(仅零和正数) Int8和UInt8位版本; Int16和UInt16 — 16位版本; Int32和UInt32位版本; 和 Int64和UInt64位版本。 除非您知道自己在做什么,否则在处理整数时始终使用Int数据类型。 使用十进制 还有其他几种用于处理十进制数字的数据类型: Float32 —浮点类型的32位版本; Float64位版本; 和 […]

使用Vapor 2和PostgreSQL持久化数据

这是正在进行的“蒸气入门”系列的第3部分。 在本教程中,我们将结合到目前为止所学的知识,使用我们保存到数据库中的数据来创建一些网页。 在本教程中,我们将使用开源关系数据库PostgreSQL。 如果您对使用数据库或编写SQL代码不完全熟悉,请不要担心。 Vapor附带了Fluent,Fluent是一种Swift ORM(对象关系映射工具),它使数据库的使用变得异常简单。 虽然学习SQL和关系数据库很有帮助,但您会在本教程中注意到并不需要完成。 对于今天的教程,我们将制作一个简单的博客应用程序。 对于本教程,我们将使其保持简单,因此我们将不包括任何身份验证。 好吧,让我们潜入。 首先,让我们开始创建一个新的Vapor项目 步骤1 —生成一个新的Vapor项目 打开您的终端并输入vapor new blogger 第2步-生成 .xcodeproj 项目文件 在终端中,输入cd blogger && vapor xcode这将带我们进入blogger文件夹并生成一个xcode项目文件 步骤3 —安装自制软件 Homebrew是一个软件包管理器,可以帮助开发人员在其MacOS设备上安装工具。 复制并粘贴以下代码以安装Homebrew /usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)” 第4步-安装Postgresql 在终端类型brew install postgresql 我已经安装了Postgresql,所以您的终端看起来与我的略有不同。 第5步–运行PostgreSQL 要启动Postgresql,请在新终端中运行以下命令。 postgres -D / usr / local / var / postgres 输入此命令后,您应该看到以下内容: 现在您已经启动并运行了Postgresql,现在需要为全新的Blogger应用创建数据库。 如果您对SQL不太满意,请不要担心,我们不会大量使用它。 第6步-创建一个新数据库 在终端中,在新的终端窗口中键入psql以打开PostgreSQL控制台。 […]

Xcode高级技巧第1/2部分

在本文中,我将介绍一个主题,它将帮助您提高工作效率。 对于程序员来说,使用快捷键非常普遍。以下是我的一些高级技巧的简要介绍。 1. Xcode欢迎屏幕:Sift + Command +1 欢迎屏幕对于切换最近打开的项目很有用。 2. Xcode设备屏幕:Sift + Command + 2 快速下载和浏览沙箱文档数据,例如plist,首选项,SQLite DB,缓存数据。 3.搜索时快速打开文件:Shift + Command + o 您可以使用“快速打开”搜索框来搜索和打开文件或符号。 符号可以包括变量,枚举,类型,常量,方法或类。 搜索使用模糊匹配。 例如,如果我要搜索“ application(_ application:didFinishLaunchingWithOptions launchOptions :)”。我只需输入“ appdidopt” 4.管理导航视图: 1.将文件添加到目标:Alt + Command + a 快捷键用于通过弹出窗口从实际位置添加文件以进行投影。 2.浏览以前的历史文件:Control + 2 3.浏览下一个历史文件:Control + 3 4.浏览通话记录:Shift + Control +命令+ H 最有用的XCode命令,可查看详细的调用堆栈历史记录,而无需导航到调用者文件。 要在导航视图中获取堆栈跟踪,请选择方法定义文本,然后在键盘中键入Shift + Control + command +H。 […]

语言之间的界线模糊…正在进行代码生成

实验项目CodeGen –可以创建多种语言的代码。尽管我听说人们一旦学习了一种语言,就会很容易学习新的语言 。 -C被Swift取代,几乎在同一时间,我决定不再只使用iOS,而是转而使用Web。 我了解一件事。 有很多共同点。但是由于最初是Javascript,我花了一些时间来适应语言的无限灵活性。 我发现很难适应它。 然后我开始使用Typescript。。几乎在那时,我感到不仅在概念上而且在语法上都有很多共同点…… CodeGen最初是从通用实体/模型开始创建React app / Angular 2本机代码的。很快,注意力就转移到了多语言可能性的产生上。 可能已经想知道它了..如果可能的话。 工作仍在进行中。但是似乎Swift和Typescript或多或少是兄弟,可能是同父异母的兄弟…… WIP:在我探索更多内容时会更新… 杰克逊·S·罗德里格斯/ RTSCodeGen RTSCodeGen –尝试从模型 github.com 为React&Angular2项目生成Typescript代码/文件 我的样本来自Colin Eberhardt ..的Todo List组件 CodeGen – 打字稿 –生成的文件 CodeGen — Swift –生成的文件 CodeGen —源 结论 一旦Typescript的基础准备就绪并可以正常工作,只需半小时即可包含Swift代码。 似乎语言障碍正在模糊……。

了解Firebase观察功能-第2部分

我想出了一个很好的解决方案来解决我一直在解决的Firebase / TableView问题。 我决定采用涉及.observeSingleEvent Firebase函数的解决方案。 作为读者,这可能并不完全有意义,因为它涉及到某些特定于我正在构建的应用程序的东西,但希望您能从中受益。 我决定不创建将观察到一系列挑战的Firebase函数,因为它仍然会产生相同的问题:我填充挑战数组的循环将存在于Firebase观察者的闭包之外。 因此,我复制了FirebaseManager.fetchChallenges函数,但有一个小区别: 静态函数fetchChallengeOnce(withChallengeID ChallengeID:字符串,完成:@转义(Challenge)-> Void) dataRef.child(“ challenges”)。child(challengeID).observeSingleEvent(of:.value,with:{(snapshot)in 如果让challengeDict = snapshot.value为? [String:任何] { 让Challenge = Challenge(id:ChallengeID,dict:ChallengeDict) 完成(挑战) }其他{ 打印(“未完成”) } }) } 观察单个事件! ! 凉。 现在,在我的TeamsDetailVC类中,我有一个Team对象,该对象除其他外还拥有ChallengeID列表。 我还将所有团队存储在Firebase中,因此我为视图控制器当前正在显示的团队设置了一个观察者: func watchTeamData(完成情况:@escaping()-> Void){ 后卫让teamID = self.team?.id else {return} FirebaseManager.fetchTeam(withTeamID:teamID){(团队)在 self.team =团队 self.fetchChallenges(forTeam:team){ 完成() } } } 请注意,它如何调用另一个函数:fetchChallenges。 这是从Firebase获取挑战的单个实例的函数: func fetchChallenges(适用于团队团队:团队,完成情况:@escaping()->无效){ self.teamChallenges.removeAll() for team.challengeIDs […]

堆栈

在舒适地使用了数据结构数组和字典之后,我将探索诸如Stacks和Queues之类的不熟悉的数组。 在本文中,我们将重点介绍Stacks。 排队等待我有关队列的文章。 堆叠—遵循后进先出(LIFO)的顺序。 1. PUSH —只能将元素推到堆栈的顶部 2. POP —从堆栈顶部删除元素 3. PEEK-窥探堆栈顶部的元素 将一堆书想象成一堆书,但要用书本的内容代替书而不是书(而不是心脏……哈)。 在生活中,您不想遇到任何泛型,但是在为Stack编写代码时,我已经使用泛型实现了进一步的可重用性。 让我们大致了解一下实际发生的情况。 我们有一个变量数组,仅对我们正在使用的文件具有有限的访问权限。 在该数组中,每当我们添加一个元素时,该元素都会作为最后一个元素添加,如果您尝试删除元素,则最后一个添加的元素也会被删除。 最后,您只能看到堆栈中的最后一个元素。 这是Stacks的一个更有趣的版本。 我创建了一个名为Lannister的结构,然后继续创建三个相同类型的对象Lannister。 然后,我将这些元素放入Lannister堆栈中,并能够获得对我已推送的所有内容的描述。