Category: Apple

Apple Magic Mouse paremmaksi BetterTouchToolilla

in Technology, Apple

Applen nykyinen Magic Mouse on kiva tuote. Se yhdistää perinteisen langattoman hiiren tuntuman kosketuslevyjen multitouch-ominaisuuksiin. Webbisivujen skrollaaminen pelkästään hiiren pintaa koskettelemalla tuntuu miellyttävältä.

Sisäänrakennetuista ominaisuuksista puuttuu kuitenkin hiiren keskinappi. Oikean hiirinapin saa kyllä konfiguroitua käyttöön yhdellä rastilla asetuksista, mutta keskinappi on unohtunut kokonaan. Itse käytän kyseistä painallusta webbilinkkien avaamiseen uuteen tabiin, joten en oikein tule toimeen ilman sitä.

Kaikeksi onneksi asiaan löytyy korjaus. BetterTouchTool on ilmainen apuohjelma, jolla Magic Mouseen voi määritellä vapaasti erilaisia painalluksia ja eleitä. Itse käytin sitä lisätäkseni yksinkertaisen mappauksen "Single Finger Middle Click => Middleclick".

Keskinapin simulointiin liittyy kuitenkin pieni ongelma. Magic Mousen pinta on täysin tasainen ja eri ihmisten sormet asettuvat siinä luonnostaan eri kohtiin. Itse painan keskinappia etusormella, ja painallus menee luonnostaan hiukan vasemmalle hiiren keskikohdasta.

Asian voi korjata määrittelemällä BetterTouchToolin asetuksista itselleen luontevimmat rajat hiiren virtuaalisille painikkeille (ks. kuva). Reaaliaikainen multitouch-näyttö kertoo visuaalisesti, mihin kohtaan sormi (tai sormet) asettuvat hiiren päällä, ja rajat voi vetää sen mukaan.

Ihan täydellinen tämä ratkaisu ei ole, sillä hiiren pinnassa edelleenkään mikään ei kerro sormille, missä kohtaa rajat menevät. Pienellä hienosäädöllä ja totuttelulla käyttö tuntuu kuitenkin luonnistuvan.

PS. Kokeilin samaan tarkoitukseen aluksi erästä toista sovellusta nimeltä MagicPrefs. Se kuitenkin sekoitti hiiren kiihtyvyyden eikä huvittanut alkaa selvittelemään mistä ongelma johtui. BetterTouchTool ei ole toistaiseksi aiheuttanut vastaavaa.

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"];

Mac OS X ja "next window" -näppäin

in Technology, Apple

Monille uusille Mac-käyttäjille tuntuu oudolta, että Cmd-Tab toimii eri logiikalla kuin Windowsin Alt-Tab. Windowsissa Alt-Tab ei tee eroa eri sovellusten kesken vaan vaihtaa kaikkien ikkunoiden välillä. Macissa taas Cmd-Tab vaihtaa sovellusten välillä, mutta kullakin sovelluksella voi olla auki useita ikkunoita.

Oletuksena sovelluksen sisäinen ikkunan vaihto tapahtuu näppäinyhdistelmällä Cmd-`, joka on suomalaisessa näppäimistössä aika hankala. `-merkki on siis "käänteinen heittomerkki", jonka saa näppäinyhdistelmällä Shift-´.

Tämä näppäinyhdistelmä kannattaa vaihtaa. Avaa ensin System Preferences, valitse sieltä Keyboard ja sen alta Keyboard Shortcuts -välilehti. Klikkaa vasemmanpuoleisesta listasta Keyboard & Text Input ja etsi sitten oikeanpuoleisesta listasta "Move focus to next window in application".

