Как насчет хранения в массиве или словаре

екте Cocoa Touch мне нужен определенный класс, чтобы иметь не только один объект делегата, но и многие из них.

Похоже, я должен создать NSArray для этих делегатов; проблема в том, что NSArray сохранит все эти делегаты, чего не должно (по соглашению объекты не должны сохранять своих делегатов).

Должен ли я написать свой собственный класс массива, чтобы предотвратить сохранение или есть более простые методы? Спасибо!

 dave16 июл. 2016 г., 20:13
совершенно действующее требование
 Mike Abdullah14 янв. 2011 г., 17:40
Вы почти наверняка не хотите этого делать. Обычно в такой ситуации ваш код должен транслироватьсяNSNotificationЭто то, на что подписывается несколько объектов (делегатов в вашем вопросе).
 wh1t3cat1k16 янв. 2011 г., 21:23
Майк, боюсь, я хочу - по соображениям контроля и безопасности. Я хочу знать, какие вещи прикреплены к моему делегату.
 leviathan06 июн. 2013 г., 10:18
Я бы посоветовал не бороться со структурой и использовать NSPointerArray с NSPointerFunctionsWeakMemory NSPointerFunctionOption

Ответы на вопрос(10)

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

Целевое действие: для элементов управления пользовательского интерфейса, таких как нажатия кнопок. Один отправитель, ноль или более получателей.Делегаты: дляодин отправитель иодин только получатель.Уведомление: Дляодин отправитель иноль или больше приемников.КВО: Более мелкозернистые, что уведомления.

Что вы должны сделать, это посмотреть, как использоватьNSNotificationCenter класс. Это правильный способ отправки уведомления, в котором имеется более одного получателя.

 matt24 нояб. 2011 г., 00:57
Тем не менее, естьнаходятся ситуации, в которых полезен набор не удерживаемых объектов.
 Oded Ben Dov01 июн. 2011 г., 17:01
Хотя это и не тот ответ, который искал оригинальный автор, мне нужен был кто-то, чтобы выложить его и иметь несколько восклицательных знаков, чтобы убедиться, что я слушаю…
 PeyloW07 дек. 2011 г., 20:51
@matt -, для редких и редких случаевNSHashMap в Mac OS X, или может выпасть доCFDictionary на iOS и Mac OS X.
Решение Вопроса

к кому его приписать).

Это довольно изобретательно, используя Категорию, чтобы разрешить создание изменяемого массива, который не сохраняет / освобождает, поддерживая егоCFArray с правильными обратными вызовами.

@implementation NSMutableArray (WeakReferences)
    + (id)mutableArrayUsingWeakReferences {
    return [self mutableArrayUsingWeakReferencesWithCapacity:0];
    }

    + (id)mutableArrayUsingWeakReferencesWithCapacity:(NSUInteger)capacity {
    CFArrayCallBacks callbacks = {0, NULL, NULL, CFCopyDescription, CFEqual};
    // We create a weak reference array
    return (id)(CFArrayCreateMutable(0, capacity, &callbacks));
    }
@end

РЕДАКТИРОВАТЬ Нашел оригинальную статью:http://ofcodeandmen.poltras.com

 Paul Berg16 янв. 2017 г., 20:16
Только что протестировал в iOS 10. Я не верю, что он больше работает, добавляемый элемент - это строка вроде «iphoneos10.1». Хотя очень странно.
 Slipp D. Thompson26 июл. 2018 г., 14:09
В качестве альтернативы просто используйтеCFArrayCreateMutable(…) в вашем клиентском коде, используя его какNSMutableArray (например.[(NSMutableArray *)myCFArray addObject:aDelegate] или просто[(id)myCFArray addObject:aDelegate]), Это работает, потому чтоNSMutableArray «бесплатный мост соединен сCFMutableArrayRef, Больше информации вСтатья для разработчиков Apple по бесплатному мостовому соединению.
 Thomas Tempelmann12 нояб. 2012 г., 22:19
На самом деле, я добавил ответ об этом к аналогичному вопросу, смотрите здесь:stackoverflow.com/a/13351665/43615
 Thomas Tempelmann12 нояб. 2012 г., 22:02
Как и в случае с предложением использовать временные объекты NSValue для хранения слабых ссылок, я считаю, что это решение не будет хранить истинные слабые ссылки, для которых будет установлено значение ноль, если целевой объект будет освобожден. Это только мое подозрение - поправьте меня, если я ошибаюсь. Самым безопасным способом по-прежнему может быть определение собственного вспомогательного объекта со слабым свойством и сохранение этого вспомогательного объекта в коллекции (массив, словарь, набор), как это предлагается в комментарии к использованию NSArray.

наряду с объяснением и улучшением.

Джонф предложил использовать[NSValue valueWithNonretainedObject:].

Обратите внимание, что когда вы делаете это, ваша ссылка действуетне любить__weak, а скорее как__unsafe_unretained находясь внутри объекта NSValue. Более конкретно, когда вы пытаетесь вернуть свою ссылку (используя [myNSValue nonretainedObjectValue]), ваше приложение будет аварийно завершать работу с сигналом EXC_BAD_ACCESS, если объект был освобожден до этого времени!

Другими словами, слабая ссылка автоматически не устанавливается на ноль, когда внутриNSValue объект. Мне понадобилось несколько часов, чтобы понять. Я работал над этим, создавая простой класс со слабым свойством ref.

Более красиво, используяNSProxyмы можем полностью обработать объект-обертку так, как если бы он сам содержал объект!

