Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Objective-C

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 20, средняя оценка - 4.80
IhorMihal
0 / 0 / 0
Регистрация: 03.01.2013
Сообщений: 9
#1

Как правильно вызвать -(void)setNeedsDisplay? - Objective-C

03.01.2013, 22:43. Просмотров 2680. Ответов 14
Метки нет (Все метки)

Здравствуйте, форумчане. Собственно начал изучать сей язык. Решил написать программку, которая рисует график функции по некоторому параметру. При этом отрисовка идет в классе Graph: UIView (он присвоен отдельной вьюшке)внутри метода drawRect. При этом в контроллере ViewController у меня текстовое поле для ввода и кнопка для передачи параметра в класс Graph.
Как мне обновить мой график при нажатии на кнопку?

Objective-C
1
2
3
4
5
- (IBAction)bSend:(id)sender {
    int input = [tfield.text intValue]; //Получаю с текстового поля и перевожу в int
    [Graph getInputValue:(int)input]; //Отправляю в класс graph
    //Хотелось бы здесь сразу вызвать setNeedsDisplay
}


Но только я выношу [self setNeedsDisplay] вне метода drawRect, как компилятор начинает ругаться. ((
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.01.2013, 22:43
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Как правильно вызвать -(void)setNeedsDisplay? (Objective-C):

Как вызвать функцию другого окна - Программирование iOS
Как вызвать функцию одного ВьюКонтроллера, в другом ВьюКонтроллере? Вопрос может быть глупым и банальным, но никак не могу разобраться. Я...

Как вызвать реакцию на нажатие кнопки? - Программирование iOS
Добрый день. Есть кнопка, текстовое поле и метка. Ожидается послее ввода текста и нажатия кнопки, текст появится в метке UIlabel. ...

Internal Void? как правильно аргумент преобразовать в int - C#
using System; using ConsoleApp2; using ConsoleApp2.Fifo; using System; using System.Collections.Generic; using System.Linq; ...

Как правильно заполнить массив из указателей типа void* - C (СИ)
Насколько я понимаю, его можно заполнить, только присваивая адреса элементам Как это реализовать, если данные вводятся с клавиатуры? ...

как правильно вызвать sub? - Visual Basic
Назрело несколько ворпросов об использовании sub'ов 1)как правильно вызвать sub,почему если я пишу Draw(Player, CountOBlocks, b(), C1)...

Как правильно вызвать JS - JavaScript
Здравствуйте. Есть код: <a class="btn btn-success waves-effect waves-light" href="javascript:;"...

14
zulkis
682 / 609 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
04.01.2013, 10:55 #2
Цитата Сообщение от IhorMihal Посмотреть сообщение
[Graph getInputValueint)input]; //Отправляю в класс graph
Если getSomething - то по идее он должен быть без аргумента, и метод должен возвращать что либо(геттер).

Цитата Сообщение от IhorMihal Посмотреть сообщение
Но только я выношу [self setNeedsDisplay] вне метода drawRect, как компилятор начинает ругаться. ((
А self у Вас какого типа?
Вероятно UIViewController. А Вам нужно перерисовать Ваш Graph. Ну вот его экземпляру и посылайте setNeedsDisplay.
1
IhorMihal
0 / 0 / 0
Регистрация: 03.01.2013
Сообщений: 9
04.01.2013, 21:39  [ТС] #3
Цитата Сообщение от IhorMihal Посмотреть сообщение
[Graph getInputValueint)input]; //Отправляю в класс graph
Не обращайте внимание на название - параметр передается хорошо - проверено. Проблема сделать обновление при нажатии кнопки bSend, которое вызывает метод displayUpdate

Признаю, пока для меня все это туго...
Вот мой класс Graph.m:

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "Graph.h"
 
@implementation Graph
int tvalue=1; //Значение по умолчанию
+(void)getInputValue:(int) temp {    //Получаем значение
    tvalue=temp;
}
+(int)sendInputValue {  //При вызове мотод отправляет значение обратно для вывода на экран (для проверки)
    return tvalue;
}
 - (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
    }
    return self;
}
 - (void)drawRect:(CGRect)rect
{
 CGContextRef context = UIGraphicsGetCurrentContext();
 CGContextClearRect(context, rect); 
 CGContextSetRGBStrokeColor (context, 255, 255, 255, 1);
 int y;
 for (int x=rect.origin.x; x<rect.size.width; x++)
 {   
 y = x*tvalue;     //Собственно пример моей функции
     if (x==0) CGContextMoveToPoint (context, x, y);
 else CGContextAddLineToPoint (context, x, y);
 }
 CGContextStrokePath (context);
    [self setNeedsDisplay];     // Здесь компилятору все нравится, но нет возможности обновления при нажатии на кнопку
}
/* +(void) displayUpdate {
 [self setNeedsDisplay];       //Здесь компилятор выдает: No known class method for selector 'setneedsdisplay'
} */
@end
0
zulkis
682 / 609 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
06.01.2013, 19:43 #4
Цитата Сообщение от IhorMihal Посмотреть сообщение
Не обращайте внимание на название - параметр передается хорошо - проверено
При чем тут "не обращайте внимание". У Вас написано семантически неверно - вот и все внимание.
Насчет кода: CTRL+I спасет положение. Форматирования нет совсем, что не есть хорошо.

Цитата Сообщение от IhorMihal Посмотреть сообщение
[self setNeedsDisplay];
в drawRect - это очень плохо. Это неверно в корне. Прочитайте для чего нужен данный метод в документации.


Цитата Сообщение от IhorMihal Посмотреть сообщение
+(void) displayUpdate {
*[self setNeedsDisplay]; * * * //Здесь компилятор выдает: No known class method for selector 'setneedsdisplay'
}
Вы написали статический метод. И посылается сообщение классу с итоге, а не экземпляру.
Напишите
Objective-C
1
2
3
- (void)displayUpdate {
    [self setNeedsDisplay]; 
}
и вызывайте его у экземпляра класса.
А лучше уберите этот ненужный метод и вызывайте
Objective-C
1
[_yourGraphView setNeedsDisplay];
1
IhorMihal
0 / 0 / 0
Регистрация: 03.01.2013
Сообщений: 9
07.01.2013, 17:25  [ТС] #5
Объявил экземпляр класса Graph. Ошибок в коде теперь нет. Но мой View не обновляется при вызове [myGraph setNeedsDisplay]. Может проблема в инициализации экземпляра myGraph класса Graph?

в ViewController.m:

Objective-C
1
2
3
4
5
6
- (IBAction)bSend:(id)sender {
    int input = [inputvalue.text intValue];
    MyCanvas* myGraph = [[MyCanvas alloc] init];
    [myGraph setParametr:(int) input];
    [myGraph setNeedsDisplay];
}
В Graph.h и Graph.m тоже нужно объявлять экземпляр myGraph?
И еще не совсем понятно (документацию прочел) назначение этого:
Objective-C
1
2
3
4
5
6
7
8
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
     //  Initialization code here
    }
    return self;
}
Что именно здесь нужно инициализировать? И нужно ли мне это делать в моем случае?
0
zulkis
682 / 609 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
08.01.2013, 11:36 #6
Каждый раз не нужно создавать новую view(Ваш MyCanvas).
И если Вы создали view, её же нужно отобразить(читай добавить на "экран")
Используйте -addSubview: метод

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@interface ViewController() {
   MyCanvas *myGraph;
}
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad {
   [super viewDidLoad];
   myGraph = [[MyCanvas alloc] init];
   [self.view addSubview:myGraph];
}
 
- (IBAction)bSend:(id)sender {
    int input = [inputvalue.text intValue];
    [myGraph setParametr:(int) input];
    [myGraph setNeedsDisplay];
}
 
@end
Как то так.
0
IhorMihal
0 / 0 / 0
Регистрация: 03.01.2013
Сообщений: 9
09.01.2013, 04:18  [ТС] #7
Все равно вьюшка не обновляется . Надеялся, что ошибка в передаче параметра. Проверил всевозможными способами - мой график обновляется только при первой загрузке... [myGraph setNeedsDisplay] ничего не делает
0
mobidevelop
182 / 182 / 3
Регистрация: 10.01.2013
Сообщений: 596
10.01.2013, 21:12 #8
Я бы начал отладку с того, что поставил в drawRect: break point или NSLog и посмотрел вызывается ли этот метод после нажатия на кнопку, а заодно и значение tvalue. Уж больно оно хитро меняется - через метод класса, а не экземпляра. Это точно так надо или Вы просто разницы между ними не видите?
0
IhorMihal
0 / 0 / 0
Регистрация: 03.01.2013
Сообщений: 9
10.01.2013, 22:48  [ТС] #9
У меня все методы теперь от экземпляра. Выполнения drawRect по нажатии на кнопку не происходит. Только при запуске....
0
mobidevelop
182 / 182 / 3
Регистрация: 10.01.2013
Сообщений: 596
10.01.2013, 22:53 #10
Последний вариант кода можно увидеть? И не только реализацию, но и заголовок этого класса.
0
IhorMihal
0 / 0 / 0
Регистрация: 03.01.2013
Сообщений: 9
11.01.2013, 03:14  [ТС] #11
Цитата Сообщение от mobidevelop Посмотреть сообщение
Последний вариант кода можно увидеть? И не только реализацию, но и заголовок этого класса.
ViewController.h:
Objective-C
1
2
3
4
5
6
7
8
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
    {
        IBOutlet UITextField *inputvalue;
        IBOutlet UILabel *outputvalue;
    }