Nyt voit tuplaklikata kyseisessä kohdassa olevaa ⌘` -symbolia, ja painaa sitten haluamasi näppäinyhdistelmän sen tilalle. Itse käytän yhdistelmää Cmd-§, eli Command sekä Tabin yläpuolella oleva näppäin.

Muutos tulee heti voimaan ja nyt voit painella Cmd-§ vaihdellaksesi nopeasti ikkunoita esimerkiksi webbiselaimessa, Terminalissa, Wordissa ja niin edelleen.

iPhone 4 ja videopuhelut

in Technology, Apple

iPhone 4 julkaistiin odotetusti ja Apple näyttää ajavan FaceTimeä eli videopuheluita sen pääasiallisena myyntiargumenttina. Jännä nähdä, onnistuuko Steve Jobs tekemään niistä yhtä mainstreamia kuin kännykkäsurffailusta. Nokiahan ei ole onnistunut kummassakaan, vaikka aikaa on ollut.

Gizmodon mukaan FaceTime perustuu cocktailille avoimia standardeja:

[FaceTime is] Based on many open standards, h.264, AAC, SIP, STUN, TURN, ICE, RTP, SRTP, Apple going to standards body tomorrow to make FaceTime an open industry standard.

Vaikuttaa siis hyvin samanlaiselta, kuin perinteiset SIP-pohjaiset VoIP-puhelut. Ei kovin nättiä, mutta toisaalta aika vakioitua. Tämä tarkoittaa myös, että kolmansien osapuolten on mahdollista toteuttaa videopalveluita suoraan nettiin. Perinteisissä Nokian käyttämissä WCDMA-videopuheluissahan näin ei ole ollut, vaan koko puhelinverkko on ollut täysin irrallisena Internetistä. Ehkä se on sen juuri takia jäänyt niin vähäiselle käytölle.

On mielenkiintoista myös nähdä, millaisia videopuheluita ja etukameraa hyödyntäviä iPhone-sovelluksia tulee App Storeen. Ensimmäiseksi voisi veikata jonkinlaista Chatroulette-kloonia.

iPad-ohjelmointivinkkejä

in Technology, Apple

Olen käyttänyt tänä keväänä paljon aikaa iPhone- ja iPad-ohjelmointiin. Tästä syystä en ole bloggaillut kovin paljon web-asioista, vaikka niitäkin yhä kehittelen.

iPad-ohjelmointi on sikäli haastavaa, että isolla ruudulla esitettävät käyttöliittymät ja sisällöt vaativat paljon muistia. iPadissa on DRAM-muistia vain 256MB eli saman verran kuin iPhone 3GS:ssä. Näytön resoluutio ja kuvien koot ovat iPhoneen nähden nelinkertaisia, joten muistin kanssa pitää olla tarkkana.

Eniten muistia vievät sellaiset käyttöliittymät, joissa näyttöä "flippaillaan" sormella oikealle ja vasemmalle. Muistissa täytyy pitää vähintään kolme näytöllistä tavaraa, jotta skrollaus toimii ripeästi kumpaan suuntaan tahansa. Aiempia näkymiä täytyy sitten jatkuvasti vapauttaa muistista sitä mukaa, kun niitä ei enää tarvita.

Muistinhallinnassa on muutama kohta, jotka menevät helposti pieleen. Käyn ne tässä läpi.

UIViewController: viewDidUnload

Käyttöjärjestelmä lähettää toisinaan UIViewController-objekteille viewDidUnload-viestin muistin käydessä vähiin. Tässä tilanteessa .xib-tiedostosta ladattu näkymä (UIView) ollaan vapauttamassa. UIViewControllerin velvollisuus on vapauttaa kaikki viittaukset kyseisen näkymän elementteihin, kuten tekstikenttiin ja nappeihin, jotta ne poistuvat muistista. Tyypillinen toteutus voi näyttää tältä:

- (void)viewDidUnload {
    [super viewDidUnload];
    self.textLabel = nil;
    self.pushButton = nil;
}

Propertyjen vapautus deallocissa

Propertyt ovat Objective-C 2.0:n kätevä ominaisuus. Niiden avulla ei tarvitse kirjoitella erikseen getter- ja setter-metodeja. Riittää, että luokkaan määritellään @property- ja @synthesize-direktiivit näin:

@interface OmaLuokka : NSObject {
    NSString *teksti;
}
@property (nonatomic, retain) NSString *teksti;
@end

//...

@implementation OmaLuokka
@synthesize teksti;
@end

Jujuna tässä on kuitenkin se, että Objective-C ei vapauta propertyjä automaattisesti. Jokainen property pitää erikseen vapauttaa dealloc-viestin yhteydessä, tai muuten muisti vuotaa:

- (void)dealloc {
    [teksti release];
    [super dealloc];
}

Vuotamisen voi todeta ajamalla iPhone/iPad-sovelluksensa läpi Xcoden Leaks Performance Toolilla. Se näyttää suorituksen lopuksi ne objektit, jota ei vapautettu kunnolla.

SQLite ja binääridata

Eräs iPhonen ja iPadin kätevimpiä ominaisuuksia on Core Dataan sisäänrakennettu SQLite-tuki. Sovellus voi varastoida kaiken datansa paikalliseen SQL-tietokantaan. Melko usein tulee sitten eteen tilanne, että tietokannasta ladataan muistiin esimerkiksi 100 riviä UITableView-listausta varten.

Ongelmia aiheuttavat tässä sellaiset tietokantataulut, joihin on tallennettu suuria binääriobjekteja, kuten JPEG- ja PNG-kuvia. Jos tietokannasta ladataan muistiin 100 riviä, joissa jokaisessa on mukana 500 kilotavun kuva, muistia kuluu hetkessä 50MB. Jos rivejä on 500, hakutulokset eivät enää mahdu muistiin ollenkaan.

Ratkaisu on tallentaa binääriobjektit erilliseen tauluun, jolla on one-to-one relationship alkuperäisen taulun riveihin. Tällöin Core Data lataa binääriobjektit faultingia käyttäen automaattisesti muistiin vasta sitten, kun niihin viitataan koodissa. Esimerkiksi silloin, kun käyttäjä klikkaa luettelonäkymästä yhtä riviä ja sovellus siirtyy detaljinäkymään.

Käytön jälkeen binääriobjektit voi poistaa muistista ja palauttaa faulteiksi refreshObjectilla tähän tapaan:

[managedObjectContext refreshObject:binaariObjekti mergeChanges:NO];

Tyypillisesti tämä tehtäisiin silloin, kun isoa binääriobjektia käyttänyt detaljinäkymä suljetaan ja palataan luettelonäkymään.

Ubuntu 10.04 and afpd problems with Mac OS X mounts

in Technology, Apple

If you have just upgraded to Ubuntu 10.04 Lucid Lynx, you may have noticed that mounting AFP volumes from Mac OS X no longer works. On the command line, you will get errors like this:

mount_afp: AFPMountURL returned error -5014, errno is 89

The problem is simple and is described in this post from 2007. The Berkeley DB file format of existing .AppleDB directories on Ubuntu has not been updated properly. The easiest fix is to just delete the old .AppleDB directory of your volume and run /etc/init.d/netatalk restart. By default, .AppleDB is in your home directory. AFP mounting will now work and a new database will be generated automatically.

While you are at it, I also recommend adding the options:usedots setting to /etc/netatalk/AppleVolumes.default. It will make the usual Mac OS X generated dot files like .DS_Store appear in their original form under Linux instead of the annoying :2eDS_Store. A simple AppleVolumes.default should look something like this:

~/    "Home"    options:usedots

Ensikokemuksia iPadista

in Technology, Apple

Kylläpä tämä painaa paljon! 680g on yli tuplasti sen mihin on tottunut 290g Kindleä käsissä pitäessään. En ole siis mitenkään vakuuttunut, että iPad olisi välittömästi jonkinlainen Kindlentappaja sähköisen lukemisen saralla.

Visuaalisesti ja toimivuudeltaan iPad on tietysti mahtava, kuten odotettiinkin. iPhoneen tottuneelle se ei ehkä kuitenkaan ole niin mullistava. Itse kiinnitin ensimmäisenä huomiota isoon virtuaalinäppäimistöön, joka mahdollistaa nyt ihan oikeasti kymmensormijärjestelmällä näppäilyn. Kirjoitan tätäkin olohuoneen nojatuolissa iPad sylissä. Asetuksista tosin puuttuu vielä suomenkielinen layout, jolla saisi myös ääkköset esiin.

App Store ei vielä toimi Suomessa, mutta ilmaisia sovelluksia voi silti ladata iTunesin kautta ja synkronoida sitten iPadiin. Oletuksena iTunes näytti tarjoavan synkronointia myös niille iPhone-sovelluksille, jotka jo tukevat natiivisti iPadia. Vanhemmat sovelluksethan näkyvät vähän kökösti 1x/2x-skaalattuina.

Kotimatkalla tuli myös testailtua iPadia raitiovaunussa. Se toimii ihan kivasti webbisurffailuun niin kauan, kun HKL:n Wi-Fi pysyy pystyssä. Auringonpaistekaan ei varsinaisesti estänyt käyttöä. Eniten häiritsi se, että Google Readerin artikkelilistan skrollaus ei toimi desktop-tilassa, joten pitää käyttää mobiilitilaa. Se taas ei hyödynnä iPadin näyttöä kunnolla.

Kokeilin myös iPadin akun lataamista eri keinoin. Laitteen mukana tulee 10W-USB-laturi, johon on helppo vaihtaa eurooppaliitin iPhonen laturista. Lataus toimii myös 1,5v vanhassa MacBookissa, mutta 4v vanhassa iMacissa ei riittänyt puhtia. Myöskään mitkään kokeilemani PC:t eivät tarjonneet riittävästi tehoa - ei edes tänä vuonna ostettu, itse koottu i5-pelikone. USB-synkkaus toki toimii kaikissa.

[Update: Lataus toimii heikoissakin USB-porteissa, jos iPadin näytön sammuttaa.]

1 2 3 4