Tag: iOS应用开发

iOS中的网络调试-netfox

如今,许多应用程序都使用某种HTTPS API,其中有大量的库(Alamofire,Moya,AFNetworking等),并且我在Medium上看到了许多有关网络体系结构的文章。 但是有一件事,几乎没人谈论—网络调试。 错误是软件开发的正常部分,可以在它的每个部分(包括网络)中找到。 什么是netfox? 对于任何需要在其应用程序中调试网络的iOS或macOS开发人员而言,Netfox都是一个很棒的库。 您可以在netfox GitHub README中阅读有关它的更多信息。 Netfox入门 使用netfox入门非常简单。 它支持两个主要的依赖管理器-CocoaPods和Carthage。 // CocoaPods pod’netfox’ //迦太基 github“ kasketis / netfox” 如果您希望手动将库添加到项目中,请 参阅netfox GitHub README中的说明 。 添加库后便是最好的部分-要启用netfox日志记录,您只需向AppDelegate添加一行代码即可。 就这样,您不需要任何其他东西,也不管您如何处理网络请求(Alamofire,AFNetworking等)。 NFX.sharedInstance()。start() 将此行添加到AppDelegate,didFinishLaunchingWithOptions中。 不要忘记导入netfox。 查看您的日志 Netfox将在后台记录您的所有网络请求。 有两种方法可以打开netfox日志屏幕(图2): 1)手势 NFX.sharedInstance()。setGesture(.shake) 在您的AppDelegate中的“ NFX.sharedInstance()。start() ”下添加以下代码行。 要打开网络日志屏幕,只需摇动您的iPhone,它将自动打开。 2)代码: NFX.sharedInstance()。show() 这行代码也将打开网络日志。 例如,您可以在按钮的@IBAction中调用它。

使用diff框架更新Swift中UICollectionView数据的更好方法

熟悉的朋友 通过iOS中的UITableView , NSCollectionView ,macOS中的tvOS或NSTableView , NSCollectionView NSTableView ,很难想象没有使用表视图或集合视图的应用程序。 大多数时候,我们从后端,缓存和过滤器中获取数据,以列表或网格形式显示该数据。 之后,当数据更改时,我们将更新您的界面以反映某些项目已被插入或删除。 那就是您最喜欢的函数出现的地方reloadData 。 这样,整个列表将以全新的内容刷新。 当您需要快速刷新内容的方案时,这是很好的选择。 但这会使UITableView再次使单元格大小无效,这会降低性能。 此外,如果这些更改应引起注意,并且您想让用户更好地了解发生了什么,那么最好手动插入和删除行。 如果您使用的是Android,则可能知道不用调用notifyDataSetChanged ,而可以使用提供的DiffUtil为我们计算更改,从而使RecyclerView更新变得容易。 不幸的是,您在iOS中没有那么奢侈,但是我们可以学习如何做到这一点。 本指南以UICollectionView为例,但UITableView行为相同。 对于在Google上搜索NSCollectionView任何人来说,这都有点困难: 拖放 让我们看UICollectionView情况。 想象一下一个应用程序,在该应用程序中,用户可以通过将项目从一个集合移到另一个集合来自定义其体验。 您可以看一下示例DragAndDrop,它在iOS 11中使用了新的拖放API。 在UICollectionView上调用更新方法之前,必须确保数据已更改。 然后我们调用deleteItems和insertItems以反映数据更改。 UICollectionView为您执行漂亮的动画 索引与偏移 在我们进行进一步讨论之前,我只想提及一下,实际上是指从一开始的offset 。 如果您看一下枚举函数,它建议使用名称作为偏移量而不是索引 编辑距离 手工进行这些计算非常繁琐且容易出错。 我们可以使用一些算法来构建自己的抽象。 天真的是Wagner-Fischer算法,该算法使用动态编程来告诉两个字符串之间的编辑距离。 编辑距离是指从一个字符串更改为另一个字符串所需的步数。 字符串只是字符的集合,因此我们可以推广这个概念以使其适用于任何项目集合。 而不是比较字符,我们要求项目符合Hashable 。 从“套件”到“ kat” 我们如何将“套件”一词的形式转换为“ kat”? 我们需要执行哪种操作? 您可能会说“只是将字母i更改为a”,但是这个简单的示例可以帮助您理解算法。 让我们开始吧。 删除项 如果从“ kit”转到空字符串“”,则需要删除3次 “套件”->“”” 3个删除项 “ […]

Swift 3:使用单行输入的自定义UITextField

