SWIFT UITabBarController

在iOS中,TabbarController是一种很常见的视图控制器,UITabBarController支持用户在一组不同的屏幕之间切换,每个屏幕都代表程序的一种不同的操作模式。 UITabBarController通常最为整个程序的rootViewController,而且不能添加到别的视图控制器中,UITabBarController主要用来管理用户提供的包含各种内容的子视图控制器,而每一个子视图控制器则负责管理自己的视图层级关系。 当用户的应用打算提供一些相同等级、系列性的不同界面时,UITabBarController将是你最好的选择,你可以设置多个Tab,每个Tab对应一个UIViewController。当某个Tab被点击时,UITabBarController就会选中该Tab,并显示该Tab对应的视图控制器中的内容。 创建一个UITabBarController 1. 创建四个子视图控制器 这里以微信为例,首先我们新建一个项目,并且添加四个新的视图控制器类: WeChatViewController、AddressBookViewController、FindViewController和MineViewController。 然后我们分别在这四个viewController中设置各自的属性,用于区分。 WeChatViewController.swift 其他的三个只是改了背景颜色、label的文本,这里就不一一贴了。 然后我们在Assets.xcassets文件夹中添加4张Tab的图片,这个是我之前在微信里扒出来的。 2. 实现UITabBarController 添加了图片,创建了4个ViewController之后,就可以创建UITabBarController了,我们可以在AppDelegate.swfit文件的didFinishLaunchingWithOptions方法中创建: a. 上面代码中可以看出,是在AppDelegate.swift文件中,我们创建了4个视图控制器,并分别设置他们的tabBarItem的未选中图片、选中图片和文本。 b. 在UIImage()的后面为什么添加withRenderingMode的实例方法呢?各位也可以试一下,不加的情况下,图片会变成蓝色,失真了,UIImageRenderingMode枚举有三个属性: UIImageRenderingMode 说明 automatic 根据图片的使用环境和所处的绘图上下文自动调整渲染模式 alwaysOriginal 始终绘制图片原始状态,不使用Tint Color。 alwaysTemplate 始终根据Tint Color绘制图片,忽略图片的颜色信息。 c. 可以试一下没有设置tabBarController.tabbar.tintColor的情况下,选中状态会默认是蓝色。 d. 放出最后的图片看一下: 3. 改变TabBar的位置 UITabbarController的tabbar默认是放在屏幕底部的,如果项目有特殊要求,也可以修改它的位置,比如把它放到顶部去: e. 可以看到,状态栏有遮挡了一部分tabbar,我们可以去掉状态栏: 在General中有一个Hide status bar的单选框,勾选,info.plist中会新增一条Status bar is initially hidden ,然后在下面再添加一条View controller-based status bar appearance,就可以了,这个是有自动补全的,所以不用担心拼错。然后再跑一下项目看一下,没有状态栏了。 4. 修改UITabBarController的索引 在使用TabBarController时,一般打开APP会默认呈现的是第一个Tab的viewController,但有时我们可能需要向用户呈现的是第2个其他两个,这时,我们可以通过设置tabbarController的selecteIndex属性来设置: a. 跑下项目,会发现打开项目后默认呈现的是第三个viewController。(索引是从0开始数的~~~~) …

SWIFT中viewcontroller关系

写在一切最前, 在SWIFT中, View Controller(以下都叫VC) 有一定的不同的逻辑关系. 主要是包含两种: 1, 具备父级关系, 比如Tabbar Controller中的每个页面和Base页面的关系, 从子页面调用到父页面可以使用self.parent来获取父页面对象. 通过print(debugDescription)查看. 2, 平级传递关系, 不存在父子关系中的VC跳转. 这部分VC中, self.parent属性为nil, 而需要通过self.presentingViewController来获取上级VC. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

GOOGLE S2算法简介

https://zsr.github.io/2016/10/17/Google-S2/ Google S2作用: 根据多边形的边界区域映射成由许多一维数值构成的集合,这样就可以由这个集合代替多边形区域,便于后续计算。典型的可以将不同国家(或者地区)的边界区域(经纬度)计算成一维数值的集合,可以用于判断该区域的任何一个坐标是否包涵在内,简单的说就是地理定位。 s2库提供了一个Cell的概念,每个Cell相当于一个单元格,在一个单元格内的所有Point,都可以算出同一个CellId。同时可以认为,一个Polygon可以用一个Cell的集合来表示。那么这时的步骤就是通过区域的坐标,来初始化其内包含的所有的CellId,将这些CellId的id放入redis中做key,对应的value是区域名称(譬如,上海浦东新区),构建完全国范围的CellId后,查询用户的区域就可以通过用户的坐标获得一个CellId,然后去redis中查询,在使用LocalCache后,基本就没有什么计算成本,完全可以满足性能需求。 操作步骤: 1)首先获取地域图形的坐标点集合,可以从Natural Earth网站获取全球的坐标元数据(.shp文件)。2)解析shp文件,生成区域坐标集合,这里选择pyshp(解析shp文件的python插件),这里需要注意:同一个国家可能包涵多个区域(muti Polygon),需要分开处理。下载地址:https://pypi.python.org/pypi/pyshp/3)使用Google S2将多边形的边界坐标集合转化为一维数值集合,代表这个多边形的覆盖区域。 S2原理: 1234567891011 S2RegionCoverer coverer = new S2RegionCoverer();ArrayList<S2CellId> covering = new ArrayList<S2CellId>();coverer.setMinLevel(minLevel);coverer.setMaxLevel(maxLevel);coverer.setMaxCells(1000000);S2Polygon s2Polygon = S2Polygon.makePolygon(polygonValue);//getCovering()表示可以最小程度覆盖整个区域,外接多边形coverer.getCovering(s2Polygon, covering);//getInteriorCovering()表示最大程度填充整个区域,内接多边形// coverer.getInteriorCovering(s2Polygon, covering);System.out.println(“covering of size:” + covering.size()); 这里采用getCovering()外接多边形模式,避免多边形区域有盲点。MinLevel=9,MaxLevel=14 说明:MaxLevel最多可以设置30级,每升一级精度提升接近4倍,14级单个Cell可以表示范围:200平米~400平米,层级越高,构建越慢。 S2需要将地理位置表示为计算机可以理解的方式,即二进制码的表示,所以我们的目标就是用二进制码来表示三维空间。如何来做呢?需要进行降维。 1) 首先从三维降到二维,我们将地球放在一个正方体中,假设地球中心发光,光线穿过球体表面到达正方体平面的点就是球体表面的点的投影。于是我们就可以将地球投影到正方体的六个正方形表面。 通过投影我们可以将三维球体映射到二维平面,但是这个方法有一个问题,就是投影长度的比例不同。水平方向上的投影长度比上下两端的投影长度小,这就造成了投射面积不均匀,会影响以后对地图的切分。解决方法就是再进行一次区间转换,对长度进行微挑,将长的拉短,短的拉长,尽量使投影面积分布均匀。 2) 将二维变成一维。我们有很多点组成的正方形平面,如何对这个平面进行一维表示呢?方法就是遍历,比如我们就可以用00 01 10 11来表示下面四个点组成的平面。将这种方法不断扩展到极限,我们可以得到填充整个二维平面的一条曲线,这就是著名的希尔伯特曲线(Hilbert Curve)。希尔伯特曲线可以把二维平面映射到一条线段上,它还有一个优势就是可以保存局部性,即空间位置相近的点在希尔伯特曲线上的位置也是相近的。 可以发现位置相近的二维坐标在一维线段上面也是邻近的。 3) 创建cell集合: 简单来说,就是将一个能完整覆盖多边形面积的cell,不断的划分(4块cell),如果4快仍然全部与多边形相交则继续划分,否则有一个或多个cell不与多边形相交则抛弃,直至最大划分到maxLevel。可以发现如果maxLevel设置的越大,则精度越高(测试效率来看,maxLevel设置为14,15级已经比较精确,层级大于15级非常影响生成cell的效率)。 这里假设多边形区域为二维图形,如果需要对该图形进行覆盖,可能有以下可能: cell被包含在多边形内部 cell与多边形相交(有一部分在外面)图中大的cell和多边形相交,如果该cell的level已经达到maxLevel则停止划分,并将这个cell加入最后集合;如果这时候该cell的level小于maxLevel,则继续划分为4小块(不一定等分),可以发现有2个小的cell仍然与多边形相交,如果这2个cell层级已经达到MaxLevel则将这2个加入最终集合,否则继续划分,另外2个cell已经在多边形的外面则抛弃, 如果多边形内部可以完整填充一个cell(注意限制:minLevel,maxLevel; 级别越小,cell越大),则将该cell直接添加到集合中。比如这里设置的minLevel=9(一般只有面积非常大的国家才会有level=9),所以多边形区域所能生成的最大面积cell只有可能是level=9. 根据实际测试来看,像美国,俄罗斯相对面积比较大的国家,最小的level可以达到7(目测地球所有国家中最小的level就是7),也就是说这些国家的面积可以内涵完整的level=7的cell,这么做可以将许多高层次的cell由一个低层次的cell替代,减少了生成的cell数量同时表示的范围没有变化。 之所以这里选择minLevel=9,是为了以后定位方便,目前的定位是通过经纬度由Google S2生成CellId,再由这个CellId查询所有的CellId集合,如果有匹配的则命中。匹配的代码 …

Generating a model from an existing database

https://www.learnentityframeworkcore.com/walkthroughs/existing-database In previous versions of Entity Framework, you had the option to take a Database-First approach to modelling from an existing database, resulting in the generation of an EDMX file. Support for the EDMX file was dropped in Entity Framework Core in favour of using commands to reverse-engineering files for the model from an existing …

ubuntu下安装程序的三种方法

https://www.cnblogs.com/xwdreamer/p/3623454.html 在ubuntu当中,安装应用程序我所知道的有三种方法,分别是apt-get,dpkg安装deb和make install安装源码包三种。下面针对每一种方法各举例来说明。 apt-get方法 使用apt-get install来安装应用程序算是最常见的一种安装方法了,比如我要安装build-essential这个软件,使用以下,他会帮我把所有的依赖包都一起安装了。 sudo apt-get install build-essential 执行上述命令以后,我们可以看到一下信息,The following extra packages will be installed:表示所有需要再安装的依赖包。 sudo apt-get install build-essential password for enadmin: Reading package lists… Done Building dependency tree Reading state information… Done The following extra packages will be installed: binutils cpp cpp-4.6 dpkg-dev fakeroot g++ g++-4.6 gcc gcc-4.6 libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libc-bin …