drawRect не отвечает на setNeedsDisplay (mcve)

Я знаю, что этот вопрос задавался много раз, но я нашел частичное решение.

У меня есть пользовательский класс GraphView, в котором у меня есть несколько ползунков, которые изменяют параметры графика и инициируют перерисовку с помощью [self setNeedsDisplay]. Единственный способ заставить setNeedsDisplay работать — это иметь представление типа GraphView под контроллером представления и ползунок под (и внутри) GraphView (в иерархии раскадровки). Это проблематично, так как ползунок должен находиться внутри графика.

Вот интерфейс mcve @:

#import <UIKit/UIKit.h>

@interface GraphView : UIView
@property float red;
@property   __weak IBOutlet UITextField *redout;
@property   UIBezierPath *aPath;
@property   CGPoint aPoint;
- (void)drawRect:(CGRect)rect;
- (id)  initWithFrame:(CGRect)frameRect;
- (IBAction)red_rabi:(id)sender;

Вот реализация mcve @:

#import "GraphView.h"

@implementation GraphView

- (id)  initWithFrame:(CGRect)frameRect
{
    if ((self = [super initWithFrame:frameRect]) != nil)
    {
        _red=1.0;
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    int i;
    NSString *redstr;
    float width, height;
    width = rect.size.width;
    height = rect.size.height;
    _aPath =[UIBezierPath bezierPathWithRect:rect] ;
    [_aPath setLineWidth:1.0];
    _aPoint.x=0.0;
    _aPoint.y=0.0;
    [_aPath moveToPoint:_aPoint];
    redstr = [NSString localizedStringWithFormat:@"%6.2f", _red];
    for (i=1;i<400;i++)
{
        _aPoint.x=i*width/400.0;
        _aPoint.y=height-height*(sin(i*_red/30.)+1.0)/2.0;
        [_aPath addLineToPoint:_aPoint];
}
        [_aPath stroke];
}


- (IBAction)red_rabi:(id)sender
{
    NSString *redstr;
    UISlider *slider = (UISlider *)sender;
    _red= slider.value;
    redstr = [NSString localizedStringWithFormat:@"%6.2f", _red];
    _redout.text = redstr;
    [self setNeedsDisplay];
}

@end

Если вы разместите общий вид прямо под контроллером Вида (который я не трогал), измените класс общего вида на GraphView и поместите ползунок и текстовое поле внутри GraphView (подключив их к розетке и действию), это приложение создаст несколько циклов синусоидальной волны с частотой, контролируемой ползунком, и ее значением, отображаемым в текстовом поле.

Если вы хотите, чтобы слайдер и текстовое поле были в другом представлении, необходимо использовать охватывающее представление для всех трех элементов (GraphView, slider, text), и нельзя подключить слайдер и текстовое поле к GraphView с помощью Ctrl_drag к GraphView.H файл. Чтобы исправить это, я разместил универсальный объект на самом высоком уровне и переименовал его в GraphView — я мог бы затем подключить ползунок и текстовое поле. Хотя текстовое поле читается правильно, ползунок не обновляет GraphView.

Кстати, по сути, тот же код с GraphView и слайдером в отдельных видах отлично работает в OS X.

Извините за длину этого запроса и спасибо!

1 ответ

  1. Проблема решена! Благодаря интересному посту SO трехлетней давности (о подключении к подвидам UIView), я обнаружил, что один просто тянет (не Ctrl_drag!) от действия или выходного круга (в .H файл)к элементу управления и все. Отлично работает, даже если элементы управления находятся в другом представлении из подкласса UIView. Работает одинаково хорошо как с розетками, так и с действиями, хотя вы всегда оттягиваете от круга.

    Спасибо всем за их помощь.