使用LLDB在Xcode中进行调试

数据冒险 犯了错误 有时,我们会对不正确的事情做出假设。 这种说法似乎很明显,这是人的天性。 编写软件时,最好质疑您的假设是否正确。 很多时候,您会发现,仔细检查后发现事情与最初出现的情况并不完全相同。 🤔挑战你的假设 使用Xcode时,可以质疑我们的假设的一种方法是使用调试器。 调试器是一种工具,可让您使用细粒度的控件检查和操纵代码执行。 通过调试,您可以更好地了解您的代码在做什么。 这篇文章旨在简要概述Xcode中的调试以及一些可以帮助您的工具。 我打算就调试主题撰写一系列文章,这是第一篇。 调试的主题非常广泛,本文并不旨在提供完整的概述。 如果您觉得缺少什么,请继续关注本系列的更多帖子。 另外,请随时给我评论。 崩溃的土地之旅 这听起来可能有些奇怪,但是可以将代码崩溃视为旅途。 当您点击运行时,它开始运行并编译。 在此过程中,它继续使用方法并具有许多特性。 最终,它成功地找到了坠机土地。 当您开始调试时,您只有一小幅图片。 您有起点和终点,但要知道如何到达那里,就需要追溯旅程的步骤。 为了帮助您完成旅程,Apple向您赠送了一个有价值的物品LLDB调试器。 控制台和LLDB LLDB是Apple提供的软件调试器,它是Xcode中的标准调试工具。 LLDB是一个功能强大的工具,可将应用程序分解为各个组件。 它的用途不仅限于Xcode IDE,即使您无法访问其源代码,也可以使用LLDB分解并检查应用程序。 鉴于功能和用途的广泛性,本文的含义更像是粗略的概述,我不想通过详细研究这些内容而超出范围。 调用堆栈 使用LLDB,我们能够检查调用堆栈以及堆栈中的特定堆栈帧 。 调用堆栈是由应用程序创建的数据结构,用于跟踪其所有行为。 数据结构 堆栈数据结构只是一个队列,在队列中添加的最后一个元素是从中返回的第一个元素(LIFO队列-先进先出)。这与物理世界中的情况大同小异:一堆砖的顶部(如果您从底部取出,即添加的第一块砖,它们都将崩溃。) 堆叠框架 在调用堆栈中有称为堆栈帧的结构。 堆栈框架包含有关为其创建执行的信息。 在调试时,许多此类信息可能会变得有用。 数据范围从局部变量到完成时返回的内存地址。 苹果文档: 程序运行时,它将有关正在执行的操作的信息存储在称为调用栈的数据结构中。 每次调用方法时,程序都会在调用堆栈的顶部推入一个新的堆栈框架 ,其中包含以下内容:传递给该方法的参数(如果有),该方法的局部变量(如果有的话)以及指向该地址的地址。方法调用完成后返回。 断点 如果您不熟悉代码断点,请允许我给您简要介绍一下。 在Xcode中,断点使您可以在特定点中断代码的执行。 这很有用,因为它使您可以在给定的时刻详细检查应用程序的状态。 断点类型 象征绕道 在进一步进入断点之前,让我们先谈谈符号化。 符号化是将内存地址映射到更简单的函数名称。 返回我们以前计划的编程 处理断点时,重要的是要了解有不止一种类型。 让我们简要地谈谈一些重要的类型: […]

iOS推送通知背景下载神秘化

