Как получить уведомление об отмене выбора на UILabel

У меня есть UILabel, и мне нужно, чтобы он поддерживал копирование и вставку (на самом деле только копирование, поскольку оно доступно только для чтения). Я создал подкласс UILabel для поддержки копирования, и он отлично работает. Я также добавил выделение текста, чтобы пользователь знал, что именно он копирует, когда нажимает на ярлык.

Моя проблема в том, что я не знаю, как отменить это выделение, когда пользователь щелкает где-то еще. Пузырь с копией исчезает, но я не получаю обратного вызова, поэтому текст остается выделенным. Есть ли специальный обратный вызов, который я пропустил, который я могу использовать, или мне нужно придумать какой-то грязный хак? Или, возможно, есть более стандартный способ выделения текста в UILabel, о котором я не знаю, который будет обрабатываться автоматически, как пузырь копирования?

Вот мой пользовательский код UILabel:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if(action == @selector(copy:)) {
        return YES;
    }
    else {
        return [super canPerformAction:action withSender:sender];
    }
}

- (BOOL)becomeFirstResponder {
    if([super becomeFirstResponder]) {
        self.highlighted = YES; 

        UIMenuController *menu = [UIMenuController sharedMenuController];
        [menu setTargetRect:self.bounds inView:self];
        [menu setMenuVisible:YES animated:YES];

        return YES;
    }
    return NO;
}

- (BOOL)resignFirstResponder {
    if([super resignFirstResponder]) {
        self.highlighted = NO;

        UIMenuController *menu = [UIMenuController sharedMenuController];
        [menu setMenuVisible:NO animated:YES];
        [menu update];

        return true;
    }
    return false;
}

- (void)copy:(id)sender {
    UIPasteboard *board = [UIPasteboard generalPasteboard];
    [board setString:self.text];
    self.highlighted = NO;
    [self resignFirstResponder];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if([self isFirstResponder]) {
        //UIMenuController *menu = [UIMenuController sharedMenuController];
        //[menu setMenuVisible:NO animated:YES];
        //[menu update];
        [self resignFirstResponder];
    }
    else if([self becomeFirstResponder]) {
        //UIMenuController *menu = [UIMenuController sharedMenuController];
        //[menu setTargetRect:self.bounds inView:self];
        //[menu setMenuVisible:YES animated:YES];
    }
}

- (void)setHighlighted:(BOOL)hl {
    [super setHighlighted:hl];

    [self setNeedsLayout];
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    if(self.highlighted) {
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSetRGBFillColor(ctx, 0.3, 0.8, 1.0, 0.3);
        CGContextAddRect(ctx, CGRectMake(0, 0, [self textRectForBounds:self.frame limitedToNumberOfLines:1].size.width, self.frame.size.height));
        CGContextFillPath(ctx);
    }
}

Любая помощь приветствуется!


person Lope    schedule 08.10.2010    source источник


Ответы (1)


Лично я бы использовал UITextView с возможностью редактирования, установленной на NO.

в противном случае, если вы хотите больше контроля, создайте подкласс вашего самого верхнего полноэкранного представления (или окна), дочерним элементом которого является ваш UILabel.

переопределить - (UIView *) hitTest: (CGPoint) точка withEvent: (UIEvent *) событие;

и если представление попадания не является вашим UILabel, создайте NSNotification, которое вы обрабатываете в своем подклассе UILabel, и отмените выбор.

Кстати, вы должны ВСЕГДА обрабатывать touchesCanceled также!

person Nick H247    schedule 11.10.2010
comment
Спасибо за советы. Я думаю, что была причина, по которой я не использовал UITextView, но я не помню, что это было. Я проверю. Я не знал о методе hittest, я тоже попробую его. Что касается touchesCancel, я полагаю, что в большинстве случаев можно просто делать то же самое, что и в touchesEnded, верно? - person Lope; 12.10.2010
comment
да, я думаю, что просто копия touchesEnded должна быть в порядке. - person Nick H247; 12.10.2010
comment
хорошо, переопределение hitTest помогло. Теперь все работает, как и ожидалось. Огромное спасибо! Я многому научился благодаря этому :) Кстати, я, вероятно, не использовал UITextView, потому что он менее настраиваемый в конструкторе интерфейса, чем UILabel (шрифт, цвет фона...) - person Lope; 12.10.2010
comment
тем не менее, вы можете легко установить все это программно! Но рад быть полезным. - person Nick H247; 12.10.2010