标签: swift-extensions

如何使用泛型类型来获取相同类型的对象

我有扩展NSManagedObject,应该帮助我在上下文之间传输对象:

extension NSManagedObject {

    func transferTo(#context: NSManagedObjectContext) -> NSManagedObject? {

        return context.objectWithID(objectID)
    }

}
Run Code Online (Sandbox Code Playgroud)

现在它返回对象,NSManagedObject我应该把它投射到我想要的类,像这样:

let someEntity: MyEntity = // ...create someEntity
let entity: MyEntity = someEntity.transferTo(context: newContext) as? MyEntity
Run Code Online (Sandbox Code Playgroud)

有没有办法Swift避免无用的转换,如果我transferTo(context: ...)从类的对象调用MyEntity使它返回类型MyEntity

generics swift swift-extensions

6
推荐指数
1
解决办法
1262
查看次数

扩展UICollectionViewDataSource协议以添加默认实现

我有一个相当大的应用程序,它有很多集合视图.大多数集合视图都具有相同的数据源和流布局代表(相同的大小,边距等)的实现.我正在尝试创建一个提供UICollectionViewDataSource和UICollectionViewDelegateFlowLayout的默认实现的协议.这是我的代码.

protocol TiledCollectionView{}

extension UICollectionViewDataSource where Self: TiledCollectionView{
    //default implementation of the 3 methods to load the data ...
}
extension UICollectionViewDelegateFlowLayout where Self: TiledCollectionView {
    //default implementation for layout methods to set default margins etc...
}

class MyViewController: UIViewController, TiledCollectionView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
    // the rest of the required logic for view controller
    // here I Don't implement any CollectionView methods since I have provided the default implementation already
}
Run Code Online (Sandbox Code Playgroud)

问题是,编译器抱怨MyViewController不符合UICollectionViewDataSource.这不应该是这种情况,因为我清楚地说,如果类型是TiledCollectionView,则添加默认实现.

有人可以帮忙吗?

uicollectionview swift swift-extensions swift-protocols protocol-extension

6
推荐指数
1
解决办法
3184
查看次数

泛型类的 Swift 扩展类型约束,其中泛型类型是另一种泛型类型

我正在尝试了解 Swift 中的泛型类型约束。这是我的出发点:

