I have a tableview.
Each cell opens a new ViewController and loads a .txt file to a textview from my github repo.
But now i want to make each cells to load a different .txt file from the same repo.
So like the first cell loads the first.txt, the second loads the second.txt and so on
is this even possible?
It would be like a news reader app where you click on a title and can read the article.
Here is my current code which is bad but im a beginner :(
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async {
let content = self.downloadContent()
DispatchQueue.main.async {
self.myTextView.text = content
}
}
}
func downloadContent() -> String {
var data : Data!
data = try? Data(contentsOf: URL(string: "https://raw.githubusercontent.com/SiposPtr/umszkiapp/master/cikk2.txt")!)
let data_str = String(data: data, encoding: .utf8)
return data_str!
}
I upload my files to a new github repo so you can see the whole stuff:
https://github.com/SiposPtr/stackoverflow
Could you please check if this is working?
import UIKit
class TableViewController: UITableViewController {
var TableData: Array<String> = Array<String>()
var currentCell: String?
var selectedValue: String?
var numberOfFileToLoad: Int = 1
override func viewDidLoad() {
super.viewDidLoad()
get_data_from_url("https://raw.githubusercontent.com/SiposPtr/umszkiapp/master/cimek.json")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TableData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row]
cell.textLabel!.numberOfLines = 2;
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 90.0;
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedValue = TableData[indexPath.row]
numberOfFileToLoad = indexPath.row + 1
}
func get_data_from_url(_ link:String)
{
let url:URL = URL(string: link)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(
data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
return
}
self.extract_json(data!)
})
task.resume()
}
func extract_json(_ data: Data) {
let json: Any?
do
{
json = try JSONSerialization.jsonObject(with: data, options: [])
}
catch
{
return
}
guard let data_list = json as? NSArray else
{
return
}
if let hir_lista = json as? NSArray {
for i in 0 ..< data_list.count
{
if let hir_obj = hir_lista[i] as? NSDictionary
{
if let cim_nev = hir_obj["cim"] as? String
{
if let hir_code = hir_obj["datum"] as? String
{
TableData.append(cim_nev + "\n(" + hir_code + ")")
}
}
}
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
// ez működik, de a run utáni első cikknek üres a titléje és akk csúszik minden cím eggyel
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "gotoSentences"{
let nextViewController = segue.destination as! HirNezetViewController
nextViewController.title = selectedValue
print(selectedValue)
nextViewController.numberOfFileToLoad = numberOfFileToLoad
print(numberOfFileToLoad)
}
}
#IBAction func reloadButton(_ sender: Any) {
let alert = UIAlertController(title: "A cikkeket újratöltöttem", message: "Kattints a gombra az eltüntetéshez", preferredStyle: .alert)
let ok = UIAlertAction(title: "Rendben", style: .default, handler: { action in
})
alert.addAction(ok)
get_data_from_url("https://raw.githubusercontent.com/SiposPtr/umszkiapp/master/cimek.json")
tableView.reloadData()
}
}
import UIKit
class HirNezetViewController: UIViewController {
var data:String!
var content: String?
var numberOfFileToLoad: Int = 1
#IBOutlet weak var myTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async {
let content = self.downloadContent()
DispatchQueue.main.async {
self.myTextView.text = content
}
}
}
func downloadContent() -> String {
var data : Data!
data = try? Data(contentsOf: URL(string: "https://raw.githubusercontent.com/SiposPtr/umszkiapp/master/cikk\(String(numberOfFileToLoad)).txt")!)
let data_str = String(data: data, encoding: .utf8)
return data_str!
}
}
Related
I am currently trying to display firebase objects in my tableview. However, I am only getting empty prototype cells. Thanks if you can take a glance at it!
import UIKit
import Firebase
class UsersTableViewController: UITableViewController {
var user = [User]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getusers() {
let userID = Auth.auth().currentUser?.uid
let rootRef = Database.database().reference()
let query = rootRef.child("users").queryOrdered(byChild: "fullname")
query.observe(.value) { (snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
if let value = child.value as? NSDictionary {
let userToShow = User()
let fullname = value["fullname"] as? String ?? "Name not found"
let uid = value["uid"] as? String ?? "uid not found"
userToShow.fullname = fullname
userToShow.userID = uid
self.user.append(userToShow)
DispatchQueue.main.async { self.tableView.reloadData() }
}
}
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return user.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as! TableViewCell
cell.nameLabel.text = self.user[indexPath.row].fullname
cell.userID = self.user[indexPath.row].userID
cell.userImage.downloadImage(from: self.user[indexPath.row].imagePath!)
return cell
}
}
extension UIImageView {
#objc func downloadImage(from imgURL: String!) {
let url = URLRequest(url: URL(string: imgURL)!)
let task = URLSession.shared.dataTask(with: url) {
(data, response, error) in
if error != nil {
print(error!)
return
}
DispatchQueue.main.async {
self.image = UIImage(data: data!)
}
}
task.resume()
}}
Thanks again for anyone willing to help! I am currently using Swift 4 with Google's Firebase API.
p.s. I know that I have connected delegate and dataSource. I am also sure that I have properly titled my Identifier. Thanks!
Im not sure why but I have a button and textfield on my viewController,
the button is not visible when the view appears but when I click where the button should be it then appears. The pre-populated text in the text box also does not appear.
I am being presented with the following warning (im not sure if its related):
2016-12-30 11:25:26.030 wellpleased[5462:776953] This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.
How would I prevent this warning and have the elements appear correctly?
class events: UIViewController, UITableViewDelegate, UITableViewDataSource {
var rowID:String = ""
var value:String!
#IBOutlet var tableView: UITableView!
var tableData: [String] = []
var tableEventMonth: [String] = []
var tableEventDay: [String] = []
var tableEventCity: [String] = []
var tableEventLink: [String] = []
var tableEventID: [String] = []
#IBOutlet weak var tableTopConstraint: NSLayoutConstraint!
#IBOutlet weak var eventCodeView: UIView!
#IBAction func addButton(_ sender: Any) {
if self.eventCodeView.alpha == 1{
self.view.layoutIfNeeded()
UIView.animate(withDuration: 1, animations: {
self.view.layoutIfNeeded()
self.eventCodeView.alpha = 0
})
self.tableTopConstraint.constant = 1
UIView.animate(withDuration: 1) {
self.view.layoutIfNeeded()
}
}else{
self.view.layoutIfNeeded()
UIView.animate(withDuration: 1, animations: {
self.view.layoutIfNeeded()
self.eventCodeView.alpha = 1
})
self.tableTopConstraint.constant = 70
UIView.animate(withDuration: 1) {
self.view.layoutIfNeeded()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "vwTblCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "cell")
}
override func viewDidAppear(_ animated: Bool) {
getTableData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TblCell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! TblCell
cell.lblCarName.text = self.tableData[indexPath.row]
cell.calendarDay.text = self.tableEventDay[indexPath.row]
cell.calendarMonth.text = self.tableEventMonth[indexPath.row]
cell.city.text = self.tableEventCity[indexPath.row]
let defaults = UserDefaults()
let event = defaults.string(forKey: "event")
if self.tableData[indexPath.row] == event {
cell.hereLabel.isHidden = false
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Row \(indexPath.row) selected")
rowID = tableEventID[indexPath.row]
self.performSegue(withIdentifier: "goAttendees", sender: self)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 90
}
func getTableData(){
let defaults = UserDefaults()
let userid = defaults.string(forKey: "id")
let url = NSURL(string: "https://www.asmserver.co.uk/wellpleased/backend/eventselect.php?userid=\(userid!)")
let task = URLSession.shared.dataTask(with: url as! URL) { (data, response, error) -> Void in
if let urlContent = data {
do {
if let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: []) as? [[String:AnyObject]] {
var i = 0
while i < jsonResult.count {
self.tableData.append(jsonResult[i]["eventname"]! as! String)
self.tableEventDay.append(jsonResult[i]["eventday"]! as! String)
self.tableEventMonth.append(jsonResult[i]["eventmonth"]! as! String)
self.tableEventCity.append(jsonResult[i]["city"]! as! String)
self.tableEventLink.append(jsonResult[i]["link"]! as! String)
self.tableEventID.append(jsonResult[i]["eventid"]! as! String)
i = i + 1
}
}
} catch {
print("JSON serialization failed")
}
} else {
print("ERROR FOUND HERE")
}
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.reloadData()
})
self.tableView.isUserInteractionEnabled = true
}
task.resume()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if(segue.identifier == "goAttendees") {
let attendees = (segue.destination as! attendees)
attendees.value = rowID
}
}
}
You had better change UI only in the main thread. For swift3 refer to this post,
for more swift<2, 3 objective-c.
class ProductTableViewController: UITableViewController
{
var products = [Product]()
override func viewDidLoad() {
super.viewDidLoad()
getData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return products.count // zero
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductCell", for: indexPath) as! ProductCell
cell.userIdLabel?.text = "user id" + "$\(products[indexPath.row].userId)"
cell.idLabel?.text = "id" + "$\(products[indexPath.row].id)"
cell.titleLabel?.text = products[indexPath.row].title
cell.bodyLabel?.text = products[indexPath.row].body
return cell
}
func getData(){
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [[String:Any]]
for post in json{
let product = Product()
product.userId = post["userId"] as! Int
product.id = post["id"] as! Int
product.title = post["title"] as! String
product.body = post["body"] as! String
self.products.append(product)
}
//OperationQueue.main.addOperation({ () -> Void in self.tableView.reloadData()})
} catch let error as NSError {
print(error)
}
//HERE!!!
OperationQueue.main.addOperation({ () -> Void in self.tableView.reloadData()})
}).resume()
}
}
When my UITableViewController executed first of all will implement func tableView and he will return zero count cause getData() didn't run yet and of course second tableView who returning my Cell will not implement.
And now, I wanna see what parsed my getData() in order to do I try to reload my tableView with OperationQueue.main.addOperation({ () -> Void in self.tableView.reloadData()})but caught an error :
Thread1 :SIGABRT.
How I should correctly reload my tableView?
Try this
func getData(){
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [[String:Any]]
for post in json{
let product = Product()
product.userId = post["userId"] as! Int
product.id = post["id"] as! Int
product.title = post["title"] as! String
product.body = post["body"] as! String
self.products.append(product)
}
// just reload here after finish appends
self.tableView.reloadData()
} catch let error as NSError {
print(error)
}
}).resume()
}
I am new to swift and have set up a table which fills using data from an sql database.
The table loads fine but occasionally it gives the error:
"Fatal Error: Index out of range".
It doesn't happen all the time just every now and again.
Also I have migrated from parse to using sql and http requests. Have I taken the correct approach to this when populating the data into the table?
Any help much appreciated!
#IBOutlet var tableView: UITableView!
var tableData = [String]()
var tableImages = [String]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
if Reachability.isConnectedToNetwork() == true {
self.tableView.hidden = true
self.tableData.removeAll(keepCapacity: true)
self.tableImages.removeAll(keepCapacity: true)
var nib = UINib(nibName: "vwTblCell3", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell3")
let request = NSURLRequest(URL: NSURL(string: "********.php")!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{
(response: NSURLResponse?, data: NSData?, error: NSError?)-> Void in
let str2 = String(data: data!, encoding: NSUTF8StringEncoding)
let str3 = Int(str2!)!
let url = NSURL(string: "********")!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
if let urlContent = data {
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(urlContent, options: NSJSONReadingOptions.MutableContainers)
print(str3)
var i = 0
while i < str3 {
print(jsonResult[i]["title"]! as! String)
print(jsonResult[i]["image"]! as! String)
self.tableData.append(jsonResult[i]["title"]! as! String)
self.tableImages.append(jsonResult[i]["image"]! as! String)
i = i + 1
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
} catch {
print("JSON serialization failed")
}
}
}
task.resume()
});
print(tableData)
self.tableView.hidden = false
}
}
// 2
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData.count
}
// 3
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: TblCell3 = self.tableView.dequeueReusableCellWithIdentifier("cell3") as! TblCell3
cell.lblAffiliate.text = tableData[indexPath.row]
let url3 = NSURL(string: "https://www.********.co.uk/\(tableImages[(indexPath as NSIndexPath).row]).png")
cell.affiliateImage.sd_setImageWithURL(url3)
return cell
}
// 4
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Row \(indexPath.row) selected")
}
// 5
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 400
}
}
I hope this helps. I changed a couple small things around for better code (half could be considered bias). I think the issue is mostly that you were reloading the tableView in the loop. Everything else was just a slightly better way to handle this case. I put everything in viewDidLoad, and made the tableView load empty input prequel to receiving data. I think this is more standard for handling this scenario. If you need any other help let me know.
class ViewController: UIViewController {
#IBOutlet var tableView: UITableView!
var tableData: [String] = []
var tableImages: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
if Reachability.isConnectedToNetwork() == true {
var nib = UINib(nibName: "vwTblCell3", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell3")
let request = NSURLRequest(URL: NSURL(string: "********.php")!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{
(response: NSURLResponse?, data: NSData?, error: NSError?)-> Void in
let str2 = String(data: data!, encoding: NSUTF8StringEncoding)
let str3 = Int(str2!)!
let url = NSURL(string: "********")!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
if let urlContent = data {
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(urlContent, options: NSJSONReadingOptions.MutableContainers)
self.tableData = []
self.tableImages = []
for i in 0..<str3 {
self.tableData.append(jsonResult[i]["title"]! as! String)
self.tableImages.append(jsonResult[i]["image"]! as! String)
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
} catch {
print("JSON serialization failed")
}
}
}
task.resume()
});
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: TblCell3 = self.tableView.dequeueReusableCellWithIdentifier("cell3") as! TblCell3
cell.lblAffiliate.text = tableData[indexPath.row]
let url3 = NSURL(string: "https://www.********.co.uk/\(tableImages[(indexPath as NSIndexPath).row]).png")
cell.affiliateImage.sd_setImageWithURL(url3)
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Row \(indexPath.row) selected")
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 400
}
}
The problem is that your call to reloadData() is inside the while loop in which you are building tableData and tableImages. Move that after the while loop, by which point both of those arrays will be fully populated.
I am creating an App on Xcode7 using swift and I really need some help. I would like to make the SWRevealViewController sidebar appear on all of my scene but the problem is it only appears on the first view controller I set the push segue to show. And also upon clicking a link on the sidebar the navigation bar disappears on the next scene? Please somebody help...
sidebar
Here is the script I used on my UITableViewController for the sidebar links
var catArrayId = [String]()
var catArrayName = [String]()
var catArrayImg2 = [String]()
override func viewDidLoad(){
// get available categories according to customer country
get_categories()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return catArrayId.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("navCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = self.catArrayName[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("showCategory", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showCategory" {
let VC = segue.destinationViewController as! CategoryProductsViewController
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow!
let categoryImage = UIImage(named: catArrayImg2[indexPath.row])
VC.catId = self.catArrayId[indexPath.row]
VC.image = categoryImage!
}
}
func get_categories(){
let country_id = 168
//let startTime = NSDate.timeIntervalSinceReferenceDate()
let pageUrl = "https://domain.com/ios/home-categories-image.php?country_id=\(country_id)&uudi=" + NSUUID().UUIDString
let myUrl = NSURL(string: pageUrl)
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "GET"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request){
(let data, let response, let error) in
if(error != nil){
print(error?.localizedDescription)
return
}
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
let catArray = json as? [[String: AnyObject]]
for catArr in catArray!{
let catName = catArr["name"] as? String
let catID = catArr["id"] as? String
let img2 = catArr["image2"] as? String
dispatch_async(dispatch_get_main_queue(), {
self.catArrayId.append(catID!)
self.catArrayName.append(catName!)
self.catArrayImg2.append(img2!)
self.tableView.reloadData()
})
}
}
catch{
print("Error serializing JSON: \(error)")
}
}
task.resume()
}
If I understood your question right, then you can do the same as in example provided by an author of controller ("RevealControllerStoryboardExample2"). When you select something from rear VC, segue for that action needs to have class "SWRevealViewControllerSeguePushController". Here is a screenshot of this example: