I want to make a gallery with UIScrollview like this.
In case, I want to get the images from web, but with this code my VC is very slow to load
var pageImage: [UIImage] = []
for d in image {
var imgUrl: NSURL = NSURL(string: "https://images.com/\(d.thumbnail)")!
var imgData = NSData(contentsOfURL: imgUrl)
pageImage.append(UIImage(data: imgData!)!)
}
How to make my VC load faster?
Only load the images when you actually need them. Use the scroll view delegate to find out when an image is about to appear on screen.
You should also not fetch the images on the UIThread which will make the app feel unresponsive. I would recommend using a 3rd party lib for loading and displaying the images such as SDWebImage or AFNetworking+UIImageView
as eric said you are loading imae on main thread you can set image in swift with url like imageView.setImageWithURL
or you can load image with background thread
Related
I am getting an Image as Data from server.To show it I am using UIImage?(data:) to show it.For a specific image application is getting crash because of memory pressure. What could be the reason, how to fix it.
if let imgData = Utils.fetchDataFromDocumentDirectory(imageName:"test.jpg"){
attachmentImgView.image = UIImage(data:imgData)
}
How big is the Image? and are you downloading only 1 image or an array?
This might be caused from the size of the image you are trying to download.
My advice if you are trying to show an image, only giving it the url like so:
let url = URL(string: "http://i.imgur.com/w5rkSIj.jpg")
let data = try? Data(contentsOf: url)
if let imageData = data {
let image = UIImage(data: data)
}
even better you can try to use AsyncImageView 3rd party library where you give it the url of the image and it shows it asynchronously without delays in the app.
Hope this helps!
I am trying to make the background of my app an animated gif. This is my code by i am getting the error 'exc_bad_instruction' for this line: images.append(UIImage(named: imageNames[i])!)
I don't see what the problem is. Here is the code:
var imageNames = ["tmp-0.gif", "tmp-1.gif", "tmp-2.gif", "tmp-3.gif", "tmp-4.gif", "tmp-5.gif", "tmp-6.gif", "tmp-7.gif", "tmp-8.gif", "tmp-9.gif", "tmp-10.gif", "tmp11.gif", "tmp-12.gif", "tmp-13.gif", "tmp-14.gif", "tmp-15.gif", "tmp-16.gif", "tmp-17.gif", "tmp-18.gif", "tmp-19.gif"]
var images = [UIImage]()
for i in 0..<imageNames.count{
images.append(UIImage(named: imageNames[i])!)
}
theGif.animationImages = images
theGif.animationDuration = 1.0
theGif.startAnimating()
If you're considering using an animated GIF for the background, instead of trying to decouple all of the frames in the GIF and using the animation capabilities of UIImageView, I'd recommend using a proper animated GIF library.
Flipboard's FLAnimatedImage library is apparently one of the more popular ones (I haven't used it personally, so I can't say for sure). It's Objective-C, but it should interoperate with Swift with no issues.
I am using "SVProgressHUD" for loader. When I want to load an image from url I am using async process to load the image in background. After completing the download I am updating the UI. And for that time span I am using a placeholder on the imageview and a loader with "Please wait..". But I want to use a loader like "Instagram". That means, when an image is loading from online it loads a blurry image of the original image and upon downloading the image , the blurry image show the original image.
Can any one please suggest me how can I do this?
The stuff you are talking about is Progressive JPEG.
Progressive JPEG (PJPEG) is an image format that stores multiple,
individual “scans” of a photo, each with an increasing level of
detail. When put together, the scans create a full-quality image. The
first scan gives a very low-quality representation of the image, and
each following scan further increases the level of detail and quality.
When images are downloaded using PJPEG, we can render the image as
soon as we have the first scan. As later scans come through, we update
the image and re-render it at higher and higher quality.
So, you have to make images loadable in this modern progressive format.You can follow a approach where every image before saving on server just convert it into appropriate progressive format.There are several tools avaiable for different type of server. E.g jpegtran
To check whether image is progressive or not you can use this tool or tool2.You can search for online tool a lot of tool is available.
Now for iOS
You can follow this tutorial
Some library
Concorde
DFImageManager
Assuming you are in control of the hosting of the images you can host lower resolution images and make 2 fetches, one for the lower resolution, and one for the higher. If you make the lower resolution image significantly smaller in file size the fetch for it will finish before the fetch for the full image, and you populate the UIImageView with this image until such a time as you can replace it.
Purely example code would look like this:
let imageView = UIImageView()
let lowResOperation = NSBlockOperation {
guard let imageData = NSData(contentsOfURL: NSURL(string: "https://myhost.org/low-res-image")!),
image = UIImage(data: imageData) else { return }
if imageView.image == nil {
imageView.image = image
}
}
let highResOperation = NSBlockOperation {
guard let imageData = NSData(contentsOfURL: NSURL(string: "https://myhost.org/high-res-image")!),
image = UIImage(data: imageData) else { return }
imageView.image = image
}
let backgroundQueue = NSOperationQueue()
backgroundQueue.addOperations([lowResOperation, highResOperation], waitUntilFinished: true)
I have a UITableView with A lot of UITableViewCell, I use this code to load content and images to the UITableCell but it takes long time for the image to show for each UITableViewCell.
var loadOnce : [String] = []
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("ProfileActivities", forIndexPath: indexPath) as! ProfileActivitiesTableViewCell
if !loadOnce.contains("\(indexPath.row)") {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let LocationImage = self.postmap[indexPath.row]
let LocationImageUrl = NSURL(string: LocationImage)
let LocationImageData = NSData(contentsOfURL: LocationImageUrl!)
let ProfileImage = self.postimg[indexPath.row]
let ProfileImageUrl = NSURL(string: ProfileImage)
let ProfileImageData = NSData(contentsOfURL: ProfileImageUrl!)
dispatch_async(dispatch_get_main_queue(), {
cell.locationImg.image = UIImage(data: LocationImageData!)
cell.activitesProfileImg.image = UIImage(data: ProfileImageData!)
});
});
loadOnce.append("\(indexPath.row)")
}
return cell
}
Putting the code in dispatch_async made scrolling smother but its still takes time to load images.
how to make it load images faster considering I have to many images something like Facebook or Instagram.
Thanks.
There will be issue because of Async call and ReUsability. Lets say your Image at IndexPath 1 is loading image but it is still taking time to download and meanwhile user scrolled down at some another index i.e. 15 and Internally the same cell of Index 1 is alloted to Index 15 and Image of cell 1 will be displayed in Cell 15 if you have not managed to handle previous calls for same instance of cell. Thats why its Better to use some caching library like SDWebImage(As #SeanLintern88 said) or AFNetworking's UIImageView Category
AlamoFire's UIImageView (For Swift)
Event if you wanted to do this, then better is to go with subclassing, it will help you to manage the Calls and Its termination.
In your case the Loading of Image might be because of Size of actual image that you are loading from server. CDN kind of service provide some easy to implement techniques to serve different size of images as per the request. So even If User has uploaded 1200x1200 sized image but on list screen you can fetch its 120x120 sized image, This helps is faster loading as well as it will save Physical Memories.
Use one of the following libraries to asynchronously load images to you view :
1) Asyncimageview https://github.com/nicklockwood/AsyncImageView
2) SDWebImage https://github.com/rs/SDWebImage
It sounds like your image sizes could be large as the code looks fine, usually apps like FB/Insta would use low res renditions and then load in higher res after/when needed.
Most people use an image fetching library such as SDWebImage as this will async fetch the images and cache them so you don't have to save them on your model and consume the memory.
https://github.com/rs/SDWebImage
I have a sign up and sign in view controller and a moving gif background along with other storyboarded UI elements.
Currently I have the gif coding on each view controller obviously making the gif restart as I segue between each view controller and also more concerning having a quick pop of white before it loads whenever moving between the pages.
What can I add to my code to:
1. Prevent the white pop when it segues
2. Swapping between view controllers smoothly with the gif just continuing as if nothing has happened, so it looks like you move the UI not the page.
Look at Vine Sign In / Sign Up for reference as it basically functions in a similar way and want the background gif to function as it does on Vine.
override func viewDidLoad() {
super.viewDidLoad()
let filePath = NSBundle.mainBundle().pathForResource("beachwater", ofType: "gif")
let gif = NSData(contentsOfFile: filePath!)
let webViewBG = UIWebView(frame: self.view.frame)
webViewBG.loadData(gif!, MIMEType: "image/gif", textEncodingName: "UTF-8", baseURL: NSURL(string: "")!)
webViewBG.userInteractionEnabled = false;
webViewBG.layer.zPosition = -3.0;
self.view.addSubview(webViewBG)
As a starting point don't use a UIWebView for this. It is the reason you are seeing a white background just before the gif, the web view has been rendered on screen then shortly after the gif is rendered.
I'd recommend separating out the frames of the gif and loading them into a UIImage (and finally into a UIImageView) using one of the following techniques:
animatedImageNamed:duration:
animatedImageWithImages:duration:
If you don't want to separate the frames, use a gif rendering library such as FLAnimatedImage