百度地图 iOS SDK 2.5.0版的变化

这篇博客 中,介绍了 iOS8 中定位的变化,百度地图等第三方地图 SDK 在 Xcode6 下均出现水土不服。在广大人民群众的热切期待和漫长等待后,百度地图终于释出了新版 iOS SDK,版本号 2.5.0。在官方的 Change Log 中,看到主要增加了对 arm64、iPhone6、iPhone 6P Plus、iOS8 的支持。解决了一些bug。

在工程中替换为新版 SDK 并 Build 后,满眼都是 Error。研究下去,发现变动相当多(之前使用的 SDK 版本号为 2.2.1),完全不管向下兼容性。

地图搜索

(1) BMKSearch 分拆为 BMKRouteSearchBMKGeoCodeSearch

(2) BMKSearchDelegate 分拆为 BMKRouteSearchDelegateBMKGeoCodeSearchDelegate

(3) 新增类 BMKTransitRoutePlanOptionBMKWalkingRoutePlanOptionBMKDrivingRoutePlanOption,且 BMKRouteSearch(原 BMKSearch) 的方法 drivingSearch、transitSearch、walkingSearch 所需的参数变更为一个与之对应的 BMK…RoutePlanOption 类型的对象。

原方法:

1
2
3
4
- (BOOL)transitSearch:(NSString*)city startNode:(BMKPlanNode*)start endNode:(BMKPlanNode*)end;
- (BOOL)drivingSearch:(NSString*)startCity startNode:(BMKPlanNode*)start endCity:(NSString*)endCity endNode:(BMKPlanNode*)end;
- (BOOL)drivingSearch:(NSString*)startCity startNode:(BMKPlanNode*)start endCity:(NSString*)endCity endNode:(BMKPlanNode*)end throughWayPoints:(NSArray*)wayPointsArray;
- (BOOL)walkingSearch:(NSString*)startCity startNode:(BMKPlanNode*)start endCity:(NSString*)endCity endNode:(BMKPlanNode*)end;

新方法:

1
2
3
- (BOOL)transitSearch:(BMKTransitRoutePlanOption*)transitRoutePlanOption;
- (BOOL)drivingSearch:(BMKDrivingRoutePlanOption*)drivingRoutePlanOption;
- (BOOL)walkingSearch:(BMKWalkingRoutePlanOption*)walkingRoutePlanOption;

同时须注意,相比其他两种路径搜索,公交搜索必须指定城市名称,否则会直接不予检索,transitSearch 方法返回 NO。

1
transitRouteSearchOption.city = @"济南市";

(4) BMKPlanResult 分拆为 BMKWalkingRouteResultBMKTransitRouteResultBMKDrivingRouteResult,同时 BMKRouteSearchDelegate(原 BMKSearchDelegate) 的代理方法变更,由:

1
2
3
- (void)onGetWalkingRouteResult:(BMKSearch *)searcher result:(BMKPlanResult *)result errorCode:(int)error;
- (void)onGetTransitRouteResult:(BMKSearch *)searcher result:(BMKPlanResult *)result errorCode:(int)error;
- (void)onGetDrivingRouteResult:(BMKSearch *)searcher result:(BMKPlanResult *)result errorCode:(int)error;

变更为:

1
2
3
- (void)onGetWalkingRouteResult:(BMKRouteSearch*)searcher result:(BMKWalkingRouteResult*)result errorCode:(BMKSearchErrorCode)error;
- (void)onGetTransitRouteResult:(BMKRouteSearch*)searcher result:(BMKTransitRouteResult*)result errorCode:(BMKSearchErrorCode)error;
- (void)onGetDrivingRouteResult:(BMKRouteSearch*)searcher result:(BMKDrivingRouteResult*)result errorCode:(BMKSearchErrorCode)error;

地图定位

(1) 新增类 BMKLocationService 及代理 BMKLocationServiceDelegate。BMKMapView 不再管理定位功能,其属性 location,和代理方法:

1
- (void)mapView:(BMKMapView *)mapView didUpdateUserLocation:(BMKUserLocation *)userLocation;

