I am having a lot of trouble correctly parsing the JSON from a local JSON file, storing it into an array and then displaying it in my view.
My app does not crash. The labels I have on the screen (4 buttons and 1 label) simply do not change values. They just get those sample values I added in there "Question 1", "Question 2", etc...
How do I get it to display the values from my JSON file ? It looks like this
/* Question label storyboard outlet */
#IBOutlet weak var questionLabel: UILabel!
// Answer button storyboard outlets
#IBOutlet weak var topLeftButton: UIButton!
#IBOutlet weak var topRightButton: UIButton!
#IBOutlet weak var bottomLeftButton: UIButton!
#IBOutlet weak var bottomRightButton: UIButton!
/* Questions Set */
var questionObjects = NSMutableOrderedSet(capacity: 100)
override func viewDidLoad() {
super.viewDidLoad()
getQuestionsFromJSONFile()
displayQuestion(0, jsonObjectsSet: questionObjects)
let string = "some Random Question"
questionLabel.text = string.capitalizeFirstCharacter
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getQuestionsFromJSONFile() {
var questionsJSONData: NSData? = nil
do {
let pathToQuestionsJSONFile = try NSBundle.mainBundle().pathForResource("Trivia_100-199", ofType: "json")
do {
questionsJSONData = try NSData(contentsOfFile: pathToQuestionsJSONFile!, options: NSDataReadingOptions.DataReadingMappedIfSafe)
let questionsJSONContent = JSON(data: questionsJSONData!)
if let object : [String:[String:AnyObject]] = questionsJSONContent.object as? [String:[String:AnyObject]] {
parseJSONContentIntoObjects(object)
}
} catch let error as NSError {
print(error.localizedDescription)
}
/*
if let questionsJSONContent = JSON(data: questionsJSONData!) as? [String: [String : AnyObject]] {
parseJSONContentIntoObjects(questionsJSONContent) // PSE: Potential Source of Error
}
*/
} catch let error as NSError {
print(error.localizedDescription)
print(error.localizedFailureReason)
print(error.localizedRecoveryOptions)
print(error.localizedRecoverySuggestion)
}
}
func parseJSONContentIntoObjects(jsonData: [String: [String : AnyObject]]) {
var questionHasAProperAnswer = false // indicator to determine if a proper answer was provided by the API for this specific question
let jsonObjects = NSMutableOrderedSet(capacity: 100)
for (questionAnswer,questionPropertiesSubJson):(String,[String:AnyObject]) in jsonData {
if let questionObject = Question(questionObjectSubJson: questionPropertiesSubJson) as? Question { // All parsing code is in the model file (Question.swift)
if let answerText = questionObject.questionAnswer as? String {
let questionExclusionKeywords = ["the Earth probably", "boring", "uninteresting", "unremarkable", "we do not know", "nothing", "remarkable", "a number for which", "missing a fact"]
for questionExclusionKeyword in (questionExclusionKeywords as? [String])! {
questionHasAProperAnswer = !answerText.containsString(questionExclusionKeyword)
/*
if questionHasAProperAnswer {
jsonObjects.addObject(questionObject)
}
}
if answerText.containsAny(questionExclusionKeywords) {
jsonObjects.addObject(questionObject)
}
*/
jsonObjects.addObject(questionObject)
}
}
}
questionObjects = jsonObjects
if questionObjects.count == 0 {
let fillerObject = Question(questionText: "Some question", questionAnswer: 1234, questionFalseAnswer1: "333", questionFalseAnswer2: "444", questionFalseAnswer3: "555")
questionObjects.addObject(fillerObject)
}
}
}
func displayQuestion(questionIndex: Int, jsonObjectsSet: NSMutableOrderedSet) {
if let specificQuestionObject = jsonObjectsSet.objectAtIndex(questionIndex) as? Question {
if let questionText = specificQuestionObject.questionText {
questionLabel.text = questionText
}
if let questionAnswer = specificQuestionObject.questionAnswer as? String {
let capitalizedQuestionAnswer = questionAnswer.capitalizeFirstCharacter
topLeftButton.titleLabel?.text = capitalizedQuestionAnswer
}
bottomLeftButton.titleLabel?.text = "Some false answer"
topRightButton.titleLabel?.text = "Some other false answer"
bottomRightButton.titleLabel?.text = "Another random false answer"
}
}
Related
I am using MySQL and PHP to download a restaurants menu but the user of the app should be able to add a certain amount to which item from the menu they want. Currently I am using a stepper to indicate the amount and adding that amount to a UserDefaults key which gets called when the menu is downloaded again.
This makes me have to download the menu again when I go to another viewController which sums up the order but I can't seem to filter out only them items which do have an amount.
What is a better way to add that amount to the downloaded data and how can I filter these items in my cart ViewController to only show and use the items which have an amount.
My current downloadModel, MenuModel, cellViewController (for the menu tableview) look like this:
MenuDownload.swift:
import UIKit
protocol MenuDownloadProtocol: class {
func productsDownloaded(products: NSArray)
}
class MenuDownload: NSObject {
//properties
weak var delegate: MenuDownloadProtocol!
func downloadProducts() {
let urlPath = "http://server.com/download.php" // Fake URL obviously
let url: URL = URL(string: urlPath)!
let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: url) { (data, response, error) in
if error != nil {
print("Failed to download data")
}else {
print("Menu downloaded")
self.parseJSON(data!)
}
}
task.resume()
}
func parseJSON(_ data:Data) {
var jsonResult = NSArray()
do{
jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
var jsonElement = NSDictionary()
let products = NSMutableArray()
for i in 0 ..< jsonResult.count
{
jsonElement = jsonResult[i] as! NSDictionary
let restomenu = MenuModel()
//the following insures none of the JsonElement values are nil through optional binding
if let product = jsonElement["product"] as? String,
let price = jsonElement["price"] as? String,
let info = jsonElement["info"] as? String,
let imageurl = jsonElement["imageurl"] as? String
{
let productandprice = product + " " + "€" + price
let quantityy = UserDefaults.standard.object(forKey: productandprice) as? String
restomenu.product = product
restomenu.price = price
restomenu.info = info
restomenu.imageurl = imageurl
restomenu.quantity = quantityy
}
products.add(restomenu)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.productsDownloaded(products: products)
})
}
}
extension String {
func chopPrefix(_ count: Int = 1) -> String {
return substring(from: index(startIndex, offsetBy: count))
}
func chopSuffix(_ count: Int = 1) -> String {
return substring(to: index(endIndex, offsetBy: -count))
}
}
MenuModel.swift:
import UIKit
class MenuModel: NSObject {
//properties
var product: String?
var price: String?
var info: String?
var imageurl: String?
var quantity: String?
//empty constructor
override init()
{
}
init(product: String, price: String, info: String, imageurl: String, quantity: String) {
self.product = product
self.price = price
self.info = info
self.imageurl = imageurl
self.quantity = quantity
}
//prints object's current state
override var description: String {
return "product: \(String(describing: product)), price: \(String(describing: price)), info: \(String(describing: info)), imageurl: \(String(describing: imageurl)), quantity: \(String(describing: quantity))"
}
}
tableViewCell.swift:
import UIKit
class productTableViewCell: UITableViewCell {
#IBOutlet weak var productLabel: UILabel!
#IBOutlet weak var productImage: UIImageView!
#IBOutlet weak var cellView: UIView!
#IBOutlet weak var orderCount: UILabel!
#IBOutlet weak var stepper: UIStepper!
var amount: String?
#IBAction func stepperValueChanged(_ sender: UIStepper) {
amount = Int(sender.value).description
orderCount.text = amount
// let defaultkey = String(productLabel.text!)
UserDefaults.standard.setValue(amount, forKey: productLabel.text!)
if amount == "0"
{
orderCount.isHidden = true
UserDefaults.standard.removeObject(forKey: productLabel.text!)
}
else
{
orderCount.isHidden = false
}
}
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
}
}
EDIT: after trying filtering options and many different ways I still haven't found how to fix this. I think I'm overthinking it too much.
I am trying to parse json data in my table view cell and its not parsing and not showing the cells . I am attaching all my code please tell me whats the mistake i am doing .. I am not getting any error but the cells are not showing. I have made separate class and functions for json parsing and storing it in an array .
//
// ViewController.swift
// WorkingFeed2
//
// Created by keshu rai on 08/08/17.
// Copyright © 2017 keshu rai. All rights reserved.
//
import UIKit
import Alamofire
import MediaPlayer
class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource{
var post : PostData!
var posts = [PostData]()
typealias DownloadComplete = () -> ()
var arrayOfPostData : [String] = []
#IBOutlet weak var feedTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
feedTable.dataSource = self
feedTable.delegate = self
}
func downloadPostData(completed: #escaping DownloadComplete) {
Alamofire.request("https://new.example.com/api/posts/get_all_posts").responseJSON { response in
let result = response.result
if let dict = result.value as? Dictionary<String,AnyObject> {
if let successcode = dict["STATUS_CODE"] as? Int {
if successcode == 1 {
if let postsArray = dict["posts"] as? [Dictionary<String,AnyObject>]
{
for obj in postsArray
{
let post = PostData(postDict: obj)
self.posts.append(post)
print(obj)
}
// self.posts.remove(at: 0)
self.feedTable.reloadData()
}
}
}
}
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 419
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : ImageTableViewCell = self.feedTable.dequeueReusableCell(withIdentifier: "contentViewReuse") as! ImageTableViewCell
let post = posts[indexPath.row]
print(post)
cell.configureCell(post : post)
return cell
}
}
This is my PostData Class.
import Foundation
class PostData {
var _profileImageURL : String?
var _fullName : String?
var _location : String?
var _title : String?
var _postTime : String?
var _likes : Int?
var _comments : Int?
var _mediaType : String?
var _contentURL : String?
var _content : String?
var _plocation : String?
var profileImageURL : String
{
if _profileImageURL == nil {
_profileImageURL = ""
}
return _profileImageURL!
}
var fullName : String
{
if _fullName == nil {
_fullName = ""
}
return _fullName!
}
var location : String {
if _location == nil {
_location = ""
}
return _location!
}
var title : String {
if _title == nil {
_title = ""
}
return _title!
}
var postTime : String {
if _postTime == nil {
_postTime = ""
}
return _postTime!
}
var likes : Int {
if _likes == nil {
_likes = 0
}
return _likes!
}
var comments : Int {
if _comments == nil {
_comments = 0
}
return _comments!
}
var mediaType : String {
if _mediaType == nil {
_mediaType = ""
}
return _mediaType!
}
var contentURL : String {
if _contentURL == nil {
_contentURL = ""
}
return _contentURL!
}
var content : String {
if _content == nil {
_content = ""
}
return _content!
}
var pLocation : String {
if _plocation == nil {
_plocation = ""
}
return _plocation!
}
init(postDict : Dictionary<String , AnyObject>)
{
if let postsArray = postDict["posts"] as? [Dictionary<String,AnyObject>]
{
for i in 1..<postsArray.count
{
let fullName1 = postsArray[i]["full_name"] as? String
self._fullName = fullName1
let profileImageURL1 = postsArray[i]["profile_pic"] as? String
self._profileImageURL = profileImageURL1
let location1 = postsArray[i]["user_city"] as? String
self._location = location1
let title1 = postsArray[i]["title"] as? String
self._title = title1
let postTime1 = postsArray[i]["order_by_date"] as? String
self._postTime = postTime1
let likes1 = postsArray[i]["liked_count"] as? Int
self._likes = likes1
let comments1 = postsArray[i]["comment_count"] as? Int
self._comments = comments1
let mediaType1 = postsArray[i]["media_path"] as? String
self._mediaType = mediaType1
let contentURL1 = postsArray[i]["media_path"] as? String
self._contentURL = contentURL1
let content1 = postsArray[i]["content"] as? String
self._content = content1
let plocation1 = postsArray[i]["location"] as? String
self._plocation = plocation1
}
}
}
}
This is my PostDataTableViewCell code.
import UIKit
import Alamofire
class PostDataTableViewCell: UITableViewCell {
#IBOutlet weak var profileImage: UIImageView!
#IBOutlet weak var titlePost: UILabel!
#IBOutlet weak var profileFullName: UILabel!
#IBOutlet weak var profileUserLocation: UILabel!
#IBOutlet weak var likeBtn: UIButton!
var buttonAction: ( () -> Void) = {}
var pressed = false
#IBAction func likeBtnPressed(_ sender: Any) {
if !pressed {
let image = UIImage(named: "Like-1.png") as UIImage!
likeBtn.setImage(image, for: .normal)
pressed = true
} else {
let image = UIImage(named: "liked.png") as UIImage!
likeBtn.transform = CGAffineTransform(scaleX: 0.15, y: 0.15)
UIView.animate(withDuration: 2.0,
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
options: .allowUserInteraction,
animations: { [weak self] in
self?.likeBtn.transform = .identity
},
completion: nil)
likeBtn.setImage(image, for: .normal)
pressed = false
}
}
#IBAction func commentBtnPressed(_ sender: Any) {
print("Commented")
}
#IBAction func shareBtnPressed(_ sender: Any) {
self.buttonAction()
}
#IBAction func readContentBtnPressed(_ sender: Any) {
print("Read")
}
#IBOutlet weak var contentPostLabel: UILabel!
#IBOutlet weak var contentTypeView: UIView!
#IBOutlet weak var likeAndCommentView: UIView!
#IBOutlet weak var numberOfLikes: UILabel!
#IBOutlet weak var numberOfComments: UILabel!
#IBOutlet weak var postLocation: UILabel!
#IBOutlet weak var postTimeOutlet: UILabel!
func configureCell(post : PostData)
{
titlePost.text = "\(post.title)"
profileFullName.text = "\(post.fullName)"
profileUserLocation.text = "\(post.location)"
numberOfLikes.text = "\(post.likes) Likes"
numberOfComments.text = "\(post.comments) Comments"
postLocation.text = "\(post.pLocation)"
postTimeOutlet.text = "\(post.postTime)"
let url = URL(string: post.profileImageURL)
let data = try? Data(contentsOf: url!)
profileImage.image = UIImage(data: data!)
contentPostLabel.text = "\(post.content)"
if post.mediaType == "image"
{
let url1 = URL(string: post.contentURL)
let data1 = try? Data(contentsOf: url1!)
let image = UIImage(data: data1!)
let imageToView = UIImageView(image: image!)
imageToView.frame = CGRect(x: 0, y: 0, width: 375 , height: 250)
imageToView.contentMode = UIViewContentMode.scaleToFill
contentTypeView.addSubview(imageToView)
}
else if post.mediaType == "null"
{
print("Status")
}
else if post.mediaType == "video"
{
print("Video")
}
else if post.mediaType == "youtube"
{
print("youtube")
}
}
}
Most likely the issue occurs because you are trying to parse the value for key posts twice, once in PostData and once in ViewController.
First of all in Swift 3 a JSON dictionary is [String:Any], secondly – as already mentioned in my comment – private backing variables are nonsense in Swift.
The class PostData can be reduced to
class PostData {
let profileImageURL : String
let fullName : String
let location : String
let title : String
let postTime : String
let likes : Int
let comments : Int
let mediaType : String
let contentURL : String
let content : String
let plocation : String
init(postDict : [String:Any])
{
fullName = postDict["full_name"] as? String ?? ""
profileImageURL = postDict["profile_pic"] as? String ?? ""
location = postDict["user_city"] as? String ?? ""
title = postDict["title"] as? String ?? ""
postTime = postDict["order_by_date"] as? String ?? ""
likes = postDict["liked_count"] as? Int ?? 0
comments = postDict["comment_count"] as? Int ?? 0
mediaType = postDict["media_path"] as? String ?? ""
contentURL = postDict["media_path"] as? String ?? ""
content = postDict["content"] as? String ?? ""
plocation = postDict["location"] as? String ?? ""
}
}
I'm currently trying to make a label showing different text for each user, to have a standard text before this label but not inside the cell on the .xib file.
What i've done until know is this
import UIKit
class profileViewController: UIViewController {
#IBOutlet var lblUsersname: UILabel!
#IBOutlet var lblUserspoints: UILabel!
#IBOutlet var imgViewUserAvatar: UIImageView!
var profileJson : [String:AnyObject] = [ : ]
var userid = ""
var usersname = ""
var userspoints = ""
var usersavatar = ""
var pointtxt = "Points: "
override func viewDidLoad() {
super.viewDidLoad()
let defaults = NSUserDefaults.standardUserDefaults()
if let usersid = defaults.stringForKey("usersId") {
userid = usersid
fetchDatas()
lblUsersname.text = usersname
lblUserspoints.text = userspoints
}else{
print("Error")
}
if let checkedUrl = NSURL(string: usersavatar) {
downloadImage(checkedUrl)
}
}
func fetchDatas(){
let urlara = NSLocalizedString("profileRequest", comment: "")
let loginRequest = receiveData(data1: "id=\(userid)", url1: NSURL(string: urlara)!)
profileJson = loginRequest.fetchData()
if let locationsArray = profileJson["profile"] as? [[String:AnyObject]] {
for locationDictionary in locationsArray {
if let name = locationDictionary["name"] as? String {
usersname = name
}
if let points = locationDictionary["points"] as? String {
userspoints = points
}
if let avatar = locationDictionary["avatar"] as? String {
usersavatar = avatar
}
}
}
}
So now it's show only the number of the points
And i'm trying to make it show
Points: lblUserpoints
Anyone has any idea?
After some tryings i find it out. changed the line
lblUserspoints.text = userspoints
to this
lblUserpoints.text = String(pointtxt) + userpoints
And i had the desired output which was
Points: 2910
Video showing the problem at runtime: https://www.youtube.com/watch?v=INVTDEJ8ZqY
I am having a lot of trouble correctly parsing the JSON from a local JSON file, storing it into an array and then displaying it in my view.
My app doesn't crash. My 4 buttons and 1 label simply do not change values. They just get those sample values I added in there "Question 1", "Question 2", etc...
How do I get it to display the values from my JSON file ? It looks like this
/* Question label storyboard outlet */
#IBOutlet weak var questionLabel: UILabel!
// Answer button storyboard outlets
#IBOutlet weak var topLeftButton: UIButton!
#IBOutlet weak var topRightButton: UIButton!
#IBOutlet weak var bottomLeftButton: UIButton!
#IBOutlet weak var bottomRightButton: UIButton!
/* Questions Set */
var questionObjects = NSMutableOrderedSet(capacity: 100)
override func viewDidLoad() {
super.viewDidLoad()
getQuestionsFromJSONFile()
displayQuestion(0, jsonObjectsSet: questionObjects)
let string = "some Random Question"
questionLabel.text = string.capitalizeFirstCharacter
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getQuestionsFromJSONFile() {
var questionsJSONData: NSData? = nil
do {
let pathToQuestionsJSONFile = try NSBundle.mainBundle().pathForResource("Trivia_100-199", ofType: "json")
do {
questionsJSONData = try NSData(contentsOfFile: pathToQuestionsJSONFile!, options: NSDataReadingOptions.DataReadingMappedIfSafe)
let questionsJSONContent = JSON(data: questionsJSONData!)
if let object : [String:[String:AnyObject]] = questionsJSONContent.object as? [String:[String:AnyObject]] {
parseJSONContentIntoObjects(object)
}
} catch let error as NSError {
print(error.localizedDescription)
}
/*
if let questionsJSONContent = JSON(data: questionsJSONData!) as? [String: [String : AnyObject]] {
parseJSONContentIntoObjects(questionsJSONContent) // PSE: Potential Source of Error
}
*/
} catch let error as NSError {
print(error.localizedDescription)
print(error.localizedFailureReason)
print(error.localizedRecoveryOptions)
print(error.localizedRecoverySuggestion)
}
}
func parseJSONContentIntoObjects(jsonData: [String: [String : AnyObject]]) {
var questionHasAProperAnswer = false // indicator to determine if a proper answer was provided by the API for this specific question
let jsonObjects = NSMutableOrderedSet(capacity: 100)
for (questionAnswer,questionPropertiesSubJson):(String,[String:AnyObject]) in jsonData {
if let questionObject = Question(questionObjectSubJson: questionPropertiesSubJson) as? Question { // All parsing code is in the model file (Question.swift)
if let answerText = questionObject.questionAnswer as? String {
let questionExclusionKeywords = ["the Earth probably", "boring", "uninteresting", "unremarkable", "we do not know", "nothing", "remarkable", "a number for which", "missing a fact"]
for questionExclusionKeyword in (questionExclusionKeywords as? [String])! {
questionHasAProperAnswer = !answerText.containsString(questionExclusionKeyword)
/*
if questionHasAProperAnswer {
jsonObjects.addObject(questionObject)
}
}
if answerText.containsAny(questionExclusionKeywords) {
jsonObjects.addObject(questionObject)
}
*/
jsonObjects.addObject(questionObject)
}
}
}
questionObjects = jsonObjects
if questionObjects.count == 0 {
let fillerObject = Question(questionText: "Some question", questionAnswer: 1234, questionFalseAnswer1: "333", questionFalseAnswer2: "444", questionFalseAnswer3: "555")
questionObjects.addObject(fillerObject)
}
}
}
func displayQuestion(questionIndex: Int, jsonObjectsSet: NSMutableOrderedSet) {
if let specificQuestionObject = jsonObjectsSet.objectAtIndex(questionIndex) as? Question {
if let questionText = specificQuestionObject.questionText {
questionLabel.text = questionText
}
if let questionAnswer = specificQuestionObject.questionAnswer as? String {
let capitalizedQuestionAnswer = questionAnswer.capitalizeFirstCharacter
topLeftButton.titleLabel?.text = capitalizedQuestionAnswer
}
bottomLeftButton.titleLabel?.text = "Some false answer"
topRightButton.titleLabel?.text = "Some other false answer"
bottomRightButton.titleLabel?.text = "Another random false answer"
}
}
For buttons, you should use setTitle(forState:). For example:
button.setTitle("foo", forState: .Normal)
I am attempting to send an array of data to a new view controller and I'm currently getting the error fatal error: unexpectedly found nil while unwrapping an Optional value
Im using the API data from www.thecocktaildb.com
Example:
http://www.thecocktaildb.com/api/json/v1/1/search.php?s=margarita
Not sure what I'm doing wrong. Tried debugging and checking values before the segue in my search view controller and they're accurate.
Heres my code:
Main Storyboard
SearchViewController
class SearchViewController: UIViewController, UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var TableView: UITableView!
#IBOutlet weak var SearchBar: UISearchBar!
var valueToPass:Drinks!
var isSearching : Bool = false
class Drinks {
var idDrink: Int = 0
var strDrink: String = ""
var strCategory: String = ""
var strAlcoholic: String = ""
var strGlass: String = ""
var strInstructions: String = ""
var strDrinkThumb: String = ""
var strIngredient1: String = ""
var strIngredient2: String = ""
var strIngredient3: String = ""
var strIngredient4: String = ""
var strIngredient5: String = ""
var strIngredient6: String = ""
var strIngredient7: String = ""
var strIngredient8: String = ""
var strIngredient9: String = ""
var strIngredient10: String = ""
var strIngredient11: String = ""
var strIngredient12: String = ""
var strIngredient13: String = ""
var strIngredient14: String = ""
var strIngredient15: String = ""
var strMeasure1: String = ""
var strMeasure2: String = ""
var strMeasure3: String = ""
var strMeasure4: String = ""
var strMeasure5: String = ""
var strMeasure6: String = ""
var strMeasure7: String = ""
var strMeasure8: String = ""
var strMeasure9: String = ""
var strMeasure10: String = ""
var strMeasure11: String = ""
var strMeasure12: String = ""
var strMeasure13: String = ""
var strMeasure14: String = ""
var strMeasure15: String = ""
}
var TableData:Array< Drinks > = Array < Drinks >()
override func viewDidLoad() {
super.viewDidLoad()
for subView in self.SearchBar.subviews
{
for subsubView in subView.subviews
{
if let textField = subsubView as? UITextField
{
textField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Search", comment: ""))
}
}
}
self.SearchBar.delegate = self
self.TableView.delegate = self
self.TableView.dataSource = self
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if self.SearchBar.text!.isEmpty {
self.isSearching = false
}else{
self.isSearching = true
let userSearchInput = self.SearchBar.text!.lowercaseString
let newString = userSearchInput.stringByReplacingOccurrencesOfString(" ", withString: "%20", options: NSStringCompareOptions.LiteralSearch, range: nil)
let postEndpoint: String = "http://www.thecocktaildb.com/api/json/v1/1/search.php?s=" + newString
guard let url = NSURL(string: postEndpoint) else {
print("Error: cannot create URL")
return
}
let urlRequest = NSURLRequest(URL: url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(urlRequest, completionHandler: { (data, response, error) in
guard let responseData = data else {
print("Error: did not receive data")
return
}
guard error == nil else {
print("error calling GET on www.thecocktaildb.com")
print(error)
return
}
let post: NSDictionary
do {
post = try NSJSONSerialization.JSONObjectWithData(responseData,
options: []) as! NSDictionary
} catch {
print("error trying to convert data to JSON")
return
}
var count = 1
if let drinks = post["drinks"] as? [NSDictionary] {
self.TableData.removeAll()
for drink in drinks {
let adrink = Drinks()
if let strDrink = drink["strDrink"] as? String {
print(String(count) + ". " + strDrink)
adrink.strDrink = strDrink
count++
}
if let strCategory = drink["strCategory"] as? String {
print(" Category: " + strCategory)
adrink.strCategory = strCategory
}
if let strDrinkThumb = drink["strDrinkThumb"] as? String {
print(" Thumbnail Image: " + strDrinkThumb)
adrink.strDrinkThumb = strDrinkThumb
}
self.TableData.append(adrink)
self.TableView.reloadData()
}
}
})
task.resume()
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TableData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
//title = TableData[indexPath.row].strDrink
cell.textLabel?.text = TableData[indexPath.row].strDrink;
let imageString = TableData[indexPath.row].strDrinkThumb
if (imageString == ""){
let noDrinkImage : UIImage = UIImage(named: "noimage.jpg")!
cell.imageView!.image = noDrinkImage
}else{
let drinkImage = UIImage(data: NSData(contentsOfURL: NSURL(string:TableData[indexPath.row].strDrinkThumb)!)!)
cell.imageView!.image = drinkImage
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
print(TableData[indexPath.row].strDrink)
valueToPass = TableData[indexPath.row]
//self.performSegueWithIdentifier("drinkSegue", sender: TableData[indexPath.row])
}
// hide kwyboard when search button clicked
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
self.SearchBar.resignFirstResponder()
}
// hide keyboard when cancel button clicked
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
self.SearchBar.text = ""
self.SearchBar.resignFirstResponder()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "DrinkSegue") {
// initialize new view controller and cast it as your view controller
let drinkViewController = segue.destinationViewController as! DrinkViewController
// your new view controller should have property that will store passed value
drinkViewController.passedValue = valueToPass
}
}
}
DrinkViewController.swift
class DrinkViewController: UIViewController {
#IBOutlet weak var DrinkNameLabel: UILabel!
var passedValue : SearchViewController.Drinks!
override func viewDidLoad() {
super.viewDidLoad()
DrinkNameLabel.text = passedValue!.strDrink
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Do it like this instead
In your didSelectRowAtIndexPath pass the array
self.performSegueWithIdentifier("drinkSegue", sender: TableData[indexPath.row])
Here you need to pass the array to your DrinkViewController
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "DrinkSegue") {
// initialize new view controller and cast it as your view controller
let drinkViewController = segue.destinationViewController as! DrinkViewController
// your new view controller should have property that will store passed value
drinkViewController.passedValue = valueToPass
// declare myArray in your drinkViewController and then assign it here
// now your array that you passed will be available through myArray
drinkViewController.myArray = sender
}
}
Update
After I got your project I noticed that the issue you had was that you did drag a segue from the tableView to the drinksController directly - what happened is that didSelectRowAtIndexPath will not be called and your sender will always be nil drinkViewController.myArray = sender as! Drinks.
I changed that by dragging the segue from the viewController to the drinksController instead.