使用Google Maps样式向导自定义MapKit的MKMapView

定制MKMapView外观并不是那么容易。 在这里,我将告诉您如何使用代码示例完全自定义它。 上周,我一直在尝试自定义MKMapView,但这是不可能的。 如果您使用MapKit已有一段时间,您可能会知道,当需要叠加层和折线时,它很棒,并且它具有许多有用且非常有趣的功能。 但是事实是它不是非常可定制的。 我需要使地图看起来与使用Google Maps构建的Uber相似,并且我不想更改为Google Maps,因为我有很多事情是使用MapKit完成的。 深度重构并不是一个好的选择。 经过大量搜索和阅读StackOverflow线程后,我提供了一个解决方案。 瓷砖覆盖 如果您以前从未听说过瓷砖叠加层,可以告诉您它们可以完全自定义您的地图。 该机制很简单,每当地图需要显示“平铺”(瓷砖上的一小块区域)时,它都会向服务器请求该图块的图像。 称为“平铺服务器”的服务器将返回图块图像,并将其显示在地图上。 简单。 这是一些免费的磁贴服务器的列表。 在iOS中,可以使用MKTileOverlay完成此操作。 磁贴叠加层需要一个URL。 该URL遵循以下架构: https://somecoolserver.com/path?x= {x} &y = {y} &z = {z} 看到那些参数了吗? {x},{y}和{z}? {x}和{y}参数将由地图视图使用其所请求的图块的坐标填充,而{z}将由缩放级别填充。 Google样式向导 Google的Google Map Styling Wizard做得非常出色。 我必须认识它。 它具有简单的界面,功能绝对强大。 使用此向导,您可以创建可从Google Maps SDK导入的配置JSON,或者获取可显示静态地图(图像)的URL。 但是在这一点上,我面临着一个大问题。 好的,这很好,我可以根据需要自定义地图,但是如何将其导入到MKMapView中呢? 我以为我必须将该JSON文件转换为图块叠加服务器URL架构。 该解决方案随StackOverflow一起提供。 请参阅此http://stackoverflow.com/questions/29692737/customizing-google-map-tile-server-url。 该线程的末尾是用javascript编写的简短脚本。 所以我首先要做的就是将该函数复制到一个js文件中,并使用node.js执行它。 有效! 但这不是很方便。 想象另一个开发人员必须做同样的事情。 每当他想对地图进行任何更改时,他都将需要执行该node.js脚本。 最终的解决方案 最后,我翻译了该脚本以进行快速处理,并将其作为cocoapod上传。 该吊舱称为MapKitGoogleStyler,您可以在以下位置找到它:https://github.com/fmo91/MapKitGoogleStyler。 将其嵌入到项目中具有一些优势,例如将json保存在直接在项目中的文件中。 […]

Swift — 4 —核心数据—第4部分编写单元测试用例

嗨,我回来了,我最喜欢的主题核心数据带有单元测试😀。 希望您对编写单元测试用例有一些基本的了解。 我们将使用XCTestCase类和XCTest框架来编写单元测试并对其进行测试。 源代码在本教程的底部。 单元测试对于测试代码非常有用,而无需在设备或模拟器上启动代码并转到特定的视图控制器。 我们可以非常快速地测试所需的代码,而无需在设备/模拟器上运行。 它将节省大量的开发时间。 一旦您采用了单元测试,它将激发您按照MVVM,依赖注入和适配器模式等编写小的可测试代码。 我将继续第3部分。请从此处下载第3部分源代码。 我在CoreDataManager类中添加了另一个方法。 只需复制以下方法并粘贴到CoreDataManager类中即可。 此方法使用获取请求来获取个人记录并删除它们。 / *在需要刷新人员数据的情况下,可以调用此方法* / func flushData(){ 让fetchRequest:NSFetchRequest = NSFetchRequest (实体名称:“人”) 让objs =试试! CoreDataManager.sharedManager.persistentContainer.viewContext.fetch(fetchRequest) 例如,让obj作为objs中的NSManagedObject { CoreDataManager.sharedManager.persistentContainer.viewContext.delete(obj) } 尝试! CoreDataManager.sharedManager.persistentContainer.viewContext.save() } } 现在,让我们开始设置单元测试: 我们还需要在测试目标中添加PersonData.xcdatamodeld。 请参考所附的屏幕截图,并仔细查看右侧底部的Target Membership: 让我们复制下面的代码,并将其粘贴到PersonDataTests.swift中。 它看起来应该像这样: // // PersonDataTests.swift // PersonDataTests // //由Alok Upadhyay在18/3/28创建。 //版权所有©2018 Alok。 版权所有。 // 导入XCTest 导入CoreData @testable导入PersonData class PersonDataTests:XCTestCase […]

