分類彙整:程式

Developers are responsible for assigning appropriate ratings to their Apps

3.8 – Developers are responsible for assigning appropriate ratings to their Apps. Inappropriate ratings may be changed/deleted by Apple

3.8 Details

The rating you’ve selected, 12+, is inconsistent with the content of your app. Since your app includes contests or sweepstakes, you must select “Yes” for Gambling and Contests in iTunes Connect.

Next Steps

Please update your Rating selections in iTunes Connect.

– Log in to iTunes Connect
– Click on “My Apps”
– Select your app
– Scroll down to select a Rating on the App Details page
– Click the Edit button next to “Rating”
– Change the Rating selections
– Click “Save”
– Once you’ve completed all changes, click the “Submit for Review” button at the top of the App Details page.

NOTE: Applications must be rated accordingly for the highest level of content that the user is able to access in the app.

 

簡單說就是 App 裡面的抽獎、贈獎活動包含了賭博的成分,必須在年齡分級裡勾選 “賭博和競賽” 。

另外可能也需要增加與 Apple 無關之聲明,請參考此文章

Official rules for sweepstakes and contests must be presented in the App and make it clear

20.2 – Official rules for sweepstakes and contests must be presented in the App and make it clear that Apple is not a sponsor or involved in the activity in any manner

20.2 Details

Your app includes a contest but it does not:

– Indicate that Apple is not involved in any way with the contest.

Next Steps

It is necessary to:

– Include official rules of the contest or sweepstakes in the app
– Include an explicit statement in the contest or sweepstakes rules specifying that Apple is not a sponsor
– Ensure that the contest or sweepstake prizes are not Apple products

 

App 裡必須要有參加辦法,並聲明 Apple 不是該比賽、活動、賭博的主辦、協辦廠商與贊助商,且獎品不是 Apple 的產品。

另外可能也要修改年齡分級,請參考此文章

卡在 TestFlight 邀請函無法同意

最近嘗試使用 TestFlight Beta 版測試,其中有個外部測試人員點了信中的邀請連結登入 Apple ID 後仍然顯示以下訊息:

You aren’t currently testing any apps. To accept an invitation, you must tap the link in the invitation email.

 

原因是你”必須”使用 Safari 開啟該連結,最好是用內建的郵件 App 開啟就絕對沒問題。如果是使用 Gmail App 點選它可能是用 Chrome App 打開,千萬別讓費時間在這啊~

Apps must follow the iOS Data Storage Guidelines or they will be rejected

2.23 – Apps must follow the iOS Data Storage Guidelines or they will be rejected

On launch and content download, your app stores 19.1MB, which does not comply with the iOS Data Storage Guidelines.

原因是我把下載的內容放到 <Application_Home>/Documents 底下,而這目錄預設是會備份到 iCloud 以及 iTunes 。依照 Guidelines 來看,Documents 只能放由使用者操作後產生的,而那種能重複下載或產生的要放在 <Application_Home>/Library/Caches ,暫存檔則放在 <Application_Home>/tmp

Cachestmp 不會備份,且 Caches 不是永久的,當裝置容量不夠時會刪除、系統還原時也會清空,如果想要永久就只能放 Documents 。 Library 底下除了 Caches 以外都會備份到 iTunes ,但不會上傳至 iCloud 。

放在 Documents 的檔案也可以手動標示為不要備份,由於我想永久保留至 App 內所以我採用此方法。

- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL

{

    assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);

    const char* filePath = [[URL path] fileSystemRepresentation];

    const char* attrName = "com.apple.MobileBackup";

    u_int8_t attrValue = 1;

    int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);

    return result == 0;

}

請照以下步驟檢查 Documents 是否肥大
Install and launch your app
Go to Settings > iCloud > Storage > Manage Storage
Select your device
If necessary, tap “Show all apps”
Check your app’s storage

參考連結
iOS Data Storage Guidelines
How do I prevent files from being backed up to iCloud and iTunes?
File System Programming Guide

註冊推播在 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];