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

Objective-C

Войти
Регистрация
Восстановить пароль
 
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
#1

Хранение WEAK объектов в массиве - Objective-C

26.05.2014, 14:07. Просмотров 950. Ответов 17
Метки нет (Все метки)

Иногда возникает ситуация хранить в массиве просто указатели на объекты, таким образом, чтобы счетчик их ссылок при таком хранении не увеличивался, и они удалялись самостоятельно.

При самопроизвольном удалении естественно в массиве вместо объекта должен лежать nil.

Итак класс который позволяет хранить вот такие weak ссылки.

@interface
Objective-C
1
2
3
4
5
6
7
@interface NSWeakObject : NSObject
 
+(instancetype) newWithObj: (id) obj;
 
@property (weak,nonatomic) id weakObject;
 
@end
@implementation
Objective-C
1
2
3
4
5
6
7
8
9
@implementation NSWeakObject
 
+(instancetype)newWithObj:(id)obj {
    NSWeakObject *value = [NSWeakObject new];
    value.weakObject = obj;
    return value;
}
 
@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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
int cu_random(int min, int max) {
    return ((arc4random() % (max-min+1)) + min);
}
 
#pragma mark -
 
@interface ViewController ()
 
@property NSMutableArray * data;
 
@property NSNumber * number1;
@property NSNumber * number2;
 
@end
 
#pragma mark -
 
@implementation ViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    _data = [NSMutableArray new];
}
 
 
-(void)dealloc {
    _data = nil;
    _number1 = nil;
    _number2 = nil;
}
 
 
- (IBAction)btn_create:(id)sender {
    
    NSLog(@">> btn_create <<");
    
    _number1 = @( cu_random(0, 99) );
    _number2 = @( cu_random(0, 99) );
    
    [_data addObject: [NSWeakObject newWithObj:_number1]];
    [_data addObject: [NSWeakObject newWithObj:_number2]];
}
 
- (IBAction)btn_show:(id)sender {
    NSLog(@">> btn_show <<");
    int i = 0;
    for (NSWeakObject * obj in _data) {
        NSLog(@"Object %d is : %@", i, obj.weakObject);
        i++;
    }
}
- (IBAction)btn_clear:(id)sender {
    NSLog(@">> btn_clear <<");
    _number1 = nil;
    _number2 = nil;
}
@end
Ответ консоли
2014-05-26 13:58:52.780 testWeak[2993:90b] >> btn_create <<
2014-05-26 13:58:54.236 testWeak[2993:90b] >> btn_show <<
2014-05-26 13:58:54.236 testWeak[2993:90b] Object 0 is : 97
2014-05-26 13:58:54.237 testWeak[2993:90b] Object 1 is : 34
2014-05-26 13:58:56.252 testWeak[2993:90b] >> btn_clear <<
2014-05-26 13:58:58.172 testWeak[2993:90b] >> btn_show <<
2014-05-26 13:58:58.172 testWeak[2993:90b] Object 0 is : (null)
2014-05-26 13:58:58.172 testWeak[2993:90b] Object 1 is : (null)
Видно что после нажатия на кнопку btn_clear ARC удалил объекты.

При этом в массиве остались лежать экземпляры NSWeakObject, только они стали ссылаться на NIL.

То есть если объект был уничтожен то можно безболезненно проверить (NSWeakObject.weakObject == NIL) и работать дальше без каких либо ошибок памяти.
Вложения
Тип файла: zip testWeak.zip (31.8 Кб, 10 просмотров)
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Pro2005
44 / 44 / 3
Регистрация: 27.05.2013
Сообщений: 163
26.05.2014, 18:49     Хранение WEAK объектов в массиве #2
Собственно, а зачем это ? Если не сложно объясните чайнику... Что я выиграю или в чем проиграю. В какой ситуации можно/нужно применять ваш код ?
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
26.05.2014, 19:51  [ТС]     Хранение WEAK объектов в массиве #3
Трудно вспомнить. Несколько раз я это "нечто" применял. Но однако уже потом находился способ который позволял сделать тоже самое но без NSWeakObject.