Swift编程入门第2部分—值类型,引用类型,指针和集合类型

之前,我们讨论过变量,常量和类型。 开始Swift编程第1部分-变量,常量和类型 我知道那里有很多教程,Apple有很好的学习Swift的资源,包括他们的WWDC视频…… medium.com 在这一部分中,我们将讨论几个特殊类型,但是为了深入实现这一点,我们必须首先讨论值类型,引用类型和指针。 提醒一句,指针可能是最难掌握的概念之一,我会尽力而为。 初步的东西 是的,我们上次这样做,现在我们将再次进行。 上一次我们讨论了内存以及它如何以块,字节和位的形式排列。 我想在这里对此进行扩展,并为您提供一些有关内存工作原理的直观表示。 让我们创建一个包含值Hello的字符串。 我们之前没有做过什么特别的事情。 我在上一篇文章中告诉您,内存具有价值。 如果我们可以看一下该内存,它将像这样存储: 我敢打赌,您要问的是\0在字符串的末尾。 这称为空终止符。 斜线表示程序已准备好执行命令,零表示没有任何意义。 这是字符串值的存储方式,并在字符串允许使用空格的同时让程序知道字符串何时完成。 数字略有不同。 数字存储为二进制数字。 二进制很容易理解,从内存块最右边的1开始,向左移动,每次将当前值乘以2。 如果您对图形卡或记忆棒有所了解,这就是为什么我们会看到8位(Atari,NES),16位(Sega Genesis,SNES),32位(PlayStation),64位(Nintendo 64)和以此类推。 在二进制中,如果位置为0,则表示关闭,这是错误的。 如果位置为1,则为开或为true。 基于此逻辑,我们只需要计算位置为1的位置即可。 您能找出上图中的数字吗? 现在,这是一组8位内存,是的,它是一个完整的内存字节。 之前我说过字符串中的每个字符都是2个字节,这意味着我们使用16位来存储字符。 16位二进制文​​件的最大值为256。但是,当我们谈论位置时,我们总是从0开始。因此16位二进制数的范围是0-255 。 我敢打赌,您在问我们如何才能使字符超出此范围。 好吧,在这种情况下,我将带您到ASCII表,您可以在其中查看自己的值。 您甚至还会看到隐藏的字符,例如空终止符/0如上所示。 内存将值存储在静态内存中,该位置称为stack ,而该位置称为堆。 可以快速访问静态内存和堆栈内存,但是从堆访问内容的速度很慢(以计算机时间计)。 尽管对您来说似乎并不慢,但从堆栈加载可能要花费一毫秒或更短的时间,而从堆加载可能要花费10毫秒。 在介绍事物时,我将解释它们的实现位置,以便您以后知道将其放置在何处。 值类型 值类型很容易学习,这就是我们自然地思考事物的方式。 当您描述某些事物时,例如说一个高尔夫球,您可能会说一个高尔夫球很小,或者一个篮球是橙色。 值类型是包含您要查找的值的内存。 如果您将值8存储在内存中,然后再要求输入该值,则会收到数字8,非常简单,对吧? 字符串,整数,双精度型,浮点型和布尔型都是值类型,还有更多,但是我们还没有涉及它们,到目前为止,我所有的例子都是值类型。 值类型存储在堆栈中。 如果在它们前面添加静态元素,那么它们会添加到静态内存中,而不仅仅是在各处都这样做,这会带来另一个问题,我将在后面讨论。 参考类型和指针 引用类型在某种程度上类似于值类型,因为它们可以为您提供与值类型相同的值,但它们可以为您提供更多的价值。 引用类型使用指针为您提供所需的值。 之所以要准备这么长的篇幅,主要是因为本节有保证。 如果您看一下C和Objective-C程序,您会发现到处都使用了指针,看起来像这样 集合类型 继续本部分的最后一部分。 […]

使用IOS动画中的约束…

