Tag: 软件开发

iOS-SOLID原则第1页-SRP

SOLID原则是5个OOP设计原则,可帮助您使软件更加灵活,可读性和可维护性。 在这个由五部分组成的系列文章中,我将介绍其中的每一个,并通过示例介绍其中的每一个如何为您提供帮助。 S —单一责任原则(或简称为SRP) 一个模块应该只有一个责任,只有一个改变的理由。 O —打开/关闭原理(OCP) 应该打开一个模块进行扩展,但关闭该模块进行修改。 L — Liskov替换原理(LSP) 程序中的对象应该可以用其子类型的实例替换,而不会改变该程序的正确性。 I —接口隔离原理(ISP) 许多特定于客户端的接口比一个通用接口要好。 D-依赖倒置原则(DIP) 一个人应该“依靠抽象而不是凝结。” 在第一部分中,我将介绍第一个原理SRP。 我认为,这是iOS开发中最重要的5个。 “一个模块应该只有一个责任,只有一个改变的理由。” 从本质上讲,这意味着代码中的对象,类型,类或任何其他模块应负单一责任,这也是更改的唯一理由。 为了说明这一点,假设您有一个应用程序,用户可以在其中设置个人资料图片。 该图像仅显示给用户,因此可以将其存储在磁盘上。 没有SRP,用于编辑个人资料图片的视图控制器将如下所示: 它不在乎也不应该在意如何将食物带到餐桌上。 唯一的责任就是吃它。 他不需要知道您换了工作,升职或被解雇了。 他根本不在乎您如何工作,只要您将他需要的食物带给他即可。 —唯一要担心的是。 我们的下一步将是分离关注点。 就像上面的猫一样,我们的视图控制器不需要知道默认的配置文件资产名称,也不需要知道如何保存它或保存在哪里。 唯一的责任是在UIImageView上显示UIImage。 现在,我们需要一个将处理所有个人资料图片加载和保存的类。 我们可能最终会得到这样的结果: 因此,视图控制器现在看起来像这样: 如我们所见,将个人资料图片管理与视图控制器分离,可以为我们提供更高的可读性和灵活性。 首先,该类现在可以在其他视图控制器中使用,因为我们将个人资料图片管理职责分离到了另一个模块。 现在也阅读视图控制器会更好。 我们只需将图像从ProfilePicManager加载到将在完成时调用的闭包上,然后显示图像。 认为这种方法比第一种更好,但仍不是SRP。 因为如果我们需要保存的图像不是个人资料图片,还会存储更多图像吗? 在前面的示例中,我们将个人资料图片管理与视图控制器分开。 但是我们的ProfilePicManager没有单一职责。 目前它有两件事: 个人资料图片管理 从存储层获取数据(在这种情况下为文件系统) 从中获取图像或保存图像的方式不是ProfilePicManager的责任或责任。 唯一的工作是从存储层获取个人资料图片,并在用户选择图片时将其交给存储层。 一个模块应该只有一个责任,只有一个改变的理由 。 如果确实要仅更改存储层(例如,从文件系统存储更改为远程服务器存储),而这与ProfilePicManager无关,则也必须更改它。 那不是我们想要的。 在这种情况下,使用SRP,我们只想更改存储层模块。 为了实现这一点,我们将不得不再创建一个类来处理与存储层的通信-ImageStorage 。 […]

iOS开发人员设置:清理,准备

从干净的石板开始,并添加必需品:rvm,npm,自制 这篇文章是有关设置iOS开发环境的系列文章的一部分。 我上一次设置iOS环境时,我的Mac已作为学生机器使用了多年。 我在数十个教程中都失败或部分安装。 我有用于语言的SDK,我再也不会碰。 在开始设置环境之前,我清理并清除了所有可能的旧应用程序和安装。 如果您是从一台闪亮的新机器或全新安装开始的,则可以跳过第一部分。 塔布拉罗莎 您需要自行决定清洁机器的认真程度。 因为我不信任几年前愚昧无知的安装完整性,所以我清除了ruby,rvm,rbenv,gem,postegres,sqlite,node,javascript和bundler。 万一我弄坏了东西,在清洁过程之前克隆硬盘驱动器就给了我一个安全网。 删除所有内容后,我确认系统已在运行且稳定,因此再次克隆,以便在安装出现问题时可以重新使用。 Ruby和RVM(红宝石版本管理器) 安装rvm来管理您的ruby版本。 这将安装rvm和Ruby的最新稳定版本。 \ curl -sSL https://get.rvm.io | bash -s稳定–ruby 您可能需要根据所使用的宝石和Cocoapods版本在Ruby的不同版本之间进行切换。 除了最新的稳定发行版,这些是我安装的版本: rvm安装2.2.3 rvm安装2.4.0 列出可用的版本,并将2.2.3(或您的首选版本)设置为默认值: rvm列表已知 rvm-默认使用2.2.3 家酿 是否安装了自制软件? 酿造-v 如果没有,请继续并立即安装。 将以下内容复制并粘贴到命令提示符中,然后按Enter。 /usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)” 如果您有自制软件,请更新并运行医生。 解决出现的任何问题。 酿造更新 酿造医生 尝试酿造更新时权限错误的快速修复:“ / usr / local error”: 须藤chown -R $(whoami)/ usr / local […]

迅捷:链式铸造

