Tag: xcode

iOS框架文件是为x86_64(不是要链接的体系结构(arm64))构建的,链接器命令失败,退出代码为1

在处理框架时,这是一个常见错误。 大多数人只是遵循stackoverflow上的解决方案(将Build Active Architecture Only仅设置为NO ,并将i386,x86_64添加到有效架构中),但实际上并不需要花费很多时间来了解其背后的原理。 armv64:iPhoneX,iPhone 5s-8,iPad Air-iPad Pro armv7:iPhone3Gs-5c,iPad WIFI(第四代) armv6:iPhone — iPhone3G 上面的如果用于真实设备 i386:32位模拟器 x86_64:64位模拟器 上面的列表是向下兼容的,这意味着iPhoneX也可以与armv6一起运行,而不能完全利用armv64的功能 有关iOS体系结构的更多信息,请参见: 设备兼容性 描述有关现有iOS设备功能的详细信息。 developer.apple.com 如果选择“是”,它将仅将框架构建到“所选设备”,即实际设备(armv)或模拟器(x86_64或i386)。 对于“否”,它将把您的框架构建到“有效架构”列表中 默认情况下,在调试模式下为“是”。 在更多版本中,它表示“否”,可以节省调试模式下的编译时间,并确保您的发布项目框架可以在您指定的所有体系结构上运行。 这就是为什么接受的答案通过强制框架针对所有体系结构进行构建而起作用的原因,但是通过阅读更多内容,您会知道背后的内容,并且可以肯定地节省编译框架的时间。 当然,您也可以更好地控制自己。 因此,如果您使用的是框架,并且要导入到另一个项目,则可以使用模拟器(i386或x86_64)通过 “ 仅构建Active Architecture ”编译该框架,然后使用 “ 仅构建Active Architecture ”将其导入项目。如果是真实设备(armv)的 “是”,您将遇到此错误。 寻找错误说明: 该文件是为x86_64构建的,不是链接的体系结构( i386 )意味着您在64位模拟器中构建框架,并使用32位模拟器构建合并的项目。 而更常见的是: 框架文件是为 x86_64 构建的, 它不是要链接的体系结构( arm64 ):这意味着您的框架是在模拟器中构建的,而合并的项目是使用实际设备构建的。 一种常见的做法是右键单击框架,然后选择“在Finder中显示” ,而大多数开发人员将Finder保持打开状态,而新编译的框架将替换旧框架,而无需关闭Finder并再次重新打开。 是的,这是正确的,但是如果您在两者之间切换构建目标设备,则框架将导致存在不同的文件夹 。 有时您认为自己已经编译了框架,但实际上它在另一个文件夹中。 […]

场景之间的数据传输-iOS App

