Куки принимаются в UIWebView?
Я должен задать вам вопрос.
1: я использую UIWebView
в моем приложении для iPhone. Я не хочу, чтобы пользователи могли добавлять комментарии в новостях. Но, чтобы комментировать они должны войти в систему.
Если нет, как я могу принять куки в UIWebView
с?
2: файлы cookie созданы на UIWebView
доступны в других UIWebView
в другом виде?
Пример: у меня есть LoginViewController
со встроенным UIWebView
где мой пользователь может войти / выйти. Если они войдут в систему в этом представлении, файл cookie будет по-прежнему доступен в CommentViewController
?
Если нет, как я могу сделать это возможным?
Заранее спасибо!
7 ответов
UIWebView
автоматически сохранит файлы cookie в [NSHTTPCookieStorage sharedHTTPCookieStorage]
коллекция, и должна быть доступна во всех других UIWebView
в вашем приложении, во время запуска того же самого приложения. Тем не менее UIWebView
Класс не сохраняет автоматически куки для страниц, которые загружаются между запусками приложения. Вам необходимо вручную сохранять файлы cookie, когда приложение перемещается в фоновый режим, и перезагружать значения, когда приложение возвращается на передний план.
Поместите следующий код в свой класс AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Other existing code
[self loadHTTPCookies];
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
//Other existing code
[self saveHTTPCookies];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[self loadHTTPCookies];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
//Other existing code
[self saveHTTPCookies];
}
-(void)loadHTTPCookies
{
NSMutableArray* cookieDictionary = [[NSUserDefaults standardUserDefaults] valueForKey:@"cookieArray"];
for (int i=0; i < cookieDictionary.count; i++)
{
NSMutableDictionary* cookieDictionary1 = [[NSUserDefaults standardUserDefaults] valueForKey:[cookieDictionary objectAtIndex:i]];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieDictionary1];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
}
-(void)saveHTTPCookies
{
NSMutableArray *cookieArray = [[NSMutableArray alloc] init];
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
[cookieArray addObject:cookie.name];
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:cookie.name forKey:NSHTTPCookieName];
[cookieProperties setObject:cookie.value forKey:NSHTTPCookieValue];
[cookieProperties setObject:cookie.domain forKey:NSHTTPCookieDomain];
[cookieProperties setObject:cookie.path forKey:NSHTTPCookiePath];
[cookieProperties setObject:[NSNumber numberWithUnsignedInteger:cookie.version] forKey:NSHTTPCookieVersion];
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];
[[NSUserDefaults standardUserDefaults] setValue:cookieProperties forKey:cookie.name];
[[NSUserDefaults standardUserDefaults] synchronize];
}
[[NSUserDefaults standardUserDefaults] setValue:cookieArray forKey:@"cookieArray"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Расширяя другие ответы:
поскольку NSHTTPCookieStorage cookies
может быть заархивирован с помощью NSKeyedArchiver
Вам не нужно извлекать каждое свойство cookie самостоятельно. Кроме того, вы захотите удалить NSUserDefaults
свойство cookie, когда нет файлов cookie для хранения.
Таким образом, вы можете упростить хранение / загрузку файлов cookie в это расширение:
static NSString *const kCookiesKey = @"cookies";
@implementation NSHTTPCookieStorage (Persistence)
- (void)saveToUserDefaults
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if (self.cookies != nil && self.cookies.count > 0) {
NSData *cookieData = [NSKeyedArchiver archivedDataWithRootObject:self.cookies];
[userDefaults setObject:cookieData forKey:kCookiesKey];
} else {
[userDefaults removeObjectForKey:kCookiesKey];
}
[userDefaults synchronize];
}
- (void)loadFromUserDefaults
{
NSData *cookieData = [[NSUserDefaults standardUserDefaults] objectForKey:kCookiesKey];
if (cookieData != nil) {
NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookieData];
for (NSHTTPCookie *cookie in cookies) {
[self setCookie:cookie];
}
}
}
@end
Тогда просто используйте [[NSHTTPCookieStorage sharedHTTPCookieStorage] loadFromUserDefaults];
а также [[NSHTTPCookieStorage sharedHTTPCookieStorage] saveToUserDefaults];
в вашем AppDelegate
как уже упоминалось выше.
Из всех замечательных ответов на этот вопрос я составил полезное UserDefaults
это сокращает необходимый код.
UserDefaults
Удлинитель для Swift 3
extension UserDefaults {
/// A dictionary of properties representing a cookie.
typealias CookieProperties = [HTTPCookiePropertyKey: Any]
/// The `UserDefaults` key for accessing cookies.
private static let cookieKey = "cookies"
/// Saves all cookies currently in the shared `HTTPCookieStorage` to the shared `UserDefaults`.
func saveCookies() {
guard let cookies = HTTPCookieStorage.shared.cookies else {
return
}
let cookiePropertiesArray = cookies.flatMap { $0.properties }
set(cookiePropertiesArray, forKey: UserDefaults.cookieKey)
synchronize()
}
/// Loads all cookies stored in the shared `UserDefaults` and adds them to the current shared `HTTPCookieStorage`.
func loadCoookies() {
let cookiePropertiesArray = value(forKey: UserDefaults.cookieKey) as? [CookieProperties]
cookiePropertiesArray?.forEach {
if let cookie = HTTPCookie(properties: $0) {
HTTPCookieStorage.shared.setCookie(cookie)
}
}
}
}
Вы можете добавить этот код в отдельный файл UserDefaults+Cookies.swift
(например), а затем вызвать методы из вашего AppDelegate
как описал Брайан Шамблен в своем первоначальном ответе:
Звонки из AppDelegate
func applicationDidBecomeActive(_ application: UIApplication) {
UserDefaults.standard.loadCoookies()
}
func applicationWillEnterForeground(_ application: UIApplication) {
UserDefaults.standard.loadCoookies()
}
func applicationDidEnterBackground(_ application: UIApplication) {
UserDefaults.standard.saveCookies()
}
func applicationWillTerminate(_ application: UIApplication) {
UserDefaults.standard.saveCookies()
}
swift 3 clear version
func saveCookies() {
guard let cookies = HTTPCookieStorage.shared.cookies else {
return
}
let array = cookies.flatMap { (cookie) -> [HTTPCookiePropertyKey: Any]? in
cookie.properties
}
UserDefaults.standard.set(array, forKey: "cookies")
UserDefaults.standard.synchronize()
}
func loadCookies() {
guard let cookies = UserDefaults.standard.value(forKey: "cookies") as? [[HTTPCookiePropertyKey: Any]] else {
return
}
cookies.forEach { (cookie) in
guard let cookie = HTTPCookie.init(properties: cookie) else {
return
}
HTTPCookieStorage.shared.setCookie(cookie)
}
}
Свифт 3
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any] ? ) - > Bool {
loadHTTPCookies()
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
saveCookies()
}
func applicationWillEnterForeground(_ application: UIApplication) {
loadHTTPCookies()
}
func applicationWillTerminate(_ application: UIApplication) {
saveCookies()
}
func loadHTTPCookies() {
if let cookieDict = UserDefaults.standard.value(forKey: "cookieArray") as? NSMutableArray {
for c in cookieDict {
let cookies = UserDefaults.standard.value(forKey: c as!String) as!NSDictionary
let cookie = HTTPCookie(properties: cookies as![HTTPCookiePropertyKey: Any])
HTTPCookieStorage.shared.setCookie(cookie!)
}
}
}
func saveCookies() {
let cookieArray = NSMutableArray()
if let savedC = HTTPCookieStorage.shared.cookies {
for c: HTTPCookie in savedC {
let cookieProps = NSMutableDictionary()
cookieArray.add(c.name)
cookieProps.setValue(c.name, forKey: HTTPCookiePropertyKey.name.rawValue)
cookieProps.setValue(c.value, forKey: HTTPCookiePropertyKey.value.rawValue)
cookieProps.setValue(c.domain, forKey: HTTPCookiePropertyKey.domain.rawValue)
cookieProps.setValue(c.path, forKey: HTTPCookiePropertyKey.path.rawValue)
cookieProps.setValue(c.version, forKey: HTTPCookiePropertyKey.version.rawValue)
cookieProps.setValue(NSDate().addingTimeInterval(2629743), forKey: HTTPCookiePropertyKey.expires.rawValue)
UserDefaults.standard.setValue(cookieProps, forKey: c.name)
UserDefaults.standard.synchronize()
}
}
UserDefaults.standard.setValue(cookieArray, forKey: "cookieArray")
}
Вот более чистая и безопасная версия Swift:
private func loadCookies() {
guard let cookies = NSUserDefaults.standardUserDefaults().valueForKey("cookies") as? [[String: AnyObject]] else {
return
}
for cookieProperties in cookies {
if let cookie = NSHTTPCookie(properties: cookieProperties) {
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(cookie)
}
}
}
private func saveCookies() {
guard let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies else {
return
}
var array = [[String: AnyObject]]()
for cookie in cookies {
if let properties = cookie.properties {
array.append(properties)
}
}
NSUserDefaults.standardUserDefaults().setValue(array, forKey: "cookies")
NSUserDefaults.standardUserDefaults().synchronize()
}
Swift 4.2
Пожалуйста, добавьте это расширение в ваш контроллер
extension UserDefaults {
/// A dictionary of properties representing a cookie.
typealias CookieProperties = [HTTPCookiePropertyKey: Any]
/// The `UserDefaults` key for accessing cookies.
private static let cookieKey = "cookies"
/// Saves all cookies currently in the shared `HTTPCookieStorage` to the shared `UserDefaults`.
func saveCookies() {
guard let cookies = HTTPCookieStorage.shared.cookies else {
return
}
let cookiePropertiesArray = cookies.compactMap { $0.properties }
set(cookiePropertiesArray, forKey: UserDefaults.cookieKey)
synchronize()
}
/// Loads all cookies stored in the shared `UserDefaults` and adds them to the current shared `HTTPCookieStorage`.
func loadCoookies() {
let cookiePropertiesArray = value(forKey: UserDefaults.cookieKey) as? [CookieProperties]
cookiePropertiesArray?.forEach {
if let cookie = HTTPCookie(properties: $0) {
HTTPCookieStorage.shared.setCookie(cookie)
}
}
}
}
И заменить в AppDelegate следующие строки кода:
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
с такими строками кода:
func applicationDidBecomeActive(_ application: UIApplication) {
UserDefaults.standard.loadCoookies()
}
func applicationWillEnterForeground(_ application: UIApplication) {
UserDefaults.standard.loadCoookies()
}
func applicationDidEnterBackground(_ application: UIApplication) {
UserDefaults.standard.saveCookies()
}
func applicationWillTerminate(_ application: UIApplication) {
UserDefaults.standard.saveCookies()
}
Версия Swift 2.0
func loadCookies() {
let cookieDict : NSMutableArray? = NSUserDefaults.standardUserDefaults().valueForKey("cookieArray") as? NSMutableArray
if cookieDict != nil {
for var c in cookieDict! {
let cookies = NSUserDefaults.standardUserDefaults().valueForKey(c as! String) as! NSDictionary
let cookie = NSHTTPCookie(properties: cookies as! [String : AnyObject])
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(cookie!)
}
}
}
func saveCookies() {
var cookieArray = NSMutableArray()
let savedC = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies
for var c : NSHTTPCookie in savedC! {
var cookieProps = NSMutableDictionary()
cookieArray.addObject(c.name)
cookieProps.setValue(c.name, forKey: NSHTTPCookieName)
cookieProps.setValue(c.value, forKey: NSHTTPCookieValue)
cookieProps.setValue(c.domain, forKey: NSHTTPCookieDomain)
cookieProps.setValue(c.path, forKey: NSHTTPCookiePath)
cookieProps.setValue(c.version, forKey: NSHTTPCookieVersion)
cookieProps.setValue(NSDate().dateByAddingTimeInterval(2629743), forKey: NSHTTPCookieExpires)
NSUserDefaults.standardUserDefaults().setValue(cookieProps, forKey: c.name)
NSUserDefaults.standardUserDefaults().synchronize()
}
NSUserDefaults.standardUserDefaults().setValue(cookieArray, forKey: "cookieArray")
}