Swift

iOS Developer เขียนแอป iPhone ดึง JSON Image ด้วย SDWebImageSwiftUI

บทเรียนการเขียน SwiftUI สำหรับการพัฒนาแอปพลิเคชัน iOS หรือ iPhone ดึงรูปภาพจาก JSON มาแสดงด้วย SDWebImageSwiftUI

บทเรียนการเขียน SwiftUI สำหรับการพัฒนาแอปพลิเคชัน iOS หรือ iPhone ดึงรูปภาพจาก JSON มาแสดงด้วย SDWebImageSwiftUI เบื้องต้น

บทเรียนก่อนหน้า SwiftUI:

สำหรับนักพัฒนาแอปพลิเคชันของเรา เวลาดึงข้อมูลจาก JSON หรือเว็บเซอร์วิส (Web Services) หลายครั้งที่เราจำเป็นต้อง Feed เนื้อหามาแสดงเหมือนในบทความก่อนหน้า เขียนแอป iPhone การเรียก JSON Web API ด้วย SwiftUI ซึ่งเราไม่ได้พูดถึง ส่วนประกอบหลักคือรูปภาพ หรือวิดีโอ การเขียนแอปพลิเคชันจำเป็นต้องทำฟังก์ชันสำหรับการเก็บแคช Cache รูปภาพที่โหลดมาจาก JSON ออนไลน์

ทางเลือกสำหรับสาย SwiftUI หรือ iOS Developer นั้นก็คงจะต้องเลือก Library ยอดฮิต อย่าง SDWebImage ที่มีฟังก์ชันจัดการ Cache Image ที่โหลดจาก JSON Web Services ได้ซึ่งตอนนี้ SDWebImage เองก็มี Library ของ SwiftUI โดยเฉพาะคือ SDWebImageSwiftUI

git repo: https://github.com/SDWebImage/SDWebImageSwiftUI

มาเริ่มเขียนโปรแกรมกันดีกว่า:

ตัวอย่างนี้เราจะใช้ Web Services ของผมเองที่ทำเล่น https://enet5-7f9f6.firebaseio.com/Books.json

เป็นหน้าหนังสือจากเว็บไซต์ https://www.creativethailand.org/magazine ซึ่งโครงสร้าง JSON เป็นดังนี้:

[
    {
        "id" :0,
        "title": "Life After Covid-19",
        "thumbnail": "https://www.creativethailand.org/admin/public/uploads/images/2563/06/cover/MagazineCover_185.jpg"
    },
    {
        "id" :1,
        "title": "Creativity Must Go On",
        "thumbnail": "https://www.creativethailand.org/admin/public/uploads/images/2563/05/cover/MagazineCover_184.jpg"
    },
    {
        "id" :2,
        "title": "Living with COVID-19",
        "thumbnail": "https://www.creativethailand.org/admin/public/uploads/images/2563/04/cover/MagazineCover_182.jpg"

    },
    {
        "id" :3,
        "title": "Look Isan Now",
        "thumbnail": "https://www.creativethailand.org/admin/public/uploads/images/2563/03/cover/MagazineCover_180.jpg"
    },
    {
        "id" :4,
        "title": "VERTICAL LIVING: WHY DO WE ALWAYS LIVE HIGHER?",
        "thumbnail": "https://www.creativethailand.org/admin/public/uploads/images/2563/02/cover/MagazineCover_181.jpg"
    },
    {
        "id" :5,
        "title": "THE FUTURE OF WORK IS NOW",
        "thumbnail": "https://www.creativethailand.org/admin/public/uploads/images/2563/01/cover/MagazineCover_177.jpg"
    }
]

ทำการ New Single View Application บน XCode ขึ้นมาเลย:

ตั้งชื่อแนวๆ เช็คว่าเป็น SwiftUI หรือเปล่า

ทีนี้เราต้องเพิ่ม Library เข้าไปยัง Project โดย XCode 11 ขึ้นมา(ตอนนี้ใช้ 11.5) จะมีวิธีการที่เรียกว่า App integration โดยโหลด Package Dependencies มาที่แอปเราได้เลยตรงๆ ให้ทำวิธีนี้ (ส่วนใครใช้ cocoapods สบายง่ายๆ)

คลิกที่ XCode Project หลังจากนั้นสังเกตที่ตำแหน่ง General เลื่อนไปที่ Frameworks, Libraries, and Embedded Content หาเครื่องหมาย +

คลิกแล้วจะพบหน้าต่างดังภาพด้านล่างนี้ครับ ให้คลิกที่ Add Other เลือก Add Package Dependency…

เมื่อคลิกแล้วจะมีช่องกรอก Package Dependencies ให้เราใส่ URL: https://github.com/SDWebImage/SDWebImageSwiftUI.git 

ลงไปบนช่อง

เมือ่เสร็จแล้วกด Next รอระบบประมวลผลประมาณนึง จะมีหน้าต่างบอกให้เลือก ผมเลือก Version เป็น Up to Next Major เลยอัพเด็ตดี

เมื่อ Library พร้อมใช้มันจะขึ้นหน้าจอนี้

ตรวจสอบดูอีกรอบ ถ้าเป็นแบบภาพข้าวล่างคือโอเค ส่วนของ XCode Project เราพร้อมใช้งานแล้ว

ไปที่ ContentView.swift เขียนโปรแกรมกันให้ประกาศตัวแปร import บน Header เพิ่มคือ:

import SDWebImageSwiftUI