这个主题对我和您都很重要,因为使用应用程序时,场景之间的数据传输一直在发生,因此我们必须确保一定要学习好。 在我的示例中,我将使用segue将数据发送到下一个场景,当涉及到返回上一个场景时,我将使用通知。 今天的挑战是创建一个列表,列表的数据将发送到下一个场景,并且有一个编辑场景,如果我们更改列表的内容,前一个场景的数据也会被更改。 以下是我通过segue将数据发送到下一场景的核心代码 覆盖func prepare(对于segue:UIStoryboardSegue,发件人:AnyObject?){//为segue准备数据 让destination = segue.destinationViewController为! DetailViewController //设置segue的目标控制器 如果segue.identifier ==“ lover1Segue” {//考虑我正在使用哪个segue destination.loverId = loverA.id //将数据发送到目标场景 destination.loverName = loverA.name destination.loverCons = loverA.constellation destination.loverImageName = loverA.photoName } } @IBAction func lover1Act(_ sender:AnyObject){ self.performSegue(withIdentifier:“ lover1Segue”,发送者:nil)//执行segue } 以下是我的核心代码,用于通过通知将数据发送回上一个场景 起始场景: func updateData(_ sender:AnyObject){ 让notiName = Notification.Name(“ updateData”)//定义通知的名称 NotificationCenter.default.post(名称:notiName,对象:nil,userInfo:[“ loverId”:self.loverId,“ loverName”:self.nameTxt.text!,“ loverCons”:self.consTxt.text!,“ loverImageName” :loverImageName])//发送通知 navigationController?.popViewController(animated:true)//将导航控制器弹出回到上一个场景 } 目的地场景: […]

Xcode 8-将Alcatraz的插件转换为Source Editor Extension

数组XCSourceEditorCommandDefinitions将保存选项的详细信息。 复制/粘贴项目0并将其修改为上面的plist。 XCSourceEditorCommandIdentifier,它是一个标识符,将在SourceEditorCommand中使用该标识符来识别按下了哪个按钮。 XCSourceEditorCommandName是将显示在“编辑器”菜单中的文本。 现在,如果您运行该项目,您将注意到带有灰色图标的Xcode新实例已启动。 这意味着它是包含我们扩展名的Xcode。打开一个项目,然后单击any。 m或。 迅速的文件。 然后转到编辑器,您会注意到一个选项Manage Logs和另外两个选项Enable Logs和Disable Logs 。 尝试单击它们,当然什么也不会发生。 PS。 ( 编辑器->管理日志->禁用日志)中的“ 管理日志”选项出现,因为它是目标的名称。 因此,如果您需要更改该选项,只需更改目标名称。 回到SourceEditorCommand.m 好的,我们现在可以开始开发了! 我们只需要用// NSLog替换NSLog(,用// print(替换print() 。那应该很容易吧? 不幸的是,这个问题并不是那么容易,它有点复杂,但是最后也不是那么困难。 因此,让我们看看我们需要做什么: 识别当前文件是.swift还是.m文件 确定按下了哪个按钮(“ 启用日志”或“ 禁用日志” ) 使用NSArray获取当前文件的行 遍历各行,查找包含日志的行 用注释掉的日志替换特定行。 这是我们项目的代码: 不用担心 我们将讨论每个步骤。 识别当前文件的类型 因此,识别当前文件的类型非常容易。 只需检查invocation.buffer.contentUTI中的字符串值以获取public.objective-c-source或public.swift-source。 由于在我们的项目中, 正则表达式和用于注释日志的字符串对于Swift和Objective-C而言是不同的,因此我们需要检查文件的类型并设置适当的变量。 识别按下了哪个按钮 还记得我们为Info.plist上的每个按钮设置键XCSourceEditorCommandIdentifier的值的时候吗? 在第2行中,我们使用invocation.commandIdentifier来检查单击了哪个按钮。 循环浏览当前文件的各行 在第5行上,我们遍历invocation.buffer.lines ,这是一个保存当前文件行的数组。 您可以作为NSString访问该行。 在第8行,我们检查当前行是否已被注释掉。 如果是真的,我们将其跳过。 在第13行,我们检查当前行是否包含NSLog(或print(。如果包含字符串,则它将继续进行进一步的检查。否则,它将跳过当前行。 在第16行,我们调用了我创建的函数。 此函数正在检查字符串是否包含有效的日志消息,如果该字符串为true,则返回修改后的字符串(注释掉的日志)。 […]

使用R.swift和Sourcery为IBOutlet生成测试

R.swift及其替代品是在更短的时间内编写更安全代码的绝佳方法。 它在基于情节提要的项目中特别有效,可以节省大量工作。 如果您的项目中没有用于资源的任何代码生成器,我建议您考虑添加一个。 安装和设置后,您可以使用生成的代码访问笔尖中的视图: 还不错,不是吗? 我们的项目非常有力地保证现在仅使用现有资源。 但是我们不能确定是否使用连接到某物的插座。 在开发过程中没什么大不了的。 生产呢? 没问题。 让我们编写一些单元测试。 还有更多测试 到了某个时候,我们肯定会遇到另一端的问题-不再需要某些出口,因此将它们删除了,我们必须调整单元测试。 相当重复无聊的工作。 我们有更好的选择,也许还有更好的消磨时间的方式,而不是支持我们的测试,因此-完全放弃! 更长的选择是使用Sourcery自动生成它们。 安装非常简单,但是正如这里提到的,使用brew获得新版本目前并不容易。 我下载了最新版本并将其直接添加到项目中。 之后,就可以使用了。 在R.swift的帮助下,我们已经为我们提取了所有视图。 我们唯一需要的是一个实际的测试模板。 Sourcery当前支持Swift,Stencil和JavaScript。 我坚持使用第二个,发现它非常方便并且得到了很好的支持。 用于为我们的xib生成测试的模板如下所示: 我们要做的仅有两件事-遍历所有属性并找到我们的出口。 在拥有所有数据之后。 从我们的模板中: {method.returnType.variables%中的变量所占的百分比} {%为variable.attributes中的属性,其中attribute ==“ IBOutlet”和variable.typeName | hasSuffix:“!” %} 接下来,我们将进行由{{staticXibVar.name}}和{{variable.name}}组成的特定测试。 XCTAssertNotNil(R.nib。{{staticXibVar.name}}。firstView(owner:nil)!。{{variable.name}}) 现在,我们准备将所有测试放入XCTestCase中并添加到项目中。 在我的情况下,结果如下所示: import,class和func都在模板的内部,我跳过了它们以使其更短。 同样,我创建了第二个用于检查情节提要的模板: 查看控制器测试 核心思想是相同的,主要问题是实际了解在哪里寻找特定类型和变量。 同样,为了使R.swift能够找到您的视图控制器,您必须为其添加Storyboard ID 。 元编程对我来说是个新主意,有很多功能可以发现。 如果您有一个很好的用法示例以及一些问题,请发表评论或在LinkedIn或Facebook上与我联系 可以在此处找到示例项目。 如果您喜欢这篇文章-给它一些鼓掌👏🙂

如何在Xcode项目中计算行数

这个故事最初发布在 AppMakers.Dev上 有时您可能会对Xcode项目文件中的几行代码感兴趣。 有几种方法可以计算行数。 这是简单的一个。 简单是最终的复杂性。 达芬奇(Leonardo da Vinci) 如何在Xcode项目中计算行数 在Mac上打开终端 在终端中输入cd导航到您的Xcode项目目录 在终端的项目内部键入以下内容以仅查找.swift文件: find。 名称“ * .swift” -print0 | xargs -0 wc -l 您将在终端中使用行的数字作为结果,并在底部显示与列出的文件相关的总行数 聚苯乙烯 如果要从搜索结果中排除Pod,请在项目目录中的终端中输入以下内容: 找 。 -path ./Pods -prune -o -name“ * .swift” -print0! 名称“ / Pods” | xargs -0 wc -l

iOS中的表单-第1部分

大家好! 这是我的第一篇中篇文章,非常感谢您提供反馈。 今天,我们将研究在Xcode Storyboard中使用Object引用。 由于我一直喜欢现实世界的用例,因此本文的大部分内容将研究如何使用这些Object引用实现Forms。 到本文结尾,目标是拥有可通过故事板进行配置的高度可重用的表单组件。 这也只是第1部分。在这一部分中,我们将构建一个简单的表单示例,在第二篇文章中,我们将研究一个更复杂的示例。 对象引用 好了,情节提要中的对象引用是什么? 您可能已经在Xcode的UI库中看到了Object引用(这是图1中显示的黄色小方块)。 早在iOS开发人员的早期,此对象曾用于Nib文件中的文件所有者引用。 如果那没有任何意义,请不要担心。 我们现在生活在更好的时代。 现在,从我所看到的来看,它今天使用不多。 我知道直到最近我才从未使用过它。 那怎么办呢? 图1.0的描述说明了一切。 这些对象可用于建模从NSObject类继承的任何对象。 您可以附加N个这些东西来在情节提要中查看控制器。 然后,您可以从默认的NSObject覆盖它们的类。 真的很棒! 我可以通过Storyboard将一堆依赖项附加到我的视图控制器。 然后,在视图控制器上设置IBOutlet ,以创建对这些对象的引用,情节提要将处理实例化所有这些对象。 现在您可能会认为这很酷,但是我不能没有出口就直接将这些依赖项添加到我的视图控制器中……当然可以。 但是,使用情节提要板的强大功能意味着也可以通过情节提要板配置这些对象的任何依赖关系。 情节提要将为我们处理所有这些对象的实例化,我们不必担心。 这些对象还可以通过IBOutlet引用视图上的元素。 接下来,我们将在实现表单时看到这将如何帮助我们。 情节提要中的表单对象 本节将逐步为我们的表单示例构建一个示例Xcode项目。 欢迎继续阅读,或者如果您想阅读,本文结尾处的Github上有一个指向该项目的链接。 让我们从简单的示例开始。 图2具有我们表单的情节提要配置。 有两个视图控制器,一个带有一个可导航到第二个视图控制器的按钮,这些按钮全部嵌入在导航控制器中。 这将使我们在第2部分的稍后部分中创建更多链接。 第二个视图控制器包含我们的表单。 这种形式只是三个标签和三个文本字段,它们都嵌入在UIStackView中 。 底部还有一个提交按钮,将打印出表单的值。 好的。 让我们开始编码。 首先,在Xcode项目中创建一个名为Forms的新组。 然后创建两个名为Form.swift和FormControl.swift的新文件,如图3所示。 我们将从FormControl.swift文件开始。 该文件将包含以下协议: @objc 协议 FormControl { var键:字符串? { 得到 } var文字:字串? […]

Swift中的线程简单解释

如果您来自其他平台,或者您是Swift的初学者,那么很难理解iOS中的线程。 这里有一些技巧,可帮助您使用GCD进行穿线。 首先,线程是关于管理应用程序中工作优先级的全部内容。 使您的代码更快地执行是很棒的,但是更重要的是用户感知的速度 您的应用程序将成为。 作为开发人员,您的目标是确定用户可以看到并与之交互的所有事物的优先级。 它使您的应用程序感觉更快,更敏捷。 不要让用户等待他们没有注意到或关心的东西。 这是避免问题的最简单方法。 基本思想是确保所有视图和界面元素都不会被主队列中的其他项目阻止。 一个很好的例子: 通过仅在主线程上执行与UI相关的工作,可以确保不会阻止用户加载视图或退出视图。 避免使用会在主线程上加载数据,图像等的副作用的函数。 在iOS中执行工作有几个不同的优先级。 较高质量的优先级最高,并且立即处理,而较低质量的服务则在系统释放一些资源时处理。 下面列出了从最高到最低排名的不同质量。 创建具有服务质量的自己的队列真的很容易。 您只需为其提供标签和QoS。 要找出当前线程是什么,请在代码中的任何给定位置: Thread.current 。 这样,您可以确切地看到功能在哪个优先级上运行。 您还可以使用Thread.current.isMainThread检查您是否专门位于主线程上。 这是线程化时最容易出错的方法之一,但也是最容易避免的方法。 在代码中使用同步有很多好处,某些特殊情况需要同步,但是对于刚开始进行iOS开发的人来说,最好避免同步。 注意: 切勿在主DispatchQueue上调用sync,如以下示例所示: 还应避免在.userInteractive队列上使用同步,因为它的优先级与主队列相同。 深入了解WWDC并发视频。 如果您是视觉学习者,请阅读此文章。 它确实帮助我了解了不同的服务质量如何相互作用,以及如何调用不同的优先级。 Ray Wenderlich在线程方面也有很好的指导

使用XCode 10创建自定义代码段变得更加容易

如何使用XCode 10创建自定义代码段 需要什么? 您是否遇到过这样的情况,即我们一次又一次地编写相同的代码,而其实现却几乎没有变化? 可能是的,对! 我们iOS开发人员喜欢UITableView,我们希望在几乎所有控制器中都使用它,并且此UITableView附带了开发人员需要在每个控制器中实现的委托和dataSource方法的列表,只有其实现被更改。 您是否不认为应该有一种机制,在这种机制中,我只键入一个字,所有获得的UITableView委托/数据源方法都应出现在编辑器中? 在这里,Xcode自定义代码段进来了。您只需为UITableView委托/数据源编写自己的自定义代码段即可,并且可以随时使用与该代码段相关的关键字。 这只是一种情况,但是您可以为Xcode中的N个代码操作编写自己的自定义代码片段。 如何创建片段? 使用XCode 10创建代码片段非常容易。请转到“编辑器”->“创建代码片段”。 将出现一个窗口,您可以在其中编写其定义。 如果要在代码段中添加占位符,只需将其放在之间,即可在编辑器和最终代码段中进行转换。 如何使用摘要? 您可以在创建自定义代码段时指定完成快捷方式 。 因此,当您在编辑器区域中键入完成快捷方式时,相关的代码片段将出现在屏幕上以供选择。就像下面的gif示例中一样,我创建了名为snippet-uitableviewdelegate的完成快捷方式。 在Xcode 10中,代码片段库移至顶部工具栏区域,如下GIF所示。 只需单击它,代码段列表就会出现,然后选择您的代码段。 奖金 您是否已经创建了一些常用的自定义swift代码段? 从我的GitHub Repository中获取它。 如果您喜欢这篇文章,请分享并给予一些鼓掌 👏 ! 您可以在Medium上关注我以获取新文章。 另外,在LinkedIn上与我联系。 happyCoding()-> 😃

在GIT中使用Xcode自定义文件模板

Xcode自定义文件模板是加快开发速度并使您能够定义包含所有重复性工作的基本模板的好方法。 将其与GIT结合使用可使您在团队中共享这些文件,并使它们也从中受益。 Xcode的用户定义模板位于~/Library/Developer/Xcode/Templates/File Template 。 如果缺少该文件夹,则可以自己创建它,并且Xcode将在重新启动时链接到该文件夹​​。 子文件夹可用于为模板创建自定义标题。 为您的GIT存储库创建一个子文件夹,并将此新位置用于您的自定义模板。 有很多很棒的资源来学习如何创建自己的自定义文件模板。 一些例子是: Xcode 9自定义模板 创建自定义Xcode项目模板 创建一个“智能” Xcode文件模板 但是对我来说,最简单的方法是从我已经熟悉的Xcode复制基本模板。 您可以通过打开终端并为通用模板执行以下行来轻松找到它们: 打开/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates 或以下针对平台特定模板的行,将#platform_name#替换为您要探索的平台: 打开/Applications/Xcode.app/Contents/Developer/Platforms/#platform_name#/Developer/Library/Xcode/Template 创建第一个自定义文件模板后,可以将更改推送到GIT存储库。 您的团队将能够通过获取最新更改来使用它们。 这个故事最初发布在: https://www.avanderlee.com/workflow/xcode-custom-file-templates-git/

在Xcode 10 Playgrounds中使用3rd party框架

注意:这是上一篇文章的Xcode 10更新,但有一些补充。 Xcode Playgrounds是编写代码原型甚至练习测试驱动开发的好地方。 有时,第三方库可能会方便使用。 在本文中,我将向您展示两种在框架中使用Xcode Playgrounds的方法。 第三方框架不能简单地包含在游乐场中,甚至不能作为“来源”的一部分: 假设我们有一个要在操场上测试的框架-在下面的示例中,我选择了一个著名的库:由多产的开源和作者Marin Todorov编写的SwiftSpinner。 下载的档案包含可以直接打开的Xcode项目。 确保项目构建成功(Cmd + B) 操场 现在,让我们创建要使用的游乐场-从菜单中选择“文件”>“新建”>“游乐场”,确保它是一个iOS游乐场,然后选择“单一视图”模板。 您可以使用默认名称(MyPlayground.playground)并将其存储在框架本身中: 创建游乐场后,切换到“助手编辑器”以查看游乐场输出: 现在,使用该框架非常容易: 将其导入顶部: 让我们看看如何在操场上使用多个框架。 我们将使用相同的SwiftSpinner和Alamofile。 首先,下载两个库并将它们并排存储在文件夹中: 现在,我们将像以前一样打开SwiftSpinner Xcode项目,并围绕它创建一个工作区-从菜单中选择:File> Save as Workspace。 我将其命名为:Playground.workspace,并将其保存在两个文件夹旁边: 添加第二个框架 现在,让我们添加第二个框架—从Alamofire主项目中,将Alamofire.xcodeproj(确保您添加了项目而不是Alamofire.xcworkspace)拖放到SwiftSpinner项目旁边的工作区中。 现在,工作空间应包含来自两个框架的方案。 操场 与上一节一样,我们将创建一个游乐场-从菜单中选择“文件”>“新建”>“游乐场”,确保它是一个iOS游乐场,然后选择“单视图”模板。 确保将其添加到“游乐场”组。 一种统治所有人的方案 现在,在使用框架之前,我们必须一个一个地构建它们。 虽然对于我们而言,这并不难,但是如果使用更多的它们,或者如果您在操场上使用它们时积极开发它们,可能会很麻烦。 为此,我们将添加一个将构建所有框架的新方案。 从方案选择器中,选择“新方案…”: 确保目标是“无” —我已将其命名为“我的游乐场”: 在下一个屏幕的Build类别下,使用小+按钮添加从属目标-这是应如何配置的: 点击“关闭”。 现在,每次您建立Playground目标时,也会建立所有的依存关系。 注意:请确保您要为模拟器而不是真实设备而构建。 使用框架 现在可以像以前一样使用这些框架: 导入它们 快乐的游乐场! 🤓