settings snippets

How to store user settings with NSUserDefaults

Tagged nsuserdefaults, preferences, settings, objective-c  Languages objectivec

Storing preferences

NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
[preferences setObject:@"SOME_DATA" forKey:@"KEY"];

Retrieving preferences

[preferences stringForKey:@"KEY"];
[preferences integerForKey:@"KEY"];
[preferences booleanForKey:@"KEY"];

Listing preferences with the defaults command

To list all preferences for a specific app, use this command:

$ defaults read com.aktagon.XXXApp

References

http://developer.apple.com/documentation/Cocoa/Conceptual/UserDefaults/UserDefaults.html

How to use NSKeyedArchiver to store user settings on the iPhone

Tagged objective-c, nskeyedarchiver, settings  Languages objectivec

The interface we define here is called Account:

#import <Foundation/Foundation.h>

@interface Account : NSObject <NSCoding> {
    NSString * username;
}

@property (retain) NSString * username;

-(NSString *)description;

@end

The implementation is this:

#import "Account.h"

@implementation Account

@synthesize username;

// Called when unserialized
- (id) initWithCoder: (NSCoder *)coder {
    if (self = [super init]) {
        self.username = [coder decodeObjectForKey:@"username"];
    }
    return self;
}

// Called when serialized
- (void) encodeWithCoder: (NSCoder *)coder {
    [coder encodeObject: self.username forKey:@"username"];
}

-(NSString *)description {
    return [NSString stringWithFormat:@"Account { username: '%@' }", self.username];
}

- (void) dealloc {
    [username release];
    [super dealloc];
}
@end

The application delegate interface named TheAppDelegate is defined here:

@interface TheAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    NSMutableDictionary * accounts;
    ...
}

@property (nonatomic, retain) NSMutableDictionary * accounts;


- (NSString *) pathForDataFile;
- (void) saveDataToDisk;
- (void) loadDataFromDisk;

The application delegate implementation has these methods defined:

// Called when application launches
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self loadDataFromDisk]; 
}

// Path to the data file in the app's Documents directory
- (NSString *) pathForDataFile {
    NSArray*    documentDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString*   path = nil;
    
    if (documentDir) {
        path = [documentDir objectAtIndex:0];    
    }
    
    return [NSString stringWithFormat:@"%@/%@", path, @"data.bin"];
}

- (void) saveDataToDisk {
    NSString * path = [self pathForDataFile];
    NSLog(@"Writing accounts to '%@' %@", path, self.accounts);
    
    NSMutableDictionary * rootObject;
    rootObject = [NSMutableDictionary dictionary];
    
    [rootObject setValue: [self accounts] forKey:@"accounts"];
    [NSKeyedArchiver archiveRootObject: rootObject toFile: path];
}

- (void) loadDataFromDisk {
    NSString     * path         = [self pathForDataFile];
    NSLog(@"Loading accounts from file '%@'", path);
    
    NSDictionary * rootObject;
    
    rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    self.accounts = [rootObject valueForKey:@"accounts"];
    NSLog(@"Loaded accounts %@", accounts);
    if (self.accounts == nil) {
        self.accounts = [[NSMutableDictionary alloc] init];  
     }
}

Now to save the account data to data.bin in the app's Documents folder you only have to call [self saveDataToDisk], or if you're doing it from a controller use this:

TheAppDelegate *delegate = (TheAppDelegate *)[UIApplication sharedApplication].delegate;
[delegate saveDataToDisk];

The code was adapted from this article.

Where should I store my application configuration in Sinatra?

Tagged configuration, sinatra, settings  Languages ruby

This is one option:

require 'yaml'
require 'ostruct'
require 'sinatra/base'

# Usage:
#
# config/application.yml:
#   development:
#     username: ...
#   production:
#     username: ...
#   url: http://...
#
# app.rb:
# class App < Sinatra::Base                    
#   register Sinatra::Configuration            
#   load_configuration 'config/application.yml'
#   get '/' do
#     App.configuration.username
#   end
#
module Sinatra
  module Configuration
    # From https://www.ruby-forum.com/topic/137104
    class NestedOstruct
      def self.new(hash={})
        OpenStruct.new(hash.inject({}){|r,p| r[p[0]] = p[1].kind_of?(Hash) ?  NestedOstruct.new(p[1]) : p[1]; r })
      end

      def self.to_ostruct(object)
        return case object
        when Hash
          object = object.clone
          object.each do |key, value|
            object[key] = to_ostruct(value)
          end
          OpenStruct.new(object)
        when Array
          object = object.clone
          object.map! { |i| to_ostruct(i) }
        else
          object
        end
      end
    end

    def self.registered(base)
      base.set :environments, %w[test development staging production]
    end

    def load_configuration(file, namespace = :configuration)
      set namespace, parse_configuration(YAML.load_file(file)) || {}
    end

    private

    def parse_configuration(hash)
      base = hash.except(*environments)
      base.merge!(hash[environment.to_s])
      NestedOstruct.to_ostruct(base)
    end
  end

  register Configuration
  Delegator.delegate :load_configuration
end