38- LLVM和Clang有什么区别? Clang是LLVM工具链的前端(“ clang”是LLVM的C语言家族前端)。 每个编译器都有三个部分。 1.前端(词法分析,解析) 2.优化器(优化抽象语法树) 3.后端(机器代码生成) 前端(Clang)获取源代码并生成抽象语法树(LLVM IR)。 39-什么是阶级? 类旨在定义一个对象及其工作方式。 这样, 类就像对象的蓝图。 40-什么是物体? 对象是类的实例。 41-什么是界面? Objective-C中的@interface与Java接口无关。 它只是声明一个类的公共接口,即其公共API。 42-我们何时以及为什么使用对象而不是结构? 结构是值类型。 类(对象)是引用类型。 43-什么是UIStackView? UIStackView提供了一种水平或垂直布置一系列视图的方法。 我们可以定义所包含的视图如何将自身调整为可用空间。 不要错过这篇文章。 44- iOS应用程序的状态是什么? 非运行中 -应用程序未运行。 无效 -应用程序在前台运行,但未收到事件。 例如,当收到呼叫或SMS消息时,可以将iOS应用置于非活动状态。 活动 -应用程序在前台运行,并接收事件。 后台 -该应用程序在后台运行,并正在执行代码。 已暂停 -应用程序在后台,但是没有代码在执行。 45-开发人员应该处理的最重要的应用程序委托方法是什么? 操作系统在应用程序委托中调用特定方法,以促进与各种状态之间的转换。 开发人员应处理的七个最重要的应用程序委托方法是: 应用程序:willFinishLaunchingWithOptions 启动启动过程时调用的方法。 这是在应用程序内执行任何代码的第一个机会。 应用程序:didFinishLaunchingWithOptions 启动过程快要完成时调用的方法。 由于此方法是在显示任何应用程序窗口之前调用的,因此这是准备界面和进行任何最终调整的最后机会。 applicationDidBecomeActive 一旦应用程序变为活动状态,应用程序委托将通过applicationDidBecomeActive方法接收回调通知消息。 每当应用程序从上一次切换到活动状态(由此产生的电话或SMS变为非活动状态)时,都会调用此方法。 applicationWillResignActive 有几种情况将产生applicationWillResignActive方法。 每次发生临时事件(例如电话)时,都会调用此方法。 还需要注意的是,“退出” […]
Apple已正式验证我们的Kommander库,并将其添加到Swift Source Compatibility中 。 灵感来自我们Android架构师Wokdsem的Java库Kommander。 Intelygenz iOS团队已经合作从头开始编写该库,并对其进行了优化以在iOS,tvOS,watchOS或macOS上有效地工作。 El Pais或Los 40等应用程序可将其用于所有网络,数据库和核心请求,并且它是新的Intelygenz iOS体系结构的一部分 。 但是它是什么,它有什么作用? 意图 将同步执行封装为对象。 控制执行线程/队列。 支持执行取消。 将调用操作的对象与知道如何执行操作的对象分离。 能够同时或顺序执行多个操作。 独立于任何上下文封装执行所需的所有内容。 始终知道执行状态。 问题 OperationQueue和DispatchQueue的功能不足以自己完成此操作。 解 通过遵循命令设计模式来实现我们自己的并发库。 科曼德 Kommander是一个Swift库,用于管理不同线程中的任务执行。 通过定义,一个简单但功能强大的概念Kommand。 特征 制作一个或多个命令 执行命令或多个命令 取消一个或多个命令 设置命令成功阻止 设置命令错误块 主线程分配器 当前线程分派器 自定义OperationQueue调度程序 自定义DispatchQueue调度程序 执行一次或多次操作 执行顺序或并发块 执行DispatchWorkItem 科曼德州 与watchOS兼容 与tvOS兼容 Swift 2版本 Objective-C版本 安装 Kommander可通过CocoaPods获得。 要安装它,只需将以下行添加到您的Podfile中: pod ‘Kommander’ 或者,您可以使用迦太基安装它: github “intelygenz/Kommander-iOS” […]
最近,我观看了一段有关iOS架构的视频,讲师在演讲中提到了一种名为ReSwift的架构。 几天后,这个名字再次出现在SwiftCoder播客的一集中。 因此,我决定进行一些研究并尝试找出答案。 介绍 ReSwift的GitHub页面引用了以下内容。 ReSwift是Swift中单向数据流架构的类似Redux的实现。 ReSwift可帮助您将应用程序组件的三个重要方面分开: 状态:在ReSwift应用中,整个应用状态都明确存储在数据结构中。 视图:在ReSwift应用程序中,当状态更改时,视图也会更新。 您的视图成为当前应用程序状态的简单可视化。 状态更改:在ReSwift应用中,您只能通过操作执行状态更改。 动作是描述状态变化的小数据。 ReSwift还依赖于一些原则: 商店以单个数据结构的形式存储整个应用程序状态。 只能通过将操作调度到商店来修改此状态。 每当商店中的状态发生变化时,商店都会通知所有观察者。 动作是描述状态变化的一种声明方式。 动作不包含任何代码,它们由商店使用并转发给减速器。 减速器将通过为每个动作实施不同的状态更改来处理这些动作。 Reducer提供了纯函数,这些函数基于当前操作和当前应用程序状态创建新的应用程序状态。 示范 我将演示如何在一个简单的项目中采用ReSwift。 该项目使用SWAPI来获取《星球大战》的电影,并在表格视图中显示它们。 以下是我的视图控制器的直观展示。 让我们开始定义我的State 。 因为我的项目非常简单,所以我只用一个enum来描述FilmsState 。 struct AppState: StateType { let filmsState: FilmsState } enum FilmsState { case loading case finished([Film]) } 其次,我创建三个不同的Action ,包括LoadingFilmsAction , SetFilmsAction和fetchFilms 。 由于影片的数据是从SWAPI获取的,并且此操作是异步的,因此fetchFilms实际上是ActionCreator而不是Action类型。 提取影片的数据完成后,我使用Store来调度SetFilmsAction以便更新表格视图。 此外,我编写了一个WebService类来处理网络操作,您可以在本文中找到更多详细信息。 struct LoadingFilmsAction: Action […]
了解如何在模型,父母,孩子和兄弟姐妹之间建立关系。 我们将创建一个小型Web应用程序,了解如何实现Model作为Parent , Children和Siblings之间的关系 。 本文假定您已经对 Vapor 有所了解, 并希望 使用 Fluent 在您的模型之间 建立一些 关系 。 否则,您可以参考 Vapor的Documentation 来设置您的第一个项目 。 列出主人约翰的所有宠物 在第一个教程中,我们将构建一个简单的Web API,以在线添加宠物及其主人信息。 让我们将数据保存到数据库中 ,该数据库可通过路线访问。 我们将通过JSON将数据提供给客户端。 建立关系 关系允许数据库实体之间基于外键的连接。 我们要做的是创建Pet并将其设置为“ Children”作为所有者 。 这样,我们将能够从一个所有者那里获取所有Pet 。 外键 为使魔术发生,我们需要在Pet上添加一个外键 ,该键将是一个Node类型,该类型将存储Parent的ID,即Node。 var owner_id: Node? 并在数据库中建立关系,请将以下行添加到prepare方法中: pets.parent(Owner.self, optional: false) 如果您想迁移数据库,请单击“如何使用Vapor的Fluent迁移数据库”的链接。 最后,您的Pet.swift文件应如下所示: 此外,要建立关系,您需要将所有者的ID设置为宠物的owner_id 。 注意:请记住,实体 所有者 将获得一个 id 在 save() 。 我们知道我们其中一位主人的id为1 ,我们可以设置一条路线来放置Pet […]
位置管理器是一种包装器,可以以更简单的方式使用CLLocationManager(iOS框架使用GPS)并摆脱所有这些委托和错误处理。 位置管理器同时提供了一次性定位和实时跟踪的功能。 特征: 易于使用。 提供事先的错误处理。 根据设备电池百分比调整位置精度。 如何使用: 不要忘记添加“ NSLocationWhenInUseUsageDescription”键和“ NSLocationAlwaysAndWhenInUseUsageDescription”键到您的Info.plist文件中。 (Xcode在Info.plist编辑器中将这些键显示为“隐私-使用时位置用法说明”和“隐私-始终和使用时位置用法说明”。) 1.一次获取位置信息: let locationManager = LocationManager(withAccuracy: LMLocationAccuracy.bestForNavigation) locationManager.getCurrentLocation { (response) in switch response { case .failure(let locationError): switch locationError { case .authorizationFailed(let description): print(description) case .locationUpdationFailed(let description): print(description) } case .success(let location): print(“location is :”, location) self.lbllat.text = “\(location.coordinate.latitude)” self.lblLong.text = “\(location.coordinate.longitude)” } } 2.对于实时跟踪: […]
最近,我构建并发布了Canopy,该服务可通过Mac和iOS应用程序为您的GitHub存储库上的活动提供即时推送通知。 我多年没有在服务器端工作过,设置服务器和编写服务器端代码真的很有趣。 中断与事件驱动的类似应用程序的编程并做一些不同的事情是令人耳目一新的,但是我仍然必须用自己喜欢的语言编写它:JavaScript……只是在开玩笑,Swift。 客户端和服务器端都是Swift。 关于服务器端Swift的信息量很低,这不足为奇,但是我在这里告诉您,如果您已经了解Swift并且也了解macOS命令行的话,这并不是一件容易的事。 斯威夫特很棒 Swift并不是所有语言中最好的语言,但它是最佳的折衷方案,这使它成为目前所有事物(它支持)的最佳语言。 自宣布以来,Swift-Core清晰而谨慎的设计决定给我留下了深刻的印象,可以全心投入。 我已经用许多种语言进行编程,并且经常发现该语言及其标准库的质量不一致,Team-Swift对他们的语言及其标准库一无所知。 本周,我将重点介绍Swift为什么适用于服务器的一些细节。 显然,协议驱动的开发,功能编程,可选的选项,错误处理模型等使Swift总体上很棒,但是我不会特别指出。 当然,这些事情使写Canopy成为一种快乐。 没有JSON 应用程序和服务器使用JSON进行通信,但是我不知道或不在乎,因为它的两端都是Codable 。 创建我的结构,传输,接收我的类型安全的结构。 感觉很棒。 我几乎不需要做任何工作就可以进行固有的类型安全跨进程,这使我和服务器之间的1,000英里看上去与在视图控制器之间传递数据没有什么不同。 但是,缺乏动态性意味着即使向这些结构添加单个参数也意味着对端点进行版本控制或将新参数设置为Optional 。 并非全是玫瑰花,但坦率地说,版本管理工作得很好,这意味着我解释输入数据的代码不是if语句的逻辑炸弹,它是经过仔细地,单独封装和测试的,类型安全的端点。 正常运行时间 由于使用太多文件描述符,服务器代码在生产中一次“崩溃”,因为我不得不使用(C库)libcurl编写我的APNs(Apple Push Notification service)代码(我编写了Swift,而不是C,这是另一个很棒的功能Swift能够轻松地与C库接口),但我做错了,因为UnmanagedPointer很难。 因此内核终止了它。 一次崩溃:Swift很棒。 您必须积极地致力于编写不稳定的Swift代码。 当然,Swift可为您提供健壮的代码和高性能。 很棒的开发者经验 Xcode非常棒(它很烂,但是考虑到同等的开发人员工具时,这是相当令人惊讶的),Swift软件包管理器意味着跨平台开发所需的工具随Swift发行版一起提供,没有成千上万个组件的史诗级工具链出问题并要安装,这是Mac上来自App Store的一个二进制文件,服务器上是swift.org的一个二进制文件。 您可以在Mac上开发和测试服务器代码,同时运行客户端应用程序并使它们一起通信(仅使用Xcode)。 目前,这样做比我们想要的要笨拙,您必须让SwiftPM从描述服务器端应用程序的Package.swift中生成一个Xcodeproj( swift package generate-xcodeproj ),然后将其嵌入到.xcodeproj (拖放)到您的客户端应用程序。 Xcode知道此后该怎么办。 这样做还可以更轻松地在各种服务器和客户端应用程序之间共享代码。 由于SwiftPM并不真正支持iOS,但您仍然需要Carthage作为iOS应用程序的依赖项,但是,如果您制作的是macOS应用程序,则可以使用SwiftPM获取的依赖项(如果您正在使用类似的依赖项)。 当然,这是不理想的,但是到2020年会变得更好(所以我们被告知-更好的Xcode集成即将到来)。 您必须在此时使用Xcode(我想您可能可以使用AppCode),因为愉快地使用Swift 绝对需要自动完成。 苹果公司承认这是阻碍其广泛采用的障碍,并且最近已承诺提供语言服务器协议服务,以便其他编辑者和其他平台可以为其开发人员提供一流的Swift体验。 在服务器端运行代码就像rsync和swift run foo一样简单。 显然,您应该有一个比这更好的部署过程,但是我试图证明它是多么简单。 守则第一次生效 我喜欢Swift的许多原因之一是在编写它之后感觉到,如果对其进行编译,它将可以正常工作。 显然,情况并非总是如此,但大多数情况是这样,对于Canopy,大多数情况下都是如此。 语言是严格的,可以使您严格地编写它,但是以某种方式仍然绝对是编写代码的乐趣。 […]
在构建应用程序时,必须考虑将内容显示给用户的方式。 将功能和逻辑分离到不同的视图控制器中,可以使用户和您的代码库保持整洁。 尽管Apple提供了使用UINavigationController或UITabBarController导航到这些视图控制器的方法,但有时它们不太适合您的应用程序需求。 在本文中,我将构建一个简单的应用程序,演示如何创建导航界面。 它将涉及创建一个主视图控制器,该主视图控制器将负责根据用户操作来呈现和关闭其他视图控制器视图。 设置项目 让我们从创建一个单一视图应用程序开始。 创建项目后,我将删除main.storyboard文件,并从部署信息下的项目主界面中删除main。 接下来,将默认的ViewController重命名为MasterViewController。 最后,在AppDelegate中并设置我们的窗口以使用MasterViewConroller作为根视图控制器。 我将masterVC背景色设置为红色,以便我们知道一切正常。 此时运行该应用程序将使您出现一个红色屏幕。 设置MasterViewController 这里的概念是让MasterViewController显示其他视图控制器的视图。 为了做到这一点, MasterViewController需要做两件事-一种过渡到要显示的视图控制器的方法,以及一个指定为包含该视图控制器主视图的视图。 对于我们的示例,我们将UISegmentedControl放置在页面顶部,并在MasterViewController的视图中添加一个容器视图以显示其他视图控制器视图。 这是用于设置navSegmentedControl和contentView的代码。 接下来,我们可以为要显示的视图控制器创建一些新的swift文件。 这些将是MasterViewController的子视图控制器,我们将在viewDidLoad中更改其颜色,以便我们知道何时切换到它们。 现在,我们有了主视图控制器和要显示的视图控制器。 接下来,我们将向MasterViewController添加逻辑,这将使我们能够根据我们选择的段过渡到子视图控制器。 添加子视图控制器 我们需要做的第一件事是告诉我们的MasterViewController哪个视图控制器将是它的子级。 您决定如何存储子视图控制器取决于您-在本示例中,我将创建两个惰性变量,如果将它们导航到,它们会将自身添加为子变量。 首先让我们创建一个将子视图控制器添加到MasterViewController的函数。 在此函数中,我们使用apples API将视图控制器作为子级添加到自身( MasterViewController )中,并使用containerView显示视图控制器视图。 使用addChildToViewController和didMoveToParentViewController很重要,因为它可以正确地在要添加的子视图控制器的生命周期中移动。 如果我们只是简单地将childVC.view作为子视图添加到与UIViewController生命周期相关的self.view函数,则将不会调用该函数(例如viewDidAppear )。 现在,我们可以使用在惰性变量中创建的此函数。 通过使这些变量变得惰性,可以避免在用户不过渡到子视图控制器时创建子视图控制器的情况。 向分段控件添加功能 现在,我们可以将一个目标添加到navSegmentControl ,该目标告诉我们选择是否更改-如果更改,则在containerView中显示正确的视图控制器。 让我们先创建一个函数,该函数包含在分段控制器的选择更改时发生的逻辑。 一旦选择了要移动到的视图控制器,就会在此处进行转换。 在此示例中,我只是基于所选索引隐藏或显示视图控制器。 如果要创建自定义动画来呈现视图,则应在此处调用它。 记住,我们不需要在这里调用addAsChildVC函数,因为在创建惰性变量时会调用该函数。 现在,我们可以将此功能添加为setupViews函数中的目标。 最后,我们可以取消隐藏确实加载了视图的blueVC,以便当appRun运行时,我们看到的是蓝色选择,而不是白色的屏幕。 差不多了! 现在,当我们运行该应用程序时,我们可以通过在分段控件中进行选择来在视图控制器之间进行转换。 如果要从MasterViewController中删除一个视图控制器作为子视图控制器,则可以实现以下功能。 您可以在此处查看完整的项目。 希望你喜欢这个帖子!
正如之前在这里宣布的那样,Vapor框架刚刚推出了其2.0版本。 在Monk Software,我们一直在寻找新技术,我们为Vapor提供了机会! 什么是蒸气? Vapor是服务器端Swift Web框架。 无论您需要什么,Restful API Server,显示html页面,发送电子邮件或推送通知,Vapor几乎可以满足所有需求。 我们将在这篇博客文章中介绍什么? 今天,我想向您展示从Vapor API模板开始,添加一些端点然后将服务器部署到Heroku多么容易。 让我们开始吧 我假设您使用的是装有Swift和Xcode的Mac,如果没有,请安装Xcode(Swift捆绑在其中),如果您使用的是Ubuntu,请按照此指南进行操作。 1)安装蒸气工具箱 要充分利用Vapor,我们还需要它的工具箱,您可以通过在终端中输入以下内容进行安装: 冲泡安装蒸气 或者,如果您在Ubuntu上,请执行以下操作: sudo apt-get更新 sudo apt-get安装蒸气 2)创建一个新的应用程序 创建一个超级简单的应用程序,只需在终端中输入: 蒸气新的IncredibleVaporApp –template = api(或您想要的任何名称) 在少数情况下,Vapor应该下载所有依赖项,并使用给定的应用程序名称创建一个文件夹。 3)可选:生成Xcode项目文件 如果您想利用Xcode自动补全功能,可以在vapor app文件夹内的终端中键入以下内容: 蒸气Xcode 这将生成.xcodeproj,键入“ y”以在Xcode中打开。 4)运行服务器 好的,我们已经准备好运行我们的服务器,如果您使用Xcode,请选择方案App并按play,如果您在Ubuntu中,请输入终端: 蒸气生成和&蒸气运行 build将提取要部署的构建,然后运行将启动服务器。 默认情况下,Vapor将在以下地址启动服务器: 0.0.0.0:8080进行测试,请访问http://0.0.0.0:8080/hello, 您将看到此类型的json: {“你好,世界”} 一切都按预期进行! 5)添加自定义端点 现在是时候添加我们的自定义终结点了,假设我们要通过传入一个人的名字来问候他。 首先,在我们的项目中打开Routes.swift文件,然后在方法中 func build(_ builder:RouteBuilder)抛出 我们可以添加新的API: builder.get(“ greet”){要求 let name […]
现实世界中的代表团 一个很好的起点是通过解释现实世界中的授权。 在现实世界中,委托封装了某人(委托人)将任务(委托人)交给其他人(委托人)。 有两个名词和一个动词组成委派: 委托(动词):“将任务或责任委托给另一个人”。 委托人(名词):“委托他人的人”。 代表(名词):“被选择或当选代表他人的人”。 为了澄清-委托人(名词)会将责任(动词)委托给委托人(名词)。 现在我们有了组成委派的组件的字典定义,接下来让我们实际展示一个真实的委派示例: 在仓库中,将有一名物流经理( 代理人 ),他们将知道卡车何时到达以及何时到达。 物流经理很忙,虽然他们很擅长管理物流,但在装卸和搬运箱子时却不那么擅长。 因此,他们将这项工作( 代表–动词 )交给仓库操作员( 代表–名词 )。 后勤经理告诉仓库操作员,一辆卡车将在09.00到达,当到达09.00时,他们告诉仓库操作员该卡车已经到达。 然后,仓库操作员卸下货车并将箱子运到需要的地方。 iOS世界中的代表团 数字世界中的委派与现实世界中的委派非常相似,不同之处在于,我们拥有的不是对象而不是人,而对象在Swift中将是类,结构或枚举的实例。 让我们以对现实世界相同的方式来分解软件开发中的委托: 委托(动词):将任务或责任委托给另一个对象。 委托人(名词):将职责“移交给”另一种类型的实例(对象)的类或结构实例(对象)。 委托(名词):保证处理已委派职责的对象,即提供委派的功能。 需要澄清的是,委托是指一个对象(代理)代表另一个对象(代理)提供功能时的行为。 现在,让我们通过从参与对象的角度来考虑委派来进一步深入研究: 您创建一个待办事项列表应用程序。 您可以将UIViewController子类化,以创建名为“ ToDoListViewController ”( 委托–名词 )的视图控制器对象。 您将一个UITableView实例( 委托人 )放在ToDoListViewController 。 UITableView会显示要执行的项目并检测与之交互的时间,但会将处理这些交互( 委托–动词 )的责任移交给另一个对象。 UITableView实例( delegator )将向事件的委托对象通知其将要处理或刚刚处理的事件。 ToDoListViewController ( 委托人–名词 )声明它将提供响应UITableView处理的事件而发生的功能。 假设UITableView实例( delegator )可以讲话,该对象可能会说:“ 我是一个表视图对象,并且选择了第3行 ”。 “ ToDoListViewController […]
每个iOS开发人员都会创建UITableViewCells,但让我们做得更好。 根据我的实践,这里有五个原则。 TL; DR 在自己的小腿上做; 将用户界面设为私有; 不要配置模型; 让他们暗恋; 重用之前重设。 完整示例应用程序的源代码: https : //github.com/alekseishirokov/medium-01-better-uitableviewcell 每次在情节提要中创建新的UITableViewController时,XCode都会创建一个空单元格原型。 这导致开发人员使用此模板将UI元素直接放置到此单元格视图中。 但这是一个坏习惯。 迟早,您的项目经理会要求您使用完全相同的单元格设计,但要使用另一个表。 当他们告诉我不仅要在人员的详细信息视图中还必须在部门的详细信息视图中显示文档列表时,我已经摆脱了这种行为。 我文档的单元格原型包含10个UILabel,2个UIImageViews和一堆棘手的约束。 尽管XCode具有复制粘贴命令,但这并不容易。 让我们做得更好:在自己的xib文件中创建UITableViewCell并在所需的任何表中重复使用。 这很容易做到。 按Cmd + N创建一个新文件。 然后选择iOS → Cocoa Touch Class 。 然后在下拉菜单的子类中选择UITableViewCell ,输入类名,并选中“ 同时创建XIB文件”复选框。 XCode创建两个文件: DocumentTableViewCell.swift和DocumentTableViewCell.xib 。 使用xib文件将UI元素放入单元格视图中。 使用swift文件将IBOutlet与这些UI元素绑定。 然后,您可以在表视图控制器中使用此DocumentTableViewCell ,如下所示: 这意味着我需要重构每个使用我的DocumentTableViewCell的表视图控制器,如下所示: 如今,我做得更好。 我将UI出口声明为单元格视图专用。 我仅使用configure方法将数据传递给UI元素: 在表视图控制器中,您只需将文档的优先级作为参数传递给configure方法。 直觉是, 优先级是数据,取决于单元格视图如何显示数据。 同样,在单元设计发生更改的情况下,也无需重构表视图控制器。 即使在教程中,也通常通过将模型对象传递给configure方法来用数据填充单元格: 这似乎是一个优雅的解决方案,但事实并非如此。 这会将单元格的视图与模型对象耦合在一起。 单元格视图取决于模型对象的结构。 但是,我们坚持的MVC模式就是将视图和模型分离。 我倾向于将数据作为单独的参数传递给configure方法: […]