Swift匿名类 1.0.0

Swift匿名类 1.0.0

Sergey Makeev维护。



  • Sergey Makeev

Swift匿名类

Swift中匿名类的等价物。

Swift匿名类为您的项目添加了 _new 功能。

public func _new<Type>(owner: AnyObject? = nil, _ objectCreator:()->Type) -> Type

比如说,您有一个协议

protocol Greeting {
    func sayHello() -> String
}

您需要一个能够说“hello”的类。

let object: Greeting = _new {
  class NoName: Greeting {
    func sayHello() -> String {
      return "hello from no name class"
    }
  }
  return NoName()
}

object.sayHello()

更实际的例子

        let configuration = URLSessionConfiguration.default
        var downloadsSession = URLSession(configuration: configuration,
                                          delegate: _new {
                                            class NoName: NSObject, URLSessionDownloadDelegate {
                                                func urlSession(_ session: URLSession,
                                                                downloadTask: URLSessionDownloadTask,
                                                                didFinishDownloadingTo location: URL) {
                                                    print("Finished downloading to \(location).")
                                                }
                                            }
                                            return NoName()
                                          },
                                          delegateQueue: nil)

注意URLSession会强引用其代理,但通常代理会被弱引用。如果只是使用 some.delegate = _new {...},您将得到nil。首先,您需要对其进行强引用。为此,您可以使用 _new 函数的 owner 参数。此参数将 _new 对象的生命周期与 owner 绑定,当调用 ownerdeinit 方法时,新的匿名对象将被移除。

例子

protocol ADelegate: class {
	func `do`()
 }
 
 class A {
	weak var delegate: ADelegate?
	
	deinit {
		delegate?.do()
	}
}

...

let a = A()
a.delegate = _new(owner: a) {			
			class ADelegateInstance: ADelegate {
			
				func `do`() {
					print("DO from delegate")
				}
			}
      }

如果您设置了新的匿名代理,第一个将被释放。如果设置了新的代理(而不是使用 _new),匿名代理将保留直到代理被释放。要强制将其移除,您可以先设置为nil。例如

假设您有一个具有弱代理的Some类和SomeDelegate。您还有SomeDelegate的实例,它的实例被某地强烈引用。首先,您将Some实例的代理设置为一个匿名对象。但后来,您将其更改为非匿名类,匿名类变得不可达但仍然存在。要确保在某个实例释放之前销毁它,您可以执行以下操作

some.delegate = _new(owner:some) {
    class NoName: SomeDelegate {
        func `do`() {
            print("DO")
        }
    }
    return NoName()
}

some.delegate = _new(owner:some) { nil }
some.delegate = someDelegateInstance