热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:如何在Swift中声明一个弱引用数组?

篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何在Swift中声明一个弱引用数组?相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何在Swift中声明一个弱引用数组?相关的知识,希望对你有一定的参考价值。



我想在Swift中存储一组弱引用。数组本身不应该是弱引用 - 它的元素应该是。我认为Cocoa NSPointerArray提供了非类型安全版本。


答案

创建一个通用包装器:

class Weak {
weak var value : T?
init (value: T) {
self.value = value
}
}

将此类的实例添加到您的数组。

class Stuff {}
var weakly : [Weak] = [Weak(value: Stuff()), Weak(value: Stuff())]

在定义Weak时,您可以使用structclass

此外,为了帮助获取数组内容,您可以执行以下操作:

extension Array where Element:Weak {
mutating func reap () {
self = self.filter { nil != $0.value }
}
}

上面的AnyObject的使用应该用T替换 - 但我不认为当前的Swift语言允许扩展定义为这样。


另一答案

以下是如何使@ GoZoner的答案符合Hashable,因此它可以在Container对象中编入索引,例如:SetDictionaryArray等。

private class Weak: Hashable {
weak var value : T!
init (value: T) {
self.value = value
}
var hashValue : Int {
// ObjectIdentifier creates a unique hashvalue for objects.
return ObjectIdentifier(self.value).hashValue
}
}
// Need to override so we can conform to Equitable.
private func == (lhs: Weak, rhs: Weak) -> Bool {
return lhs.hashValue == rhs.hashValue
}

另一答案

其他答案涵盖了泛型角度。以为我会分享一些涵盖nil角度的简单代码。

我想要一个当前存在于应用程序中的所有Labels的静态数组(偶尔读取),但是不想看到旧的那些曾经是nil的地方。

没什么好看的,这是我的代码......

public struct WeakLabel {
public weak var label : Label?
public init(_ label: Label?) {
self.label = label
}
}
public class Label : UILabel {
static var _allLabels = [WeakLabel]()
public static var allLabels:[WeakLabel] {
get {
_allLabels = _allLabels.filter{$0.label != nil}
return _allLabels.filter{$0.label != nil}.map{$0.label!}
}
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
Label._allLabels.append(WeakLabel(self))
}
public override init(frame: CGRect) {
super.init(frame: frame)
Label._allLabels.append(WeakLabel(self))
}
}

另一答案

针对同一问题的又一个解决方案......这个问题的重点是存储对象的弱引用,但也允许存储结构。

[我不确定它有多有用,但确实需要一段时间才能使语法正确]

class WeakWrapper : Equatable {
var valueAny : Any?
weak var value : AnyObject?
init(value: Any) {
if let valueObj = value as? AnyObject {
self.value = valueObj
} else {
self.valueAny = value
}
}
func recall() -> Any? {
if let value = value {
return value
} else if let value = valueAny {
return value
}
return nil
}
}
func ==(lhs: WeakWrapper, rhs: WeakWrapper) -> Bool {
return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}
class Stuff {}
var weakArray : [WeakWrapper] = [WeakWrapper(value: Stuff()), WeakWrapper(value: CGRectZero)]
extension Array where Element : WeakWrapper {
mutating func removeObject(object: Element) {
if let index = self.indexOf(object) {
self.removeAtIndex(index)
}
}
mutating func compress() {
for obj in self {
if obj.recall() == nil {
self.removeObject(obj)
}
}
}
}
weakArray[0].recall()
weakArray[1].recall() == nil
weakArray.compress()
weakArray.count

另一答案

由于NSPointerArray已经自动处理了大部分内容,因此我通过为其设置类型安全包装来解决问题,这避免了其他答案中的许多样板:

class WeakArray {
private let pointers = NSPointerArray.weakObjects()
init (_ elements: T...) {
elements.forEach{self.pointers.addPointer(Unmanaged.passUnretained($0).toOpaque())}
}
func get (_ index: Int) -> T? {
if index return Unmanaged.fromOpaque(pointer).takeUnretainedValue()
} else {
return nil
}
}
func append (_ element: T) {
self.pointers.addPointer(Unmanaged.passUnretained(element).toOpaque())
}
func forEach (_ callback: (T) -> ()) {
for i in 0.. if let element = self.get(i) {
callback(element)
}
}
}
// implement other functionality as needed
}

用法示例:

class Foo {}
var foo: Foo? = Foo()
let array = WeakArray(foo!)
print(array.get(0)) // Optional(Foo)
foo = nil
DispatchQueue.main.async{print(array.get(0))} // nil

它预先做的更多,但在其余代码中的使用更加清晰IMO。如果你想让它更像数组,你甚至可以实现下标,使它成为SequenceType等(但我的项目只需要appendforEach所以我手头没有确切的代码)。


另一答案

你可以在Array周围创建包装器。或使用此库https://github.com/NickRybalko/WeakPointerArray
let array = WeakPointerArray()
它是类型安全的。


另一答案

我基于@Eonil的工作,因为我喜欢闭包弱绑定策略,但我不想使用函数运算符来变量,因为它感觉非常反直觉

相反,我所做的如下:

class Weak where T: AnyObject {
fileprivate var storedWeakReference: ()->T? = { return nil }
var value: T? {
get {
return storedWeakReference()
}
}
init(_ object: T) {
self.storedWeakReference = storeWeakReference(object)
}
fileprivate func storeWeakReference (_ target:T) -> ()->T? where T: AnyObject {
return { [weak target] in
return target
}
}
}

通过这种方式,您可以执行以下操作:

var a: UIViewController? = UIViewController()
let b = Weak(a)
print(a) //prints Optional()
print(b.value) //prints Optional()
a = nil
print(a) //prints nil
print(b.value) //prints nil