在实施推送通知时,我发现许多有关后台下载如何工作的不完整和不准确的信息。 我必须通过实验弄清楚其中的一些内容,以防万一它可以帮助其他人,这就是我所学到的。 (请注意,我将不介绍设置Apple Push Notifications的详细信息-这是一个完全不同的主题)。 期望的行为 至少对于我的应用程序而言,期望的行为是到达推送通知以触发后台下载,以便在用户下次打开该应用程序时(通过点击通知或正常打开该应用程序),该数据已经在那里。 此外,如果用户点击通知本身,则该应用应打开并显示该通知引用的特定视图/数据。 为了更具体一点,在紧急电子邮件和任务管理应用程序中,有关新电子邮件的通知应触发该应用程序从服务器下载该消息的内容,然后点击通知应打开该应用程序并显示该特定线程。 一个明显的问题是为什么您不能仅随通知一起直接发送所需的内容。 问题在于,Apple将通知有效载荷限制为2 KB,不足以包含大多数电子邮件的内容和元数据。 配置项目以进行通知背景下载 首先,您需要为您的应用设置适当的功能。 我假设您已经在目标设置的“功能”部分中启用了“推送通知”。 对于后台获取,您还需要在“后台模式”下启用“后台获取”和“远程通知”。 所有重要内容可用标志 其次,不要忘记在服务器发出的实际通知中将content-available设置为1,以触发后台下载。 如果您未能在通知中包含此标志,则通知到达时,您的应用将不会收到任何协议方法调用。 了解相关的App Delegate协议方法 乍一看,这似乎很简单。 UIApplicationDelegateProtocol提供了application:didReceiveRemoteNotification:fetchCompletionHandler:方法,该方法在通知到达电话时被调用。 并发症有两个方面: 当用户点击通知以启动应用程序时,也会使用完全相同的参数调用完全相同的didReceiveRemoteNotification方法。 如果通知到达时(或用户点击通知时)应用尚未运行,则通知信息将作为启动选项传递给didFinishLaunchingWithOptions,然后调用didReceiveRemoteNotification *。 同样,没有区分通知到达与用户点击通知。 因此,您需要处理四种情况: 通知到达,应用程序在后台运行。 通知到达,应用未在后台运行。 用户点击通知,应用程序在后台运行。 用户点击通知,应用未在后台运行。 案例1和3仅在案例2和4在didFinishLaunchingWithOptions的启动选项中提供通知详细信息时才调用didReceiveRemoteNotification,然后调用didReceiveRemoteNotification。 更为复杂的是,如果用户通过将其从内存中刷出而手动杀死了您的应用程序,则不会发生情况2。 也就是说,您的应用程序永远不会在后台启动以获取数据,直到用户选择再次启动它。 从用户点击通知中区分通知到达 除了一个例外,您可以通过检查应用程序状态来区分通知到达和用户在didReceiveRemoteNotification(或didFinishLaunchingWithOptions)中点击通知的情况。 如果应用程序在后台运行(UIApplicationStateBackground),则应执行后台下载。 相反,如果应用程序是“非活动的”(UIApplicationStateInactive),则表示它是响应于用户点击通知而从后台移动到活动的。 如果该应用程序已经处于活动状态(UIApplicationStateActive),则通常不需要执行任何操作。 但是,有一个重要的例子。 如果应用程序已暂停(在快速应用程序切换模式下,双击主页按钮后),并且通知到达,则应用程序的状态将为UIApplicationStateInactive而不是UIApplicationStateBackground。 但是,这并不意味着用户点击了通知。 因此,您需要其他逻辑来检测这种情况。 您可以将applicationWillEnterForeground用作其他信息。 当应用程序从后台转换为非活动状态时,始终会调用该方法,因此您可以依靠它在用户点击通知且应用程序实际上正在启动时(而不是通知到达时)被调用,而用户尚未交互。 您可以保留一个标志来跟踪该应用程序是否真正启动。 这是AppDelegate中的基本代码: -(void)applicationWillResignActive:(UIApplication *)application { self.appIsStarting =否; } […]

流行的Swift iOS图表库

大多数iOS开发人员正在学习中,或者现在正在Swift中进行全面开发。 我想快速汇总一下令人难以置信的code.com上三个评分最高的Swift iOS图表库。 这些是根据受欢迎程度,各种图表和功能选择的。 图表 流行的且恰当命名的Charts是一个很好的起点。 使用iOS,tvOS和OSX的Swift编写。 但是,值得注意的是该演示项目位于目标C中。 该库为我们提供了8种不同的图表类型: 线,条,组合,饼图,散点图,烛台,气泡和雷达 还有很多选择,例如 在两个轴上缩放(触摸手势,单独轴或捏缩放)。 使用触摸手势和组合图(线,条,散点图,烛台,气泡)进行拖动/平移。 可自定义的轴(x轴和y轴)和突出显示值(具有可自定义的弹出视图)。 将图表保存到相机胶卷并导出到PNG / JPEG。 图例是自动生成的,但也可以自定义。 2.汇票 这是适用于iOS的高度可定制的图表库,包括: 条形(普通,堆叠,分组,水平,垂直) 散点图,直线(直线/三次/自定义路径生成器) 面积,气泡,多轴。 蜡烛。 一切都是可自定义的,例如颜色,视图,单位,标签,动画,交互,轴等。 使用叠加层,信息视图等,可以轻松创建任意标记。 它使用模块化架构,应该可以轻松创建新的图表类型或添加效果。 3. PNChart-Swift-这是原始PNChart目标C库的快速版本。 它具有一些不错的动画并支持: 酒吧 线 雷达 馅饼 散点图。 如果您对此列表有任何补充,请联系我们,让我们知道。