都不再存在,定位功能全部剥离到 BMKLocationService。

(2) 如果地图需要定位,需要单独创建一个 BMKLocationService 对象,并实现代理 BMKLocationServiceDelegate,在代理方法中执行 mapView 新增的 updateLocationData 方法,大致如下:

1
2
3
4
- (void)didUpdateUserLocation:(BMKUserLocation *)userLocation
{
[_bMapView updateLocationData:userLocation];
}

(3) 含有定位的地图界面,pop 回上一层 ViewController ,再 push 到这个界面,会崩溃的问题。
如果你遇到这个问题,请用真机运行,如果依然崩溃,确保以下两条:

  • viewWillDisappear 中写了 [_locService stopUserLocationService];
  • [_locService startUserLocationService];viewWillAppear 中,而不是在 viewDidLoad 中。

iOS 代码规范

这是我为团队制定的 iOS 代码规范,供大家参考。

文档说明

Version Time Author
0.1 Alpha 2014-08-21 StoneArk
0.2 Beta 2014-09-02 StoneArk
0.3 Beta 2014-09-15 StoneArk
1.0 2014-09-16 StoneArk

基本原则

求同存异。

合理的编码风格不只一个,尊重每位开发人员的编码习惯。但不合理的编码习惯必须避免。

命名规则

  • 命名规则
范围 命名规则 示例
变量名、方法名 驼峰式命名 (小驼峰式命名) onlineCount
- (void)viewDidLoad
类名、枚举类型名 Pascal 命名 MainViewController
FruitType
常量 全部大写或k开头的驼峰式命名 FONTNAME
kFontName
宏定义 全部大写 LOCALDEBUG
枚举值 要有枚举类型前缀 FruitType 枚举类型的枚举值应为 FruitTypeApple, FruitTypeBanana
  • 命名约定

新版 iTunes Connect 提交流程有变有 bug

上一篇博客 中,对 iTunes Connect 的改版从界面上进行了了解。今天进行了一次新版本的提交,发现提交的流程也有变化,并且貌似存在一个 bug。

以往的流程中,在填写完版本信息上传程序之前,是”Prepare for Upload”状态,需要在 iTunes Connect 网站点击”Ready to Upload Binary”按钮,才会进入”Waiting for Upload”状态,允许通过 Xcode 或 Application Loader 上传程序。成功上传程序后,无需进行其他操作,在 iTunes Connect 中就会自动变为”Upload Received”状态,经过几分钟的处理后,再自动变为”Waiting for Review”状态,等待审核。

而现在的流程是,一个程序版本一旦建立,即进入”Prepare for Submission”状态,在这个状态就可以上传程序,而不再有”Ready to Upload Binary”按钮,也不再有”Prepare for Upload”和”Waiting for Upload”两个状态。但上传后不会自动开始审核,需要在 iTunes Conect 中选择上传的 Build,然后点击”Submit for Review”按钮,才会提交审核,进入”Waiting for Review”状态。


但问题是,明明已经选择了 Build,但是点击提交后,依然提示没有选择 Build:

尝试着删掉重新选择、重新上传一个 Build、换浏览器等都不奏效,推测是新版 iTunes Connect 的一个 bug 吧。

不过这次的流程变动我认为还是非常合理的,上传程序并不代表提交审核,只有点击了提交按钮才意味着提交审核。这样也就允许我们可以提前将程序上传,待测试结果出来后,点击按钮提交即可。同时,这样也允许了多次上传程序(只要 Build Version 不同)。

PS. 9 月 15 日早上重新点了一次 “Submit for Review” 按钮,什么都没改动,已经可以成功提交了。证明的确是新版 iTunes Connect 的问题。

iOS 8 Glance

把自己的 4S 升级到了 iOS 8 GM Seed。第一次恢复了 iOS 7 上做的备份,结果卡得要命。然后重新刷了一遍,并设置为全新的 iPhone,流畅了许多,流畅度跟 iOS 7 差距不大。

Home Screen,多了个健康:

iTunes Connect 更新了

iTunes Connect 更新了,最直观的感受就是网站界面换成了扁平风格,与 iCloud 风格一致。
login page
main page

