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  

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

Advertisement
Read more
Read more
Similar to
Popular now
Just for you