Но это не отменяет того что такая ситуация может возникнуть. И если она возникнет NSWeakObject с ней успешно справится.

Что я выиграю или в чем проиграю. В какой ситуации можно/нужно применять ваш код ?
Выбор за вами.

Можно провести аналогию с NSValue

И если NSValue хранит простые типы
То NSWeakObject хранит указатели, счетчик которых не увеличивается.
zulkis
681 / 608 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
26.05.2014, 20:48     Хранение WEAK объектов в массиве #4
Цитата Сообщение от Pro2005 Посмотреть сообщение
Собственно, а зачем это ? Если не сложно объясните чайнику...
Вот вы знаете, я себя не считаю гуру, но чайником тоже не считаю. Но вопрос у меня почему-то такой же.
Какой-то ненужный фантик над конфеткой.
Называется "прочитай одну статью" про управление памятью, и не нужно такие выдумки использовать...
Pro2005
44 / 44 / 3
Регистрация: 27.05.2013
Сообщений: 163
26.05.2014, 22:30     Хранение WEAK объектов в массиве #5
Цитата Сообщение от noname_club Посмотреть сообщение
То NSWeakObject хранит указатели, счетчик которых не увеличивается.
Ок... если мы просто создали объект и сохранили только адрес на него. При этом мы не увеличиваем retainCount. ARC - просто удалит объект из памяти, т.к вы просто храните указатель на него. В итоге... в итоге мы храним - нечего. Т.к нет не какой гарантии что объект еще "жив". И тут как мне кажется могут начаться проблемы.
Это мой взгляд на ваше решение.
+ NSValue... в нем же есть метод valueWithNonretainedObject
Почему не юзать его ? В чем ваше решение лучше ? Не пойму зачем, если есть возможность - объясните...
glvrzzz
95 / 71 / 12
Регистрация: 12.12.2012
Сообщений: 214
27.05.2014, 07:08     Хранение WEAK объектов в массиве #6
+1 к NSValue, еще есть [NSPointerArray weakObjectsPointerArray]
Посему я буду третьим, кто задаст вопрос: зачем это?
zulkis
681 / 608 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
27.05.2014, 07:56     Хранение WEAK объектов в массиве #7
Pro2005, не хочу никого обидеть, но у noname_club очень большая тяга к написанию велосипедов. Эти мелкие споры уже несколько месяцев продолжаются...
Цитата Сообщение от Pro2005 Посмотреть сообщение
Ок... если мы просто создали объект и сохранили только адрес на него. При этом мы не увеличиваем retainCount. ARC - просто удалит объект из памяти, т.к вы просто храните указатель на него.
Кстати вот тут вы правы абсолютно. Да и пример его работает потому лишь только, что strong это спецификатор @property по умолчанию.

И еще:
Цитата Сообщение от noname_club Посмотреть сообщение
Трудно вспомнить.
Это не классный ответ на вопрос зачем вы вообще пост написали...
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
27.05.2014, 12:11  [ТС]     Хранение WEAK объектов в массиве #8
Это мой взгляд на ваше решение.
+ NSValue... в нем же есть метод valueWithNonretainedObject
Почему не юзать его ? В чем ваше решение лучше ? Не пойму зачем, если есть возможность - объясните...
Вот она задача. С которой не справляется valueWithNonretainedObject зато справляется NSWeakObject

Итак имеем следующий код

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
- (IBAction)btn_create:(id)sender {
    
    NSLog(@">> btn_create <<");
    
    _number1 = @( cu_random(0, 99) );
    _number2 = @( cu_random(0, 99) );
    
    [_data addObject: [NSValue valueWithNonretainedObject:_number1]];
    [_data addObject: [NSValue valueWithNonretainedObject:_number2]];
}
 
- (IBAction)btn_show:(id)sender {
    NSLog(@">> btn_show <<");
    int i = 0;
 
    for (NSValue * obj in _data) {
        NSLog(@"Object %d is : %@", i, obj.nonretainedObjectValue);
        i++;
    }
}
- (IBAction)btn_clear:(id)sender {
    NSLog(@">> btn_clear <<");
    _number1 = nil;
    _number2 = nil;
}
@end
Ответ консоли

