У меня есть приложение iOS, которое делает небольшие сетевые запросы при запуске приложения (обновления ресурсов и т.д.). Если пользователь отключает сотовый доступ для приложения в настройках iOS, они получают приглашение от iOS о сетевом использовании при каждом запуске. Есть ли способ узнать программно, что сотовые данные для этого приложения были отключены, поэтому я могу отключить запросы при запуске?
Как узнать, отключен ли сотовый доступ для моего приложения iOS?
Ответ 1
Так что я нашел это на форумах Apple Dev от инженера Apple (https://devforums.apple.com/message/1059332#1059332).
Другой разработчик написал в DTS, и у меня была возможность подробно изучить это. Увы, новости такие же, как я ожидал: нет поддерживаемого способа определить, что ваше приложение находится в этом состоянии. Также нет способа сделать сетевое соединение "без взаимодействия с пользователем", то есть запросить сбой соединения, а не представлять подобный интерфейс. Если эти ограничения создают проблемы для вашего приложения, я рекомендую вам сообщить об ошибке, описывающей ваши конкретные требования.
https://developer.apple.com/bug-reporting/
Таким образом, похоже, что невозможно определить, были ли отключены сотовые данные для вашего приложения.
редактировать
Я подал радар для этого с просьбой добавить его. Я только что получил это уведомление в моем радаре
Мы считаем, что эта проблема была решена в последней бета-версии iOS 9.
Я просмотрел различия API, но пока не могу найти новый API.
Ответ 2
Начиная с iOS9, возможность проверки установки для включения/выключения использования сотовых данных для вашего приложения (Settings/Cellular/AppName) доступна с использованием класса Apple CTCellularData. Следующий код будет устанавливать cellDataRestrictedState, когда он запускается изначально, а затем устанавливает его и регистрирует при каждом изменении:
import CoreTelephony
var cellularDataRestrictedState = CTCellularDataRestrictedState.restrictedStateUnknown
let cellState = CTCellularData.init()
cellState.cellularDataRestrictionDidUpdateNotifier = { (dataRestrictedState) in
if cellularDataRestrictedState != .restrictedStateUnknown { // State has changed - log to console
print("cellularDataRestrictedState: " + "\(dataRestrictedState == .restrictedStateUnknown ? "unknown" : dataRestrictedState == .restricted ? "restricted" : "not restricted")")
}
cellularDataRestrictedState = dataRestrictedState
}
К сожалению (с iOS11), похоже, проверяется только состояние переключателя приложения - если ваш переключатель приложения настроен на включение, и пользователь переключает главный переключатель Cellular Data на отключенный, этот API вернет состояние приложения как "не ограничивается".
Ответ 3
Просто хотел добавить версию Objective C вышеуказанного кода Swift для будущих путешественников.
- (void)monitorCanUseCellularData {
if (GCIsiOS9) {
CTCellularData *cellularData = [[CTCellularData alloc] init];
NSLog(@"%ld", cellularData.restrictedState);
// 0, kCTCellularDataRestrictedStateUnknown
[cellularData setCellularDataRestrictionDidUpdateNotifier:^(CTCellularDataRestrictedState state) {
NSLog(@"%ld", state);
self.canUseCellularData = cellularData.restrictedState ==2?true:false;
}];
}
}
Ответ 4
Я обнаружил, что классу CTCellularData
нужно некоторое время, чтобы получить правильное значение. В моей реализации я вызываю didUpdateNotifier
очень рано после appDidFinishLaunching
. К тому времени, когда мой сетевой вызов возвращается с ошибками, у меня уже есть правильное значение для состояния с ограничениями.
class CellularRestriction: NSObject {
private static var cellularData = CTCellularData()
private static var currentState = CTCellularDataRestrictedState.restrictedStateUnknown
static var isRestricted: Bool {
currentState = cellularData.restrictedState
return currentState == .restricted
}
static func prepare() {
if currentState == .restrictedStateUnknown {
cellularData.cellularDataRestrictionDidUpdateNotifier = { state in
currentState = cellularData.restrictedState // This value may be inconsistent, however the next read of isRestricted should be correct.
}
}
}
}
Ответ 5
Добавив ответ dirkgroten, вы можете использовать класс Apple Reachability, который можно найти здесь:
https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html
Он использует SCNetworkReachability
, и он очень прост в использовании, он обнаруживает возможность подключения через Cell и WiFi, поскольку вам нужно будет проверить их при запуске.
Ответ 6
Существует множество фреймворков, которые предоставят вам статус вашего сетевого подключения, и, конечно же, вы сможете сворачивать свои собственные. Я нашел AFNetworking
одним из лучших. Он имеет одноэлементный класс под названием AFNetworkReachabilityManager
, который абстрагирует некоторые сложности для вас. В частности, вам нужно посмотреть на два логических свойства:
reachableViaWWAN
reachableViaWiFi
Существует также измененный статусный блок достижимости, который вы можете установить:
– setReachabilityStatusChangeBlock: