iOS开发人员必须知道的14件事

经作者许可,我发表了Norberto Gil Vasconcelos的文章翻译,内容为“ 14位iOS开发者必须知道”链接到原始作者)。在本文发表时,Swift 3版本是相关的,

作为iOS开发人员(目前绝对依赖Swift),我从头开始创建了应用程序,受支持的应用程序并在各个团队中工作。在从事该行业的所有时间里,我经常听到这样的短语:“您无法解释,那么您将无法理解。”因此,为了理解我每天到底要做什么,我创建了一份清单,我认为这对任何iOS开发人员都很重要。我会尽力解释每时每刻。 [请随时纠正我,表达您的意见或建议您对此列表进行补充。]


主题: [ 版本控制 | 建筑图案 | Objective-C的与斯威夫特 | 反应 | 依赖管理器 | 信息存储 | CollectionViews和TableViews | 用户界面 | 协议 | 短路 | 方案 | 测试 | 地理位置 | 可本地化的字符串 ]


这是我的列表,事不宜迟,随机排列。

1- 版本控制


恭喜,您已被接受!从存储库中提取代码并开始工作。停什么

版本控制对于任何项目都是必需的,即使您只是开发人员。最常用的系统是Git和SVN。

SVN基于集中式版本控制系统。这是在其中创建工作副本的存储库,要访问它们,您需要网络连接。更改授权以特定方式进行;系统通过注册每个文件来监视更改,更改的完整历史记录只能在存储库中查看。工作副本仅包含最新版本。

吉特使用分布式版本控制系统。您将拥有一个可以在其中工作的本地存储库,只有同步才需要网络连接。更改工作副本时,将保存整个目录的状态,但仅记录所做的更改;存储库和工作副本都具有完整的更改历史记录。

2- 建筑图案


您的手指激动得发抖,您发现了版本控制功能!还是因为喝咖啡?没关系!您即将来到,编程的时机已到!不。还等什么呢?
坐在键盘上之前,必须选择要遵循的建筑模式。如果尚未启动项目,则必须匹配现有模式。
在移动应用程序的开发中使用了多种模式(MVC,MVP,MVVM,VIPER等)。我将简要概述iOS开发中最常用的:

  • MVC — Model, View, Controller. Controller Model View, . View Controller , Controller . ? , View, (ViewController) . , MVC. MVC . ( !), , , Model, , . MVC , , iOS .


    MVC –
  • MVVMModel, View, ViewModel. ( ) View ViewModel, ViewModel , ViewModel, View - . ViewModel View, , .


    MVVM –


为了更深入地了解和了解其他模式,建议阅读以下文章

这看起来可能不那么多,但是结构良好且组织良好的代码可以避免很多麻烦。每个开发人员在某个时候犯的一个大错误就是仅仅获得期望的结果而拒绝组织代码,错误地认为这样做可以节省时间。如果您不同意,请听旧的Benji:
您花在组织业务上的每一分钟都可以节省一个小时

-本杰明·富兰克林

我们的目标是获得易于使用和维护的直观易读的代码。

3- Objective-C与Swift


在决定使用哪种编程语言编写应用程序时,您应该知道它们各自具有的功能。如果可能的话,我更喜欢使用Swift。为什么?老实说,与Swift相比,Objective-C几乎没有优势。大多数示例和教程都是用Objective-C编写的,而Swift每次更新都会对范例进行调整,这可能会令人沮丧。但是,这些问题最终将消失。

与Objective-C相比,Swift在许多方面都有了飞跃。它易于阅读,看起来像自然的英语,并且由于它不是基于C的,因此您可以放弃传统约定。对于那些了解Objective-C的人来说,这意味着不再需要分号,并且方法调用和表达式条件也不需要放在方括号中。维护代码也更容易:Swift仅需要.swift文件而不是.h和.m文件,因为Xcode和LLVM编译器可以检测依赖关系并自动执行增量构建。通常,您不必担心创建标准化代码,并且您会发现用更少的行就能达到相同的结果。

还是有疑问吗? Swift更安全,更快速,并且可以进行内存管理(大部分情况下!)。您知道用未初始化的指针变量调用方法时在Objective-C中会发生什么吗?没有。该表达式变为非活动状态并被跳过。听起来不错,因为它不会导致应用程序崩溃,但是会导致许多错误和不稳定行为,因此您需要考虑改变职业。说真的成为专业的walk狗人的想法闪耀着新的色彩。同时,Swift计数器可使用可选值。您不仅会更好地了解nil可以做什么,并设置条件以防止使用nil值,而且如果仍然使用nil可选,还会导致运行时崩溃,这将简化调试。ARC(自动引用计数)可帮助您更好地管理Swift中的内存。在Objective-C中,ARC不适用于过程C或诸如Core Graphics之类的API。

