最近,我发布了名为Socium的iOS社交网络应用模板。 在这里,我想与您分享我从开发中学到的知识。 功能清单 首先,我们需要写下要在应用程序中看到的功能列表。 例如,Socium与典型的社交网络应用程序一样,具有以下功能: 用户资料 用户帖子和评论 发表喜欢 浏览和搜索其他用户 私人实时聊天 追随者/追随者 推送通知 考虑到此列表,我们可以为项目选择一个后端。 后端 社交网络应用程序是一个复杂的系统,由客户端和服务器端组成。 Socium的服务器端建立在Parse Server之上。 Parse Server有许多优点:它是开源的,具有庞大的社区,并且具有出色的iOS SDK(顺便说一下,还有Android SDK)。 Parse Server需要VPS或Heroku之类的云应用程序平台,对于不熟悉后端内容的用户而言,可能难以设置和维护。 但是,我相信控制后端是一件好事。 即使需要一些其他技能。 毕竟,我从课程中学习。 数据库架构 现在,当我们知道要求时,就该写下所有必要的表及其之间的关系了。 这是我为Socium设计的架构: 让我们来看几个最有趣的实体(或Parse Server术语中的“类”)。 用户 / UserProfile 。 为了保护用户的电子邮件,我为公共用户配置文件创建了另一个类UserProfile,并与User类添加了一对一的关系。 任何人都可以看到UserProfile 。 用户仅对所有者和管理员可见。 UserProfile具有followings , followers和postLikes字段,它们分别是与UserProfile和Post实体的一对多关系。 他们全部 图片 。 我没有将图像直接存储在PFFile字段中,而是为此创建了一个单独的类。 因此,图像可以阵列和多对多关系存储。 如果我们想在照片中添加喜欢/不喜欢的功能,则可以提供更好的灵活性。 Post , PostComment , Conversation和Message实体非常不言自明。 客户端应用架构 定义数据库架构后,该考虑一下我们的iOS应用了。 […]
以及如何通过应用4 Hour Body和Freeletics方法真正成为收入最高的程序员。 广告策略-更好的您 学习编程需要改变行为。 做某事的长期承诺可能是您不习惯的。 健身房的类比很直白。 获得健身卡不会使您变得更健康,而持续进行锻炼则会使您变得更健康。 不幸的是,在线编程课程的经济学侧重于按下与健身房相同的按钮。 毕竟,这是每月订阅的相同业务模型。 为了使您更好地了解自己的形象,需要进行很多预售。 您想成为的人,一个更好的自己: 让我们看一些领先于在线课程的广告技巧,这些技巧与这种策略非常相似: [COURSE NAME]不仅消除了对移动应用程序进行编码的恐惧,而且使它变得有趣。 [课程名称]向我展示了我想要做的事,直到今天,在家学习Web开发已被证明是我一生中最好的决定之一。 售后—内lt 购买健身卡并订阅在线课程会怎样? 该程序将告诉您该怎么做。 这样做很长时间。 不要跳过培训。 走。 从您成为客户的那一刻起,您基本上就是一个人。 此外,当您无法跟上时,可以去健身房或定期观看教程。 怎么了? 正确-内the卡被使用。 我们不能为您在5:00醒来,现在可以了吗? 我以为您说过想用Swift学习iOS开发–是不是说要改变生活? 好吧-这就是需要的。 每天学习3个小时。 每天。 6个月。 然后您会到达那里。 没有? 好吧-谁该怪? 会坚持吗? 蒂姆·费里斯(Tim Ferris)在他的《四小时的身体》(4 Hour Body)一书中建立了一个我在教学生必须使用的学习策略时经常使用的测试。 该测试称为“导带测试”。 还有一个简单的问题:“会坚持吗?”: 每天砍蔬菜和清洗Cuisinart三次,将导致一个地方:放弃该方法。 这是否意味着某些人无法使用? 不。这只是意味着它将对大多数人失败。 认真对待坚持:在达到目标之前,您是否会坚持这一改变? 如果不是,请寻找另一种方法,即使该方法效率较低且效率较低。 您遵循的体面方法比您退出的理想方法更好。 经过测试 我已经对自己进行了测试。 我有多年的健身卡,很少去那里。 然后我找到了Freeletics。 我可以看到前两周的最初结果。 动机不再是问题。 我减掉了8公斤。 […]
具有Google,Xcode和Swift-3的自动完成地点选择器 我想在照片中添加位置。 我想以instagram的方式来做:以模态呈现,一旦选择一个位置就消失。 我遇到了Google地图Google的地点选择器。 看起来是这样的: 步骤1: 在项目的PodFile中安装以下Pod: pod“ GooglePlaces” pod’GooglePlacePicker’ pod’GoogleMaps’ 第2步: 获取API密钥: https://console.developers.google.com 要么 https://developers.google.com/places/ 第三步: 将以下内容添加到您的AppDelegate中: 导入GooglePlaces 和(_:didFinishLaunchingWithOptions 🙂 GMSPlacesClient.provideAPIKey(“ YOUR_API_KEY ”) 步骤4: 在用户界面上创建一个按钮,该按钮将以模态显示位置选择器视图: *不要忘记将委托分配给自己 类ViewController:UIViewController { @IBAction func autocompleteClicked(_发件人:UIButton){ 让placePickerController = GMSAutocompleteViewController() placePickerController.delegate =自我 present(placePickerControllerController,动画:true,完成:无) } } 步骤5: 实现所需的功能: 如果需要将地点分配给某些东西,则可以在GMSAutocompletViewController,didAutocompleteWith地点中进行:GMSPlace 扩展ViewController:GMSAutocompleteViewControllerDelegate { //处理用户的选择。 func viewController(_ viewController:GMSAutocompleteViewController,didAutocompleteWithplace:GMSPlace){ print(“地名:\(place.name)”) print(“地址:\(place.formattedAddress)”) print(“地点归因:\(place.attributions”“) 关闭(动画:true,完成:nil) } func […]
Apple于2015年12月将Swift开源,此后新版本的Swift频繁发布。 在瞬息万变的Swift开发环境中,必须确保用于构建iOS应用的Swift版本正确且符合预期。 我们将介绍如何使用我写的名为“ ensure-swift-version”的Fastlane插件自动检查Swift的版本。 为什么要检查Swift版本 根据Swift仓库上的Github版本,我们可以看到几乎每天都有新的DEVELOPMENT-SNAPSHOT发布。 我们可以轻松地切换到Swift的不同工具链,以尝试Swift语言的新功能。 在此处的Swift文档页面上有关于使用自定义工具链的信息。 迅捷版 我们可以通过从终端运行swift-version命令来检查版本,但是我们必须将此步骤插入到构建过程中。 Fastlane是用于iOS应用程序构建自动化的流行工具之一。 我认为,将插件添加到Fastlane以检查Swift版本是一个好主意。 让我们看看如何将插件添加到项目中。 为项目添加Fastlane支持 让我们创建一个新的Xcode项目作为单视图iOS应用程序。 我们称之为“演示” 我们可以通过在fastlane目录中创建Fastfile来为项目添加Fastlane支持。 $ mkdir fastlane $ touch fastlane / Fastfile 添加Fastlane插件 假设您已经在macOS上安装了fastlane,如果没有,请按照此处文档中的安装步骤进行操作。 我们可以通过运行添加快速通道插件 $ fastlane add_plugin sure_swift_version 这将为我们的项目设置Gemfile和Pluginfile并安装插件“ ensure-swift-version”。 使用插件 现在,我们可以使用我们新添加的插件了。 让我们在Fastfile中添加一条车道 泳道:迅捷 sure_swift_version(版本:“ Apple Swift版本3.1”) 结束 在这里,我们正在检查我们使用的Swift版本是3.1。 我们可以使用 $快速通道 如我们所见,将此检查插入我们的构建过程将多么容易。 最好将此检查用作before_all通道的一部分,以便我们可以在构建和测试应用程序之前执行此检查。 范例程式码 该插件可在Github仓库’fastlane_plugin_ensure_swift_version’上获得,并且有使用此插件’demo_ensure_swift_version_plaugin’的演示仓库。 希望您觉得这个插件有用。 像XCBlog的 XCTEQ 发布的帖子一样 ? 您可能还喜欢我们的一些服务,例如访客博客或Mobile […]
在这里,我们再次慢慢地成为一名出色的iOS开发人员。🙂在本课程中,我们将经历循环和条件。 首先让我们看一下循环。 循环 循环用于遍历数据集合并对其执行一些任务。 我们知道Swift中的三种循环: while , repeat-while和for-in 。 While循环 var homeworkDone = false 而!homeworkDone { 打印(“做我的作业”) } 尽管这不是while循环的很好示例,但我希望您了解它是如何工作的。 这很简单,虽然homeworkDone不是正确的,但它会打印“正在做作业”。 为什么这是一个不好的例子? 因为它将永远运行,因为我们没有更改homeworkDone变量,所以那不是确定的 。 这个例子不错,只是为了让您了解它是如何工作的。 重复循环 变数= 0 重复{ 数字=数字+ 1 }而数字<10 你觉得和重复的时候很相似吗? 唯一的区别是此代码在检查条件之前执行了代码。 循环内 var carsInMyGarage = [“特斯拉S型”,“三菱蓝瑟X”,“高尔夫R”,“焦点RS”] 用于carsInMyGarage中的汽车{ 打印(汽车) } for-in循环用于循环遍历数据集合并对其进行处理。 在这种情况下,我们将打印carsInMyGarage数组中的每辆车。 “ Car”只是临时存储数组中数据的变量,您可以随意调用它。 通过此循环,您还可以循环显示一系列数字。 您可能会这样: 1 … 5中的数字{ 打印(数量) } 这将打印从1到5的数字。您也可以使用以下非包含范围: 对于1 .. […]
介绍 我写了一篇有关将我们的iOS应用程序迁移到框架中以及该应用程序如何从此类工作中受益的文章。 本文将继续进行,并详细介绍迁移后在项目上完成的工作。 我描述了如何将内部开发的框架完美地链接在一起,以及应该遵循哪种模式才能为大型iOS应用程序实现真正的分离架构。 为我的PM记录……一切都在我的“产品空闲时间”中完成了🙂 动机 在我之前讨论的体系结构中,所有事物都属于一个适当的框架,主应用程序目标链接了所有框架,项目结构尽可能地分离,这提出了一个重要问题……将所有事物链接在一起的最佳方法是什么? 最先进的技术是使主应用程序目标(将所有框架链接在一起的应用程序)将责任委派给框架,然后通知框架需求,例如当前正在使用的框架想要呈现属于该框架的ViewController到另一个框架。 然后将通知主应用有关此更改,并显示所需的ViewController。 我希望您可以想象这种方法的所有优点。 首先,我想提一下可重用性,想象一下Facebook发生的情况。 他们的应用程序分为两部分(Facebook,Messenger),采用这种体系结构可以轻松实现这一目标,从而同时支持两个应用程序。 由于所有内容都在一个位置链接到应用程序,因此您也可以轻松地将整个框架/功能取出并链接到多个应用程序。 不用说,在团队中,每个开发人员都可以对某个特定的框架负责,但是在上一篇文章中有更多的责任。 三层架构 在上一篇文章中,我讨论了如何将应用模块化到框架中。 在本文中,我将把我们的项目分为遵循某些严格规则的3个逻辑层,以我们在该文章中所做的工作为基础。 第一层(胶水) 第一层包括我们的主要应用目标。 它具有AppDelegate对象,初始化我们的一些服务,响应通知等等。 除此之外,它还有我们的主要应用程序协调器。 协调员的职责是处理应用程序中的转换。 它从框架功能实例化协调器,并将责任作为其子协调器传递给他们。 儿童协调员将其不负责的行为通知父母(在我们的代码库中为主要应用程序协调员)。 我们之所以将责任从孩子协调员那里转移出去,有很多原因,主要是因为我们不希望一个孩子协调员依赖于另一个孩子协调员,如上图所示。 第二层(功能) 第二层具有我们的所有功能,例如发布项目,管理页面,聊天等。 这些框架中的每个框架都实现自己的协调器,该协调器将在第一层中实例化。 理想情况下,协调员应该是框架之外唯一公开可见的对象。 通过将框架协调器作为唯一可见的对象,我们确保这是与该功能进行交互的唯一方法。 第二层遵循严格的规则,不得链接第二层中的任何其他框架。 这样做的原因是要使功能与其他功能保持脱钩状态,因此可以很容易地将其带入或带出项目。 但是,第二层可以链接第三层的任何框架,并且被第一层链接。 话虽如此,第二层的框架可能需要具有一些共享的依赖关系,例如,功能框架很可能需要访问网络或持久性,这就是第三层的目的。 第三层(核心) 第三层是应用程序的核心,例如模型,网络,持久性,本地化等。第二层的框架由第二层链接,没有任何限制。 但是,与第二层不同,第三层的框架可以相互链接。 要避免在第三层建立这种联系将是极其困难的。 例如,您的网络框架(如持久性框架)将要使用模型框架……您可以想到许多类似的情况。 一种可能的解决方案是创建第四层。 只有第三层的共享框架才在第四层。 这可能是一个很好的解决方案,但是我们发现它有些过分设计。 这是一个工作区外观的示例。 实作 这是一个看起来很幼稚的例子。 在代码中,我使用术语流程代替协调器,因为根据我的观点,它是一个更准确的术语。 让我们从为Flow定义协议开始。 您可以在此处查看完整的演示。 流协议的实现 现在,让我们看一下主要的AppFlow(AppCoordinator)。 主AppFlow 最后,从其中一个框架实施子流程。 协调器模式已为人所知已有一段时间,有很多文档可以激发您的灵感。 我想在这里指出,我已经看到了一些实现,其中协调器接管了模型并正在获取数据或执行其他一些控制器/视图模型作业。 不用说,协调器是为应用程序流而设计的,这就是工作。 […]
在开发iOS应用程序时,也许您将使用键值观察(KVO)来帮助一个对象观察另一个对象的状态变化。 这是观察者模式的一个例子。 如果您想了解更多有关它的信息,那么官方编程指南和objc.io的这篇文章都是不错的参考。 如下图所示,这种模式既有主体又有观察者。 主题是要观察的目标。 它包含观察者实例,并将有关更改的信息通知他们。 观察者会收到通知并处理更改。 逻辑很清楚。 让我们编写代码。 作为观察者,它只会在收到通知时打印一些信息。 protocol Observer { func update () } class ConcreteObserver : Observer { var id: String init (id: String ) { self. id = id } func update () { print (id + ” observered the subject’s state was changed.”) } } 正如我们提到的,主题有一个观察者列表,并在状态改变时通知每个观察者。 class Subject { […]
本地通知是一种将通知发送给用户的好方法,而无需Internet连接或服务器端编程。 这些通知对于任何类型的“提醒类型的应用程序”都是完美的,并且自iOS 4发行以来就可用。如果您正在编程一段时间,我确定您已经熟悉UILocalNotification类,现在就熟悉iOS的发布10,我敢打赌,您和我一样高兴(这是非常讽刺的方式), UILocalNotification已过时。 好吧,新的更新随新的代码实现一起出现,作为开发人员,我们应该保持代码更新,对吗? 好的,让我们来聊聊吧,让我们构建一个非常简单的应用程序,它会使用新的UserNotifications Framework’s UNNotificationRequest.提醒我们进行UserNotifications Framework’s UNNotificationRequest. 首先在Xcode中创建一个新项目,然后在“链接框架和库”部分中添加UserNotifications Framework 。 转到您的AppDelegate.m文件,然后像这样导入框架… 现在,在didFinishLaunchingWithOptions:内部didFinishLaunchingWithOptions:复制并粘贴… – (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) { UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (!granted) { //Show […]
我们将尝试演示MVVM和Clean Archi如何帮助以BDD方法进行开发(行为驱动开发)。 该示例源代码可在此GitHub存储库上找到。 本杰西/计算器 计算器–具有BDD,Clean Archi和RxSwift的示例github.com 好的方法是从用户需求和示例映射开始。 我们将使用一个非常简单的示例来描述一个附加项。 通过这个非常简单的示例,我们试图证明MVVM / Clean Archi / RxSwift概念不仅有助于使用BDD,它们也是有教益的。 使用这种严格的方法,我们必须思考:一些输入,一个转换函数和一些输出:有助于我们清楚地识别不同的步骤。 现在我们不再问自己:我可以在哪里使用测试以及必须测试哪些类…… 请享用 ! 😉
这是一个有关如何使用新的UISearchController向UITableViews添加搜索功能的简单教程。 UISearchController是几年前在iOS 8中引入的,以取代现在不推荐使用的UISearchDisplayController。 在新的搜索控制器中,将搜索添加到表视图更加容易。 从Xcode 8.1开始,UISearchController尚未添加到Interface Builder,因此您必须以编程方式添加它。 即使如此,使用它还是很容易的。 设置我们的UITableView 在Interface Builder中,将UITableViewController添加到情节提要中。 默认情况下,UITableViewController将使用动态单元格。 这对于我们的演示来说是完美的。 我们需要做的唯一其他配置是配置动态单元。 单击该单元格,并为其提供重用标识符。 我将其标记为“ basicCell”。接下来,将单元格样式设置为“基本”,因为我所需要的只是在单元格中显示文本。 现在我们需要用数据填充表格视图,因此我们需要搜索一些内容。 我目前正在看周一足球比赛,所以我想着足球。 我将所有NFL球队添加到我们的表格视图中。 以下是一些非常基本的UITableView内容。 一个函数指示我们有多少节,另一个函数指示我们有多少行,最后的覆盖为单元格配置数据。 它们都使用数据源unfilteredNFLTeams ,这是我在viewDidLoad函数中填充的数组。 请参阅完整文章中的代码。 这就是我们运行演示时的样子。 添加UISearchController 现在我们的表视图已设置好要搜索的数据,下一步是添加一个UISearchController并对其进行配置。 UISearchController的初始化程序可以使用一个参数,该参数可以指定其他视图控制器以显示搜索结果。 我认为最常见的用例是在具有表视图的同一视图控制器中显示搜索结果。 传递nil表示我们不希望其他视图控制器显示搜索结果。 请参阅完整文章中的代码。 现在,我们创建了UISearchController,我们需要应用一些设置。 在viewDidLoad函数中,使用以下代码配置UISearchController: 请参阅完整文章中的代码。 让我解释一下您刚刚添加的内容: 我们需要实现UISearchResultsUpdating协议(稍后会详细介绍)。 将searchResultsUpdater属性设置为self,将委托设置为我们的视图控制器实例。 将hidesNavigationBarDuringPresentation设置为false可以防止在您键入搜索栏时隐藏导航栏。 dimsBackgroundDuringPresentation指示键入搜索时搜索结果是否看起来暗淡。 我发现这会分散注意力,因此将其设置为false 最后,我们将表视图的标题视图设置为UISearchController的搜索栏。 实施UISearchResultsUpdating协议 该协议仅包含我们需要实现的一个功能。 对于在搜索栏中键入的每个字符,都会调用updateSearchResults函数。 您需要过滤自己的数据并自己更新表视图。 让我们为NFL球队做到这一点。 这是我对updateSearchResults函数的实现。 请参阅完整文章中的代码。 我在视图控制器中引入了第二个变量,以跟踪称为filteredNFLTeams的NFL团队的已过滤列表。 当有人在搜索栏中键入内容时,我需要使用包含这些字符的NFL小组更新过滤后的列表。 if let语句检查searchBar.text是否为nil,还检查文本是否为空字符串。 如果没有搜索文字,则将NFL球队的原始完整列表分配给filteredNFLTeams变量。 否则,我会在NFL球队名单上使用Swift的过滤器功能。 […]