2015-08-22 18:31:39 +03:00
---
language: swift
contributors:
- ["Özgür Şahin", "https://github.com/ozgurshn/"]
filename: learnswift.swift
2015-10-04 22:01:10 +03:00
lang: tr-tr
2015-08-22 18:31:39 +03:00
---
Swift iOS ve OSX platformları nda geliştirme yapmak için Apple tarafı ndan oluşturulan yeni bir programlama dilidir. Objective - C ile beraber kullanı labilecek ve de hatalı kodlara karşı daha esnek bir yapı sunacak bir şekilde tasarlanmı ştı r. Swift 2014 yı lı nda Apple'ı n geliştirici konferansı WWDC de tanı tı ldı . Xcode 6+'a dahil edilen LLVM derleyici ile geliştirildi.
2015-10-04 22:01:10 +03:00
2015-08-22 18:31:39 +03:00
Apple'ı n resmi [Swift Programlama Dili ](https://itunes.apple.com/us/book/swift-programming-language/id881256329 ) kitabı iBooks'ta yerini aldı .
Ayrı ca Swift ile gelen tüm özellikleri görmek için Apple'ı n [başlangı ç kı lavuzu ](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html )na bakmanı zda yarar var.
```swift
// modülü import etme
import UIKit
//
// MARK: Temeller
//
//XCode işaretlemelerle kodunuzu bölümlere ayı rmanı zı ve sağ üstteki metot
2015-10-31 21:19:11 +03:00
//listesinde gruplama yapmanı za olanak sağlı yor
2015-08-22 18:31:39 +03:00
// MARK: Bölüm işareti
// TODO: Daha sonra yapı lacak
// FIXME: Bu kodu düzelt
2015-10-31 21:19:11 +03:00
//Swift 2 de, println ve print metotları print komutunda birleştirildi.
//Print otomatik olarak yeni satı r ekliyor.
2015-08-22 18:31:39 +03:00
print("Merhaba dünya") // println print olarak kullanı lı yor.
print("Merhaba dünya", appendNewLine: false) // yeni bir satı r eklemeden yazar.
// variables (var) değer atandı ktan sonra değiştirilebilir.
// constants (let) değer atndı ktan sonra değiştirilemez.
var degiskenim = 42
let øπΩ = "deger" // unicode degişken adları
let π = 3.1415926
let convenience = "keyword" // bağlamsal değişken adı
let isim = "ahmet"; let soyad = "un" // farklı ifadeler noktalı virgül
kullanı larak ayrı labilir.
let `class` = "keyword" // rezerve edilmiş keywordler tek tı rnak içerisine
alı narak değişken adı olarak kullanı labilir
let doubleOlduguBelli: Double = 70
let intDegisken = 0007 // 7
let largeIntDegisken = 77_000 // 77000
let etiket = "birseyler " + String(degiskenim) // Cast etme
let piYazi = "Pi = \(π), Pi 2 = \(π * 2)" // String içerisine değiken yazdı rma
// Builde özel değişkenler
// -D build ayarı nı kullanı r.
#if false
print("yazı lmadı ")
let buildDegiskeni= 3
#else
let buildDegiskeni = 7
#endif
print("Build degiskeni: \(buildDegiskeni)") // Build degeri: 7
/*
Optionals Swift dilinde bazı değerleri veya yokluğu (None) bir değişkende
tutmanı za olanak sağlar.
Swift'te her bir degişkeninin bir değeri olması gerektiğinden, nil değeri
bile Optional değer olarak saklanı r.
Optional< T > bir enum'dı r.
*/
var baziOptionalString: String? = "optional" // nil olabilir.
// yukarı dakiyle aynı ama ? bir postfix (sona eklenir) operatördür. (kolay
2015-10-31 21:19:11 +03:00
//okunabilir)
2015-08-22 18:31:39 +03:00
var someOptionalString2: Optional< String > = "optional"
if baziOptionalString != nil {
// ben nil değilim
if baziOptionalString!.hasPrefix("opt") {
print("ön eki var")
}
let bos = baziOptionalString?.isEmpty
}
baziOptionalString = nil
// belirgin olarak acilan(unwrap) opsiyonel (optional) değer
var acilanString: String! = "Değer bekleniliyor"
//yukarı dakiyle aynı ama ! bir postfix operatördür (kolay okunabilir)
var acilanString2: ImplicitlyUnwrappedOptional< String > = "Değer bekleniliyor."
if let baziOpsiyonelSabitString = baziOptionalString {
// eğer bir değeri varsa, nil değilse
if ! baziOpsiyonelSabitString("tamam") {
// ön eke sahip değil
}
}
// Swift değişkenlerde herhangi bir tip saklanabilir.
// AnyObject == id
// Objective-C deki `id` den farklı olarak, AnyObject tüm değişkenlerle
2015-10-31 21:19:11 +03:00
//çalı şabilir
(Class, Int, struct, etc)
2015-08-22 18:31:39 +03:00
var herhangiBirObject: AnyObject = 7
herhangiBirObject = "Değer string olarak değişti, iyi bir yöntem değil ama mümkün"
/*
Yorumlar buraya
/*
İç içe yorum yazı lması da mümkün
*/
*/
//
// MARK: Koleksiyonlar
//
/*
Array ve Dictionary tipleri aslı nda structdı rlar. Bu yüzden `let` ve `var`
ayrı ca bu tipleri tanı mlarken değişebilir(var) veya değişemez(let)
olduğunu belirtir.
*/
// Diziler
var liste = ["balik", "su", "limon"]
liste[1] = "şişe su"
let bosDizi = [String]() // let == değiştirilemez
let bosDizi2 = Array< String > () // yukarı dakiyle aynı
var bosDegistirilebilirDizi = [String]() // var == değişebilir
// Dictionary
var meslekler = [
"Kamil": "Kaptan",
"Ayse": "Analist"
]
meslekler["Cansu"] = "Halkla İlişkiler"
let bosDictionary = [String: Float]() // let == değiştirilemez
let bosDictionary2 = Dictionary< String , Float > () // yukarı dakiyle aynı
var bosDegistirilebirDictionary = [String: Float]() // var == değiştirilebilir
//
// MARK: Kontroller
//
// for döngüsü (dizi)
let dizi = [1, 1, 2, 3, 5]
for deger in dizi {
if deger == 1 {
print("Bir!")
} else {
print("Bir degil!")
}
}
// for döngüsü (dictionary)
var dict = ["one": 1, "two": 2]
for (key, value) in dict {
print("\(key): \(value)")
}
// for döngüsü (aralı k)
for i in -1...liste.count {
print(i)
}
liste[1...2] = ["et", "yogurt"]
// ..< kullanarak son elemanı çı kartabilirsiniz
// while döngüsü
var i = 1
while i < 1000 {
i *= 2
}
// do-while döngüsü
do {
print("merhaba")
} while 1 == 2
// Switch
// Çok güçlü, `if` ifadesenin daha kolay okunabilir hali olarak düşünün
// String, object örnekleri, ve primitif tipleri (Int, Double, vs) destekler.
let sebze = "kı rmı zı biber"
switch sebze {
case "sogan":
let sebzeYorumu = "Biraz da domates ekle"
case "domates", "salata":
let sebzeYorumu = "İyi bir sandviç olur"
case let lokalScopeDegeri where lokalScopeDegeri.hasSuffix("biber"):
let sebzeYorumu = "Acı bir \(lokalScopeDegeri)?"
default: // zorunludur (tüm olası lı kları yakalamak icin)
let sebzeYorumu = "Corbadaki herseyin tadı güzel"
}
//
// MARK: Fonksiyonlar
//
// Fonksiyonlar first-class tiplerdir, yani başka fonksiyon içine konabilir
// ve parametre olarak geçirilebilirler.
// Swift dökümanları ylaa birlikte Fonksiyonlar (format as reStructedText)
/**
selamlama işlemi
:param: isim e isim
:param: gun e A gun
:returns: isim ve gunu iceren bir String
*/
func selam(isim: String, gun: String) -> String {
return "Merhaba \(isim), bugün \(gun)."
}
selam("Can", "Salı ")
// fonksiyon parametre davranı şı hariç yukarı dakine benzer
func selam2(#gerekliIsim: String, disParametreIsmi lokalParamtreIsmi: String) -> String {
return "Merhaba \(gerekliIsim), bugün \(lokalParamtreIsmi)"
}
selam2(gerekliIsim:"Can", disParametreIsmi: "Salı ")
// Bir tuple ile birden fazla deger dönen fonksiyon
func fiyatlariGetir() -> (Double, Double, Double) {
return (3.59, 3.69, 3.79)
}
let fiyatTuple = fiyatlariGetir()
let fiyat = fiyatTuple.2 // 3.79
// _ (alt çizgi) kullanı mı Tuple degerlerini veya diğer değerleri görmezden
2015-10-31 21:19:11 +03:00
//gelir
2015-08-22 18:31:39 +03:00
let (_, fiyat1, _) = fiyatTuple // fiyat1 == 3.69
print(fiyat1 == fiyatTuple.1) // true
print("Benzin fiyatı : \(fiyat)")
// Çeşitli Argümanlar
func ayarla(sayilar: Int...) {
2015-10-04 22:01:10 +03:00
// bu bir dizidir
2015-08-22 18:31:39 +03:00
let sayi = sayilar[0]
let argumanSAyisi = sayilar.count
}
// fonksiyonu parametre olarak geçirme veya döndürme
func arttirmaIslemi() -> (Int -> Int) {
func birEkle(sayi: Int) -> Int {
return 1 + sayi
}
return birEkle
}
var arttir = arttirmaIslemi()
arttir(7)
// referans geçirme
func yerDegistir(inout a: Int, inout b: Int) {
let tempA = a
a = b
b = tempA
}
var someIntA = 7
var someIntB = 3
yerDegistir(& someIntA, & someIntB)
print(someIntB) // 7
//
// MARK: Closurelar
//
var sayilar = [1, 2, 6]
// Fonksiyonlar özelleştirilmiş closurelardı r. ({})
// Closure örneği.
// `->` parametrelerle dönüş tipini birbirinden ayı rı r
// `in` closure başlı ğı nı closure bodysinden ayı rı r.
sayilar.map({
(sayi: Int) -> Int in
let sonuc = 3 * sayi
return sonuc
})
// eger tip biliniyorsa, yukarı daki gibi, şöyle yapabiliriz
sayilar = sayilar.map({ sayi in 3 * sayi })
// Hatta bunu
//sayilar = sayilar.map({ $0 * 3 })
print(sayilar) // [3, 6, 18]
// Trailing closure
sayilar = sorted(sayilar) { $0 > $1 }
print(sayilar) // [18, 6, 3]
// Super kı sa hali ise, < operatörü tipleri çı kartabildiği için
sayilar = sorted(sayilar, < )
print(sayilar) // [3, 6, 18]
//
// MARK: Yapı lar
//
// Structurelar ve sı nı flar birçok aynı özelliğe sahiptir.
struct IsimTablosu {
let isimler = [String]()
// Özelleştirilmiş dizi erişimi
subscript(index: Int) -> String {
return isimler[index]
}
}
// Structurelar otomatik oluşturulmuş kurucu metoda sahiptir.
let isimTablosu = IsimTablosu(isimler: ["Ben", "Onlar"])
let isim = isimTablosu[1]
print("İsim \(name)") // İsim Onlar
//
// MARK: Sı nı flar
//
// Sı nı flar, structurelar ve üyeleri 3 seviye erişime sahiptir.
// Bunlar: internal (default), public, private
public class Sekil {
public func alaniGetir() -> Int {
return 0;
}
}
// Sı nı fı n tüm değişkenleri ve metotları publictir.
// Eğer sadece veriyi yapı landı rı lmı ş bir objede
// saklamak istiyorsanı z, `struct` kullanmalı sı nı z.
internal class Rect: Sekil {
var yanUzunluk: Int = 1
// Özelleştirilmiş getter ve setter propertyleri
private var cevre: Int {
get {
return 4 * yanUzunluk
}
set {
// `newValue ` setterlarda yeni değere erişimi sağlar
yanUzunluk = newValue / 4
}
}
// Bir değişkene geç atama(lazy load) yapmak
// altSekil getter cağrı lana dek nil (oluşturulmamı ş) olarak kalı r
lazy var altSekil = Rect(yanUzunluk: 4)
// Eğer özelleştirilmiş getter ve setter a ihtiyacı nı z yoksa,
// ama bir değişkene get veya set yapı ldı ktan sonra bir işlem yapmak
// istiyorsanı z, `willSet` ve `didSet` metotları nı kullanabilirsiniz
var identifier: String = "defaultID" {
// `willSet` argümanı yeni değer için değişkenin adı olacaktı r.
willSet(someIdentifier) {
print(someIdentifier)
}
}
init(yanUzunluk: Int) {
self. yanUzunluk = yanUzunluk
// super.init i her zaman özelleştirilmiş değerleri oluşturduktan sonra
çağı rı n
super.init()
}
func kisalt() {
if yanUzunluk > 0 {
--yanUzunluk
}
}
override func alaniGetir() -> Int {
return yanUzunluk * yanUzunluk
}
}
// Basit `Kare` sı nı fI `Rect` sı nı fı nı extend ediyor.
class Kare: Rect {
convenience init() {
self.init(yanUzunluk: 5)
}
}
var benimKarem = Kare()
print(m benimKarem.alaniGetir()) // 25
benimKarem.kisalt()
print(benimKarem.yanUzunluk) // 4
// sı nı f örneğini cast etme
let birSekil = benimKarem as Sekil
// örnekleri karşı laştı r, objeleri karşı laştı ran == (equal to) ile aynı değil
if benimKarem === benimKarem {
print("Evet, bu benimKarem")
}
// Opsiyonel init
class Daire: Sekil {
var yaricap: Int
override func alaniGetir() -> Int {
return 3 * yaricap * yaricap
}
// Eğer init opsiyonelse (nil dönebilir) `init` den sonra soru işareti
// son eki ekle.
init?(yaricap: Int) {
self.yaricap = yaricap
super.init()
if yaricap < = 0 {
return nil
}
}
}
var benimDairem = Daire(radius: 1)
print(benimDairem?.alaniGetir()) // Optional(3)
print(benimDairem!. alaniGetir()) // 3
var benimBosDairem = Daire(yaricap: -1)
print(benimBosDairem?. alaniGetir()) // "nil"
if let daire = benimBosDairem {
// benimBosDairem nil olduğu için çalı şmayacak
print("circle is not nil")
}
//
// MARK: Enumlar
//
// Enumlar opsiyonel olarak özel bir tip veya kendi tiplerinde olabilirler.
// Sı nı flar gibi metotlar içerebilirler.
enum Kart {
case Kupa, Maca, Sinek, Karo
func getIcon() -> String {
switch self {
case .Maca: return "♤"
case .Kupa: return "♡"
case .Karo: return "♢"
case .Sinek: return "♧"
}
}
}
// Enum değerleri kı sayol syntaxa izin verir. Eğer değişken tipi açı k olarak belirtildiyse enum tipini yazmaya gerek kalmaz.
var kartTipi: Kart = .Kupa
// Integer olmayan enumlar direk değer (rawValue) atama gerektirir.
enum KitapAdi: String {
case John = "John"
case Luke = "Luke"
}
print("Name: \(KitapAdi.John.rawValue)")
// Değerlerle ilişkilendirilmiş Enum
enum Mobilya {
// Int ile ilişkilendirilmiş
case Masa(yukseklik: Int)
// String ve Int ile ilişkilendirilmiş
case Sandalye(String, Int)
func aciklama() -> String {
switch self {
case .Masa(let yukseklik):
return "Masa boyu \(yukseklik) cm"
case .Sandalye(let marka, let yukseklik):
return "\(brand) marka sandalyenin boyu \(yukseklik) cm"
}
}
}
var masa: Mobilya = .Masa(yukseklik: 80)
print(masa.aciklama()) // "Masa boyu 80 cm"
var sandalye = Mobilya.Sandalye("Foo", 40)
print(sandalye.aciklama()) // "Foo marka sandalyenin boyu 40 cm"
//
// MARK: Protokoller
//
// `protocol` onu kullanan tiplerin bazı özel değişkenleri, metotları ,
// tip metotları nı ,opertörleri ve alt indisleri (subscripts) içermesini
// zorunlu hale getirebilir.
protocol SekilUretici {
var aktif: Bool { get set }
func sekilOlustur() -> Sekil
}
// @objc ile tanı mlanan protokoller, uygunluğu kontrol edebilmenizi sağlayacak
// şekilde opsiyonel fonksiyonlara izin verir
@objc protocol SekliDondur {
optional func sekillendirilmis()
optional func sekillendirilebilir() -> Bool
}
class BenimSeklim: Rect {
var delegate: SekliDondur?
func buyut() {
yanUzlunluk += 2
// Bir çalı şma zamanı hatası ("optional chaining") fı rlatmak yerine nil
//değeri görmezden gelerek nil dönmek için opsiyonel değişken, metot veya
// altindisten sonra soru işareti koyabilirsiniz.
if let izinVeriyormu = self.delegate?.sekillendirilebilir?() {
// önce delegate i sonra metodu test edin
self.delegate?.sekillendirilmis?()
}
}
}
//
// MARK: Diğerleri
//
// `extension` lar: Var olan tiplere ekstra özellikler ekleyin
// Kare artı k `Printable` protokolüne uyuyor.
extension Kare: Printable {
var description: String {
return "Alan: \(alaniGetir()) - ID: \(self.identifier)"
}
}
print("Kare: \(benimKarem)")
// Dahili tipleri de yeni özellikler ekleyebilirsiniz
extension Int {
var customProperty: String {
return "Bu sayı \(self)"
}
func carp(num: Int) -> Int {
return num * self
}
}
print(7.customProperty) // "Bu sayı 7"
print(14.carp(3)) // 42
// Genericler: Java ve C#'a benzer şekilde. `where` anahtar kelimesini
// kullanarak genericlerin özelliklerini belirleyin
func indexiBul< T: Equatable > (dizi: [T], bulunacakDeger: T) -> Int? {
for (index, deger) in enumerate(dizi) {
if deger == bulunacakDeger {
return index
}
}
return nil
}
let bulunanIndex = indexiBul([1, 2, 3, 4], 3)
print(bulunanIndex == 2) // true
// Operatorler:
// Özel operatorler şu karakterlerle başlayabilir:
// / = - + * % < > ! & | ^ . ~
// veya
// Unicode math, symbol, arrow, dingbat, ve line/box karakterleri.
prefix operator !!! {}
// Yan uzunluğu 3 katı na çı kartan prefix operatörü
prefix func !!! (inout sekil: Kare) -> Kare {
sekil.YanUzunluk *= 3
return sekil
}
// güncel deger
print(benimKarem.YanUzunluk) // 4
// yan uzunluğu !!! operatorü kullanarak 3 katı na çı kar
!!!benimKarem
print(benimKarem.YanUzunluk) // 12
```