ในปี 2008 Apple ได้ประกาศและเปิดตัว iPhone SDK 2.0 เหตุการณ์นี้เริ่มต้นการปฏิวัติอีกครั้งในการพัฒนาซอฟต์แวร์และด้วยเหตุนี้นักพัฒนารุ่นใหม่จึงถือกำเนิดขึ้นซึ่งปัจจุบันได้รับการยอมรับว่าเป็น นักพัฒนา iOS .
นักพัฒนาเหล่านี้หลายคนไม่เคยใช้ Objective-C มาก่อนและนั่นเป็นความท้าทายแรกที่ Apple มีให้กับพวกเขา แม้จะมีไวยากรณ์ที่ไม่รู้จักและการจัดการหน่วยความจำแบบแมนนวล แต่ก็ประสบความสำเร็จอย่างมากช่วยเติม App Store ด้วยแอปพลิเคชันนับหมื่น Apple ปรับปรุง Objective-C อย่างต่อเนื่องในแต่ละรุ่นใหม่เพิ่มบล็อกและตัวอักษร ( ตัวอักษร ) เพิ่มการจัดการหน่วยความจำที่ง่ายขึ้นด้วยการนับการอ้างอิงอัตโนมัติและคุณสมบัติอื่น ๆ อีกมากมายที่บ่งบอกถึงภาษาโปรแกรมสมัยใหม่
และหลังจากหกปีในการทำงานและปรับปรุง Objective-C Apple ก็ตัดสินใจที่จะท้าทายนักพัฒนาอีกครั้ง อีกครั้งนักพัฒนา iOS จะต้องเรียนรู้ภาษาโปรแกรมใหม่: รวดเร็ว . Swift จะลบการจัดการตัวชี้ที่ไม่ปลอดภัยและแนะนำคุณสมบัติใหม่ที่ไร้ประสิทธิภาพในขณะที่ยังคงการโต้ตอบกับทั้ง Objective-C และ C
Swift 1.0 เป็นแพลตฟอร์มการพัฒนาที่มั่นคงและแข็งแกร่งซึ่งแน่นอนว่าจะพัฒนาไปในรูปแบบที่น่าสนใจในอีกไม่กี่ปีข้างหน้า เป็นเวลาที่เหมาะสำหรับการเริ่มต้นสำรวจภาษาใหม่นี้เนื่องจากเห็นได้ชัดว่าเป็นอนาคตของการพัฒนา iOS
ข้อยกเว้นของสปริงในการจัดการแนวปฏิบัติที่ดีที่สุด
จุดประสงค์ของบทช่วยสอนนี้คือการให้ สำหรับนักพัฒนา Objective-C ภาพรวมโดยย่อของคุณสมบัติใหม่ในภาษา Swift ช่วยให้คุณก้าวไปอีกขั้นและเริ่มใช้ Swift ในการทำงานประจำวันของคุณ ฉันจะไม่ใช้เวลามากในการอธิบาย Objective-C ฉันจะถือว่าคุณคุ้นเคยกับการพัฒนา iOS
ในการเริ่มต้นสำรวจ Swift สิ่งที่คุณต้องการคือ ดาวน์โหลด XCode 6 จาก App Store และสร้างพื้นที่เล่นเพื่อทดลอง ตัวอย่างทั้งหมดที่กล่าวถึงในบทความนี้ทำด้วยวิธีนี้
เว็บไซต์ Apple Swift เป็นข้อมูลอ้างอิงที่ดีที่สุดสำหรับการเรียนรู้เกี่ยวกับการเขียนโปรแกรม Swift คุณจะเห็นว่ามันมีค่ามากและจนกว่าคุณจะเป็น อัปเดตอย่างเต็มที่ด้วยการพัฒนา Swift ฉันคิดว่าคุณจะกลับมาที่นี่บ่อยๆ
ในการประกาศตัวแปรใน Swift ให้ใช้คีย์เวิร์ด var
var x = 1 var s = 'Hello'
คุณจะสังเกตเห็นว่าตัวแปรทั้งสอง s
และ x
เป็นประเภทต่างๆ x
เป็นจำนวนเต็มในขณะที่ 's' เป็นสตริงอักขระ Swift เป็นประเภทภาษาที่ปลอดภัยและจะอนุมานประเภทตัวแปรจากค่าที่กำหนด หากคุณต้องการให้โค้ดของคุณอ่านง่ายขึ้นคุณสามารถเลือกใส่คำอธิบายประกอบประเภทตัวแปรได้:
var y: Int y = 2
ค่าคงที่คล้ายกัน แต่ประกาศโดยใช้ let
แทน var
. คุณไม่จำเป็นต้องทราบค่าของค่าคงที่ในขณะคอมไพล์ แต่คุณต้องกำหนดค่าหนึ่งครั้ง
let c1 = 1 // Constante conocida al momento de la compilación var v = arc4random() let c2 = v // Constante conocida solo en momento de ejecución
ตามความหมายของชื่อจึงไม่เปลี่ยนรูปดังนั้นรหัสต่อไปนี้จะทำให้เกิดข้อผิดพลาดในขณะคอมไพล์
let c = 1 c = 3 // error
ประเภทอื่น ๆ สามารถประกาศเป็นค่าคงที่ได้ ตัวอย่างเช่นรหัสต่อไปนี้ประกาศว่าอาร์เรย์เป็นค่าคงที่และหากคุณพยายามแก้ไของค์ประกอบใด ๆ คอมไพเลอร์ Swift จะรายงานข้อผิดพลาด:
var arr2 = [4, 5, 6] arr2[0] = 8 print (arr2) // [8, 5, 6] let arr = [1, 2, 3] a[0] = 5 // error
ค่าคงที่จำเป็นต้องเริ่มต้นเมื่อมีการประกาศเช่นเดียวกับตัวแปรที่จำเป็นต้องเริ่มต้นก่อนที่จะใช้งาน แล้วเทียบเท่า nil
ของ Objective-C? Swift แนะนำ ค่าทางเลือก . ค่าทางเลือกสามารถมีค่าหรือเป็น nil
หากคุณดูรหัสต่อไปนี้คุณจะสังเกตเห็นว่า x
ถูกกำหนดให้เป็นค่า Opcional
ของ 2014
. ซึ่งหมายความว่าคอมไพเลอร์ Swift รู้ว่า x
อาจเป็น nil
.
var s = '2014' var x = s.toInt() print(x) // Optional(2014)
หากคุณทำการเปลี่ยนแปลงในรหัสนี้และกำหนดค่า 'abc'
เป็น s
ซึ่งไม่สามารถแปลงเป็นจำนวนเต็มได้คุณจะสังเกตเห็นว่า x
ตอนนี้เป็น nil
.
var s = 'abc' var x = s.toInt() print(x) // nil
ประเภทการส่งคืนของ toInt()
คือ Int?
ซึ่งคือ int ทางเลือก . ลองเรียกฟังก์ชันมาตรฐานบน x
:
var x = '2014'.toInt() print(x.successor()) // error
คอมไพเลอร์รายงานข้อผิดพลาดเนื่องจาก x
คือ เป็นทางเลือกและอาจเป็นศูนย์ . เราควรลอง x
ก่อนอื่นและตรวจสอบให้แน่ใจว่า sucessor
ถูกเรียกด้วยจำนวนจริงไม่ใช่ค่า nil
:
var x = '2014'.toInt() if x != nil { print(x!.successor()) // 2015 }
จำไว้ว่าเราต้องแกะออก x
การเพิ่มเครื่องหมายอัศเจรีย์ (!) . เมื่อเราแน่ใจว่า x
มีค่าเราสามารถเข้าถึงได้ มิฉะนั้นเราจะได้รับข้อผิดพลาดรันไทม์ เราสามารถทำสิ่งที่ Swift เรียกได้ด้วย การผูกเพิ่มเติม ดังนั้นการแปลงทางเลือกเป็นตัวแปรที่ไม่ใช่ทางเลือก
let x = '123'.toInt() if let y = x { print(y) }
รหัสสำหรับ if
จะทำงานก็ต่อเมื่อ x
มีค่าและถูกกำหนดให้กับ y
โปรดทราบว่าเราไม่จำเป็นต้องแกะ y
ซึ่งเป็นประเภทที่ไม่ใช่ทางเลือกเนื่องจากเรารู้ว่า x
ไม่ใช่ nil
.
ดูบทช่วยสอน Swift ของ Apple ซึ่งคุณสามารถอ่านรายละเอียดเกี่ยวกับคุณสมบัติเสริมและคุณสมบัติที่น่าสนใจเช่น โซ่เสริม
ใน Objective-C สตริงการจัดรูปแบบมักจะทำด้วยเมธอด stringWithFormat:
:
NSString *user = @'Gabriel'; int days = 3; NSString *s = [NSString stringWithFormat:@'posted by %@ (%d days ago)', user, days];
Swift มีคุณสมบัติที่เรียกว่า การแก้ไขสตริง ซึ่งทำเหมือนกัน แต่มีขนาดกะทัดรัดและอ่านง่ายกว่า:
let user = 'Gabriel' let days = 3 let s = 'posted by (user) (days) ago'
คุณยังสามารถใช้นิพจน์:
let width = 2 let height = 3 let s = 'Area for square with sides (width) and (height) is (width*height)'
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการแก้ไขสตริง Swift ให้ไปที่ ที่นี่ .
องค์ประกอบที่ดึงดูดสำหรับการออกแบบในจักรวาลรวมถึงข้อใดต่อไปนี้
คำจำกัดความของฟังก์ชันใน Swift แตกต่างจาก C ตัวอย่างนิยามฟังก์ชันมีดังต่อไปนี้:
func someFunction(s:String, i: Int) -> Bool { ... // code }
ฟังก์ชัน Swift เป็นประเภทชั้นหนึ่ง . ซึ่งหมายความว่าคุณสามารถกำหนดฟังก์ชันให้กับตัวแปรส่งผ่านเป็นพารามิเตอร์ไปยังฟังก์ชันหรือทำให้เป็นประเภทส่งคืน:
func stringLength(s:String) -> Int { return countElements(s) } func stringValue(s:String) -> Int { if let x = s.toInt() { return x } return 0 } func doSomething(f:String -> Int, s:String) -> Int { return f(s).successor() } let f1 = stringLength let f2 = stringValue doSomething(f1, '123') // 4 doSomething(f2, '123') // 124
อีกครั้ง Swift อนุมานประเภทของ f1
และ f2
(String
-> Int
) แม้ว่าเราจะสามารถกำหนดได้อย่างชัดเจน:
let f1:String -> Int = stringLength
ฟังก์ชันยังสามารถส่งคืนฟังก์ชันอื่น ๆ ได้:
func compareGreaterThan(a: Int, b: Int) -> Bool { return a > b } func compareLessThan(a: Int, b: Int) -> Bool { return a (Int, Int) -> Bool { if greaterThan { return compareGreaterThan } else { return compareLessThan } } let f = comparator(true) println(f(5, 9))
คำแนะนำเกี่ยวกับฟังก์ชันใน Swift อยู่ ที่นี่ .
Enums ใน Swift มีประสิทธิภาพมากกว่า Objective-C มาก ในฐานะที่เป็นโครงสร้างของ Swift พวกเขาสามารถมีวิธีการและส่งผ่านเป็นค่า:
enum MobileDevice : String { case iPhone = 'iPhone', Android = 'Android', WP8 = 'Windows Phone8', BB = 'BlackBerry' func name() -> String { return self.toRaw() } } let m = MobileDevice.Android print(m.name()) // 'Android'
ต่างจาก Objective-C Swift enums สามารถกำหนดสตริงอักขระหรือลอยเป็นค่าสำหรับสมาชิกแต่ละคนนอกเหนือจากจำนวนเต็ม วิธีที่สะดวก toRaw()
ส่งคืนค่าที่กำหนดให้กับสมาชิกแต่ละคน
การแจงนับสามารถกำหนดพารามิเตอร์ได้:
ประสิทธิภาพ php 7 เทียบกับ java
enum Location { case Address(street:String, city:String) case LatLon(lat:Float, lon:Float) func description() -> String { switch self { case let .Address(street, city): return street + ', ' + city case let .LatLon(lat, lon): return '((lat), (lon))' } } } let loc1 = Location.Address(street: '2070 Fell St', city: 'San Francisco') let loc2 = Location.LatLon(lat: 23.117, lon: 45.899) print(loc1.description()) // '2070 Fell St, San Francisco' print(loc2.description()) // '(23.117, 45.988)'
คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับ enums ที่นี่ .
ทูเปิลจัดกลุ่มค่าหลายค่าเป็นค่าผสมเดียว ค่าภายในทูเปิลอาจเป็นประเภทใดก็ได้และไม่จำเป็นต้องเป็นประเภทเดียวกัน
let person = ('Gabriel', 'Kirkpatrick') print(person.0) // Gabriel
คุณยังสามารถตั้งชื่อองค์ประกอบทูเพิลแต่ละรายการ:
let person = (first: 'Gabriel', last: 'Kirkpatrick') print(person.first)
Tuples มีความสะดวกอย่างยิ่งเนื่องจากเป็นประเภทการส่งคืนสำหรับฟังก์ชันที่ต้องการส่งคืนมากกว่าหนึ่งค่า:
func intDivision(a: Int, b: Int) -> (quotient: Int, remainder: Int) { return (a/b, a%b) } print(intDivision(11, 3)) // (3, 2) let result = intDivision(15, 4) print(result.remainder) // 3
ไม่เหมือนกับ Objective-C Swift รองรับรูปแบบการค้นหาใน case statement หรือ switch case:
let complex = (2.0, 1.1) // real and imaginary parts switch complex { case (0, 0): println('Number is zero') case (_, 0): println('Number is real') default: println('Number is imaginary') }
ในกรณีที่สองเราไม่สนใจส่วนที่แท้จริงของจำนวนดังนั้นเราจึงใช้ a _
จึงสามารถจับคู่อะไรก็ได้ คุณยังสามารถตรวจสอบว่ามีเงื่อนไขเพิ่มเติมในแต่ละกรณีหรือไม่ สำหรับสิ่งนี้คุณต้องเข้าร่วมค่ารูปแบบ:
let complex = (2.0, 1.1) switch complex { case (0, 0): println('Number is zero') case (let a, 0) where a > 0: println('Number is real and positive') case (let a, 0) where a <0: println('Number is real and negative') case (0, let b) where b != 0: println('Number has only imaginary part') case let (a, b): println('Number is imaginary with distance (a*a + b*b)') }
สังเกตว่าเราต้องจับคู่เฉพาะค่าที่เราจะใช้ในการเปรียบเทียบหรือในไฟล์ เปลี่ยนกรณี .
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับ Tuples ที่นี่ .
ไม่เหมือน Objective-C Swift ไม่ต้องการให้คุณสร้างอินเทอร์เฟซและเอกสารการใช้งานแยกต่างหากสำหรับคลาสและโครงสร้างที่กำหนดเอง เมื่อคุณเรียนรู้เกี่ยวกับ Swift คุณจะได้เรียนรู้การกำหนดคลาสหรือโครงสร้างในเอกสารเดียวและอินเทอร์เฟซภายนอกสำหรับคลาสหรือโครงสร้างนั้นจะพร้อมใช้งานโดยอัตโนมัติสำหรับโค้ดอื่น ๆ
คำจำกัดความของคลาสนั้นง่ายมาก:
class Bottle { var volume: Int = 1000 func description() -> String { return 'This bottle has (volume) ml' } } let b = Bottle() print(b.description())
อย่างที่เห็น, การประกาศและการนำไปใช้งานอยู่ในเอกสารเดียวกัน . Swift ไม่ใช้ส่วนหัวหรือเอกสารการใช้งานอีกต่อไป มาเพิ่มแท็กในตัวอย่างของเรา:
class Bottle { var volume: Int = 1000 var label:String func description() -> String { return 'This bottle of (label) has (volume) ml' } }
คอมไพเลอร์จะบ่นเนื่องจากเลเบลเป็นตัวแปรที่ไม่เป็นทางเลือกและจะไม่เก็บค่าไว้เมื่อมีการสร้างอินสแตนซ์ Bottle เราจำเป็นต้องเพิ่ม initializer:
class Bottle { var volume: Int = 1000 var label:String init(label:String) { self.label = label } func description() -> String { return 'This bottle of (label) has (volume) ml' } }
หรือเราสามารถใช้ประเภท Opcional
สำหรับคุณสมบัติซึ่งไม่จำเป็นต้องเริ่มต้น ในตัวอย่างต่อไปนี้เราแปลงเป็น volumen
ก Número entero Opcional
:
class Bottle { var volume: Int? var label:String init(label:String) { self.label = label } func description() -> String { if self.volume != nil { return 'This bottle of (label) has (volume!) ml' } else { return 'A bootle of (label)' } } }
ภาษา Swift ยังมี structs
แต่มีความยืดหยุ่นมากกว่าใน Objective-C บทแนะนำเกี่ยวกับรหัสต่อไปนี้กำหนด struct
:
c corp vs.s corp vs llc
struct Seat { var row: Int var letter:String init (row: Int, letter:String) { self.row = row self.letter = letter } func description() -> String { return '(row)-(letter)' } }
เช่นเดียวกับคลาสใน Swift โครงสร้างสามารถมีวิธีการคุณสมบัติตัวเริ่มต้นและเป็นไปตามโปรโตคอล ความแตกต่างที่สำคัญระหว่างคลาสและโครงสร้างคือ คลาสจะถูกส่งผ่านโดยการอ้างอิงในขณะที่โครงสร้างถูกส่งผ่านค่า .
ตัวอย่างนี้แสดงให้เห็นถึงการส่งผ่านคลาสโดยการอ้างอิง:
let b = Bottle() print(b.description()) // 'b' bottle has 1000 ml var b2 = b b.volume = 750 print(b2.description()) // 'b' and 'b2' bottles have 750 ml
หากเราพยายามทำสิ่งที่คล้ายกับ struct
คุณจะสังเกตเห็นว่าตัวแปรถูกส่งด้วยค่า:
var s1 = Seat(row: 14, letter:'A') var s2 = s1 s1.letter = 'B' print(s1.description()) // 14-B print(s2.description()) // 14-A
เมื่อไหร่ที่เราควรใช้ struct
แล้วเราจะใช้ class
เมื่อไหร่? เช่นเดียวกับใน Objective-C และ C ให้ใช้โครงสร้างเมื่อคุณต้องการจัดกลุ่มค่าบางค่าและคาดว่าจะถูกคัดลอกแทนที่จะเป็นสีอ้างอิงหรือ RGB
อินสแตนซ์ของคลาสเป็นที่รู้จักกันในชื่อวัตถุ อย่างไรก็ตามคลาสและโครงสร้างของ Swift มีความใกล้เคียงในการทำงานมากกว่าในภาษาอื่น ๆ และฟังก์ชันการทำงานจำนวนมากสามารถนำไปใช้กับอินสแตนซ์ประเภทโครงสร้างหรือคลาสได้ ด้วยเหตุนี้คำทั่วไปส่วนใหญ่ที่ใช้ในการอ้างอิงถึง Swift คือ instancia
ซึ่งใช้ได้กับทั้งสองอย่างนี้
เรียนรู้พื้นฐานของคลาสและโครงสร้างของ Swift ที่นี่ .
อย่างที่เราเห็นก่อนหน้านี้คุณสมบัติใน Swift จะประกาศด้วยคีย์เวิร์ด var
ภายในนิยามของคลาสหรือโครงสร้าง นอกจากนี้เรายังสามารถประกาศด้วยคำสั่ง let
struct FixedPointNumber { var digits: Int let decimals: Int } var n = FixedPointNumber(digits: 12345, decimals: 2) n.digits = 4567 // ok n.decimals = 3 // error, decimals is a constant
โปรดทราบว่าคุณสมบัติของคลาสนั้นมีการอ้างอิงอย่างมากเว้นแต่คุณจะใช้คำนำหน้า weak
เป็นคำหลัก อย่างไรก็ตามมีบางสิ่งบางอย่างที่มีคุณสมบัติที่ไม่เป็นทางเลือกของจุดอ่อนดังนั้นโปรดอ่านไฟล์ บทบัญชีอ้างอิงอัตโนมัติ ใน Swift Guide ของ Apple ..
คุณสมบัติที่คำนวณจะไม่เก็บค่า แต่จะมี getter และ setter เผื่อเลือกเพื่อดึงและตั้งค่าคุณสมบัติและค่าอื่น ๆ โดยอ้อม
โค้ดต่อไปนี้เป็นตัวอย่างของค่าที่คำนวณ sign
:
enum Sign { case Positive case Negative } struct SomeNumber { var number:Int var sign:Sign { get { if number <0 { return Sign.Negative } else { return Sign.Positive } } set (newSign) { if (newSign == Sign.Negative) { self.number = -abs(self.number) } else { self.number = abs(self.number) } } } }
นอกจากนี้เรายังสามารถกำหนดคุณสมบัติอ่านอย่างเดียวได้โดยใช้ getter:
struct SomeNumber { var number:Int var isEven:Bool { get { return number % 2 == 0 } } }
ใน Objective-C โดยทั่วไปคุณสมบัติจะได้รับการสนับสนุนโดยตัวแปรอินสแตนซ์ซึ่งคอมไพเลอร์ประกาศอย่างชัดเจนหรือสร้างขึ้นโดยอัตโนมัติ ในทางกลับกันใน Swift คุณสมบัติไม่มีตัวแปรอินสแตนซ์ที่เกี่ยวข้อง . นั่นคือไม่สามารถเข้าถึงที่เก็บสำรองสำหรับคุณสมบัติได้โดยตรง สมมติว่าเรามีสิ่งนี้ใน Objective-C:
// .h @interface OnlyInitialString : NSObject @property(strong) NSString *string; @end // .m @implementation OnlyInitialString - (void)setString:(NSString *newString) { if (newString.length > 0) { _string = [newString substringToIndex:1]; } else { _string = @''; } } @end
เนื่องจากในคุณสมบัติที่คำนวณโดย Swift ไม่มีที่เก็บสำรองเราจึงต้องการสิ่งนี้:
class OnlyInitialString { var initial:String = '' var string:String { set (newString) { if countElements(newString) > 0 { self.initial = newString.substringToIndex(advance(newString.startIndex, 1)) } else { self.initial = '' } } get { return self.initial } } }
คุณสมบัติมีการอธิบายรายละเอียดเพิ่มเติม ที่นี่
มีสิ่งที่สำคัญและใหม่ ๆ อีกมากมายให้เรียนรู้ใน Swift เช่นการเขียนโปรแกรมทั่วไปการโต้ตอบกับไลบรารี Objective-C การปิด โซ่เสริม และตัวดำเนินการเกินพิกัด บทช่วยสอนเดียวไม่สามารถอธิบายภาษาใหม่ได้อย่างสมบูรณ์ แต่ฉันไม่สงสัยเลยว่าจะมีการเขียนโปรแกรม Swift อีกมากมาย อย่างไรก็ตามฉันคิดว่านี่ อ่านเร็ว จะช่วยให้นักพัฒนา Objective-C หลายคนที่ยังไม่พบเวลาหรือเรียนรู้รายละเอียดเกี่ยวกับภาษา Swift ได้ไปและปล่อยให้นก Swift พาคุณไปสู่จุดสูงสุดใหม่