SwiftUI教程(八)實現(xiàn)iPhone、iPad、Mac的文章閱讀器應用熟悉SwiftUI的跨平臺操作

SwiftUI教程系列文章匯總

本文通過創(chuàng)建一個文章閱讀器應用,將SwiftUI代碼應用到多個平臺上,來實現(xiàn)跨平臺操作。主要了解如何在不同平臺間實現(xiàn)共享資源,以及如何在各自平臺使用特定資源。

主要內(nèi)容:

  1. 跨平臺應用的創(chuàng)建
  2. TabBarView和SideBarView的使用
  3. 不同平臺的特殊處理

0、介紹和演示

我們在一個平臺上編寫SwiftUI代碼,可以將其擴展到許多平臺。 這也是SwiftUI的一個很重要的特點。在本文我們將創(chuàng)建一個iOS應用程序,之后并重用它的一些組件來創(chuàng)建iPad、macOS平臺應用。

主要可以查看如何在平臺之間共享公共資源,比如模型就可以在各個平臺間共享。還可以給每個平臺使用自己特定的其他資源,比如視圖。
擁有平臺特定的視圖讓我們能夠遵循平臺特定的設計方式,并改進所提供的用戶體驗我們的應用程序。

還有其他的比如watchOS,本文不做分析。

本文將創(chuàng)建一個文章閱讀器應用,應用在iPhone、iPad、macOS平臺。

1、創(chuàng)建一個工程

創(chuàng)建一個工程

說明:

  • 注意這里是在Multiplatform創(chuàng)建APP的。
  • 只有在這里創(chuàng)建才可以實現(xiàn)在Mac和iOS上多平臺開發(fā)。

2、創(chuàng)建數(shù)據(jù)模型:

將需要顯示的文章內(nèi)容添加到數(shù)據(jù)模型中。這個數(shù)據(jù)模型是共享的,所以要放到Shared文件夾下。

為了工程文件更條理性,創(chuàng)建一個Group文件夾來存儲我們的數(shù)據(jù)模型。因為模型是在所有平臺上共享的,所以我們將創(chuàng)建在“Shared”文件夾下。右鍵點擊Shared文件夾,選擇“New Group”并命名為Models的文件夾。

文件夾

在Models文件夾中,創(chuàng)建一個新的Swift文件,命名為Article。在“Target”下,勾選“Cross-Platform(iOS)”,“Cross-Platform(macOS)”,然后選擇“創(chuàng)建”。

文件創(chuàng)建時勾選多個平臺,該文件就會在多個平臺上共享

文件創(chuàng)建

將下來在Article.swift中,創(chuàng)建一個Article結構體:

import Foundation 
struct Article: Identifiable { 
    var id = UUID() 
    let title: String 
    let description: 
    String let type: String 
}

說明:

  • 給每一篇文章都創(chuàng)建四個屬性,分別為ID,標題、描述、類型
  • 標題和描述是文章內(nèi)容本身
  • 類型是將其歸類到哪個分類。
  • id用來表示文章,用于后面的判斷

在結構體下面,創(chuàng)建三個數(shù)組,每個數(shù)組代表一個虛擬Article實例的數(shù)據(jù)。當然我們自己可以隨便寫。

數(shù)據(jù)

3、ArticleView

在SharedFolder中,創(chuàng)建一個ArticleView來顯示一個單獨的文章。 同樣,在“Targets”下,勾選“Cross-Platform(iOS)”,“Cross-Platform(macOS)”,以此讓文件在多個平臺共享。
代碼:

import SwiftUI

struct ArticleView: View {
    let article: Article
    var body: some View {
        VStack(alignment: .leading, spacing: 5) {
            Text(article.title)
            .font(.title)
            Text(article.description)
            .font(.headline)
            Spacer()
        }.padding()
    }
}

說明:

  • 文章本身只是用來顯示文章的標題和描述的視圖
  • 這里為了演示僅做簡單的展示,在實際開發(fā)中可以寫更多的視圖。

4、ArticlesListView

文章選擇列表顯示。
接下來,在Shared中,創(chuàng)建一個名為ArticlesListView的SwiftUI視圖,該視圖可以對文章進行排列。

代碼:

import SwiftUI

struct ArticlesListView: View {
    let articles: [Article ]
    var body: some View {
#if os(macOS)
        return view.frame(minWidth: 400, minHeight: 600)
#else
        return view
#endif
    }
    @ViewBuilder
    private var view: some View {
        List(articles) {article in
            NavigationLink(destination: ArticleView(article: article)) {
                ArticleView(article: article)  
            }
        }.navigationTitle("\(articles[0].type)")
    }
}

說明:

  1. 在這里,我們通過編譯器指令#if os(macOS)。檢查應用程序是否編譯為Mac設備使用
  2. 我們的代碼正在編譯中,構建指令允許我們執(zhí)行某些檢查和自定義邏輯
  3. 這對于基于不同平臺的自定義編譯的跨平臺代碼庫非常方便
  4. 因此通過對不同平臺的判斷,我們可以對于擁有更大屏幕的Mac應用程序,使用frame方法調(diào)整視圖畫面的大小
  5. 在顯示ArticlesListView時,使用了NavigationLink進行跳轉導航。
  6. 這里的列表顯示有多個文章標題,點擊后就可以跳轉到文章視圖界面。

5、TabBarView實現(xiàn)iPhone分類

接下來要對文章進行分類。

