I have a Core Data entity which has logo as one of its attributes - I need to check the count of logo, so I can properly set an image view in the cell (i.e. avoid a crash when a new company is added and doesn't have a logo). With a hardcoded array of, say, logos, it's as simple as logos.count, but I'm not sure how to perform the same check on a Core Data entity. What's the best way of doing this?
DispatchQueue.main.async {
if /*What to count?*/.count >= indexPath.row + 1 {
cell.logoView.image = UIImage(named: (company.value(forKey: "logo") as? String)!)
} else {
cell.logoView.image = UIImage(named: "noImage")
}
}
Based on what I can see from your current setup, the following should be fine:
DispatchQueue.main.async {
if let logo = company.value(forKey: "logo") as? String {
cell.logoView.image = UIImage(named: logo)
} else {
cell.logoView.image = UIImage(named: "noImage")
}
}
Let me know if this makes sense.
Related
I'm trying to check the image name in the UIButton like this:
#IBAction func buttonTapped(_ sender: Any) {
if xcodeButton.currentImage == UIImage(named: "xcode") {
print("xcode image")
}
}
But I have a break point in the if statement and this is the output:
po xcodeButton.currentImage
▿ Optional<UIImage>
- some : <UIImage:0x6000011a93b0 named(main: xcode) {500, 500}>
but if I compare it
po xcodeButton.currentImage == UIImage(named: "xcode")
false
Any of you knows why the comparison is returning false? or how can compare the name of the image in UIButton?
I'll really appreciate your help.
You should use isEqual(_:) From Docs scroll to Comparing Images section
let image1 = UIImage(named: "MyImage")
let image2 = UIImage(named: "MyImage")
if image1 != nil && image1!.isEqual(image2) {
// Correct. This technique compares the image data correctly.
}
if image1 == image2 {
// Incorrect! Direct object comparisons may not work.
}
None of these solutions were working for me. So I used pngData to compare images:
let image1Data = UIImage(named: "MyImage")?.pngData()
let image2Data = UIImage(named: "MyImage")?.pngData()
if image1Data == image2Data {
// It compares data correctly
}
I've got a struct, which contains a static variable called userProfileImage, this struct is in a view controller called UserProfilePage.swift, here is the code:
struct UserProfile {
static let userProfileImage = UIImageView(image: #imageLiteral(resourceName: "profilePicture"))
}
class UserProfilePage: UIViewController {
// Some code that sets the userProfileImage to another image
}
The following code is in another swift file that has a struct called Downloads:
struct Downloads {
guard let profilePicURL = URL(string: profilePictureString) else {
UserProfile.userProfileImage.image = UIImage(named: "profilePicture")
print("Profile picture set to default profile picture")
return
}
// Some code
}
When profilePicURL is not empty, some code gets executed, but when it is empty (equal to ""), the code inside the else block gets executed. The problem is that the profile picture doesn't change, it just executes the print statement inside the else block. Does anyone know what's wrong with my code?
First of all, you have to change your userProfileImage. This Should be a var instead of **static let.
You can use if let statement with an async call in your code. Please try the following code.
let profilePictureString = "http://SOME URl STRING.."
if let profilePicURL = URL(string: profilePictureString){
// Plcae Your Network Code Here.
} else {
DispatchQueue.main.async {
UserProfile.userProfileImage.image = UIImage(named: "profilePicture")
print("Profile picture set to default profile picture")
}
}
You can call the setNeedsDisplay() for update the imageview
DispatchQueue.main.async {
UserProfile.userProfileImage.image = UIImage(named: "profilePicture")
UserProfile.userProfileImage.setNeedsDisplay()
}
use image literal
struct Downloads {
guard let profilePicURL = URL(string: profilePictureString) else {
UserProfile.userProfileImage.image = imageLiteral(resourceName: "profilePicture")
print("Profile picture set to default profile picture")
return
}
// Some code
}
I am working on a image quiz. I have a button that will display either the correct image or the wrong image if there is no correct image. The unique question number comes from an array.
if (questionlist[1]correct = [UIImage imageNamed:#"questionlist[1]correct.png"]) {
Answer4.setImage(UIImage(named: "\(questionlist[1])correct.png"), forState: UIControlState.Normal)
} else {
Answer4.setImage(UIImage(named: "\(questionlist[1])fourthwrong.png"), forState: UIControlState.Normal)
}
Okay so if I'm understanding your questionList array is simply an array of numbers? So questionList = [1,2,3,etc]? In that case, you may want to try something like:
let imageName = "\(questionList[1])wrong.png" //for instance 2wrong.png
if (UIImage(named: imageName) == nil) { // no wrong image exists
imageView.image = UIImage(named: "\(questionList[1])correct.png")
} else {
imageView.image = UIImage(named: "\(questionList[1])wrong.png")
}
Of course this is assuming a correct image exists. It's unclear what you're after, some more information/more code would help.
Is it appropriate to send UIImage between two Uiviewcontrollers?
I'm working on assignment 4 of CS193P Spring - Smashtag.
There I have to implement Mention Table View (It's kind of additional data of tweet: mentions, hashtags, images, urls). I have to place images to appropriate cell there. For that purpose I already download it. After that If user tap on one of that images It should segue to another UIViewController where user can zoom and scroll image.
In many examples which I've seen, people send url of image and fetch it again and again (for mention controller and the same image for another one). I think It decreases perfomance. So I send UIImage object between controllers.
But is it correct?
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == Storyboard.SearchSegue {
if let svc = segue.destinationViewController as? SearchResultsTableViewController {
if let cell = sender as? TextTableViewCell {
if let text = cell.hashtagLabel.text {
if text.hasPrefix("#") || text.hasPrefix("#") {
svc.searchText = text
}
}
}
} else if let svc = segue.destinationViewController as? ImageViewController {
if let cell = sender as? ImagesTableViewCell {
svc.image =
}
}
}
}
svc.image is var:
var image: UIImage? {
get {
return imageView.image
}
set {
imageView.image = newValue
imageView.sizeToFit()
scrollView?.contentSize = imageView.frame.size
}
}
and cell.imageVar
var imageVar: UIImage? {
get {
return imageField.image
}
set {
imageField.image = newValue
spinner.stopAnimating()
}
}
fetch function
private func fetchImage () {
if let u = url {
spinner?.startAnimating()
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
let contentsOfURL = NSData(contentsOfURL: u)
dispatch_async(dispatch_get_main_queue()) {
if u == self.url {
if let imageData = contentsOfURL {
self.imageVar = UIImage(data: imageData)
} else {
self.spinner.stopAnimating()
}
}
}
}
}
}
That only make sense if you're using different image sizes. For instance, if you're using the image in a cell, you should use a small image, a thumbnail, to make the download faster. And then when you see the detail and want to zoom the image, you should use a bigger image (so you have to retrieve it using the url).
But if you only have one image size, it's totally correct to pass an UIImage through view controller.
You can think of caching the image. You can save the image in document directory and use its link to load in other places. One thing however you need to keep in mind is that you need to keep a track of how long you want the images to be cached this way, and a mechanism for deleting them. If you want the image only for one session you can even choose to use NSCache.
I am using parse to retrieve my images and labels and display it on a collection view. The problem was that the collection view loads all the images and labels at once making the load time long and memory usage was high. I was thinking that I would load 10 cells each time however I was recommended to use SDWebImage to make the app lighter. However I don't know how to implement it with parse using swift. I am suspecting that I would put some code in this piece of code below
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("newview", forIndexPath: indexPath) as! NewCollectionViewCell
let item = self.votes[indexPath.row]
let gesture = UITapGestureRecognizer(target: self, action: Selector("onDoubleTap:"))
gesture.numberOfTapsRequired = 2
cell.addGestureRecognizer(gesture)
// Display "initial" flag image
var initialThumbnail = UIImage(named: "question")
cell.postsImageView.image = initialThumbnail
// Display the country name
if let user = item["uploader"] as? PFUser{
item.fetchIfNeeded()
cell.userName!.text = user.username
var profileImgFile = user["profilePicture"] as! PFFile
cell.profileImageView.file = profileImgFile
cell.profileImageView.loadInBackground { image, error in
if error == nil {
cell.profileImageView.image = image
}
}
var sexInt = user["sex"] as! Int
var sex: NSString!
if sexInt == 0 {
sex = "M"
}else if sexInt == 1{
sex = "F"
}
var height = user["height"] as! Int
cell.heightSexLabel.text = "\(sex) \(height)cm"
}
if let votesValue = item["votes"] as? Int
{
cell.votesLabel?.text = "\(votesValue)"
}
// Fetch final flag image - if it exists
if let value = item["imageFile"] as? PFFile {
println("Value \(value)")
cell.postsImageView.file = value
cell.postsImageView.loadInBackground({ (image: UIImage?, error: NSError?) -> Void in
if error != nil {
cell.postsImageView.image = image
}
})
}
return cell
}
I have implemented SDWebImage using Pods and have imported through the Bridging Header. Is there anyone who knows how to implement SDWebImage with parse using Swift?
You should rethink your approach -
I believe you are using collectionViewDelegate method - collectionView(_:cellForItemAtIndexPath:)
this fires every time the collection view needs a view to handle.
In there you can access the cell imageView and set its image (For Example)-
cell.imageView.sd_setImageWithURL(url, placeholderImage:placeHolderImage, completed: { (image, error, cacheType, url) -> Void in })
And if you wish to fade in the image nicely, you could -
cell.imageView.sd_setImageWithURL(url, placeholderImage:placeHolderImage, completed: { (image, error, cacheType, url) -> Void in
if (cacheType == SDImageCacheType.None && image != nil) {
imageView.alpha = 0;
UIView.animateWithDuration(0.0, animations: { () -> Void in
imageView.alpha = 1
})
} else {
imageView.alpha = 1;
}
})
EDIT
I see the you use Parse, so you don't need SDWebImage, you need to use Parse - PFImageView, It will handle your background fetch for the image when it loads. You will need to save reference to your PFObject, but I believe you already do that.
For example (inside your cellForItemAtIndexPath)-
imageView.image = [UIImage imageNamed:#"..."]; // placeholder image
imageView.file = (PFFile *)someObject[#"picture"]; // remote image
[imageView loadInBackground];
How many objects are displaying in the collection view?
Since you mentioned SDWebImage, are you downloading the images in the background as well?
If you want to load the images as the user scrolls, have a look at the documentation for SDWebImage. The first use case describes how to display images in table view cells withouth blocking the main thread. The implementation for collection view cells should be similar.