我一直在使用Swift中的iOS应用程序(其中大部分都是从Objective-C中移除的).我正在使用Core Data并尝试使用扩展来为我的模型自动生成的类添加功能.我在Objective-C中做的一件事就是在类A的类别中添加一个方法,并在类B(从A派生)的类别中覆盖该方法,我希望在Swift中也这样做.
有一段时间我在我的项目中已经有了以下代码(这只是一个例子),虽然我还没有使用过这个功能,但编译器已经很好地编译了这段代码:
// From CellType.swift -- NOTE: Imports from Foundation and CoreData
@objc(CellType)
class CellType: NSManagedObject {
@NSManaged var maxUses: NSNumber
@NSManaged var useCount: NSNumber
// Other properties removed for brevity
}
// From SwitchCellType.swift -- NOTE: Imports from Foundation and CoreData
@objc(SwitchCellType)
class SwitchCellType: CellType {
@NSManaged var targetCellXIndex: NSNumber
@NSManaged var targetCellYIndex: NSNumber
@NSManaged var targetCellType: CellType
// Other properties removed for brevity
}
// From CellTypeLogic.swift -- NOTE: Imports from Foundation and CoreData
extension CellType
{ …Run Code Online (Sandbox Code Playgroud) 从Swift 2.0开始,似乎我们可以更接近适用于谓词情境的泛型类型的扩展.
虽然我们仍然不能这样做:
protocol Idable {
var id : String { get }
}
extension Array where T : Idable {
...
}
Run Code Online (Sandbox Code Playgroud)
......我们现在可以这样做:
extension Array {
func filterWithId<T where T : Idable>(id : String) -> [T] {
...
}
}
Run Code Online (Sandbox Code Playgroud)
...和Swift语法接受它.但是,对于我的生活,当我填写示例函数的内容时,我无法弄清楚如何让编译器开心.假设我要尽可能明确:
extension Array {
func filterWithId<T where T : Idable>(id : String) -> [T] {
return self.filter { (item : T) -> Bool in
return item.id == id
}
}
}
Run Code Online (Sandbox Code Playgroud)
...编译器不会接受提供的过滤,过滤,抱怨
无法使用类型为'((T) - > Bool)'的参数列表调用'filter'
如果将item指定为Idable,则类似.这里有运气吗?
我有一个扩展名:
extension UILabel {
func animateHidden(flag: Bool) {
self.hidden = flag
}
}
Run Code Online (Sandbox Code Playgroud)
我需要制作相同的,UIImageView但我不想复制整个代码.是否可以为多个类进行扩展?
谢谢.
假设我有一个名为SwiftKit的框架,它有一个名为someClassMethod的UIView扩展类方法和一个名为someProperty的属性:
// SwiftKit
public extension UIView {
class func someClassMethod() {
print("someClassMethod from Swift Kit")
}
var someProperty: Double {
print("someProperty from Swift Kit")
return 0
}
}
Run Code Online (Sandbox Code Playgroud)
我还有一个名为SwiftFoundation的框架,它还有一个名为someClassMethod的UIView扩展类方法和一个名为someProperty的属性:
// SwiftFoundation
public extension UIView {
class func someClassMethod() {
print("someClassMethod from Swift Foundation")
}
var someProperty: Double {
print("someProperty from Swift Foundation")
return 0
}
}
Run Code Online (Sandbox Code Playgroud)
然后我创建了一个项目介绍这些框架,事情是,如果我在同一个swift文件中导入它们并访问这些扩展,我得到了"不明确使用someProperty/someClassMethod()"错误,即使我指定了调用SwiftKit.UIView.someClassMethod()的形式:
import UIKit
import SwiftKit
import SwiftFoundation
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the …Run Code Online (Sandbox Code Playgroud) 说你有
class Fancy:UIView
Run Code Online (Sandbox Code Playgroud)
你想找到所有兄弟姐妹的Fancy意见. 没问题 ......
for v:UIView in superview!.subviews
{
if let f = v as? Fancy
{ f.hungry = false }
}
Run Code Online (Sandbox Code Playgroud)
所以,尝试扩展,
public extension UIView
{
internal func fancySiblings()->([Fancy])
{
return (self.superview!
.subviews
.filter { $0 != self }
.flatMap { $0 as? Fancy }
)
}
}
Run Code Online (Sandbox Code Playgroud)
太棒了,你现在可以
for f:Fancy in self.fancySiblings()
{ f.hungry = false }
Run Code Online (Sandbox Code Playgroud)
太棒了.
但,
所以,像......
public extension UIView
{
internal func siblings<T>( something T )->([T]) …Run Code Online (Sandbox Code Playgroud) 嗨那里=)我刚刚面临一个设计问题,我需要(基本上)做以下事情:
我要注入一些代码上viewWillAppear:的任何UIViewController符合协议的子类MyProtocol.在代码中解释:
protocol MyProtocol
{
func protocolFunction() {
//do cool stuff...
}
}
extension UIViewController where Self: MyProtocol //<-----compilation error
{
public override class func initialize()
{
//swizzling stuff switching viewWillAppear(_: Bool) with xxx_viewWillAppear(animated: Bool)
}
// MARK: - Swizzling
func xxx_viewWillAppear(animated: Bool)
{
self.xxx_viewWillAppear(animated)
//invoke APIs from
self.protocolFunction() // MyProtocol APIs
let viewLoaded = self.isViewLoaded // UIViewController APIs
}
}
Run Code Online (Sandbox Code Playgroud)
这里的主要问题是我需要UIVIewController扩展中的两件事:
MyProtocol和UIViewControllerAPIUIViewController方法initialize() …我看到了很多以下格式的例子
extension Protocolname where Self: UIViewController
Run Code Online (Sandbox Code Playgroud)
什么是where Self协议扩展.我找不到关于此的文档.
扩展不能包含存储属性,但为什么可以在扩展中定义静态存储属性?
我也没有找到任何文档提到扩展中允许静态属性.
extension String {
static let test = "Test"
static var test2 = "Test2"
}
Run Code Online (Sandbox Code Playgroud) 我有一个UIView实现协议的扩展
protocol SomeProtocol {
var property : Int
}
extension UIView : SomeProtocol {
var property : Int {
get {
return 0
}
set {
// do nothing
}
}
}
Run Code Online (Sandbox Code Playgroud)
在具体的子类中,我想覆盖此扩展方法:
class Subclass : UIView, SomeProtocol {
var _property : Int = 1
var property : Int {
get { return _property}
set(val) {_property = val}
}
}
Run Code Online (Sandbox Code Playgroud)
我设置断点并看到调用扩展方法而不是具体的子类方法:
var subclassObject = Subclass()
someObject.doSomethingWithConcreteSubclassObject(subclassObject)
// other code;
fun doSomethingWithConcreteSuclassObject(object : UIView) {
var value = object.property // always …Run Code Online (Sandbox Code Playgroud) 在Swift中,我历史上使用扩展来扩展封闭类型并提供方便的,无逻辑的功能,如动画,数学扩展等.但是,由于扩展是硬依赖性遍布整个代码库,我总是在实现之前三次思考某事作为延伸.
最近,我已经看到Apple建议在更大程度上使用扩展,例如将协议实现为单独的扩展.
也就是说,如果你有一个实现协议B的A类,你最终会得到这样的设计:
class A {
// Initializers, stored properties etc.
}
extension A: B {
// Protocol implementation
}
Run Code Online (Sandbox Code Playgroud)
当你进入那个兔子洞时,我开始看到更多基于扩展的代码,例如:
fileprivate extension A {
// Private, calculated properties
}
fileprivate extension A {
// Private functions
}
Run Code Online (Sandbox Code Playgroud)
我的一部分就像你在单独的扩展中实现协议时获得的构建块.它使得该类的独立部分非常独特.但是,只要继承此类,就必须更改此设计,因为无法覆盖扩展函数.
我认为第二种方法是......有趣.一旦它成功,那就是你不需要注释每个私有属性并将其作为私有属性,因为你可以为扩展指定.
但是,这种设计还会分割存储和非存储的属性,公共和私有函数,使类的"逻辑"更难遵循(我知道写较小的类).这与子类化问题一起使我在延伸仙境的门廊上停了下来.
很想听听Swift社区如何看待扩展.你怎么看?有一个银色的小礼物吗?
swift ×10
swift-extensions ×10
ios ×5
generics ×1
namespaces ×1
overriding ×1
protocols ×1
where-clause ×1