Posts

Post marked as solved
8 Replies
@Jim Dovey Thank you very much for your detailed, complete, understandable and complete answer!As I now see your code above, implementation in SwiftUI is similar, but as a new user, - unfortunately - I had not fully understood it and had trouble with it as I had not found it anywhere in any documentation or third party example.I didn't know how to create (override) a SwiftUI UIViewControllerRepresentable view for that.Personally I don't mind that the (share) sheet view opens across the screen, because now I think that's the way it is in iOS 13.I am wrong ? In the past, it was different, but I think it now opens up to full screen.After all, "share view" is not a built-in function common to all apps and ready to use it?I suppose it should be a standard code supported by Apple and apply to all apps. Because this is how I imagine it should be.But thanks to you, my question has been completely resolved and I believe you will help many more people!Really your code works perfectly for me just like I expected, I think, and I should!Your help is incredible! Your help is incredible! Even more you upload a sample xcode project to github! I have no words!Thanks so much for your help and detailed information!
Post not yet marked as solved
5 Replies
I have no problem with parsing the HTML code. As I mentioned above, downloading the page and parsing it works smoothly and without any problems. I had done this from the beginning very easily ( thanks to SwiftSoup ). The problem was that I wanted to completely separate the code of this work from the user interface.I just did not know how to check from the graphical interface (TableViewController), when the data has been downloaded and if it has been downloaded, to show it to the user.Eventually I managed to do exactly what I wanted with the code below :import Foundation import SwiftSoup class Announcements { private var annTitles = [String]() // https://stackoverflow.com/questions/25407447/getting-data-from-a-website-in-swift // https://stackoverflow.com/questions/24016142/how-to-make-an-http-request-in-swift private func getHTML(aURL: String, completion: ( (String) -> (Void) )?) { let url = URL(string: aURL)! let task = URLSession.shared.dataTask(with: url) { (data, response, error) in guard let data = data else { return } // print(String(data: data, encoding: .utf8)!) let tempHTML = String(data: data, encoding: .utf8)! completion?(tempHTML) } task.resume() } public func getAnnouncements(completion: @escaping (Bool?) -> Void) { self.getHTML(aURL: "https://www.my.site/news.php") { result in if result.isEmpty { debugPrint("Announcements could not be downloaded!") completion(false) } else { debugPrint("Successful download of announcements.") self.parseHTML(html: result) completion(true) } // Default } } private func parseHTML(html : String) { do { let doc: Document = try SwiftSoup.parse( html ) let table: Elements = try doc.getElementsByClass( "table" ) for tr in try! table.select("tr")[1...100] { let td : Elements = try tr.select("td") self.annTitles.append( try td[0].text() ) } // self.viewData() } catch Exception.Error(let type, let message) { print(type) print(message) } catch { print("SwiftSoup parsing data error!") } print("All good!") } public func getTitles() -> [String] { return self.annTitles } public func viewData() { for i in 0...99 { print( self.annTitles[i] ) } } } // // TableViewController.swift // uoiAnnouncements // import UIKit class TableViewController: UITableViewController { @IBOutlet var announcementsTableView: UITableView! // Linked from UI. var announcements : Announcements? let announceCellIdentifier = "announcementCell" override func viewDidLoad() { super.viewDidLoad() // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem self.announcements = Announcements() self.announcements?.getAnnouncements() { (announcements) in if announcements! { DispatchQueue.main.async { print("Okay! I have them! Let's go!!") self.announcementsTableView.reloadData() } } } } // MARK: - Table view data source // override func numberOfSections(in tableView: UITableView) -> Int { // // #warning Incomplete implementation, return the number of sections // return 0 // } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // #warning Incomplete implementation, return the number of rows return 100 // Const because only 100 are initially announcements. } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: announceCellIdentifier, for: indexPath) // Configure the cell... self.reloadInputViews() // If they have not yet downloaded, the arrays are empty! ;) let titles = self.announcements?.getTitles() if titles!.isEmpty == false // So, Only if we have data..drop them on the user's screen!! { cell.textLabel?.text = titles?[indexPath.row] } return cell } } In essence the real change is in the "getAnnouncements" method, which is now a completion function ( I pronounce it correctly? - so there are called these functions? ) and returns a boolean value when it is completed.How do you view about my implementation?Do you think my code is correct?I am very happy because my application now works as I wanted from the beginning and the backed code is separated from UI.
Post not yet marked as solved
5 Replies
I know that this question is first general and theoretical and then practical. Personally I would like to discuss both parties and see in the end how it would be better to implement my code. Thanks for the time, the mood and the views/knowledge you share with us.Personally I am interested in the details and knowledge. The only third-party library I use (if I'm not mistaken) is "SwiftSoup" for html parsing. Could I do some other parsing of the HTML code with pure Swift ? Of course with out regex.Almost everything in mobile phones, is asynchronous. Ok.I know, of course in this example the use of semaphores is wrong. It's not a distributed programming problem, but the "connection" of backend with the graphical user interaction environment. And I'm sure in iOS you have ways to implement it this.What are the ways to do this on iOS ?To make my whole class "Announcements" a thread ( extended ) ?Play with the following code?DispatchQueue.global(qos: .background).async { print("This is run on the background queue") DispatchQueue.main.async { print("This is run on the main queue, after the previous code in outer block") } }But the problem is that in Swift and in general to iOS programming ( in which I am still newbie and have not fully understood it ) that the online requests are all by default asynchronous!For example, I've done something similar with Python 3 using the "urllib" library which does not create a parallel thread for the request, just waiting for the response to the main thread. Look at this very simple code :try : allPage = urllib.request.urlopen('https://www.my.site/news.php') except urllib.error.URLError : print("something goes wrong.... or raise an exception") raise print(allPage)Ok. Then, in use, I would create a parallel thread, where when the download was finished and I had the data in the data sets how I wanted, then I updated the graphical interface. So I think the main problem is that the "URLSession" create by default a parallel thread.And I ask you, aren't 3 lines of code more beautiful than 13 or 23 in the "viewDidLoad" method on TableViewController class?Because I have seen that most people execute the parallel request (URLSession) within the "viewDidLoad" method."You just issue your load request. When it completes, you (safely) update the data that your table is based upon.Then you reload the table (safely and in the main thread)."Because sometimes really talk is cheap. Can you show me the code for the above description (based on my code above)?"If you wanted to be really clever and had lots of data to update, or only a little bit of changed data, you could (even more safely) update your data and (even more carefully and always in the main thread) insert/delete/update just the individual rows that have changed."I like this approach and I also too thought it. But first I'd like to make my code in the simplest form above and then play with more fun stuff.I would really like to see an experienced/professional and beautiful approach to this issue. For this I make my question here.An experienced or professional on iOS cannot stand out the graphical interface from backend?My object oriented approach is failure ?I really want your views.Thank you.