不过依然可以看到,还是有很多页面没有完成风格的切换。
rights page

增加了 4.7-inch 和 5.5-inch,以及 Video Preview。
video and screenshot

Become a DDOS attacker unluckily

下午客户反馈后台管理系统打不开,经排查发现服务器停机了,原因是防火墙发现我们的服务器对外发起了 DDOS 攻击。

重新启动服务器后,打开任务管理器发现了一大堆可疑进程:
Task list

其中的 hrlFFFF.tmp, hrl1C83.tmp, hrlAAC1.tmp, Bf.exe, svchobst.exe, WinHogb32.exe, bbyo.exe, jqs.exe, bytbac.exe, hrl11.tmp, 还有开机自启的两个 iexplorer.exe,都是十分可疑的进程。

将 Google Fonts 替换到本地读取

由于 Google Fonts 服务在国内被屏蔽了,所以导致很多引用了谷歌字体的网页在加载时打开十分缓慢。

解决方法也很简单,把网页中需要的字体下载到本地,并从本地加载字体文件即可。

不过有个小前提:需要先翻出去才能下载到所需要的谷歌字体文件哦。

  1. 翻出去
  2. 在网页的 html 源代码(假设为 index.html )中,找到引用了谷歌字体的部分,如:

    1
    <link href="http://fonts.googleapis.com/css?family=Open+Sans:300,800" rel="stylesheet" type="text/css" />
  3. 在网页浏览器中访问上面的地址 http://fonts.googleapis.com/css?family=Open+Sans:300,800 ,可以得到一个 css 文件,文件内容为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: 300;
    src: local('Open Sans Light'), local('OpenSans-Light'), url(https://themes.googleusercontent.com/static/fonts/opensans/v8/DXI1ORHCpsQm3Vp6mXoaTaRDOzjiPcYnFooOUGCOsRk.woff) format('woff');
    }
    @font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: 800;
    src: local('Open Sans Extrabold'), local('OpenSans-Extrabold'), url(https://themes.googleusercontent.com/static/fonts/opensans/v8/EInbV5DfGHOiMmvb1Xr-hqRDOzjiPcYnFooOUGCOsRk.woff) format('woff');
    }

把它保存到本地,可命名为 OpenSans.css 。在 index.html 所在的位置新建一个目录,命名为 googlefonts ,将刚才得到的 OpenSans.css 文件放置在这个目录下。

  1. 在上面的 OpenSans.css 文件中,可以找到字体文件的地址,即:
    1
    https://themes.googleusercontent.com/static/fonts/opensans/v8/DXI1ORHCpsQm3Vp6mXoaTaRDOzjiPcYnFooOUGCOsRk.woff]]]


1
https://themes.googleusercontent.com/static/fonts/opensans/v8/EInbV5DfGHOiMmvb1Xr-hqRDOzjiPcYnFooOUGCOsRk.woff

将这两个文件下载到本地(不需修改文件名。以下的步骤假设保存时未修改文件名,若修改了文件名请自行修改以下步骤中的内容),并放置在 googlefonts 目录下。

  1. 修改 OpenSans.css 文件,将字体的地址改为本地地址,即将:
    1
    https://themes.googleusercontent.com/static/fonts/opensans/v8/DXI1ORHCpsQm3Vp6mXoaTaRDOzjiPcYnFooOUGCOsRk.woff

修改为:

1
DXI1ORHCpsQm3Vp6mXoaTaRDOzjiPcYnFooOUGCOsRk.woff

对另一个 woff 文件链接同样地做处理,即将:

1
https://themes.googleusercontent.com/static/fonts/opensans/v8/EInbV5DfGHOiMmvb1Xr-hqRDOzjiPcYnFooOUGCOsRk.woff

修改为:

1
DXI1ORHCpsQm3Vp6mXoaTaRDOzjiPcYnFooOUGCOsRk.woff

  1. 修改 index.html ,将 css 的地址改为本地地址,即将:
    1
    <link href="http://fonts.googleapis.com/css?family=Open+Sans:300,800" rel="stylesheet" type="text/css" />

