標籤彙整: ios

註冊推播在 iOS 8 上失效

在 iOS 8 上編譯會出現以下 log :

registerForRemoteNotificationTypes: is not supported in iOS 8.0 and later.

 

在 iOS 8 必須用 registerForRemoteNotifications 和 registerUserNotificationSettings 取代
以下程式碼同時支援 iOS 8 與 iOS 7

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        
    [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings
                                                                             settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
                                                                             categories:nil]];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
        
}else {
        
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}

 

如果要檢查推播有沒有打開,這部份也要修改。

UIRemoteNotificationType types;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {

    types = [[UIApplication sharedApplication] currentUserNotificationSettings].types;

}else {

    types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
}

if (types == UIRemoteNotificationTypeNone) {
    // 推播未打開
}

shows user location 在 iOS 8 上失效

在 iOS 7 以及更早之前的版本,MapView 顯示使用者位置不需實作到 CLLocationManager ,現在都要了。

在 iOS 8 上編譯會出現以下 log :

Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.

 

首先必須要修改 info.plist
新增 key值為 NSLocationWhenInUseUsageDescription 或 NSLocationAlwaysUsageDescription
Value值為要出現在螢幕上的字,終於可以客製化訊息了!但也可以留白。
兩者差異僅在前者只有使用中才會定位,後者是在背景也會持續定位。

 

接著修改程式碼,第5行是重點

locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        locationManager.desiredAccuracy=kCLLocationAccuracyBest;
        if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            [locationManager requestWhenInUseAuthorization];
        }
        [locationManager startUpdatingLocation];

 

另外授權檢查部分也要修改,請注意4,5行的差異

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {

    if (
        ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)] && status != kCLAuthorizationStatusNotDetermined && status != kCLAuthorizationStatusAuthorizedWhenInUse) ||
        (![locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)] && status != kCLAuthorizationStatusNotDetermined && status != kCLAuthorizationStatusAuthorized)
        ) {

        NSString *message = @"您的手機目前並未開啟定位服務,如欲開啟定位服務,請至設定->隱私->定位服務,開啟本程式的定位服務功能";
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"無法定位" message:message delegate:nil cancelButtonTitle:@"確定" otherButtonTitles: nil];
        [alertView show];

    }else {

        [locationManager startUpdatingLocation];
    }
}

上面那行是 iOS 8 以上,第二行是 iOS 7 以下,因為 kCLAuthorizationStatusAuthorized 在 iOS 8 完全不能使用。

 

別的地方要這樣寫

CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
    
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorized) {

    // 開始定位

}else {

    // 顯示警告
}

多個 URL 跳轉判斷

使用社群 SDK 時會跳到另一個 App 要求授權再回來,這時需要判斷回來後要做什麼事。

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    
    if ([url.scheme isEqualToString:@"fbxxxxxxxxxx"]) {
        return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
        
    }else if ([url.scheme isEqualToString:@"wbxxxxxxxxxx"]) {
        return [WeiboSDK handleOpenURL:url delegate:self];
        
    }else if ([url.scheme isEqualToString:@"wxxxxxxxxxxx"]) {
        return [WXApi handleOpenURL:url delegate:self];
        
    }else if ([url.host isEqualToString:@"home"]) {
        // do something
        return YES;
    }

    return NO;
}

以上同時有 Facebook 微博 微信 以及回到此 App 的第一個畫面。

解決 navigation bar 與 toolbar 背景顏色不一致

在 navigation bar 設定了背景顏色,並且右邊的 navigation item 使用 toolbar 來包2個 button 。

結果不但背景是預設的灰白色,而且上方還有細細的黑線。
toolbar1

這才是我想要的樣子~
toolbar2

    UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 90, 44)];
    toolBar.barStyle = -1;   //透明背景
    toolBar.clipsToBounds = YES;   //修正上方的線
    [toolBar setItems:@[shareBarButton, favoriteBarButton] animated:NO];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:toolBar];

personal hotspot 造成 status bar 高度改變

有兩種情況會讓 Status Bar 高度變成 40px (原來的兩倍)
1.打開個人熱點時
2.當有來電不接回到 App 時

模擬器也可以模擬40px 的 Status Bar
Hardware → Toggle In-Call Status Bar

使用 [[UIApplication sharedApplication] statusBarFrame].size.height 取得高度
或是使用 [UIScreen mainScreen].applicationFrame.size.height 取得扣除 Status Bar 的畫面高度

如果要兼容 iOS 6 與 iOS 7
除了元件的位置以及高度外
contentInset 與 contentOffset 也都要注意一下

如果無聊了話可以試試讓 Status Bar 變成 40px 再檢查別人 App 畫面有沒有怪怪的,畢竟不是所有開發者都會注意到此例外。

improper Advertising identifier [IDFA] Usage

IDFA 全名是 Identifier for Advertisers
我有用 AdMob SDK ,在驗證時出現這警告,沒理它直接上傳,狀態變成 Upload Received ,正當我還沉浸在愉悅中時狀態又變成 Invalid Binary ... (我還第一次遇到這種狀態)

好吧 原來還要另外做設定
在 Advertising Identifier 這區塊要做調整

Does this app use the Advertising Identifier (IDFA)?

選 Yes

This app uses the Advertising Identifier to (select all that apply):
Serve advertisements within the app

Limit Ad Tracking setting in iOS
打勾

做完上述設定後,驗證不再有警告,也順利上傳啦~

Xcode 5.1 不編譯 64bit 的方法

Xcode 升級到 5.1 後, Architectures 預設都會包含 arm64 ,若你之前是設定 armv7 armv7s ,竟然會變成 $(ARCHS_STANDARD_INCLUDING_64_BIT) ,預設值則變成 Standard architectures(armv7,armv7s,arm64) ,這兩個不管怎麼選都會包含 arm64。未選預設值編譯時也會出現建議你 Automatically Select Architectures 的黃色驚嘆號提示。




64biterror2

但是我使用的一些第三方 SDK 不支援 64bit ,例如 AdMob 與百度地圖,編譯時會出現以下錯誤訊息:
missing required architecture x86_64 in file
Undefined symbols for architecture x86_64

解決方法是 Architectures 選擇 Other... 刪除 $(ARCHS_STANDARD) 並輸入 armv7 armv7s ,這樣編譯時就不會包含 64bit 了。這只是暫時的解決方法,還是等第三方 SDK 出新版比較實在。

隱藏 navigation bar 的陰影底線

從 iOS 6 開始, navigation bar 最下方都有一條陰影。

在 iOS 6 上我都是使用偷吃步來處理,用 320*45px 的圖片蓋住1px的陰影。

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"header.png"] forBarMetrics:UIBarMetricsDefault];


到了 iOS 7 上發現陰影永遠都在最上層,我把圖片改成 320*64px ( 多出的 20px 是 status bar),第一行方法名稱也換了。

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"headerIos7.png"] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:[UIImage new]];


這方法不適用於 setBackgroundColor ,因為 setShadowImage 似乎要與 setBackgroundImage 一起使用。