0

I want to create a pickerView programmatically and have it use it's own version of a method like pickerView:numberOfRowsInComponent.

I create the instance at runtime like this:

UIPickerView *myPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 200, 320, 200)];
myPickerView.delegate = self;
myPickerView.dataSource = self;
myPickerView.showsSelectionIndicator = YES;
[self.view addSubview:myPickerView];

The standard method called would be:

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    NSUInteger numRows = 5;
    return numRows;
}    

What I want to do is replace this standard method with another method for this instance only.

-(NSInteger)xxxpickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{ // special method for this instance only
    return 1;
}

I've been able to use method swizzle to do this with other things, but I can't seem to get it to work with UIPickerView.

@implementation UIPickerView (Tracking)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        SEL originalSelector =   @selector(pickerView:numberOfRowsInComponent:);
        SEL swizzledSelector = @selector(xxxpickerView:numberOfRowsInComponent:);

      Method originalMethod = class_getInstanceMethod(class, originalSelector);
      Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
      BOOL didAddMethod =
      class_addMethod(class,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));

      if (didAddMethod) {
          class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
      } else {
          method_exchangeImplementations(originalMethod, swizzledMethod);
      }

  });

}

I've listed the methods to see if the 2nd method was added to the instance during runtime and it is in the list.

However, the 2nd method doesn't run, the 1st method does run.

Here's a link to the post that got me started on this, and I've confirmed it works, but I seem to be missing something about this. http://nshipster.com/method-swizzling/

I'm open to other suggestions, the problem I'm trying to solve is that I want to create the instance of a UIPickerView object that won't be dependent on another instance that will be running at the same time. So I want a different method that will work only with the one instance and completely ignore any other instances that might be running and I want to do this programmatically.

At lest one reason for not using a tag/switch, is that I don't know what the conditions will be until runtime.

I don't know why swizzle would work with one object and not another, and I'm open to other way to replace stock methods with others at runtime.

Is there something about the method I'm trying to replace that won't allow it to be replaced?

EDIT: in order to try and make the question clear, the following code in the link works. It swaps one method for another method. What I need to do is the same thing for another object and I can't figure out what it works for 1 object and not another.

This works for another object: http://nshipster.com/method-swizzling/

Here's another link as well: http://blog.newrelic.com/2014/04/16/right-way-to-swizzle/

4

1 回答 1

0

一种简单的方法是在属性中保留指针的副本,然后比较数据源/委托方法中的指针。

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if ( pickerView == self.myPickerView )
        return 1;   // response for this particular picker view
    else
        return 5;   // standard response
}
于 2015-03-01T09:30:26.167 回答