我們有三類文章:科技、商業(yè)和體育。對于iPhone,我們希望這三個類別是在底部的標簽欄中顯示為三個不同的標簽
,對于iPad和Mac,我們希望這三個類別被列在側邊欄,因此要分別進行處理,對于iPhone就需要使用TabBarView視圖進行處理。

在iOS文件夾中,新建一個SwiftUI視圖文件TabBarView.swift。注意,這里我們不需要將“Cross-Platform(macOS)”作為Target,因為它只適用于iOS。 是單獨為iPhone使用的,是特有資源。

**代碼實現(xiàn)如下 **

import SwiftUI
struct TabBarView: View {
    var body: some View {
        TabView {
            ArticlesListView(articles: techArticles)
            .tabItem {
                Image(systemName: "desktopcomputer")
                Text("Tech")
            }.tag(0)
            ArticlesListView(articles: businessArticles)
            .tabItem {
                Image(systemName: "dollarsign.circle")
                Text("Science")
            }.tag(1)
            ArticlesListView(articles: sportArticles)
            .tabItem {
                Image(systemName: "sportscourt")
                Text("Design")
            }.tag(2)
        }.navigationTitle("Articles")
    }
}

說明:

  • 在TabView內(nèi)使用之前定義的ArticlesListView
  • 每個選項卡都填充之前定義好的Article數(shù)組
  • 這樣在切換三種選項卡的時候,就可以顯示對應的文章內(nèi)容。
  • 使用.tabitem修飾符來設置每個標簽的圖像和文本的樣式。
  • 圖片是使用systemName創(chuàng)建的,它允許我們從內(nèi)置的SF Symbols圖標集wh中加載圖片
  • 使用tag()來定位它們的制表符順序。

開始運行
在ContentView中添加代碼:

struct ContentView: View { 
    var body: some View { 
        NavigationView{ 
            TabBarView() 
        } 
    } 
}

說明:

  • 將TabBarView添加到一個NavigationView中
  • 這樣可以確保在ArticlesListView可以使用NavigationLink
  • 當您導航到不同的標簽類別時,該類別的文章就會顯示出來

結果:

結果

6、SideBarView實現(xiàn)Mac

側邊欄導航是一個三列導航,提供對頂級集合的快速訪問。 需要使用SideBarView來實現(xiàn)。

在macOS文件夾下,創(chuàng)建一個新的SwiftUI視圖文件SideBarView.swift。 在創(chuàng)建時,同時選擇iOS和Mac版本,雖然iPhone不使用SideBarView,但是我們還需要將這個文件作用于iPad。所以需要在多個平臺進行使用。是共享資源。

import SwiftUI

struct SideBarView: View {
    @ViewBuilder
    var body: some View {
        List() {
            NavigationLink(
                destination: ArticlesListView(articles: techArticles),
                label: {
                    Label("Tech", systemImage: "desktopcomputer")
                }
            )
            NavigationLink(
                destination: ArticlesListView(articles: businessArticles) ,
                label: { Label("Business", systemImage: "dollarsign.circle")
                }
            )
            NavigationLink(
                destination: ArticlesListView(articles: sportArticles),
                label: { Label("Sport", systemImage: "sportscourt") }
            )
        }
        .navigationTitle("Articles")
        .listStyle(SidebarListStyle())
    }
}
  • 在實現(xiàn)上使用了iOS 14和macOS Big Sur上新的SideBarListStyle列表樣式。
  • 其他的點擊跳轉實現(xiàn)和iPhone上的一樣。
  • 通過這種新的樣式就可以顯示出側邊欄使用List列出文章類型的三種類型的效果
  • 注意一下listStyle

運行:
在ContentView中,注釋掉TabBarView并添加SideBarView:

struct ContentView: View { 
    var body: some View { 
        NavigationView{ 
            //TabBarView() 
            SideBarView() 
        }
    } 
}

修改后,在Mac上運行這個應用程序時,就會在Mac上得到一個三級導航文章閱讀應用程序,如下圖所示:

Mac

7、iPad實現(xiàn)

上面我們知道Mac和iPad使用SideBarView來顯示,iPhone使用TabBarView來顯示。而iPad又屬于iOS,所以我們需要在ContentView視圖中進行判斷這三種情況.

使用#if來檢測應用程序在哪個操作系統(tǒng)上運行,同時使用horizontalSizeClass屬性來檢測設備是iPad還是iPhone。

代碼:

import SwiftUI

struct ContentView: View {
#if os(iOS)
    @Environment(\.horizontalSizeClass) var horizontalSizeClass:UserInterfaceSizeClass?
#endif
    @ViewBuilder
    var body: some View {
        NavigationView {
#if os(iOS)
            if horizontalSizeClass == .compact {
                TabBarView()
            } else {
                SideBarView()
            }
#else
            SideBarView()
#endif
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

說明:

  • 創(chuàng)建一個@Environment對象來存儲size類的值。
  • 通過檢查size類的值是否為"compact"size類來判斷shi否為iPad或iPhone。
  • 因為iphone的尺寸是“compact”,而ipad的尺寸是“compact”。
  • 因此,如果size為compact (iPhone),我們將顯示TabBarView。否則是iPad或Mac,我們顯示SideBarView。

如果我們運行在iPad上,將會顯示為

iPad

8、總結

  • 跨平臺實現(xiàn)的實現(xiàn)需要在Multiplatform下創(chuàng)建工程
  • 可以在創(chuàng)建文件時選擇不同的平臺,來決定是否是多平臺共享資源
  • Mac和iOS可以通過編譯器指令#if os(macOS)來判斷
  • iPhone和iPad可以通過尺寸大小來判斷
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容