Подтвердить что ты не робот

Завершить CGFloat в Swift

Как я могу объединить CGFloat в Swift? Я пробовал ceil(CDouble(myCGFloat)), но это работает только на iPad Air и iPhone 5S.

При запуске на другом симулированном устройстве я получаю сообщение об ошибке 'NSNumber' is not a subtype of 'CGFloat'

4b9b3361

Ответ 1

Обновление. Теперь Apple определила некоторые версии общих функций CGFloat, таких как ceil:

func ceil(x: CGFloat) -> CGFloat

... специально для того, чтобы справиться с 32/64-битной разницей. Если вы просто используете ceil с аргументом CGFloat, он должен теперь работать на всех архитектурах.

Мой оригинальный ответ:

Это довольно ужасно, я думаю, но может ли кто-нибудь подумать о лучшем пути? #if, похоже, не работает для CGFLOAT_IS_DOUBLE; Я думаю, что вы ограничены созданием конфигураций, из чего я вижу в документации для условной компиляции.

var x = CGFloat(0.5)

#if arch(x86_64) || arch(arm64)
var test = ceil(x)
#else
var test = ceilf(x)
#endif

Ответ 2

С Swift 5 вы можете выбрать один из 3 следующих путей, чтобы округлить CGFloat.


# 1. Использование CGFloat rounded(_:) CGFloat rounded(_:)

Протокол FloatingPoint предоставляет типы, которые ему соответствуют, rounded(_:) метод. CGFloat rounded(_:) имеет следующее объявление:

func rounded(_ rule: FloatingPointRoundingRule) -> CGFloat

Возвращает это значение, округленное до целого значения, используя указанное правило округления.

Пример кода Playground ниже показывает, как использовать rounded(_:) для CGFloat значения CGFloat:

import CoreGraphics

let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1

let roundedValue1 = value1.rounded(.up)
let roundedValue2 = value2.rounded(.up)
let roundedValue3 = value3.rounded(.up)
let roundedValue4 = value4.rounded(.up)
let roundedValue5 = value5.rounded(.up)
let roundedValue6 = value6.rounded(.up)

print(roundedValue1) // prints -0.0
print(roundedValue2) // prints -0.0
print(roundedValue3) // prints -1.0
print(roundedValue4) // prints 1.0
print(roundedValue5) // prints 1.0
print(roundedValue6) // prints 1.0

# 2. Использование функции ceil(_:)

Дарвин предоставляет функцию ceil(_:) которая имеет следующее объявление:

func ceil<T>(_ x: T) -> T where T : FloatingPoint

Код Playground ниже показывает, как использовать ceil(_:) для CGFloat значения CGFloat:

import CoreGraphics

let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1

let roundedValue1 = ceil(value1)
let roundedValue2 = ceil(value2)
let roundedValue3 = ceil(value3)
let roundedValue4 = ceil(value4)
let roundedValue5 = ceil(value5)
let roundedValue6 = ceil(value6)

print(roundedValue1) // prints -0.0
print(roundedValue2) // prints -0.0
print(roundedValue3) // prints -1.0
print(roundedValue4) // prints 1.0
print(roundedValue5) // prints 1.0
print(roundedValue6) // prints 1.0

# 3. Использование NumberFormatter

Если вы хотите округлить CGFloat и отформатировать его со стилем в той же операции, вы можете использовать NumberFormatter.

import Foundation
import CoreGraphics

let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1

let formatter = NumberFormatter()
formatter.numberStyle = NumberFormatter.Style.decimal
formatter.roundingMode = NumberFormatter.RoundingMode.ceiling
formatter.maximumFractionDigits = 0

let roundedValue1 = formatter.string(for: value1)
let roundedValue2 = formatter.string(for: value2)
let roundedValue3 = formatter.string(for: value3)
let roundedValue4 = formatter.string(for: value4)
let roundedValue5 = formatter.string(for: value5)
let roundedValue6 = formatter.string(for: value6)

print(String(describing: roundedValue1)) // prints Optional("-0")
print(String(describing: roundedValue2)) // prints Optional("-0")
print(String(describing: roundedValue3)) // prints Optional("-1")
print(String(describing: roundedValue4)) // prints Optional("1")
print(String(describing: roundedValue5)) // prints Optional("1")
print(String(describing: roundedValue6)) // prints Optional("1")

Ответ 3

Наиболее правильным синтаксисом, вероятно, будет:

var f: CGFloat = 2.5
var roundedF = CGFloat(ceil(Double(f)))

Чтобы использовать ceil, я сначала сделаю CGFloat a Double и после потолка, я верну его обратно в CGFloat.

Это работает, когда CGFloat определяется как CFloat или CDouble.

Вы также можете определить ceil для float (Это было фактически реализовано в Swift 2):

func ceil(f: CFloat) -> CFloat {
   return ceilf(f)
}

Затем вы сможете напрямую позвонить

var roundedF: CGFloat = ceil(f)

при сохранении безопасности типов.

Я действительно считаю, что это должно быть решение, выбранное Apple, вместо отдельных функций ceil и ceilf, потому что они не имеют смысла в Swift.

Ответ 5

Создание holex-ответа. Я сделал

func accurateRound(value: Double) -> Int {

            var d : Double = value - Double(Int(value))

            if d < 0.5 {
                return Int(value)
            } else {
                return Int(value) + 1
            }
        }

-edit edition -

Я также недавно превратил это в расширение для Floats, которое я бы разделил:)

extension Float {
    func roundToInt() -> Int{
        var value = Int(self)
        var f = self - Float(value)
        if f < 0.5{
            return value
        } else {
            return value + 1
        }
    }
}

Это делает так, чтобы вы могли просто выглядеть как

var f : Float = 3.3
f.roundToInt()

Ответ 6

Используйте его на Swift 5

let x = 6.5

// Equivalent to the C 'round' function:
print(x.rounded(.toNearestOrAwayFromZero))
// Prints "7.0"

// Equivalent to the C 'trunc' function:
print(x.rounded(.towardZero))
// Prints "6.0"

// Equivalent to the C 'ceil' function:
print(x.rounded(.up))
// Prints "7.0"

// Equivalent to the C 'floor' function:
print(x.rounded(.down))
// Prints "6.0"