I have a tablecell to work with and I can populate it when I use a written array (like values = [""]) so I know it is working.
But I am using json with swiftyjson to get my info in my table, which is part of a right slideout page I made with mmdrawer. When I println the json output I get all the info I need, but it is not being taken to the table or other variables/arrays.
How do I make this code work?
import UIKit
class RightSideViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var songname = [String]()
var menuImage = [String]()
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBarHidden = true
}
override func prefersStatusBarHidden() -> Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
getmusiclist()
}
func getmusiclist(){
let search:NSString = "music" as NSString
let url = NSURL(string:"http://xxxxxx/music-manager.php")
let cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
var request = NSMutableURLRequest(URL: url!, cachePolicy: cachePolicy, timeoutInterval: 2.0)
request.HTTPMethod = "POST"
// set Content-Type in HTTP header
let boundaryConstant = "----------V2ymHFg03esomerandomstuffhbqgZCaKO6jy";
let contentType = "multipart/form-data; boundary=" + boundaryConstant
NSURLProtocol.setProperty(contentType, forKey: "Content-Type", inRequest: request)
// set data
var dataString = "search=\(search)"
let requestBodyData = (dataString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
request.HTTPBody = requestBodyData
// set content length
//NSURLProtocol.setProperty(requestBodyData.length, forKey: "Content-Length", inRequest: request)
var response: NSURLResponse? = nil
var error: NSError? = nil
let dataReply = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)
var results = NSJSONSerialization.JSONObjectWithData(dataReply!, options: nil, error: &error) as! NSDictionary
var jsonOutput = JSON(data: dataReply!)
println(jsonOutput)
let musicListArray = jsonOutput.arrayValue
dispatch_async(dispatch_get_main_queue(), {
for playlist in musicListArray
{
let trackname = playlist["track_name"].stringValue
println("trackName: \(trackname)")
self.songname.append(trackname)
}
/* dispatch_async(dispatch_get_main_queue(),{
self.tableView.reloadData()
})*/
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return songname.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var mycell = tableView.dequeueReusableCellWithIdentifier("playerCell", forIndexPath: indexPath) as! MusicTableViewCell
mycell.artistLabel?.text = songname[indexPath.row]
return mycell
}
}
Eventually I would also like to take the name, genre and streaming url and have avplayer play it - will that be something I can add to this code?
the problem with in the part that i forgot to add the uitableview outlet in the uiviewcontroller. I have added it and now the error is gone. I still have to figure out why i am not getting anything but it seems that i am nu getting the data from the jsonOutput.arrayvalue.
Related
I am adding tableview cell label text to phNumArray, in tableview i am getting all values but when i try to pass in service call then its coming nill why?
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var joinersTableView: UITableView!
var tablcellArray = [String]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: Namescell = tableView.dequeueReusableCell(withIdentifier: "Namescell") as! Namescell
cell.empRoleLbl.text = empTeftfield.text
tablcellArray.append((cell.empRoleLbl.text!))
print("employee names array \(tablcellArray)")// here coming all appende values
return cell
}
func getPostData(params: [String:Any]) -> Data? {
return try? JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
DispatchQueue.main.async {
self.joinersTableView.reloadData()
}
}
func callPostApi() {
print("tableview emp values\(tablcellArray)")// here array values not coming
let url = URL(string: "http://itaag-env-1/")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
print("appende values \(tablcellArray)")
try? request.setMultipartFormData(["contactsList": "\(tablcellArray)"], encoding: .utf8)
DispatchQueue.main.async {
self.joinersTableView.reloadData()
}
URLSession.shared.dataTask(with: request) { data, _, _ in
if let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
}
}.resume()
}
}
in tableview cellfor row appended values coming.. but when i try to bring that array in callPostApi func then tablcellArray showing nil why?
please share your knowledge, please try to solve this error.
firstly change
var tablcellArray = [String]()
to
var tablcellArray = [String]
then in your cellForRowAt try to access your data such as
let empTeftfield = tablcellArray[indexPath.row]
if this line prints correctly
cell.empRoleLbl.text = empTeftfield.text
this should work.
if not prints your value reload tableview after fetching data from api. you shouldnt add values to your array in your conditions.
My json contains image, type and id.. here i want my ids in separate individual array called idArray.. here i am able to get single id in log, i have append ids to idArray but i am not getting ids in array it shows nil why?
i have taken idArray as string. please help me in code.
here is my json structure:
{
"financer": [
{
"id": "45",
"icon": "https://hello.com//images/img1.png"
"tpe": "bank"
}
{
"id": "40",
"icon": "https://hello.com//images/img2.png"
"tpe": "wallet"
}
.
.
.
]
}
here is my code:
import UIKit
import SDWebImage
struct JsonData {
var iconHome: String?
var typeName: String?
init(icon: String, tpe: String) {
self.iconHome = icon
self.typeName = tpe
}
}
class HomeViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITextFieldDelegate {
#IBOutlet weak var collectionView: UICollectionView!
var itemsArray = [JsonData]()
var idArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
homeServiceCall()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return itemsArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! HomeCollectionViewCell
let aData = itemsArray[indexPath.row]
cell.paymentLabel.text = aData.typeName
cell.paymentImage.sd_setImage(with: URL(string:aData.iconHome!), placeholderImage: UIImage(named: "GVMC_icon"))
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "MakePaymentViewController") as? MakePaymentViewController
{
nextViewController.financerId = idArray[indexPath.row]
self.navigationController?.pushViewController(nextViewController, animated: true)
}
else{
AlertFun.ShowAlert(title: "", message: "will update soon..", in: self)
}
}
//MARK:- Service-call
func homeServiceCall(){
let urlStr = "https://webservices/getfinancer"
let url = URL(string: urlStr)
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
guard let respData = data else {
return
}
guard error == nil else {
print("error")
return
}
do{
let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any]
//print("the home json is \(jsonObj)")
let financerArray = jsonObj["financer"] as! [[String: Any]]
print("home financerData \(financerArray)")
for financer in financerArray {
let id = financer["id"] as? String
let pic = financer["icon"] as? String
let typeName = financer["tpe"] as! String
print("home financer id \(String(describing: id))")
self.idArray.append(id ?? "")
print("the home financer idsArray \(self.idArray.append(id ?? ""))")
self.itemsArray.append(JsonData(icon: pic ?? "", tpe: typeName))
}
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
catch {
print("catch error")
}
}).resume()
}
}
Unable to json ids in separate array please help me in my code.
Don't use multiple arrays as data source. That's very bad practice.
Create two structs conforming to Decodable
struct Root : Decodable {
let financer : [Financer]
}
enum Type : String, Decodable {
case bank, wallet
}
struct Financer : Decodable {
let id : String
let icon : URL
let tpe : Type
}
Declare the data source array
var itemsArray = [Financer]()
and delete
var idArray = [String]()
Replace homeServiceCall with
func homeServiceCall() {
let url = URL(string: "https://dev.com/webservices/getfinancer")
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
if let error = error { print(error); return }
do {
DispatchQueue.main.async {
self.activityIndicator.startAnimating()
}
let result = try JSONDecoder().decode(Root.self, from: data!)
self.itemsArray = result.financer
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
catch {
print(error) -- print always the error instance.
}
}).resume()
}
In cellForRow get the id value with
let aData = itemsArray[indexPath.row]
cell.paymentLabel.text = aData.id
Important note:
Never never ever use synchronous Data(contentsOf to load data from a remote URL. Use an API which loads the data asynchronously and caches the images
My PhotoModel is returning nothing for eventDate()..
I have set it with
let newPhotos = PhotosModel() // Create the instance
newPhotos.eventDate = item.event_date! // Set the parameter
inside didSelectItemAt which when printed returns the correct date in the previous viewcontroller but isn't pushing it to the PhotoModel string.
If anyone could point me in the right direction or demonstrate what needs to be done that would be great, thank you.
ViewController:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath.row)
// Configure the cell
let item: CoverModel = feedItems[indexPath.row] as! CoverModel
let Storyboard = UIStoryboard(name: "Main", bundle: nil)
let DvC = Storyboard.instantiateViewController(withIdentifier: "DetailCollectionViewController") as! DetailCollectionViewController
print(item.event_date!)
let newPhotos = PhotosModel() // Create the instance
newPhotos.eventDate = item.event_date! // Set the parameter
print(newPhotos.eventDate)
self.navigationController?.pushViewController(DvC, animated: true)
}
PhotosModel:
protocol PhotosProtocol: class {
func itemsDownloaded(items: NSArray)
}
class PhotosModel: NSObject, URLSessionDataDelegate {
//properties
weak var delegate: PhotosProtocol!
var eventDate = String()
var data = Data()
func downloadItems() {
let urlPath: String = "http://www.britanniaclub.co.uk/app_calls/britalbum.php?eventdate=\(eventDate)"
let url: URL = URL(string: urlPath)!
print("the event date is \(eventDate)")
print("the urlPath is \(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("Event Data downloaded")
self.parseJSON(data!)
}
}
task.resume()
}
Output is:
2017-07-14
the event date is
the urlPath is http://www.britanniaclub.co.uk/app_calls/britalbum.php?eventdate=
Event Data downloaded
My guess is you are not assigning newPhotos to any property of DetailCollectionViewController. You will have to do it before pushing this view controller.
I am fairly new to Swift and I am having a few issues with getting understanding how to do what I want to do.
I am currently testing some stuff with json.
What I am trying to do is to append the data I get from my json data into an array. And when my array contains the data I wish to present it to my UICollectionView. I am assuming that I should be using an array.
import UIKit
import Foundation
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getData() {
let path = "http://myurl/test.json"
let url = URL(string: path)
let session = URLSession.shared
let task = session.dataTask(with: url!) { (data: Data?, response: URLResponse?, error: Error?) in
let json = JSON(data: data!)
for result in json["dokumentstatus"]["dokutskott"]["utskott"].array! {
let punkter = result["punkt"].string!
print("punkt: \(punkt)")
let rubrik = result["rubrik"].string
print("rubrik: \(rubrik)")
let forslag = result["forslag"].string
print("förslag: \(forslag)")
}
}
task.resume()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return //someArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCollectionViewCell
cell.customLabel.text = //Put the data form rubrik variable
cell.customTW.text = //Put the data from foreleg variable
return cell
}
}
the function getData() gets the correct json data I just need help understanding how to put this data to an array.
(Also, I know I probably shouldn't be getting the data in the ViewController, but this is only a test.)
import Foundation
class Information: NSObject {
var punkter: String?
var rubrik: String?
var forslag: String?
}
I'm thinking that maybe I should be using an array that looks something like this:var someArray = [Information]()
But I do not know how to then use my getData()
Or maybe I should be using three different arrays, one for each of my json variables.
Since you're still using a custom class (well done!, three different arrays are horrible) it's correct to declare a data source array like you suggested
var someArray = [Information]()
Most likely a struct is sufficient, I recommend to use non-optional strings
struct Information {
var punkter : String
var rubrik : String
var forslag : String
}
If the properties won't change you could even use let to make the properties constants.
To populate the array use the nil coalescing operator to check for nil,create the Information instance with the memberwise initializer and append the instance to the datasource array. Then reload the collection view on the main thread.
...
for result in json["dokumentstatus"]["dokutskott"]["utskott"].array! {
let punkter = result["punkt"].string ?? ""
let rubrik = result["rubrik"].string ?? ""
let forslag = result["forslag"].string ?? ""
let information = Information(punkter:punkter, rubrik:rubrik, forslag:forslag)
self.someArray.append(information)
}
DispatchQueue.main.async {
self.collectionView.reloadData()
}
...
Edit:
To display the data in cellForItemAtIndexPath use
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCollectionViewCell
let information = someArray[indexPath.row]
cell.customLabel.text = information.rubrik
cell.customTW.text = information.foreleg
return cell
}
I have two ViewControllers. For the first ViewController, it displays my Array data on the table. I want to get the indexPath of the selected cell, and pass this data to another ViewController.
In my First ViewController
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
var nameList = [NameManager]()
#IBOutlet weak var NameTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
NameTable.dataSource = self
GetData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func GetData(){
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.json-generator.com/api/json/get/bPfifKWNaq?indent=2")!)
request.HTTPMethod = "GET"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let data = data{
do{
let resultJSON = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions())
let resultArray = resultJSON as? NSArray
for jsonObjectString in resultArray!{
let code = jsonObjectString["code"] as! String
let name = jsonObjectString["name"] as! String
let description = jsonObjectString["description"] as! String
self.nameList.append(NameManager(code: code, name: name, description: description))
}
self.nameList.count
dispatch_async(dispatch_get_main_queue(), {
self.NameTable.reloadData()
})
}catch _{
print("Received not-well-formatted JSON")
}
}
if let response = response {
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
let count = nameList.count
return count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let myCell = NameTable.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
myCell.textLabel?.text = nameList[indexPath.row].name
myCell.detailTextLabel?.text = nameList[indexPath.row].description
return myCell
}
In my Second ViewController, which is also another class, I want to capture the indexPath of what was selected. Using the index value, I search my Array and pass that particular object to the next class. I don't have codes for this as I don't know how it works.
You could create a property outside the scope of your class and then set that within the cellForRowAtIndexPath method. That property could be accessed in your second view controller. You’ll want to look at the tableview method didSelectRowAtIndexPath as that will be where you set your property to the cell that’s been selected.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
appDelegate().index = indexPath.row
}
I’ve made a super simple project on github showing two ways of creating a property outside the scope of your view controller. One way is creating a variable within AppDelegate to be accessed via a singleton, the other is a Globals.swift file.
Hope this helps!
If you want to pass values to the controller which pops after tapping on the cell, using a singleton wouldn't be an elegant way. If you are using storyboards, then you have to use 'prepare for segue'. You implement the method in the class that handles the transfer and set all the properties in another view controller.
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "SecondVC") {
// set properties
}
}