I am trying to ping an array containing different hosts. In each loop, I am saving an image depending on whether the ping was successful or not (checkImg, errorImg). Afterwards, I want to present the information (hostname and img) in a table.
The following code does work somehow but it is not stable. Sometimes I receive the following warning:
Thread 1: Fatal error: Index out of range In line: imgServer.image =
UIImage(named: statusImagesMain[indexPath.row])
So I suppose the ping loop for the different hosts did not get completed before serverStatusTable.reloadData() is executed.
Do you have any idea what I can do to overcome this problem?
swift 4
import UIKit
class ServerVC: SimplePingDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var serverStatusTable: UITableView!
let imageError = UIImage(named: "error")
let imageCheck = UIImage(named: "check")
var pings = ["www.apple.com", "www.appleidontknowwhy.de", "www.apple.com", "www.apple.com"]
var hosts = [String]() // hostnames which get pinged
var componentTextArray = [String]() // project names
var statusImagesTemporary = [String]() // temporary store images
var statusImagesMain = [String]() // array filled with temporary stored images
var serverStatusMain = [String]() // server status string (connected, error)
var serverStatusTemporary = [String]() // temporary server status
override func viewDidLoad() {
super.viewDidLoad()
serverStatusTable.dataSource = self
serverStatusTable.delegate = self
statusImagesMain = ["error", "error", "error", "error"]
componentTextArray = ["Project 1", "Project 2", "Project 3", "Project 4"]
serverStatusMain = ["no data", "no data", "no data", "no data"]
hosts = pings
pingNext()
serverStatusTable.reloadData()
}
override func viewDidAppear(_ animated: Bool) {
// initial ping host process when loading the view
startHostRequest()
}
#IBAction func refreshBtnAction(_ sender: Any) {
// manual ping host process when clicking the button "refresh"
startHostRequest()
}
func startHostRequest () {
print("refresh server status")
pingNext()
// clear array before each host ping process in order for the array to keep only four items
statusImagesMain.removeAll()
serverStatusMain.removeAll()
for statusImageTemporary in statusImagesTemporary {
statusImagesMain.append(statusImageTemporary)
}
for i in serverStatusTemporary {
serverStatusMain.append(i)
}
serverStatusTable.reloadData()
}
func pingNext() {
guard pings.count > 0 else {
return
}
let ping = pings.removeFirst()
PlainPing.ping(ping, withTimeout: 1.0, completionBlock: { (timeElapsed:Double?, error:Error?) in
if let latency = timeElapsed {
print("\(ping) latency (ms): \(latency)")
// fill temporary arrays with img and serverStatus text for successful connection
self.statusImagesTemporary.append("check")
self.serverStatusTemporary.append("Running ")
}
if let error = error {
print("error: \(error.localizedDescription)")
// fill temporary arrays with img and serverStatus text for failed connection attempt
self.statusImagesTemporary.append("error")
self.serverStatusTemporary.append("Error ")
}
self.pingNext()
})
}
// fill table with host data
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return componentTextArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = serverStatusTable.dequeueReusableCell(withIdentifier: "serverStatusCell", for: indexPath)
let lblServerStatus : UILabel = cell.contentView.viewWithTag(8) as! UILabel
let imgServer : UIImageView = cell.contentView.viewWithTag(7) as! UIImageView
imgServer.image = UIImage(named: statusImagesMain[indexPath.row])
lblServerStatus.text = serverStatusMain[indexPath.row]
return cell
}
}
Your bug lies in startHostRequest() and tableView(_ tableView: UITableView, numberOfRowsInSection section: Int).
In startHostRequest() you copy statusImagesTemporary to statusImagesMain, and statusImageTemporary is empty at the start, and it finishes with .reloadData(). tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) returns componentTextArray.count which is always 4. When these two are put together once startHostRequest() is called the table is reloaded, instructed to have 4 rows, but there are 0 rows of data to fill in the rows.
Managing your UITableView can be simplified by using ALTableViewHelper [commercial - available on here
]. The UITableView’s cells are maintained for you - matched, in your case, to the contents of statusImagesTemporary:
class ServerVC: UIViewController, UITableViewDelegate {
#IBOutlet weak var serverStatusTable: UITableView!
#objc let imageError = UIImage(named: "error")
#objc let imageCheck = UIImage(named: "check")
var pings = ["www.apple.com", "www.appleidontknowwhy.de", "www.apple.com", "www.apple.com"]
var hosts = [String]() // hostnames which get pinged
#objc var componentTextArray = [String]() // project names
#objc var serverStatusMain = NSMutableArray() // not [String]() to allow changes to be observed
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// do not set dataSource, but instead:
serverStatusTable.setHelperString(
"section\n" +
" body\n" +
" serverStatusCell * serverStatusMain\n" +
" $.viewWithTag:(8).text <~ #[1] == 'error' ? 'Error ' : 'Running '\n" +
" $.viewWithTag:(7).image <~ #[1] == 'error' ? imageError : imageCheck \n" +
" $.viewWithTag:(2).text <~ componentTextArray[#[0]]\n" +
"", context:self)
// # is the value from the array (serverStatusMain), and $ is the serverStatusCell for #
// The selector for UIView.viewWithTag() is 'viewWithTag:', which is why you see that in the helper string
// Short arrays were added below as the values in serverStatusMain. In each short array:
// [0] is the index into hosts[] and componentTextArray[]
// [1] is the result of the ping, ie "check" or "error"
// so #[0] is the index and #[1] is the result of the ping
serverStatusTable.delegate = self
componentTextArray = ["Project 1", "Project 2", "Project 3", "Project 4"]
hosts = pings
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
// initial ping host process when loading the view
startHostRequest()
}
#IBAction func refreshBtnAction(_ sender: Any) {
// manual ping host process when clicking the button "refresh"
startHostRequest()
}
func startHostRequest () {
// I thought you might need this here so that the 2nd and later ‘starts’ do the whole list
pings = hosts
// This will empty your UITableView
serverStatusMain.removeAllObjects()
print("refresh server status")
pingNext()
}
func pingNext() {
guard pings.count > 0 else {
return
}
let ping = pings.removeFirst()
PlainPing.ping(ping, withTimeout: 1.0, completionBlock: { [weak self](timeElapsed:Double?, error:Error?) in
if let me = self {
if let latency = timeElapsed {
print("\(ping) latency (ms): \(latency)")
me.serverStatusMain.add([me.serverStatusMain.count, "check"])
}
if let error = error {
print("error: \(error.localizedDescription)")
me.serverStatusMain.add([me.serverStatusMain.count, "error"])
}
me.pingNext()
}
})
}
}
You can see the complete demo project including this code here.
Related
In each row of a tableview there is a label and button. The label displays a quotes from an array. Users can tap the button to save the quote. Right now it works fine with UserDefaults, but I want to also save the information to Firebase. I can't seem to figure out how to get the quote to save to Firebase based on the heart/row that was tapped. I thought I could use IdexPath, but I can't seem to get it right. I'd like to save each quote as a unique value in Firebase and be able to delete it when the button is tapped again. However, I'm not so familiar with firebase.
I thought I could use IdexPath to determine which row was selected and then grab the label in that row to send to Firebase, but I can't seem to get it right. Instead I got an error preventing the code from running "Instance member 'row' cannot be used on type 'IndexPath'; did you mean to use a value of this type instead?"
import UIKit
import FirebaseDatabase
import FirebaseAuth
class QuotesMainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var quotesTableView: UITableView!
struct Quote: Codable {
var label: String
var like: Bool = false // a priori, false
}
var quoteList: [Quote] = []
override func viewDidLoad() {
super.viewDidLoad()
quotesTableView.delegate = self
quotesTableView.dataSource = self
let defaults = UserDefaults.standard
if let data = defaults.data(forKey: "QuoteListKey") {
if let array = try? PropertyListDecoder().decode([Quote].self, from: data) {
quoteList = array
}
} else {
quoteList = [Quote(label: "Quote1"), Quote(label: "Quote2"), Quote(label: "Quote3")]
}
}
#IBAction func likeTapped(_ sender: UIButton) {
var ref: DatabaseReference?
ref = Database.database().reference()
quoteList[sender.tag].like.toggle() // update the dataSource ; sender.tag gives the row in the array
if quoteList[sender.tag].like {
sender.setImage(UIImage(named: "GreenHeart"), for: .normal) // You can change here or ask for a reloadData()
guard let user = Auth.auth().currentUser?.uid else { return }
ref!.child("users").child(Auth.auth().currentUser!.uid).child("Quotes").setValue(quoteList[IndexPath.row].label)
if let data = try? PropertyListEncoder().encode(quoteList) {
UserDefaults.standard.set(data, forKey: "QuoteListKey")
}
} else {
sender.setImage(UIImage(named: "blankHeart"), for: .normal)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return quoteList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = quotesTableView.dequeueReusableCell(withIdentifier: "cell") as! QuotesTableViewCell
cell.quoteLabel.text = quoteList[indexPath.row].label
cell.likeButton.tag = indexPath.row // Use tag to reference the cell, not to set true / false
cell.likeButton.setImage(UIImage(named: quoteList[indexPath.row].like ? "GreenHeart" : "blankHeart"), for: .normal)
return cell
}
}
When clicking a cell from the tableView, the cells data (fetched from an array) gets passed on to the 'Detail View Controller' to be displayed in labels. When pressing edit on the Detailview, data gets passed to the 'Edit View Controller' textfields.
When editing those textfields and pressing "Save" I want this data to overwrite the current data in the arrays dictionary based on which cell that was pressed in the tableView.
What would be the best approach to this? Right now data gets passed all the way to the 'EditViewController', but not back to the corresponding dictionary in array when saved.
Main ViewController:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { // Set up Delegate and Data Source for Table View
#IBOutlet weak var tradeTableView: UITableView!
var tradesList = TradeList()
// Go to detail view of trade when pressing its tableview cell
#IBSegueAction func showDetailView(_ coder: NSCoder) -> DetailViewController? {
guard let indexPath = tradeTableView.indexPathForSelectedRow
else { fatalError("Nothing selected!")}
let trade = tradesList.trades[indexPath.row]
return DetailViewController(coder: coder, trade: trade)
}
override func viewDidLoad() {
super.viewDidLoad()
// Set the table view as the delegate and data source
tradeTableView.dataSource = self
tradeTableView.delegate = self
}
// Delegating functions for Table View
func numberOfSections(in tableView: UITableView) -> Int {
1
}
// Delegating functions for Table View
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
tradesList.trades.count
}
// Delegating functions for Table View
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "\(TradeCell.self)", for: indexPath) as? TradeCell
else { fatalError("Could not create TradeCell")}
let trade = tradesList.trades[indexPath.row]
// Text to display in cells 'ticker' and 'name' label
cell.tickerLabel?.text = trade.ticker
cell.nameLabel?.text = trade.name
return cell
}
}
DetailViewController:
class DetailViewController: UIViewController {
let trade: Trade
#IBOutlet var tickerLabel: UILabel!
#IBOutlet var nameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Changes labels according to which cell was pressed in ViewController
tickerLabel.text = trade.ticker
nameLabel.text = trade.name
}
// Initializers
required init?(coder: NSCoder) { fatalError("This should never be called!")}
required init?(coder: NSCoder, trade: Trade) {
self.trade = trade
super.init(coder: coder)
}
// Edit button tapped
#IBAction func editTapped(_ sender: Any) {
self.performSegue(withIdentifier: "DetailVCToEditVC", sender: self)
}
// Prepare data to pass to 'EditViewController'
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "DetailVCToEditVC"){
let displayVC = segue.destination as! EditViewController
displayVC.editTitle = tickerLabel.text
displayVC.editPrice = nameLabel.text
}
}
}
EditViewController:
class EditViewController: UIViewController {
// Variables recieving passed data from 'DetailViewController'
var editTitle: String?
var editPrice: String?
#IBOutlet weak var editTitleField: UITextField!
#IBOutlet weak var editPriceField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Setting the textfields text according to the passed data from 'DetailViewController'.
editTitleField.text = editTitle
editPriceField.text = editPrice
}
#IBAction func editSaveButton(_ sender: UIButton) {
// Dismisses edit screen overlay
self.dismiss(animated: true, completion: nil);
}
}
My array is as follows in another swift file:
struct TradeList {
let trades: [Trade] = [
Trade(ticker: "AAPL", name: "Apple"),
Trade(ticker: "AMD", name: "Advanced Micro Devices")
]
}
Use singleton pattern to update data. You don't need to pass data to view controllers. It will update automatically. Here is how your trade list struct should be
struct TradeList {
static let shared = TradeList(trades: [
Trade(ticker: "AAPL", name: "Apple"),
Trade(ticker: "AMD", name: "Advanced Micro Devices")
])
var trades: [Trade] = []
}
U can use it as following anywhere
for getting values
print(TradeList.shared.trades)
for updating values
TradeList.shared.trades = [...]//Any value here
I have one tableview containing data that is fed from an Array with 14 entries. I have added a search bar where I can filter this data and this works fine, but when I try to send the filtered data to a second table view, the data that is sent is the count of my filtered data. So if I search something starting with G(13th and 14th place in my array), that brings back two results which is fine but when I choose the first entry off my filtered data(the two results), the data that is passed to the second Table View is the [0] entry(A) of my initial TVC and not the 13th(G12).So depending on the filtered data I always get the first few entries of my initial array.
struct ImageForManuf {
let image: UIImage
let name: String
init(nameInit: String) {
self.name = nameInit
image = UIImage(named: nameInit)!
}
}
struct SecondTable {
var secondTitle : [String]
var pic : [UIImage?]
}
//for search bar
#IBOutlet weak var searchBar: UISearchBar!
var filteredData: [ImageForManuf]!
var searching = false
var firstArray = [ImageForManuf]()
//we are adding elements on the SecondTable structure
var secondArray = [SecondTable]()
override func viewDidLoad() {
super.viewDidLoad()
//for search bar
searchBar.delegate = self
filteredData = firstArray
firstArray = [ "A","A2","B3","B4","B5","C6","C7","D8","E9","F10","F11","G12","G13","H14",
].map(ImageForManuf.init(nameInit:))
filteredData = firstArray
secondArray = [SecondTable(secondTitle: ["A1"],
pic: [UIImage(named: "A1")]),
SecondTable(secondTitle: ["B1","B2","B3"],
pic: [UIImage(named: "B1"),UIImage(named: "B2"),UIImage(named: "B3")]),
SecondTable(secondTitle: ["C1","C2"],
pic: [UIImage(named: "C1"),pic: [UIImage(named: "C2")]),
SecondTable(secondTitle: ["D1"],
pic: [UIImage(named: "D1"),
SecondTable(secondTitle: ["E1"],
pic: [UIImage(named: "E1"),
SecondTable(secondTitle: ["F1","F2"],
pic: [UIImage(named: "F1"),pic: [UIImage(named: "F2")]),
SecondTable(secondTitle: ["G1","G2"],
pic: [UIImage(named: "G1"),pic: [UIImage(named: "G2")]),
SecondTable(secondTitle: ["H1"],
pic: [UIImage(named: "H1")
]
This is my TV configuration
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if searching
{
return filteredData.count
}else{
return firstArray.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let Cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableTableViewCell
Cell.textLabel?.textColor = .systemBlue
Cell.textLabel?.font = .boldSystemFont(ofSize: 20)
if searching
{
Cell.textLabel?.text = filteredData[indexPath.row].name
Cell.imageManuf?.image = filteredData[indexPath.row].image
}else{
Cell.textLabel?.text = firstArray[indexPath.row].name
Cell.imageManuf?.image = filteredData[indexPath.row].image
}
return Cell
}
//we need to create a variable that can hold the destination view controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if searching {
let row = self.tableView?.indexPathForSelectedRow?.row ?? 0
let destViewController = segue.destination as! SecondTableViewController var secondTableArray : SecondTable
secondTableArray = secondArray[row]
destViewController.secondTableVcArray = secondTableArray.secondTitle
destViewController.detailVcArray = thirdArray[row]
}else{
let row = self.tableView?.indexPathForSelectedRow?.row ?? 0
let destViewController = segue.destination as! SecondTableViewController
var secondTableArray : SecondTable
secondTableArray = secondArray[row]
secondTableArray created in SecondTableViewController
destViewController.secondTableVcArray = secondTableArray.secondTitle
destViewController.detailVcArray = thirdArray[row]
}
}
Lastly this is my searchBar configuration
//Mark: Search Bar config
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = firstArray.filter({$0.name.lowercased().prefix(searchText.count) == searchText.lowercased()})
searching = true
//to reload the data
self.tableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tableView.reloadData()
}
This is the second TVC:
class SecondTableViewController: UITableViewController {
//we are loading the secondArray via the secondTableVcArray
var secondTableVcArray = [String]()
//we are loading the thirdArray via the detailVcArray
var detailVcArray : [DetailView]?
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return secondTableVcArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "secondCell", for: indexPath) as! SecondTableViewCell
cell.textLabel?.textColor = .white
cell.textLabel?.font = .boldSystemFont(ofSize: 20)
//we load the data of the secondTableVcArray to our cell
cell.textLabel?.text = secondTableVcArray[indexPath.row]
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let row = self.tableView?.indexPathForSelectedRow?.row else {
print("Error: problem with second table view or selection")
return
}
guard let dest = segue.destination as? DetailsViewController else {
print("Error: couldn't find expected DetailsViewController")
return
}
guard let details = detailVcArray else {
print("Error: data not set for SecondTableViewController")
return
}
dest.displayDetail = details[row]
}
}
Can somebody help with the row element of my prepareforSeque method and advice the syntax on how to get the indexPath of my firstArray as #vadian suggested? The second condition works fine(not searching) but I don't seem to be able to pull the right item from my DataSource in the searching condition.
I have the following error-free code and can't seem to use any of the information purposed for my results array. After playing around, I can print every businessID location listed but I can't add/use the array meant to hold this information. I do not understand why every location prints but my array appears as empty.
I apologize for the entirety of my code but I've spent hours trying to correct my issue...
import UIKit
import GooglePlaces
class FoodTwo: UITableViewController {
var placesClient: GMSPlacesClient!
let international: [String] = ["ChIJAQDABX7CIogRIEY3k6r7R-g",
"ChIJqX3q1IbCIogRFcuI05IPNDU",
"ChIJAQDABX7CIogRY2MA6XVas8E"]
let american: [String] = ["ChIJkX9tTSvoIogROXkxd0gpg3s", "ChIJy7lUZCfoIogRVBuB9jWKHUk", "ChIJyzCZMiroIogRkuMavnKsA0w", "ChIJbYvWJ5jCIogRxh0VQA_yD0I", "ChIJa4Sks23CIogRpRod4v5GEN8", "ChIJxVpGsNbpIogRG5HIAKbNyDU", "ChIJ1W32UyvoIogRyp_Rdxn6f8I", "ChIJwTht4ifoIogRsuXdEOrKGMk", "ChIJ6UXEgNPpIogR4Q3ZAAWQQSI", "ChIJUZVAjdTpIogRpyca26a6D8o", "ChIJ6-h6_EctIIgRO1kypozaGGs", "ChIJK8NGam7CIogRlzU1TKeSjVI", "ChIJ7Xxh1m3CIogRZ_yabslUzd8", "ChIJ_dxSGJ7CIogRcYwJhjAm7TQ"]
// more arrays here - deleted to reduce scrolling//
var results = [GMSPlace]()
var index: IndexPath!
override func viewDidLoad() {
super.viewDidLoad()
placesClient = GMSPlacesClient.shared()
var place: [String]
switch index.row
{
case 0 :
place = international
case 1 :
place = american
case 2 :
place = asian
case 3 :
place = bakery
case 4 :
place = bar
case 5 :
place = indian
case 6 :
place = italian
default :
place = mexican
}
for id in place
{
placesClient.lookUpPlaceID(id, callback: { (result, error) -> Void in
if let error = error {
print("lookup place id query error: \(error.localizedDescription)")
return
}
guard let result = result
else
{
print("No place details for \(id)")
return
}
self.results.append(result)
})
OperationQueue.main.addOperation( { () -> Void in
self.tableView.reloadData()
})
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return results.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FCT") as! FoodCellTwo
let each = results[indexPath.row]
cell.nameLabel.text = each.name
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
placesClient.lookUpPlaceID is an asynchronous function. You have to wait until it finishes. So, you are esentially reloading the table view before the array populates.
You should reload the table view after the array was filled.
for id in place {
placesClient.lookUpPlaceID(id) { result, error in
if let error = error {
print("lookup place id query error: \(error.localizedDescription)")
return
}
guard let result = result else {
print("No place details for \(id)")
return
}
self.results.append(result)
if place.count == self.results.count {
self.tableView.reloadData()
}
}
}
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.