Skip to content
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Fx Studio
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Written by chuotfx on January 17, 2022

Multiple storyboards trong iOS

iOS & Swift . Tutorials

Contents

  • Chuẩn bị
  • Storyboards và nhược điểm
  • Tách Storyboards
  • Kết nối với một Storyboard có sẵn
  • Kết nối tới một màn hình trong một Storyboard
  • Sử dụng các màn hình trong Storyboard bằng code
  • Change Root
  • Tạm kết

Chào mừng bạn đến với Fx Studio. Chủ đề bài viết lần này là Multiple storyboards. Hướng dẫn cách sử dụng nhiều Storyboard trong một iOS Project. Qua đây, bạn sẽ thấy được cách khắc phục những nhược điểm tồn tại lâu nay của Storyboard.

Nếu bạn chưa biết gì về nó, thì có thể tìm đọc ở bài viết dưới đây:

    • Storyboard & Tạo giao diện cơ bản trong iOS

Còn nếu mọi việc đã ổn rồi, thì …

Bắt đầu thôi!

Chuẩn bị

Storyboard là một trong những tính năng được cập nhật mới trong iOS 5. Do đó, hầu như Xcode của bạn đang dùng lúc này đều đảm bảo có tính năng Storyboard trong iOS project rồi.

Như mình nói ở trên, hầu hết các dev iOS đều không thích Storyboard. Việc đầu tiên mà họ sẽ là khi tạo mới một iOS Project là sẽ xóa nó và thay đổi cấu hình project lại. Nếu bạn không biết cách xóa nó, thì hãy tham khảo bài viết dưới đây.

    • Bắt đầu iOS Project không sử dụng Storyboard với Xcode 11 và Swift 5.1

Về mặt kiến thức, yêu cầu bạn đã biết về lập trình iOS ở mức cơ bản. Mình sẽ không giải thích hay đi hướng dẫn những gì quán cơ bản, như là: IBAction, IBOutlet, UIViewController … Và nếu bạn chưa biết về lập trình iOS thì có thể đọc qua loạt bài về Lập trình iOS cho mọi người này nhóe!

Storyboards và nhược điểm

Ở bài viết trước, bạn đã tìm hiểu nhiều về Storyboard và cách tạo giao diện cơ bản trên iOS với chúng. Và mình đã nói về sự ảnh hưởng từ quá khứ & thói quen lập trình của dev iOS. Dẫn tới sự hạn chế sử dụng Storyboards trong các dự án iOS nói chung. Kinh khủng nhất là …

Nó sẽ bị xóa ngay sau khi tạo mới một iOS Project.

Có rất nhiều nhược điểm được liệt kê ra, ví dụ như:

  • Khó kéo thả các view phức tạp
  • IBOutlet & IBAction dễ gây crash app
  • Vấn đề về reusable trong các Cell của UITableView & UICollectionView
  • Sự phức tạp của hệ thống Segue Identifier
  • Thời gian build lâu
  • Code khá chậm
  • Một mớ hỗn độn khi số lượng các màn hình nhiều lên trong 1 file Storyboard
  • Vấn đề về điều hướng
  • Không tốt khi làm việc theo team và dễ bị conflict code với người khác
  • Không có tính tái sử dụng lại
  • Màn hình máy tính nhỏ quá
  • …

Cũng phải tới 7749 lý do được đưa ra, nhằm cũng cố mục đích xóa nó ra khỏi dự án. Hoặc làm cái cớ cho bạn tránh việc đổ vỏ các dự án liên quan tới Storyboards. Tuy nhiên, với sự ra đời của chip M1. Hầu như các vấn đề trên đều đã được giải quyết. Cái hạn chế tồn tại duy nhất và trường tồn với thới gian, chính là:

Suy nghĩ của bạn

Và cách giải pháp tiếp theo chính là việc tách và sử dụng nhiều Storyboards trong cùng một dự án.

Tách Storyboards

Chúng ta sẽ bắt tay vào việc demo ngay. Bạn hãy tạo một iOS Project của riêng bạn hoặc có thể làm theo ví dụ của mình. Bạn hãy yên tâm, vì giao diện cũng rất chi là đơn giản. Chúng ta sẽ bắt đầu với 2 màn hình đơn giản như sau.

Storyboards

