How can I display my data from a uitableview to uicollectionview? - json

I have some code for a uitableview with works pretty well. Here's the code.
import UIKit
import Alamofire
import ObjectMapper
import SwiftyJSON
import FirebaseAuth
import FirebaseStorage
class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
// #IBOutlet weak var symbolLbl: UILabel!
// #IBOutlet weak var BidLbl: UILabel!
var NumberofRows = 0
let stockURL = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22+GRPN+SIRI+TVIX+EVOK+ZNGA+EPRS+TKAI+EBIO+DELT+SQNM+ALIM+ODP+ASTI+GBSN+FATE+BLDP+ETRM+GALE+VSTM+BIND+GEVO+DRAM+AMDA+BIOD+VNR+GLUU+AXAS+INFI+BLDP+SGYP+HLIT+ZIOP+XGTI+CIDM+CPLP+ORIG+DRRX+MNKD+GLBS+GERN+IMGN+IMMU+GLBS+GERN+IMGN+IMMU+GLBL+REXX+VIP+NETE+EXTR+CLNE+EBIO+ULTR+AAPL+TSLA+%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&format=json"
//var StockArray = [String]()
var BidArray = [Double]()
var ChangeArray = [Double]()
struct combinedStock {
var symbol: String = ""
var bid : Double = 0.0
var change: Double = 0.0
}
var stockArray = [combinedStock]()
#IBOutlet weak var tableView: UITableView!
// #IBOutlet weak var StockSymbolLbl: UILabel!
// #IBOutlet weak var BidSymbolLbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
getJSON()
automaticallyAdjustsScrollViewInsets = false
tableView.dataSource = self
tableView.delegate = self
tableView.registerNib(UINib(nibName: "StockHome", bundle: NSBundle.mainBundle()),forCellReuseIdentifier: "stockHome")
tableView.rowHeight = 60
// StockSymbolLbl.text = ""
// BidSymbolLbl.text = ""
}
#IBAction func logout(sender: AnyObject) {
let actionSheetController = UIAlertController(title: "Please Selecet", message: "Option to select", preferredStyle: UIAlertControllerStyle.ActionSheet)
let cancelActionButton = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (action) in
print("Cancel")
}
actionSheetController.addAction(cancelActionButton)
let profileActionButton = UIAlertAction(title: "Profile", style: UIAlertActionStyle.Default) { (action) in
let profileVC = self.storyboard?.instantiateViewControllerWithIdentifier("profileViewConrtoller") as! ProfileTableViewController
self.navigationController?.pushViewController(profileVC, animated: true)
}
actionSheetController.addAction(profileActionButton)
let logoutAction = UIAlertAction(title: "Log Out", style: UIAlertActionStyle.Default) { (action) in
print("log out")
self.logoutDidTapped()
}
actionSheetController.addAction(logoutAction)
self.presentViewController(actionSheetController, animated: true, completion: nil)
}
func logoutDidTapped() {
DataService.dataService.logout()
}
func getJSON(){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let url = NSURL(string: self.stockURL)
let request = NSURLRequest(URL: url!)
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error == nil {
let swiftyJSON = JSON(data: data!)
let Symbol: String? = swiftyJSON["query"]["results"]["quote"][0]["symbol"].stringValue
let bid: String? = swiftyJSON["query"]["results"]["quote"][0]["Bid"].stringValue
let change: String? = swiftyJSON["query"]["results"]["quote"][0]["Change"].stringValue
print(change!)
print(Symbol!)
print(bid!)
dispatch_async(dispatch_get_main_queue()) {
// self.StockSymbolLbl.text? = "\(Symbol!)"
// self.BidSymbolLbl.text? = "\(bid!)"
self.NumberofRows = swiftyJSON["query"]["results"]["quote"].count
for i in 0...self.NumberofRows {
var stockcount = 0
stockcount += i
let Stock = swiftyJSON["query"]["results"]["quote"][stockcount]["symbol"].stringValue
let Bid = swiftyJSON["query"]["results"]["quote"][stockcount]["Bid"].doubleValue
let Change = swiftyJSON["query"]["results"]["quote"][stockcount]["Change"].doubleValue
let homestocks = combinedStock(symbol: Stock, bid: Bid, change: Change)
// self.StockArray.append(Stock)
// print(Stock)
// self.BidArray.append(Bid)
// print(Bid)
// self.ChangeArray.append(Change)
// p
print(Change)
self.stockArray.append(homestocks)
}
self.stockArray = self.stockArray.sort({
return $0.change > $1.change
})
self.tableView.reloadData()
}
}else{
print("There was an error")
}
}
task.resume()
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return NumberofRows
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: StockHome = tableView.dequeueReusableCellWithIdentifier("stockHome", forIndexPath: indexPath) as! StockHome
if stockArray.count != 0{
cell.symbolLbl?.text = stockArray[indexPath.row].symbol
let bid = stockArray[indexPath.row].bid
let changeRate = stockArray[indexPath.row].change
cell.bidLbl?.text = "\(bid)" + " USD "
cell.changeLbl?.text = "\(changeRate)" + " %"
}
print(self.stockArray)
return cell
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
switch stockArray[indexPath.row].change {
case let x where x < 0.0:
cell.backgroundColor = UIColor(red: 255.0/255.0, green: 59.0/255.0, blue: 48.0/255.0, alpha: 1.0)
case let x where x > 0.0:
cell.backgroundColor = UIColor(red: 76.0/255.0, green: 217.0/255.0, blue: 100.0/255.0, alpha: 1.0)
case let x:
cell.backgroundColor = UIColor(red: 44.0/255.0, green: 186.0/255.0, blue: 231.0/255.0, alpha: 1.0)
}
cell.textLabel!.textColor = UIColor.whiteColor()
}
}
I am trying to change the view from a tableview to a collection view. I did so, but nothing is displayed. I was greeted with a black screen until I changed the background to white. Here is the code for my collection view
import UIKit
import Alamofire
import ObjectMapper
import SwiftyJSON
import FirebaseAuth
import FirebaseStorage
class StockViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var NumberofRows = 0
let stockURL = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22+GRPN+SIRI+TVIX+EVOK+ZNGA+EPRS+TKAI+EBIO+DELT+SQNM+ALIM+ODP+ASTI+GBSN+FATE+BLDP+ETRM+GALE+VSTM+BIND+GEVO+DRAM+AMDA+BIOD+VNR+GLUU+AXAS+INFI+BLDP+SGYP+HLIT+ZIOP+XGTI+CIDM+CPLP+ORIG+DRRX+MNKD+GLBS+GERN+IMGN+IMMU+GLBS+GERN+IMGN+IMMU+GLBL+REXX+VIP+NETE+EXTR+CLNE+EBIO+ULTR+AAPL+TSLA+%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&format=json"
var BidArray = [Double]()
var ChangeArray = [Double]()
struct combinedStock {
var symbol: String = ""
var bid : Double = 0.0
var change: Double = 0.0
}
var stockArray = [combinedStock]()
#IBOutlet weak var collectionview: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
automaticallyAdjustsScrollViewInsets = false
collectionview.dataSource = self
collectionview.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getJSON(){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let url = NSURL(string: self.stockURL)
let request = NSURLRequest(URL: url!)
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error == nil {
let swiftyJSON = JSON(data: data!)
let Symbol: String? = swiftyJSON["query"]["results"]["quote"][0]["symbol"].stringValue
let bid: String? = swiftyJSON["query"]["results"]["quote"][0]["Bid"].stringValue
let change: String? = swiftyJSON["query"]["results"]["quote"][0]["Change"].stringValue
print(change!)
print(Symbol!)
print(bid!)
dispatch_async(dispatch_get_main_queue()) {
// self.StockSymbolLbl.text? = "\(Symbol!)"
// self.BidSymbolLbl.text? = "\(bid!)"
self.NumberofRows = swiftyJSON["query"]["results"]["quote"].count
for i in 0...self.NumberofRows {
var stockcount = 0
stockcount += i
let Stock = swiftyJSON["query"]["results"]["quote"][stockcount]["symbol"].stringValue
let Bid = swiftyJSON["query"]["results"]["quote"][stockcount]["Bid"].doubleValue
let Change = swiftyJSON["query"]["results"]["quote"][stockcount]["Change"].doubleValue
let homestocks = combinedStock(symbol: Stock, bid: Bid, change: Change)
// self.StockArray.append(Stock)
// print(Stock)
// self.BidArray.append(Bid)
// print(Bid)
// self.ChangeArray.append(Change)
// p
print(Change)
self.stockArray.append(homestocks)
}
self.stockArray = self.stockArray.sort({
return $0.change > $1.change
})
self.collectionview.reloadData()
}
}else{
print("There was an error")
}
}
task.resume()
}
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return NumberofRows
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionview.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! homeCollectionViewCell
if stockArray.count != 0{
cell.symbolLbl?.text = self.stockArray[indexPath.item].symbol
let bid = stockArray[indexPath.item].change
let changeRate = stockArray[indexPath.item].change
cell.bidLbl?.text = "\(bid)" + " USD "
cell.percentLbl?.text = "\(changeRate)" + " %"
}
print(self.stockArray)
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
}
As you can tell they are quite similar. I was curious to know what I am missing or doing wrong. Thank you.
P.S. here is the code for the uicollectionviewcell
import UIKit
class homeCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var symbolLbl: UILabel!
#IBOutlet weak var percentLbl: UILabel!
#IBOutlet weak var bidLbl: UILabel!
}
Thank you.

