Bagaimana saya bisa meneruskan Blockke Function/ Method?
Saya mencoba - (void)someFunc:(__Block)someBlocktanpa hasil.
yaitu. Apa jenis untuk Block?
Bagaimana saya bisa meneruskan Blockke Function/ Method?
Saya mencoba - (void)someFunc:(__Block)someBlocktanpa hasil.
yaitu. Apa jenis untuk Block?
Jawaban:
Jenis blok bervariasi tergantung pada argumen dan jenis kembalinya. Dalam kasus umum, tipe blok dideklarasikan dengan cara yang sama dengan tipe pointer fungsi, tetapi mengganti *dengan a ^. Salah satu cara untuk meneruskan blok ke metode adalah sebagai berikut:
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
Tapi seperti yang Anda lihat, itu berantakan. Anda bisa menggunakan a typedefuntuk membuat pembersih jenis blok:
typedef void (^ IteratorBlock)(id, int);
Dan kemudian meneruskan blok itu ke metode seperti:
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
NSNumber *atau std::string&atau apa pun yang Anda bisa berikan sebagai argumen fungsi. Ini hanya sebuah contoh. (Untuk blok yang setara kecuali untuk diganti iddengan NSNumber, typedefakan menjadi typedef void (^ IteratorWithNumberBlock)(NSNumber *, int);.)
NS_NOESCAPE, tetapi enumerateObjectsUsingBlocksaya diberi tahu tidak melarikan diri, namun saya tidak melihat NS_NOESCAPEdi mana pun di situs, juga tidak melarikan diri disebutkan sama sekali dalam dokumen Apple. Bisakah kamu menolong?
Penjelasan termudah untuk pertanyaan ini adalah ikuti templat ini:
1. Blok sebagai parameter metode
Templat
- (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
// your code
}
Contoh
-(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
// your code
}
Penggunaan kasus lainnya:
2. Blokir sebagai Properti
Templat
@property (nonatomic, copy) returnType (^blockName)(parameters);
Contoh
@property (nonatomic,copy)void (^completionBlock)(NSArray *array, NSError *error);
3. Blokir sebagai argumen metode
Templat
[anObject aMethodWithBlock: ^returnType (parameters) {
// your code
}];
Contoh
[self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
// your code
}];
4. Blokir sebagai variabel lokal
Templat
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
Contoh
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
5. Blokir sebagai typedef
Templat
typedef returnType (^typeName)(parameters);
typeName blockName = ^(parameters) {
// your code
}
Contoh
typedef void(^completionBlock)(NSArray *array, NSError *error);
completionBlock didComplete = ^(NSArray *array, NSError *error){
// your code
};
Anda dapat melakukannya seperti ini, melewati blok sebagai parameter blok:
//creating a block named "completion" that will take no arguments and will return void
void(^completion)() = ^() {
NSLog(@"bbb");
};
//creating a block namd "block" that will take a block as argument and will return void
void(^block)(void(^completion)()) = ^(void(^completion)()) {
NSLog(@"aaa");
completion();
};
//invoking block "block" with block "completion" as argument
block(completion);
Satu lagi cara untuk melewatkan blok menggunakan fungsi с pada contoh di bawah ini. Saya sudah membuat fungsi untuk melakukan apa saja di latar belakang dan antrian utama.
file blocks.h
void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));
file blocks.m
#import "blocks.h"
void performInBackground(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
}
void performOnMainQueue(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_main_queue(), block);
}
Dari impor blok. H bila perlu dan aktifkan:
- (void)loadInBackground {
performInBackground(^{
NSLog(@"Loading something in background");
//loading code
performOnMainQueue(^{
//completion hadler code on main queue
});
});
}
Anda juga dapat mengatur blok sebagai properti sederhana jika itu berlaku untuk Anda:
@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
pastikan bahwa properti blok adalah "salin"!
dan tentu saja Anda juga dapat menggunakan typedef:
typedef void (^SimpleBlock)(id);
@property (nonatomic, copy) SimpleBlock someActionHandler;
Anda juga memanggil atau memanggil blok menggunakan sintaks fungsi c biasa
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
Info lebih lanjut tentang blok di sini
Saya selalu cenderung lupa tentang sintaks blok. Ini selalu muncul di pikiran saya ketika saya harus mendeklarasikan blok. Saya harap ini membantu seseorang :)
Saya menulis sebuahlockBlock untuk kelas yang akan mengembalikan nilai-nilai dadu setelah mereka diguncang:
Tentukan typedef dengan returnType ( deklarasi di .hatas @interface)
typedef void (^CompleteDiceRolling)(NSInteger diceValue);Tentukan a @propertyuntuk blok ( .h)
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;Tetapkan metode dengan finishBlock( .h)
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;Masukkan metode yang didefinisikan sebelumnya dalam .mfile dan komit finishBlockuntuk @propertydidefinisikan sebelumnya
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}Untuk memicu completionBlocklulus Variabel jenis yang telah ditentukan sebelumnya (Jangan lupa untuk memeriksa apakah completionBlockada)
if( self.completeDiceRolling ){
self.completeDiceRolling(self.dieValue);
}Terlepas dari jawaban yang diberikan pada utas ini, saya benar-benar berjuang untuk menulis suatu fungsi yang akan mengambil Blok sebagai fungsi - dan dengan parameter. Akhirnya, inilah solusi yang saya buat.
Saya ingin menulis fungsi umum loadJSONthread, yang akan mengambil URL Layanan Web JSON, memuat beberapa data JSON dari URL ini di utas latar belakang, lalu mengembalikan hasil NSArray * kembali ke fungsi pemanggilan.
Pada dasarnya, saya ingin menyembunyikan semua kompleksitas background-thread dalam fungsi generik yang dapat digunakan kembali.
Inilah cara saya memanggil fungsi ini:
NSString* WebServiceURL = @"http://www.inorthwind.com/Service1.svc/getAllCustomers";
[JSONHelper loadJSONthread:WebServiceURL onLoadedData:^(NSArray *results) {
// Finished loading the JSON data
NSLog(@"Loaded %lu rows.", (unsigned long)results.count);
// Iterate through our array of Company records, and create/update the records in our SQLite database
for (NSDictionary *oneCompany in results)
{
// Do something with this Company record (eg store it in our SQLite database)
}
} ];
... dan ini adalah bagian yang saya perjuangkan: cara mendeklarasikannya, dan cara membuatnya memanggil fungsi Blok begitu data dimuat, dan meneruskan BlockNSArray * dari catatan yang dimuat:
+(void)loadJSONthread:(NSString*)urlString onLoadedData:(void (^)(NSArray*))onLoadedData
{
__block NSArray* results = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// Call an external function to load the JSON data
NSDictionary * dictionary = [JSONHelper loadJSONDataFromURL:urlString];
results = [dictionary objectForKey:@"Results"];
dispatch_async(dispatch_get_main_queue(), ^{
// This code gets run on the main thread when the JSON has loaded
onLoadedData(results);
});
});
}
Pertanyaan StackOverflow ini menyangkut cara memanggil fungsi, melewati Blok sebagai parameter, jadi saya menyederhanakan kode di atas, dan tidak termasuk loadJSONDataFromURL fungsi.
Tetapi, jika Anda tertarik, Anda dapat menemukan salinan fungsi pemuatan JSON ini di blog ini: http://mikesknowledgebase.azurewebsites.net/pages/Services/WebServices-Page6.htm
Semoga ini bisa membantu beberapa pengembang XCode lainnya! (Jangan lupa memilih pertanyaan ini dan jawaban saya, jika ya!)
Templat lengkapnya terlihat seperti
- (void) main {
//Call
[self someMethodWithSuccessBlock:^{[self successMethod];}
withFailureBlock:^(NSError * error) {[self failureMethod:error];}];
}
//Definition
- (void) someMethodWithSuccessBlock:(void (^) (void))successBlock
withFailureBlock:(void (^) (NSError*))failureBlock {
//Execute a block
successBlock();
// failureBlock([[NSError alloc]init]);
}
- (void) successMethod {
}
- (void) failureMethod:(NSError*) error {
}