【问题标题】:Are cookies in UIWebView accepted?UIWebView 中的 cookie 是否被接受?
【发布时间】:2014-11-18 06:46:17
【问题描述】:

我要问你。

1:我在我的 iPhone 应用程序中使用UIWebViews。我不希望用户能够在新闻中添加 cmets。但是,要发表评论,他们必须登录。

如果没有,我如何接受UIWebViews 中的 cookie?

2 : 在 UIWebView 创建的 cookie 是否在其他视图中的其他 UIWebView 中可用?

例如:我有我的LoginViewController,带有一个嵌入的UIWebView,我的用户可以在其中登录/注销。如果他们在此视图中登录,cookie 仍将在CommentViewController 中可用?

如果没有,我怎样才能做到这一点?

提前致谢!

【问题讨论】:

    标签: ios objective-c iphone cookies uiwebview


    【解决方案1】:

    UIWebView 将自动将 cookie 存储在 [NSHTTPCookieStorage sharedHTTPCookieStorage] 集合中,并且在同一个应用启动期间,您的应用内的所有其他 UIWebViews 中都应该可以使用这些 cookie。但是,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];
    }
    

    【讨论】:

    • @jan 它应该可以工作,因为此代码存储整个 cookie 集合,无论域如何。
    • 有没有办法通过php实现这个解决方案?
    • 它是否适用于 ios10 及更高版本?我无法在 ios11 中获取 cookie。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      扩展其他答案:

      由于NSHTTPCookieStorage cookies 可以使用NSKeyedArchiver 存档,因此您无需自己提取每个cookie 属性。此外,当没有要存储的 cookie 时,您需要删除 NSUserDefaults 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
      

      然后如上所述,只需在您的AppDelegate 中使用[[NSHTTPCookieStorage sharedHTTPCookieStorage] loadFromUserDefaults];[[NSHTTPCookieStorage sharedHTTPCookieStorage] saveToUserDefaults];

      【讨论】:

        【解决方案4】:

        这是一个更干净、更安全的 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()
        }
        

        【讨论】:

        • 我第一次通过 API 或其他方式手动加载带有 cookie 的 webview 的任何方式。所以自动登录。
        【解决方案5】:

        斯威夫特 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 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)
            }
        }
        

        【讨论】:

          【解决方案7】:

          从这个问题的所有其他答案中,我在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 调用方法,如 Brian Shamblen 在他的 original answer 中所述:

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

          【讨论】:

            【解决方案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()
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-05-04
              • 2011-10-21
              • 1970-01-01
              • 2020-08-19
              • 1970-01-01
              • 2016-09-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多