正如我之前在Swift的类型推断中所提到的。 我真的对在我的代码中各处编写iflet和guard感到厌倦。 Swift中的类型推断 我要坦白。 我真的对在我的代码中各处编写iflet和guard感到厌倦。 有… blog.idapgroup.com 为了概述问题,让我们假设有一个UITableView ,其中我们需要呈现来自不同继承层次结构的UITableViewCell子类: 然后,让我们想象一下,Swift开发团队会使iflet失效。 众所周知,xCode Swift迁移工具并非始终可用,在某些情况下,我们必须手动重写代码。 我在Swift选择器上进行了这样的转换,这对我来说是一个巨大的痛苦。 而且,在我看来,iflets违反了我们所有人都喜欢和崇拜的DRY原则。 非DRY代码在重构或重写方面确实很痛苦,因为您没有集中的访问点。 为了解决这些问题,我更喜欢使用自己的解决方案: 稍后我们将详细介绍实现细节,但是现在让我解释一下,为什么我(不是真的)认为这种解决方案更好: 它使用类型推断; 富有表现力; 它是可扩展的; 它很健壮。 是的,我知道,对于任何不了解它的新手来说,它会使学习曲线更加陡峭。 是的,开关模式匹配也可以做到这一点,尽管语法会更加冗长。 但是它最终提供的是,只要我遵守界面,就可以注入任何我想要的行为,无论Swift如何改变。 当然,如果您愿意使用它,那将最终由您决定。 我绝对喜欢,因为我可以用更少的按键来表达相同的逻辑,并专注于真正重要的东西(我关于我要表达的内容的想法,而不是我要表达的想法)。 那么,它是如何在后台运行的呢? 请阅读我以前有关强制转换功能的文章之一。 为了更大的利益,我将在此处概述其签名,但是您需要知道如何使用它: 我提出的解决方案的实质是基于Castable泛型类型的: 首先,让我们回答一个最明显的问题:“为什么我们要在一种情况下使用switch ? 原因是很简单。 为了让Swift在没有默认返回值的情况下处理这样的表达式,该函数应该是穷举的,除了涵盖所有枚举情况的开关,Swift都认为该函数不是穷举的。 穷举是指处理所有枚举的情况。 此外, 如果case的语法更差: 这将失败,并在预期返回’NonExhaustive ‘的函数中缺少返回错误,并使用默认返回值作为self重写它可以解决问题: 但这只是为了自己的利益而编写的太多代码。 可能会出现的第二个问题是:“它是如何工作的?” 您看,我认为Castable作为一种类型可以通过两种方式进行处理:匹配和提取。 通过匹配,我的意思是强制转换一个包装的值,如果强制转换成功,则使用强制转换的结果调用该函数。 为了能够链接操作,我只返回了另一个包装相同值的Castable 。 提取只是解包并返回一个值。 从我的观点来看,通过一遍又一遍地重写相同的行来创建Castable不是一个好主意。 试想一下,每次要使用匹配和提取时,都必须编写Castable.value(x).match(…这是最常见的用例,对吗?可悲的是,我们不能只创建一个全局变量函数超出Castable.value初始值设定项,因为Swift不允许泛型使用该函数: let castableFunction = Castable.value导致错误:无法推断出泛型参数“ Wrapped”注意:显式指定泛型参数来解决此问题 。我能说什么Swiftc,你喝醉了,回家。 因此,为了修复该问题,我创建了几个最常用的功能-我认为是这样的情况: […]

Mengenal代表团pada Swift

彭加塔尔 Biasanya kalau bermain dengan UITableView ataupun UICollectionView杨diletakkan pada UIViewController Pasti akan menemui suatu语法sepiti ini … self.tableView.delegate =自我 Untuk bisa berinteraksi dengan tableView塔迪,misalkan melakukan suatu aksi tertentu ketika salah satu baris pada tableView telah dipilih maupun akan dihapuskan,maka kita sering kali menggunakan 代表团 pada tableView supaya bisa melakukan aksi dissebutbut。 彭巴哈桑 塞卡拉·巴哈萨(Secara bahasa), 代表团成员 auau […]

适用于开发人员的iOS App开发的新趋势2018

如今,iOS应用程序的需求量更大。 iOS应用开发公司推出了许多新功能。 苹果公司首先在iPhone和iPad中应用了几乎所有新技术。 例如,iBeacon是被视为物联网的设备,可以使更多更好的应用程序和用户使用更加便捷。 苹果一直在为用户提供新的东西,并保持其简单和安全。 在此博客中,我们正在分享针对Developers 2018的iOS App开发中的一些新趋势。 iOS应用程序开发的主要趋势 随需应变iBeacon技术 iBeacon是Apple的专利之一,但这并不意味着Android设备和其他媒体也看不到该信标。 信标和iBeacons并不仅仅适用于Apple设备,您还可以在客户支持中使用它们。 零售商在本地市场使用信标技术可能会获得巨大利益。 该技术最初在2015年初未被接受。但是,很少有Apple iOS App为零售业推出Beacon App,并且与其他技术相比,其成功率呈爆炸式增长。 当地市场的主人说: 到2016年,已有85%的美国零售商使用过Beacon。 云创新相结合 如您所知,根据用户需求,应用程序开发受到限制。 用户想在任何地方访问应用程序。 对于Android和IOS应用程序而言,安全性是其最大的弱点。 用户正在全球范围内使用智能手机。 商界人士可以使用云计算功能来保持与协作者和客户之间远距离位置的关系。 您可以向差旅员工,自由职业者或远程员工提供访问信息,以实现良好的工作与生活和谐。 Swift编程—创建出色的应用 自几年前以来,Objective-C一直是iOS应用程序的主体。 Swift是一种创新技术,它是Apple的一种新的专有编程语言,可以与Objective-C共存,但要好得多。 斯威夫特语言在增长。 如果他们正在开发应用程序,则必须立即学习Swift。 语言不会随着Apple发明该语言而改变。 Swift将为iPhone,Mac和iPad用户带来更好的应用程序。 与Objective-C相比,Swift的编码速度更快,测试更容易。 Swift旨在提供与Cocoa和Objective-C的无缝兼容性。 Swift旨在替代Apple应用程序的Objective-C,并提供比Python更强大的语言。 Swift是2018年iOS应用程序开发中最受欢迎的趋势之一。

Objective-C中的单元测试

飞行猕猴桃 每种语言都有自己的规则。 查看语法,语言功能或语言类型都没关系。 一切都改变了,同时保持不变。 在我们的主题应用程序中,我们将使用swift,但是由于Objective-C是iOS开发的起源,因此我们绕了弯路,以了解此处的具体操作。 我不是XCTest的忠实拥护者。 不要误会我的意思,它确实可以正常工作..但是就这样..就可以了。 了解我们要测试的应用程序和操作的整体状态,取决于我们命名测试的能力。 总的来说,我们很讨厌这样做。 一种替代方法是基于RSpec的框架。 他们在我们的测试中添加了语法糖,可能只是为了了解测试2小时或解决问题而有所不同。 猕猴桃 对于Objective-C,这是猕猴桃。 它提供了我们可以描述,正在测试什么以及处于何种状态的不同阶段: describe :描述被测系统(sut) 上下文 :描述缝合状态 关于这些定义,我们可以编写一个带有演示类的简单测试文件结构: 私下入侵 我已经提到每种语言都有自己的怪癖。 在Objective-C中,私有不存在。 相反,它仅对编译器可见。 我们仍然可以通过运行时将消息发送到对象的特定实例,从而忽略可见性。 好的..我们不会开始使用objc_msgSend。 不用担心 相反,我们可以使用类别来完成这项工作。 在我们的测试类中,我们将添加一个类别,其中包含我们要测试的所有私有属性和方法,这些属性和方法无法从外部访问。 这样做将为编译器提供可见性,即使它们被认为是私有的,我们也可以将任何消息发送给对象。 存根 时不时地,我们不得不依靠我们无法控制的API。 这可以是简单的SDK API或网络服务。 想象一下有一个登录视图控制器。 您如何测试呢? 尤其是当您的测试应该在没有外部依赖性的黑暗洞穴中运行时,该怎么办? 欢迎进行嘲笑和存根。 在本文中,我们将讨论如何在单元测试和集成测试中对方法调用进行存根。 存根的想法是通过指定返回值或简单地替换它来定义方法调用的行为。要存根方法,我们需要对象对此方法做出响应。 有了这个,我们可以简单地通过编写以下代码来定义返回值: [testClass存根:@selector(方法)和Return:Value]; 该值可以是任何值:布尔值,NSString,NSInteger或您返回的任何值。 猕猴桃不在乎。 这样,我们可以简单地替换本地网络服务器的登录方法。 是不是很简单? 但是,当我们无法获得所用类的实例时,我们该怎么办? 铁杆存根 为此,有方法令人毛骨悚然。 这是Objective-C内的黑魔法的一部分,不应粗心使用。 但是,如果您知道自己在做什么,并且将其用于测试,则可能会从中获得一些价值。 那么什么是方法混乱? 基本上在运行时,您将另一个方法添加到一个类中,并用另一个方法切换该方法的签名。 关于我们先前描述的登录方法,让我们添加另一个名为swizzleLogin的方法。 通过使用swizzleLogin修改登录方法,现在每次登录都将执行swizzleLogin,反之亦然。 这很容易做错,所以让我们介绍一下JRSwizzle。 […]

如何在iOS测试中使用Chaos

您听说过无穷大的猴子定理吗? 内容如下: “如果您让猴子在打字机上敲击随机键,在无限的时间内,它会扑灭任何预期的书面文字” 还有其他版本使用无限数量的猴子而不是时间。 作为应用程序开发人员,我们有类似的情况。 我们的应用程序被大量以无法想象的方式使用我们的应用程序的用户使用(好吧,他们被编号了,而不是猴子,但是仍然相似。) 结果,他们将发现我们从未预料到的错误。 那么我们该怎么做呢? Netflix创造了一个新名词:混沌工程。 这样做的目的是在生产代码中引入混乱,以发现系统在出现故障时的行为。 他们发表了他们的混乱猴子,杀死了他们生命系统的实例。 我们也许可以在后端系统上使用它,但是总的来说,我们的应用程序有其自身的问题,我们不能仅仅在用户使用它们时就杀死它们;)。 所以,我们能做些什么? 单元测试 在为算法编写单元测试时,通常必须减少输入值,因为它们可能很大。 相反,我们考虑一些极端情况并进行测试。 可悲的是,这可能导致我们遗漏了一些错误。 考虑到上述在测试中添加受控混乱的想法,我们可以开始使用特定范围内的随机值。 这些值需要生成,并且我们的算法必须包含一个条件(意味着条件始终为真)。 幸运的是,我们不必自己写所有这些随机性。 SwiftCheck已创建为我们做到这一点。 让我们开始吧! 阅读以下说明时,请考虑将电子邮件作为我们的域结构: 结构电子邮件{ var local:字串 var host:字符串 var tld:字符串 } 发电机 在SwiftCheck中,您可以使用生成器来创建任意数据。 尝试生成电子邮件地址时,我们必须生成三个部分:本地,主机和TLD。 本地部分可以包括大写和小写字母,数字和某些种类的字符。 完成此操作后,我们可以构建库并以通常的方式包括它们: 迦太基建造 完成所有这些之后,我们可以添加相应的测试: 结论 即使是最优秀的开发人员,也无法预测其应用程序可能具有的所有状态。 这导致没有测试所有内容。 由于没有人是完美的,并且我们无法测试所有内容,因此我们的应用程序容易出现错误。 找到这些错误很困难,但是混沌测试可以提供帮助。 在单元测试中,我们可以在测试算法时测试各种属性。 在UI测试中,我们可以使用猴子来完成应用程序的操作,这是我们从未想到的。 听起来需要做很多工作,但是由于这可以防止生产中的重大错误,因此我认为这是值得的。 如上文所述,它甚至可以用于查找生产中的错误。 如果您感兴趣,它是UIWebView。 从iOS 9开始,似乎每个导航都会创建很多手势识别器。 过渡到其他页面时,这些页面不会被释放,因此会保留下来。 当您触摸屏幕时,所有这些动作都会使主队列超载,从而使您的应用无响应。 最后,看门狗杀死了它。 上一篇:黄金大师测试

