Je dois poser des questions pour vous.
1: J'utilise UIWebView
s dans mon application iPhone. Je ne veux pas que les utilisateurs puissent ajouter des commentaires dans les nouvelles. Mais, pour commenter, ils doivent se connecter.
Sinon, comment puis-je accepter les cookies dans UIWebView
s?
2: Les cookies créés dans UIWebView
sont-ils disponibles dans d'autres UIWebView
dans une autre vue?
Ex: j'ai mon LoginViewController
, avec un UIWebView
intégré, où mon utilisateur peut se connecter/se déconnecter. S'ils se connectent dans cette vue, le cookie sera toujours disponible dans CommentViewController
?
Si non, comment puis-je rendre cela possible?
Merci d'avance !
La UIWebView
va automatiquement stocker les cookies dans la collection [NSHTTPCookieStorage sharedHTTPCookieStorage]
et devrait être disponible dans toutes les autres UIWebView
s de votre application, au cours du même lancement. Cependant, la classe UIWebView
ne stocke pas automatiquement les cookies pour les pages chargées entre les lancements d'applications. Vous devez stocker manuellement les cookies lorsque l'application est déplacée en arrière-plan et recharger les valeurs lorsque l'application est ramenée au premier plan.
Placez le code suivant dans votre classe 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];
}
Développer les autres réponses:
Étant donné que NSHTTPCookieStorage cookies
peut être archivé à l'aide de NSKeyedArchiver
, vous n'avez pas besoin d'extraire vous-même chaque propriété de cookie. En outre, vous souhaiterez supprimer la propriété de cookie NSUserDefaults
lorsqu'il n'y a pas de cookies à stocker.
Vous pouvez donc simplifier le stockage/chargement des cookies dans cette extension:
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
Ensuite, utilisez simplement [[NSHTTPCookieStorage sharedHTTPCookieStorage] loadFromUserDefaults];
et [[NSHTTPCookieStorage sharedHTTPCookieStorage] saveToUserDefaults];
dans votre AppDelegate
comme mentionné ci-dessus.
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)
}
}
Parmi toutes les bonnes réponses à cette question, j’ai compilé une extension pratique sur UserDefaults
qui raccourcit le code nécessaire.
UserDefaults
Extension pour Swift 3extension 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)
}
}
}
}
Vous pouvez ajouter ce code à un fichier distinct UserDefaults+Cookies.Swift
(par exemple), puis appeler les méthodes de votre AppDelegate
comme décrit par Brian Shamblen dans sa réponse originale :
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
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")
}
Voici une version plus propre et plus sûre 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()
}
Version 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")
}
Swift 4.2
S'il vous plaît ajouter cette extension à votre contrôleur
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)
}
}
}
}
Et remplacez dans AppDelegate ces lignes de code:
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:.
}
avec ces lignes de code:
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()
}