\n\n
class Promise<T> {\n    func resolve(_ block:@escaping (T) ->Void) {}\n    func fulfill(_ result:T) {}\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

Promise 就是将来可以实现的事情。当它与 Swift 类型一起使用时,Result将结果从后台队列返回到主队列时,这会变得非常有用:

\n\n
let promise = Promise<Result<String, Error>>()\npromise.fulfill(.success("Hello"))\npromise.fulfill(.failure(NSError()))\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我想向所有用于Result添加这些辅助方法的 Promise 实例添加扩展:

\n\n
extension Promise where T == Result<X, Error> {\n                                    \xe2\xac\x86\xef\xb8\x8e Here\'s the problem \xe2\x9a\xa1\xef\xb8\x8f\n    func failure(_ error:Error) {\n        fulfill(.failure(error))\n    }\n\n    func success(_ result:X) {\n        fulfill(.success(result))\n    }\n}\n\n// Shorter:\nlet promise = Promise<Result<String, Error>>()\npromise.success("Hello")\npromise.failure(NSError())\n
Run Code Online (Sandbox Code Playgroud)\n\n

唯一的问题是上面的代码无法编译,因为X没有定义。我想表达的是这样的:

\n\n

Promise当其泛型类型T为 where 类型Result<X,Z>且 …

generics type-constraints swift swift-extensions

6
推荐指数
1
解决办法
1745
查看次数

在Int扩展上调用mutating func

在命令行应用程序中创建了一个扩展.当我尝试调用calc方法时,它将无法工作.调用desc有效.

我错过了什么?

protocol Calculatable {
    var desc:String { get }
    mutating func calc()
}

class MyClass : Calculatable {
    var desc:String = "MyClass"
    func calc()  {
        desc += " is great"
    }
}

extension Int: Calculatable {
    var desc:String { return "hi" }
    mutating func calc() {
        self += 10
    }
}

7.desc  // works
7.calc() // Compiler error: could not find member calc
Run Code Online (Sandbox Code Playgroud)

swift swift-extensions

5
推荐指数
1
解决办法
691
查看次数

Swift Extension无法将重载方法添加到Objective-C类

如果使用Swift扩展将重载方法添加到Objective-C类,它似乎只调用第一个方法,在运行时产生意外行为或崩溃.Swift类的扩展(与Objective-C相对)可以正常工作.我想确定是否有任何解决方法,并确认这是一个我应该向Apple报告的错误.鉴于Objective-C不支持Swift的重载方法,我可以想象将两者混合是一个问题的处方.

除了具有init函数的Objective-C类之外,获取扩展的类都是空的.ObjClass在.h和.m文件中声明,并使用Swift桥接头导入.原始SwiftClass在代码示例中与Swift扩展一起定义:

extension ObjClass {
    func log(param: Int32)    { NSLog("ObjClass->Int32: " + String(param)) }
    func log(param: String)   { NSLog("ObjClass->String: " + param) }
    func log(param: ObjClass) { NSLog("ObjClass->ObjClass") }
}

class SwiftClass {
}

extension SwiftClass {
    func log(param: Int32)    { NSLog("SwiftClass->Int32: " + String(param)) }
    func log(param: String)   { NSLog("SwiftClass->String: " + param) }
    func log(param: ObjClass) { NSLog("SwiftClass->ObjClass") }
}
Run Code Online (Sandbox Code Playgroud)

现在用字符串,int和object调用重载的方法:

var objClass = ObjClass()
objClass.log(10)
objClass.log("string")
objClass.log(objClass)

var swiftClass = SwiftClass()
swiftClass.log(10)
swiftClass.log("string")
swiftClass.log(objClass)
Run Code Online (Sandbox Code Playgroud)

对于ObjClass,所有方法调用都是对类型为Int32的第一个方法进行的.通过使用COpaquePointer,我可以看到这与对象指针有关但略有不同. …

objective-c swift swift-extensions

5
推荐指数
1
解决办法
1095
查看次数

使用NSManagedObject的keyPathsForValuesAffecting

Bonjour,我想把一个客观的练习从Aaron的书翻译成快速但我无法找到解决方案.Objective'c代码是:

@dynamic firstName;
@dynamic lastName;
@dynamic department;

+ (NSSet *)keyPathsForValuesAffectingFullName
{
    return [NSSet setWithObjects:@"firstName", @"lastName", nil];
}

- (NSString *)fullName
{
    NSString *first = [self firstName];
    NSString *last = [self lastName];
    if (!first)
        return last;
    if (!last)
        return first;
    return [NSString stringWithFormat:@"%@ %@", first, last];
}
Run Code Online (Sandbox Code Playgroud)

我在开发人员文档中找到了一个函数,但我无法理解如何实现此代码.

更明确一点,这是Apple doc

一对一的关系

要为一对一关系自动触发通知,您应该覆盖keyPathsForValuesAffectingValueForKey:或者实现一个合适的方法,该方法遵循它为注册依赖键定义的模式.

例如,人的全名取决于名字和姓氏.返回全名的方法可以写成如下:

- (NSString *)fullName {
    return [NSString stringWithFormat:@"%@ %@",firstName, lastName];
}
Run Code Online (Sandbox Code Playgroud)

当firstName或lastName属性发生更改时,必须通知观察fullName属性的应用程序,因为它们会影响属性的值.

一种解决方案是覆盖keyPathsForValuesAffectingValueForKey:指定人员的fullName属性依赖于lastName和firstName属性.清单1显示了这种依赖的示例实现:

清单1 keyPathsForValuesAffectingValueForKey的示例实现:

+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {

    NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];

