আমি কীভাবে Block
একটি Function
/ এ পাস করতে পারি Method
?
আমি চেষ্টা - (void)someFunc:(__Block)someBlock
করেও কোন লাভ হয়নি।
অর্থাত। কি ধরনের একটি জন্য Block
?
আমি কীভাবে Block
একটি 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
}];
৪. স্থানীয় ভেরিয়েবল হিসাবে ব্লক করুন
টেমপ্লেট
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
উদাহরণ
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
৫. টাইপডেফ হিসাবে ব্লক করুন
টেমপ্লেট
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);
নীচের উদাহরণে с ফাংশনগুলি ব্যবহার করে ব্লকটি পাস করার আরও একটি উপায়। আমি ব্যাকগ্রাউন্ডে এবং মূল কাতারে কিছু করার জন্য ফাংশন তৈরি করেছি।
block.h ফাইল
void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));
block.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);
}
যখন প্রয়োজন হয় আমদানি করে block.h এর চেয়ে বেশি:
- (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 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 নেবে, এই ইউআরএল থেকে কিছু জেএসএন ডেটা একটি পটভূমির থ্রেডে লোড করবে, তারপরে কলিং ফাংশনে কোনও ফলাফলের এনএসআর্রে * ফিরিয়ে দেবে।
মূলত, আমি সমস্ত ব্যাকগ্রাউন্ড-থ্রেড জটিলতা জেনেরিক পুনঃব্যবহারযোগ্য ফাংশনে লুকিয়ে রাখতে চেয়েছিলাম।
এখানে আমি এই ফাংশনটি কীভাবে বলব:
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
লোড হওয়া রেকর্ডগুলির একটি এনএসআরএ * পাস করতে হয় :
+(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.azurewebsites.net/pages/Services/WebServices-Page6.htm
আশা করি এটি আরও কিছু এক্সকোড বিকাশকারীকে সহায়তা করবে! (এই প্রশ্নটি এবং আমার উত্তরটি যদি ভোগ না করে তবে ভুলে যাবেন না!)
সম্পূর্ণ টেমপ্লেটটি দেখতে মনে হচ্ছে
- (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 {
}