另一答案

我的解决方案:



  • 解除分配时清理数组,因为WeakObjectSet正在存储而不是从WeakObject中删除

  • 在Set中找到重复元素时解决致命错误

--

// MARK: - WeakObjectSet
public class WeakObject: Equatable, Hashable {
// MARK: Public propreties
public weak var object: T?
public var hashValue: Int {
return self.identifier.hashValue
}
// MARK: Private propreties
private let identifier: ObjectIdentifier
// MARK: Initializer
public init(object: T) {
self.identifier = ObjectIdentifier(object)
self.object = object
}
public static func == (lhs: WeakObject, rhs: WeakObject) -> Bool {
return lhs.identifier == rhs.identifier
}
}
// MARK: - WeakObjectSet
public class WeakObjectSet {
// MARK: Public propreties
public var allObjects: [T] {
return allSetObjects.compactMap { $0.object }
}
// MARK: Private propreties
private var objects: Set>
private var allSetObjects: Set> {
get {
objects = self.objects.filter { $0.object != nil }
return objects
}
set {
objects.formUnion(newValue.filter { $0.object != nil })
}
}
// MARK: Initializer
public init() {
self.objects = Set>([])
}
public init(objects: [T]) {
self.objects = Set>(objects.map { WeakObject(object: $0) })
}
// MARK: Public function
public func contains(_ object: T) -> Bool {
return self.allSetObjects.contains(WeakObject(object: object))
}
public func addObject(_ object: T) {
self.allSetObjects.insert(WeakObjec

推荐阅读
  • 第六章:枚举类型与switch结构的应用分析
    第六章深入探讨了枚举类型与 `switch` 结构在编程中的应用。枚举类型(`enum`)是一种将一组相关常量组织在一起的数据类型,广泛存在于多种编程语言中。例如,在 Cocoa 框架中,处理文本对齐时常用 `NSTextAlignment` 枚举来表示不同的对齐方式。通过结合 `switch` 结构,可以更清晰、高效地实现基于枚举值的逻辑分支,提高代码的可读性和维护性。 ... [详细]
  • 在 Swift 中,初始化器的参数名称使用 "with" 前缀是一种常见的规范,但需要注意的是,对于第一个参数,编译器默认会省略外部参数名。因此,直接在第一个参数前使用 "with" 会导致编译错误。本文深入探讨了这一规范的最佳实践,并提供了避免此类错误的具体方法,帮助开发者更好地理解和应用 Swift 的初始化器设计原则。 ... [详细]
  • Hadoop MapReduce 实战案例:手机流量使用统计分析
    本文通过一个具体的Hadoop MapReduce案例,详细介绍了如何利用MapReduce框架来统计和分析手机用户的流量使用情况,包括上行和下行流量的计算以及总流量的汇总。 ... [详细]
  • 本文旨在探讨Swift中的Closure与Objective-C中的Block之间的区别与联系,通过定义、使用方式以及外部变量捕获等方面的比较,帮助开发者更好地理解这两种机制的特点及应用场景。 ... [详细]
  • 本文详细介绍了如何使用C#实现不同类型的系统服务账户(如Windows服务、计划任务和IIS应用池)的密码重置方法。 ... [详细]
  • 管理UINavigationController中的手势返回 - Managing Swipe Back Gestures in UINavigationController
    本文介绍了如何在一个简单的闪存卡片应用中实现平滑的手势返回功能,以增强用户体验。 ... [详细]
  • 开发技巧:在Interface Builder中实现UIButton文本居中对齐的方法与步骤
    开发技巧:在Interface Builder中实现UIButton文本居中对齐的方法与步骤 ... [详细]
  • 本文详细对比了HashMap和HashTable在多线程环境下的安全性、对null值的支持、性能表现以及方法同步等方面的特点,帮助开发者根据具体需求选择合适的数据结构。 ... [详细]
  • 页面预渲染适用于主要包含静态内容的页面。对于依赖大量API调用的动态页面,建议采用SSR(服务器端渲染),如Nuxt等框架。更多优化策略可参见:https://github.com/HaoChuan9421/vue-cli3-optimization ... [详细]
  • iOS如何实现手势
    这篇文章主要为大家展示了“iOS如何实现手势”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“iOS ... [详细]
  • Android 开发技巧:使用 AsyncTask 实现后台任务与 UI 交互
    本文详细介绍了如何在 Android 应用中利用 AsyncTask 来执行后台任务,并及时将任务进展反馈给用户界面,提高用户体验。 ... [详细]
  • 本文探讨了如何使用Scrapy框架构建高效的数据采集系统,以及如何通过异步处理技术提升数据存储的效率。同时,文章还介绍了针对不同网站采用的不同采集策略。 ... [详细]
  • 一、使用Microsoft.Office.Interop.Excel.DLL需要安装Office代码如下:2publicstaticboolExportExcel(S ... [详细]
  • 解析Java虚拟机HotSpot中的GC算法实现
    本文探讨了Java虚拟机(JVM)中HotSpot实现的垃圾回收(GC)算法,重点介绍了根节点枚举、安全点及安全区域的概念和技术细节,以及这些机制如何影响GC的效率和准确性。 ... [详细]
  • 本文深入探讨了 iOS 开发中 `int`、`NSInteger`、`NSUInteger` 和 `NSNumber` 的应用与区别。首先,我们将详细介绍 `NSNumber` 类型,该类用于封装基本数据类型,如整数、浮点数等,使其能够在 Objective-C 的集合类中使用。通过分析这些类型的特性和应用场景,帮助开发者更好地理解和选择合适的数据类型,提高代码的健壮性和可维护性。苹果官方文档提供了更多详细信息,可供进一步参考。 ... [详细]
author-avatar
小楼GH81_660
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有