4- 反应还是不反应?(就是那个问题)


功能反应式编程(FRP)是新的热门。它旨在简化异步操作和事件/数据流的编译。对于Swift来说,这是通过Observable接口表达的通用计算抽象。

举例说明,最简单的方法就是编写一些代码。假设婴儿蒂米(Timmy)和他的妹妹珍妮(Jenny)想购买一个新的游戏机。蒂米每周从父母那里收到5欧元,詹妮也是如此。但是,珍妮在周末分发报纸又赚了5欧​​元。如果两者都节省一分钱,我们可以每周检查控制台是否可用!每次储蓄的值更改时,都会计算其总值。如果足够,该消息将存储在isConsoleAttainable变量中。在任何时候,我们都可以通过订阅来检查消息。

// 
let timmySavings = Variable(5)
let jennySavings = Variable(10)

var isConsoleAttainable =
Observable
.combineLatest(timmy.asObservable(), jenny.asObservable()) { $0 + $1 }
.filter { $0 >= 300 }
.map { "\($0)    !" }

//  
timmySavings.value = 10
jennySavings.value = 20
isConsoleAttainable
   .subscribe(onNext: { print($0) }) //   

//  
timmySavings.value = 100
jennySavings.value = 200
isConsoleAttainable
   .subscribe(onNext: { print($0) }) // 300    !

这只是FRP可以完成的一个示例,一旦您掌握了FRP,它将为使用MVC以外的体系结构开辟一个全新的可能性世界……是的,是的!MVVM!
您可以查看两个主要的Swift FRP头衔申请人:


5- 依赖经理


CocoaPods和Carthage是Cocoa Swift和Objective-C项目中最常见的依赖项管理器。它们简化了实现库并保持其最新状态的过程。

CocoaPods有许多使用Ruby构建的库,可以使用以下命令进行安装:

$ sudo gem install cocoapods

安装后,您将要为您的项目创建一个Podfile。您可以运行以下命令:

$ pod install

或使用以下结构创建自定义Podfile:

platform :ios, '8.0'
use_frameworks!

target 'MyApp' do
pod 'AFNetworking', '~> 2.6'
pod 'ORStackView', '~> 3.0'
pod 'SwiftyJSON', '~> 2.3'
end

创建完成后,就该安装新模块了:

$ pod install

现在,您可以打开项目.xcworkspace,不要忘记导入依赖项。与CocoaPods不同,

Carthage是一个分散的依赖性管理器。这样做的缺点是,用户查找现有库变得越来越困难。另一方面,此方法需要较少的支持工作,并避免了由于集中存储而造成的中断。

有关安装和使用的更多信息,请查看GitHub项目

6- 数据存储


让我们从最简单的方法为应用程序保存数据开始。之所以命名为NSUserDefaults,是因为它通常用于保存应用程序首次加载时显示的默认用户数据。因此,它变得简单易用,但这也意味着一些限制。其中之一是此方法接受的对象的类型。它的行为与属性列表(Plist)非常相似,后者具有相同的限制。它们可以存储以下六种类型的对象:

  • NSData
  • NSDate
  • NS编号
  • NSDictionary
  • Nsstring
  • NSArray

为了与Swift兼容,NSNumber可以接受以下类型:

  • UInt
  • 整数
  • 浮动
  • 布尔

可以按如下方式将对象存储在NSUserDefaults中(首先创建一个常数,该常数将存储所存储对象的密钥):

let keyConstant = "objectKey"

let defaults = NSUserDefaults.standardsUserDefaults()
defaults.setObject("Object to save", objectKey: keyConstant)

要从NSUserDefaults中读取对象,我们可以执行以下操作:

if let name = defaults.stringForKey(keyConstant) {
   print(name)
}

有几种方便的方法可以读取和写入NSUserDefaults,这些方法接收特定的对象而不是AnyObject。

钥匙串是一个密码管理系统,可能包含密码,证书,私钥或个人注释。钥匙串具有两个级别的设备加密。第一级使用锁定屏幕锁定代码作为加密密钥。第二级使用生成并存储在设备上的密钥。

