简体   繁体   中英

Class attribute (string) returning optional value (Swift)

I'm having difficulty using an attribute of a class, which stores a url as a String. It's returning Optional("url") instead of just the url. The other string attribute User.name is not having that same issue. I've tried unwrapping the attibute when I'm accessing it, but it's not working because it's telling me that it "Cannot force unwrap value of non-optional type 'String'"

See below for details

I've created a class, which looks like

import Foundation

class User {
    var name : String
    var age : Double
    var gender : String
    var imagelink : String

    init(name: String, age: Double, gender: String, imagelink: String) {
        self.name = name
        self.age = age
        self.gender = gender
        self.imagelink = imagelink
    }
}

The users are listen in a table, and when a cell is pressed, it segues into a new view where I want the user's profile information and image to be displayed.

The prepareforsegue is set up like this

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "userCellPressed" {
        if let indexPath = tableView.indexPathForSelectedRow {
            let user = userList[indexPath.row]
            let controller = (segue.destinationViewController as! ProfileViewController)
            controller.detailUser = user
            controller.navigationItem.leftItemsSupplementBackButton = true
        }
    }
}

Then in the new view, the user's name is displayed correctly, but the image won't display because detailUser.imagelink is returning Optional("url") and it's not allowing me to use ! or ? on it because it's a string.

var detailUser: User? {
    didSet {
        configureView()
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    configureView()
    // Do any additional setup after loading the view.
}

func configureView() {
    if let detailUser = detailUser {
        if let nameLabel = nameLabel, userImage = userImage {
            nameLabel.text = detailUser.name                

            let url = NSURL(string: detailUser.imagelink)
            let data = NSData(contentsOfURL:url!)
            if data != nil {
                userImage.image = UIImage(data:data!)
            }
        }
    }
}

you must unwrap url before using it. following your syntax would look like this:

func configureView() {
    if let detailUser = detailUser {
        if let nameLabel = nameLabel, userImage = userImage {
            nameLabel.text = detailUser.name                

            if let url = NSURL(string: detailUser.imagelink) {
                let data = NSData(contentsOfURL:url)
                if data != nil {
                    userImage.image = UIImage(data:data!)
                }
            }
        }
    }
}

for more readable code, i would recommend using guards (not tested):

UPDATED WITH ASYNC REQUEST:

func configureView() {
    // set name label
    guard let detailUser = detailUser else { return }
    guard let nameLabel = nameLabel else { return }
    nameLabel.text = detailUser.name

    // get weak copy of self to prevent retain cycle
    weak var weakSelf = self

    // retrieve and set user image
    guard let url = NSURL(string: detailUser.imagelink) else { return }
    NSURLSession.sharedSession().dataTaskWithRequest(NSURLRequest(URL: url), completionHandler: { data, response, error in
        // only carry on if self still exists and data was returned
        guard let strongSelf = weakSelf else { print("self released before response."); return }
        guard let data = data else { print("error retrieving image: \(error)"); return }

        // if userImage exists parse the data as an UIImage and set it
        strongSelf.userImage?.image = UIImage(data: data)
    }).resume()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM