Подтвердить что ты не робот

Принимаются ли файлы cookie в UIWebView?

Я должен задать вам вопрос.

1: Я использую UIWebView в своем приложении для iPhone. Я не хочу, чтобы пользователи могли добавлять комментарии в новостях. Но, чтобы прокомментировать, они должны войти в систему.

Если нет, как я могу принимать файлы cookie в UIWebView?

2: Могут ли файлы cookie, созданные на UIWebView в других UIWebView в другом представлении?

Пример: у меня есть LoginViewController со встроенным UIWebView, где мой пользователь может войти в систему/выйти из системы. Если они войдут в это представление, файл cookie будет по-прежнему доступен в CommentViewController?

Если нет, как я могу сделать это возможным?

Спасибо заранее!

4b9b3361

Ответ 1

UIWebView автоматически сохранит файлы cookie в коллекции [NSHTTPCookieStorage sharedHTTPCookieStorage] и будет доступен во всех остальных UIWebView в вашем приложении во время того же запуска приложения. Однако класс UIWebView не сохраняет файлы cookie для страниц, загружаемых между запусками приложений, автоматически. Вам необходимо вручную сохранить файлы 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];
}

Ответ 2

Развертывание других ответов:

Так как 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, как указано выше.

Ответ 3

скоростная версия 3 четкой версии

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)
    }
}

Ответ 4

Из всех замечательных ответов на этот вопрос я собрал удобное расширение на 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()
}

Ответ 5

Swift 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")
}

Ответ 6

Вот более чистая и безопасная версия 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()
}

Ответ 7

Версия 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")
}

Ответ 8

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()
    }