আমি কি বৈশিষ্ট্য হিসাবে অবজেক্টিভ-সি ব্লক ব্যবহার করতে পারি?


321

স্ট্যান্ডার্ড প্রোপার্টি সিনট্যাক্স ব্যবহার করে সম্পত্তি হিসাবে ব্লক থাকা কি সম্ভব?

এআরসি-র জন্য কি কোনও পরিবর্তন আছে ?


1
ঠিক আছে, কারণ এটি খুব কার্যকর হবে। যতক্ষণ না আমার সিনট্যাক্সটি সঠিক থাকে এবং এটি কোনও এনএসবজেক্টের মতো আচরণ করে ততক্ষণ এটি কী তা আমার জানতে হবে না।
গুড়গেট

5
এটি কী তা আপনি যদি না জানেন তবে কীভাবে আপনি জানেন যে এটি খুব সহজ হবে?
স্টিফেন ক্যানন

5
আপনার সেগুলি ব্যবহার করা উচিত নয় তবে আপনি কী তা জানেন না :)
রিচার্ড জে রস তৃতীয়

5
@ মোশিকে এখানে কিছু কারণ মনে পড়ছে। সম্পূর্ণ প্রতিনিধি শ্রেণীর চেয়ে ব্লকগুলি কার্যকর করা সহজ, ব্লকগুলি হালকা ওজনের এবং আপনার ব্লকের প্রসঙ্গে থাকা ভেরিয়েবলগুলির অ্যাক্সেস রয়েছে। ইভেন্ট কলব্যাকগুলি কার্যকরভাবে ব্লকগুলি ব্যবহার করে করা যেতে পারে (কোকোস 2 ডি সেগুলি প্রায় একচেটিয়াভাবে ব্যবহার করে)।
রিচার্ড জে রস তৃতীয়

2
সম্পূর্ণ সম্পর্কিত নয়, তবে যেহেতু কিছু মন্তব্য "কুরুচিপূর্ণ" ব্লক সিনট্যাক্স সম্পর্কে অভিযোগ করে, তাই এখানে একটি দুর্দান্ত নিবন্ধ যা প্রথম নীতিগুলি থেকে সিনট্যাক্সটি পেয়েছে: নিলসো.com
paulrehkugler

উত্তর:


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

আপনি যদি একই জায়গায় একই স্থানে বিভিন্ন জায়গায় পুনরাবৃত্তি করতে চান তবে একটি টাইপ ডিএফ ব্যবহার করুন

typedef void(^MyCompletionBlock)(BOOL success, NSError *error);
@property (nonatomic) MyCompletionBlock completion;

3
এক্সকোড ৪.৪ বা আরও নতুন দিয়ে আপনাকে সংশ্লেষিত করতে হবে না। এটি আরও সংক্ষিপ্ত করে তুলবে। অ্যাপল ডক
এরিক

বাহ, আমি জানি না, ধন্যবাদ! ... যদিও আমি প্রায়শই করি@synthesize myProp = _myProp
রবার্ট

7
@Robert: আপনি কারণ নির্বাণ ছাড়া আবার ভাগ্য হয়, @synthesizeডিফল্ট কি করছ হয় @synthesize name = _name; stackoverflow.com/a/12119360/1052616
এরিক

1
@ চর্লিমনরো - হ্যাঁ আপনি সম্ভবত সঠিক, তবে এআরসি ছাড়াই ব্লক সম্পত্তি বাতিল বা প্রকাশের জন্য আপনার কোনও ডিলোক বাস্তবায়ন প্রয়োজন? (আমি নন-এআরসি ব্যবহার করার পরে এটির কিছুক্ষণ হয়ে গেছে)
রবার্ট

1
@ আইক্যাপ্টর: হ্যাঁ, আপনি যদি এটি কোনও ডায়ালকে ছেড়ে না দেন তবে মেমরি ফাঁস হতে পারে - ঠিক যেমন অন্য কোনও ভেরিয়েবলের মতো।
চার্লি মনরো

210

আপনি কীভাবে এই ধরনের কাজটি সম্পাদন করবেন তার উদাহরণ এখানে:

#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 সম্পাদনা করুন:

