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

Objective-C

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.70
spens
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 7
#1

Вызов объекта в keyDown - Objective-C

16.05.2013, 13:43. Просмотров 1236. Ответов 14
Метки нет (Все метки)

являясь новичком в обжекте встал в ступор в ситуации, когда у меня есть класс, в нем инициализируется объект и в нем же оверрайдится keyDown:


View.h
Objective-C
1
2
3
4
5
6
7
@interface View : NSView
 
@property (strong, nonatomic) NSString *string;
 
- (id)init;
 
@end

View.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
@implementation View
 
@synthesize string;
 
- (id)init
{
self = [super init];
   if (self)
   {
       string = @"string";
   }
   return self;
}
 
- (void)keyDown:(NSEvent *)event
{
    if ([event keyCode] == 125)
    {
       NSLog(@"%@", string);
    }
}
 
@end

AppDelegate.m
Objective-C
1
2
3
4
5
6
7
8
@implementation AppDelegate
 
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    View *v = [[View alloc] init];
}
 
@end
и по нажатию кнопки я получаю null
нутром чую что пытаюсь вызвать неинициализириованную переменную совсем по другому адресу нежели [v string], но как сделать что бы заработало пока понять не могу.

подымите мне веки, пожалуйста.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
mobidevelop
16.05.2013, 14:31
  #2

Не по теме:

Здесь была глупость, вызванная невнимательностью. А как удалить сообщение не нашел...

spens
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 7
16.05.2013, 16:52  [ТС]     Вызов объекта в keyDown #3
ну вопрос решился убиванием @property (strong, nonatomic) NSString *string;
прописыванием NSString *string = nil; до вызова init

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
@implementation View
 
NSString *string = nil;
 
- (id)init
{
self = [super init];
   if (self)
   {
       string = @"string";
   }
   return self;
}
 
- (void)keyDown:(NSEvent *)event
{
    if ([event keyCode] == 125)
    {
       NSLog(@"%@", string);
    }
}
 
@end
отсюда глупый вопрос:

получается в таком раскладе все вызовы string обращаются к единому указателю заданному глобально,
но почему при использовании @property методы обращались к разным указателям?
Vorona
Peace 2 all shining faces
666 / 528 / 44
Регистрация: 05.03.2010
Сообщений: 1,271
16.05.2013, 20:30     Вызов объекта в keyDown #4
Цитата Сообщение от spens Посмотреть сообщение
@implementation View
NSString *string = nil;
- (id)init
что это за подход?

верните все, как было в первом посте, только к свойству нужно обращаться с помощью указателя self

т.е вместо string, будет self.string

т.к. @property это не просто переменная, а набор методов мутаторов и аксессоров (get/set), потому вызывая self.string вы вызываете аксессор метод данного инстанса, на который указывает self
spens
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 7
16.05.2013, 20:36  [ТС]     Вызов объекта в keyDown #5
Цитата Сообщение от Vorona Посмотреть сообщение
что это за подход?

верните все, как было в первом посте, только к свойству нужно обращаться с помощью указателя self

т.е вместо string, будет self.string

т.к. @property это не просто переменная, а набор методов мутаторов и аксессоров (get/set), потому вызывая self.string вы вызываете аксессор метод данного инстанса, на который указывает self
попробовал

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@synthesize string;
 
- (id)init
{
    self = [super init];
    if (self)
    {
        string = @"test";
    }
    return self;
}
 
- (void)keyDown:(NSEvent *)theEvent
{
    if ([theEvent keyCode] == 125)
    {
        NSLog(@"%@", self.string);
    }
}
по нажатию кнопки опять имею null
mobidevelop
182 / 182 / 3
Регистрация: 10.01.2013
Сообщений: 596
16.05.2013, 20:38     Вызов объекта в keyDown #6
В 9-й строке еще бы self. приписать...
spens
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 7
16.05.2013, 20:53  [ТС]     Вызов объекта в keyDown #7
Цитата Сообщение от mobidevelop Посмотреть сообщение
В 9-й строке еще бы self. приписать...
все равно null

Добавлено через 7 минут
я логически это вижу так:

keyDown принадлежит View который привязан к окну в интерфейс билдере и получается что инициализируется раньше чем проходит инициализация string и поэтому обращается еще к пустому указателю

Добавлено через 1 минуту
хотя тогда не понятно почему конструкция без @property инициализирует все нормально и все обращения идут по одному адресу
Vorona
Peace 2 all shining faces
666 / 528 / 44
Регистрация: 05.03.2010
Сообщений: 1,271
16.05.2013, 20:57     Вызов объекта в keyDown #8
рабочий код
Objective-C
1
2
3
4
5
@interface View : NSView
 
@property (strong, nonatomic) NSString *string;
 
@end
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
@implementation View
 
@synthesize string;
 
- (id)init
{
   self = [super init];
   if (self)
   {
       self.string = @"string";
   }
   return self;
}
 
- (void)keyDown:(NSEvent *)event
{
    if ([event keyCode] == 125)
    {
       NSLog(@"%@", self.string);
    }
}
 
@end
Цитата Сообщение от spens Посмотреть сообщение
хотя тогда не понятно почему конструкция без @property инициализирует все нормально и все обращения идут по одному адресу
все объявления переменных\свойств должны происходить в рамках конструкции @interface /* ... */ @end
объявление внутри @implementation полная фигня и вообще забудьте о таком варианте

дерзайте
spens
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 7
16.05.2013, 21:05  [ТС]     Вызов объекта в keyDown #9
копипаста
не работает

Objective-C
1
2
3
4
5
6
7
#import <Cocoa/Cocoa.h>
 
@interface View : NSView
 
@property (strong, nonatomic) NSString *string;
 
@end
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
#import "View.h"
 
@implementation View
 
@synthesize string;
 
- (id)init
{
    self = [super init];
    if (self)
    {
        self.string = @"string";
    }
    return self;
}
 
- (void)keyDown:(NSEvent *)event
{
    if ([event keyCode] == 125)
    {
        NSLog(@"%@", self.string);
    }
}
 
- (BOOL)acceptsFirstResponder
{
    return YES;
}
 
- (BOOL)becomeFirstResponder
{
    return YES;
}
 
@end
Vorona
Peace 2 all shining faces
666 / 528 / 44
Регистрация: 05.03.2010
Сообщений: 1,271
16.05.2013, 21:05     Вызов объекта в keyDown #10
Цитата Сообщение от spens Посмотреть сообщение
keyDown принадлежит View который привязан к окну в интерфейс билдере и получается что инициализируется раньше чем проходит инициализация string и поэтому обращается еще к пустому указателю
используйте метод awakeFromNib

думал, что вы View создаете методом инит
вообще, если вам что-то кажется, поставьте брейкпоинт на init и посмотрите или дебаггер вообще остановиться на этом методе, тогда будете хотя бы знать вызвался он или нет
spens
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 7
16.05.2013, 23:40  [ТС]     Вызов объекта в keyDown #11
чорт точно

Objective-C
1
2
3
4
- (void)awakeFromNib
{
    self.string = @"string";
}
и все работает

спасибо!

Добавлено через 2 часа 23 минуты
что-то я снова затупил.

с последним вариантом работает, пока я не вызываю этот объект через другой метод.

View.m

добавляю
Objective-C
1
2
3
4
- (void)say
{
    NSLog(@"%@", self.string);
}
и в аппделегат

Objective-C
1
2
3
4
5
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    View *v = [[View alloc] init];
    [v say];
}
по нажатию кнопки все ок, а вызов через экземпляр класса снова null
Vorona
Peace 2 all shining faces
666 / 528 / 44
Регистрация: 05.03.2010
Сообщений: 1,271
17.05.2013, 02:55     Вызов объекта в keyDown #12
ну так теперь же вы создаете View с помощью метода init
т.е. чтобы сейчас в лог вывелось значение, нужно в методе init его присвоить

а вот если вы View просто привяжете к элементу в интерфейсбилдере и руками нигде не будете его инитить, то лучше делать инициализацию переменных членов класса в awakeFromNib, в этот момент все элементы ниб файла приконекчены и инициализированы, потому этот вариант более "безопасный", чем initWithCoder или initWithFrame, где некоторые IBOutlet переменные в ниб файле могут все еще равняться nil на данном этапе, а вы получите головную боль от неясности

подытожим:
в awakeFromNib вы делаете инициализацию, когда вьюшка создана в интерфейс билдере, а не с помощью initXXX методов
в initXXX методах вы делаете инициализацию, когда создаете вьюшку руками при помощи initXXX методов и руками кладете ее на основную вьюху или что там еще

