@_zerocool Δημοσ. 24 Σεπτεμβρίου 2015 Δημοσ. 24 Σεπτεμβρίου 2015 Βάζω την ερώτηση που εκάνα στο stack overflow σχετικά με το πως μπορείς να βελιτιωθεί το παρακάτω. http://stackoverflow.com/questions/32758832/downloading-json-and-displaying-in-uitableview-with-swift import UIKit class ViewController: UIViewController, UITableViewDelegate { @IBOutlet weak var tableView: UITableView! //This is a the quick fix, another way would be to create a data class with objects and properties: name, viewers and image. //Then create an arrray of objects where there are stored. Although the implemented solution is a quick faster and has a little les memory usage. //setting up different arrays for each data type to access them globally at some point var JSONGameName: [String] = [] var JSONViewers: [Int] = [] var JSONGameImages: [String] = [] override func viewDidLoad() { super.viewDidLoad() loadAndDecodeJson() } //this functions uses the default way to implement json in swift. For more advanced data or multiple json files //the suggestions is to use an external library like SwiftyJson func loadAndDecodeJson(){ //defining the url of the nsurl string to download //if not secure URL allow it in the plist file let url = NSURL(string: "https://api.twitch.tv/kraken/games/top") //create the task to handle the url let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) -> Void in //when task completes this will run //need to check if data is not nil if error == nil { //serialize the json to a dictionary do { let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary //loop through the data but first check if it hsa something in it if jsonResult.count > 0 { if let items = jsonResult["top"] as? NSArray { for item in items { if let viewers = item["viewers"] as? NSInteger { print(viewers) self.JSONViewers.append(viewers) } if let games = item["game"] as? NSDictionary { if let name = games["name"] as? NSString { print (name) self.JSONGameName.append(name as String) } if let logo = games["logo"] as? NSDictionary { if let small = logo["small"] as? NSString { print (small) self.JSONGameImages.append(small as String) } } } } } } //reload table after json parsing is done dispatch_async(dispatch_get_main_queue(), { () -> Void in self.tableView.reloadData() }) } catch { print("error: parsing json") } } else { //Show error message that there is probably no connection let alert = UIAlertController(title: "Oopps..", message: "The was an error downloading data", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) } } //execute the async task task.resume() } //defining number os section func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } //function to determine the number of list items func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return JSONGameName.count } //the view of every cell of the list func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { //custom cell identifier let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! ViewControllerCell //setting up the images and casting them from strings to UIImages let imageURL = NSURL(string: JSONGameImages[indexPath.row]) let data = NSData(contentsOfURL: imageURL!) //setting game name, images and viewers on cells cell.gameName?.text = JSONGameName[indexPath.row] cell.gameViewers?.text = String (JSONViewers[indexPath.row]) cell.gameImage?.image = UIImage(data: data!) return cell } }
Papakaliati Δημοσ. 24 Σεπτεμβρίου 2015 Δημοσ. 24 Σεπτεμβρίου 2015 Θα παρουσιασω τα επιφανειακα που βλεπω και με κανουνε να καταλαβω γιατι δεν τους αρεσε η λυση σου. Γενικα εχει πολλα θεματα στην παρουσιαση. πχ η συναρτηση func loadAndDecodeJson() ειναι ενα τερας, και απο τα κλασσικοτερα παραδειγματα παραβιασης του function single principle , που ειναι να εχει and στο ονομα. Το let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary παραειναι μεγαλο για να το εχεις σε μια γραμμη. ( αμα οντως το εχεις ). Αντι να κανεις if jsonResult.count > 0 { κτλ κτλ και να αρχισεις ατελειωτα Ifs, ειδικα αμα δεν εχεις else, κανε απλα if (! jsonResult.count > 0) return; και μετα ο κωδικας που εχεις μεσα στο if Οταν σου δινεται απο μια εταιρια ενα τετοιο προβλημα, το 50% ειναι η παρουσια του κωδικα, ειναι πολυ σημαντικο να ξερεις τις σωστες πρακτικες. Α και υποθετω οτι το εστειλες χωρις unit testing μιας και δεν ανεφερες τιποτα, κατι που ειναι παντα κακο.
@_zerocool Δημοσ. 24 Σεπτεμβρίου 2015 Μέλος Δημοσ. 24 Σεπτεμβρίου 2015 Καταρχήν σε ευχαριστώ για την απάντηση. Αυτά που λες προκύπτουν από το γεγονός ότι στην swift και τα optional μπλέκεις πολυ με if let και για αυτό όλος αυτός ο κώδικας. Δεν είχα προλάβει να βάλω library που όλο αυτό το κάνει 4 γραμμές. Την μέθοδο την έβαλα απλά (θα μπρούσα να το αφήσω και όλο στο viewDidLoad που έχω δεί άπειρους να την γεμήζουν με γραμμές κώδικα. Όχι δεν έβαλα unit test γιατί δεν το ανέφερε η εκφώνηση. Η λογική με τους τρείς πίνακες πως σου φαίνεται; Description In this task you shall implement a simple UITableView and fill it with custom designed UITableViewCells. These cells shall represent the custom data fetched from the internet. The main objective is to be able to download data from Twitch and then use this in one of the most common use cases in iOS, in a UITableView. In order to make this task more comprehensive the UITableView shall contain custom UITableViewCells and thus give you an opportunity to design user interface elements. There is no restriction in terms of technology except that which is stated below. It is thus allowed to use common technologies such as CocoaPods, third party libraries, XCode, et cetera. Requirements • The iOS application must be written in Swift (1.2+) or Objective-C. • Implement a UITableView. • Implement a custom UITableViewCell in the UITableView. • Download data from Twitch and display it in the custom cells. Goals • Showcase your code quality and design. • Showcase your approach in solving a common task in iOS development
Aisthimatiaas Δημοσ. 25 Σεπτεμβρίου 2015 Δημοσ. 25 Σεπτεμβρίου 2015 Best practice? Μάθετε πρώτα να γράφετε κώδικα και μετά θα μάθετε και best practices. Που έχετε μείνει στο HelloWorld!
@_zerocool Δημοσ. 25 Σεπτεμβρίου 2015 Μέλος Δημοσ. 25 Σεπτεμβρίου 2015 Best practice? Μάθετε πρώτα να γράφετε κώδικα και μετά θα μάθετε και best practices. Που έχετε μείνει στο HelloWorld! Γιατί δεν μας λες τι κάνουμε λάθος για να μάθουμε; 1
AllCowsEatGrass Δημοσ. 26 Σεπτεμβρίου 2015 Δημοσ. 26 Σεπτεμβρίου 2015 Αν μιλάμε για πρακτικές, πιστεύω το μεγαλύτερο λάθος που έχεις κάνει είναι πως έχεις βάλει logic που κάνει retrieve τα data μέσα σε ένα class που είναι υπεύθυνο για το UI. Καταλαβαίνεις ότι αυτό δεν είναι καθόλου πρακτικό γιατί αν θες να κάνεις render στο μέλλον τα Games σε άλλο widget, πως θα το κάνεις;Επιπλέον, αφού λαμβάνεις τα games από ένα rest service σε json μορφή θα βοηθούσε πάρα πολύ να είχες φτιάξει ένα concrete class Game με το υποσύνολο των properties που θέλεις να χρησιμοποιήσεις στο domain σου, πρώτο πράμα που έκανα ήταν hit το url στον browser για να δω τη μορφή. Επίσης, τώρα που βλέπω το result, φαίνεται να έχει paging. Δεν βλέπω να το έχεις κάνει implement, νομίζω θα σου κόστισε. _links: { self: "https://api.twitch.tv/kraken/games/top?limit=10&offset=0", next: "https://api.twitch.tv/kraken/games/top?limit=10&offset=10" }, Άλλο πρόβλημα είναι τα inline comments που έχεις μέσα στο function, δεν βοηθάνε κανέναν. Comments πχ όπως //when task completes this will run//need to check if data is not nilή//loop through the data but first check if it hsa something in itπρέπει να καταλάβεις ότι δεν βοηθάνε κανέναν, το μόνο που κάνουν είναι πιο βρώμικο τον κώδικά σου. Τα lines if error == nil {...} και if jsonResult.count > 0 {...} είναι όσο documentation χρειάζεται κάποιος για να καταλάβει τι γίνεται, αυτό ισχύει σχεδόν για όλα τα comments στο file που βλέπω.Επίσης επαναλαμβάνω αυτό που ανέφερε ο Παπακαλιάτι για τα nested blocks, είναι ο διάολος μου. Θέμα έχουν και τα names που έχεις δώσει στα variables καθώς και τα func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } //function to determine the number of list items func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return JSONGameName.count } αν καταλαβαίνω το σκοπό τους. Τέλος, αυτά από κάποιον που δεν ξέρει swift, είμαι σίγουρος πως η γλώσσα έχει να σου προσφέρει κάποια idioms για να κάνεις τον κώδικα σου ακόμα πιο καθαρό. Αν θέλεις κάποια διευκρίνιση στη διάθεση σου.
@_zerocool Δημοσ. 26 Σεπτεμβρίου 2015 Μέλος Δημοσ. 26 Σεπτεμβρίου 2015 Ευχαριστώ για τα σχόλια σου. Αυτό που λες για το logic το διαπίστωσα και έτσι ήθελα να το κάνω αλλά μου έβγαζε ένα error όταν έτρεχε με array out of bounds. Διαπίστωσα πλέον και που είναι το error αλλά πλέον είναι αργά για αυτό. numberOfSectionsInTableView είναι μέθοδος delegate σαν interface (java) δηλαδή. Είναι από class της Apple και όλες τέτoια ονόματα έχουν. Τα nested blocks έχουν αλλάξει νομίζω στην 2.1 swift ενώ αυτό είναι 2.0 οπότε αναγκαστηκά το κάνεις έτσι αν δεν έχεις lib. Μπορείς να μου διευκρινήσεις τι εννοείς με τα comments; Η να μου δώσει ένα παράδειγμα πως θα έπρεπε να είναι τα inline comments;
AllCowsEatGrass Δημοσ. 26 Σεπτεμβρίου 2015 Δημοσ. 26 Σεπτεμβρίου 2015 Εννοώ πως είναι αχρείαστα στην προκειμένη περίπτωση, και προσωπικά δεν τα προτιμώ γενικότερα. Ο κώδικας είναι ικανός να εξηγήσει το τι κάνει το function που έχεις γράψει, τα comments σου δεν επεξηγούν κάτι που δεν έχει καταλάβει αυτός που διαβάζει τον κώδικα.Π.χ ένα τυχαίο παράδειγμα, απλουστευμένο : function theLoop () { ... // increase turns count _turns = _turns + 1; ... } vs /// // Does the main thing that needs to be done // and increases the global turns count /// function theLoop () { ... _turns = _turns + 1; ... } Αν θέλεις μπορείς να βάλεις comments πάνω από το definition του function. Αν νιώθεις πως πρέπει να γράψεις πολλά ή ότι χρειάζεσαι inline comments γιατί το function σου κάνει πολλά πράγματα, ίσως να πρέπει να σπάσει το function σου σε περισσότερα.Edit: Γράψε λάθος για την αναφορά μου στα funcs του framework.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα