매개 변수로서 Objective-C 패스 블록
어떻게 전달할 수 BlockA를 Function/ Method?
나는 - (void)someFunc:(__Block)someBlock아무 소용없이 노력했다 .
즉. 이란 무엇입니까 타입 A의는 Block?
블록의 유형은 인수 및 반환 유형에 따라 다릅니다. 일반적인 경우, 블록 유형의 함수 포인터 유형은 동일한 방식으로 선언되어 있지만 교체 *로모그래퍼 ^. 메소드에 블록을 전달하는 한 가지 방법은 다음과 같습니다.
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
그러나 보시다시피 지저분합니다. 대신 a typedef를 사용하여 블록 유형을 더 깨끗하게 만들 수 있습니다 .
typedef void (^ IteratorBlock)(id, int);
그런 다음 해당 블록을 다음과 같은 방법으로 전달하십시오.
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
이 질문에 대한 가장 쉬운 설명은 다음 템플릿을 따르는 것입니다.
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로 차단
주형
typedef returnType (^typeName)(parameters);
typeName blockName = ^(parameters) {
// your code
}
예
typedef void(^completionBlock)(NSArray *array, NSError *error);
completionBlock didComplete = ^(NSArray *array, NSError *error){
// your code
};
도움이 될 수 있습니다.
- (void)someFunc:(void(^)(void))someBlock;
다음과 같이 블록을 블록 매개 변수로 전달하면됩니다 :
//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);
아래 예에서 с 함수를 사용하여 블록을 전달하는 또 다른 방법입니다. 백그라운드와 메인 큐에서 무엇이든 수행하는 기능을 만들었습니다.
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);
}
필요한 경우 import blocks.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를 사용할 수도 있습니다.
typedef void (^SimpleBlock)(id);
@property (nonatomic, copy) SimpleBlock someActionHandler;
또한 일반적인 c 함수 구문을 사용하여 블록을 호출하거나 호출합니다.
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
여기 블록에 대한 자세한 정보
I always tend to forget about blocks syntax. This always comes to my mind when I need to declare a block. I hope it helps someone :)
Despite the answers given on this thread, I really struggled to write a function which would take a Block as a function - and with a parameter. Eventually, here's the solution I came up with.
I wanted to write a generic function, loadJSONthread, which would take the URL of a JSON Web Service, load some JSON data from this URL on a background thread, then return an NSArray* of results back to the calling function.
Basically, I wanted to keep all the background-thread complexity hidden away in a generic reuseable function.
Here's how I would call this function:
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)
}
} ];
...and this is the bit I struggled with: how to declare it, and how to get it to call the Block function once the data was loaded, and pass the Block an NSArray* of records loaded:
+(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);
});
});
}
This StackOverflow question concerns how to call functions, passing a Block as a parameter, so I've simplified the code above, and not included the loadJSONDataFromURL function.
But, if you are interested, you can find a copy of this JSON loading function on this blog: http://mikesknowledgebase.azurewebsites.net/pages/Services/WebServices-Page6.htm
Hope this helps some other XCode developers ! (Don't forget to vote up this question and my answer, if it does !)
I wrote a completionBlock for a class which will return the values of dice after they have been shaken:
Define typedef with returnType (
.habove@interfacedeclaration)typedef void (^CompleteDiceRolling)(NSInteger diceValue);Define a
@propertyfor the block (.h)@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;Define a method with
finishBlock(.h)- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;Insert previous defined method in
.mfile and commitfinishBlockto@propertydefined before- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{ self.completeDiceRolling = finishBlock; }To trigger
completionBlockpass predefined variableType to it (Don't forget to check whether thecompletionBlockexists)if( self.completeDiceRolling ){ self.completeDiceRolling(self.dieValue); }
The full template looks like
- (void) main {
[self someMethodWithSuccessBlock:^{[self successMethod];}
withFailureBlock:^(NSError * error) {[self failureMethod:error];}];
}
- (void) someMethodWithSuccessBlock:(void (^) (void))successBlock
withFailureBlock:(void (^) (NSError*))failureBlock {
//Execute a block
successBlock();
// failureBlock([[NSError alloc]init]);
}
- (void) successMethod {
}
- (void) failureMethod:(NSError*) error {
}
참고URL : https://stackoverflow.com/questions/7936570/objective-c-pass-block-as-parameter
'IT' 카테고리의 다른 글
| Objective-C 2.0에서 메소드를 더 이상 사용되지 않는 것으로 플래그 지정하려면 어떻게합니까? (0) | 2020.06.23 |
|---|---|
| 배열에서 가장 가까운 숫자를 얻습니다 (0) | 2020.06.23 |
| onConfigurationChanged가 호출되지 않음 (0) | 2020.06.23 |
| 테스트 어댑터가 설치된 테스트 탐색기에 NUnit 장치 테스트가 표시되지 않음 (0) | 2020.06.23 |
| 구속 조건을 동시에 만족시킬 수 없으며 구속 조건을 해제하여 복구를 시도합니다. (0) | 2020.06.23 |