Estéartigo pretende trazer ao seu leitor,软件开发者,软件开发者,可移动iOS应用程序的速记4 SOLID和KISS解决方案的重要性软件quando desejamos construir umasoluçãorobustaesustentável。 Arquitetura软件 从本质上说,使用高质量的语音软件可以通信和使用Carinho。 可以使用部分软件,也可以使用ganhar novas funcionalidades软件。 一种由软件组成的软件,它可以解决软件开发中的任何问题。 Neste linkháum materialtambémescrito por mim quepoderáte explicar mais sobre o problema。 通用软件安装软件鲁棒软件,依赖软件。 界面和接口的实现以及实现的接口。 EstePadrãonos ajudatambém是princípiodainversãodadependência (SOLI D )的代表。 蟒蛇 Como boaspráticas, POO的公用事业概念,通用的公用事业RXSwift公用程序。 Estaspráticas,pro deto的长期运作,nos ajudaram和SOLI D restantes的回应。 没有iOS的重要事项 Este artigoabordaráo或us e dedeçênciautilizando使用了一个故事板 ,并推荐了一个UI。 使用casovocênão,使用nãopoderáusar ométodo 准备(用于segue :) pois作为seguessão类,特别用于故事板 。 […]
快速调用函数时何时以及何时不编写参数说明 TLDR; 这些是编写参数标签的准则: 初始化函数的所有参数都应具有外部参数标签。 除第一个参数外,其他函数和方法的所有参数都应具有外部参数标签。 长版 因此,您声明了只有两个成员的MyClass : 类MyClass { var计数器:整数? var anotherCounter:整数? } 然后,声明一个名为的初始化函数: 初始化(第一个:整数,第二个:整数){ self.counter =第一; self.anotherCounter =秒; } 还有一个名为的自定义方法: func myFunction(counter:Int,anotherCounter:Int){ 打印(“打印此”); } 每当我们调用init方法时,都将需要其参数的所有描述。 例如。 var myObject = MyClass(第一:5,第二:5); 但是,要调用其他函数,我们不会在第一个参数中使用描述。 例如。 myObject.myFunction(5,anotherCounter:10); 但是,如果您决定无论如何都不会写描述,则可以使用_关键字将其隐藏。 函数的定义更改为: func myFunction(counter:Int,_ anotherCounter:Int){ 打印(“打印此”); } 然后,函数可以称为: myObject.myFunction(5,10);
我想介绍一下在日本举行的iOS聚会。 东京iOS聚会 这次聚会主要是针对对iOS平台编程(iPhone,iPod … www.meetup.com) 感兴趣的人。 名为“ Tokyo iOS Meetup ”的聚会每月在日本东京举行。 我们尝试用英语交谈,因为它是一个国际社区。 我通常会说一点英语,这对我来说是极大的鼓励。 2016年12月10日举行了“ 12月iOS聚会 ” 。 3位演讲者做了精彩的演讲:
当您的UITableView没有足够的数据来填充屏幕的长度时,它将显示带有分隔符的空单元格来填充屏幕。 我遇到了几种不需要多余的分隔线的情况。 如果您自己遇到过这种情况,那么这是摆脱它们的简单技巧,不需要任何代码。 UITableView具有两种不同的模式。 一个用于静态内容,其中您在Xcode的Interface Builder中手动添加每个单元格,另一个用于在代码中动态构建内容。 仅当使用动态内容时,才会出现带有分隔符的多余的空单元格。 将普通的UIView添加到UITableView的页脚 为了摆脱空单元格,我们要做的就是在UITableView的页脚中添加一个空的UIView。 UITableview有两个插入点,可在单元原型的上方和下方添加页眉和页脚视图。 首先,从对象浏览器中获取一个普通的UIView,并将其拖动到所有单元原型下方的页脚位置。 有效! 分隔线不见了。 自定义颜色可能需要其他工作 如果您的UITableView使用默认的背景色,那么您不必做任何其他工作。 但是,如果您为UITableView使用自定义背景色,或者希望页脚与单元格的颜色匹配,请更改页脚视图的背景色以进行匹配。 如果UITableView中没有数据,则可能还必须拖动页脚视图的大小以使其足以覆盖屏幕。 我希望您发现此解决方案有用。 如果您知道在不添加自定义代码的情况下完成同一件事的更简单方法,请在下面留下评论。
协议定义了适合特定任务或功能的方法,属性和其他要求的蓝图。 然后,该协议可以由类,结构或枚举采用,以提供这些要求的实际实现。 满足协议要求的任何类型都被称为符合该协议。 因此,为了简单起见,一个协议会说一个struct,class或enum,如果您想成为那个,请执行this,this和This。 示例:如果您想成为一名开发人员,则必须阅读并编写代码。 协议创建和采用 我们可以创建如下的Protocol : 协议SomeProtocol { //协议定义在这里 } 类,结构和枚举可以采用这些协议,方法是将协议名称放在类型名称之后,并用冒号分隔,作为其定义的一部分。 可以列出多个协议,并用逗号分隔。 struct SomeStruct:FirstProtocol,SecondProtocol { //结构定义在这里 } 如果一个类具有超类,请在其采用的任何协议之前列出超类名称,后跟逗号。 class SomeClass:SomeSuperClass,FirstProtocol,AnotherProtocol { //类定义在这里 } 示例一:财产要求 上面的协议只是说要采用我的任何类/结构/枚举必须具有一个名为fullName的属性,该属性必须是String的类型,并且该属性必须是一个用{get}表示的gettable属性 。 第First Implementation和Second Implementation都有一个名为fullName的属性,因此尽管它们具有不同的实现,但它们都符合FullNameable protocol 。 我们的FullNameable协议说的是,我们需要有一个fullName属性,它没有说明我们应该如何获取此属性。 等等,那么什么使属性可gettable呢? gettable属性是一个只有赋予初始值后才能读取的属性。 当我们尝试为fullName属性分配新值时,由于初始化Lecturer结构时使用了let关键字,它将失败。 该示例的原因是: 展示如何使用协议并遵守该协议 让我们理解,符合属性的类不必具有相同的实现。 了解{ get }代表什么 示例二:连接松散的最终类别 让我们假设我们要制作冰沙,而制作冰沙所需的要求是Milk和Dairy 。 做冰沙,我们必须混合一些水果以及一些乳制品。 因此,我们将需要一个混合方法,所有制作冰沙的类都必须具有此方法,因此我们必须使用如下所示的协议来实施此方法 要制作冰沙,我们需要在每个符合Blendable协议的类上调用blend方法,我们可以实现 makeSmoothie方法将接受符合Blendable协议的类的数组,然后使用for循环访问每个类中的blend方法。 如果将不符合Blendable协议的类作为数组传递,则应用程序将引发错误。 该示例的原因是: 展示如何使用方法作为协议要求 了解如何访问符合协议的松散终端类 示例三:何时使用协议 […]
服务器端Swift任重道远 最近我很想起Swift。 大多数情况下,这是因为有关该语言的动态性的讨论。 但是,我已经写过有关此的内容。 昨天,我读了一篇非常有趣的文章,有关称为Vapor的Web框架。 看起来很酷。 我正在考虑踢轮胎。 但是,我也想行使作为互联网公民的权利,也可以提出申诉。 我认为采用Swift作为有用的服务器端工具非常冒险。 此外,如果不自己做大量工作,就不可能在许多任务上使用Swift。 宣布几个月后,Crashlytics将Swift引入我们的生产服务器端基础架构中,我们就一直在运行它,这可能会让您感到惊讶。 公平地说,这只是一小段代码。 我们使用它将残缺不清的Swift符号转换为更易理解的形式。 但是,我们必须将其包装在Objective-C中。 为什么? 因为我们必须将其托管在Go流程中。 为什么? 因为我们需要与称为NSQ(http://nsq.io)的队列服务器(我很喜欢并强烈建议)进行对话。 Swift没有NSQ客户端。 自己编写客户是可能的,但这将是一项艰巨的任务。 我们不久前就谈到了这一点,但最终决定,这笔投资太大,收益太少。 那是因为在NSQ客户端之上,我还不知道对statsd的支持。 我们将statsd用于通过石墨的服务器端监视。 没有监控,我们就无法在生产中运行事物。 Go也对此提供了大力支持。 我很高兴看到Swift获得对服务器端工作的支持。 我并不高兴将速度作为主要重点,但这是可以理解的。 (顺便说一句,我很想看看它与Go和DropWizard的比较。我们的Go端点具有不到毫秒的响应时间。)我认为Swift确实会为Go和Java带来真正的收益,长期的。 但是,Go如今拥有大量高质量的客户。 我四处闲逛,确实找到了一些Kafka和MySQL的Swift客户端。 这很有希望,但不足以构建您可以依赖的东西。 除非我们为队列服务器,数据库和其他服务器端基础结构提供一些经过考验的客户端,否则我认为服务器端Swift是一个入门者。 当然,我知道您必须从某个地方开始。 蒸气看起来是一个不错的开始。 谁知道,也许新苹果公司为他们正在运行的那个巨大集群提供了一个强大的工具,并且即将开放源代码的Swift Cassandra驱动程序🙂
在项目中采用视图代码确实可以帮助它变得更加模块化。 几周前,我写了一篇文章,展示了如何迁移使用情节提要+ xibs构建的Marvel项目来查看代码,您可以在此处进行检查。 在那篇文章中,我描述了这样做的一些好处,其中之一就是与测试有关。 视图代码更易于测试,因此,当您采用视图代码时,您的测试服会越来越多。 今天,我将展示如何为项目编写测试以及在此过程中进行的一些重构。 您可以在此处通过测试检查存储库。 **这个Marvel的项目是在一系列的帖子中创建的,如果您错过了查看的话。 为什么测试更容易? 首先,查看代码使您可以控制代码的初始化过程。 这似乎没什么大不了,但请相信我。 现在,您可以编写一个与给定类型一起使用的自定义初始化程序,这有几个好处: 您可以在测试环境中使用setter注入,例如,提供伪造的实现(模拟)而不是真实的实现。 这可以帮助您独立运行测试,稍后再介绍。 现在,您可以控制初始化过程,您可以使用let删除一些可选参数并将变量定义为常量。 语义上更正确,比方说您正在创建角色视图控制器。 现在,您可以强制要求有人在视图控制器初始化过程中提供字符,这很有意义。 经过所有的重构和测试编写,我设法将应用程序的代码覆盖率提高到100% 。 代码覆盖率本身不应达到某个特定数字。 而是应将其用作地图,该指南显示了可以在项目中改进的地方的提示。 在某种程度上,代码覆盖率的真正价值是回答这个问题, 接下来我要测试什么? 以同样的方式,您的测试应用于重构代码并使之更好。 更好的代码意味着: 更具模块化 更可重用 封装好 明确而单一的目的 易于开发的代码 易于维护的代码 测试之所以能够帮助您“使代码变得更好”,是因为它们使您可以从接口的角度来了解代码的调用者。 如果要在后台做很多事情,通常很难测试,因此需要重构。 有无视图代码..! 现在,让我们将在早期版本的项目中使用Storyboard + xibs进行的测试与在该版本中的视图代码进行比较。 这将使我们能够检查两种方法之间的好处和区别。 使用Storyboard进行CharacterViewController测试 使用查看代码的CharacterViewController测试 您现在可以看到,使用视图代码,我们可以摆脱以前用于获取视图控制器的许多样板代码。 以前,我们无法控制初始化过程,因此我们必须从情节提要中恢复它,并重复相同的旧配方。 好吧, 不再了! 第二个版本不需要测试不是从视图控制器给出字符的情况,因为现在它是init进程的参数,这意味着如果有人想要一个CharacterViewController,他们将需要为该字符提供一个字符。在里面。 CharactersViewController测试.. 现在我们可以控制视图控制器的初始化过程了,我们可以将apiManager作为视图控制器的参数来提供,使设置器注入变得轻而易举,同时使用let可以将控制器中apiManager的变量保持不变。 在没有视图代码的先前版本中,我们必须将其保留为var进行注入,将其返回时我们无法控制初始化。 没有查看代码.. 与查看代码.. 能够控制初始化过程是如此重要,它使您可以更好地控制代码! 您可以使用下面的视图代码检查对CharactersViewController的改进测试。 CharacterTableCell规格.. characterTableCell测试也得到了极大的增强,没有视图代码,我们不得不使用cellForRow方法从数据源中恢复它,这意味着我们不得不重复同样的方法,从情节提要中加载视图控制器。 不再! […]
React native是一个功能强大的工具,因为它可以让我们使用本地代码(iOS中为Swift / Obj-C,Android中为Java / Kotlin)并桥接它们以访问我们的react-native JavaScript文件中的本地方法。 当您构建反应本机尚不支持的内容,或者您不想使用JavaScript重写某些旧的本机代码时,此功能真的非常有用。 我遇到过这样一种情况,我想为WebView清除所有cookie,但是在react-native中没有任何方法可以实现这一点。 ios Native Module中的示例都在Objective-C中,我想使用Swift来实现。 首先,在YourReactNativeProject / ios / YourReactNativeProject.xcodeproj或YourReactNativeProject / ios / YourReactNativeProject.xcworkspace下打开用于React-native的ios项目,如果您之前安装过Pod。 首先创建一个新的swift文件,并将其命名为项目目录下的CookieManager。 创建Swift文件时,系统会提示您创建桥接头。 在桥接标题内添加导入语句 #import“ RCTBridgeModule.h” 在您的CookieManager.swift文件中 进口基金会 @objc(CookieManager) 类CookieManager:NSObject { @objc func clearCookies()->无效{ //删除所有缓存 URLCache.shared.removeAllCachedResponses() //删除任何关联的cookie 如果让cookie = HTTPCookieStorage.shared.cookies { 用于Cookie中的Cookie { HTTPCookieStorage.shared.deleteCookie(cookie) } } } } 不幸的是,我们必须提供一个Objective-C文件,以便将Swift暴露给React Native Objective-C框架。 创建一个新的Objective-C文件,并将其命名为CookieManagerBridge 在CookieManagerBridge.m文件中,您可以公开CookieManager类和clearCookies方法 #import #import“ […]
作为iOS开发人员,您一定熟悉AppDelegate类及其遵循的协议。 那是一切*开始并有时结束的地方。 App委托托管了大量有用的方法和回调。 与您应用的生命周期,后台传输,后台获取或连续性相关的所有内容。 更不用说用户和远程通知了。 确实功能强大,但是……对于一个很小的班级来说,这不是太多吗? 那么单一负责原则呢? 它只有一个改变的理由吗? 当您的应用程序增长时,您会添加更多服务,例如社交登录,分析,崩溃报告。 所有这些好东西都有它们自己的库,当然需要在AppDelegate中进行设置。 这就是您的代表开始看起来和闻起来像一些旧的意大利细面条代码的地步。 对于我的一些旧AppDelegates增长了多少行,我将不为您提供令人尴尬的细节。 不要误会我的意思。 Apple Cocoa上存在的代表模式非常好,而且一定会成功。 但是,这是一对一的关系,显然不适合这种情况。 如何将代表变成更适合这份工作的代表? 这就是我最喜欢的一对多设计模式之一,即观察员。 让我们尝试一下。 将此数组作为实例变量添加到您的AppDelegate。 私人 var观察者:[UIApplicationDelegate]? 现在,在需要转发给观察者的每个委托方法中,添加此简单循环。 func 应用程序 ( _应用程序:UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->布尔{ 观察者?.forEach { _ = $ 0.application?(应用程序,didFinishLaunchingWithOptions:launchOptions) } 返回 真 } 而且…就是这样。 您(可能)永远不会再触摸AppDelegate。 太好了,但是我需要在AppDelegate中设置的新炫酷服务呢? 让我们设置Firebase。 导入UIKit 导入Firebase FirebaseObserver类 :NSObject,UIApplicationDelegate { func应用程序 (_应用程序:UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptionsKey:任何]? = nil)->布尔{ FirebaseApp.configure() […]
在我的上一篇文章中,我展示了如何将UITableView迁移到IGListCollectionView,今天,我将展示如何通过添加其他类型的单元格和处理触摸事件来改进它。 所以我们将最后一篇文章的项目用作我们的入门项目,您可以在这里找到 我们的目标是添加一个UISearchBar,一个带有水平滚动的UICollectionView,它将填充事件(我将其称为EmbeddedView),这是一种查看字符(行和网格)并在触摸事件上更改viewcontroller的替代方法。 为了简短而无聊,我将仅介绍一些关键主题,向您展示我们如何实现这一目标的: 首先,我们需要更改将模型加载到IGListCollectionView的方式。 我们的ViewController有一个应该符合IGListDiffable的Character数组,但是现在我们将使用该协议而不是一个具体的类,因此我们需要创建一个新的IGListDiffable.数组IGListDiffable. 我们要包含在列表中的所有对象都应符合它,因此我们将创建一个Search ,一个CharactableView (将在我们的单元格是行还是网格时处理), Portrait和一个Embedded模型。 每个模型将代表我们的IGListCollectionView中的一个单元格。 您可以在下面看到我们如何在Search模型中做到这一点 之后,我们将在SectionControllers上工作。 除了EmbeddedSectionController之外,每个SectionController的工作方式都与我在上一篇文章中看到的一样,这一点值得特别注意,因为它将具有自己的IGListCollectionView和IGListAdapter因此我们可以从Marvel API中提取事件并将其显示给用户。 它应该实现IGListAdapterDataSource和IGListAdapterDelegate来拉动更多事件,例如在无尽的TableView中。 最后,我们只需要更改ViewController即可使用我们的新单元格。 我们创建了一个名为views的IGListDiffable数组。 在IGListAdapterDataSource objects(for:)方法中,我们基于filterString过滤字符,并添加Seach和EmbbedView以便将其放置在字符列表之前。 return [self.searchView as IGListDiffable] + [self.embeddedView] + (filter as [IGListDiffabe]) 每次更改列表的布局时,我们都需要调用adapter.performUpdates()来更改列表,行到网格或网格到行的位置,它会基于diff算法重新加载IGListCollectionView。 要处理单元格上的触摸事件,我们需要实现didSelectItem()方法,就像在RowSectionController上RowSectionController 您可以在此处检查最终项目。 如果您有任何意见,请通知我。