İlişkili değerleri yok sayarak ardışık Swift enum durumlarını bastırmak için ayrı bir durum anahtarını karşılaştırın ve her dizideki ilk tam değeri koruyun. Bu yerel Mac örneği sıralamayı korur ve bir durumun başka bir durumdan sonra yeniden görünmesine izin verir.
Yinelenen olarak tam olarak neyin sayılacağını tanımlayın
Bir masaüstü grafik önizlemesinin şu adımlardan oluşan sentetik bir dizi ürettiğini varsayalım: boşta, adı belirtilmiş bir şekli çizme ve adı belirtilmiş bir önizlemeyi gösterme. Durum geçişlerinin kısa bir listesini istiyorsunuz. Şekil adları farklı olsa bile ardışık iki çizim adımı yinelenen sayılır.
Swift enum'ları her durum için farklı ilişkili değerler taşıyabilir. Bu değerler enum değerinin parçasıdır; dolayısıyla onları yok saymayı seçmek için açık bir karşılaştırma kuralı gerekir. Swift dil kılavuzu bu ayrımı Enumerations bölümünde açıklar.
Bu görev için şu sözleşmeyi kullanın:
- İlk girdi değerini koruyun.
- Sonraki değerlerden, durumu önceki dizinin durumuyla eşleşenleri bastırın.
- Korunan her öğenin ilişkili değerinin tamamını saklayın.
- Farklı bir durumdan sonra geldiğinde aynı duruma yeniden izin verin.
- Girdi sırasını koruyun; boş bir girdi boş bir sonuç üretir.
Aşağıda örnek bir girdi için amaçlanan davranış gösterilmiştir. Tüm adlar sentetiktir.
| Girdi değeri | Karar | Gerekçe |
|---|---|---|
.idle |
Koru | İlk değer |
.drawing("Circle") |
Koru | Durum değişti |
.drawing("Square") |
Bastır | Hâlâ çizim yapılıyor |
.ready("Preview A") |
Koru | Durum değişti |
.ready("Preview B") |
Bastır | Hâlâ hazır |
.drawing("Triangle") |
Koru | Hazır durumundan sonra çizim geliyor |
.idle |
Koru | Durum değişti |
.idle |
Bastır | Hâlâ boşta |
Böylece korunan çizim değerleri \"Circle\" ve \"Triangle\" olur. \"Square\" yükü bilerek dışarıda bırakılır. Masaüstü görünümünün güncellenen tüm şekil adlarını göstermesi gerekiyorsa bu sözleşme görünümün ihtiyaç duyduğu değişiklikleri atar; bu tüketici için yüke duyarlı bir karşılaştırma seçin.
Mac'inizde eksiksiz bir yerel Swift örneği çalıştırın
Çalışan bir Swift geliştirme ortamına sahip bir Mac kullanın. Swift.org, Apple platformu geliştirme için Xcode'u önerir ve Swift Package Manager ile komut satırında çalıştırılabilir dosya oluşturma iş akışını belgeler. Araçları hazırlamanız gerekiyorsa Install Swift — macOS yönergelerini izleyin.
Terminal'de yeni bir çalışma dizininde küçük bir çalıştırılabilir paket oluşturun:
mkdir EnumCaseDemo
cd EnumCaseDemo
swift package init --name EnumCaseDemo --type executable
Oluşturulan çalıştırılabilir kaynak dosyasının içeriğini aşağıdaki eksiksiz programla değiştirin. Program Swift standart kitaplık türlerini kullanır; içe aktarma veya paket bağımlılığı gerektirmez. Girdisi ve çıktısı bellekte kalır; korunan sentetik adımları yazdırır.
enum PreviewStep: Equatable {
case idle
case drawing(String)
case ready(String)
enum Kind: Equatable {
case idle
case drawing
case ready
}
var kind: Kind {
switch self {
case .idle:
return .idle
case .drawing(_):
return .drawing
case .ready(_):
return .ready
}
}
var label: String {
switch self {
case .idle:
return "idle"
case .drawing(let shape):
return "drawing: \(shape)"
case .ready(let name):
return "ready: \(name)"
}
}
}
func suppressConsecutiveCases(
_ steps: [PreviewStep]
) -> [PreviewStep] {
var result: [PreviewStep] = []
var previousKind: PreviewStep.Kind? = nil
for step in steps {
let currentKind = step.kind
if let previous = previousKind,
previous == currentKind {
continue
}
result.append(step)
previousKind = currentKind
}
return result
}
let input: [PreviewStep] = [
.idle,
.drawing("Circle"),
.drawing("Square"),
.ready("Preview A"),
.ready("Preview B"),
.drawing("Triangle"),
.idle,
.idle
]
let expected: [PreviewStep] = [
.idle,
.drawing("Circle"),
.ready("Preview A"),
.drawing("Triangle"),
.idle
]
let output = suppressConsecutiveCases(input)
precondition(output == expected)
precondition(suppressConsecutiveCases([]).isEmpty)
precondition(
suppressConsecutiveCases([
.drawing("Circle"), .drawing("Square")
]) == [.drawing("Circle")]
)
precondition(
suppressConsecutiveCases([
.idle, .drawing("Circle"), .idle
]) == [.idle, .drawing("Circle"), .idle]
)
for step in output {
print(step.label)
}
Paketi kendi dizininden çalıştırın:
swift run EnumCaseDemo
Derleme mesajlarından sonra beklenen program çıktısı şöyledir:
idle
drawing: Circle
ready: Preview A
drawing: Triangle
idle
Bu örnekler, alınan belgelere göre incelendi; araştırma ortamında Swift çalıştırılabilir dosyası bulunmadığından burada yürütülmedi. Dahil edilen önkoşul kontrolleri beklenen korunan yükleri, boş girdiyi, art arda gelen farklı yükleri ve bir geçişten sonra durumun yeniden görünmesini denetler.
Ayrı bir durum anahtarı neden işe yarar
kind özelliği, her tam enum değerini yük taşımayan küçük bir anahtara dönüştürür. Hem .drawing("Circle") hem de .drawing("Square") .drawing anahtarını üretir. Filtreleme işlevi bu anahtarları karşılaştırırken özgün step değerini ekler; böylece korunan ilişkili değerler olduğu gibi kalır.
İşlevin hatırlaması gereken tek bir anahtar vardır. Başlangıçta previousKind, nil değeridir ve bu, ilk öğenin geçmesine izin verir. Bir öğeyi koruduktan sonra onun türünü hatırlar. Bastırılan öğeler aynı türde olduğundan, onlar için hatırlanan anahtarı güncellemek sonucu değiştirmez.
Bu uygulama girdiyi bir kez dolaşır. Bu sabit enum ve sabit boyutlu anahtarları için, sonraki her öğede bir durum anahtarı karşılaştırması yapar ve döndürülen dizi dışında sabit miktarda yardımcı durum kullanır. Swift'in Sequence belgeleri, sıralı yinelemeyi ve olağan doğrusal dolaşım modelini açıklar.
Tam PreviewStep türü ayrıca Equatable uyumludur; bu sayede önkoşullar, korunan dizeler de dahil olmak üzere sonuçların tamamını doğrulayabilir. İlişkili değerleri Equatable uyumlu olan uygun enum'larda Swift eşitliğin sentezlenmesini destekler; Protocols bölümüne bakın. Durum karşılaştırmasını Kind içinde tutmak, program genelinde eşitliği yeniden tanımlamadan bu filtreleme işlemine açık bir kural verir.
kind içindeki kapsamlı switch yapısı da yararlı bir bakım kontrol noktası sunar. Yeni bir durum eklediğinizde ona karşılık gelen anahtarı ve eşlemeyi de ekleyin. Yeni bir durumu yanlışlıkla mevcut bir durumla gruplandırabilecek genel bir eşlemeden kaçının. Swift, enum'lar üzerinde kapsamlı switch kullanımını Enumerations bölümünde belgeler.
Combine ile aynı karşılaştırmayı kullanın
Mac kodunuz zaten bir Combine publisher kullanıyorsa Apple, özel bir karşılaştırma için removeDuplicates(by:) sağlar. Yüklemi, ikinci değerin yinelenen sayılması gerektiğinde true döndürür. Apple, istenen karşılaştırma çıktı türünün olağan eşitliğinden farklı olduğunda bu operatörün kullanımını açıkça destekler. macOS 10.15 ve sonraki sürümlerde kullanılabilir. Bkz. removeDuplicates(by:).
Aşağıdaki kod bağımsız bir program değil, bir uzantı parçasıdır. Combine'ın kullanılabildiği bir Mac'te bunu yukarıdaki eksiksiz örneğe ekleyin. Mevcut PreviewStep tanımını ve input dizisini yeniden kullanır:
import Combine
let subscription = input.publisher
.removeDuplicates { previous, current in
previous.kind == current.kind
}
.sink { step in
print("Combine: \(step.label)")
}
Bu, aynı beş korunan adımı \"Combine: \" önekiyle yazdırır. Yüklem durum anahtarlarını karşılaştırır ve publisher, korunan özgün enum değerlerini aktarır. Apple'ın kendi operatör örneği de bir özelliği karşılaştırıp diğerini yok sayarak aynı ilkeyi izler. removeDuplicates(by:)
Döndürülen aboneliği, gereken abonelik süresi boyunca canlı tutun. Apple, sink(receiveValue:) tarafından döndürülen değerin serbest bırakılmasının aboneliği sonlandırdığını belgeler. Bu aşırı yük, Apple'ın dizi publisher örneklerinde olduğu gibi hata türü Never olan publisher'lar için geçerlidir. sink(receiveValue:)
Kodu uyarlamadan önce sınır durumlarını denetleyin
Elinizde zaten sonlu bir yerel liste varsa dizi işlevini kullanın. Değerler zaten bir publisher üzerinden geliyorsa Combine operatörünü kullanın. Buradaki iki sürüm de aynı durum geçişi sözleşmesini ifade eder.
| Gereksinim | Uygun karşılaştırma veya yaklaşım |
|---|---|
| Her durum dizisindeki ilk tam değeri korumak | Gösterildiği gibi kind değerini karşılaştırın |
| İlişkili dizelerdeki değişiklikleri korumak | Olağan eşitliği kullanarak tam değerleri karşılaştırın |
| Her dizideki son tam değeri korumak | Bekleyen bir değeri arabelleğe alın; durum geçişinde ve sonda arabelleği boşaltın |
| Başka bir durumdan sonra geri dönen durumu korumak | Genel bir daha önce görülmüş durum listesi tutmak yerine ardışık dizileri karşılaştırın |
| Ayrı dizileri birbirinden bağımsız filtrelemek | İşlevi ayrı ayrı çağırın; her çağrı karşılaştırma durumunu boş başlatır |
Son yükü korumak farklı bir algoritma gerektirir; çünkü bu program ilk değeri hemen ekler. Benzer şekilde, tek bir mantıksal diziyi ayrı dizilere bölmek karşılaştırma durumunu sıfırlar: bir grubun sonundaki çizim değeri ile sonraki grubun başındaki başka bir çizim değeri ayrı çağrılarda ikisi de korunur. Grupların tek bir dizi gibi davranması gerekiyorsa önceki anahtarı grup sınırları boyunca koruyun.
Foundation, Apple platformu uygulamaları için koleksiyonlar ve diğer temel işlevleri sağlar; ancak bu hesaplama tümüyle Swift türleriyle uygulanır. Publisher sürümü özellikle Combine gerektirir; import Foundation eklemek bu operatörü içe aktarmaz. Apple, bu çerçeveleri Foundation ve removeDuplicates(by:) bölümlerinde ayrı ayrı belgeler.
Eşzamanlı dizi işlevi de eşzamanlılık mekanizması gerektirmez: karşılaştırma durumu her çağrıya aittir. Daha sonra paylaşılan masaüstü sunum durumu eklerseniz bu durumun yalıtımını ayrıca tanımlayın. Apple, MainActor'ı yürütücüsü ana dispatch kuyruğuna eşdeğer olan tekil bir aktör olarak belgeler; yinelenenleri bastırma işlemi kendi başına bir aktör seçmez. MainActor
Burada gösterilen yerel görev için belirleyici seçim, bir dizide hangi yükün korunacağıdır. İlk yükü seçtikten sonra ayrı bir durum anahtarıyla davranışı kolayca okuyup doğrulayabilirsiniz: durum geçişinde özgün değeri koruyun, eşleşen ardışık anahtarları bastırın ve geri dönen durumların geçmesine izin verin.
Kaynaklar
- Enumerations — The Swift Programming Language, Swift.org.
- Protocols — The Swift Programming Language, Swift.org.
- Install Swift — macOS — Swift.org.
- Sequence — Apple Developer Documentation.
- removeDuplicates(by:) — Apple Developer Documentation.
- sink(receiveValue:) — Apple Developer Documentation.
- Foundation — Apple Developer Documentation.
- MainActor — Apple Developer Documentation.