使用Vapor Server Side Swift框架存根XCUITests

最初在XCBlog上发布在这里 毫无疑问,Swift是用于为iOS,macOS,watchOS和tvOS等Apple平台开发本机应用程序的出色语言。 但是,作为一种新语言,Swift缺少许多测试功能,就像我们在其他编程语言(如Ruby)中看到的那样。 在Swift中使用协议模拟类非常困难,并且存根网络请求的选项非常有限。 模拟是脆弱而艰苦的,到Swift时模拟变得更加困难。 Swift中没有可用的成熟模拟库来生成类似Java,Ruby,Python或其他语言的模拟。 开发人员必须手动编写所有模拟,并将测试代码与生产代码紧密耦合。 这里有一篇很棒的关于iOS网络测试的文章,以了解有关如何使用协议进行模拟的更多信息。 存根是测试代码的另一种方式,而不必依赖后端或网络。 使用存根,我们仍然可以实现网络测试的目标,并且不必将测试代码与生产代码紧密耦合。 我们将看到可用于存根的库的详细信息。 一些最受欢迎的库是用于XCTest(unit)测试的OHHTTPStubs,Mockingjay,Hippolyte。 用户界面测试贯穿网络层,涵盖了网络测试的所有方面。 苹果有XCUITest框架来涵盖Xcode UI测试。 我们可以使用一些库来为UITest存根网络。 一些流行的库包括Swifter,SBTUITestTunel和XCUITest(UITest)的Embassy。 但是,市场上出现了新的服务器端Swift框架,例如Vapor,Kitura,Perfect,它们也可以用于暂存网络请求。 在这篇文章中,我们将看到如何使用Vapor服务器端swift框架对网络请求进行存根。 Apple在WWDC 2015上宣布了Xcode的UI测试支持。UI测试被设计为完全黑盒,无需访问主应用程序代码和数据。 XCUITest使用两个独立的进程Test Runner和Target应用程序,测试运行器启动了目标应用程序,并使用UIKit内置的可访问性功能与在单独进程中运行的应用程序进行交互。 在嘲笑或测试UITest时,我们几乎没有选择 模拟和通过发射参数/环境 这意味着您不能直接模拟API。 与代理应用程序通信的唯一方法是传递启动参数或启动环境。 我们可以传递模拟API并创建启动环境变量,然后将其传递给XCUITests,但这需要大量的工作。 代码用if-else语句括起来,以确定听起来不太好的构建配置。 Web服务器存根后端并返回响应 剩下的其他选择是对网络呼叫进行存根并从服务器获取所需的数据。 为此,我们需要模拟后端并指向我们的应用程序以使用这些端点。 问题是我们是否仍可以使用上面提到的存根服务进行单元测试。 我们仍然可以使用这些库来处理网络请求,但是有时它需要更改主应用程序的逻辑,并且需要重构某些东西以增加额外的工作。 我们需要在生产代码中添加很多测试代码。 在我先前关于XCUITest的网络存根选项的文章中,我们介绍了所有选项,例如Swifter,SBTUITestTunel和Embassy for XCUITest。 现在,让我们详细介绍一下Vapor。 服务器端Swift框架尚未投入生产,但我们可以将其用于存根XCUITest的目的。 我还没有在互联网上读过任何人做的书,但是它工作得很好。 市场上几乎没有可用的Server Side Swift框架,例如Perfect,Kitura,Zewo和Vapor,但在此演示中,我们将使用Vapor。 选择蒸气的原因是它很容易学习,并且蒸气周围的社区正在迅速发展。 它完全由Swift编写,并带有易于上手的Vapor工具箱。 为了演示此功能,我创建了一个演示应用程序,当我们在文本字段中输入Github用户名时,它将显示Github用户信息。 您可以从Github Vapor-XCTest克隆该应用程序,该应用程序具有带有和不带有存根的XCUITests。 您需要安装Xcode 9+和OpenSSL,然后我们才能签出演示应用程序。 $ git clone https://github.com/Shashikant86/Vapor-XCTest […]