这是什么意思?这不是绝对超级安全,尤其是在锁定屏幕上不使用密码的情况下。由于第二级使用的密钥存储在设备中,因此还有其他方法可以访问。

最好的解决方案是使用您自己的加密。 (不要将密钥存储在设备上)

CoreData-这是Apple开发的框架,因此您的应用程序可以以面向对象的方式与数据库进行交互。通过减少代码量并消除了测试本节的需要,这简化了过程。

如果您的应用程序需要持久性数据,则应使用CoreData,这将大大简化保存它们的过程,并允许您不创建/测试自己的与数据库通信的方式。

7- CollectionViews和TableViews


几乎每个应用程序都有一个或多个CollectionViews和/或TableViews。了解它们的工作方式以及何时使用一种或另一种将防止将来对应用程序进行复杂的更改。

TableViews在垂直的单个列中显示项目列表,并且仅受垂直滚动限制。每个项目都由一个UITableViewCell表示,可以完全自定义。它们可以按节和行进行排序。

CollectionViews还显示项目列表,但它们可以具有多个列和行(例如,网格)。它们可以水平和/或垂直滚动​​,每个元素由一个UICollectionViewCell表示。与UITableViewCells一样,可以根据需要对其进行自定义并按节和行进行排序。

它们都具有相似的功能,并使用可重复使用的单元来提高移动性。您需要什么的选择取决于列表上要具有的复杂性。 CollectionView可用于表示任何列表,我认为,它始终是最佳选择。假设您要提交联系人列表。该列表很简单,您可以用一个列来实现它,因此选择一个UITableView。一切正常!几个月后,您的设计师将决定应以网格格式而不是列表显示联系人。唯一的方法是将UITableView的实现更改为UICollectionView的实现。我想说的是,尽管您的列表可能很简单,并且如果设计更改的可能性很大,那么UITableView可能就足够了,最好使用UICollectionView实现此列表。

无论您做出什么选择,创建一个通用的TableView / CollectionView都是一个好主意。这有助于实现并允许重用大量代码。

8- 情节提要VS Xibs VS可编程UI


这些方法中的每一个都可以单独用于创建用户界面,但是没有什么可以阻止您将它们组合在一起。

故事板提供了设计人员希望的项目的更广泛视图,使您可以查看应用程序的流程及其窗口。缺点是,随着窗口的增加,连接变得更加混乱,并且情节提要的加载时间增加。合并问题更为常见,因为整个用户界面都在单个文件中。它们也变得更加难以解决。

锡伯斯提供窗口或窗口部分的可视视图。优点是易于重用,与情节提要相比合并冲突更少,并且易于查看每个窗口的内容。

通过编程用户界面,您可以更好地控制它,减少合并冲突的频率,如果发生冲突,则更容易消除。缺点是可视化较少,编写时需要更多时间。

创建用户界面的上述方法差别很大。但是,以我的主观观点,最好的选择是将这三者结合起来。几个情节提要板(现在我们可以在情节提要板之间切换!),使用Xib代替不是主窗口的任何可视对象,最后还需要进行一些编程以进行其他控制,因此在某些情况下是必需的。

9- 协议!


在日常生活中,存在协议,因此在某种情况下我们知道如何应对。假设您是一名消防员,并且发生了紧急情况。每名消防员都必须遵循一项协议,该协议列出了成功响应的要求。Swift / Objective-C中的协议也是如此。

协议定义了指定功能的方法,属性和其他要求的草图。它可以由类,结构或枚举采用,然后将具有这些要求的实际实现。

这是创建和使用协议的

示例在我的示例中,我将需要一个枚举,列出用于扑灭火灾的不同类型的材料。

enum ExtinguisherType: String {

   case water, foam, sand

}

接下来,我将创建一个紧急响应协议。

protocol RespondEmergencyProtocol {

   func putOutFire(with material: ExtinguisherType)

}

现在,我将创建一个遵守该协议的消防员类。

class Fireman: RespondEmergencyProtocol {

    func putOutFire(with material: ExtinguisherType) {

       print("Fire was put out using \(material.rawValue).")

    }

}

精细!现在我们使用消防员。

var fireman: Fireman = Fireman()

fireman.putOutFire(with: .foam)

结果应该是:“用泡沫扑灭了火。”