嗨,大家好! 这将是一篇简短的提示与技巧样式文章。 今天,我正在尝试(幸运地成功)构建了一个包含一个底线的自定义UITextField。 我敢肯定您之前看过,或者至少看过类似*的东西。 它并不复杂,但是使用自动布局时会变得棘手。 让我们看看如何首先制作这样的UITextField,您要做的就是创建扩展 扩展UITextField { func setBottomLine(borderColor:UIColor){ self.borderStyle = UITextBorderStyle.none self.backgroundColor = UIColor.clear 让borderLine = UIView() borderLine.frame = CGRect(x:0,y:Double(self.frame.height)—高度,宽度:Double(self.frame.width),height:height) borderLine.backgroundColor = borderColor self.addSubview(borderLine) } } 您可能想知道那里到底发生了什么,我将立即解释! 在我们设置透明背景并为文本字段禁用边框后,将创建UIView。 然后,将其框架设置为高度等于1.0的线,并通过以下y点计算将其放置在文本字段的底部 Double(self.frame.height)—高度 接下来是设置背景颜色,并准备添加子视图。 很简约! 现在,对于那些想要使用自动布局的人来说,棘手的部分是: 你不敢打电话 setBottomLine(borderColor:UIColor) 在ViewDidLoad()中,由于当时尚未应用所有自动布局规则,因此导致行为不确定。 要使其正确,只需调用viewDidLayoutSubviews()函数中的方法 覆盖func viewDidLayoutSubviews(){ 让lineColor = UIColor(红色:0.12,绿色:0.23,蓝色:0.35,阿尔法:1.0) self.myTextField.setBottomBorder(borderColor:lineColor) } 而已! 请让我知道这对你有没有用!

在深度第2部分中反应本地身份验证-真实世界的身份验证流程

这篇文章将涵盖: 经生产测试的认证流程概述。 使用第1部分中的现有应用程序实现Auth流。 连接Redux以处理应用程序UI和某些身份验证状态。 使用AWS Amplify处理Cognito用户会话。 我们将使用的导航库是React Navigation,但是这些模式基本上可以转换为任何导航库。 验证流程 如果正确实施身份验证流程,那么在您的应用程序开发之初就获得正确的身份验证流程可以节省大量时间。 这篇文章的目的是向您展示如何建立端到端的一些基本而又真实的身份验证,以及如何以一种在现实世界中有意义的方式将其连接到应用程序的UI中。 让我们快速浏览一个非常常见且有用的导航/身份验证流程。 在示例1中,LoggedInNavContainer和LoggedOutNavContainer包装在单个条目组件中。 这两个组件可以是任何类型的导航(抽屉,堆栈,标签),但是在我们的示例中,我们将要构建, LoggedInNavContainer将是Stack,而LoggedOutNavContainer将是标签。 在示例1中,我们基本上是检查一个loggedIn布尔值(来自您选择的状态管理),并根据其登录状态呈现一个完全不同的组件。 这两个主要组件通常本身就是导航组件。 当然,还有其他一些情况需要考虑,例如“帐户锁定” , “重置密码”或“忘记密码” ,尽管我们可以在带有组件/ UI的if语句中添加更多逻辑来处理此问题,或者处理这些来自LoggedOutNavContainer导航器中。 另一个选择是使Main条目本身成为一个Navigator,以处理整个auth状态并进行相应的导航。 让我们更详细地看一下另一种方法: 在此示例中,有一个主要的导航组件(React Navigation的Think Stack Navigator),具有一个Login / Auth堆栈(或同一堆栈中的Login / Auth路由),以及一个“ Application”堆栈,该堆栈仅可访问/推送到如果用户已登录。 我们将重点关注第一个示例,因为它实现了选项卡,并且在实践中不像仅使用StackNavigators的第二组路由那样容易推论。 入门 首先,您应该跟着第一部分进行准备,或者准备好该项目,或者克隆该项目并配置src/aws-exports.js所有字段,以匹配来自AWS控制台的信息。 您还可以通过以下屏幕录像来创建第1部分: 在此文件中,我们有一个基本的登录表单,带有一个按钮,该按钮将向redux分配一个身份验证操作,然后该按钮将调用Auth.signIn ,并将用户名和密码输入到表单中。 我们还有一个模式,仅当用户成功使用用户名和密码登录但尚未通过两因素身份验证进行身份验证时,才会显示该模式。 用户成功登录后,我们将显示模式并允许用户输入其验证码。 auth / SignUp.js 此组件与“登录”组件相似,只是我们还有几个额外的字段可用于捕获用户的电话号码和电子邮件地址。 我们还具有模式功能,因此,当用户创建帐户时,我们通过两步验证进行验证,向用户发送短信并确认其短信,并在确认用户注册后隐藏模式。 auth / Tabs.js 在这里,我们进入SignIn和SignUp屏幕,并将其实现到TabNavigator中。 登录状态 用户登录后, Nav组件将呈现在我们的App.js文件中。 Nav是一个StackNavigator,目前只有一个Home路由。 本地路线将具有一个注销按钮,以演示注销功能。 […]

