标签: swift-extensions

为什么具有协议一致性的扩展不能具有特定的访问级别?

假设我们有以下示例代码:

protocol MyProtocol {
    func someFunction()
}

public class MyClass {

}

public extension MyClass: MyProtocol {
    func someFunction() {
        print("hello")
    }
}
Run Code Online (Sandbox Code Playgroud)

编译上面的代码会出现以下错误:

错误:'public'修饰符不能与声明协议一致性的扩展一起使用

如果我将扩展名标记为,则会出现同样的情况private.它好像不能设置符合协议的扩展的访问级别,无论使用什么访问级别设置为中.甚至将协议声明设置为publicprivate不删除错误.

如果Swift符合协议,Swift以这种方式限制扩展访问级别的原因是什么?如果在类级别应用协议一致性,则不存在此类限制.

如果我服从编译器并删除private/ public指定,那么访问级别是someFunction()多少?

extension MyClass: MyProtocol {
    func someFunction() {
        print("hello")
    }
}
Run Code Online (Sandbox Code Playgroud)

我想在这种情况下,它将遵循原始的MyClass实现,public但我不确定.

这种行为是否存在,因为扩展中的协议一致性意味着整个类符合协议,因此在扩展中重新指定访问级别是多余的?

protocols access-levels swift swift-extensions

15
推荐指数
2
解决办法
4422
查看次数

我可以在Swift中扩展元组吗?

我想在Swift中为(例如)两个值的元组编写扩展.例如,我想写这个swap方法:

let t = (1, "one")
let s = t.swap
Run Code Online (Sandbox Code Playgroud)

s将是(String, Int)有价值的类型("one", 1).(我知道我可以很容易地实现一个swap(t)函数,但这不是我感兴趣的.)

我可以这样做吗?我似乎无法在extension声明中写出正确的类型名称.

另外,我想答案是一样的,我可以让2元组采用给定的协议吗?

tuples swift swift-extensions swift-protocols

14
推荐指数
2
解决办法
4171
查看次数

Set(Collection) - 插入多个元素

Set是一系列独特元素的无序集合.几乎与数组类似.

我想在一个Set中添加/插入多个元素String.但是只提供了一种方法,只能插入一个元素(接受单个Set元素作为参数参数),我收集了字符串(id).

插入(_:)

@discardableResult mutating func insert(_ newMember: Set.Element) -> (inserted: Bool, memberAfterInsert: Set.Element)
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

我尝试过:
我尝试创建一个非常类似于insert(_:)方法的扩展,但它可以接受多个Set元素.它与使用迭代而不是集合相同,但不需要在任何地方手动处理它.

extension Set {

