Tag: iOS应用开发

介绍AppFolder

每个iOS应用程序都有一个关联的容器,作为开发人员,您可以在其中基本上存储所需的任何内容。 这通常称为“沙盒”。 在此沙箱中,您可以放置​​用于不同目的的文件-它可以是用户可见的文档,数据库文件,缓存或某种元数据-任何东西。 基本上,iOS上的所有持久性技术都使用应用程序的容器在其中存储信息。 因此,了解应用程序文件夹的外观,结构以及放置在其中的文件对于每个iOS开发人员都是至关重要的。 但是,这里存在问题: 不幸的是,对于每个iOS应用程序都至关重要的概念,Apple并未对其API进行过多考虑 因此,例如,如果您需要获取应用程序的“ Documents”文件夹URL,则需要编写以下代码: let urls = FileManager.default.urls(for:.documentDirectory,in:.userDomainMask) 让documentsURL = urls [0] 如果您确切知道该代码在做什么,那可能看起来还不错。 但是对于不习惯此API的人来说,它看起来也很恐怖。 因为当您尝试使用自动完成功能来发现您的选项时,会得到以下信息: 在这种情况下,有人会怀疑“这里到底发生了什么?”。 .adminApplicationDirectory ? .applicationScriptsDirectory ? .moviesDirectory , .trashDirectory吗? 有很多东西,其中大多数对于iOS应用程序绝对没有任何意义 。 然后是搜索路径域掩码: …嗯, 是的,我确切知道该选择哪一个。 这个API对于macOS可以说是合理的,但是在iOS上,这显然是令人误解的: cachesDirectory放置在musicDirectory和desktopDirectory (显然,这不仅对每个设备而言都是唯一的,而且对于iOS而言也是荒谬的)。 由于某种原因,“ Documents / ”目录表示为.documentDirectory (单数),这可能使您质疑是否选择了正确的文件夹。 它返回一个URL 数组 (可以有多个URL吗?可以没有一个吗?谁知道。) 最后,使用此API,您几乎不了解文件夹在磁盘上的实际结构。 尚不清楚此巨型列表中的哪个文件夹甚至存在,哪些不存在。 我们可以做得更好 好吧,想象一下我们是否可以交易上面的代码 let urls = FileManager.default.urls(for:.documentDirectory,in:.userDomainMask) 让documentsURL = urls […]

Raspberry Pi Remote-使用Flask,Swift和GoPiGo3