在制作子视图动画时,通常使用该子视图的约束来更改其位置或值。 基本上,“动画”定义为值或位置的变化。 IOS中的每个视图都包含一个称为“ constraints ”的属性,该属性仅是get,它给出了该视图所持有的所有约束。约束由最近的视图持有,该视图包含约束中的两个项目。 子视图之间/之间连接的约束通常由其超级视图持有。 视图所包含的所有约束均在大小检查器中列出。 子视图与其父视图之间的约束由其父视图保持。 因此,在使用约束进行动画处理时,首先我们需要找到哪种视图持有我们要设置动画的约束。 对于动画,意味着更改约束或其乘数/常量值,首先我们需要获取所有现有约束。 通过依赖约束,选择包含所需约束的视图。 要获取约束,我们可以使用仅获取属性“ constraints”,它提供了一系列约束。 为了获得每个约束,我们可以遍历结果数组。 注意:像“约束”属性一样,乘数也是“仅获取”值。 就像我们为现有约束更改常量值一样,我们无法更改乘数值。 因此,要更改乘数值,我们需要访问该约束,使其为“ .active = false”。 通过将其激活设置为false,在下一个布局更新中,自动布局引擎将删除该约束。 因此,在定义新约束之后,将其设置为“ .active = true”。 2.我们可以在定义约束的同时为约束赋予标识符。 稍后,我们可以使用“ constraints”属性来获取约束,然后可以通过使用其标识符值来访问所需的约束。 3.我们还可以定义两个具有两个不同值,具有不同标识符和优先级的约束。 但是在任何给定时间都应该只有一个处于活动状态。 因此,从已定义的这两个约束中,将其卸载。 然后,您可以根据需要通过访问这些变量来随时激活一个。

在Swift中的UITableView(客户端和服务器端)中加载更多

调用Rest API并在UITableView中滚动时检索大量数据 介绍 我一直想知道移动应用程序如何通过在需要时以便捷的方式加载向下滚动来加载更多数据,从而管理UITableView和UICollectionView显示的数据。 我还试图从服务器端以及客户端对这个问题找出一个全面的观点。 好吧,所以我们在这里尝试承担这个常见问题的负担,并以这种方便的方式简化答案。 我们走吧。 👶 场景: 我们将使用PHP Laravel框架(服务器端)实现Rest API,它将在每次调用中返回最新的feed作为大量数据(20项)。 迅速的代码可以使用API​​向下滚动以加载更多数据。 服务器端 : 该API将返回大量数据,例如ex。 每个呼叫分别以降序排列20个订阅源。 这样,第一个呼叫的最新20个提要,第二个呼叫的最近20个提要之前的下一个..依此类推。 take(20) :将查询返回的结果数限制为20。 skip(0) :跳过查询中给定数量的结果。 这样,在第一个调用中, skip(0)不会跳过任何提要,而在第二个调用中, skip(20)会跳过前20个提要,并检索最近的2o个提要之前的下一个提要,依此类推…… skip(40),跳过(60) …等等。 公共函数 getData($ bulk_no) { return Feed :: orderBy ( ‘created_at’ , ‘desc’ )-> skip($ bulk_no)-> take(20)-> get(); } 客户端 : 嗯,有许多基于swift的库用于执行HTTP请求。 其中最好的之一是Alamofire。 由于其简单性并减轻了网络任务的负担,并提供了用户友好的请求/响应方法。 ViewController将实现UITableView,在cellForRowAt委托方法将如下所示: var bulk_no = 0 […]

Swift 3和缺乏递归协议约束

经过更多的挖掘之后,我终于确认它是Swift中的当前限制。 在此处,此处和此处查看未解决的问题以及有关此主题的讨论。 我在Stack Overflow上寻求了临时解决方法的建议,直到Swift支持。 不幸的是,还没有添加任何答案,但是投票和明星的数量让我觉得其他人也在为此而苦苦挣扎。 无论如何,我需要一个临时的解决方法,我能想到的最好的方法是以下方法,也可以在SO帖子中看到: 主要思想是通过使某人符合Any来打破递归性。 这不是理想的,但是暂时可以接受。 在我的示例中,某人是一个delegate ,该delegate基本上是某种“中介对象”,用于处理View和ViewModel之间的ViewModel 。 拥有此delegate的唯一缺点是,需要从创建对象的“外部”进行设置,并且不能在View实现中进行设置。 如果尝试这样做,则会出现错误Cannot assign value of type View to type _? 会出现。 但是,通过这种方法,我们无需进行大量专业化操作即可获得正确的类型。 当然,可以添加更多协议以具有更多抽象,但是将应用相同的解决方案。

在Swift 4中关于JSON解析的简短思考