在Swift中对MVVM架构进行单元测试

为确保新代码不会破坏已经实施的旧代码,最佳实践是编写单元测试。 对于应用程序体系结构,编写这些测试可能是一个挑战。 遵循MVVM模式, 如何对视图及其viewModel进行单元测试? 这就是我想在这里使用依赖注入的内容。 MVVM体系结构的主要优点是将逻辑解耦并保持关注点分离。 每个类和文件都有特定的目标。 该代码保持模块化,可重用且易于测试。 测试用例应采用相同的逻辑:编写的每个测试仅覆盖一个用例,而仅覆盖一个用例,请隔离逻辑并确保其正常工作。 在此示例中,我还将保持关注点分离,一次测试一个元素。 我的意思是,对于MVVM模式,我至少要有3个测试文件:一个用于我的模型,一个用于我的视图,一个用于我的viewModel。 但是在深入研究代码之前,如果您不熟悉MVVM,我建议您先看一下我最近编写的实现MVVM模式的介绍。 准备您的viewModel 为了能够针对我的viewModel运行测试,我需要能够使用其他服务,并能够通过依赖注入来模拟我的服务。 第一步是为服务创建一个协议,然后将其实现到当前服务,最后更新视图模型。 我这就是我的协议和服务的样子 protocol CurrencyServiceProtocol : class { func fetchConverter(_ completion: @escaping ((Result) -> Void)) } final class CurrencyService : RequestHandler, CurrencyServiceProtocol { … } 然后我可以在viewModel中使用依赖项注入和默认参数 weak var service: CurrencyServiceProtocol? init(service: CurrencyServiceProtocol = CurrencyService.shared, dataSource : GenericDataSource?) { self.dataSource = dataSource self.service […]

与React Native中的Debug和Release不同的iOS构建配置

默认的iOS构建配置Debug和Release可能一开始就足够了,但是迟早您可能需要扩展应用程序中的构建配置数量。 尽管这在本机开发中非常简单,但是不幸的是,在React Native中却并非如此。 构建配置 要管理构建配置,请转至Xcode项目设置([PROJECT]→Info): 您可以通过复制现有构建配置轻松地添加新的构建配置。 用于开发的重复调试配置以及用于测试飞行和App Store构建的发布配置。 您也可以通过快速双击任何配置来重命名。 调试与发布 调试配置无需任何代码优化即可构建完整的符号调试信息,以方便调试应用程序。 在发行版配置中,代码执行得到优化,并且构建中不包含符号信息,这导致最终可执行文件的尺寸较小。 尽管由于编译器的优化,您可能会期望内存布局或初始化方面的差异,这可能会导致所谓的“仅发行”错误,但发行版本的执行速度会更快。 运行构建配置 上面介绍的步骤足以在本机开发中设置新的构建配置。 要在构建配置打开方案中运行该应用并更改运行构建配置: React Native中的问题 请记住要检查您的TypeScript代码是否已编译(如果有)以及打包程序是否正在运行。 要使用指定的构建配置在React Native中启动iOS应用,您只需运行: react-native run-ios –configuration Stage 不幸的是,这对于任何基于发行版的配置都将失败,并显示一条错误消息,指出无法在AppDelegate中找到RCTBundleURLProvider : AppDelegate.m:2:9:找不到“ React / RCTBundleURLProvider.h”文件 我们需要在目标构建设置([TARGET]→构建设置)中为新的Release构建配置添加缺少的标题搜索路径和库搜索路径 。 为每个新的“发布”构建配置在“ 标题搜索路径”中添加一个条目: $(BUILD_DIR)/Release-$(PLATFORM_NAME)/include 为每个新的发布版本配置向库搜索路径添加一个条目: $(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME) 现在,您可以在指定的构建配置中启动该应用程序: react-native run-ios –configuration Stage 请记住对“测试目标”执行相同的操作,否则此命令将失败。 黑暗中总有一线光明 没有任何以前的经验,在React Native中定义不同于Debug和Release的iOS构建配置可能会令人沮丧。 但是,在一点指导下,这可能是一个快速而轻松的过程。 如果您对如何为每个构建配置设置不同的Google配置感兴趣,建议您阅读本教程。 尽管它是为本机开发而编写的,但是您可以在React Native中完全相同地设置运行脚本 。 最初发布于 brightinventions.pl 。 […]

3D Touch — Peak&Pop功能

在我以前的文章中,我写了关于在您的应用中采用UIApplicationShortcutItems的文章。 现在是时候实现Peak&Pop了-3d Touch提供的一项功能。 开始吧 首先,我们需要检查我们的设备是否支持强制触摸事件。 然后,如果我们的设备熟悉强制触摸,则可以轻松注册UIViewController的强制触摸事件。 看一下这个片段: 第二种方法负责一个称为Pop的事件。 当3d touch机制检测到您强烈按下从viewControllerForLocation方法返回的ViewController ,它将调用该UIViewController并将其作为viewControllerToCommit给第二个viewControllerToCommit previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)函数。 重要的是,当 viewControllerForLocation 返回 nil , 将不会调用 第二个函数 viewControllerToCommit 。 在此方法中,我们可以显示viewControllerToCommit或执行其他操作,例如,为触摸的视图添加动画。 实作 假设您有UIViewController ,其中包含两个UIImageViews ,其中包含漂亮的苹果图像。 对于此控制器,我们要实现3d Touch Peak&Pop功能。 在viewDidLoad()函数中,为强制触摸事件注册我们的控制器。 很好,是吗? 结论 我不喜欢确定用户触摸哪个视图的方法。 检查一个点并为此计算位置并不是很好。 实现视图的3d触摸机制的另一种更好的方法可能是:通过某些属性(例如3dTouchGestureRecognizerDelegate扩展UIView类,然后在UIViewControllerPreviewingDelegate实现某些方法。 然后,我们不必检查视图是否被触摸,因为在委托方法上,触摸的视图可以作为方法参数传递。 gestureRecognizer熟悉的东西。 也许在将来的iOS更新中,API会更改吗? 综上所述, UIViewControllerPreviewing允许我们创建非常漂亮的功能,我强烈建议您使用它并改善您的应用程序! 您可以在我的GitHub存储库中找到示例应用程序的整个实现。 感谢您的阅读,很快再见! 关于我 我是波兰格但斯克的软件开发人员。 大多数情况下都使用iOS,但我对其他任何技术,框架和挑战都持开放态度。 如果您喜欢我的帖子,请随时在Twitter上关注我并阅读我的个人博客。

iBeacons和iOS:Rantmedia Hack Day

什么是iBeacon? iBeacon是由Apple开发的协议,该协议利用低功耗蓝牙将信息广播到收听设备和应用程序。 iBeacon广播三个重要信息:其UUID,主要ID和次要ID。 这些用于识别单个信标,并允许应用程序在靠近信标的情况下做出适当响应。 例如,事件中心可以设置一些iBeacon并将它们配置为使用相同的UUID。 在这种情况下,UUID标识信标的所有者。 每个信标可​​以被赋予不同的主要或次要ID。 然后,应用程序可以侦听具有给定UUID的任何信标,并在进入信标覆盖的每个不同区域时执行操作。 对于我们的Hack Day,我们使用Android应用程序BeaconToy设置了多个具有不同值的信标。 iBeacon与iOS集成 苹果在其CoreLocation和CoreBluetooth框架中包括对iBeacons的支持。 如果要编写只需要侦听iBeacon的应用程序,则需要使用CoreLocation,而如果要从应用程序中作为iBeacon广播,则需要CoreBluetooth框架。 出于Hack Day的目的,我们正在编写一个仅监听和响应信标而不是广播的应用程序。 构建一个iBeacons应用 如果您想继续,可以找到我们在Github上构建的应用程序。 总览 该应用程序使用CoreLocation的CLLocationManager监视CLBeaconRegion。 输入信标区域时,它将开始对区域内的所有信标进行测距。 远程信标以其UUID,主要和次要ID以及相对接近程度显示在表格视图中。 当输入区域时,如果应用程序未激活,我们还使用后台信标监视来显示通知。 创建一个新项目,并使用UITableViewController设置基本UI。 设置CoreLocation 在开始监视之前,我们需要设置视图控制器以导入CoreLocation框架,并设置CLLocationManager并使表视图控制器符合CLLocationManagerDelegate协议: 导入 UIKit 导入 CoreLocation 类 ViewController : UITableViewController , CLLocationManagerDelegate { 让 locationManager = CLLocationManager () 覆盖 func viewDidLoad (){ 超级 .viewDidLoad() locationManager.delegate = 自我 如果 CLLocationManager .authorizationStatus()!= .authorizedAlways { […]

Swift 3中的API.AI

目的 我希望到本文结束时,您将像老板一样,学习如何在自己的Swift 3项目中实现API.AI。 这篇文章是我一段时间以来收集到的信息的汇总,并认为这对分享很有帮助。 一个帖子,面向有意构建自己的机器人或在互联网上发现不足/过时信息的人们。 如果您阅读了我以前的博客文章,您会知道我对API.AI缺乏相关支持的感觉。 过时的资源和大量的挖掘工作。 这是您可以遵循的直线指南。 先决条件 在继续之前,强烈建议您对API.AI有足够的了解。 如果这是您第一次了解API.AI,请查看API.AI简介。 除此之外,让我们开始吧。 项目构想 在写完上面的标题后,我决定花15分钟的时间提出一个简单而有意义的AI项目构想。 我已经决定我们要构建一个交通信号灯机器人应用程序。 我想要一个简单且适用的项目。 我们将拥有一个了解我们的机器人。 根据我们的输入更改屏幕上的颜色。 我们还将有一个与我们对话的机器人。 设置API.AI 再说一次,如果您还没有签出API.AI指南,我强烈建议您在继续之前进行操作。 这里。 让我们从打开API.AI开始。 然后登录,我们应该在主控制台上。 现在创建一个名为“ Traffic-Master”的代理。创建一个名为“ change.color”的意图。 用红色,黄色和绿色条目创建一个“颜色”实体。 还添加同义词,如停止,减速和前进。 我们可能想用动词来指代这些颜色,例如“向我展示停止色”。 现在转到我们刚才创建的“ change.color”意图。 输入您的意图的用户表达式。 例: 太酷了,现在让我们向下滚动到“响应”部分。 在文本响应下添加以下两行: am! 我是彩色的! 玫瑰是红色的。 紫罗兰是蓝色的。 我只是将颜色更改为只适合您的颜色。 我们刚刚教我们的机器人如何以文本形式响应更改颜色的意图。 我们给了它两种响应方式,所以我们的机器人不是那么平淡。 机器人的行为将与人类更相似。 您向漫游器添加的变化越多,漫游器对您的响应方式就越多 。 它太酷了。 在API.AI上测试 现在,我们将测试我们的机器人。 向右看,您应该看到一个要测试的空间。 按下麦克风按钮,然后说“给我看红色”。或者直接输入。 然后尝试“该走了。”记住,我们将go设置为绿色等。还要注意我们的机器人的两个不同响应。 太好了,我们的流量管理员了解我们! 现在将“ change.color”作为我们的操作,然后按保存。 […]

iOS教程:制作自己的计时器应用

在您的Xcode上,转到“ 文件” >“ 新建” >“ 项目”以创建一个新的空白项目。 继续,给您的项目起任何名字。 为了我,我放了Timer 。 您可以继续输入所需的信息作为您自己的信息。 现在,您应该知道如何从对象库中获取对象。 如果不是,则位于右下角。 为此,我们将需要3个按钮和1个标签。 继续并相应地放置它们并命名。 在右上角,单击助手编辑器以获取分屏。 基本上,您现在所看到的是右侧的类包含运行左侧布局的代码。 现在,单击每个按钮上的“控制”并将其拖动到代码侧 然后,它将弹出您可以选择的位置,将“ Outlet”替换为“ Action”。 确保开始,暂停和重置具有@IBAction 你应该有: @IBAction for StartButton,我将其命名为startPressed @IBAction for PauseButton,我将其命名为pausePressed @IBAction对于ResetButton,我将其命名为resetPressed @IBOutlet for StartButton,我将其命名为startButton @IBOutlet for PauseButton,我将其命名为pauseButton 标签的@IBOutlet,我将其命名为timeLabel 如果遇到问题,您的代码应如下所示: 导入UIKit 类ViewController:UIViewController { @IBOutlet弱var startButton:UIButton! @IBOutlet弱var pauseButton:UIButton! @IBOutlet弱var timeLabel:UILabel! 变数计数器= 0.0 var time = Timer() var isCounting = […]