Я хотел бы хранить массив слабых ссылок в Swift. Сам массив не должен быть слабой ссылкой - его элементы должны быть. Я думаю, что Какао NSPointerArray
предлагает нетипичную версию этого.
179
Я хотел бы хранить массив слабых ссылок в Swift. Сам массив не должен быть слабой ссылкой - его элементы должны быть. Я думаю, что Какао NSPointerArray
предлагает нетипичную версию этого.
Ответы:
Создайте универсальную оболочку как:
Добавьте экземпляры этого класса в ваш массив.
При определении
Weak
вы можете использовать либоstruct
илиclass
.Также, чтобы помочь с получением содержимого массива, вы можете сделать что-то вроде:
Использование
AnyObject
выше должно быть заменено наT
- но я не думаю, что текущий язык Swift допускает расширение, определенное как таковое.источник
Stuff
протоколом; см. этот связанный вопросВы можете использовать NSHashTable со слабой таблицей.
NSHashTable<ObjectType>.weakObjectsHashTable()
Для Swift 3:
NSHashTable<ObjectType>.weakObjects()
Ссылка на класс NSHashTable
источник
Any
но не сAnyObject
такими, как протоколы.MyProtocol: class
иNSHashTable<MyProtocol>.weakObjects()
. «NSHashTable» требует, чтобы «MyProtocol» был типом класса.Уже поздно для вечеринки, но попробуй мою. Я реализовал как набор, а не массив.
WeakObjectSet
использование
Помните, что WeakObjectSet не будет принимать тип String, но NSString. Потому что тип String не является AnyType. Моя быстрая версия есть
Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
.Код можно получить из Gist. https://gist.github.com/codelynx/30d3c42a833321f17d39
** ДОБАВЛЕНО В НОЯРЕ 2017
Я обновил код до Swift 4
Как упомянул gokeji, я понял, что NSString не будет освобожден в зависимости от используемого кода. Я почесал голову и написал класс MyString следующим образом.
Затем замените
NSString
наMyString
вот так. Тогда странно сказать, что это работает.Тогда я обнаружил, что странная страница может быть связана с этой проблемой.
https://bugs.swift.org/browse/SR-5511
Там говорится, что проблема в том,
RESOLVED
но мне интересно, связано ли это еще с этой проблемой. В любом случае, различия в поведении между MyString и NSString выходят за рамки этого контекста, но я был бы признателен, если бы кто-то решил эту проблему.источник
nil
значения из внутреннегоSet
. Поэтому я добавилreap()
функцию, упомянутую в верхнем ответе, и проверял, чтобы она вызывалась приreap()
каждомWeakObjectSet
обращении к ней.nil
большеNSString
нет.UnsafeMutablePointer<T>(&object)
может меняться случайным образом (то же самое сwithUnsafePointer
). Теперь я использую версию, поддерживаемуюNSHashTable
: gist.github.com/simonseyer/cf73e733355501405982042f760d2a7d .Это не мое решение. Я нашел это на форумах разработчиков Apple .
У @GoZoner хороший ответ, но он ломает компилятор Swift.
Вот версия контейнера слабых объектов, которая не приводит к сбою текущего выпущенного компилятора.
Затем вы можете создать массив этих контейнеров:
источник
EXC_BAD_ACCESS
для меня. С классом работает просто отличноВы можете сделать это, создав объект-обертку для хранения слабого указателя.
И затем, используя их в массиве
источник
class
чтобы использоватьweak
переменныеprotocol Protocol : class { ... }
Как насчет функционального стиля оболочки?
Просто позвоните, верните закрытие, чтобы проверить, что цель еще жива.
И вы можете хранить эти замыкания в массиве.
И вы можете получить слабо захваченные значения, сопоставляя вызовы замыканий.
На самом деле, вам не нужна функция для закрытия. Просто захватите объект напрямую.
источник
var array: [(x: Int, y: () -> T?)]
. Именно то, что я искал.let values = Array(array1.map({ $0() })) part
. Поскольку это больше не массив закрытий со слабыми ссылками, значения будут сохраняться до тех пор, пока этот массив не будет освобожден. Если я прав, то важно отметить, что вы никогда не должны сохранять этот массив,self.items = Array(array1.map({ $0() }))
как это соответствует цели.У меня была такая же идея создать слабый контейнер с генериками.
В результате я создал обертку для
NSHashTable
:Использование:
Это не лучшее решение, потому что
WeakSet
может быть инициализировано с любым типом, и если этот тип не соответствуетAnyObject
протоколу, приложение будет аварийно завершено с подробной причиной. Но я не вижу лучшего решения прямо сейчас.Первоначальное решение было определить
WeakSet
таким образом:Но в этом случае
WeakSet
нельзя инициализировать протоколом:В настоящее время приведенный выше код не может быть скомпилирован (Swift 2.1, Xcode 7.1).
Вот почему я упал в соответствии с
AnyObject
и добавил дополнительных охранников сfatalError()
утверждениями.источник
подробности
Решение
Опция 1
Вариант 1 использования
Вариант 2
Вариант 2 использования
Полный образец
источник
protocol TP: class { } class TC { var a = WeakArray<TP>() var b = WeakObjectsArray<TP>() }
protocol TP: class { } class TC<TYPE> where TYPE: TP { var a = WeakObjectsArray<TYPE>() // Use like regular array. With any objects var weakObjectsArray = [TYPE?]() }
delegates
. Тогда у вас будет некоторое количество контроллеров представления, которые хотели бы использовать эту функцию. Вы ожидаете позвонитьMyManager.delegates.append(self)
. Но еслиMyManager
привязан к какому-то универсальному типу, тогда это не очень удобно.protocol TP: class { } class MyManager { typealias Delegate = AnyObject & TP static var delegates = [Delegate?]() } class A: TP { } class B: TP { } //MyManager.delegates.append(A()) //MyManager.delegates.append(B())
Существующий пример WeakContainer полезен, но на самом деле он не помогает использовать слабые ссылки в существующих быстрых контейнерах, таких как списки и словари.
Если вы хотите использовать методы List, такие как contains, то WeakContainer должен будет реализовать Equatable. Поэтому я добавил код, чтобы позволить WeakContainer быть уравновешенным.
Если вы хотите использовать WeakContainer в словарях, я также сделал его хешируемым, чтобы его можно было использовать в качестве ключей словаря.
Я также переименовал его в WeakObject, чтобы подчеркнуть, что это только для типов классов, и дифференцировать его от примеров WeakContainer:
Это позволяет вам делать некоторые интересные вещи, такие как использование словаря слабых ссылок:
источник
Вот как сделать @ большой ответ GoZoner в соответствие
Hashable
, так что он может быть проиндексирован в объекты Container , как:Set
,Dictionary
,Array
и т.д.источник
Поскольку
NSPointerArray
большая часть этого уже обрабатывается автоматически, я решил эту проблему, создав безопасную для типов оболочку, которая позволяет избежать большого количества шаблонов в других ответах:Пример использования:
Это больше работы, но использование в остальной части кода намного чище IMO. Если вы хотите сделать его более похожим на массив, вы можете даже реализовать подписку, сделать это и
SequenceType
т. Д. (Но мой проект нуждается только в этом,append
иforEach
поэтому у меня нет точного кода под рукой).источник
Еще одно решение той же проблемы ... основное внимание уделяется хранению слабой ссылки на объект, но также позволяет хранить структуру.
[Я не уверен, насколько это полезно, но потребовалось время, чтобы понять синтаксис]
источник
Вы можете создать обертку вокруг
Array
. Или используйте эту библиотеку https://github.com/NickRybalko/WeakPointerArraylet array = WeakPointerArray<AnyObject>()
Это безопасный тип.источник
Другие ответы охватили общий вид. Думаю, я бы поделился простым кодом, охватывающим этот
nil
угол.Я хотел статический массив (иногда читаемый) из всех,
Label
которые в настоящее время существуют в приложении, но не хотел видетьnil
, где были старые.Ничего особенного, это мой код ...
источник
flatMap
вместоfilter
&map
?Я основал это на работе @Eonil, так как мне понравилась стратегия слабого связывания замыкания, но я не хотел использовать оператор функции для переменной, так как она была чрезвычайно противоречивой.
Вместо этого я сделал следующее:
Таким образом, вы можете сделать что-то вроде:
источник
Это мое решение:
-
источник
Это безопасная коллекция типов, которая содержит контейнеры со слабыми объектами. Он также автоматически удаляет ноль контейнеров / упаковщиков при доступе.
Пример:
Пользовательская коллекция https://gist.github.com/djk12587/46d85017fb3fad6946046925f36cefdc
источник
Как насчет функционального подхода ?
Это основная идея, затем добавьте любую удобную логику, чтобы отслеживать, что находится в массиве. Например, можно рассмотреть тот же подход со словарем, используя ключ как способ найти то, что там.
источник