Xcode 8 Beta 4 CGColor.components 不可用

Posted

技术标签:

【中文标题】Xcode 8 Beta 4 CGColor.components 不可用【英文标题】:Xcode 8 Beta 4 CGColor.components unavailable 【发布时间】:2016-08-04 13:52:56 【问题描述】:

虽然下面的代码以前可以工作,但它在 Xcode 8 Beta 4 中已停止工作,可能是因为 components 返回的浮点数非常不符合 Swift-y C 数组,因此已被删除。错误很明显——“'组件'不可用”——我找不到替换它的东西,如果有的话。有谁知道如何产生相同的功能?

public var cgColour: CGColor 
    get 
        return CGColor(red: self.colourRed, green: self.colourGreen, blue: self.colourBlue, alpha: self.colourAlpha)
    
    set 
        let comps = newValue.components // No longer available
        self.colourRed = (comps?[0])!
        self.colourGreen = (comps?[1])!
        self.colourBlue = (comps?[2])!
        self.colourAlpha = (comps?[3])!
    

更新 @Hamish 的回答有效,但我的初衷不是使用 UIColor 或 NSColor ,以便我的代码在 ios 和 MacOS 中都可以使用。我最终做的是这个......

#if os(iOS)
import UIKit
#elseif os(OSX)
import Cocoa
#endif

extension CGColor 
    var components: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) 
        var r: CGFloat = 0
        var g: CGFloat = 0
        var b: CGFloat = 0
        var a: CGFloat = 0
        #if os(iOS)
            UIColor(cgColor: self).getRed(&r, green: &g, blue: &b, alpha: &a)
        #elseif os(OSX)
            NSColor(cgColor: self)?.getRed(&r, green: &g, blue: &b, alpha: &a)
        #endif
        return (r, g, b, a)
    

// Playground code to test...
#if os(iOS)
let rgba = UIColor.brown.cgColor.components //(0.6, 0.4, 0.2, 1.0)
#elseif os(OSX)
let rgba = NSColor.brown.cgColor.components //(0.6, 0.4, 0.2, 1.0)
#endif

...这是一个这样的组合 - 有人有更好的答案吗?

【问题讨论】:

developer.apple.com/reference/spritekit/skcolor 好主意 - 但实际上 CIColor 是一个更好的调用,因为 SKColor 没有直接从 CGColor 初始化,而 CIColor 有,并且还有 .red.green.blue.alpha特性。你想这样回答吗? @LeoDabus SKColor 的唯一问题是它只是一个类型别名,所以 AFAIK 你不能使用它来解决NSColorinit?(cgColor:) 是失败的事实,而UIColorinit(cgColor:) 不是。因此,您最终仍然不得不使用条件编译语句(一个带有可选链,一个没有)。 CIColor 看起来确实不错。 【参考方案1】:

这看起来像是一个过渡性测试版问题。

Github 上的 Swift 存储库包含一个 extensive SDK overlay for CoreGraphics,其中包括一个新版本的 CGColor.components,其返回类型是 Swift 数组而不是 UnsafePointer。他们使 SDK 覆盖工作的部分原因是 API notes,它将一些底层 C 调用映射到双下划线的 Swift 方法,以便覆盖可以将它们包装在更 Swifty 的接口中。

看起来 beta 4 和 beta 5 编译器接受了 API 注释的更改,但没有包含新版本 components 的覆盖。据推测,未来的测试版(或最终的 Swift 3.0 / Xcode 8.0 版本)将包括现在在 github 上的所有内容。

【讨论】:

【参考方案2】:

@Hamish 的回答有效,但我最初的意图是 使用 UIColorNSColor 以便我的代码在 iOS 和 MacOS 中都有效。 @LeoDabus 建议使用SKColor,但这只是NSColorUIColor 的类型别名,无论如何都没有来自CGColor 的直接初始化,但是,Leo 的建议促使我使用 CIColor 改为:

import CoreImage

extension CGColor 
    var components: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) 
        let ciColor = CIColor(cgColor: self)
        return (ciColor.red, ciColor.green, ciColor.blue, ciColor.alpha)
    

