Frage

I have a (NSObject) Block *my_block with a UIView *main_view as property. On the ViewController I add a UIPanGestureRecognizer to the main_view, so the gesture method must be on the ViewController. Is there already a way to know the my_block owner of the specific main_view from the gesture method?

This is because I have a NSMutableArray of Block. The Blocks are added to the NSMutableArray on runtime.

My first idea was a loop through the NSMutableArray comparing each main_view to the UIView of the recognizer. Another idea was to subclass the UIView and create a reference to its respective Block. But maybe there is a cleaner way to do it.

Here is a simple example of my classes and methods.

Block.h

#import <Foundation/Foundation.h>

@interface Block : NSObject

@property (nonatomic, strong) UIView *main_view;

@end

ViewController.m

#import "ViewController.h"
#import "Block.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // the Blocks are actually added on runtime to a NSMutableArray, but this is a simpler example

    Block *my_block = [[Block alloc] init];
    [[my_block main_view] addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]];
    [self.view addSubview:[my_block main_view]];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    Block *block_temp = [recognizer.view ....];
    //recognizer.view = main_view, how to get the Block owner of this view?
}
War es hilfreich?

Lösung

Have you Block classes be the target for your gesture recogniser:

Block.h

@interface Block : NSObject

@property (nonatomic, strong) UIView *main_view;

@end

Block.m

@implementation Block

-(void)handleMainViewPan:(UIPanGestureRecognizer *)recognizer
{
    // Now recognizer.view is the same view as self.main_view
    // Use self as this is now your block
}

@end

ViewController.m

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // the Blocks are actually added on runtime to a NSMutableArray, but this is a simpler example

    Block *my_block = [[Block alloc] init];
    UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:my_block action:@selector(handleMainViewPan:)];
    [my_block.main_view addGestureRecognizer:gestureRecognizer];
    [self.view addSubview:my_block.main_view];
}

@end

Andere Tipps

Instead of subclassing UIView you can also use functions:

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
id objc_getAssociatedObject(id object, const void *key)

From docs

Sets an associated value for a given object using a given key and association policy.

Good article http://nshipster.com/associated-objects/

If you already have blocks in array (I believe that array is a property in ViewController) you can find block with one for loop.

Example:

// self.blocks is NSMutableArray where blocks are stored

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    Block *owner = nil;
    for (block in self.blocks) {
        if (block.main_view == recognizer.view) {
            owner = block;
            break;
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top