Fånga exceptions i Xcode

Ola Bäckström 23 juni 2008

I nyare Xcode (3.0-) så kan man lägga till brytpunkter som gäller för alla dina debug-sessioner.

Speciellt händigt är då att lägga till två som har med exeptions att göra.
På platser där rader liknande dessa körs:

[aFreshlyCreatedExceptionsObject raise];

eller möjligen

@throw aFreshlyCreatedExceptionsObject;

så kommer ett gammalt eller ett nytt (=obj-c 2.0) exception att kastas. Då finns det två platser som du kanske vill ha brytpunkt på:

- [NSException raise]
objc_exception_throw()

Om du plockar fram brytpunktsfönstret i Xcode och lägger till dem så här:

så är det klart!

,

Kommentera

---

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.

,

Kommentera

---

Egen samlingsvy i Cocoa

Det är snabbt och lätt att binda ihop en NSTableView med en NSArrayController i Interface Builder. Men om man vill göra sin alldeles egna vy som hämtar data från controllern… vad behövs egentligen?

Ola Bäckström 19 juni 2008

Jag har googlat ordentligt men inte funnit något färdigt exempel, så jag håller på att bygga upp en vyklass från grunden.

Grundkraven på vyn:
-Enkelt kunna kopplas mot NSArrayController med bindings.
-ett rektangulärt område “ruta” motsvarar en “item” i arrangedObjects, och där varje ruta kan innehålla flera NSCeller för att presentera en viss aspekt av datat. Det senare motsvarar varje kolumn i en NSTableView.
-Kunna använda egna och standardceller.
-Antingen via något slags hack, eller via en riktig IB-palett kunna läggas in i en nibfil.

Suck.

Var startar man? Kanske kritisera tankegången… behöver jag verkligen bygga från grunden — kan jag inte ärva direkt från NSTableView och modifiera?

Här är en bild av det hela

,

Kommentera [2]

---

Bindings i Cocoa

[080620: jag har lagt till rubriker i artikeln för att bryta ned den i mera hanterbara delar]

Äntligen har jag kommit fram till slipp-skriva-massa-kod-bindings!
Baserat på KVO och KVC så har Apple byggt upp något de kallar för “bindings”. Läs mer…

Ola Bäckström 19 juni 2008

När man gör en lite större applikation så börjar snart användargränssnittets programkod att grisa till sig. Jag har alltför ofta i jobbet sett enkla program som växt till sig och efter ett tag sett ut som spagetti därför att användarinterfacet har byggts ut ohämmat och utan god strategi.

MVC och dataflöde

Nu har fler och fler sett tjusningen med det gamla Modell-vy-kontroll mönstret (infört på 80-talet med Smalltalk) om man samtidigt har någon slags hjälpmotor för att styra informationen runt mellan dessa tre delar. Moderna exempel är Eclipse EMF (läs om .Edit framework) och .Net databinding och naturligtvis bindings i Cocoa .

Apples variant av MVC+dataflöde

Man kan säga att Bindings är en samling olika teknologier som tillsammans ger mer än summan av delarna:

  • Dataflöde (Key-value Binding), från modell över till kontoll över till vy (användargränssnittet). Detta är kanske kärnan in det större begreppet Bindings. Underliggande teknik är både KVC och KVO:, men ovanpå KVO ligger grejer som gör att olika datatyper kan hållas synkroniserade. Det hela görs i runtime och kan till exempel omvandla tal till strängar osv.
  • Standardvyer som ser till att få dataflöde baklänges vy->kontroller->model. (Här har poletten just nyligen ramlat ned hos mig… så det får bli en separat artikel om detta.)
  • Himla finurliga standard-kontrollers. NSArrayController är ett exempel. Man slipper i många fall skriva kontrollen själv utan tar standardvarianten och konfigurerar upp den enligt sina behov.
    Kontrollerna tar hand om vad som är markerat, kan filtera modelldata, ser till att inte tappa bort förändringar gjorda i inmatningsvyer osv. Mer än man tror. Ja just ja… fixar direkt kontakt mot Core Data om man vill.
  • Värdeförvandlare (value transformer) som kan användas till att förvandla data på något speciellt sätt. Man kopplar in dessa mellan vyerna och kontrollerna.
  • Integration med Interface Builder. Man kan lätt kroka upp bindings mellan vyer, kontroller och bakomliggande modellobjekt.

I praktiken?

För ögonblicket håller jag på att bygga en egen vy som kan jobba mot NSArrayController. På ett sätt kan man säga att det är enkelt, men genom att det är så mycket att tänka på samtidigt så är det grisigt: drag&drop, bindings, ansvarsfördelning vy-cell etc. Kanske är det dags för en artikel om detta? Oavsett måste jag ordna till röran i huvudet först.

,

Kommentera

---

KVO i Cocoa

Fortsättning på ett tidigare inlägg om KVC . Nu ser vi på nyckel-värde-observation.

Ola Bäckström 19 juni 2008

Jag tänker inte gå i detalj på hur KVO används därför att man i själva verket ska använda Bindings i stället… men några korta ord.

KVO löser problemet att få reda på när andra objekts properties/attribut förändras. Specifikt så kan man säga att KVO ser till att registrerade observatörer får reda på förändringar. Ansvaret för att hålla ordning på observatörer och vilka attribut som är observerade är lagt på det observerade objektet. KVO har alltså ingen central notifikationstjänst, så det hela är inte byggt runt NSNotification.

Själva hålla-ordning-på-allt-joxet sker under ytan, halvvägs ned i obj-c-runtimen, långt bortom min begreppsvärld. Till exempel så byts ISA-värdena ut på observerade objekt (isa-swizzling) och ersätts med något slags proxy som gör … ja vadå?

I praktiken går det ut på att använda metoderna i det informella protokollet NSKeyValueObserving:

addObserver:forKeyPath:options:context:
observeValueForKeyPath:ofObject:change:context:
removeObserver:forKeyPath:

Dessa metoder har en vettig implementation redan i NSObject, så i stort sett alla dina objekt kan ta rollerna som observerat eller observerande objekt.

Nedan ett sekvensdiagram som visar att man kan få notiser både före och efter en förändring av ett övervakat attribut.

Om för många notiser går ut (kanske för att en hel list-attribut förändras på en gång) kan man välja att manuellt styra upp notis-processen med willChangeValueForKey: och didChangeValueForKey:, se Manual Observer Notification . Detta görs internt på det objekt som ska observeras.

En sista sak, flera observatörer kan välja att observera attribut på ett och samma objekt. De kan observera samma attribut eller olika attribut, spelar ingen roll.

,

Kommentera

---

« Äldre Nyare »