【讨论】:

这绝对看起来是最好的解决方案 (+1) - 尽管 IMO 仍然觉得在另一个实例中包装 CGColor 只是为了访问颜色组件有点不满意。我希望 Apple 正在开发更好的界面以直接从 CGColor 获取颜色组件,但我想我们将不得不等待,看看 Xcode 8 beta 5 带来了什么(如果有的话)。【参考方案3】:

我也有点困惑为什么他们从CGColor 中删除了components 属性,因为似乎没有任何明显的替换方法/属性。 看起来他们正试图让人们改用更高级别的 UIColorNSColor 类。(作为 @rickster has discovered,这看起来更像是一个简单的过渡问题)。 p>

当您使用 RGB 颜色时,一种解决方案是简单地将您的 CGColor 包装在 UIColor/NSColor 中,然后使用 getRed(_:green:blue:alpha:) 方法取出组件。

public var cgColour : CGColor 
    get 
        return CGColor(red: colourRed, green: colourGreen, blue: colourBlue, alpha: colourAlpha)
    
    set 
        NSColor(cgColor: newValue)?.getRed(&colourRed, green: &colourGreen, blue: &colourBlue, alpha: &colourAlpha)
    

也许不是最理想的解决方案——当然会很想知道是否有其他人有更好的解决方案,或者对这种变化有更多的了解。根据此属性的使用情况,您可能还需要考虑简单地将其设为 UIColor/NSColor 类型,以防止此解决方案所需的不必要的包装。

【讨论】:

嗯。我使用 CGColor(通常是 Core Graphics)的原因是拥有与平台无关的代码...... @Grimxn 好吧...我不确定我能否为您提供与平台无关的解决方案——因为这种变化似乎没有得到很好的记录(如果有的话!)。我会在这里留下我的答案,以防它对其他人有用,并希望其他人提出更好的主意:) 我暂时不接受你的回答,看看有没有其他人回答...对不起! @Grimxn 没问题,我也很想看看是否有人有更好的解决方案:) 我在移植一个库时遇到了同样的事情。我没有其他解决方案,只是想感谢@Hamish 的回答。【参考方案4】:

我可能弄错了什么,但你可以在 CGColor 的导入标头中找到它。

/* Return the color components (including alpha) associated with `color'. */

@available(OSX 10.3, *)
public var __unsafeComponents: UnsafePointer<CGFloat>?  get 

这不是你要找的吗?

我可以这样写:

public var cgColour: CGColor 
    get 
        return CGColor(red: self.colourRed, green: self.colourGreen, blue: self.colourBlue, alpha: self.colourAlpha)
    
    set 
        if let comps = newValue.__unsafeComponents, newValue.numberOfComponents == 4 
            self.colourRed = comps[0]
            self.colourGreen = comps[1]
            self.colourBlue = comps[2]
            self.colourAlpha = comps[3]
        
    

它按我的预期工作,但我不确定它是否如你所愿,否则 Apple 会将其视为使用私有 API。 (Apple's latest documentation of CGColor 不包含双下划线前导符号。)

【讨论】:

看起来很像!【参考方案5】:
extension UIColor 
    var all4Components:(red:CGFloat, green:CGFloat, blue: CGFloat, alpha:CGFloat) 
    let components = self.cgColor.components!
    let red = components[0]
    let green = components[1]
    let blue = components[2]
    let alpha = components[3]
    return (red:red, green:green, blue: blue, alpha:alpha)

    

【讨论】:

以上是关于Xcode 8 Beta 4 CGColor.components 不可用的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 8 Beta 4 CGColor.components 不可用

在 Xcode 8 beta 4 中,隐式展开的选项数组永远迭代

Xcode 8 beta 4:在物理设备上运行时“无法附加到 pid:1110”

iPhone 升级到 iOS 8.4 后在 Xcode 7 beta2 中成为不合格设备

Xcode 8 Beta 6 不支持 iOS 10 Beta 7 sdk

Xcode 8 beta 6 中的 performActionForShortcutItem