AppCode和单元测试

由于不稳定,XCode的质量每天都在下降。 这些天,我正在尝试AppCode,感觉好多了。 但是对于一直使用XCode的人来说,几乎不可能迁移到AppCode,因为它看起来或感觉上都不像XCode。 在我的职业生涯中,我曾从事过各种IDE的工作,从Visual Studio,PhpStorm,PyCharm,Android Studio,Eclipse,最后是用于iOS开发的XCode。 在XCode中,即使重新启动计算机后,XCode中的小菱形测试按钮也会消失并且永远不会显示,更不用说重新启动XCode了。 有没有想过为什么? 查看我的这篇博客文章,以找回它们。 这就是为什么我想尝试用于iOS开发的新IDE的原因之一,而我在这里使用AppCode。 与XCode不同,AppCode并未配置其他目标。 我们将必须手动配置它们。 请按照以下步骤操作,您将一路顺风。 从“选择运行/调试配置”菜单中单击“编辑配置”。 在打开的窗口中,单击左上角的“ +”,将弹出上面显示的菜单。 选择XCTest / Kiwi选项。 在“名称”字段中为测试目标命名。 如果要测试类或方法,只需为“测试种类”选择“类/方法”。在“类”字段中,可以将其保留为空白以测试测试目标中的所有类,也可以测试特定的类。 键入测试类的名称后,“方法”下拉菜单将显示该特定类中的所有测试,您甚至可以选择测试一个类的单个方法。 这提供了非常好的灵活性。 将“目标”设置为项目中的测试目标。 单击“应用”。现在,您将在“选择运行/调试配置”下拉菜单中看到测试目标的配置。 选择测试目标和设备,然后单击“运行”按钮。 瞧! 您的测试将开始运行。 撰写本文时使用的AppCode版本为2016.1.2。

自动布局使用的视图属性

有些视图会根据其持有的内容自动调整大小,这称为其intrinsic content size 。 EG按钮的固有内容大小是其标题的大小加上少量的空白。 并非所有视图都具有固有的内容大小。 对于包含视图的视图,固有内容大小可以定义视图的高度,宽度或两者。 假设我们有一个带有文本“ Click Me”的按钮。 我们绝对不希望按钮小于其内部的文本,否则文本将被剪切。 这就是所谓的Compression Resistance Priority 。 视图的“抗压缩优先级”越高,则视图抵抗增长到大于其固有内容大小的能力就越大。 仍在“单击我”按钮上,如果我们不希望按钮的大小大于其内部内容,如下图所示: 如果我们希望按钮在没有太多填充的情况下拥抱其内容,则必须增加Content Hugging Priority 。 视图的“内容拥抱优先级”越高,则视图抵抗增长到大于其固有内容大小的能力就越大。 我们可以通过编程方式设置内容拥抱和抗压缩优先级,如下所示: 这两个方法采用两个参数,分别是UILayoutPriority和UILayoutConstraintAxis 。 优先级可以是必填项 , defaultHigh , defaultLow , fittingSizeLevel ,其中必填项是最高的,而fittingSizeLevel是最低的。 UILayoutConstraintAxis可以是垂直轴或水平轴。 我将在UIStackview上写另一篇文章,之后我将展示以编程方式编写不同视图的方法。 谢谢阅读。

Pola Arsitektur MVVM pada迅捷

您尝试过MVVM吗? 嗨,😁! Pastikan Anda Sudah Paham Mengenai TableViewController , Extension和 关闭回调 西伯利亚甜菜 苹果merekomendasikan Pola Arsitektur MVC(模型-视图-控制器) 开发者 dalam iOS / MacOS 开发。 Namun dengan adanya ViewController pada Swift,banyak aplikasi yang dibuat menjadi seperti: Dengan ViewController是MVC(Massive View Controller)。 月经MVVM Dengan menggunakan MVVM,维护部门维护Sebuah aplikasi dapat dibangun secara lebih rapi dan mudah untuk di maintenance。 MVVM(Model-View-ViewModel)记录数据和数据数据ViewController和ViewModel。 Dimana ViewController […]

