Tag: swift

为您的应用找到合适的获利模型

在本文中,我们将介绍四种最流行的移动应用货币化模型。 支付一次: 现在,让我们首先讨论使用应用程序赚钱的最明显方法。 在上面贴上价格标签。 并非每个应用程序都适用于此概念,因为面对它,您会发现与花费免费的应用程序相比,下载该应用程序的下载量要少得多。 因此,我的建议是,真正考虑您作为应用程序开发人员的目标是什么,您是否只想使用此应用程序并继续进行改进? 还是举例来说,您是游戏开发商,并且一年四季都在开发大量游戏? 有时,像我这样的开发人员会以自我宣传的形式免费提供一些应用程序。 您想获得自己的名字或公司的名称,并且很有可能,如果您提供用户喜欢的出色应用,他们将签出您的其他应用,甚至可能下载它们。 所有这些都是理论上的,但是仍然是开发人员中非常普遍的做法。 但是,如果您不是这种情况,那么您应该问自己,您提供的应用程序确实是人们愿意支付的东西吗? 您愿意为此付费吗? 询问您的朋友,如果可能,请询问适合您应用的目标人群的人。 如果大多数人都同意您的应用程序值得一买,那么您绝对应该这样做。 但是不要期望太大,如果您只是开始开发和发布自己的应用程序,除非您的应用程序是每个人都在等待的令人难以置信的东西,否则您下载的内容不会像您期望的那样多。 您必须考虑一种营销策略,这对于不免费的应用程序来说更为重要,因为与免费下载的应用程序相比,只有一小部分人会购买它。 免费增值 让我们谈谈免费增值模式。 这是一种在游戏中非常流行的货币化方式。 免费增值游戏的基本前提是可以免费玩标准游戏,但是游戏的不同方面仅适用于愿意付费的用户。 这可以像为角色创建新皮肤或使您更擅长游戏的某些物品一样简单。 基本上有两种不同的免费增值模式,一种更直接,另一种更微妙。 在第一个游戏中,除非用户付费,否则用户无法解锁游戏的某些方面。 从更细微的角度来看,用户可以通过玩游戏从技术上获得所需的物品或进行升级。 但是有一个陷阱,用户需要花费多长时间才能访问该项目与该项目的实际价值无关。 因此,假设您有一件商品,花费用户约100个游戏币,而用户一天可以赚取的最大游戏币约为50个币,那么该用户必须玩两天直接获得物品。 因此,这背后的想法通常是诱使用户购买它,因为这在现实生活中只会花费他一美元,并使他能够更快地进入游戏。 订阅服务 订阅服务非常棘手,因为您必须设置一个特定的时间范围以确保可以履行协议的一部分,这意味着,如果您承诺在此过程中进行更新或提供任何其他内容,则必须交付所述内容。 否则,您在客户注册时答应的承诺与他们实际获得的承诺之间会有差异,这将使您承担责任,并且在技术上允许用户要求退款。 对于某些应用程序,订阅服务确实很有意义,请不要误解我。 如果您不断向应用程序中添加新内容,并提供更多的超时价值,那么订阅货币化模型就很有意义。 但是,如果您还记得Whatsapp的订阅业务模型,则必须支付约1美元才能使用该服务一年。 但是他们在介绍奖金后不久便将其关闭,并免费提供给所有人。 这个例子只是表明,即使像Facebook这样的大型公司,或更确切地说是WhatsApp,也不是完美的,它应该使您充满信心,即使您决定采用一种货币化模型,也不必一成不变。 原生广告 原生广告是我们这一代的标语广告,与标语不同,它们更加集成在应用程序流程中,不会像弹出标语广告那样困扰用户。 原生广告可能是很多事情,例如新闻源中的赞助故事。 用户更有可能点击不太清晰可见的广告。 本地广告的其他示例是您在snapchat上看到的赞助故事或在instagram上看到的故事。 您必须记住,要使本机广告真正发挥作用并赚钱,它们必须与您的用户群匹配。 因此,假设您有一个旅行日志应用程序,您的用户群结构非常清晰,这非常好,因为对于广告客户而言,了解他们要购买哪种“广告空间”非常重要。 因此,从根本上讲,细分的客户越好,钱包越好。 因此,在决定采用货币化模型之前,请确保它适合您正在使用的应用程序类型,并且不要过分考虑,进行研究,研究竞争情况,然后顺其自然。 如果您还不是专业开发人员,但想成为一名开发人员,请确保您签出了我们有关Swift开发中iOS开发的Udemy课程,并在结帐时使用此链接或代码MEDIUM15可获得90%的折扣。

Swift中的委托模式

