신속하게 클래스에서 정적 상수를 정의하는 방법


105

내 기능에 이러한 정의가 있습니다.

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() {

    }
}

"테스트"를 두 번 입력 / 입력 할 필요가없는 방법이 있습니까? 감사.


3
ViewControl.Type의 중복 가능성 에는 이름이 지정된 멤버가 없습니다 (속성의 초기 값은 다른 속성에 의존 할 수 없습니다.)
Martin R

1
CGRectMake에서 X와 Y를 복제 할 수 있습니다 (게으른 속성을 사용하는 멋진 솔루션 사용)
Martin R

""test "를 두 번 입력 / 입력하지 않아도되는 방법이 있습니까?" - 예. testStrLen의 초기화를 init 메서드 (첫 번째 가능한 중복에 대한 답변에서 제 안됨)로 이동하거나 지연 초기화를 사용합니다 (두 번째 가능한 중복에 대한 답변에서 제안 된대로).
Martin R

답변:


177

Swift에서 클래스에 대한 상수를 선언하는 좋은 관용구는 다음과 같이 MyClassConstants라는 구조체를 사용하는 것입니다.

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

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

이런 식으로 상수는 전역 적으로 떠 다니는 대신 선언 된 구조 내에서 범위가 지정됩니다.

최신 정보

정적 배열 초기화에 대한 의견에 대한 응답으로 정적 배열 상수를 추가했습니다. "Swift 프로그래밍 언어"의 배열 리터럴 을 참조하십시오 .

문자열 리터럴과 문자열 상수를 모두 사용하여 배열을 초기화 할 수 있습니다. 그러나 배열 유형이 알려져 testStrLength있으므로 배열 이니셜 라이저에서 정수 상수를 사용할 수 없습니다.


2
대신 상수를 정적 전용으로 선언 할 수 없습니까? 그렇다면 그들은 더 이상 세계적이지 않을까요?
sethfri

3
내가 열거 사용되면서 .rawValue를 사용 친다
DogCoffee

1
코드가 스위프트의 구조체가 목표 C로 번역되지 않기 때문에,뿐만 아니라 목표 C에서 사용하는 경우, 이것은 최선의 해결책이 될 수 없습니다
mbpro

1
staticin Struct과 in Classes 에서 상수 선언의 차이점은 무엇입니까 ?
Jauzee

1
@YOUNG Swift 2.2 열거 형 은 작동 할 수 있지만 일반적으로 그룹화 상수보다 더 강력한 의미 적 연관성을 갖는 열거 형입니다. 링크에서 Swift 열거 형은 관련 값과 원시 값을 모두 제공합니다. 원시 값을 사용할 수 있지만 구문은 MyClassConstants.testStr.rawValue값에 액세스하는 것이므로 구문 적으로 MyClassConstants.testStr.
Martin Woolstenhulme

72

@Martin의 답변에 추가 ...

응용 프로그램 수준을 상수 파일로 유지하려는 사람이 있으면 유형 또는 특성에 따라 상수를 그룹화 할 수 있습니다.

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

전화 : Constants.MixpanelConstants.activeScreen

업데이트 5/5/2019 (주제에서 약간 벗어 났지만 🤷🏽‍♂️)

몇 가지 코드 지침과 개인적인 경험을 읽은 후 몇 가지 이유로 구조체가 전역 상수를 저장하는 가장 좋은 방법이 아닌 것 같습니다. 특히 위의 코드는 구조체 초기화를 방해하지 않습니다. 상용구 코드를 추가하여 달성 할 수 있지만 더 나은 접근 방식이 있습니다.

ENUMS

더 안전하고 명확한 표현을 가진 열거 형을 사용하여 동일한 결과를 얻을 수 있습니다.

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

print(Constants.MixpanelConstants.activeScreen.rawValue)

2
감사합니다. 나는 이것을 좋아하고 struct를 통해 상수를 관리하는 우아한 방법을 제공합니다.
Abhijeet 2015 년

1
더 많은 예제와 나는 더 나은 방법 추가 한 여기에
아니시 Parajuli 웃

15

내가 귀하의 질문을 올바르게 이해하면 a) 모든 인스턴스에서 오버 헤드를 복제하지 않고 b 그렇지 않으면 상수를 다시 계산해야하지 않도록 클래스 수준 상수 (정적-C ++ 용어)를 만드는 방법을 묻습니다.

모든 독자가 알고 있듯이 언어는 발전해 왔지만 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

컴파일러가 바이너리의 정적 섹션에 const 변수 당 하나의 항목 만 추가하기 때문에 정적이 엄격하게 필요한지 여부는 모르겠지만 구문과 액세스에 영향을 미칩니다. static을 사용하면 인스턴스가 없어도 참조 할 수 있습니다 MyClass.testStrLen..


11

실제로 클래스의 정적 속성을 원하면 현재 Swift에서 지원되지 않습니다. 현재 조언은 전역 상수를 사용하여이 문제를 해결하는 것입니다.

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

class MyClass {
    func myFunc() {
    }
}

대신 인스턴스 속성이되도록 하려면 길이에 대해 지연 저장 속성 을 사용할 수 있습니다.이 속성 은 처음 액세스 할 때만 평가되므로 반복해서 계산하지 않습니다.

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

    func myFunc() {
    }
}

1
+1이 전역 변수보다 더 좋은 방법은없는 것 같습니다.
Drux

1
나는 이것이 현재 언어 제약이라는 것을 알고 있지만 모든 대가를 치르더라도 전역을 사용하는 것을 피하고 싶습니다. ClassNameConstants와 같은 구조 컨테이너를 사용하는 것이 지금은 더 나은 접근 방법이라고 생각합니다.
Zorayr 2015 년

7

계산 된 속성을 사용하는 것은 어떻습니까?

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

MyClass.myConstant

7

일부는 특정 클래스 상수를 공개하고 다른 일부는 비공개를 원할 수 있습니다.

private 키워드는 동일한 swift 파일 내에서 상수 범위를 제한하는 데 사용할 수 있습니다.

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's testStr=\(MyClass.Constants.testStr)")
}

} 

2

놀이터에서 시도 함


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()

이것이 질문과 어떤 관련이 있습니까?
Franklin Yu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.