Tag: ios

在iOS上使用MVVM进行路由

我在多个项目中使用MVVM已有一段时间了,我非常喜欢它的简单性。 特别是,如果您像许多人一样从MVC移出,则只需要在体系结构中增加一层即可; 查看模型。 如果您发现太多复杂的图层,这确实使事情变得容易。 这是一个好的开始,但是这种简单性并不总是很好。 在MVVM中,将业务逻辑移出视图控制器(VC),然后意识到它仍然很胖。 视图模型(VM)现在具有业务逻辑,但是表示数据(格式)或路由又如何呢? 它们仍然停留在VC中,我们需要将它们移出。 样品流量 假设我们正在实现一个登录屏幕,如下所示。 路线清单: 登录>主屏幕 注册>注册屏幕 忘记密码(?)>忘记密码屏幕 这似乎是一个简单的屏幕,可以使用带有3个脚本的情节提要实现。 但是请相信我,事实并非如此。 例如,您通常会在登录时打开主屏幕。 但是在这种情况下,用户的密码可能已过期,您需要实现重定向以更改密码屏幕。 因此,登录路径变为: 登录>主屏幕或更改密码屏幕 这是情节提要路由失败的地方。 它只是无法应付这种动力。 因此,通常要做的就是让VC处理它: func loginButtonTapped(){ //开始网络请求… //回应后: 如果viewModel.shouldChangePassword { performSegue(id:“ ChangePasswordScreen”,发送者:nil) }其他{ performSegue(id:“ HomeScreen”,发送者:nil) } } 这是路由逻辑,不应在VC中使用。 如果要使用轻量级VC,请在编写if语句之前三思。 他们是决定,不属于那里。 以我的理解,VC仅应具有与视图相关的代码和粘合代码。 永远没有决定。 让我们定义一个路由器协议,并将这些if语句从VC中删除。 我们会需要: 路由ID :字符串标识符,例如segue ID。 上下文 :要从其路由的当前视图控制器。 可选参数 :过渡所需的临时数据。 (点击的行索引等) 协议路由器{ 功能路线( 到routeID:字符串, 来自上下文:UIViewController, […]

开放封闭原则和规范模式的重要性。

Lehlohonolo Isaac,iOS开发人员,DVT 您是否曾经不得不一遍又一遍地重写相同的功能? 举例来说, 您想按类型,颜色和价格过滤车辆列表。 尽管有不同的规范,但我将通过编写三个过滤函数来实现此目的。 因此,即使这三个功能执行相同的操作(正在过滤车辆列表),这三个功能也仅因其规格不同而不同。 解决此问题的简单方法是将规范插入过滤器中。 在这种情况下,我们将只有一个过滤器。 为了使我们能够按颜色进行过滤,我们将注入颜色说明。 要按类型过滤,我们将插入“车辆类型规范”,依此类推。 现在,我们的应用程序只有一个过滤器。 让我们看一下如果在上面的示例中不使用“规范”模式,将会发生什么。 让我们首先创建一个Vehicle对象。 现在,假设您具有以下定义的车辆清单。 让我们创建一个Filter类: 下面的代码段演示了过滤车辆列表的方式: 仅当您知道Vehicle具有一个属性大小时,这才足够好。 但是,它足以应付车辆规格的变化,即当我们现在要按颜色或车辆类型过滤车辆列表时,它将无法正常工作。 取而代之的是,我们必须在VehicleFilter中添加另一个函数,该函数不可行,因为它不遵循开放式封闭原则(OCP)。 我们如何克服这一弊端? 好吧,我要实现的解决方案之一是按规范过滤,而不是明确说明过滤标准。 通过这样做,您可以使VehicleFilter具有足够的灵活性,以适应各种过滤条件。 让我们定义车辆规格。 因此,我们可以指定以下过滤条件: 让我们创建一个过滤器协议。 让我们看看上述变化将如何帮助我们遵守开放式封闭原则。 从上面的代码片段可以看到,我们现在可以过滤颜色和大小,而无需创建两个过滤器。 这使我们的过滤器类别遵循SRP(单一责任原则)和OCP(开放-封闭原则)。 规范模式还可以做很多事情。 例如,您可以创建一个具体的规范来处理要同时按大小和颜色过滤列表的情况。 这称为And规范。 但是,AND有一个缺点。 它没有严格遵循单一责任原则。 我希望您对规范模式学到了很多。 我还要感谢Kennedy Sigauke对创建此博客所做的贡献。

如何提高Swift的编译时间?

在使用Swift 2.3和Xcode 7.3.1时,我在此IDE中编译源代码时遇到问题。 因为出于某些项目机密原因,我和我的团队决定继续使用2.3,而不是升级到3.0或更高版本。 影响团队绩效的主要原因之一是我们在没有足够的时间进行大量迁移。 实际上,问题仍然没有发生在Xcode 7.3.1上,我认为Xcode 8也没有,但是相当容易(p / s:我听说8.2版本解决了问题:x)。 谈论它,有两个主要因素: 通过Xcode,它不利于Dynamic Framework执行。 这意味着Xcode会重新构建所有源代码项目,而不是仅查找和构建未构建的源。 如果添加更多框架或第三方,则需要更多时间来编译它们。 开发人员,我为什么要这样说。 通常,在进行编码时,开发人员通常会忽略来自Xcode的使用Auto Layout对行和UI进行编码的警告(aka⚠),而倾向于使用Swift提供的推断变量。 贾佐 保存屏幕截图,GIF和网站的简单方法。 通过与您的用户更快,更智能地共享,让每个人都开心。 理想情况下,我们将解决以上每个问题。 使用Xcode,更新到最新的Xcode版本,并尽可能将Swift升级到当前版本(3.0)。 好了,有了Dev,我们还有另一件事要做: 解决所有来自Xcode的警告。 改进自己的代码。 示例代码: 让myCompany = [ “雇员”: [ “员工1”:[“属性”:“值”], “员工2”:[“属性”:“价值”], “员工3”:[“属性”:“价值”], “员工4”:[“属性”:“价值”], “员工5”:[“属性”:“价值”], “员工6”:[“属性”:“价值”], “员工7”:[“属性”:“价值”], “员工8”:[“属性”:“价值”], “员工9”:[“属性”:“价值”], “员工10”:[“属性”:“价值”], “员工11”:[“属性”:“价值”], “员工12”:[“属性”:“价值”], “员工13”:[“属性”:“价值”], “员工14”:[“属性”:“价值”], “员工15”:[“属性”:“价值”], “员工16”:[“属性”:“价值”], “员工17”:[“属性”:“价值”], “员工18”:[“属性”:“价值”], “员工19”:[“属性”:“价值”], “员工20”:[“属性”:“价值”], ] ] 修正为: […]

Google标记群集

Google iOS库提供了基于网格的聚类技术,该技术可将地图划分为正方形并将标记(注释)分​​组到每个正方形网格中。它提供了摘要标记,可让您大致了解缩放级别下的“下方”。 在这里,我参考Google官方API编写此博客。 在本博客中,将讨论一个演示,该演示具有Google地图集群的示例实现。 逐步会看到并学习实现。 第1步:最初,您应该在项目文件夹中包含pod(终端命令:pod init)文件,然后在同一文件中添加Google-Maps-iOS-Utils Pod。 安装Pod之后,打开生成的.xcworkspace扩展文件。 步骤2:以这种方式初始打开ViewController并覆盖方法 私人var mapView:GMSMapView! 私有var clusterManager:GMUClusterManager! 覆盖func loadView(){ let camera = GMSCameraPosition.camera(withLatitude:37.4220,经度:-122.0841,缩放:17) mapView = GMSMapView.map(withFrame:CGRect.zero,camera:camera) self.view = mapView } 步骤3:在viewDidLoad方法内部添加代码,如下所示 覆盖func viewDidLoad(){ super.viewDidLoad() //使用默认的图标生成器和渲染器设置集群管理器。 让iconGenerator = GMUDefaultClusterIconGenerator() let算法= GMUNonHierarchicalDistanceBasedAlgorithm() 让渲染器= GMUDefaultClusterRenderer(mapView:mapView,clusterIconGenerator:iconGenerator) clusterManager = GMUClusterManager(地图:mapView,算法:算法,渲染器:渲染器) //生成随机项并将其添加到集群管理器。 generateClusterItems() clusterManager.cluster() //注册self来侦听GMUClusterManagerDelegate和GMSMapViewDelegate事件。 clusterManager.setDelegate(self,mapDelegate:self) } 私人功能generateClusterItems(){ 让范围= 0.2 用于1 … kClusterItemCount中的索引{ 令lat […]

Swift —参考类型与值类型

在Swift上,请参阅Apple文档的ClassesAndStructures:类将称为“引用类型”,而Struct将是“值类型”: – 类是引用类型:与值类型不同,将引用类型分配给变量或常量或将它们传递给函数时, 不会复制引用类型 。 而不是副本,而是使用对相同现有实例的引用。 – 结构和枚举是值类型: 值类型是一种类型,其值在分配给变量或常量或传递给函数时将被复制 。 因此,让我们尝试下面的示例来了解什么是引用类型,值类型: class HumanClass { var name: String init(name: String) { self.name = name } } var classyHuman = HumanClass(name: “Bob”) classyHuman.name // “Bob” var newClassyHuman = classyHuman // Created a “copied” object new ClassyHuman.name = “Bobby” classyHuman.name // “Bobby” 当我将newClassHuman的name属性更改为“ Bobby”时,原始对象的name属性,classyHuman也更改为“ Bobby”。 那么Struct怎么样,让我们​​看下面的例子: struct HumanStruct […]

在您的应用中采用3D Touch快捷方式项。

随着iPhone 6s的问世,Apple引入了3D Touch机制,这是非常酷的事情。 最新的iPhone 7上也可以使用3D Touch。没有任何迹象表明未来的Apple设备将使用该功能,因此,这里有一个快速教程,介绍如何使用3D Touch的三个主要功能之一来改善您的应用程序。 修改您的Info.plist文件 在您的Info.plist文件中添加一个名为UIApplicationShortcutItems的特殊键。 它应该是一个数组。 将项目添加到UIApplicationShortcutItems数组。 项目应为字典类型。 放置每个项目的信息。 在此设置的值很少。 UIApplicationShortcutItemType(必需) UIApplicationShortcutItemTitle(必需) UIApplicationShortcutItemSubtitle UIApplicationShortcutItemIconType UIApplicationShortcutItemIconFile UIApplicationShortcutItemUserInfo 我将重点介绍在示例应用程序中设置的值。 UIApplicationShortcutItemType是一个字符串,用于向您的应用程序提供有关按下了哪种快捷方式的信息。 UIApplicationShortcutItemTitle是显示快捷方式时用户看到的内容。 UIApplicationShortcutItemIconType是一个字符串,用于通知应用程序此快捷方式应使用哪种系统图标。 最后一个是UIApplicationShortcutItemIconFile定义出现快捷方式时应显示的图标名称(而不是系统图标)。 重要的是,您可以使用系统或自定义图标。 Apple建议自定义图标应为方形,单色和35×35磅。 您可以从Apple文档中获取有关UIApplicationShortcutItems键和描述的更多信息。 配置的Info.plist可能如下所示: 并通过代码: 应用程序快捷点击处理 好的,现在移至AppDelegate类,让我们处理应用程序的快捷点击事件。 1.重写并实现UIApplicationDelegate方法。 让我们专注于这种方法: 如您在上面看到的,我创建了两个带有自定义图标,标题和副标题的快速操作。 动态快捷方式项 值得一提的是动态快捷项。 是的,UIApplicationShortcutItems分为static和dynamic 。 静态-将项目放置在info.plist 动态的-可以在代码中添加和删除项目 要添加动态快捷方式项,您只需将其添加到shortcutItems数组中。 关于我 我是波兰格但斯克的软件开发人员。 大多数情况下都使用iOS,但我对其他任何技术,框架和挑战都持开放态度。 如果您喜欢我的帖子,请随时在Twitter上关注我并阅读我的个人博客。

使用协议扩展在iOS中进行编辑

iOS开发人员将遇到的最常见的事情之一是创建专用于表单输入的屏幕。 这往往包括样式化输入字段,执行验证以及保存/放弃更改。 我将向您展示如何处理UIViewController的第三项,但是以可以扩展到其他UI组件的方式。 我们将创建一个简单的协议,然后将其扩展为我们的用例。 前言 我们将使用出色的ActionKit库,通过不使用UIBarButtonItem上的target/action来使我们的代码更好。 可以使用的替代方法是RxSwift的rx_tap 。 避免target/action也意味着我们不参与Objective C运行时(库正在这样做并充当包装器),这意味着我们不必在协议上使用@objc进行方法@objc 。 协议书 由于我们是iOS的超级明星开发人员,因此我们将使用Swift及其出色的功能以侵入性最小且可重复使用的方式实现我们的目标。 首先,让我们定义一个对象可编辑的协议。 由于我们希望匹配未做任何更改时出现的后退按钮的行为,因此,我们将利用UINavigationController显示后退按钮并处理UIViewController的navigationItem 。 要指出的一点是,在设置leftBarButtonItems时,也禁用了滑动后退功能, leftBarButtonItems是我希望的行为,因为希望用户如果希望后退它们,则取消编辑。 会更反应吗? 我在iOS中使用Rx放松,所以让我们继续制作一个可绑定的接收器以进行edit(make: Bool) 现在我们可以删除对UITextFieldDelegate的使用,, 时髦! 这是一个示例,由于有了Swift的强大功能,我们无需在代码库中进行侵入性更改(即,强制每个编辑View Controller的子类都将EditViewController子类化)。 您可以通过使用协议扩展进一步扩展Editable并将其添加到自己的自定义类或其他UIKit组件中。 代码可以在这里找到。 雨燕快乐!

为什么我喜欢SnapKit,您也可以

刚开始编码时,我100%参与StoryBoard团队。 很容易看到不同的UIView是如何交互的,您可以将它们精确地放置在所需的位置。 这适用于单个屏幕尺寸,但是随着视图变得越来越复杂并且需要适应各种屏幕尺寸,约束的层次结构变得越来越难以确定。 尽管如此,程序化还是令人恐惧! Swift的内置方法是噩梦。 即使我现在已经全心全意地通过程序设计应用程序,但仅查看这些方法仍然会让我感到恐惧。 幸运的是,令许多程序员感到宽慰的是,SnapKit幸运的灵魂为iOS和OS X设计了一个完全用Swift编写的疯狂简单的自动布局DSL! 首先,只需在pod文件中使用pod ‘SnapKit’安装SnapKit CocoaPod,然后打开项目的.xcworkspace。 以编程方式设计应用程序需要一些设置。 首先转到您应用的“常规设置”,然后在“部署信息”的“主界面”下,删除“ Main所在的位置。 这告诉您的应用不再担心故事板! 尽管如此,应用程序仍需要一个切入点……这就是AppDelegate发挥作用的地方。 在这里,您要声明第一个ViewController的实例。 (如果您使用的是UINavigationController,UITabBarController或ContainerViewController,则也可以在其中进行设置,但现在我们将使用单个ViewController)。 在AppDelegate的func application(… didFinishLaunchingWithOptions…)方法中,将window初始化为具有与UIScreen绑定的框架相同的框架的UIWindow() ,然后初始化主ViewController。 接下来将window?.rootViewController设置为与您新创建的ViewController相等,并使该window可见! 五行代码,您的应用程序将打开您指定的ViewController。 现在,让我们来看看有趣的东西吧! 当然,第一步是导入SnapKit。 (如果它声称不存在这样的模块,请给它旧的Command + B;还要检查您是否在xcworkspace中工作,而不仅仅是xcodeproj)。 通常,我制作的第一个UIView会占据整个屏幕,因此让我们创建一个mainView: UIView!实例mainView: UIView! ,对其进行初始化,然后将其添加到ViewController的view将其设置为等于屏幕的大小。 在mainView.snp.makeContraints方法中,每次您写入$0它只是简单地引用受约束的-view本身! 将边缘设置为equalToSuperview将允许此View扩展到其superView(UIScreen的view )所允许的最大范围。 这是一个简单的介绍,但让我们看看snp.makeConstraints还有哪些其他选项。 现在我们有了背景视图,让我们在可能要显示一些常规信息的地方添加标题。 此新视图将添加到mainView顶部,并将与Screen / SuperView的高度成比例: 请注意,如果属性有所不同,如何将不同的约束链接在一起,并添加新行。 这使得代码非常容易键入和阅读! 在这一点上,我们有一个mainView,大小为UIScreen的青色,还有一个headerView的彩色迷离,它覆盖了屏幕的前25%。 让我们添加一个Label并将其直接放置在headerView : 使用UILabels,您不必将它们设置为特定的高度或宽度。 取决于您选择的文字和字体/大小。 这样,您只需给它一个X / Y轴位置,Xcode就会假定其余的位置。 最终结果应显示3/4青色和1/4蓝色屏幕,其中标签直接位于蓝色部分的中心。 SnapKit中提供了许多其他方法,其中大多数是完全不言自明的。 例如,如果我们希望mainLabel位于屏幕中央,但在蓝色headerView ,则可以删除centerY约束并添加新行,指示$0.top.equalTo(mainHeader.snp.bottom).offset(10) […]

WBSwiftyMenu

WBSwipeableCell用于在TableViewCell和CollectionViewCell中显示选项菜单。 我们制作了此菜单,以在单个单元格中显示多个选项。 Apple在一个单元格中最多支持3个项目,但是在我们的控制器中,您可以添加3个以上的项目。 我已经从这个控制器中获取了这个想法-> https://github.com/SwipeCellKit/SwipeCellKit 背景 我已经为tableviewcell和collectionviewcell使用了许多菜单,但是它们都有一些局限性。 WBSwipeableCell用于菜单项过多且需要在一个视图中显示的地方。 示范 菜单垂直布局 对于Vertical菜单布局,我们需要实现MenuViewDelegate协议的一种可选委托方法,如下所示 func menuView(_ view:MenuView,menuLayoutForRowAtIndexPath indexPath:IndexPath)-> MenuLayout { 返回.vertical } 菜单方块布局 对于Square菜单布局,我们需要实现MenuViewDelegate协议的一种可选委托方法,如下所示 func menuView(_ view:MenuView,menuLayoutForRowAtIndexPath indexPath:IndexPath)-> MenuLayout { 返回.square } 菜单水平布局 对于水平菜单布局,我们需要实现MenuViewDelegate协议的一种可选委托方法,如下所示 func menuView(_ view:MenuView,menuLayoutForRowAtIndexPath indexPath:IndexPath)-> MenuLayout { 返回水平 } 有关此控制器的详细信息,可以在Github上进行检查:https://github.com/mwaqasbhati/WBSwipeableCell 我希望大家分叉它,并帮助我改进此库。

使用Swift-NIO开发基本的Swift Echo Server

我不是Java或JVM类型的开发人员。 这可能是我从未感到需要尝试Netty框架的原因之一。 我一直在用Erlang,Elixir或Go开发所有高性能服务器代码,并对工具感到满意。 但是,Apple最近发布了Swift-NIO,这是一个用于开发跨平台服务器和客户端应用程序的新库和框架。 我不是前端开发人员,而是更具可伸缩性的后端开发人员。 就是说,我喜欢Swift编程语言,并且自从Apple在2014年发布它以来就一直关注着它的进步。这就是为什么这个新框架引起了我的注意。 编写服务器端软件有多好? 由于Swift-NIO是Netty的一个端口,它是由Netty杰出贡献者Norman Maurer领导的团队开发的,因此我首先研究了Netty设计,以更好地了解Swift-NIO的工作方式。 我喜欢我所读到的东西。 Netty的概念提供了很好的通用抽象,这是好的网络应用程序所共有的。 它是一个参考框架,在Java世界中用于构建许多非常高级的服务器和客户端工具。 这些概念与Swift编程语言非常吻合。 很好的契合度让我认为这确实可以加速Swift服务器端开发和跨平台推广。 我敢打赌它可能会产生很大的影响,并帮助Swift继续迅速崛起为顶级编程语言之一。 Swift-NIO依赖于非阻塞IO。 这意味着您可以通过使中间层分派准备好处理到工作线程的网络操作的方式,来管理相对数量的线程,从而管理大量的网络连接。 因此,从处理线程的角度来看,网络操作是无阻塞的。 他们可以完全使用CPU,因为它们可以共享大量套接字的网络操作,而无需等待。 在Swift-NIO措辞中,阻塞操作被委派给通道。 通道将网络操作上的事件触发到负责管理通道的事件循环。 开发人员将服务器或客户端的逻辑作为处理程序提供给事件循环。 处理程序是实现触发网络事件时执行的操作的代码段。 可以将它们组合在处理程序管道中以提供额外的灵活性。 这为去耦增加了一层,并使处理程序更可重用。 在客户端服务器环境中,“ Hello World”应用程序通常是“ Echo”服务器。 服务器接收客户端发送的内容,并将其发送回客户端。 使用Swift-NIO非常容易实现。 让我们看看如何做到。 请注意,以下步骤已在MacOS上进行了测试,但是如果您已安装Swift,则它们也应该在Linux上也可以使用。 您可以使用Swift命令行引导项目: $ mkdir EchoServer $ cd EchoServer / $ swift package init —键入可执行文件 创建可执行程序包:EchoServer 创建Package.swift 创建README.md 创建.gitignore 创建源/ 创建Sources / EchoServer / […]