Related

Tableviewcell data won't translate to another view controller

I did a parse json in my listingshopvc and it shows.Now I want to select a row and it pops up another view controller but there's error just a blank page with no error. I just want to press a row and convert it to show up on another view controller.
I have listing in the following view controller: ListingShopVc,ProductDetail,TableCellData
ListingShopVC
import UIKit
import CoreData
class ListingShopVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var creditsdisplay: UILabel!
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var myUser:[User] = []
var mySecond:[Product] = []
var id:String = ""
var name:String = ""
var price:Double = 0.0
var image:String = ""
var details:String = ""
override func viewDidLoad() {
super.viewDidLoad()
fetch()
tableView.delegate = self
tableView.dataSource = self
extracted()
creditsdisplay.text = "You have 200 credits"
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return mySecond.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "hello", for: indexPath) as! TableCellData
// Configure the cell...
cell.shopTitle.text = mySecond[indexPath.row].name
cell.shopPrice.text = "$" + String(mySecond[indexPath.row].price) + "0"
cell.shopDesc.text = mySecond[indexPath.row].description
if let url = URL(string: mySecond[indexPath.row].image){
DispatchQueue.global().async {
let data = try? Data(contentsOf: url)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.shopImageView.image = image
}
}
}
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
id = mySecond[indexPath.row].id
name = mySecond[indexPath.row].name
price = mySecond[indexPath.row].price
details = mySecond[indexPath.row].description
image = mySecond[indexPath.row].image
performSegue(withIdentifier: "toDetails", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toDetails"{
let vc = segue.destination as! ProductDetail
vc.productPicture = image
vc.productName = name
vc.productPrice = price
vc.productDetails = details
vc.productID = id
print(vc.productName)
}
}
func extracted(){
guard let url = URL(string: "http://rajeshrmohan.com/sport.json")
else {return}
let task = URLSession.shared.dataTask(with: url){
(data,response,error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return
}
do {
let decoder = JSONDecoder()
let model:[Product] = try decoder.decode([Product].self, from: dataResponse)
//print(model)
for i in 0..<model.count{
self.mySecond.append(model[i])
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
func fetch(){
userList = try! context.fetch(User.fetchRequest())
tableView.reloadData()
}
}
TableViewCell
import UIKit
class TableCellData: UITableViewCell {
#IBOutlet weak var shopImageView: UIImageView!
#IBOutlet weak var shopTitle: UILabel!
#IBOutlet weak var shopPrice: UILabel!
#IBOutlet weak var shopDesc: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
ProductDetail
import UIKit
import CoreData
class ProductDetail: UIViewController {
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var myArray:[Cart] = []
var mySecondArray:[Products] = []
var newTots:Double = 0.0
#IBOutlet weak var AddImage: UIImageView!
#IBOutlet weak var AddTitle: UILabel!
#IBOutlet weak var AddPrice: UILabel!
#IBOutlet weak var AddDesc: UILabel!
var productID = String()
var productName = String()
var productPrice:Double = 0.0
var productPicture = String()
var productDetails:String = ""
override func viewDidLoad() {
super.viewDidLoad()
AddTitle.text = productName
AddDesc.text = productDetails
AddPrice.text = String(productPrice)
if let imageUrl = URL(string: productPicture),
let imageData = try? Data(contentsOf: imageUrl) {
AddImage.image = UIImage(data: imageData)
}
}
#IBAction func add2Cart(_ sender: Any) {
let neww = Cart(context: context)
neww.image = productPicture
neww.name = productName
neww.desc = productDetails
neww.price = productPrice
neww.total = productPrice
try! context.save()
performSegue(withIdentifier: "gotoCheckout", sender: nil)
}
func fetch(){
self.mySecondArray = try! context.fetch(Products.fetchRequest())
}
}
What it shows it this [1]: https://i.stack.imgur.com/XWUt0.png
-> You just need to call a delegate method of table view didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let tag = projectEquipmentList?[indexPath.row].tag // Object data to take in next VC
let QR = R.storyboard.main.qrScannerVC()! // View Controller
QR.manageVC(projectEquipmentTag: tag!) // setter method of View controller to set data
navigationController?.pushViewController(QR, animated: true) // push to next view controller
}

Open pdf in tableview from a json file

I am in a bind.
My regular developer has secured a full time gig, and I am trying to finish a project.
Literally stuck on the last line of code.....
I have a tableview that parses a json file to populate and open a pdf file when a row is selected.
I reworked the tableview in order to add a searchbar and associated code, which works when running the bundle.
I am, however, stuck with connecting the didSelectRow with the appropriate pdf file.
Can someone please lend a hand? Thanks
import UIKit
import WebKit
// Model
struct Section {
var section: String
var pdfs: [PDF]
}
struct PDF {
var code: String
var name: String
var airport: String
}
class PdfVC: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var tableViewLeft: NSLayoutConstraint!
#IBOutlet weak var btnMenuLeft: NSLayoutConstraint!
#IBOutlet weak var btnMenu: UIButton!
#IBOutlet weak var searchBar: UISearchBar!
//json
var jsonData: [Section] = []
var filtedJsonData: [Section] = []
//WebView
var fileName: String?
var isVideo: Bool = false
var btnMenuClose:UIBarButtonItem?
override func viewDidLoad() {
super.viewDidLoad()
hideKeyboardWhenTappedAround()
// Setup TableView
tableView.delegate = self
tableView.dataSource = self
setupData()
tableView.reloadData()
// Setup SearchBar
searchBar.delegate = self
// Setup WebView
if let fileName = fileName {
isVideo = fileName.contains(".mp4")
if let range = fileName.range(of: isVideo ? ".mp4" : ".pdf") {
self.fileName!.removeSubrange(range)
}
}
if let file = Bundle.main.url(forResource: fileName ?? "", withExtension: isVideo ? ".mp4" : ".pdf", subdirectory: nil, localization: nil) {
let request = URLRequest(url: file)
webView.load(request)
}
if let image = UIImage(named: "ico_close") {
navigationItem.rightBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(onWebTap))
//self.navigationItem.leftItemsSupplementBackButton = true
btnMenuClose = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(onWebTap))
self.navigationItem.rightBarButtonItems = [btnMenuClose!];
}
//navigationItem.title = "Airport Maps"
}
private func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc private func dismissKeyboard() {
view.endEditing(true)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
// title color to white
let titleTextAttributed: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.white, .font: UIFont(name: "HelveticaNeue-Light", size: 20) as Any]
self.navigationController?.navigationBar.titleTextAttributes = titleTextAttributed
// back arrow white
self.navigationController?.navigationBar.tintColor = UIColor.white
// blueish navigation bar
self.navigationController?.navigationBar.barTintColor = UIColor(red: 0.00, green: 0.54, blue: 0.92, alpha: 1.00)
self.navigationController?.navigationBar.isTranslucent = false
showMenu(false, animated: false)
}
private func setupData() {
// Parse data from local json file
if let path = Bundle.main.path(forResource: "airports", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
if let jsonResult = jsonResult as? [Dictionary<String, String>] {
for result in jsonResult {
if !jsonData.contains(where: { $0.section == result["Section"] }) {
let section = Section(section: result["Section"] ?? "", pdfs: [])
jsonData.append(section)
}
let pdf = PDF(code: result["Code"] ?? "", name: result["Filename"] ?? "", airport: result["Name"] ?? "")
let index = jsonData.firstIndex(where: { $0.section == result["Section"] })
if let index = index {
jsonData[index].pdfs.append(pdf)
}
}
}
} catch {
// Handle error
print("error parsing json")
}
}
// Sort data before use
jsonData.sort(by: { $0.section < $1.section })
for index in 0..<jsonData.count {
jsonData[index].pdfs.sort(by: { $0.airport < $1.airport } )
}
filtedJsonData = jsonData
}
#objc func onWebTap() {
var left:CGFloat = 0
if tableViewLeft.constant == 0 {
left = -320
}
tableViewLeft.constant = left
showMenu(left != 0, animated: true)
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
func showMenu(_ show:Bool, animated:Bool) {
if let image = UIImage(named: show ? "ico_open" : "ico_close") {
btnMenuClose?.image = image
//navigationItem.rightBarButtonItem?.image = image
//}
//var left:CGFloat = 20
//if show == false {
// left = -64
}
//btnMenuLeft.constant = left
UIView.animate(withDuration: animated ? 0.3 : 0.0, delay: 0, options: .curveEaseInOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
}
// TableView
extension PdfVC: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return filtedJsonData.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if filtedJsonData[section].pdfs.count == 0 {
return nil
}
return filtedJsonData[section].section
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filtedJsonData[section].pdfs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PdfCell", for: indexPath) as! PdfCell
let pdf = filtedJsonData[indexPath.section].pdfs[indexPath.row]
cell.setupCell(pdf: pdf)
return cell
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
dismissKeyboard()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let pdf = filtedJsonData[indexPath.section].pdfs[indexPath.row]
//THIS IS WHERE I'M STUCK<<<<<<<<<
self.title = pdf.airport
}
}
// SearchBar
extension PdfVC: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
for (index, data) in jsonData.enumerated() {
// Filter pdfs by code and name
let filtedPdf = data.pdfs.filter { $0.code.lowercased().prefix(searchText.count) == searchText.lowercased() || $0.airport.lowercased().prefix(searchText.count) == searchText.lowercased() }
filtedJsonData[index].pdfs = filtedPdf
}
tableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.text = ""
tableView.reloadData()
}
}
Got it figured out. Thanks for all who spent some time reading my issue. I changed as follows
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let pdf = filtedJsonData[indexPath.section].pdfs[indexPath.row]
self.fileName = pdf.name
self.title = pdf.airport
DispatchQueue.main.async {
self.reloadWebView()
}
}
and added
private func reloadWebView() {
// Setup WebView
if let fileName = fileName {
isVideo = fileName.contains(".mp4")
if let range = fileName.range(of: isVideo ? ".mp4" : ".pdf") {
self.fileName!.removeSubrange(range)
}
}
if let file = Bundle.main.url(forResource: fileName ?? "", withExtension: isVideo ? ".mp4" : ".pdf", subdirectory: nil, localization: nil) {
let request = URLRequest(url: file)
webView.load(request)
}
}

