Yah, karena itu akan sangat berguna. Saya tidak perlu tahu apa itu asalkan saya memiliki sintaks yang benar dan berperilaku seperti NSObject.
gurghet
5
Jika Anda tidak tahu apa itu, bagaimana Anda tahu itu akan sangat berguna?
Stephen Canon
5
Anda tidak boleh menggunakannya Jika Anda tidak tahu apa itu :)
Richard J. Ross III
5
@ Moshe di sini adalah beberapa alasan yang terlintas dalam pikiran. Blok lebih mudah diimplementasikan daripada kelas delegasi penuh, blok ringan, dan Anda memiliki akses ke variabel yang ada dalam konteks blok itu. Event Callback dapat dilakukan secara efektif menggunakan blok (cocos2d menggunakannya hampir secara eksklusif).
Richard J. Ross III
2
Tidak sepenuhnya terkait, tetapi karena beberapa komentar mengeluhkan sintaks blok "jelek", berikut adalah artikel hebat yang mendapatkan sintaksis dari prinsip pertama: nilsou.com/blog/2013/08/21/objective-c-blocks-syntax
Dengan xCode 4.4 atau lebih baru Anda tidak perlu mensintesis. Itu akan membuatnya lebih ringkas. Apple Doc
Eric
wow, saya tidak tahu itu, terima kasih! ... Meskipun saya sering melakukannya@synthesize myProp = _myProp
Robert
7
@ Robert: Anda beruntung lagi, karena tanpa meletakkan @synthesizedefault adalah apa yang Anda lakukan @synthesize name = _name;stackoverflow.com/a/12119360/1052616
Eric
1
@CharlieMonroe - Ya Anda mungkin benar, tetapi tidakkah Anda memerlukan implementasi dealloc untuk nil atau melepaskan properti blok tanpa ARC? (sudah lama sejak saya menggunakan non-ARC)
Robert
1
@impcaptor: Ya, ini dapat menyebabkan kebocoran memori jika Anda tidak melepaskannya di dealloc - sama seperti variabel lainnya.
Charlie Monroe
210
Berikut adalah contoh bagaimana Anda akan menyelesaikan tugas seperti itu:
#import <Foundation/Foundation.h>typedefint(^IntBlock)();@interface myobj :NSObject{IntBlock compare;}@property(readwrite, copy)IntBlock compare;@end@implementation myobj
@synthesize compare;-(void)dealloc
{// need to release the block since the property was declared copy. (for heap// allocated blocks this prevents a potential leak, for compiler-optimized // stack blocks it is a no-op)// Note that for ARC, this is unnecessary, as with all properties, the memory management is handled for you.[compare release];[super dealloc];}@endint main (){@autoreleasepool{
myobj *ob =[[myobj alloc] init];
ob.compare =^{return rand();};NSLog(@"%i", ob.compare());// if not ARC[ob release];}return0;}
Sekarang, satu-satunya hal yang perlu diubah jika Anda perlu mengubah jenis perbandingan adalah typedef int (^IntBlock)(). Jika Anda perlu mengirimkan dua objek ke sana, ubah ke ini:, typedef int (^IntBlock)(id, id)dan ubah blok Anda ke:
^(id obj1, id obj2){return rand();};
Saya harap ini membantu.
EDIT 12 Maret 2012:
Untuk ARC, tidak ada perubahan khusus yang diperlukan, karena ARC akan mengelola blok untuk Anda selama mereka didefinisikan sebagai salinan. Anda tidak perlu mengatur properti ke nol di destructor Anda, baik.
// Here is a block as a property://// Someone passes you a block. You "hold on to it",// while you do other stuff. Later, you use the block.//// The property 'doStuff' will hold the incoming block.@property(copy)void(^doStuff)(void);// Here's a method in your class.// When someone CALLS this method, they PASS IN a block of code,// which they want to be performed after the method is finished.-(void)doSomethingAndThenDoThis:(void(^)(void))pleaseDoMeLater;// We will hold on to that block of code in "doStuff".
Ini file .m Anda:
-(void)doSomethingAndThenDoThis:(void(^)(void))pleaseDoMeLater
{// Regarding the incoming block of code, save it for later:
self.doStuff = pleaseDoMeLater;// Now do other processing, which could follow various paths,// involve delays, and so on. Then after everything:[self _alldone];}-(void)_alldone
{NSLog(@"Processing finished, running the completion block.");// Here's how to run the block:if( self.doStuff != nil )
self.doStuff();}
Waspadai kode contoh yang kedaluwarsa.
Dengan sistem modern (2014+), lakukan apa yang ditunjukkan di sini. Sesederhana itu.
Demi anak cucu / kelengkapan ... Berikut adalah dua contoh LENGKAP tentang bagaimana menerapkan "cara melakukan sesuatu" yang sangat fleksibel dan serba bisa ini. @ Robert menjawab dengan singkat dan benar, tetapi di sini saya juga ingin menunjukkan cara untuk benar-benar "mendefinisikan" blok.
@interfaceReusableClass:NSObject@property(nonatomic,copy)CALayer*(^layerFromArray)(NSArray*);@end@implementationResusableClassstaticNSStringconst* privateScope =@"Touch my monkey.";-(CALayer*(^)(NSArray*)) layerFromArray {return^CALayer*(NSArray*array){CALayer*returnLayer =CALayer.layer
for(id thing in array){[returnLayer doSomethingCrazy];[returnLayer setValue:privateScope
forKey:@"anticsAndShenanigans"];}returnlist;};}@end
Bodoh? Iya. Berguna? Hells yeah. Berikut adalah cara pengaturan properti yang lebih "atomik" dan kelas yang sangat berguna ...
Ini menggambarkan pengaturan properti blok melalui accessor (meskipun di dalam init, sebuah praktik yang tidak pasti.) Vs contoh pertama mekanisme "nonatomik" "pengambil". Dalam kedua kasus ... implementasi "hardcoded" selalu dapat ditimpa, misalnya .. a l ..
Juga .. jika Anda ingin menambahkan properti blok dalam suatu kategori ... katakanlah Anda ingin menggunakan Blok alih-alih beberapa "aksi" target / aksi sekolah lama ... Anda bisa menggunakan nilai yang terkait dengannya, well .. kaitkan blok.
typedefvoid(^NSControlActionBlock)(NSControl*);@interfaceNSControl(ActionBlocks)@property(copy)NSControlActionBlock actionBlock;@end@implementationNSControl(ActionBlocks)-(NSControlActionBlock) actionBlock {// use the "getter" method's selector to store/retrieve the block!return objc_getAssociatedObject(self, _cmd);}-(void) setActionBlock:(NSControlActionBlock)ab {
objc_setAssociatedObject(// save (copy) the block associatively, as categories can't synthesize Ivars.
self,@selector(actionBlock),ab ,OBJC_ASSOCIATION_COPY);
self.target = self;// set self as target (where you call the block)
self.action =@selector(doItYourself);// this is where it's called.}-(void) doItYourself {if(self.actionBlock && self.target == self) self.actionBlock(self);}@end
Sekarang, ketika Anda membuat tombol, Anda tidak perlu mengatur beberapa IBActiondrama .. Asosiasikan saja pekerjaan yang harus dilakukan saat penciptaan ...
Pola ini dapat diterapkan LEBIH dan LEBIH ke API Kakao. Gunakan properti untuk membawa bagian-bagian yang relevan dari kode Anda lebih dekat bersama-sama , menghilangkan paradigma delegasi berbelit-belit , dan leverage kekuatan benda-benda di luar itu hanya bertindak sebagai "wadah" bodoh.
Alex, contoh yang bagus. Anda tahu, saya bertanya-tanya tentang nonatomik. Pikiran?
Fattie
2
Sangat jarang bahwa "atom" akan menjadi hal yang benar untuk dilakukan pada sebuah properti. Ini akan menjadi hal yang sangat aneh untuk mengatur properti blok di satu utas dan membacanya di utas lainnya secara bersamaan , atau untuk mengatur properti blok secara simultan dari beberapa utas. Jadi biaya "atomik" vs "nonatomik" tidak memberi Anda keuntungan nyata.
gnasher729
8
Tentu saja Anda bisa menggunakan blok sebagai properti. Tetapi pastikan mereka dinyatakan sebagai @ properti (copy) . Sebagai contoh:
Dalam MRC, blok yang menangkap variabel konteks dialokasikan dalam tumpukan ; mereka akan dirilis ketika bingkai tumpukan dihancurkan. Jika mereka disalin, blok baru akan dialokasikan di heap , yang dapat dieksekusi nanti setelah bingkai tumpukan poped.
Ini tidak dimaksudkan sebagai "jawaban yang baik", karena pertanyaan ini diajukan secara eksplisit untuk ObjectiveC. Ketika Apple memperkenalkan Swift di WWDC14, saya ingin berbagi cara berbeda untuk menggunakan blok (atau penutupan) di Swift.
Halo, Swift
Anda memiliki banyak cara yang ditawarkan untuk melewati blok yang setara dengan fungsi di Swift.
Saya menemukan tiga.
Untuk memahami ini, saya sarankan Anda untuk menguji di bagian kecil ini kode.
func test(function:String->String)->String{return function("test")}
func funcStyle(s:String)->String{return"FUNC__"+ s +"__FUNC"}
let resultFunc = test(funcStyle)
let blockStyle:(String)->String={s in return"BLOCK__"+ s +"__BLOCK"}
let resultBlock = test(blockStyle)
let resultAnon = test({(s:String)->String in return"ANON_"+ s +"__ANON"})
println(resultFunc)
println(resultBlock)
println(resultAnon)
Cepat, dioptimalkan untuk penutupan
Karena Swift dioptimalkan untuk pengembangan asinkron, Apple bekerja lebih banyak pada penutupan. Yang pertama adalah fungsi signature dapat disimpulkan sehingga Anda tidak perlu menulis ulang.
Akses params dengan angka
let resultShortAnon = test({return"ANON_"+ $0 +"__ANON"})
Params menyimpulkan dengan memberi nama
let resultShortAnon2 = test({myParam in return"ANON_"+ myParam +"__ANON"})
Penutupan Trailing
Kasus khusus ini hanya berfungsi jika blok adalah argumen terakhir, itu disebut trailing closure
Berikut ini sebuah contoh (digabung dengan tanda tangan yang disimpulkan untuk menunjukkan kekuatan Swift)
let resultTrailingClosure = test {return"TRAILCLOS_"+ $0 +"__TRAILCLOS"}
Akhirnya:
Menggunakan semua kekuatan ini apa yang saya lakukan adalah mencampur trailing closure dan ketik inferensi (dengan penamaan agar mudah dibaca)
PFFacebookUtils.logInWithPermissions(permissions){
user, error in
if(!user){
println("Uh oh. The user cancelled the Facebook login.")}elseif(user.isNew){
println("User signed up and logged in through Facebook!")}else{
println("User logged in through Facebook!")}}
func test(function:String->String, param1:String, param2:String)->String{return function("test"+param1 + param2)}
func funcStyle(s:String)->String{return"FUNC__"+ s +"__FUNC"}
let resultFunc = test(funcStyle,"parameter 1","parameter 2")
let blockStyle:(String)->String={s in return"BLOCK__"+ s +"__BLOCK"}
let resultBlock = test(blockStyle,"parameter 1","parameter 2")
let resultAnon = test({(s:String)->String in return"ANON_"+ s +"__ANON"},"parameter 1","parameter 2")
println(resultFunc)
println(resultBlock)
println(resultAnon)
Jawaban:
Jika Anda akan mengulangi blok yang sama di beberapa tempat menggunakan tipe def
sumber
@synthesize myProp = _myProp
@synthesize
default adalah apa yang Anda lakukan@synthesize name = _name;
stackoverflow.com/a/12119360/1052616Berikut adalah contoh bagaimana Anda akan menyelesaikan tugas seperti itu:
Sekarang, satu-satunya hal yang perlu diubah jika Anda perlu mengubah jenis perbandingan adalah
typedef int (^IntBlock)()
. Jika Anda perlu mengirimkan dua objek ke sana, ubah ke ini:,typedef int (^IntBlock)(id, id)
dan ubah blok Anda ke:Saya harap ini membantu.
EDIT 12 Maret 2012:
Untuk ARC, tidak ada perubahan khusus yang diperlukan, karena ARC akan mengelola blok untuk Anda selama mereka didefinisikan sebagai salinan. Anda tidak perlu mengatur properti ke nol di destructor Anda, baik.
Untuk bacaan lebih lanjut, silakan periksa dokumen ini: http://clang.llvm.org/docs/AutomaticReferenceCounting.html
sumber
Untuk Swift, cukup gunakan penutupan: contoh.
Dalam Objective-C:
@ properti (copy) batal
Sesederhana itu.
Berikut adalah dokumentasi Apple yang sebenarnya, yang menyatakan dengan tepat apa yang harus digunakan:
Apple doco.
Dalam file .h Anda:
Ini file .m Anda:
Waspadai kode contoh yang kedaluwarsa.
Dengan sistem modern (2014+), lakukan apa yang ditunjukkan di sini. Sesederhana itu.
sumber
strong
bukancopy
?nonatomic
seperti praktik terbaik untuk sebagian besar kasus lainnya menggunakan properti?Demi anak cucu / kelengkapan ... Berikut adalah dua contoh LENGKAP tentang bagaimana menerapkan "cara melakukan sesuatu" yang sangat fleksibel dan serba bisa ini. @ Robert menjawab dengan singkat dan benar, tetapi di sini saya juga ingin menunjukkan cara untuk benar-benar "mendefinisikan" blok.
Bodoh? Iya. Berguna? Hells yeah. Berikut adalah cara pengaturan properti yang lebih "atomik" dan kelas yang sangat berguna ...
Ini menggambarkan pengaturan properti blok melalui accessor (meskipun di dalam init, sebuah praktik yang tidak pasti.) Vs contoh pertama mekanisme "nonatomik" "pengambil". Dalam kedua kasus ... implementasi "hardcoded" selalu dapat ditimpa, misalnya .. a l ..
Juga .. jika Anda ingin menambahkan properti blok dalam suatu kategori ... katakanlah Anda ingin menggunakan Blok alih-alih beberapa "aksi" target / aksi sekolah lama ... Anda bisa menggunakan nilai yang terkait dengannya, well .. kaitkan blok.
Sekarang, ketika Anda membuat tombol, Anda tidak perlu mengatur beberapa
IBAction
drama .. Asosiasikan saja pekerjaan yang harus dilakukan saat penciptaan ...Pola ini dapat diterapkan LEBIH dan LEBIH ke API Kakao. Gunakan properti untuk membawa bagian-bagian yang relevan dari kode Anda lebih dekat bersama-sama , menghilangkan paradigma delegasi berbelit-belit , dan leverage kekuatan benda-benda di luar itu hanya bertindak sebagai "wadah" bodoh.
sumber
Tentu saja Anda bisa menggunakan blok sebagai properti. Tetapi pastikan mereka dinyatakan sebagai @ properti (copy) . Sebagai contoh:
Dalam MRC, blok yang menangkap variabel konteks dialokasikan dalam tumpukan ; mereka akan dirilis ketika bingkai tumpukan dihancurkan. Jika mereka disalin, blok baru akan dialokasikan di heap , yang dapat dieksekusi nanti setelah bingkai tumpukan poped.
sumber
Disclamer
Ini tidak dimaksudkan sebagai "jawaban yang baik", karena pertanyaan ini diajukan secara eksplisit untuk ObjectiveC. Ketika Apple memperkenalkan Swift di WWDC14, saya ingin berbagi cara berbeda untuk menggunakan blok (atau penutupan) di Swift.
Halo, Swift
Anda memiliki banyak cara yang ditawarkan untuk melewati blok yang setara dengan fungsi di Swift.
Saya menemukan tiga.
Untuk memahami ini, saya sarankan Anda untuk menguji di bagian kecil ini kode.
Cepat, dioptimalkan untuk penutupan
Karena Swift dioptimalkan untuk pengembangan asinkron, Apple bekerja lebih banyak pada penutupan. Yang pertama adalah fungsi signature dapat disimpulkan sehingga Anda tidak perlu menulis ulang.
Akses params dengan angka
Params menyimpulkan dengan memberi nama
Penutupan Trailing
Kasus khusus ini hanya berfungsi jika blok adalah argumen terakhir, itu disebut trailing closure
Berikut ini sebuah contoh (digabung dengan tanda tangan yang disimpulkan untuk menunjukkan kekuatan Swift)
Akhirnya:
Menggunakan semua kekuatan ini apa yang saya lakukan adalah mencampur trailing closure dan ketik inferensi (dengan penamaan agar mudah dibaca)
sumber
Halo, Swift
Melengkapi apa yang dijawab @Francescu.
Menambahkan parameter ekstra:
sumber
Anda dapat mengikuti format di bawah ini dan dapat menggunakan
testingObjectiveCBlock
properti di kelas.Untuk info lebih lanjut lihat di sini
sumber