2014-05-27 11:59:59.710 testWeak[304:90b] >> btn_create <<
2014-05-27 12:00:02.398 testWeak[304:90b] >> btn_show <<
2014-05-27 12:00:02.398 testWeak[304:90b] Object 0 is : 61
2014-05-27 12:00:02.399 testWeak[304:90b] Object 1 is : 19
2014-05-27 12:00:04.262 testWeak[304:90b] >> btn_clear <<
2014-05-27 12:00:05.790 testWeak[304:90b] >> btn_show <<
далее падение
Хранение WEAK объектов в массиве

Выводы?
NSWeakObject может быть использован в качестве более безопасной альтернативы [NSValue valueWithNonretainedObject]

Так как если объект самоуничтожился. То в NSWeakObject будет лежать nil. В отличии от зомби указателя в NSValue.
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
27.05.2014, 12:25  [ТС]     Хранение WEAK объектов в массиве #9
Да и пример его работает потому лишь только, что strong это спецификатор @property по умолчанию.
Еще скажи, что пример работает потому что компилятор LLVM стоит по-умолчанию.

Сравнение абсолютно не корректное. Если бы даже strong не был по-умолчанию то он был бы выставлен вручную. Просто в этом нет необходимости.

Добавлено через 7 минут
+1 к NSValue, еще есть [NSPointerArray weakObjectsPointerArray]
Посему я буду третьим, кто задаст вопрос: зачем это?
что то мне подсказывает что там тоже будут зомби лежать если объект самоудалится? я прав?
glvrzzz
95 / 71 / 12
Регистрация: 12.12.2012
Сообщений: 214
27.05.2014, 13:39     Хранение WEAK объектов в массиве #10
Цитата Сообщение от noname_club Посмотреть сообщение
что то мне подсказывает что там тоже будут зомби лежать если объект самоудалится? я прав?
Нет, будет лежать NULL. На то оно и weak, в отличие от того же NSValue, который просто nonretained.
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
27.05.2014, 13:53  [ТС]     Хранение WEAK объектов в массиве #11
Возможно NSPointerArray это и есть стандартное решение в данной ситуации

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#import "ViewController.h"
 
int cu_random(int min, int max) {
    return ((arc4random() % (max-min+1)) + min);
}
 
#pragma mark -
 
@interface ViewController ()
 
@property NSMutableArray * data;
 
@property NSPointerArray * data2;
 
@property NSNumber * number1;
@property NSNumber * number2;
 
@end
 
#pragma mark -
 
@implementation ViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //_data = [NSMutableArray new];
    
    _data2 = [NSPointerArray weakObjectsPointerArray];
 
}
 
 
-(void)dealloc {
    //_data = nil;
    _data2 = nil;
    _number1 = nil;
    _number2 = nil;
}
 
 
- (IBAction)btn_create:(id)sender {
    
    NSLog(@">> btn_create <<");
    
    _number1 = @( cu_random(0, 99) );
    _number2 = @( cu_random(0, 99) );
    
    [_data2 addPointer:(__bridge void *)(_number1)];
    [_data2 addPointer:(__bridge void *)(_number2)];
    
 
}
 
- (IBAction)btn_show:(id)sender {
    NSLog(@">> btn_show <<");
    int i = 0;
    
    for (id obj in _data2) {
        NSLog(@"Object %d is : %@", i, obj);
    }
}
- (IBAction)btn_clear:(id)sender {
    NSLog(@">> btn_clear <<");
    _number1 = nil;
    _number2 = nil;
}
@end
Ответ консоли