// WeakRef.h
@interface WeakRef : NSProxy

@property (weak) id ref;
- (id)initWithObject:(id)object;

@end


// WeakRef.m
@implementation WeakRef

- (id)initWithObject:(id)object
{
    self.ref = object;
    return self;
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
    invocation.target = self.ref;
    [invocation invoke];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    return [self.ref methodSignatureForSelector:sel];
}

@end
 Slipp D. Thompson26 июл. 2018 г., 14:24
Примечание: для лучшей производительности сNSProxys, вы должны реализовать- (id)forwardingTargetForSelector:(SEL)aSelector в дополнении к- forwardInvocation: (Я знаю я знаю,-forwardingTargetForSelector: ни вNSProxy ниNSObject-protocol, но среда выполнения Obj-C использует его в любом случае дляNSProxy-subclasses), Также время выполнения проверит- (BOOL)respondsToSelector:(SEL)aSelector (и иногда- (BOOL)conformsToProtocol:(Protocol *)aProtocol) во-первых, так что вам придется реализовать их тоже для использования- forwardingTargetForSelector, Но разница в скорости стоит того!
 walkingbrad28 июл. 2014 г., 04:18
Святое дерьмо ... УДИВИТЕЛЬНЫЙ! Спасибо! NSProxy выглядит весело играть.

Я бы предложил не бороться с рамками и использоватьNSPointerArray сNSPointerFunctionsWeakMemory NSPointerFunctionOption нравится:

NSPointerArray *weakReferencingArray = [NSPointerArray pointerArrayWithOptions:NSPointerFunctionsWeakMemory];

// NSPointerFunctionsWeakMemory - Uses weak read and write barriers 
// appropriate for ARC or GC. Using NSPointerFunctionsWeakMemory 
// object references will turn to NULL on last release.

Хорошо послужил мне в сценариях, где я должен был создать массив делегатов, который ссылается на auto-NULL.

Как насчет хранения в массиве или словаре

__weak typeof(pointer) weakPointer = pointer;

XMPPFramewrok

В проекте есть решение для многоадресного делегата.

https://github.com/robbiehanson/XMPPFramework/wiki/MulticastDelegate

NSHashTableИщите в документации.

 Slipp D. Thompson26 июл. 2018 г., 14:15
Черт возьми, я не знаю, как я не знал (забыл?) Об этом. Больше нужно сказать об этой находке класса. Из документов Apple:Хеш-таблица моделируется после NSSet со следующими отличиями: 1.Он может содержать слабые ссылки на своих членов. 2. Его члены могут быть скопированы на вход или могут использовать идентичность указателя для равенства и хеширования. 3. Он может содержать произвольные указатели (его члены не обязательно должны быть объектами). TL; DR: это «правильный» ответ - тот, который использует встроенный класс NSFoundation, специально разработанный NeXT / Apple для решения вашей проблемы.

надеюсь, это поможет ...

NSMutableArray* TTCreateNonRetainingArray() {
  CFArrayCallBacks callbacks = kCFTypeArrayCallBacks;
  callbacks.retain = TTRetainNoOp;
  callbacks.release = TTReleaseNoOp;
  return (NSMutableArray*)CFArrayCreateMutable(nil, 0, &callbacks);
}


NSMutableDictionary* TTCreateNonRetainingDictionary() {
  CFDictionaryKeyCallBacks keyCallbacks = kCFTypeDictionaryKeyCallBacks;
  CFDictionaryValueCallBacks callbacks = kCFTypeDictionaryValueCallBacks;
  callbacks.retain = TTRetainNoOp;
  callbacks.release = TTReleaseNoOp;
  return (NSMutableDictionary*)CFDictionaryCreateMutable(nil, 0, &keyCallbacks, &callbacks);
}

NSMutableArray* NICreateNonRetainingMutableArray(void) {
  return (NSMutableArray *)CFArrayCreateMutable(nil, 0, nil);
}

NSMutableDictionary* NICreateNonRetainingMutableDictionary(void) {
  return (NSMutableDictionary *)CFDictionaryCreateMutable(nil, 0, nil, nil);
}

NSMutableSet* NICreateNonRetainingMutableSet(void) {
  return (NSMutableSet *)CFSetCreateMutable(nil, 0, nil);
}

Этот метод полезен для предотвращения сохранения объекта при его добавлении в объект коллекции (например, экземпляр NSArray или NSDictionary).

 codrut29 апр. 2013 г., 14:03
@ Тимо ваш комментарий нуждается в большей наглядности. опубликуйте это как ответ
 Timo12 июл. 2012 г., 12:17
Обратите внимание, что когда вы делаете это, ваша ссылка действует НЕ как __weak, а скорее как __unsafe_unretained в объекте NSValue. Более конкретно, когда вы пытаетесь вернуть свою ссылку (используя [myNSValue nonretainedObjectValue]), ваше приложение аварийно завершит работу с сигналом EXC_BAD_ACCESS, если объект был освобожден до этого времени. Другими словами, слабая ссылка автоматически не устанавливается на ноль, находясь внутри объекта NSValue. Мне понадобилось несколько часов, чтобы понять. Я работал над этим, создавая простой класс со слабым свойством ref. Добавить в массив, вуаля!
 Timo06 авг. 2013 г., 14:41
Я разместил свой комментарий в качестве ответа и добавил сексуальную альтернативу, которая использует NSProxy.

Ваш ответ на вопрос