Swift에서 네임 스페이스를 사용하는 방법은 무엇입니까?


144

설명서에는 중첩 형식 만 언급되어 있지만 네임 스페이스로 사용할 수 있는지 확실하지 않습니다. 네임 스페이스에 대한 명시 적 언급을 찾지 못했습니다.


iBook을 빠르게 Ctrl-F로 검색하면 네임 스페이스의 인스턴스가 표시되지 않습니다.
Justin Niessner

1
이 질문이 왜 종결되는지 모르겠습니다. Swift 아이콘의 왼쪽에있는 기조 연설에서 네임 스페이스 를 보았지만 여전히 설명서에서 언급을 찾을 수 없습니다 ...
eonil

나는 이것에 대한 정보를 찾을 수 없었습니다 .Google 은이 질문으로 이끌었습니다 :). 아마도 WWDC 세션 중 하나가 이것에 대해 조금 더 밝을 것입니다.
Zyphrax

또한 WWDC의 누군가가 좋은 설명을 내기를 기다리고 있습니다.
eonil

Eonil의 대답은 맞습니다. Xcode에서 모듈을 사용하여 클래스를 분리하십시오.
Zyphrax

답변:


113

Apple dev 포럼 에서 SevenTenEleven 님이 답변 함 :

네임 스페이스는 파일 단위가 아닙니다. 대상별로 설정되어 있습니다 ( "제품 모듈 이름"빌드 설정 기준). 따라서 다음과 같은 결과가 나타납니다.

import FrameworkA
import FrameworkB

FrameworkA.foo()

모든 Swift 선언은 일부 모듈의 일부로 간주되므로 " NSLog"(예, 여전히 존재 함) 라고 말하더라도 Swift가 " Foundation.NSLog" 로 생각하는 것을 얻습니다 .

또한 Chris Lattner 는 네임 스페이스에 대해 트윗했습니다 .

네임 스페이스는 Swift에 내재되어 있으며 모든 클래스 (등)는 내부에있는 모듈 (Xcode 대상)에 의해 내재적으로 범위가 지정됩니다. 클래스 접두사가 필요하지 않습니다.

내가 생각했던 것과는 매우 다른 것 같습니다.


6
애플 데브 (Apple Dev) 포럼 ... 나는 당신이 믿지 못할 많은 tumbleweed를 보았습니다!
Nicolas Miari

1
Apple 개발 포럼에 대한 링크가 끊어졌으며 forums.developer.apple.com, 불행히도 Apple은 해당 스레드를 새 포럼 사이트 로 가져 오지 않았습니다 .
Dai

2
@Dai 그것이 우리가 Q & A를위한 Apple 포럼을 피해야하는 이유 인 것 같습니다 ...하지만 핵심 개발자 팀 멤버들은 그렇게 신경 쓰지 않는 것 같습니다. 참 비극이야
eonil

1
tumbleweed의 의미는 무엇입니까?
Alexander Mills

148

나는 스위프트의 이름이 감동적이라고 묘사 할 것이다. 그것은 지상에서 의미있는 현실에 해당하지 않는 많은 광고가 주어졌습니다.

