Author: NhatHM

  • Fresher Training—iOS Swift Day 3

    Fresher Training—iOS Swift Day 3

    Today topic:

    • Access Control & Code Organization
    • Custom Operators, Subscripts & Keypaths
    • Pattern Matching
    • Error Handling

    Thao khảo: Swift—Advanced control flow

    Exercises:

    Exercise 01: SINGLETON
    • A singleton is a design pattern that restricts the instantiation of a class to one object.
    • Use access modifiers to create a singleton class Logger. This Logger should:
    • Provide shared, public, global access to the single Logger object.
    • Not be able to be instantiated by consuming code.
    • Have a method log() that will print a string to the console.

    Điểm: 2

    Exercise 02: STACK
    • Declare a generic type Stack. A stack is a LIFO (last-in-first-out) data structure that supports the following operations:
    • peek: returns the top element on the stack without removing it. Returns nil if the stack is empty.
    • push: adds an element on top of the stack.
    • pop: returns and removes the top element on the stack. Returns nil if the stack is empty.
    • count: returns the size of the stack.
    • Ensure that these operations are the only exposed interface. In other words, additional properties or methods needed to implement the type should not be visible.

    Điểm: 2.5

    Exercise 03: SUBSCRIPT
    extension Array {
        subscript(index: Int) -> (String, String)? {
            guard let value = self[index] as? Int else {
                return nil
            }
            
            switch (value >= 0, abs(value) % 2) {
            case (true, 0):
                return ("positive", "even")
            case (true, 1):
                return ("positive", "odd")
            case (false, 0):
                return ("negative", "even")
            case (false, 1):
                return ("negative", "odd")
            default:
                return nil
            }
        }
    }

    What wrong with this code? How to fix?

    Điểm: 1.5

    Exercise 04: ERROR HANDLING

    Write a throwing function that converts a String to an even number, rounding down if necessary.

    Điểm: 2

  • Swift—Advanced control flow

    Swift—Advanced control flow

    Bài viết này giới thiếu cái khái niệm và các dùng về control flow trong Swift:

    For loop

    Countable ranges

    • countable closed range: 0…5
    • countable half-open range: let halfOpenRange = 0..<5

    For in với where condition

    • Swift hỗ trợ for in where để lọc ra các điều kiện phù hợp trong tập cho trước:
    var sum = 0
    
    for i in 1...10 where i % 2 == 1 {
        sum += i
    }

    Continue and labeled statements

    • Trong nhiều trường hợp, khi điều kiện trong vòng loops trở nên phức tạp hơn, thì ta có thể sử dụng “labeled statements” để tiếp tục vòng loop tương ứng, ví dụ như dưới:
    var sum = 0
    rowLoop: for row in 0..<8 {
        columnLoop: for column in 0..<8 {
            if row == column {
                continue rowLoop
            }
            sum += row * column
            print(sum)
        }
    }
    • Ở đây, rowLoop và columnLoop được gọi là “labeled statements”, ta có thể tiếp tục vòng loop tương ứng bằng câu lệnh “continue”

    Switch statements

    • Không như Objective C là switch điều kiện switch (expression) chỉ có thể sử dụng các loại data dạng như int, character…, thì trong Swift, điều kiện switch đã trở nên phong phú và thuận tiện hơn rất nhiều.
    • Các điều kiện switch mà Swift support:
      • Điều kiện switch là một hoặc nhiều giá trị cùng loại data với nhau
      • Điều kiện switch có thể là range
    • Các điểm chính của Switch Statement:
      • No implicit Fallthrough (không tự động chuyển sang case tiếp theo): đối với các case điều kiện của Switch statement thì không có chuyện điều kiện switch được tự động chuyển sang case tiếp theo, nghĩa là mỗi điều kiện trong case của switch đều phải có body. Đoạn code như dưới sẽ báo lỗi khi compile. (Trong trường hợp muốn kết hợp nhiều điều kiện switch case thì sử dụng “compound case” switch.)
    switch age {
    case 19: // Error
    case 20:
        print("adult")
    default:
        print("default case")
    }
    • Interval matching: switch trong Swift hỗ trợ switch case theo từng khoảng giá trị. Ví dụ:
    let age = 18
    
    switch age {
    case 0..<18:
        print("child")
    case 18..<60:
        print("adult")
    default:
        print("old")
    }
    • Tuples: Swift switch statement hỗ trợ điều kiện trong switch case là tuple, cách sử dụng cũng rất linh hoạt. Ví dụ (lấy từ swift.org):
    let somePoint = (1, 1)
    switch somePoint {
    case (0, 0):
        print("\(somePoint) is at the origin")
    case (_, 0):
        print("\(somePoint) is on the x-axis")
    case (0, _):
        print("\(somePoint) is on the y-axis")
    case (-2...2, -2...2):
        print("\(somePoint) is inside the box")
    default:
        print("\(somePoint) is outside of the box")
    }
    • Đối với trường hợp sử dụng tuple thì điều kiện trong case có thể là mapping cả tuple, hoặc chỉ 1 giá trị trong tuple mà thôi, đối với giá trị không cần so sánh thì dùng ký tự “_” (wildcard pattern) để định nghĩa.
    • Value Bindings: trong trường hợp muốn lấy giá trị của giá trị trong tuple khi đã thoả mãn điều kiện thì dùng câu lệnh như sau:
    let anotherPoint = (2, 0)
    switch anotherPoint {
    case (let x, 0):
        print("on the x-axis with an x value of \(x)")
    case (0, let y):
        print("on the y-axis with a y value of \(y)")
    case let (x, y):
        print("somewhere else at (\(x), \(y))")
    }
    • -> như trong trường hợp này thì chỉ cần giá trị point thoả mãn y = 0 thì sẽ lấy được giá trị của x ra bằng câu lệnh “let x”
    • Where: where statement được dùng trong switch case để xử lý những câu switch với điều kiện phức tạp, ví dụ:
    let person = ("Gaby", "Female", 18)
    switch person {
    case (_, _, let age) where (age > 50):
        print("This person is not in age range")
    case (_, let gender, _) where (gender == "Male"):
        print("This is male employee")
    case (_, let gender, _) where (gender == "Female"):
        print("This is female employee")
    default:
        print("Default")
    }
    • Compound case: trong trường hợp nhiều điều kiện case xử lý chung một logic thì ta có thể kết hợp các điều kiện đó vào chung 1 case switch, ví dụ:
    let language = "Swift">switch language {
    case "Swift", "Objective-C":
        print("Company: Apple")
    case "Dart", "Go lang":
        print("Company: Google")
    default:
        print("Some other companies")
    }
    • Switch statement cho phép sau khi xử lý logic ở case trên, sẽ tiếp tục xử lý logic ở case dưới với keyword “fallthrough”

    Control Transfer Statements

    • continue:
      • Câu lệnh continue hỗ trợ việc break ra khỏi vòng lặp hiện tại của for-loop mà không break hoàn toàn khỏi for-loop
    • break
      • Câu lệnh break trong loop statement sẽ ngắt hoàn toàn vòng lặp.
      • Câu lệnh break trong switch statement sẽ kết thúc switch statement. Bởi vì các case của switch statement không được phép empty nên thường add break vào để tránh compile error. Ví dụ add break vào default case.
    • fallthrough
      • Fallthrough cho phép switch statement sau khi thực hiện xong logic của case bất kỳ, sẽ được chuyển tiếp xuống dưới để thực hiện case tiếp theo. Thường ứng dụng trong trường hợp muốn append thêm logic vào kết quả đã được xử lý ở các case của switch statement (sẽ viết ở default case)
    • return
    • throw
      • https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html#ID510
  • Fresher Training—iOS Swift Day 2

    Fresher Training—iOS Swift Day 2

    Today topic:

    • Properties
    • Methods
    • Advanced Classes Enumerations
    • Protocols
    • Generics

    Exercises:

    Exercise 01: PROPERTY
    1. Show me an example about a struct have property is another struct
    2. What is type property, example by source code

    1 and 1 point

    Exercise 02: Methods
    1. Define struct Coordinate with property have latitude and longitude. Write a method to get/set for this property
    2. (Optional) Compare between class’s method and struct’s method

    1 and 0.5 point

    Exercise 03: Advanced class

    What is deinit of class?

    Create three simple classes called A, B, and C where C inherits from B and B inherits from A.

    Write init method that print class name before and after call super.init

    Write deinit method then printed simple log like: Destroy A / B / C

    Now, look at below codes

    do {
        let _ = C()
    }

    These codes will create an instace of C then release. Please explain printed log

    2 point

    Exercise 04: Protocols

    Define a protocol Vehical, this protocol will have some properties like fuel, speed, and some method like run()…

    Implement at least 3 class conform to this protocol and show me difference kind of run()

    What do you think about inheritance and protocol for this case?

    2.5 point

  • Fresher Training—iOS Swift Day 1

    Fresher Training—iOS Swift Day 1

    Today topic:

    • Expressions, Variables & Constants
    • Types & Operations
    • Control Flow
    • Functions
    • Optionals
    • Arrays, Dictionaries & Sets
    • Collection Iteration with Closures
    • Strings
    • Structures
    • Classes

    Exerices:

    Exercise 01: Expressions, Variables & Constants

    Declare four constants named x1, y1, x2 and y2 of type Double. These constants represent the 2-dimensional coordinates of two points. Calculate the distance between these two points and store the result in a constant named distance.

    1 point

    Exercise 02: Expressions, Variables & Constants

    Given a number n, calculate the factorial of n.  (Example: 4 factorial is equal to 1 * 2 * 3 * 4.)

    1 point

    Exercise 03: Control Flow
    1. Print 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0. Don’t use stride(from:by:to:)
    2. What is Labeled statements? Using source code to explain.

    1 point and 1.5 point

    Exercise 03: Control Flow
    1. Write a function that print log. This function can take a string as parameter, or multiple strings as paramsters. Return false if any string is empty.
    2. (Optional) Write a function that calculate fibonancy sequence:  func fibonacci(_ number: Int) -> Int

    1 point and bonus 0.5 point

    Exercise 04: Collection Iteration with Closures

    Define a dictionary with key is name: String and value is score: Double
    Calculate sum of all score in dictionary

    1 point

    Exercise 05: Struct vs Class

    Compare between struct and class

    1.5 point

  • Swift—Closure

    Swift—Closure

    Khi mới làm quen với Swift, đôi khi ta gặp phải những đoạn code như dưới:

    Client Side Swift — iOS
    Server Side Swift — Vapor

    Tuy nhiên ta không hiểu chúng là gì, và dùng như nào. Trong Swift, những đoạn code kiểu như trên được gọi là Closure, bài Note này sẽ đi sâu vào bới móc xem Closure là gì ;))

    Trong Swift thì Closure là khái niệm khá quan trọng, ứng dụng nhiều cũng như là khó đọc cho người mới nếu chưa nắm được syntax của nó. Bài viết này sẽ nói về khái niệm Closure cũng như một vài ứng dụng của nó.

    Closure là?

    Closure là một block code, có thể tách ra để tái sử dụng. Hiểu đơn giản hơn thì Closure là function, nhưng khuyết danh. Ta có thể gán Closure vào biến và sử dụng như các kiểu value khác.

    Closures có thể là 1 trong 3 loại sau:

    • Global functions: là closures có tên và không “capture” các giá trị.
    • Nested functions: là closures có tên và có thể “capture” các giá trị từ function chứa nó.
    • Closure expressions: là closures không có tên được viết dưới dạng giản lược syntax và có thể “capture” các giá trị từ các bối cảnh xung quanh.

    Capturing value:
    https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID103

    2 loại đầu được gọi với cái tên khác là function. Và khi nhắc đến Closures, thường ta chỉ quan tâm đến trường hợp thứ 3, Closure expressions (từ giờ chỉ gọi tắt là Closure).

    Closure Syntax

    Ví dụ cụ thể về khai báo Closure:

    import Foundation
    // Declare a variable to hold a closure
    var add: (Int, Int) -> Int
    // Assign a closure to a variable
    add = { (a: Int, b: Int) -> Int in
    return a + b
    }
    // Or combine like this
    var sub = { (a: Int, b: Int) -> Int in
    return a – b
    }
    add(1, 2)
    sub(1, 2)

    Note: parameters trong Closure có thể là kiểu “in-out”, variadic, tuples, nhưng không thể có default value.

    So với Function thì Closure đã được viết ra với mục đích ngắn gọn nhất có thể, và nó như sau:

    // Declare a variable to hold a closure
    var add: (Int, Int) -> Int
    /** SHORTHAND SYNTAX **/
    // Not need return keyword when only have single return statement
    add = {(a: Int, b: Int) -> Int in
    a + b
    }
    add(1, 1)
    // Remove return type and parameters type
    // Because we already declare: var add: (Int, Int) -> Int
    add = {(a, b) in
    a + b
    }
    add(9, 2)
    // Remove parameters, Swift will refer parameters by number, start from 0:
    add = {
    $0 + $1
    }
    add(99, 1)

    Ứng dụng của Closure:

    Closure như là parameter cho function, Trailing closure syntax

    Với function thì ta hoàn toàn có thể truyền vào cho function khác dưới dạng arguments, tuy nhiên trước khi truyền thì phải define function sẽ dùng làm argument:

    Ví dụ dùng function làm parameter cho function

    Đối với Closure thì đơn giản hơn, ta có thể define closure inline:

    Ví dụ dùng closure làm parameter cho function
    Note: {$0 + $1}: Swift cho phép refer đến mỗi parameter bằng format như bên, bắt đầu từ index 0.

    Đối với những function có parameter cuối cùng là Closure, thì ta có thể viết lại function call dưới dạng Trailing Closure như sau:

    Trailing Closure example

    Cách làm này phù hợp với những Closure dài, dùng như complete block/callback…Ví dụ về cách sử dụng callback/block khi request data từ server, ví dụ:

    Objective C:

    Khai báo method:

    Gọi hàm:

    Swift Closure:

    Khai báo func:

    Gọi hàm:

    Các ứng dụng của Closure nên biết:

    sorted(): dùng để thay đổi điều kiện sort cho array/collection…

    filter(): dùng dể lọc các phần tử của collection/array với điều kiện nhất định, ví dụ như lọc tuổi người dùng để kiểm tra nhưng ai đủ tuổi xem 18+ chẳng hạn

    map(): dùng để áp dụng điều kiện nào đó cho tất cả các item trong array/collection, ví dụ tính tiền của sản phẩm sau khi áp dụng thuế tiêu thụ chẳng hạn

    reduce(): dùng để tính tổng của array…Xem ví dụ bên dưới, bài toán là cần tính tổng tất cả các sách có trong kho, mỗi record sách được lưu dưới dạng: tên sách, số lượng, và giá.

    reduce() có 2 parameters là giá trị ban đầu, tức là giá trị kết quả giả định ban đầu, ở ví dụ này được set là 0, và 1 closure tính toán trả về giá trị cần tính, giá trị này tiếp theo sẽ được truyền vào closure dưới dạng first parameter ($0), và lặp lại cho đến hết array.

    Với ví dụ ở trên thì reduce() sẽ xử lý như sau

    Step1. $0 sẽ có giá trị là 0 (chính là giá trị của init result). $1 là object đầu tiên của array books. Closure này sẽ return kết quả là $0 (=0)+ (12 * 39.000) = 468.000. Kết quả này sẽ được gán cho $0 của step tiếp theo. Nếu truyền vào giá trị ban đầu là số khác, thì $0 cũng tương đương với giá trị của số đó. Ví dụ ở trên, nếu truyền vào là books.reduce(5)… thì closure sẽ return kết quả là $0 (=5)+ (12 * 39.000)

    Step2. $0 sẽ có giá trị là kết quả của step 1, và $1 là object ở index = 1 của array books. Kết quả return của Closure là $0 (=468.000) + (9 * 22.000). Step này sẽ được lặp lại cho đến hết array books. Về cơ bản, step 1 và 2 chỉ khác nhau ở chỗ, ở step 1, $0 chưa có giá trị, nên nó sẽ được chỉ định là giá trị của parameter thứ nhất của Closure reduce(), a hi hi hi.


    Closure được dùng rất nhiều trong source code Swift, nếu biết syntax thì sẽ dễ hơn trong việc đọc source code, nắm được các ưu điểm và ứng dụng đúng lúc sẽ đem lại source code ngắn gọn và hiệu quả hơn…

    Note: Một vài gist về function và closure.

  • Missing pieces for developers using macOS

    Missing pieces for developers using macOS

    Homebrew (The missing package manager for macOS)

    • Homebrew là package manager rất có ích cho macOS, nó giúp bạn cài đặt các thư viện, ngôn ngữ, framework… rất nhanh và dễ dàng.
    • Ưu điểm của Homebrew đó là bạn chỉ cần gõ câu lệnh để cài đặt package mà được Homebrew support, sau đó nó sẽ tự động download, check các dependencies (các package cần phải có trước khi cài đặt package mình mong muốn), nếu chưa có nó sẽ download và install dependencies trước, rồi sẽ install package mà bạn muốn cài
    • Ngoài ra thì Homebrew cũng cài đặt các package lên máy trong folder riêng của nó, sau đó mới link sang thư mục /usr/local, việc này sẽ đảm bảo môi trường default trên máy bạn không bị ảnh hưởng.
    • Homebrew cũng đảm bảo các package luôn được up-to-date. Điều này chắc chắn là tiết kiệm cho bạn rất nhiều thời gian.
    • Ngoài ra, bạn có thể cài đặt các application trên macOS bằng cách sử dụng Homebrew Cask. (No more download, no more .dmg)

    Oh my zsh

    • Các developer sử dụng macOS và các OS Linux khác chắc hẳn rằng không còn xa lạ gì với bash, có thể nói rằng bash chính là một phần không thể thiếu trong công việc hàng ngày. Khi bạn mở Terminal lên, gõ câu lệnh và OS thực thi nó, vậy là bạn đã sử dụng bash.
    • Vậy bash là gì?
      • bash (Bourne-Again SHell) thực chất là các shell, hay còn gọi là command-line interpreter hoặc command language interpreter (CLI). Nó cho phép người dùng sử dụng các câu lệnh dạng text để gọi đến các service của OS (kernel), qua đó thực thi các câu lệnh của người dùng.
      • bash là shell mặc định trên các OS như macOS, Linux. Ngoài việc nhận lệnh trực tiếp từ user thông qua các ứng dụng như Terminal thì bash còn có thể thực thi lệnh thông qua file được gọi là shell script.
    • zsh là gì?
      • zsh cũng giống như bash, nhưng nó được thiết kế nhằm mục đích phục vụ cho việc tương tác với người dùng (thực hiện  lệnh mà người dùng input vào). zsh cũng “học hỏi” rất nhiều tính năng từ bash, ksh, tcsh ngoài những tính năng nó có sẵn, đem đến cho người dùng một bộ công cụ mạnh mẽ khi làm việc với shell.
      • Những điểm thú vị khi so sánh zsh với bash
        • muốn thay đổi directory thì chỉ cần gõ tên directory, không cần thêm cd ở đầu
        • ls *.(h|m) : list tất cả các file có đuôi .h hoặc .m trong folder
        • completing command options: example git — + tab => liệt kê các options tương ứng với command vừa gõ.
        • hiển thị thời điểm gõ câu lệnh RPROMPT=”%t”

    oh-my-zsh

    • Không dừng lại ở zsh, cộng đồng developers đã tạo ra oh-my-zsh, một framework thú vị, giúp người dùng không còn cảm thấy nhàm chán mỗi khi làm việc với command line.
    • oh-my-zsh có gì thú vị?
      • Có bộ plugin khổng lồ cho các công cụ, ngôn ngữ và framework mà bạn hay dùng như: aws, docker, git, rails, laravel, npm, osx, python… Nó giúp bạn có thể autocomplete câu lệnh hoặc cung cấp các alias ngắn gọn, giúp rút ngắn thời gian gõ lệnh.
      • Cung cấp các bộ theme đẹp và tiện dụng cho terminal, một terminal màu mè với các symbol hiển thị phù hợp sẽ đỡ nhàm chán hơn rất nhiều so với một terminal đen trắng.
      • Bạn có thể trở thành contributor để cung cấp những plugin do chính mình viết.
    • Install oh-my-zsh
      • Mở terminal, paste câu lệnh sau và nhấn enter:
        1. sh -c “$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)”
      • Config plugin cho on-my-zsh
        1. Mở file ~/.zshrc
        2. Tìm đến dòng plugins=(…) và add plugin cho phù hợp với nhu cầu. Ví dụ muốn dùng plugin git, macos, aws, docker thì chỉnh sửa thành:
          1. plugins=(git osx aws docker)
        3. Restart terminal
      • Kết quả:
        1. Ví dụ, trước đây khi muốn show hidden file trong macOS thì cần phải gõ
          1. defaults write com.apple.finder AppleShowAllFiles -bool TRUE
          2. killall Finder 
        2. Sau khi dùng plugin osx thì chỉ cần gõ
          1. showfiles / hidefiles để hiện và ẩn hidden file (hidden file là những file có tên bắt đầu bằng dấu .)
    • Install theme cho on-my-zsh
      • Mở file ~/.zshrc
      • Điền tên theme vào sau ZSH_THEME=, ví dụ ZSH_THEME=”robbyrussell”

    iTerm2

    • App Terminal, default của macOS có thể thực hiện tốt các nhiệm vụ khi người dùng muốn làm việc với shell. Tuy nhiên, nếu bạn thực sự muốn một app có tính tuỳ biến cao, nhiều tính năng thú vị hỗ trợ thì nên thử qua app iTerm2.
    • Một vài tính năng thú vị của iTerm2:
      • Split panels: tính năng này cho phép bạn chia tab hiện tại của iTerms ra thành các “panel” khác nhau, mỗi panel là một section riêng biệt. Rất có ích khi làm việc mà cần phải tham chiếu kết quả giữa các section với nhau.
      • Search: tính năng search trên iTerm2 có sự khác biệt khi so sánh với Terminal, iTerm2 highlight tất cả các kết quả phù hợp với điều kiện search, ngoài ra nó còn hỗ trợ cả search theo regular expression.
      • Autocomplete: với những câu lệnh bạn đã từng gõ trong iTerm, thì lần sau chỉ cần gõ vài ký tự đầu và nhấn tổ hợp phím Cmd + ; thì iTerm sẽ liệt kê lịch sử các câu lệnh đã gõ tương ứng cho bạn lựa chọn.

    ref:

  • Swift —Giới thiệu sơ lược

    Swift —Giới thiệu sơ lược

    Swift là gì?
    Swift là ngôn ngữ lập trình được phát triển bởi Apple, do Chris Lattner làm trưởng nhóm thiết kế. Lần đầu tiên được giới thiệu công khai là vào WWDC năm 2014 của Apple. Năm 2015, Swift chính thức trở thành open source và từ đó luôn phát triển mạnh mẽ với những đóng góp không ngừng từ cộng đồng lập trình viên quốc tế.


    Điểm mạnh của Swift
    Swift là ngôn ngữ lập trình mạnh mẽ và trực quan, dùng để viết ứng dụng cho macOS, iOS, watchOS, tvOS, Linux (và một vài OS khác). Do được truyền cảm hứng từ các ngôn ngữ khác như Objective-C, Haskell, Ruby, Python, C#… nên Swif mang hơi hướng hiện đại và luôn có những tính năng mới mẻ. Swift cũng rất dễ dàng để làm quen vì syntax đơn giản, ngắn gọn.  Swift được thiết kế với tiêu chí là sẽ trở thành ngôn ngữ mạnh mẽ và an toàn, cùng với đó là tốc độ xử lý cũng như hiệu suất cao, đảm bảo rằng Swift sẽ còn phát triển và còn mạnh mẽ hơn trong tương lai.

    Swift là ngôn ngữ cân bằng giữa performance và productivity https://developer.apple.com/videos/play/wwdc2014/102/

    Swift có thể làm được gì?
    Swift là ngôn ngữ chính để phát triển ứng dụng chạy trên các OS của Apple như macOS, iOS, tvOS, watchOS. Ngoài ra Swift còn được dùng để phát triển các ứng dụng server/web chạy trên các nền tảng Linux OS, hiện tại có các Web Framework nổi tiếng có thể kể tên như Vapor, Perfect, Kitura (phát triển bởi IBM). Trong một vài bài test benchmarks thì Vapor và Perfect cũng có rất nhiều điểm nổi bật so với NodeJS. Điều này rất thuận lợi cho các lập trình viên iOS/macOS xây dựng các ứng dụng server-side cho bản thân họ.

    Hệ sinh thái Swift


    Làm thế nào để cài đặt và sử dụng Swift?
    Đối với những người dùng macOS thì cách nhanh nhất để install Swift là tải và cài đặt XCode, Swift sẽ được cài đặt cùng với XCode. Nếu không muốn download cả bộ cài XCode thì có thể cài đặt riêng thông qua toolchain tại đây https://swift.org/download/, sau khi cài đặt toolchain thì có thể sử dụng Swift bình thường.
    Đối với người dùng Ubuntu thì chỉ có phương pháp cài đặt thông qua toolchain, tham khảo chi tiết tại https://swift.org/download/
    Sau khi cài đặt xong thì gõ command swift -version để kiểm tra xem cài đặt thành công hay chưa.


    What’s next?

    Swift vẫn đang được phát triển bởi cộng đồng lập trình viên trên toàn thế giới, ngoài ra Swift còn được các công ty lớn như Apple, IBM hỗ trợ nên chắc chắn rằng Swift còn rất nhiều điều hấp dẫn đang chờ đợi. Nếu như bạn đã cài đặt XCode/Swift thành công thì hãy bắt tay vào việc viết một ứng dụng đi thôi.

  • Swift — Optionals, Guard and Nil Coalescing

    Guard

    Guard cũng gần giống như “if let” (optionals binding), nó cũng được sử dụng để xử lý các object dạng Optionals, cũng check các điều kiện khác “nil” thì cho phép thực hiện các logic tiếp theo… Nhưng Guard còn được gọi với tên gọi khác là “Early Exit”, vậy Guard khác “if let” (Optional binding) ở điểm nào?

    Hãy xem xét ví dụ sau:

    Raw: https://gist.github.com/RioV/f551c21f3c2c16946f2bdd338c3fd24f

    Ví dụ trên là sự so sánh giữa việc sử dụng Optional Binding và Guard để xử lý việc check object có thoả mãn điều kiện là khác “nil” hay không.

    Với Optional Binding thì ta tập trung xử lý trường hợp có value trước. Còn với Guard thì ta ưu tiên xử lý trường hợp không có value trước. Hai khái niệm trên cùng xử lý việc tương tự nhau, nhưng tuỳ hoàn cảnh cụ thể mà ta dùng Optional binding hay Guard cho phù hợp.

    Tất nhiên là Guard còn được sử dụng để check hàng loạt các điều kiện khác nhau (không nhất thiết chỉ là check nil) xem các điều kiện có cùng thoả mãn hay không.

    Ví dụ:

    let name : String? = "Swift"
    let version : Int = 3
    let owner : String = "Apple"
    func checkMultiCondition(name : String?, version : Int, owner : String) {
    guard let name = name, version > 2, owner == "Apple" else {
    print("Input parameters not match!!!")
    return
    }
    print(name)
    print(version)
    print(owner)
    }

    Và dùng Guard để check các điều kiện tuần tự thì…tuyệt vời ông mặt giời luôn. (search thêm về Happy-Path Programming)

    struct Student {
    let name: String?
    let age: Int?
    let gender: String?
    }
    let student = Student(name: "Rio", age: 27, gender: "Male")
    func validateStudentInfo (_ student: Student) -> String {
    // We do NOT need to using student name, just want to check if
    // student name have value, so using underscore here
    if let _ = student.name {
    if let _ = student.age {
    if let _ = student.gender {
    return "OK"
    } else {
    return "Gender not valid"
    }
    } else {
    return "Age not valid"
    }
    } else {
    return "Name not valid"
    }
    }
    func validateStudentInfoWithGuard (_ student: Student) -> String {
    guard let _ = student.name else {
    return "Name not valid"
    }
    guard let _ = student.age else {
    return "Age not valid"
    }
    guard let _ = student.gender else {
    return "Gender not valid"
    }
    return "OK"
    }
    validateStudentInfo(student)
    validateStudentInfoWithGuard(student)

    Như đoạn code sample trên thì việc sử dụng Guard để check các điều kiện tuần tự nhau rất đơn giản và dễ đọc. Còn nếu sử dụng Optional Binding lồng nhau để check thì source code trông rất tệ và khó đọc. Hãy cân nhắc khi sử dụng 😉

    Có một điều cần chú ý là, với Guard statement thì trong trường hợp “else”, ta bắt buộc phải return ;). Và sử dụng Guard một cách hợp lý sẽ làm source code dễ đọc hơn, dễ maintain hơn.

    Nil Coalescing

    Còn một cách khác để unwrap một object Optionals là sử dụng “nil coalescing”, trong các ngôn ngữ khác thì quen thuộc với cái tên “Null Coalescing” https://en.wikipedia.org/wiki/Null_coalescing_operator

    Dùng “Nil Coalescing” khi mà bạn muốn có giá trị default nào đó cho Optional object, trong trường hợp nó bị nil, như dưới đây:

    Trong ví dụ này ta thấy rằng trường hợp biến “name” bị nil thì lập tức nó được gán value là “No Name”

    Chú ý rằng chỉ sử dụng “Nil Coalescing” với các Object optionals thôi nhé, nếu dùng cho object non-optionals thì compiler sẽ báo lỗi như dưới:

    Nó dụ dỗ xoá nil coalescing đi luôn

    Have Fun

  • Swift — Đôi nét về Optionals

    Swift — Đôi nét về Optionals

    Swift đã giới thiệu một khái niệm mới là Optionals. Vậy Optionals là gì?

    Optional là một khái niệm đặc biệt trong Swift dùng để xử lý việc thiếu giá trị (absence of value — của variable, const, object…)

    Thiếu giá trị là gì? Trong Objective-C, khi muốn thể hiện biến hay object nào đó không có giá trị (value) nào cả thì ta sẽ set chúng bằng “nil”, hay trong các ngôn ngữ khác là “Null”.

    Nhưng trong Swift, việc set một object thành “nil” là không thể, thay vào đó, ta sử dụng Optional.

    Quay trở lại với câu hỏi “Optionals là gì”, ta có thể hiểu một cách dân dã hơn như sau:

    Optional giống như cái hộp quà, có thể trong hộp có quà (optional bao hàm value), mà cũng có thể là không có (optional bao hàm nil). Cái hộp quà (tức optional) lúc nào cũng tồn tại, nhưng quà (value) thì có thể có, cũng có thể không.

    Cách khai báo một biến dưới dạng Optionals:

    Tại sao lại sinh ra Optionals?

    Swift sinh ra là để thay thế cho Objective-C, nên về mặt nào đó nó phải tốt hơn Objective-C. Và có lẽ, Optionals là để đảm bảo tính an toàn hơn của Swift so với Objective-C (Swift được gọi là type safe language :v)

    Xem ví dụ sau

    Objective — C
    Swift

    Ví dụ trên là tạo array chứa danh sách các String, trong đó có String sẽ bị nil. Với Objective-C thì compiler không báo lỗi khi add thêm biến có giá trị nil vào array, do đó khi run time sẽ bị crash (vì không thể add nil vào array). Tuy nhiên, với Swift thì compiler đã báo lỗi Optional type String? chưa được “unwrapped” -> Báo lỗi trong quá trình compile.

    Khi sử dụng Optionals, coder luôn được nhắc đến việc “unwrapped” — mở hộp — một biến để sử dụng (đảm bảo coder luôn chú ý đến việc chắc chắn rằng biến đó có bị nil hay không)

    Làm thế nào để sử dụng giá trị của biến dạng Optionals?

    Unwrapping Optionals — hay còn gọi là mở hộp lấy quà :v

    Các phương pháp unwrapped optionals

    Force unwrapping: sử dụng dấu “!” sau biến optionals:

    Khi sử dụng cách làm này, phải luôn chắc chắn rằng biến có values, nếu không sẽ gây crash chương trình (run time error: fatal error: unexpectedly found nil while unwrapping an Optional value)

    Optional binding: sử dụng “if let” hoặc “if var” để kiểm tra nếu như biến có gía trị thì unwrap và sử dụng giá trị của biến, nếu không thì thôi, ví dụ:

    Cách làm này an toàn hơn vì luôn đảm bảo biến được kiểm tra xem có giá trị hay không trước khi sử dụng, tránh các trường hợp crash chương trình đáng tiếc.

    Về quan điểm cá nhân thì tốt nhất là nên dùng Optional binding khi thao tác với các biến dạng Optionals, dài hơn một chút, nhưng an toàn hơn.

    Tổng kết lại: Optionals là khái niệm mới trong Swift dùng để xử lý việc biến không có giá trị. Khai báo biến dưới dạng Optionals bằng cách thêm “?” vào sau type của biến. Và nên dùng Optionals binding để lấy giá trị của biến optionals.

    !