    if ([key isEqualToString:@"fullName"]) { …
Run Code Online (Sandbox Code Playgroud)

swift swift-extensions

5
推荐指数
1
解决办法
2791
查看次数

如何同时使用带有可选和扩展的@objc协议?

这段代码无法编译,可能听起来很愚蠢,但我会解释为什么它如此重要!

@objc protocol p {
    optional func f1()
    func f2()
}

extension p {
    func f1() { }
    func f2() { }
}


class foo: p {
}
Run Code Online (Sandbox Code Playgroud)

编译器说Type c does not conform to protocol 'p',这可能是因为您不能同时使用 @objc 可选和扩展(并且在这种情况下也没有意义)。但请考虑以下示例:

我想在我的扩展中的协议中定义的非可选方法上设置一个选择器(我使用@objc的主要原因):

func f1() { }->func f1() { ... #selector(Self.f2) ... }

我也希望我的f2()函数具有默认行为。如果我标记f2()optional,则不能使用它,#selector因为编译器不知道该方法是否确实存在于需要的情况下。当然有很多令人讨厌的解决方法,例如全局方法、将Selectors 作为输入发送给方法等,但是有没有一种干净的方法来实现它?


这是实际问题

@objc
protocol Refreshable {
    weak var refreshControl: UIRefreshControl? { get set }
    optional func …
Run Code Online (Sandbox Code Playgroud)

protocols objective-c ios swift swift-extensions

5
推荐指数
1
解决办法
1万
查看次数

替代扩展的方法

我想UIView通过添加一些函数来扩展,并在UIView我想要的任何子类中重写它们。我在苹果文档中发现我无法覆盖扩展(编译器会抱怨),这是有道理的。所以

我需要有人提出以下替代方法:

extension UIView { 
  func hide() { //do almost nothing } 
}

class myLabel: UILabel { 
  override func hide() { 
    //do work on uilabel that can't be done on imgView
  }
}

class myImageView: UIImageView {
 override func hide() { 
    //do work on imgView that can't be done on uilabel
  }
}
Run Code Online (Sandbox Code Playgroud)

我想要这个的原因是,稍后在我的代码中我将面对下面的代码,并且我有很多子类,并且我不想编写太多if-lets尝试将其转换viewmyLabel, myTextView, myImageView... etc

let view = cell.viewWithTag(someTag)
// and I want to write this below without casting …
Run Code Online (Sandbox Code Playgroud)

ios swift swift-extensions swift-protocols

5
推荐指数
1
解决办法
743
查看次数

Swift 4:扩展数组<Optional <SomeType <T >>>生成数组<Optional <T >>可能吗?

在Swift 4中,我有一个带有这个基本前提的自定义结构:

一个包装器结构,可以包含任何符合BinaryIntegerInt,UInt8,Int16等类型的类型.

protocol SomeTypeProtocol {
    associatedtype NumberType

    var value: NumberType { get set }
}

struct SomeType<T: BinaryInteger>: SomeTypeProtocol {
    typealias NumberType = T

    var value: NumberType
}
Run Code Online (Sandbox Code Playgroud)

收藏的扩展:

extension Collection where Element: SomeTypeProtocol {
    var values: [Element.NumberType] {
        return self.map { $0.value }
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,这很好用:

let arr = [SomeType(value: 123), SomeType(value: 456)]

// this produces [123, 456] of type [Int] since literals are Int by default
arr.values
Run Code Online (Sandbox Code Playgroud)

我想做的是完全相同的事情,但是 SomeType<T>?

let arr: [SomeType<Int>?] = [SomeType(value: 123), …
Run Code Online (Sandbox Code Playgroud)

arrays generics optional swift swift-extensions

5
推荐指数
2
解决办法
708
查看次数

为 SKAudioNode 创建 SKAction 扩展

我决定结束与 SKAction.playSoundFileNamed 的痛苦关系,转而在我们的项目中使用 SKAudioNodes —— 突破点是它们完全被中断所破坏,没有任何一致性。

我们正在尝试创建 SKAction 的扩展,它将模仿播放 SKAudioNodes 而不增加延迟,类似于将 playSoundFileNamed 中的 waitForCompletion 属性设置为 false 时。但是,我们添加 SKAudioNode,然后在短时间内(3.0 秒)后将其处置,但在扩展中,这将为任何操作添加 3.0 秒的延迟。我认为我们必须有这个延迟然后删除,否则我们会不必要地积累 SKAudioNodes。这是我们当前的代码:

func playAudioNode(node: SKSpriteNode?, sound: SoundType, delay: Double)
{
    if node == nil
    {
        return
    }

    let audioNode = audioNodeDictionary[sound]!.copy() as! SKAudioNode

    node!.addChild(audioNode)

    let playSound = SKAction.run
    {
        audioNode.run(.play())
    }

    node!.run(SKAction.sequence([SKAction.wait(forDuration: delay), playSound, SKAction.wait(forDuration: 3.0), SKAction.removeFromParent()]))
}
Run Code Online (Sandbox Code Playgroud)

是否有人以类似的临时方式使用 SKAudioNodes 并在 SKAction 序列中使用它们,并且对实现此目的的最佳方法有任何想法?

sprite-kit skaction swift-extensions skaudionode

5
推荐指数
0
解决办法
145
查看次数