मैं Block
a Function
/ कैसे पास कर सकता हूं Method
?
मैंने - (void)someFunc:(__Block)someBlock
कोई फायदा नहीं हुआ।
अर्थात। एक प्रकार के लिए क्या है Block
?
मैं Block
a Function
/ कैसे पास कर सकता हूं Method
?
मैंने - (void)someFunc:(__Block)someBlock
कोई फायदा नहीं हुआ।
अर्थात। एक प्रकार के लिए क्या है Block
?
जवाबों:
एक ब्लॉक का प्रकार उसके तर्कों और उसके रिटर्न प्रकार के आधार पर भिन्न होता है। सामान्य स्थिति में, ब्लॉक प्रकारों को उसी तरह से घोषित किया जाता है जैसे फ़ंक्शन पॉइंटर प्रकार होते हैं, लेकिन *
ए के साथ प्रतिस्थापित करना ^
। एक ब्लॉक को एक विधि में पारित करने का एक तरीका इस प्रकार है:
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
लेकिन जैसा कि आप देख सकते हैं, यह गड़बड़ है। आप इसके बजाय typedef
ब्लॉक प्रकार को क्लीनर बनाने के लिए उपयोग कर सकते हैं :
typedef void (^ IteratorBlock)(id, int);
और फिर उस ब्लॉक को इस तरह से पास करें:
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
NSNumber *
या std::string&
या कुछ और आप एक समारोह तर्क के रूप में दे सकते हैं। यह सिर्फ एक उदाहरण है। (एक ब्लॉक है कि जगह के लिए छोड़कर बराबर है के लिए id
के साथ NSNumber
, typedef
हो सकता है typedef void (^ IteratorWithNumberBlock)(NSNumber *, int);
।)
NS_NOESCAPE
, लेकिन enumerateObjectsUsingBlock
मुझे बताया गया है कि गैर-बच रहा है, फिर भी मैं NS_NOESCAPE
साइट में कहीं भी नहीं देखता हूं , और न ही एप्पल डॉक्स में उल्लेख किया गया है। क्या आप मदद कर सकते हैं?
इस प्रश्न का सबसे आसान स्पष्टीकरण इन टेम्पलेट्स का पालन करना है:
1. एक विधि पैरामीटर के रूप में ब्लॉक करें
खाका
- (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
// your code
}
उदाहरण
-(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
// your code
}
मामलों का अन्य उपयोग:
2. एक संपत्ति के रूप में ब्लॉक करें
खाका
@property (nonatomic, copy) returnType (^blockName)(parameters);
उदाहरण
@property (nonatomic,copy)void (^completionBlock)(NSArray *array, NSError *error);
3. विधि तर्क के रूप में ब्लॉक करें
खाका
[anObject aMethodWithBlock: ^returnType (parameters) {
// your code
}];
उदाहरण
[self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
// your code
}];
4. एक स्थानीय चर के रूप में ब्लॉक करें
खाका
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
उदाहरण
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
5. एक टंकण के रूप में ब्लॉक करें
खाका
typedef returnType (^typeName)(parameters);
typeName blockName = ^(parameters) {
// your code
}
उदाहरण
typedef void(^completionBlock)(NSArray *array, NSError *error);
completionBlock didComplete = ^(NSArray *array, NSError *error){
// your code
};
आप इस तरह से कर सकते हैं, एक ब्लॉक पैरामीटर के रूप में पासिंग ब्लॉक:
//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);
नीचे उदाहरण में с फ़ंक्शन का उपयोग करके ब्लॉक पास करने का एक और तरीका। I`ve ने पृष्ठभूमि में और मुख्य कतार में कुछ भी प्रदर्शन करने के लिए फ़ंक्शंस बनाए।
blocks.h फ़ाइल
void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));
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);
}
आवश्यक होने पर ब्लॉक इंसेक्ट करें और इसे लागू करें:
- (void)loadInBackground {
performInBackground(^{
NSLog(@"Loading something in background");
//loading code
performOnMainQueue(^{
//completion hadler code on main queue
});
});
}
यदि यह आपके लिए लागू है, तो आप ब्लॉक को एक साधारण संपत्ति के रूप में भी सेट कर सकते हैं:
@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
सुनिश्चित करें कि ब्लॉक संपत्ति "कॉपी" है!
और निश्चित रूप से आप typedef का उपयोग कर सकते हैं:
typedef void (^SimpleBlock)(id);
@property (nonatomic, copy) SimpleBlock someActionHandler;
इसके अलावा आप सामान्य सी फ़ंक्शन सिंटैक्स का उपयोग करके किसी ब्लॉक को आमंत्रित या कॉल करते हैं
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
यहाँ ब्लॉकों पर अधिक जानकारी
मैं हमेशा ब्लॉक सिंटैक्स के बारे में भूल जाता हूं। यह हमेशा मेरे दिमाग में आता है जब मुझे ब्लॉक घोषित करने की आवश्यकता होती है। मुझे आशा है कि यह किसी की मदद करता है :)
मैंने एक वर्ग के लिए एक पूरा लेखन लिखा है जो पासा के मूल्यों को वापस कर देगा, जिसके बाद वे हिल गए हैं:
वापसी के साथ टाइपराइफ को परिभाषित करें ( घोषणा के .h
ऊपर @interface
)
typedef void (^CompleteDiceRolling)(NSInteger diceValue);
@property
ब्लॉक के लिए परिभाषित करें ( .h
)
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
finishBlock
( .h
) के साथ एक विधि परिभाषित करें
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
में पहले से निर्धारित विधि सम्मिलित .m
फ़ाइल और प्रतिबद्ध finishBlock
करने @property
से पहले परिभाषित
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}
completionBlock
पास पूर्वनिर्धारित चर टाइप करने के लिए इसे ट्रिगर करें (यह जाँचना न भूलें कि क्या completionBlock
मौजूद है)
if( self.completeDiceRolling ){
self.completeDiceRolling(self.dieValue);
}
इस सूत्र पर दिए गए उत्तर के बावजूद, मैं वास्तव में एक फ़ंक्शन लिखने के लिए संघर्ष कर रहा था, जो एक फ़ंक्शन के रूप में ब्लॉक ले जाएगा - और एक पैरामीटर के साथ। आखिरकार, यहाँ मैं समाधान के साथ आया हूँ।
मैं एक सामान्य फ़ंक्शन लिखना चाहता था loadJSONthread
, जो JSON वेब सेवा का URL लेगा, इस JSON डेटा को बैकग्राउंड थ्रेड पर कुछ JSON डेटा लोड करेगा, फिर परिणाम के NSArray * को कॉलिंग फ़ंक्शन पर वापस लौटाएगा।
मूल रूप से, मैं एक सामान्य पुन: प्रयोज्य समारोह में सभी पृष्ठभूमि-धागा जटिलता को दूर रखना चाहता था।
यहां बताया गया है कि मैं इस फ़ंक्शन को कैसे कॉल करूंगा:
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)
}
} ];
... और यह थोड़ा सा मैंने संघर्ष किया है: इसे कैसे घोषित किया जाए, और डेटा लोड होने पर इसे ब्लॉक फ़ंक्शन को कॉल करने के लिए कैसे प्राप्त किया जाए, और Block
लोड किए गए रिकॉर्ड का एक NSArray * पास करें :
+(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);
});
});
}
यह स्टैकऑवरफ़्लो प्रश्न यह कहता है कि फ़ंक्शंस को कैसे कॉल किया जाए, एक ब्लॉक को एक पैरामीटर के रूप में पारित किया जाए, इसलिए मैंने ऊपर दिए गए कोड को सरल किया है, और loadJSONDataFromURL
फ़ंक्शन को शामिल नहीं किया है ।
लेकिन, यदि आप रुचि रखते हैं, तो आप इस ब्लॉग पर JSON लोडिंग फ़ंक्शन की एक प्रति पा सकते हैं: http://mikesknowledgebase.azurewebooks.net/pages/Services/WebServices-Page6.htm
उम्मीद है कि यह कुछ अन्य XCode डेवलपर्स में मदद करता है! (इस सवाल और मेरे जवाब को मत भूलना, अगर यह करता है!)
पूरा खाका जैसा दिखता है
- (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 {
}