地理栅栏:如何使用Swift在现实世界中实现虚拟边界?

什么是地理围栏? 地理围栏是一种定义现实世界地理区域周围的虚拟边界的技术。 每次用户进入或退出某个地理围栏的边界时,都可以在支持位置的设备(通常是智能手机)中触发动作。 通常,用户将根据其位置实时接收包含某些信息的通知。 这项技术的主要优势在于,它将虚拟世界与真实世界融合在一起。 在横向视图中,我们在多个项目中利用了地理围栏,特别是在卫生行业。 地理围栏在移动开发中的应用 地理围栏可以有多种应用程序: 市场营销 :服装店附近时,服装店可以通过当天的优惠和折扣触发推送通知。 提醒 :此应用程序可以提醒足球俱乐部的球迷在周围时进入体育场的大门的地址。 到达和离开特定位置:航空公司可以发送通知,希望用户在飞机起飞后安全旅行,或者在飞机降落时发送欢迎消息。 儿童追踪 :应用程式可以传送通知,告知父母其子女已离开或进入特定区域。 安全性:进入或离开区域时,该应用可以启用或禁用功能。 但是,地理围栏并不是要随身携带推送通知轰炸用户。 重要的是要向用户提供相关信息,以便在正确的时刻考虑到用户的需求,从而做出更好的决策。地理围栏的目的是增加价值并为客户提供更好的体验。 相应地使用它,将为客户和企业创造双赢局面。 因此,了解这种技术的强大功能的重要性。 优点 通过提供实时报价,折扣和促销来吸引客户。 增强用户体验。 向用户发送位置特定的通知。 缺点 地理围栏需要用户的批准。 如果用户拒绝或禁用位置服务,则必须在应用设置中启用地理围栏,然后才能使用。 位置跟踪会消耗过多的电池电量,这是用户关闭设备中的位置服务的首要原因。 仅适用于大范围区域。 知名应用中的地理围栏 您是否曾经问过自己,当您在已经访问过并签到过的地方附近时,Foursquare会如何向您发送提醒? 或《 Pokemon-Go》如何在关键区域禁用狩猎小精灵? 答案是地理围栏:在现实世界中创建边界,同时通过移动设备跟踪您的位置。

基于Texture的聊天应用程序

