iOS开发笔记15:地图坐标转换那些事、block引用循环/weak–strong dance、UICollectionviewLayout及瀑布流、图层混合
1.地图坐标转换那些事
(1)投影坐标系与地理坐标系
地理坐标系使用三维球面来定义地球上的位置,单位即经纬度。但经纬度无法精确测量距离戒面积,也难以在平面地图戒计算机屏幕上显示数据。通过投影的方式可以将其转换成平面的投影坐标系,不同的投影方式可能会带来不同的变形及误差,类似于把一个橘子的橘子皮剥开摊平到桌面。




GPS以及iOS系统定位获得的坐标是地理坐标系WGS1984,Web地图一般用的坐标细是投影坐标系WGS 1984 Web Mercator,国内出于相关法律法规要求,对国内所有GPS设备及地图数据都进行了加密偏移处理,代号GCJ-02,这样GPS定位获得的坐标与地图上的位置刚好对应上,特殊的是百度地图在这基础上又进行一次偏移,所以在处理系统定位坐标及相关地图SDK坐标时需要转换处理下,根据网络资源,目前有一些公开的转换算法。
(2)系统定位坐标显示在原生地图、谷歌地图或高德地图--WGS1984转GCJ-02
苹果地图及谷歌地图用的都是高德地图的数据,所以这三种情况坐标处理方法一样,即将WGS1984坐标转换成偏移后的GCJ-02才可以在地图上正确显示位置。
const double a = 6378245.0;
const double ee = 0.00669342162296594323; + (CLLocationCoordinate2D)transform:(CLLocationCoordinate2D) latLng
{
double wgLat = latLng.latitude;
double wgLon = latLng.longitude;
double mgLat;
double mgLon; if ([self outOfChina:wgLat :wgLon ])
{
return latLng;
}
double dLat = [self transformLat:wgLon-105.0 :wgLat - 35 ];
double dLon = [self transformLon:wgLon-105.0 :wgLat - 35 ]; double radLat = wgLat / 180.0 * M_PI;
double magic = sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * M_PI);
dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * M_PI);
mgLat = wgLat + dLat;
mgLon = wgLon + dLon;
CLLocationCoordinate2D loc2D ;
loc2D.latitude = mgLat;
loc2D.longitude = mgLon; return loc2D;
} + (BOOL) outOfChina:(double) lat :(double) lon
{
if (lon < 72.004 || lon > 137.8347) {
return true;
}
if (lat < 0.8293 || lat > 55.8271) {
return true;
}
return false;
} + (double) transformLat:(double)x :(double) y
{
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y +
0.2 * sqrt(fabs(x));
ret += (20.0 * sin(6.0 * x * M_PI) + 20.0 *sin(2.0 * x *M_PI)) * 2.0 /
3.0;
ret += (20.0 * sin(y * M_PI) + 40.0 *sin(y / 3.0 *M_PI)) * 2.0 / 3.0;
ret += (160.0 * sin(y / 12.0 * M_PI) + 320 *sin(y * M_PI / 30.0)) * 2.0 /
3.0;
return ret;
} + (double) transformLon:(double) x :(double) y
{
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x));
ret += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 /
3.0;
ret += (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0;
ret += (150.0 * sin(x / 12.0 *M_PI) + 300.0 *sin(x / 30.0 * M_PI)) * 2.0 /
3.0;
return ret;
}
(3)使用百度地图SDK
使用百度地图SDK,定位也使用sdk中提供的方法,则获得坐标是百度在GCJ-02基础上再一次偏移的坐标,如果要将定位坐标显示在苹果地图上,则需要转换成GCJ-02下的坐标,JZLocationConverter提供了三种坐标间的转换方法,
(4)参考
2.block引用循环及检测方法&weak–strong dance
使用block需要注意避免引用循环造成内存问题,如图所示,对于strong属性的property或者复用的cell,都是被self持有或者说强引用的,在使用block回调前,需要将self声明为一个weak类型的weakSelf再进行使用,否则将造成引用循环。


但并不是所有block回调处理中都需要使用weakSelf,例如self并没有强引用vc,在vc里使用self,是不会造成引用循环的。

对于类似这种可能造成引用循环的地方,使用Instrumens的Leaks工具是检测不出来的,比较便捷的方法是在controller检测“dealloc”是否执行,当然也有可能是其它原因造成,但只要有引用循环发生则controller肯定无法释放,“dealloc”也是无法执行的。
当然,这是一般情况,有一些特殊情况例如多线程下block,block里的weak变量执行指令前可能已经被释放掉了,这时可以对其__strong 一下,这样系统会在block执行完成后再释放该变量。
3.UICollectionviewLayout及瀑布流
目前用到了一些第三方的UICollectionviewLayout类库,例如CSStickyHeaderFlowLayout,提供header悬停及下拉放大的视差效果等
通过自定义UICollectionviewLayout可以灵活自定义很多布局效果,以经典的瀑布流为例。

其特点是cell的高度不一致,首尾间隔要保持一致,如此一来就需要自定义layout来调整cell的布局位置。
这里cell高度随机生成为40-140之间的数值。

(1)计算并缓存相关布局信息

重点是计算布局这里,第一行Y值都相同,但后续每个cell的高度不同,需要去调整cell的位置,首先找到目前高度最小的那一列(排列第一行时,所有cell的Y值一致,将第一列当做高度最小的一列或者将顶部间距看成是一行高度一致的cell),将cell排列在此列下方,并更新此列的Y值,然后再继续找高度最小的一列,将cell排列在其下方并更新此列Y值,以此类推,不断寻找高度最小的那一列,将后续cell排列在其下方并更新这一列的Y值,即可完成布局,当然设置cell布局时还要将cell之间的间隔考虑进去。
(2)计算contentSize并生成布局
contentSize中关键是高度,这里取高度最大那一列的Y值即为collectionview的高度。

(3)参考
4.图层混合
使用Instruments中的Core Animation工具能够检测图层渲染和动画的相关问题,包括图层混合问题,即当多个图层叠加在一起,颜色不同时,处理这样的颜色混合情况会消耗GPU资源,监测发现这些区域会变红,其它正常区域为绿色

对于UILabel的图层混合问题,将其设置为与背景色一致并裁剪即可。(不会产生离屏渲染)

iOS开发笔记15:地图坐标转换那些事、block引用循环/weak–strong dance、UICollectionviewLayout及瀑布流、图层混合的更多相关文章
- iOS开发笔记6:图片轮播及其无限循环效果
平时APP中的广告位或者滚动的新闻图片等用到的就是图片轮播这种效果,实现方式主要有两种,一种是ScrollView+ImageView,另一种则是通过CollectionView,今天总结的是Scro ...
- iOS开发小技巧--键盘处理以及解决block造成循环引用的小技巧
- iOS开发笔记--什么时候调用layoutSubviews
iOS开发笔记--什么时候调用layoutSubviews 分类: iOS2014-04-22 16:15 610人阅读 评论(0) 收藏 举报 今天在写程序时候遇见layoutSubviews触发时 ...
- 【Swift】iOS开发笔记(二)
前言 这个系列主要是一些开发中遇到的坑记录分享,有助于初学者跨过这些坑,攒够 7 条发一篇. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民伯 ...
- 那些在学习iOS开发前就应该知道的事(part 2)
英文原文:Things I wish I had known before starting iOS development—Part 2 http://www.cocoachina.com/ios/ ...
- iOS开发笔记7:Text、UI交互细节、两个动画效果等
Text主要总结UILabel.UITextField.UITextView.UIMenuController以及UIWebView/WKWebView相关的一些问题. UI细节主要总结界面交互开发中 ...
- iOS开发笔记-两种单例模式的写法
iOS开发笔记-两种单例模式的写法 单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" ...
- IOS开发笔记(4)数据离线缓存与读取
IOS开发笔记(4)数据离线缓存与读取 分类: IOS学习2012-12-06 16:30 7082人阅读 评论(0) 收藏 举报 iosiOSIOS 方法一:一般将服务器第一次返回的数据保存在沙盒里 ...
- IOS开发笔记 IOS如何访问通讯录
IOS开发笔记 IOS如何访问通讯录 其实我是反对这类的需求,你说你读我的隐私,我肯定不愿意的. 幸好ios6.0 以后给了个权限控制.当打开app的时候你可以选择拒绝. 实现方法: [plain] ...
随机推荐
- c++中基类与派生类中隐含的this指针的分析
先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...
- window xp Apache与Tomcat集群配置--转载
转载地址:http://www.cnblogs.com/obullxl/archive/2011/06/09/apache-tomcat-cluster-config.html 一. 环境说明 Win ...
- Bucky – 免费开源的实时用户监控工具
Bucky 是一个开源的实时用户监控工具,用于衡量用户在浏览器中使用 Web 应用程序时的性能.它可以自动测量你的网页需要多长时间来加载,Ajax 请求需要多长时间和各个函数需要实行多久. 您可能感兴 ...
- hash函数为什么要选择对素数求余?
常用的hash函数是选一个数m取模(余数),这个数在课本中推荐m是素数,但是经常见到选择m=2^n,因为对2^n求余数更快,并认为在key分布均匀的情况下,key%m也是在[0,m-1]区间均匀分布的 ...
- MvvmLight框架使用入门(一)
MvvmLight是比较流行的MVVM框架,相对较为简单易用.可能正因为简单,对应的帮助文档不多,对初学者就不够友好了.这里会用几篇随笔,就个人对MvvmLight的使用经验,来做一个入门的介绍. 第 ...
- [操作系统实验lab3]实验报告
[感受] 这次操作系统实验感觉还是比较难的,除了因为助教老师笔误引发的2个错误外,还有一些关键性的理解的地方感觉还没有很到位,这些天一直在不断地消化.理解Lab3里的内容,到现在感觉比Lab2里面所蕴 ...
- 转载---QRcodeJS生成二维码
QRCode.js QRCode.js是依赖JS生成二维码的.主要是通过获取DOM的标签,再通过HTML5Canvas绘制而成,不依赖JQ 获取QRCode.js Github-Page:qrcode ...
- ChartDirector应用笔记(二)
关于Simple Bar Chart Simple bar chart是XYChart大类中的Bar chart类型中的最简单的例子.Bar chart的表现形式简单直观,在数据量较少.数据维度简单等 ...
- PHP 简单处理--文件下载--文件上传
文件下载部分 从 down 目录下下载,先获取目录下所有文件,再为每个文件添加download 信息,主要是文件名,后缀的关系. 分两部分,down_1.php 部分初始化,点击download 则跳 ...
- thread_Semaphore信号量
Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制. 使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数. 一个计数信 ...