I have a collection view in view controller 1 and i want to pass the image to next view controller in a scroll view.The image is getting loaded using this code
let image = selectedimage
let smoothLinesImage = image
imageSize = smoothLinesImage?.size
imageScale = smoothLinesImage?.scale
let transparencyTolerance = 90
drawingView.loadImage(smoothLinesImage!, savedImage: selectedimage, transparencyTolerance: transparencyTolerance)
This selectedimage has been passed from the view controller 1 using segue.
This image is getting loaded faster in xcode simulator whereas it is taking more time to be loaded in iphone.It takes almost 10 secs to load in iphone whereas it takes less than 3 secs in xcode simulator.Could anyone tell me what could be the reason for it?
Simulator is faster than most iOS Devices since it's running on a faster CPU. So that behavior is to be expected. However, if it's taking more time to load than you want, there's something going wrong with your code.
I'd check if your image is too large, or if there's some method making it larger than expected.
Note: Simulator is usually faster on CPU and Storage tasks, GPU tasks should be faster on the physical device.
Related
I'm currently trying to load a map image which is a large(16mb) .jpg file inside a scrollView so you can zoom in and out.
When I launch the app inside the simulator everything runs fine and smooth. However once I run it on my test device (iPod 4.1, iOS 6.0) the app shows the launch image and then it crashes with no error messages at all.
This is how the code currently looks like.
myImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"map.jpg"]];
myScrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(15,120,290,365)];
myScrollView.showsVerticalScrollIndicator=YES;
myScrollView.scrollEnabled=YES;
myScrollView.maximumZoomScale = 10.0;
myScrollView.minimumZoomScale = [myScrollView frame].size.width / myImage.frame.size.width;
myScrollView.clipsToBounds = YES;
myScrollView.bounces = NO;
myScrollView.showsHorizontalScrollIndicator = NO;
myScrollView.showsVerticalScrollIndicator = NO;
[self.view addSubview:whiteFrame];
[self.view addSubview:myScrollView];
myScrollView.contentSize = CGSizeMake(myImage.frame.size.width,myImage.frame.size.height);
myScrollView.delegate = self;
myScrollView.zoomScale = [myScrollView frame].size.width / myImage.frame.size.width;
[myScrollView addSubview:myImage];
Any help is greatly appreciated.
EDIT:
I found this in the docs
If you have a very large image, or are loading image data over the web, you may want to create an incremental image source so that you can draw the image data as you accumulate it. You need to perform the following tasks to load an image incrementally from a CFData object:
Create the CFData object for accumulating the image data.
Create an incremental image source by calling the function CGImageSourceCreateIncremental.
Add image data to the CFData object.
Call the function CGImageSourceUpdateData, passing the CFData object and a Boolean value (bool data type) that specifies whether the data parameter contains the entire image, or just partial image data. In any case, the data parameter must contain all the image file data accumulated up to that point.
If you have accumulated enough image data, create an image by calling CGImageSourceCreateImageAtIndex, draw the partial image, and then release it.
Check to see if you have all the data for an image by calling the function CGImageSourceGetStatusAtIndex. If the image is complete, this function returns kCGImageStatusComplete. If the image is not complete, repeat steps 3 and 4 until it is.
Release the incremental image source.
Does anyone know about a sample code for that ?
A 16mb jpg is going to take a pretty decent chunk of RAM when uncompressed. Your app is probably crashing because it is using too much memory. You can check this by reproducing the crash and checking the device's console log in the Xcode organizer.
You will need to either:
Reduce the dimensions of the image as much as your design will permit to greatly reduce memory usage. For example, there's no reason to have a 16mb jpg if it will never be shown at full-resolution.
Chop the image up into tiles and only load the tiles currently displayed on the screen and the surrounding areas. Then load additional tiles as the user scrolls around. This is how maps apps are able to display extremely large images without running out of RAM.
Remember to also test your app on the supported device with the lowest amount of RAM. These devices will probably kill your app sooner than the newest devices.
At 16 MB, the image is too big for your iPod to handle. The app is crashing because it's loading the image directly, and asking for too much memory and the system has had to kill it.
You should create a smaller version of your image, in terms of both canvas size and image quality, for your app.
You could also incrementally load the image instead.
When you're testing on the simulator, it has full access to the gobs of memory on your computer. Way more than the 256MB available to your iPod 4 (there isn't such thing as an iPod 4.1).
Have a look at CATiledLayer
https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CATiledLayer_class/Introduction/Introduction.html
There is also an example Apple project using it
https://developer.apple.com/library/ios/samplecode/PhotoScroller/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010080
Good luck
I hope you are not loading this image on app launch. Application launch should be as light as possible. If launch time is more than 20 secs then iOS kills the app on its own. On simulator resources are much bigger and you may not see the similar behavior as that with device. You may also want to use the lazy loading technique to load lighter image first and then load heavy image only when needed while zooming, panning etc.
Having said that, one imortant aspect of [UIImage imageNamed] is that it caches all images loaded in that way and they never get unloaded, even if you dealloc the UIImage that was created! This is good in some circumstances (e.g. smallish images in UITableView cells), but bad in others (e.g. large images).
The solution is to use [UIImage imageWithData] which does not do this caching and which unloads the data when the UIImage is dealloc'd.
Another solution to this problem consists of either loading scaled version of the image (*1) or you have option to display it in full resolution with help of CATiledLayer(*2).
[UIImage imageWithCGImage:scale:orientation:];
CATiledLayer example
Please see this simple CATiledLayer example https://github.com/seanhess/CATiledLayer-Example
It consists of one viewController with a hierarchy like this:
view: (frame = window size)
scrollView: (frame = window size, content size = 200 x 4000)
contentView: (frame = content size = 200 x 4000, tile size = 100 x 100)
The content view's layer has been overriden to be a CATiledLayer.
If you run the linked code, you'll see that tiles with the same rect are requested multiple times. It happens both when you first run the code, and when you scroll.
Switch to branch "one-column" - it only happens on init, never when you scroll down.
Switch to branch "default-tile-size" - it only happens on init, but very rarely (you have to run it multiple times before it happens)
I'm trying to write some code in drawLayer:inContext: that locates the correct data and draws it. It could be expensive, and I don't want to do it more than once.
Any idea what is going on? What could I do differently?
This is a bug in IOS. It happens when the CPU is dual-core, in that case there are two threads each requesting each tile. That means that the bug is present in the simulator, and on the iPhone 4S, but not on the other iPhone models. I assume it will also be present on dual-core iPads.
I have reported the bug to Apple long ago already (for the simulator) and recently again (for the iPhone 4S). Apple recently gave the impression that they have solved it in IOS 6.
Very well solved here:
https://stackoverflow.com/a/8783396/341994
The problem is that (at least in my testing) drawRect: is called simultaneously on two threads. By logging, I can see individual lines of my code being executed twice before we go on to the next line, which is also executed twice! The logging shows that this is because one thread is executing a line and then another thread is executing the same line - and then they both go on to the next line.
This is as nasty as it gets. The solution is to wrap the the whole interior of drawRect: in a dispatch_sync on a serial queue.
Have you tried your code on a device? I consistently see this behavior in the simulator, but not on my iPad 1. I just tried this again in an app that is displaying a large tiled image. My tile size is 256 and on the device my drawRect: method is being called 12 times, which is how many tiles are on the screen. In the simulator, the method gets called between 20 and 23 times, with all but the last few tiles being drawn twice.
Isn't this due to the setLevelsOfDetailBias ? When I leave everything standard the tiles only get rendered once (testing on the device). But when I set the levelofdetailbias to 2, the tiles get loaded multiple times. I think that's due to the fact that CATiledLayer just starts caching extra detail levels when the device is idle.
In the end, the answers didn't work. It is fairly simple, though, to make your delegate method be aware of whether or not it has drawn that cycle.
I have a 6000x3000 px image that is in a zoomable view in my xCode project. In the initial view, a button is pressed to access the view with the large, zoomable image. This all works fine, except for the time that is taken to "load" the image often times causes a crash in the app, especially when I am testing on older devices (it seems to work fine most of the time on my 4G itouch). Is there any way to "pre-render" this one large image, or anything else that I can do to prevent crashing?
Do the math: 6000 x 3000 x 3 (red green blue) = 54,000,000 bytes = 51.5MiB of raw data. The normal image handling has a lot of overhead and that simply takes too much memory.
According to this question the solution is to use a CATiledLayer. As far as I have understood it, you need to divide your large image into smaller parts and draw these smaller parts with the help of CATiledLayer.
Edit: Here's a quote from the UIView class reference:
Note: In iOS 2.x, the maximum size of a UIView object is 1024 x 1024 points. In iOS 3.0 and later, views are no longer restricted to this maximum size but are still limited by the amount of memory they consume. It is in your best interests to keep view sizes as small as possible. Regardless of which version of iOS is running, you should consider tiling any content that is significantly larger than the dimensions the screen.
Read: If it's larger, use a CATiledLayer to draw smaller parts.
Is it normal for the imagepicker to take a while to load the photo album the first time and subsequent views are fast?
I've noticed that in my testing as well. It doesn't surprise me, iOS probably keeps the imagepicker in memory once it has created and initialized it.
My application contains more than 200 images each with size approx. 15 KB. I want to flip these image one by one. Is there will be any time lag for loading images? Is there any alternate method for doing that?
Anyone please help!
My application contains more than 200 images each with size approx. 15 KB. I want to flip these image one by one.
OK.
Is there will be any time lag for loading images?
Maybe. Try it and see. If there is, run your app under Instruments to see what really caused it.
Is there any alternate method for doing that?
You haven't proposed a primary method to be alternate to.
The main thing is that, since this is an iPhone app, you're probably not going to need 200 images loaded at once. Consider the Home screen: Those icons are about as small as is practical, and there are only 20 (24 on the iPad) of them on the screen at one time.
Assuming you want to allow scrolling or paging through the list, you'll probably want to keep a pageful up and a pageful down already loaded and flipped and ready to display, to make scrolling/paging faster. That's still only 60–72 images, and you can do half to two-thirds of them after displaying the visible 20–36.
Moreover, are the images always flipped? If so, then flip them at build time and copy the flipped images into your app, and do no flips at runtime. Then you're just displaying images.