KVB i Cocoa

[editerad 080621, lagt till exempel på värdetransformerare]

En tidigare artikel om Bindings gick lite snabbt över något jag kallade “dataflöde”. En viktig del i detta är KVB som är byggt ovanpå byggstenarna KVC och KVO.

Ola Bäckström 20 juni 2008

Jag skrev tidigare att man i stort sett ska hoppa över KVO, för att i stället använda bindings.

Det är nog inte helts sant, så här dyker vi in i KVB-KVO-träsket…

Rekapitulation av KVO

KVO hjälper en att skriva objekt som kan lyssna på (=få notiser om) attributförändringar i andra objekt. KVO är själva mekaniken som ser till att dessa notiser blir utsända.

Som programmerare får man ansvaret att ta hand om denna information. Ofta är målet att hålla ett attribut a1 uppdaterat mot attribut a2; exempelvis messageSentSuccessfully (av typen BOOL) kanske man vill koppla mot huruvida det finns ett datum satt i messageSendningConfirmationDate (av typen NSDate) eller inte. Mappningen datum->bool kan då se ut så här:

  • nil -> NO
  • vilket datum som helst -> YES

Man får då se till att varje gång datumattributet ändras kolla om det är nil eller inte. Denna bit kod som ansvarar för detta får då läggas i oberservatörens observeValueForKeyPath:ofObject:change:context:-metod. Så varje gång du vill koppla något attribut mot ett annat får du skriva lite kod.

KVB

Key-Value-Binding är speciellt framtaget för att just synkronisera attribut. Eventuell mappning mellan datatyper görs med en slags plugin (av typen NSValueTransformer). Tänk dig att KVB har en slags standardlösning som du sedan kan konfigurera till att passa det speciella fallet. Det som gör KVB speciellt är att konfigureringen i många fall kan göras i Interface Builder – speciellt om det är ett objekt av typen NSView, alltså en standardvy (ett textfält eller en knapp i användarinterfacet t ex).
Poängen är att mindre kod konfigureringskod behövs skrivas; man fyller i informationen i IBs inspektörfönster:

Den informationen som fylls i här består av 4 bitar:

  1. Namnet på knytningen. I bilden “value”
  2. Vilket objekt som ska observeras. I bilden ovan “ArrayController”, notera dock att vid laddning av Nib-filen så ersätts strängen med adressen till objektet som i nibfilen kallas för ArrayController.
  3. Vilket attribut som det hela gäller. Anges i IB på två rader “Controller key” och “Model Key path”.
  4. Sedan kommer själva konfigurationen av denna bindning. Exempelvis om värdetransformerare ska användas. Man anger namnet på antingen en standardvariant eller namnet på någon egendefinerad. I vårt tidigare NSDate->BOOL exempel så skulle NSIsNotNil kunna passa.

Rent praktiskt hittar man KVB i det informella protokollet NSKeyValueBindingCreation . De två huvud-metoderna som styr KVB är:

bind:toObject:withKeyPath:options:
unbind:

Det man anger i IB kommer till slut som ett bind:-anrop. All information som man fyllt i IB-paletten kommer då fram i argumenten till denna metod. Notera att options-argumentet är en NSDictionary som sedan kan slås upp med t ex

NSString valueTransformerNameForThisBinding = [[options objectForKey:NSValueTransformerNameBindingOption] copy];

Vidare, det man i IB anger under “Controller Key” och “Model Key path” läggs ihop och bildar en enda keypath.

Skillnad mellan Key-Value Observing och Key-Value Binding

  • KVB är mer Interface Builder-vänligt.
  • KVC är strikt enkelriktad från observerat objekt till observatör. KVB är lite mer än så, därför att standardkontrollerna i IB är byggda så att de tittar på vad som angetts som options för bindningarna. Till exempel kommer NSTextView, under programmens körning, när en användare editerat textfältet att antropa den matchande settern på det observerade objektet. Då fås full tvåvägs kommunikation: men det fås bara med kombinationen KVB och en kontroll som “förstår sig på” bindings.

,

---
---