標籤彙整: ios

使用 Network Link Conditioner 在 iOS 實機與模擬器模擬伺服器無回應逾時或網路極慢的狀況

在製作一個需要連網的 App 時,常常會需要打 API 取得資料,所以我們一定會針對伺服器回傳的資料處理,但要是伺服器根本就無回應呢?這時我們就需要使用 Network Link Conditioner 這項工具模擬出不同的網路環境做處理。

 


實機設定

先從 設定 → 開發者 → Network Link Conditioner 進去。
選擇 profile ,這裡因為要模擬 timedout 的情況所以選擇 100% Loss 。
並且 Enable 設定為開啟,這樣整台 iOS 裝置都會受到影響。

Network Link Conditioner iOS

 


模擬器設定

由於模擬器的設定裡沒有 Network Link Conditioner ,必須透過電腦設定才行。
請依照 Xcode 版本下載對應的檔案,不然會沒有效果。
Xcode 8 以上請從這下載安裝。
Xcode 7 以下請從這下載安裝。

掛載 dmg 尋找 Network Link Conditioner.prefPane 並點兩下安裝重開機。
路徑是 Additional Tools/Hardware/Network Link Conditioner.prefPane 。
安裝成功會在系統偏好設定裡出現 Network Link Conditioner。

Network Link Conditioner Mac 1

Network Link Conditioner Mac 2

使用方法跟實機一樣就不多說了,也可用用 Very Bad Network 這個 profile 模擬網路超慢的情況,這個會影響到整台電腦與模擬器請小心使用。

 

在 UITableViewCell 中取得 UITableView 或 UIViewController

在 iOS 7 ~ iOS 10 , UITableViewCell 與 UITableView 中間多了一層 UITableViewWrapperView ,直到 iOS 11 又移除…

將以下兩段複製到繼承 UITableViewCell 的自定義 class 裡


weak var tableView: UITableView? {
// 在 iOS 7 ~ 10 中 ,UITableViewCell 的 superview 為 UITableViewWrapperView 而不是 UITableView
if #available(iOS 11, *) {
return self.superview as? UITableView
}else {
return self.superview?.superview as? UITableView
}
}

weak var viewController: UIViewController? {
return self.tableView?.delegate as? UIViewController
}

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 {

// 顯示警告
}