Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialRea Rahhal
Courses Plus Student 4,732 PointsImages don't display ...
Here is my Code:
import UIKit
class ContactDetailController: UITableViewController {
var contact: Contact?////checking if we have a contact associated with the controller
//outlets
@IBOutlet weak var profileView: UIImageView!
@IBOutlet weak var phoneNumberLabel: UILabel!
@IBOutlet weak var emailLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var StreetAddressLabel: UILabel!
@IBOutlet weak var cityLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
configureViews()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Configure View method to set up labels .Called when the view loads
func configureViews(){
//contact property is an optional so we unwrap it
guard let contact = contact else {return}
phoneNumberLabel.text = contact.phone
emailLabel.text = contact.email
StreetAddressLabel.text = contact.street
cityLabel.text = contact.city
profileView.image = contact.image
nameLabel.text = "\(contact.firstName) \(contact.lastName)"//string interpolation to display first name and last name
}
and the ContctListController:
import UIKit
class ContactListController: UITableViewController {//view controller for the master view
var contacts = ContactsSource.contacts
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {//a section is a way to group data
//asks data source to returna a number
return 1// to specify that we have one section.We are goin to treat our data as a single long list of contacts so we will return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contacts.count//we ant as many rows as contacts
}
//each row displays data in a cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {//this metod is called for each row and provides a value for the indexpath argument which indicates which section we are in and which row we are in
let cell = tableView.dequeueReusableCell(withIdentifier: "ContactCell", for: indexPath)//ask the method to create a reusable cell from a prototype.
let contact = contacts[indexPath.row]//display contacts at a particular index at a row that has the same index path
cell.textLabel?.text = contact.firstName//assigning the contact first name to text label
cell.imageView?.image = contact.image//displaying images
cell.detailTextLabel?.text = contact.lastName
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//the code here is executed when we go from master to detail
if segue.identifier == "showContact"{
//the next step is to figure out which row was tapped
if let indexPath = tableView.indexPathForSelectedRow{
let contact = contacts[indexPath.row]
//the dest vc is the nav controller the detail controller is embedded in
guard let navigationController = segue.destination as?UINavigationController,let contactDetailController = navigationController.topViewController as? ContactDetailController
else{return}
//getting a reference to the destination and casting it to the right type
contactDetailController.contact = contact//assigniung this instance of the contact on the stored property on the contact detail controller
}
}
}
Thanks in advance
Harold Davis
Courses Plus Student 14,604 PointsLinus Karlsson,
A dispatch queue is a queue that you can put your code in to execution while there rest of your code continues on .. or it can be a queue of code you need to execute and you can say when your done. It probably seems weird because you may think - "well setting an image is such a simple task does it matter?" Yes:
this is getting advanced or intermediate but its important to know in iOS Dev or Engineering
DispatchQueue - Main - Async
- DispatchQueue is a structure that manages tasks or methods you you put in it.( with in the curly braces)...
(after dispatchQueue I use dot notation "." and the compiler tells me what "thread" I want to use...)
- "Main" refers to the main thread of execution...
(There is the main thread and there is the background thread), in some states of America we have something called an "HOV lane" on the highway, or you can call it the fast lane where you are in less threat of being in slow traffic and you get to go faster then everyone else.
The "Main thread" of execution is like the" HOV lane" on a highway and all code execution will go much faster on this lane while lower priority tasks are done on the "default" "Background thread" (which are all the other lanes on the highway)
Lastly, in regards to threads and queues, you have the ability to create your own and manage what happens during after or before execution and thats where things are super advanced lol, but good to know about it may come up in an interview question to see if you know about it)
- "async" is short for Asynchronous, which means other code written below the curly braces will continue while the code in side is still being executed... for example if Rea Rahhal does what I recommended then there will not be a hold up while the image is being set and loaded the code will skip onward and return his cell. (synchronous code would me the code has to finish its execution before moving forward)
At the end of it all the apple encourages us (really almost requires) to load UI elements, and Service calls (calling to servers) on the "main thread asynchronously"
- Harold
1 Answer
Harold Davis
Courses Plus Student 14,604 PointsSomething you may want to try is putting your cell.imageView = contact.image on the main que... apple likes for you to do UI thing on the main thread so they appear faster you can try this by doing something like:
DispatchQueue.main.async {
Cell.imageView.image = contact.image
}
Hope this helps buddy I was just walking on my lunch break,
Also set a break point on that line and make sure there is an image there at that time... you can do this by typing po contact.image in the console and see if itβs not nil if itβs nil the image is not successfully loading.
Linus Karlsson
7,402 PointsLinus Karlsson
7,402 PointsI'm not advanced enough to do this. I will be someday, but I'm just on my first month of Swift/iOS coding yet.
Harold's response seems resonable though! If Apple encourages/tells you to load image files through the main que (what does this mean, "que"?) to load faster, then that is something that I would at least try.