委托中也使用协议。这允许类或结构将某些功能委托给另一种类型的实例。创建具有委托职责的协议,以确保其功能具有适当的类型。
一个小例子!

protocol FireStationDelegate: AnyObject {

func handleEmergency()

}

消防部门委托消防员采取应急措施。

class FireStation {
   weak var delegate: FireStationDelegate?

   func emergencyCallReceived() {
      delegate?.handleEmergency()
   }
}

这意味着消防员还必须遵守FireStationDelegate协议。

class Fireman: RespondEmergencyProtocol, FireStationDelegate {

   func putOutFire(with material: ExtinguisherType) {
      print("Fire was put out using \(material.rawValue).")
   }

   func handleEmergency() {
      putOutFire(with: .water)
   }

}

所有要做的就是让消防员被任命为消防局的代表,他将处理接到的紧急呼叫。

let firestation: FireStation = FireStation()
firestation.delegate = fireman
firestation.emergencyCallReceived()

结果,我们得到:“用水灭火了。”

10- 短路


它只涉及Swift闭包。它们主要用于返回尾随块或具有高阶函数。顾名思义,最终块用于在任务完成后执行代码块。
Swift中的闭包类似于C和Objective-C中的闭包。

闭包是一流的对象*,因此可以嵌套和传递闭包(类似于Objective-C中的块)。

在Swift中,函数是闭包的特殊情况。

来源-fuckingswiftblocksyntax.com **

该资源是学习闭包语法的好地方。

*一流的对象-可以不受限制地使用的对象:分配给变量,从函数传递/返回,在程序执行期间创建/销毁等。更多细节(以下简称-近似翻译器)
**该站点无法正常运行,但是在Waybackmachine中仍然有图片,例如


十一- 方案


简而言之,电路是在配置之间切换的任何简便方法。让我们从基本信息开始。工作区包含各种相关项目。一个项目可以有各种目标-这些目标确定要组装的产品和组装方法。此外,项目可能具有各种配置。Xcode中的模式定义了程序集的目标集合,程序集期间使用的配置以及要执行的测试的集合。

紫色显示一种可能的模式。

12-测试


如果您花时间测试您的应用程序,那么您就走对了。当然,这不是万能药,您无法修复每个错误,也不能保证您的应用程序不会出现任何问题。但是我认为利弊大于利弊。

让我们从单元测试缺点开始

  • 增加开发时间;
  • 增加代码量。

优点

  • 需要创建模块化代码(以简化测试);
  • 显然在发布之前检测到大多数错误;
  • 简化支持。

Tools实用程序结合使用,您将拥有使该应用程序灵活且正常运行且没有错误和崩溃的一切。

您可以使用许多工具来测试应用程序。根据要跟踪的内容,可以选择一个或多个。也许最常用的工具是LeaksTime ProfilerAllocations

13-地理位置


在许多应用程序中,某些功能需要定位用户。因此,对位置如何适用于iOS有了一个大概的想法将是很好的。

有一个名为“核心位置”的框架,该框架使您可以访问所需的所有内容:

核心位置框架允许您确定设备的当前位置或移动方向。该框架使用可用的硬件来确定用户的位置和方向。您可以使用此框架的类和协议来配置和安排与位置和方向有关的事件。您还可以使用“核心位置”来跟踪跨地理区域的移动。在iOS中,您还可以确定到蓝牙信标*的距离。

*据我了解,这与iBeacon技术有关

不错,不是吗?查看Apple文档和那里的示例,以更好地了解框架的功能。

14- 可本地化的字符串


在任何应用程序中应实现什么。这使您可以根据设备所在的区域来更改语言。即使您的应用程序仅使用一种语言,将来也可能需要添加新的语言。如果使用可本地化的字符串输入所有文本,那么您要做的就是为新语言添加Localizable.strings文件的翻译版本。

可以通过文件检查器将资源添加到语言。要使用NSLocalizedString获取字符串,您需要编写以下内容:

NSLocalizedString(key:, comment:)

不幸的是,要将新行添加到可本地化文件中,必须手动完成。这是一个示例结构:

{
"APP_NAME" = "MyApp"
"LOGIN_LBL" = "Login"
...
}

现在是另一种语言(葡萄牙语),本地化文件:

{
"APP_NAME" = "MinhaApp"
"LOGIN_LBL" = "Entrar"
...
}

甚至还有实现复数的方法。

始终分享您所学。

-尤达大师

希望本文对您有所帮助!

All Articles