Tag: swift

适用于iOS的简单立体声和ARKit

希望为希望利用iOS 11新型基于ARKit SLAM的世界跟踪器将SceneKit游戏扩展到Google Cardboard的用户提供一些快速模板代码。 主要组件是SLAMRunner,它在您和ARKit的ARSession之间进行中介。 第二个是一个简单的StereoViewController,它将您的SCScene附加到立体声“头节点”上。 可以根据自己的喜好调整摄像机的值,但普通用户对启动器的内在功能感到满意。 DualViewController.swift是一个示例类,它以100倍的喷射量实现了入门级XCode场景。 这是存储库: mikezucc / SimpleStereoARKit SimpleStereoARKit –关于在没有ARScene的情况下使用ARKit的简单参考指南,以及用于附加的简单便捷类…… github.com SLAMRunner.swift 裸露的简单对象即可运行基础ARKit SLAM。 这将以matrix_float4x4的形式向matrix_float4x4提供更新,该更新是matrix_float4x4的类型别名。 您可以使用诸如headNode?.simdTransform = transform这样的值来更新SCNode的位置。 像这样附加: tracker = SLAMRunner() tracker?.delegate = self 像这样接收更新: protocol SLAMRunnerDelegate { func updatedTransform(_ transform: matrix_float4x4, imagePixelBuffer: CVPixelBuffer) // plz lock up your buffers necessarily func trackingBadState(_ status: SLAMRunnerStatus, trackingState: ARCamera.TrackingState, error: Error?) } […]

迅捷笔记周02

第二周(这根本不是什么第二周其实算是第二部分了吧,事隔一个月了ㄟ)都已经过了那么久终于要来整理学了啥(懒惰病真的是不容小觑)。直到我只能表示,真的是越学越头痛呢,看来脑袋太差的人不适合学写程式🙃 如果判断式 遵循情况更改程序执行的流程。 如果情况1成立,就执行程式码,否则执行第二条程式码,如果情况1、2皆不成立,则执行第三条程式码。 如果判断式一有符合条件的情况,就不会继续往下执行其他判断式。 如果情况1 { 程式码 }否则,如果情况2 { 程式码 }其他{ 程式码 } ————————————- var价格= 80 如果价格== 80 { //听起来不错,要买 打印(“购买”) } 如果价格> 150 { 打印(“你疯了吗?”) }否则,如果价格<50 { 打印(“非常便宜”) }其他{ 打印(“购买”) } ————————————- 让myName =“ Thomas” 让时间= 7 让isHungry = true 如果myName == “ Thomas” &&时间<12 && isHungry = true { 打印(“早上好,\(我的名字)。你想吃点早餐吗?”) }否则,如果myName ==“ […]

使用NSLayoutAnchor删除情节提要

接口构建器是Apple提供的出色工具。 但是,了解事物的编程方面也很重要。 不用担心,那不会那么痛苦。 卸下主板 在Xcode中打开一个新项目,然后选择“单一视图应用程序模板”。 默认情况下,此模板提供Storyboard,因此让我们先删除Main.Storyboard。 更新信息列表 尽管已删除它,但Xcode仍认为它正在引用情节提要,因此我们需要进入info.plist并删除以下行。 更新AppDelegate 现在,在AppDelegate.swift中,找到didFinishLaunchingWithOptions(:)并使用以下代码对其进行更新。 窗口= UIWindow(框架:UIScreen.mainScreen()。bounds) window?.rootViewController = UINavigationController(rootViewController:ViewController()) 窗口?.makeKeyAndVisible() 返回真 我们正在使用屏幕边界初始化window属性,并设置其rootViewController。 通过将ViewController放置在导航控制器中,我们可以免费获得导航栏。 此外,makeKeyAndVisible被调用,Apple提供了一个很好的解释: 这是一种方便的方法,可以显示当前窗口并将其放置在所有其他相同或更低级别的窗口之前。 使用NSLayoutAnchor的视图 让我们继续使用快速的hello world标签进行测试。 在ViewController.swift中,我们将更新viewDidLoad(:)以在红色背景上显示标签。 我们将首先将视图的背景色更新为红色。 这显示了不使用Interface Builder来更新视图属性是多么容易。 view.backgroundColor = UIColor.redColor() 接下来,我们将创建一个带有文本Hello World的标签,其中文本颜色为白色。 让标签= UILabel() label.text =“世界你好” label.textColor = UIColor.whiteColor() 容易吧? 有趣的部分是当我们需要以编程方式应用约束时! 要通过代码创建类似于Storyboard的约束,我们可以使用NSLayoutConstraints。 但是,NSLayoutConstraint可能太冗长,因此可能会使您有点眼花hard乱。 Apple在iOS9中推出了名为NSLayoutAnchor的工厂类来帮助我们。 绝对值得一看! view.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false label.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true label.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor).active = […]

MVVM->避免“紧急汤”

设置 在过去的几年中与MVC和MVP在可可粉接触领域合作之后,我认为现在应该退后一步,考虑MVVM方法。 最近,我在Ben DiFrancesco上观看了一次演讲,他在会议上讨论了如何以及为何在项目中采用MVVM。 Ben解释了如何在您的ViewControllers中添加目标/动作,委派,通知,KVO和块(Swift中的闭包)实际上只是创建了这种“命令性汤”,在此情况下,您需要为业务逻辑和其他代码做出复杂的推理。 此外,由于您与特定于平台的框架紧密耦合,因此将代码测试和定位到其他平台变得更加困难。 从经验上来讲,当您想开始向应用程序添加扩展时,这绝对成为问题。 确保您的所有业务逻辑都适用于Today,Watch和其他扩展, 并且如果不小心处理实现,您的主应用程序将是一场噩梦。 回顾MVC 对于iOS中的MVC,控制器具有共同的职责; 表示逻辑与业务逻辑混合在一起。 这创造了Ben谈论的当务之急:“最终结果是使代码难以理解,难以测试并且[通常]丑陋的代码。” 让我们看一下MVVM如何尝试解决此问题。 MVVM概述 使用MVVM,我们引入了一个称为ViewModel的新对象,该对象封装了表示逻辑。 ViewModel使用一个模型或一组模型,并创建已预先格式化以在视图上呈现的属性。 Ben给出的示例是格式化字符串,确定子视图的颜色,设置显示/隐藏布尔值或确定表视图中的行数。 使用这种模式,ViewController的工作变得简单得多,因为它只是将ViewModel属性连接到视图属性。 示例应用 本着学习新事物的精神,我们将通过制作示例应用程序来测试MVVM技能。 想象一下,您刚刚被一家摄影公司聘用为新职位,他们委托您制作一个应用程序来展示公司的代理商目录及其投资组合。 他们决定使用Portfolious这个名字,是因为它在时髦/时髦的焦点小组中表现很好。 无论如何,在Portfolious中,您将拥有一个座席列表,其中包含与他们有关的数据以及他们的工作组合。 首先,您将使用此JSON占位符数据的子集和最近启用的最新网络库。 您可以在Github上签出完整的项目。 应用布局 使用Sketch,我们将创建一个视图来展示Portfolious的主题。 我们将有一个座席的表格视图,其中每个单元格将具有一些基本信息,例如其名称。 进入代理后,您将获得扩展的详细信息集(由用户模型提供)。 在此下方,我们将看到其相册的表格视图,其中每个相册将呈现该相册中照片的集合视图。 资料模型 对于我们的数据源,我们将使用三个主要模型:用户,相册和照片。 每个用户都是该目录中的一名员工,当您进入他们的个人资料时,我们会在其中添加他们最喜欢的照片的相册。 用户的定义如下: { “ id”:1 “ name”:“ Leanne Graham”, “用户名”:“布雷”, “电子邮件”:“ Sincere@april.biz”, “地址”: { “街道”:“库拉斯之光”, “ suite”:“ Apt。556”, “ city”:“ Gwenborough”, “邮政编码”:“ […]

开始进行Swift编程,第7部分-初始化和反初始化,覆盖和引用计数

在上一篇文章中,我们讨论了结构,类,属性和方法。 开始进行Swift编程第6部分-结构,类,属性和方法 在上一篇文章中,我们介绍了函数,枚举和范围。 medium.com 它帮助我们弄清楚如何创建对象以及将类似的属性和方法组合在一起。 本系列的内容不会教您Apple提供的更具体的类,例如UIButton或更实际的URLSession。 它会教给您足够的知识,因此当您在自己的程序中看到这些类时,您将对如何开始使用它们有所了解。 因此,让我们深入研究这一课。 从最基本的意义上讲,类和结构的初始化是为类和结构提供值。 有时,我们希望类或结构在创建时具有默认值,而其他时候,我们想告诉类或结构其默认值是什么。 初始化Class和初始化Struct之间的区别是:Swift中的Struct有自己的默认初始化器 ,而Classes没有。 这是什么意思? 这意味着当我们创建结构时,我们不需要在Struct中包含init()方法,它会自动为您创建。 仅当创建类时未实例化该类的属性时,类才必须具有init()方法。 让我们看看我在说什么。 在myFullyInitializedClass我们可以使用 var myFirstClass = myFullyInitializedClass() 。 如果要使用myFirstClass.myFunction()调用函数,则它将返回整数1因为我们为该类设置了初始值。 在myNonInitializedClass ,我们需要传入给定的givenNumber来创建它,以便初始化该类的所有属性。 在这种情况下,我们只有一个属性,但是如果有更多属性,则必须传递所有默认值。 只需将init()方法想像为目前没有func关键字的函数即可。 其唯一目的是为类中的属性分配值。 当我们调用方法myFunction ,它将返回值2 。 在myStruct示例中,我们没有初始化程序,因为在后台为我们创建了默认初始化程序。 创建新结构时,我们使用var myThirdStruct = myStruct(firstNumber: 3) 。 不,我们没有创建3个结构,但我以这种方式命名,因此您可以看到类和结构的总体顺序。 我们可以调用myThirdStruct.myFunction ,该方法将返回3 。 如果我们要创建一个myStruct的新实例,而不传递第一个数字的默认值,则会收到错误消息。 因此,对于结构,您必须设置默认值或在调用它时传递一个默认值。 可以在类和结构中使用Optionals以满足初始化程序的要求。 假设您创建的类并不总是需要其所有属性。 我们可以将不需要的属性设置为立即可用。 通过使用可选值,我们不必包括初始化程序,但是,如进一步所示,我们需要强制展开可选值,以删除设置了我们值的Optional()包装器。 我知道我告诉过您不要使用! ,强制解包,操作员。 但是如果没有更多工具可供使用,那么现在就必须这样做。 不用担心那些新工具即将推出。 如果您确实解开了nil可选项,则程序将崩溃,并且Found nil while […]

类型擦除— Apagando tipos!?

向前,向后,向后,向前,向后,向后推荐方案的协议: https://www.raywenderlich.com/148448/introducing-protocol-oriented-programming https://developer.apple.com/videos/play/wwdc2015/408/ Mas por queiríamosquerer“ apagar” um tipo? 您可以在法律上迅速获得Swiftéuma linguagem fortemente tipada的权利 。 可以通过entãoiríamosquerer“ apagar” um tipo吗? 参赞者,vamos primeiro参评者,que queremos solucionar com essaestratégia。 Swift和jáse aventurou pelas suas的通用协议具有 maisavançadas,dave ter tentado usar与“ famosos” 相关类型 (tipos associados)。 注意 :在Swift 2.2中引入了相关类型,而在“ typealias”时代之前,它已被使用 Em resumo,um 关联类型 ,通用协议的“ nada maisédo que ”,“ propusade”的服务对象,parâmetro, “ retorno demétodos”等的服务。Imagine-o como uma caixa […]

Swift中的保护套

您最可能听说过if语句,可以将switch情况视为if的更高级形式。 要启动switch语句,请告诉Swift您要使用哪个变量运行事物,然后提供可能情况的列表。 Swift将首先找到与您的代码匹配的大小写 ,然后执行它,然后退出开关 。 这是一个简单的例子: 即使您认为自己的案件将始终执行,也需要使用默认值:重新使用。 多种情况 让我们添加更多案例并利用更多类型的条件。 我们有一个像上次一样的数字,尽管这次我们将检查每种情况下的数字范围 。 像这样: 要检查范围,您只需使用三个句点,如下所示: 1…100 自从第一个以来,没有任何改变。 我们只是添加了更多案例,并检查了一系列数字,以证明您在案例中可以做什么。 差不多了!

Swift —动态UILabel文本

在进行多个API调用并从API响应解析文本的项目中,我遇到了我收到的文本量无法预测的问题。 有些文本很容易以2–3行适合,而其他文本则需要6–7行或更多才能正确适合。 我一直使用换行符 (自动换行)调整文本标签,并更改行数以解决从API收到的文本行。 我很快就感到自己不是很聪明,这是一种更好的方法。 当然,像往常一样,您的代码应该是动态的,它应该能够适应传入的数据。 此处适用相同的规则,我的文本标签应适用于单行或多行。 解决方案:让我们建立一个简单的项目进行练习。 制作一个“单视图”应用程序,然后在情节提要中添加一个UILabel和一个UIButton。 如下图所示,为UILabel定义约束: 如下图所示设置标签属性: 将约束添加到UIButton。 确保UILabel和UIButton之间的垂直间距为100 现在将UILabel的尾随约束的优先级设置为749 现在,将UILabel的“水平内容拥抱”和“水平内容压缩”属性设置为750和748 下面是我的控制器类。 您必须将UILabel属性和Button操作从情节提要板连接到viewcontroller类。 导入UIKit 类ViewController:UIViewController { @IBOutlet弱var textLabel:UILabel! var count = 0 let items = [“杰克逊不再是这个世界”,“强尼·强尼是爸爸吃糖而不是爸爸”,“ Ab”,“尽管采取了所有措施来扭转自然”] @IBAction func updateLabelText(sender:UIButton){ 如果计数> 3 { 计数= 0 } textLabel.text = items [count] 计数=计数+ 1 } 覆盖func viewDidLoad(){ super.viewDidLoad() //加载视图后进行其他任何设置,通常是从笔尖进行。 //self.textLabel.sizeToFit() //self.textLabel.preferredMaxLayoutWidth = 500 […]

TableView / CollectionView单元格的索引

获取选定单元格的索引是一件容易的事,但是我已经看到很多实现都使用非常奇怪的方法来获取选择的实现,特别是在单元格具有许多按钮/动作来获取其索引的情况下。 让我们回到基础,如何获取选定单元格的索引? 通过简单地实现tableview / collection视图委托 func collectionView(_ collectionView:UICollectionView,didSelectItemAt indexPath:IndexPath){}或:func tableView(_ tableView:UITableView,didSelectRowAt indexPath:IndexPath){} 这些是从用户那里进行选择的基本方法,但是如果我在单元格中只有一个按钮该怎么办? 我认为不必担心按钮,使其对触摸没有反应并让上述选择代表为您处理该按钮是不值得的! 但是,如果我想要该特定按钮怎么办? 如果我有多个按钮可以触发业务逻辑中的多个操作? 这就是处理视图中的触摸并将通知它的两种方法的地方:委托和闭包! 我自己发现,闭包是将视图连接到其父级的一种非常不好的方式,而且开发人员往往会忘记使用弱的或未使用的方式,以阻止两个类相互引用,从而容易导致内存泄漏。 因此,我相信代理人提供了更方便,更清晰的方式来轻松显示交互,更易于阅读,修复甚至通过您的应用进行通用。 要使用委托,人们会将indexPath作为变量发送到单元格,因此它知道它在其控制器内的位置,这是一个后果,因为现在视图知道的内容比其应了解的更多。 通过一个简单的函数调用就可以很容易地从管理它的集合/表视图中获取该信息: tableView.indexPath(for:UITableViewCell) 因此,我们为此目的编写一个协议:通过用户交互通知控制器。 协议TableViewCellDelegate:类{func didSelect(_ cell:UITableViewCell,_ button:UIButton)} 集合怎么样? 协议CollectionViewCellDelegate:类{func didSelect(_ cell:UICollectionViewCell,_ button:UIButton)} 这个功能是您在不同单元格中所需的全部功能,现在它返回对单元格的引用以及在其中单击的按钮! 我们添加了类,因此可以在单元格中将其削弱: 弱var委托:TableViewCellDelegate? 将其添加到您的按钮操作中: @IBAction buttonTapped(_ sender:UIButton){委托?.didSelect(自己,sender) } 就是这样,现在使单元格委托引用您的控制器,并由您的控制器进行确认,现在您已经拥有所有选项卡并与表/集合单元格进行了交互! 扩展UIViewController:TableViewCellDelegate {func didSelect(_ cell:UITableViewCell,_ button:UIButton){保护let index = tableView.indexPath(for:cell)else {return} let tag = button.tag}} 在这里,我们确认它的viewController,获取索引,并获取按钮的标签以知道单击了哪个按钮,标签可以轻松地设置为0、1、2,具体取决于您单元格中有多少个按钮/动作。 […]

使用TypeAlias在Swift中编写与平台无关的代码

众所周知的事实是,与MacOS开发相比,iOS开发有更多的资源,如果您正在使用或计划将Swift用于开发,则查找资源会更加困难。 最近,我偶然发现了swift-2048。 我更新了代码以支持Swift 4.2,并发送了请求请求。 后来我认为使用代码使该应用程序与MacOS兼容将是很棒的。 因此,我添加了一个新的Mac目标并开始进行工作。 这是不使用typealias的文件中的代码。 在此代码中,您可以看到代码是不能重用的,并且该代码在字面上重复了两次,并且由于存在平台编译时检查的API的不同,在一些细微差别上几乎相同。 MacOS中没有UILabel类,我们改用NSTextField并将其isEditable属性设置为false,以便无法对其进行编辑。 我们将文本设置为NSTextField的方式也不同。 它没有text属性,而是具有stringValue属性,也没有minimumScaleFactor属性。 我们将背景颜色设置为视图和NSView的方式也不同。 我们可以直接将背景色设置为UIView,但是我们必须将背景色设置为cgColor层 两种平台之间还有一个细微的区别,那就是NSView可以有或不能有一层,而UIView总是有一层支持它。 因此,layer属性的类型对于NSView是可选的,而对于UIView不是可选的。 显然,这不是任何开发人员都会喜欢的代码。 避免代码重复的一种可能解决方案是使用类型别名 ,并在整个项目中的此处和其他类中避免重复。 下面给出的是避免重复的重构代码。 重构的代码量更大,但是可以避免您在整个Project中一遍又一遍地编写相同的代码。 您可以在Twitter,Linkedin上与我联系,并在StackOverflow和Github上查看我的开源工作。