Dokumentacja wspomina tylko o typach zagnieżdżonych, ale nie jest jasne, czy można ich używać jako przestrzeni nazw. Nie znalazłem żadnej wyraźnej wzmianki o przestrzeniach nazw.
Szybkie przeszukiwanie ich iBooka z wciśniętym klawiszem Ctrl-F nie pokazuje żadnych instancji przestrzeni nazw ... więc wybieram bez?
Justin Niessner
1
Nie wiem, dlaczego to pytanie jest zamknięte. Widziałem przestrzeń nazw w keynote po lewej stronie ikony Swift i nadal nie mogę znaleźć żadnej wzmianki w dokumentacji ...
eonil
Nie mogłem znaleźć żadnych informacji na ten temat, Google doprowadziło mnie do tego pytania :). Być może jedna z sesji WWDC rzuci nieco więcej światła na to.
Zyphrax
Czekam też, aż ktoś z WWDC przedstawi miłe wyjaśnienie.
eonil
Odpowiedź Eonila jest poprawna. Używasz modułów w Xcode do rozdzielania klas.
Zyphrax
Odpowiedzi:
113
Odpowiedział SevenTenEleven na forum deweloperów Apple :
Przestrzenie nazw nie są przypisane do poszczególnych plików; są dla celu (na podstawie ustawienia kompilacji „Nazwa modułu produktu”). Więc skończyłbyś z czymś takim:
importFrameworkAimportFrameworkBFrameworkA.foo()
Wszystkie deklaracje Swift są uważane za część jakiegoś modułu, więc nawet gdy powiesz „ NSLog” (tak, nadal istnieje), otrzymujesz to, o czym Swift myśli jako „ Foundation.NSLog”.
Przestrzenie nazw są niejawne w Swift, wszystkie klasy (itp.) Są niejawnie określane przez moduł (cel Xcode), w którym się znajdują. Nie są potrzebne przedrostki klas
Wydaje się, że bardzo różni się to, o czym myślałem.
Fora Apple Dev ... Widziałem tam tak wiele tumbleweedów, że nie uwierzysz!
Nicolas Miari
1
Łącze do forów deweloperów Apple jest teraz zepsute, a Apple niestety nie zaimportowało tego wątku do nowej forums.developer.apple.comwitryny forów.
Dai
2
@Dai Wydaje się, że dlatego powinniśmy unikać forów Apple w poszukiwaniu pytań i odpowiedzi ... Ale członkowie zespołu programistów nie przejmują się zbytnio SO. Co za tragedia.
eonil
1
co masz na myśli mówiąc przez tumbleweed?
Alexander Mills,
148
Przestrzenie nazw Swifta opisałbym jako aspiracyjne; otrzymała wiele reklam, które nie odpowiadają żadnej znaczącej rzeczywistości w terenie.
Na przykład filmy WWDC stwierdzają, że jeśli importowana struktura ma klasę MyClass, a kod ma klasę MyClass, nazwy te nie powodują konfliktu, ponieważ „zniekształcanie nazw” nadaje im różne nazwy wewnętrzne. W rzeczywistości jednak powodują konflikty w tym sensie, że wygrywa MyClass twojego własnego kodu i nie możesz określić "Nie, nie, mam na myśli MyClass w frameworku" - stwierdzenie TheFramework.MyClassnie działa (kompilator wie, co masz na myśli , ale mówi, że nie może znaleźć takiej klasy we frameworku).
Z mojego doświadczenia wynika, że w związku z tym Swift nie jest w najmniejszym stopniu przestrzenią nazw. Zmieniając jedną z moich aplikacji z Objective-C na Swift, stworzyłem wbudowany framework, ponieważ było to tak łatwe i fajne do wykonania. Importowanie frameworka importuje jednak wszystkie rzeczy Swift we frameworku - więc presto, po raz kolejny jest tylko jedna przestrzeń nazw i jest globalna. I nie ma nagłówków Swift, więc nie możesz ukryć żadnych nazw.
EDYCJA: W seed 3 ta funkcja zaczyna być teraz dostępna online, w następującym sensie: jeśli twój główny kod zawiera MyClass, a twój framework MyFramework zawiera MyClass, pierwsza domyślnie przesłania drugą, ale możesz dotrzeć do tego we frameworku używając składni MyFramework.MyClass. Tak więc w rzeczywistości mamy podstawy odrębnej przestrzeni nazw!
EDYCJA 2: W seed 4 mamy teraz kontrolę dostępu! Ponadto w jednej z moich aplikacji mam osadzony framework i oczywiście wszystko było domyślnie ukryte i musiałem jawnie ujawnić wszystkie bity publicznego API. To duża poprawa.
Dzięki za tę odpowiedź. Działa nie tylko z ramami, ale także z biblioteką standardową. Możesz na przykład „nadpisać” tablicę. Następnie „Array” odnosi się do Twojej własnej niestandardowej klasy Array, a tablica biblioteki Standard Library jest dostępna jako „Swift.Array”.
George,
3
@George I podobnie dla NSArray; jeśli go przyćmisz, nadal możesz nazywać go jako Foundation.NSArray.
mat.
1
Więc bez konieczności przeglądania historii myśli o przestrzeniach nazw w wersjach beta: gdzie teraz znajduje się ta odpowiedź?
Dan Rosenstark
1
@Yar, jak stwierdzono w edycjach. Nazwa modułu jest opcjonalną przestrzenią nazw, jeśli występuje niejasność, a teraz istnieje prywatność, więc nazwy modułów są ukryte, chyba że są ujawnione, a nazwa może być ograniczona do pliku.
mat.
2
Martwi mnie to już od dawna, wydaje się, że żadne projekty Swift nie powinny używać prefiksu z powodu tego, co twierdzi Apple, jednak w tej chwili prefiks jest nadal wymagany, nawet z modyfikatorami dostępu. Chociaż nie będziesz w konflikcie z pakietem lub klasami prywatnymi w ramach Apple, wszystko, co zadeklarowano jako publiczne, na przykład String, jeśli zadeklarujesz to ponownie, lub jakakolwiek nowa klasa, w końcu użyje twojej, chyba że masz zwyczaj odwołując się do wszystkich klas z jego przestrzenią nazw… nie jest dobre imo.
Oscar Gomez
19
Robiąc z tym pewne eksperymenty, skończyło się na utworzeniu tych klas z "przestrzenią nazw" w ich własnych plikach poprzez rozszerzenie "pakietu" głównego. Nie jestem pewien, czy jest to sprzeczne z najlepszymi praktykami lub czy ma jakieś konsekwencje, o których jestem świadomy (?)
extensionPackageOne{classClass{var name:Stringinit(name:String){self.name = name
}}}
PackageTwoClass.swift
extensionPackageTwo{classClass{var name:Stringinit(name:String){self.name = name
}}}
Edytować:
Właśnie się dowiedziałem, że tworzenie „podpakietów” w powyższym kodzie nie zadziała, jeśli używasz oddzielnych plików. Może ktoś podpowie, dlaczego tak się dzieje?
Nie jestem pewien, co rozumiesz przez „testowanie”, ale zacząłem budować moją aplikację przy użyciu powyższej techniki i wydaje się, że jak dotąd działa ona dobrze, z zastrzeżeniem, które dodałem do mojego wpisu powyżej. Robię to głównie dlatego, że zwykłem organizować swój kod w ten sposób w innych językach i byłbym wdzięczny, gdyby ktoś z większą wiedzą mógł mi powiedzieć, że to zły pomysł, dopóki nie posunę się za daleko! :)
bWlrYWphdWhvbmVu
1
kontynuuj ... tego chcemy ... aby móc mieć tę samą klasę nazw w dwóch różnych pakietach, aby móc istnieć i odpowiednio się do nich odwoływać (co ważniejsze, różne pliki), a jeśli to nie działa, całość idea przestrzeni nazw to pomysł na klapę ...
user2727195
Czy są jakieś skutki uboczne używania „struct” jako sposobu na hakowanie przestrzeni nazw?
Alex Nolasco,
Nie żebym spotkał się z takim wykonaniem. Xcode (6.1 GM) w niektórych rzadkich przypadkach narzeka na nieistniejące typy, ale sądzę, że może tak być w przypadku, gdy nie tworzy się kodu w ten sposób. Niedawno rozwiązałem jeden problem, dodając wszystkie pliki do mojego celu testowego, co nie ma żadnego sensu, ale rozwiązało problem. :)
bWlrYWphdWhvbmVu
12
Uważam, że osiąga się to za pomocą:
structFoo{classBar{}}
Następnie można uzyskać do niego dostęp za pomocą:
Nadal nie jestem zadowolony ze sposobu, w jaki tworzone są przestrzenie nazw ... co jeśli mam dziesięć różnych klas w przestrzeni nazw, a na dodatek wolę trzymać klasy w ich indywidualnych plikach, nie chcę nadużywać jednej file / struct ze wszystkimi klasami, wszelkie sugestie Kevin.
user2727195
2
Zastanawiam się, dlaczego nie pomyśleli o dołączeniu pakietów, właśnie tego potrzebujemy, a nie przestrzeni nazw, mam na myśli spojrzenie na inne języki wysokiego poziomu, takie jak Java, C #, ActionScript, wszystkie mają pakiety, przestrzenie nazw w tym kontekście niczym nie różnią się od używania NS lub inne prefiksy dla klas projektu
user2727195
1
Nie mogę się powstrzymać od zastanawiania się, czy używanie struktur jako sposobu na hakowanie przestrzeni nazw może powodować nieznane problemy.
Alex Nolasco,
1
To fajne obejście tego problemu. Próbowałem zastosować to podejście, ale musiałem natychmiast przestać. Kiedy próbowałem nazwać moje klasy związane z widokiem (powiedzmy CustomTableViewCell), autouzupełnianie w konstruktorze interfejsu nie sugerowało tego. Musiałbym ręcznie skopiować i wkleić nazwę klasy dla widoku, gdybym użył tego podejścia.
ArG
1
Zwykle używałbyś an enum, a nie a struct, więc nie możesz utworzyć instancji Foo.
Kevin
7
Swift używa modułów podobnie jak w Pythonie (patrz tutaj i tutaj ) i jak zasugerował @Kevin Sylvestre, możesz również użyć zagnieżdżonych typów jako przestrzeni nazw.
Aby rozszerzyć odpowiedź @Daniel A. White, w WWDC rozmawiali o modułach w bardzo krótkim czasie.
Szukam pakietów takich jak konstrukcja, jak wspomniano w drugim linku. 6.4 Pakiety (Python), przestrzenie nazw jako typy zagnieżdżone nie mogą zająć zbyt wiele, a co, jeśli mam 10 różnych klas i różnych plików w przestrzeni nazw lub powiedzmy pakiet???
user2727195
7
Przestrzenie nazw są przydatne, gdy trzeba zdefiniować klasę o takiej samej nazwie jak klasa w istniejącej strukturze.
Załóżmy, że Twoja aplikacja ma MyAppnazwę i musisz zadeklarować swoją niestandardową UICollectionViewController.
Nie musisz dodawać przedrostków i podklas w ten sposób:
Czemu? . Ponieważ to, co zadeklarowałeś, jest zadeklarowane w bieżącym module , który jest twoim aktualnym celem . A UICollectionViewControllerfrom UIKitjest zadeklarowany w UIKitmodule.
Jak z niego korzystać w ramach obecnego modułu?
var customController =UICollectionViewController()//your custom class
var uikitController =UIKit.UICollectionViewController()//class from UIKit
Jak odróżnić je od innego modułu?
var customController =MyApp.UICollectionViewController()//your custom class
var uikitController =UIKit.UICollectionViewController()//class from UIKit
Możesz użyć extensionwspomnianego structpodejścia do przestrzeni nazw bez konieczności wcięcia całego kodu w prawo. Byłem bawiąc się tym trochę i nie jestem pewien, czy tam w miarę tworzenia Controllersi Viewsnazw, jak w poniższym przykładzie, ale nie pokazują, jak daleko może pójść:
Profile.swift :
// Define the namespaces
structProfiles{structViews{}structViewControllers{}}
Profile / ViewControllers / Edit.swift
// Define your new class within its namespace
extensionProfiles.ViewControllers{classEdit:UIViewController{}}// Extend your new class to avoid the extra whitespace on the left
extensionProfiles.ViewControllers.Edit{overridefunc viewDidLoad(){// Do some stuff
}}
Profile / Views / Edit.swift
extensionProfiles.Views{classEdit:UIView{}}extensionProfiles.Views.Edit{overridefunc drawRect(rect:CGRect){// Do some stuff
}}
Nie używałem tego w aplikacji, ponieważ nie potrzebowałem jeszcze tego poziomu separacji, ale myślę, że to ciekawy pomysł. Eliminuje to potrzebę stosowania nawet sufiksów klas, takich jak wszechobecny sufiks * ViewController, który jest irytująco długi.
Jednak nie skraca niczego, gdy jest przywoływany, na przykład w parametrach metody, takich jak:
Odpowiedzi:
Odpowiedział SevenTenEleven na forum deweloperów Apple :
Również Chris Lattner napisał na Twitterze o przestrzeni nazw .
Wydaje się, że bardzo różni się to, o czym myślałem.
źródło
forums.developer.apple.com
witryny forów.Przestrzenie nazw Swifta opisałbym jako aspiracyjne; otrzymała wiele reklam, które nie odpowiadają żadnej znaczącej rzeczywistości w terenie.
Na przykład filmy WWDC stwierdzają, że jeśli importowana struktura ma klasę MyClass, a kod ma klasę MyClass, nazwy te nie powodują konfliktu, ponieważ „zniekształcanie nazw” nadaje im różne nazwy wewnętrzne. W rzeczywistości jednak powodują konflikty w tym sensie, że wygrywa MyClass twojego własnego kodu i nie możesz określić "Nie, nie, mam na myśli MyClass w frameworku" - stwierdzenie
TheFramework.MyClass
nie działa (kompilator wie, co masz na myśli , ale mówi, że nie może znaleźć takiej klasy we frameworku).Z mojego doświadczenia wynika, że w związku z tym Swift nie jest w najmniejszym stopniu przestrzenią nazw. Zmieniając jedną z moich aplikacji z Objective-C na Swift, stworzyłem wbudowany framework, ponieważ było to tak łatwe i fajne do wykonania. Importowanie frameworka importuje jednak wszystkie rzeczy Swift we frameworku - więc presto, po raz kolejny jest tylko jedna przestrzeń nazw i jest globalna. I nie ma nagłówków Swift, więc nie możesz ukryć żadnych nazw.
EDYCJA: W seed 3 ta funkcja zaczyna być teraz dostępna online, w następującym sensie: jeśli twój główny kod zawiera MyClass, a twój framework MyFramework zawiera MyClass, pierwsza domyślnie przesłania drugą, ale możesz dotrzeć do tego we frameworku używając składni
MyFramework.MyClass
. Tak więc w rzeczywistości mamy podstawy odrębnej przestrzeni nazw!EDYCJA 2: W seed 4 mamy teraz kontrolę dostępu! Ponadto w jednej z moich aplikacji mam osadzony framework i oczywiście wszystko było domyślnie ukryte i musiałem jawnie ujawnić wszystkie bity publicznego API. To duża poprawa.
źródło
Foundation.NSArray
.Robiąc z tym pewne eksperymenty, skończyło się na utworzeniu tych klas z "przestrzenią nazw" w ich własnych plikach poprzez rozszerzenie "pakietu" głównego. Nie jestem pewien, czy jest to sprzeczne z najlepszymi praktykami lub czy ma jakieś konsekwencje, o których jestem świadomy (?)
AppDelegate.swift
PackageOne.swift
PackageTwo.swift
PackageOneClass.swift
PackageTwoClass.swift
Edytować:
Właśnie się dowiedziałem, że tworzenie „podpakietów” w powyższym kodzie nie zadziała, jeśli używasz oddzielnych plików. Może ktoś podpowie, dlaczego tak się dzieje?
Dodanie następujących plików do powyższego:
PackageOneSubPackage.swift
PackageOneSubPackageClass.swift
Zgłasza błąd kompilatora: „Pakiet podrzędny” nie jest typem elementu członkowskiego „PakietOne”
Jeśli przeniosę kod z PackageOneSubPackageClass.swift do PackageOneSubPackage.swift, to działa. Ktoś?
Edycja 2:
Bawiąc się tym nadal i odkryłem (w Xcode 6.1 beta 2), że definiując pakiety w jednym pliku, można je rozszerzyć w oddzielnych plikach:
Oto moje pliki w skrócie: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
źródło
Uważam, że osiąga się to za pomocą:
Następnie można uzyskać do niego dostęp za pomocą:
źródło
enum
, a nie astruct
, więc nie możesz utworzyć instancjiFoo
.Swift używa modułów podobnie jak w Pythonie (patrz tutaj i tutaj ) i jak zasugerował @Kevin Sylvestre, możesz również użyć zagnieżdżonych typów jako przestrzeni nazw.
Aby rozszerzyć odpowiedź @Daniel A. White, w WWDC rozmawiali o modułach w bardzo krótkim czasie.
Tutaj również wyjaśniono:
źródło
Nie musisz dodawać przedrostków i podklas w ten sposób:
Zrób to tak:
Czemu? . Ponieważ to, co zadeklarowałeś, jest zadeklarowane w bieżącym module , który jest twoim aktualnym celem . A
UICollectionViewController
fromUIKit
jest zadeklarowany wUIKit
module.Jak z niego korzystać w ramach obecnego modułu?
Jak odróżnić je od innego modułu?
źródło
Możesz użyć
extension
wspomnianegostruct
podejścia do przestrzeni nazw bez konieczności wcięcia całego kodu w prawo. Byłem bawiąc się tym trochę i nie jestem pewien, czy tam w miarę tworzeniaControllers
iViews
nazw, jak w poniższym przykładzie, ale nie pokazują, jak daleko może pójść:Profile.swift :
Profile / ViewControllers / Edit.swift
Profile / Views / Edit.swift
Nie używałem tego w aplikacji, ponieważ nie potrzebowałem jeszcze tego poziomu separacji, ale myślę, że to ciekawy pomysł. Eliminuje to potrzebę stosowania nawet sufiksów klas, takich jak wszechobecny sufiks * ViewController, który jest irytująco długi.
Jednak nie skraca niczego, gdy jest przywoływany, na przykład w parametrach metody, takich jak:
źródło
Jeśli ktoś był ciekawy, od 10 czerwca 2014 r. Jest to znany błąd w Swift:
Od SevenTenEleven
„Znany błąd, przepraszam! Rdar: // problem / 17127940 Kwalifikowanie typów Swift na podstawie nazwy modułu nie działa.”
źródło