- (IBAction)sendInputvalue:(id)sender;
@end
ViewController.m:
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "ViewController.h"
#import "MyCanvas.h"
 
@interface ViewController () {
 MyCanvas* myGraph;
}
@end
 
@implementation ViewController
 
int input;
- (void)viewDidLoad
{
    [super viewDidLoad];
    myGraph = [[MyCanvas alloc] init];
    [self.view addSubview:myGraph];    
}
 
- (IBAction)sendInputvalue:(id)sender {
    input = [inputvalue.text intValue];
    [myGraph setParametr:(int) input];
    [myGraph setNeedsDisplay];
    int output = [myGraph getParametr];
    outputvalue.text = [NSString stringWithFormat:@"%d",output];
}
 
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
    inputvalue = nil;
    outputvalue = nil;
    [super viewDidUnload];
}
@end
MyCanvas.h:
Objective-C
1
2
3
4
5
6
7
#import <UIKit/UIKit.h>
 
@interface MyCanvas : UIView
 
- (void) setParametr:(int)input;
- (int) getParametr;
@end
MyCanvas.m:
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "MyCanvas.h"
 
@implementation MyCanvas
 
int parametr=0;
 
-(void) setParametr:(int)input {
    parametr=input;
}
 
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {       
    }
    return self;
}
- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, rect);
    
    CGContextSetRGBStrokeColor (context, 255, 255, 255, 1);
    int y;
    for (int x=rect.origin.x; x<rect.size.width; x++)
    {
        y = x*parametr;
        if (x==0) CGContextMoveToPoint (context, x, y);
        else CGContextAddLineToPoint (context, x, y);
    }
    CGContextStrokePath (context);
}
-(int) getParametr {
    return parametr;
}
@end
0
mobidevelop
182 / 182 / 3
Регистрация: 10.01.2013
Сообщений: 596
11.01.2013, 12:12 #12
1. ViewController.m, строка 15:
Objective-C
1
myGraph = [[MyCanvas alloc] initWithFrame:self.view.bounds];
2. MyCanvas.m, строка 25:
Objective-C
1
for (int x=rect.origin.x; x<rect.origin.x+rect.size.width; x++)
width - это не правая координата прямоугольника, а его ширина. Разница существенная, если левая координата не нулевая.
А в 23-й строке цвет задается белый. Поэтому саму вьюху лучше бы для уверенности в черный перекрасить. Сразу после создания вставить:
Objective-C
1
myGraph.backgroundColor = [UIColor blackColor];
Попробуйте - должно получиться.
0
IhorMihal
0 / 0 / 0
Регистрация: 03.01.2013
Сообщений: 9
11.01.2013, 18:40  [ТС] #13
Цитата Сообщение от mobidevelop Посмотреть сообщение
1. ViewController.m, строка 15:
Код Objective-C
Objective-C
1
myGraph = [[MyCanvas alloc] initWithFrame:self.view.bounds];
Теперь вью моего графика занимает весь экран... Как сделать такой же размер как и view в IB, которому назначен класс MyCanvas?
0
mobidevelop
182 / 182 / 3
Регистрация: 10.01.2013
Сообщений: 596
11.01.2013, 18:55 #14
А! Теперь проблема понятна. Ручное создание этой вьюхи вообще убрать надо. Надо создать в контроллере проперть с модификатором IBOutlet типа MyCanvas и прицепить к ней вью, созданную в IB.
Objective-C
1
@property (nonatomic, strong) IBOutlet MyCanvas* myGraph;
Тогда все начнет перерисовываться
1
IhorMihal
0 / 0 / 0
Регистрация: 03.01.2013
Сообщений: 9
11.01.2013, 19:39  [ТС] #15
Цитата Сообщение от mobidevelop Посмотреть сообщение
Objective-C
1
@property (nonatomic, strong) IBOutlet MyCanvas* myGraph;
Ааа! Вот это оно! К контроллеру забыл привязать! Не знаю, сколько еще сам бы думал. Спасибо!
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.01.2013, 19:39
Привет! Вот еще темы с ответами:

Как правильно вызвать EnumDisplayDevices? - Assembler
Здравствуйте, подскажите, как мне вызвать правильно EnumDisplayDevices Пробую как в коде, который мне скомпилировала Visual Studio, но...

Как правильно вызвать функцию? - C (СИ)
как вызвать функцию? int sum_last(list_ptr a) { list_ptr ptr; assert(NULL != a); assert(NULL != a-&gt;next); for (ptr = a;...

Как правильно вызвать объект - C++ Builder
Доброго времени суток, такое дело создаю свою функцию и из неё вызвать Label, но выходит ошибка. Вот так, но это стандарт всё работает...

Как правильно вызвать процедуру? - Pascal
как правильно вызвать данную процедуру? procedure n1(i:integer; A:T1); begin for I := 1 to 3 do begin if...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
11.01.2013, 19:39
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru