├── A-Temeller ├── 3-Standartlar │ ├── 5-Labeled Statements.md │ ├── 1- Karşılaştırmalar.md │ ├── 3- İf statements.md │ ├── 2-For Loop.md │ └── 4- Switch.md ├── 1-Değişkenler │ ├── 7-Any ve AnyObject.md │ ├── 3-Tür dönüşümleri.md │ ├── 4-Touples.md │ ├── 2-Integer.md │ ├── 1-Değişkenler Giriş.md │ ├── 5-Optionals.md │ └── 6-String.md ├── 2-Operatörler │ ├── 4-Available.md │ ├── 3-Defer.md │ ├── 1-Operatörlere Giriş.md │ └── 2-Guard.md └── 4-Ekstralar │ └── 1- Value ve Reference Types Kavramı.md ├── B-Collections ├── 5-Flatmap ve Reduce.md ├── 2-Sets.md ├── 4-Map-CompactMap.md ├── 3-Dictionaries.md └── 1-Array.md ├── K-Initialization ├── 5-Deinit.md ├── 3-Initializer Overriding.md ├── 2-Initializer Delegation.md ├── 4-Failable Initializers.md └── 1-Initialization.md ├── N-Concurrency ├── 2-Async Sequence.md ├── 1-Concurrency.md ├── 5-Sendable Types.md ├── 4-Actors.md └── 3-Unstructured Concurrency.md ├── J-Inheritance ├── 1-Inheritance.md └── 2-Override.md ├── L-Optional Chaining └── 1-Optional Chaining.md ├── O-Macros ├── 2-AST.md └── 1-Macros.md ├── F-Struct & Class ├── 1-Class.md ├── 2-Struct.md ├── 5-Ne Zaman Struct - Ne Zaman Class.md ├── 3-Encapsulation.md └── 4-Arasındaki Farklılıklar.md ├── LICENSE ├── C-Fonksiyonlar ├── 3-Function Types.md ├── 2-Parametreler.md └── 1-Değer Döndüren Fonksiyonlar.md ├── G-Properties ├── 2-Property Observers.md ├── 4-Type Properties.md ├── 3-Property Wrappers.md └── 1-Properties.md ├── R-Extensions └── 1-Extensions.md ├── P-Types ├── 1-Type Casting.md ├── 2-Nested Types.md └── 3-Opaque & Boxed Types.md ├── I-Subscripts └── 1-Subscripts.md ├── S-Protocols ├── 2-Delegation.md ├── 3-Standart Protocols.md └── 1-Protocols.md ├── M-Error Handling └── 1-Error Handling.md ├── T-Generics └── 1-Generics.md ├── U-Memory ├── 2-Memory Safety.md └── 1-ARC.md ├── E-Enumeration └── 1-Enumeration.md ├── V-Access Control └── 1- Access Control.md ├── D-Closure └── 1-Closure.md ├── H-Methods └── 1-Methods.md └── README.md /A-Temeller/3-Standartlar/5-Labeled Statements.md: -------------------------------------------------------------------------------- 1 | ## Labeled Statements 2 | 3 | Bir döngü veya switch ifadesine isim vermek için kullanılır. Break ve continue ifadelerinde doğrudan bu isim eklenerek yalnızca istediğimiz döngü veya switch ifadesinden çıkabiliriz. 4 | 5 | ```swift 6 | outerLoop: for i in 1...10 { 7 | for j in 1...10 { 8 | let product = i * j 9 | if product == 50 { 10 | print("50 bulundu!") 11 | break outerLoop 12 | } 13 | } 14 | } 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /A-Temeller/1-Değişkenler/7-Any ve AnyObject.md: -------------------------------------------------------------------------------- 1 | ## Any ve AnyObject 2 | 3 | Any, Swift dilinde, herhangi bir türden değerleri temsil etmek için kullanılır. AnyObject, Swift dilinde, herhangi bir sınıf türünden değerleri temsil etmek için kullanılır. Any ve AnyObject, tür güvenliği olmayan kod yazmak için kullanılır. Bu nedenle, Any ve AnyObject kullanımından kaçınılmalıdır. 4 | 5 | ```swift 6 | var anyValue: Any = 5 7 | anyValue = "Hello, World!" 8 | anyValue = true 9 | ``` 10 | 11 | ```swift 12 | var anyObjectValue: AnyObject = "Hello, World!" 13 | anyObjectValue = 5 14 | anyObjectValue = true 15 | ``` 16 | -------------------------------------------------------------------------------- /A-Temeller/1-Değişkenler/3-Tür dönüşümleri.md: -------------------------------------------------------------------------------- 1 | ## Tür Dönüşümleri 2 | 3 | Swift'te tür dönüştürebilmek için doğrudan tür adı ve parantezler kullanılır. 4 | 5 | Örneğin Int bir değeri Double'a dönüştürmek için: 6 | 7 | ```swift 8 | let three = 3 9 | let pointOneFourOneFiveNine = 0.14159 10 | let pi = Double(three) + pointOneFourOneFiveNine 11 | ``` 12 | 13 | ## typealias 14 | 15 | Swift'te istersek kendimizde bir tür oluşturup buna isim verebiliriz. Buna typealias ismi veriliyor. 16 | 17 | Örneğin: 18 | 19 | ```swift 20 | typealias AudioSample = UInt16 21 | var maxAmplitudeFound = AudioSample.min 22 | ``` 23 | 24 | -------------------------------------------------------------------------------- /B-Collections/5-Flatmap ve Reduce.md: -------------------------------------------------------------------------------- 1 | ## Flatmap 2 | 3 | Birden fazla array varsa ve bu arraylerin içindeki elemanları tek bir array içinde toplamak istiyorsak flatmap kullanırız. 4 | 5 | ```swift 6 | let numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 7 | let flatMapped = numbers.flatMap { $0 } 8 | print(flatMapped) // [1, 2, 3, 4, 5, 6, 7, 8, 9] 9 | ``` 10 | 11 | ## Reduce 12 | 13 | Reduce fonksiyonu bir arrayi tek bir değere indirgemek için kullanılır. Örneğin bir arraydeki sayıların toplamını bulmak için reduce kullanabiliriz. 14 | 15 | ```swift 16 | let numbers = [1, 2, 3, 4, 5] 17 | let sum = numbers.reduce(0) { $0 + $1 } 18 | print(sum) // 15 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /K-Initialization/5-Deinit.md: -------------------------------------------------------------------------------- 1 | ## Deinit 2 | 3 | Bir class'ın deinit fonksiyonu, class'ın bir instance'ı yok edilirken çağrılır. Deinitler yalnızca class'larda kullanılabilir. Swift, bir instance'a artık ihtiyaç olmazsa bu işlemi otomatik olarak yapar. Ancak bazı durumlarda bizim bellek yönetimi için manuel olarak bu işlemi yapmamız gerekebilir. Deinit herhangi bir parametre almaz ve parantezsiz yazılır. 4 | 5 | ```swift 6 | class SomeClass { 7 | deinit { 8 | // perform the deinitialization 9 | } 10 | } 11 | ``` 12 | 13 | Inheritance olarak deinit superclass'tan subclass'lara doğru aktarılır. Superclass'ların deinit'leri subclass'larda tanımlanmasa bile her zaman çağırılır. 14 | 15 | -------------------------------------------------------------------------------- /A-Temeller/3-Standartlar/1- Karşılaştırmalar.md: -------------------------------------------------------------------------------- 1 | ## Touples Karşılaştırmaları 2 | 3 | Soldan sağa doğru karşılaştırma yapılır. İlk true yakalanana kadar devam eder. 4 | 5 | ```swift 6 | (1, "zebra") < (2, "apple") // true because 1 is less than 2; "zebra" and "apple" aren't compared 7 | (3, "apple") < (3, "bird") // true because 3 is equal to 3, and "apple" is less than "bird" 8 | (4, "dog") == (4, "dog") // true because 4 is equal to 4, and "dog" is equal to "dog" 9 | ``` 10 | 11 | Bool değer karşılaştırılamadğı için her Touples'da her zaman false döner. 12 | 13 | ```swift 14 | ("blue", -1) < ("purple", 1) // OK, evaluates to true 15 | ("blue", false) < ("purple", true) // Error because < can't compare Boolean values 16 | ``` -------------------------------------------------------------------------------- /N-Concurrency/2-Async Sequence.md: -------------------------------------------------------------------------------- 1 | ## Async Sequence 2 | 3 | Swift 5.5 ile eklenen bu özellik asenkron operasyonların diziler halinde temsil edilmesini sağlar ve asenkron bir şekilde elemanları üretmeyi destekler. 4 | 5 | Bir asenkron diziyi tanımlamak için `AsyncSequence` protokolünü kullanabiliriz: 6 | 7 | ```swift 8 | func makeAsyncSequence() async -> AsyncSequence { 9 | return AsyncSequence { continuation in 10 | Task { 11 | for i in 1...5 { 12 | await Task.sleep(1_000_000_000) // 1 saniye bekle 13 | continuation.yield(i) 14 | } 15 | } 16 | } 17 | } 18 | 19 | Task { 20 | let asyncSeq = await makeAsyncSequence() 21 | 22 | for await number in asyncSeq { 23 | print(number) 24 | } 25 | } 26 | ``` -------------------------------------------------------------------------------- /J-Inheritance/1-Inheritance.md: -------------------------------------------------------------------------------- 1 | ## Inheritance 2 | 3 | Inheritance yani kalıtım bir class'ın başka bir class'tan özelliklerini almasıdır. Kalıtım alınan class'a **superclass** denir. Kalıtım veren class'a ise **subclass** denir. Hiçbir inheritance işlemi yapılmamış class'lar **base class** olarak adlandırılır. Swift çoklu kalıtımı desteklemez. 4 | 5 | Kalıtım için basitçe : operatorü kullanılır. 6 | 7 | ```swift 8 | class Vehicle { 9 | var currentSpeed = 0.0 10 | var description: String { 11 | return "traveling at \(currentSpeed) miles per hour" 12 | } 13 | func makeNoise() { 14 | // do nothing - an arbitrary vehicle doesn't necessarily make a noise 15 | } 16 | } 17 | 18 | class Car: Vehicle { // Car class'ı Vehicle class'ından kalıtım aldı. 19 | 20 | } 21 | ``` -------------------------------------------------------------------------------- /L-Optional Chaining/1-Optional Chaining.md: -------------------------------------------------------------------------------- 1 | ## Optional Chaining 2 | 3 | Optional Chaining, bir değeri veya metodu zincirleme şeklinde güvenli bir şekilde kullanmanıza olanak sağlayan bir özelliktir. Bu özellik, birçok durumda nil değerlerle çalışırken güvenliğinizi sağlamak için kullanılır. 4 | 5 | Optional Chaining'in temel fikri, bir değeri kullanmadan önce nil kontrolü yapmanıza gerek kalmadan değeri zincirleme şeklinde kontrol etmenizi sağlamaktır. Bu, nil değerlerle çalışırken sürekli nil kontrolü yapma ihtiyacını ortadan kaldırır ve kodunuzun daha temiz ve daha okunaklı olmasını sağlar. 6 | 7 | Optional Chaining'i kullanarak bir değeri veya metodu zincirleme şeklinde erişmek için aşağıdaki syntax'ı kullanabilirsiniz: 8 | 9 | ```swift 10 | optionalValue?.property 11 | optionalValue?.method() 12 | ``` -------------------------------------------------------------------------------- /A-Temeller/1-Değişkenler/4-Touples.md: -------------------------------------------------------------------------------- 1 | ## Touples 2 | 3 | İçerisinde çok sayıda ve farklı türde verilerin tutulmasına yarayan data structure. 4 | 5 | Kullanım: 6 | 7 | ```swift 8 | var t1 = (12,14.6,"string",true) 9 | ``` 10 | 11 | Erişmek için: 12 | 13 | ```swift 14 | t1.0 // 12'yi alır 15 | ``` 16 | 17 | Atamada yapabiliriz, uygun türde olması kaydıyla: 18 | 19 | ```swift 20 | t1.0 = 13 21 | ``` 22 | 23 | Touple değerlerine isimde verebiliriz. 24 | 25 | ```swift 26 | var t2 = (td1: 21, td2: "string") 27 | ``` 28 | 29 | Sonradan da isim verebiliriz: 30 | 31 | ```swift 32 | let http404Error = (404, "Not Found") 33 | let (statusCode, statusMessage) = http404Error 34 | ``` 35 | 36 | Eğer sadece birine ihtiyacımız varsa _ ile boşta geçebiliriz. 37 | 38 | ```swift 39 | let (statusCode, _ ) = http404Error 40 | ``` 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /O-Macros/2-AST.md: -------------------------------------------------------------------------------- 1 | ## AST (Abstract Syntax Tree) 2 | 3 | AST, Swift dilinde, derleme süreci sırasında kaynak kodun analiz edilmesi ve derlenmesi için kullanılır. AST, kaynak kodun sözdizimini ve semantik yapısını ağaç benzeri bir yapıda temsil eder. Bu ağaç, derleyici tarafından kullanılarak derleme süreci boyunca kodun analiz edilmesi ve optimize edilmesi için kullanılır. 4 | 5 | AST, kaynak kodun her bir ifadesini, deyimi veya deklarasyonu bir düğüm olarak temsil eder. Bu düğümler, birbirleriyle ilişkili olarak bağlantılıdır ve programın yapısını yansıtır. AST, dilbilgisine ve derleme sürecine bağlı olarak farklı düğüm türlerini içerebilir, örneğin değişken tanımlamaları, fonksiyon çağrıları, kontrol akış ifadeleri vb. 6 | 7 | AST, derleme sürecinin bir aşamasında kodun analiz edildiği ve sentaktik ve semantik hataların tespit edildiği noktada kullanılır. Ayrıca, derleme optimizasyonları da AST'yi kullanarak gerçekleştirilir. -------------------------------------------------------------------------------- /A-Temeller/2-Operatörler/4-Available.md: -------------------------------------------------------------------------------- 1 | ## Available 2 | 3 | İşletim sistemi, platform ve derleme koşullarına göre kodun çalıştırılmasını sağlar. 4 | 5 | ```swift 6 | @available(macOS 10.12, *) 7 | struct ColorPreference { 8 | var bestColor = "blue" 9 | } 10 | 11 | 12 | func chooseBestColor() -> String { 13 | guard #available(macOS 10.12, *) else { 14 | return "gray" 15 | } 16 | let colors = ColorPreference() 17 | return colors.bestColor 18 | } 19 | 20 | ``` 21 | 22 | ```swift 23 | if #available(iOS 10, macOS 10.12, *) { 24 | // Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS 25 | } else { 26 | // Fall back to earlier iOS and macOS APIs 27 | } 28 | 29 | ``` 30 | 31 | Ters kontrolde mümükün: 32 | 33 | ```swift 34 | if #available(iOS 10, *) { 35 | } else { 36 | // Fallback code 37 | } 38 | 39 | 40 | if #unavailable(iOS 10) { 41 | // Fallback code 42 | } 43 | ``` -------------------------------------------------------------------------------- /A-Temeller/1-Değişkenler/2-Integer.md: -------------------------------------------------------------------------------- 1 | ## Integer 2 | 3 | Swift 8, 16, 32 ve 64 bitlik int tanımlamalarına izin verir. 4 | 5 | Burada bitlik tanımlamalar işaretli ve işaretsiz olarak ikiye ayrılır. 6 | 7 | İşaretliler için doğrudan Int8, Int32 gibi tanımlamalar kullanılır. 8 | 9 | Örneğin Int8 için: 10 | 11 | ```swift 12 | let myInt : Int8 = 120 --> bu değişkenin değer aralığı -128 ile 127 arasındadır yani negatif değer alabilir 13 | ``` 14 | 15 | ```swift 16 | let myInt : UInt8 = 120 -> bu değişken ise negatif değer alamaz. Aralığı 0 ile 255'tir 17 | ``` 18 | 19 | Yazılacak kod bu tarzda minik bit ayarlamaları ve işaretli/işaretsiz ayarlamalarına ihtiyaç duymuyorsa sayının negatif olunacağı bilinse bile Int kullanılmalı. 20 | 21 | ## Sınırlar (Max-Min) 22 | 23 | Integer'da değişken tanımlamasından sonra değer aralığının max ve minini her zaman alabiliriz. 24 | 25 | Örneğin: 26 | 27 | ```swift 28 | let myInt = Int8.max -> Int8'nin max değeri atanır. 29 | ``` 30 | -------------------------------------------------------------------------------- /N-Concurrency/1-Concurrency.md: -------------------------------------------------------------------------------- 1 | ## Concurrency 2 | 3 | Bu başlık altında Swift'in asenkron programlama için sunduğu özellikleri inceleyeceğiz. 4 | 5 | Bir asenkron fonksiyonu tanımlamak için `async` anahtar kelimesini kullanabiliriz: 6 | 7 | ```swift 8 | func fetchUser() async -> User { 9 | // ... 10 | } 11 | ``` 12 | 13 | Birden fazla async fonksiyon oluşturur ve çağırırsak hepsi sırasıyla birer birer çalışacaktır. 14 | 15 | Toplu async fonksiyonu çağırmak için şöyle bir kısa yol izlenebilir: 16 | 17 | ```swift 18 | async let firstPhoto = downloadPhoto(named: photoNames[0]) 19 | async let secondPhoto = downloadPhoto(named: photoNames[1]) 20 | async let thirdPhoto = downloadPhoto(named: photoNames[2]) 21 | 22 | 23 | let photos = await [firstPhoto, secondPhoto, thirdPhoto] 24 | show(photos) 25 | ``` 26 | 27 | Fonksiyonu çağırırken işlem tamamlanana kadar beklemek için `await` anahtar kelimesini kullanabiliriz: 28 | 29 | ```swift 30 | let user = await fetchUser() 31 | ``` 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /A-Temeller/3-Standartlar/3- İf statements.md: -------------------------------------------------------------------------------- 1 | ## If 2 | 3 | Bir if bloğundan direkt olarak bir değer yakalayabiliriz. Burada değerlerin türleri aynı olmalıdır. 4 | 5 | Örneğin: 6 | 7 | ```swift 8 | let weatherAdvice = if temperatureInCelsius <= 0 { 9 | "It's very cold. Consider wearing a scarf." 10 | } else if temperatureInCelsius >= 30 { 11 | "It's really warm. Don't forget to wear sunscreen." 12 | } else { 13 | "It's not that cold. Wear a T-shirt." 14 | } 15 | 16 | 17 | print(weatherAdvice) 18 | // Prints "It's not that cold. Wear a T-shirt." 19 | ``` 20 | 21 | ## If Let Kullanımı 22 | 23 | if let ifadesi, bir değerin nil olup olmadığını kontrol etmek ve değeri nil olmayan bir geçici sabite atamak için kullanılır. Bu, güvenli bir şekilde nil değerlerini ele almanın bir yoludur. 24 | 25 | ```swift 26 | let optionalNumber: Int? = 42 27 | 28 | if let number = optionalNumber { 29 | print("Optional number is not nil. Value is \(number)") 30 | } else { 31 | print("Optional number is nil.") 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /F-Struct & Class/1-Class.md: -------------------------------------------------------------------------------- 1 | ## Class 2 | 3 | Oluşturma syntax'ı aşağıdaki gibidir. 4 | 5 | ```swift 6 | class SomeClass { 7 | // class definition goes here 8 | } 9 | ``` 10 | 11 | ## Değişkenler İçin Bellek Yönetimi 12 | 13 | - Weak = Weak olarak işaretlenmiş bir değişken bellekten kaldırılma konusunda önceliklidir. 14 | 15 | Örnek: 16 | 17 | ```swift 18 | weak var myWeakVar = SomeClass() 19 | ``` 20 | 21 | - Strong = Strong olarak işaretlenmiş bir değişken bellekten kaldırılma konusunda öncelikli değildir. Bellekte tutulmaya çalışılır. Strong yapmak için herhangi bir şey yazmaya gerek yok default olarak değişken tanımlandığında strong'tur. 22 | 23 | Örnek: 24 | 25 | ```swift 26 | var myStrongVar = SomeClass() 27 | ``` 28 | ## Identity Operator 29 | 30 | Class'lar referans tipli olduğu için bellekteki adresleriyle karşılaştırılır. Bu yüzden == operatörü yerine === operatörü kullanılır. 31 | 32 | ```swift 33 | if someIdenticalPerson === anotherPerson { 34 | print("These two people are indeed the same person") 35 | } 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /A-Temeller/3-Standartlar/2-For Loop.md: -------------------------------------------------------------------------------- 1 | ## For Loop 2 | 3 | Key ve value'a göre iterasyon örneği: 4 | 5 | ```swift 6 | let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] 7 | for (animalName, legCount) in numberOfLegs { 8 | print("\(animalName)s have \(legCount) legs") 9 | } 10 | ``` 11 | 12 | Aralık olarak iterasyon: 13 | 14 | ```swift 15 | for index in 1...5 { 16 | print("\(index) times 5 is \(index * 5)") 17 | } 18 | // 1 times 5 is 5 19 | // 2 times 5 is 10 20 | // 3 times 5 is 15 21 | // 4 times 5 is 20 22 | // 5 times 5 is 25 23 | ``` 24 | 25 | İndex kullanılmayacaksa tanımlanmayabilir: 26 | 27 | ```swift 28 | let base = 3 29 | let power = 10 30 | var answer = 1 31 | for _ in 1...power { 32 | answer *= base 33 | } 34 | print("\(base) to the power of \(power) is \(answer)") 35 | // Prints "3 to the power of 10 is 59049" 36 | ``` 37 | 38 | ## For Loop'ta Value Binding 39 | 40 | ```swift 41 | let numbers = [1, 2, 3, 4, 5] 42 | 43 | for case let number in numbers where number % 2 == 0 { 44 | print("\(number) çift bir sayıdır.") 45 | } 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 DogukanSakin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /A-Temeller/1-Değişkenler/1-Değişkenler Giriş.md: -------------------------------------------------------------------------------- 1 | ## Swift'te Değişken Tipleri 2 | 3 | Swift Type Safety bir dil olduğu için kullanılabilir tipler: 4 | 5 | - Int 6 | - Float 7 | - Double 8 | - String 9 | - Bool 10 | 11 | ## Swift'te Sabit/Değişebilen Tanımlama 12 | 13 | Değişebilenleri tanımlarken var kullanılır. 14 | 15 | Örneğin: 16 | 17 | ```swift 18 | var d1: Int = 6 19 | ``` 20 | 21 | Sabitler tanımlarken let kullanılır. 22 | 23 | Örneğin: 24 | 25 | ```swift 26 | let pi: Float = 3.14 27 | ``` 28 | 29 | ## Değişkenler İçin Ek Bilgiler 30 | 31 | - Ondalıklı sayı tanımlandığında default olarak double tanımlanır 32 | 33 | Örneğin: 34 | 35 | ```swift 36 | var d = 5.6 // Türü double -- Float olmasını istersek başta türünü belirtmeliyiz. 37 | ``` 38 | 39 | - Swift Type Safety dildir. Eğer tür belirtilmezse başta eşitlenen değeri alacaktır. Buna Type Inference denir. 40 | 41 | - Bir türü başka bir türe dönüştürürken muhakkak yeni değişken tanımlanmalı ve işlem yapabilmek için aynı türde olmalı. 42 | 43 | ```swift 44 | let twoThousand: UInt16 = 2_000 45 | let one: UInt8 = 1 46 | let twoThousandAndOne = twoThousand + UInt16(one) 47 | ``` 48 | 49 | 50 | -------------------------------------------------------------------------------- /A-Temeller/2-Operatörler/3-Defer.md: -------------------------------------------------------------------------------- 1 | ## Defer 2 | 3 | "defer" ifadesi, bir kod bloğunun, belirli bir kapsamdan çıkış yapmadan hemen önce çalıştırılmasını sağlayan bir yapıdır. Defer ifadesi, genellikle kaynakların temizlenmesi, dosyaların kapatılması veya geçici durumların sıfırlanması gibi işlemleri gerçekleştirmek için kullanılır. 4 | 5 | Defer ifadesi, bir blok içindeki kodun sona erdiği noktada veya kapsamdan çıkış yapılacağı noktada çalıştırılır. Bu, fonksiyonun sonunda, döngünün tamamlanmasında veya bir kontrol akışı yapısının sonunda çalıştırılmasını sağlar. Defer ifadesi, kodun okunabilirliğini artırır ve kaynak yönetimi ve temizleme işlemlerini daha tutarlı ve hatasız hale getirir. 6 | 7 | ```swift 8 | var score = 1 9 | if score < 10 { 10 | defer { 11 | print(score) 12 | } 13 | score += 5 14 | } 15 | // Prints "6" 16 | ``` 17 | 18 | Bir kod bloğunda birden fazla defer varsa en son tanımlanan ilk çalışır. 19 | 20 | ```swift 21 | if score < 10 { 22 | defer { 23 | print(score) 24 | } 25 | defer { 26 | print("The score is:") 27 | } 28 | score += 5 29 | } 30 | // Prints "The score is:" 31 | // Prints "6" 32 | ``` 33 | -------------------------------------------------------------------------------- /B-Collections/2-Sets.md: -------------------------------------------------------------------------------- 1 | ## Setler 2 | 3 | İndex değeri olmadan aynı türdeki dataları saklar. 4 | 5 | Örnek: 6 | 7 | ```swift 8 | var letters = Set() 9 | print("letters is of type Set with \(letters.count) items.") 10 | // Prints "letters is of type Set with 0 items." 11 | ``` 12 | 13 | Bir seti Array olarak da tanımlayabiliriz: 14 | 15 | ```swift 16 | var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"] 17 | ``` 18 | 19 | Swift inferences sayesinde şöyle de tanımlayabiliriz: 20 | 21 | ```swift 22 | var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"] 23 | ``` 24 | 25 | Arrayde kullandığımız insert, remove gibi fonksiyonlar burada da kullanılabilir. 26 | 27 | Setlerde sıralama olmadığı için for ile iterasyon yaparken sıralı bir şekilde dönmeyebilir. Bunun için sorted fonksiyonu kullanılabilir. 28 | 29 | ```swift 30 | for genre in favoriteGenres.sorted() { 31 | print("\(genre)") 32 | } 33 | // Classical 34 | // Hip hop 35 | // Jazz 36 | // Rock 37 | ``` 38 | 39 | Eleman eklemek için insert kullanılır. 40 | 41 | ## Setlerde kesişim 42 | 43 | -------------------------------------------------------------------------------- /B-Collections/4-Map-CompactMap.md: -------------------------------------------------------------------------------- 1 | ## Map Kullanımı 2 | 3 | Map bir arrayden yeni bir array oluşturmak için kullanılıyor. 4 | 5 | ```swift 6 | let numbers = [1, 2, 3, 4, 5] 7 | let doubledNumbers = numbers.map { $0 * 2 } 8 | print(doubledNumbers) // [2, 4, 6, 8, 10] 9 | ``` 10 | 11 | ```swift 12 | let names = ["John", "Paul", "George", "Ringo"] 13 | let uppercasedNames = names.map { (names) -> String in 14 | return names.uppercased() 15 | } 16 | print(uppercasedNames) // ["JOHN", "PAUL", "GEORGE", "RINGO"] 17 | ``` 18 | 19 | ```swift 20 | let numbers = [1, 2, 3, 4, 5] 21 | let strings = numbers.map { number in return String(number) } 22 | print(strings) // ["1", "2", "3", "4", "5"] 23 | ``` 24 | 25 | ```swift 26 | let numbers = [1, 2, 3, 4, 5] 27 | let strings = numbers.map {( String($0)) } 28 | print(strings) // ["1", "2", "3", "4", "5"] 29 | ``` 30 | 31 | compactMap ise Map ile aynı işi yapar fakat nil değerleri atlar. 32 | 33 | ```swift 34 | let numbers = ["1", "2", "3", "4", "5", "A", "B", "C", "D", "E"] 35 | let mapped: [Int?] = numbers.map { str in Int(str) } 36 | print(mapped) // [1, 2, 3, 4, 5, nil, nil, nil, nil, nil] 37 | let compactMapped: [Int] = numbers.compactMap { str in Int(str) } 38 | print(compactMapped) // [1, 2, 3, 4, 5] 39 | ``` 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /F-Struct & Class/2-Struct.md: -------------------------------------------------------------------------------- 1 | ## Struct 2 | 3 | Swift'te Sturct'lar Class ile aynı amaç doğrultusunda kullanılırlar. Ancak Struct bazı özellikleriyle Class'lardan ayrılmıştır. 4 | 5 | Oluşturma syntax'ı aşağıdaki gibidir. 6 | 7 | ```swift 8 | struct SomeStruct { 9 | // struct definition goes here 10 | } 11 | ``` 12 | 13 | Swift'te struct gibi değer tipli yapıların bütünü kopyalandığında bellek yönetimi için aynı alanlar kullanılır. Bu olay enumlarda da vardır: 14 | 15 | ```swift 16 | enum CompassPoint { 17 | case north, south, east, west 18 | mutating func turnNorth() { 19 | self = .north 20 | } 21 | } 22 | var currentDirection = CompassPoint.west 23 | let rememberedDirection = currentDirection 24 | currentDirection.turnNorth() 25 | 26 | 27 | print("The current direction is \(currentDirection)") 28 | print("The remembered direction is \(rememberedDirection)") 29 | // Prints "The current direction is north" 30 | // Prints "The remembered direction is west" 31 | ``` 32 | 33 | ## Mutable & Immutable 34 | 35 | Struct içerisinde fonksiyonlar aracılığıyla tanımlı ifadeleri değiştirmek için mutating anahtar kelimesiyle tanımlamaya ihtiyaç duyarız. 36 | 37 | ```swift 38 | struct SomeStruct { 39 | var name: String 40 | mutating func changeName(name: String) { 41 | self.name = name 42 | } 43 | } 44 | ``` 45 | 46 | -------------------------------------------------------------------------------- /N-Concurrency/5-Sendable Types.md: -------------------------------------------------------------------------------- 1 | ## Sendable Types 2 | 3 | Swift 5.5 ile gelen bu özellik asenkron işlemler arasında güvenli bir şekilde veri paylaşımını sağlamak için kullanılan türlerdir. 4 | 5 | Sendable türler, eşzamanlılık ve paralellik senaryolarında güvenli bir şekilde kullanılmak üzere tasarlanmıştır. Bu türler, farklı iş parçacıklarında eşzamanlı olarak çalışan asenkron işlemler arasında veri paylaşımını mümkün kılar. 6 | 7 | Bir türün Sendable olarak işaretlenmesi, bu türün eşzamanlılık sorunlarına karşı güvenli olduğunu ve birden çok iş parçacığı tarafından aynı anda erişilebileceğini belirtir. Sendable türler, güvenli bir şekilde kopyalanabilen ve paylaşılabilen türlerdir. 8 | 9 | Sendable bir tür oluşturmak için, türü Sendable protokolünü uygulayacak şekilde işaretlemeniz yeterlidir: 10 | 11 | ```swift 12 | struct Point: Sendable { 13 | var x: Int 14 | var y: Int 15 | } 16 | ``` 17 | 18 | Point yapısı Sendable protokolünü uyguladığı için Sendable olarak işaretlenmiştir. Artık bu Point yapısı, farklı iş parçacıkları arasında güvenli bir şekilde paylaşılabilir. 19 | 20 | Sendable türler, genellikle asenkron işlemlerle birlikte kullanılan aktörler ve diğer eşzamanlılık özellikleriyle birlikte etkin olarak kullanılır. Örneğin, bir aktör içinde Sendable türler kullanarak verilerin güvenli bir şekilde paylaşılmasını sağlayabilirsiniz. 21 | -------------------------------------------------------------------------------- /K-Initialization/3-Initializer Overriding.md: -------------------------------------------------------------------------------- 1 | ## Initializer Overriding 2 | 3 | Swift'te subclass'lar default olarak superclass'ların initializer'ını kalıtım olarak almaz. Initializer'ı override etmek için belirli kurallar vardır: 4 | 5 | - Alt sınıf, üst sınıfın designated initializer'ını override etmek için override anahtar kelimesini kullanmalıdır. Bu, alt sınıfın kendi implementasyonunu sağlar ve üst sınıftaki davranışı değiştirebilir. Override edilen başlatıcı, aynı parametreleri almalıdır ve super.init çağrısı ile üst sınıfın başlatıcısını çağırmalıdır. 6 | 7 | - Convenience initializer'lar üst sınıftaki designated initializer'ı override edemez. 8 | Convenience initializer'lar, sadece aynı sınıf içindeki başka bir başlatıcıyı veya üst sınıftaki convenience initializer'ı çağırabilir. Bu nedenle, bir alt sınıfın convenience initializer'ı, üst sınıftaki designated initializer'ı override edemez. 9 | 10 | - Bir alt sınıf, üst sınıfın convenience initializer'ını override edebilir. Bu durumda, alt sınıfın convenience initializer'ı, üst sınıftaki convenience initializer'ı çağırırken override anahtar kelimesini kullanmalıdır. 11 | 12 | - Bir başlatıcıyı override ederken, override edilen başlatıcının erişim düzeyi değiştirilebilir. Override eden başlatıcının erişim düzeyi, override edilen başlatıcının erişim düzeyinden daha yüksek olamaz. 13 | 14 | Örnek: 15 | 16 | ```swift 17 | class Person { 18 | let name: String 19 | 20 | init(name: String) { 21 | self.name = name 22 | } 23 | } 24 | 25 | class Employee: Person { 26 | let employeeID: String 27 | 28 | init(name: String, employeeID: String) { 29 | self.employeeID = employeeID 30 | super.init(name: name) 31 | } 32 | } 33 | ``` 34 | 35 | subclass'lar override sonrası superclass'ın constant değerlerini değiştiremezler. 36 | 37 | -------------------------------------------------------------------------------- /C-Fonksiyonlar/3-Function Types.md: -------------------------------------------------------------------------------- 1 | ## Function Types 2 | 3 | Swift'te "function types" (fonksiyon tipleri), fonksiyonları ve metotları bir veri türü olarak temsil eden bir özelliktir. Fonksiyon tipleri, bir fonksiyonu veya metodu bir değişkene veya sabite atayabilmenizi, başka bir fonksiyonun parametre olarak alabilmenizi veya bir fonksiyonun sonucu olarak döndürebilmenizi sağlar. 4 | 5 | Bir fonksiyon tipini tanımlamak için, fonksiyonun giriş parametrelerinin tipleri ve dönüş değerinin tipi kullanılır. 6 | 7 | ```swift 8 | func addNumbers(_ a: Int, _ b: Int) -> Int { 9 | return a + b 10 | } 11 | 12 | var mathOperation: (Int, Int) -> Int = addNumbers 13 | ``` 14 | 15 | ## Kullanım Alanları 16 | 17 | Bir fonksiyonu başka bir fonksiyona parametre olarak gönderirken: 18 | 19 | ```swift 20 | func calculate(_ operation: (Int, Int) -> Int, _ a: Int, _ b: Int) -> Int { 21 | return operation(a, b) 22 | } 23 | 24 | func multiply(_ a: Int, _ b: Int) -> Int { 25 | return a * b 26 | } 27 | 28 | let result = calculate(multiply, 5, 3) 29 | print(result) // Çıktı: 15 30 | ``` 31 | 32 | 33 | Fonksiyon tiplerini bir fonksiyon içinde geri dönüş değeri olarak kullanabiliriz: 34 | 35 | ```swift 36 | func calculator(_ operation: String) -> (Double, Double) -> Double { 37 | switch operation { 38 | case "+": 39 | return { a, b in a + b } 40 | case "-": 41 | return { a, b in a - b } 42 | case "*": 43 | return { a, b in a * b } 44 | case "/": 45 | return { a, b in a / b } 46 | default: 47 | fatalError("Invalid operation") 48 | } 49 | } 50 | 51 | let addition = calculator("+") 52 | let result = addition(3.5, 2.5) 53 | print(result) // Çıktı: 6.0 54 | 55 | let multiplication = calculator("*") 56 | let result2 = multiplication(4.0, 2.0) 57 | print(result2) // Çıktı: 8.0 58 | ``` -------------------------------------------------------------------------------- /G-Properties/2-Property Observers.md: -------------------------------------------------------------------------------- 1 | ## Property Observers 2 | 3 | Property Observers" (Özellik Gözlemcileri), bir saklanan özelliğin değeri değiştiğinde otomatik olarak gerçekleştirilecek eylemleri tanımlamamıza olanak sağlar. Property Observers, bir özelliğin değerindeki değişiklikleri izlememize ve bu değişiklikler üzerinde özel kod blokları çalıştırmamıza olanak tanır. 4 | 5 | Swift'te iki tür Property Observer bulunur: "willSet" ve "didSet". 6 | 7 | ## willSet 8 | 9 | "willSet" Property Observer, bir saklanan özelliğin değeri ayarlanmadan önce çalışır. Bu observer, yeni değeri ve değişkenin varsayılan ismi olan "newValue" aracılığıyla erişebilir. "willSet" bloğu, yeni değerin atanmadan önce kontrol edilmesi, işlenmesi veya geçerliliğinin doğrulanması gibi eylemleri gerçekleştirmek için kullanılabilir. Hiçbir parametre eklenmezse default olarak "newValue" kullanılır. 10 | 11 | ```swift 12 | class User { 13 | var name: String { 14 | willSet { 15 | print("New name: \(newValue)") 16 | } 17 | } 18 | 19 | init(name: String) { 20 | self.name = name 21 | } 22 | } 23 | 24 | let user = User(name: "John") 25 | user.name = "Jane" 26 | // Çıktı: New name: Jane 27 | ``` 28 | 29 | ## didSet 30 | 31 | "didSet" Property Observer, bir saklanan özelliğin değeri ayarlandıktan sonra çalışır. Bu observer, önceki değere "oldValue" aracılığıyla erişebilir. "didSet" bloğu, önceki değere dayalı olarak değişiklik sonrası işlemleri gerçekleştirmek için kullanılabilir. Hiçbir parametre eklenmezse default olarak "oldValue" kullanılır. 32 | 33 | ```swift 34 | class Counter { 35 | var count: Int = 0 { 36 | didSet { 37 | print("Count changed from \(oldValue) to \(count)") 38 | } 39 | } 40 | 41 | func increment() { 42 | count += 1 43 | } 44 | } 45 | 46 | let counter = Counter() 47 | counter.increment() 48 | // Çıktı: Count changed from 0 to 1 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /G-Properties/4-Type Properties.md: -------------------------------------------------------------------------------- 1 | ## Type Properties 2 | 3 | Swift'te "Type Properties" olarak adlandırılan özellikler, bir türün kendisine ait olan ve tüm örnekler arasında paylaşılan özelliklerdir. Bu özellikler, bir türün tek bir kopyasını tutar ve örneklere özgü olmayan değerler veya davranışlar sağlar. 4 | 5 | Type Properties, bir türün kendisine ait olan ve tüm örnekler tarafından kullanılan sabit veya değişken özellikler olabilir. Bu özellikler, türün kendisine ait olduğu için doğrudan tür adı üzerinden erişilebilirler ve örneklere ait bir kopyaları olmadığından örneklere özgü değerler taşımazlar. static anahtar kelimesi ile tanımlanırlar. 6 | 7 | ```swift 8 | struct MyStruct { 9 | static var myTypeProperty: Int = 10 10 | 11 | static func myTypeMethod() { 12 | print("This is a type method.") 13 | } 14 | } 15 | 16 | print(MyStruct.myTypeProperty) // 10 17 | MyStruct.myTypeProperty = 20 18 | print(MyStruct.myTypeProperty) // 20 19 | 20 | MyStruct.myTypeMethod() // This is a type method 21 | ``` 22 | 23 | Burada tanımlama yaparken her zaman bir başlangıç değeri vermek zorundayız. Bunun nedeni, türün kendisinin, initialize zamanında depolanan tür özelliğine bir değer atayabilecek bir init'e sahip olmamasıdır. Saklanan tür özellikleri, ilk erişimlerinde lazy olarak başlatılır. Aynı anda birden fazla iş parçacığı tarafından erişildiğinde bile yalnızca bir kez başlatılmaları garanti edilir ve lazy modifier ile işaretlenmeleri gerekmez. 24 | 25 | Ayrıca class anahtar kelimesi ile tanımlanan sınıflar için de type property tanımlanabilir. Bu durumda, type property'lerin varsayılan değeri static anahtar kelimesi ile tanımlanan type property'lerden farklıdır. class anahtar kelimesi ile tanımlanan type property'lerin varsayılan değeri override edilebilir. 26 | 27 | ```swift 28 | class MyClass { 29 | class var myTypeProperty: Int { 30 | return 10 31 | } 32 | } 33 | 34 | print(MyClass.myTypeProperty) // 10 35 | ``` -------------------------------------------------------------------------------- /B-Collections/3-Dictionaries.md: -------------------------------------------------------------------------------- 1 | ## Dictionaries 2 | 3 | Swift'te Dictionaryler key-value çiftleri şeklinde tanımlanır. Dictionarylerin keyleri ve valueleri aynı türden olmak zorunda değildir. Dictionarylerin içerisindeki keyler unique olmak zorundadır. Dictionarylerin içerisindeki valueler unique olmak zorunda değildir. Dictionarylerde her zaman value'lar optional olarak tutulur. 4 | 5 | Boş bir dictionary oluşturma: 6 | 7 | ```swift 8 | var namesOfIntegers = [Int: String]() 9 | // namesOfIntegers is an empty [Int: String] dictionary 10 | ``` 11 | 12 | Yeni item eklerken doğrudan şöyle yazılabilir: 13 | 14 | ```swift 15 | airports["LHR"] = "London" 16 | ``` 17 | 18 | Değer eklemek veya güncellemek için updateValue kullanılabilir. Bu fonksiyon eğer verilen parametre mevcutsa günceller, yoksa ekler. 19 | 20 | ```swift 21 | if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB"){ 22 | print("The old value for DUB was \(oldValue).") 23 | } 24 | // Prints "The old value for DUB was Dublin." 25 | ``` 26 | 27 | Eleman silmek için benzer şekilde: 28 | 29 | ```swift 30 | if let removedValue = airports.removeValue(forKey: "DUB") { 31 | print("The removed airport's name is \(removedValue).") 32 | } else { 33 | print("The airports dictionary doesn't contain a value for DUB.") 34 | } 35 | ``` 36 | 37 | ya da 38 | 39 | ```swift 40 | airports["APL"] = nil 41 | ``` 42 | 43 | ## İterasyon 44 | 45 | Key-Value ayrı ayrı alınabilir: 46 | 47 | ```swift 48 | for airportCode in airports.keys { 49 | print("Airport code: \(airportCode)") 50 | } 51 | // Airport code: LHR 52 | // Airport code: YYZ 53 | 54 | 55 | for airportName in airports.values { 56 | print("Airport name: \(airportName)") 57 | } 58 | // Airport name: London Heathrow 59 | // Airport name: Toronto Pearson 60 | ``` 61 | 62 | For/in iterasyonu: 63 | 64 | ```swift 65 | for (airportCode, airportName) in airports { 66 | print("\(airportCode): \(airportName)") 67 | } 68 | // LHR: London Heathrow 69 | // YYZ: Toronto Pearson 70 | ``` 71 | -------------------------------------------------------------------------------- /R-Extensions/1-Extensions.md: -------------------------------------------------------------------------------- 1 | ## Extensions 2 | 3 | Extension'lar class'lara, struct'lara, enum'lara veya protocol'lere yeni işlevsellik kazandırmak için kullanılan bir yapıdır. Extension'ların kaynak kodların erişilmediği durumda da yapının genişletilmesine izin verir. 4 | 5 | Extension'lar şunları yapabilir: 6 | 7 | - Yeni hesaplanmış property'ler ve hesaplanmış property'lerin getter ve setter'ları tanımlayabilir. 8 | - Yeni instance method'lar ve type method'lar tanımlayabilir. 9 | - Yeni initializer'lar tanımlayabilir. 10 | - Subscript'ler tanımlayabilir. 11 | - Yeni nested type'lar tanımlayabilir. 12 | - Var olan bir türün protokol uygulamasını genişletebilir. 13 | 14 | Extension'lar yeni fonksiyonellikler eklerken var olan fonksiyonları override edemez. 15 | 16 | Temel syntax: 17 | 18 | ```swift 19 | extension SomeType { 20 | // new functionality to add to SomeType goes here 21 | } 22 | ``` 23 | 24 | Extension'lar birden fazla protocol'ü uygulayabilir. Bu durumda, protocol'ler arasında virgülle ayrılmış bir liste kullanılır: 25 | 26 | ```swift 27 | extension SomeType: SomeProtocol, AnotherProtocol { 28 | // protocol implementations go here 29 | } 30 | ``` 31 | 32 | ## Extensions - Initializers 33 | 34 | Extension'lar ile yeni initializer'lar tanımlanabilir. Bu initializer'lar, extension'ın tanımlandığı türün tüm instance'ları için kullanılabilir. Extension içerisinde tanımlanan initializer'lar orijinal türün initializer'ı üzerinde bir değişiklik yapamaz. Bunun yerine, extension'ın initializer'ı, orijinal türün initializer'ını çağırır. 35 | 36 | Temel syntax: 37 | 38 | ```swift 39 | extension SomeType { 40 | init(parameters) { 41 | // initializer implementation goes here 42 | } 43 | } 44 | ``` 45 | 46 | ## Extensions - Methods 47 | 48 | Extension'lar ile yeni instance method'lar ve type method'lar tanımlanabilir. Örneğin: 49 | 50 | ```swift 51 | extension Int { 52 | func repetitions(task: () -> Void) { 53 | for _ in 0.. Int { 8 | // Burada, index parametresiyle gelen indeksin değerini döndüren bir get bloğu bulunur 9 | get { 10 | // İndeksi kullanarak, istenen değeri döndürme 11 | // Örnek olarak, bir diziyi temsil ediyor olabilir 12 | // Bu durumda, diziye erişmek için index parametresini kullanarak ilgili elemanı döndürebilirsiniz. 13 | } 14 | 15 | // Bir set bloğu da tanımlayabilirsiniz 16 | set(newValue) { 17 | // İndeksi kullanarak, ilgili değeri yeni değerle değiştirme 18 | // Örnek olarak, bir diziyi temsil ediyor olabilir ve yeni değeri, index parametresi ile belirtilen indeksteki elemana atayabilirsiniz. 19 | } 20 | } 21 | } 22 | ``` 23 | 24 | Instance method'larının aksine subscript'ler okunabilir ve yazılabilir olabilirler. Bu yüzden, get ve set bloklarını tanımlamak zorunda değilsiniz. Sadece get bloğu tanımlayarak, subscript'in sadece okunabilir olmasını sağlayabilirsiniz. Aynı şekilde, sadece set bloğu tanımlayarak, subscript'in sadece yazılabilir olmasını sağlayabilirsiniz. 25 | 26 | Daha önce willSet'te gördüğümüz gibi burada da parametre ismi belirtilmezse default olarak newValue kullanılır. 27 | 28 | Ayrıca getter veya setter yazılmazsa bir subscript default olarak getter olur. 29 | Yani sadece read-only bir subscript yazmak istiyorsanız getter yazmanıza gerek yoktur. 30 | 31 | ```swift 32 | subscript(index: Int) -> Int { 33 | // Return an appropriate subscript value here. 34 | } 35 | ``` 36 | 37 | ## Type Subscripts 38 | 39 | Type Subscript'ler, bir type'ın instance'larına değil, type'ın kendisine ait olan subscript'lerdir. Type Subscript'ler, static keyword'ü ile tanımlanırlar. 40 | 41 | ```swift 42 | enum Planet: Int { 43 | case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune 44 | static subscript(n: Int) -> Planet { 45 | return Planet(rawValue: n)! 46 | } 47 | } 48 | let mars = Planet[4] 49 | print(mars) 50 | ``` 51 | 52 | 53 | -------------------------------------------------------------------------------- /A-Temeller/4-Ekstralar/1- Value ve Reference Types Kavramı.md: -------------------------------------------------------------------------------- 1 | ## Value Types 2 | 3 | - Değer tipli veriler, değerleri doğrudan depolarlar ve bellekte ayrı alanlarda saklanırlar. 4 | - Bir değer tipi değişkeni bir başka değişkene veya sabite atanırken, değerler kopyalanır. Yani, orijinal değişkenin değeri bağımsız olarak kopyalanır ve iki değişkenin bellekte ayrı kopyaları bulunur. 5 | - Değer tipli veriler, sabitlendikten sonra değiştirilemez. Bir değer tipi değişkeni kopyalayarak elde edilen yeni değişken, orijinal veriden bağımsız olarak hareket eder. 6 | - Swift dilindeki temel değer tipleri arasında sayılar (Int, Float, Double), karakterler (Character), bool (Bool) ve yapılar (struct) yer alır. 7 | 8 | Örnek: 9 | 10 | ```swift 11 | var a = 5 12 | var b = a // b, a'nın değerini kopyalar 13 | 14 | b = 10 // b'yi değiştirir, a etkilenmez 15 | print(a) // Çıktı: 5 16 | print(b) // Çıktı: 10 17 | ``` 18 | 19 | ## Reference Types 20 | 21 | - Referans tipli veriler, bellekte bir referans (adres) tutarlar ve verinin değeri bu referans aracılığıyla erişilir. 22 | - Bir referans tipli veri atandığında, asıl veri bellekte paylaşılır ve kopyalanmaz. Yani, iki referans aynı veriyi işaret eder ve verinin değişiklikleri tüm referanslara yansır. 23 | - Referans tipli veriler, değerleri değiştirilebilir. Bir referansın üzerinde yapılan değişiklikler, tüm referansları etkiler. 24 | - Swift dilindeki temel referans tipleri arasında sınıflar (class), fonksiyonlar (function) ve kimi özel durumlar (örneğin, array ve touple) yer alır. 25 | 26 | Örnek: 27 | ```swift 28 | class Person { 29 | var name: String 30 | 31 | init(name: String) { 32 | self.name = name 33 | } 34 | } 35 | 36 | var person1 = Person(name: "Ahmet") 37 | var person2 = person1 // person2, person1'in referansını kopyalar 38 | 39 | person2.name = "Mehmet" // person2'yi değiştirir, person1 etkilenir 40 | print(person1.name) // Çıktı: "Mehmet" 41 | print(person2.name) // Çıktı: "Mehmet" 42 | ``` 43 | 44 | Değer tipli ve referans tipli veriler arasındaki farklar, verilerin bellekte nasıl temsil edildiği, atama işlemlerinin nasıl gerçekleştiği ve değişikliklerin nasıl yayıldığı gibi konuları içerir. Bu farklılıklar, programlamada bellek kullanımı, performans ve veri yönetimi açısından önemlidir. -------------------------------------------------------------------------------- /N-Concurrency/4-Actors.md: -------------------------------------------------------------------------------- 1 | ## Actors 2 | 3 | Actors, eşzamanlılık ve paralellik sorunlarını ele almak için kullanılan bir modeldir. Actors, paylaşılan durumun güvenli bir şekilde kullanılmasını sağlar ve aynı anda yalnızca bir iş parçacığı tarafından erişilebilirler. 4 | 5 | Actors, belirli bir kapsamda tanımlanan ve birincil iş parçacığı dışında hiçbir iş parçacığı tarafından doğrudan erişilemeyen özel nesnelerdir. Actors, diğer iş parçacıklarıyla iletişim kurmak için mesajlaşma yoluyla etkileşimde bulunurlar. Yani, bir aktöre mesaj gönderildiğinde, aktör bu mesajı alır, işler ve gerekirse yanıt döndürür. 6 | 7 | ```swift 8 | actor Counter { 9 | private var count = 0 10 | 11 | func increment() { 12 | count += 1 13 | } 14 | 15 | func getCount() -> Int { 16 | return count 17 | } 18 | } 19 | ``` 20 | 21 | Bu örnekte, Counter adında bir aktör tanımlanmıştır. count adında özel bir değişken ve increment ve getCount adında iki metot bulunmaktadır. count değişkeni, aktör içinde paylaşılan durumu temsil eder ve yalnızca aktörün kendi iş parçacığı tarafından güncellenebilir. 22 | 23 | Actors, bir actore ait metotlara erişmek için await ifadesiyle mesaj gönderme yöntemini kullanırız. 24 | 25 | ```swift 26 | Task { 27 | let counter = Counter() 28 | await counter.increment() 29 | let count = await counter.getCount() 30 | print(count) // Output: 1 31 | } 32 | ``` 33 | 34 | Actors, paylaşılan durumu güvenli bir şekilde yönetmeyi sağlar ve eşzamanlı çalışma ortamında hatalara ve yarış koşullarına karşı koruma sağlar. Aynı anda yalnızca bir iş parçacığı tarafından erişilebilen actors, paralel işleme ihtiyacı duyan uygulamalar için önemli bir araçtır. 35 | 36 | Actors referans tiplidir. Dolayısıyla class gibi kullanılabilirler: 37 | 38 | ```swift 39 | actor TemperatureLogger { 40 | let label: String 41 | var measurements: [Int] 42 | private(set) var max: Int 43 | 44 | 45 | init(label: String, measurement: Int) { 46 | self.label = label 47 | self.measurements = [measurement] 48 | self.max = measurement 49 | } 50 | } 51 | ``` 52 | 53 | class'lardan farklı olarak aynı anda yalnızca bir iş parçacığı tarafından erişilebilirler. Dolayısıyla, actors'lerin paylaşılan durumu güvenli bir şekilde yönetmesi sağlanır. -------------------------------------------------------------------------------- /F-Struct & Class/5-Ne Zaman Struct - Ne Zaman Class.md: -------------------------------------------------------------------------------- 1 | ## Ne Zaman Struct - Ne Zaman Class 2 | 3 | Swift programlama dilinde, class ve struct yapıları benzer işlevlere sahip olsalar da bazı farklılıklara sahiptir. Genel olarak, aşağıdaki durumlarda class veya struct kullanımını tercih edebilirsiniz: 4 | 5 | Referans Semantiği: Eğer nesnenin referans semantiği taşıması gerekiyorsa, yani bir örneğin farklı yerlerde kullanılan aynı verilere ihtiyaç duyuluyorsa, class kullanılması uygun olabilir. Örneğin, bir kullanıcı nesnesini temsil etmek için bir sınıf kullanabiliriz: 6 | 7 | ```swift 8 | class User { 9 | var name: String 10 | var age: Int 11 | 12 | init(name: String, age: Int) { 13 | self.name = name 14 | self.age = age 15 | } 16 | 17 | } 18 | ``` 19 | 20 | alıtım: Eğer kalıtım yapısı kullanmanız gerekiyorsa, class kullanılması gerekebilir. Sınıflar, başka bir sınıftan özellikleri ve davranışları devralabilir. Örneğin: 21 | 22 | ```swift 23 | class Vehicle { 24 | var brand: String 25 | 26 | init(brand: String) { 27 | self.brand = brand 28 | } 29 | 30 | func startEngine() { 31 | print("Engine started.") 32 | } 33 | } 34 | 35 | class Car: Vehicle { 36 | var numberOfWheels: Int 37 | 38 | init(brand: String, numberOfWheels: Int) { 39 | self.numberOfWheels = numberOfWheels 40 | super.init(brand: brand) 41 | } 42 | 43 | override func startEngine() { 44 | print("Car engine started.") 45 | } 46 | } 47 | ``` 48 | 49 | Değer Semantiği: Eğer nesnenin değer semantiği taşıması yeterliyse, yani bir örneğin kopyalanması yerine yeni bir örnek oluşturulmasını tercih ediyorsanız, struct kullanabilirsiniz. Örneğin, bir dikdörtgenin boyutunu temsil etmek için bir yapı kullanabiliriz: 50 | 51 | ```swift 52 | struct Rectangle { 53 | var width: Double 54 | var height: Double 55 | 56 | func calculateArea() -> Double { 57 | return width * height 58 | } 59 | } 60 | ``` 61 | 62 | Değişmezlik (Immutability): Eğer bir nesnenin değişmez olması gerekiyorsa, yani içindeki verilerin değişmemesi gerekiyorsa, struct kullanabiliriz. Bu, değeri değiştirememe garantisi sağlayarak yan etkileri azaltabilir. Örneğin: 63 | 64 | ```swift 65 | struct Point { 66 | let x: Int 67 | let y: Int 68 | } 69 | ``` 70 | 71 | 72 | -------------------------------------------------------------------------------- /K-Initialization/2-Initializer Delegation.md: -------------------------------------------------------------------------------- 1 | ## Initilazer Delegation 2 | 3 | Initializer delegation, bir class'ın veya struct'ın başka bir initializer'ı kullanarak kendi başlatıcılarını çağırma işlemidir. Bu konsept, tekrarlayan kodu önlemek ve kodun daha temiz ve sürdürülebilir olmasını sağlamak için kullanılır. 4 | 5 | Örneğin: 6 | 7 | ```swift 8 | class Person { 9 | let name: String 10 | let age: Int 11 | 12 | init(name: String, age: Int) { 13 | self.name = name 14 | self.age = age 15 | } 16 | 17 | convenience init(name: String) { 18 | self.init(name: name, age: 0) 19 | } 20 | } 21 | ``` 22 | 23 | Yukarıdaki örnekte, "Person" adında bir sınıf tanımlanmıştır. Sınıfın iki farklı başlatıcısı bulunmaktadır. İlk başlatıcı, "name" ve "age" adında iki parametre alır ve bu parametrelerle sınıfın özelliklerini başlatır. İkinci başlatıcı ise sadece "name" parametresini alır ve "age" parametresini varsayılan değeri olan 0 ile başlatmak için ilk başlatıcıyı çağırır. Bu durumda, ikinci başlatıcıda "convenience" anahtar kelimesi kullanılmıştır. 24 | 25 | "convenience" anahtar kelimesi, bir başlatıcının diğer bir başlatıcıyı çağırması durumunda kullanılır. İlgili başlatıcıya "convenience" anahtar kelimesi eklemek, başlatıcının kendi sınıfının tüm özelliklerini başlatmasına gerek olmadığını belirtir. Bunun yerine, başka bir başlatıcıyı çağırabilir ve sadece belirli parametreleri ayarlayabilir. 26 | 27 | ## Value Type'ta Initilazer Delegation 28 | 29 | Struct value type olduğu için initializer delegation farklı bir şekilde çalışır. Value type olan yapılar, başka bir başlatıcıyı doğrudan çağıramazlar. Bunun yerine, kendi içlerinde başka bir başlatıcıyı çağırmak yerine, varsayılan değerlerle başlatılmış bir örneğe değer atayarak veya mevcut bir örneğin değerlerini kopyalayarak başlatılırlar. 30 | 31 | ```swift 32 | struct Person { 33 | let name: String 34 | let age: Int 35 | 36 | init(name: String, age: Int) { 37 | self.name = name 38 | self.age = age 39 | } 40 | 41 | init(name: String) { 42 | self.init(name: name, age: 0) 43 | } 44 | } 45 | ``` 46 | Bu şekilde, value type olan yapılar için initializer delegation, kendisini varsayılan değerlerle başlatılmış bir örneğe atayarak veya mevcut bir örneğin değerlerini kopyalayarak gerçekleştirilir. 47 | -------------------------------------------------------------------------------- /F-Struct & Class/3-Encapsulation.md: -------------------------------------------------------------------------------- 1 | ## Encapsulation 2 | 3 | Encapsulation, bir class'ın veya yapıyı oluşturan verilerin ve işlevlerin nasıl gizlendiğini ve erişilebilir olduğunu kontrol etme yeteneğidir. Encapsulation, nesne yönelimli programlamanın temel prensiplerinden biridir ve kodun daha organize, anlaşılır ve bakımı kolay hale getirilmesini sağlar. Encapsulation şunları sağlar: 4 | 5 | - Veri Gizliliği: Encapsulation, bir class'ın veya yapının içindeki verilerin gizlenmesini sağlar. Sadece class'ın kendisi bu verilere doğrudan erişebilir ve dışarıdan erişim engellenir. Bu, verilerin yanlışlıkla değiştirilmesini veya doğrudan erişimle hatalı manipülasyonlara neden olmasını önler. 6 | 7 | - Arayüz Standardizasyonu: Class'ların veya yapıların nasıl kullanılacağına dair bir arayüz sağlamak encapsulation'ın bir parçasıdır. Class'ın veya yapının iç detaylarına odaklanmaktan ziyade, dışarıdaki kullanıcılar için erişilebilir işlevler ve özellikler sunulur. Bu, kullanıcıların class'ın iç yapısını bilmelerine gerek kalmadan, class'ın sunduğu özellikleri ve işlevleri kullanmalarını sağlar. 8 | 9 | - Kodun Modüleritesi: Encapsulation, kodun modüler ve yeniden kullanılabilir olmasını sağlar. Bir class'ın veya yapının iç yapısında yapılan değişiklikler, dışarıya etki etmeden class'ın dış arayüzünü korur. Bu, kodun daha kolay bakımını sağlar ve bir bileşenin iç yapısında yapılan değişikliklerin diğer kod bölümlerini etkilemeden yapılabilmesini sağlar. 10 | 11 | - Güvenlik: Encapsulation, class'ın veya yapının dışarıdaki kodlardan korunmasını sağlar. Class'ın iç detaylarının gizli kalması, kodun daha güvenli olmasını sağlar. Dışarıdaki kodlar sadece class'ın sunduğu arayüzü kullanarak etkileşimde bulunabilir ve iç detaylara erişemez. 12 | 13 | - Kodun Anlaşılabilirliği: Encapsulation, kodun daha anlaşılabilir olmasını sağlar. Bir class veya yapı, sadece ilgili işlevlerin ve özelliklerin bir arada olduğu birim olarak düşünülür. Bu, kodun daha okunaklı, anlaşılır ve bakımı kolay hale gelmesini sağlar. 14 | 15 | 16 | Encapsulation temelde getter ve setter'lar ile yapılır: 17 | 18 | ```swift 19 | var myVar: String { 20 | get { 21 | return "Hello" // Burada değişkenin kendisini sonsuz döngü oluşmaması için kullanmamalıyız. 22 | } 23 | set (newValue) { 24 | print(newValue) 25 | } 26 | } 27 | ``` 28 | 29 | Eğer yalnızca get yazılırsa değişkene hiçbir şekilde atama yapamayız. Benzer şekilde setlersek okuyamayız. 30 | -------------------------------------------------------------------------------- /P-Types/2-Nested Types.md: -------------------------------------------------------------------------------- 1 | ## Nested Types 2 | 3 | Nested Types, bir türün içinde başka bir türün tanımlanmasını ifade eder. Bir türün içinde başka bir yapı olan türleri tanımlamak, kod organizasyonunu geliştirir ve ilgili türleri daha düzenli bir şekilde gruplandırır. 4 | 5 | İç içe geçmiş tipler sınıflar, struct'lar ve enum'lar için kullanılabilir. İç içe geçmiş tipler, dışarıdaki türe bağlıdır ve onun içinde kullanılır. Bu şekilde, dış türün içindeki özellikler veya işlevler iç içe geçmiş türe erişebilir ve onları kullanabilir. 6 | 7 | Örnekler: 8 | 9 | ```swift 10 | class OuterClass { 11 | // Dışarıdaki sınıfın özellikleri ve işlevleri 12 | 13 | class InnerClass { 14 | // İç içe geçmiş sınıfın özellikleri ve işlevleri 15 | } 16 | } 17 | ``` 18 | ```swift 19 | struct OuterStruct { 20 | // Dışarıdaki yapıya ait özellikler 21 | 22 | struct InnerStruct { 23 | // İç içe geçmiş yapının özellikleri 24 | } 25 | } 26 | ``` 27 | ```swift 28 | enum OuterEnum { 29 | // Dışarıdaki numaralandırmanın durumları 30 | 31 | enum InnerEnum { 32 | // İç içe geçmiş numaralandırmanın durumları 33 | } 34 | } 35 | ``` 36 | 37 | Kapsamlı örnek: 38 | 39 | ```swift 40 | struct BlackjackCard { 41 | 42 | 43 | // nested Suit enumeration 44 | enum Suit: Character { 45 | case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣" 46 | } 47 | 48 | 49 | // nested Rank enumeration 50 | enum Rank: Int { 51 | case two = 2, three, four, five, six, seven, eight, nine, ten 52 | case jack, queen, king, ace 53 | struct Values { 54 | let first: Int, second: Int? 55 | } 56 | var values: Values { 57 | switch self { 58 | case .ace: 59 | return Values(first: 1, second: 11) 60 | case .jack, .queen, .king: 61 | return Values(first: 10, second: nil) 62 | default: 63 | return Values(first: self.rawValue, second: nil) 64 | } 65 | } 66 | } 67 | 68 | 69 | // BlackjackCard properties and methods 70 | let rank: Rank, suit: Suit 71 | var description: String { 72 | var output = "suit is \(suit.rawValue)," 73 | output += " value is \(rank.values.first)" 74 | if let second = rank.values.second { 75 | output += " or \(second)" 76 | } 77 | return output 78 | } 79 | } 80 | ``` 81 | 82 | ```swift -------------------------------------------------------------------------------- /A-Temeller/1-Değişkenler/5-Optionals.md: -------------------------------------------------------------------------------- 1 | ## Optionals 2 | 3 | Nullable ifadesi olarakta değerlendirilen bu ifade özetle bir değişken için bellekte bulunabilirde bulunmayabilirde demenin yoludur. 4 | 5 | Örneğin "abc" stringini bir int'e çevirmeye çalıştığımızda program doğal olarak çöker. Bu çökmeyi önlemenin yolu optionals'dan geçer. 6 | 7 | Örneğin 8 | 9 | ```swift 10 | var age : Int 11 | ``` 12 | 13 | Tanımlamasını yaptığımızı düşünelim. Burada age'i print etmek istesek initilaze olmadığı için hata alacağız ancak değişkeni optional yaparsak 14 | 15 | ```swift 16 | var age : Int? 17 | ``` 18 | 19 | Ve bu halde print etmek istersek nil sonucunu görürüz. Bu kullanımda herhangi bir değer ataması yapmazsak değişkene otomatik olarak nil atanır. 20 | 21 | Optional bir değeri derleyiciye nil gelmeyeceğini garanti etmek için ! kullanılır. 22 | 23 | ```swift 24 | print(age!) 25 | ``` 26 | 27 | Ancak bu durum risklidir. Eğer age'e bir değer ataması yapılmazsa kod çöker. 28 | 29 | ## ! ve ? işaretleri için ayrıntı: 30 | 31 | Swift programlama dilinde, ? ve ! operatörleri, değişkenlerin veya nesnelerin opsiyonel (optional) türleriyle çalışırken kullanılır. Bu operatörler, Swift'in opsiyonel değerleri işleme biçimini belirler. 32 | 33 | ? Operatörü (Opsiyonel Zincirleme Operatörü): 34 | 35 | - Bir değişkenin veya nesnenin opsiyonel bir değere sahip olup olmadığını kontrol etmek için kullanılır. 36 | - Eğer opsiyonel değer nil ise, ? operatörü sonucu nil olarak döndürür. 37 | - Eğer opsiyonel değer nil değilse, ? operatörü sonraki işleme geçer. 38 | - ? operatörü, bir zincirleme yapısı içinde birden fazla kullanılabilir. 39 | - Örneğin: myOptionalVariable?.property 40 | 41 | ! Operatörü (Zorunlu Çözme Operatörü): 42 | 43 | - Bir değişkenin veya nesnenin opsiyonel değerini zorunlu olarak çözmek (unwrap) için kullanılır. 44 | - Eğer opsiyonel değer nil ise, ! operatörü hata verir (runtime hatası) ve program çalışmayı durdurur. Eğer opsiyonel değer nil değilse, ! operatörü opsiyonel değeri zorunlu değere dönüştürür. 45 | - ! operatörü, opsiyonel değerin kesinlikle nil olmadığı durumlar için kullanılmalıdır. 46 | 47 | Örneğin: myOptionalVariable! 48 | 49 | ? ve ! operatörleri, opsiyonel değerleri güvenli bir şekilde kontrol etmek ve kullanmak için kullanılır. Özellikle, bir değişkenin nil olma durumunu kontrol etmek istediğinizde ? operatörünü, değişkenin kesinlikle nil olmadığını bildiğiniz durumlarda ise ! operatörünü kullanabilirsiniz. Ancak ! operatörünü dikkatli bir şekilde kullanmalı ve opsiyonel değerlerin nil olma durumunu önceden kontrol etmek için ? operatörünü kullanmanız önerilir. Bu, programınızda beklenmedik hataları önlemeye yardımcı olur. -------------------------------------------------------------------------------- /A-Temeller/2-Operatörler/1-Operatörlere Giriş.md: -------------------------------------------------------------------------------- 1 | ## Operatörlere Giriş 2 | 3 | Operatörler üç grupta incelenir: 4 | 5 | - Unary 6 | - Binary 7 | - Ternary 8 | 9 | ## Unary 10 | 11 | Unary operatör, yalnızca bir operand üzerinde işlem yapar. Bu tür operatörler, operandın önünde veya arkasında yer alabilir. 12 | 13 | Örneğin: 14 | 15 | - Bir sayının işaretini değiştiren - operatörü: -5 16 | - Bir bool değerini tersine çeviren ! operatörü: !true 17 | 18 | ## Binary 19 | 20 | Binary operatör, iki operand üzerinde işlem yapar. Bu operatörlerin her biri, iki operandı arasında yer alır. 21 | 22 | Örneğin: 23 | 24 | - İki sayıyı toplayan + operatörü: 2 + 3 25 | - İki sayıyı çarpan * operatörü: 4 * 5 26 | - İki stringi birleştiren + operatörü: "Hello, " + "World" 27 | 28 | ## Ternary 29 | 30 | Ternary operatör, üç operand üzerinde işlem yapar ve bir koşula dayanarak sonuç üretir. 31 | 32 | ```swift 33 | let sayı = 10 34 | let sonuç = sayı > 5 ? "Büyük" : "Küçük" 35 | ``` 36 | 37 | 38 | ## Atama Operatörü (=) 39 | 40 | Birden fazla değer aynı anda atanabilir. 41 | 42 | Örneğin: 43 | 44 | ```swift 45 | let (x, y) = (1, 2) 46 | ``` 47 | 48 | ## ?? Opearatörü (Nil-Coalescing) 49 | 50 | Nil-Coalescing operatörü, nil olmayan bir değer döndürür. Eğer değer nil ise, varsayılan değeri döndürür. 51 | 52 | ```swift 53 | let defaultColorName = "red" 54 | var userDefinedColorName: String? // default değeri nil 55 | var colorNameToUse = userDefinedColorName ?? defaultColorName 56 | ``` 57 | 58 | ## Range Operatörü: Closed Range (a...b) 59 | 60 | Closed Range operatörü, a'dan b'ye kadar olan tüm değerleri içerir. 61 | 62 | ```swift 63 | for index in 1...5 { 64 | print("\(index) times 5 is \(index * 5)") 65 | } 66 | ``` 67 | 68 | ## Range Operatörü: Half-Open Range (a..= 18 else { 17 | print("Yaş geçersiz veya yaş sınırı tutmuyor.") 18 | return 19 | } 20 | 21 | // Koşullar sağlandı, devam eden kodlar... 22 | print("Kullanıcı adı: \(username), yaş: \(age)") 23 | } 24 | 25 | processUser(username: "john", age: 25) 26 | ``` 27 | 28 | ## If'ten Farkı 29 | 30 | Guard ifadesi ve if ifadesi, Swift'te kontrol akışı için kullanılan iki farklı ifadedir. İkisi de koşulları değerlendirir ve koşulun sağlanıp sağlanmadığını kontrol eder, ancak çalışma şekilleri ve amaçları açısından farklılık gösterirler. 31 | 32 | İşte guard ifadesi ve if ifadesi arasındaki farklar: 33 | 34 | - Erken Çıkış: Guard ifadesi, koşulun sağlanmadığı durumlarda erken çıkış yapar. Else bloğunda yer alan kod çalışır ve fonksiyondan, döngüden veya kod bloğundan çıkılır. Bu, kodun okunabilirliğini artırır ve beklenmeyen durumları erken tespit etmeye yardımcı olur. If ifadesi ise, koşulun sağlanmadığı durumda else bloğu çalışır, ancak else bloğundan sonra kodun devam etmesine izin verir. 35 | 36 | - Değeri Unwrap Etme: Guard ifadesi, bir opsiyonel değeri unwrap etmek veya çıkarım yapmak için sıklıkla kullanılır. Eğer unwrap işlemi başarısız olursa, else bloğundaki kod çalışır ve erken çıkış yapılır. If ifadesi ise, değeri unwrap etmek için kullanılan "?" veya "!" operatörlerini kullanır, ancak unwrap işlemi başarısız olduğunda hata alır ve else bloğuna geçmez. 37 | 38 | - Scoping: Guard ifadesi, geçerli bir kapsam (scope) içinde çalışır. Değişkenlerin veya sabitlerin değerlerini guard ifadesi içerisinde unwrap ettikten sonra, bu değerler kapsamın geri kalanında kullanılabilir. If ifadesi ise, değişkenlerin veya sabitlerin değerlerini sadece if bloğu içinde kullanır ve if bloğundan sonra bu değerlere erişim sağlanmaz. -------------------------------------------------------------------------------- /S-Protocols/2-Delegation.md: -------------------------------------------------------------------------------- 1 | ## Delegation 2 | 3 | Delegation tasarım deseni, nesneler arasındaki iletişimi kolaylaştıran ve yeniden kullanılabilirlik sağlayan bir yöntemdir. Delegation, bir nesnenin belirli görevlerini veya olaylarını başka bir nesneye devretmek için kullanılır. Bu desen, bir nesnenin başka bir nesne adına bazı görevleri yerine getirmesine izin verir. 4 | 5 | Swift'te Delegation, iki temel bileşen üzerinde çalışır: delegator (temsilci) ve delegate (temsil eden). Delegator, görevlerini veya olaylarını temsil eden nesnedir. Delegate ise, bu görevleri gerçekleştirecek nesnedir. Delegator, delegate'e sahip olur ve ona belirli görevleri yerine getirmesi için yetki verir. 6 | 7 | Delegation kullanmanın temel avantajlarından biri, nesneler arasındaki bağımlılığı azaltmasıdır. Delegator, görevlerini gerçekleştirmek için direkt olarak bir sınıfa bağlı olmak yerine, bu görevleri delegate'e devreder. Böylece, delegator ve delegate arasındaki ilişki gevşetilir ve daha esnek bir yapı oluşturulur. Bu da kodun bakımını ve yeniden kullanılabilirliğini artırır. 8 | 9 | ## Delegation Aşamaları 10 | 11 | Protocol oluşturma: İlk adım, delegate'in uygulaması gereken yöntemleri tanımlayan bir protocol oluşturmaktır. Bu protocol, delegator ve delegate arasında bir anlaşma sağlar ve hangi yöntemlerin uygulanması gerektiğini belirtir. 12 | 13 | ```swift 14 | protocol MyDelegate { 15 | func didSomething() 16 | func didReceiveData(data: Any) 17 | } 18 | ``` 19 | 20 | Delegate tanımlama: Delegator sınıfında, bir delegate özelliği tanımlanmalıdır. Bu özellik, delegate'e sahip olmak için kullanılır. Delegate, yukarıda oluşturulan protocolü uygulayan bir nesne olmalıdır. 21 | 22 | ```swift 23 | class MyDelegator { 24 | var delegate: MyDelegate? 25 | 26 | func performTask() { 27 | // Görevin gerçekleştirilmesi 28 | delegate?.didSomething() 29 | } 30 | 31 | func receiveData(data: Any) { 32 | // Veri alındığında delegate'e bildirme 33 | delegate?.didReceiveData(data: data) 34 | } 35 | } 36 | ``` 37 | 38 | Delegate'i atama: Delegate'i belirlemek için delegator sınıfının bir örneğini oluşturmanız ve delegate özelliğine bir değer atamanız gerekmektedir. Bu değer, yukarıda oluşturulan protocolü uygulayan bir nesne olmalıdır. 39 | 40 | ```swift 41 | class MyDelegateImplementation: MyDelegate { 42 | func didSomething() { 43 | // Görev tamamlandığında yapılacaklar 44 | } 45 | 46 | func didReceiveData(data: Any) { 47 | // Veri alındığında yapılacaklar 48 | } 49 | } 50 | 51 | let delegator = MyDelegator() 52 | let delegateImplementation = MyDelegateImplementation() 53 | 54 | delegator.delegate = delegateImplementation 55 | ``` 56 | -------------------------------------------------------------------------------- /C-Fonksiyonlar/2-Parametreler.md: -------------------------------------------------------------------------------- 1 | ## Parametre Label'ları 2 | 3 | Swift'te kod okunabilirliğini artırmak amacıyla argümanlara label olarak etiket eklenebilir: 4 | 5 | ```swift 6 | func greet(person: String, from hometown: String) -> String { 7 | return "Hello \(person)! Glad you could visit from \(hometown)." 8 | } 9 | print(greet(person: "Bill", from: "Cupertino")) 10 | // Prints "Hello Bill! Glad you could visit from Cupertino." 11 | ``` 12 | 13 | ## Parametreler için _ 14 | 15 | Fonksiyonu çağırırken parametre isimlerini yazmak istemiyorsak parametre isimlerinin önüne _ koyabiliriz: 16 | 17 | ```swift 18 | func someFunction(_ firstParameterName: Int, secondParameterName: Int) { 19 | // In the function body, firstParameterName and secondParameterName 20 | // refer to the argument values for the first and second parameters. 21 | } 22 | someFunction(1, secondParameterName: 2) 23 | ``` 24 | 25 | ## Değişken Parametreler 26 | 27 | Bir fonksiyonun parametrelerinin sayısı belli değilse değişken parametreler kullanılabilir. Bunun için parametre tipinin önüne `...` konur: 28 | 29 | ```swift 30 | func arithmeticMean(_ numbers: Double...) -> Double { 31 | var total: Double = 0 32 | for number in numbers { 33 | total += number 34 | } 35 | return total / Double(numbers.count) 36 | } 37 | arithmeticMean(1, 2, 3, 4, 5) 38 | // returns 3.0, which is the arithmetic mean of these five numbers 39 | arithmeticMean(3, 8.25, 18.75) 40 | // returns 10.0, which is the arithmetic mean of these three numbers 41 | ``` 42 | 43 | ## inout parametreler 44 | 45 | Bir fonksiyonun parametreleri varsayılan olarak sabit değerlerdir. Yani fonksiyon içinde bu parametrelerin değerleri değiştirilemez. Eğer bir fonksiyonun parametresinin değerini değiştirmek istiyorsak bu parametreyi `inout` olarak tanımlamalıyız. 46 | 47 | ```swift 48 | func swapTwoInts(_ a: inout Int, _ b: inout Int) { 49 | let temporaryA = a 50 | a = b 51 | b = temporaryA 52 | } 53 | ``` 54 | 55 | ```swift 56 | func doubleInPlace(number: inout Int) { 57 | number *= 2 58 | } 59 | 60 | var myNumber = 5 61 | doubleInPlace(number: &myNumber) 62 | print(myNumber) // Çıktı: 10 63 | ``` 64 | 65 | Bu örnekte, doubleInPlace(number:) adlı bir fonksiyon tanımlanmıştır. Bu fonksiyon, bir inout parametre olan number'ı alır ve değerini iki katına çıkarır. Fonksiyonu çağırmadan önce myNumber değişkenini & operatörü ile geçerek, referansını fonksiyona iletmeliyiz. Sonuç olarak, myNumber'ın değeri fonksiyon içinde değiştirilir ve print işlemiyle 10 çıktısı alınır. 66 | 67 | - inout parametreleri, değiştirilebilir (var) değişkenlere ve bellekte geçici bir alana ihtiyaç duyabilir. 68 | - inout parametreleri, fonksiyon çağrıldığında değiştirilmelidir. Bu nedenle, let ile tanımlanan sabitler inout parametre olarak kullanılamaz. 69 | - inout parametrelerinin varsayılan değeri olamaz. 70 | -------------------------------------------------------------------------------- /O-Macros/1-Macros.md: -------------------------------------------------------------------------------- 1 | ## Macros 2 | 3 | Swift'te doğrudan makroların kullanımı yoktur. Bunun yerine, derleme zamanında çalışan ifadeleri oluşturmak için derleme süresi önişlemcisi direktifleri kullanılır. Swift dilindeki önişlemci direktiflerinin kullanım amaçları şunlar olabilir: 4 | 5 | Derleme Koşulları: Önişlemci direktifleri, belirli derleme koşullarına göre kodun derlenmesini yönlendirmek için kullanılabilir. Örneğin, farklı platformlar (iOS, macOS) için platforma özgü kod bloklarını belirlemek veya derleme seçeneklerine bağlı olarak farklı kod parçalarını derlemek için kullanılabilir. 6 | 7 | Hata Ayıklama ve Test Amaçları: Önişlemci direktifleri, hata ayıklama veya test sırasında ek kod veya loglama işlevselliği eklemek için kullanılabilir. Örneğin, DEBUG koşulunda yalnızca hata ayıklama modunda çalışacak kod bloklarını belirlemek için kullanılabilir. 8 | 9 | Özelleştirilmiş Derleme Seçenekleri: Önişlemci direktifleri, belirli derleme seçeneklerine veya sembollere bağlı olarak farklı kod parçalarını derlemek için kullanılabilir. Örneğin, belirli bir sembolün tanımlı olup olmadığına veya belirli derleme seçeneklerine bağlı olarak farklı özelliklerin açılıp kapatılmasını sağlayabilirsiniz. 10 | 11 | ## Freestanding Macros 12 | 13 | Freestanding macrolar için # operatörü kullanılır: 14 | 15 | ```swift 16 | func myFunction() { 17 | print("Currently running \(#function)") 18 | #warning("Something's wrong") 19 | } 20 | ``` 21 | 22 | Burada #function, #warning gibi önişlemci direktifleri freestanding makrolardır. Bu önişlemci direktifleri, derleme zamanında çalışan ifadeleri oluşturmak için kullanılır. 23 | 24 | ## Attachted Macros 25 | 26 | Ekli macro'lar için @ operatörü kullanılır. 27 | 28 | Örneğin bu kodu: 29 | 30 | ```swift 31 | struct SundaeToppings: OptionSet { 32 | let rawValue: Int 33 | static let nuts = SundaeToppings(rawValue: 1 << 0) 34 | static let cherry = SundaeToppings(rawValue: 1 << 1) 35 | static let fudge = SundaeToppings(rawValue: 1 << 2) 36 | } 37 | ``` 38 | 39 | Bu şekilde yazabiliriz: 40 | 41 | ```swift 42 | @OptionSet 43 | struct SundaeToppings { 44 | private enum Options: Int { 45 | case nuts 46 | case cherry 47 | case fudge 48 | } 49 | } 50 | ``` 51 | 52 | Bu sayede okunabilirliği arttırabiliriz. Buradaki @OptionSet Swift'in standart kütüphanesindeki OptionSet protokolünü uygulayan bir struct oluşturur. Bu macro listedeki case'leri okur ve onlardan constant'lar oluşturur. 53 | 54 | ## Macro Yazıldığında Compiler'ın Davranışı 55 | 56 | Swift macro'ları şu şekilde genişletir: 57 | 58 | - Compiler kodu okur ve memory içerisinde bir macro temsilcisi oluşturur. 59 | - Compiler bellekteki temsilin bir kısmını makroya gönderir. Bu işlem makroyu genişletir. 60 | - Compiler makro çağırısını genişletilmiş haliyle değiştirir. 61 | - Genişletilmiş makro kullanılarak derleme devam eder. 62 | 63 | -------------------------------------------------------------------------------- /B-Collections/1-Array.md: -------------------------------------------------------------------------------- 1 | ## Listler - Arraylar 2 | 3 | Arrayler, birden fazla veriyi tek bir değişkende tutmamızı sağlayan veri tipleridir. Array oluşturmak için köşeli parantezler kullanılır. 4 | 5 | Array'leri let yerine var ile tanımlamak mantıklıdır. Çünkü append gibi fonksiyonlar ile array'e yeni elemanlar eklenebilir. 6 | 7 | 8 | ```swift 9 | var someInts = [Int]() 10 | print("someInts is of type [Int] with \(someInts.count) items.") 11 | // Prints "someInts is of type [Int] with 0 items." 12 | ``` 13 | 14 | Bu tanımlama initilaze edilmiş listedir. Initilaze edilmemiş liste için: 15 | 16 | ```swift 17 | var someInts = [Int] 18 | ``` 19 | Eğer başta değer verirsek listemiz initilaze edilmiş olur. 20 | 21 | ```swift 22 | var someInts = [1, 2, 3] 23 | ``` 24 | 25 | Ayrıca default değer ile Array oluşturabiliriz: 26 | 27 | ```swift 28 | var threeDoubles = Array(repeating: 0.0, count: 3) 29 | // threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0] 30 | ``` 31 | 32 | + operatorü ile aynı türden arrayleri birleştirebiliriz: 33 | 34 | ```swift 35 | var anotherThreeDoubles = Array(repeating: 2.5, count: 3) 36 | // anotherThreeDoubles is of type [Double], and equals [2.5, 2.5, 2.5] 37 | var sixDoubles = threeDoubles + anotherThreeDoubles 38 | // sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5] 39 | ``` 40 | ## Array Eleman Ekleme 41 | 42 | append fonksiyonu kullanılabilir ya da += operatörü ile eklenebilir. 43 | 44 | ```swift 45 | var shoppingList = ["Eggs", "Milk"] 46 | shoppingList.append("Flour") 47 | // shoppingList now contains 3 items, and someone is making pancakes 48 | shoppingList += ["Baking Powder"] 49 | // shoppingList now contains 4 items 50 | shoppingList += ["Chocolate Spread", "Cheese", "Butter"] 51 | // shoppingList now contains 7 items 52 | ``` 53 | 54 | Belirli bir index'e eklemek için insert fonksiyonu kullanılır. 55 | 56 | ```swift 57 | shoppingList.insert("Maple Syrup", at: 0) 58 | // shoppingList now contains 7 items 59 | // "Maple Syrup" is now the first item in the list 60 | ``` 61 | 62 | ## Array Eleman Çıkarma 63 | 64 | remove fonksiyonu kullanılır. 65 | 66 | ```swift 67 | let mapleSyrup = shoppingList.remove(at: 0) 68 | ``` 69 | 70 | sondan çıkartmak için: 71 | 72 | ```swift 73 | let apples = shoppingList.removeLast() 74 | ``` 75 | 76 | ## Array Filtreleme 77 | 78 | ```swift 79 | var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] 80 | 81 | var filteredNumbers = numbers.filter { $0 % 2 == 0 } // [2, 4, 6, 8] 82 | ``` 83 | Burada $0 listenin elemanlarını temsil eder ve tüm elemanları gezmemizi sağlar. $0 yerine başka bir isim de verebiliriz. 84 | 85 | ## Array İterasyonu 86 | 87 | Normalde for/in ile yapılabilir ama hem index hem de value'ya ihtiyacımız varsa enumerated() fonksiyonu kullanılabilir. 88 | 89 | ```swift 90 | for (index, value) in array.enumerated() { 91 | print("index: \(index), value: \(value)") 92 | } 93 | ``` 94 | -------------------------------------------------------------------------------- /M-Error Handling/1-Error Handling.md: -------------------------------------------------------------------------------- 1 | ## Error Handling 2 | 3 | Swift, program runtime'ı boyunca oluşabilecek hataları yakalamak için, hata işleme mekanizması sunar. Bir hata oluştuğunda, programın çalışması durur ve hata yakalama mekanizması, hata ile ilgili bilgileri yakalar ve hata ile ilgili bilgileri, programın başka bir yerinde hata ile ilgili işlem yapmak için kullanılabilir. 4 | 5 | Karşılaşabilinecek hataları enum'lar ile modelleyebiliriz: 6 | 7 | ```swift 8 | enum LoginError: Error { 9 | case wrongUsername 10 | case wrongPassword 11 | } 12 | ``` 13 | 14 | Hata fırlatmak için `throw` anahtar kelimesini kullanabiliriz: 15 | 16 | ```swift 17 | func login(username: String, password: String) throws { 18 | if username != "admin" { 19 | throw LoginError.wrongUsername 20 | } 21 | 22 | if password != "1234" { 23 | throw LoginError.wrongPassword 24 | } 25 | } 26 | ``` 27 | 28 | Swift'te error handling için 4 yol vardır: 29 | 30 | - `do-catch` blokları 31 | - `try?` ile optional dönüş değeri 32 | - `try!` ile forced dönüş değeri 33 | - `defer` blokları 34 | 35 | Bir fonksiyonun hata fırlatabileceğini belirtmek için tanımlama: 36 | 37 | ```swift 38 | func login(username: String, password: String) throws { 39 | // ... 40 | } 41 | ``` 42 | 43 | Buradaki throws anahtar kelimesi return değerinden önce yazılır bir değer return ettiğimizde fonksiyon böyle gözükecek: 44 | 45 | ```swift 46 | func login(username: String, password: String) throws -> Bool { 47 | // ... 48 | } 49 | ``` 50 | 51 | ### do-catch 52 | 53 | `do-catch` blokları ile hata fırlatıldığında yakalayabiliriz: 54 | 55 | ```swift 56 | do { 57 | try login(username: "admin", password: "1234") 58 | print("Login success") 59 | } catch LoginError.wrongUsername { 60 | print("Wrong username") 61 | } catch LoginError.wrongPassword { 62 | print("Wrong password") 63 | } catch { 64 | print("Unknown error") 65 | } 66 | ``` 67 | 68 | ### try? 69 | 70 | `try?` ile hata fırlatıldığında optional bir değer döner: 71 | 72 | ```swift 73 | let loginResult = try? login(username: "admin", password: "1234") 74 | ``` 75 | 76 | ### try! 77 | 78 | `try!` ile hata fırlatıldığında forced bir değer döner: 79 | 80 | ```swift 81 | let loginResult = try! login(username: "admin", password: "1234") 82 | ``` 83 | 84 | ### defer 85 | 86 | `defer` blokları, fonksiyonun sonunda çalıştırılacak kod bloklarıdır. Hata fırlatılsa bile çalıştırılır: 87 | 88 | ```swift 89 | func login(username: String, password: String) throws { 90 | defer { 91 | print("Login finished") 92 | } 93 | 94 | if username != "admin" { 95 | throw LoginError.wrongUsername 96 | } 97 | 98 | if password != "1234" { 99 | throw LoginError.wrongPassword 100 | } 101 | 102 | print("Login success") 103 | } 104 | ``` 105 | 106 | 107 | -------------------------------------------------------------------------------- /N-Concurrency/3-Unstructured Concurrency.md: -------------------------------------------------------------------------------- 1 | ## Unstructured Concurrency 2 | 3 | Swift 5.5 ile birlikte, Unstructured Concurrency adı verilen yeni bir özellik eklendi. Bu özellik, geliştiricilere daha esnek ve ifade odaklı bir şekilde eşzamanlı işlemler gerçekleştirme imkanı sunar. Yapısal olmayan eşzamanlılık, bir görevin başka görevleri başlatması ve yönetmesi için kullanılır. 4 | 5 | ```swift 6 | func performTasksConcurrently() async { 7 | await withTaskGroup(of: Void.self) { group in 8 | group.addTask { 9 | await Task.sleep(1_000_000_000) // 1 saniye bekle 10 | print("Görev 1 tamamlandı") 11 | } 12 | 13 | group.addTask { 14 | await Task.sleep(2_000_000_000) // 2 saniye bekle 15 | print("Görev 2 tamamlandı") 16 | } 17 | } 18 | 19 | print("Tüm görevler tamamlandı") 20 | } 21 | 22 | Task { 23 | await performTasksConcurrently() 24 | } 25 | 26 | ``` 27 | 28 | ## Task 29 | 30 | Task anahtar kelimesi, Swift dilinde asenkron işlemleri temsil etmek için kullanılan bir yapıdır. Swift 5.5 ve sonraki sürümlerde yer almaktadır. Task anahtar kelimesi, asenkron işlemleri oluşturmak, başlatmak ve yönetmek için kullanılır. 31 | 32 | Bir Task nesnesi, bir görevin temsilidir ve bağımsız bir çalışma birimidir. Bu görev, yanlızca bir kere çalıştırılabilir ve tamamlandığında sonlanır. Task yapısı, iş parçacıklarında veya dispatçı kuyruklarında çalışabilen eşzamanlı bir şekilde yürütülebilir. 33 | 34 | Task yapısı, asenkron işlemleri oluşturmak için çeşitli yöntemlere sahiptir: 35 | 36 | Task.detached yöntemi, bağımsız bir görevi başlatmak için kullanılır. Bu görev, anında başlar ve yürütülmesi için bir iş parçacığı veya dispatçı kuyruğu seçilir. 37 | 38 | ```swift 39 | Task.detached { 40 | // Görevin yürütülmesi gereken kod 41 | } 42 | ``` 43 | 44 | Task { } yapıcısı, await ifadesiyle birlikte kullanılarak bir görev oluşturur. Bu görev, çalıştırıldığında bir iş parçacığı veya dispatçı kuyruğunda yürütülür. 45 | 46 | ```swift 47 | Task { 48 | // Görevin yürütülmesi gereken kod 49 | } 50 | ``` 51 | 52 | Task(priority: .default) { } yapıcısı, önceliği belirtilmiş bir görev oluşturur. Öncelik, .userInitiated, .default, .utility veya .background gibi değerlerle belirtilebilir. 53 | 54 | 55 | ```swift 56 | Task(priority: .default) { 57 | // Görevin yürütülmesi gereken kod 58 | } 59 | ``` 60 | Task yapısı, asenkron işlemleri yürütmek ve yönetmek için çeşitli yöntemlere ve özelliklere sahiptir: 61 | 62 | - await ifadesi, bir görevin tamamlanmasını beklemek için kullanılır. 63 | - Task.sleep yöntemi, belirli bir süre boyunca görevin uyumasını sağlar. 64 | - Task.isCancelled özelliği, görevin iptal edilip edilmediğini belirtir. 65 | - Task.checkCancellation yöntemi, görevin iptal edilip edilmediğini kontrol eder ve gerekirse bir hata fırlatır. 66 | 67 | Ayrıca, Task yapısı, görevler arasında veri paylaşımı ve senkronizasyon sağlamak için Task.LocalValues ve Task.Group gibi ilgili yapılarla da birlikte kullanılabilir. 68 | -------------------------------------------------------------------------------- /C-Fonksiyonlar/1-Değer Döndüren Fonksiyonlar.md: -------------------------------------------------------------------------------- 1 | ## Geri Değer Döndüren Fonksiyonlar 2 | 3 | Fonksiyonlar geri değer döndürebilir. Bir fonksiyonun geri döndürdüğü değer fonksiyonun sonundaki `->` işaretinden sonra yazılır. 4 | 5 | ```swift 6 | func topla(a: Int, b: Int) -> Int { 7 | return a + b 8 | } 9 | ``` 10 | 11 | Bir fonksiyonun geri dönüş değeri tanımlanmasa bile bir değer döndürür. Bu değer `Void` olarak adlandırılır. `Void` aslında bir `Tuple`'dır. 12 | 13 | ```swift 14 | func topla(a: Int, b: Int) { 15 | print(a + b) 16 | } 17 | ``` 18 | 19 | Eğer fonksiyon tek satırdan oluşuyorsa fonksiyonun sonundaki `->` işaretinden sonra yazılan değer tanımlanmasa bile otomatik olarak fonksiyonun tek satırı geri dönüş değeri olarak kabul edilir. 20 | 21 | ```swift 22 | func topla(a: Int, b: Int) -> Int { 23 | a + b 24 | } 25 | ``` 26 | 27 | Bu fonksiyon return ile yazılırsa da iki fonksiyon aynı işi yapar: 28 | 29 | ```swift 30 | func topla(a: Int, b: Int) -> Int { 31 | return a + b 32 | } 33 | ``` 34 | 35 | 36 | 37 | ## Birden Fazla Değer Döndürme (Touples) 38 | 39 | Bir fonksiyon birden fazla değer döndürebilir. Bunun için fonksiyonun geri dönüş değeri `Tuple` olarak tanımlanır. 40 | 41 | ```swift 42 | func minMax(array: [Int]) -> (min: Int, max: Int) { 43 | var currentMin = array[0] 44 | var currentMax = array[0] 45 | for value in array[1.. currentMax { 49 | currentMax = value 50 | } 51 | } 52 | return (currentMin, currentMax) 53 | } 54 | ``` 55 | 56 | Buradan değerleri almak için ise fonksiyonun çağırıldığı yerde `Tuple`'ın elemanlarına erişilir. 57 | 58 | ```swift 59 | let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) 60 | print("min is \(bounds.min) and max is \(bounds.max)") 61 | // Prints "min is -6 and max is 109" 62 | ``` 63 | 64 | ## Opsiyonel Değer Döndürme 65 | 66 | Bir fonksiyonun geri dönüş değeri opsiyonel olabilir. Bu durumda fonksiyonun geri dönüş değeri `?` ile tanımlanır. 67 | 68 | ```swift 69 | func sayiBul(array: [Int], sayi: Int) -> Int? { 70 | for (index, value) in array.enumerated() { 71 | if value == sayi { 72 | return index 73 | } 74 | } 75 | return nil 76 | } 77 | ``` 78 | 79 | ## implicit return 80 | 81 | ```swift 82 | func divide(_ a: Int, by b: Int) -> Int { 83 | if b == 0 { 84 | fatalError("Division by zero is not allowed.") 85 | } 86 | 87 | return a / b 88 | } 89 | ``` 90 | 91 | Bu örnekte, divide(_:_:) adlı bir fonksiyon tanımlanmıştır. Eğer b değeri sıfıra eşitse, fatalError fonksiyonu çağrılarak bir hata durumu oluşturulur ve program sonlandırılır. Bu hata durumu, bir değer döndürmeyen bir fonksiyon olduğu için implicit return olarak kullanılabilir. Bunun sebebi, Swift'in bu noktada bir değer döndürülmeyeceğini bilmesidir. 92 | 93 | Ancak, print(13) gibi bir ifadeyi implicit return olarak kullanamazsınız çünkü print fonksiyonu bir değer döndürmez. implicit return ile kullanılabilecek bir ifade, bir değer döndüren bir fonksiyon olmalıdır. 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /A-Temeller/3-Standartlar/4- Switch.md: -------------------------------------------------------------------------------- 1 | ## Switch 2 | 3 | Swift'te switch kullanırken break gerektirmeden ilk işleşme sağlandığı an kontrolden çıkarak performans artışı sağlanır. 4 | 5 | 6 | Birden fazla kontrol için virgül kullanılabilir. 7 | 8 | ```swift 9 | let anotherCharacter: Character = "a" 10 | switch anotherCharacter { 11 | case "a", "A": 12 | print("The letter A") 13 | default: 14 | print("Not the letter A") 15 | } 16 | // Prints "The letter A" 17 | ``` 18 | 19 | Swift'te switch içerisinde aralık eşleştirme mevcuttur. 20 | 21 | ```swift 22 | et approximateCount = 62 23 | let countedThings = "moons orbiting Saturn" 24 | let naturalCount: String 25 | switch approximateCount { 26 | case 0: 27 | naturalCount = "no" 28 | case 1..<5: 29 | naturalCount = "a few" 30 | case 5..<12: 31 | naturalCount = "several" 32 | case 12..<100: 33 | naturalCount = "dozens of" 34 | case 100..<1000: 35 | naturalCount = "hundreds of" 36 | default: 37 | naturalCount = "many" 38 | } 39 | print("There are \(naturalCount) \(countedThings).") 40 | // Prints "There are dozens of moons orbiting Saturn." 41 | ``` 42 | 43 | Switch'ler touples ile beraberde kullanılabilir ve aşama aşama eşleştirme yapılabilir. Ayrıca _ ile eşleşmeyen değerler için default değer belirlenebilir. 44 | 45 | ```swift 46 | let somePoint = (1, 1) 47 | switch somePoint { 48 | case (0, 0): 49 | print("\(somePoint) is at the origin") 50 | case (_, 0): 51 | print("\(somePoint) is on the x-axis") 52 | case (0, _): 53 | print("\(somePoint) is on the y-axis") 54 | case (-2...2, -2...2): 55 | print("\(somePoint) is inside the box") 56 | default: 57 | print("\(somePoint) is outside of the box") 58 | } 59 | // Prints "(1, 1) is inside the box" 60 | 61 | ``` 62 | 63 | Switch case'de where sorgusu da kullanılabilir. 64 | 65 | ```swift 66 | let yetAnotherPoint = (1, -1) 67 | switch yetAnotherPoint { 68 | case let (x, y) where x == y: 69 | print("(\(x), \(y)) is on the line x == y") 70 | case let (x, y) where x == -y: 71 | print("(\(x), \(y)) is on the line x == -y") 72 | case let (x, y): 73 | print("(\(x), \(y)) is just some arbitrary point") 74 | } 75 | // Prints "(1, -1) is on the line x == -y" 76 | ``` 77 | 78 | ## Value Bindings 79 | 80 | Switch case içerisinde değerlerin atanması için value bindings kullanılabilir. 81 | 82 | ```swift 83 | let yetAnotherPoint = (2, 0) 84 | switch yetAnotherPoint { 85 | case (let distance, 0), (0, let distance): 86 | print("On an axis, \(distance) from the origin") 87 | default: 88 | print("Not on an axis") 89 | } 90 | // Prints "On an axis, 2 from the origin" 91 | ``` 92 | 93 | ## Fallthrough 94 | 95 | Normalde swift switch case'de bir case'in sonunda break kullanılmazsa otomatik olarak break eklenir. Ancak bazen birden fazla case'in aynı kodu çalıştırması gerekebilir. Bu durumda fallthrough kullanılabilir. 96 | 97 | ```swift 98 | let character: Character = "a" 99 | 100 | switch character { 101 | case "a", "A": 102 | print("Vowel") 103 | fallthrough 104 | default: 105 | print("Character") 106 | } 107 | ``` -------------------------------------------------------------------------------- /S-Protocols/3-Standart Protocols.md: -------------------------------------------------------------------------------- 1 | ## Standart Protocols 2 | 3 | Swift'te, bir tipin bir protocol'e uyum sağlaması durumunda, belirli durumlarda uyum sağlayan kodun otomatik olarak oluşturulmasını sağlar. Bu özellik, protocol'ün gerektirdiği tüm özellikleri sağlayan varsayılan uygulamaların oluşturulmasıyla tipin protocol'e uyum sağlamasını kolaylaştırır. Protokolün bazı gereklilikleri, tipin kendi içerisinde uygulanabilirken, diğer gereklilikler otomatik olarak oluşturulan varsayılan bir uygulama ile sağlanabilir. Böylece, tekrarlayan veya basit uygulamaları tekrar yazma ihtiyacı ortadan kalkar ve kodun daha az tekrarlanması ve daha sade olması sağlanır. 4 | 5 | Swift'in sağladığı otomatik olarak eklenen protocol'ler: 6 | 7 | - Equatable 8 | - Hashable 9 | - Comparable 10 | - Error 11 | 12 | ## Equatable 13 | 14 | Equatable protokolü, bir tipin eşitlik karşılaştırmasını gerçekleştirmesini sağlar. Bu protokolü benimseyen bir tip, == operatörünü kullanarak başka bir aynı tipteki değerle karşılaştırılabilir. Equatable protokolü, örneğin iki dizeyi veya iki sayıyı karşılaştırmak için kullanılabilir. 15 | 16 | ```swift 17 | struct Person: Equatable { 18 | var name: String 19 | var age: Int 20 | } 21 | 22 | let person1 = Person(name: "Alice", age: 25) 23 | let person2 = Person(name: "Bob", age: 30) 24 | 25 | if person1 == person2 { 26 | print("Person1 and Person2 are equal") 27 | } else { 28 | print("Person1 and Person2 are not equal") 29 | } 30 | ``` 31 | 32 | ## Hashable 33 | 34 | Hashable protokolü, bir tipin karma işlevini uygulamasını sağlar. Karma işlevi, bir değeri benzersiz bir sayısal değere dönüştürür. Hashable protokolü, bir tipin eşitlik karşılaştırmasının yanı sıra, veri yapıları gibi hash tablolarında veya kümeleme yapısında kullanılabilmesini sağlar. 35 | 36 | ```swift 37 | struct Person: Hashable { 38 | var name: String 39 | var age: Int 40 | } 41 | 42 | let person = Person(name: "Alice", age: 25) 43 | let hashValue = person.hashValue 44 | ``` 45 | 46 | ## Comparable 47 | 48 | Comparable protokolü, bir tipin karşılaştırılabilirlik işlevini sağlar. Bu protokolü benimseyen bir tip, <, <=, >, >= operatörlerini kullanarak başka bir aynı tipteki değerle karşılaştırılabilir. Comparable protokolü, sıralama gerektiren veri yapılarında veya algoritmalarında kullanılabilir. 49 | 50 | ```swift 51 | struct Person: Comparable { 52 | var name: String 53 | var age: Int 54 | } 55 | 56 | let person1 = Person(name: "Alice", age: 25) 57 | let person2 = Person(name: "Bob", age: 30) 58 | 59 | if person1 < person2 { 60 | print("Person1 is younger than Person2") 61 | } else if person1 > person2 { 62 | print("Person1 is older than Person2") 63 | } else { 64 | print("Person1 and Person2 have the same age") 65 | } 66 | ``` 67 | 68 | ## Error 69 | 70 | Error protokolü, bir hata durumunu temsil etmek için kullanılır. Bir hata durumu oluştuğunda, hata fırlatılabilir (throw) ve Error protokolünü benimseyen bir türle temsil edilebilir. Hata fırlatma ve hata yakalama mekanizması, Swift'teki hata yönetimi için kullanılır. 71 | 72 | ```swift 73 | enum NetworkError: Error { 74 | case invalidURL 75 | case serverError 76 | case authenticationError 77 | } 78 | 79 | func fetchData(from url: String) throws { 80 | guard let validURL = URL(string: url) else { 81 | throw NetworkError.invalidURL 82 | } 83 | } 84 | 85 | do { 86 | try fetchData(from: "https://example.com") 87 | } catch let error { 88 | print("Error occurred: \(error)") 89 | } 90 | ``` 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /T-Generics/1-Generics.md: -------------------------------------------------------------------------------- 1 | ## Generics 2 | 3 | Generic fonksiyonlar Swift'in oldukça güçlü yönlerinden biridir. Türe bağlı olmadan çalışan fonksiyonlar yazmamızı sağlar. Bu sayede kod tekrarını önler ve daha az hata yapmamızı sağlar. 4 | 5 | Örneğin integer için toplama yapmayı hedeflediğimiz bir fonksiyonumuz olsun: 6 | 7 | ```swift 8 | func addIntegers(x: Int, y: Int) -> Int { 9 | return x + y 10 | } 11 | ``` 12 | 13 | Daha sonra Double için de bunu yapmak istediğimizi düşünelim. Benzer şekilde Float için de. Böyle böyle kod satırlarımız her tür için artacak ve aynı işlemi kopylayacağız. İşte tam olarak generic yapılar bu sorunu çözer. Bu toplama fonksiyonunu generic fonksiyon olarak yazmak istersek: 14 | 15 | ```swift 16 | func add(x: T, y: T) -> T { 17 | return x + y 18 | } 19 | ``` 20 | Bu şekilde integer,double, float,string vs. tüm türler için ortak çalışan bir fonksiyon yazmış olduk. 21 | 22 | Burada generic fonkisyon oluştururken paramtere isimleri için normalde aralarında eğer bir ilişki olan türlerin isimlendirilmesi doğrudan anlaşılır yazılmalıdır. Örneğin: Dictionary gibi. 23 | 24 | Ancak yukarıdaki örnekte olduğu gibi doğrudan bir fonksiyon aralarında bir ilişki olmayan türler için kullanılacağından ötürü T, U, V gibi isimler kullanılabilir. Ayrıca burada upper camel case kullanılması da önemlidir. 25 | 26 | ## Extension ve Generics 27 | 28 | Extensionlar generic türler için de kullanılabilir. Örneğin: 29 | 30 | ```swift 31 | extension Array { 32 | func randomItem() -> Element? { 33 | if isEmpty { return nil } 34 | let index = Int(arc4random_uniform(UInt32(self.count))) 35 | return self[index] 36 | } 37 | } 38 | ``` 39 | 40 | Burada Element generic türdür ve array içindeki öğeleri temsil etmek için kullanılır. Bu tür standart olarak gelir. 41 | 42 | ## Generic Subscripts 43 | 44 | Generic türler için subscript'ler de kullanılabilir. Örneğin: 45 | 46 | ```swift 47 | extension Array { 48 | subscript(indices: Indices) -> [Element] where Indices.Iterator.Element == Int { 49 | var result = [Element]() 50 | for index in indices { 51 | result.append(self[index]) 52 | } 53 | return result 54 | } 55 | } 56 | ``` 57 | 58 | ## Type Constraints 59 | 60 | Generic fonksiyonlar için tür kısıtlamaları getirilebilir. Örneğin: 61 | 62 | ```swift 63 | func add(x: T, y: T) -> T { 64 | return x + y 65 | } 66 | ``` 67 | 68 | Burada T türü Numeric protokolünü uygulayan türlerden biri olmalıdır. Bu sayede sadece sayısal türler için çalışan bir fonksiyon yazmış olduk. 69 | 70 | ## associatedtype 71 | 72 | Protokollerde de generic türler kullanılabilir. Örneğin: 73 | 74 | ```swift 75 | protocol Container { 76 | associatedtype Item 77 | mutating func append(_ item: Item) 78 | var count: Int { get } 79 | subscript(i: Int) -> Item { get } 80 | } 81 | ``` 82 | 83 | ## Generic ve Where 84 | 85 | Generic fonksiyonlarda where kullanarak tür kısıtlamaları getirebiliriz. Örneğin: 86 | 87 | ```swift 88 | func add(x: T, y: T) -> T where T: Numeric { 89 | return x + y 90 | } 91 | ``` 92 | 93 | Benzer şekilde extension'lar için de where kullanılabilir. Örneğin: 94 | 95 | ```swift 96 | extension Array where Element: Numeric { 97 | func sum() -> Element { 98 | return reduce(0, +) 99 | } 100 | } 101 | ``` 102 | 103 | Benzer şekilde protocol'de tanımladığımız associatedtype için de where kullanılabilir. Örneğin: 104 | 105 | ```swift 106 | protocol Container { 107 | associatedtype Item 108 | mutating func append(_ item: Item) 109 | var count: Int { get } 110 | subscript(i: Int) -> Item { get } 111 | func sum() -> Item where Item: Numeric 112 | } 113 | ``` 114 | 115 | -------------------------------------------------------------------------------- /U-Memory/2-Memory Safety.md: -------------------------------------------------------------------------------- 1 | ## Memory Safety 2 | 3 | Swift çoğu durumda bellek yönetimini otomatik olarak kontrol eder. Ancak bazı durumlarda bellek erişiminde conflict çıkması durumunda run-time hataları almak mümkündür. 4 | 5 | ## Bellek Erişimindeki Conflict 6 | 7 | Swift'te belleğe erişim bir değişkenin değerini değiştirmek, okumak veya bir fonksiyona parametre geçirmek gibi durumlarda gerçekleşir. Conflict, kodun farklı bölümlerinin aynı anda aynı bellek konumuna erişmeye çalıştığında gerçekleşebilir. Özellikle multithread kod yazarken bu sorunla karşılaşmak olasıdır. 8 | 9 | ## Bellek Erişim Conflict'inin Karakteristiği 10 | 11 | Bellek erişiminde conflict için dikkate alınması gereken üç durum vardır: 12 | 13 | - Erişim işlemi read veya write işlemi mi? 14 | - Erişim işlemi hangi bellek konumuna yapılıyor? 15 | - Erişimin süresi ne kadar? 16 | 17 | Özellikle aşağıdaki koşullar altında iki kez erişime sahipsek conflict oluşur: 18 | 19 | - Erişimlerden biri write işlemi ise 20 | - Erişimler aynı bellek konumuna yapılıyorsa 21 | - Erişim süreleri aynıysa 22 | 23 | ## inout Parametrelerinde Conflict 24 | 25 | Bir fonksiyon inout paramterleri için long term write işlemine sahiptir. Birden çok inout parametreye sahip bir fonksiyon varsa write erişimleri parametrelerin görüntülendiği sırada başlar. inout parametresi olarak geçirilen değerlere aynı anda birden fazla erişim yapma girişimi conflict'e neden olur. Fonksiyon parametresi inout olarak işaretlendiğinde, bu parametrenin değeri fonksiyonun çalışma süresince değiştirilebilir. inout parametresi, bir değeri işaret eden bir referans gibi davranır. Birden fazla eşzamanlı erişim, doğru bir şekilde yönetilmediğinde hatalara ve beklenmeyen sonuçlara neden olabilir. 26 | 27 | Örneğin: 28 | 29 | ```swift 30 | func increment(_ number: inout Int) { 31 | number += 1 32 | } 33 | 34 | var value = 5 35 | increment(&value) 36 | 37 | var value = 5 38 | increment(&value) 39 | increment(&value) 40 | // Error: Conflicting accesses to value 41 | ``` 42 | 43 | Bu örnekte, increment fonksiyonuna &value ifadesiyle bir referans geçildi. İkinci increment çağrısında ise aynı referansın tekrar kullanılmasıyla çakışan erişim oluşur ve derleme zamanında hata üretilir. 44 | 45 | 46 | ## Fonksiyon İçerisinde Self Kullanımında Conflict 47 | 48 | self referansına aynı anda birden fazla erişim yapma girişimi yapılırsa conflict oluşur. Örneğin, aşağıdaki kod parçasında, bir sınıf içindeki bir metodun self referansına erişim yapılmaktadır: 49 | 50 | ```swift 51 | class Counter { 52 | private var count = 0 53 | 54 | func increment() { 55 | count += 1 56 | } 57 | 58 | func incrementTwice() { 59 | increment() 60 | increment() 61 | } 62 | } 63 | ``` 64 | 65 | Ancak, aşağıdaki gibi bir çakışan erişim durumunda hatalar oluşabilir: 66 | 67 | ```swift 68 | let counter = Counter() 69 | counter.incrementTwice() 70 | // Error: Conflicting accesses to self in methods 71 | ``` 72 | 73 | ## Property'lerde Conflict 74 | 75 | Benzer şekilde property'lere aynı anda birden fazla erişim yapma girişimi yapılırsa conflict oluşur. Swift dilinde, bir sınıfın veya yapının özelliklerine erişim, bir getter veya setter metodu aracılığıyla gerçekleştirilir. Özelliklere yapılan erişimlerin senkronize bir şekilde gerçekleşmesi önemlidir. Birden fazla eşzamanlı erişim, doğru bir şekilde yönetilmediğinde hatalara ve beklenmeyen sonuçlara neden olabilir. 76 | 77 | Örneğin, aşağıdaki kod parçasında, bir sınıfın özelliğine aynı anda birden fazla erişim yapma girişimini görebiliriz: 78 | 79 | ```swift 80 | class Counter { 81 | private var count = 0 82 | 83 | var value: Int { 84 | get { 85 | return count 86 | } 87 | set { 88 | count = newValue 89 | } 90 | } 91 | 92 | func increment() { 93 | value += 1 94 | } 95 | 96 | func incrementTwice() { 97 | value += 1 98 | value += 1 99 | } 100 | } 101 | ``` 102 | 103 | Ancak, aşağıdaki gibi bir çakışan erişim durumunda hatalar oluşabilir: 104 | 105 | ```swift 106 | let counter = Counter() 107 | counter.incrementTwice() 108 | // Error: Conflicting accesses to value 109 | ``` 110 | Bu örnekte, incrementTwice metodunun içinde value özelliğine iki kez erişim yapılır. Ancak, aynı anda birden fazla erişim yapıldığı için çakışan erişim hatası oluşur ve derleme zamanında hata üretilir. 111 | -------------------------------------------------------------------------------- /K-Initialization/4-Failable Initializers.md: -------------------------------------------------------------------------------- 1 | ## Failable Initializers 2 | 3 | Failable initializer'lar, başlatma işlemi sırasında bir başarısızlık durumunu temsil etmek için kullanılır. Başarısızlık durumu, nil değeri döndürerek veya nil döndürülebilen bir opsiyonel değer döndürerek ifade edilir. Failable initializer'lar, belirli bir koşulu sağlamayan durumlarda nesne oluşturma girişimlerini başarısızlığa uğratabilir. Bu durumlar, verilen parametrelere veya diğer koşullara bağlı olarak oluşabilir. Failable initializer'lar, sınıf, yapıcı veya enum türleri için tanımlanabilir. 4 | 5 | Failable initializer'ların kullanılması için init? ifadesi kullanılır: 6 | 7 | ```swift 8 | struct Temperature { 9 | var celsius: Double 10 | 11 | init?(celsius: Double) { 12 | if celsius < -273.15 { // sıfırın altında sıcaklık yok 13 | return nil 14 | } 15 | self.celsius = celsius 16 | } 17 | } 18 | 19 | let temperature = Temperature(celsius: -300.0) 20 | 21 | if temperature == nil { 22 | print("sıfırın altında sıcaklık yok") 23 | } 24 | ``` 25 | 26 | Aynı parametre türlerine ve isimlere sahip bir normal bir failiable initializer oluşturamayız. 27 | 28 | Benzer şekilde Failable initializer'lar, belirli bir raw değeri temsil eden enum'ları oluştururken başarısızlık durumunu temsil etmek için kullanılır. Eğer belirli bir raw değere sahip bir enum oluşturulamazsa, failable initializer nil döndürür. 29 | 30 | ```swift 31 | enum Direction: String { 32 | case north = "N" 33 | case south = "S" 34 | case east = "E" 35 | case west = "W" 36 | 37 | init?(rawValue: String) { 38 | switch rawValue { 39 | case "N": 40 | self = .north 41 | case "S": 42 | self = .south 43 | case "E": 44 | self = .east 45 | case "W": 46 | self = .west 47 | default: 48 | return nil 49 | } 50 | } 51 | } 52 | ``` 53 | 54 | ## Failable Initializer'ların Yayılması / Paylaşımı 55 | 56 | Bir başlatıcı başarısız olduğunda, bu başarısızlık durumunun üst sınıflara, alt sınıflara veya aynı sınıfın diğer başlatıcılarına yayılabilir. 57 | 58 | ```swift 59 | class Vehicle { 60 | var numberOfWheels: Int 61 | 62 | init?(numberOfWheels: Int) { 63 | if numberOfWheels < 0 { 64 | return nil 65 | } 66 | self.numberOfWheels = numberOfWheels 67 | } 68 | } 69 | 70 | class Car: Vehicle { 71 | var brand: String 72 | 73 | init?(brand: String, numberOfWheels: Int) { 74 | self.brand = brand 75 | super.init(numberOfWheels: numberOfWheels) 76 | 77 | if brand.isEmpty { 78 | return nil 79 | } 80 | } 81 | } 82 | ``` 83 | 84 | Car sınıfı, üst sınıf olan Vehicle'ın failable initializer'ını çağırır ve kendi başarısızlık durumunu kontrol eder. Eğer brand parametresi boş bir dize ise, başlatma işlemi başarısız olur ve nil döndürülür. 85 | 86 | Bu durumda, başarısızlık durumu (nil) alt sınıftan üst sınıfa otomatik olarak yayılır. Yani, Car sınıfından oluşturulan bir nesne, brand parametresi boş bir dize veya negatif bir numberOfWheels değeri içeriyorsa, başlatma işlemi başarısız olur ve nil döndürülür. 87 | 88 | ## Override 89 | 90 | Failable initializer'larda override edilebilir. 91 | 92 | ```swift 93 | class Document { 94 | var name: String? 95 | // this initializer creates a document with a nil name value 96 | init() {} 97 | // this initializer creates a document with a nonempty name value 98 | init?(name: String) { 99 | if name.isEmpty { return nil } 100 | self.name = name 101 | } 102 | } 103 | 104 | class AutomaticallyNamedDocument: Document { 105 | override init() { 106 | super.init() 107 | self.name = "[Untitled]" 108 | } 109 | override init(name: String) { 110 | super.init() 111 | if name.isEmpty { 112 | self.name = "[Untitled]" 113 | } else { 114 | self.name = name 115 | } 116 | } 117 | } 118 | ``` 119 | 120 | init? 'e alternatif olarak init! kullanılabilir. init! kullanıldığında, başlatma işlemi başarısız olursa, program çöker. 121 | 122 | ```swift 123 | class Document { 124 | var name: String? 125 | // this initializer creates a document with a nil name value 126 | init() {} 127 | // this initializer creates a document with a nonempty name value 128 | init!(name: String) { 129 | if name.isEmpty { return nil } 130 | self.name = name 131 | } 132 | } 133 | 134 | let document = Document(name: "") 135 | ``` 136 | -------------------------------------------------------------------------------- /E-Enumeration/1-Enumeration.md: -------------------------------------------------------------------------------- 1 | ## Enumeration 2 | 3 | Swift'te enum'lar, birbirine bağlı değerlerin bir arada tutulduğu bir yapıdır. Enum'lar, Objective-C'deki enum'lardan farklı olarak, birbirine bağlı değerlerin yanı sıra, fonksiyonlar ve hesaplanmış özellikler de içerebilir. 4 | 5 | ```swift 6 | enum CompassPoint { 7 | case north 8 | case south 9 | case east 10 | case west 11 | } 12 | 13 | var directionToHead = CompassPoint.west 14 | 15 | directionToHead = .east //farklı atama için 16 | ``` 17 | Buradaki case'lerin bir integer indexleri yoktur. 18 | 19 | Case'ler tek satırda da yazılabilir: 20 | 21 | ```swift 22 | enum Planet { 23 | case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune 24 | } 25 | ``` 26 | 27 | Enum'lar, bir türdür. Bu yüzden büyük harfle başlarlar. 28 | 29 | 30 | ## Enum'lar ve Switch 31 | 32 | Enum'lar, switch ifadeleriyle kullanıldıklarında çok güçlüdürler. Enum'ların tüm case'lerini kapsayan bir switch ifadesi yazmak zorunda değilsiniz. Enum'ın tüm case'lerini kapsamayan bir switch ifadesi yazarsanız, default case'i yazmak zorunda değilsiniz. 33 | 34 | ```swift 35 | directionToHead = .south 36 | 37 | switch directionToHead { 38 | case .north: 39 | print("Lots of planets have a north") 40 | case .south: 41 | print("Watch out for penguins") 42 | case .east: 43 | print("Where the sun rises") 44 | case .west: 45 | print("Where the skies are blue") 46 | } 47 | 48 | // Prints "Watch out for penguins" 49 | ``` 50 | 51 | Enumları Switch ile kullanırken her case'i switch içerisinde yazmalıyız. Eğer tüm case'leri yazamazsak default case'i kullanmalıyız. 52 | 53 | ## allCases 54 | 55 | Enum'ların tüm case'lerini almak için allCases kullanabiliriz. 56 | 57 | ```swift 58 | enum Beverage: CaseIterable { 59 | case coffee, tea, juice 60 | } 61 | 62 | let numberOfChoices = Beverage.allCases.count 63 | print("\(numberOfChoices) beverages available") 64 | 65 | // Prints "3 beverages available" 66 | ``` 67 | 68 | allCase iterasyon için kullanılabilir: 69 | 70 | ```swift 71 | for beverage in Beverage.allCases { 72 | print(beverage) 73 | } 74 | 75 | // coffee 76 | // tea 77 | // juice 78 | ``` 79 | 80 | ## Değer Ayrıştırma 81 | 82 | ```swift 83 | enum Barcode { 84 | case upc(Int, Int, Int, Int) 85 | case qrCode(String) 86 | } 87 | 88 | var productBarcode = Barcode.upc(8, 85909, 51226, 3) 89 | productBarcode = .qrCode("ABCDEFGHIJKLMNOP") 90 | 91 | switch productBarcode { 92 | case let .upc(numberSystem, manufacturer, product, check): 93 | print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).") 94 | case let .qrCode(productCode): 95 | print("QR code: \(productCode).") 96 | } 97 | ``` 98 | 99 | ## Raw Değerler 100 | 101 | Enum'lar, raw değerlerle de oluşturulabilir. Raw değerler, aynı türden olmalıdır. Raw değerler, String, Character, Integer veya Floating Point değerleri olabilir. 102 | 103 | ```swift 104 | enum ASCIIControlCharacter: Character { 105 | case tab = "\t" 106 | case lineFeed = "\n" 107 | case carriageReturn = "\r" 108 | } 109 | ``` 110 | Eğer raw değeri yoksa otomatik olarak verilen isim kullanılır: 111 | 112 | ```swift 113 | enum MyEnum { 114 | case A 115 | case B 116 | case C 117 | } 118 | 119 | print(MyEnum.A) 120 | // Prints "A" 121 | ``` 122 | 123 | Raw değerlerinde integer için başlangıç değerinin belirlenmesiyle otomatik olarak arttırılır: 124 | 125 | ```swift 126 | enum Planet: Int { 127 | case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune 128 | } 129 | 130 | print(Planet.earth.rawValue) 131 | // Prints "3" 132 | ``` 133 | 134 | ## Recursive Enumerations 135 | 136 | Bir enum durumunun kendisiyle veya başka bir durumuyla ilişkilendirilmiş olduğu durumlarda kullanılır. Bu, enumların daha karmaşık ve yapısı iç içe geçmiş durumları temsil etmesine olanak tanır. Recursive Enumerations, enum'ların kendi içlerindeki değerleri kullanarak kendilerini çağırmasına izin verir. Recursive Enumerations, indirect anahtar kelimesiyle belirtilir. 137 | 138 | ```swift 139 | enum Tree { 140 | case leaf 141 | indirect case node(left: Tree, right: Tree) 142 | } 143 | 144 | let tree = Tree.node(left: .leaf, right: .leaf) 145 | ``` 146 | 147 | Burada, Tree adında bir enum tanımlanmıştır. leaf durumu, ağacın yaprak düğümünü temsil ederken, node durumu ise ağacın iç düğümlerini temsil eder. node durumu, left ve right adında iki alt ağaçla ilişkilendirilmiştir. 148 | 149 | Dikkat edilmesi gereken nokta, node durumunun indirect anahtar kelimesi ile işaretlenmiş olmasıdır. Bu, node durumunun özyinelemeli olduğunu belirtir ve alt ağaçlarının kendi enum durumlarını içerebileceği anlamına gelir. -------------------------------------------------------------------------------- /G-Properties/3-Property Wrappers.md: -------------------------------------------------------------------------------- 1 | ## Property Wrappers 2 | 3 | Swift 5.1 ile birlikte tanıtılan "Property Wrappers" (Özellik Sarmalayıcılar), property'lerin davranışını özelleştirmek ve tekrar kullanılabilirliği artırmak için kullanılan bir özelliktir. Property Wrappers, bir property'i sarmalayarak, property'nin değer ataması, erişimi ve depolanması gibi işlemleri kontrol etmemizi sağlar. 4 | 5 | Property Wrappers, property'lerin üzerine uygulanır ve property'lerin işlevselliğini değiştirmek veya genişletmek için kullanılır. Bu sayede, tekrar eden kod bloklarını azaltabilir ve property'leri daha okunabilir ve sade hale getirebiliriz. 6 | 7 | Bir Property Wrapper oluşturmak için, @propertyWrapper adlandırılmış bir struct veya class tanımlamamız gerekmektedir. Property Wrapper, wrappedValue adında bir özellik sağlar ve wrappedValue üzerinde işlemler gerçekleştirerek özelliğin davranışını değiştirebilir. 8 | 9 | ```swift 10 | @propertyWrapper 11 | struct Trimmed { 12 | private(set) var value: String = "" 13 | 14 | var wrappedValue: String { 15 | get { value } 16 | set { value = newValue.trimmingCharacters(in: .whitespacesAndNewlines) } 17 | } 18 | 19 | init(wrappedValue: String) { 20 | self.wrappedValue = wrappedValue.trimmingCharacters(in: .whitespacesAndNewlines) 21 | } 22 | } 23 | 24 | struct User { 25 | @Trimmed var name: String 26 | } 27 | 28 | let user = User(name: " John ") 29 | print(user.name) // "John" 30 | ``` 31 | Yukarıdaki örnekte, "Trimmed" adında bir Property Wrapper oluşturulmuştur. Bu Property Wrapper, bir String değerini alırken başında ve sonunda bulunan boşlukları temizleyen bir işlevselliği sağlar. "Trimmed" yapısı bir wrappedValue özelliği sağlar ve bu özelliği üzerinde işlem yaparak değerleri işler. 32 | 33 | "User" yapısında, "name" özelliği @Trimmed Property Wrapper ile sarmalanmıştır. Böylece, "name" özelliğine atanan değer otomatik olarak boşlukları temizlenir. Örnekte, "user.name" ifadesiyle "name" özelliği atanırken başında ve sonunda bulunan boşluklar temizlenir ve "John" olarak döndürülür. 34 | 35 | Property Wrappers, property'leri özelleştirmek, doğrulama yapmak, geçerlilik kontrolü yapmak veya özellik değerlerini otomatik olarak dönüştürmek gibi durumlarda oldukça kullanışlıdır. Ayrıca, kod tekrarını azaltır ve daha okunabilir, sade bir kod yazmamızı sağlar. 36 | 37 | ## Property Wrappers ve Init 38 | 39 | Bazı durumlarda Wrapper'da property'e bir değer verilmediğinde init ile bir değer vermek isteyebiliriz. Bunun için init fonksiyonunu kullanabiliriz. 40 | 41 | ```swift 42 | @propertyWrapper 43 | struct MyWrapper { 44 | private var value: Int 45 | 46 | var wrappedValue: Int { 47 | get { value } 48 | set { value = newValue } 49 | } 50 | 51 | init(wrappedValue initialValue: Int) { 52 | self.value = initialValue 53 | } 54 | } 55 | 56 | struct MyStruct { 57 | @MyWrapper(wrappedValue: 20) var myProperty: Int 58 | } 59 | 60 | let myStruct = MyStruct() 61 | print(myStruct.myProperty) // 20 62 | ``` 63 | 64 | ## Property Wrappers'ta Projecting 65 | 66 | Property Wrapper'ın sarmaladığı özelliğin üzerinden ek bilgiler veya işlemler sağlamak için kullanılır. Projecting, Property Wrapper yapısının üzerinde tanımlanan bir özelliğe erişmeyi ve o özellik üzerinde belirli işlemler gerçekleştirmeyi mümkün kılar. 67 | 68 | ```swift 69 | @propertyWrapper 70 | struct MyWrapper { 71 | private var value: Value 72 | 73 | var wrappedValue: Value { 74 | get { value } 75 | set { value = newValue } 76 | } 77 | 78 | var projectedValue: String { 79 | return "Projected value: \(value)" 80 | } 81 | 82 | init(initialValue: Value) { 83 | self.value = initialValue 84 | } 85 | } 86 | 87 | struct MyStruct { 88 | @MyWrapper(initialValue: 10) var myProperty: Int 89 | } 90 | 91 | let myStruct = MyStruct() 92 | print(myStruct.$myProperty) // Projected value: 10 93 | ``` 94 | 95 | Yukarıdaki örnekte, "MyWrapper" adında bir Property Wrapper tanımlanmıştır. Bu Property Wrapper, bir değeri saklar ve wrappedValue özelliği üzerinde işlemler gerçekleştirir. Ayrıca, "projectedValue" adında bir özellik tanımlanmıştır. Bu özellik, sarılmış özelliğin üzerinden projection yapılacak değeri temsil eder. 96 | 97 | "MyStruct" adında bir yapı tanımlanmıştır ve "myProperty" adında bir sarılmış özellik içerir. Bu sarılmış özelliğin üzerinden projection yapmak için "$" sembolü kullanılır ve projection yapılan değer elde edilir. 98 | 99 | Sonuç olarak, "myStruct.$myProperty" ifadesi kullanıldığında, sarılmış özelliğin projection değeri olan "Projected value: 10" elde edilir ve yazdırılır. 100 | 101 | -------------------------------------------------------------------------------- /P-Types/3-Opaque & Boxed Types.md: -------------------------------------------------------------------------------- 1 | ## Opaque & Boxed Types 2 | 3 | Swift implemente detaylarını gizlemek için iki yol sunar. Opauqe ve boxed types. 4 | 5 | ## Opaque Types 6 | 7 | Opaque types, bir değeri veya dönüş değerini belirli bir tür yerine soyut bir tür olarak kullanmanızı sağlar. Bu, bir fonksiyonun iç mantığını gizleyerek kodunun daha basit ve anlaşılır olmasını sağlar. Gizli türler, aşağıdaki durumlarda kullanışlı olabilir: 8 | 9 | - İç mantığı gizlenen bir veri yapısı döndürmek istediğinizde. 10 | - Bir API'nin dış dünyaya sadece belirli bir türle etkileşimde bulunmasını sağlamak istediğinizde. 11 | - Protokollerin karmaşık ilişkilerini gizlemek ve yalnızca sonucunu kullanıcılara sunmak istediğinizde. 12 | 13 | ```swift 14 | struct Square: Shape { 15 | var size: Int 16 | func draw() -> String { 17 | let line = String(repeating: "*", count: size) 18 | let result = Array(repeating: line, count: size) 19 | return result.joined(separator: "\n") 20 | } 21 | } 22 | 23 | 24 | func makeTrapezoid() -> some Shape { 25 | let top = Triangle(size: 2) 26 | let middle = Square(size: 2) 27 | let bottom = FlippedShape(shape: top) 28 | let trapezoid = JoinedShape( 29 | top: top, 30 | bottom: JoinedShape(top: middle, bottom: bottom) 31 | ) 32 | return trapezoid 33 | } 34 | let trapezoid = makeTrapezoid() 35 | print(trapezoid.draw()) 36 | ``` 37 | 38 | Yukarıdaki örnekte makeTrapezoid() fonksiyonu, Shape protokolünü uygulayan bir tür döndürür. Ancak, fonksiyonun içindeki karmaşık mantığı gizlemek için, fonksiyonun dönüş değerini some Shape olarak belirtiriz. Bu, fonksiyonun dış dünyaya sadece Shape protokolünü uygulayan bir tür döndürdüğünü söyler. Bu, fonksiyonun iç mantığını gizler ve kodun daha basit ve anlaşılır olmasını sağlar. 39 | 40 | 41 | ## Boxed Types 42 | 43 | Boxed Types, karmaşık veya değerlerini saklamak istediğiniz bir türü daha basit bir kap içine koyarak kullanmanızı sağlar. Bu, daha basit bir arayüz veya soyutlama kullanmanızı ve karmaşık detayları gizlemenizi sağlar. Boxed Types, aşağıdaki durumlarda kullanışlı olabilir: 44 | 45 | - Bellek yönetimini gizlemek ve sızıntıları önlemek istediğinizde. 46 | - Dış dünya için basit bir arayüz sağlamak istediğinizde. 47 | - İçerideki karmaşık yapının değişebilirliğini sağlamak istediğinizde. 48 | 49 | ```swift 50 | struct VerticalShapes: Shape { 51 | var shapes: [any Shape] 52 | func draw() -> String { 53 | return shapes.map { $0.draw() }.joined(separator: "\n\n") 54 | } 55 | } 56 | 57 | 58 | let largeTriangle = Triangle(size: 5) 59 | let largeSquare = Square(size: 5) 60 | let vertical = VerticalShapes(shapes: [largeTriangle, largeSquare]) 61 | print(vertical.draw()) 62 | ``` 63 | 64 | Yukaridaki örnekte VerticalShapes struct'ı [any Shape] yani Shape'i uygulayan herhangi bir türü tutan bir array içerir. Bu, VerticalShapes struct'ının dış dünyaya sadece Shape protokolünü uygulayan bir türü tuttuğunu söyler. Bu, VerticalShapes struct'ının iç mantığını gizler ve kodun daha basit ve anlaşılır olmasını sağlar. 65 | 66 | ## Opaque Types vs. Boxed Types 67 | 68 | - Saklama Mekanizması: Boxed Types, değeri içinde saklayarak karmaşık veya farklı türlerin basit bir arayüz sağlar. Değerin kendisi box'ın içinde saklanır. Opaque Types ise değeri gizler ve soyut bir tür olarak kullanır. Değerin kendisi belirsizdir ve iç detayları gizlenmiştir. 69 | 70 | - Tür İlişkisi: Boxed Types, değerlerini sakladıkları türlerin hiyerarşisini veya ilişkisini korur. Örneğin, bir BoxedAnimal türü, Animal sınıfının alt sınıflarını saklayabilir. Opaque Types ise tür ilişkisini gizler ve kullanıcıya sadece belirli bir arayüzü sunar. Bu sayede, arka planda farklı türlerin kullanılmasına izin verilir ve kullanıcıya sadece sonuç sunulur. 71 | 72 | - Genel Kullanım Amaçları: Boxed Types, karmaşık yapılara veya farklı türlerin bir arada saklanması gereken durumlarda kullanılır. Değerleri box'a yerleştirerek, basit bir arayüz sağlar ve değerlerin kontrolünü kolaylaştırır. Opaque Types ise soyutlama sağlamak veya gizli bir yapıyı basitleştirmek için kullanılır. Değerleri gizleyerek, karmaşık yapıların detaylarını saklar ve kullanıcıya sadece sonucu sunar. 73 | 74 | - Çalışma Zamanı Davranışı: Boxed Types, değerleri box'a yerleştirerek bellekte ayrı bir alan oluşturur ve referans semantiğiyle çalışır. Opaque Types ise değerleri gizler ve bazen daha fazla bellek kullanmadan optimize edilmiş çalışma zamanı davranışı sağlar. Bu, değerlerin kullanıldığı yerde doğrudan erişim sağlanmasına olanak tanır. 75 | 76 | Özetle, Boxed Types, farklı türleri bir arada saklamak ve kontrol etmek için kullanılırken, Opaque Types, soyutlama sağlamak ve değerlerin gizlenmesini sağlamak için kullanılır. Boxed Types, değerlerin saklandığı bir box olarak düşünülebilirken, Opaque Types, değerlerin soyut bir arayüz olarak kullanılmasını temsil eder. -------------------------------------------------------------------------------- /V-Access Control/1- Access Control.md: -------------------------------------------------------------------------------- 1 | ## Access Control 2 | 3 | OOP Temellerinden biri olan Encaupsulation, bir nesnenin içindeki verilerin ve fonksiyonların dışarıdan erişilebilir olmasını engelleyen bir kavramdır. Bu kavramın uygulanması için de erişim belirleyicileri kullanılır. Erişim belirleyicileri, bir nesnenin içindeki verilerin ve fonksiyonların dışarıdan erişilebilir olmasını engeller. Bu belirleyiciler, nesnenin içindeki verilerin ve fonksiyonların hangi durumlarda dışarıdan erişilebilir olacağını belirler. Bu başlık altında da Swift dilinde bulunan erişim belirleyicileri incelenecektir. 4 | 5 | - Bir fonksiyonun geri dönüş değerinin access level'i, fonksiyonun access level'inden daha düşük olamaz. 6 | 7 | - Bir public değişken dosyaya file-private veya private ile işaretlenemez. 8 | 9 | 10 | ## Access Levels 11 | 12 | Swift 5 farklı access level sunar. Bu access level'ler şunlardır: 13 | 14 | - Open : En geniş erişim belirleyicisidir. Yalnızca class'lar ve class member'lar ile kullanılabilir. Open erişim belirleyicisine sahip bir class, başka bir modül içindeki class'lar tarafından miras alınabilir. Aynı zamanda open erişim belirleyicisine sahip bir class'ın member'ları, başka bir modül içindeki class'lar tarafından override edilebilir. 15 | - Public : İşlevi Open ile aynı olmakla beraber Open'dan farkı, başka bir modül içindeki sınıfların ve yapıların bu sınıf ve yapıları miras alamamasıdır. 16 | - Internal : Sadece modül içinde erişilebilir. Dışarıdan erişilemez. Default access level'dir. Bir değişkenin veya fonksiyonun access level'i belirtilmediğinde internal olarak kabul edilir. 17 | - File-private : Sadece tanımlandığı dosya içinde erişilebilir. Dışarıdan erişilemez. Belirli bir işlevsellik tüm dosya içinde kullanıldığında dışarıya gizlemek için kullanılır. 18 | - Private : Sadece tanımlandığı scope içinde erişilebilir. Dışarıdan erişilemez. Belirli bir işlevsellik tüm scope içinde kullanıldığında dışarıya gizlemek için kullanılır. 19 | 20 | ```swift 21 | public class SomePublicClass {} 22 | internal class SomeInternalClass {} 23 | fileprivate class SomeFilePrivateClass {} 24 | private class SomePrivateClass {} 25 | 26 | 27 | public var somePublicVariable = 0 28 | internal let someInternalConstant = 0 29 | fileprivate func someFilePrivateFunction() {} 30 | private func somePrivateFunction() {} 31 | ``` 32 | 33 | ## Kullanımlar ve Notlar 34 | 35 | Eğer bir class, struct veya enum'un access level'i belirtilmişse içerisindeki member'ların access level'i değiştirilmediği sürece default olarak mevcut yapıdan gelir. Örneğin: 36 | 37 | ```swift 38 | public class SomePublicClass { // explicitly public class 39 | public var somePublicProperty = 0 // explicitly public class member 40 | var someInternalProperty = 0 // implicitly internal class member 41 | fileprivate func someFilePrivateMethod() {} // explicitly file-private class member 42 | private func somePrivateMethod() {} // explicitly private class member 43 | } 44 | 45 | 46 | class SomeInternalClass { // implicitly internal class 47 | var someInternalProperty = 0 // implicitly internal class member 48 | fileprivate func someFilePrivateMethod() {} // explicitly file-private class member 49 | private func somePrivateMethod() {} // explicitly private class member 50 | } 51 | 52 | 53 | fileprivate class SomeFilePrivateClass { // explicitly file-private class 54 | func someFilePrivateMethod() {} // implicitly file-private class member 55 | private func somePrivateMethod() {} // explicitly private class member 56 | } 57 | 58 | 59 | private class SomePrivateClass { // explicitly private class 60 | func somePrivateMethod() {} // implicitly private class member 61 | } 62 | ``` 63 | 64 | Burada eğer bir inheritence varsa subclass'ın access level'i superclass'tan yüksek olamaz. 65 | 66 | Access level'ler override edilebilir: 67 | 68 | ```swift 69 | public class A { 70 | fileprivate func someMethod() {} 71 | } 72 | 73 | 74 | internal class B: A { 75 | override internal func someMethod() {} 76 | } 77 | ``` 78 | 79 | Bir fonksiyon, döndürdüğü değerdeki erişim düzeyinin en düşük erişim düzeyine sahip olmalıdır: 80 | 81 | ```swift 82 | func someFunction() -> (SomeInternalClass, SomePrivateClass) { // error: Function must be declared private or fileprivate because its result uses a private type 83 | 84 | } 85 | ``` 86 | 87 | Düzeltirsek: 88 | 89 | ```swift 90 | private func someFunction() -> (SomeInternalClass, SomePrivateClass) { 91 | 92 | } 93 | ``` 94 | 95 | Bir yapıdan instance üretirken, instance'ın access level'i, yapıdan daha düşük olamaz: 96 | 97 | ```swift 98 | private var privateInstance = SomePrivateClass() // private tanımlanmazsa hata verir. 99 | ``` 100 | 101 | -------------------------------------------------------------------------------- /G-Properties/1-Properties.md: -------------------------------------------------------------------------------- 1 | ## Properties 2 | 3 | Swift programlama dilinde "properties" (özellikler), bir sınıf, yapı veya numaralandırma türünde değerlerin depolanması, erişilmesi ve ayarlanması için kullanılan öğelerdir. Properties, bir nesnenin durumunu veya özelliklerini temsil eder ve nesne tarafından taşınan verileri saklar. 4 | 5 | Swift'te iki tür properties bulunur: "stored properties" (saklanan özellikler) ve "computed properties" (hesaplanan özellikler). 6 | 7 | ### Stored Properties 8 | 9 | Stored properties, bir class'ın, struct veya enum türünün bir parçası olarak doğrudan bir değeri saklar. Bunlar bellekte ayrı bir alan işgal ederler ve özellikle değişken (var/let) olarak tanımlanır. Stored properties, class ve struct türleri için kullanılabilirken, enum türleri için yalnızca hesaplanan (computed) özellikler kullanılabilir. 10 | 11 | ```swift 12 | struct Person { 13 | var name: String 14 | var age: Int 15 | } 16 | 17 | var person1 = Person(name: "John", age: 25) 18 | print(person1.name) // John 19 | print(person1.age) // 25 20 | 21 | person1.name = "Jane" 22 | print(person1.name) // Jane 23 | ``` 24 | 25 | Yukarıdaki örnekte, "Person" struct'ında "name" ve "age" adında iki stored property bulunmaktadır. Bu özellikler, struct'ın bir parçası olarak doğrudan bir değer saklar ve erişilebilir/ayarlanabilir. 26 | 27 | ### Lazy Stored Properties 28 | 29 | "Lazy Stored Properties" (Geç Otomatikleştirilmiş Saklanan Özellikler), değerleri kullanıldığı anda hesaplanan ve sadece ilk erişim anında değer atanmış olan özelliklerdir. Bu özellikler, bellek kullanımını azaltmak ve performansı iyileştirmek için kullanışlıdır. 30 | 31 | Bir lazy stored property, değerine ilk erişim yapıldığında hesaplanır ve sonraki erişimlerde aynı değeri döndürür. Bu özelliği kullanarak, değeri gerektiğinde hesaplanacak olan özelliklerin başlangıç değerlerini atamaktan kaçınabiliriz. 32 | 33 | Lazy stored property'ler yalnızca değişken (var) özelliklerde kullanılabilir ve 'lazy' anahtar kelimesiyle tanımlanır. Ayrıca, sadece değer tipi olan (class değil) ve başlangıç değerine ihtiyaç duyan saklanan özelliklerde kullanılabilirler. 34 | 35 | ```swift 36 | class ImageLoader { 37 | lazy var image: UIImage = self.loadImage() 38 | 39 | func loadImage() -> UIImage { 40 | // Burada görüntünün yüklenme işlemi gerçekleştirilir 41 | // Örnek olarak, bir dosyadan veya bir ağ isteğinden görüntü yüklenir 42 | return UIImage(named: "exampleImage")! 43 | } 44 | } 45 | 46 | let loader = ImageLoader() 47 | // 'image' özelliğine ilk erişimde görüntü yüklenir 48 | let loadedImage = loader.image 49 | ``` 50 | 51 | Yukarıdaki örnekte, "ImageLoader" adında bir sınıfımız var. Bu sınıfın "image" adında bir lazy stored property'si bulunmaktadır. İlk erişim anında, "image" özelliği "loadImage()" metodunu çağırarak görüntüyü yükler. Sonraki erişimlerde ise hesaplanan değer doğrudan döndürülür. Bu sayede, görüntüye ihtiyaç duyulmadığı durumlarda gereksiz yüklemelerden kaçınılabilir ve bellek kullanımı azaltılır. 52 | 53 | Lazy stored property'lerin kullanımı, performansı artırmak ve kaynakları etkin kullanmak için faydalı olabilir, özellikle hesaplama maliyeti yüksek olan değerlere sahip özelliklerde veya başlangıç değerlerine zamanla ihtiyaç duyan durumlarda kullanılabilir. 54 | 55 | ## Computed Properties 56 | 57 | Computed properties, gerçek değeri saklamak yerine her erişildiğinde hesaplanan bir değeri temsil eder. Computed properties, "get" ve opsiyonel olarak "set" bloklarını içeren bir yapıya sahiptir. Get bloğunda, hesaplanan değeri döndürürken set bloğunda ise yeni bir değer alır ve uygun eylemleri gerçekleştirir. Computed properties, herhangi bir tür için kullanılabilir. 58 | 59 | ```swift 60 | struct Circle { 61 | var radius: Double 62 | 63 | var area: Double { 64 | get { 65 | return Double.pi * radius * radius 66 | } 67 | set(newArea) { 68 | radius = sqrt(newArea / Double.pi) 69 | } 70 | } 71 | } 72 | 73 | var circle = Circle(radius: 5.0) 74 | print(circle.area) // 78.53981633974483 75 | 76 | circle.area = 100.0 77 | print(circle.radius) // 5.641895835477563 78 | ``` 79 | 80 | 81 | Properties, Swift programlama dilinde nesnelerin durumunu temsil etmek için önemli bir araçtır. Stored properties, verileri doğrudan saklar ve computed properties, değerleri dinamik olarak hesaplayabilir. Bu sayede nesnelerin davranışlarını ve özelliklerini daha esnek bir şekilde yönetebiliriz. 82 | 83 | ## Read-Only Computed Properties 84 | 85 | Computed properties, sadece okunabilir (read-only) olarak da tanımlanabilir. Bu durumda, sadece get bloğu bulunur ve set bloğu bulunmaz. Read-only computed properties, sadece get bloğu bulunan computed properties'lerdir. 86 | 87 | ```swift 88 | struct Circle { 89 | var radius: Double 90 | 91 | var area: Double { 92 | return Double.pi * radius * radius 93 | } 94 | } 95 | 96 | var circle = Circle(radius: 5.0) 97 | 98 | print(circle.area) // 78.53981633974483 99 | ``` 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /D-Closure/1-Closure.md: -------------------------------------------------------------------------------- 1 | ## Closure 2 | 3 | Swift'te closure'lar, bir kod bloğunu veya işlevi başka bir yerde kullanılabilen bir nesne olarak temsil eden özel bir yapıdır. Closure'lar, işlevsel programlama ve asenkron programlama gibi durumlarda oldukça kullanışlıdır. 4 | 5 | Türleri: 6 | 7 | - Temel Closure: 8 | 9 | ```swift 10 | let greet = { 11 | print("Merhaba, dünya!") 12 | } 13 | greet() // "Merhaba, dünya!" çıktısını verir 14 | ``` 15 | 16 | - Parametreli Closure: 17 | 18 | ```swift 19 | let greet = { (name: String) in 20 | print("Merhaba, \(name)!") 21 | } 22 | greet("Swift") // "Merhaba, Swift!" çıktısını verir 23 | ``` 24 | 25 | - Dönüş Değeri Olan Closure: 26 | 27 | ```swift 28 | let multiply = { (a: Int, b: Int) -> Int in 29 | return a * b 30 | } 31 | let result = multiply(5, 3) // 15 32 | ``` 33 | 34 | - Closure'ları Parametre Olarak Alan Fonksiyonlar: 35 | 36 | ```swift 37 | func calculate(a: Int, b: Int, operation: (Int, Int) -> Int) { 38 | let result = operation(a, b) 39 | print("Sonuç: \(result)") 40 | } 41 | 42 | calculate(a: 10, b: 5, operation: { (a, b) in 43 | return a + b 44 | }) // "Sonuç: 15" çıktısını verir 45 | 46 | calculate(a: 8, b: 4, operation: { (a, b) in 47 | return a * b 48 | }) // "Sonuç: 32" çıktısını verir 49 | ``` 50 | 51 | - Sıralama için örnek: 52 | 53 | ```swift 54 | let numbers = [5, 2, 10, 1, 8] 55 | let sortedNumbers = numbers.sorted { (a, b) in 56 | return a < b 57 | } 58 | print(sortedNumbers) // [1, 2, 5, 8, 10] çıktısını verir 59 | ``` 60 | 61 | ## Çağırımlar 62 | 63 | İki farklı türde çağırım vardır: 64 | 65 | ```swift 66 | // Here's how you call this function without using a trailing closure: 67 | 68 | 69 | someFunctionThatTakesAClosure(closure: { 70 | // closure's body goes here 71 | }) 72 | 73 | 74 | // Here's how you call this function with a trailing closure instead: 75 | 76 | 77 | someFunctionThatTakesAClosure() { 78 | // trailing closure's body goes here 79 | } 80 | ``` 81 | 82 | ## Notlar 83 | 84 | Closure'ların parametresi inout alabilir ama default değer almazlar. 85 | 86 | Parantezlere gerek kalmadan Closure tek satırda yazılabilir ve return kullanmaya da gerek yoktur: 87 | 88 | ```swift 89 | reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } ) 90 | ``` 91 | 92 | Parametrelere isim verilmeden de kullanılabilir. 93 | 94 | ```swift 95 | reversedNames = names.sorted(by: { $0 > $1 } ) 96 | ``` 97 | 98 | Hiçbir parametre verilmeden sıralama yapılabilir: 99 | 100 | ```swift 101 | reversedNames = names.sorted(by: >) 102 | ``` 103 | 104 | Closure tarafından değiştirilmeyen bir değişken varsa Swift bellek yönetimi için değişkeni elden çıkarır. 105 | 106 | Closure'lar referans tiplidir: 107 | 108 | ```swift 109 | var incrementByTwo: () -> Int = { 110 | var count = 0 111 | let incrementClosure: () -> Int = { 112 | count += 2 113 | return count 114 | } 115 | return incrementClosure 116 | } 117 | 118 | var firstClosure = incrementByTwo() 119 | print(firstClosure()) // Çıktı: 2 120 | 121 | var secondClosure = firstClosure 122 | print(secondClosure()) // Çıktı: 4 123 | 124 | print(firstClosure()) // Çıktı: 6 125 | ``` 126 | 127 | ## Escaping 128 | 129 | @escaping anahtar kelimesi, closure'ın belirli bir süre boyunca yaşaması gerektiğini ve fonksiyonun dışında çağrılabileceğini ifade eder. Bu, genellikle asenkron operasyonlarda veya bir fonksiyonun içinde başlatılan işlemlerin tamamlandığında geri çağırma yapmak için kullanılır. 130 | 131 | ```swift 132 | func doSomething(completion: @escaping () -> Void) { 133 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 134 | completion() 135 | } 136 | } 137 | 138 | doSomething { 139 | print("Tamamlandı!") 140 | } 141 | ``` 142 | 143 | 144 | ## Autoclosure 145 | 146 | Swift'te "Autoclosures" (otomatik kapanan closure'lar) adı verilen bir özellik vardır. Autoclosures, bir işlev veya ifade içinde gecikmiş değerlendirme sağlar. Bu, bir değeri kapatmak ve o değerin sadece ihtiyaç duyulduğunda hesaplanmasını sağlamak için kullanışlıdır. Autoclosures, genellikle argüman olarak alınacak bir closure için kısa ve kullanımı kolay bir sözdizini sağlar. Autoclosures, genellikle geçici olarak değerlendirilmemesi gereken ifadeleri geciktirmek veya değerlendirmek için kullanılır. Bu sayede, gerektiğinde performans ve hafıza optimizasyonu sağlanabilir. 147 | 148 | ```swift 149 | var names = ["Ahmet", "Mehmet", "Ayşe", "Fatma"] 150 | 151 | let closureExample: () -> String = { 152 | return names.remove(at: 0) 153 | } 154 | 155 | let removedName = closureExample() 156 | print(names) // ["Mehmet", "Ayşe", "Fatma"] 157 | print(removedName) // "Ahmet" 158 | ``` 159 | 160 | @aoutoclosure anahtar kelimesi, closure'ın otomatik olarak kapanmasını sağlar. Bu sayede closure'ın çağrıldığı yerde değerlendirilmesi sağlanır. 161 | 162 | ```swift 163 | var numbers = [1, 2, 3, 4, 5] 164 | 165 | func processNextNumber(_ closure: @autoclosure () -> Int) { 166 | let nextNumber = closure() 167 | print("Sonraki sayı: \(nextNumber)") 168 | } 169 | 170 | processNextNumber(numbers.remove(at: 0)) 171 | print(numbers) // [2, 3, 4, 5] 172 | ``` 173 | 174 | -------------------------------------------------------------------------------- /A-Temeller/1-Değişkenler/6-String.md: -------------------------------------------------------------------------------- 1 | ## String 2 | 3 | Multiline için: 4 | 5 | ```swift 6 | let quotation = """ 7 | The White Rabbit put on his spectacles. "Where shall I begin, 8 | please your Majesty?" he asked. 9 | """ 10 | ``` 11 | 12 | Kodu kolay okunabilir hale getirmek için: 13 | 14 | ```swift 15 | let softWrappedQuotation = """ 16 | The White Rabbit put on his spectacles. "Where shall I begin, \ 17 | please your Majesty?" he asked. 18 | """ 19 | ``` 20 | 21 | Swift'te String oluşturulduğunda beraberinde bir kopyası da oluşturulur ve bu string değeri bir fonksiyona vs. iletildiğinde orjinal hali değil kopyası gönderilir. Bu sayede orjinal string değeri korunmuş olur. 22 | 23 | Swift'te bir karakter için değişken oluşturulabilir. 24 | 25 | Örneğin: 26 | 27 | ```swift 28 | let exclamationMark: Character = "!" 29 | ``` 30 | 31 | Bir string array'inden string oluşturulabilir benzer şekilde bir string'te iterasyon uygulanabilir array gibi davranır. 32 | 33 | Örneğin: 34 | 35 | ```swift 36 | let catCharacters: [Character] = ["C", "a", "t", "!", "?"] 37 | let catString = String(catCharacters) 38 | print(catString) 39 | // Prints "Cat!?" 40 | ``` 41 | 42 | 43 | ## Kaçış Karakterleri 44 | 45 | ```swift 46 | let wiseWords = "\"Imagination is more important than knowledge\" - Einstein" 47 | let dollarSign = "\u{24}" // $, Unicode scalar U+0024 48 | let blackHeart = "\u{2665}" // ♥, Unicode scalar U+2665 49 | let sparklingHeart = "\u{1F496}" // 💖, Unicode scalar U+1F496 50 | ``` 51 | 52 | - Burada ek olarak özel karakterler için # kullanılabilir. Örneğin: 53 | 54 | ```swift 55 | let filePath = #"C:\Users\Username\Documents\"# 56 | print(filePath) // "C:\Users\Username\Documents\" 57 | ``` 58 | 59 | 60 | ## Stringlerde Indexler 61 | 62 | ```swift 63 | let greeting = "Guten Tag!" 64 | greeting[greeting.startIndex] 65 | // G 66 | greeting[greeting.index(before: greeting.endIndex)] 67 | // ! 68 | greeting[greeting.index(after: greeting.startIndex)] 69 | // u 70 | let index = greeting.index(greeting.startIndex, offsetBy: 7) 71 | greeting[index] 72 | // a 73 | ``` 74 | 75 | Burada endIndex'e ve endIndex'in sonrasına erişmek string range'inden çıkmak olduğu için hata verir. 76 | 77 | ```swift 78 | greeting[greeting.endIndex] // Error 79 | greeting.index(after: greeting.endIndex) // Error 80 | ``` 81 | 82 | ## Stringlerde insert ve remove 83 | 84 | ```swift 85 | var welcome = "hello" 86 | welcome.insert("!", at: welcome.endIndex) 87 | // welcome now equals "hello!" 88 | welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex)) 89 | // welcome now equals "hello there!" 90 | welcome.remove(at: welcome.index(before: welcome.endIndex)) 91 | // welcome now equals "hello there" 92 | let range = welcome.index(welcome.endIndex, offsetBy: -6).. 112 | 113 | ## String Eşitliği 114 | 115 | Stringlerin içeriği eşit olduğu sürece eşittirler. 116 | 117 | ```swift 118 | let quotation = "We're a lot alike, you and I." 119 | let sameQuotation = "We're a lot alike, you and I." 120 | if quotation == sameQuotation { 121 | print("These two strings are considered equal") 122 | } 123 | // Prints "These two strings are considered equal" 124 | ``` 125 | 126 | - hasPrefix ve hasSuffix ile stringlerin başlangıç ve bitişlerini kontrol edebiliriz. 127 | 128 | 129 | ```swift 130 | let romeoAndJuliet = [ 131 | "Act 1 Scene 1: Verona, A public place", 132 | "Act 1 Scene 2: Capulet's mansion", 133 | "Act 1 Scene 3: A room in Capulet's mansion", 134 | "Act 1 Scene 4: A street outside Capulet's mansion", 135 | "Act 1 Scene 5: The Great Hall in Capulet's mansion", 136 | "Act 2 Scene 1: Outside Capulet's mansion", 137 | "Act 2 Scene 2: Capulet's orchard", 138 | "Act 2 Scene 3: Outside Friar Lawrence's cell", 139 | "Act 2 Scene 4: A street in Verona", 140 | "Act 2 Scene 5: Capulet's mansion", 141 | "Act 2 Scene 6: Friar Lawrence's cell" 142 | ] 143 | 144 | var act1SceneCount = 0 145 | 146 | for scene in romeoAndJuliet { 147 | if scene.hasPrefix("Act 1 ") { 148 | act1SceneCount += 1 149 | } 150 | } 151 | 152 | print("There are \(act1SceneCount) scenes in Act 1") 153 | 154 | // Prints "There are 5 scenes in Act 1" 155 | ``` 156 | 157 | - hasSuffix ile de bitiş kontrolü yapılabilir. 158 | 159 | -------------------------------------------------------------------------------- /F-Struct & Class/4-Arasındaki Farklılıklar.md: -------------------------------------------------------------------------------- 1 | ## Class ve Struct Arasındaki Farklılıklar 2 | 3 | Class'lar referans tiplerdir ve Heap bölgesinde tutulur. Stack bölgesinde ise referanslar tutulur. Kod bloğunun dışına çıkıldığında stack'teki referans hemen bellekten düşüp uygun görüldüğünde heap bölgesindeki verisi de temizlenir. 4 | 5 | Struct'lar değer tiplerdir. Referans yapısı bulunmaz ve veri Stack'te tutulur. Kod bloğunun dışına çıkıldığında stack'teki veri hemen bellekten düşer. 6 | 7 | Eğer her durumda veri bellekte tutulmadan doğrudan temizlenmesini istiyorsak Struct kullanabiliriz. 8 | 9 | ```swift 10 | class Person { 11 | var name: String 12 | init(name: String) { 13 | self.name = name 14 | } 15 | } 16 | 17 | var person1 = Person(name: "John") 18 | 19 | var person2 = person1 20 | 21 | person1.name = "Jack" 22 | 23 | print(person1.name) // Jack 24 | 25 | print(person2.name) // Jack 26 | ``` 27 | 28 | ```swift 29 | 30 | struct Person { 31 | var name: String 32 | init(name: String) { 33 | self.name = name 34 | } 35 | } 36 | 37 | var person1 = Person(name: "John") 38 | 39 | var person2 = person1 40 | 41 | person1.name = "Jack" 42 | 43 | print(person1.name) // Jack 44 | 45 | print(person2.name) // John 46 | ``` 47 | 48 | Fonksiyonlara parametre gönderirken Class'lar referans olarak gönderilir. Struct'lar ise kopyalanarak gönderilir. 49 | 50 | ```swift 51 | class Person { 52 | var name: String 53 | init(name: String) { 54 | self.name = name 55 | } 56 | } 57 | 58 | func changeName(person: Person) { 59 | person.name = "Jack" 60 | } 61 | 62 | var person = Person(name: "John") 63 | 64 | changeName(person: person) 65 | 66 | print(person.name) // Jack 67 | ``` 68 | 69 | ```swift 70 | 71 | struct Person { 72 | var name: String 73 | init(name: String) { 74 | self.name = name 75 | } 76 | } 77 | 78 | func changeName(person: Person) { 79 | var person = person 80 | person.name = "Jack" 81 | } 82 | 83 | var person = Person(name: "John") 84 | 85 | changeName(person: person) 86 | 87 | print(person.name) // John 88 | ``` 89 | 90 | Class oluştururken tanımladığımız değerler optional değilse init yazmak zorundayız. Struct'lar için bu zorunlu değildir. 91 | 92 | ```swift 93 | class Person { 94 | var name: String 95 | init(name: String) { 96 | self.name = name 97 | } 98 | } 99 | 100 | var person = Person(name: "John") 101 | 102 | print(person.name) // John 103 | ``` 104 | 105 | ```swift 106 | 107 | struct Person { 108 | var name: String 109 | } 110 | 111 | var person = Person(name: "John") 112 | 113 | print(person.name) // John 114 | ``` 115 | 116 | Struct içerisinde tutulan verilere başlangıç değeri vermezsek instance oluştururken mutlaka değer vermek zorundayız. Class'ta bunu yapmak için parametreli init yazmak zorundayız. 117 | 118 | ```swift 119 | 120 | struct Person { 121 | var name: String 122 | } 123 | 124 | var person = Person() // Error 125 | ``` 126 | 127 | ```swift 128 | 129 | struct Person { 130 | var name: String 131 | } 132 | 133 | var person = Person(name: "John") 134 | 135 | print(person.name) // John 136 | ``` 137 | 138 | ```swift 139 | 140 | class Person { 141 | var name: String 142 | init(name: String) { 143 | self.name = name 144 | } 145 | } 146 | 147 | var person = Person() // Error 148 | ``` 149 | 150 | ```swift 151 | 152 | class Person { 153 | var name: String 154 | init(name: String) { 155 | self.name = name 156 | } 157 | } 158 | 159 | var person = Person(name: "John") 160 | 161 | print(person.name) // John 162 | ``` 163 | 164 | 165 | Class'lar inheritance yapabilir. Struct'lar yapamaz. 166 | 167 | ```swift 168 | class Person { 169 | var name: String 170 | init(name: String) { 171 | self.name = name 172 | } 173 | } 174 | 175 | class Student: Person { 176 | var studentNumber: Int 177 | init(name: String, studentNumber: Int) { 178 | self.studentNumber = studentNumber 179 | super.init(name: name) 180 | } 181 | } 182 | 183 | var student = Student(name: "John", studentNumber: 123) 184 | 185 | print(student.name) // John 186 | 187 | print(student.studentNumber) // 123 188 | ``` 189 | 190 | ```swift 191 | 192 | struct Person { 193 | var name: String 194 | init(name: String) { 195 | self.name = name 196 | } 197 | } 198 | 199 | struct Student: Person { // Error 200 | var studentNumber: Int 201 | init(name: String, studentNumber: Int) { 202 | self.studentNumber = studentNumber 203 | super.init(name: name) 204 | } 205 | } 206 | ``` 207 | 208 | Class'lar deinit metodu ile bellekten temizlenir. Struct'lar ise deinit metodu bulundurmaz. 209 | 210 | ```swift 211 | class Person { 212 | var name: String 213 | init(name: String) { 214 | self.name = name 215 | } 216 | deinit { 217 | print("Person deinit") 218 | } 219 | } 220 | 221 | var person: Person? = Person(name: "John") 222 | 223 | person = nil // Person deinit 224 | ``` 225 | 226 | ```swift 227 | 228 | struct Person { 229 | var name: String 230 | init(name: String) { 231 | self.name = name 232 | } 233 | } 234 | 235 | var person: Person? = Person(name: "John") 236 | 237 | person = nil 238 | ``` 239 | 240 | Class'larda type casting yani tür dönüşümü yapılabilir. Struct'larda yapılamaz. 241 | 242 | 243 | 244 | 245 | 246 | -------------------------------------------------------------------------------- /J-Inheritance/2-Override.md: -------------------------------------------------------------------------------- 1 | ## Override 2 | 3 | Override veya overwriting bir sınıf tarafından kalıtım almış başka bir sınıfın kalıtımla aldığı özelliklerin veya methodların kendi içerisinde değiştirilmesidir. Override işlemi için override keyword'ü kullanılır. 4 | 5 | ```swift 6 | class Vehicle { 7 | var currentSpeed = 0.0 8 | var description: String { 9 | return "traveling at \(currentSpeed) miles per hour" 10 | } 11 | func makeNoise() { 12 | // do nothing - an arbitrary vehicle doesn't necessarily make a noise 13 | } 14 | } 15 | 16 | class Car : Vehicle { 17 | var gear = 1 18 | override var description: String { 19 | return super.description + " in gear \(gear)" 20 | } 21 | } 22 | ``` 23 | 24 | ## getter/setter Override 25 | 26 | ```swift 27 | class Superclass { 28 | var myProperty: Int { 29 | get { 30 | return 10 31 | } 32 | set { 33 | print("Superclass set") 34 | } 35 | } 36 | } 37 | 38 | class Subclass: Superclass { 39 | override var myProperty: Int { 40 | get { 41 | return super.myProperty + 5 42 | } 43 | set { 44 | print("Subclass set") 45 | } 46 | } 47 | } 48 | 49 | let obj = Subclass() 50 | print(obj.myProperty) // Output: 15 51 | obj.myProperty = 20 // Output: "Subclass set" 52 | ``` 53 | 54 | Override edilmiş bir özelliğin yalnızca get veya set gözlemcilerini kullanmak: 55 | 56 | ```swift 57 | class Superclass { 58 | var myProperty: Int { 59 | get { 60 | return 10 61 | } 62 | set { 63 | print("Superclass set") 64 | } 65 | } 66 | } 67 | 68 | class Subclass: Superclass { 69 | override var myProperty: Int { 70 | get { 71 | return super.myProperty + 5 72 | } 73 | } 74 | } 75 | 76 | let obj = Subclass() 77 | print(obj.myProperty) // Output: 15 78 | obj.myProperty = 20 // Error: Cannot assign to property: 'myProperty' is a get-only property 79 | ``` 80 | 81 | Bu örnekte, Subclass alt sınıfı, myProperty adlı özelliğin sadece get gözlemcisini override etmiştir. Set gözlemcisi override edilmemiştir ve alt sınıfta özelliğin sadece okunabilir (get-only) olduğu bir durum oluşmuştur. 82 | 83 | ## super 84 | 85 | super keyword'ü ile override edilmiş bir özelliğin veya methodun superclass'ındaki orijinal haline erişilebilir. 86 | 87 | ```swift 88 | class Superclass { 89 | func myMethod() { 90 | print("Superclass") 91 | } 92 | } 93 | 94 | class Subclass: Superclass { 95 | override func myMethod() { 96 | super.myMethod() 97 | print("Subclass") 98 | } 99 | } 100 | 101 | let obj = Subclass() 102 | 103 | obj.myMethod() // Output: Superclass 104 | // Subclass 105 | ``` 106 | 107 | ## Property Observes Override 108 | 109 | ```swift 110 | class Superclass { 111 | var myProperty: Int = 0 { 112 | willSet { 113 | print("Superclass willSet - New value: \(newValue)") 114 | } 115 | didSet { 116 | print("Superclass didSet - Old value: \(oldValue), New value: \(myProperty)") 117 | } 118 | } 119 | } 120 | 121 | class Subclass: Superclass { 122 | override var myProperty: Int { 123 | willSet { 124 | print("Subclass willSet - New value: \(newValue)") 125 | } 126 | didSet { 127 | print("Subclass didSet - Old value: \(oldValue), New value: \(myProperty)") 128 | } 129 | } 130 | } 131 | 132 | let obj = Subclass() 133 | obj.myProperty = 5 134 | // Output: 135 | // Superclass willSet - New value: 5 136 | // Superclass didSet - Old value: 0, New value: 5 137 | // Subclass willSet - New value: 5 138 | // Subclass didSet - Old value: 0, New value: 5 139 | 140 | obj.myProperty = 10 141 | // Output: 142 | // Superclass willSet - New value: 10 143 | // Superclass didSet - Old value: 5, New value: 10 144 | // Subclass willSet - New value: 10 145 | // Subclass didSet - Old value: 5, New value: 10 146 | ``` 147 | 148 | Not: setter'a sahip olmayan bir özelliğin willSet ve didSet gözlemcileri override edilemez. 149 | 150 | ## init() Override 151 | 152 | ```swift 153 | class Superclass { 154 | let constantProperty: Int = 10 // Inherited constant stored property 155 | 156 | var readOnlyProperty: Int { // Inherited read-only computed property 157 | return 20 158 | } 159 | } 160 | 161 | class Subclass: Superclass { 162 | override var constantProperty: Int { 163 | didSet { 164 | print("Subclass didSet - New value: \(constantProperty)") 165 | } 166 | } 167 | 168 | override var readOnlyProperty: Int { 169 | didSet { 170 | print("Subclass didSet - New value: \(readOnlyProperty)") 171 | } 172 | } 173 | // Error: Cannot override with a stored property 'constantProperty' with a setter 174 | // Error: Property does not override any property from its superclass 175 | } 176 | ``` 177 | 178 | ## final 179 | 180 | final keyword'ü ile bir sınıfın veya sınıfın özelliğinin veya methodunun override edilmesi engellenebilir. 181 | 182 | ```swift 183 | class Superclass { 184 | final func myMethod() { 185 | print("Superclass") 186 | } 187 | } 188 | 189 | class Subclass: Superclass { 190 | override func myMethod() { // Error: Cannot override 'final' method 191 | print("Subclass") 192 | } 193 | } 194 | ``` 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /H-Methods/1-Methods.md: -------------------------------------------------------------------------------- 1 | ## Methods 2 | 3 | Swift'te methodlar, bir sınıf, yapıcı (initializer) veya bir tipin içindeki işlevleri ifade eden kod bloklarıdır. Methodlar, belirli bir nesne türünün davranışını tanımlar ve bu nesneler üzerinde çalışabilen işlemleri gerçekleştirir. 4 | 5 | Methodlar ile fonksiyonlar arasındaki temel farklar: 6 | 7 | - İlişkili Nesne: Methodlar, bir sınıf, yapı veya enum gibi bir türün bir parçasıdır ve bu türe ait özelliklere ve diğer methodlara erişebilir. Fonksiyonlar ise bağımsız olarak tanımlanır ve herhangi bir türe ait olmadan çalışabilir. 8 | 9 | 10 | - Self Referansı: Methodlar, ilgili türe ait özelliklere ve methodlara erişmek için self kelimesini kullanabilir. Bu şekilde, method içindeki diğer özelliklere ve methodlara erişebilir ve onları değiştirebilir. Fonksiyonlar ise bağımsız olduğundan, bir self referansına sahip değillerdir. 11 | 12 | - Çağırma Sözdizimi: Methodlar, ilgili türün bir örneği üzerinden çağrılır. Örneğin, myObject.myMethod() şeklinde bir çağırma sözdizimi kullanılır. Fonksiyonlar ise doğrudan adlarıyla çağrılabilir, örneğin myFunction() şeklinde bir çağırma sözdizimi kullanılır. 13 | 14 | - Genişletilebilirlik: Methodlar, ilgili türlerin genişletilmelerine izin veren bir yapıya sahiptir. Yani, bir türe ait olan methodları daha sonra uzatabilir veya yenilerini ekleyebilirsiniz. Fonksiyonlar ise doğrudan genişletilemezler. 15 | 16 | Methodlar temelde iki kategoriye ayrılır: 17 | 18 | ## Instance Methods 19 | 20 | Instance Methodlar: Bir sınıf, yapıcı veya bir yapı (struct) içinde tanımlanan methodlardır. Bunlar, belirli bir nesneye ait davranışları ifade eder. Instance methodları kullanabilmek için ilgili yapıdan bir instance oluşturmamız gerekir. 21 | 22 | ```swift 23 | class Counter { 24 | var count = 0 25 | 26 | func increment() { 27 | count += 1 28 | } 29 | 30 | func reset() { 31 | count = 0 32 | } 33 | } 34 | 35 | let counter = Counter() 36 | counter.increment() 37 | print(counter.count) // Çıktı: 1 38 | counter.reset() 39 | print(counter.count) // Çıktı: 0 40 | ``` 41 | ## Value Type'larının Instance Metodlarıyla Modifiye Edilmesi 42 | 43 | Value type'larının instance metodlarıyla modifiye edilmesi için metodun mutating olarak tanımlanması gerekir. Bu sayede value type'ın instance metodları içerisindeki özellikler değiştirilebilir. 44 | 45 | ```swift 46 | struct Point { 47 | var x = 0.0, y = 0.0 48 | 49 | mutating func moveBy(x deltaX: Double, y deltaY: Double) { 50 | x += deltaX 51 | y += deltaY 52 | } 53 | } 54 | 55 | var somePoint = Point(x: 1.0, y: 1.0) 56 | somePoint.moveBy(x: 2.0, y: 3.0) 57 | print("The point is now at (\(somePoint.x), \(somePoint.y))") 58 | // Prints "The point is now at (3.0, 4.0)" 59 | ``` 60 | 61 | Bu örnekte değişkenlerimiz value type olduğu için, metodumuzun mutating olarak tanımlanması gerekiyor. Aksi takdirde metodumuz içerisindeki değişiklikler, değişkenin değerini değiştirmeyecektir. 62 | 63 | ## Mutating'in Self ile Kullanımı 64 | 65 | Mutating metodlar, self ile kullanıldığında, self'in yeni bir instance'ı ile değiştirilmesini sağlar. Örneğin, Point struct'ımızı kullanarak bir metod tanımlayalım: 66 | 67 | ```swift 68 | struct Point { 69 | var x = 0.0, y = 0.0 70 | 71 | mutating func moveBy(x deltaX: Double, y deltaY: Double) { 72 | self = Point(x: x + deltaX, y: y + deltaY) 73 | } 74 | } 75 | ``` 76 | Burada self, yeni bir Point instance'ı ile değiştirilir. Point struct'ının bir instance'ı üzerinde çağrıldığında, bu instance'ın yeni bir kopyası oluşturulur ve bu kopya üzerinde değişiklikler yapılır. 77 | 78 | Enumaration'lar için de aynı durum geçerlidir. 79 | 80 | ```swift 81 | enum TriStateSwitch { 82 | case off, low, high 83 | mutating func next() { 84 | switch self { 85 | case .off: 86 | self = .low 87 | case .low: 88 | self = .high 89 | case .high: 90 | self = .off 91 | } 92 | } 93 | } 94 | var ovenLight = TriStateSwitch.low 95 | ovenLight.next() 96 | // ovenLight is now equal to .high 97 | ovenLight.next() 98 | // ovenLight is now equal to .off 99 | ``` 100 | 101 | ## Type Methods 102 | 103 | Type Methods, bir sınıf, yapıcı (initializer) veya bir enum tipine ait olan ve doğrudan tipe ait olan metodlardır. Bunlar, bir türün genel davranışını ifade eder ve örneklendirilmiş bir nesne üzerinden değil, tipe doğrudan erişilerek çağrılırlar. 104 | 105 | Type Methods, aşağıdaki özelliklere sahiptir: 106 | 107 | "static" veya "class" Anahtar Kelimeleri: Bir Type Method'u tanımlamak için "static" veya "class" anahtar kelimelerinden birini kullanırız. Hangi anahtar kelimenin kullanılacağı, türe bağlı olarak farklılık gösterebilir. 108 | 109 | static: final olarak işaretlenmiş sınıflar, yapılar ve enumlar için kullanılır. Bu tip türlerdeki metodlar alt sınıflar tarafından yeniden uygulanamaz. Örneğin: 110 | 111 | ```swift 112 | class MyClass { 113 | static func myStaticMethod() { 114 | // Type Method kodu 115 | } 116 | } 117 | ``` 118 | 119 | class: "class" Anahtar Kelimesi: "class" anahtar kelimesi ise alt sınıflar tarafından yeniden uygulanabilen sınıflar için kullanılır. 120 | 121 | ```swift 122 | class MyClass { 123 | class func myClassMethod() { 124 | // Type Method kodu 125 | } 126 | } 127 | ``` 128 | 129 | Tipe Özgü Erişim: Type Methods, tipe ait olduğu için doğrudan tipe erişilerek çağrılırlar. 130 | 131 | ```swift 132 | MyClass.myStaticMethod() 133 | MyClass.myClassMethod() 134 | ``` 135 | 136 | Tipe Ait Özelliklere Erişim: Type Methods, tipe ait özelliklere doğrudan erişebilir ve onları değiştirebilir. 137 | 138 | ```swift 139 | class MyClass { 140 | static var count = 0 141 | 142 | static func incrementCount() { 143 | count += 1 144 | } 145 | } 146 | 147 | MyClass.incrementCount() 148 | print(MyClass.count) // Çıktı: 1 149 | ``` 150 | 151 | Override Edilebilirlik: Type Methods, override edilebilen türlere (subclass) aitse, alt sınıflar tarafından yeniden uygulanabilir. 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /S-Protocols/1-Protocols.md: -------------------------------------------------------------------------------- 1 | ## Protocols 2 | 3 | Protocol'ler, bir türün belirli bir işlevselliği veya özelliği uygulamasını sağlar. Bir protocol, bir veya birden fazla property, method, initializer veya subscript tanımlayabilir. Bir tür, bir protocol'ü uyguladığında, tür, protocol'ün tüm gereksinimlerini karşılamalıdır. 4 | 5 | Temel syntax: 6 | 7 | ```swift 8 | protocol SomeProtocol { 9 | // protocol definition goes here 10 | } 11 | ``` 12 | 13 | Bir class, protocol vs. birden fazla protocol'ü uygulayabilir. Bu durumda, protocol'ler arasında virgülle ayrılmış bir liste kullanılır: 14 | 15 | ```swift 16 | struct SomeStructure: FirstProtocol, AnotherProtocol { 17 | // structure definition goes here 18 | } 19 | 20 | class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol { 21 | // class definition goes here 22 | } 23 | ``` 24 | 25 | Protocol'e bir property eklemek istersek: 26 | 27 | ```swift 28 | protocol SomeProtocol { 29 | var mustBeSettable: Int { get set } 30 | var doesNotNeedToBeSettable: Int { get } 31 | static func someTypeMethod() 32 | } 33 | ``` 34 | 35 | Burada protocol içerisinde tanımlanan property her türe özgü olmayacaksa `static` keyword'ü kullanılabilir. Bu durumda, property'ye erişmek için türün adı kullanılır: 36 | 37 | ```swift 38 | protocol AnotherProtocol { 39 | static var someTypeProperty: Int { get set } 40 | } 41 | ``` 42 | 43 | ## Protocol'ler ve Initializer'lar 44 | 45 | Bir protocol, initializer tanımlayabilir. Bir tür, protocol'ü uyguladığında, tür, protocol'ün initializer'ını uygulamalıdır. Bir initializer, initializer'ı uygulayan türün initializer'ını override edemez. 46 | 47 | ```swift 48 | protocol SomeProtocol { 49 | init(someParameter: Int) 50 | } 51 | ``` 52 | 53 | Eğer aynı anda hem bir superclass'ın hem de bir protocol'ün initializer'ı uygulanmak isteniyorsa required ve override keyword'leri kullanılır: 54 | 55 | ```swift 56 | protocol SomeProtocol { 57 | init() 58 | } 59 | 60 | class SomeSuperClass { 61 | init() { 62 | // initializer implementation goes here 63 | } 64 | } 65 | 66 | class SomeSubClass: SomeSuperClass, SomeProtocol { 67 | // "required" from SomeProtocol conformance; "override" from SomeSuperClass 68 | required override init() { 69 | // initializer implementation goes here 70 | } 71 | } 72 | ``` 73 | 74 | Protocol'ler extension'lar ile de kullanılabilir: 75 | 76 | ```swift 77 | protocol TextRepresentable { 78 | var textualDescription: String { get } 79 | } 80 | 81 | extension Dice: TextRepresentable { 82 | var textualDescription: String { 83 | return "A \(sides)-sided dice" 84 | } 85 | } 86 | ``` 87 | 88 | Bir protocol extension ile genişletilebilir: 89 | 90 | ```swift 91 | protocol MyProtocol { 92 | func someMethod() 93 | } 94 | 95 | extension MyProtocol { 96 | func someMethod() { 97 | print("Default implementation of someMethod") 98 | } 99 | 100 | func additionalMethod() { 101 | print("Additional method provided by the extension") 102 | } 103 | } 104 | 105 | struct MyStruct: MyProtocol { 106 | // MyProtocol'ün gerekliliklerini otomatik olarak karşılar 107 | } 108 | 109 | let myStruct = MyStruct() 110 | myStruct.someMethod() // Default implementation of someMethod 111 | myStruct.additionalMethod() // Additional method provided by the extension 112 | 113 | ``` 114 | 115 | Bir protocol bir veya daha fazla protocol'ü inherit edebilir: 116 | 117 | ```swift 118 | protocol InheritingProtocol: SomeProtocol, AnotherProtocol { 119 | // protocol definition goes here 120 | } 121 | ``` 122 | 123 | ## Class-Only Protocols 124 | 125 | Bir protocol, sadece class'lar tarafından uygulanabilirse, class-only protocol olarak adlandırılır. Bir protocol'ü class-only yapmak için, protocol'ün inheritance listesinin başına `AnyObject` keyword'ü eklenir: 126 | 127 | ```swift 128 | protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { 129 | // class-only protocol definition goes here 130 | } 131 | ``` 132 | 133 | ## Protocol İçerisinde Optional Gereksinimler 134 | 135 | Bir protocol, optional gereksinimler tanımlayabilir. Bu gereksinimler, uygulayan tür tarafından uygulanmayabilir. Bir optional gereksinim, `optional` keyword'ü ile tanımlanır. Bir optional gereksinim, `?` ile işaretlenmiş bir property veya method olabilir. Bir optional gereksinim, `optional` keyword'ü ile tanımlanmış bir initializer olamaz. 136 | 137 | ```swift 138 | @objc protocol CounterDataSource { 139 | @objc optional func increment(forCount count: Int) -> Int 140 | @objc optional var fixedIncrement: Int { get } 141 | } 142 | ``` 143 | 144 | ## Protocol Extension'larında Kısıtlayıcılar 145 | 146 | Swift'te bir protocol'ü genişletmek için extension yazarken kısıtlamalar yani constraint'ler oluşturmaya izin verir.Protokol genişletmeleri, protokolü uygulayan tüm tipler için ortak uygulamalar sağlar. Ancak, bazen genişlemeyle sağlanan işlevselliğin belirli tiplerle sınırlanması gerekebilir. Bu durumda bu yönteme başvurulabilir. 147 | 148 | ```swift 149 | protocol MyProtocol { 150 | func someMethod() 151 | } 152 | 153 | extension MyProtocol where Self: SomeClass { 154 | func someMethod() { 155 | print("SomeClass implementation of someMethod") 156 | } 157 | } 158 | 159 | class SomeClass: MyProtocol { 160 | // MyProtocol'ün gerekliliklerini otomatik olarak karşılar 161 | } 162 | 163 | struct SomeStruct: MyProtocol { 164 | // MyProtocol'ün gerekliliklerini otomatik olarak karşılamaz 165 | } 166 | 167 | let someClass = SomeClass() 168 | someClass.someMethod() // SomeClass implementation of someMethod 169 | 170 | let someStruct = SomeStruct() 171 | someStruct.someMethod() // Default implementation of someMethod 172 | ``` 173 | 174 | Yukarıdaki örnekte, MyProtocol adında bir protokol tanımlanmış ve bir extension ile genişletilmiştir. Ancak, extension yalnızca SomeClass adlı bir sınıf tarafından benimsendiğinde geçerlidir. SomeClass, MyProtocol'ü benimsemektedir ve genişleme, someMethod() adlı bir özel uygulama sağlar. Diğer yandan, SomeStruct adlı bir yapı, MyProtocol'ü benimsemesine rağmen genişleme kısıtlamalarını karşılamadığından varsayılan bir someMethod() uygulaması kullanılır. 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /U-Memory/1-ARC.md: -------------------------------------------------------------------------------- 1 | ## Automatic Reference Counting (ARC) 2 | 3 | Swift ARC'yi kullanarak hafızayı otomatik olarak yönetir. ARC, bir sınıf örneğine kaç referans olduğunu takip eder. Bir sınıf örneğine referans sayısı 0 olduğunda, ARC, sınıf örneğini hafızadan siler. ARC Yalnızca class'ları ve instance'ları yönetir. Struct'lar ve enum'ları değil. Çünkü bunlar değer türleridir. 4 | 5 | ## Nasıl Çalışır? 6 | 7 | Class'tan bir instance oluşturduğumuz her zaman ARC bu instance ile ilgili bilgileri depolamak için bir bellek ayırır. Bu bellek, instance'ın türüyle ilgili bilgileri ve bu instance ile ilişkilendirilmiş property'lerin değerlerini tutar. Bu instance'a ihtiyaç kalmadığı durumda ARC, bu belleği serbest bırakır. Bu sayede bellek kullanımı optimize edilir. ARC bir instance'ın gerekli olup olmadığını belirlemek için instance'a kaç referans olduğunu takip eder. Bu referans sayısı, instance'a yeni bir referans oluşturulduğunda 1 artar. Bir referansın scope'u dışına çıktığında 1 azalır. Bir instance'a referans sayısı 0 olduğunda ARC, instance'ı hafızadan siler. 8 | 9 | 10 | Örneğin: 11 | 12 | ```swift 13 | class Person { 14 | let name: String 15 | init(name: String) { 16 | self.name = name 17 | print("\(name) is being initialized") 18 | } 19 | deinit { 20 | print("\(name) is being deinitialized") 21 | } 22 | } 23 | 24 | var reference1: Person? 25 | var reference2: Person? 26 | var reference3: Person? 27 | 28 | reference1 = Person(name: "John Appleseed") 29 | // Prints "John Appleseed is being initialized" 30 | 31 | reference2 = reference1 32 | reference3 = reference1 33 | 34 | reference1 = nil 35 | reference2 = nil 36 | reference3 = nil // Tam bu satırda, Person instance'ı hafızadan silinir. 37 | ``` 38 | 39 | ## Strong Reference Cycles 40 | 41 | ARC'nin hiçbir zaman hafızayı serbest bırakamadığı durumlar vardır. Bu durumlara Strong Reference Cycles denir. Strong Reference Cycles, iki class instance'ı arasında oluşan bir ilişkidir. Bu ilişki, her iki instance'ın da birbirine strong reference oluşturmasıyla oluşur. Bu durumda ARC, bu iki instance'ı hafızadan silmez. Bu durumda ARC'nin hafızayı serbest bırakabilmesi için, bu iki instance'ın birbirine strong reference oluşturmasını engellememiz gerekir. 42 | 43 | Bu durum aşağıdaki koşulda oluşur: 44 | 45 | ```swift 46 | class Person { 47 | let name: String 48 | init(name: String) { self.name = name } 49 | var apartment: Apartment? 50 | deinit { print("\(name) is being deinitialized") } 51 | } 52 | 53 | 54 | class Apartment { 55 | let unit: String 56 | init(unit: String) { self.unit = unit } 57 | var tenant: Person? 58 | deinit { print("Apartment \(unit) is being deinitialized") } 59 | } 60 | 61 | var john: Person? 62 | var unit4A: Apartment? 63 | 64 | john = Person(name: "John Appleseed") 65 | unit4A = Apartment(unit: "4A") 66 | 67 | john!.apartment = unit4A //Linklendi, Strong Reference Cycle 68 | unit4A!.tenant = john //Linklendi, Strong Reference Cycle 69 | 70 | john = nil 71 | unit4A = nil 72 | ``` 73 | 74 | Yukarıdaki örnekte en son aşamada instance'ları nil yaptığımızda, ARC bu instance'ları hafızadan silmez. Çünkü bu instance'lar birbirine strong reference oluşturmuştur. Bu durumda ARC'nin hafızayı serbest bırakabilmesi için, bu iki instance'ın birbirine strong reference oluşturmasını engellememiz gerekir. Çözüm için iki yol vardır. Weak ve Unowned Reference'lar. Burada bir instance'ın ömrü diğerine göre daha kısaysa Weak Reference, ömrü daha uzunsa Unowned Reference kullanılır. 75 | 76 | ## Weak Reference 77 | 78 | Weak Reference, instance'ı hafızada kalıp kalmadığını kontrol etmez ve instance bellekten silindiğinde otomatik olarak nil değeri alır. Weak referance için weak keyword'ünü kullanırız. Weak referance'lar her zaman optional'dır. Çünkü instance'ın hafızada kalıp kalmadığını kontrol etmez. Bu yüzden weak referance'lar her zaman optional'dır. 79 | 80 | ```swift 81 | class Person { 82 | let name: String 83 | weak var friend: Person? 84 | 85 | init(name: String) { 86 | self.name = name 87 | } 88 | 89 | deinit { 90 | print("\(name) deallocated") 91 | } 92 | } 93 | 94 | var john: Person? = Person(name: "John") 95 | var jane: Person? = Person(name: "Jane") 96 | 97 | john?.friend = jane 98 | jane?.friend = john 99 | 100 | john = nil 101 | jane = nil 102 | ``` 103 | 104 | ## Unowned Reference 105 | 106 | Unowned Reference, weak reference'tan farklı olarak nil değerini almadan bir referansın varlığını garanti eder ve bir referansın her zaman geçerli olduğunu varsayar. Bu referans türü, bir nesnenin ömrü boyunca sürekli olarak var olması gerektiği durumlarda kullanılır. 107 | 108 | ```swift 109 | class Person { 110 | let name: String 111 | unowned let bestFriend: Person 112 | 113 | init(name: String, bestFriend: Person) { 114 | self.name = name 115 | self.bestFriend = bestFriend 116 | } 117 | 118 | deinit { 119 | print("\(name) deallocated") 120 | } 121 | } 122 | 123 | var john: Person? = Person(name: "John", bestFriend: Person(name: "Jane", bestFriend: nil)) 124 | var jane: Person? = john?.bestFriend 125 | 126 | john = nil 127 | jane = nil 128 | ``` 129 | 130 | Unowned referanslar, referansların yaşam döngüsünün birbirine bağlı olduğu durumlarda kullanılır. Bellek yönetimi açısından weak'lerden farklıdır ve kullanırken dikkatli olunmalıdır. Eğer unowned bir referansın işaret ettiği instance bellekten silinirse, hata oluşabilir. Bu nedenle, kullanmadan önce referansın sürekli olarak geçerli olacağından emin olunmalıdır. 131 | 132 | ## Strong Reference Cycles for Closures 133 | 134 | Bir clouser içinde başka bir instance'a referans oluşturulduğunda ve bu instance'da clouser'a string bir şekilde referans oluşturduğunda strong reference cycle oluşur. Bu durumda, instance'lar birbirlerini hatırlar ve bellekte kalır, bu da hafıza sızıntısına yol açar. 135 | 136 | ```swift 137 | class Person { 138 | var name: String 139 | lazy var introduce: () -> String = { 140 | return "My name is \(self.name)" 141 | } 142 | 143 | init(name: String) { 144 | self.name = name 145 | } 146 | 147 | deinit { 148 | print("\(name) deallocated") 149 | } 150 | } 151 | 152 | var john: Person? = Person(name: "John") 153 | print(john?.introduce() ?? "") // "My name is John" 154 | 155 | john = nil 156 | ``` 157 | 158 | Yukarıdaki örnekte, Person adında bir class tanımlanmıştır. Bu class'ın name adında bir property'si ve introduce adında bir clouser'ı bulunur. Clouser, kendi adını ve name özelliğini kullanarak bir string döndürür. 159 | 160 | Person class'ının introduce clouser'ı, self keyword'üyle Person örneğine erişir. Bu durumda, clouser Person örneğine strong bir şekilde bağlıdır. 161 | 162 | Örnekte, john adında bir Person instance'ı oluşturulur ve introduce clouser'ı çağrılır. Bu durumda, clouser self.name ifadesine strong reference cycle oluşturarak john instance'ını hatırlar. 163 | 164 | Sonrasında john değişkeni nil olarak atanır. Bu durumda, referans sayısı sıfıra düştüğünde Person örneği bellekten otomatik olarak silinir. 165 | 166 | deinit metodu, bir instance bellekten silindiğinde çağrılır. Bu örnekte, deinit metodu çağrıldığında, silinen örneğin adını ekrana yazdırır. 167 | 168 | Bu örnekte, clouser içindeki self ifadesi, strong reference cycle'a neden olan bir referansa dönüşür. Bu tür bir durumda, bellek sızıntısı meydana gelebilir ve instance'ların beklenmedik bir şekilde bellekte kalmasına neden olabilir. 169 | 170 | Strong reference cycle durumunu önlemek için, weak veya unowned referansları kullanabiliriz. Bu, clouser'ın kendi içindeki self referansını string bir şekilde tutmamasını sağlar ve bellek sızıntısını önler. 171 | 172 | ```swift 173 | class Person { 174 | var name: String 175 | lazy var introduce: () -> String = { [weak self] in 176 | guard let self = self else { 177 | return "Person is deallocated" 178 | } 179 | return "My name is \(self.name)" 180 | } 181 | 182 | init(name: String) { 183 | self.name = name 184 | } 185 | 186 | deinit { 187 | print("\(name) deallocated") 188 | } 189 | } 190 | 191 | var john: Person? = Person(name: "John") 192 | print(john?.introduce() ?? "") // "My name is John" 193 | 194 | john = nil 195 | ``` 196 | 197 | introduce clouser'ı [weak self] ifadesi kullanılarak güncellenmiştir. Bu sayede clouser içinde self için zayıf bir referans oluşturulur. guard let ifadesi kullanılarak, clouser'ın çalışma zamanında self referansının nil olup olmadığı kontrol edilir. Eğer self nil ise, "Person is deallocated" mesajı döndürülür. Aksi takdirde, self güçlü hale getirilerek kullanılır ve clouser'ın çalışması devam eder. 198 | 199 | Bu değişiklik, clouser'ın kendisine güçlü bir şekilde referans oluşturmaktan kaçınarak referans döngüsünü önler ve bellek sızıntısını çözer. Artık Person örneği bellekten silindiğinde, introduce clouser'ı nil değeri döndürerek doğru bir mesaj döndürür ve bellek sızıntısı oluşmaz. 200 | 201 | Bu şekilde, weak referans kullanarak güçlü referans döngülerini çözebiliriz ve bellek yönetimini daha etkin hale getirebiliriz. 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /K-Initialization/1-Initialization.md: -------------------------------------------------------------------------------- 1 | ## Initilazition 2 | 3 | Initializers class, struct veya enumeration instance'larını oluşturmak için kullanılır. Swift'te initilazers bir değer döndürmez. Bir initilazer oluşturmak için: 4 | 5 | ```swift 6 | init() { 7 | // initializer implementation goes here 8 | } 9 | ``` 10 | 11 | Parametre eklemek gerekirse: 12 | 13 | ```swift 14 | init(param1: Int, param2: String) { 15 | // initializer implementation goes here 16 | } 17 | ``` 18 | 19 | Birden fazla initilazer oluşturmak için: 20 | 21 | ```swift 22 | struct Color { 23 | let red, green, blue: Double 24 | init(red: Double, green: Double, blue: Double) { 25 | self.red = red 26 | self.green = green 27 | self.blue = blue 28 | } 29 | init(white: Double) { 30 | red = white 31 | green = white 32 | blue = white 33 | } 34 | } 35 | ``` 36 | 37 | Argüman label'larınının yazılmasını engellemek için diğer yerlerde kullanıldı gibi _ kullanılabilir: 38 | 39 | ```swift 40 | struct Celsius { 41 | var temperatureInCelsius: Double 42 | init(fromFahrenheit fahrenheit: Double) { 43 | temperatureInCelsius = (fahrenheit - 32.0) / 1.8 44 | } 45 | init(fromKelvin kelvin: Double) { 46 | temperatureInCelsius = kelvin - 273.15 47 | } 48 | init(_ celsius: Double) { 49 | temperatureInCelsius = celsius 50 | } 51 | } 52 | let bodyTemperature = Celsius(37.0) 53 | // bodyTemperature.temperatureInCelsius is 37.0 54 | ``` 55 | 56 | Eğer optional bir değeri initilazer'da değer ataması yapmazsak otomatik olarak nil atanır. 57 | 58 | Bir constant değere initilazer'da atama yapabiliriz: 59 | 60 | ```swift 61 | class SurveyQuestion { 62 | let text: String 63 | var response: String? 64 | init(text: String) { 65 | self.text = text 66 | } 67 | func ask() { 68 | print(text) 69 | } 70 | } 71 | let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?") 72 | cheeseQuestion.ask() 73 | // Prints "Do you like cheese?" 74 | cheeseQuestion.response = "Yes, I do like cheese." 75 | 76 | //Daha sonrasında atama yapılamaz 77 | cheeseQuestion.text = "Something else" // Error 78 | ``` 79 | 80 | Bir class'ın içerisinde değişkenlere default değer atanırsa initilazer oluşturmak zorunda değiliz: 81 | 82 | ```swift 83 | class ShoppingListItem { 84 | var name: String? 85 | var quantity = 1 86 | var purchased = false 87 | } 88 | var item = ShoppingListItem() 89 | ``` 90 | 91 | Sturct'lar için initilazer'lar otomatik olarak oluşturulur: 92 | ```swift 93 | struct Size { 94 | var width = 0.0, height = 0.0 95 | } 96 | let twoByTwo = Size(width: 2.0, height: 2.0) 97 | ``` 98 | 99 | Swift'te initializer'lar ikiye ayrılır: designated ve convenience. 100 | 101 | ## Designated Initializers 102 | 103 | - Bir sınıfın temel başlatıcısıdır. 104 | - Tüm özellikleri (stored properties) başlatır veya başlatmaz. 105 | - Başka bir designated initializer'ı veya superclass'ın designated initializer'ını çağırabilir. 106 | - init kelimesiyle başlar. 107 | - İlgili nesnenin tam bir geçerli durumda olmasını sağlar. 108 | 109 | ```swift 110 | class Person { 111 | let name: String 112 | let age: Int 113 | 114 | init(name: String, age: Int) { 115 | self.name = name 116 | self.age = age 117 | } 118 | } 119 | ``` 120 | 121 | ## Convenience Initializers 122 | 123 | - Bir sınıfta (class) ekstra bir başlatıcı sağlar. 124 | - Designated initializer'ları veya diğer convenience initializer'ları çağırır. 125 | - Tüm özellikleri başlatmak zorunda değildir. 126 | - convenience init şeklinde tanımlanır. 127 | 128 | ```swift 129 | class Person { 130 | let name: String 131 | let age: Int 132 | 133 | init(name: String, age: Int) { 134 | self.name = name 135 | self.age = age 136 | } 137 | 138 | convenience init(name: String) { 139 | self.init(name: name, age: 0) 140 | } 141 | } 142 | ``` 143 | 144 | ## Initialization 2 Aşamalı Süreçtir 145 | 146 | Swift'te initilazer'lar 2 aşamalıdır. İlk aşamada tüm stored property'lerin değerleri atanır. İkinci aşamada ise inherited class'ların initilazer'ları çağırılır. Bu aşamada tüm stored property'lerin değerleri atanmış olmalıdır. 147 | 148 | ```swift 149 | class Vehicle { 150 | var numberOfWheels = 0 151 | var description: String { 152 | return "\(numberOfWheels) wheel(s)" 153 | } 154 | } 155 | 156 | let vehicle = Vehicle() 157 | print("Vehicle: \(vehicle.description)") 158 | // Vehicle: 0 wheel(s) 159 | ``` 160 | 161 | ```swift 162 | class Bicycle: Vehicle { 163 | override init() { 164 | super.init() 165 | numberOfWheels = 2 166 | } 167 | } 168 | 169 | let bicycle = Bicycle() 170 | print("Bicycle: \(bicycle.description)") 171 | // Bicycle: 2 wheel(s) 172 | ``` 173 | 174 | ```swift 175 | class Hoverboard: Vehicle { 176 | var color: String 177 | init(color: String) { 178 | self.color = color 179 | // super.init() implicitly called here 180 | } 181 | override var description: String { 182 | return "\(super.description) in a beautiful \(color)" 183 | } 184 | } 185 | 186 | let hoverboard = Hoverboard(color: "silver") 187 | print("Hoverboard: \(hoverboard.description)") 188 | // Hoverboard: 0 wheel(s) in a beautiful silver 189 | ``` 190 | 191 | Swift burada iki aşamalı initilazer'ın başlatılmasında hata olmadığından emin olmak için dört adet güvenlik önlemi alır: 192 | 193 | - Bir nesne önce tüm depolama alanlarını (stored properties) geçerli bir değerle başlatmalıdır. 194 | Bir nesnenin depolama alanları, uygun bir değerle başlatılmadan önce erişilemez durumdadır. Bu nedenle, initializer işlemi sırasında, bir nesne tüm depolama alanlarını geçerli bir değerle başlatmalıdır. Bu kurala uyulmadığında, derleme zamanında hata alırsınız. 195 | 196 | - Bir sınıfın designated initializer'ı, üst sınıfının designated initializer'ını çağırmalıdır. 197 | Bir sınıfın designated initializer'ı, üst sınıfının designated initializer'ını çağırmak zorundadır. Bu, sınıf hiyerarşisindeki tüm sınıfların geçerli bir durumda başlatılmış olmasını sağlar. Eğer üst sınıfın designated initializer'ı çağrılmazsa, derleme zamanında hata alırsınız. 198 | 199 | - Bir convenience initializer, aynı sınıftaki başka bir initializer'ı çağırmalıdır. 200 | Convenience initializer'lar, aynı sınıftaki başka bir initializer'ı çağırmak için kullanılmalıdır. Bu, initializer zincirlemesini sağlar ve tekrarlayan kodu önler. Convenience initializer, aynı sınıftaki başka bir initializer'ı çağırmazsa, derleme zamanında hata alırsınız. 201 | 202 | - Bir initializer, tüm işlemler tamamlandıktan sonra self referansını kullanabilir. 203 | Bir initializer, nesnenin depolama alanları ve diğer ayarlamaları tamamladıktan sonra self referansını kullanabilir. Bu nedenle, başka bir initializer çağrılmadan önce self referansını kullanmaya çalışırsanız, derleme zamanında hata alırsınız. 204 | 205 | 206 | ## İki Aşamadan Oluşan Initialization Süreci 207 | 208 | İlk aşama sırasıyla: 209 | 210 | - Bir class'ta belirlenmiş initializer çağırılır. 211 | 212 | - Bir bellek alanı oluşturulur ancak henüz başlatılmaz. 213 | 214 | - Designated initializer tüm özelliklerin bir değere sahip olduğunu onaylar ve bellek alanını başlatır. 215 | 216 | - Designated initializer, üst sınıfın designated initializer'ını çağırır. Bu işlem inheritance zincirini takip ederek en üst sınıfa kadar devam eder. 217 | 218 | - Zincirin en üstünde bulunan class'ında bir değere sahip olması sağlandığında 1. aşamanın tamamlandığı kabul edilir. 219 | 220 | İkinci aşama sırasıyla: 221 | 222 | - Inheritence zincirinin tepesinden aşağıya doğru her class'ın convenience initializer'ları çağırılır. Artık class'lar self referansını kullanabilir. 223 | 224 | - Son olarak en alttaki class'ın convenience initializer'ı çağırılır. 225 | 226 | 227 | ## Otomatik Initializer'lar 228 | 229 | Default olarak subclasslar superclass'ların initializer'larını inherit edemezler. Ancak bazı durumlarda subclass'ların içerisinde superclass'ların initializer'ları otomatik oluşur. Bu durumlar: 230 | 231 | - Subclass'ta herhangi bir initializer tanımlanmamışsa. 232 | 233 | - Subclass superclass'ta belirlenen tüm initializer'ları implement etmişse. 234 | 235 | Örneğin: 236 | 237 | ```swift 238 | class Vehicle { 239 | var numberOfWheels: Int 240 | 241 | init(numberOfWheels: Int) { 242 | self.numberOfWheels = numberOfWheels 243 | } 244 | 245 | convenience init() { 246 | self.init(numberOfWheels: 4) 247 | } 248 | } 249 | 250 | class Car: Vehicle { 251 | var brand: String 252 | 253 | init(brand: String, numberOfWheels: Int) { 254 | self.brand = brand 255 | super.init(numberOfWheels: numberOfWheels) 256 | } 257 | } 258 | ``` 259 | 260 | Car sınıfı, üst sınıf olan Vehicle'ın designated initializer'ını override ederek kendi designated initializer'ını tanımlar. Ancak, convenience initializer'ı tanımlamaz. 261 | 262 | Durum 2'ye göre, Car sınıfı, Vehicle sınıfının tüm designated initializer'larının bir implementasyonunu sağladığı için, Vehicle'ın convenience initializer'ını da otomatik olarak miras alır. Yani Car sınıfı aşağıdaki gibi bir şekilde oluşturulabilir: 263 | 264 | ```swift 265 | let car = Car() 266 | print(car.numberOfWheels) // Output: 4 267 | ``` 268 | 269 | ## Required Initializer'lar 270 | 271 | Bir superclass'ta subclass'ların implement etmesi gereken bir initializer varsa bunu required olarak belirlemek gerekir. Subclass'larda required olan bir initializer'ı override etmek için override anahtar kelimesini yazmaya gerek yoktur. 272 | 273 | ```swift 274 | class SomeClass { 275 | required init() { 276 | 277 | } 278 | } 279 | class SomeSubclass: SomeClass { 280 | required init() { 281 | // direkt olarak bu şekilde override edilebilir. 282 | } 283 | } 284 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | # Swift Notlarım 6 | 7 | Merhaba, hoş geldiniz. Bu repo'da Swift öğrenirken geriye dönüp bakabilmek amacıyla notlarımı tutuyorum. Başta sadece kendime özel olarak dizayn ettiğim bu notları daha sonrasında sizlerle de paylaşmak istedim. Notların ağırlığı Swift'in resmi dökümantasyonundan yola çıkılarak hazırlanmış olup ek olarak merak edip araştırdığım konuları da içermektedir. Umarım sizlere faydası dokunur. 8 | 9 | Şu konuyu da söylemeden geçmeyeyim. Notların bütününü tamamen kendime göre dizayn ettim. Yani aradığınız her bilgiyi bulamayabilirsiniz. Zaten öğrenmek istediğiniz spesifik bir konu olursa da resmi dökümantasyonu okumanızı tavsiye ederim. Bu notlar sadece bir rehber niteliğindedir. 10 | 11 | Eğer mobil uygulama geliştirmekle ilgileniyorsanız, sizin gibi Swift/iOS Developer'lar ile buluşabileceğiniz bir topluluk inşa ediyoruz. Farklı alanlardaki mobil geliştiriciler ile bir araya gelebilir, sorularınızı sorabilir ve network kazanabilirsiniz. [Topluluk Discord sunucumuza katılmak için tıklayın.](https://discord.gg/2Zp9DzVYjx) 12 | 13 | ## İçindekiler 14 | 15 | - [Temeller](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/A-Temeller) 16 | - [Değişkenler](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/A-Temeller/1-De%C4%9Fi%C5%9Fkenler) 17 | - [Değişkenlere Giriş](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/1-De%C4%9Fi%C5%9Fkenler/1-De%C4%9Fi%C5%9Fkenler%20Giri%C5%9F.md) 18 | - [Integer](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/1-De%C4%9Fi%C5%9Fkenler/2-Integer.md) 19 | - [Tür Dönüşümleri](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/1-De%C4%9Fi%C5%9Fkenler/3-T%C3%BCr%20d%C3%B6n%C3%BC%C5%9F%C3%BCmleri.md) 20 | - [Touples](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/1-De%C4%9Fi%C5%9Fkenler/4-Touples.md) 21 | - [Optionals](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/1-De%C4%9Fi%C5%9Fkenler/5-Optionals.md) 22 | - [String](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/1-De%C4%9Fi%C5%9Fkenler/6-String.md) 23 | - [Any ve AnyObject](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/1-De%C4%9Fi%C5%9Fkenler/7-Any%20ve%20AnyObject.md) 24 | - [Operatörler](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/A-Temeller/2-Operat%C3%B6rler) 25 | - [Operatörlere Giriş](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/2-Operat%C3%B6rler/1-Operat%C3%B6rlere%20Giri%C5%9F.md) 26 | - [Guard](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/2-Operat%C3%B6rler/2-Guard.md) 27 | - [Defer](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/2-Operat%C3%B6rler/3-Defer.md) 28 | - [Available](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/2-Operat%C3%B6rler/4-Available.md) 29 | - [Standartlar](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/A-Temeller/3-Standartlar) 30 | - [Karşılaştırmalar](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/3-Standartlar/1-%20Kar%C5%9F%C4%B1la%C5%9Ft%C4%B1rmalar.md) 31 | - [For Loop](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/3-Standartlar/2-For%20Loop.md) 32 | - [If Statements](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/3-Standartlar/3-%20%C4%B0f%20statements.md) 33 | - [Switch](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/3-Standartlar/4-%20Switch.md) 34 | - [Labeled Statements](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/3-Standartlar/5-Labeled%20Statements.md) 35 | - [Ekstralar](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/A-Temeller/4-Ekstralar) 36 | - [Value ve Reference Types Kavramı](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/A-Temeller/4-Ekstralar/1-%20Value%20ve%20Reference%20Types%20Kavram%C4%B1.md) 37 | 38 | - [Collections](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/B-Collections) 39 | - [Array](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/B-Collections/1-Array.md) 40 | - [Sets](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/B-Collections/2-Sets.md) 41 | - [Dictionaries](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/B-Collections/3-Dictionaries.md) 42 | - [Map-CompactMap](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/B-Collections/4-Map-CompactMap.md) 43 | - [Flatmap ve Reduce](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/B-Collections/5-Flatmap%20ve%20Reduce.md) 44 | 45 | - [Fonksiyonlar](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/C-Fonksiyonlar) 46 | - [Değer Döndüren Fonksiyonlar](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/C-Fonksiyonlar/1-De%C4%9Fer%20D%C3%B6nd%C3%BCren%20Fonksiyonlar.md) 47 | - [Parametreler](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/C-Fonksiyonlar/2-Parametreler.md) 48 | - [Function Types](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/C-Fonksiyonlar/3-Function%20Types.md) 49 | 50 | - [Closure](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/D-Closure/1-Closure.md) 51 | 52 | - [Enumeration](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/E-Enumeration/1-Enumeration.md) 53 | 54 | - [Struct & Class](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/F-Struct%20%26%20Class) 55 | - [Class](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/F-Struct%20%26%20Class/1-Class.md) 56 | - [Struct](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/F-Struct%20%26%20Class/2-Struct.md) 57 | - [Encapsulation](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/F-Struct%20&%20Class/3-Encapsulation.md) 58 | - [Class & Struct Farklılıkları](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/F-Struct%20%26%20Class/4-Aras%C4%B1ndaki%20Farkl%C4%B1l%C4%B1klar.md) 59 | - [Ne zaman Struct - Ne zaman Class](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/F-Struct%20%26%20Class/5-Ne%20Zaman%20Struct%20-%20Ne%20Zaman%20Class.md) 60 | 61 | - [Properties](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/G-Properties) 62 | - [Properties Giriş](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/G-Properties/1-Properties.md) 63 | - [Property Observers](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/G-Properties/2-Property%20Observers.md) 64 | - [Property Wrappers](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/G-Properties/3-Property%20Wrappers.md) 65 | - [Type Properties](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/G-Properties/4-Type%20Properties.md) 66 | 67 | - [Methods](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/H-Methods/1-Methods.md) 68 | 69 | - [Subscripts](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/I-Subscripts/1-Subscripts.md) 70 | 71 | - [Inheritence](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/J-Inheritance) 72 | - [Inheritence Giriş](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/J-Inheritance/1-Inheritance.md) 73 | - [Override](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/J-Inheritance/2-Override.md) 74 | 75 | - [Initialization](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/K-Initialization) 76 | - [Initialization Giriş](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/K-Initialization/1-Initialization.md) 77 | - [Initilazer Delegation](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/K-Initialization/2-Initializer%20Delegation.md) 78 | - [Initializer Overriding](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/K-Initialization/3-Initializer%20Overriding.md) 79 | - [Failable Initializers](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/K-Initialization/4-Failable%20Initializers.md) 80 | - [Deinit](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/K-Initialization/5-Deinit.md) 81 | 82 | - [Optional Chaining](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/L-Optional%20Chaining/1-Optional%20Chaining.md) 83 | 84 | - [Error Handling](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/M-Error%20Handling/1-Error%20Handling.md) 85 | 86 | - [Concurrency](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/N-Concurrency) 87 | - [Concurrency Giriş](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/N-Concurrency/1-Concurrency.md) 88 | - [Async Sequence](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/N-Concurrency/2-Async%20Sequence.md) 89 | - [Unstructured Concurrency](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/N-Concurrency/3-Unstructured%20Concurrency.md) 90 | - [Actors](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/N-Concurrency/4-Actors.md) 91 | - [Sendable Types](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/N-Concurrency/5-Sendable%20Types.md) 92 | 93 | - [Macros](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/O-Macros) 94 | - [Macros Giriş](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/O-Macros/1-Macros.md) 95 | - [AST](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/O-Macros/2-AST.md) 96 | 97 | - [Types](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/P-Types) 98 | - [Type Casting](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/P-Types/1-Type%20Casting.md) 99 | - [Nested Types](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/P-Types/2-Nested%20Types.md) 100 | - [Opaque & Boxed Types](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/P-Types/3-Opaque%20%26%20Boxed%20Types.md) 101 | 102 | - [Extensions](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/R-Extensions/1-Extensions.md) 103 | 104 | - [Protocols](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/S-Protocols) 105 | - [Protocols Giriş](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/S-Protocols/1-Protocols.md) 106 | - [Delegation](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/S-Protocols/2-Delegation.md) 107 | - [Standart Protocols](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/S-Protocols/3-Standart%20Protocols.md) 108 | 109 | - [Generics](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/T-Generics/1-Generics.md) 110 | 111 | - [Memory](https://github.com/DogukanSakin/SwiftNotlarim/tree/main/U-Memory) 112 | - [ARC](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/U-Memory/1-ARC.md) 113 | - [Memory Safety](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/U-Memory/2-Memory%20Safety.md) 114 | 115 | - [Access Control](https://github.com/DogukanSakin/SwiftNotlarim/blob/main/V-Access%20Control/1-%20Access%20Control.md) 116 | 117 | 118 | 119 | --------------------------------------------------------------------------------