刚进入软件开发领域,我首先开始学习用Python编写代码,然后再学习Java。 两种语言都是进入面向对象编程世界的绝佳机会。 但是,直到我开始学习Swift时,我才遇到了委托模式。 许多人警告我,由于这是一个新主意,因此可能需要一些时间来学习和习惯。 我准备好自己,看了一些视频,并完成了一些教程,但是第一次遇到一个复杂的话题时,有时会遇到挫折和困惑。 我继续前进,并自信地将其从我要学习的新主题列表中删除。 我以为,如果我在项目中需要它,我已经获得了足够的知识,至少可以查找它并将其轻松集成到我的代码中。 当机会出现在实际项目中使用它时,我很快意识到我对自己的理解并没有我想象的那么好。 此外,我很难找到一种资源来列出所需的代码行以及它们如何在涉及的两个类之间组合在一起。 我再次“打书”(隐喻地,我完全使用了互联网。)并开始了一个过于简单的实践项目,该项目隔离了授权模式,以便在它起作用之前我可以一直使用它,并且我完全理解了概念和用法。 因此,我对所学内容进行了反思。 代表团 简单来说,委托允许两个类进行通信。 从非技术意义上讲,委派(动词)是“将任务或责任委托给另一个人”(《牛津词典》)。 在技​​术世界中,除了对象之外,它是完全相同的。 该项目 我做了一个练习项目,该项目跟踪按下按钮时增加的计数。 我在这篇文章的底部包括了完整的代码,以及指向项目所在的GitHub的链接。 在我解释每个步骤时,请随时跳过或继续进行。 在第一个视图控制器中,我有一个显示计数的标签和一个通过segue移至下一个视图控制器的按钮。 在第二个视图控制器中,我只有一个按钮来更新计数。 在第二个视图控制器中,我可以多次点击“更新计数”按钮。 它将当前计数打印到控制台。 完成后,我可以在顶部的导航控制器中进行回溯,并看到第一个视图控制器中的计数标签已更新。 以下是我在第二个视图控制器上单击“更新计数”五次并返回到第一个视图后的示例。 如果我在不关闭应用程序的情况下再次重复该过程,它将继续从我上次中断的地方开始更新计数,在这种情况下为5。 代码 设置委派模式需要使用几行代码。 这里将扮演三个更大的对象:定义需求的协议,符合协议的类(即委托)和访问属性或调用协议中概述的方法的委托类。 定义协议 对于此示例,需要在两个类之间传递的唯一操作是增加计数器。 协议本身就是对象。 关键字协议是必填项,后跟用户提供的名称以及方括号。 该名称的处理方式与类名或枚举相同,其中首字母大写。 通常,在委托模式中使用时,协议名称将包含单词“ Delegate”以阐明其用途。 在方括号内,我定义了所需的方法。 我使用关键字func来指定我需要一个方法,该方法之后是我为其分配的名称,并带有开括号和闭括号。 协议IncrementCountDelegate { func gainCount() } 如果我的函数要返回某些东西或有参数,我会这样表示: func myFunction(参数:ParameterType)-> ReturnType 在协议中,我可能还需要一个属性,但对于此示例,则不需要。 虽然我知道我的方法gainCount()最终可能会需要一个称为count的属性,但委托类不一定需要了解它,因此我没有在协议中包括它。 以后再说。 但是,如果确实需要包含一个属性,则该属性应如下所示: var myVariable:VariableType {获取设置} 设置关键字 […]

Mac App动画外卖

我正在开发需要完成一些动画的Mac App。 实际上,我对Mac App上的动画主题还很陌生。 例如,我的动画代码可以在iOS中使用,但是我想移植到Mac App。 这是动画的一些要点,动画沿x轴旋转图层。 应用3D变换 只是从iOS复制代码,我遇到的第一个问题是初始转换无法正常工作。 我想将初始状态设置为旋转45度,但是该层保持在朝前的位置。 最后,我意识到在Cocoa中,必须在应用转换之前将视图添加到视图层次结构中。 如果不添加为子视图,则不会渲染相应的视图。 因此,应用变换对其没有影响。 转换所有子视图 在寻找上一个问题的解决方案时,我认为这可能是默认情况下不支持CALayer的问题。 我什至以为可能无法将转换应用于相应视图的根层。 我最终知道,如果我为转换创建了另一个CALayer,并将该层插入到层层次结构中。 仅此层将被转换,所有子视图(如NSTextField)将保持不变。 另一个发现是,可以在将根视图添加到视图层次结构之前转换此层。 比较iOS动画API 在iOS中,可以使用“ UIView.animateWithDuration()” API进行动画处理。 该方法允许我设置持续时间,延迟,阻尼系数以及完成块。 但是,这个漂亮的API或类似的东西在Cocoa中不可用。 我最终使用“ CABasicAnimation”为旋转动画,然后使用“ CATransaction”应用完成块。 我可以选择使用委托方法来在动画完成时引起注意,但是我认为完成块使代码更清晰。 动画转换 如前所述,我使用CABasicAnimation对旋转进行动画处理。 它正在使用keyPath。 由于我要使图层沿x轴旋转,因此必须使用“ transform.rotation.x”。 该API非常简单,但是不够迅速。 keyPath的使用不是类型安全的。 自Swift 3起,此类API将会有巨大的改进。 Swift 3的API已变得稳定。 这将在Xcode 8公开发布中正式提供。 这是此职位的示例操场。 参考文献: 如何将适用于UIView的视图转换应用于NSView? 将NSImageView的CALayer旋转90度 CATransform3DRotate旋转360度 CATransform3D关键路径 XCPlayground基础🎪

Curso de iOS 10和Swift 3

¿Quéprender? Conocer和Sabre utilizar Xcode 8 Saber实用Swift 3 ,可用于Apple iOS 10程序 Conocer los nuevos框架desarrollo como消息,语音或Siri工具包 禁止在框架中单独注册,注册,注册,并授权的专业人士。 Utilizar Un control de versiones en formma en repositorio Github o Bitbucket Sabre文档和Expandir Conocimientos Con框架avanzados como核心数据,CloudKit,AVFoundation… 可解析的basadas en servidores remotos,Montando el tuyo propio con解析和Amazon Web Services 要求 Un Mac con Yosemite o steriorema pistivo instalado Descripción *在 iOS 10上的《 Udemy […]

在Swift中编写更好的单元测试:第一部分

问题 瞧,我们是这里的朋友,所以我觉得我很坦白:我在职业生涯中写了一些非常糟糕的单元测试。 20行怪物,具有多个模拟和断言以及异步期望。 您在书中看到的这类标题为“如何修复以前工作过的白痴留下的混乱”的书。我还必须在写完单元测试和不太那么说的代码后维护该代码。更好。 可以这么说,我现在将编写“好的”单元测试作为优先事项。 在开始之前,我将定义我认为是“良好”的单元测试。 如果我们可以同意一个单元测试(或者实际上是任何一个测试)是由一些设置 ,我们正在测试的动作以及关于该动作效果的断言组成的,那么我可以这么简单地说,一种“好的”单元测试可以使这三个组件中的每一个都清晰可见。 (此外:这可能与您对“好的”单元测试的定义有所不同,而这只是我们俩都必须忍受的。) 在一些博客文章中,我将向您展示我们在Clue所做的一些工作,以确保我们始终试图编写“良好”的单元测试。 在本文中,我们将看一个简单的技巧,我们可以使用它来最小化单元测试的设置部分,同时保持清晰度。 假设我们要在一个简单的Swift结构上对相等方法进行单元测试。 struct用户:Equatable { 命名:字符串 让电子邮件:字符串 让需求验证:布尔 静态函数==(lhs:用户,rhs:用户)-> Bool { 返回lhs.name == rhs.name && lhs.email == rhs.email && lhs.needsVerification == rhs.needsVerification } } 我们可以(无限)有许多不同的参数组合可以传递给此方法进行测试。 显然,我们无法对所有这些进行测试,因此我们必须选择一些代表总体趋势的案例。 对该方法进行单元测试的有效方法(实际上,我通常会使用测试驱动的开发方法编写这种方法)是从两个User的所有属性均相等的情况开始,然后测试每个属性不同时会发生什么。 这给了我们这样的测试套件: func test_equals_allPropertiesMatch_isTrue(){ let sut = User(名称:“”,电子邮件:“”,needsVerification:false) 让其他=用户(名称:“”,电子邮件:“”,需要验证:false) XCTAssertEqual(ut,其他) XCTAssertEqual(other,sut) } func test_equals_nameDiffers_isFalse(){ let sut = User(名称:“ Jo”,电子邮件:“”,需要验证:false) 让其他=用户(名称:“”,电子邮件:“”,需要验证:false) […]

iOS本地化正确! SwiftGen巴蒂·克鲁奇

本地化是一个广泛的话题,很多时候所要做的不仅仅是将单词翻译成预期的语言。 雷·温德利希(Ray Wenderlich)在他的博客上有很多与此相关的文章。 苹果公司已经就该主题制作了多个WWDC视频。 这是一个在网络上覆盖面很广的主题,那么另一篇文章的重点是什么? 我将与大家分享一些技巧和库,这些技巧和库可以在两个常见问题上为您提供很多帮助: 保持情节提要的.strings文件同步 使用枚举而不是使用NSLocalizedString宏处理本地化 这篇文章从您已经在项目中配置了本地化的地方继续进行,包括字符串和情节提要。 如果不是这种情况,您可以在Ray Wenderlich的帖子中找到所需要做的一切。 SwiftGen比NSLocalizedString更好 SwiftGen是一个神奇的宝石,它为我们的iOS管道带来了很多自动化,它可以帮助您生成一个故事板,字符串等枚举。 您可以在github页面上找到一些用例和更多信息。 AliSoftware / SwiftGen SwiftGen –用于生成Swift代码的Swift工具集合(用于您的资产的枚举,情节提要,Localizable.strings… github.com 脚步: 首先,我们需要安装swiftgen,我们可以通过自制软件完成 $ brew更新 $ brew install swiftgen 2.在此之后,我们只需要向项目的“构建”阶段添加一个新的运行脚本阶段 代码很简单,在上面的屏幕快照中,我同时生成了情节提要和字符串枚举 $ PODS_ROOT / SwiftGen / bin / swiftgen故事板-t swift3 $ SOURCE_ROOT —输出$ SOURCE_ROOT / {STORYBOARD_ENUM_OUTPUT_PATH} /Storyboard.swift — sceneEnumName故事板 $ PODS_ROOT / SwiftGen / bin / […]

iOS 10中的Spotlight搜索增强功能

早在iOS 9发布时,Apple便取得了很大的进步,它允许第三方应用程序将其数据与Spotlight数据库集成在一起,从而使系统Spotlight搜索对用户更有用(有关更多详细信息,请参阅使用Core Spotlight为应用程序内容编制索引)。 通过允许对应用程序的数据建立索引,您可以允许用户在一个方便的位置找到其内容,从而增加与应用程序的互动。 但是,这一轮更新存在一些明显的遗漏。 首先是Spotlight索引是一个完整的黑匣子。 您可以将数据放入其中,但是无法重新取回任何东西。 第二个问题是,尽管用户可以在Spotlight UI中执行简单的文本搜索来查找您的内容,但是无法扩展此功能以允许进行更复杂的查询。 聚光灯已经打开,但我们只允许窥视它。 现在,在iOS 10中,我们可以走得更远。 在您的应用程序中继续Spotlight搜索 iOS 10的Spotlight搜索的一个不太被广告宣传的功能是,现在可以在应用程序内继续搜索。 看一下以下搜索: 请注意,“地图”应用的结果旁边没有“显示更多”选项。 而是有一个“在应用程序中搜索”选项。 轻触此选项,我们将直接进入Maps应用,并向我们显示搜索结果: 以前,唯一的选择是在Spotlight用户界面中显示更多搜索结果。 但是,这仅在用户做出选择结果的选择之前向用户提供有限的信息。 通过允许用户继续在应用程序中进行搜索,他们可以利用应用程序中提供的额外详细信息,并且可以选择进一步优化搜索条件。 您可能会认为,扩展应用程序以允许Spotligh搜索在其中继续进行比较困难。 但是你会错的! 让我们看看它是如何完成的。

在Swift中创建一个私有iOS框架并使用CocoaPods分发它

框架是代码和资源的集合,用于封装在多个项目中有价值的功能。 一个swift框架包括一个Swift模块文件和一个共享库,其中Swift文件文件传达了框架API的源级别信息,共享库提供了在运行时加载的已编译实现。 有多种发布iOS框架的方法。 可以通过将其推送到任何git仓库管理器(例如github,gitlab等)来分发它。 在这里,您可以将整个框架项目推送到远程仓库,并使您的源代码可见,或者您可以在不共享源代码的情况下推送您的iOS框架。 在本文中,我们将学习如何快速创建一个私有框架,并在不共享其源代码的情况下使用CocoaPods分发它。 让我们从创建框架开始。 创建一个Swift框架 在这里,我们将创建一个HelloWorld框架,其中包含一个Logger类,该类又具有一个func类printHelloWorld ,该类将打印“ Hello World!”文本。 开启Xcode 从顶部菜单中选择Cocoa Touch Framework ,然后单击下一步。 将产品名称设置为HelloWorld并选择语言为Swift。 单击下一步并创建。 如果在项目中展开HelloWorld文件夹,则会找到两个文件: Info.plist和HelloWorld.h-后者是用于在框架和主机应用程序之间进行通信的头文件。 单击文件 → 新建 → 文件 选择“ 可可接触类” ,然后单击“ 下一步”。 将类名称设置为Logger并确保它是NSObject的子类。 单击下一步并创建。 现在Logger类将如下所示 类记录器:NSObject { } 用以下代码行替换Logger类。 @objc公共类记录器:NSObject { @objc公共类func printHelloWorld(){ 打印(“ Hello World!”) } } Logger是一个公共类,其中包含printHelloWorld函数,该函数打印“ Hello World!Hello World! ”文字。 添加了公共说明符,以便主机应用程序可以访问Logger类和printHelloWorld函数。 @objc→这告诉编译器可以从Objective-C访问这段Swift代码,如果主机应用程序是用Objective-C编写的,则很有用。 生成通用框架 要制作可在设备和模拟器上使用的通用框架,您可以配置一个归档后脚本,该脚本将在存档后为iOS模拟器构建框架,并将模拟器和iOS二进制文件合并为一个胖通用框架。 […]

Swift中的NSBatchUpdateRequest及其优势

在此博客中,我们将学习实现NSBatchUpdateRequest Swift 3.x版本在iOS 8中引入的Core Data的说明。 我们还将关注内存使用情况和执行时间。 我还制作了有关此主题的视频教程。 请检查博客末尾的链接。 从iOS 8和更高版本以及OS X Yosemite和更高版本,我们可以直接与持久性存储进行交互并更新属性。 根据Apple的说法,这是批量更新。 因此,在不浪费更多时间的情况下,让我们深入了解Xcode中的代码部分。 创建一个新项目,并确保选中使用核心数据复选框。 创建项目后,转到。 xcdatamodeld文件并创建一个名为Student的实体。 我们还将创建它的两个属性, studentName和studentRollNo 。 每当我们尝试从编辑器创建NSManagedObject类时,在Swift 3.x中都会出现一个奇怪的错误- 具有相同名称的文件名redeclaration 。 因此,为了解决该问题,请选择实体,然后在“ 数据检查器”部分中转到“ 类” 。 如下图所示,将Module更改为Current Product Module ,将Codegen为Manual / None 。 然后,最后单击“编辑器”,然后单击“ 创建NSManagedObject子类”。 因此,我们已经准备好模型子类。 在这里,它们看起来像。 Student + CoreDataClass.swift 进口基金会 导入CoreData 公共班学生:NSManagedObject { } Student + CoreDataProperties.swift 进口基金会 导入CoreData 扩展学生{ @nonobjc公共类func fetchRequest()-> […]

Firebase –检索数据(iOS)📩

baseอต้องการแบบอมูลจากFirebase侦听器แบบ异步ซึ่ง侦听器ตัวนี้จะเชื่อมต่อกับฐานข้อมูลจาก数据库参考เมื่อเริ่มสร้างจะมีการงจะมีกอมูลมาก่อน1ครั้งหลังจากนั้นก็จะได้รก็จะได้数据ตาม ที่ตั้งไว้เช่น值,已添加子项,已更改子项 总览 导入 FirebaseDatabase 创建引用— referenceามารถอ้างอิงแบบอื่นได้อีก(),(fromURL:String),(WithPath:String) 创建监听器/ 使用功能 读取事件类型 侦听器จะทุกเรียกทุกครั้งเมื่อ事件เปลี่ยนแปลงซึ่งก็ขึ้นกับtypeที่ได้สร้างไว้ 值 —数据มีการเปลี่ยนที่ 添加的孩子— childรียกเมื่อchildถูกเพิ่ม 换了孩子— childรียกเมื่อchildถูกเปลี่ยน 子级已删除 —เรียกเมื่อchildถูกลบ 孩子感动 — childรียกเมื่อchildถูกย้าย 一次读取数据 ับางครั้งเราไม่ต้องการรอรับ数据ตลอดเวลาเช่นอาจจะแค่ต้องการ用户名มา设置标题แค่ตอน登录ก็สามารถใช้ เพิ่มเติม。กรณีนี้หากต้องการหา名称จะใช้ากโครงสร้างข้างต้นจะใช้ จะไล่ค้นหาตั้งแต่儿童ท้ายสุดไปแรกสุด) 查询数据 queryOrderedByChild: queryOrderedByKey: queryOrderedByValue: queryOrderedByPriority: คำสั่ง查询ที่ใช้เสริมกับตัวด้านบนเพื่อนำมาใช้ร่วมกันในการ查询ระดับเมพขึ้นไปอีก💪 queryLimitedToFirst: queryLimitedToLast: queryStartingAtValue: queryEndingAtValue: queryEqualToValue: 例如 复杂查询 例如 摘要代码