Добавлено через 31 минуту
и вообще, я надеюсь вы понимаете, что View, которую вы создаете в интрефейс билдере и вью, которую вы создаете с помощью init метода в аппделегате, это две разные вью и между собой никак не связаны?
(вплане два разных инстанса одного и того же класса)
spens
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 7
17.05.2013, 12:05  [ТС]     Вызов объекта в keyDown #13
Цитата Сообщение от Vorona Посмотреть сообщение
ну так теперь же вы создаете View с помощью метода init
т.е. чтобы сейчас в лог вывелось значение, нужно в методе init его присвоить

а вот если вы View просто привяжете к элементу в интерфейсбилдере и руками нигде не будете его инитить, то лучше делать инициализацию переменных членов класса в awakeFromNib, в этот момент все элементы ниб файла приконекчены и инициализированы, потому этот вариант более "безопасный", чем initWithCoder или initWithFrame, где некоторые IBOutlet переменные в ниб файле могут все еще равняться nil на данном этапе, а вы получите головную боль от неясности

подытожим:
в awakeFromNib вы делаете инициализацию, когда вьюшка создана в интерфейс билдере, а не с помощью initXXX методов
в initXXX методах вы делаете инициализацию, когда создаете вьюшку руками при помощи initXXX методов и руками кладете ее на основную вьюху или что там еще

Добавлено через 31 минуту
и вообще, я надеюсь вы понимаете, что View, которую вы создаете в интрефейс билдере и вью, которую вы создаете с помощью init метода в аппделегате, это две разные вью и между собой никак не связаны?
(вплане два разных инстанса одного и того же класса)
да, понимаю что это разные экземпляры создаются, просто не понимаю путь как решить что бы переменная была доступна и так и так причем одна ее версия

все работает когда initWithFrame и awakeFromNib вместе

View.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
@synthesize string;
 
- (void)awakeFromNib
{
    self.string = @"string";
}
 
- (id)initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    if (self)
    {      
        self.string = @"string";
    }
    return self;
}
 
- (void)say
{
    NSLog(@"%@", self.string);
    NSLog(@"%p", self.string);
}
 
- (void)keyDown:(NSEvent *)event
{
    if ([event keyCode] == 125)
    {
        NSLog(@"%@", self.string);
        NSLog(@"%p", self.string);
    }
}
AppDelegate.m

Objective-C
1
2
3
4
5
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    View *v = [[View alloc] initWithFrame:[[self window] frame]];
    [v say];
}
обращение идет к одному адресу и на первый взгляд все хорошо

но ведь это же костыль и криворукость?

Добавлено через 7 минут
или все таки это нормально?

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (void)awakeFromNib
{
    self.string = @"string";
}
 
- (id)init
{
    self = [super init];
    if (self)
    {      
        [self awakeFromNib];
    }
    return self;
}
zulkis
681 / 608 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
17.05.2013, 13:00     Вызов объекта в keyDown #14
Цитата Сообщение от spens Посмотреть сообщение
да, понимаю что это разные экземпляры создаются, просто не понимаю путь как решить что бы переменная была доступна и так и так причем одна ее версия
static Вам в помощь. И в геттере проверку на существование указателя.

Если я правильно понял проблему...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.05.2013, 21:34     Вызов объекта в keyDown
Еще ссылки по теме:

Не получается связать два объекта Objective-C
C# Бесконечный вызов KeyDown для формы
Вызов блока с переменными параметрами Objective-C
Вызов метода базового класса, если он был переопределён в наследнике Objective-C
Вызов функции после некоторого времени Objective-C

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

Или воспользуйтесь поиском по форуму:
Vorona
Peace 2 all shining faces
666 / 528 / 44
Регистрация: 05.03.2010
Сообщений: 1,271
17.05.2013, 21:34     Вызов объекта в keyDown #15
напишите метод для инициализации обычных переменных
Objective-C
1
2
3
4
5
- (void)initializeLocalVariables
{
    self.string = @"string";
    // ...
}
так же можно написать initializeUIElements для инициализации юайных элементов, чтобы разделить одни от других

и вызывайте его и там и там, избежите копипаста и разложите все по разным методам, по сути, - обычная процедура выделения метода
Yandex
Объявления
17.05.2013, 21:34     Вызов объекта в keyDown
Ответ Создать тему
Опции темы

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