簡體   English   中英

Swift數字和CGFloat(CGPoint,CGRect等)

[英]Swift numerics and CGFloat (CGPoint, CGRect, etc.)

我發現Swift數字尤其笨拙,正如在現實生活中經常發生的那樣,我必須就CGRect和CGPoint與Cocoa Touch進行溝通(例如,因為我們談論的是framebounds )。

CGFloat vs. Double

從UIViewController子類中考慮以下看似無辜的代碼:

let scale = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.size.width * scale

此代碼無法編譯,最后一行通常有神秘錯誤:

找不到接受提供的參數的'*'的重載

正如我現在所知道的那樣,這個錯誤表明類型之間存在某種阻抗不匹配。 r.size.width作為CGFloat到達,它將與Swift Float自動交換,但不能與Swift Double變量互操作(默認情況下,它是scale )。

這個例子是人為簡短的,所以有一個人為簡單的解決方案,即從一開始就將scale到Float。 但是當從所有地方抽取的許多變量都參與了CGRect元素的計算時,需要進行大量的投射。

詳細初始化器

另一個惱人的是當創建新的CGRect時會發生什么。 盡管有文檔,但沒有帶有值但沒有標簽的初始值設定項。 這無法編譯,因為我們有雙打:

let d = 2.0
var r3 = CGRect(d, d, d, d)

但即使我們將d轉換為Float,我們也不會編譯:

在調用中缺少參數標簽'x:y:width:height:'

所以我們最終會回到CGRectMake ,這對Objective-C沒有任何改進。 有時CGRectMake和CGSizeMake沒有任何改進。 請考慮我的某個應用中的實際代碼:

let kSEP : Float = 2.0
let intercellSpacing = CGSizeMake(kSEP, kSEP);

在我的一個項目中,這是有效的。 在另一個,它神秘失敗 - 完全相同的代碼! - 出現此錯誤:

'NSNumber'不是'CGFloat'的子類型

有時,Swift試圖通過將Float轉換為NSNumber來“過橋”,當橋的另一側需要CGFloat時,這當然是錯誤的。 我還沒有弄清楚導致錯誤出現在一個而不是另一個(可能是其他人有)的兩個項目之間的區別。

注意:我可能已經發現了這個問題:它似乎依賴於Build Active Architecture Only構建設置,這反過來表明它是一個64位問題。 這是有道理的,因為Float不會與64位設備上的CGFloat匹配。 這意味着阻抗不匹配問題甚至比我想象的還要糟糕。

結論

我正在尋找關於這個主題的實用智慧詞。 我想有人可能已經設計了一些CGRect和CGPoint擴展,這將使生活變得更加容易。 (或者可能有人寫了一大堆額外的算術運算符函數重載,這樣將CGFloat與Int或Double結合起來“只是工作” - 如果可能的話。)

正如您所發現的那樣,明確scaleCGFloat鍵入scale確實是處理swift中的鍵入問題的方法。 供他人參考:

let scale: CGFloat = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.width * scale

不確定如何回答您的第二個問題,您可能希望使用不同的標題單獨發布。

更新:

Swift創建者和首席開發人員Chris Lattner在2014年7月4日的Apple開發者論壇上就此問題發表了這樣的話:

這里發生的是CGFloat是Float或Double的類型,具體取決於你是構建32位還是64位。 這正是Objective-C的工作方式,但在Swift中存在問題,因為Swift不允許隱式轉換。

我們已經意識到這個問題並認為它是嚴肅的:我們現在正在評估幾種不同的解決方案,並將在稍后的測試版中推出一個。 正如您所注意到的,您可以通過強制轉換為Double來應對此問題。 這是不優雅但有效的:-)

在Xcode 6 Beta 5中更新:

CGFloat可以從任何Integer類型(包括大小的整數類型)構造,反之亦然。 (17670817)

我寫了一個處理運算符重載的庫,允許Int,CGFloat和Double之間的交互。

https://github.com/seivan/ScalarArithmetic

從Beta 5開始,這里列出了目前你無法用vanilla Swift做的事情。 https://github.com/seivan/ScalarArithmetic#sample

我建議運行帶有和不帶ScalarArithmetic的測試套件,看看是怎么回事。

我為Double和Int創建了一個擴展,它為它們添加了一個計算的CGFloatValue屬性。

extension Double {
    var CGFloatValue: CGFloat {
        get {
            return CGFloat(self)
        }
    }
}
extension Int {
    var CGFloatValue: CGFloat {
        get {
            return CGFloat(self)
        }
    }
}

您可以使用let someCGFloat = someDoubleOrInt.CGFloatValue來訪問它

另外,對於你的CGRect初始化程序,你得到了缺少的參數標簽錯誤,因為你沒有關閉標簽,你需要CGRect(x: d, y: d, width: d, height: d)你不能留下標簽除非只有一個論點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM