Вопрос

Можно ли использовать блоки в качестве свойств, используя стандартный синтаксис свойств?

Есть ли какие-либо изменения для АРК?

Это было полезно?

Решение

@property (nonatomic, copy) void (^simpleBlock)(void);
@property (nonatomic, copy) BOOL (^blockWithParamter)(NSString *input);

Если вы будете повторять один и тот же блок в нескольких местах, используйте тип DEF

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;
}

Теперь единственное, что нужно будет изменить, если вам понадобится изменить тип сравнения, это typedef int (^IntBlock)().Если вам нужно передать ему два объекта, измените его на следующее: typedef int (^IntBlock)(id, id), и измените свой блок на:

^ (id obj1, id obj2)
{
    return rand();
};

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ 12 марта 2012 г.:

Для ARC не требуется никаких особых изменений, поскольку ARC будет управлять блоками за вас, пока они определены как копии.Вам также не нужно устанавливать свойство в ноль в своем деструкторе.

Для получения дополнительной информации, пожалуйста, ознакомьтесь с этим документом:http://clang.llvm.org/docs/AutomaticReferenceCounting.html

Для Swift просто используйте замыкание: пример.


В объекте-с,

@Property (Copy) пустота (^ восстановление) (пустота);

Это так просто.

Документация Apple, полностью объясняющая эту проблему:

Apple Doco.

В вашем файле .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+) систем, сделайте то, что здесь показано. Это так просто. Надеюсь, это поможет кому-то. Счастливого Рождества 2013!

Ради потомства / полноты ... вот два полных примера того, как промежуточно реализовать этот смехотворный универсальный «способ делать вещи». @ Ответ Роберта блаженно кратко и правильно, но здесь я хочу также показать способы на самом деле «определить» блоки.

@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

Это иллюстрирует установку свойства блока через Accessior (хотя и внутри инициативы, спортивную практику Dicey.) Вс. «Нетомический« нетомический »« нетомический »механизм« DITTER ». В любом случае ... «Харкодированные» реализации всегда могут быть перезаписаны, за экземпляр.. lá ..

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 какао. Используйте свойства, чтобы принести соответствующие части вашего кода ближе, ликвидировать Безумированные делегические парадигмы, и используйте силу объектов за пределы того, что просто действуют как глупые «контейнеры».

Конечно, вы можете использовать блоки как свойства. Но убедитесь, что они объявлены как @Property (копия). Отказ Например:

typedef void(^TestBlock)(void);

@interface SecondViewController : UIViewController
@property (nonatomic, copy) TestBlock block;
@end

В MRC, переменные контекста блоков выделены в куча; Они будут выпущены, когда рама стека уничтожена. Если они скопированы, новый блок будет выделен в куча, который может быть выполнен позже после заполнения кадра стека.

Раскрывать

Это не предназначено для того, чтобы быть «хорошим ответом», так как этот вопрос задают явно для Objectivec. Когда Apple представила SWIFT на WWDC14, я хотел бы поделиться различными способами использования блока (или закрытий) в SWIFT.

Здравствуйте, Swift

У вас есть много способов передавать блок эквиваленту для функции в SWIFT.

Я нашел три.

Чтобы понять это, я предлагаю вам проверить в детской площадке этот маленький кусок кода.

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 оптимизирован для асинхронного развития, Apple работала больше на замыканиях. Первый в том, что подпись функции может быть выведена, поэтому вам не нужно переписать ее.

Доступ к параметрам по номерам

let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })

Парный вывод с именами

let resultShortAnon2 = test({myParam in return "ANON_" + myParam + "__ANON" })

Трейлинг замыкает

Этот специальный корпус работает только в том случае, если блок является последним аргументом, он называется Трейлинг замыкает

Вот пример (объединенный с предполагаемой подписью, чтобы показать Swift Power)

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!")
    }
}

Здравствуйте, Swift

Дополняя, что ответил @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

Для получения дополнительной информации посмотреть здесь

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top