确保您添加了Alamofire容器,这就是我们将用来向烧瓶服务器发出GET请求的容器。 返回您的终端,并确保您仍在正确的目录中,然后致电: 吊舱安装 现在应该安装Alamofire了,我们可以发出GET请求了。 确保您现在正在打开工作区文件。 设计UI 本节将简短,因为您应该自行设计UI,但是,您要确保我们用python编写的每个命令都有5个按钮。 前进,后退,左,右,停止。 打开助手编辑器,然后按住Ctrl并将每个按钮拖到ViewController.swift中。 确保将连接从IBOutlet切换到IBAction。 您现在应该在ViewController.swift文件中具有以下5个连接: 如果按钮已连接到main.storyboard,则应填充每个IBAction旁边的圆圈。 现在我们要导入Alamofire。 在导入UIKit上方,输入: 进口Alamofire 发出GET请求 最后一步,我们需要根据要运行Pi的功能向每个动作添加Alamofire请求。 在每个IBAction下写: Alamofire.request(“ http:// IPADDRESS:PORT / ROUTE”).responseString {(已打印)在 让结果=打印。描述 打印(结果) } 重要: IPADDRESS =您的Rasberry Pi的IP地址,可以通过在Pi的命令行中输入以下地址来找到: 须藤ifconfig PORT =您在Python文件中选择的任意端口EX:5000 ROUTE =烧瓶服务器将使用EX的Python函数路由:“ / forward” 运行遥控器 现在我们完成了,请继续使用Raspberry Pi并启动flask服务器: cd桌面 cd sudo python pythonRemote.py 然后将您的iOS应用构建到iOS设备或模拟器上,然后单击按钮以运行您的功能! 您应该在Xcode调试器和Raspi终端中看到响应。 如果您跟随GoPiGo功能一起使用,那么您现在应该拥有一辆遥控车! 这可以用于远程运行用flask和Python为pi编写的任何函数。 请在下面分享您的项目! 在我的github上查看我的代码。

在Swift中使用NSNotificationCenter

NSNotificationCenter可以被视为在您的应用程序中传达信息的工具。 与推送通知或本地通知不同,在这些通知中,您会通知用户您希望他们接收的任何内容,NSNotificationCenter允许我们根据应用程序中发生的操作在类和/或结构之间发送和接收信息。 简而言之,可以将NSNotificationCenter视为广播公司,我们可以收听不同的电台或频道以收听任何更改。 NotificationCenter.default是所有通知发布和观察对象的位置。 每个通知都必须具有一种独特的方式来标识自己,如果继续进行类比,则该方式将代表我们要进入的频道。 同样,如果我们要观察或收听任何频道,则可以通过NotificationCenter.default调用对我们可用的观察方法,并基于此侦听执行某种类型的操作。 我创建了一个简单的应用程序,该应用程序演示了NSNotifcationCenter的用法,以便我们可以更好地理解代码中的形式以及它的实际工作方式。 如果您像我一样,并且是动手学习者,请随时进行编码。 在此应用程序中,我嵌入了导航控制器,并连接了所需的所有IBOutlet和IBAction。 该应用程序的目标是显示从其他视图控制器中选择的目的地的名称。 首先,我们将创建在NotificationCenter在给定通道中检测到更改时将执行的操作。 在我们的案例中,我们正在创建两个函数,这些函数将更改ChoiceDestinationVC中的城市标签。 func setToPeru(notification:NSNotification){ cityChosenLabel.text =“秘鲁” } func setToArgentina(notfication:NSNotification){ cityChosenLabel.text =“阿根廷” } 每个函数都会将cityChosenLabel设置cityChosenLabel相应的文本。 我们将不会对这些功能做任何事情,但是很快,当我们开始在应用程序中进行观察时,我们将对其进行调用。 还记得我提到每个通知应具有唯一身份吗? 好了,我在Notification.Name上创建了一个扩展,并在每个通道的名称上添加了两个静态属性。 通常,您可以手动键入包含您要在调用observe或post方法时用于通知的名称的字符串,但这可以帮助我们避免错误,并减少因拼写错误而导致错误的空间。 扩展Notification.Name { 静态让秘鲁= Notification.Name(“秘鲁”) 静态让阿根廷= Notification.Name(“阿根廷”) } 之后,我们将在ViewDidLoad中添加观察方法,这些方法将侦听其指定的通道并根据每个通道执行操作。 NotificationCenter.default.addObserver(自身,选择器:#selector(setToPeru(notification :)),名称:.peru,对象:无) NotificationCenter.default.addObserver(自身,选择器:#selector(setToArgentina(notfication :)),名称:.argentina,对象:nil) 我们的第一个观察者方法将执行我们上面创建的功能setToPeru(notification:) ,如果通知已发布到.peru通道,我们将在其中更改标签的文本。 然后将相同的内容应用于侦听并将标签文本更改为阿根廷的setToArgentina(notification:) 。 从这里开始,我们进入下一个视图控制器DestinationVC。 当有人单击任一按钮时,我们将在此处发布通知。 @IBAction func peruButton(_ sender:Any){ NotificationCenter.default.post(名称:.peru,对象:无) } @IBAction func argentinaButton(_ sender:Any){ […]

Pod自动更新脚本

为什么要开发此脚本 当我们在iOS领域中开发一些Pod组件时,我们必须在终端上键入那么多git和pod命令。 如果Pod项目很大,并且运行pod lib lint和pod repo push将花费大量时间,则还必须更新.podspec文件和push标签中的pod版本。 这是一个非常无聊且机械化的过程。 该脚本将使您摆脱此过程。 该脚本包含哪些操作 1.在.podspec文件中制作小版本加一个,例如,将s.version = “0.1.1”更改为s.version = “0.1.2”或将s.version = “1.2.15”更改为s.version = “1.2.16”或s.version = “10.22.0.15”到s.version = “10.22.0.16” ,无论您的版本是什么样,它都会更新版本号的最后一位。 2.运行pod lib lint 。 如果您的Pod项目依赖于其他私有资源,则可以在脚本顶部对其进行配置。 在Github和GitLab上运行良好。 至于BitBucket,您可以尝试一下。 如果您发现它不起作用,请让我知道。 3.运行一系列git操作,例如git add,git commit,git push,git tag,git push-标签。 4.运行pod repo push 使用情况 1.将auto.py添加到您的pod项目中,并确保它与.podspec文件位于同一目录中。 如果您认为有必要,可以将此python脚本文件添加到.gitignore 。 2.打开auto.py文件,并在顶部对其进行配置。 像这样的截图 您可以在sources数组中添加从属源,但是不需要添加https://github.com/CocoaPods/Specs.git 。 3.打开终端,导航到poedspec和此脚本文件所在的目录。 4.在终端上运行python auto.py命令。 它会自动更新您的Pod项目版本并将其自动推送到原始位置。 如果失败,则必须检查并确保您的podspec配置正确。 下载 […]

OpenCalc — React Native —深入研究(第2部分)

这是OpenCalc的2部分系列的第2部分,OpenCalc是使用react-native,javascript和flow构建的开源移动计算器。 第一部分处理设计和UI组件,而上一篇文章则介绍了如何在应用市场中编写该应用程序。 第二部分将处理计算和验证。 OpenCalc在iOS和Android上可用。 主控制器具有一个称为Brain的属性,它是CalculatorBrain的一个实例。 控制器调用以下大脑功能: brain.clear()//清除大脑队列 brain.setItem(button)//将一个项目添加到队列 brain.deleteLast()//删除队列中的最后一项 brain.getDisplay()//返回队列的文本显示 brain.getResult()//返回评估队列的结果 大脑的主要目的是处理一系列操作。 操作在操作文件中定义。 运作方式 Operations.js提供了许多与定义,存储和使用Operations相关的功能。 Operations文件的主要目的之一是定义Operation类。 操作课 Operation构造函数如下: 构造函数 stringVal:字符串, operationType:数字, operationSubType:数字, val:任何, 优先级:?数字, operationArgs:?Set ) stringVal只是显示中的字符串表示形式。 operationType和operationSubType仅包含一个值,以帮助验证器确定操作是否合法以及如何处理每个操作。 类型和子类型只是枚举值。 val用于存储与运算符相关的功能。 优先级是操作(例如PEMDAS)的优先级。 例如,+和*的优先级分别为2和4。 因此,当计算器计算1 + 2 * 3时,它会优先执行*,因为它具有较高的优先级。 最后,operationArgs只是一组存储特殊情况的枚举。 例如,pi是一个数字,但应将其打印为字符串而不是数字表示形式。 将所有可用估值存储在计算器中 操作是计算器可用的各种操作的字典。 在此屏幕上添加新操作或更改操作方式很容易。 操作示例: ‘+’:操作( stringVal =’+’, operationType = OperationType.Operation, operationSubType = OperationSubType.BinaryOp, val = function(x,y){return […]

Swift中的依赖注入— iOS

在Twitter上关注我: @ kiranjasvanee 依赖项注入对于一个简单的概念来说是个大词,该概念是允许对象接收其所需的依赖项。 让我们先用一个不好的例子来说明这一点,然后再使用依赖注入来查看使用它可以获得的所有好处,改进和安全性。 假设您正在构建一个用于创建专辑并在其中添加歌曲的应用程序。 首先创建相册模型。 类相册{ private var albumName:字符串! func getAlbumName()->字符串{ 返回专辑名称 } } 让我们尝试在您的ViewController之一中获取albumName 类ViewController:UIViewController { 覆盖func viewDidLoad(){ super.viewDidLoad() 让albumInstance = Album() print(“相册名称:\(albumInstance.getAlbumName())”) } } 现在,您在这里崩溃了您的应用程序。 您正在尝试使用getAlbumName()来获取albumName ,但albumName设置albumName 。 在这里, albumName是您必须注入的依赖项,当然,没有专辑名称时,您将如何发行或添加歌曲。 让我们通过注入依赖关系来解决此问题。 类相册{ private var albumName:字符串! init(albumName:String){ self.albumName = albumName } func getAlbumName()->字符串{ 返回专辑名称 } } 现在,使用我们的新init函数设置albumName的值。 let albumInstance = Album(albumName:“信誉”) print(“相册名称:\(albumInstance.getAlbumName())”) […]

Swift 3中的分段控制教程

在本教程中,学习如何为iOS 10创建分段控件 。 分段控件允许用户在每次按下按钮时更改其应用程序中的内容。 在本教程中,我们将创建一个基本的分段控件,以在每次按下按钮时更改标签的文本。 让我们开始吧 首先,打开Xcode并单击Create a new Xcode project 。 然后,在iOS标签下选择“ 单一视图应用程序 ”。 单击下一步 。 然后,在“ 产品名称”字段中,输入SegmentedControl 。 在“ 组织名称”和“ 组织标识符”字段中,键入所需的任何名称。 确保在“ 语言 ”下选择“ Swift” ,在“ 设备”中选择“ iPhone” 。 保留Use CoreData并取消选中两个测试。 然后,单击“ 下一步”并将其保存到所需的位置。 保存文件后,在Project Navigator上转到Main.storyboard文件。 然后在对象库中搜索分段控件 ,并将其拖动到视图控制器的顶部。 接下来,在对象库中,拖动标签并将其放置在新的分段控件的正下方。 选择您的标签,然后单击右上角名为“ 显示属性检查器”的第四个图标。 命名您的Label One ,这将是分段控件第一个按钮的起始值。 您可以将字体增加到24,以便更好地显示标签 。 在“ 对齐”区域中单击“ 居中 ”。 添加约束 选择您的分段控件,然后在右下方的“ 自动布局约束”图标所在的位置,单击“ 添加新约束” […]

Swift World:设计模式-命令

从今天开始,我们将讨论专注于对象之间通信的行为模式。 它包括命令,中介,观察者,状态,策略等。 在本文中,我们将介绍命令模式。 就像在现实世界中一样,命令是从其调用者(即调用者)发送到接收者的请求。 通过隔离和封装请求,此模式将调用方和接收方分开,如下图所示。 从命令模式— Wikipedia 那它给我们带来什么好处呢? 让我们从车上的故事开始吧。 protocol Car { func move () } class Sedan : Car { func move () { print (“Sedan is moving.”) } } class SUV : Car { func move () { print (“SUV is moving.”) } } 现在,您作为iOS应用开发者,拥有一辆轿车并每天开车。 class Developer { let sedan = Sedan () […]

我应该跨平台使用我的第一个版本吗?

这是移动软件开发领域中最受欢迎的问题之一。 而且您在任何地方都找不到任何明确的答案 。 但是,让我刺一下它。 如果您已阅读有关此问题的其他文章,请确保首先考虑作者是谁。 作者是开发商还是开发商的附属公司? 如果是这样,他们是创建本机应用程序还是创建混合应用程序? 您很可能会开始注意到他们每个人都在讲自己的技能。 意味着本机开发人员会告诉您本机更好,而混合开发人员会告诉您混合本就更好。 那我呢 好吧,我是一名本地开发人员。 因此,我从事本机iPhone项目,而不是混合项目。 现在您知道我的忠诚了。 但这不能回答您的问题。 因此,要回答您的问题,需要考虑一些事项。 您真的需要使用ANDROID和IOS吗? 人们真的对此挂了电话。 您的用户在哪里? 您在两个平台上都有用户吗? 收入驱动哪个平台的用户? 认真思考,这将直接影响您的项目成本 。 您真的需要同时使用ANDROID和IOS吗? 同时开发两个应用程序(无论是混合应用程序还是本机应用程序)比创建一个应用程序要付出更大的努力 。 您的测试工作将加倍。 您的营销工作将会更大。 您的团队将需要更大。 一种简化的方法是先为一个平台创建一个版本 (即使采用混​​合路线), 然后根据收到的反馈在您的应用上进行迭代, 然后再发布第二个版本 。 如果您要使用本机,则可以节省开发和测试成本,因为您不会编写最终在初始迭代中终止的功能。 如果您要使用混合功能,则可以节省测试时间,因为您不必测试被淘汰的功能,并且可以减少的错误修复。 您的工作量也将减少一些,因为您不会同时做两件事。 最后一个好处,因为您将有两个版本,所以您只是获得了第二个版本而引起了一些轰动:-) 您是否要寻找适合自己的产品市场? 然后在单一平台上倾向于本机 。 当您疯狂地想出自己的市场时,这将使事情变得简单。 您是否需要完善的用户体验? 个人观点,我知道有些开发人员不同意,但是如果您需要高度修饰的UI并想使用OS的最新功能,请倾向于native 。 绑扎现金了吗? 我知道这不是很性感,但是如果您被现金束缚,那么短期内使用单个平台将会更便宜(甚至比混合平台还便宜)。 之后,一旦您证明了自己的市场,就可以筹集一些现金,否则收入将开始增加,您可以进行重新评估。 开发人员知道什么? 也许最重要的是,您必须考虑您的团队。 他们习惯创建什么样的应用程序。 学习新技术将需要时间和精力。 因此,您可能会在那里找到答案。 请记住,找到知道要使用混合技术的开发人员也将更加困难。 因此,请考虑您必须投入的招聘工作。 因此,像往常一样,没有简单的答案。 […]

Swift 4中的重大更改

在这个博客中,我想深入了解Swift 4中将引入的代码破坏更改的数量。此外,我还将演示如何在当前的 Xcode 8.3.2中使用Swift 4。 重大变化 如果我们总结所有已实施的Swift 4提案,我们(截至31–5–17)将列出以下清单。 用粗体突出显示的建议是在Swift 4中引入源代码更改的建议。让我们更深入地研究每个建议。 区分单元组和多参数函数类型-( SE-0110) 有了这个建议,您现在必须从现在的单个参数手动扩展元组。 让我们用一个例子来解释。 typealias名称=(名字:字符串,姓:字符串) 让名字:[名称] = [(“ Bart”,“ den Hollander”)] 我已经在数组中声明了一个元组。 现在,我想遍历数组中的每个元组并打印姓氏。 让我们在Swift 3中执行此操作。 // Swift 3 names.forEach({首先,最后一个 print(last) //“ den Hollander” }) Swift 3编译器从元组扩展了“ first”和“ last”变量。 这是非常有用和可读的。 现在让我们在Swift 4中做同样的事情。 // Swift 4 names.forEach({首先,最后一个 打印(最后) }) //错误:闭包元组参数’(firstName:String,lastName:String)’不支持解构 这不再起作用的原因是,在Swift 4中,您必须从单个参数手动扩展元组。 您可以执行以下操作来解决此问题。 // Swift 4 A:通过提供元组键进行扩展 […]