修改为:

1
<link href="googlefonts/OpenSans.css" rel="stylesheet" type="text/css" />

Jailbreak my iOS 7

iOS 7 的越狱已经发布好久了,不过我一直没越。iOS 7 已经有了许多不错的改变,比如增加了快捷开关、增加了中文的九宫格输入法等,让越狱需求已经不那么强烈。起码我越狱最大的目的无非就是,快捷开关、输入法、用手势替代 Home 按键。

但 Apple 做得还是有些不够。

快捷开关只是有限定的五个:飞行模式、WIFI、蓝牙、勿扰模式、屏幕旋转锁定,但飞行模式和蓝牙我几乎不会碰它,我更希望有的是蜂窝数据开关和铃声开关。

中文九宫格输入法限定只能中国大陆行货才有这个功能,可惜我的 iPhone 不是大陆的。

AssistiveTouch 虽然能解放 Home 按键,但实在是感觉既碍眼又不好用,还是用 Activator 的手势更舒服。

所以…我今天还是越狱了。

evasi0n7

Commit a issue about code block in hexo

用 Hexo 这段时间一直被一个问题困扰:代码段的行号显示不正确,如:

Markdown source:

After generate:

虽然右侧只有一行代码,但左侧行号显示了1和2,且跟代码没有对齐。使用 codeblock 块也是这样,使用 backtick 方式在代码较短的时候行号正确,代码长了也会出现这样的行号错误(我也不确定是否与代码长度有关)

一直认为应该是我这边的问题,要不然不会一直没有人发现。但在我进行了很多尝试并失败后,觉得又不像是我的问题,于是在 github 上提交了一个 issue(#443)

Hexo 的作者确认这是一个 bug,并且已经在 Release 2.4.5 修复了。

在 iOS 7 上实现圆角 TableView

问题产生

iOS 7 改变了许多 UI 控件的样式,其中 TableView 就由原来的圆角样式变为了横条平铺样式,但有时我们仍然需要圆角的 TableView,如下图:

iOS7的TableView 圆角的TableView
iOS7的TableView 圆角的TableView

实现

在 TableView 的 delegate 中,在 willDisplayCell 代理方法中绘制圆角:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell respondsToSelector:@selector(tintColor)])
{
CGFloat cornerRadius = 5.f;
cell.backgroundColor = UIColor.clearColor;
CAShapeLayer *layer = [[CAShapeLayer alloc] init];
CGMutablePathRef pathRef = CGPathCreateMutable();
CGRect bounds = CGRectInset(cell.bounds, 10, 0);
BOOL addLine = NO;
if (indexPath.row == 0 && indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1)
{
CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
}
else if (indexPath.row == 0)
{ //最顶端的Cell
CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds), CGRectGetMidX(bounds), CGRectGetMinY(bounds), cornerRadius);
CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
addLine = YES;
}
else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1)
{ //最底端的Cell
CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds), CGRectGetMidX(bounds), CGRectGetMaxY(bounds), cornerRadius);
CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
}
else
{ //中间的Cell
CGPathAddRect(pathRef, nil, bounds);
addLine = YES;
}
layer.path = pathRef;
CFRelease(pathRef);
layer.fillColor = [UIColor whiteColor].CGColor; //填充颜色
layer.strokeColor = [UIColor blackColor].CGColor; //绘制边缘
if (addLine == YES) {
CALayer *lineLayer = [[CALayer alloc] init];
CGFloat lineHeight = (1.f / [UIScreen mainScreen].scale);
lineLayer.frame = CGRectMake(CGRectGetMinX(bounds), bounds.size.height-lineHeight, bounds.size.width, lineHeight);
lineLayer.backgroundColor = [UIColor blackColor].CGColor; //绘制中间间隔线
[layer addSublayer:lineLayer];
}
UIView *testView = [[UIView alloc] initWithFrame:bounds];
[testView.layer insertSublayer:layer atIndex:0];
testView.backgroundColor = UIColor.clearColor;
cell.backgroundView = testView;
}
}

并且要将 tableView 的 Seperator 设置为 None:

Seperator