2015-04-21 7 views
15

Ho un problema in cui se memorizzo i dati utilizzando [[NSUserDefaults alloc] initWithSuiteName:SUITE_NAME]] i dati persistono anche dopo aver eliminato l'app. Questo dovrebbe succedere?NSUserDefaults initWithSuiteName persistente dopo l'eliminazione dell'app

+5

che avrebbe senso in quanto la documentazione dicendo questo metodo in scenari come _Use: Quando si sviluppa una suite di app, per condividere le preferenze o altri dati tra le applicazioni ..._ (così se elimini un'app di quella suite i prefs sarebbero ancora disponibili per altre app della stessa suite), anche se sarei sorpreso se questo accada davvero perché mi aspetterei che le persone lo superassero già (e quindi sentiremmo su questo più spesso). Domanda interessante! – Alladinian

+0

se si desidera rimuovere i dati, inizializzare le impostazioni predefinite dell'utente nel modo standard: 'NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];' – Lukas1

+0

@ Lukas1 Questa non è un'opzione, poiché è necessario utilizzare suite per condividere i dati con la mia estensione. – thisiscrazy4

risposta

6

Questo dovrebbe succedere. Questo è infatti lo scopo di initWithSuiteName, per condividere i dati tra tutte le app nel gruppo di app. La documentazione dicono:

utilizzare questo metodo in scenari come:

  • Quando si sviluppa una suite di app, per condividere le preferenze o altri dati tra le applicazioni

  • Quando si sviluppa un'applicazione estensione, per condividere preferenze o altri dati tra l'estensione e la sua app contenente

Non c'è modo per un'app di eliminarlo, perché quando un'app viene cancellata non viene notificata. Questo è lo stesso problema con la memorizzazione degli oggetti nel Portachiavi - persistono oltre la vita dell'app. Questa può essere una buona o una cattiva cosa a seconda delle esigenze della tua app.

Una soluzione consiste nel crittografare le parti appropriate del contenuto del file e archiviare la chiave in un portachiavi condiviso. Per qualcosa di simile, una chiave simmetrica AES casuale a 256 bit è perfetta. Generalmente però, finché l'utente ha un passcode sul dispositivo, il filesystem è crittografato e gli elementi nello storage condiviso dovrebbero essere considerati puliti.

Un'altra opzione è utilizzare la memoria condivisa come passthrough; lo facciamo nella nostra suite di app. Un'app inserisce un file crittografato nella memoria condivisa, quindi chiama un'altra app nella nostra suite con l'URI del file e la chiave di crittografia. L'app ricevente copierà il file nella sua memoria locale, rimuoverà il file condiviso e decodificherà il file locale.

+1

Se qualcosa è segreto, in primo luogo non dovrebbe entrare nelle impostazioni predefinite dell'utente, quindi i consigli sulla crittografia non sono realmente validi qui. – Sulthan

3

Come altri hanno già menzionato, le impostazioni predefinite memorizzate in una suite condivisa possono persistere nonostante la cancellazione dell'app e non c'è modo di rilevare l'eliminazione delle app e di eliminare queste impostazioni predefinite. Tuttavia, c'è un modo per affrontarlo nel caso in cui qualcuno reinstallasse l'app (e non si desidera che le vecchie impostazioni predefinite siano presenti).

Per risolvere questo problema, è sufficiente salvare un valore bool sulle impostazioni predefinite dell'utente standard all'avvio dell'app. Se il bool non è presente quando si avvia l'app (poiché è la prima installazione), è possibile eliminare le impostazioni di default della suite condivisa per farla avviare come una nuova installazione. In questo modo, su una nuova installazione avrai un default condiviso vuoto.

Ad esempio:

let defaults = NSUserDefaults.standardUserDefaults() 
if !defaults.boolForKey("firstInstallComplete") { 
    let sharedSuite = NSUserDefaults(suiteName: "com.example.app.shared")! 

    // delete whatever keys you want 
    sharedSuite.removeObjectForKey("example") 
    sharedSuite.removeObjectForKey("another") 
    ... 
    sharedSuite.synchronize() 

    defaults.setBool(true, forKey: "firstInstallComplete") 
    defaults.synchronize() 
}