Bạn hãy tưởng tượng đó là một Storyboard với rất nhiều màn hình.

Khi đó việc load file sẽ rất là lâu.

Và khi bạn tách chúng nhỏ thì sẽ ổn hơn rất nhiều. Bạn sẽ làm theo các bước sau:

    1. Chọn các màn hình liên quan với nhau
    2. Chọn Menu > Editor > Refactor to Storyboard
    3. Đặt tên cho Storyboard mới

Kết quả nhận được như sau:

  • Tại file Storyboard gốc

Storyboards

 

  • Tại file Storyboard mới

Storyboard

Khá nhanh & khá đơn giản, khi bạn đã có thể tách các Storyboard. Và không gây ảnh hưởng gì tới toàn bộ. Bạn hãy build và cảm nhận kết quả nào!

Kết nối với một Storyboard có sẵn

Chúng ta sẽ có một trường hợp khác, đó là bạn đã có nhiều Storyboards rồi. Công việc lúc này, bạn sẽ tìm cách kết nối chúng lại với nhau. Công việc này sẽ thực hiện được dựa vào các

Storyboard Reference

Bắt đầu, bạn sẽ tạo thêm một luồng các màn hình mới. Mình gọi nó là LoginFlow.

storyboards

Với các màn hình như sau:

    • Login
    • Register
    • Forgot Password

Chúng ta sẽ dùng một UINavigationController để kết nối chúng và điều hướng giữa các màn hình. Việc điều hướng, bạn vẫn sử dụng tới các Segue và kéo thả mà thôi (mình đã trình bày ở bài viết trước đó).

Bạn sẽ kết nối vào Storyboard khác thông qua việc tạo các Storyboard Reference trong các file Storyboard đó.

Bước tiếp theo, bạn chọn đúng Storyboard liên kết tới tại Attributes Inspector nhóe!

storyboards

Bước cuối cùng, bạn kéo thả một Segue từ một màn hình nào đó tới Storyboard Reference nhóe.

Quan trong nhất là bạn phải xác định “Is Initial View Controller” của Storyboard Reference nữa nhóe! Build lại project và cảm nhận kết quả tiếp nha!

Kết nối tới một màn hình trong một Storyboard

Trường hợp tiếp theo, bạn sẽ giải quyết vấn đề tái sử dụng lại các màn hình hay các View Controller trong project. Khắc phục được nhược điểm

Tái sử dụng & xung đột code

Lúc này, mỗi người một storyboard và họ sẽ tự quản lý cả một luồng màn hình mà họ đảm nhận. Do đó, về mặt logic của một cá nhân sẽ dễ nắm bắt hơn. Người khác có thể nhìn vào và thấy được tổng thể luồng màn hình di chuyển. Đây chính là ưu điểm của Storyboards. Và khi bạn muốn sử dụng hay gọi lại màn hình của người khác, thì hãy triệu hồi chính màn hình đó trong file storyboard của bạn.

Demo tiếp tục với các màn hình của luồng màn hình Tabbar, với UITabbarController và các màn hình như sau:

storyboards

Bạn sẽ không cần quan tâm tới chúng nhiều đâu. Vì chúng ta sẽ dùng riêng một màn hình HomeVC mà thôi. Và khi bạn muốn dùng tới HomeVC ở nơi khác, thì hãy định danh nó như sau:

  • Chọn màn hình mà bạn muốn sử dụng
  • Tại mục Identify Inspector
  • Cập nhật thêm Storyboard ID

Bạn có thể đặt tên tùy ý, tốt nhất là tránh trùng lặp với nhau. Sau đó, bạn sẽ làm giống như với cách tạo Storyboard Reference, những sẽ điền thêm Storyboard ID.

Storyboards

Kết quả như sau:

(Cập nhật luôn 2 trường hợp ở trên trong cùng một file Storyboard.)

Hãy build project và cảm nhận kết quả nhóe!

Sử dụng các màn hình trong Storyboard bằng code

Trường hợp này, dành cho các bạn không muốn sử dụng Storyboards, mà lại trúng các dự án có Storyboard. Mục đích tối thượng sẽ là:

Không đổ vỏ!

Vì cuộc đời đôi khi là thế, bạn không tự quyết định được cách bạn sống. Và tốt nhất là chung sống với chúng, học cách thích nghi nhóe.

