Short notes about Swift
Variables
-
Değişkenler için
, constant içinvar
kullan.let
1var age = 24 2let PI = 3.14159
-
Temel değerlerin tipler type inference ile otomatik algılanır. Ancak initialize edilmiyorsa type annotation verilmelidir.
1let year = 1999 2let year: Int = 1999 3var name: String 4name = "Enes"
Data Types
String
1var name = "Enes"
-
Çok satır metinler için üç tırnak kullan. Yeni satıra inmesini engellemek için satır sonuna
ekle.\
1var address = """ 2Y Mahallesi \ 3X Sokak No:1 Kat:5 4Kadıköy/Türkiye 5"""
Y Mahallesi X Sokak No:1 Kat:5 Kadıköy/Türkiye
-
Dinamik string'ler için string interpolation kullan.
1// example 1: 2var score = 85 3var str = "Your score was \(score)" 4// example 2: 5var greeting = "Hi, \(user ?? "Anonymous")"
-
String'in boş olup olmadığını kontrol etmek için
kullan..isEmpty()
Integer
1var age = 24
2var population = 8_000_000
Float and Double
1let justOverOneMillion = 1_000_000.000_000_1
2let PI: Float = 3.14159
- Varsayılan noktalı değer tipi Double'dır. Float oluşturmak için tip tanımlamalıyız.
- Int bir değerle toplarken otomatik tür dönüşümü yapılmaz. Bunu yerine Double() kullanılabilir.
1let num1 = 1.2 2let num2 = 5 3print(num1 + Double(num2))
Boolean
1var isSuccess = true
6.2
Collections
Array
1var emptyArray = [Int]()
2var emptyArray2: [Int] = []
3var emptyArray3: Array<Float> = Array()
4var emptyArray4 = Array<Int>()
5let beatles = ["John Lennon", "Paul McCartney", "George Harrison", "Ringo Starr"]
6let numbers: [Int] = [1, 10, 5, 7]
-
Array annotation'ları
ve[String]
gibi tanımlanabilir.[Boolean]
-
Değer okunurken köşeli parantez kullanımı uygulanır ve yoksa hata verir.
1let beatles = ["John Lennon", "Paul McCartney", "George Harrison", "Ringo Starr"] 2beatles[1] 3beatles[12] // crash verir
-
Sona değer eklemek için
metodu kullanılır. Birden fazla değer eklemek içinappend
parametresi kullanılır. Belirli indekse eleman eklemek istersekcontentsOf
metodu kullanılır.insert
1var students = ["Ben", "Ivy", "Jordell"] 2students.append("Maxime") 3students.append(contentsOf: ["Shakia", "William"]) 4students.insert("Liam", at: 3) 5print(students)
["Ben", "Ivy", "Jordell", "Liam", "Maxime", "Shakia", "William"]
-
Eleman silmek için
veremove
kullanılır.removeLast
1students.remove(at: 0) 2students.removeLast() 3print(students)
["Ivy", "Jordell", "Liam", "Maxime", "Shakia"]
-
Array'in slice etmek için range operatör kullanılabilir.
1let names = ["Piper", "Alex", "Suzanne", "Gloria"] 2print(names[1...3]) 3print(names[2...])
["Alex", "Suzanne", "Gloria"] ["Suzanne", "Gloria"]
-
İki array'i birleştirmek için artı operatörü kullanılabilir. Bu operator overloading olarak geçer.
1let firstHalf = ["John", "Paul"] 2let secondHalf = ["George", "Ringo"] 3let beatles = firstHalf + secondHalf
Set
1var emptySet1 = Set<String>()
2var emptySet2: Set<String> = Set()
3let colors = Set(["red", "green", "blue", "red", "blue"])
4print(colors)
["red", "green", "blue"]
- Unordered'dır ve öğeler benzersizdir. Bu sayede arama işlemleri çok hızlı gerçekleşir.
- Tanımlamak için
fonksiyonu kullanılır.Set()
Tuple
1let name = (first: "Taylor", last: "Swift")
- Birkaç değeri tek değerde saklamanıza izin verir.
- Boyutu sabittir yani öğe eklenemez ve çıkarılamaz. Ancak değerler değiştirilebilir.
- Dictionary'den farklı olarak bir değerin var olduğu garantidir ve boyutu büyüyemez.
- Erişmek için index ve key kullanılır.
1print(name.0) 2print(name.first)
Dictionary
1var emptyDict1 = [String: String]()
2var emptyDict2: [String: String] = [:]
3var emptyDict3 = Dictionary<String, Int>()
4let person = [
5 "name": "Enes Başpınar",
6 "aeg": 24
7]
8var responseMessages = [
9 200: "OK",
10 403: "Access forbidden",
11 404: "File not found",
12 500: "Internal server error"
13]
- Değer okunurken key yoksa
yerine varsayılan değer döndürülebilir.nil
1favoriteIceCream["Charlotte", default: "Unknown"]
Enum(eration)
1enum Result {
2 case success
3 case failure
4}
-
İlişkili değerleri bir arada tutar.
-
Değer olarak kullanırken tip tanımlanmışsa
ismini kullanmaya gerek yoktur.enum
1var result: Result = Result.success; 2var result2: Result = .success;
-
Enum değerlerine raw index ile de erişebiliriz.
1enum Planet: Int { 2 case mercury = 1 3 case venus 4 case earth 5 case mars 6} 7 8let earth = Planet(rawValue: 3)
-
Enum değerleri ilişkili değerleri de depolayabilir.
1enum Activity { 2 case bored 3 case running(destination: String) 4 case talking(topic: String) 5 case singing(volume: Int) 6} 7 8let talking = Activity.talking(topic: "football")
-
Enum değerlerini karşılaştırılabilir hale getirmek için
protokolü kullanılabilir.Comparable
1enum Sizes: Comparable { 2 case small 3 case medium 4 case large 5} 6 7print(Sizes.small < Sizes.large)
Conditions
- String'lerde alfabetik sıra olduğu için büyüktür küçüktür kullanılabilir. Örneğin
."Taylor" <= "Swift"
If else
1let firstCard = 11
2let secondCard = 10
3
4if firstCard + secondCard == 2 {
5 print("Aces – lucky!")
6} else if firstCard + secondCard == 21 {
7 print("Blackjack!")
8} else {
9 print("Regular cards")
10}
Ternary operator
1print(isLoggedIn ? "Welcome." : "Please login.")
Switch
1switch weather {
2case "rain":
3 print("Bring an umbrella")
4case "snow":
5 print("Wrap up warm")
6case "sunny":
7 print("Wear sunscreen")
8 fallthrough
9default:
10 print("Enjoy your day!")
11}
-
Eğer altındaki case'e devam etmesi için
kullanılabilir.fallthrough
-
Belirli değer aralığında mı diye kontrol etmek için
operatör kullanılabilir.range
ve1..<5
arasındaki fark son değerin dahil edilip edilmediğidir.1...5
1let score = 85 2 3switch score { 4case 0..<50: 5 print("You failed badly.") 6case 50..<85: 7 print("You did OK.") 8default: 9 print("You did great!") 10}
Loops
For
1// example 1:
2for number in 1...5 {
3 print("Number is \(number)")
4}
5// example 2:
6let names = ["Sterling", "Cyril", "Lana", "Ray", "Pam"]
7for _ in names {
8 print("[CENSORED] is a secret agent!")
9}
-
Array iterate etmek için
opeatörü kullanılabilir.in
1let albums = ["Red", "1989", "Reputation"] 2 3for album in albums { 4 print("\(album) is on Apple Music") 5}
While
1var number = 1
2
3while number <= 4 {
4 print(number)
5 number += 1
6}
1
2
3
4
Repeat (aka Do-While)
1var number = 1
2
3repeat {
4 print(number)
5 number += 1
6} while number < 1
1
Functions
1func square(number: Int) -> Int {
2 return number * number
3}
4
5let result = square(number: 8)
-
Fonksiyon tek bir ifade içeriyorsa
atlanabilir.return
1func isUppercase(string: String) -> Bool { 2 string == string.uppercased() 3} 4 5func greet(name: String) -> String { 6 name == "Taylor Swift" ? "Oh wow!" : "Hello, \(name)" 7}
-
Birden çok değer döndürmek istiyorsak tuple kullanabiliriz.
1func getUser() -> (firstName: String, lastName: String) { 2 return (firstName: "Taylor", lastName: "Swift") 3 // ya da return ("Taylor", "Swift") 4} 5 6let (firstName, lastName) = getUser() 7print("Name: \(firstName) \(lastName)")
Name: Taylor Swift
-
Parametrelere fonksiyon çalıştırırken kullanmak üzere label atayabiliriz.
1func sayHello(to name: String) { 2 print("Hello, \(name)!") 3} 4 5sayHello(to: "Taylor")
Hello, Taylor!
-
Parametre label'ını es geçmek için
kullanılabilir._
1func greet(_ person: String, nicely: Bool = true) { 2 if nicely == true { 3 print("Hello, \(person)!") 4 } else { 5 print("Oh no, it's \(person) again...") 6 } 7} 8 9greet("Taylor") 10greet("Taylor", nicely: false)
Hello, Taylor! Oh no, it's Taylor again...
-
Variadic fonksiyon parametresi tanımlamak için tipinin sonuna
eklenir. Parametre gönderilmezse değeri...
olur.[]
1func square(_ numbers: Int...) { 2 for number in numbers { 3 print("\(number) squared is \(number * number)") 4 } 5} 6 7square(1, 2, 3, 4, 5)
1 squared is 1 2 squared is 4 3 squared is 9 4 squared is 16 5 squared is 25
-
Fonksiyon çalışırken hata fırlatmak için
keyword kullanılabilir.throws
1enum LoginErrors: Error { 2 case badUsername 3 case badPassword 4} 5 6func login(username: String, password: String) throws -> Bool { 7 if username.isEmpty { throw LoginErrors.badUsername } 8 if password.isEmpty { throw LoginErrors.badPassword } 9 return true 10}
-
Fonksiyon parametreleri constant'tır. Parametre değiştiğinde orjinalinin de değişmesini istersek
anahtar kelimesi kullanabiliriz.inout
1func doubleInPlace(number: inout Int) { 2 return number *= 2 3} 4 5var myNum = 10 6doubleInPlace(number: &myNum) 7print(myNum)
20
Closure
1{ (parameters) -> returnType in
2 // statements
3}
-
İsmi olmayan özel bir fonksiyon türüdür.
-
Değişkene atanabilir.
1var greet = { 2 print("Hello, World!") 3} 4greet()
-
Parametre alabilir. Fonksiyondan farklı olarak çağırırken parametre adını vermek gerekmez.
1let greetUser = { (name: String) in 2 print("Hey there, \(name).") 3} 4 5greetUser("Delilah")
-
Değer döndürebilir.
1// usage 1: 2var findSquare = { (num: Int) -> (Int) in 3 var square = num * num 4 return square 5} 6 7// usage 2: 8var findSquare = { (num: Int) -> Int in num * num } 9 10// usage 3: 11var findSquare: (Int) -> Int = { num in num * num } 12 13// usage 4: 14var findSquare: (Int) -> Int = { $0 * $0 } 15 16var result = findSquare(3)
-
Başka fonksiyona parametre olarak iletilebilir.
1func grabLunch(search: () -> ()) { 2 search() 3} 4 5grabLunch(search: { 6 print("Alfredo's Pizza: 2 miles away") 7})
-
Fonksiyonun son parametresi closure ise trailing closure dediğimiz özel sözdizimi kullanabilir.
1func grabLunch(message: String = "", search: () -> ()) { 2 if (message != "") { 3 print(message) 4 } 5 search() 6} 7 8grabLunch(message:"Let's go out for lunch") { 9 print("Alfredo's Pizza: 2 miles away") 10} 11 12grabLunch { 13 print("Alfredo's Pizza: 2 miles away") 14}
Let's go out for lunch Alfredo's Pizza: 2 miles away
-
Referans tiplidir.
-
Tanımlandığı bağlamda bulunan değişkenlerin referanslarını saklar.
1func travel() -> (String) -> Void { 2 var counter = 1 3 4 return { 5 print("\(counter). I'm going to \($0)") 6 counter += 1 7 } 8} 9 10let makeTravel = travel() 11makeTravel("London") 12makeTravel("London") 13makeTravel("London")
Error handling
-
Hata fırlatabilecek bir kod çalıştıracaksak
bloğu içinde kullanmalıyız. Hata fırlatabilecek fonksiyonun başınado
konur. Hata fırlattığındatry
'e düşer.catch
1enum PasswordError: Error { 2 case obvious 3} 4 5func checkPassword(_ password: String) throws -> Bool { 6 if password == "password" { 7 throw PasswordError.obvious 8 } 9 10 return true 11} 12 13do { 14 try checkPassword("password") 15 print("That password is good!") 16} catch { 17 print("You can't use that password.") 18}
-
Başarısız olduğunda
dönmesini isterseniznil
kullanabilirsiniz.try?
1if let result = try? checkPassword("password") { 2 print("Result was \(result)") 3} else { 4 print("D'oh.") 5}
Struct
-
Özel değişken tipi oluşturmanın en yaygın yoludur.
1struct Sport { 2 var name: String 3} 4 5var tennis = Sport(name: "Tennis") 6print(tennis.name) 7tennis.name = "Lawn tennis" 8print(tennis.name)
Tennis Lawn tennis
Initializer
-
Varsayılan olarak memberwise initializer ile gelir. Manuel işlemek için
kullanabiliriz.init()
-
mevcut instance'a işaret eder.self
haricinde kullanmamalıyız.init
1// usage 1: memberwise 2struct Employee { 3 var name: String 4 var yearsActive = 0 5} 6 7let roslin = Employee(name: "Laura Roslin") 8let adama = Employee(name: "William Adama", yearsActive: 45) 9 10// usage 2: 11struct Employee { 12 var name: String 13 var yearsActive = 0 14 15 init() { 16 self.name = "Anonymous" 17 print("Creating an anonymous employee…") 18 } 19} 20 21var roslin = Employee() 22roslin.name = "Laura Roslin" 23 24// usage 3: 25struct Employee { 26 var name: String 27 var yearsActive = 0 28 29 init(name: String) { 30 self.name = name 31 } 32} 33 34var roslin = Employee(name: "Laura Roslin")
Creating a new user!
Property
-
Eğer bir property'nin ilk erişildiğinde hesaplanmasını istiyorsak
anahtar kelimesini kullanabiliriz. Hesaplama maliyeti nesne oluşturulurken atlanmış olur. Sonraki her çağrılışta hesaplanan sonucu bellekten döndürür.lazy
1struct FamilyTree { 2 init() { 3 print("Creating family tree!") 4 } 5} 6 7struct Person { 8 var name: String 9 lazy var familyTree = FamilyTree() 10 11 init(name: String) { 12 self.name = name 13 } 14} 15 16let ed = Person(name: "Ed") 17let edFamilyTree = ed.familyTree
Creating family tree!
Computed property
-
Başka bir property değerine göre hesaplanan property'lerdir. Ağır hesaplamalar için metod kullanmak daha iyidir.
1struct Sport { 2 var name: String 3 var isOlympicSport: Bool 4 5 var olympicStatus: String { 6 return isOlympicSport ? "\(name) is an Olympic sport" : "\(name) is not an Olympic sport" 7 } 8 9 func play() { 10 // ... 11 } 12} 13 14let chessBoxing = Sport(name: "Chessboxing", isOlympicSport: false) 15print(chessBoxing.olympicStatus)
Static property
1struct Student {
2 static var classSize = 0
3 var name: String
4
5 init(name: String) {
6 self.name = name
7 Student.classSize += 1
8 }
9}
10let ed = Student(name: "Ed")
11let taylor = Student(name: "Taylor")
12print(Student.classSize)
2
Property observe
-
Değeri değiştiğinde ve değişmeden önce bir işlem gerçekleştirmek için
vedidSet
kullanılır.willSet
1struct Progress { 2 var task: String 3 var amount: Int { 4 didSet { 5 print("\(task) is now \(amount)% complete") 6 } 7 } 8} 9 10var progress = Progress(task: "Loading data", amount: 0) 11progress.amount = 30 12progress.amount = 80 13progress.amount = 100
Loading data is now 30% complete Loading data is now 80% complete Loading data is now 100% complete
Mutating
-
Varsayılan olarak metotların içinde property değiştirilemez yani constant struct'tır. Buna izin vermek için
anahtar kelimesi kullanılır.mutating
1struct Person { 2 var name: String 3 4 mutating func makeAnonymous() { 5 name = "Anonymous" 6 } 7} 8 9var person = Person(name: "Ed") 10person.makeAnonymous()
Access control
-
vepublic
property ve metodlara nereden erişilebileceğini tanımlar.private
1struct Person { 2 private var id: String 3 4 init(id: String) { 5 self.id = id 6 } 7 8 func identify() -> String { 9 return "My social security number is \(id)" 10 } 11}
Class
1class Dog {
2 var name: String
3 var breed: String
4
5 init(name: String, breed: String) {
6 self.name = name
7 self.breed = breed
8 }
9}
10
11let poppy = Dog(name: "Poppy", breed: "Poodle")
-
Referans tiplidirler yani instance'ların referansı aynıdır.
-
Inheritance yapmak için ilgili sınıf annotation ile belirtilebilir.
1class Dog { 2 var name: String 3 var breed: String 4 5 init(name: String, breed: String) { 6 self.name = name 7 self.breed = breed 8 } 9} 10 11class Poodle: Dog { 12 init(name: String) { 13 super.init(name: name, breed: "Poodle") 14 } 15}
-
Inherit edilmemesini istediğimiz fonksiyonları
ile tanımlayabiliriz. Kritik bir şey yapıyorsanız override edilmemesi için bunu uygulayabilirsiniz.final
-
Metodu override etmek için
anahtar kelimesi kullanılır.override
1class Dog { 2 func makeNoise() { 3 print("Woof!") 4 } 5} 6 7class Poodle: Dog { 8 override func makeNoise() { 9 print("Yip!") 10 } 11} 12 13let poppy = Poodle() 14poppy.makeNoise()
Yip!
-
Nesne yok edildiğinde bir işlem yapmak için deinitializer tanımlanabilir.
1class Person { 2 var name = "John Doe" 3 4 init() { 5 print("\(name) is alive!") 6 } 7 8 deinit { 9 print("\(name) is no more!") 10 } 11 12 func printGreeting() { 13 print("Hello, I'm \(name)") 14 } 15} 16 17for _ in 1...3 { 18 let person = Person() 19 person.printGreeting() 20}
John Doe is alive! Hello, I'm John Doe John Doe is no more! John Doe is alive! Hello, I'm John Doe John Doe is no more! John Doe is alive! Hello, I'm John Doe John Doe is no more!
-
Sınıf sabit olarak oluşturulduğunda bile bir sınıf üzerindeki property'ler değiştirebilir. Dolayısıyla
anahtar kelimesine ihtiyacı yok.mutating
-
Bir property'nin immutable olması için
ile constant olarak tanımlanabilir.let
Protocol
-
Bir şeyin hangi property ve metodlara sahip olması gerektiğini tanımlar. Java interface'lerine çok benzerdir.
1protocol Purchaseable { 2 var name: String { get set } 3} 4 5struct Book: Purchaseable { 6 var name: String 7 var author: String 8} 9 10struct Movie: Purchaseable { 11 var name: String 12 var actors: [String] 13} 14 15struct Car: Purchaseable { 16 var name: String 17 var manufacturer: String 18} 19 20func buy(_ item: Purchaseable) { 21 print("I'm buying \(item.name)") 22}
-
Protocol'lerde inheritance destekler.
1// bad usage: 2protocol Computer { 3 var price: Double { get set } 4 var weight: Int { get set } 5 var cpu: String { get set } 6 var memory: Int { get set } 7 var storage: Int { get set } 8} 9 10protocol Laptop { 11 var price: Double { get set } 12 var weight: Int { get set } 13 var cpu: String { get set } 14 var memory: Int { get set } 15 var storage: Int { get set } 16 var screenSize: Int { get set } 17} 18 19// good usage: 20protocol Product { 21 var price: Double { get set } 22 var weight: Int { get set } 23} 24 25protocol Computer: Product { 26 var cpu: String { get set } 27 var memory: Int { get set } 28 var storage: Int { get set } 29} 30 31protocol Laptop: Computer { 32 var screenSize: Int { get set } 33}
Extension
-
Orjinalini bozmadan mevcuttaki tiplere ekstra metodlar eklemenize izin verir.
1extension Int { 2 var isEven: Bool { 3 return self % 2 == 0 4 } 5 6 func squared() -> Int { 7 return self * self 8 } 9} 10 11let number = 8 12print(number.squared()) 13print(number.isEven)
-
Protokoldeki metodlara varsayılan implementasyon vermek için protocol extension kullanılabilir. Protocol inherit eden her yeri etkiler.
1extension Collection { 2 func summarize() { 3 print("There are \(count) of us:") 4 5 for name in self { 6 print(name) 7 } 8 } 9} 10 11let pythons = ["Eric", "Graham", "John", "Michael", "Terry", "Terry"] 12let beatles = Set(["John", "Paul", "George", "Ringo"]) 13 14pythons.summarize() 15beatles.summarize()
Optionals
-
Bir değerin olmayabileceğini (
) belirtir.nil
1var age: Int? = nil 2age = 38
-
Optional değerler direk kullanılmaz ve unwrapping yapmak gerekir.
veif let
ile yapılabilir:guard let
1func getUsername() -> String? { "Taylor" } 2 3if let username = getUsername() { 4 print("Username is \(username)") 5} else { 6 print("No username") 7}
1func greet(_ name: String?) { 2 guard let unwrapped = name else { 3 print("You didn't provide a name!") 4 return 5 } 6 7 print("Hello, \(unwrapped)!") 8}
-
Bazen bir değerin nil olmadığından eminsinizdir. Bu durumda force unwrapping kullanılabilir.
aynı zamanda crash operator olara isimlendirilir.!
1// usage 1: 2enum Direction: CaseIterable { 3 case north, south, east, west 4} 5let randomDirection = Direction.allCases.randomElement()! 6 7// usage 2: 8enum Direction: CaseIterable { 9 case north, south, east, west 10 11 static func random() -> Direction { 12 Direction.allCases.randomElement()! 13 } 14} 15let randomDirection = Direction.allCases.randomElement()!
-
Bir değerin sadece tanımlarken nil olduğunu ancak kullanırken her zaman dolu olacağını biliyorsak direk unwrapped optional olarak tanımlayabiliriz.
1let age: Int! = nil
-
Değer nil olduğunda varsayılan belirtmek için
kullanılır. Birden fazla zincirlenebilir.nil coalescing
1func username(for id: Int) -> String? { 2 return id == 1 ? "Taylor Swift" : nil 3} 4 5let user = username(for: 15) ?? "Anonymous"
-
Nil olabilecek bir nesneden değer okuyacaksak crash almamak için
kullanılabilir.optional chaining
1let names = ["Vincent": "van Gogh", "Pablo": "Picasso", "Claude": "Monet"] 2let surnameLetter = names["Vincent"]?.first?.uppercased()
-
Initializer'da nesne oluşturma enasında problem yaşadığınızda nil dönmek isterseniz
kullanabilirsiniz.init?
1struct Employee { 2 var username: String 3 var password: String 4 5 init?(username: String, password: String) { 6 guard password.count >= 8 else { return nil } 7 guard password.lowercased() != "password" else { return nil } 8 9 self.username = username 10 self.password = password 11 } 12}