Swift 5.4 daha iyi kod tamamlama ve artımlı derleme için büyük hızlandırmalar dahil olmak üzere bazı büyük derleme iyileştirmeler getiriyor. Aynı zamanda bazı önemli yeni özellikler ve iyileştirmeler de ekliyor, bu yüzden burada bunları inceleyelim …
Geliştirilmiş implicit member syntax
SE-0287 , Swift’in implicit member ifadelerini kullanma becerisini geliştirir, böylece sadece tek bir statik member için destek almak yerine, bunların zincirlerini oluşturabilirsiniz.
Swift, basit ifadeler için her zaman implicit member sözdizimini kullanma yeteneğine sahipti, örneğin SwiftUI’de bir metni renklendirmek isterseniz, bunun Color.red
yerine .red
kullanabilirsiniz :
struct ContentView1: View {
var body: some View {
Text("You're not my supervisor!")
.foregroundColor(.red)
}
}
Swift 5.4'ten önce bu, daha karmaşık ifadelerle çalışmıyordu. Örneğin, kırmızı renginizin biraz şeffaf olmasını istiyorsanız, şunu yazmanız gerekir:
struct ContentView2: View {
var body: some View {
Text("You're not my supervisor!")
.foregroundColor(Color.red.opacity(0.5))
}
}
Swift 5.4'ten itibaren derleyici birden çok zincirli member’ı anlayabilir, yani Color
'ı tür çıkarılabilir:
struct ContentView3: View {
var body: some View {
Text("You're not my supervisor!")
.foregroundColor(.red.opacity(0.5))
}
}
Multiple variadic parameters functions
SE-0284 , değişken bir parametrenin tüm etiketleri olduğu sürece, işlevlere, alt simgelere ve initiator sahip olma özelliğini tanıttı. Swift 5.4'ten önce, bu durumda yalnızca bir değişken parametreniz olabilirdi.
Dolayısıyla, bu iyileştirmeyle, bir futbol maçı sırasında gollerin atıldığı zamanları depolayan değişken bir parametreyi kabul eden bir işlev ve gol atan oyuncuların adlarını puanlayan ikinci bir değişken parametre yazabiliriz:
func summarizeGoals(times: Int..., players: String...) {
let joinedNames = ListFormatter.localizedString(byJoining: players)
let joinedTimes = ListFormatter.localizedString(byJoining: times.map(String.init)) print("\(times.count) goals where scored by \(joinedNames) at the follow minutes: \(joinedTimes)")
}
Bu işlevi çağırmak için, her iki değer kümesini de değişken parametreler olarak sağlayın ve sonraki tüm parametrelerin etiketlendiğinden emin olun:
summarizeGoals(times: 18, 33, 55, 90, players: "Dany", "Jamie", "Rayy")
Result builders
İşlev oluşturucular gayri resmi olarak Swift 5.1'e geldiler, ancak Swift 5.4'e kadar olan süreçte, tartışılmak ve iyileştirilmek için SE-0289 olarak Swift Evolution öneri sürecinden resmi olarak geçtiler . Bu sürecin bir parçası olarak, gerçek amaçlarını daha iyi yansıtmaları için sonuç oluşturuculara yeniden adlandırıldılar ve hatta bazı yeni işlevler geliştirdiler.
İlk olarak, en önemli kısım: result builders, seçtiğimiz bir sırayı geçerek adım adım yeni bir değer oluşturmamızı sağlar. SwiftUI’ın görüş oluşturma sisteminin büyük bölümlerine güç veriyorlar, böylece VStack
içeride çeşitli görüşlere sahip olduğunda , Swift onları dahili bir TupleView
tipinde gruplandırıyor, böylece tek bir veri olarak saklanabiliyorlar VStack
- bir dizi’yi tek bir view görüntüler.
İşte tek bir dize döndüren bir işlev:
func makeSentence1() -> String {
"Why settle for a Duke when you can have a Prince?"
}print(makeSentence1())
Bu harika çalışıyor, fakat bir araya getirmek istediğimiz birkaç dizimiz olsaydı? Tıpkı SwiftUI gibi, hepsini ayrı ayrı sağlamak ve Swift’in bunu çözmesini isteyebiliriz:
// This is invalid Swift, and will not compile.
// func makeSentence2() -> String {
// "Why settle for a Duke"
// "when you can have"
// "a Prince?"
// }
Kendi başına, bu kod işe yaramayacak çünkü Swift ne demek istediğimizi artık anlamıyor. Bununla birlikte, aşağıdaki gibi, istediğimiz dönüşümü kullanarak birkaç dizeyi tek bir dizeye nasıl dönüştürebileceğimizi anlayan bir sonuç oluşturucu oluşturabiliriz:
@resultBuilder
struct SimpleStringBuilder {
staticfunc buildBlock(_ parts: String...) -> String {
parts.joined(separator: "\n")
}
}
Bu az miktarda bir kod olsa da, açılacak çok şey var:
@resultBuilder
Özniteliği bir sonuç oluşturucu olarak ele alınmalıdır . Daha önce bu davranış@_functionBuilder
, bunun genel kullanım için tasarlanmadığını gösteren bir alt çizgiye sahip olan kullanılarak gerçekleştiriliyordu.- Her sonuç oluşturucu
buildBlock()
, bir tür veri alıp dönüştürmesi gereken en az bir statik yöntem sağlamalıdır. Yukarıdaki örnek, sıfır veya daha fazla dizeyi alır, birleştirir ve tek bir dize olarak geri döner. - Sonuç, yapımızın
SimpleStringBuilder
bir result buildes haline gelmesi, yani@SimpleStringBuilder
onun string birleştirme güçlerine ihtiyaç duyduğumuz her yerde kullanabileceğimiz anlamına gelir .
Bunun SimpleStringBuilder.buildBlock()
gibi doğrudan kullanmamızı engelleyecek hiçbir şey yok :
let joined = SimpleStringBuilder.buildBlock(
"Why settle for a Duke",
"when you can have",
"a Prince?"
)print(joined)
Bununla birlikte, @resultBuilder
ek açıklamayı SimpleStringBuilder
yapımızla kullandığımız için , bunu aşağıdaki gibi işlevlere de uygulayabiliriz:
@SimpleStringBuilder func makeSentence3() -> String {
"Why settle for a Duke"
"when you can have"
"a Prince?"
}print(makeSentence3())
Artık her dizenin sonundaki virgüllere ihtiyacımız olmadığına dikkat edin — @resultBuilder
her ifadeyi otomatik olarak makeSentence()
tek bir dizeye dönüştürür SimpleStringBuilder
.
Pratikte, result builders, türünüze daha fazla method ekleyerek önemli ölçüde daha fazlasını yapabilir. Örneğin SimpleStringBuilder
, verileri nasıl dönüştürmek istediğimizi açıklayan iki ekstra method ekleyerek if / else desteğini ekleyebiliriz. Kodumuzda dizelerimizi hiç dönüştürmek istemiyoruz, bu yüzden onları hemen geri gönderebiliriz:
@resultBuilder
struct ConditionalStringBuilder {
staticfunc buildBlock(_ parts: String...) -> String {
parts.joined(separator: "\n")
}staticfunc buildEither(first component: String) -> String {
return component
}staticfunc buildEither(second component: String) -> String {
return component
}
}
Şimdi işlevlerimiz koşulları kullanabilir:
@ConditionalStringBuilder func makeSentence4() -> String {
"Why settle for a Duke"
"when you can have"if Bool.random() {
"a Prince?"
} else {
"a King?"
}
}print(makeSentence4())
Benzer şekilde, buildArray()
oluşturucu tipimize bir method ekleyerek döngüler için destek ekleyebiliriz :
@resultBuilder
struct ComplexStringBuilder {
staticfunc buildBlock(_ parts: String...) -> String {
parts.joined(separator: "\n")
}staticfunc buildEither(first component: String) -> String {
return component
}staticfunc buildEither(second component: String) -> String {
return component
}staticfunc buildArray(_ components: [String]) -> String {
components.joined(separator: "\n")
}
}
Ve şimdi for
döngüleri kullanabiliriz :
@ComplexStringBuilder func countDown() -> String {
for i in (0...10).reversed() {
"\(i)…"
} "Lift off!"
}print(countDown())
Result builder neredeyse tüm işi bizim için yapıyor.
Swift 5.4'ün result builder sistemini , depolanmış özelliklere yerleştirilen öznitelikleri destekleyecek şekilde genişlettiğini eklemeye değer , bu da yapıların result builder’a uygulaması için implicit member initiator otomatik olarak ayarlıyor.
Bu özellikle aşağıdakiler gibi result builder kullanan özel SwiftUI view için yararlıdır:
struct CustomVStack<Content: View>: View {
@ViewBuilder let content: Contentvar body: some View {
VStack {
// custom functionality here
content
}
}
}
Local functions overloading
SR-10069 , local function aşırı yükleme yeteneği geldi böylece Swift, kullanılan türlere göre hangisinin çalıştırılacağını seçer.
Örneğin, bazı basit çerezler yapmak istersek, aşağıdaki gibi kod yazabiliriz:
struct Butter { }
struct Flour { }
struct Sugar { }func makeCookies() {
func add(item: Butter) {
print("Adding butter…")
}func add(item: Flour) {
print("Adding flour…")
}func add(item: Sugar) {
print("Adding sugar…")
} add(item: Butter())
add(item: Flour())
add(item: Sugar())
}
Swift 5.4'ten önce, üç add()
methor’u yalnızca iç içe geçmemişlerse aşırı yüklenebilirdi makeCookies()
, ancak Swift 5.4'ten itibaren function aşırı yüklemesi bu durumda da destekleniyor.
Property wrappers
Property wrappers, özelliklere kolay ve yeniden kullanılabilir bir şekilde ekstra işlevsellik eklemenin bir yolu olarak ilk kez Swift 5.1'de tanıtıldı, ancak Swift 5.4'te davranışları, işlevlerde yerel değişkenler olarak kullanılmasını desteklemek için genişletildi.
Örneğin, değerinin hiçbir zaman sıfırın altına düşmemesini sağlayan bir property wrappers oluşturabiliriz:
@propertyWrapper struct NonNegative<T: Numeric & Comparable> {
var value: Tvar wrappedValue: T {
get { value }set {
if newValue < 0 {
value = 0
} else {
value = newValue
}
}
}init(wrappedValue: T) {
if wrappedValue < 0 {
self.value = 0
} else {
self.value = wrappedValue
}
}
}
Ve Swift 5.4'ten itibaren bu property wrappers sadece bir mülke iliştirmek yerine normal bir işlevin içinde kullanabiliriz. Örneğin, oyuncumuzun puan kazanabileceği veya kaybedebileceği ancak puanlarının asla 0'ın altına düşmemesi gereken bir oyun yazabiliriz:
func playGame() {
@NonNegative var score = 0 // player was correct
score += 4 // player was correct again
score += 8 // player got one wrong
score -= 15 // player got another one wrong
score -= 16 print(score)
}
Not : Swift 5.4, 1 sadece Xcode 12.5 aracılığıyla kullanılabilir.
Yorum Yap