#10 Instagram照片牆

Tai
彼得潘的 Swift iOS / Flutter App 開發教室
10 min readNov 19, 2022

IG是現在必備的社交軟體,在個人資訊會有一個PO文圖片的照片牆,今天利用API及JOSON模擬製作照片牆,建置步驟如下:

由於IG官方未提供下載PO文圖的API,故利用網路上有人研究出來的方式抓取JSON檔後,放置在Xcode左邊的檔案樹狀圖區下,再使用程式碼讀取JSON檔內容。

使用下方API抓取IG的PO文圖片及文字檔(下方"iambaijiji”可以置換成想要抓取的帳號):

https://www.instagram.com/iambaijiji/?__a=1&__d=dis

  1. 在編輯區內新增Collection View Controller,IG的個人檔案畫面中,最上方是個人檔案的部份,需在Collection View Controller將Accessories這個項目打勾,顯示表頭。

2. 新增1個Table View Controller,並拉Collection View Cell連線給這個Controller用來顯示圖片詳細內容,並完成2個Controller中要呈現畫面的元件

3. 接下來解析JSON,並將下載下來的JSON檔放置在Xcode左側的樹狀圖區,撰寫程式碼讀取

JSON解析檔:

struct IGResponse: Codable {
var graphql: Graphql
struct Graphql: Codable {
var user: User
struct User: Codable {
var biography: String //作者簡介
var external_url: URL //白吉FB首頁
var edge_followed_by: EdgeFollowedBy //粉絲追蹤數
struct EdgeFollowedBy: Codable {
var count: Int //粉絲追蹤數
}
var edge_follow: EdgeFollow
struct EdgeFollow: Codable {
var count: Int
}
var full_name: String //大頭照下方名字
var category_name: String //名字下方類型
var profile_pic_url: URL //個人檔案大頭照
var username: String //最上方IG使用者名字
var edge_felix_video_timeline: VideoDetail //影片貼文資訊
struct VideoDetail: Codable {
var count: Int //影片貼文數
var page_info: VideoPageInfo //影片貼文是否有下一頁
struct VideoPageInfo: Codable {
var has_next_page: Bool
var end_cursor: String
}
var edges: [VideoEdges]
struct VideoEdges: Codable {
var node: VideoNode
struct VideoNode: Codable {
var video_url: URL //影片url
var edge_media_to_caption: EdgeMediaToCaption //影片貼文文字
struct EdgeMediaToCaption: Codable {
var edges: [VideoEdgeNode]
struct VideoEdgeNode: Codable {
var node: Text

struct Text: Codable {
var text: String //影片貼文
}
}
}
var edge_media_to_comment: EdgeMediaToComment //影片貼文留言數
struct EdgeMediaToComment: Codable {
var count: Int //影片貼文留言數
}
var edge_liked_by: EdgeLikedBy
struct EdgeLikedBy: Codable {
var count: Int //影片貼文按讚數
}
}
}
}
var edge_owner_to_timeline_media: PhotoDetail //照片貼文資訊
struct PhotoDetail: Codable {
var count: Int //照片貼文數
var page_info: PhotoPageInfo //照片貼文是否有下一頁
struct PhotoPageInfo: Codable {
var has_next_page: Bool
var end_cursor: String
}
var edges: [Edges]
struct Edges: Codable {
var node: PhotoNode
struct PhotoNode: Codable {
var display_url: URL //照片貼文圖片
var edge_media_to_caption: EdgeMediaToCaption //照片貼文文字
struct EdgeMediaToCaption: Codable {
var edges: [PhotoEdges]
struct PhotoEdges: Codable {
var node: PhotoEdgesNode
struct PhotoEdgesNode: Codable {
var text: String //照片貼文文字
}
}
}
var edge_media_to_comment: EdgeMediaToComment
struct EdgeMediaToComment: Codable {
var count: Int //圖片貼文留言數
}
var edge_liked_by: EdgeLikedBy
struct EdgeLikedBy: Codable {
var count: Int //圖片貼文安讚數
}
}
}
}

}
}
}

讀取JSON檔的程式碼(iambaijiji.json):

//在ViewDidLoad()中呼叫
let searchResponse: IGResponse = load("iambaijiji")

//在第一頁的類別檔中的函數
func load<T: Decodable>(_ filename: String) -> T {
let data: Data

guard let file = Bundle.main.url(forResource: filename, withExtension: "json") else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) in main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}

4. 設定Cell的大小及間距

func configureCellSize() {
let itemSpace: Double = 4
let columnCount: Double = 3
let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout
let width = floor((collectionView.bounds.width - itemSpace * (columnCount - 1)) / columnCount)
flowLayout?.itemSize = CGSize(width: width, height: width)
flowLayout?.estimatedItemSize = .zero
flowLayout?.minimumInteritemSpacing = itemSpace
flowLayout?.minimumLineSpacing = itemSpace
}

5. 自定義Collection View Cell後,在第一頁將拉@IBSegueAction用來點擊Cell時將資料傳給第二頁

@IBSegueAction func showDetailSegue(_ coder: NSCoder) -> DetailTableViewController? {
guard let row = collectionView.indexPathsForSelectedItems?.first?.row else { return nil}
return DetailTableViewController(coder: coder, userInfo: userInfo!, indexPath: row)

}

6. 第二頁定義好接收的變數

let searchResponse: String
let postInfo:IGResponse.Graphql.User.PhotoDetail
let indexPath:Int
let userImageUrl:URL
let userAcount:String

init?(coder:NSCoder,userInfo:IGResponse, indexPath:Int ) {
self.postInfo = userInfo.graphql.user.edge_owner_to_timeline_media
self.indexPath = indexPath
self.userImageUrl = userInfo.graphql.user.profile_pic_url
self.userAcount = userInfo.graphql.user.username
self.searchResponse = userInfo.graphql.user.full_name
super.init(coder: coder)
}

7. 進入第二頁時,想直接跳到第一頁點選的圖片

//詳細頁面跳到所選的圖片位置
var isShow = false
override func viewDidLayoutSubviews() {
if isShow == false{
tableView.scrollToRow(at: IndexPath(item: indexPath, section: 0), at: .top, animated: true)
isShow = true

}
}

8. 自己製作返回上一頁的按鈕( < )

@IBAction func backToPrepage(_ sender: Any) {
self.dismiss(animated: true)
}

以上就是使用Collection View製作圖片牆主要步驟~收工!回家吃飯~~~

完成圖:

--

--

Tai
彼得潘的 Swift iOS / Flutter App 開發教室

跌跌撞撞走了編碼人生的前半段,一切又得重來~但勇敢站起來,決定從 IOS APP 作為下一個人生段的起點,好好的再走他一段編碼人生!