สร้าง Class ใหม่ขึ้นมาดังนี้:

class datas : ObservableObject{
    @Published var jsonData = [datatype]()
    
}

หลังจากนั้นกำหนด ฟังก์ชัน Struct ใหม่เป็นการกำหนด DataType ให้กับ Key JSON:

struct datatype : Identifiable, Decodable {
    var id : Int
    var thumbnail : String
    var title : String
}

เราจะเก็บค่า Key ของ id, title และ thumbnail ตาม Data Type ของมัน ไปที่ struct ContentView() เขียนคำสั่งต่อไปนี้:

struct ContentView: View {
    @ObservedObject var getData = datas()
    var body: some View {
        //Text("Hello, World!")
        NavigationView {
            List(getData.jsonData){ i in
                ListRow(name: i.title, thumbnail: i.thumbnail)
            }
            .navigationBarTitle("Books")
        }
    }
}

เราจะทำการสร้าง NavigationView โดยไปเรียก ListRow เป็นเหมือน Class นึงที่จัดการ Binding ข้อมูลของการส่ง title และ Thumbnail มาแสดงผลแถวแต่ละแถว ผ่าน List ที่ดึงจาก jsonData ใน Class ชื่อ datas ที่เราสร้างขึ้น ดังนั้นเราต้องไปเพิ่ม คำสั่งใน Class ของ datas()

init(){
        let session = URLSession(configuration: .default)
        session.dataTask(with: URL(string:"https://enet5-7f9f6.firebaseio.com/Books.json")!){
            (data, _, _) in
            do{
                let fetch = try JSONDecoder().decode([datatype].self, from: data!)
                DispatchQueue.main.async {
                    self.jsonData = fetch
                }
            }catch{
                print(error.localizedDescription)
            }
        }.resume()
    }

เป็นคำสั่งในการเรียก API ของ URL ที่เป็น Webservices หรือ JSON มาทำการ Decode JSON และ Fetch ข้อมูลเก็บในตัวแปล jsonData

เพิ่ม struct หรือฟังก์ชันในการจัดการ แถว หรือ Row ในรายการของ List กันหน่อยชื่อ ListRow() ตามที่เราตั้งชื่อใน NavigationView ข้างต้น ผมจะใช้ HStack เพื่อเรียงการแสดงผลเป็นแนว Horizontal รูปทางซ้าย ชื่อหนังสือทางขวา

struct ListRow : View {
    var name : String
    var thumbnail : String
    var body : some View{
        HStack{
            AnimatedImage(url: URL(string: thumbnail))
            .resizable()
            .transition(.fade)
            .scaledToFit()
                .frame(width: 100, height: 200)
           
            Text(name).fontWeight(.regular).padding(.leading, 10)
        }
    }
}

อ่ะมาดูกันว่าไฟล์ ContentView.swft ทั้งหมดเป็นยังไง:

//
//  ContentView.swift
//  SDWebSwiftUI
//
//  Created by Banyapon Poolsawas on 3/6/2563 BE.
//  Copyright © 2563 Banyapon Poolsawas. All rights reserved.
//

import SwiftUI
import SDWebImageSwiftUI

struct ContentView: View {
    //3
     @ObservedObject var getData = datas()
    var body: some View {
        //Text("Hello, World!")
        //4
        NavigationView {
            List(getData.jsonData){ i in
                ListRow(name: i.title, thumbnail: i.thumbnail)
            }
            .navigationBarTitle("Books")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
//1
class datas : ObservableObject{
    @Published var jsonData = [datatype]()
    //5
    init(){
        let session = URLSession(configuration: .default)
        session.dataTask(with: URL(string:"https://enet5-7f9f6.firebaseio.com/Books.json")!){
            (data, _, _) in
            do{
                let fetch = try JSONDecoder().decode([datatype].self, from: data!)
                DispatchQueue.main.async {
                    self.jsonData = fetch
                }
            }catch{
                print(error.localizedDescription)
            }
        }.resume()
    }
}
//2
struct datatype : Identifiable, Decodable {
    var id : Int
    var thumbnail : String
    var title : String
}

//6
struct ListRow : View {
    var name : String
    var thumbnail : String
    var body : some View{
        HStack{
            AnimatedImage(url: URL(string: thumbnail))
            .resizable()
            .transition(.fade)
            .scaledToFit()
                .frame(width: 100, height: 200)
           
            Text(name).fontWeight(.regular).padding(.leading, 10)
        }
    }
}

ทดสอบโดยการรันผ่าน Simulator กันดูหน่อย

ลองเอาไปฝึกดูนะครับ สรุปคือ SwiftUI เป็นภาษาที่ยังไม่ค่อย Smooth และหาแนวทางตัวเองไม่ชัดเท่าไร อาจจะต้องรออีกสักพักถึงจะเสถียรครับ

Asst. Prof. Banyapon Poolsawas

อาจารย์ประจำสาขาวิชาการออกแบบเชิงโต้ตอบ และการพัฒนาเกม วิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี มหาวิทยาลัยธุรกิจบัณฑิตย์ ผู้ก่อตั้ง บริษัท Daydev Co., Ltd, (เดย์เดฟ จำกัด)

Related Articles

Back to top button

Adblock Detected

เราตรวจพบว่าคุณใช้ Adblock บนบราวเซอร์ของคุณ,กรุณาปิดระบบ Adblock ก่อนเข้าอ่าน Content ของเรานะครับ, ถือว่าช่วยเหลือกัน