Objective-C 블록을 속성으로 사용할 수 있습니까?
표준 속성 구문을 사용하여 블록을 속성으로 사용할 수 있습니까?
ARC에 대한 변경 사항이 있습니까?
@property (nonatomic, copy) void (^simpleBlock)(void);
@property (nonatomic, copy) BOOL (^blockWithParamter)(NSString *input);
같은 블록을 여러 곳에서 반복하려면 유형 정의를 사용합니다.
typedef void(^MyCompletionBlock)(BOOL success, NSError *error);
@property (nonatomic) MyCompletionBlock completion;
다음은 이러한 작업을 수행하는 방법의 예입니다.
#import <Foundation/Foundation.h>
typedef int (^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];
}
@end
int main () {
@autoreleasepool {
myobj *ob = [[myobj alloc] init];
ob.compare = ^
{
return rand();
};
NSLog(@"%i", ob.compare());
// if not ARC
[ob release];
}
return 0;
}
비교 해야 할 해야 할 은 이비교유변야할경경변야경할같사다다습니음과항은해우제형을해▁the▁now▁be▁thing▁only입니다.typedef int (^IntBlock)()
해야 할 과 같이 합니다.typedef int (^IntBlock)(id, id)
블록을 다음으로 변경합니다.
^ (id obj1, id obj2)
{
return rand();
};
2012년 3월 12일 편집:
ARC의 경우 블록이 복사로 정의되어 있는 한 ARC가 블록을 관리하므로 특별히 변경할 필요가 없습니다.소멸자에서 속성을 0으로 설정할 필요도 없습니다.
자세한 내용은 다음 문서를 참조하십시오. http://clang.llvm.org/docs/AutomaticReferenceCounting.html
@문서(복사본) 문서
@property (copy)void (^doStuff)(void);
사용할 항목을 정확하게 명시한 실제 Apple 설명서:
.h 파일:
// 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".
.m 파일:
-(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();
}
오래된 예제 코드에 주의하십시오.
최신(2014+) 시스템에서는 이 방법이 정확하고 문서화된 접근 방식입니다.
후세를 위하여 / 완전성을 위하여…여기 이 터무니없이 다재다능한 "일을 하는 방법"을 구현하는 방법에 대한 두 가지 전체 예가 있습니다.@로버트의 대답은 행복할 정도로 간결하고 정확하지만, 여기서는 블록을 실제로 "정의"하는 방법도 보여주고 싶습니다.
@interface ReusableClass : NSObject
@property (nonatomic,copy) CALayer*(^layerFromArray)(NSArray*);
@end
@implementation ResusableClass
static NSString const * 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"];
}
return list;
};
}
@end
바보? 네. 유용하다고요?당연하지요.여기 속성을 설정하는 다른 "더 원자적인" 방법이 있습니다.그리고 터무니없이 유용한 수업.
@interface CALayoutDelegator : NSObject
@property (nonatomic,strong) void(^layoutBlock)(CALayer*);
@end
@implementation CALayoutDelegator
- (id) init {
return self = super.init ?
[self setLayoutBlock: ^(CALayer*layer){
for (CALayer* sub in layer.sublayers)
[sub someDefaultLayoutRoutine];
}], self : nil;
}
- (void) layoutSublayersOfLayer:(CALayer*)layer {
self.layoutBlock ? self.layoutBlock(layer) : nil;
}
@end
이것은 접근자를 통해 블록 속성을 설정하는 것을 보여줍니다(비록 그 안에 있지만, 논쟁의 여지가 있는 다이스 관행입니다).) vs 첫 번째 예시의 "비원자" "게터" 메커니즘.어느 경우든 "하드코딩된" 구현은 항상 인스턴스별로 덮어쓸 수 있습니다.대저택배
CALayoutDelegator *littleHelper = CALayoutDelegator.new;
littleHelper.layoutBlock = ^(CALayer*layer){
[layer.sublayers do:^(id sub){ [sub somethingElseEntirely]; }];
};
someLayer.layoutManager = littleHelper;
또한... 범주에 블록 속성을 추가하려는 경우...예전의 목표물/액션 대신 블록을 사용하고 싶다고 말합니다.연관된 값을 사용하면 됩니다.블록을 연결합니다.
typedef void(^NSControlActionBlock)(NSControl*);
@interface NSControl (ActionBlocks)
@property (copy) NSControlActionBlock actionBlock; @end
@implementation NSControl (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
할 필요가 IBAction
때 할 .창조할 때 해야 할 일을 연관지으면 됩니다.
_button.actionBlock = ^(NSControl*thisButton){
[doc open]; [thisButton setEnabled:NO];
};
이 패턴은 코코아 API에 OVER와 OVER를 적용할 수 있습니다.속성을 사용하여 코드의 관련 부분을 더 가깝게 만들고, 복잡한 위임 패러다임을 제거하며, 멍청한 "컨테이너" 역할을 하는 것 이상의 개체의 힘을 활용할 수 있습니다.
물론 블록을 속성으로 사용할 수도 있습니다.그러나 @property(copy)로 선언되었는지 확인합니다.예:
typedef void(^TestBlock)(void);
@interface SecondViewController : UIViewController
@property (nonatomic, copy) TestBlock block;
@end
MRC에서 컨텍스트 변수를 캡처하는 블록은 스택에 할당되며, 스택 프레임이 파괴될 때 해제됩니다.이러한 블록이 복사되면 힙에 새 블록이 할당되며, 이 블록은 나중에 스택 프레임이 팝업된 후에 실행될 수 있습니다.
공시자
이 질문은 목표 C에 대해 명시적으로 질문하기 때문에 "좋은 답변"이 아닙니다.Apple이 WWDC14에서 Swift를 소개하면서 Swift에서 블록(또는 폐쇄)을 사용하는 다양한 방법을 공유하고자 합니다.
안녕, 스위프트
Swift의 기능에 해당하는 블록을 통과할 수 있는 여러 가지 방법이 있습니다.
3개 찾았어요.
이것을 이해하기 위해, 저는 여러분이 이 작은 코드 조각을 놀이터에서 테스트하는 것을 제안합니다.
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)
마감에 최적화된 Swift
Swift가 비동기식 개발에 최적화되어 있기 때문에, Apple은 폐쇄에 더 많은 노력을 기울였습니다.첫 번째는 함수 서명을 유추할 수 있기 때문에 다시 쓸 필요가 없다는 것입니다.
번호별 액세스 매개 변수
let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })
명명을 사용한 매개 변수 추론
let resultShortAnon2 = test({myParam in return "ANON_" + myParam + "__ANON" })
후행 마감
이 특수한 경우는 블록이 마지막 인수인 경우에만 작동하며, 이를 후행 폐쇄라고 합니다.
다음은 예입니다(Swift의 힘을 보여주기 위해 유추된 서명과 병합됨).
let resultTrailingClosure = test { return "TRAILCLOS_" + $0 + "__TRAILCLOS" }
마지막으로:
이 모든 힘을 사용하여 제가 할 일은 후행 폐쇄와 유형 추론을 혼합하는 것입니다(가독성을 위해 명명).
PFFacebookUtils.logInWithPermissions(permissions) {
user, error in
if (!user) {
println("Uh oh. The user cancelled the Facebook login.")
} else if (user.isNew) {
println("User signed up and logged in through Facebook!")
} else {
println("User logged in through Facebook!")
}
}
안녕, 스위프트
@Francescu가 대답한 것을 보완합니다.
추가 매개 변수 추가:
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)
아래 형식을 따를 수 있으며 다음을 사용할 수 있습니다.testingObjectiveCBlock
학급의 재산
typedef void (^testingObjectiveCBlock)(NSString *errorMsg);
@interface MyClass : NSObject
@property (nonatomic, strong) testingObjectiveCBlock testingObjectiveCBlock;
@end
자세한 내용은 여기를 참조하십시오.
언급URL : https://stackoverflow.com/questions/3935574/can-i-use-objective-c-blocks-as-properties
'programing' 카테고리의 다른 글
Eclipse 프로젝트에서 모든 Java 파일을 한 번에 포맷하는 방법은 무엇입니까? (0) | 2023.05.26 |
---|---|
버려진 Mongodb를 어떻게 수입합니까? (0) | 2023.05.26 |
Node.js에 파일/디렉토리가 있는지 동기화하여 확인 (0) | 2023.05.26 |
WPF를 배울 때 가장 이해하기 어려웠던 점은 무엇입니까? (0) | 2023.05.26 |
기본 키와 클러스터된 인덱스의 관계 (0) | 2023.05.26 |