可编码协议

从Objective-C到Swift的过渡当然也取得了成果-尽管有时陡峭的学习曲线和不断发展的语言性质有时可能会带来挑战。 (当然也有挫折 。多年来,iOS处理设备轮换的多种方式越少说越好!) 对我来说,在不遥远的历史中最能引起欢乐的变化之一就是添加了Codable协议。 Swift 5 刚刚发布(并获得了广泛好评),但是-在Swift 4中增加了Codable-对我而言,这是一个更加令人兴奋的发行版。 可编码协议 Codable是一个非常漂亮的Swift协议。 在Swift中(与Objective-C相反),相比于继承,它更加强调组合,使用协议在不使用子类的情况下向类,结构或枚举实例添加功能。 实现协议的类,结构或枚举被称为与该协议兼容 ,从而在该过程中获得了该协议的功能。 可编码的独特之处在于,它实际上只是可Encodable和可Decodable协议的结合的Encodable Decodable 。 一个实例可以独立地符合任何一个,但是如果它同时符合两个,那么它也是可编码的。 这些协议给我们带来了什么? 让我们来看看! 编码利益 许多应用程序的一项常见操作是从API提取内容。 例如,我们的KPCC API客户端下载文章,剧集和节目时间表数据,并将其转换为适用于应用程序的模型实例。 这是解码的示例(也称为反序列化)。 我们使用数据的序列化表示形式(在本例中为JSON),并将其转换为可以使用的形式。 我们还可以反向执行此操作,将数据编码(序列化)为一种格式,该格式可以传递回服务器或以本地缓存的形式保存到用户的设备中。 总而言之,我们得到了一个用于编码/解码的标准化系统,并且有机会删除许多样板代码。 我们的KPCC API客户端项目在很大程度上依赖于使用Codable来获取API响应,并使用它们返回本地模型实例。 基本编码和解码 符合Codable很简单。 假设您有一个结构,只需将Codable协议添加到您的结构定义中,如下所示: struct Cat:可编码{ var age:Int 变量名称:字符串 } 而已! 现在,如果您希望对该Cat结构进行编码并将其保存到用户的设备中,然后将其读回,则可以这样进行: let apollo = Cat(年龄:10,名字:“ Apollo”) 让apolloData =尝试吗? JSONEncoder()。encode(apollo) 让documentsURL = FileManager.default.urls(用于:.documentDirectory,在:.userDomainMask中)。 让fileURL = documentsURL?.appendingPathComponent(“ Cat.json”) […]

Swift中的内存管理,具有强而弱的无人参考

对于iOS应用程序,学习内存管理至关重要。 您正在使用Objective C还是Swift,但是您需要熟悉内存管理将如何有所帮助。 从本文开始,我假设您对Objective C以及对OOP的Swift和清晰概念,闭包,可选和属性有一些了解。 基本上,内存管理是引用计数,在Objective C或Swift中,当您在代码中引用变量时,其保留计数会增加,反之亦然。 如果变量的保留计数达到0,则将释放该变量。 您已经知道swift使用ARC(自动引用计数)来管理应用程序的内存使用情况。 因此,您不必自己担心内存管理。 但是,您需要知识来管理代码中的内存,以避免内存泄漏。 当您创建任何新的变量实例时,ARC会分配内存来存储信息,而当不再需要该变量时,ARC将释放分配给该实例的内存。 您需要确保一旦变量被释放,就无法再次访问它,否则您的应用程序将崩溃。 初始化任何变量或对象时调用Init(),而对象的引用计数达到0时,调用deinit()取消对象或变量的分配。 下面,我编写了示例代码以更好地理解。 实际上deinit块是由ARC自动运行的,但是为了更好地理解,我在这里写了详细的文章,介绍了如何编写适当的代码。 我在那篇文章中用代码示例介绍了以下内容: 使用Swift定义属性时,默认会应用强引用。 在Swift中几乎所有地方都使用了强引用。 类的每个新创建的对象都有引用计数器。 将值的属性分配给对象后,它将增加。 在引用计数器的值大于0之前,它不会被释放。 它允许创建实例,但不增加ARC的引用计数。 大多数情况下,参考标记应被标记为较弱,并且比其他类型的参考具有较短的寿命。 如果将其引用设置为nil,则应使用弱引用。 如果没有其他实例强烈引用该实例,则实例将取消分配。 就像弱引用一样,保留计数器不增加1。 与弱引用不同,无主不必是可选的,因为在解除分配时它们不会自动设置为nil。 仅当您知道该实例的对象永远不会为零时,才应使用无主引用。 注意:只要您知道弱引用会在某个时候变为零,就可以使用它。 当您知道其引用一旦初始化就永远不会为零时,使用无主引用。 最后,如果您不管理内存,那么它会使您的应用程序不稳定,并导致大量内存泄漏。 但是通过谨慎地使用弱者和无人者,我们可以管理内存泄漏并放弃内存。 最初发布在 www.logisticinfotech.com