এআরসি-র জন্য, কোনও নির্দিষ্ট পরিবর্তন প্রয়োজন নেই, কারণ এআরসি আপনার জন্য ব্লকগুলি যতক্ষণ না অনুলিপি হিসাবে সংজ্ঞায়িত করা হয় ততক্ষণ পরিচালনা করে। আপনার নিজের ডেস্টস্ট্রাক্টরের জন্য সম্পত্তি বিলোপ করার দরকার নেই either

আরও পড়ার জন্য, দয়া করে এই দস্তাবেজটি দেখুন: http://clang.llvm.org/docs/ AutomaticReferencesCounting.html


158

সুইফ্টের জন্য, কেবল ক্লোজার ব্যবহার করুন: উদাহরণস্বরূপ।


উদ্দেশ্য-সি:

@ প্রপার্টি (অনুলিপি) বাতিল

@property (copy)void (^doStuff)(void);

এটা খুব সহজ।

এখানে আসল অ্যাপল ডকুমেন্টেশন রয়েছে, যা সঠিকভাবে কী ব্যবহার করতে হবে তা উল্লেখ করেছে:

অ্যাপল ডকো

আপনার .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+) সিস্টেমের সাথে এখানে যা দেখানো হয়েছে তা করুন। এটা যে সহজ।


হয়তো আপনারও বলা উচিত, এখন (2016) এর strongপরিবর্তে এটি ব্যবহার করা ঠিক আছে copy?
নিক কোভ

সম্পত্তি ব্যাখ্যা দিয়ে কেন nonatomicঅন্যান্য বেশিরভাগ ক্ষেত্রে সম্পত্তি সেরা পদ্ধতির থেকে পৃথক হওয়া উচিত তা আপনি ব্যাখ্যা করতে পারেন ?
অ্যালেক্স প্রেটজ্লাভ

অ্যাপল থেকে ওয়ার্কউইথব্লকস html "আপনার সম্পত্তিটির বৈশিষ্ট্য হিসাবে অনুলিপি নির্দিষ্ট করা উচিত, কারণ ..."
ফ্যাটি

20

উত্তরোত্তর / সম্পূর্ণতার জন্য ... এই হাস্যকরভাবে বহুমুখী "কাজ করার পদ্ধতি" কীভাবে বাস্তবায়ন করা যায় তার দুটি সম্পূর্ণ উদাহরণ এখানে রয়েছে। @ রবার্টের উত্তর সুখী সংক্ষিপ্ত এবং সঠিক, তবে এখানে আমি ব্লকগুলিকে আসলে "সংজ্ঞায়িত" করার উপায়গুলিও দেখাতে চাই।

@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

এটি অ্যাক্সেসরের মাধ্যমে ব্লক সম্পত্তি নির্ধারণের (উদাহরণস্বরূপ, একটি বিতর্কিত ধরণের অভ্যাস ..) এর বিপরীতে প্রথম উদাহরণটির "ননোটমিক" "গেটেটর" প্রক্রিয়া বনাম চিত্রিত করে। উভয় ক্ষেত্রেই ... "হার্ডকোডযুক্ত" প্রয়োগগুলি সর্বদা উদাহরণস্বরূপ , ওভাররাইট করা যেতে পারে .. একটি 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]; 
};

এই প্যাটার্নটি কোকো এপিআই এর ওভার এবং ওভার প্রয়োগ করা যেতে পারে । আপনার কোডের প্রাসঙ্গিক অংশগুলি একত্রে আনতে , সংশ্লেষিত প্রতিনিধি দৃষ্টান্তগুলি দূর করতে এবং কেবল বোবা "পাত্রে" হিসাবে অভিনয় করার পরে অবজেক্টগুলির শক্তি উত্তোলনের জন্য বৈশিষ্ট্যগুলি ব্যবহার করুন।


অ্যালেক্স, দুর্দান্ত সহযোগী উদাহরণ। আপনি জানেন, আমি ননোটমিক সম্পর্কে ভাবছি। থটস?
ফ্যাটি

2
এটি খুব বিরল যে কোনও সম্পত্তির জন্য "পারমাণবিক" হ'ল সঠিক জিনিস। এক থ্রেডে কোনও ব্লক সম্পত্তি সেট করা এবং একই সাথে অন্য থ্রেডে পড়া বা একাধিক থ্রেড থেকে একসাথে ব্লক সম্পত্তি সেট করা খুব আশ্চর্যের বিষয় হবে । সুতরাং "পরমাণু" বনাম "ননোটমিক" এর ব্যয় আপনাকে কোনও আসল সুবিধা দেয় না।
gnasher729

8

অবশ্যই আপনি সম্পত্তি হিসাবে ব্লক ব্যবহার করতে পারেন। তবে নিশ্চিত হয়ে নিন যে সেগুলি @ প্রপার্টি (অনুলিপি) হিসাবে ঘোষিত হয়েছে । উদাহরণ স্বরূপ:

typedef void(^TestBlock)(void);

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

এমআরসি-তে, প্রসঙ্গের ভেরিয়েবলগুলি ক্যাপচারকারী ব্লকগুলি স্ট্যাকের মধ্যে বরাদ্দ করা হয় ; স্ট্যাক ফ্রেম নষ্ট হয়ে গেলে এগুলি মুক্তি দেওয়া হবে। যদি সেগুলি অনুলিপি করা হয় তবে একটি নতুন ব্লককে গাদা পরিমাণে বরাদ্দ দেওয়া হবে , যা স্ট্যাক ফ্রেমটি পপ করার পরে পরে কার্যকর করা যেতে পারে।


যথাযথভাবে। আপনার অনুলিপি এবং অন্য কিছুই ব্যবহার করা উচিত না কেন এটি সম্পর্কে আসল অ্যাপল ডকো। বিকাশকারী.অ্যাপল.
com

7

Disclamer

এটি "ভাল উত্তর" হওয়ার উদ্দেশ্যে নয়, কারণ এই প্রশ্নটি স্পষ্টভাবে ObjectiveC এর জন্য জিজ্ঞাসা করে। অ্যাপল যেমন ডাব্লুডাব্লুডিসি 14-এ সুইফট চালু করেছিল, আমি সুইফটে ব্লক (বা ক্লোজার) ব্যবহারের বিভিন্ন উপায় ভাগ করতে চাই।

হ্যালো, সুইফ্ট

আপনার কাছে সুইফটে ফাংশনের সমতুল্য একটি ব্লক পাস করার অফার রয়েছে।

আমি তিনটি পেয়েছি।

এটি বুঝতে আমি আপনাকে কোডের এই সামান্য অংশের খেলার মাঠে পরীক্ষা করার পরামর্শ দিচ্ছি।

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)

সুইফ্ট, ক্লোজারগুলির জন্য অনুকূলিত

সুইচ অ্যাসিক্রোনাস বিকাশের জন্য অনুকূলিত হওয়ায় অ্যাপল ক্লোজারে আরও কাজ করেছে। প্রথমটি হ'ল ফাংশনের স্বাক্ষরটি অনুমান করা যায় যাতে আপনার এটি পুনরায় লিখতে হবে না।

সংখ্যা দ্বারা প্যারাম অ্যাক্সেস

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

নামকরণের সাথে প্যারাম অনুমিতি

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

ট্রেলিং বন্ধ

এই বিশেষ কেসটি কেবল তখনই কাজ করে যদি ব্লকটি সর্বশেষ যুক্তি হয়, তাকে বলা হয় ট্রেলিং বন্ধ

এখানে একটি উদাহরণ রয়েছে (সুইফ্ট শক্তি দেখানোর জন্য অনুমিত স্বাক্ষরের সাথে একীভূত)

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

0

হ্যালো, সুইফ্ট

@ ফ্রান্সস্কু কী উত্তর দিয়েছে তা পরিপূরণ করছে।

অতিরিক্ত পরামিতি যুক্ত করা হচ্ছে:

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)

-3

আপনি নীচের ফর্ম্যাটটি অনুসরণ করতে পারেন testingObjectiveCBlockএবং শ্রেণিতে সম্পত্তি ব্যবহার করতে পারেন ।

typedef void (^testingObjectiveCBlock)(NSString *errorMsg);

@interface MyClass : NSObject
@property (nonatomic, strong) testingObjectiveCBlock testingObjectiveCBlock;
@end

আরও তথ্যের জন্য এখানে দেখুন


2
এই উত্তরটি ইতিমধ্যে সরবরাহ করা অন্যান্য উত্তরগুলিতে কি আরও কিছু যুক্ত করে?
রিচার্ড জে রস তৃতীয়
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.