Как определить статическую константу в классе в swift

У меня есть это определение в моей функции, которые работают

class MyClass {
    func myFunc() {
        let testStr = "test"
        let testStrLen = countElements(testStr)
    }
}

Но если я переведу 'testStr' и 'testStrLen' на уровень класса, он не будет компилироваться. Он сказал: "MyClass.Type не имеет члена с именем" testStr ".

class MyClass {
    let testStr = "test"
    let testStrLen = countElements(testStr)

    func myFunc() {

    }
}

Как я могу это исправить? Я не хочу платить штраф за подсчет len от постоянного "теста" каждый раз.

Основываясь на моем понимании приведенных ниже комментариев, мне нужно сделать следующее:

class MyClass {
    let testStr = "test"
    let testStrLen = countElements("test")

    func myFunc() {

    }
}

Есть ли способ, которым мне не нужно дважды вводить "тест"? Спасибо.

Ответ 1

Возможно, приятная идиома для объявления констант для класса в Swift заключается в том, чтобы просто использовать структуру с именем MyClassConstants, как показано ниже.

struct MyClassConstants{
    static let testStr = "test"
    static let testStrLength = countElements(testStr)

    static let arrayOfTests: [String] = ["foo", "bar", testStr]
}

Таким образом, ваши константы будут помещаться внутри объявленной конструкции, а не плавать по всему миру.

Update

Я добавил константу статического массива в ответ на комментарий, спрашивающий о статической инициализации массива. См. Литералы массивов в разделе "Быстрый язык программирования".

Обратите внимание, что для инициализации массива могут использоваться как строковые литералы, так и строковая константа. Однако, поскольку тип массива известен, целочисленная константа testStrLength не может использоваться в инициализаторе массива.

Ответ 2

Добавление к @Martin ответа...

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

struct Constants {
    struct MixpanelConstants {
        static let activeScreen = "Active Screen";
    }
    struct CrashlyticsConstants {
        static let userType = "User Type";
    }
}

Вызов: Constants.MixpanelConstants.activeScreen

ОБНОВЛЕНИЕ 5/5/2019 (вроде не по теме, но 🤷🏽‍♂️)

После прочтения некоторых рекомендаций по коду и из личного опыта кажется, что структуры - не лучший подход для хранения глобальных констант по нескольким причинам. Особенно приведенный выше код не препятствует инициализации структуры. Мы можем достичь этого, добавив некоторый шаблонный код, но есть лучший подход

Перечисления

То же самое может быть достигнуто с помощью enum с более безопасным и ясным представлением

enum Constants {
    enum MixpanelConstants: String {
        case activeScreen = "Active Screen";
    }
    enum CrashlyticsConstants: String {
        case userType = "User Type";
    }
}

print(Constants.MixpanelConstants.activeScreen.rawValue)

Ответ 3

Если я правильно понимаю ваш вопрос, вы спрашиваете, как создать константы уровня класса (static - на языке С++), чтобы вы не а) не реплицировали накладные расходы в каждом экземпляре, а b должны были перекомпоновать то, что в противном случае константа.

Язык развился - как знает каждый читатель, но по мере того как я проверяю это в Xcode 6.3.1, решение:

import Swift

class MyClass {
    static let testStr = "test"
    static let testStrLen = count(testStr)

    init() {
        println("There are \(MyClass.testStrLen) characters in \(MyClass.testStr)")
    }
}

let a = MyClass()

// -> There are 4 characters in test

Я не знаю, строго ли статично, поскольку компилятор, конечно же, добавляет только одну запись в константную переменную в статический раздел двоичного файла, но это влияет на синтаксис и доступ. Используя static, вы можете ссылаться на него, даже если у вас нет экземпляра: MyClass.testStrLen.

Ответ 4

Если вы действительно хотите статическое свойство своего класса, которое в настоящее время не поддерживается в Swift. В настоящее время советуем обойти это, используя глобальные константы:

let testStr = "test"
let testStrLen = countElements(testStr)

class MyClass {
    func myFunc() {
    }
}

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

class MyClass {
    let testStr: String = "test"
    lazy var testStrLen: Int = countElements(self.testStr)

    func myFunc() {
    }
}

Ответ 5

Как насчет использования вычисленных свойств?

class MyClass {
  class var myConstant: String { return "What is Love? Baby don't hurt me" }
}

MyClass.myConstant

Ответ 6

Некоторые могут хотеть, чтобы определенные константы класса были общедоступными, а другие - частными.

личное ключевое слово может использоваться для ограничения объема констант в одном и том же файле быстрого доступа.

class MyClass {

struct Constants {

    static let testStr = "test"
    static let testStrLen = testStr.characters.count

    //testInt will not be accessable by other classes in different swift files
    private static let testInt = 1
}

func ownFunction()
{

    var newInt = Constants.testInt + 1

    print("Print testStr=\(Constants.testStr)")
}

}

Другие классы смогут получить доступ к вашим константам класса, как показано ниже

class MyClass2
{

func accessOtherConstants()
{
    print("MyClass testStr=\(MyClass.Constants.testStr)")
}

} 

Ответ 7

Пробовал на игровой площадке


class MyClass {

struct Constants {

    static let testStr = "test"
    static let testStrLen = testStr.characters.count

    //testInt will not be accessable by other classes in different swift files
    private static let testInt = 1

    static func singletonFunction()
    {
        //accessable
        print("Print singletonFunction testInt=\(testInt)")

        var newInt = testStrLen
        newInt = newInt + 1
        print("Print singletonFunction testStr=\(testStr)")
    }
}

func ownFunction() {
    //not accessable
    //var newInt1 = Constants.testInt + 1

    var newInt2 = Constants.testStrLen
    newInt2 = newInt2 + 1
    print("Print ownFunction testStr=\(Constants.testStr)")
    print("Print ownFunction newInt2=\(newInt2)")
}
}


let newInt = MyClass.Constants.testStrLen
print("Print testStr=\(MyClass.Constants.testStr)")
print("Print testInt=\(newInt)")


let myClass = MyClass()
myClass.ownFunction()
MyClass.Constants.singletonFunction()