I want to know how to get each name from the parsed json response in swift. I want to assign the name value of the reponse to cell.label.text based on my code cell.label.text = item.name. Label will automate depending on how many item.name , what I want is that it will automate depending on how many name there is from json response
if indexPath.row == 0 {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AddNewCell", for: indexPath as IndexPath) as! AddNewCollectionViewCell
cell.backgroundColor = unselectedCellColor // make cell more visible in our example project
return cell
} else {
let index = IndexPath(row: (indexPath.row - 1), section: 0)
let item = fetchedResultsController.object(at: index)
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! GroceryItemCollectionViewCell
cell.buttonDelegate = self
cell.deleteButton.tag = indexPath.row - 1
cell.label.text = item.name
if item.isSelected {
cell.backgroundColor = selectedCellColor
} else {
cell.backgroundColor = unselectedCellColor
}
return cell
}
Http request code:
responseString = Optional("[{\"id\":51,\"name\":\"jelord\",\"desc\":\"ako si jelord\",\"reward\":\"1.00\",\"sched\":\"2018-04-06T11:37:09+08:00\",\"parent\":null,\"child\":null,\"occurrence\":{\"name\":\"once\"},\"status\":\"created\"},{\"id\":53,\"name\":\"uuuuuu\",\"desc\":\"uuuuu\",\"reward\":\"8.00\",\"sched\":\"2018-03-06T10:49:54+08:00\",\"parent\":null,\"child\":null,\"occurrence\":{\"name\":\"once\"},\"status\":\"created\"},{\"id\":54,\"name\":\"iiiii\",\"desc\":\"oiii\",\"reward\":\"67.00\",\"sched\":\"2018-02-06T10:51:34+08:00\",\"parent\":null,\"child\":null,\"occurrence\":{\"name\":\"once\"},\"status\":\"created\"},{\"id\":55,\"name\":\"uuuu\",\"desc\":\"uuuu\",\"reward\":\"8.00\",\"sched\":\"2018-03-06T10:52:55+08:00\",\"parent\":null,\"child\":null,\"occurrence\":{\"name\":\"once\"},\"status\":\"created\"},{\"id\":57,\"name\":\"uuuuuuuu\",\"desc\":\"uuuuuu\",\"reward\":\"8888.00\",\"sched\":\"2018-04-06T11:54:16.431000+08:00\",\"parent\":null,\"child\":null,\"occurrence\":{\"name\":\"once\"},\"status\":\"created\"},{\"id\":61,\"name\":\"hhu\",\"desc\":\"yhh\",\"reward\":\"67.00\",\"sched\":\"2018-02-06T13:45:09+08:00\",\"parent\":null,\"child\":null,\"occurrence\":{\"name\":\"once\"},\"status\":\"created\"},{\"id\":62,\"name\":\"huhu\",\"desc\":\"huu\",\"reward\":\"8.00\",\"sched\":\"2018-04-06T14:46:36.620000+08:00\",\"parent\":null,\"child\":null,\"occurrence\":{\"name\":\"once\"},\"status\":\"created\"}]")
code for getting the request.
var request = URLRequest(url: URL(string: "http://test.test:8000/api/v1/test/")!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
}
task.resume()
import UIKit
import Alamofire
class MenuCollectionViewController: UIViewController,
UICollectionViewDelegate, UICollectionViewDataSource {
var titleArray = [String]()
#IBOutlet var collectionView: UICollectionView!
#IBAction func signOutButtonIsPressed(_ sender: Any) {
let appDelegate : AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.showLoginScreen()
}
#IBOutlet var signoutButton: UIButton!
var items = [Item]()
override func viewDidLoad() {
super.viewDidLoad()
self.signoutButton.layer.cornerRadius = 3.0
demoApi()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.isHidden = true
self.navigationItem.hidesBackButton = true
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titleArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionCell
cell.nameLabel.text = titleArray[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
}
func demoApi() {
Alamofire.request("https://jsonplaceholder.typicode.com/posts", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
guard let json = response.result.value as! [[String:Any]]? else{ return}
print("Response \(json)")
for item in json {
if let title = item["title"] as? String {
self.titleArray.append(title)
}
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
break
case .failure(_):
print("Error")
break
}
}
}
}
class CollectionCell: UICollectionViewCell {
#IBOutlet weak var imgPhoto: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
}
Related
I am trying to make api call and print the result at UICollectionView cellForItemAt function but UICollectionView is lagging while fetching data from api. I tried collection view prefetching api but I couldn't implement it. How can I solve lagging scroll problem? Here is the problem:
Here is my api call class:
class ApiManager {
static var url: String?
static var header: [String : String]?
static var httpMethod: String?
static let session = URLSession.shared
static func getTask(itemName: String, completion:#escaping ([String]) -> Void) -> URLSessionDataTask {
let url = URL(string: ApiManager.url!)
var request = URLRequest(url: url!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.allHTTPHeaderFields = ApiManager.header!
request.httpMethod = ApiManager.httpMethod
let session = ApiManager.session
let dataTask = session.dataTask(with: request) { data, response, error in
if error == nil && data != nil {
if (error != nil) {
print(error!)
} else {
do {
if let dictionary = try JSONSerialization.jsonObject(with: data!, options: []) as? [[String:Any]] {
var itemArray = [String]()
for index in 0...dictionary.count - 1 {
if let items = dictionary[index][itemName] as? String {
itemArray.append(items)
}
}
completion(itemArray)
}
} catch {
}
}
}
}
return dataTask
}
}
Here is my ViewController code:
class ViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
var quoteArray = [String]()
var categories = ["love", "motivational", "mothersday", "all"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
for category in categories {
ApiManager.url = "https://famous-quotes4.p.rapidapi.com/random?category=\(category)&count=1000"
}
ApiManager.header = ["x-rapidapi-host": "famous-quotes4.p.rapidapi.com", "x-rapidapi-key": "SECRET_API_KEY" ]
ApiManager.httpMethod = "GET"
ApiManager.getTask(itemName: "text") { items in
DispatchQueue.main.async {
self.quoteArray.append(contentsOf: items)
self.collectionView.reloadData()
}
}.resume()
}
}
Here is my cellForItemAt func code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? Cell else { fatalError("cell dequeue error") }
cell.label.text = self.quoteArray[indexPath.row]
return cell
}
This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 4 years ago.
I have created an App using xcode 10 and use swift 4.
I am getting an error:
Fatal error: Unexpectedly found nil while unwrapping an Optional value`
I started to use NavigationController, and now I get an error. When doing Segue in the state before use, no error occurred.
I checked for Typo's etc, but there is no problem.
Error is this part
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
switch indexPath.section {
case 0 :
//Price Cell
let priceCell = tableView.dequeueReusableCell(withIdentifier: "priceCell", for: indexPath) as? priceTableViewCell
//Fatal error: Unexpectedly found nil while unwrapping an Optional value
if let price:String = store![indexPath.row].price{
priceCell?.priceLabel.text! = price
}else{
priceCell?.priceLabel.text! = "-"
}
return priceCell!
case 1 :
//timeCell
let timeCell = tableView.dequeueReusableCell(withIdentifier: "timeCell", for: indexPath) as? timeTableViewCell
if let time:String = store![indexPath.row].open_time{
timeCell?.timeLabel.text! = time
}else{
timeCell?.timeLabel.text! = "-"
}
return timeCell!
case 2 :
//closedayCell
let closedayCell = tableView.dequeueReusableCell(withIdentifier: "closedayCell", for: indexPath) as? closedayTableViewCell
if let closeday:String = store![indexPath.row].closed_day{
closedayCell?.closedayLabel.text! = closeday
}else{
closedayCell?.closedayLabel.text! = "-"
}
return closedayCell!
default :
print("Default Selected")
}
return cell
}
Store View Controller All view
import UIKit
class StoreViewController:
UIViewController,UICollectionViewDataSource,UICollectionViewDelegate,
UICollectionViewDelegateFlowLayout,UITableViewDelegate,
UITableViewDataSource {
var store_id = ""
var store : [Store]?
var photoPath : [Store.photos]?
var tag : [Store.tags]?
var selectedImage : UIImage?
let defaultValues = UserDefaults.standard
#IBOutlet weak var imageCollectionView: UICollectionView!
#IBOutlet weak var mainImage: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var locationLabel: UILabel!
#IBOutlet weak var UIView: UIView!
#IBOutlet weak var tagCollectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//Collectiopn DetaSources
imageCollectionView.dataSource = self
imageCollectionView.delegate = self
tagCollectionView.dataSource = self
tagCollectionView.delegate = self
//UIView Shadow
let shadowPath = UIBezierPath(rect: UIView.bounds)
UIView.layer.masksToBounds = false
UIView.layer.shadowColor = UIColor.black.cgColor
UIView.layer.shadowOffset = .zero
UIView.layer.shadowOpacity = 0.2
UIView.layer.shadowPath = shadowPath.cgPath
//Request API
let url = URL(string: "http://localhost:8000/store/api?store_id=" + store_id)
let request = URLRequest(url: url!)
let session = URLSession.shared
let encoder: JSONEncoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
encoder.outputFormatting = .prettyPrinted
session.dataTask(with: request){(data, response, error)in if error == nil,
let data = data,
let response = response as? HTTPURLResponse{
let decoder: JSONDecoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
do {
let json = try decoder.decode(Store.self, from: data)
if json != nil {
print(json)
}else{
print("nil")
}
self.store = [json]
self.photoPath = json.photos
self.tag = json.tags
if let imageURL = URL(string: "http://127.0.0.1:8000/photos/" + json.photos[0].path){
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.mainImage.image = image
}
}
}
}
DispatchQueue.main.async {
self.nameLabel.text = json.name
self.locationLabel.text = json.location
}
} catch {
print("error:", error.localizedDescription)
}
}
}.resume()
//print(defaultValues.string(forKey: "id"))
// Image Collection view Layout
let itemSize = UIScreen.main.bounds.width/3.62 - 3.62
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)
layout.itemSize = CGSize(width: itemSize, height: itemSize)
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
imageCollectionView.collectionViewLayout = layout
// Tag Collection View
let tagLayout = UICollectionViewFlowLayout()
tagLayout.minimumLineSpacing = 1
tagLayout.minimumInteritemSpacing = 1
tagLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)
tagLayout.itemSize = CGSize(width: 80, height: 24)
tagCollectionView.collectionViewLayout = tagLayout
print("storeID is"+store_id)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// UI coner redius
let uiViewPath = UIBezierPath(roundedRect: UIView.bounds,
byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 8, height: 8))
let uiViewMask = CAShapeLayer()
uiViewMask.path = uiViewPath.cgPath
UIView.layer.mask = uiViewMask
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Collection
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.imageCollectionView{
let imageCell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell",for: indexPath)
let imageView = imageCell.contentView.viewWithTag(1) as! UIImageView
let imageURL = URL(string: "http://127.0.0.1:8000/photos/" + photoPath![indexPath.row].path)
if imageURL == nil {
print("nil")
}else{
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL!)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
imageCell.layer.masksToBounds = true;
imageCell.layer.cornerRadius = 3
imageView.image = image
}
}
}
}
return imageCell
//Tag collection view
}else if collectionView == self.tagCollectionView{
let tagCell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Tag",for: indexPath)
let tagLabel = tagCell.contentView.viewWithTag(2) as! UILabel
tagLabel.text! = tag![indexPath.row].name
tagCell.layer.cornerRadius = 12
return tagCell
}else{
return UICollectionViewCell()
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 3
}
func tagcollectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tag?.count ?? 0
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return 1
case 1 :
return 1
case 2 :
return 1
default:
return 0
}
}
//Collection view tap
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == self.imageCollectionView{
if photoPath![indexPath.row].path != nil {
if let imageURL = URL(string: "http://127.0.0.1:8000/photos/" + photoPath![indexPath.row].path ){
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.mainImage.image = image
}
}
}
}
}else{
print("error")
return
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
switch indexPath.section {
case 0 :
//Price Cell
let priceCell = tableView.dequeueReusableCell(withIdentifier: "priceCell", for: indexPath) as? priceTableViewCell
if let price:String = store![indexPath.row].price{
priceCell?.priceLabel.text! = price
}else{
priceCell?.priceLabel.text! = "-"
}
return priceCell!
case 1 :
//timeCell
let timeCell = tableView.dequeueReusableCell(withIdentifier: "timeCell", for: indexPath) as? timeTableViewCell
if let time:String = store![indexPath.row].open_time{
timeCell?.timeLabel.text! = time
}else{
timeCell?.timeLabel.text! = "-"
}
return timeCell!
case 2 :
//closedayCell
let closedayCell = tableView.dequeueReusableCell(withIdentifier: "closedayCell", for: indexPath) as? closedayTableViewCell
if let closeday:String = store![indexPath.row].closed_day{
closedayCell?.closedayLabel.text! = closeday
}else{
closedayCell?.closedayLabel.text! = "-"
}
return closedayCell!
default :
print("Default Selected")
}
return cell
}
#IBAction func moreImageBtn(_ sender: Any) {
let store_id = self.store_id
self.performSegue(withIdentifier: "toStorePhotoViewController", sender: store_id)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toStorePhotoViewController"{
let storePhotoViewController = segue.destination as! StorePhotoViewController
storePhotoViewController.store_id = sender as! String
}
}
//Bookmark Button
#IBAction func bookmarkBtn(_ sender: Any) {
let user_id = defaultValues.string(forKey: "userId")
let url = URL(string: "http://localhost:8000/api/store/favorite?")
var request = URLRequest(url: url!)
// POSTを指定
request.httpMethod = "POST"
// POSTするデータをBodyとして設定
let postParameters = "user_id=" + user_id! + "&store_id=" + store_id
request.httpBody = postParameters.data(using: .utf8)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if error == nil, let data = data, let response = response as? HTTPURLResponse {
// HTTPヘッダの取得
print("Content-Type: \(response.allHeaderFields["Content-Type"] ?? "")")
// HTTPステータスコード
print("statusCode: \(response.statusCode)")
print(String(data: data, encoding: .utf8) ?? "")
}
}.resume()
}
#IBAction func locationBtn(_ sender: Any) {
let lat = store![0].lat
let lng = store![0].lng
if UIApplication.shared.canOpenURL(URL(string:"comgooglemaps://")!){
let urlStr : String = "comgooglemaps://?daddr=\(lat),\(lng)&directionsmode=walking&zoom=14"
UIApplication.shared.open(URL(string:urlStr)!,options: [:], completionHandler: nil)
}else{
let daddr = String(format: "%f,%f", lat, lng)
let urlString = "http://maps.apple.com/?daddr=\(daddr)&dirflg=w"
let encodeUrl = urlString.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)!
let url = URL(string: encodeUrl)!
UIApplication.shared.open(url,options: [:], completionHandler: nil)
}
}
}
Declare array as below
var store = [Store]()
Change TableView datasource as per below:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return store.count > 0 ? 1 : 0 // if array count greater than return 1 else 0
case 1 :
return store.count > 0 ? 1 : 0
case 2 :
return store.count > 0 ? 1 : 0
default:
return 0
}
}
As mentioned by #Scriptable, You should not force unwrap.
You can add Exception break point for break point navigator like below
And then
This will help to pin point issue, Hopefully.
I don't know why but when I open the app, it takes a while to load all the data on the screen, until there remains a white screen without content. All the data loaded is downloaded from an API. What should I do to make it better?
App Loaded after about 10 seconds:
I'll post below how I'm parsing all the data.
ViewController.swift:
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UITableViewDataSource {
#IBOutlet weak var tableViewTopSell: UITableView!
#IBOutlet var collectionView: UICollectionView!
#IBOutlet weak var collectionViewBanner: UICollectionView!
var dataSource: [Content] = [Content]()
var dataBanner: [Banner] = [Banner]()
var dataTopSold: [Top10] = [Top10]()
override func viewDidLoad() {
super.viewDidLoad()
//SetupNavBarCustom
self.navigationController?.navigationBar.CustomNavigationBar()
let logo = UIImage(named: "tag.png")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView
//CallAPIData
getTopSold { (data) in
DispatchQueue.main.async {
self.dataTopSold = data
self.tableViewTopSell.reloadData()
}
}
getBanner { (data) in
DispatchQueue.main.async {
self.dataBanner = data
self.collectionViewBanner.reloadData()
}
}
getAudiobooksAPI { (data) in
DispatchQueue.main.async {
self.dataSource = data
self.collectionView.reloadData()
}
}
}
//CollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if (collectionView == self.collectionView) {
return self.dataSource.count
}else{
return self.dataBanner.count
}}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if (collectionView == self.collectionView) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell
let content = self.dataSource[indexPath.item]
cell.bookLabel.text = content.descricao
cell.bookImage.setImage(url: content.urlImagem, placeholder: "")
return cell
}else if (collectionView == self.collectionViewBanner) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCellBanner", for: indexPath) as! CollectionViewCell
let content = self.dataBanner[indexPath.item]
cell.bannerImage.setImage(url: content.urlImagem, placeholder: "")
return cell
}
return UICollectionViewCell()
}
//TableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataTopSold.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "topSoldCell", for: indexPath) as! TableViewCell
let content = self.dataTopSold[indexPath.item]
cell.labelNomeTopSell.text = content.nome
cell.imageViewTopSell.setImage(url: content.urlImagem, placeholder: "")
return cell
}
}
extension UIImageView{
func setImage(url : String, placeholder: String, callback : (() -> Void)? = nil){
self.image = UIImage(named: "no-photo")
URLSession.shared.dataTask(with: NSURL(string: url)! as URL, completionHandler: { (data, response, error) -> Void in
guard error == nil else{
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
self.image = image
if let callback = callback{
callback()
}
})
}).resume()
}
}
DataStore.swift:
import Foundation
import UIKit
func getBanner(_ completion:#escaping ([Banner])->Void) {
let url = URL(string: "https://alodjinha.herokuapp.com/banner")
let session = URLSession.shared
guard let unwrappedURL = url else { print("Error unwrapping URL"); return }
let dataTask = session.dataTask(with: unwrappedURL) { (data, response, error) in
guard let unwrappedDAta = data else { print("Error unwrapping data"); return }
do {
let jsonBanner = try JSONDecoder().decode(BannerData.self, from: unwrappedDAta)
completion(jsonBanner.data)
} catch {
print("Could not get API data. \(error), \(error.localizedDescription)")
}
}
dataTask.resume()
}
func getTopSold(_completion:#escaping ([Top10])->Void) {
let url = URL(string: "https://alodjinha.herokuapp.com/produto/maisvendidos")
let session = URLSession.shared
guard let unwrappedURL = url else { print("Error url"); return}
let dataTask = session.dataTask(with: unwrappedURL) { (data, response, error) in
guard let unwrappedData = data else { print("Error data"); return}
do {
let jsonTop10 = try JSONDecoder().decode(Top10Data.self, from: unwrappedData)
_completion(jsonTop10.data)
}catch{
print("Could no get API data")
}
}
dataTask.resume()
}
Model.swift:
import Foundation
//Categorias
struct Contents : Decodable {
let data : [Content]
}
struct Content : Decodable {
let id : Int
let descricao : String
let urlImagem : String
}
//Banner
struct BannerData : Decodable {
let data : [Banner]
}
struct Banner : Decodable {
let id : Int
let urlImagem : String
let linkUrl : String
}
//Top10
struct Top10Data:Decodable {
let data: [Top10]
}
struct Top10:Decodable {
let id : Int
let nome : String
let urlImagem : String
}
Apart from it's a heavy network loading VC , you Currently don't have any problems loading the data as all are out of main thread , the only problem is loading the images as when you scroll it re-download the image again which may be just downloaded for this i recommend using SDWebImage which will take care of the download & cache for you , your main problem may be low network speed for many requests
Another thing to manage this network problem you may serial queue the download of the data that will help you load one part fastly and display it which will make the impression to the user that the app is in request for more data instead of make all the requests at once
I'm want to use some custom struct in my collection view cell. I get the data from my API service and trying to pass it to my custom collection view cell.
I found couple answers but I still couldn't figure out how to do
Here is where I get the actual data:
func FetchFormData(linkUrl: String) {
let parameters: [String: AnyObject] = [:]
let postString = (parameters.flatMap({ (key, value) -> String in
return "\(key)=\(value)"
}) as Array).joined(separator: "&")
let url = URL(string: linkUrl)!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
let contentData = responseString?.data(using: .utf8)
do {
let decoder = JSONDecoder()
self.formData = try decoder.decode(FormModel.self, from: contentData!)
} catch let err {
print("Err", err)
}
DispatchQueue.main.async {
//here is the where I reload Collection View
self.collectionView.reloadData()
}
}
task.resume()
}
Also here I'm trying to pass data to the cell:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! BaseFormCollectionViewCell
cell.backgroundColor = .green
//Data could be print out here
print(self.formData?.components?[indexPath.row])
cell.formComponent = (self.formData?.components?[indexPath.row])!
return cell
}
The actual problem is starting into my cell class
class BaseFormCollectionViewCell: UICollectionViewCell {
var formComponent: FormComponent!{
didSet {
//data can be print out here
print("Passed value is: \(formComponent)")
}
}
override init(frame: CGRect) {
super.init(frame: frame)
//this part is always nill
print(formComponent)
}
}
As you guys can see in the code It's going well until my collection view cell.
It should be a lot more simple but I couldn't figure out what's going on and Why its happening.
Modify your cell class as
class BaseFormCollectionViewCell: UICollectionViewCell {
var formComponent: FormComponent!{
didSet {
//this is unnecessary. You can achieve what u want with a bit more cleaner way using configure function as shown below
//data can be print out here
print("Passed value is: \(formComponent)")
}
}
override init(frame: CGRect) {
super.init(frame: frame)
//this part is always nill
print(formComponent)
}
func configure() {
//configure your UI of cell using self.formComponent here
}
}
finally
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! BaseFormCollectionViewCell
cell.backgroundColor = .green
//Data could be print out here
print(self.formData?.components?[indexPath.row])
cell.formComponent = (self.formData?.components?[indexPath.row])!
(cell as! BaseFormCollectionViewCell).configure()
return cell
}
Look for (cell as! BaseFormCollectionViewCell).configure() in cellForItemAt thats how u trigger the UI configuration of cell after passing data to cell in statement above it.
Quite frankly u can get rid of didSet and relay on configure as shown
Hope it helps
I have an app which have a table view
and iam using custom cell class in my table
and this is my custom table cell class :
class addCommentTableViewCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
postText.layer.borderWidth = 1
postText.layer.borderColor = UIColor.grayColor().CGColor
postText.layer.cornerRadius = 3
}
#IBOutlet weak var postText: UITextView!
#IBOutlet weak var postCommentButton: UIButton!
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
i need to click the button in the cell class and get the value from the textView
so i added this code to make that :
class singleNewViewController: UIViewController , UITableViewDataSource , UITableViewDelegate{
override func viewDidLoad() {
let indexPath = NSIndexPath(forRow: 1, inSection: 0)
let secondCellPostComment = mainTable.dequeueReusableCellWithIdentifier("addCommentCell" , forIndexPath: indexPath) as! addCommentTableViewCell
let postButton = secondCellPostComment.postCommentButton
postButton!.addTarget(self, action: "postUserComment", forControlEvents: .TouchUpInside)
}
func postUserComment()
{
let indexPath = NSIndexPath(forRow: 1, inSection: 0)
let secondCellPostComment = mainTable.dequeueReusableCellWithIdentifier("addCommentCell" , forIndexPath: indexPath) as! addCommentTableViewCell
var textFieldComment = secondCellPostComment.postText
let textF = textFieldComment.text!
let request = NSMutableURLRequest(URL: NSURL(string: "http://mydomain/comment")!)
request.HTTPMethod = "POST"
let postString = "user_id=\(addResourcesViewController.userLoggedID)&news_id=\(singleNewViewController.newID)&comment=\(textF.text!)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data , response , error in
guard error == nil && data != nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
dispatch_async(dispatch_get_main_queue(), {
self.mainTable.reloadData()
})
}
task.resume()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (indexPath.row == 0 )
{
let cell = mainTable.dequeueReusableCellWithIdentifier("singleTableDetails", forIndexPath: indexPath) as! singleNewTableViewCell
let readmorebutton = cell.readmore
let focusComment = cell.addcomments
readmorebutton.addTarget(self, action: "loadURLinBrowser", forControlEvents: UIControlEvents.TouchUpInside)
focusComment.addTarget(self, action: "focusToView", forControlEvents: UIControlEvents.TouchUpInside)
let remoteImageUrlString = "http://mydomian/"+singleNewViewController.image
let imageURL = NSURL(string: remoteImageUrlString)
let myBlock: SDWebImageCompletionBlock! = { (image:UIImage! , error : NSError! , cacheType: SDImageCacheType! , imageURL: NSURL! ) -> Void in
print("Image with urk \(imageURL.absoluteString) is loaded" )
}
cell.cellImage.sd_setImageWithURL(imageURL, placeholderImage: UIImage(named:"welcome_bg") , options: SDWebImageOptions.ProgressiveDownload, completed: myBlock)
return cell
}else if (indexPath.row == 1 )
{
let cell = mainTable.dequeueReusableCellWithIdentifier("addCommentCell", forIndexPath: indexPath) as! addCommentTableViewCell
return cell
}
else
{
let cell = mainTable.dequeueReusableCellWithIdentifier("allCommentsCell", forIndexPath: indexPath) as! commentsTableViewCell
cell.commentUser.text = self.commentsUser[(indexPath.row - 2)]
cell.comment.text = self.comments[(indexPath.row - 2)]
return cell
}
}
}
the code is working but i don't get the value of the UITextView
and i tried to add a default value to the UITextView from the storyboard it's working but when i run in simulator and replace it with any string it's send the default value to the url any suggestion why it's not read any new values ?