La documentazione menziona solo i tipi nidificati, ma non è chiaro se possano essere usati come spazi dei nomi. Non ho trovato alcuna menzione esplicita di spazi dei nomi.
La documentazione menziona solo i tipi nidificati, ma non è chiaro se possano essere usati come spazi dei nomi. Non ho trovato alcuna menzione esplicita di spazi dei nomi.
Risposte:
Risposta di SevenTenEleven nel forum degli sviluppatori Apple :
Gli spazi dei nomi non sono per file; sono per target (in base all'impostazione di build "Nome modulo prodotto"). Quindi finiresti con qualcosa del genere:
import FrameworkA import FrameworkB FrameworkA.foo()
Tutte le dichiarazioni di Swift sono considerate parte di alcuni moduli, quindi anche quando dici "
NSLog
" (sì, esiste ancora) otterrai quello che Swift pensa come "Foundation.NSLog
".
Anche Chris Lattner ha twittato su namespace .
Lo spazio dei nomi è implicito in Swift, tutte le classi (ecc.) Sono implicitamente definite dal modulo (destinazione Xcode) in cui si trovano. Non sono necessari prefissi di classe
Sembra essere molto diverso quello che ho pensato.
forums.developer.apple.com
sito dei forum, sfortunatamente.
Descriverei lo spazio dei nomi di Swift come aspirazionale; è stato dato un sacco di pubblicità che non corrisponde a nessuna realtà significativa sul campo.
Ad esempio, i video del WWDC affermano che se un framework che stai importando ha una classe MyClass e il tuo codice ha una classe MyClass, quei nomi non sono in conflitto perché "manipolazione dei nomi" dà loro nomi interni diversi. In realtà, tuttavia, essi fanno il conflitto, nel senso che vince MyClass del proprio codice, e non è possibile specificare "No no, voglio dire le MyClass nel quadro" - dicendoTheFramework.MyClass
non funziona (il compilatore sa cosa vuoi dire , ma dice che non riesce a trovare una tale classe nel framework).
La mia esperienza è che Swift quindi non è minimamente spaziato. Nel trasformare una delle mie app da Objective-C a Swift, ho creato un framework incorporato perché era così facile e bello da fare. L'importazione del framework, tuttavia, importa tutte le cose Swift nel framework - quindi presto, ancora una volta c'è un solo spazio dei nomi ed è globale. E non ci sono intestazioni Swift quindi non puoi nascondere alcun nome.
EDIT: Nel seed 3, questa funzione sta ora iniziando a diventare online, nel seguente senso: se il tuo codice principale contiene MyClass e il tuo framework MyFramework contiene MyClass, il primo oscura il secondo di default, ma puoi raggiungere quello nel framework usando la sintassi MyFramework.MyClass
. Quindi in effetti abbiamo i rudimenti di uno spazio dei nomi distinto!
EDIT 2: Nel seed 4, ora abbiamo i controlli di accesso! Inoltre, in una delle mie app ho un framework incorporato e abbastanza sicuro, tutto era nascosto per impostazione predefinita e ho dovuto esporre esplicitamente tutti i bit dell'API pubblica. Questo è un grande miglioramento.
Foundation.NSArray
.
Durante alcuni esperimenti con questo ho finito per creare queste classi "namespace" nei loro file estendendo il "pacchetto" di root. Non sono sicuro se questo è contro le migliori pratiche o se ha delle implicazioni di cui sono a conoscenza (?)
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
}
}
}
Modificare:
Ho appena scoperto che la creazione di "pacchetti secondari" nel codice sopra non funzionerà se si utilizzano file separati. Forse qualcuno può accennare al perché sarebbe così?
Aggiunta dei seguenti file a quanto sopra:
PackageOneSubPackage.swift
import Foundation
extension PackageOne {
struct SubPackage {
}
}
PackageOneSubPackageClass.swift
extension PackageOne.SubPackage {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Sta generando un errore del compilatore: 'SubPackage' non è un tipo di membro di 'PackageOne'
Se sposto il codice da PackageOneSubPackageClass.swift a PackageOneSubPackage.swift, funziona. Chiunque?
Modifica 2:
Giocherellando con questo ancora e ho scoperto (in Xcode 6.1 beta 2) che definendo i pacchetti in un file possono essere estesi in file separati:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Ecco i miei file in sintesi: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
Credo che questo sia ottenuto usando:
struct Foo
{
class Bar
{
}
}
Quindi è possibile accedervi utilizzando:
var dds = Foo.Bar();
enum
, non un struct
, quindi non puoi istanziare a Foo
.
Swift usa moduli simili a quelli di Python (vedi qui e qui ) e come suggerito da @Kevin Sylvestre puoi anche usare i tipi nidificati come spazi dei nomi.
E per estendere la risposta di @Daniel A. White, nel WWDC stavano parlando rapidamente dei moduli.
Anche qui è spiegato:
I tipi dedotti rendono il codice più pulito e meno soggetto a errori, mentre i moduli eliminano le intestazioni e forniscono spazi dei nomi.
Gli spazi dei nomi sono utili quando è necessario definire la classe con lo stesso nome della classe nel framework esistente.
Supponiamo che la tua app abbia un
MyApp
nome e che tu debba dichiarare la tua abitudineUICollectionViewController
.
Non è necessario aggiungere il prefisso e la sottoclasse in questo modo:
class MAUICollectionViewController: UICollectionViewController {}
Fai cosi:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Perché? . Perché ciò che hai dichiarato è dichiarato nel modulo corrente , che è il tuo obiettivo attuale . E UICollectionViewController
da UIKit
è dichiarato inUIKit
modulo.
Come usarlo all'interno del modulo corrente?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Come distinguerli da un altro modulo?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
È possibile utilizzare extension
per utilizzare l' struct
approccio c citato per lo spazio dei nomi senza dover rientrare tutto il codice verso destra. Ho giocato un po 'con questo e non sono sicuro di andare fino alla creazione Controllers
eViews
spazi dei nomi come nell'esempio qui sotto, ma illustra quanto lontano può andare:
Profiles.swift :
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Profili / 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
}
}
Profili / Vista / Edit.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
Non l'ho usato in un'app poiché non ho ancora avuto bisogno di questo livello di separazione, ma penso che sia un'idea interessante. Ciò elimina la necessità di suffissi di classe pari come l'onnipresente * suffisso ViewController che è fastidiosamente lungo.
Tuttavia, non accorcia nulla quando viene indicato come nei parametri di metodo come questo:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
Nel caso in cui qualcuno fosse curioso, a partire dal 10 giugno 2014, questo è un bug noto in Swift:
Da SevenTenEleven
"Bug noto, scusa! Rdar: // problem / 17127940 I tipi di Swift qualificati in base al nome del modulo non funzionano."