iOS 4 SDK:sta puuttuvat toiminnot

in Technology, Apple

Olen koodaillut tänä keväänä ja kesänä aika paljon iPad- ja iPhone-sovelluksia, lähinnä erilaisia prototyyppejä. Olen tunnistanut ainakin seuraavat kaksi jatkuvasti toistuvaa "patternia", joihin olisi kiva löytää vakioitu ratkaisu.

NSURLConnection: Jonotettu tiedonsiirto

Useimmat sovellukseni rakentuvat siten, että Core Datalla määritellään tietorakenne eli joukko SQLite-tauluja ja niiden kenttiä. Sitten verkosta haetaan JSON-muotoista tietoa ja tallennetaan se kyseisiin tauluihin.

iOS 4 SDK:n vakiotoiminnallisuus mahdollistaa vain yksittäisen taustalla latautuvan downloadin NSURLRequest- ja NSURLConnection-luokilla. Jokaista siirtoa varten pitää tehdä oma delegate-objekti, joka ymmärtää mitä vastaanotetulla tiedolla tehdään. Lisäksi sen pitää osata käynnistää seuraava tiedonsiirto edellisen päätyttyä.

Olisi paljon kätevämpää, jos voisi määritellä vapaamittaisen jonon ladattavia URLeja ja kullekin sitten yksinkertaisen käsittelylogiikan. Jonoon voisi lennossa heittää lisää tavaraa latautumaan sitä mukaa, kun esimerkiksi aiemmin ladatuista JSON-rakenteista huomataan, että tarvitaan myös niihin liittyviä kuvia tai videoita.

Rajapinta voisi toimia esimerkiksi näin:

// Wish for simpler queued NSURLConnections

- (void)startDownloading {
  self.queue = [DownloadQueue queue]
  [queue addDataURL:[NSURL URLWithString:@"http://www.google.com"]
         target:self
         onComplete:@selector(googleComplete:data:)
         onError:nil];
}

- (void)googleComplete:(DownloadQueue *)queue data:(NSData *)data {
  // Parse data and load images...
  [queue addDataURL:[NSURL ...]
         target:self
         onComplete:@selector(imageComplete:data:)
         onError:nil];
}

- (void)imageComplete:(DownloadQueue *)queue data:(NSData *)data {
  // ...
}

Core Data: "Hae kaikki" ja "Poista kaikki" -toiminnot

Core Data ei ole mielestäni kovinkaan onnistunut rajapinta. Sen käyttö on työlästä ja monimutkaista. Erityisesti ärsyttää se, että yksittäisen taulun kaikkien rivien poistaminen edellyttää niiden lataamista ensin muistiin ja sitten kunkin poistamista erikseen. Rivien lataaminenkin on aika työlästä, kun NSFetchRequest-koodia pitää kirjoittaa ~10 riviä.

Useimpia käyttötapauksia varten olisi siis kätevää olla yksinkeraisempi rajapinta, jolla voisi hakea tai poistaa taulun kaikki rivit. Rajapinnalle annettaisiin vain taulun nimi (entiteetti), ja mahdollisesti jotain yksinkertaisia järjestys- tai maksimirivimääräehtoja.

Rajapinta voisi toimia esimerkiksi näin:

// Wish for simpler NSFetchRequest
NSFetchRequest *req = [NSFetchRequest requestEntities:@"Article"
                       sortBy:@"pubDate" ascend:NO
                       limit:10 offset:0 context:managedObjectContext];

// Wish for simpler "delete all" API
[managedObjectContext deleteAllEntities:@"Article"];

4 Comments
Matias 1.7.2010 18:53:18

NSURLConnectionin asynkroninen rajapinta on kieltämättä kankea. Yksi kokeilemisen arvoinen vaihtoehto on suosiolla käyttää NSURLConnectionin blokkaavia metodeja ja laittaa lataaminen taustasäikeeseen NSOperationQueuen avulla. Pääsäikeeseen voi postata notifikaation NSNotification-luokalla kun HTTP-pyyntö on suoriutunut loppuun.

Ideaa on selitetty tarkemmin Dr. Touchin blogipostauksessa.

Kannattaa kuitenkin pohtia kuinka monta rinnakkaista HTTP-yhteyttä käyttää. Hitaalla 3G-yhteydellä ei välttämättä kannata tehdä kauhean monta samanaikaista HTTP-pyyntöä.

Sqliten käpistelyyn olen käyttänyt fmdb-nimistä palikkaa. Se on toiminut muutamassa projektissa hyvin.

Tero Lehto 26.7.2010 02:09:16

Oletko ilmoittanut näistä puutteista Applelle, ja saavatko kehittäjät sieltä mitään vastausta?

En tunne Applen kehittäjäsuhteiden hoitoa. Mediasuhteiden hoito tuntuu olevan ainakin eurooppalaisille olematonta. Juuri koskaan ei saa mitään vastausta mihinkään tiedusteluun.

Kennu 26.7.2010 11:50:20

Noup, olen vasta koodaillut omaa pientä kirjastoa, jolla olen kokeillut, miten kyseiset asiat voisi parhaiten ratkaista.

Tero Lehto 26.7.2010 17:37:23

Suuttuuko Steve, jos sinne laittaa palautetta puutteista?


You can use Markdown to format your comment:

  • > quoted text
  • *italic* text
  • **bold** text
  • `code block` (multi-line is ok, whitespace is preserved)
  • [link text](http://www.google.com "link title")

Separate paragraphs in your text with two newlines