首先,将Codable定义为typealias Codable = Decodable&Encodable,我们采用两种必需的协议: 可解码 :解析JSON(获取响应) –通过解码JSONData,我们将接收/读取数据 2. Encodable :生成JSON(响应后) –要将可编码 类型转换为Data 。 它适用于基本类型(Int,String和Float等),某些基础类型(数据,URL,日期等)以及数组,字典和可选参数(枚举)。 – NSData – NSString – NSNumber – UInt – Int – Float – Double – Bool – NSDate – NSArray – NSDictionary 为什么? 在我们的数据管理器中简化依赖关系 将数据结构转换为JSON数据从未如此简单(hmmmm ..),允许开发人员将JSON数据存储到磁盘或将其编码为URLRequest的httpBody :)。 您可以编写一个使用外部来源的JSON或通过存根进行测试的应用。 这里的开始问题是您在应用程序中建模的概念的结构与JSON生产者建模的概念之间的不一致。 在您的应用中更改和使用JSON结构的一些示例: 使用CodingKey更改名称属性 2.通过手动编码和解码简化复杂的结构 3.使用嵌套数据(数组JSON内的数组) 对于1.,即使我们不必解析JSON表示形式的每个元素,我们也需要创建与JSONData中名称相同的属性,或者使用CodingKey重命名它们以直接存储基本示例。 到目前为止很简单!🤠🤠 struct SurfBoard:可编码{ var品牌:字符串 var size:大小 枚举CodingKeys:字符串,CodingKey […]

VINchain iOS App的Alpha版本已准备就绪并可用!

尊敬的VINchain社区, 众所周知,最近我们一直在忙于开发区块链和OBD设备,现在我们为您提供了很棒的更新。 我们正在发布VINchain iOS应用程序。 你们中有些人已经等了很久了。 您现在可以在Apple商店下载它并签出! (https://itunes.apple.com/by/app/vinchain-app/id1366593531?mt=8) 借助我们的应用程序,您将能够查看您感兴趣的任何汽车的历史记录。您将在这里轻松获得所有奖金和折扣。 无需携带很多卡,仅您的电话就足够了! 通过分析驾驶风格,您将改善驾驶体验,并且在开始驾驶之前,您将确保自己的汽车处于良好状态! 在我们的应用程序中,您将可以存储所有数据,还可以决定要与系统共享哪些数据,以及要保留哪些数据为私有数据,但是共享得越多,您获得的代币奖励就越多得到。 不要错过您签出我们的应用程序的机会。 参加汽车革命就像在手机上下载我们的应用程序一样简单! 创建新帐户并检查任何汽车的历史记录。 您还将免费获得25个代币! 您将可以将它们用于报表或保存以备将来使用! 保持最新: 加入我们的公告小组,了解所有最新消息和最新动态。 加入社交媒体上的对话: 电报 推特 脸书 Blogspot 介质 比特币谈话 Github

iOS商店现已提供Metaverse LightWallet iOS版本!

我们很高兴地宣布 ,Metaverse lightwallet现在可以在iOS商店中使用! MyETPWallet是一种轻型钱包,为用户提供了比全节点桌面钱包更简单的替代方案。 用户可以在不同步所有块的情况下发送和接收资产,并且由于用户的私钥存储在本地设备上,因此可以确保安全性。 用户可以检查其投资组合中的交易历史记录,并且可以在应用程序中发送和接收MST(反向智能令牌)资产。 MyETPWallet(iOS版本)的功能是: ·ETP交易 ·数字身份(头像) ·智能令牌(MST)的发行和转让 ·可识别令牌(MIT)注册 ·在多个主题之间切换 ·多国语言支持 您可以在https://itunes.apple.com/us/app/myetpwallet/id1354404036上找到应用商店的链接,或者也可以转到iOS应用商店并搜索“ MyETPWallet”。 如果您已经通过https://www.myetpwallet.com/或通过全节点钱包创建了帐户,则可以通过扫描OR代码或导入备用字词将现有帐户导入iOS应用。 在Metaverse,我们认真对待社区反馈。 请在https://github.com/mvs-org/lightwallet/issues向我们发布报告和错误,我们非常感谢。 要随时了解Metaverse,请在Github,Facebook,Twitter,Youtube,Telegram,Reddit,Discord和我们的博客上关注我们! 希望您喜欢新版本!

一个没有Storyboard的UIViewController和UIViews(swift 3)

在Xcode中,情节提要可以轻松构建ViewController,Views,Button,Label等,而无需编写太多代码。 我们可以使用IBOutlets和IBAction将这些视觉元素连接到我们的代码。 虽然这样做有助于简化构建应用程序的过程,但它也有其缺点。 对于初学者来说,使用Storyboard可以抽象出代码中每个对象的状况。 了解TableView或ViewController作为对象的工作方式非常重要。 使用版本控制(例如git)时,情节提要板也会引起一些重大问题。 如果多个合作者对情节提要进行了更改,那么您将要处理XML文件中的冲突,这是一个很大的痛苦。 最后,如果您有大型应用程序,则根据您对视图和约束的管理方式,故事板上的内容可能会变得非常混乱。 查看具有20个视图且每个视图都具有自定义约束的视图控制器通常不是一个不错的站点。 在本文中,我将介绍如何在不使用情节提要的情况下使用初始UIViewController,一些UIView和UICollectionView来启动和运行应用程序。 配置 创建项目时,Xcode为我们提供了一个默认的情节提要文件,并附加了一个视图控制器。 我们需要做的第一件事是告诉Xcode我们不想使用情节提要。 为此,我们可以删除main.storyboard文件,然后选择项目,并在部署信息中删除“ main”,以便“ main interface”为空白。 您应该注意,main既是初始情节提要板文件的名称,也是“ main interface”选择的名称。 通过从“主界面”中删除“ main”,我们告诉项目不要将该文件作为初始ViewController。 如果我们现在尝试运行我们的项目,则由于应用程序没有初始视图控制器,它将崩溃—我们在didFinishLaunchWithOptions函数的AppDelegate中修复了该问题。 在这里,我们使用自定义类ViewController和window属性(这两个属性在项目中默认提供给我们)来创建初始视图控制器。 您还可以使用您自己的自定义类(即UIViewController的子类)来设置初始视图控制器。 用代码构建应用 让我们从简单开始,并将视图作为标题添加到视图控制器的顶部。 首先,我们创建一个UIView类型的变量,并在viewDidLoad中对其进行初始化。 从那里,我们可以将其添加到ViewControllers的视图中(所有视图控制器都带有一个名为view的view属性,该属性填充了视图控制器)。 现在,我们可以添加约束以将其放置在ViewController的视图顶部,并更改背景色,以便在运行应用程序时可以看到它的位置。 注意: 初始化视图时,可以使用带有CGRect的初始化程序。 使用此初始化程序将在您指定x,y,宽度和高度的任何位置放置和调整视图的大小。 我更喜欢使用约束,因为它支持多种屏幕尺寸。 现在我们已经设置了标题视图,可以在其中添加标签了。 让我们按照相同的过程创建标签。 由于我们正在使用标签,因此可以使用其他一些属性,例如文本大小和对齐方式。 在情节提要中,您可以使用属性编辑器来调整这些值,但我们也可以在代码中对其进行调整。 请注意,我们将标签添加为headerView的子视图,并且还将其限制为headerView而不是视图。 将视图添加到其他视图时,重要的是考虑视图层次结构以及应将其约束到什么。 以后添加的视图将与之前添加的所有视图重叠。 最后,让我们添加一个收藏夹视图。 在集合视图中,我们将使其显示为0到99。由于集合视图是更为复杂的视图类型,我们需要以不同的方式对其进行初始化,提供数据源和委托,并为其提供内容以填充细胞。 我将首先清理viewDidLoad并添加集合视图,就像添加其他视图一样。 像这样运行应用程序会导致崩溃。 集合视图在初始化时需要更多信息。 该错误告诉我们必须使用非nil布局参数初始化集合视图。 查看可用的初始化程序,我们可以使用CGRect和UICollectionViewLayout对其进行初始化。 现在,我们可以设置数据源,委托和自定义单元格,以用信息填充集合视图。 为此,我将创建几个新的swift文件和类,以防止ViewController类变得太大。 您可以查看此github以查看完整的项目。 设置好这些类后,我们需要将它们链接到集合视图。 在情节提要中,您可以在检查面板中执行此操作,但在代码中将如下所示:(最后3行) NumbersCollectionViewDelegateAndDataSource类包含所有信息和必需的方法,这些信息和必需的方法将成为NumbersCollectionView的委托和数据源。 然后,我们用与在委托和数据源类中调用的useuseIdentifier相匹配的reuseIdentifier注册该单元。 […]