    @discardableResult mutating func insert(_ newMembers: [Set.Element]) -> (inserted: Bool, memberAfterInsert: Set.Element) {

        newMembers.forEach { (member) in
            self.insert(member)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它应该工作,如果我按预期返回一个元组但不知道如何以及在哪里(哪一行)以及返回值的内容.

这是错误消息.

期望返回的函数中缺少返回'(inserted:Bool,memberAfterInsert:Set.Element)'

在此输入图像描述

什么可以解决这个问题.是否有更好的解决方案/方法来处理此操作?

tuples set ios swift swift-extensions

14
推荐指数
3
解决办法
5372
查看次数

Set()的Swift map(_ :)扩展名?

  let numberSet = Set(1...11)
  let divideSet = numberSet.map({  $0 / 10 }) 
  //Error: Set does not have a member named map   :(
Run Code Online (Sandbox Code Playgroud)

Swift 1.2支持Set()无序集合,但map(_:)似乎不适用于集合,所以我决定在我的操场上变聪明并尝试:

 let stringSet = Set(map(numberSet, { String($0)}))
 println(stringSet)
 stringSet =  ["2", "11", "1", "8", "6", "4", "3", "9", "7", "10", "5]
Run Code Online (Sandbox Code Playgroud)

这似乎有效.所以我尝试扩展Set:

    extension Set {
        func map<U>(transform: (T) -> U) -> Set<U> {
        return Set(Swift.map(self, transform))  }
    }
   Error: "couldn't find initialiser for Set(T) that accepts argument of type U"
Run Code Online (Sandbox Code Playgroud)

我认为它有一个很好的理由,它不起作用,就像这个例子:

   let smarDividSet …
Run Code Online (Sandbox Code Playgroud)

swift swift-extensions

13
推荐指数
2
解决办法
5270
查看次数

命名来自不同框架的扩展方法的冲突

作为测试,我创建了两个框架.两个框架都包含此扩展:

public extension UIDevice {
    var extraInfo: UIDeviceExtraInfo {
        return UIDeviceExtraInfo()
    }
}

public class UIDeviceExtraInfo {
    public var prop: String = "Device1"  //"Device2" is used in another framework
}
Run Code Online (Sandbox Code Playgroud)

然后我导入了两个框架并尝试打印UIDevice.currentDevice().extraInfo.prop.Swift编译器给出错误:Ambiguous use of extraInfo".

如何解决这样的名字冲突?

namespaces ios swift swift-extensions

13
推荐指数
2
解决办法
2421
查看次数

自我,协议扩展和非最终类

我尝试为UIView编写一个静态方法,它从nib实例化该类的视图.方法应该是通用的,并且适用于每个UIView子类.另外,我想保存类型信息 - 例如,在此代码中

let myView = MyView.loadFromNib()
Run Code Online (Sandbox Code Playgroud)

编译器推断出myViewMyView类.经过几次试验,我决定使用协议扩展,否则我将无法访问Self内部方法体.

看起来这应该工作:

protocol NibLoadable {
    static func loadFromNib(name: String?) -> Self
}

extension NibLoadable where Self: UIView {
    static func loadFromNib(name: String? = nil) -> Self {
        let nibName = name ?? "\(self)"
        let nib = UINib(nibName: nibName, bundle: nil)
        return nib.instantiateWithOwner(nil, options: nil)[0] as! Self
    }
}

extension UIView: NibLoadable {}
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.我收到编译错误

Method 'loadFromNib' in non-final class 'UIView' must return `Self` to conform to …
Run Code Online (Sandbox Code Playgroud)

protocols swift swift-extensions swift-protocols

13
推荐指数
1
解决办法
3511
查看次数

Swift中数组的通用扩展

坦率地说,我是学习扩展创建和使用的新手.

我想创建一个类别(在swift 3.0中扩展),可以在整个应用程序中使用它来执行Array的重复操作.

示例链接1

这是我在研究时所看到和理解的,我想创建一个扩展,其中包含各种方法,这些方法应该是通用的,而不是基于创建单独扩展所需的数据类型.

在上面的示例中,如果我们将使用特定的数据类型明智扩展,我们将需要创建单个扩展.如果有任何方法可以创建泛型类别(在swift中扩展),我想要一个指导.

  1. extension _ArrayType where Generator.Element == Int
  2. extension Array where Element: Equatable
  3. extension Array where Element == Int
  4. extension _ArrayType where Generator.Element == Float
  5. extension SequenceType where Self.Generator.Element: FloatingPointType
  6. extension Array where Element: DoubleValue
  7. extension Sequence where Iterator.Element == String

,等等...

示例链接2

注意:简而言之,我们可以考虑在单个扩展中执行基于Array的操作,而不是按照上述要求为每个数据类型创建单个扩展.

swift swift-extensions

13
推荐指数
2
解决办法
7048
查看次数

在扩展中为通用参数添加约束

我有这个功能:

func flatten<Key: Hashable, Value>(dict: Dictionary<Key, Optional<Value>>) -> Dictionary<Key, Value> {
    var result = [Key: Value]()
    for (key, value) in dict {
        guard let value = value else { continue }
        result[key] = value
    }
    return result
}
Run Code Online (Sandbox Code Playgroud)

如您所见,它将[Key: Value?]字典转换为[Key: Value]一个字典(没有可选字段).

我想Dictionary用一个新方法扩展该类只适用于值为Optional任何类型的类,但我无法为字典的泛型参数添加约束.

这是我试过的:

extension Dictionary where Value: Optional<Any> {
    func flatten() -> [Key: Any] {
        var result = [Key: Any]()
        for (key, value) in self {
            guard let value = value else …
Run Code Online (Sandbox Code Playgroud)

generics dictionary swift swift-extensions swift2

12
推荐指数
2
解决办法
1504
查看次数

处理Swift扩展中的类初始化失败

我正在将下面的Objective C类重写为Swift:

@implementation UIImage (Extra)

+ (UIImage *)validImageNamed:(NSString *)name
{
    UIImage *image = [self imageNamed:name];
    NSAssert(image, @"Unable to find image named '%@'", name);
    return image;
}
Run Code Online (Sandbox Code Playgroud)

这要求作为一个方便的init实现,但是如何检查指定的初始化程序self.init(命名:)是否成功?

extension UIImage {
    convenience init(validateAndLoad name: String!) {
        self.init(named: name)

        // need to assert here if self.init fails
    }
Run Code Online (Sandbox Code Playgroud)

当self.init(named :)调用失败时,扩展的init停止执行.

我已经尝试创建一个UIImage实例并将其分配给自己,但这不会编译.

当然,可以像ObjC版本一样使用辅助方法:

extension UIImage {

    class func validImage(named name: String) -> UIImage {
        var image = UIImage(named: name)
        assert(image == nil, "Image doesn't exist")
        return image
    }
Run Code Online (Sandbox Code Playgroud)

但有没有办法使用初始化程序实现这一点?

ios swift swift-extensions

11
推荐指数
1
解决办法
4177
查看次数

非'@ objc'方法不满足带条件扩展的'@objc'协议的可选要求

我正在尝试使用条件扩展创建MKMapViewDelegate的默认实现,如下所示:

extension MKMapViewDelegate where Self: NSObject {
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            ...
        }

        func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            ...
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是当我编译代码时,我得到了警告

非'@ objc'方法'mapView(_:viewFor :)'不满足'@objc'协议'MKMapViewDelegate'的可选要求

我期望NSObject对'Self'的一致性意味着警告不会发生.除了警告之外,即使委托实例是UIViewController并且因此符合NSObject,也不会调用委托方法.

我是否误解了"哪里"在扩展中的作用?

swift swift-extensions

10
推荐指数
1
解决办法
3023
查看次数