Page 1


Concurrent Programming in Mac OS X and iOS


Concurrent Programming in Mac OS X and iOS

9DQGDG1DKDYDQGLSRRU

Beijing • Cambridge • Farnham • Köln • Sebastopol • Tokyo


Concurrent Programming in Mac OS X and iOS E\9DQGDG1DKDYDQGLSRRU &RS\ULJKW‹9DQGDG1DKDYDQGLSRRU$OOULJKWVUHVHUYHG 3ULQWHGLQWKH8QLWHG6WDWHVRI$PHULFD 3XEOLVKHGE\2¦5HLOO\0HGLD,QF*UDYHQVWHLQ+LJKZD\1RUWK6HEDVWRSRO&$ 2¦5HLOO\ERRNVPD\EHSXUFKDVHGIRUHGXFDWLRQDOEXVLQHVVRUVDOHVSURPRWLRQDOXVH2QOLQHHGLWLRQV DUHDOVRDYDLODEOHIRUPRVWWLWOHV KWWSP\VDIDULERRNVRQOLQHFRP )RUPRUHLQIRUPDWLRQFRQWDFWRXU FRUSRUDWHLQVWLWXWLRQDOVDOHVGHSDUWPHQW  RUFRUSRUDWH#RUHLOO\FRP

Editor: $QG\2UDP Production Editor: 7HUHVD(OVH\ Proofreader: 7HUHVD(OVH\

Cover Designer: .DUHQ0RQWJRPHU\ Interior Designer: 'DYLG)XWDWR Illustrator: 5REHUW5RPDQR

Printing History: -XQH

)LUVW(GLWLRQ

1XWVKHOO+DQGERRNWKH1XWVKHOO+DQGERRNORJRDQGWKH2¦5HLOO\ORJRDUHUHJLVWHUHGWUDGHPDUNVRI 2¦5HLOO\0HGLD,QF&RQFXUUHQW3URJUDPPLQJLQ0DF26;DQGL26WKHLPDJHRID5XVVLDQJUH\KRXQG DQGUHODWHGWUDGHGUHVVDUHWUDGHPDUNVRI2¦5HLOO\0HGLD,QF 0DQ\RIWKHGHVLJQDWLRQVXVHGE\PDQXIDFWXUHUVDQGVHOOHUVWRGLVWLQJXLVKWKHLUSURGXFWVDUHFODLPHGDV WUDGHPDUNV:KHUHWKRVHGHVLJQDWLRQVDSSHDULQWKLVERRNDQG2¦5HLOO\0HGLD,QFZDVDZDUHRID WUDGHPDUNFODLPWKHGHVLJQDWLRQVKDYHEHHQSULQWHGLQFDSVRULQLWLDOFDSV :KLOHHYHU\SUHFDXWLRQKDVEHHQWDNHQLQWKHSUHSDUDWLRQRIWKLVERRNWKHSXEOLVKHUDQGDXWKRUVDVVXPH QRUHVSRQVLELOLW\IRUHUURUVRURPLVVLRQVRUIRUGDPDJHVUHVXOWLQJIURPWKHXVHRIWKHLQIRUPDWLRQFRQ WDLQHGKHUHLQ

,6%1 >/6,@ 


Table of Contents

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1. Introducing Block Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 6KRUW,QWURGXFWLRQWR%ORFN2EMHFWV &RQVWUXFWLQJ%ORFN2EMHFWVDQG7KHLU6\QWD[ 9DULDEOHVDQG7KHLU6FRSHLQ%ORFN2EMHFWV ,QYRNLQJ%ORFN2EMHFWV 0HPRU\0DQDJHPHQWIRU%ORFN2EMHFWV

    

2. Programming Grand Central Dispatch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 6KRUW,QWURGXFWLRQWR*UDQG&HQWUDO'LVSDWFK 'LIIHUHQW7\SHVRI'LVSDWFK4XHXHV 'LVSDWFKLQJ7DVNVWR*UDQG&HQWUDO'LVSDWFK 3HUIRUPLQJ8,5HODWHG7DVNV 3HUIRUPLQJ1RQ8,5HODWHG7DVNV6\QFKURQRXVO\ 3HUIRUPLQJ1RQ8,5HODWHG7DVNV$V\QFKURQRXVO\ 3HUIRUPLQJ7DVNV$IWHUD'HOD\ 3HUIRUPLQJD7DVNDW0RVW2QFH 5XQQLQJD*URXSRI7DVNV7RJHWKHU &RQVWUXFWLQJ<RXU2ZQ'LVSDWFK4XHXHV

         

v


Preface

:LWKWKHLQWURGXFWLRQRIPXOWLFRUHGHYLFHVVXFKDVWKHL3DGDQGWKHTXDGFRUH0DF %RRN3URZULWLQJPXOWLWKUHDGHGDSSVWKDWWDNHDGYDQWDJHRIPXOWLSOHFRUHVRQDGHYLFH KDVEHFRPHRQHRIWKHELJJHVWKHDGDFKHVIRUGHYHORSHUV7DNHIRULQVWDQFHWKHLQWUR GXFWLRQRIL3DG2QWKHODXQFKGD\RQO\DIHZDSSOLFDWLRQVEDVLFDOO\WKRVHUHOHDVHG E\$SSOHZHUHDEOHWRWDNHDGYDQWDJHRILWVPXOWLSOHFRUHV$SSOLFDWLRQVOLNH6DIDUL SHUIRUPHGYHU\ZHOORQWKHL3DGFRPSDUHGWRWKHRULJLQDOL3DGEXWVRPHWKLUGSDUW\ EURZVHUVGLGQRWSHUIRUPDVZHOODV6DIDUL7KHUHDVRQEHKLQGWKLVLVWKDW$SSOHKDV XWLOL]HG*UDQG&HQWUDO'LVSDWFK *&' LQ6DIDUL¦VFRGHEDVH*&'LVDORZOHYHO&$3, WKDWDOORZVGHYHORSHUVWRZULWHPXOWLWKUHDGHGDSSOLFDWLRQVZLWKRXWWKHQHHGWRPDQDJH WKUHDGVDWDOO$OOGHYHORSHUVKDYHWRGRLVGHILQHWDVNVDQGOHDYHWKHUHVWWR*&' 7KHWUHQGLQWKHLQGXVWU\LVPRELOLW\0RELOHGHYLFHVZKHWKHUWKH\DUHDVFRPSDFWDV DQL3KRQHRUDVVWURQJDQGIXOOIOHGJHGDVDQ$SSOH0DF%RRN3URKDYHPDQ\IHZHU UHVRXUFHVWKDQFRPSXWHUVVXFKDVWKH0DF3UREHFDXVHDOOWKHKDUGZDUHKDVWREH SODFHGLQVLGHWKHVPDOOGHYLFHV¦FRPSDFWERGLHV%HFDXVHRIWKLVLWLVYHU\LPSRUWDQWWR ZULWHDSSOLFDWLRQVWKDWZRUNVPRRWKO\RQPRELOHGHYLFHVVXFKDVWKHL3KRQH:HDUH QRWWKDWIDUDZD\IURPKDYLQJTXDGFRUHRUFRUHVPDUWSKRQHV2QFHZHKDYHFRUHV LQ WKH &38 DQ DSS H[HFXWHG RQ RQO\ RQH RI WKH FRUHV ZLOO UXQ WUHPHQGRXVO\ PRUH VORZO\WKDQDQDSSWKDWKDVEHHQRSWLPL]HGZLWKDWHFKQRORJ\VXFKDV*&'ZKLFK DOORZVWKHFRGHWREHVFKHGXOHGRQPXOWLSOHFRUHVZLWKRXWWKHSURJUDPPHUKDYLQJWR PDQDJHWKLVV\QFKURQL]DWLRQ $SSOHLVSXVKLQJGHYHORSHUVDZD\IURPXVLQJWKUHDGVDQGLVVORZO\VWDUWLQJWRLQWHJUDWH *&'LQWRLWVYDULRXVIUDPHZRUNV)RULQVWDQFHSULRUWRWKHLQWURGXFWLRQRI*&'LQ L26RSHUDWLRQVDQGRSHUDWLRQTXHXHVXVHGWKUHDGV:LWKWKHLQWURGXFWLRQRI*&' $SSOHFRPSOHWHO\FKDQJHGWKHLPSOHPHQWDWLRQRIRSHUDWLRQVDQGRSHUDWLRQTXHXHVE\ XVLQJ*&'LQVWHDGRIWKUHDGV 7KLVERRNLVZULWWHQIRUWKRVHRI\RXZKRZDQWWRGRZKDW$SSOHVXJJHVWVDQGZKDW VHHPVOLNHWKHEULJKWIXWXUHIRUVRIWZDUHGHYHORSPHQWPLJUDWLQJDZD\IURPWKUHDGV DQGDOORZLQJWKHRSHUDWLQJV\VWHPWRWDNHFDUHRIWKUHDGVIRU\RXE\UHSODFLQJWKUHDG SURJUDPPLQJZLWK*&'

vii


Audience ,QWKLVERRN,DVVXPHWKDW\RXKDYHDIDLUO\EDVLFXQGHUVWDQGLQJRIWKHXQGHUO\LQJ WHFKQRORJLHVXVHGLQZULWLQJL26DQGRU0DF26;DSSOLFDWLRQV:HZLOOQRWEHGLV FXVVLQJVXEMHFWVUHODWHGWR&RFRD7RXFKRU&RFRD:HZLOOEHXVLQJFRGHWKDWZRUNV LQSULQFLSOHDQG*&'OD\HUERWKZLWKL26DQG0DF26;7KHUHIRUH\RXZLOOQHHGWR NQRZWKHEDVLFVRI2EMHFWLYH&DQG\RXUZD\DURXQGEDVLFIXQFWLRQDOLWLHVXWLOL]HGE\ &RUH)RXQGDWLRQVXFKDVVWULQJPDQLSXODWLRQDQGDUUD\V 2¦5HLOO\¦V L26  3URJUDPPLQJ &RRNERRN LV D JRRG VRXUFH IRU PRUH DERXW REMHFW DOORFDWLRQ DUUD\V DQG 8,UHODWHG FRGH LQ FDVH \RX DUH ORRNLQJWREURDGHQ\RXUSHUVSHFWLYHWRZDUGL26SURJUDPPLQJ

Conventions Used in This Book 7KHIROORZLQJW\SRJUDSKLFDOFRQYHQWLRQVDUHXVHGLQWKLVERRN ,WDOLF ,QGLFDWHVQHZWHUPV85/VHPDLODGGUHVVHVILOHQDPHVDQGILOHH[WHQVLRQV Constant width

8VHGIRUSURJUDPOLVWLQJVDVZHOODVZLWKLQSDUDJUDSKVWRUHIHUWRSURJUDPHOHPHQWV VXFKDVYDULDEOHRUIXQFWLRQQDPHVGDWDEDVHVGDWDW\SHVHQYLURQPHQWYDULDEOHV VWDWHPHQWVDQGNH\ZRUGV Constant width bold

6KRZVFRPPDQGVRURWKHUWH[WWKDWVKRXOGEHW\SHGOLWHUDOO\E\WKHXVHU Constant width italic

6KRZVWH[WWKDWVKRXOGEHUHSODFHGZLWKXVHUVXSSOLHGYDOXHVRUE\YDOXHVGHWHU PLQHGE\FRQWH[W 7KLVLFRQVLJQLILHVDWLSVXJJHVWLRQRUJHQHUDOQRWH

Using Code Examples 7KLVERRNLVKHUHWRKHOS\RXJHW\RXUMREGRQH,QJHQHUDO\RXPD\XVHWKHFRGHLQ WKLVERRNLQ\RXUSURJUDPVDQGGRFXPHQWDWLRQ<RXGRQRWQHHGWRFRQWDFWXVIRU SHUPLVVLRQXQOHVV\RX¦UHUHSURGXFLQJDVLJQLILFDQWSRUWLRQRIWKHFRGH)RUH[DPSOH ZULWLQJDSURJUDPWKDWXVHVVHYHUDOFKXQNVRIFRGHIURPWKLVERRNGRHVQRWUHTXLUH SHUPLVVLRQ6HOOLQJRUGLVWULEXWLQJD&'520RIH[DPSOHVIURP2¦5HLOO\ERRNVGRHV UHTXLUH SHUPLVVLRQ $QVZHULQJ D TXHVWLRQ E\ FLWLQJ WKLV ERRNDQGTXRWLQJH[DPSOH viii | Preface


FRGHGRHVQRWUHTXLUHSHUPLVVLRQ,QFRUSRUDWLQJDVLJQLILFDQWDPRXQWRIH[DPSOHFRGH IURPWKLVERRNLQWR\RXUSURGXFW¦VGRFXPHQWDWLRQGRHVUHTXLUHSHUPLVVLRQ :HDSSUHFLDWHEXWGRQRWUHTXLUHDWWULEXWLRQ$QDWWULEXWLRQXVXDOO\LQFOXGHVWKHWLWOH DXWKRUSXEOLVKHUDQG,6%1)RUH[DPSOH£&RQFXUUHQW3URJUDPPLQJLQ0DF26;DQG L26E\9DQGDG1DKDYDQGLSRRU 2¦5HLOO\ &RS\ULJKW9DQGDG1DKDYDQGLSRRU ¤ ,I\RXIHHO\RXUXVHRIFRGHH[DPSOHVIDOOVRXWVLGHIDLUXVHRUWKHSHUPLVVLRQJLYHQDERYH IHHOIUHHWRFRQWDFWXVDWSHUPLVVLRQV#RUHLOO\FRP

Safari® Books Online 6DIDUL%RRNV2QOLQHLVDQRQGHPDQGGLJLWDOOLEUDU\WKDWOHWV\RXHDVLO\ VHDUFKRYHUWHFKQRORJ\DQGFUHDWLYHUHIHUHQFHERRNVDQGYLGHRVWR ILQGWKHDQVZHUV\RXQHHGTXLFNO\ :LWKDVXEVFULSWLRQ\RXFDQUHDGDQ\SDJHDQGZDWFKDQ\YLGHRIURPRXUOLEUDU\RQOLQH 5HDGERRNVRQ\RXUFHOOSKRQHDQGPRELOHGHYLFHV$FFHVVQHZWLWOHVEHIRUHWKH\DUH DYDLODEOHIRUSULQWDQGJHWH[FOXVLYHDFFHVVWRPDQXVFULSWVLQGHYHORSPHQWDQGSRVW IHHGEDFNIRUWKHDXWKRUV&RS\DQGSDVWHFRGHVDPSOHVRUJDQL]H\RXUIDYRULWHVGRZQ ORDGFKDSWHUVERRNPDUNNH\VHFWLRQVFUHDWHQRWHVSULQWRXWSDJHVDQGEHQHILWIURP WRQVRIRWKHUWLPHVDYLQJIHDWXUHV 2¦5HLOO\0HGLDKDVXSORDGHGWKLVERRNWRWKH6DIDUL%RRNV2QOLQHVHUYLFH7RKDYHIXOO GLJLWDODFFHVVWRWKLVERRNDQGRWKHUVRQVLPLODUWRSLFVIURP2¦5HLOO\DQGRWKHUSXE OLVKHUVVLJQXSIRUIUHHDWKWWSP\VDIDULERRNVRQOLQHFRP

How to Contact Us 3OHDVHDGGUHVVFRPPHQWVDQGTXHVWLRQVFRQFHUQLQJWKLVERRNWRWKHSXEOLVKHU 2¦5HLOO\0HGLD,QF *UDYHQVWHLQ+LJKZD\1RUWK 6HEDVWRSRO&$  LQWKH8QLWHG6WDWHVRU&DQDGD

 LQWHUQDWLRQDORUORFDO

 ID[

:HKDYHDZHESDJHIRUWKLVERRNZKHUHZHOLVWHUUDWDH[DPSOHVDQGDQ\DGGLWLRQDO LQIRUPDWLRQ<RXFDQDFFHVVWKLVSDJHDW KWWSZZZRUHLOO\FRPFDWDORJ 7RFRPPHQWRUDVNWHFKQLFDOTXHVWLRQVDERXWWKLVERRNVHQGHPDLOWR ERRNTXHVWLRQV#RUHLOO\FRP

Preface | ix


)RUPRUHLQIRUPDWLRQDERXWRXUERRNVFRXUVHVFRQIHUHQFHVDQGQHZVVHHRXUZHEVLWH DWKWWSZZZRUHLOO\FRP )LQGXVRQ)DFHERRNKWWSIDFHERRNFRPRUHLOO\ )ROORZXVRQ7ZLWWHUKWWSWZLWWHUFRPRUHLOO\PHGLD :DWFKXVRQ<RX7XEHKWWSZZZ\RXWXEHFRPRUHLOO\PHGLD

Acknowledgments :RUNLQJZLWK2¦5HLOO\WRZULWHERRNVKDVDOZD\VEHHQDSOHDVXUHDQGWKLVERRNLVQRW DQH[FHSWLRQ,PXVWVD\,DPYHU\IRUWXQDWHWRKDYHIDQWDVWLFIULHQGVDQGDIDQWDVWLF VXSSRUWWHDPDURXQGPHIRUZLWKRXWWKHP,ZRXOGQ¦WEHWKHSHUVRQ,DPWRGD\DQG \RXZRXOGQ¦WEHUHDGLQJWKLVERRN $QG\2UDPDQG%ULDQ-HSVRQKDYHEHHQLQFUHGLEO\VXSSRUWLYHRIP\HIIRUWVDQGKDYH IRUWKHIRXUWKWLPHJLYHQPHDFKDQFHWRUHDFKRXWWRWKRVHZKRZDQWWREHHGXFDWHG IXUWKHULQFXWWLQJHGJHWHFKQRORJLHVVXFKDV*UDQG&HQWUDO'LVSDWFK ,DPJUDWHIXOIRUP\ZRQGHUIXOIULHQGVZKRKDYHEHHQDFRQWLQXRXVVRXUFHRILQVSLUDWLRQ DQGVXSSRUW7KDQNVWRP\IULHQGVDQGFROOHDJXHV6XVKLO6KLUNH6KHQF\5HYLQGUDQ $QJHOD 5RU\ &KULV +DUPDQ 1DWDOLH 6]UDMEHU 6LPRQ :KLWW\ 6KDXQ 3XFNULQ *DU\ 0F&DUYLOOH0DUN+DUULVDQG.LUN3DWWLQVRQ ,ZRXOGDOVROLNHWRWKDQNHYHU\ERG\IURP2¦5HLOO\ZKRKDVKHOSHGPHVRIDUZLWKP\ VRPHWLPHVLQFUHGLEO\DQQR\LQJUHTXHVWV7KDQNVWR6DUDK6FKQHLGHUIRUKHOSLQJPH ZLWK691VHWXSDQGRWKHUWHFKQLFDO'RF%RRNTXHVWLRQV7KDQNVWR5DFKHO-DPHVIRU KHOSLQJPHPDQDJHUHDGHUV¦UHTXHVWVIRUP\H[LVWLQJERRNV$ELJWKDQN\RXJRHVWR %HWV\:DOLV]HZVNLDQG*UHWFKHQ*LOHVRI2¦5HLOO\IRUDUUDQJLQJDWKUHHGD\KDOISULFH RIIHURQPDQ\2¦5HLOO\WLWOHVWRKHOSZLWK-DSDQHVHGLVDVWHUUHOLHI:LWKDOO\RXZRQ GHUIXO UHDGHUV¦ KHOS 2¦5HLOO\ GRQDWHG  WR -DSDQHVH GLVDVWHU UHOLHI LQ 0DUFK /DVWEXWQRWOHDVW,ZRXOGOLNHWRWKDQN\RXIRUUHDGLQJWKLVERRN<RXUEHOLHILQP\ ZRUNLVZKDWNHHSVPHZULWLQJPRUHERRNVWKDWKHOSUHDGHUVEHPRUHSURGXFWLYHDQG FUHDWLYH

x | Preface


CHAPTER 1

Introducing Block Objects

%ORFN REMHFWV DUH SDFNDJHV RI FRGH WKDW XVXDOO\ DSSHDU LQ WKH IRUP RI PHWKRGV LQ 2EMHFWLYH& %ORFN REMHFWV WRJHWKHU ZLWK *UDQG &HQWUDO 'LVSDWFK *&'  FUHDWH D KDUPRQLRXVHQYLURQPHQWLQZKLFK\RXFDQGHOLYHUKLJKSHUIRUPDQFHPXOWLWKUHDGHG DSSVLQL26DQG0DF26;:KDW¦VVRVSHFLDODERXWEORFNREMHFWVDQG*&'\RXPLJKW DVN",W¦VVLPSOHQRPRUHWKUHDGV$OO\RXKDYHWRGRLVWRSXW\RXUFRGHLQEORFNREMHFWV DQGDVN*&'WRWDNHFDUHRIWKHH[HFXWLRQRIWKDWFRGHIRU\RX ,QWKLVFKDSWHU\RXZLOOOHDUQWKHEDVLFVRIEORFNREMHFWVIROORZHGE\VRPHPRUHDG YDQFHGVXEMHFWV<RXZLOOXQGHUVWDQGHYHU\WKLQJ\RXQHHGWRNQRZDERXWEORFNREMHFWV EHIRUHPRYLQJWRWKH*UDQG&HQWUDO'LVSDWFKFKDSWHU)URPP\H[SHULHQFHWKHEHVW ZD\WROHDUQEORFNREMHFWVLVWKURXJKH[DPSOHVVR\RXZLOOVHHDORWRIWKHPLQWKLV FKDSWHU0DNHVXUH\RXWU\WKHH[DPSOHVIRU\RXUVHOILQ;FRGHWRUHDOO\JHWWKHV\QWD[ RIEORFNREMHFWV

Short Introduction to Block Objects %ORFNREMHFWVLQ2EMHFWLYH&DUHZKDWWKHSURJUDPPLQJILHOGFDOOVILUVWFODVVREMHFWV 7KLV PHDQV \RX FDQ EXLOG FRGH G\QDPLFDOO\ SDVV D EORFN REMHFW WR D PHWKRG DV D SDUDPHWHUDQGUHWXUQDEORFNREMHFWIURPDPHWKRG$OORIWKHVHWKLQJVPDNHLWHDVLHU WRFKRRVHZKDW\RXZDQWWRGRDWUXQWLPHDQGFKDQJHWKHDFWLYLW\RIDSURJUDP,Q SDUWLFXODUEORFNREMHFWVFDQEHUXQLQLQGLYLGXDOWKUHDGVE\*&'%HLQJ2EMHFWLYH& REMHFWVEORFNREMHFWVFDQEHWUHDWHGOLNHDQ\RWKHUREMHFW\RXFDQUHWDLQWKHPUHOHDVH WKHPDQGVRIRUWK%ORFNREMHFWVFDQDOVREHFDOOHGFORVXUHV %ORFNREMHFWVDUHVRPHWLPHVUHIHUUHGWRDVFORVXUHV

&RQVWUXFWLQJEORFNREMHFWVLVVLPLODUWRFRQVWUXFWLQJWUDGLWLRQDO&IXQFWLRQVDVZHZLOO VHHLQ£&RQVWUXFWLQJ%ORFN2EMHFWVDQG7KHLU6\QWD[¤RQSDJH%ORFNREMHFWVFDQ 1


KDYHUHWXUQYDOXHVDQGFDQDFFHSWSDUDPHWHUV%ORFNREMHFWVFDQEHGHILQHGLQOLQHRU WUHDWHGDVDVHSDUDWHEORFNRIFRGHVLPLODUWRD&IXQFWLRQ:KHQFUHDWHGLQOLQHWKH VFRSH RI YDULDEOHV DFFHVVLEOH WR EORFN REMHFWV LV FRQVLGHUDEO\ GLIIHUHQW IURP ZKHQ D EORFNREMHFWLVLPSOHPHQWHGDVDVHSDUDWHEORFNRIFRGH *&'ZRUNVZLWKEORFNREMHFWV:KHQSHUIRUPLQJWDVNVZLWK*&'\RXFDQSDVVD EORFNREMHFWZKRVHFRGHFDQJHWH[HFXWHGV\QFKURQRXVO\RUDV\QFKURQRXVO\GHSHQG LQJRQZKLFKPHWKRGV\RXXVHLQ*&'7KXV\RXFDQFUHDWHDEORFNREMHFWWKDWLV UHVSRQVLEOHIRUGRZQORDGLQJD85/SDVVHGWRLWDVDSDUDPHWHU7KDWVLQJOHEORFNREMHFW FDQWKHQEHXVHGLQYDULRXVSODFHVLQ\RXUDSSV\QFKURQRXVO\RUDV\QFKURQRXVO\GH SHQGLQJRQKRZ\RXZRXOGOLNHWRUXQLW<RXGRQ¦WKDYHWRPDNHWKHEORFNREMHFW V\QFKURQRXVRUDV\QFKURQRXVSHUVH\RXZLOOVLPSO\FDOOLWZLWKV\QFKURQRXVRUDV\Q FKURQRXV*&'PHWKRGVDQGWKHEORFNREMHFWZLOOMXVWZRUN %ORFNREMHFWVDUHTXLWHQHZWRSURJUDPPHUVZULWLQJL26DQG26;DSSV,QIDFWEORFN REMHFWVDUHQRWDVSRSXODUDVWKUHDGV\HWSHUKDSVEHFDXVHWKHLUV\QWD[LVDELWGLIIHUHQW IURPSXUH2EMHFWLYH&PHWKRGVDQGPRUHFRPSOLFDWHG1RQHWKHOHVVEORFNREMHFWVDUH HQRUPRXVO\SRZHUIXODQG$SSOHLVPDNLQJDELJSXVKWRZDUGLQFRUSRUDWLQJWKHPLQWR $SSOHOLEUDULHV<RXFDQDOUHDG\VHHWKHVHDGGLWLRQVLQFODVVHVVXFKDVNSMutableArray ZKHUHSURJUDPPHUVFDQVRUWWKHDUUD\XVLQJDEORFNREMHFW 7KLVFKDSWHULVGHGLFDWHGHQWLUHO\WRFRQVWUXFWLQJDQGXVLQJEORFNREMHFWVLQL26DQG 0DF26;DSSV,ZRXOGOLNHWRVWUHVVWKDWWKHRQO\ZD\WRJHWXVHGWREORFNREMHFWV¦ V\QWD[LVWRZULWHDIHZRIWKHPIRU\RXUVHOI+DYHDORRNDWWKHVDPSOHFRGHLQWKLV FKDSWHUDQGWU\LPSOHPHQWLQJ\RXURZQEORFNREMHFWV

Constructing Block Objects and Their Syntax %ORFNREMHFWVFDQHLWKHUEHLQOLQHRUFRGHGDVLQGHSHQGHQWEORFNVRIFRGH/HW¦VVWDUW ZLWKWKHODWWHUW\SH6XSSRVH\RXKDYHDPHWKRGLQ2EMHFWLYH&WKDWDFFHSWVWZRLQWHJHU YDOXHVRIW\SH NSIntegerDQGUHWXUQVWKHGLIIHUHQFHRIWKHWZRYDOXHVE\VXEWUDFWLQJ RQHIURPWKHRWKHUDVDQNSInteger - (NSInteger) subtract:(NSInteger)paramValue from:(NSInteger)paramFrom{ return paramFrom - paramValue; }

7KDWZDVYHU\VLPSOHZDVQ¦WLW"1RZOHW¦VWUDQVODWHWKLV2EMHFWLYH&FRGHWRDSXUH& IXQFWLRQ WKDW SURYLGHV WKH VDPH IXQFWLRQDOLW\ WR JHW RQH VWHS FORVHU WR OHDUQLQJ WKH V\QWD[RIEORFNREMHFWV NSInteger subtract(NSInteger paramValue, NSInteger paramFrom){ return paramFrom - paramValue; }

2 | Chapter 1: Introducing Block Objects


<RXFDQVHHWKDWWKH&IXQFWLRQLVTXLWHGLIIHUHQWLQV\QWD[IURPLWV2EMHFWLYH&FRXQ WHUSDUW1RZOHW¦VKDYHDORRNDWKRZZHFRXOGFRGHWKHVDPHIXQFWLRQDVDEORFNREMHFW NSInteger (^subtract)(NSInteger, NSInteger) = ^(NSInteger paramValue, NSInteger paramFrom){ return paramValue - paramValue; };

%HIRUH,JRLQWRGHWDLOVDERXWWKHV\QWD[RIEORFNREMHFWVOHWPHVKRZ\RXDIHZPRUH H[DPSOHV6XSSRVHZHKDYHDIXQFWLRQLQ&WKDWWDNHVDSDUDPHWHURIW\SHNSUInteger DQXQVLJQHGLQWHJHU DQGUHWXUQVLWDVDVWULQJRIW\SH NSString+HUHLVKRZZHLP SOHPHQWWKLVLQ& NSString* intToString (NSUInteger paramInteger){ return [NSString stringWithFormat:@"%lu", (unsigned long)paramInteger]; }

7R OHDUQ DERXW IRUPDWWLQJ VWULQJV ZLWK V\VWHPLQGHSHQGHQW IRUPDW VSHFLILHUVLQ2EMHFWLYH&SOHDVHUHIHUWR6WULQJ3URJUDPPLQJ*XLGHL26 'HYHORSHU/LEUDU\RQ$SSOH¦VZHEVLWH

7KHEORFNREMHFWHTXLYDOHQWRIWKLV&IXQFWLRQLVVKRZQLQ([DPSOH ([DPSOH([DPSOHEORFNREMHFWGHILQHGDVIXQFWLRQ NSString* (^intToString)(NSUInteger) = ^(NSUInteger paramInteger){ NSString *result = [NSString stringWithFormat:@"%lu", (unsigned long)paramInteger]; return result; };

7KHVLPSOHVWIRUPRIDQLQGHSHQGHQWEORFNREMHFWZRXOGEHDEORFNREMHFWWKDWUHWXUQV voidDQGGRHVQRWWDNHDQ\SDUDPHWHUVLQ void (^simpleBlock)(void) = ^{ /* Implement the block object here */ };

%ORFNREMHFWVFDQEHLQYRNHGLQWKHH[DFWVDPHZD\DV&IXQFWLRQV,IWKH\KDYHDQ\ SDUDPHWHUV\RXSDVVWKHSDUDPHWHUVWRWKHPOLNHD&IXQFWLRQDQGDQ\UHWXUQYDOXH FDQEHUHWULHYHGH[DFWO\DV\RXZRXOGUHWULHYHD&IXQFWLRQ¦VUHWXUQYDOXH+HUHLVDQ H[DPSOH

Constructing Block Objects and Their Syntax | 3


NSString* (^intToString)(NSUInteger) = ^(NSUInteger paramInteger){ NSString *result = [NSString stringWithFormat:@"%lu", (unsigned long)paramInteger]; return result; }; - (void) callIntToString{ NSString *string = intToString(10); NSLog(@"string = %@", string); }

7KH callIntToString2EMHFWLYH&PHWKRGLVFDOOLQJWKH intToStringEORFNREMHFWE\ SDVVLQJWKHYDOXHDVWKHRQO\SDUDPHWHUWRWKLVEORFNREMHFWDQGSODFLQJWKHUHWXUQ YDOXHRIWKLVEORFNREMHFWLQWKHstringORFDOYDULDEOH 1RZWKDWZHNQRZKRZWRZULWHEORFNREMHFWVDVLQGHSHQGHQWEORFNVRIFRGHOHW¦VKDYH DORRNDWSDVVLQJEORFNREMHFWVDVSDUDPHWHUVWR2EMHFWLYH&PHWKRGV:HZLOOKDYHWR WKLQNDELWDEVWUDFWO\WRXQGHUVWDQGWKHJRDORIWKHIROORZLQJH[DPSOH 6XSSRVHZHKDYHDQ2EMHFWLYH&PHWKRGWKDWDFFHSWVDQLQWHJHUDQGSHUIRUPVVRPH NLQGRIWUDQVIRUPDWLRQRQLWZKLFKPD\FKDQJHGHSHQGLQJRQZKDWHOVHLVKDSSHQLQJ LQRXUSURJUDP:HNQRZWKDWZH¦OOKDYHDQLQWHJHUDVLQSXWDQGDVWULQJDVRXWSXW EXWZH¦OOOHDYHWKHH[DFWWUDQVIRUPDWLRQXSWRDEORFNREMHFWWKDWFDQEHGLIIHUHQWHDFK WLPHRXUPHWKRGUXQV7KLVPHWKRGWKHUHIRUHZLOODFFHSWDVSDUDPHWHUVERWKWKHLQ WHJHUWREHWUDQVIRUPHGDQGWKHEORFNWKDWZLOOWUDQVIRUPLW )RURXUEORFNREMHFWZH¦OOXVHWKHVDPHintToStringEORFNREMHFWWKDWZHLPSOHPHQWHG HDUOLHULQ([DPSOH1RZZHQHHGDQ2EMHFWLYH&PHWKRGWKDWZLOODFFHSWDQXQ VLJQHG LQWHJHU SDUDPHWHU DQG D EORFN REMHFW DV LWV SDUDPHWHU 7KH XQVLJQHG LQWHJHU SDUDPHWHULVHDV\EXWKRZGRZHWHOORXUPHWKRGWKDWLWKDVWRDFFHSWDEORFNREMHFW RIWKHVDPHW\SHDVWKHintToStringEORFNREMHFW")LUVWZHtypedefWKHVLJQDWXUHRIWKH intToStringEORFNREMHFWZKLFKWHOOVWKHFRPSLOHUZKDWSDUDPHWHUVRXUEORFNREMHFW VKRXOGDFFHSW typedef NSString* (^IntToStringConverter)(NSUInteger paramInteger);

7KLVtypedefMXVWWHOOVWKHFRPSLOHUWKDWEORFNREMHFWVWKDWDFFHSWDQLQWHJHUSDUDPHWHU DQG UHWXUQ D VWULQJ FDQ VLPSO\ EH UHSUHVHQWHG E\ DQ LGHQWLILHU QDPHG IntToString Converter1RZOHW¦VJRDKHDGDQGZULWHRXU2EMHFWLYH&PHWKRGWKDWDFFHSWVERWKDQ LQWHJHUDQGDEORFNREMHFWRIW\SHIntToStringConverter - (NSString *) convertIntToString:(NSUInteger)paramInteger usingBlockObject:(IntToStringConverter)paramBlockObject{ return paramBlockObject(paramInteger); }

4 | Chapter 1: Introducing Block Objects


$OOZHKDYHWRGRQRZLVFDOOWKHconvertIntToString:PHWKRGZLWKRXUEORFNREMHFWRI FKRLFH ([DPSOH  ([DPSOH&DOOLQJWKHEORFNREMHFWLQDQRWKHUPHWKRG - (void) doTheConversion{ NSString *result = [self convertIntToString:123 usingBlockObject:intToString]; NSLog(@"result = %@", result); }

1RZWKDWZHNQRZVRPHWKLQJDERXWLQGHSHQGHQWEORFNREMHFWVOHW¦VWXUQWRLQOLQH EORFN REMHFWV ,Q WKH doTheConversion PHWKRG ZH MXVW VDZ ZH SDVVHG WKH intTo String EORFN REMHFW DV WKH SDUDPHWHU WR WKH convertIntToString:usingBlockObject: PHWKRG:KDWLIZHGLGQ¦WKDYHDEORFNREMHFWUHDG\WREHSDVVHGWRWKLVPHWKRG":HOO WKDWZRXOGQ¦WEHDSUREOHP$VPHQWLRQHGEHIRUHEORFNREMHFWVDUHILUVWFODVVIXQFWLRQV DQGFDQEHFRQVWUXFWHGDWUXQWLPH/HW¦VKDYHDORRNDWDQDOWHUQDWLYHLPSOHPHQWDWLRQ RIWKHdoTheConversionPHWKRG ([DPSOH  ([DPSOH([DPSOHEORFNREMHFWGHILQHGDVIXQFWLRQ - (void) doTheConversion{ IntToStringConverter inlineConverter = ^(NSUInteger paramInteger){ NSString *result = [NSString stringWithFormat:@"%lu", (unsigned long)paramInteger]; return result; }; NSString *result = [self convertIntToString:123 usingBlockObject:inlineConverter]; NSLog(@"result = %@", result); }

&RPSDUH([DPSOHWRWKHHDUOLHU([DPSOH,KDYHUHPRYHGWKHLQLWLDOFRGHWKDW SURYLGHG WKH EORFN REMHFW¦V VLJQDWXUH ZKLFK FRQVLVWHG RI D QDPH DQG DUJXPHQW (^intToString)(NSUInteger),OHIWDOOWKHUHVWRIWKHEORFNREMHFWLQWDFW,WLVQRZDQ DQRQ\PRXVREMHFW%XWWKLVGRHVQ¦WPHDQ,KDYHQRZD\WRUHIHUWRWKHEORFNREMHFW, DVVLJQ LW XVLQJ DQ HTXDO VLJQ WR D W\SH DQG D QDPH IntToStringConverter inline Converter1RZ,FDQXVHWKHGDWDW\SHWRHQIRUFHSURSHUXVHLQPHWKRGVDQGXVHWKH QDPHWRDFWXDOO\SDVVWKHEORFNREMHFW ,QDGGLWLRQWRFRQVWUXFWLQJEORFNREMHFWVLQOLQHDVMXVWVKRZQZHFDQFRQVWUXFWDEORFN REMHFWZKLOHSDVVLQJLWDVDSDUDPHWHU

Constructing Block Objects and Their Syntax | 5


- (void) doTheConversion{ NSString *result = [self convertIntToString:123 usingBlockObject:^NSString *(NSUInteger paramInteger) { NSString *result = [NSString stringWithFormat:@"%lu", (unsigned long)paramInteger]; return result; }]; NSLog(@"result = %@", result); }

&RPSDUHWKLVH[DPSOHZLWK([DPSOH%RWKPHWKRGVXVHDEORFNREMHFWWKURXJK WKH usingBlockObjectV\QWD[%XWZKHUHDVWKHHDUOLHUYHUVLRQUHIHUUHGWRDSUHYLRXVO\ GHFODUHGEORFNREMHFWE\QDPH intToString WKLVRQHVLPSO\FUHDWHVDEORFNREMHFWRQ WKH IO\ ,Q WKLV FRGH ZH FRQVWUXFWHG DQ LQOLQH EORFN REMHFW WKDW JHWV SDVVHG WR WKH convertIntToString:usingBlockObject:PHWKRGDVWKHVHFRQGSDUDPHWHU ,EHOLHYHWKDWDWWKLVSRLQW\RXNQRZHQRXJKDERXWEORFNREMHFWVWREHDEOHWRPRYHWR PRUHLQWHUHVWLQJGHWDLOVZKLFKZH¦OOEHJLQZLWKLQWKHIROORZLQJVHFWLRQ

Variables and Their Scope in Block Objects +HUHLVDEULHIVXPPDU\RIZKDW\RXPXVWNQRZDERXWYDULDEOHVLQEORFNREMHFWV Â&#x2021; /RFDOYDULDEOHVLQEORFNREMHFWVZRUNH[DFWO\WKHVDPHDVLQ2EMHFWLYH&PHWKRGV Â&#x2021; )RULQOLQHEORFNREMHFWVORFDOYDULDEOHVFRQVWLWXWHQRWRQO\YDULDEOHVGHILQHGZLWKLQ WKHEORFNEXWDOVRWKHYDULDEOHVWKDWKDYHEHHQGHILQHGLQWKHPHWKRGWKDWLPSOH PHQWVWKDWEORFNREMHFW ([DPSOHVZLOOFRPHVKRUWO\

Â&#x2021; <RX FDQQRW UHIHU WR self LQ LQGHSHQGHQW EORFN REMHFWV LPSOHPHQWHG LQ DQ 2EMHFWLYH&FODVV,I\RXQHHGWRDFFHVVself\RXPXVWSDVVWKDWREMHFWWRWKHEORFN REMHFWDVDSDUDPHWHU:HZLOOVHHDQH[DPSOHRIWKLVVRRQ Â&#x2021; <RXFDQUHIHUWRselfLQDQLQOLQHEORFNREMHFWRQO\LIselfLVSUHVHQWLQWKHOH[LFDO VFRSHLQVLGHZKLFKWKHEORFNREMHFWLVFUHDWHG Â&#x2021; )RULQOLQHEORFNREMHFWVORFDOYDULDEOHVWKDWDUHGHILQHGLQVLGHWKHEORFNREMHFW¦V LPSOHPHQWDWLRQFDQEHUHDGIURPDQGZULWWHQWR,QRWKHUZRUGVWKHEORFNREMHFW KDVUHDGZULWHDFFHVVWRYDULDEOHVGHILQHGLQVLGHWKHEORFNREMHFW¦VERG\ Â&#x2021; )RULQOLQHEORFNREMHFWVYDULDEOHVORFDOWRWKH2EMHFWLYH&PHWKRGWKDWLPSOHPHQWV WKDWEORFNFDQRQO\EHUHDGIURPQRWZULWWHQWR7KHUHLVDQH[FHSWLRQWKRXJKD EORFNREMHFWFDQZULWHWRVXFKYDULDEOHVLIWKH\DUHGHILQHGZLWKWKH__blockVWRUDJH W\SH:HZLOOVHHDQH[DPSOHRIWKLVDVZHOO

6 | Chapter 1: Introducing Block Objects


Â&#x2021; 6XSSRVH\RXKDYHDQREMHFWRIW\SH NSObjectDQGLQVLGHWKDWREMHFW¦VLPSOHPHQ WDWLRQ\RXDUHXVLQJDEORFNREMHFWLQFRQMXQFWLRQZLWK*&',QVLGHWKLVEORFN REMHFW\RXZLOOKDYHUHDGZULWHDFFHVVWRGHFODUHGSURSHUWLHVRIWKDWNSObjectLQVLGH ZKLFK\RXUEORFNLVLPSOHPHQWHG Â&#x2021; <RXFDQDFFHVVGHFODUHGSURSHUWLHVRI\RXUNSObjectLQVLGHLQGHSHQGHQWEORFNRE MHFWVRQO\LI\RXXVHWKHVHWWHUDQGJHWWHUPHWKRGVRIWKHVHSURSHUWLHV<RXFDQQRW DFFHVVGHFODUHGSURSHUWLHVRIDQREMHFWXVLQJGRWQRWDWLRQLQVLGHDQLQGHSHQGHQW EORFNREMHFW /HW¦VILUVWVHHKRZZHFDQXVHYDULDEOHVWKDWDUHORFDOWRWKHLPSOHPHQWDWLRQRIWZR EORFNREMHFWV2QHLVDQLQOLQHEORFNREMHFWDQGWKHRWKHUDQLQGHSHQGHQWEORFNREMHFW void (^independentBlockObject)(void) = ^(void){ NSInteger localInteger = 10; NSLog(@"local integer = %lu", (unsigned long)localInteger); localInteger = 20; NSLog(@"local integer = %lu", (unsigned long)localInteger); };

,QYRNLQJWKLVEORFNREMHFWWKHYDOXHVZHDVVLJQHGDUHSULQWHGWRWKHFRQVROHZLQGRZ local integer = 10 local integer = 20

6RIDUVRJRRG1RZOHW¦VKDYHDORRNDWLQOLQHEORFNREMHFWVDQGYDULDEOHVWKDWDUHORFDO WRWKHP - (void) simpleMethod{ NSUInteger outsideVariable = 10; NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"obj1", @"obj2", nil]; [array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSUInteger insideVariable = 20; NSLog(@"Outside variable = %lu", (unsigned long)outsideVariable); NSLog(@"Inside variable = %lu", (unsigned long)insideVariable); /* Return value for our block object */ return NSOrderedSame; }]; [array release]; }

Variables and Their Scope in Block Objects | 7


7KHsortUsingComparator:LQVWDQFHPHWKRGRINSMutableArrayDWWHPSWV WRVRUWDPXWDEOHDUUD\7KHJRDORIWKLVH[DPSOHFRGHLVMXVWWRGHP RQVWUDWHWKHXVHRIORFDOYDULDEOHVVR\RXGRQ¦WKDYHWRNQRZZKDWWKLV PHWKRGDFWXDOO\GRHV

7KHEORFNREMHFWFDQUHDGDQGZULWHLWVRZQ insideVariableORFDOYDULDEOH+RZHYHU WKHEORFNREMHFWKDVUHDGRQO\DFFHVVWRWKH outsideVariableYDULDEOHE\GHIDXOW,Q RUGHUWRDOORZWKHEORFNREMHFWWRZULWHWR outsideVariableZHPXVWSUHIL[ outside VariableZLWKWKH__blockVWRUDJHW\SH - (void) simpleMethod{ __block NSUInteger outsideVariable = 10; NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"obj1", @"obj2", nil]; [array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSUInteger insideVariable = 20; outsideVariable = 30; NSLog(@"Outside variable = %lu", (unsigned long)outsideVariable); NSLog(@"Inside variable = %lu", (unsigned long)insideVariable); /* Return value for our block object */ return NSOrderedSame; }]; [array release]; }

$FFHVVLQJ selfLQLQOLQHEORFNREMHFWVLVILQHDVORQJDV selfLVGHILQHGLQWKHOH[LFDO VFRSHLQVLGHZKLFKWKHLQOLQHEORFNREMHFWLVFUHDWHG)RULQVWDQFHLQWKLVH[DPSOHWKH EORFNREMHFWZLOOEHDEOHWRDFFHVVselfVLQFHsimpleMethodLVDQLQVWDQFHPHWKRGRIDQ 2EMHFWLYH&FODVV - (void) simpleMethod{ NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"obj1", @"obj2", nil]; [array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSLog(@"self = %@", self); /* Return value for our block object */ return NSOrderedSame;

8 | Chapter 1: Introducing Block Objects


}]; [array release]; }

<RXFDQQRWZLWKRXWDFKDQJHLQ\RXUEORFNREMHFW¦VLPSOHPHQWDWLRQDFFHVV selfLQ DQLQGHSHQGHQWEORFNREMHFW$WWHPSWLQJWRFRPSLOHWKLVFRGHZLOOJLYH\RXDFRPSLOH WLPHHUURU void (^incorrectBlockObject)(void) = ^{ NSLog(@"self = %@", self); /* self is undefined here */ };

,I\RXZDQWWRDFFHVVselfLQDQLQGHSHQGHQWEORFNREMHFWVLPSO\SDVVWKHREMHFWWKDW selfUHSUHVHQWVDVDSDUDPHWHUWR\RXUEORFNREMHFW void (^correctBlockObject)(id) = ^(id self){ NSLog(@"self = %@", self); }; - (void) callCorrectBlockObject{ correctBlockObject(self); }

<RXGRQ¦WKDYHWRDVVLJQWKHQDPHselfWRWKLVSDUDPHWHU<RXFDQVLP SO\FDOOWKLVSDUDPHWHUDQ\WKLQJHOVH+RZHYHULI\RXFDOOWKLVSDUDPHWHU self\RXFDQVLPSO\JUDE\RXUEORFNREMHFW¦VFRGHODWHUDQGSODFHLWLQ DQ2EMHFWLYH&PHWKRG¦VLPSOHPHQWDWLRQZLWKRXWKDYLQJWRFKDQJHHY HU\LQVWDQFHRI\RXUYDULDEOH¦VQDPHWRselfIRULWWREHXQGHUVWRRGE\ WKHFRPSLOHU

/HW¦VKDYHDORRNDWGHFODUHGSURSHUWLHVDQGKRZEORFNREMHFWVFDQDFFHVVWKHP)RU LQOLQHEORFNREMHFWV\RXFDQXVHGRWQRWDWLRQWRUHDGIURPRUZULWHWRGHFODUHGSURS HUWLHVRIself)RULQVWDQFHOHW¦VVD\ZHKDYHDGHFODUHGSURSHUW\RIW\SHNSStringFDOOHG stringPropertyLQRXUFODVV #import <UIKit/UIKit.h> @interface GCDAppDelegate : NSObject <UIApplicationDelegate> { @protected NSString *stringProperty; } @property (nonatomic, retain) NSString

*stringProperty;

@end

Variables and Their Scope in Block Objects | 9


1RZZHFDQVLPSO\DFFHVVWKLVSURSHUW\LQDQLQOLQHEORFNREMHFWOLNHVR #import "GCDAppDelegate.h" @implementation GCDAppDelegate @synthesize stringProperty; - (void) simpleMethod{ NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"obj1", @"obj2", nil]; [array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSLog(@"self = %@", self); self.stringProperty = @"Block Objects"; NSLog(@"String property = %@", self.stringProperty); /* Return value for our block object */ return NSOrderedSame; }]; [array release]; } - (void) dealloc{ [stringProperty release]; [super dealloc]; } @end

,QDQLQGHSHQGHQWEORFNREMHFWKRZHYHU\RXFDQQRWXVHGRWQRWDWLRQWRUHDGIURPRU ZULWHWRDGHFODUHGSURSHUW\ void (^correctBlockObject)(id) = ^(id self){ NSLog(@"self = %@", self); /* Should use setter method instead of this */ self.stringProperty = @"Block Objects"; /* Compile-time Error */ /* Should use getter method instead of this */ NSLog(@"self.stringProperty = %@", self.stringProperty); /* Compile-time Error */ };

,QVWHDGRIGRWQRWDWLRQLQWKLVVFHQDULRXVHWKHJHWWHUDQGWKHVHWWHUPHWKRGVRIWKLV V\QWKHVL]HGSURSHUW\ 10 | Chapter 1: Introducing Block Objects


void (^correctBlockObject)(id) = ^(id self){ NSLog(@"self = %@", self); /* This will work fine */ [self setStringProperty:@"Block Objects"]; /* This will work fine as well */ NSLog(@"self.stringProperty = %@", [self stringProperty]); };

:KHQLWFRPHVWRLQOLQHEORFNREMHFWVWKHUHLVRQHYHU\LPSRUWDQWUXOHWKDW\RXKDYH WRUHPHPEHULQOLQHEORFNREMHFWVFRS\WKHYDOXHIRUWKHYDULDEOHVLQWKHLUOH[LFDOVFRSH ,I\RXGRQ¦WXQGHUVWDQGZKDWWKDWPHDQVGRQ¦WZRUU\/HW¦VKDYHDORRNDWDQH[DPSOH typedef void (^BlockWithNoParams)(void); - (void) scopeTest{ NSUInteger integerValue = 10; /*************** Definition of internal block object ***************/ BlockWithNoParams myBlock = ^{ NSLog(@"Integer value inside the block = %lu", (unsigned long)integerValue); }; /*************** End definition of internal block object ***************/ integerValue = 20; /* Call the block here after changing the value of the integerValue variable */ myBlock(); NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue); }

:HDUHGHFODULQJDQLQWHJHUORFDOYDULDEOHDQGLQLWLDOO\DVVLJQLQJWKHYDOXHRIWRLW :HWKHQLPSOHPHQWRXUEORFNREMHFWEXWGRQ¦WFDOOWKHEORFNREMHFW\HW$IWHUWKHEORFN REMHFWLVLPSOHPHQWHGZHVLPSO\FKDQJHWKHYDOXHRIWKHORFDOYDULDEOHWKDWWKHEORFN REMHFWZLOOODWHUWU\WRUHDGZKHQZHFDOOLW5LJKWDIWHUFKDQJLQJWKHORFDOYDULDEOH¦V YDOXHWRZHFDOOWKHEORFNREMHFW<RXZRXOGH[SHFWWKHEORFNREMHFWWRSULQWWKH YDOXHIRUWKHYDULDEOHEXWLWZRQ¦W,WZLOOSULQWDV\RXFDQVHHKHUH Integer value inside the block = 10 Integer value outside the block = 20

:KDW¦V KDSSHQLQJ KHUH LV WKDW WKH EORFN REMHFW LV NHHSLQJ D UHDGRQO\ FRS\ RI WKH integerValueYDULDEOHIRULWVHOIULJKWZKHUHWKHEORFNLVLPSOHPHQWHG<RXPLJKWEH WKLQNLQJ ZK\ LV WKH EORFN REMHFW FDSWXULQJ D UHDGRQO\ YDOXH RI WKH ORFDO YDULDEOH

Variables and Their Scope in Block Objects | 11


integerValue"7KHDQVZHULVVLPSOHDQGZH¦YHDOUHDG\OHDUQHGLWLQWKLVVHFWLRQ8QOHVV SUHIL[HGZLWKVWRUDJHW\SH__blockORFDOYDULDEOHVLQWKHOH[LFDOVFRSHRIDEORFNREMHFW

DUHMXVWSDVVHGWRWKHEORFNREMHFWDVUHDGRQO\YDULDEOHV7KHUHIRUHWRFKDQJHWKLV EHKDYLRUZHFRXOGFKDQJHWKHLPSOHPHQWDWLRQRIRXUscopeTestPHWKRGWRSUHIL[WKH integerValueYDULDEOHZLWK__blockVWRUDJHW\SHOLNHVR - (void) scopeTest{ __block NSUInteger integerValue = 10; /*************** Definition of internal block object ***************/ BlockWithNoParams myBlock = ^{ NSLog(@"Integer value inside the block = %lu", (unsigned long)integerValue); }; /*************** End definition of internal block object ***************/ integerValue = 20; /* Call the block here after changing the value of the integerValue variable */ myBlock(); NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue); }

1RZLIZHJHWWKHUHVXOWVIURPWKHFRQVROHZLQGRZDIWHUWKHscopeTestPHWKRGLVFDOOHG ZHZLOOVHHWKLV Integer value inside the block = 20 Integer value outside the block = 20

7KLVVHFWLRQVKRXOGKDYHJLYHQ\RXVXIILFLHQWLQIRUPDWLRQDERXWXVLQJYDULDEOHVZLWK EORFNREMHFWV,VXJJHVWWKDW\RXZULWHDIHZEORFNREMHFWVDQGXVHYDULDEOHVLQVLGHWKHP DVVLJQLQJWRWKHPDQGUHDGLQJIURPWKHPWRJHWDEHWWHUXQGHUVWDQGLQJRIKRZEORFN REMHFWVXVHYDULDEOHV.HHSFRPLQJEDFNWRWKLVVHFWLRQLI\RXIRUJHWWKHUXOHVWKDWJRYHUQ YDULDEOHDFFHVVLQEORFNREMHFWV

Invoking Block Objects :H¦YHVHHQH[DPSOHVRILQYRNLQJEORFNREMHFWVLQ£&RQVWUXFWLQJ%ORFN2EMHFWVDQG 7KHLU 6\QWD[¤ RQ SDJH  DQG £9DULDEOHV DQG 7KHLU 6FRSH LQ %ORFN 2E MHFWV¤RQSDJH7KLVVHFWLRQFRQWDLQVPRUHFRQFUHWHH[DPSOHV ,I\RXKDYHDQLQGHSHQGHQWEORFNREMHFW\RXFDQVLPSO\LQYRNHLWMXVWOLNH\RXZRXOG LQYRNHD&IXQFWLRQ void (^simpleBlock)(NSString *) = ^(NSString *paramString){ /* Implement the block object here and use the paramString parameter */

12 | Chapter 1: Introducing Block Objects


}; - (void) callSimpleBlock{ simpleBlock(@"O'Reilly"); }

,I\RXZDQWWRLQYRNHDQLQGHSHQGHQWEORFNREMHFWZLWKLQDQRWKHULQGHSHQGHQWEORFN REMHFWIROORZWKHVDPHLQVWUXFWLRQVE\LQYRNLQJWKHQHZEORFNREMHFWMXVWDV\RXZRXOG LQYRNHD&PHWKRG /*************** Definition of first block object ***************/ NSString *(^trimString)(NSString *) = ^(NSString *inputString){ NSString *result = [inputString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; return result; }; /*************** End definition of first block object ***************/ /*************** Definition of second block object ***************/ NSString *(^trimWithOtherBlock)(NSString *) = ^(NSString *inputString){ return trimString(inputString); }; /*************** End definition of second block object ***************/ - (void) callTrimBlock{ NSString *trimmedString = trimWithOtherBlock(@" NSLog(@"Trimmed string = %@", trimmedString);

O'Reilly

");

}

,QWKLVH[DPSOHJRDKHDGDQGLQYRNHWKHcallTrimBlock2EMHFWLYH&PHWKRG [self callTrimBlock];

7KHcallTrimBlockPHWKRGZLOOFDOOWKHtrimWithOtherBlockEORFNREMHFWDQGWKHtrim WithOtherBlockEORFNREMHFWZLOOFDOOWKH trimStringEORFNREMHFWLQRUGHUWRWULPWKH JLYHQVWULQJ7ULPPLQJDVWULQJLVDQHDV\WKLQJWRGRDQGFDQEHGRQHLQRQHOLQHRI FRGHEXWWKLVH[DPSOHFRGHVKRZVKRZ\RXFDQFDOOEORFNREMHFWVZLWKLQEORFNREMHFWV ,Q&KDSWHU\RXZLOOOHDUQKRZWRLQYRNHEORFNREMHFWVXVLQJ*UDQG&HQWUDO'LVSDWFK V\QFKURQRXVO\RUDV\QFKURQRXVO\WRXQOHDVKWKHUHDOSRZHURIEORFNREMHFWV

Memory Management for Block Objects L26DSSVUXQLQDUHIHUHQFHFRXQWHGHQYLURQPHQW7KDWPHDQVHYHU\REMHFWKDVDUHWDLQ FRXQWWRHQVXUHWKH2EMHFWLYH&UXQWLPHNHHSVLWDVORQJDVLWPLJKWEHXVHGDQGJHWV ULGRILWZKHQQRRQHFDQXVHLWDQ\PRUH<RXFDQWKLQNRIDUHWDLQFRXQWDVWKHQXPEHU RIOHDVKHVRQDQDQLPDO$VORQJDVWKHUHLVDWOHDVWRQHOHDVKWKHDQLPDOZLOOVWD\ZKHUH Memory Management for Block Objects | 13


LWLV,IWKHUHDUHWZROHDVKHVWKHDQLPDOKDVWREHXQOHDVKHGWZLFHWREHUHOHDVHG$V VRRQDVDOOOHDVKHVDUHUHOHDVHGWKHDQLPDOLVIUHH6XEVWLWXWHDOORFFXUUHQFHVRIDQL PDOZLWKREMHFWLQWKHSUHFHGLQJVHQWHQFHVDQG\RXZLOOXQGHUVWDQGKRZDUHIHUHQFH FRXQWHGHQYLURQPHQWZRUNV:KHQZHDOORFDWHDQREMHFWLQL26WKHUHWDLQFRXQWRI WKDWREMHFWEHFRPHV(YHU\DOORFDWLRQKDVWREHSDLUHGZLWKDUHOHDVHFDOOLQYRNHGRQ WKHREMHFWWRGHFUHPHQWWKHUHOHDVHFRXQWE\,I\RXZDQWWRNHHSWKHREMHFWDURXQG LQPHPRU\\RXKDYHWRPDNHVXUH\RXKDYHUHWDLQHGWKDWREMHFWVRWKDWLWVUHWDLQFRXQW LVLQFUHPHQWHGE\WKHUXQWLPH )RUPRUHLQIRUPDWLRQDERXWPHPRU\PDQDJHPHQWLQL26DSSVSOHDVH UHIHUWRL263URJUDPPLQJ&RRNERRN 2¦5HLOO\ 

%ORFNREMHFWVDUHREMHFWVDVZHOOVRWKH\DOVRFDQEHFRSLHGUHWDLQHGDQGUHOHDVHG :KHQZULWLQJDQL26DSS\RXFDQVLPSO\WUHDWEORFNREMHFWVDVQRUPDOREMHFWVDQG UHWDLQDQGUHOHDVHWKHPDV\RXZRXOGZLWKRWKHUREMHFWV typedef NSString* (^StringTrimmingBlockObject)(NSString *paramString); NSString* (^trimString)(NSString *) = ^(NSString *paramString){ NSString *result = nil; result = [paramString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; return result; }; - (void) callTrimString{ StringTrimmingBlockObject trimStringCopy = Block_copy(trimString); NSString *trimmedString = trimStringCopy(@"

O'Reilly

");

NSLog(@"Trimmed string = %@", trimmedString); Block_release(trimStringCopy); }

8VH Block_copy RQ D EORFN REMHFW WR GHFODUH RZQHUVKLS RI WKDW EORFN REMHFW IRU WKH SHULRGRIWLPH\RXZLVKWRXVHLW:KLOHUHWDLQLQJRZQHUVKLSRYHUDEORFNREMHFW\RX FDQEHVXUHWKDWL26ZLOOQRWGLVSRVHRIWKDWEORFNREMHFWDQGLWVPHPRU\2QFH\RX DUHGRQHZLWKWKDWEORFNREMHFW\RXPXVWUHOHDVHRZQHUVKLSXVLQJBlock_release ,I\RXDUHXVLQJEORFNREMHFWVLQ\RXU0DF26;DSSV\RXVKRXOGIROORZWKHVDPHUXOHV ZKHWKHU \RX DUH ZULWLQJ \RXU DSS LQ D JDUEDJHFROOHFWHG RU D UHIHUHQFHFRXQWLQJ

14 | Chapter 1: Introducing Block Objects


HQYLURQPHQW+HUHLVWKHVDPHH[DPSOHFRGHIURPL26ZULWWHQIRU0DF26;<RXFDQ FRPSLOHLWZLWKDQGZLWKRXWJDUEDJHFROOHFWLRQHQDEOHGIRU\RXUSURMHFW typedef NSString* (^StringTrimmingBlockObject)(NSString *paramString); NSString* (^trimString)(NSString *) = ^(NSString *paramString){ NSString *result = nil; result = [paramString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; return result; }; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { StringTrimmingBlockObject trimmingBlockObject = Block_copy(trimString); NSString *trimmedString = trimmingBlockObject(@"

O'Reilly

");

NSLog(@"Trimmed string = %@", trimmedString); Block_release(trimmingBlockObject); }

,QL26\RXFDQDOVRXVHDXWRUHOHDVHEORFNREMHFWVOLNHVR NSString* (^trimString)(NSString *) = ^(NSString *paramString){ NSString *result = nil; result = [paramString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; return result; }; - (id) autoreleaseTrimStringBlockObject{ return [trimString autorelease]; }

<RXFDQDOVR GHILQH GHFODUHG SURSHUWLHV WKDW KROG D FRS\ RIDEORFNREMHFW+HUHLV WKHKILOHRIRXUREMHFWWKDWGHFODUHVDSURSHUW\ nonatomic, copy IRUDEORFNREMHFW #import <UIKit/UIKit.h> typedef NSString* (^StringTrimmingBlockObject)(NSString *paramString); @interface GCDAppDelegate : NSObject <UIApplicationDelegate> { @protected StringTrimmingBlockObject trimmingBlock;

Memory Management for Block Objects | 15


} @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, copy) StringTrimmingBlockObject trimmingBlock; @end

7KLVFRGHLVZULWWHQLQVLGHWKHDSSOLFDWLRQGHOHJDWHRIDVLPSOHXQLYHUVDO L26DSS

1RZOHW¦VJRDKHDGDQGLPSOHPHQWRXUDSSOLFDWLRQ¦VGHOHJDWHREMHFW #import "GCDAppDelegate.h" @implementation GCDAppDelegate @synthesize window=_window; @synthesize trimmingBlock; NSString* (^trimString)(NSString *) = ^(NSString *paramString){ NSString *result = nil; result = [paramString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; return result; }; - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ self.trimmingBlock = trimString; NSString *trimmedString = self.trimmingBlock(@"

O'Reilly

NSLog(@"Trimmed string = %@", trimmedString);

");

}

// Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES;

- (void)dealloc{ [trimmingBlock release]; [_window release]; [super dealloc]; } @end

16 | Chapter 1: Introducing Block Objects


:KDWZHZDQWWRDFKLHYHLQWKLVH[DPSOHLVILUVWWRGHFODUHRZQHUVKLSRYHUWKHtrim StringEORFNREMHFWLQRXUDSSOLFDWLRQGHOHJDWHDQGWKHQWRXVHWKDWEORFNREMHFWWR WULPDVLQJOHVWULQJRIILWVZKLWHVSDFHV 7KH trimmingBlockSURSHUW\LVGHFODUHGDV nonatomic7KLVPHDQVWKDW WKLVSURSHUW\¦VWKUHDGVDIHQHVVPXVWEHPDQDJHGE\XVDQGZHVKRXOG PDNHVXUHWKLVSURSHUW\ZRQ¦WJHWDFFHVVHGIURPPRUHWKDQRQHWKUHDG DWDWLPH:HZRQ¦WUHDOO\KDYHWRFDUHDERXWWKLVDWWKHPRPHQWDVZH DUHQRWGRLQJDQ\WKLQJIDQF\ZLWKWKUHDGVULJKWQRZ7KLVSURSHUW\LV DOVRGHILQHGDVcopyZKLFKWHOOVWKHUXQWLPHWRFDOOWKHcopyPHWKRGRQ DQ\REMHFWLQFOXGLQJEORFNREMHFWVZKHQZHDVVLJQWKRVHREMHFWVWRWKLV SURSHUW\DV RSSRVHG WR UHWDLQLQJ WKRVH REMHFWV E\FDOOLQJWKH retain PHWKRGRQWKHP

$VZHVDZEHIRUHWKHtrimStringEORFNREMHFWDFFHSWVDVWULQJDVLWVSDUDPHWHUWULPV WKLV VWULQJ DQG UHWXUQV LW WR WKH FDOOHU ,QVLGH WKH application:didFinishLaunch ingWithOptions:LQVWDQFHPHWKRGRIRXUDSSOLFDWLRQGHOHJDWHZHDUHVLPSO\XVLQJGRW QRWDWLRQWRDVVLJQWKHtrimStringEORFNREMHFWWRWKHtrimmingBlockGHFODUHGSURSHUW\ 7KLVPHDQVWKDWWKHUXQWLPHZLOOLPPHGLDWHO\FDOOWKH Block_copyRQWKH trimString EORFN REMHFW DQG DVVLJQ WKH UHVXOWLQJ YDOXH WR WKH trimmingBlock GHFODUHG SURSHUW\ )URP WKLV SRLQW RQ XQWLO ZH UHOHDVH WKH EORFN REMHFW ZH KDYH D FRS\ RI LW LQ WKH trimmingBlockGHFODUHGSURSHUW\ 1RZZHFDQXVHWKHtrimmingBlockGHFODUHGSURSHUW\WRLQYRNHWKHtrimStringEORFN REMHFWDVVKRZQLQWKHIROORZLQJFRGH NSString *trimmedString = self.trimmingBlock(@"

O'Reilly

");

2QFHZHDUHGRQHLQWKH deallocLQVWDQFHPHWKRGRIRXUREMHFWZHZLOOUHOHDVHWKH trimmingBlockGHFODUHGSURSHUW\E\FDOOLQJLWVreleasePHWKRG :LWKPRUHLQVLJKWLQWREORFNREMHFWVDQGKRZWKH\PDQDJHWKHLUYDULDEOHVDQGPHPRU\ LWLVILQDOO\WLPHWRPRYHWR&KDSWHUWROHDUQDERXWWKHZRQGHUWKDWLVFDOOHG*UDQG &HQWUDO'LVSDWFK:HZLOOEHXVLQJEORFNREMHFWVZLWK*&'DORWVRPDNHVXUH\RX KDYHUHDOO\XQGHUVWRRGWKHPDWHULDOLQWKLVFKDSWHUEHIRUHPRYLQJRQWRWKHQH[W

Memory Management for Block Objects | 17


CHAPTER 2

Programming Grand Central Dispatch

*UDQG&HQWUDO'LVSDWFKRU*&'IRUVKRUWLVDORZOHYHO&$3,WKDWZRUNVZLWKEORFN REMHFWV7KHUHDOXVHIRU*&'LVWRGLVSDWFKWDVNVWRPXOWLSOHFRUHVZLWKRXWPDNLQJ \RXWKHSURJUDPPHUZRUU\DERXWZKLFKFRUHLVH[HFXWLQJZKLFKWDVN2Q0DF26; PXOWLFRUHGHYLFHVLQFOXGLQJODSWRSVKDYHEHHQDYDLODEOHWRXVHUVIRUTXLWHVRPHWLPH :LWKWKHLQWURGXFWLRQRIPXOWLFRUHGHYLFHVVXFKDVWKHL3DGSURJUDPPHUVFDQZULWH DPD]LQJPXOWLFRUHDZDUHPXOWLWKUHDGHGDSSVIRUL266HHWKHSUHIDFHIRUPRUHEDFN JURXQGRQWKHLPSRUWDQFHRIPXOWLFRUHV ,Q&KDSWHUZHOHDUQHGKRZWRXVHEORFNREMHFWV,I\RXKDYHQRWUHDGWKDWFKDSWHU, VWURQJO\VXJJHVWWKDW\RXGRVWUDLJKWDZD\DV*&'UHOLHVKHDYLO\RQEORFNREMHFWVDQG WKHLUG\QDPLFQDWXUH,QWKLVFKDSWHUZHZLOOOHDUQDERXWUHDOO\IXQDQGLQWHUHVWLQJ WKLQJVWKDWSURJUDPPHUVFDQDFKLHYHZLWK*&'LQL26DQG0DF26;

Short Introduction to Grand Central Dispatch $WWKHKHDUWRI*&'DUHGLVSDWFKTXHXHV'LVSDWFKTXHXHVDVZHZLOOVHHLQ£'LIIHUHQW 7\SHV RI 'LVSDWFK 4XHXHV¤ RQ SDJH  DUH SRROV RI WKUHDGV PDQDJHG E\ *&' RQ WKHKRVWRSHUDWLQJV\VWHPZKHWKHULWLVL26RU0DF26;<RXZLOOQRWEHZRUNLQJZLWK WKHVHWKUHDGVGLUHFWO\<RXZLOOMXVWZRUNZLWKGLVSDWFKTXHXHVGLVSDWFKLQJWDVNVWR WKHVHTXHXHVDQGDVNLQJWKHTXHXHVWRLQYRNH\RXUWDVNV*&'RIIHUVVHYHUDORSWLRQV IRUUXQQLQJWDVNVV\QFKURQRXVO\DV\QFKURQRXVO\DIWHUDFHUWDLQGHOD\HWF 7RVWDUWXVLQJ*&'LQ\RXUDSSV\RXGRQ¦WKDYHWRLPSRUWDQ\VSHFLDOOLEUDU\LQWR\RXU SURMHFW$SSOHKDVDOUHDG\LQFRUSRUDWHG*&'LQWRYDULRXVIUDPHZRUNVLQFOXGLQJ&RUH )RXQGDWLRQDQG&RFRD&RFRD7RXFK$OOPHWKRGVDQGGDWDW\SHVDYDLODEOHLQ*&' VWDUWZLWKDGLVSDWFKBNH\ZRUG)RULQVWDQFHdispatch_asyncDOORZV\RXWRGLVSDWFKD WDVNRQDTXHXHIRUDV\QFKURQRXVH[HFXWLRQZKHUHDVdispatch_afterDOORZV\RXWRUXQ DEORFNRIFRGHDIWHUDJLYHQGHOD\

19


7UDGLWLRQDOO\SURJUDPPHUVKDGWRFUHDWHWKHLURZQWKUHDGVWRSHUIRUPWDVNVLQSDUDOOHO )RU LQVWDQFH DQ L26 GHYHORSHU ZRXOG FUHDWH D WKUHDG VLPLODU WR WKLV WR SHUIRUP DQ RSHUDWLRQWLPHV - (void) doCalculation{ /* Do your calculation here */ } - (void) calculationThreadEntry{ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSUInteger counter = 0; while ([[NSThread currentThread] isCancelled] == NO){ [self doCalculation]; counter++; if (counter >= 1000){ break; } } [pool release]; } - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ /* Start the thread */ [NSThread detachNewThreadSelector:@selector(calculationThreadEntry) toTarget:self withObject:nil]; // Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES; }

7KHSURJUDPPHUKDVWRVWDUWWKHWKUHDGPDQXDOO\DQGWKHQFUHDWHWKHUHTXLUHGVWUXFWXUH IRUWKHWKUHDG HQWU\SRLQWDXWRUHOHDVHSRRODQGWKUHDG¦VPDLQORRS :KHQZHZULWH WKHVDPHFRGHZLWK*&'ZHUHDOO\ZRQ¦WKDYHWRGRPXFK

20 | Chapter 2: Programming Grand Central Dispatch


dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); size_t numberOfIterations = 1000; dispatch_async(queue, ^(void) { dispatch_apply(numberOfIterations, queue, ^(size_t iteration){ /* Perform the operation here */ }); });

,QWKLVFKDSWHU\RXZLOOOHDUQDOOWKHUHLVWRNQRZDERXW*&'DQGKRZWRXVHLWWRZULWH PRGHUQPXOWLWKUHDGHGDSSVIRUL26DQG0DF26;WKDWZLOODFKLHYHEOD]LQJSHUIRUP DQFHRQPXOWLFRUHGHYLFHVVXFKDVWKHL3DG

Different Types of Dispatch Queues $VPHQWLRQHGLQ£6KRUW,QWURGXFWLRQWR*UDQG&HQWUDO'LVSDWFK¤RQSDJHGLVSDWFK TXHXHVDUHSRROVRIWKUHDGVPDQDJHGE\*&':HZLOOEHZRUNLQJZLWKGLVSDWFKTXHXHV DORWVRSOHDVHPDNHVXUHWKDW\RXIXOO\XQGHUVWDQGWKHFRQFHSWEHKLQGWKHP7KHUH DUHWKUHHW\SHVRIGLVSDWFKTXHXHV 0DLQ4XHXH 7KLVTXHXHSHUIRUPVDOOLWVWDVNVRQWKHPDLQWKUHDGZKLFKLVZKHUH&RFRDDQG &RFRD 7RXFK UHTXLUH SURJUDPPHUV WR FDOO DOO 8,UHODWHG PHWKRGV 8VH WKH dispatch_get_main_queueIXQFWLRQWRUHWULHYHWKHKDQGOHWRWKHPDLQTXHXH &RQFXUUHQW4XHXHV 7KHVHDUHTXHXHVWKDW\RXFDQUHWULHYHIURP*&'LQRUGHUWRH[HFXWHDV\QFKURQRXV RUV\QFKURQRXVWDVNV0XOWLSOHFRQFXUUHQWTXHXHVFDQEHH[HFXWLQJPXOWLSOHWDVNV LQSDUDOOHOZLWKRXWEUHDNLQJDVZHDW1RPRUHWKUHDGPDQDJHPHQW\LSSHH8VH WKH dispatch_get_global_queue IXQFWLRQ WR UHWULHYH WKH KDQGOH WR D FRQFXUUHQW TXHXH 6HULDO4XHXHV 7KHVHDUHTXHXHVWKDWQRPDWWHUZKHWKHU\RXVXEPLWV\QFKURQRXVRUDV\QFKUR QRXVWDVNVWRWKHPZLOODOZD\VH[HFXWHWKHLUWDVNVLQDILUVWLQILUVWRXW ),)2

IDVKLRQPHDQLQJWKDWWKH\FDQRQO\H[HFXWHRQHEORFNREMHFWDWDWLPH+RZHYHU WKH\GRQRWUXQRQWKHPDLQWKUHDGDQGWKHUHIRUHDUHSHUIHFWIRUDVHULHVRIWDVNV WKDWKDYHWREHH[HFXWHGLQVWULFWRUGHUZLWKRXWEORFNLQJWKHPDLQWKUHDG8VHWKH dispatch_queue_createIXQFWLRQWRFUHDWHDVHULDOTXHXH2QFH\RXDUHGRQHZLWK WKHTXHXH\RXPXVWUHOHDVHLWXVLQJWKHdispatch_releaseIXQFWLRQ $WDQ\PRPHQWGXULQJWKHOLIHWLPHRI\RXUDSSOLFDWLRQ\RXFDQXVHPXOWLSOHGLVSDWFK TXHXHVDWWKHVDPHWLPH<RXUV\VWHPKDVRQO\RQHPDLQTXHXHEXW\RXFDQFUHDWHDV PDQ\VHULDOGLVSDWFKTXHXHVDV\RXZDQWZLWKLQUHDVRQRIFRXUVHIRUZKDWHYHUIXQF WLRQDOLW\\RXUHTXLUHIRU\RXUDSS<RXFDQDOVRUHWULHYHPXOWLSOHFRQFXUUHQWTXHXHV DQGGLVSDWFK\RXUWDVNVWRWKHP7DVNVFDQEHKDQGHGWRGLVSDWFKTXHXHVLQWZRIRUPV

Different Types of Dispatch Queues | 21


EORFNREMHFWVRU&IXQFWLRQVDVZHZLOOVHHLQ£'LVSDWFKLQJ7DVNVWR*UDQG&HQWUDO 'LVSDWFK¤RQSDJH

Dispatching Tasks to Grand Central Dispatch 7KHUHDUHWZRZD\VWRVXEPLWWDVNVWRGLVSDWFKTXHXHV Â&#x2021; %ORFN2EMHFWV VHH&KDSWHU

Â&#x2021; &IXQFWLRQV %ORFNREMHFWVDUHWKHEHVWZD\RIXWLOL]LQJ*&'DQGLWVHQRUPRXVSRZHU6RPH*&' IXQFWLRQVKDYHEHHQH[WHQGHGWRDOORZSURJUDPPHUVWRXVH&IXQFWLRQVLQVWHDGRIEORFN REMHFWV+RZHYHUWKHWUXWKLVWKDWRQO\DOLPLWHGVHWRI*&'IXQFWLRQVDOORZSURJUDP PHUV WR XVH & IXQFWLRQV VR SOHDVH GR UHDG WKH FKDSWHU DERXW EORFN REMHFWV &KDS WHU EHIRUHSURFHHGLQJZLWKWKLVFKDSWHU & IXQFWLRQV WKDW KDYH WR EH VXSSOLHG WR YDULRXV *&' IXQFWLRQV VKRXOG EH RI W\SH dispatch_function_tZKLFKLVGHILQHGDVIROORZVLQWKH$SSOHOLEUDULHV typedef void (*dispatch_function_t)(void *);

6RLIZHZDQWWRFUHDWHDIXQFWLRQQDPHGIRULQVWDQFHmyGCDFunctionZHZRXOGKDYH WRLPSOHPHQWLWLQWKLVZD\ void myGCDFunction(void * paraContext){ /* Do the work here */ }

7KHparaContextSDUDPHWHUUHIHUVWRWKHFRQWH[WWKDW*&'DOORZVSUR JUDPPHUVWRSDVVWRWKHLU&IXQFWLRQVZKHQWKH\GLVSDWFKWDVNVWRWKHP :HZLOOOHDUQDERXWWKLVVKRUWO\

%ORFNREMHFWVWKDWJHWSDVVHGWR*&'IXQFWLRQVGRQ¦WDOZD\VIROORZWKHVDPHVWUXFWXUH 6RPHPXVWDFFHSWSDUDPHWHUVDQGVRPHVKRXOGQ¦WEXWQRQHRIWKHEORFNREMHFWVVXE PLWWHGWR*&'UHWXUQDYDOXH ,QWKHQH[WWKUHHVHFWLRQV\RXZLOOOHDUQKRZWRVXEPLWWDVNVWR*&'IRUH[HFXWLRQ ZKHWKHUWKH\DUHLQWKHIRUPRIEORFNREMHFWVRU&IXQFWLRQV

Performing UI-Related Tasks 8,UHODWHG WDVNV KDYH WR EH SHUIRUPHG RQ WKH PDLQ WKUHDG VR WKH PDLQ TXHXH LV WKH RQO\ FDQGLGDWH IRU 8, WDVN H[HFXWLRQ LQ *&' :H FDQ XVH WKH dispatch_get_main_queueIXQFWLRQWRJHWWKHKDQGOHWRWKHPDLQGLVSDWFKTXHXH

22 | Chapter 2: Programming Grand Central Dispatch


7KHUHDUHWZRZD\VRIGLVSDWFKLQJWDVNVWRWKHPDLQTXHXH%RWKDUHDV\QFKURQRXV OHWWLQJ\RXUSURJUDPFRQWLQXHHYHQZKHQWKHWDVNLVQRW\HWH[HFXWHG dispatch_asyncIXQFWLRQ

([HFXWHVDEORFNREMHFWRQDGLVSDWFKTXHXH dispatch_async_fIXQFWLRQ ([HFXWHVD&IXQFWLRQRQDGLVSDWFKTXHXH 7KHdispatch_syncPHWKRGFDQQRWEHFDOOHGRQWKHPDLQTXHXHEHFDXVH LWZLOOEORFNWKHWKUHDGLQGHILQLWHO\DQGFDXVH\RXUDSSOLFDWLRQWRGHDG ORFN$OOWDVNVVXEPLWWHGWRWKHPDLQTXHXHWKURXJK*&'PXVWEHVXE PLWWHGDV\QFKURQRXVO\

/HW¦VKDYHDORRNDWXVLQJWKHdispatch_asyncIXQFWLRQ,WDFFHSWVWZRSDUDPHWHUV 'LVSDWFKTXHXHKDQGOH 7KHGLVSDWFKTXHXHRQZKLFKWKHWDVNKDVWREHH[HFXWHG %ORFNREMHFW 7KHEORFNREMHFWWREHVHQWWRWKHGLVSDWFKTXHXHIRUDV\QFKURQRXVH[HFXWLRQ +HUHLVDQH[DPSOH7KLVFRGHZLOOGLVSOD\DQDOHUWLQL26WRWKHXVHUXVLQJWKHPDLQ TXHXH dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_async(mainQueue, ^(void) { [[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"GCD", nil) message:NSLocalizedString(@"GCD is amazing!", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil, nil] autorelease] show]; });

$V\RX¦YHQRWLFHGWKHdispatch_async*&'IXQFWLRQKDVQRSDUDPHWHUV RUUHWXUQYDOXH7KHEORFNREMHFWWKDWLVVXEPLWWHGWRWKLVIXQFWLRQPXVW JDWKHULWVRZQGDWDLQRUGHUWRFRPSOHWHLWVWDVN,QWKHFRGHVQLSSHW WKDWZHMXVWVDZWKHDOHUWYLHZKDVDOOWKHYDOXHVWKDWLWQHHGVWRILQLVK LWVWDVN+RZHYHUWKLVPLJKWQRWDOZD\VEHWKHFDVH,QVXFKLQVWDQFHV \RXPXVWPDNHVXUHWKHEORFNREMHFWVXEPLWWHGWR*&'KDVDFFHVVLQ LWVVFRSHWRDOOWKHYDOXHVWKDWLWUHTXLUHV

5XQQLQJWKLVDSSLQL266LPXODWRUWKHXVHUZLOOJHWUHVXOWVVLPLODUWRWKRVHVKRZQLQ )LJXUH

Performing UI-Related Tasks | 23


)LJXUH$QDOHUWGLVSOD\HGXVLQJDV\QFKURQRXV*&'FDOOV

7KLVPLJKWQRWEHWKDWLPSUHVVLYH,QIDFWLWLVQRWLPSUHVVLYHDWDOOLI\RXWKLQNDERXW LW6RZKDWPDNHVWKHPDLQTXHXHWUXO\LQWHUHVWLQJ"7KHDQVZHULVVLPSOHZKHQ\RX DUHJHWWLQJWKHPD[LPXPSHUIRUPDQFHIURP*&'WRGRVRPHKHDY\FDOFXODWLRQRQ FRQFXUUHQWRUVHULDOWKUHDGV\RXPLJKWZDQWWRGLVSOD\WKHUHVXOWVWR\RXUXVHURUPRYH DFRPSRQHQWRQWKHVFUHHQ)RUWKDW\RXPXVWXVHWKHPDLQTXHXHEHFDXVHLWLV8, UHODWHGZRUN7KHIXQFWLRQVVKRZQLQWKLVVHFWLRQDUHWKHRQO\ZD\WRJHWRXWRIDVHULDO RUDFRQFXUUHQWTXHXHZKLOHVWLOOXWLOL]LQJ*&'WRXSGDWH\RXU8,VR\RXFDQLPDJLQH KRZLPSRUWDQWLWLV ,QVWHDGRIVXEPLWWLQJDEORFNREMHFWIRUH[HFXWLRQRQWKHPDLQTXHXH\RXFDQVXEPLW D&IXQFWLRQREMHFW6XEPLWDOO8,UHODWHG&IXQFWLRQVIRUH[HFXWLRQLQ*&'WRWKH dispatch_async_fIXQFWLRQ:HFDQJHWWKHVDPHUHVXOWVDVZHJRWLQ)LJXUHXVLQJ &IXQFWLRQVLQVWHDGRIEORFNREMHFWVZLWKDIHZDGMXVWPHQWVWRRXUFRGH $VPHQWLRQHGEHIRUHZLWKWKHdispatch_async_fIXQFWLRQZHFDQVXEPLWDSRLQWHUWR DQDSSOLFDWLRQGHILQHGFRQWH[WZKLFKFDQWKHQEHXVHGE\WKH&IXQFWLRQWKDWJHWV FDOOHG6RKHUHLVWKHSODQOHW¦VFUHDWHDVWUXFWXUHWKDWKROGVYDOXHVVXFKDVDQDOHUW YLHZ¦VWLWOHPHVVDJHDQGFDQFHOEXWWRQ¦VWLWOH:KHQRXUDSSVWDUWVZHZLOOSXWDOOWKH YDOXHVLQWKLVVWUXFWXUHDQGSDVVLWWRRXU&IXQFWLRQWRGLVSOD\+HUHLVKRZZHDUH GHILQLQJRXUVWUXFWXUH 24 | Chapter 2: Programming Grand Central Dispatch


typedef struct{ char *title; char *message; char *cancelButtonTitle; } AlertViewData;

1RZOHW¦VJRDQGLPSOHPHQWD&IXQFWLRQWKDWZHZLOOODWHUFDOOZLWK*&'7KLV& IXQFWLRQ VKRXOG H[SHFW D SDUDPHWHU RI W\SH void * ZKLFK ZH ZLOO WKHQ W\SHFDVW WR AlertViewData * ,Q RWKHU ZRUGV ZH H[SHFW WKH FDOOHU RI WKLV IXQFWLRQ WR SDVV XV D UHIHUHQFHWRWKHGDWDIRURXUDOHUWYLHZHQFDSVXODWHGLQVLGHWKHAlertViewDataVWUXFWXUH void displayAlertView(void *paramContext){ AlertViewData *alertData = (AlertViewData *)paramContext; NSString *title = [NSString stringWithUTF8String:alertData->title]; NSString *message = [NSString stringWithUTF8String:alertData->message]; NSString *cancelButtonTitle = [NSString stringWithUTF8String:alertData->cancelButtonTitle]; [[[[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil, nil] autorelease] show]; free(alertData); }

7KHUHDVRQZHDUHfreeLQJWKHFRQWH[WSDVVHGWRXVLQKHUHLQVWHDGRILQ WKHFDOOHULVWKDWWKHFDOOHULVJRLQJWRH[HFXWHWKLV&IXQFWLRQDV\QFKUR QRXVO\ DQG FDQQRW NQRZ ZKHQ RXU & IXQFWLRQ ZLOO ILQLVK H[HFXWLQJ 7KHUHIRUHWKHFDOOHUKDVWRmallocHQRXJKVSDFHIRUWKHAlertViewData FRQWH[WDQGRXUdisplayAlertView&IXQFWLRQKDVWRIUHHWKDWVSDFH

$QGQRZOHW¦VFDOOWKHdisplayAlertViewIXQFWLRQRQWKHPDLQTXHXHDQGSDVVWKHFRQ WH[W WKHVWUXFWXUHWKDWKROGVWKHDOHUWYLHZ¦VGDWD WRLW

Performing UI-Related Tasks | 25


- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ dispatch_queue_t mainQueue = dispatch_get_main_queue(); AlertViewData *context = (AlertViewData *) malloc(sizeof(AlertViewData)); if (context != NULL){ context->title = "GCD"; context->message = "GCD is amazing."; context->cancelButtonTitle = "OK"; dispatch_async_f(mainQueue, (void *)context, displayAlertView); }

}

// Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES;

,I\RXLQYRNHWKH currentThreadFODVVPHWKRGRIWKH NSThreadFODVV\RXZLOOILQGRXW WKDWWKHEORFNREMHFWVRUWKH&IXQFWLRQV\RXGLVSDWFKWRWKHPDLQTXHXHDUHLQGHHG UXQQLQJRQWKHPDLQWKUHDG - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_async(mainQueue, ^(void) { NSLog(@"Current thread = %@", [NSThread currentThread]); NSLog(@"Main thread = %@", [NSThread mainThread]); }); // Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES; }

7KHRXWSXWRIWKLVFRGHZRXOGEHVLPLODUWRWKDWVKRZQKHUH Current thread = <NSThread: 0x4b0e4e0>{name = (null), num = 1} Main thread = <NSThread: 0x4b0e4e0>{name = (null), num = 1}

1RZWKDW\RXNQRZKRZWRSHUIRUP8,UHODWHGWDVNVXVLQJ*&'LWLVWLPHZHPRYHG WRRWKHUVXEMHFWVVXFKDVSHUIRUPLQJWDVNVLQSDUDOOHOXVLQJFRQFXUUHQWTXHXHV VHH £3HUIRUPLQJ 1RQ8,5HODWHG 7DVNV 6\QFKURQRXVO\¤ RQ SDJH  DQG £3HUIRUPLQJ 1RQ8,5HODWHG 7DVNV $V\QFKURQRXVO\¤ RQ SDJH   DQG PL[LQJ RXU FRGH ZLWK 8,UHODWHGFRGHLIQHHGEH

26 | Chapter 2: Programming Grand Central Dispatch


Performing Non-UI-Related Tasks Synchronously 7KHUHDUHWLPHVZKHQ\RXZDQWWRSHUIRUPWDVNVWKDWKDYHQRWKLQJWRGRZLWKWKH8, RULQWHUDFWZLWKWKH8,DVZHOODVGRLQJRWKHUWDVNVWKDWWDNHXSDORWRIWLPH)RULQVWDQFH \RXPLJKWZDQWWRGRZQORDGDQLPDJHDQGGLVSOD\LWWRWKHXVHUDIWHULWLVGRZQORDGHG 7KHGRZQORDGLQJSURFHVVKDVDEVROXWHO\QRWKLQJWRGRZLWKWKH8, )RUDQ\WDVNWKDWGRHVQ¦WLQYROYHWKH8,\RXFDQXVHJOREDOFRQFXUUHQWTXHXHVLQ*&' 7KHVH DOORZ HLWKHU V\QFKURQRXV RU DV\QFKURQRXV H[HFXWLRQ %XW V\QFKURQRXV H[HFXWLRQGRHVQRWPHDQ\RXUSURJUDPZDLWVIRUWKHFRGHWRILQLVKEHIRUHFRQWLQXLQJ ,WVLPSO\PHDQVWKDWWKHFRQFXUUHQWTXHXHZLOOZDLWXQWLO\RXUWDVNKDVILQLVKHGEHIRUH LWFRQWLQXHVWRWKHQH[WEORFNRIFRGHRQWKHTXHXH:KHQ\RXSXWDEORFNREMHFWRQD FRQFXUUHQWTXHXH\RXURZQSURJUDPDOZD\VFRQWLQXHVULJKWDZD\ZLWKRXWZDLWLQJIRU WKHTXHXHWRH[HFXWHWKHFRGH7KLVLVEHFDXVHFRQFXUUHQWTXHXHVDVWKHLUQDPHLPSOLHV UXQWKHLUFRGHRQWKUHDGVRWKHUWKDQWKHPDLQWKUHDG 7KHUHLVRQHH[FHSWLRQWRWKLV ZKHQDWDVNLVVXEPLWWHGWRDFRQFXUUHQWRUDVHULDOTXHXHXVLQJWKH dispatch_sync IXQFWLRQL26ZLOOLISRVVLEOHUXQWKHWDVNRQWKHFXUUHQWWKUHDGZKLFKPLJKWEHWKH PDLQWKUHDGGHSHQGLQJRQZKHUHWKHFRGHSDWKLVDWWKHPRPHQW7KLVLVDQRSWLPL ]DWLRQWKDWKDVEHHQSURJUDPPHGRQ*&'DVZHVKDOOVRRQVHH

,I\RXVXEPLWDWDVNWRDFRQFXUUHQWTXHXHV\QFKURQRXVO\DQGDWWKHVDPHWLPHVXEPLW DQRWKHUV\QFKURQRXVWDVNWRDQRWKHUFRQFXUUHQWTXHXHWKHVHWZRV\QFKURQRXVWDVNV ZLOOUXQDV\QFKURQRXVO\LQUHODWLRQWRHDFKRWKHUEHFDXVHWKH\DUHUXQQLQJWZRGLIIHUHQW FRQFXUUHQWTXHXHV,W¦VLPSRUWDQWWRXQGHUVWDQGWKLVEHFDXVHVRPHWLPHVDVZH¦OOVHH \RXZDQWWRPDNHVXUHWDVN$ILQLVKHVEHIRUHWDVN%VWDUWV7RHQVXUHWKDWVXEPLWWKHP V\QFKURQRXVO\WRWKHVDPHTXHXH <RXFDQSHUIRUPV\QFKURQRXVWDVNVRQDGLVSDWFKTXHXHXVLQJWKHdispatch_syncIXQF WLRQ$OO\RXKDYHWRGRLVWRSURYLGHLWZLWKWKHKDQGOHRIWKHTXHXHWKDWKDVWRUXQWKH WDVNDQGDEORFNRIFRGHWRH[HFXWHRQWKDWTXHXH /HW¦VORRNDWDQH[DPSOH,WSULQWVWKHLQWHJHUVWRWZLFHRQHFRPSOHWHVHTXHQFH DIWHUWKHRWKHUZLWKRXWEORFNLQJWKHPDLQWKUHDG:HFDQFUHDWHDEORFNREMHFWWKDW GRHVWKHFRXQWLQJIRUXVDQGV\QFKURQRXVO\FDOOWKHVDPHEORFNREMHFWWZLFH void (^printFrom1To1000)(void) = ^{ NSUInteger counter = 0; for (counter = 1; counter <= 1000; counter++){ NSLog(@"Counter = %lu - Thread = %@", (unsigned long)counter, [NSThread currentThread]); } };

Performing Non-UI-Related Tasks Synchronously | 27


1RZOHW¦VJRDQGLQYRNHWKLVEORFNREMHFWXVLQJ*&' dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(concurrentQueue, printFrom1To1000); dispatch_sync(concurrentQueue, printFrom1To1000);

,I\RXUXQWKLVFRGH\RXPLJKWQRWLFHWKHFRXQWLQJWDNLQJSODFHRQWKHPDLQWKUHDG HYHQWKRXJK\RX¦YHDVNHGDFRQFXUUHQWTXHXHWRH[HFXWHWKHWDVN,WWXUQVRXWWKLVLV DQRSWLPL]DWLRQE\*&'7KHdispatch_syncIXQFWLRQZLOOXVHWKHFXUUHQWWKUHDG¢WKH WKUHDG\RX¦UHXVLQJZKHQ\RXGLVSDWFKWKHWDVN¢ZKHQHYHUSRVVLEOHDVDSDUWRIDQ RSWLPL]DWLRQWKDWKDVEHHQSURJUDPPHGLQWR*&'+HUHLVZKDW$SSOHVD\VDERXWLW $VDQRSWLPL]DWLRQWKLVIXQFWLRQLQYRNHVWKHEORFNRQWKHFXUUHQWWKUHDGZKHQSRVVLEOH ¢*UDQG&HQWUDO'LVSDWFK *&' 5HIHUHQFH

7RH[HFXWHD&IXQFWLRQLQVWHDGRIDEORFNREMHFWV\QFKURQRXVO\RQDGLVSDWFKTXHXH XVHWKHdispatch_sync_fIXQFWLRQ/HW¦VVLPSO\WUDQVODWHWKHFRGHZH¦YHZULWWHQIRUWKH printFrom1To1000EORFNREMHFWWRLWVHTXLYDOHQW&IXQFWLRQOLNHVR void printFrom1To1000(void *paramContext){ NSUInteger counter = 0; for (counter = 1; counter <= 1000; counter++){ NSLog(@"Counter = %lu - Thread = %@", (unsigned long)counter, [NSThread currentThread]); } }

$QGQRZZHFDQXVHWKH dispatch_sync_fIXQFWLRQWRH[HFXWHWKH printFrom1To1000 IXQFWLRQRQDFRQFXUUHQWTXHXHDVGHPRQVWUDWHGKHUH dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync_f(concurrentQueue, NULL, printFrom1To1000); dispatch_sync_f(concurrentQueue, NULL, printFrom1To1000);

7KHILUVWSDUDPHWHURIWKHdispatch_get_global_queueIXQFWLRQVSHFLILHVWKHSULRULW\RI WKHFRQFXUUHQWTXHXHWKDW*&'KDVWRUHWULHYHIRUWKHSURJUDPPHU7KHKLJKHUWKH SULRULW\WKHPRUH&38WLPHVOLFHVZLOOEHSURYLGHGWRWKHFRGHJHWWLQJH[HFXWHGRQWKDW

28 | Chapter 2: Programming Grand Central Dispatch


TXHXH <RX FDQ XVH DQ\ RI WKHVH YDOXHV IRU WKH ILUVW SDUDPHWHU WR WKH dispatch_get_global_queueIXQFWLRQ DISPATCH_QUEUE_PRIORITY_LOW

)HZHUWLPHVOLFHVZLOOEHDSSOLHGWR\RXUWDVNWKDQQRUPDOWDVNV DISPATCH_QUEUE_PRIORITY_DEFAULT

7KHGHIDXOWV\VWHPSULRULW\IRUFRGHH[HFXWLRQZLOOEHDSSOLHGWR\RXUWDVN DISPATCH_QUEUE_PRIORITY_HIGH

0RUHWLPHVOLFHVZLOOEHDSSOLHGWR\RXUWDVNWKDQQRUPDOWDVNV 7KHVHFRQGSDUDPHWHURIWKHdispatch_get_global_queueIXQFWLRQLVUH VHUYHGDQG\RXVKRXOGDOZD\VSDVVWKHYDOXHWRLW

,QWKLVVHFWLRQ\RXVDZKRZ\RXFDQGLVSDWFKWDVNVWRFRQFXUUHQWTXHXHVIRUV\QFKUR QRXV H[HFXWLRQ 7KH QH[W VHFWLRQ VKRZV DV\QFKURQRXV H[HFXWLRQ RQ FRQFXUUHQW TXHXHVZKLOH£&RQVWUXFWLQJ<RXU2ZQ'LVSDWFK4XHXHV¤RQSDJHZLOOVKRZKRZ WRH[HFXWHWDVNVV\QFKURQRXVO\DQGDV\QFKURQRXVO\RQVHULDOTXHXHVWKDW\RXFUHDWH IRU\RXUDSSOLFDWLRQV

Performing Non-UI-Related Tasks Asynchronously 7KLVLVZKHUH*&'FDQVKRZLWVWUXHSRZHUH[HFXWLQJEORFNVRIFRGHDV\QFKURQRXVO\ RQWKHPDLQVHULDORUFRQFXUUHQWTXHXHV,SURPLVHWKDWE\WKHHQGRIWKLVVHFWLRQ \RXZLOOEHFRPSOHWHO\FRQYLQFHG*&'LVWKHIXWXUHRIPXOWLWKUHDGDSSOLFDWLRQVFRP SOHWHO\UHSODFLQJWKUHDGVLQPRGHUQDSSV ,QRUGHUWRH[HFXWHDV\QFKURQRXVWDVNVRQDGLVSDWFKTXHXH\RXPXVWXVHRQHRIWKHVH IXQFWLRQV dispatch_async

6XEPLWV D EORFN REMHFW WR D GLVSDWFK TXHXH ERWK VSHFLILHG E\ SDUDPHWHUV  IRU DV\QFKURQRXVH[HFXWLRQ dispatch_async_f

6XEPLWVD&IXQFWLRQWRDGLVSDWFKTXHXHDORQJZLWKDFRQWH[WUHIHUHQFH DOOWKUHH VSHFLILHGE\SDUDPHWHUV IRUDV\QFKURQRXVH[HFXWLRQ /HW¦VKDYHDORRNDWDUHDOH[DPSOH:H¦OOZULWHDQL26DSSWKDWLVDEOHWRGRZQORDGDQ LPDJH IURP D 85/ RQ WKH ,QWHUQHW $IWHU WKH GRZQORDG LV ILQLVKHG WKH DSS VKRXOG GLVSOD\WKHLPDJHWRWKHXVHU+HUHLVWKHSODQDQGKRZZHZLOOXVHZKDWZH¦YHOHDUQHG VRIDUDERXW*&'LQRUGHUWRDFFRPSOLVKLW

Performing Non-UI-Related Tasks Asynchronously | 29


 :HDUHJRLQJWRODXQFKDEORFNREMHFWDV\QFKURQRXVO\RQDFRQFXUUHQWTXHXH  2QFHLQWKLVEORFNZHZLOOODXQFKDQRWKHUEORFNREMHFWV\QFKURQRXVO\XVLQJWKH dispatch_syncIXQFWLRQWRGRZQORDGWKHLPDJHIURPD85/6\QFKURQRXVO\GRZQ ORDGLQJD85/IURPDQDV\QFKURQRXVFRGHEORFNKROGVXSMXVWWKHTXHXHUXQQLQJ WKHV\QFKURQRXVIXQFWLRQQRWWKHPDLQWKUHDG7KHZKROHRSHUDWLRQVWLOOLVDV\Q FKURQRXVZKHQZHORRNDWLWIURPWKHPDLQWKUHDG¦VSHUVSHFWLYH$OOZHFDUHDERXW LVWKDWZHDUHQRWEORFNLQJWKHPDLQWKUHDGZKLOHGRZQORDGLQJRXULPDJH  5LJKWDIWHUWKHLPDJHLVGRZQORDGHGZHZLOOV\QFKURQRXVO\H[HFXWHDEORFNREMHFW RQWKHPDLQTXHXH VHH£3HUIRUPLQJ8,5HODWHG7DVNV¤RQSDJH LQRUGHUWR GLVSOD\WKHLPDJHWRWKHXVHURQWKH8, 7KHVNHOHWRQIRURXUSODQLVDVVLPSOHDVWKLV dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(concurrentQueue, ^{ __block UIImage *image = nil; dispatch_sync(concurrentQueue, ^{ /* Download the image here */ }); dispatch_sync(dispatch_get_main_queue(), ^{ /* Show the image to the user here on the main queue*/ }); });

7KHVHFRQGdispatch_syncFDOOZKLFKGLVSOD\VWKHLPDJHZLOOEHH[HFXWHGRQWKHTXHXH DIWHUWKHILUVWV\QFKURQRXVFDOOZKLFKGRZQORDGVRXULPDJH7KDW¦VH[DFWO\ZKDWZH ZDQWEHFDXVHZHKDYHWRZDLWIRUWKHLPDJHWREHIXOO\GRZQORDGHGEHIRUHZHFDQ GLVSOD\LWWRWKHXVHU6RDIWHUWKHLPDJHLVGRZQORDGHGZHH[HFXWHWKHVHFRQGEORFN REMHFWEXWWKLVWLPHRQWKHPDLQTXHXH /HW¦VGRZQORDGWKHLPDJHDQGGLVSOD\LWWRWKHXVHUQRZ:HZLOOGRWKLVLQWKH view DidAppear:LQVWDQFHPHWKRGRIDYLHZFRQWUROOHUGLVSOD\HGLQDQL3KRQHDSS - (void) viewDidAppear:(BOOL)paramAnimated{ dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(concurrentQueue, ^{ __block UIImage *image = nil; dispatch_sync(concurrentQueue, ^{ /* Download the image here */ /* iPad's image from Apple's website. Wrap it into two

30 | Chapter 2: Programming Grand Central Dispatch


lines as the URL is too long to fit into one line */ NSString *urlAsString = @"http://images.apple.com/mobileme/features"\ "/images/ipad_findyouripad_20100518.jpg"; NSURL *url = [NSURL URLWithString:urlAsString]; NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url]; NSError *downloadError = nil; NSData *imageData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&downloadError]; if (downloadError == nil && imageData != nil){ image = [UIImage imageWithData:imageData]; /* We have the image. We can use it now */ } else if (downloadError != nil){ NSLog(@"Error happened = %@", downloadError); } else { NSLog(@"No data could get downloaded from the URL."); } }); dispatch_sync(dispatch_get_main_queue(), ^{ /* Show the image to the user here on the main queue*/ if (image != nil){ /* Create the image view here */ UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; /* Set the image */ [imageView setImage:image]; /* Make sure the image is not scaled incorrectly */ [imageView setContentMode:UIViewContentModeScaleAspectFit]; /* Add the image to this view controller's view */ [self.view addSubview:imageView]; /* Release the image view */ [imageView release]; } else { NSLog(@"Image isn't downloaded. Nothing to display."); } });

Performing Non-UI-Related Tasks Asynchronously | 31


}); }

$V\RXFDQVHHLQ)LJXUHZHKDYHVXFFHVVIXOO\GRZQORDGHGRXULPDJHDQGDOVR FUHDWHGDQLPDJHYLHZWRGLVSOD\WKHLPDJHWRWKHXVHURQWKH8,

)LJXUH'RZQORDGLQJDQGGLVSOD\LQJLPDJHVWRXVHUVXVLQJ*&'

/HW¦VPRYHRQWRDQRWKHUH[DPSOH/HW¦VVD\WKDWZHKDYHDQDUUD\RIUDQGRP QXPEHUVWKDWKDYHEHHQVWRUHGLQDILOHRQGLVNDQGZHZDQWWRORDGWKLVDUUD\LQWR PHPRU\VRUWWKHQXPEHUVLQDQDVFHQGLQJIDVKLRQ ZLWKWKHVPDOOHVWQXPEHUDSSHDULQJ ILUVWLQWKHOLVW DQGWKHQGLVSOD\WKHOLVWWRWKHXVHU7KHFRQWUROXVHGIRUWKHGLVSOD\ GHSHQGV RQ ZKHWKHU \RX DUH FRGLQJ WKLV IRU L26 LGHDOO\ \RX¦G XVH DQ LQVWDQFH RI UITableView RU0DF26; NSTableViewZRXOGEHDJRRGFDQGLGDWH 6LQFHZHGRQ¦W KDYHDQDUUD\ZK\GRQ¦WZHFUHDWHWKHDUUD\ILUVWWKHQORDGLWDQGILQDOO\GLVSOD\LW" +HUHDUHWZRPHWKRGVWKDWZLOOKHOSXVILQGWKHORFDWLRQZKHUHZHZDQWWRVDYHWKH DUUD\RIUDQGRPQXPEHUVRQGLVNRQWKHGHYLFH - (NSString *) fileLocation{ /* Get the document folder(s) */ NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,

32 | Chapter 2: Programming Grand Central Dispatch


NSUserDomainMask, YES); /* Did we find anything? */ if ([folders count] == 0){ return nil; } /* Get the first folder */ NSString *documentsFolder = [folders objectAtIndex:0]; /* Append the file name to the end of the documents path */ return [documentsFolder stringByAppendingPathComponent:@"list.txt"]; } - (BOOL) hasFileAlreadyBeenCreated{ BOOL result = NO; NSFileManager *fileManager = [[NSFileManager alloc] init]; if ([fileManager fileExistsAtPath:[self fileLocation]] == YES){ result = YES; } [fileManager release]; return result; }

1RZWKHLPSRUWDQWSDUWZHZDQWWRVDYHDQDUUD\RIUDQGRPQXPEHUVWRGLVN LIDQGRQO\LIZHKDYHQRWFUHDWHGWKLVDUUD\EHIRUHRQGLVN,IZHKDYHZHZLOOORDGWKH DUUD\IURPGLVNLPPHGLDWHO\,IZHKDYHQRWFUHDWHGWKLVDUUD\EHIRUHRQGLVNZHZLOO ILUVWFUHDWHLWDQGWKHQPRYHRQWRORDGLQJLWIURPGLVN$WWKHHQGLIWKHDUUD\ZDV VXFFHVVIXOO\UHDGIURPGLVNZHZLOOVRUWWKHDUUD\LQDQDVFHQGLQJIDVKLRQDQGILQDOO\ GLVSOD\WKHUHVXOWVWRWKHXVHURQWKH8,,ZLOOOHDYHGLVSOD\LQJWKHUHVXOWVWRWKHXVHU XSWR\RX dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); /* If we have not already saved an array of 10,000 random numbers to the disk before, generate these numbers now and then save them to the disk in an array */ dispatch_async(concurrentQueue, ^{ NSUInteger numberOfValuesRequired = 10000; if ([self hasFileAlreadyBeenCreated] == NO){ dispatch_sync(concurrentQueue, ^{ NSMutableArray *arrayOfRandomNumbers = [[NSMutableArray alloc] initWithCapacity:numberOfValuesRequired];

Performing Non-UI-Related Tasks Asynchronously | 33


NSUInteger counter = 0; for (counter = 0; counter < numberOfValuesRequired; counter++){ unsigned int randomNumber = arc4random() % ((unsigned int)RAND_MAX + 1); [arrayOfRandomNumbers addObject: [NSNumber numberWithUnsignedInt:randomNumber]]; } /* Now let's write the array to disk */ [arrayOfRandomNumbers writeToFile:[self fileLocation] atomically:YES]; [arrayOfRandomNumbers release]; }); } __block NSMutableArray *randomNumbers = nil; /* Read the numbers from disk and sort them in an ascending fashion */ dispatch_sync(concurrentQueue, ^{ /* If the file has now been created, we have to read it */ if ([self hasFileAlreadyBeenCreated] == YES){ randomNumbers = [[NSMutableArray alloc] initWithContentsOfFile:[self fileLocation]]; /* Now sort the numbers */ [randomNumbers sortUsingComparator: ^NSComparisonResult(id obj1, id obj2) { NSNumber *number1 = (NSNumber *)obj1; NSNumber *number2 = (NSNumber *)obj2; return [number1 compare:number2]; }]; } }); dispatch_async(dispatch_get_main_queue(), ^{ if ([randomNumbers count] > 0){ /* Refresh the UI here using the numbers in the randomNumbers array */ } [randomNumbers release]; }); });

34 | Chapter 2: Programming Grand Central Dispatch


7KHUHLVDORWPRUHWR*&'WKDQV\QFKURQRXVDQGDV\QFKURQRXVEORFNRUIXQFWLRQ H[HFXWLRQ,Q£5XQQLQJD*URXSRI7DVNV7RJHWKHU¤RQSDJH\RXZLOOOHDUQKRZ WRJURXSEORFNREMHFWVWRJHWKHUDQGSUHSDUHWKHPIRUH[HFXWLRQRQDGLVSDWFKTXHXH ,DOVRVXJJHVWWKDW\RXKDYHDORRNDW£3HUIRUPLQJ7DVNV$IWHUD'HOD\¤RQSDJH DQG£3HUIRUPLQJD7DVNDW0RVW2QFH¤RQSDJHWROHDUQDERXWRWKHUIXQFWLRQDOLWLHV WKDW*&'LVFDSDEOHRISURYLGLQJWRSURJUDPPHUV

Performing Tasks After a Delay :LWK&RUH)RXQGDWLRQ\RXFDQLQYRNHDVHOHFWRULQDQREMHFWDIWHUDJLYHQSHULRGRI WLPHXVLQJWKHperformSelector:withObject:afterDelay:PHWKRGRIWKHNSObjectFODVV +HUHLVDQH[DPSOH - (void) printString:(NSString *)paramString{ NSLog(@"%@", paramString); } - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ @selector(performSelector:withObject:afterDelay:) [self performSelector:@selector(printString:) withObject:@"Grand Central Dispatch" afterDelay:3.0];

}

// Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES;

,Q WKLV H[DPSOH ZH DUH DVNLQJ WKH UXQWLPH WR FDOO WKH printString: PHWKRG DIWHU VHFRQGVRIGHOD\:HFDQGRWKHVDPHWKLQJLQ*&'XVLQJWKH dispatch_afterDQG dispatch_after_fIXQFWLRQVHDFKRIZKLFKLVGHVFULEHGKHUH dispatch_after

'LVSDWFKHVDEORFNREMHFWWRDGLVSDWFKTXHXHDIWHUDJLYHQSHULRGRIWLPHVSHFLILHG LQQDQRVHFRQGV7KHVHDUHWKHSDUDPHWHUVWKDWWKLVIXQFWLRQUHTXLUHV 'HOD\LQQDQRVHFRQGV 7KH QXPEHU RI QDQRVHFRQGV *&' KDV WR ZDLW RQ D JLYHQ GLVSDWFK TXHXH VSHFLILHGE\WKHVHFRQGSDUDPHWHU EHIRUHLWH[HFXWHVWKHJLYHQEORFNREMHFW VSHFLILHGE\WKHWKLUGSDUDPHWHU  'LVSDWFKTXHXH 7KHGLVSDWFKTXHXHRQZKLFKWKHEORFNREMHFW VSHFLILHGE\WKHWKLUGSDUDP HWHU KDVWREHH[HFXWHGDIWHUWKHJLYHQGHOD\ VSHFLILHGE\WKHILUVWSDUDPHWHU 

Performing Tasks After a Delay | 35


%ORFNREMHFW 7KHEORFNREMHFWWREHLQYRNHGDIWHUWKHVSHFLILHGQXPEHURIQDQRVHFRQGVRQ WKHJLYHQGLVSDWFKTXHXH7KLVEORFNREMHFWVKRXOGKDYHQRUHWXUQYDOXHDQG VKRXOGDFFHSWQRSDUDPHWHUV VHH£&RQVWUXFWLQJ%ORFN2EMHFWVDQG7KHLU6\Q WD[¤RQSDJH  dispatch_after_f

'LVSDWFKHVD&IXQFWLRQWR*&'IRUH[HFXWLRQDIWHUDJLYHQSHULRGRIWLPHVSHFLILHG LQQDQRVHFRQGV7KLVIXQFWLRQDFFHSWVIRXUSDUDPHWHUV 'HOD\LQQDQRVHFRQGV 7KH QXPEHU RI QDQRVHFRQGV *&' KDV WR ZDLW RQ D JLYHQ GLVSDWFK TXHXH VSHFLILHG E\ WKH VHFRQG SDUDPHWHU  EHIRUH LW H[HFXWHV WKH JLYHQ IXQFWLRQ VSHFLILHGE\WKHIRXUWKSDUDPHWHU  'LVSDWFKTXHXH 7KHGLVSDWFKTXHXHRQZKLFKWKH&IXQFWLRQ VSHFLILHGE\WKHIRXUWKSDUDP HWHU KDVWREHH[HFXWHGDIWHUWKHJLYHQGHOD\ VSHFLILHGE\WKHILUVWSDUDPHWHU  &RQWH[W 7KHPHPRU\DGGUHVVRIDYDOXHLQWKHKHDSWREHSDVVHGWRWKH&IXQFWLRQ IRU DQH[DPSOHVHH£3HUIRUPLQJ8,5HODWHG7DVNV¤RQSDJH  &IXQFWLRQ 7KHDGGUHVVRIWKH&IXQFWLRQWKDWKDVWREHH[HFXWHGDIWHUDFHUWDLQSHULRGRI WLPH VSHFLILHGE\WKHILUVWSDUDPHWHU RQWKHJLYHQGLVSDWFKTXHXH VSHFLILHG E\WKHVHFRQGSDUDPHWHU  $OWKRXJKWKHGHOD\VDUHLQQDQRVHFRQGVLWLVXSWRL26WRGHFLGHWKH JUDQXODULW\RIGLVSDWFKGHOD\DQGWKLVGHOD\PLJKWQRWEHDVSUHFLVHDV ZKDW\RXKRSHZKHQ\RXVSHFLI\DYDOXHLQQDQRVHFRQGV

/HW¦VKDYHDORRNDWDQH[DPSOHIRUdispatch_afterILUVW double delayInSeconds = 2.0; dispatch_time_t delayInNanoSeconds = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_after(delayInNanoSeconds, concurrentQueue, ^(void){ /* Perform your operations here */ });

$V \RX FDQ VHH WKH QDQRVHFRQGV GHOD\ SDUDPHWHU IRU ERWK WKH dispatch_after DQG dispatch_after_f IXQFWLRQV KDV WR EH RI W\SH dispatch_time_t ZKLFK LV DQ DEVWUDFW UHSUHVHQWDWLRQRIDEVROXWHWLPH7RJHWWKHYDOXHIRUWKLVSDUDPHWHU\RXFDQXVHWKH

36 | Chapter 2: Programming Grand Central Dispatch


dispatch_timeIXQFWLRQDVGHPRQVWUDWHGLQWKLVVDPSOHFRGH+HUHDUHWKHSDUDPHWHUV WKDW\RXFDQSDVVWRWKHdispatch_timeIXQFWLRQ

%DVHWLPH ,IWKLVYDOXHZDVGHQRWHGZLWK%DQGWKHGHOWDSDUDPHWHUZDVGHQRWHGZLWK'WKH UHVXOWLQJWLPHIURPWKLVIXQFWLRQZRXOGEHHTXDOWR%'<RXFDQVHWWKLVSDUDP HWHU¦VYDOXHWRDISPATCH_TIME_NOWWRGHQRWHQRZDVWKHEDVHWLPHDQGWKHQVSHFLI\ WKHGHOWDIURPQRZXVLQJWKHGHOWDSDUDPHWHU 'HOWDWRDGGWREDVHWLPH 7KLVSDUDPHWHULVWKHQDQRVHFRQGVWKDWZLOOJHWDGGHGWRWKHEDVHWLPHSDUDPHWHU WRFUHDWHWKHUHVXOWRIWKLVIXQFWLRQ )RUH[DPSOHWRGHQRWHDWLPHVHFRQGVIURPQRZ\RXFRXOGZULWH\RXUFRGHOLNHVR dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 3.0f * NSEC_PER_SEC);

2UWRGHQRWHKDOIDVHFRQGIURPQRZ dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (1.0 / 2.0f) * NSEC_PER_SEC);

1RZOHW¦VKDYHDORRNDWKRZZHFDQXVHWKHdispatch_after_fIXQFWLRQ void processSomething(void *paramContext){ /* Do your processing here */ NSLog(@"Processing..."); } - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ double delayInSeconds = 2.0; dispatch_time_t delayInNanoSeconds = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_after_f(delayInNanoSeconds, concurrentQueue, NULL, processSomething);

}

// Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES;

Performing Tasks After a Delay | 37


Performing a Task at Most Once $OORFDWLQJDQGLQLWLDOL]LQJDVLQJOHWRQLVRQHRIWKHWDVNVWKDWKDVWRKDSSHQH[DFWO\RQFH GXULQJWKHOLIHWLPHRIDQDSS,DPVXUH\RXNQRZRIRWKHUVFHQDULRVZKHUH\RXKDGWR PDNH VXUH D SLHFH RI FRGH ZDV H[HFXWHG RQO\ RQFH GXULQJ WKH OLIHWLPH RI \RXU DSSOLFDWLRQ *&'OHWV\RXVSHFLI\DQLGHQWLILHUIRUDSLHFHRIFRGHZKHQ\RXDWWHPSWWRH[HFXWHLW ,I*&'GHWHFWVWKDWWKLVLGHQWLILHUKDVEHHQSDVVHGWRWKHIUDPHZRUNEHIRUHLWZRQ¦W H[HFXWH WKDW EORFN RI FRGH DJDLQ 7KH IXQFWLRQ WKDW DOORZV \RX WR GR WKLV LV dispatch_onceZKLFKDFFHSWVWZRSDUDPHWHUV 7RNHQ $WRNHQRIW\SHdispatch_once_tWKDWKROGVWKHWRNHQJHQHUDWHGE\*&'ZKHQWKH EORFNRIFRGHLVH[HFXWHGIRUWKHILUVWWLPH,I\RXZDQWDSLHFHRIFRGHWREHH[HFXWHG DWPRVWRQFH\RXPXVWVSHFLI\WKHVDPHWRNHQWRWKLVPHWKRGZKHQHYHULWLVLQ YRNHGLQWKHDSS:HZLOOVHHDQH[DPSOHRIWKLVVRRQ %ORFNREMHFW 7KHEORFNREMHFWWRJHWH[HFXWHGDWPRVWRQFH7KLVEORFNREMHFWUHWXUQVQRYDOXHV DQGDFFHSWVQRSDUDPHWHUV dispatch_onceDOZD\VH[HFXWHVLWVWDVNRQWKHFXUUHQWTXHXHEHLQJXVHG

E\WKHFRGHWKDWLVVXHVWKHFDOOEHLWDVHULDOTXHXHDFRQFXUUHQWTXHXH RUWKHPDLQTXHXH

+HUHLVDQH[DPSOH static dispatch_once_t onceToken; void (^executedOnlyOnce)(void) = ^{ static NSUInteger numberOfEntries = 0; numberOfEntries++; NSLog(@"Executed %lu time(s)", (unsigned long)numberOfEntries); }; - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_once(&onceToken, ^{ dispatch_async(concurrentQueue, executedOnlyOnce); });

38 | Chapter 2: Programming Grand Central Dispatch


dispatch_once(&onceToken, ^{ dispatch_async(concurrentQueue, executedOnlyOnce); }); // Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES; }

$V\RXFDQVHHDOWKRXJKZHDUHDWWHPSWLQJWRLQYRNHWKHexecutedOnlyOnceEORFNREMHFW WZLFHXVLQJWKH dispatch_onceIXQFWLRQLQUHDOLW\*&'LVRQO\H[HFXWLQJWKLVEORFN REMHFWRQFHVLQFHWKHLGHQWLILHUSDVVHGWRWKHdispatch_onceIXQFWLRQLVWKHVDPHERWK WLPHV $SSOHLQLWV&RFRD)XQGDPHQWDOV*XLGHVKRZVSURJUDPPHUVKRZWRFUHDWHDVLQJOH WRQ+RZHYHUZHFDQFKDQJHWKLVPRGHOWRPDNHXVHRI*&'DQGWKH dispatch_once IXQFWLRQLQRUGHUWRLQLWLDOL]HDVKDUHGLQVWDQFHRIDQREMHFWOLNHVR #import "MySingleton.h" @implementation MySingleton static MySingleton *sharedMySingleton = NULL; + (MySingleton *) sharedInstance{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (sharedMySingleton == NULL){ sharedMySingleton = [[super allocWithZone:NULL] init]; } }); return sharedMySingleton; } + (id) allocWithZone:(NSZone *)paramZone{ return [[self sharedInstance] retain]; } - (id) copyWithZone:(NSZone *)paramZone{ return self; } - (void) release{ /* Do nothing */ } - (id) autorelease{ return self; } - (NSUInteger) retainCount{

Performing a Task at Most Once | 39


}

return NSUIntegerMax; - (id) retain{ return self; } @end

Running a Group of Tasks Together *&'OHWVXVFUHDWHJURXSVZKLFKDOORZ\RXWRSODFH\RXUWDVNVLQRQHSODFHUXQDOORI WKHPDQGJHWDQRWLILFDWLRQDWWKHHQGIURP*&'7KLVKDVPDQ\YDOXDEOHDSSOLFDWLRQV )RULQVWDQFHVXSSRVH\RXKDYHD8,EDVHGDSSDQGZDQWWRUHORDGWKHFRPSRQHQWVRQ \RXU8,<RXKDYHDWDEOHYLHZDVFUROOYLHZDQGDQLPDJHYLHZ<RXZDQWWRUHORDG WKHFRQWHQWVRIWKHVHFRPSRQHQWVXVLQJWKHVHPHWKRGV - (void) reloadTableView{ /* Reload the table view here */ NSLog(@"%s", __FUNCTION__); } - (void) reloadScrollView{ /* Do the work here */ NSLog(@"%s", __FUNCTION__); } - (void) reloadImageView{ /* Reload the image view here */ NSLog(@"%s", __FUNCTION__); }

$WWKHPRPHQWWKHVHPHWKRGVDUHHPSW\EXWODWHU\RXFDQSXWWKHUHOHYDQW8,FRGH LQWKHP1RZZHZDQWWRFDOOWKHVHWKUHHPHWKRGVRQHDIWHUWKHRWKHUDQGZHZDQW WRNQRZZKHQ*&'KDVILQLVKHGFDOOLQJWKHVHPHWKRGVVRWKDWZHFDQGLVSOD\DPHVVDJH WRWKHXVHU)RUWKLVZHVKRXOGEHXVLQJDJURXS<RXVKRXOGNQRZDERXWIRXUIXQFWLRQV ZKHQZRUNLQJZLWKJURXSVLQ*&' dispatch_group_create

&UHDWHVDJURXSKDQGOH2QFH\RXDUHGRQHZLWKWKLVJURXSKDQGOH\RXVKRXOG GLVSRVHRILWXVLQJWKHdispatch_releaseIXQFWLRQ dispatch_group_async

6XEPLWVDEORFNRIFRGHIRUH[HFXWLRQRQDJURXS<RXPXVWVSHFLI\WKHGLVSDWFK TXHXHRQZKLFKWKHEORFNRIFRGHKDVWREHH[HFXWHGDVZHOODVWKHJURXSWRZKLFK WKLVEORFNRIFRGHEHORQJV dispatch_group_notify

$OORZV\RXWRVXEPLWDEORFNREMHFWWKDWVKRXOGEHH[HFXWHGRQFHDOOWDVNVDGGHG WRWKHJURXSIRUH[HFXWLRQKDYHILQLVKHGWKHLUZRUN7KLVIXQFWLRQDOVRDOORZV\RX WRVSHFLI\WKHGLVSDWFKTXHXHRQZKLFKWKDWEORFNREMHFWKDVWREHH[HFXWHG 40 | Chapter 2: Programming Grand Central Dispatch


dispatch_release

8VH WKLV IXQFWLRQ WR GLVSRVH RI DQ\ GLVSDWFK JURXSV WKDW \RX FUHDWH XVLQJ WKH dispatch_group_createIXQFWLRQ /HW¦VKDYHDORRNDWDQH[DPSOH$VH[SODLQHGLQRXUH[DPSOHZHZDQWWRLQYRNHWKH reloadTableViewreloadScrollViewDQGreloadImageViewPHWKRGVRQHDIWHUWKHRWKHU DQGWKHQGLVSOD\DPHVVDJHWRWKHXVHURQFHZHDUHGRQH:HFDQXWLOL]H*&'¦VSRZHUIXO JURXSLQJIDFLOLWLHVLQRUGHUWRDFFRPSOLVKWKLV dispatch_group_t taskGroup = dispatch_queue_t mainQueue =

dispatch_group_create(); dispatch_get_main_queue();

/* Reload the table view on the main queue */ dispatch_group_async(taskGroup, mainQueue, ^{ [self reloadTableView]; }); /* Reload the scroll view on the main queue */ dispatch_group_async(taskGroup, mainQueue, ^{ [self reloadScrollView]; }); /* Reload the image view on the main queue */ dispatch_group_async(taskGroup, mainQueue, ^{ [self reloadImageView]; }); /* At the end when we are done, dispatch the following block */ dispatch_group_notify(taskGroup, mainQueue, ^{ /* Do some processing here */ [[[[UIAlertView alloc] initWithTitle:@"Finished" message:@"All tasks are finished" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] autorelease] show]; }); /* We are done with the group */ dispatch_release(taskGroup);

,QDGGLWLRQWRdispatch_group_async\RXFDQDOVRGLVSDWFKDV\QFKURQRXV&IXQFWLRQV WRDGLVSDWFKJURXSXVLQJWKHdispatch_group_async_fIXQFWLRQ GCDAppDelegateLVVLPSO\WKHQDPHRIWKHFODVVIURPZKLFKWKLVH[DPSOH

LVWDNHQ:HKDYHWRXVHWKLVFODVVQDPHLQRUGHUWRW\SHFDVWDFRQWH[W REMHFWVRWKDWWKHFRPSLOHUZLOOXQGHUVWDQGRXUFRPPDQGV

/LNHVR

Running a Group of Tasks Together | 41


- (void) reloadTableView{ /* Reload the table view here */ NSLog(@"%s", __FUNCTION__); } - (void) reloadScrollView{ /* Do the work here */ NSLog(@"%s", __FUNCTION__); } - (void) reloadImageView{ /* Reload the image view here */ NSLog(@"%s", __FUNCTION__); } void reloadAllComponents(void *context){ GCDAppDelegate *self = (GCDAppDelegate *)context; [self reloadTableView]; [self reloadScrollView]; [self reloadImageView]; } - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ dispatch_group_t taskGroup = dispatch_queue_t mainQueue =

dispatch_group_create(); dispatch_get_main_queue();

dispatch_group_async_f(taskGroup, mainQueue, (void *)self, reloadAllComponents); /* At the end when we are done, dispatch the following block */ dispatch_group_notify(taskGroup, mainQueue, ^{ /* Do some processing here */ [[[[UIAlertView alloc] initWithTitle:@"Finished" message:@"All tasks are finished" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] autorelease] show]; }); /* We are done with the group */ dispatch_release(taskGroup); // Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES; }

42 | Chapter 2: Programming Grand Central Dispatch


6LQFHWKHdispatch_group_async_fIXQFWLRQDFFHSWVD&IXQFWLRQDVWKH EORFNRIFRGHWREHH[HFXWHGWKH&IXQFWLRQPXVWKDYHDUHIHUHQFHWR selfWREHDEOHWRLQYRNHLQVWDQFHPHWKRGVRIWKHFXUUHQWREMHFWLQZKLFK WKH&IXQFWLRQLVLPSOHPHQWHG7KDWLVWKHUHDVRQEHKLQGSDVVLQJself DVWKHFRQWH[WSRLQWHULQWKHdispatch_group_async_fIXQFWLRQ)RUPRUH LQIRUPDWLRQDERXWFRQWH[WVDQG&IXQFWLRQVSOHDVHUHIHUWR£3HUIRUPLQJ 8,5HODWHG7DVNV¤RQSDJH

2QFHDOOWKHJLYHQWDVNVDUHILQLVKHGWKHXVHUZLOOVHHDUHVXOWVLPLODUWRWKDWVKRZQLQ )LJXUH

)LJXUH0DQDJLQJDJURXSRIWDVNVZLWK*&'

Constructing Your Own Dispatch Queues :LWK*&'\RXFDQFUHDWH\RXURZQVHULDOGLVSDWFKTXHXHV VHH£'LIIHUHQW7\SHVRI 'LVSDWFK4XHXHV¤RQSDJHIRUVHULDOTXHXHV 6HULDOGLVSDWFKTXHXHVUXQWKHLUWDVNV LQ D ILUVWLQILUVWRXW ),)2  IDVKLRQ 7KH DV\QFKURQRXV WDVNV RQ VHULDO TXHXHV ZLOO QRWEHSHUIRUPHGRQWKHPDLQWKUHDGKRZHYHUPDNLQJVHULDOTXHXHVKLJKO\GHVLUDEOH IRUFRQFXUUHQW),)2WDVNV Constructing Your Own Dispatch Queues | 43


$OOV\QFKURQRXVWDVNVVXEPLWWHGWRDVHULDOTXHXHZLOOEHH[HFXWHGRQWKHFXUUHQWWKUHDG EHLQJXVHGE\WKHFRGHWKDWLVVXEPLWWLQJWKHWDVNZKHQHYHUSRVVLEOH%XWDV\QFKURQRXV WDVNVVXEPLWWHGWRDVHULDOTXHXHZLOODOZD\VEHH[HFXWHGRQDWKUHDGRWKHUWKDQWKH PDLQWKUHDG :H¦OOXVHWKHdispatch_queue_createIXQFWLRQWRFUHDWHVHULDOTXHXHV7KHILUVWSDUDP HWHULQWKLVIXQFWLRQLVD&VWULQJ char * WKDWZLOOXQLTXHO\LGHQWLI\WKDWVHULDOTXHXH LQWKHV\VWHP7KHUHDVRQ,DPHPSKDVL]LQJV\VWHPLVEHFDXVHWKLVLGHQWLILHULVDV\VWHP ZLGHLGHQWLILHUPHDQLQJWKDWLI\RXUDSSFUHDWHVDQHZVHULDOTXHXHZLWKWKHLGHQWLILHU RIserialQueue1DQGVRPHERG\HOVH¦VDSSGRHVWKHVDPHWKHUHVXOWVRIFUHDWLQJDQHZ VHULDOTXHXHZLWKWKHVDPHQDPHDUHXQGHILQHGE\*&'%HFDXVHRIWKLV$SSOHVWURQJO\ UHFRPPHQGVWKDW\RXXVHDUHYHUVH'16IRUPDWIRULGHQWLILHUV5HYHUVH'16LGHQWLILHUV DUHXVXDOO\FRQVWUXFWHGLQWKLVZD\FRPCOMPANYPRODUCTIDENTIFIER)RULQVWDQFH, FRXOGFUHDWHWZRVHULDOTXHXHVDQGDVVLJQWKHVHQDPHVWRWKHP com.pixolity.GCD.serialQueue1 com.pixolity.GCD.serialQueue2

$IWHU \RX¦YH FUHDWHG \RXU VHULDO TXHXH \RX FDQ VWDUW GLVSDWFKLQJ WDVNV WR LW XVLQJ WKHYDULRXV*&'IXQFWLRQV\RX¦YHOHDUQHGLQWKLVERRN2QFH\RXDUHGRQHZLWKWKH VHULDO GLVSDWFK TXHXH WKDW \RX¦YH MXVW FUHDWHG \RX PXVW GLVSRVH RI LW XVLQJ WKH dispatch_releaseIXQFWLRQ :RXOG\RXOLNHWRVHHDQH[DPSOH",WKRXJKWVR dispatch_queue_t firstSerialQueue = dispatch_queue_create("com.pixolity.GCD.serialQueue1", 0); dispatch_async(firstSerialQueue, ^{ NSUInteger counter = 0; for (counter = 0; counter < 5; counter++){ NSLog(@"First iteration, counter = %lu", (unsigned long)counter); } }); dispatch_async(firstSerialQueue, ^{ NSUInteger counter = 0; for (counter = 0; counter < 5; counter++){ NSLog(@"Second iteration, counter = %lu", (unsigned long)counter); } }); dispatch_async(firstSerialQueue, ^{ NSUInteger counter = 0; for (counter = 0; counter < 5; counter++){ NSLog(@"Third iteration, counter = %lu", (unsigned long)counter); }

44 | Chapter 2: Programming Grand Central Dispatch


}); dispatch_release(firstSerialQueue);

,I\RXUXQWKLVFRGHDQGKDYHDORRNDWWKHRXWSXWSULQWHGWRWKHFRQVROHZLQGRZ\RX ZLOOVHHUHVXOWVVLPLODUWRWKHVH First iteration, counter = 0 First iteration, counter = 1 First iteration, counter = 2 First iteration, counter = 3 First iteration, counter = 4 Second iteration, counter = 0 Second iteration, counter = 1 Second iteration, counter = 2 Second iteration, counter = 3 Second iteration, counter = 4 Third iteration, counter = 0 Third iteration, counter = 1 Third iteration, counter = 2 Third iteration, counter = 3 Third iteration, counter = 4

,WÂŚVREYLRXVWKDWDOWKRXJKZHGLVSDWFKHGRXUEORFNREMHFWVDV\QFKURQRXVO\WRWKHVHULDO TXHXHWKHTXHXHKDVH[HFXWHGWKHLUFRGHLQD),)2IDVKLRQ:HFDQPRGLI\WKHVDPH VDPSOHFRGHWRPDNHXVHRIdispatch_async_fIXQFWLRQLQVWHDGRIWKHdispatch_async IXQFWLRQOLNHVR void firstIteration(void *paramContext){ NSUInteger counter = 0; for (counter = 0; counter < 5; counter++){ NSLog(@"First iteration, counter = %lu", (unsigned long)counter); } } void secondIteration(void *paramContext){ NSUInteger counter = 0; for (counter = 0; counter < 5; counter++){ NSLog(@"Second iteration, counter = %lu", (unsigned long)counter); } } void thirdIteration(void *paramContext){ NSUInteger counter = 0; for (counter = 0; counter < 5; counter++){ NSLog(@"Third iteration, counter = %lu", (unsigned long)counter); } }

Constructing Your Own Dispatch Queues | 45


- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ dispatch_queue_t firstSerialQueue = dispatch_queue_create("com.pixolity.GCD.serialQueue1", 0); dispatch_async_f(firstSerialQueue, NULL, firstIteration); dispatch_async_f(firstSerialQueue, NULL, secondIteration); dispatch_async_f(firstSerialQueue, NULL, thirdIteration); dispatch_release(firstSerialQueue); // Override point for customization after application launch. [self.window makeKeyAndVisible]; return YES; }

46 | Chapter 2: Programming Grand Central Dispatch

Concurrent Programming  
Concurrent Programming  

In this book you will learn how to program parallel applications for OSX and iOS.

Advertisement