Rispondo alla domanda di ILeW con un articolo vero e proprio per spiegare meglio, allegando esempio, come funzionano delegati e notifiche. Usando uno schema vediamo prima di tutto come funziona il pattern delegato:

Un oggetto in cerca di un delegato
Continua...
Spostare il doppio Tap sul simulatore
Il simulatore iPhone/iPad in Xcode permette di simulare il doppio tap con la pressione del tasto ALT. Questo è utile per simulare anche la funzione di Pinch, quella usata per ingrandire o allontare contenuti nelle view con scroll o in oggetti UIWebView. Ebbene, alcuni di voi avranno notato che la simulazione delle “due dita” procede in modo simmetrico partendo sempre dal centro dello schermo. Per muovere questo “centro” è sufficiente tenere premuto anche il tasto SHIFT.
Continua...
Quando utilizziamo una UITableView in stile Grouped potremmo aver necessità di personalizzare la grafica dei titoli delle sezioni, come California o New York dell’esempio qui sotto.

Per farlo basta utilizzare il codice seguente, inserendolo nel delegato, cioè nella classe che risponde al protocollo UITableViewDelegate:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| // Restituisco una mia View personalizzata, in questo caso un oggetto
// di tipo UILabel
- (UIView *)tableView:(UITableView *)tableView
viewForHeaderInSection:(NSInteger)section {
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
label.font = [UIFont boldSystemFontOfSize:20];
label.textAlignment = UITextAlignmentCenter;
label.shadowColor = [UIColor blackColor];
label.shadowOffset = CGSizeMake(1, 1);
label.text = @"Sezione"; // Sostituire con un array come al solito
label.textColor = [UIColor whiteColor];
label.backgroundColor = [UIColor clearColor];
label.opaque = NO;
return label;
}
// Bisogna supportare anche questo message altrimenti non funziona
- (CGFloat)tableView:(UITableView *)tableView
heightForHeaderInSection:(NSInteger)section {
return 44;
} |
È importante inserire anche heightForHeaderInSection, altrimenti non funziona.
Note interessanti
Nella creazione della nostra UILabel, che volendo potrebbe essere anche un oggetto più complesso come una UIView o UIImageView, ho utilizzato per inizializzare il frame CGRectZero che corrisponde a CGRectMake(0,0,0,0).
Continua...
Gli stati UIControlStateSelected o UIControlStateHighlighted non funzionano quando un UIButton è impostato in modalità UIButtonTypeCustom! O meglio, non funzionano come dovrebbero (perchè riservati agli altri tipi di bottone), ad esempio per creare un bottone a due stati: toggle appunto. Se abbiamo creato due immagini (stato1.png e stato2.png) per il nostro bottone, possiamo procedere in questo modo:
1 2 3
| // Nell'header file creiamo una variabile globale che usaremo per
// controllare il toggle state
BOOL toggleFlag; |
Ora creiamo il nostro bottone:
1 2 3 4 5 6 7 8 9
| // Creaiamo un bottone e lo poniamo inizialmente nello stato "stato1.png"
// Modificate initWithFrame:(CGRect){100,100,50,50} con la posizione e
// dimensioni della vostra immmagine
toggleFlag = YES;
UIButton *toggleButton = [[UIButton buttonWithType:UIButtonTypeCustom] initWithFrame:(CGRect){100,100,50,50}];
[toggleButton setTitle:@"" forState:UIControlStateNormal];
[toggleButton setBackgroundImage:[UIImage imageNamed:@"stato1.png"] forState:UIControlStateNormal];
[toggleButton addTarget:self action:@selector(onToggle:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:toggleButton]; |
Quando si clicca sul bottone verrà inviato un messaggio gestito da onToggle:
1 2 3 4 5 6 7
| - (void)onToggle:(id)sender {
// Recupero puntatore al UIButton
UIButton *buttonClicked = (UIButton *)sender;
// Eseguo il toogle
toggleFlag = !toggleFlag;
[buttonClicked setBackgroundImage:[UIImage imageNamed:(toggleFlag) ? @"stato1.png" : @"stato2.png"] forState:UIControlStateNormal];
} |
Continua...
La sintassi NSLog(@"%@", ... ); funziona ed è utilizzata per ottenere informazioni sugli oggetti, ma non funziona su tipi dato C come struct CGRect o CGPoint, ad esempio. Per poter sfruttare NSLog(@"%@", ... ); anche su struct di tipo C possiamo appoggiarci a funzioni di conversione come NSStringFromCGRect() o NSStringFromCGPoint:
1 2 3 4 5
| CGrect mioRect = (CGRect){10,20,30,40};
CGPoint mioPoint = (CGPoint){32,64};
//
NSLog( @"Info rettangolo: %@", NSStringFromCGRect(mioRect) );
NSLog( @"Info point: %@", NSStringFromCGPoint(mioPoint) ); |
Nello specifico è possibile perfezionare tale procedure scrivendosi delle piccole macro utili come:
1
| #define NSLogRect(rect) NSLog(@"%s: (%0.0f, %0.0f) %0.0f x %0.0f", #rect, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height) |
Oppure:
1 2 3 4
| #define NSLogCGPoint(point) NSLog(@"%s: (%0.0f, %0.0f)", #point point.x, point.y)
CGPoint mioPoint = (CGPoint){32,64};
NSLogCGPoint(mioPoint); |
Che darà come output:
Continua...
CGRectMake() è una funzione (in realtà è un inline #define) molto usata soprattutto quando si creano da codice oggetti grafici o di interfaccia utente. Il suo utilizzo è quindi spesso legato all’inizializzazione di componenti UIKit, ma anche a semplici UIView o UIImageView. CGRectMake() restituisce una struct (struttura di tipo) CGRect:
1 2 3 4 5
| struct CGRect {
CGPoint origin;
CGSize size;
};
typedef struct CGRect CGRect; |
Che a sua volta è composta da due diverse struct CGPoint e CGSize:
1 2 3 4 5 6 7 8 9 10 11 12 13
| struct CGPoint {
CGFloat x;
CGFloat y;
};
typedef struct CGPoint CGPoint;
/* Sizes. */
struct CGSize {
CGFloat width;
CGFloat height;
};
typedef struct CGSize CGSize; |
Che, a loro volta ancora, contengono tipi CGFloat, ovvero tipi float. Se andiamo ad analizzare il codice della CGRectMake() troviamo:
1 2 3 4 5 6 7 8
| CG_INLINE CGRect
CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)
{
CGRect rect;
rect.origin.x = x; rect.origin.y = y;
rect.size.width = width; rect.size.height = height;
return rect;
} |
Ne deriva, quindi, che questa parte di codice:
1 2 3 4
| UIButton *gbutton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
gbutton.frame = CGRectMake (12,409,100,40);
[gbutton setTitle:@"Press" forState:UIControlStateNormal];
[mainWindow addSubview:gbutton]; |
Potrebbe, a ragione, essere scritta anche come:
1 2 3 4
| UIButton *gbutton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
gbutton.frame = (CGRect) {12,409,100,40};
[gbutton setTitle:@"Press" forState:UIControlStateNormal];
[mainWindow addSubview:gbutton]; |
Giusto per velocizzare un po’ l’esecuzione del codice…
Continua...
Ultimi Commenti
Marco: Ti ringrazio moltissimo, mi hai illuminato
ho risolto impostando [cc_objc] //OptionViewController.m -...
Giovambattista Fazioli: @Marco: Ti consiglio un approccio credo più corretto. Se hai eseguito il subclass del tab...
Marco: Scusa lo spam.. ho notato che c’è un errore.. ecco la correzione [cc_objc] /** PrimaClasse.h **/ #import...
Marco: dimenticato.. in [cci]OptionViewController[/cci ] il [cci]@syntetize[/cci] del delegato l’ho messo
luigi: molto chiaro e semplice devo ammettere che anche scrivendo da un pà difficilmente uso delegati creati da...