AVISO: Cualquier pregunta que no cumpla ninguno de estos criterios podrá ser borrada sin previo aviso.

He visto varias aplicaciones de escritorio que abren una ventana de preferencias desde el menu como firefox, safari, textmate, etc, además de que esa ventana no tiene botones para guardar los cambios. Ya tengo mi ventana diseñada, pero nose como darle la funcionalidad de guardar los cambios de usuario sin usar un boton y también poder usar esos valores en cualquier momento.

preguntado 18 Ene '11, 06:26

jyr's gravatar image

jyr
269435561

editó 18 Ene '11, 07:37


Hola buenas.

La verdad que no he abierto Xcode más que 2 veces jeje, pero curioseando la doc en un par de minutos encontre algunas cosas que espero que te sirvan.

Creo que para salvar tus preferencias sin necesidad de usar un botón debes persistir tus datos cada vez que exista un cambio.

Por ejemplo si hay un checkbox conectar con IBAction y persistir los datos en cada cambio, asumo que si estás en el paso de crear una ventana de preferencias conocerás como llamar métodos vía IBAction.

Hay muchas formas de persistir los datos, pero en la documentación recomiendan que para estos casos como preferencias, posiciones de ventanas etc. se use NSUserDefaults, donde puedes guardar un valor con una clave.

Con lo que sería algo así

-(IBAction) updatePreferences:(id) sender {
    NSUserDefaults *preferences = [NSUserDefaults standarUserDefaults];
    [preferences setObject:name.text forKey:@"userName"];
}

Luego puedes volver a obtener los valores en otro momento con:

NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *userName = [prefs stringForKey:@"userName"];

Refs:Documentación NSUserDefaults

enlace permanente

respondido 19 Ene '11, 05:49

luis_munoz's gravatar image

luis_munoz
714

editó 19 Ene '11, 05:50

Bien, para guardar los datos todo bien. Tengo un problema al cargar los datos "salvados" y colocarlos en el checkbox. ¿En que método deberia poner al iniciar la aplicacion para la carga de eso valores?

Mi código

def setSettings(self, name):
    settings = NSUserDefaults.standardUserDefaults()
    startMEMP = settings.boolForKey_(name)

if startMEMP:
        self.start.setState_(NSOnState)
    else:
        self.start.setState_(NSOffState)

y completo en https://gist.github.com/787472

(20 Ene '11, 07:20) jyr

Yo tengo implementada mis preferencias a través de un subclase de NSWindowController. Siendo así, tienes disponible el método: -(void)windowDidLoad;

En el cual puedes cargar los valores almacenados.

(20 Ene '11, 17:32) JuanMiguel

Al crear mi funcion y cambiando mi clase que herede de NSWindowController me dice "object has no attribute 'setState_'" donde el object es mi checkbox. Parece como si no se estuviera cargando como debe, ¿alguna idea de que pueda ser?

puse

def windowDidLoad(self):
    self.setSettings("start")

Lo mismo sucede cuando ejecuto setSettings desde awakeFromNib y que este heredando de mi clase de NSViewController, parace que tengo que cargar mis outlets de alguna manera para que sean identificados, pero no se como.

(20 Ene '11, 18:30) jyr

Resolvi el comentario anterior con http://bit.ly/eiOC6P , pero ahora, parece que no se estan guardando los datos o los estoy mostrando mal. Cuando acceso a los datos siempre me sale False, lo hice con el siguiente código.

    @objc.IBAction
def savePreferences_(self, sender):
    settings = NSUserDefaults.standardUserDefaults()

if self.start.state():
        settings.setObject_forKey_("On", 'start')
    else:
        settings.setObject_forKey_("Off", 'start')

if self.stop.state():
        settings.setObject_forKey_("On", 'stop')
    else:
        settings.setObject_forKey_("Off", 'stop')

if self.open.state():
        settings.setObject_forKey_("On", 'open')
    else:
        settings.setObject_forKey_("Off", 'open')

if self.nginxPort.stringValue():
       settings.setObject_forKey_(self.nginxPort.stringValue(), 'nginxPort')
    else:
        settings.setObject_forKey_("80", 'nginxPort')

if self.mysqlPort.stringValue():
    settings.setObject_forKey_(self.mysqlPort.stringValue(), 'mysqlPort')
    else:
        settings.setObject_forKey_("3306", 'mysqlPort')

if self.phpPort.stringValue():
        settings.setObject_forKey_(self.phpPort.stringValue(), 'phpPort')
    else:
        settings.setObject_forKey_("9000", 'phpPort')

settings.synchronize()

Y para accesar a los datos con:

def setSettings(self, field, name):
    settings = NSUserDefaults.standardUserDefaults()
    startMEMP = settings.boolForKey_(name)
    if startMEMP:
        field.setState_(NSOnState)
    else:
        field.setState_(NSOffState)
(22 Ene '11, 21:27) jyr

Estaba leyendo mal el valor guardado, cuando se salva lo tengo como cadena y al leerlo usaba un bool,por ejemplo:

def savePreferences_(self, sender):
    settings = NSUserDefaults.standardUserDefaults()

if self.start.state():
        settings.setObject_forKey_(1, 'start')
    else:
        settings.setObject_forKey_(0, 'start')

Y para poner los valores:

def setSettings(self):
    settings = NSUserDefaults.standardUserDefaults()

startMEMP = settings.boolForKey_("start")

if startMEMP:
    self.start.setState_(NSOnState)
else:
    self.start.setState_(NSOffState)

El código completo en https://gist.github.com/787472

(22 Ene '11, 23:23) jyr

Recomendación: utiliza setBool:forKey para los booleans. Recuperarlos después será más sencillo, sobre todo si utilizas boolForKey:. Y además establecerlos se convierte en un sencillo

settings.setObject_forKey_(self.start.state(), 'start')
(22 Ene '11, 23:35) YoNoSoyTu
mostrando 5 de 6 mostrar todos

Hace unos minutos preguntabas como saber que elemento llama al evento. aunque borraste la pregunta lo pongo por si puede ayudar a alguien.

EN IB puedes dar un valor Tag a cada elemento con lo que luego en el código puedes saber que elemento realiza la llamada.

-(IBAction) updatePreferences:(id) sender {
    int tag = [sender tag]; 
    NSLog(@"Tag: %d",tag);
}
enlace permanente

respondido 19 Ene '11, 09:57

luis_munoz's gravatar image

luis_munoz
714

editó 19 Ene '11, 09:57

Bueno, la pregunta iba más por como identificar el outlet con el valor que se esta "persistiendo" pero segui leyendo más info y entendi lo que comentas. Basicamente es

[preferences setObject:name.text forKey:@"userName"]

donde name.text es cualquiera de mis 5 elementos, por ejemplo el checkbox y userName el idenficador de ese elemento dentro de la "persistencia"

(19 Ene '11, 18:40) jyr
Tu respuesta:
Activar/desactivar vista previa