Với demo, bạn sẽ tìm một màn hình khác ở bất kỳ Storyboard nào mà bạn muốn sử dụng. Tiếp theo, bạn sẽ tạo Storyboard ID cho nó. Tại function nào mà bạn muốn sử dụng màn hình đó, thì tham khảo đoạn code sau:

@IBAction func showVC(_ sender: Any) {
    let storyboard = UIStoryboard(name: "TabbarFlow", bundle: .main)
    let vc = storyboard.instantiateViewController(withIdentifier: "VideosVC") as! VideosVC
    
    self.present(vc, animated: true) {
        print("show VC")
    }
}

Khá đơn giản và dễ hiểu, trong đó:

  • Bước 1 là bạn sẽ lấy được storyboard mà bạn muốn lấy. Thông qua tên của chính nó.
  • Bước 2 là bạn sẽ lấy được viewcontroller mà bạn muốn lấy. Thông qua Storyboard ID của nó.
  • Cuối cùng, bạn sẽ sử dụng nó như một đối tượng bình thường.

Okay & build lại để cảm nhận kết quả nhóe!

Change Root

Vấn đề cuối cùng sẽ là thay đổi luồng màn hình chính của cả project. Hay dân gian gọi là:

Change root

Một công việc bắt buộc bạn phải làm. Dù cho việc sử dụng Storyboard hay các XIB files đi nữa. Còn với Multiple Storyboards thì cũng tương tự như với cách không sử dụng Storyboard trong việc change root này.

Đâu tiên, bạn đã có các luồng màn hình từ các ví dụ trên:

  • Tutorial
  • Login
  • Tabbar

Tiếp theo, chúng ta sẽ cấu hình chúng trong file SceneDelegate và thêm function để thực hiện change root.

enum RootType {
    case tutorial
    case login
    case tabbar
}

func changeRoot(type: RootType) {
        switch type {
        case .tutorial:
            let storyboard = UIStoryboard(name: "TutorialFlow", bundle: .main)
            let vc = storyboard.instantiateViewController(withIdentifier: "TutorialVC") as! TutorialVC
            
            self.window?.rootViewController = vc
        case .login:
            let storyboard = UIStoryboard(name: "LoginFlow", bundle: .main)
            let navi = storyboard.instantiateViewController(withIdentifier: "LoginNavi") as! UINavigationController
            
            self.window?.rootViewController = navi
            
        case .tabbar:
            let storyboard = UIStoryboard(name: "TabbarFlow", bundle: .main)
            let tabbar = storyboard.instantiateViewController(withIdentifier: "tabbar") as! UITabBarController
            
            self.window?.rootViewController = tabbar
        }
    }

Và bạn có thể khởi tạo project với việc xét root là một màn hình từ một Storyboard nhóe. Tham khảo đoạn code sau:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    let window = UIWindow(windowScene: windowScene)
    let storyboard = UIStoryboard(name: "TutorialFlow", bundle: .main)
    let vc = storyboard.instantiateViewController(withIdentifier: "TutorialVC") as! TutorialVC
            
    window.rootViewController = vc
    self.window = window
    window.makeKeyAndVisible()
}

Cuối cùng, tại các function diễn ra sự thay đổi root thì chúng ta sẽ gọi function changeRoot(:_) trên. Ví dụ, tại Login sang Tabbar như sau:

@IBAction func gotoTabbar(sender: Any) {
    guard let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate else {
        fatalError("could not get scene delegate ")
    }
    
    sceneDelegate.changeRoot(type: .tabbar)
}

Trong đó:

  • Bạn phải tìm cách lấy được sceneDelegate bằng mọi giá
  • Gọi changeRoot() để thực hiện công việc

Hoàn thiện tất cả và kết nối chúng lại với nhau. Sau đó, bạn hãy build và tiếp tục cả nhận kết quả nhóe!

Tạm kết

  • Tìm hiểu các nhược điểm khi sử dụng Storyboard trong project
  • Tách các Storyboard từ các Storyboard
  • Kết nối các Storyboard với nhau thông qua Storyboard Reference
  • Kết nối các màn hình riêng lẻ của các Storyboard trong Storyboard khác
  • Tìm các màn hình bằng code và sử dụng chúng trong project
  • Change root trong project với nhiều Storyboards

 

