Opaque Type (ogenomskinlig typ) — är en Swift-mekanism som gör att en funktion kan returnera ett värde av någon typ utan att avslöja den konkreta typen för den anropande koden. Nyckelordet some i returtypen — det mest kända exemplet: some View i SwiftUI betyder "en typ som uppfyller View returneras, men vilken exakt — implementeringsdetalj". Opaque type bevarar typens identitet (till skillnad från protokoll som typ), vilket gör att kompilatorn kan optimera kod och garantera konsekvens i returtypen. Enligt Swift Book, 2025 löser opaque types problemet med protokoll som har associated types, genom att tillåta returnering av värden från sådana protokoll från funktioner.
Huvudpunkter
Opaque Type — är en returtyp deklarerad med nyckelordet some, som döljer den konkreta implementeringen från den anropande koden. Den anropande parten vet bara att det returnerade värdet motsvarar ett visst protokoll, men vet inte vilken konkret typ som ligger bakom some. Samtidigt känner kompilatorn den exakta typen och använder den för statisk dispatch och optimering.
Innan opaque types kom i Swift 5.1 (SE-0244) var det omöjligt att returnera ett protokoll med associated types från en funktion utan boxning. Till exempel har protokollet Equatable en associated type och funktionen kunde inte helt enkelt returnera Equatable — kompilatorn gav felet "protocol can only be used as a generic constraint". Opaque type löste detta problem.
func makeInt() -> some Equatable {
return 42
}
func makeString() -> some Equatable {
return "Hello"
}
// Kompilatorn vet att makeInt returnerar Int
// makeInt() == makeString() — ❌ fel, olika typer
Båda funktionerna returnerar some Equatable, men de konkreta typerna är olika: Int och String. Ett försök att jämföra dem med == kommer att orsaka ett kompileringsfel, eftersom opaque type garanterar att från ett specifikt anrop returneras samma typ, men inte mellan olika funktioner. Detta är en funktion, inte en bugg: opaque type bevarar typidentiteten där protokoll som typ (any Equatable) förlorar den.
Generic och Opaque Type — två sidor av samma mynt. Generic låter den anropande koden välja typ, medan opaque type låter funktionen dölja typen från den anropande koden. Skillnaden ligger i kontrollens riktning.
| Egenskap | Generic | Opaque some |
|---|---|---|
| Vem väljer typen | Anropande kod | Funktion/metod |
| Typidentitet | Bevaras (stabil) | Bevaras (stabil) |
| Antal return-grenar | En (via generic) | Samma typ i alla grenar |
| Tillämpning | Algoritmer, datastrukturer | SwiftUI, fabriksmetoder |
I en generic-funktion bestämmer caller vilken typ som ska användas. Funktionen måste fungera med valfritt T som uppfyller begränsningarna. För opaque type känner caller inte den konkreta typen — beslutet fattas av implementeringen.
// Generic: caller väljer typ
func identity<T>(_ value: T) -> T { value }
let x: Int = identity(42)
// Opaque: funktionen döljer typ
func makeSomeEquatable() -> some Equatable { 42 }
let y = makeSomeEquatable()
Valet mellan generic och opaque type beror på avsikten. Om den anropande koden ska välja typ — använd generic. Om funktionen ska dölja implementeringsdetaljer — använd some. SwiftUI valde some View just för att body måste vara flexibel inuti men stabil utåt.
some — är ett Swift-nyckelord som introducerades i Swift 5.1 (SE-0244). Det används i returposition för att deklarera opaque type, samt i parametrar (SE-0341) och egenskaper. some garanterar att den konkreta typen är stabil och känd för kompilatorn, men dold från extern kod.
Från och med Swift 5.7 kan some användas inte bara i returposition utan även i parametrar. some Equatable i en parameter betyder "denna funktion accepterar vilken Equatable-typ som helst, men alla anrop inom den specifika kroppen ser samma typ".
func areEqual(_ a: some Equatable, _ b: some Equatable) -> Bool {
// a och b — potentiellt olika typer, == fungerar inte direkt
return isEqual(a, b)
}
func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
return a == b
}
Användning av some i parametrar ger en mer koncis syntax jämfört med
any — är ett Swift 5.6+-nyckelord för explicit deklaration av existentiella typer (protokoll som typ). Till skillnad från some raderar any typidentiteten: kompilatorn vet inte vilken konkret typ som döljer sig bakom protokollet. Detta ger flexibilitet (olika typer kan lagras i en array), men på bekostnad av prestanda.
some — statisk polymorfism: kompilatorn känner den konkreta typen, använder direkt dispatch och kan inline-kod. any — dynamisk polymorfism: en tabell med virtuella metoder (existential container) används, vilket lägger till indirektion.
protocol Drawable {
func draw()
}
// some: statisk typ är känd
func makeDrawable() -> some Drawable {
return Circle() // Enkel returtyp
}
// any: dynamisk, kan lagra olika typer
var shapes: [any Drawable] = [Circle(), Square()]
shapes.append(Triangle())
Valet mellan some och any är en kompromiss mellan prestanda och flexibilitet. Some är snabbare men begränsar till en implementering. Any är mer flexibel (typer kan blandas) men långsammare på grund av dynamisk dispatch. I SwiftUI används alltid some View för body, eftersom body för varje View är en konkret typ.
Opaque Type löser ett grundläggande problem i Swift: protokoll med associated types (PAT) kan inte användas direkt som typ. En funktion kan inte bara returnera Collection — kompilatorn kräver att Element specificeras. some Collection löser detta genom att dölja associated type.
Utan opaque type skulle man för att returnera Collection behöva använda en konkret typ (Array
func makeReversedCollection<T>(
of array: [T]
) -> some Collection {
return array.reversed()
}
let result = makeReversedCollection(of: [1, 2, 3])
// result — ReversedCollection>, hidden from caller
for item in result {
print(item)
}
result kan itereras, men egenskaperna hos ReversedCollection kan inte direkt nås. Detta skyddar inkapslingen: om reversed() senare ersätts med en annan metod med en annan implementering, kommer den anropande koden inte att gå sönder. Opaque type ger friheten att ändra implementeringen utan att ändra API.
some View — den mest kända tillämpningen av opaque type. Varje View i SwiftUI deklarerar body som some View. Detta innebär att body returnerar någon konkret View-typ, men programmeraren behöver inte tänka på vad exakt — TupleView, Group, ModifiedContent eller någon annan typ från ramverket.
Utan opaque type skulle body behöva returnera en konkret typ, till exempel ModifiedContent<Button<Text>, Padding>, vilket är opraktiskt. some View döljer denna komplexitet. Kompilatorn härleder den exakta typen av body automatiskt vid kompilering.
struct ContentView: View {
var body: some View {
VStack {
Text("Hej")
.font(.title)
Button("Tryck på mig") {
print("Tryckt")
}
}
.padding()
}
}
Kompilatorn härleder body som ModifiedContent<VStack<TupleView<(Text, Button<Text>)>>, Padding>. Programmeraren ser some View. Om layouten ändras från VStack till HStack, härleder kompilatorn automatiskt om typen — inga manuella ändringar behövs. Detta är magin med opaque type: programmeraren fokuserar på gränssnittslogik, inte på kompositionstyper.
Vanliga frågor
Opaque Type — är en typ deklarerad med nyckelordet some, som döljer den konkreta implementeringen från den anropande koden. Kompilatorn känner den exakta typen, men programmeraren som använder funktionen ser bara protokollet.
some — är en opaque type med statisk identitet: kompilatorn känner den konkreta typen. any — är en existentiell typ med dynamisk dispatch: typidentiteten är raderad. Some är effektivare, any är mer flexibel.
some View döljer den komplexa konkreta body-typen som kompilatorn automatiskt härleder. Detta befriar programmeraren från behovet att skriva den exakta typen bestående av Generic-omslag (VStack, Group, ModifiedContent).
Ja, från och med Swift 5.7. some i parametrar är syntaktiskt socker över en generic-parameter. Det förenklar funktionsdeklarationer, särskilt vid arbete med protokoll, där varje some-parameter inte kräver en separat
Kompilatorn ger fel: opaque type kräver att alla return-grenar returnerar samma konkreta typ. Detta är avsiktligt för att bevara typidentiteten. Om du behöver returnera olika typer, använd any.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också