iOS开发笔记15:地图坐标转换那些事、block引用循环、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)参考

iOS 地图坐标系转换

iOS经纬度偏移解决

2.block引用循环及检测方法

使用block需要注意避免引用循环造成内存问题,如图所示,对于strong属性的property或者复用的cell,都是被self持有或者说强引用的,在使用block回调前,需要将self声明为一个weak类型的weakSelf再进行使用,否则将造成引用循环。

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

对于类似这种可能造成引用循环的地方,使用Instrumens的Leaks工具是检测不出来的,比较便捷的方法是在controller检测“dealloc”是否执行,当然也有可能是其它原因造成,但只要有引用循环发生则controller肯定无法释放,“dealloc”也是无法执行的。

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)参考

iOS 瀑布流基本实现

4.图层混合

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

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

参考:Color Blended Layers

时间: 2024-12-20 00:40:52

iOS开发笔记15:地图坐标转换那些事、block引用循环、UICollectionviewLayout及瀑布流、图层混合的相关文章

iOS开发笔记6:图片轮播及其无限循环效果

平时APP中的广告位.或者滚动的新闻图片等用到的就是图片轮播这种效果,实现方式主要有两种,一种是ScrollView+ImageView,另一种则是通过CollectionView,今天总结的是ScrollView这种方式. 1.图片轮播效果实现 主要实现思路是:根据图片总数及宽高设置好ScrollView的大小,每切换一张图片相当于在ScrollView上进行一个图片宽度的移动行为,并加入定时器,实现自动轮播. 如图所示,设置好ScrollView及PageControl,ScrollView

IOS开发笔记-百度地图(第三方库)

最近做了百度地图,在导入SDK后遇到了一些问题 编译错误: linker command failed with exit code 1 (use -v to see invocation) 想了很多办法,查了很多资料,最后终于解决. 可能原因: 1. 有重复的.m文件,或者未导入 解决办法:有重复的删除即可 在工作左边导航栏Target-->Build Phases-->compile Sources中,第三库库的所有.m文件都添加到里面 2.Valid Architectures 的值 在

iOS开发之在地图上绘制出你运行的轨迹

首先我们看下如何在地图上绘制曲线.在Map Kit中提供了一个叫MKPolyline的类,我们可以利用它来绘制曲线,先看个简单的例子. 使用下面代码从一个文件中读取出经纬度,然后创建一个路径:MKPolyline实例. 1 -(void) loadRoute 2 { 3 NSString* filePath = [[NSBundle mainBundle] pathForResource:@"route" ofType:@"csv"]; 4 NSString* fi

iOS开发之 - 百度地图合成包(真机 , 模拟器通用)

百度地图一个是真机包,一个是模拟器包.下面是把真机包和模拟器包 合成为一个.以便开发 所有的包合成方法均是一样. 打开终端: lipo -create /Users/quancheng/Library/Developer/Xcode/DerivedData/LIBRARY-apqimrbblggwrncbmevvddjbhmcy/Build/Products/Release-iphonesimulator/libLIBRARY.a /Users/quancheng/Library/Develop

ios开发笔记----exc_bad_access(code=1, address=0x789870)野指针错误,假死debug状态

错误原因: exc_bad_access(code=1, address=0x789870)野指针错误,主要的原因是,当某个对象被完全释放,也就是retainCount,引用计数为0后.再去通过该对象去调用其它的方法就会出现野指针错误. 例如: Person *jerry = [[Person alloc]init];  //  retainCount引用计数为1 [jerry eat];  //  调用吃的方法 [jerry release];  //  释放jerry这个对象到 retain

iOS开发笔记-两种单例模式的写法

iOS开发笔记-两种单例模式的写法 单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" static ServiceManager *defaultManager; @implementation ServiceManager +(ServiceManager *)defaultManager{ if(!defaultManager) defaultManager=[[self allocWith

那些在学习iOS开发前就应该知道的事(part 2)

英文原文:Things I wish I had known before starting iOS development—Part 2 http://www.cocoachina.com/ios/20150611/12111.html 如果你还没读这篇文章的第一部分,请先读完了再来看第二部分. 那些在学习iOS开发前就应该知道的事(part 1):设计师设计出来了一个不错的引导界面,然而当我看到设计稿的时候,我们的app也没几天就要上线了…… 在第一部分中,我讨论了学习iOS开发的一些基本问

iOS陆哥开发笔记(五) (地图定位之官方API)

定位 要实现地图.导航功能,往往需要先熟悉定位功能,在iOS中通过Core Location框架进行定位操作.Core Location自身可以单独使用,和地图开发框架MapKit完全是独立的,但是往往地图开发要配合定位框架使用.在Core Location中主要包含了定位.地理编码(包括反编码)功能. 定位功能 定位是一个很常用的功能,如一些地图软件打开之后如果用户允许软件定位的话,那么打开软件后就会自动锁定到当前位置,如果用户手机移动那么当前位置也会跟随着变化.要实现这个功能需要使用Core

IOS 开发笔记-基础 UI(1)-简单的计算器

(1)UI是App的根基:一个App应该是先有UI界面,然后在UI的基础上增加实用功能 (2)UI相对简单易学:UI普遍是学习过程中最简单的一块,能快速拥有成就感和学习兴趣 (3)UI至关重要:开发中的绝大部分时间都在处理UI 谨记一条IOS软件开发定律:万物皆对象,UI界面上的每一个元素都是一个对象 IOS,android 软件开发过程 UIKit框架是跟UI有关系的,标签,文本,按钮,进度条,开关等控件,都是封装在UIKit框架内部的,UIKit框架中提供了丰富多彩的可视化组件元素,利用UI