解决iOS GIT问题

Quienes manejamos GIT,在线阅读和阅读“ enfrentado”,即解决冲突。 Pensémoslo,nuestro proyecto no puede ejecutarse por ellos,veces resultandifícilesde entender,involucra coordinarse con el resto de los desarrolladores para saberquécambios deben conservarse ycaálesno…etc。 Es por ello,que enéste指导我gustaríahablar acerca de lo que儿子,iOS系统的可识别性和解决方案,以及ejemplo的翻译。 AJMSlideAnimator Supongamos estamos trabajando en el proyecto AJMSlideAnimator,un proyecto disponible en Github和los cuales存在2个desarrolladores:CTime95(中央存储库)和TheKairuz(中央存储库)。 故事板中的Ambos desarrolladores se encuentran上的子句AJMSlideAnimatorView和se encuentran ajustando constantemente。 Ajustes TheKairuz […]

Swift-Objective-C的终结……?

根据某些数据,Apple的策略是通过减少代码来过渡到这种新语言,从而简化开发工作,而最终由“ Swift”这个名字来强调。 尽管如此,Objective-C仍然是一种落后了几年的语言,但是Apple提出了向SWIFT驱动的环境迈进的问题。 根据Apple的说法,学习SWIFT比使用Objective-C更容易。 到今天为止,尚未确认任何消息,Apple还没有强迫开发人员将其代码从Objective-C重写为SWIFT。 苹果公司在开发iOS本机应用程序时仅推荐使用Swift。 正如苹果所说,Swift是“没有C的Object-C”。

