将JSON提取到ViewController并选择到第二个ViewController

时间:2019-03-05 23:43:33

标签: ios xcode api swift4.2

我已经从JSON格式的API中提取数据并将其解析到FirstViewController,并希望使用从FirstViewController具体人员处选择的数据将其隔离到SecondViewController。问题是我有一个带有以下示例网址的API:https://www.example.com/api/?action= &ln = en,该人以这种格式提供了我所有的人:

[
  {
    "p_id": "4107",
    "p_name": "Name1 Surname1",
    "p_role": "Role1",
    "general_image": "/imagedb/persons/4107/main/1.jpg"
  },{
    "p_id": "1978",
    "p_name": "Name2 Surname2",
    "p_role": "Role2",
    "general_image": "/imagedb/persons/1978/main/1.jpg"
  }, {...
...}
]

我正在CollectionView的FirstViewController中显示所有这些人,这些人正常工作,带有图像,名称和角色。但是我还需要显示FirstVC中选择的数据来显示我的SecondViewController。我的personByID API类似于以下URL:https://www.example.com/api/?action= person &ln = en&personId = 1978,它以以下格式提供了JSON数据:

{
"p_id": "1978",
"p_category": "[2]",
"p_name": "Name2 Surname2",
"p_role": "Role2",
"p_short": null,
"p_text": "long text...",
"p_date_start": "1922.02.05",
"p_date_end": "",
"p_profile_image": "1",
"p_status": "1",
"p_lang": "en",
"general_image": "/imagedb/persons/1978/main/1.jpg",
"photos": [
    {
        "image_id": "5",
        "p_id": "1978",
        "lang": "en",
        "text": "some text...",
        "general": "/imagedb/persons/1978/5.jpg",
        "thumbs": "/imagedb/persons/1978/thumb/5.jpg"
    },
    {
        "image_id": "7",
        "p_id": "1978",
        "lang": "en",
        "text": "some text...",
        "general": "/imagedb/persons/1978/7.jpg",
        "thumbs": "/imagedb/persons/1978/thumb/7.jpg"
    }
]
}

这是我的人员结构:

struct Person {
 let id: String
 let name: String
 let role: String
 fileprivate let imageURLString: String

 var imageURL: URL? {
    return URL(string: "https://www.example.com\(imageURLString)")
 }
}

 extension Person: JSONDecodable {
  init(_ decoder: JSONDecoder) throws {
     self.id = try decoder.value(forKey: "p_id")
     self.name = try decoder.value(forKey: "p_name")
     self.role = try decoder.value(forKey: "p_role")
     self.imageURLString = try decoder.value(forKey: "general_image")
 }
}

这是我的第一个VC:

import UIKit

class PersonListViewController: UIViewController {

@IBOutlet weak var collectionView: UICollectionView!

var personPages: [PagedResult<Person>] = [] {
    didSet {
        DispatchQueue.main.async {
        self.collectionView.reloadData()
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    loadPersons()
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    guard let selectedIndexPath = collectionView.indexPathsForSelectedItems?.first else {
        return
    }
    collectionView.deselectItem(at: selectedIndexPath, animated: animated)
}

var service = ExampleWebService()
private func loadPersons(page: Int = 0, resultsPerPage: Int = 5) {
    service.persons(page: page, resultsPerPage: resultsPerPage) { (personPage) in
        guard !self.loadedPersonPageNumbers.contains(page) else { return }
        self.personPages.append(personPage)
        self.updateLastIndexPath(personPage)
    }
}

private(set) var lastIndexPath: IndexPath?
private func updateLastIndexPath(_ personPage: PagedResult<Person>) {
    if personPage.results.isEmpty {
        lastIndexPath = nil
    }
    else {
        lastIndexPath = calculateLastIndexPath()
    }
}

private func calculateLastIndexPath() -> IndexPath? {
    guard let lastPage = personPages.last else { return nil }
    let section = lastPage.pageNumber
    let row = lastPage.results.count - 1
    return IndexPath(row: row, section: section)
}

fileprivate var loadedPersonPageNumbers: [Int] {
    return personPages.map { $0.pageNumber }
}

func person(at indexPath: IndexPath) -> Person? {
    guard indexPath.section < personPages.count else {
        return nil
    }
    guard indexPath.row < personPages[indexPath.section].results.count else {
        return nil
    }
    let page = personPages[indexPath.section]
    return page.results[indexPath.row]
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard let personViewController = segue.destination as? PersonViewController,
        let selectedIndexPath = collectionView.indexPathsForSelectedItems?.first else {
        return
    }
    personViewController.person = person(at: selectedIndexPath)
}

 @IBAction func exitToPersonsView(segue: UIStoryboardSegue) {

 }
}

extension PersonListViewController: UICollectionViewDelegate {
 fileprivate var nextPageIndex: Int {
    guard let lastPage = personPages.last else {
        return 0
    }

    return lastPage.pageNumber.advanced(by: 1)
 }

 func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if indexPath == lastIndexPath {
        loadPersons(page: nextPageIndex)
    }
 }
}
extension PersonListViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {

    return personPages.count
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    return personPages[section].results.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell: PersonListCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! PersonListCollectionViewCell

    cell.person = person(at: indexPath)

    return cell
}
}

extension PersonListViewController: UINavigationBarDelegate {
 func position(for bar: UIBarPositioning) -> UIBarPosition {
    return .topAttached
 }
}

这是我的第二个VC:

import Foundation
import UIKit

final class PersonViewController: UIViewController {

@IBOutlet weak var imagesCollectionVIew: UICollectionView!
@IBOutlet weak var personRole: UILabel!
@IBOutlet weak var customNavigationBar: UINavigationBar!

var personImagesByID: [PagedResult<Person>] = [] {
    didSet {
        DispatchQueue.main.async {
            self.imagesCollectionVIew.reloadData()
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    loadPersonImagesByID()
}

var person: Person?

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if let person = person {
        title = person.name
        personRole.text = person.role
    }
    customNavigationBar.topItem?.title = title
}

var service = ExampleWebService()
private func loadPersonImagesByID(page: Int = 0, resultsperPge: Int = 5) {
    service.persons(page: page, resultsPerPage: resultsperPge) { (personPage) in
        guard !self.loadedPersonPageNumbers.contains(page) else {
            return
        }
        self.personImagesByID.append(personPage)
        self.updateLastIndexPath(personPage)
    }
}

private(set) var lastIndexPath: IndexPath?
private func updateLastIndexPath(_ personPage: PagedResult<Person>) {
    if personPage.results.isEmpty {
        lastIndexPath = nil
    }
    else {
        lastIndexPath = calculateLastIndexPath()
    }
}

private func calculateLastIndexPath() -> IndexPath? {
    guard let lastPage = personImagesByID.last else {
        return nil
    }
    let section = lastPage.pageNumber
    let item = lastPage.results.count - 1
    return IndexPath(row: item, section: section)
}

fileprivate var loadedPersonPageNumbers: [Int] {
    return personImagesByID.map { $0.pageNumber }
}

 func person(at indexPath: IndexPath) -> Person? {
    guard indexPath.section < personImagesByID.count else {
        return nil
    }
    guard indexPath.item < personImagesByID[indexPath.section].results.count else {
        return nil
    }
    let page = personImagesByID[indexPath.section]
    return page.results[indexPath.item]
 }
}

extension PersonViewController: UICollectionViewDelegate {
 fileprivate var nextPageIndex: Int {
    guard let lastPage = personImagesByID.last else {
        return 0
    }
    return lastPage.pageNumber.advanced(by: 1)
 }

 func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if indexPath == lastIndexPath {
        loadPersonImagesByID(page: nextPageIndex)
    }
 }
}

extension PersonViewController: UICollectionViewDelegateFlowLayout {
 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    return CGSize(width: self.imagesCollectionVIew.frame.height - 17, height: self.imagesCollectionVIew.frame.height - 17)
 }
}

extension PersonViewController: UICollectionViewDataSource {
 func numberOfSections(in collectionView: UICollectionView) -> Int {
    return personImagesByID.count
 }

 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return personImagesByID[section].results.count
 }

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell: PersonViewCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImagesCollectionViewCell", for: indexPath) as! PersonViewCollectionViewCell

    cell.person = person(at: indexPath)

    return cell
 }
}

extension PersonViewController: UINavigationBarDelegate {
 func position(for bar: UIBarPositioning) -> UIBarPosition {
    return .topAttached
 }
}

现在我的问题是我遇到了一个问题,即如何正确编写我的第二个结构PersonByID,以及在单击第一个VC中的人以从personByID URL路径向我显示第二个VC中的数据时。

0 个答案:

没有答案