In der Dokumentation werden nur verschachtelte Typen erwähnt, es ist jedoch nicht klar, ob sie als Namespaces verwendet werden können. Ich habe keine explizite Erwähnung von Namespaces gefunden.
In der Dokumentation werden nur verschachtelte Typen erwähnt, es ist jedoch nicht klar, ob sie als Namespaces verwendet werden können. Ich habe keine explizite Erwähnung von Namespaces gefunden.
Antworten:
Beantwortet von SevenTenEleven im Apple Dev Forum :
Namespaces sind nicht pro Datei; Sie sind pro Ziel (basierend auf der Build-Einstellung "Product Module Name"). Am Ende hätten Sie also so etwas:
import FrameworkA import FrameworkB FrameworkA.foo()
Alle Swift-Deklarationen werden als Teil eines Moduls betrachtet. Selbst wenn Sie "
NSLog
" sagen (ja, es existiert noch)), erhalten Sie das, was Swift als "Foundation.NSLog
" ansieht .
Auch Chris Lattner twitterte über Namespace .
Der Namensraum ist in Swift implizit. Alle Klassen (usw.) sind implizit von dem Modul (Xcode-Ziel) abhängig, in dem sie sich befinden. Es werden keine Klassenpräfixe benötigt
Scheint ganz anders zu sein, als ich gedacht habe.
forums.developer.apple.com
leider nicht in die neue Forenseite importiert .
Ich würde Swifts Namensraum als ehrgeizig beschreiben; Es wurde viel Werbung gemacht, die keiner sinnvollen Realität vor Ort entspricht.
In den WWDC-Videos heißt es beispielsweise, dass wenn ein Framework, das Sie importieren, eine Klasse MyClass und Ihr Code eine Klasse MyClass hat, diese Namen nicht in Konflikt stehen, da "name mangling" ihnen unterschiedliche interne Namen gibt. In Wirklichkeit aber sie tun Konflikt, in dem Sinne , dass Sie Ihren eigenen Code des MyClass gewinnt, und Sie nicht angeben können „Nein , nein, ich meine die MyClass im Rahmen“ - sagt TheFramework.MyClass
nicht funktioniert (der Compiler weiß , was du meinst , aber es heißt, dass es eine solche Klasse im Framework nicht finden kann).
Ich habe die Erfahrung gemacht, dass Swift daher nicht im geringsten einen Namensraum hat. Als ich eine meiner Apps von Objective-C auf Swift umstellte, erstellte ich ein eingebettetes Framework, weil es so einfach und cool war. Beim Importieren des Frameworks werden jedoch alle Swift-Inhalte in das Framework importiert. Daher gibt es wieder nur einen Namespace, der global ist. Und es gibt keine Swift-Header, sodass Sie keine Namen verbergen können.
BEARBEITEN: In Seed 3 wird diese Funktion jetzt im folgenden Sinne online geschaltet: Wenn Ihr Hauptcode MyClass enthält und Ihr Framework MyFramework MyClass enthält, überschattet das erstere standardmäßig das letztere, aber Sie können das im Framework erreichen unter Verwendung der Syntax MyFramework.MyClass
. Wir haben also tatsächlich die Grundlagen eines bestimmten Namespace!
EDIT 2: In Seed 4 haben wir jetzt Zugriffskontrollen! Außerdem habe ich in einer meiner Apps ein eingebettetes Framework und sicher war alles standardmäßig ausgeblendet und ich musste alle Teile der öffentlichen API explizit verfügbar machen. Dies ist eine große Verbesserung.
Foundation.NSArray
.
Während ich damit experimentierte, erstellte ich diese "Namespace" -Klassen in ihren eigenen Dateien, indem ich das Root- "Paket" erweiterte. Ich bin mir nicht sicher, ob dies gegen Best Practices verstößt oder ob es irgendwelche Auswirkungen hat, die mir bewusst sind (?)
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 {
}
PackageTwo.swift
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
}
}
}
Bearbeiten:
Ich habe gerade herausgefunden, dass das Erstellen von "Unterpaketen" im obigen Code nicht funktioniert, wenn separate Dateien verwendet werden. Vielleicht kann jemand andeuten, warum das so ist?
Hinzufügen der folgenden Dateien zu den oben genannten:
PackageOneSubPackage.swift
import Foundation
extension PackageOne {
struct SubPackage {
}
}
PackageOneSubPackageClass.swift
extension PackageOne.SubPackage {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Es wird ein Compilerfehler ausgegeben: 'SubPackage' ist kein Mitgliedstyp von 'PackageOne'.
Wenn ich den Code von PackageOneSubPackageClass.swift nach PackageOneSubPackage.swift verschiebe, funktioniert es. Jemand?
Bearbeiten 2:
Ich habe immer noch damit herumgespielt und herausgefunden (in Xcode 6.1 Beta 2), dass die Pakete durch Definieren in einer Datei in separaten Dateien erweitert werden können:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Hier sind meine Dateien in einem Kern: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
Ich glaube, dass dies erreicht wird mit:
struct Foo
{
class Bar
{
}
}
Dann kann darauf zugegriffen werden mit:
var dds = Foo.Bar();
enum
, kein a struct
, sodass Sie a nicht instanziieren können Foo
.
Swift verwendet Module ähnlich wie in Python (siehe hier und hier ) und wie @ Kevin Sylvestre vorgeschlagen hat, können Sie die verschachtelten Typen auch als Namespaces verwenden.
Und um die Antwort von @Daniel A. White zu erweitern, sprachen sie im WWDC schnell über die Module.
Auch hier wird erklärt:
Abgeleitete Typen machen Code sauberer und weniger fehleranfällig, während Module Header eliminieren und Namespaces bereitstellen.
Namespaces sind nützlich, wenn Sie eine Klasse mit demselben Namen wie die Klasse in einem vorhandenen Framework definieren müssen.
Angenommen, Ihre App hat einen
MyApp
Namen und Sie müssen Ihre benutzerdefinierte deklarierenUICollectionViewController
.
Sie müssen keine Präfixe und Unterklassen wie folgt erstellen:
class MAUICollectionViewController: UICollectionViewController {}
Mach es so:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Warum? . Denn was Sie deklariert haben, wird im aktuellen Modul deklariert , das Ihr aktuelles Ziel ist . Und UICollectionViewController
von UIKit
wird im UIKit
Modul deklariert .
Wie verwende ich es im aktuellen Modul?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Wie kann man sie von einem anderen Modul unterscheiden?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Sie können extension
den genannten struct
s-Ansatz für den Namespace verwenden, ohne den gesamten Code nach rechts einrücken zu müssen. Ich habe mit diesem ein wenig Spielerei gewesen , und ich bin nicht sicher , würde ich so weit wie die Schaffung gehen Controllers
und Views
Namensräume wie im Beispiel unten, aber es funktioniert zeigen , wie weit es gehen kann:
Profiles.swift :
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Profile / 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
}
}
Profile / Ansichten / Edit.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
Ich habe dies nicht in einer App verwendet, da ich diese Trennungsstufe noch nicht benötigt habe, aber ich denke, es ist eine interessante Idee. Dadurch sind keine Klassensuffixe wie das allgegenwärtige * ViewController-Suffix mehr erforderlich, das ärgerlich lang ist.
Es verkürzt jedoch nichts, wenn darauf verwiesen wird, wie in Methodenparametern wie diesen:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
Falls jemand neugierig war, ist dies ab dem 10. Juni 2014 ein bekannter Fehler in Swift:
Von SevenTenEleven
"Bekannter Fehler, sorry! Rdar: // problem / 17127940 Das Qualifizieren von Swift-Typen anhand ihres Modulnamens funktioniert nicht."