×

Error message

The spam filter installed on this site is currently unavailable. Per site policy, we are unable to accept new submissions until that problem is resolved. Please try resubmitting the form in a couple of minutes.
alex.reggiani's picture

Nel post precedente è stata analizzata una semplice soluzione che permette di creare ed utilizzare temi differenti per un'applicazione, utile a chi è abituato a sviluppare l'interfaccia grafica quasi esclusivamente da codice.

Per tutti coloro che invece preferiscono utilizzare Interface Builder per realizzare le viste, la tecnica precedentemente mostrata non può essere utilizzata, in quanto i nomi delle immagini, i font e tutti i restanti attributi relativi ai componenti che costituiscono l'interfaccia sono codificati all'interno dei file xib e non sono quindi impostati via codice.

Personalmente preferisco creare le viste utilizzando Interface Builder, in quanto permette di disegnare interfacce grafiche usando uno strumento grafico, che ha il vantaggio di far risparmiare allo sviluppatore decine e decine di righe di codice e permette di aver un immediato riscontro visivo di come sarà la pagina creata.

Esistono quindi diverse tecniche per temare un'applicazione anche se sviluppata con Interface Builder.
Così come per l'approccio via codice, iniziamo creando un file theme plist contenente tutte le risorse che costituiscono il tema, ed a questo punto possiamo scegliere diverse alternative.

1) E' possibile duplicare lo xib di una vista, una copia per ogni tema, attribuendo a ciascuna copia un nome differente, e poi andremo ad implementare il metodo nibName dei nostri view controllers facendo in modo che ritorni lo xib appropriato per il tema corrente.
Supponiamo ad esempio di avere un ViewController chiamato HomePageViewController e di aver 2 temi, un tema "default" ed uno "dark", andiamo quindi a realizzare due HomePage differenti, una per ciascun tema.
I file da creare saranno quindi i seguenti:

schermata_2013-07-09_alle_23.56.21.png
schermata_2013-07-09_alle_23.57.28.png

dove default.plist contiene:
schermata_2013-07-09_alle_23.59.06.png
e dark.plist :
schermata_2013-07-09_alle_23.59.49.png

e di seguito l'implementazione dell'HomePageViewController:

//
//  HomePageViewController.m
//
//  Created by Alex Reggiani on 09/07/13.
//  Copyright (c) 2013 Alex Reggiani. All rights reserved.
//

#import "HomePageViewController.h"

@implementation HomePageViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    
}

- (NSString *)nibName
{
    NSDictionary *theme = [ThemeManager sharedInstance].theme;
    return [theme objectForKey:NSStringFromClass([self class])];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

Questa tecnica, sebbene molto semplice, necessità di mantenere più copie per lo stesso xib, il che implica di dover apportare più volte le stesse modifiche su N xib qualora fosse necessario aggiungere/togliere/modificare dei componenti (ad esempio una label) sullo xib stesso.

2) Un'altra tecnica (probabilmente una delle più utilizzate, ma non per questo la migliore) consiste nel creare tanti IBOutlets quanti sono i componenti nello xib, e dettare poi le relative immagini, font, colori nel metodo viewDidLoad del view controller.
Questo è sicuramente un approccio molto ingombrante, ma che almeno non necessità di mantenere xib duplicati della stessa vista.

3) Un'ultima tecnica, quella che personalmente preferisco e ritengo essere la più efficace, è quella di creare delle sottoclassi dei componenti che vogliamo temare. Prendiamo ad esempio in considerazione le labels.
Possiamo creare una sottoclasse della label, chiamata ad esempio ThemeLabel che vada a impostare automaticamente il font ed il colore nel momento in cui è istanziata.
Andremo poi ad usare questa ThemeLabel direttamente in interface builder. Quando infatti aggiungiamo alla nostra view una UILabel, apriamo il tab "Identity Inspector" della label e sostituiamo la classe di default con ThemeLabel.
schermata_2013-07-10_alle_00.16.20.png

E' poi possibile in Interface Builder utilizzare i cosiddetti "User Defined Runtime Attributes" per specificare quale font si debba utilizzare per una determinata label.
Se aggiungiamo infatti due proprietà alla ThemeLabel (fontName e fontSize):

@interface ThemeLabel : UILabel
@property (nonatomic, copy) NSString *fontName;
@property (nonatomic, copy) NSString *fontSize;
@end

sarà sufficiente impostare nell'Identity Inspector questi 2 attributi:
schermata_2013-07-10_alle_00.26.51.png
e andarli a leggere nel metodo awakeFromNib della ThemeLabel per applicarli, ed il gioco è fatto!!!

La terza tecnica ritengo sia la migliore per due ragioni:
- consente di risparmiare tante linee di codice;
- permette di modificare il tema dell'applicazione a runtime. Sarebbe infatti possibile introdurre un meccanismo mediante il quale lo ThemeManager, ogni volta che l'utente cambia il tema, posti una notifica a tutte le ThemeLabel in modo che esse vengano ridisegnate utilizzando il tema opportuno.

A questo punto, a voi la scelta!!!!

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.