2014-05-27 13:44:55.443 testWeak[952:90b] >> btn_create <<
2014-05-27 13:44:56.275 testWeak[952:90b] >> btn_show <<
2014-05-27 13:44:56.275 testWeak[952:90b] Object 0 is : 27
2014-05-27 13:44:56.275 testWeak[952:90b] Object 0 is : 98
2014-05-27 13:44:57.715 testWeak[952:90b] >> btn_clear <<
2014-05-27 13:44:58.563 testWeak[952:90b] >> btn_show <<
2014-05-27 13:44:58.563 testWeak[952:90b] Object 0 is : (null)
2014-05-27 13:44:58.564 testWeak[952:90b] Object 0 is : (null)
Однако NSValue более гибкое, так как NSPointerArray подразумевает что все объекты в нем weak, а NSValue может лежать в обычном массиве.

Итог: NSWeakObject может быть использован только как замена [NSValue valueWithNonretainedObject] .
zulkis
681 / 608 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
27.05.2014, 14:03     Хранение WEAK объектов в массиве #12
noname_club, кстати, не стоит называть свои классы с системными префиксами.
Цитата Сообщение от noname_club Посмотреть сообщение
Однако NSValue более гибкое, так как NSPointerArray подразумевает что все объекты в нем weak, а NSValue может лежать в обычном массиве.
Итог: NSWeakObject может быть использован только как замена [NSValue valueWithNonretainedObject] .
Все так, вы молодец.
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
27.05.2014, 14:22  [ТС]     Хранение WEAK объектов в массиве #13
noname_club, кстати, не стоит называть свои классы с системными префиксами.
Префикс NS сообщает что это системный объект
Однако Xcode подсвечивает бледным цветом , а не ярко синим.

В итоге :

NS + бледный цвет = пользовательский системный класс

Сравнение:

Хранение WEAK объектов в массиве

Все выше сказанное ИМХО.
zulkis
681 / 608 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
27.05.2014, 14:27     Хранение WEAK объектов в массиве #14
noname_club, префикс NS сообщает, что это NextStep, откуда и пошло все то, чем вы сейчас пользуетесь.
А цвета можно изменить тремя кликами в настройках IDE. А можно писать в блокноте.

Поэтому:
Цитата Сообщение от zulkis Посмотреть сообщение
не стоит называть свои классы с системными префиксами.
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
27.05.2014, 14:30  [ТС]     Хранение WEAK объектов в массиве #15
Хорошо, может лучше использовать 2 уровневый префикс?

NONAME_CLUBNSWeakObject

?
zulkis
681 / 608 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
27.05.2014, 14:33     Хранение WEAK объектов в массиве #16
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от noname_club Посмотреть сообщение
Хорошо, может лучше использовать 2 уровневый префикс?
NNC|NC|WeakObject-а вполне достаточно.
Документация говорит, что лучше использовать 3 буквы, ибо 2 могут быть использованы силами Apple. И возникнет конфликт.
noname_club
102 / 90 / 9
Регистрация: 01.05.2013
Сообщений: 583
27.05.2014, 14:35  [ТС]     Хранение WEAK объектов в массиве #17
Документация говорит, что лучше использовать 3 буквы, ибо 2 могут быть использованы силами Apple
3 буквы не слишком "сладко". лучше пока 2, после захвата APPLE всех 2 букв перейду на 3.

А какже великий AFNetworking, SDWebImage ?

у них 2 буквы! сжечь их!
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.05.2014, 14:42     Хранение WEAK объектов в массиве
Еще ссылки по теме:
C# DataGridView и хранение объектов
C++ Хранение объектов в векторе
C# Хранение списка объектов в памяти
Хранение в list объектов класса C++
Хранение объектов - что оптимальнее? C++

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

Или воспользуйтесь поиском по форуму:
zulkis
681 / 608 / 38
Регистрация: 13.01.2011
Сообщений: 1,724
27.05.2014, 14:42     Хранение WEAK объектов в массиве #18
Цитата Сообщение от noname_club Посмотреть сообщение
у них 2 буквы! сжечь их!
Не нужно никого жечь. Я тоже чаще всего 2 использую. Как вы заметили,
3 буквы не слишком "сладко"
AF это поклон в сторону NS из Apple Foundation, по словам разработчика.
SD без понятия.
Yandex
Объявления
27.05.2014, 14:42     Хранение WEAK объектов в массиве
Ответ Создать тему
Опции темы

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