地理座標系使用三維球面來定義地球上的位置,單位即經緯度。但經緯度沒法精確測量距離戒面積,也難以在平面地圖戒計算機屏幕上顯示數據。經過投影的方式能夠將其轉換成平面的投影座標系,不一樣的投影方式可能會帶來不一樣的變形及偏差,相似於把一個橘子的橘子皮剝開攤平到桌面。git
GPS以及iOS系統定位得到的座標是地理座標系WGS1984,Web地圖通常用的座標細是投影座標系WGS 1984 Web Mercator,國內出於相關法律法規要求,對國內全部GPS設備及地圖數據都進行了加密偏移處理,代號GCJ-02,這樣GPS定位得到的座標與地圖上的位置恰好對應上,特殊的是百度地圖在這基礎上又進行一次偏移,因此在處理系統定位座標及相關地圖SDK座標時須要轉換處理下,根據網絡資源,目前有一些公開的轉換算法。github
蘋果地圖及谷歌地圖用的都是高德地圖的數據,因此這三種狀況座標處理方法同樣,即將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; }
使用百度地圖SDK,定位也使用sdk中提供的方法,則得到座標是百度在GCJ-02基礎上再一次偏移的座標,若是要將定位座標顯示在蘋果地圖上,則須要轉換成GCJ-02下的座標,JZLocationConverter提供了三種座標間的轉換方法,segmentfault
使用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執行完成後再釋放該變量。動畫
目前用到了一些第三方的UICollectionviewLayout類庫,例如CSStickyHeaderFlowLayout,提供header懸停及下拉放大的視差效果等
經過自定義UICollectionviewLayout能夠靈活自定義不少佈局效果,以經典的瀑布流爲例。
其特色是cell的高度不一致,首尾間隔要保持一致,如此一來就須要自定義layout來調整cell的佈局位置。
這裏cell高度隨機生成爲40-140之間的數值。
重點是計算佈局這裏,第一行Y值都相同,但後續每一個cell的高度不一樣,須要去調整cell的位置,首先找到目前高度最小的那一列(排列第一行時,全部cell的Y值一致,將第一列當作高度最小的一列或者將頂部間距當作是一行高度一致的cell),將cell排列在此列下方,並更新此列的Y值,而後再繼續找高度最小的一列,將cell排列在其下方並更新此列Y值,以此類推,不斷尋找高度最小的那一列,將後續cell排列在其下方並更新這一列的Y值,便可完成佈局,固然設置cell佈局時還要將cell之間的間隔考慮進去。
contentSize中關鍵是高度,這裏取高度最大那一列的Y值即爲collectionview的高度。
使用Instruments中的Core Animation工具可以檢測圖層渲染和動畫的相關問題,包括圖層混合問題,即當多個圖層疊加在一塊兒,顏色不一樣時,處理這樣的顏色混合狀況會消耗GPU資源,監測發現這些區域會變紅,其它正常區域爲綠色
對於UILabel的圖層混合問題,將其設置爲與背景色一致並裁剪便可。(不會產生離屏渲染)