AVAudioSession简介

这周,我将谈论一个小得多的话题,但这个话题与我的内心深处息息相关。 我从音频界开始从事iOS开发,我总是喜欢谈论Swift中的音频。 今天,我在写有关AVAudioSession的文章。 花一点时间考虑一下我们如何在应用程序中使用音频。 有时,我们会出现一些小错误和bloop来提醒用户某些事情。 其他时候,我们会提供游戏的背景音乐或视频中的声音。 有时,可以通过手机侧面的静音开关关闭声音。 一切都很好,但是如果我们有一个时钟应用程序,并且需要警报来覆盖该开关怎么办? 如果我们希望我们的应用在手机屏幕锁定时继续播放音乐怎么办? 当我们的应用程序播放声音而另一个应用程序播放音乐时会发生什么? 应用程序通过使用音频会话来处理此问题。 关于iOS应用中的音频的第一件事是,您的应用不会直接接触设备的任何音频硬件。 该应用程序通过中介与操作系统进行通信。 该中介是音频会话,特别是AVAudioSession。 看! Apple文档中的方便图形! 启动应用程序时,在幕后将为它提供AVAudioSession的单例实例。 我们的应用程序可以使用AVAudioSession的共享实例来配置应用程序中音频的行为(首先必须导入AVFoundation)。 要调整AVAudioSession的总体行为,我们可以将其设置为以下几类之一。 AVAudioSession具有一个简单的方法: setCategory(_:mode:options 🙂 。 请注意,您可以设置的类别由全局字符串常量表示,例如“ AVAudioSessionCategoryAmbient” 那么,这些类别中的每一个都有什么作用? 好吧,我不会遍历其中的每一个,因此,这里有一个方便的图表以获取更多详细信息。 AVAudioSessionCategoryAmbient是默认类别。 设置为此时,来自应用程序的音频将通过静音开关关闭,不会中断来自其他应用程序的音频,并且不会接受任何音频输入。 如果我们将类别设置为AVAudioSessionCategoryPlayAndRecord,则每个类别的情况都将相反。 重要说明:如果您打算在应用程序处于后台运行时播放音频,则必须更改info.plist文件中的某些设置。 幸运的是,Xcode有一个简单的方法可以做到这一点。 只需进入项目功能,打开背景模式,然后选择“音频,Airplay和画中画”即可。 在每个AVAudioSession类别中,可以设置许多模式,这将为您的会话添加更多功能。 同样,这些模式中的每一个都是由常量表示的字符串。 我想知道这些值是否是从较旧的Objective-C代码中遗留下来的,因为通常在Swift中,这看起来像枚举通常表示的那种。 无论如何, 这是每个列表 。 这些模式是针对特定用例进行优化的较小的性能调整。 例如,在具有多个麦克风的设备上,AVAudioSessionModeVideoRecording将打开最靠近该设备摄像机的麦克风。 仅当您设置了较大的类别AVAudioSessionCategoryRecord和AVAudioSessionCategoryPlayAndRecord时,它才起作用。 要考虑的另一重要事项是AVAudioSession的激活和停用,以及在激活或停用失败的情况下的错误处理。 首先,这是来自Apple文档的绝对荒谬的图像。 我发誓我没有化妆: 这是他们的…有关AVAudioSession激活工作原理的解释。 在适当的时间激活和停用音频会话非常重要。 如果您在激活音频会话后将其激活,则您的应用将崩溃。 这是直接从Apple文档中获得的所有内容 : let session = AVAudioSession.sharedInstance() 做{ […]