Swift: Accessing dictionary in JSON with Alamofire and private variables in a Model

I'm pulling out my hair with a problem that I think is pretty simple. I have successfully parsed an array of data from a JSON file to populate a tableview and and a collectionview but I am stuck on attempting to get a dictionary to load into my model.
{
latitude: 42.8821,
longitude: -8.541,
timezone: "Europe/Madrid",
offset: 2,
currently: {
time: 1494674291,
summary: "Drizzle",
icon: "rain",
precipIntensity: 0.1803,
precipProbability: 0.35,
precipType: "rain",
temperature: 14.73,
apparentTemperature: 14.73,
dewPoint: 11.63,
humidity: 0.82,
windSpeed: 7.15,
windBearing: 204,
cloudCover: 0.67,
pressure: 1013.37,
ozone: 378.18
},
I am attempting to access the 'currently' dictionary to populate my currentWeather Model.
import UIKit
import Alamofire
class CurrentWeather {
private var _currentTemp: Double!
private var _date: String!
private var _weatherType: String!
private var _highTemp: Double!
private var _lowTemp: Double!
private var _weatherDesc: String!
var currentTemp: Double {
if _currentTemp == nil {
_currentTemp = 0.0
}
return _currentTemp
}
var date: String {
if _date == nil {
_date = ""
}
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .none
let currentDate = dateFormatter.string(from: Date())
self._date = "Today \(currentDate)"
return _date
}
var weatherType: String {
if _weatherType == nil {
_weatherType = ""
}
return _weatherType
}
var highTemp: Double {
if _highTemp == nil {
_highTemp = 0.0
}
return _highTemp
}
var lowTemp: Double {
if _lowTemp == nil {
_lowTemp = 0.0
}
return _lowTemp
}
var weatherDesc: String {
if _weatherDesc == nil {
_weatherDesc = ""
}
return _weatherDesc
}
init(currentDict: Dictionary<String, AnyObject>) {
if let temperature = currentDict["temperature"] as? Double {
self._currentTemp = temperature
}
if let icon = currentDict["icon"] as? String {
self._weatherType = icon
}
if let summary = currentDict["summary"] as? String {
self._weatherDesc = summary
}
}
}
And my VC code for the Alamofire call looks like this -
import UIKit
import Alamofire
class CityWeatherVC: UIViewController, UITableViewDataSource, UITableViewDelegate, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var cityNameLbl: UILabel!
#IBOutlet weak var currentTempLbl: UILabel!
#IBOutlet weak var dateLbl: UILabel!
#IBOutlet weak var currentWeatherImg: UIImageView!
#IBOutlet weak var currentWeatherType: UILabel!
#IBOutlet weak var dayHighTempLbl: UILabel!
#IBOutlet weak var dayLowTempLbl: UILabel!
var currentWeather: CurrentWeather!
var currentWeathers = [CurrentWeather]()
var longRangeForecast: LongRangeForecast!
var longRangeForecasts = [LongRangeForecast]()
var hourlyForecast: HourlyForecast!
var hourlyForecasts = [HourlyForecast]()
private var _segueData: SegueData!
var segueData: SegueData {
get {
return _segueData
} set {
_segueData = newValue
}
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
collectionView.delegate = self
collectionView.dataSource = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
downloadApiData {
self.updateCurrentWeatherUI()
}
}
func downloadApiData(completed: DownloadComplete) {
let currentWeatherUrl = URL(string: "\(darkSkyUrl)\(segueData.latitude),\(segueData.longitude)?units=si")!
Alamofire.request(currentWeatherUrl).responseJSON { response in
let result = response.result
if let dict = result.value as? Dictionary<String, AnyObject> {
if let currently = dict["currently"] as? Dictionary<String, AnyObject> {
let current = CurrentWeather(currentDict: currently)
print(current) // ISSUE HERE!
}
if let hourly = dict["hourly"] as? Dictionary<String, AnyObject> {
if let data = hourly["data"] as? [Dictionary<String, AnyObject>] {
for obj in data {
let forecast = HourlyForecast(hourlyDict: obj)
self.hourlyForecasts.append(forecast)
}
self.collectionView.reloadData()
}
}
if let daily = dict["daily"] as? Dictionary<String, AnyObject> {
if let data = daily["data"] as? [Dictionary<String, AnyObject>] {
for obj in data {
let forecast = LongRangeForecast(longWeatherDict: obj)
self.longRangeForecasts.append(forecast)
}
self.longRangeForecasts.remove(at: 0)
self.tableView.reloadData()
}
}
}
}
completed()
}
// tableView - long range forecast
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "longRangeForecastCell", for: indexPath) as? LongRangeForecastCell {
let forecast = longRangeForecasts[indexPath.row]
cell.configureCell(longRangeForecast: forecast)
return cell
} else {
return LongRangeForecastCell()
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return longRangeForecasts.count
}
// collectionView - hourly forecast
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "hourlyForecastCell", for: indexPath) as? HourlyForecastCell {
let forecast = hourlyForecasts[indexPath.row]
cell.configureCell(hourlyForecast: forecast)
return cell
} else {
return HourlyForecastCell()
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return hourlyForecasts.count
}
func updateCurrentWeatherUI() {
cityNameLbl.text = segueData.cityName
dateLbl.text = currentWeather.date
currentTempLbl.text = "\(currentWeather.currentTemp)"
currentWeatherType.text = currentWeather.weatherDesc
currentWeatherImg.image = UIImage(named: "\(currentWeather.weatherType)L")
dayHighTempLbl.text = "\(Int(currentWeather.highTemp))"
dayLowTempLbl.text = "\(Int(currentWeather.lowTemp))"
}
#IBAction func backButtonPressed(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
I have a feeling that the problem has to do with how I am referencing it like the arrays of dictionarys that I handled already. Any help would be greatly appreciated.
Update: result.value received. I am looking to parse the "currently" dictionary into my model then use the variables in the model class to populate my current forecast part of my UI. I can't paste in the entire result as it is larger in characters allowed for the post.
Second Update of result.value:
["latitude": 42.660851, "timezone": Europe/Madrid, "daily": {
data = (
{
apparentTemperatureMax = "18.33";
apparentTemperatureMaxTime = 1495022400;
apparentTemperatureMin = "10.87";
apparentTemperatureMinTime = 1495054800;
cloudCover = "0.87";
dewPoint = "11.73";
humidity = "0.88";
icon = rain;
moonPhase = "0.7";
ozone = "325.51";
precipIntensity = "0.1753";
precipIntensityMax = "0.3327";
precipIntensityMaxTime = 1495040400;
precipProbability = "0.54";
precipType = rain;
pressure = "1019.68";
First of all lets declare a type alias for a JSON dictionary outside any class
typealias JSONDictionary = [String:Any]
The returned result (result.value) is an array rather than a dictionary (see the starting [).
In downloadApiData get the JSON data which is the first item in the array, replace
if let dict = result.value as? Dictionary<String, AnyObject> {
with
if let array = result.value as? [JSONDictionary],
let dict = array.first {
Now pass dict to the initializer (not the value for currently)
let current = CurrentWeather(currentDict: dict)
The values for currentTemp, weatherType and weatherDesc are in the dictionary for key currently, the values for highTemp and lowTemp are in the first dictionary in array data in dictionary daily.
Your class CurrentWeather – uncaged from the private backing variables – is
class CurrentWeather {
let currentTemp: Double
let weatherType: String
let highTemp: Double
let lowTemp: Double
let weatherDesc: String
var date: String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .none
let currentDate = dateFormatter.string(from: Date())
return "Today \(currentDate)"
}
init(currentDict: JSONDictionary) {
if let currently = currentDict["currently"] as? JSONDictionary {
self.currentTemp = currently["temperature"] as? Double ?? 0.0
self.weatherType = currently["icon"] as? String ?? "n/a"
self.weatherDesc = currently["summary"] as? String ?? "n/a"
} else {
self.currentTemp = 0.0
self.weatherType = "n/a"
self.weatherDesc = "n/a"
}
if let daily = currentDict["daily"] as? JSONDictionary,
let data = daily["data"] as? [JSONDictionary],
let firstDailyDict = data.first {
self.highTemp = firstDailyDict["temperatureMax"] as? Double ?? 0.0
self.lowTemp = firstDailyDict["temperatureMin"] as? Double ?? 0.0
} else {
self.highTemp = 0.0
self.lowTemp = 0.0
}
}
}

Search with UISearchBar through WebServer

What is the correct procedure to search with UISearchBar through a web server? The following code is what I have tried so far. It is working but not in the right way. I am not getting all the results as it has to be.
class PlacesViewController: UITableViewController, UISearchBarDelegate, UISearchControllerDelegate, UISearchDisplayDelegate {
#IBOutlet var searchController: UISearchBar!
var searchActive: Bool = false
var filtered = [PlacesData]()
var startSearching: Bool = false
var DataTable:[PlacesData] = []
var nameToPass: String!
var totalvisits: String!
var totallikes: String!
override func viewDidLoad() {
tableView.delegate = self
tableView.dataSource = self
searchController.delegate = self
definesPresentationContext = true
searchController.showsCancelButton = true
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
donwloadData()
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
searchActive = true;
tableView.reloadData()
print("textdidbegin")
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
searchActive = false;
print("textdidend")
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchActive = false;
searchBar.text = ""
searchBar.resignFirstResponder()
self.filtered.removeAll()
self.tableView.reloadData()
print("textdidcancel")
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
searchActive = false;
print("textdidsearch")
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
print("search")
self.filtered.removeAll()
tableView.reloadData()
Alamofire
.request(.POST, "mysite.com/search.php", parameters: ["type":"Stores", "word": searchText])
.responseJSON { response in
if(response.result.description == "SUCCESS"){
let json = JSON(response.result.value!)
let arrayjson = json.arrayValue
let jsondict = arrayjson[0].dictionaryValue
let firstarr = jsondict["words"]?.arrayValue
for item in firstarr!{
let name = item["name"].stringValue
let long = item["long"].stringValue
let lat = item["lat"].stringValue
print(name)
self.filtered.append(PlacesData(name: name, long: long, lat: lat))
}
}
self.tableView.reloadData()
}
}
func donwloadData(){
Alamofire
.request(.GET, "mysite.com/showplaces.php")
.responseJSON { response in
print(response.result)
if(response.result.description == "SUCCESS"){
let json = JSON(response.result.value!)
let arrayjson = json.arrayValue
let jsondict = arrayjson[0].dictionaryValue
let firstarr = jsondict["words"]?.arrayValue
for item in firstarr!{
let name = item["name"].stringValue
let long = item["long"].stringValue
let lat = item["lat"].stringValue
print(name)
self.DataTable.append(PlacesData(name: name, long: long, lat: lat))
}
self.tableView.reloadData()
}
}
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (searchActive == true) {
return filtered.count + 1
}else{
return DataTable.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! PlacesCel
let places: PlacesData
if (searchActive == true) {
print("search IS active")
if(indexPath.row == filtered.count){
cell.titleLabel.text = "Add Place"
}else{
places = filtered[indexPath.row]
cell.textLabel?.text = places.name
}
} else {
print("search IS NOT active")
places = DataTable[indexPath.row]
cell.textLabel?.text = places.name
}
return cell
}
I could not find a proper tutorial to find the correct way of doing that. Apparently this is not working properly and whatever I tried it is not working. Any solution or answer would be appreciated. Thank you.
After all the problem was that I was not canceling my requests and every time I was typing a character in the searchbar a new request was added and all were added together at the end after every request was finished. The following code gave me the solution.
if((self.request) != nil){
request?.cancel()
}
self.request = Alamofire()

Use of unresolved identifier

In my Swift code to handle push notification I have this image:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableView:UITableView?
var items = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(animated: Bool) {
let frame:CGRect;(x:0, y: 100, width: self.view.frame.width, height: self.view.frame.height-100)
self.tableView = UITableView(frame: frame)
self.tableView?.dataSource = self
self.tableView?.delegate = self
self.view.addSubview(self.tableView!)
let btn = UIButton(frame: CGRect(x: 0, y: 25, width: self.view.frame.width, height: 50))
btn.backgroundColor = UIColor.cyanColor()
btn.setTitle("EKLE", forState: UIControlState.Normal)
btn.addTarget(self, action: "addData", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(btn)
}
func addData(){
RestApiManager.sharedInstance.getRandomUser { json -> Void in
let results = json["results"]
for (index: String, subJson: JSON) in results{
let user: AnyObject = subJson["user"].object
self.items.addObject(user)
dispatch_async(dispatch_get_main_queue(), {
tableView?.reloadData()
})
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell?
if cell == nil{
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "cell")
}
let user:JSON = JSON(self.items[indexPath.row])
let picURL = user["picture"]["medium"].string
let url = NSURL(string: picURL!)
let data = NSData(contentsOfURL: url!)
cell?.textLabel?.text = user["username"].string
cell?.imageView?.image = UIImage(data: data!)
return cell!
}
}
Here is the error:
Use of unresolved identifier 'subJson'
in line let user: AnyObject = subJson["user"].object
How would this be fixed?
If you are using Swift 2 (Xcode 7) the syntax for looping over a dictionary with typed parameters has changed.
Now you should do like this:
for (index, subJson):(String, JSON) in results {
let user: AnyObject = subJson["user"].object
self.items.addObject(user)
dispatch_async(dispatch_get_main_queue(), {
tableView?.reloadData()
})
}
Old way:
(index: String, subJson: JSON)
New way:
(index, subJson):(String, JSON)