예를 들어, WWDC 비디오는 가져 오는 프레임 워크에 MyClass 클래스가 있고 코드에 MyClass 클래스가있는 경우 "name mangling"이 다른 내부 이름을 제공하므로 해당 이름이 충돌하지 않는다고 명시되어 있습니다. 그러나 실제로는, 그들은 어떻게 자신의 코드의 MyClass의 승리는, 당신은 지정할 수 없습니다 "아니 아니, 난 프레임 워크에서 MyClass의 의미"한다는 의미에서, 충돌 - 말을 TheFramework.MyClass하지 작업 (컴파일러 당신이 무슨 뜻인지 알고 않습니다 그러나 프레임 워크에서 그러한 클래스를 찾을 수 없다고 말합니다.

내 경험에 따르면 Swift는 네임 스페이스가 가장 작습니다. 내 앱 중 하나를 Objective-C에서 Swift로 전환 할 때 매우 쉽고 멋진 임베디드 프레임 워크를 만들었습니다. 그러나 프레임 워크를 임포트하면 프레임 워크에있는 모든 Swift 컨텐츠를 임포트합니다. 따라서 다시 한 번, 네임 스페이스가 하나만 있고 글로벌입니다. 그리고 Swift 헤더가 없으므로 이름을 숨길 수 없습니다.

편집 : 시드 3 에서이 기능은 이제 다음과 같은 의미에서 온라인으로 제공되기 시작합니다. 기본 코드에 MyClass가 있고 프레임 워크 MyFramework에 MyClass가 있으면 전자가 기본적으로 후자를 어둡게하지만 프레임 워크에서 하나에 도달 할 수 있습니다 구문을 사용하여 MyFramework.MyClass. 따라서 우리는 실제로 별개의 네임 스페이스의 기초를 가지고 있습니다!

편집 2 : 시드 4에는 이제 액세스 제어가 있습니다! 또한 내 앱 중 하나에 임베디드 프레임 워크가 있으며 모든 것이 기본적으로 숨겨져 있으며 공개 API의 모든 비트를 명시 적으로 노출해야했습니다. 이것은 큰 개선입니다.


4
이 답변에 감사드립니다. 프레임 워크뿐만 아니라 표준 라이브러리에서도 작동합니다. 예를 들어 어레이를 "덮어 쓰기"할 수 있습니다. 그런 다음 "배열"은 사용자 정의 배열 클래스를 나타내며 표준 라이브러리의 배열은 "Swift.Array"로 제공됩니다.
George

3
@George 그리고 NSArray와 비슷하다; 그것을 어둡게해도 여전히로 참조 할 수 있습니다 Foundation.NSArray.
matt

1
베타에서 네임 스페이스에 대한 생각의 역사를 정리할 필요가 없습니다.이 답변은 어디에 있습니까?
Dan Rosenstark

1
수정 사항에 명시된대로 @Yar. 모호성이있는 경우 모듈 이름은 선택적 네임 스페이스이며 개인 정보 보호 기능이 있으므로 모듈 이름이 노출되지 않고 파일에 제한 될 수없는 한 모듈 이름이 숨겨집니다.
matt

2
이것은 오랫동안 저를 괴롭 혔습니다 .Swift 프로젝트는 Apple이 주장하는 이유로 인해 접두사를 사용하지 않아야하는 것처럼 보이지만 현재 액세스 수정자를 사용하더라도 접두사가 여전히 필요합니다. Apple 프레임 워크에서 패키지 또는 개인 클래스와 충돌하지 않지만 String과 같이 공개로 선언 된 모든 항목은 다시 선언하거나 새 클래스를 선언하면 물론 습관을 잃지 않는 한 사용자 클래스를 사용하게됩니다. 네임 스페이스가있는 모든 클래스를 참조하십시오 .... 좋은 imo는 아닙니다.
Oscar Gomez

19

이것으로 약간의 실험을하면서 루트 "패키지"를 확장하여 자신의 파일에 이러한 "네임 스페이스"클래스를 만들었습니다. 이것이 모범 사례에 위배되는지 또는 내가 알 수있는 의미가 있는지 확실하지 않습니다 (?)

AppDelegate.swift

var n1 = PackageOne.Class(name: "Package 1 class")
var n2 = PackageTwo.Class(name: "Package 2 class")

println("Name 1: \(n1.name)")
println("Name 2: \(n2.name)")

PackageOne.swift

import Foundation

struct PackageOne {
}

패키지

import Foundation

struct PackageTwo {
}

PackageOneClass.swift

extension PackageOne {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

PackageTwoClass.swift

extension PackageTwo {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

편집하다:

위의 코드에서 "하위 패키지"를 생성하면 별도의 파일을 사용할 경우 작동하지 않는다는 것을 알았습니다. 어쩌면 누군가가 왜 그런지 암시 할 수 있습니까?

위의 파일을 추가 :

PackageOneSubPackage.swift

import Foundation

extension PackageOne {
    struct SubPackage {
    }
}

PackageOneSubPackageClass.swift

extension PackageOne.SubPackage {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

컴파일러 오류가 발생합니다 : 'SubPackage'는 'PackageOne'의 멤버 유형이 아닙니다.

PackageOneSubPackageClass.swift에서 PackageOneSubPackage.swift로 코드를 이동하면 작동합니다. 누군가?

편집 2 :

이 문제를 해결하면서 (Xcode 6.1 베타 2에서) 하나의 파일에 패키지를 정의하면 별도의 파일로 확장 할 수 있음을 알았습니다.

public struct Package {
  public struct SubPackage {
    public struct SubPackageOne {
    }
    public struct SubPackageTwo {
    }
  }
}

요점에 내 파일이 있습니다 : https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8


흥미 롭습니다. 테스트는 어땠나요?
user2727195

2
"testing"이 무슨 뜻인지 잘 모르겠지만 위의 기술을 사용하여 앱을 빌드하기 시작했으며 위의 항목에 추가 한주의 사항으로 지금까지 잘 작동하는 것 같습니다. Im은 다른 언어로 내 코드를 이런 식으로 구성하는 데 익숙했기 때문에 주로하고 있으며 더 많은 지식을 가진 사람이 나에게 너무 나아갈 때까지 나쁜 생각을 말할 수 있다면 감사 할 것입니다! :)
bWlrYWphdWhvbmVu 2016 년

1
계속해라 .. 이것은 우리가 원하는 것이다. 존재하고 참조 할 수 있도록 (더 중요한 것은 다른 파일) 두 개의 다른 패키지에 같은 이름 클래스를 가질 수 있고 그것이 작동하지 않으면 전체 네임 스페이스의 아이디어는 플롭 아이디어입니다 ...
user2727195

네임 스페이스를 해킹하는 방법으로 "struct"를 사용하는 부작용이 있습니까?
Alex Nolasco

그런 성능과 관련하여 내가 만난 것은 아닙니다. Xcode (6.1 GM)는 드물게 존재하지 않는 유형을 불평하는 경우도 있지만 이와 같은 코드를 구성하지 않을 때도 마찬가지입니다. 최근에 테스트 대상에 모든 파일을 추가하여 하나의 문제를 해결했지만 아무런 의미가 없지만 문제를 해결했습니다. :)
bWlrYWphdWhvbmVu

12

나는 이것이 다음을 사용하여 달성된다고 생각합니다.

struct Foo
{
    class Bar
    {
    }
}

그런 다음 다음을 사용하여 액세스 할 수 있습니다.

var dds = Foo.Bar();

1
나는 네임 스페이스가 수행되는 방식에 여전히 만족하지 않습니다 ... 네 네임 스페이스에 10 개의 다른 클래스가 있고 그 위에 개별 파일에 클래스를 유지하는 것을 선호한다면 어떻게해야합니까? 모든 수업과 함께 파일 / 구조, 모든 제안 케빈.
user2727195

2
패키지를 포함하지 않았다고 생각하는 이유가 궁금합니다. 네임 스페이스가 아닌 우리가 필요로하는 것입니다. Java, C #, ActionScript와 같은 다른 고급 언어를 보면 모두 패키지가 있습니다.이 컨텍스트의 네임 스페이스는 NS를 사용하는 것과 전혀 다릅니다. 또는 프로젝트 클래스의 다른 접두사
user2727195 2016

1
네임 스페이스를 해킹하는 방법으로 구조체를 사용하면 알 수없는 문제가 발생할 수 있는지 궁금합니다.
Alex Nolasco

1
이것은 좋은 해결 방법입니다. 나는이 접근법을 사용하려고 시도했지만 즉시 중지해야했습니다. 뷰 관련 클래스 (CustomTableViewCell이라고 함)를 네임 스페이스로 만들려고 할 때 인터페이스 빌더의 자동 완성 기능이 제안하지 않았습니다. 이 방법을 사용한 경우 뷰의 클래스 이름을 수동으로 복사하여 붙여 넣어야합니다.
ArG

1
보통은 사용하는 거라고 enum아닌를 struct당신이 인스턴스화 할 수 있도록 Foo.
Kevin

7

Swift는 파이썬과 매우 유사한 모듈을 사용하며 ( 여기여기 참조 ) @Kevin Sylvestre가 제안한 것처럼 중첩 유형을 사용할 수도 있습니다 것처럼 을 네임 스페이스로 .

그리고 @Daniel A. White의 답변을 확장하기 위해 WWDC에서 그들은 모듈에 대해 신속하게 이야기했습니다.

또한 여기 에 설명되어 있습니다 :

유추 된 형식은 코드를 더 깨끗하고 실수가 덜 발생하는 반면 모듈은 헤더를 제거하고 네임 스페이스를 제공합니다.


2
두 번째 링크 6.4 패키지 (Python)에서 언급 한 것처럼 구문과 같은 패키지를 찾고 있는데 중첩 된 유형의 네임 스페이스는 멀리 걸릴 수 없습니다 .10 개의 다른 클래스와 다른 파일의 네임 스페이스에 있거나 꾸러미???
user2727195

7
  • 네임 스페이스는 기존 프레임 워크의 클래스 이름 이 같은 클래스를 정의해야 할 때 유용합니다 .

  • 앱에 MyApp이름이 있고 custom을 선언해야 한다고 가정하십시오 UICollectionViewController.

다음 과 같이 접두사와 하위 클래스를 지정할 필요가 없습니다 .

class MAUICollectionViewController: UICollectionViewController {}

다음과 같이하십시오 :

class UICollectionViewController {} //no error "invalid redeclaration o..."

왜? . 당신이 선언 선언 한 일 때문에 현재 모듈 입니다, 당신의 현재 대상 . 그리고 UICollectionViewControllerfrom UIKitUIKit모듈에 선언되어 있습니다.

현재 모듈 내에서 사용하는 방법?

var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit

다른 모듈과 구별하는 방법은 무엇입니까?

var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit

3

오른쪽으로 모든 코드를 들여 쓰지 않고도 네임 스페이스에 대해 extension언급 된 struct접근 방식 을 사용할 수 있습니다 . 나는 이것을 조금 가지고 놀았고 아래 예제와 같이 네임 스페이스 ControllersViews네임 스페이스 를 만들지 확실 하지 않지만 얼마나 멀리 갈 수 있는지 보여줍니다.

Profiles.swift :

// Define the namespaces
struct Profiles {
  struct Views {}
  struct ViewControllers {}
}

프로파일 /ViewControllers/Edit.swift

// Define your new class within its namespace
extension Profiles.ViewControllers {
  class Edit: UIViewController {}
}

// Extend your new class to avoid the extra whitespace on the left
extension Profiles.ViewControllers.Edit {
  override func viewDidLoad() {
    // Do some stuff
  }
}

프로필 / 뷰 / 편집 .swift

extension Profiles.Views {
  class Edit: UIView {}
}

extension Profiles.Views.Edit {
  override func drawRect(rect: CGRect) {
    // Do some stuff
  }
}

아직이 수준의 분리가 필요하지 않았으므로 앱에서 이것을 사용하지 않았지만 흥미로운 아이디어라고 생각합니다. 이로 인해 유비쿼터스 * ViewController 접미사와 같은 클래스 접미사가 필요하지 않습니다.

그러나 다음과 같은 메소드 매개 변수와 같이 참조 할 때 아무것도 단축하지 않습니다.

class MyClass {
  func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
    // secret sauce
  }
}

2

2014 년 6 월 10 일 현재 궁금한 점이 있으면 Swift의 알려진 버그입니다.

에서 SevenTenEleven

"알려진 버그, 죄송합니다. rdar : // problem / 17127940 해당 Swift 유형의 모듈 이름으로 작동하지 않습니다."


아래 @ 매트의 게시물에 따르면, 이것은 현재 Swift의 알려진 버그입니다.
Adam Venturella

이것은 베타 3 (2014 년 7 월 7 일 릴리스)에서 수정되었습니다
Adam Venturella
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.