Texture를이용한ChatKit만들었다。 정말기능만 。다른이브러리들도해봤었다。 mukyasa / MMTextureChat MMTextureChat –用于 Whatsapp 和iMessage的 AsyncDisplayKit (Texture)平滑滚动聊天模拟 github.com MessageKit /消息包 MessageKit –开发中:JSQMessagesViewController社区驱动的替代品 github.com nguyenhuy / AsyncMessagesViewController AsyncMessagesViewController –适用于iOS的平滑,响应和灵活的消息UI库。 github.com slackhq / SlackTextViewController SlackTextViewController –带有不断增长的文本输入视图和其他有用消息传递的嵌入式UIViewController子类…… github.com 생각한이있었는데,내가생각한聊天应用程序라이브러리에서가핵심적인능은 追加,追加용이해야한다。 前置스때유이유지되야하고사용자좋아야한이좋아야한다。 消息输入UI를이기가용이해야한다。 Diff算法Diff算法,网络,网络,网络和应用程序。 聊天应用程序능들과기부부가적으로능들기능들이많다。 GTChatKit产品和服务GTGhatKit产品。 용법을먼저먼저 class기子类 类ChatNodeController:GTChatNodeController {…} 请参见GTChatNodeController子类。 그냥리。이같初始化그냥이다。 让viewController = ChatNodeController() 그리고가능한로퍼티자면보자면보간단히 类ChatNodeController:GTChatNodeController { … func foo(){ let collectionView = […]

在Swift中以编程方式创建UIViews

使用PureLayout具有视图约束 期待什么? 了解iOS屏幕 查看层次结构 何时以编程方式构建视图 如何组织我们的代码(MVC模式) 构建自定义类(UIView) Twitter iOS应用示例 !Massive View控制器 设置约束(PureLayout) 了解iOS屏幕 任何iOS应用程序都有很多视图。 这些视图需要指定四个值才能显示: x,y,width,height 。 有三种不同的方式来构建这些视图: 情节提要 , Nib 文件和Programmatically 。 iOS sdk(UIKit)中有一个框架,其中包含一组标准子类,这些子类的范围从简单的按钮到许多其他视图对象之间的复杂表。 例如,UILabel对象绘制文本字符串,而UIImageView对象绘制图像。 视图可以嵌入其他视图并创建复杂的视觉层次结构。 这将在要嵌入的视图 (称为subview )和进行嵌入的父视图(称为superview )之间创建父子关系。 查看层次结构 视图的组织方式不仅影响应用程序的外观,还影响应用程序对更改和事件的响应方式。 例如,视图层次结构中的父子关系确定哪些对象可以处理特定的触摸事件。 同样,父子关系定义每个视图如何响应界面方向更改。 何时以编程方式构建视图 在满足以下条件时,使用自定义代码通常是一个很好的选择: 动态布局 具有效果,圆角,阴影等的视图 使用情节提要的任何情况都很复杂。 如何组织我们的代码(MVC模式) Model-View-Controller可能是最常用的设计模式。 从iOS开发开始,通常会遇到Massive View Controller问题 :View Controllers常常变得太大,包含难以真正修改或重构的所有功能。 通过遵循这种模式,我们确保项目中的每个类都是Controller,Model或View。 这样可以更轻松地以编程方式创建所有视图,而无需创建意大利面条怪兽。 显然,我们可以有其他组和类,但是应用程序的核心包含在这三个类别中。 入门 启动新项目时,Xcode使用情节提要板对其进行初始化。 为了创建我们的自定义视图,我们需要丢弃情节提要。 接下来,创建两个文件: ProfileView作为View类别下的UIView类,以及ProfileViewController作为Controller类别下的UIViewController类。 […]

在iOS上使用MVVM进行路由

我在多个项目中使用MVVM已有一段时间了,我非常喜欢它的简单性。 特别是,如果您像许多人一样从MVC移出,则只需要在体系结构中增加一层即可; 查看模型。 如果您发现太多复杂的图层,这确实使事情变得容易。 这是一个好的开始,但是这种简单性并不总是很好。 在MVVM中,将业务逻辑移出视图控制器(VC),然后意识到它仍然很胖。 视图模型(VM)现在具有业务逻辑,但是表示数据(格式)或路由又如何呢? 它们仍然停留在VC中,我们需要将它们移出。 样品流量 假设我们正在实现一个登录屏幕,如下所示。 路线清单: 登录>主屏幕 注册>注册屏幕 忘记密码(?)>忘记密码屏幕 这似乎是一个简单的屏幕,可以使用带有3个脚本的情节提要实现。 但是请相信我,事实并非如此。 例如,您通常会在登录时打开主屏幕。 但是在这种情况下,用户的密码可能已过期,您需要实现重定向以更改密码屏幕。 因此,登录路径变为: 登录>主屏幕或更改密码屏幕 这是情节提要路由失败的地方。 它只是无法应付这种动力。 因此,通常要做的就是让VC处理它: func loginButtonTapped(){ //开始网络请求… //回应后: 如果viewModel.shouldChangePassword { performSegue(id:“ ChangePasswordScreen”,发送者:nil) }其他{ performSegue(id:“ HomeScreen”,发送者:nil) } } 这是路由逻辑,不应在VC中使用。 如果要使用轻量级VC,请在编写if语句之前三思。 他们是决定,不属于那里。 以我的理解,VC仅应具有与视图相关的代码和粘合代码。 永远没有决定。 让我们定义一个路由器协议,并将这些if语句从VC中删除。 我们会需要: 路由ID :字符串标识符,例如segue ID。 上下文 :要从其路由的当前视图控制器。 可选参数 :过渡所需的临时数据。 (点击的行索引等) 协议路由器{ 功能路线( 到routeID:字符串, 来自上下文:UIViewController, […]

开放封闭原则和规范模式的重要性。

Lehlohonolo Isaac,iOS开发人员,DVT 您是否曾经不得不一遍又一遍地重写相同的功能? 举例来说, 您想按类型,颜色和价格过滤车辆列表。 尽管有不同的规范,但我将通过编写三个过滤函数来实现此目的。 因此,即使这三个功能执行相同的操作(正在过滤车辆列表),这三个功能也仅因其规格不同而不同。 解决此问题的简单方法是将规范插入过滤器中。 在这种情况下,我们将只有一个过滤器。 为了使我们能够按颜色进行过滤,我们将注入颜色说明。 要按类型过滤,我们将插入“车辆类型规范”,依此类推。 现在,我们的应用程序只有一个过滤器。 让我们看一下如果在上面的示例中不使用“规范”模式,将会发生什么。 让我们首先创建一个Vehicle对象。 现在,假设您具有以下定义的车辆清单。 让我们创建一个Filter类: 下面的代码段演示了过滤车辆列表的方式: 仅当您知道Vehicle具有一个属性大小时,这才足够好。 但是,它足以应付车辆规格的变化,即当我们现在要按颜色或车辆类型过滤车辆列表时,它将无法正常工作。 取而代之的是,我们必须在VehicleFilter中添加另一个函数,该函数不可行,因为它不遵循开放式封闭原则(OCP)。 我们如何克服这一弊端? 好吧,我要实现的解决方案之一是按规范过滤,而不是明确说明过滤标准。 通过这样做,您可以使VehicleFilter具有足够的灵活性,以适应各种过滤条件。 让我们定义车辆规格。 因此,我们可以指定以下过滤条件: 让我们创建一个过滤器协议。 让我们看看上述变化将如何帮助我们遵守开放式封闭原则。 从上面的代码片段可以看到,我们现在可以过滤颜色和大小,而无需创建两个过滤器。 这使我们的过滤器类别遵循SRP(单一责任原则)和OCP(开放-封闭原则)。 规范模式还可以做很多事情。 例如,您可以创建一个具体的规范来处理要同时按大小和颜色过滤列表的情况。 这称为And规范。 但是,AND有一个缺点。 它没有严格遵循单一责任原则。 我希望您对规范模式学到了很多。 我还要感谢Kennedy Sigauke对创建此博客所做的贡献。

如何提高Swift的编译时间?

在使用Swift 2.3和Xcode 7.3.1时,我在此IDE中编译源代码时遇到问题。 因为出于某些项目机密原因,我和我的团队决定继续使用2.3,而不是升级到3.0或更高版本。 影响团队绩效的主要原因之一是我们在没有足够的时间进行大量迁移。 实际上,问题仍然没有发生在Xcode 7.3.1上,我认为Xcode 8也没有,但是相当容易(p / s:我听说8.2版本解决了问题:x)。 谈论它,有两个主要因素: 通过Xcode,它不利于Dynamic Framework执行。 这意味着Xcode会重新构建所有源代码项目,而不是仅查找和构建未构建的源。 如果添加更多框架或第三方,则需要更多时间来编译它们。 开发人员,我为什么要这样说。 通常,在进行编码时,开发人员通常会忽略来自Xcode的使用Auto Layout对行和UI进行编码的警告(aka⚠),而倾向于使用Swift提供的推断变量。 贾佐 保存屏幕截图,GIF和网站的简单方法。 通过与您的用户更快,更智能地共享,让每个人都开心。 理想情况下,我们将解决以上每个问题。 使用Xcode,更新到最新的Xcode版本,并尽可能将Swift升级到当前版本(3.0)。 好了,有了Dev,我们还有另一件事要做: 解决所有来自Xcode的警告。 改进自己的代码。 示例代码: 让myCompany = [ “雇员”: [ “员工1”:[“属性”:“值”], “员工2”:[“属性”:“价值”], “员工3”:[“属性”:“价值”], “员工4”:[“属性”:“价值”], “员工5”:[“属性”:“价值”], “员工6”:[“属性”:“价值”], “员工7”:[“属性”:“价值”], “员工8”:[“属性”:“价值”], “员工9”:[“属性”:“价值”], “员工10”:[“属性”:“价值”], “员工11”:[“属性”:“价值”], “员工12”:[“属性”:“价值”], “员工13”:[“属性”:“价值”], “员工14”:[“属性”:“价值”], “员工15”:[“属性”:“价值”], “员工16”:[“属性”:“价值”], “员工17”:[“属性”:“价值”], “员工18”:[“属性”:“价值”], “员工19”:[“属性”:“价值”], “员工20”:[“属性”:“价值”], ] ] 修正为: […]

Google标记群集

Google iOS库提供了基于网格的聚类技术,该技术可将地图划分为正方形并将标记(注释)分​​组到每个正方形网格中。它提供了摘要标记,可让您大致了解缩放级别下的“下方”。 在这里,我参考Google官方API编写此博客。 在本博客中,将讨论一个演示,该演示具有Google地图集群的示例实现。 逐步会看到并学习实现。 第1步:最初,您应该在项目文件夹中包含pod(终端命令:pod init)文件,然后在同一文件中添加Google-Maps-iOS-Utils Pod。 安装Pod之后,打开生成的.xcworkspace扩展文件。 步骤2:以这种方式初始打开ViewController并覆盖方法 私人var mapView:GMSMapView! 私有var clusterManager:GMUClusterManager! 覆盖func loadView(){ let camera = GMSCameraPosition.camera(withLatitude:37.4220,经度:-122.0841,缩放:17) mapView = GMSMapView.map(withFrame:CGRect.zero,camera:camera) self.view = mapView } 步骤3:在viewDidLoad方法内部添加代码,如下所示 覆盖func viewDidLoad(){ super.viewDidLoad() //使用默认的图标生成器和渲染器设置集群管理器。 让iconGenerator = GMUDefaultClusterIconGenerator() let算法= GMUNonHierarchicalDistanceBasedAlgorithm() 让渲染器= GMUDefaultClusterRenderer(mapView:mapView,clusterIconGenerator:iconGenerator) clusterManager = GMUClusterManager(地图:mapView,算法:算法,渲染器:渲染器) //生成随机项并将其添加到集群管理器。 generateClusterItems() clusterManager.cluster() //注册self来侦听GMUClusterManagerDelegate和GMSMapViewDelegate事件。 clusterManager.setDelegate(self,mapDelegate:self) } 私人功能generateClusterItems(){ 让范围= 0.2 用于1 … kClusterItemCount中的索引{ 令lat […]

Swift —参考类型与值类型

在Swift上,请参阅Apple文档的ClassesAndStructures:类将称为“引用类型”,而Struct将是“值类型”: – 类是引用类型:与值类型不同,将引用类型分配给变量或常量或将它们传递给函数时, 不会复制引用类型 。 而不是副本,而是使用对相同现有实例的引用。 – 结构和枚举是值类型: 值类型是一种类型,其值在分配给变量或常量或传递给函数时将被复制 。 因此,让我们尝试下面的示例来了解什么是引用类型,值类型: class HumanClass { var name: String init(name: String) { self.name = name } } var classyHuman = HumanClass(name: “Bob”) classyHuman.name // “Bob” var newClassyHuman = classyHuman // Created a “copied” object new ClassyHuman.name = “Bobby” classyHuman.name // “Bobby” 当我将newClassHuman的name属性更改为“ Bobby”时,原始对象的name属性,classyHuman也更改为“ Bobby”。 那么Struct怎么样,让我们​​看下面的例子: struct HumanStruct […]

在您的应用中采用3D Touch快捷方式项。

随着iPhone 6s的问世,Apple引入了3D Touch机制,这是非常酷的事情。 最新的iPhone 7上也可以使用3D Touch。没有任何迹象表明未来的Apple设备将使用该功能,因此,这里有一个快速教程,介绍如何使用3D Touch的三个主要功能之一来改善您的应用程序。 修改您的Info.plist文件 在您的Info.plist文件中添加一个名为UIApplicationShortcutItems的特殊键。 它应该是一个数组。 将项目添加到UIApplicationShortcutItems数组。 项目应为字典类型。 放置每个项目的信息。 在此设置的值很少。 UIApplicationShortcutItemType(必需) UIApplicationShortcutItemTitle(必需) UIApplicationShortcutItemSubtitle UIApplicationShortcutItemIconType UIApplicationShortcutItemIconFile UIApplicationShortcutItemUserInfo 我将重点介绍在示例应用程序中设置的值。 UIApplicationShortcutItemType是一个字符串,用于向您的应用程序提供有关按下了哪种快捷方式的信息。 UIApplicationShortcutItemTitle是显示快捷方式时用户看到的内容。 UIApplicationShortcutItemIconType是一个字符串,用于通知应用程序此快捷方式应使用哪种系统图标。 最后一个是UIApplicationShortcutItemIconFile定义出现快捷方式时应显示的图标名称(而不是系统图标)。 重要的是,您可以使用系统或自定义图标。 Apple建议自定义图标应为方形,单色和35×35磅。 您可以从Apple文档中获取有关UIApplicationShortcutItems键和描述的更多信息。 配置的Info.plist可能如下所示: 并通过代码: 应用程序快捷点击处理 好的,现在移至AppDelegate类,让我们处理应用程序的快捷点击事件。 1.重写并实现UIApplicationDelegate方法。 让我们专注于这种方法: 如您在上面看到的,我创建了两个带有自定义图标,标题和副标题的快速操作。 动态快捷方式项 值得一提的是动态快捷项。 是的,UIApplicationShortcutItems分为static和dynamic 。 静态-将项目放置在info.plist 动态的-可以在代码中添加和删除项目 要添加动态快捷方式项,您只需将其添加到shortcutItems数组中。 关于我 我是波兰格但斯克的软件开发人员。 大多数情况下都使用iOS,但我对其他任何技术,框架和挑战都持开放态度。 如果您喜欢我的帖子,请随时在Twitter上关注我并阅读我的个人博客。

使用协议扩展在iOS中进行编辑

iOS开发人员将遇到的最常见的事情之一是创建专用于表单输入的屏幕。 这往往包括样式化输入字段,执行验证以及保存/放弃更改。 我将向您展示如何处理UIViewController的第三项,但是以可以扩展到其他UI组件的方式。 我们将创建一个简单的协议,然后将其扩展为我们的用例。 前言 我们将使用出色的ActionKit库,通过不使用UIBarButtonItem上的target/action来使我们的代码更好。 可以使用的替代方法是RxSwift的rx_tap 。 避免target/action也意味着我们不参与Objective C运行时(库正在这样做并充当包装器),这意味着我们不必在协议上使用@objc进行方法@objc 。 协议书 由于我们是iOS的超级明星开发人员,因此我们将使用Swift及其出色的功能以侵入性最小且可重复使用的方式实现我们的目标。 首先,让我们定义一个对象可编辑的协议。 由于我们希望匹配未做任何更改时出现的后退按钮的行为,因此,我们将利用UINavigationController显示后退按钮并处理UIViewController的navigationItem 。 要指出的一点是,在设置leftBarButtonItems时,也禁用了滑动后退功能, leftBarButtonItems是我希望的行为,因为希望用户如果希望后退它们,则取消编辑。 会更反应吗? 我在iOS中使用Rx放松,所以让我们继续制作一个可绑定的接收器以进行edit(make: Bool) 现在我们可以删除对UITextFieldDelegate的使用,, 时髦! 这是一个示例,由于有了Swift的强大功能,我们无需在代码库中进行侵入性更改(即,强制每个编辑View Controller的子类都将EditViewController子类化)。 您可以通过使用协议扩展进一步扩展Editable并将其添加到自己的自定义类或其他UIKit组件中。 代码可以在这里找到。 雨燕快乐!