Okay! Tới đây, mình xin kết thúc bài viết về Multiple Storyboards trong iOS. Nếu có gì thắc mắc hay góp ý cho mình thì bạn có thể để lại bình luận hoặc gởi email theo trang Contact.

  • Bạn có thể checkout code tại đây.

Cảm ơn bạn đã đọc bài viết này!

FacebookTweetPinYummlyLinkedInPrintEmailShares5

Related Posts:

  • Text View trong 10 phút - SwiftUI Notes #25
    Text View trong 10 phút - SwiftUI Notes #25
  • Creating UI trong iOS
    Creating UI trong iOS
  • Tổng hợp về Protocol & Closure trong iOS
    Tổng hợp về Protocol & Closure trong iOS
  • Swipe Actions trong UITableViewCell
    Swipe Actions trong UITableViewCell
Tags: basic ios tutorial, iOS, Swift
Written by chuotfx

Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Donate – Buy me a coffee!

Fan page

Fx Studio

Tags

Actor Advanced Swift api AppDistribution Asynchronous autolayout basic ios tutorial blog callback ci/cd closure collectionview combine concurrency CoreData Core Location crashlytics darkmode dart dart basic dart tour Declarative decoding delegate deploy fabric fastlane firebase flavor flutter GCD iOS mapview MVVM optional protocol rxswift Swift Swift 5.5 SwiftUI SwiftUI Notes tableview testing TravisCI unittest

Recent Posts

  • Raw String trong 10 phút
  • Dispatch Semaphore trong 10 phút
  • Tổng kết năm 2022
  • KeyPath trong 10 phút – Swift
  • Make color App Flutter
  • Ứng dụng Flutter đầu tiên
  • Cài đặt Flutter SDK & Hello world
  • Coding Conventions – người hùng hay kẻ tội đồ?
  • Giới thiệu về Flutter
  • Tìm hiểu về ngôn ngữ lập trình Dart

You may also like:

  • Creating UI trong iOS
    Creating UI trong iOS
  • Tổng hợp về Protocol & Closure trong iOS
    Tổng hợp về Protocol & Closure trong iOS
  • Text View trong 10 phút - SwiftUI Notes #25
    Text View trong 10 phút - SwiftUI Notes #25
  • Multiple Grids - SwiftUI Notes #56
    Multiple Grids - SwiftUI Notes #56
  • Encoding và Decoding trong Swift
    Encoding và Decoding trong Swift

Archives

  • February 2023 (1)
  • January 2023 (2)
  • November 2022 (2)
  • October 2022 (1)
  • September 2022 (5)
  • August 2022 (6)
  • July 2022 (7)
  • June 2022 (8)
  • May 2022 (5)
  • April 2022 (1)
  • March 2022 (3)
  • February 2022 (5)
  • January 2022 (4)
  • December 2021 (6)
  • November 2021 (8)
  • October 2021 (8)
  • September 2021 (8)
  • August 2021 (8)
  • July 2021 (9)
  • June 2021 (8)
  • May 2021 (7)
  • April 2021 (11)
  • March 2021 (12)
  • February 2021 (3)
  • January 2021 (3)
  • December 2020 (3)
  • November 2020 (9)
  • October 2020 (7)
  • September 2020 (17)
  • August 2020 (1)
  • July 2020 (3)
  • June 2020 (1)
  • May 2020 (2)
  • April 2020 (3)
  • March 2020 (20)
  • February 2020 (5)
  • January 2020 (2)
  • December 2019 (12)
  • November 2019 (12)
  • October 2019 (19)
  • September 2019 (17)
  • August 2019 (10)

About me

Education, Mini Game, Digital Art & Life of coders
Contacts:
contacts@fxstudio.dev

Fx Studio

  • Home
  • About me
  • Contact us
  • Mail
  • Privacy Policy
  • Donate
  • Sitemap

Categories

  • Art (1)
  • Blog (22)
  • Code (4)
  • Combine (22)
  • Flutter & Dart (24)
  • iOS & Swift (86)
  • RxSwift (37)
  • SwiftUI (76)
  • Tutorials (70)

Newsletter

Stay up to date with our latest news and posts.
Loading

    Copyright © 2023 Fx Studio - All rights reserved.

    Share this ArticleLike this article? Email it to a friend!

    Email sent!