警卫声明被低估

前几天,当我与一个朋友谈论函数式编程时,我意识到我们经常只喜欢讨论性感的东西,而对其他简单的东西没有给予足够的重视。 在Swift中, guard声明是我认为功能非常强大但没有得到编程社区足够重视的小功能之一。 Guard不仅是if !condition语句的语法糖。 考虑以下代码。 如果!loading { 加载() } 如果当前状态未加载,它将加载。 但是我们可以更好地编写如下: 如果正在加载{return} load() 当前状态加载时返回。 它更干净,我们能够从花括号中取出load() 。 并且请注意,上面的if语句不只是if 。 如果是特殊的,用于提早返回。 它应该拥有自己的语法。 从版本2开始,Swift为此提供了guard声明。 警卫!loading else {return} load() 确保当前状态未加载,否则返回。 如果错过了return ,编译器将抱怨。 与使用if语句的版本相比,它更容易理解,因为它使用特殊的条件语法。 我们马上就知道那条线是干什么的。 警卫队要早日返回。 通常,我们将它们放在函数的顶部。 但是, guard声明并不公平,因为对我们大多数人来说,这只是一个条件声明。 但是我认为, guard应该得到更多的荣誉。 考虑以下代码。 守护!loading else {return} 警卫!渲染其他{返回} 卫队个人资料已加载其他{返回} 警卫文章已加载其他{返回} 警卫评论加载其他(返回) 守卫likesLoaded else {return} render() 以上代码在控制器中非常常见。 控制器通常是最复杂,最难阅读的。 想象一下:当控制器从服务器加载数据时,可能会发生很多事情,例如,推送通知到达,按下后退按钮,按下主屏幕按钮进入背景,设备旋转,无意间轻按了随机按钮,网络中断等等。 所有这些都应该得到妥善管理,这非常困难。 这就是为什么控制器非常丑陋的原因。 但是guard声明使它更令人恶心! […]