I'm loading an HTML string into a UIWebView. When the UIWebView finishes loading, I resize its height like this:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
float newSize = [[webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.scrollHeight"] floatValue];
[self.webViewContent setFrame:CGRectMake(self.webViewContent.bounds.origin.x,
self.webViewContent.bounds.origin.y,
self.webViewContent.frame.size.width,
newSize)];
Everything works fine until a certain height. When the HTML string gets really long - 60 000px, for example - then I get a crash. Any ideas, how could I avoid the crash? I tried to find examples where a UIWebView is being tiled, but I couldn't find anything useful.
You're almost certainly running out of memory. I've determined through experimentation that UIWebView allocates memory based on the frame size. You can have a seemingly infinite contentSize and iOS will handle the memory for you as content scrolls in and out of the visible frame.
I had to give up on a design that tiled UIWebViews inside of a UIScrollView. BTW, this behavior changed somewhere around iOS 4.2. It used to be possible to tile UIWebViews with very large frame sizes and the memory was constrained by the frame size of the containing UIScrollView.
Related
I'm having a bit of a problem: I'm trying to access the width of a container in which I've added a sprite to, but it seems to return as 1. However, when I inspect the object in the console, it gives me the proper width.
I wrote up a code pen showing the issue, but it goes something like this:
var container = new PIXI.Container();
app.stage.addChild(container);
var sprite = PIXI.Sprite.fromImage('https://i2.wp.com/techshard.com/wp-
content/uploads/2017/05/pay-1036469_1920.jpg?ssl=1&w=200');
container.addChild(sprite);
console.log(container.height);
console.log(container);
The first console log returns 1, while if I go into the object in the second log it gives me 141.
I'm trying to center the container like in the demo. The demo container returns the proper width, unless you try and do it for only one "bunny" (replacing bunny texture with internet image, also the for loop is commented out).
Any suggestions on a proper approach for this?
Cheers
There's a few things to address here.
Firstly, what the problem in your codepen is:
You're creating a texture from an image that has yet to be loaded.
Until the image loads pixi will not be able to give you the dimensions of it, and the container reports a width and height of 1 when you immediately query them. If you put the same console.log statement in a timeout then it will report the dimensions after the image has loaded and thus the dimensions will be accurate.
Logging out the object itself seems to work because when you examine the contents of it they've been updated to the correct values because the image has loaded by that point.
If the texture is already in the cache at the point that you create a new sprite using it then you won't have to wait before you can access its true dimensions.
Secondly, why the bunny example on pixi's site doesn't have the same problem:
Actually, it does. You just don't notice it.
The magic is in the bunny.anchor.set(0.5);. It lines 25 sprites with width and height of 1 out in a grid. By spacing them out, their container now has width and height of 160.
This container is now centered immediately based on its current dimensions, and then when the sprite textures finish loading and the sprites are updated with their new dimensions. Due to their anchor being set to 0.5, however, this means they remain centered despite their container now being larger.
You can play around with using a larger image than the bunny to exaggerate things and changing the anchor value, along with using the rerun code button rather than just refreshing the page. If you rerun the code the image being used for the texture remains cached by pixi so you get different results.
Lastly, how you would resolve this issue:
Loading your assets before creating sprites with them.
(Or at least waiting before they're loaded before querying their dimensions to position things)
You can find an example of the resource loader that pixi has here: http://pixijs.io/examples/?v=next-interaction#/basics/spritesheet.js
I have a couple of custom cells and web views inside each of these cells. Now,my requirement is to find the height of the HTML string to be loaded on the webview, then based on this change the Custom cell height and the webview height.
I am aware that the document's height can be found in the -webViewDidFinishLoading delegate, but in my app i have a lot of cells and webviews inside each of these cells, so i feel that the app would slow up while scrolling and making unnecessary callbacks
At present i am doing this which gives me the string height.
-(float)getDynemicHeight:(NSString *)pstrText
{
CGSize constraint = CGSizeMake(683,600);
CGSize size = [pstrText sizeWithFont:[UIFont systemFontOfSize:18] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 44.0f);
if (height>400) {
return 400;
}
return height;
}
This however causes a problem as even <div> elements are considered as string and hence a larger value of height is returned
In iOS 6, if you just want to show styled text (not text with images mixed in or something like that), you might like to use NSAttributedString instead of a web view. It allows you to create text with different styles in different stretches of text, paragraph margins, etc. etc. Its metrics are well defined and it comes with measurement methods. Simple UIView subclasses such as UILabel can now display an attributed string. Or you can just draw it yourself, directly into the interface.
http://www.apeth.com/iOSBook/ch23.html#_attributed_strings
If you can't do that, then what you're trying to do is basically impossible. You don't know how the Web view will draw a piece of complex HTML until it has drawn the complex piece of HTML. You will simply have to change your app's architecture. For example you could draw all the Web views way ahead of time so you have the needed info during table-dataSource time.
I want to build a website that looks exactly the same across all screen width's, which means the whole website will scale according to the screen's, or more accurately, the viewport's width.
This is relatively easy to do for SVG images and I have all images correctly scaling according to the viewport's width. The viewport's width is the point of reference, from which all images scale. However, the point of reference for the text is different between any desktop browser and the iPhone's Safari (and I assume any mobile browser).
According to my research there seem to be two possible reasons for different sized text: a difference in the default CSS's or a difference in the rendering engines. Since I can't find any reference to pixel sized text on Chrome's default CSS or Firefox's default CSS, I assume this setting comes from the rendering engine.
My IP is dynamic so I can't provide a live example, but here are the screens comparing the same site in iPhone's Safari and Chrome on the desktop. Notice the huge difference in the size of the text.
Is there any way I can make the text have the same relative size in both these browsers?
I found the answer in JavaScript:
onresize=onload=function(){
document.body.style.fontSize=window.innerWidth/20+"px"
}
which sets the text size according to the viewport's width on the body element. Since all the text set in em's is sized in relation to their parents, all the text is sized correctly from the body element.
Furthermore, if you want to avoid the cascading hell by using rems and respect the original layout design from a let's say 1024px width you can stick with this:
onresize = onload = function(){
document.querySelector("html").style.fontSize = ( innerWidth * 100 ) / 1024 + "%";
}
You should try CSS Unit vw, like this:
body { font-size: 1.5vw; }
However, i am not sure it is supported by mobile browsers...
EDIT
Check for browser compatibility here.
I am trying to get DirectX (DX9) to grab a screenshot of the desktop and immediately draw it back out (in smaller dimensions) to my form.
I have DirectX working to the capacity that the device is created along with a few surfaces and I can render them to screen. I am using one surface F3F3Surf9_SS to get the desktop Screenshot.
Here is my declaration and initialization of varaibles
F3D3Surf9_SS : IDirect3DSurface9; //Surface SS
F3D3Surf9_A : IDirect3DSurface9; //Surface A
F3D3Surf9_B : IDirect3DSurface9; //Surface B
...
FDirect3D9.CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,Form1.Handle,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,#D3DPresentParams,
FDirect3DDevice9);
FDirect3DDevice9.CreateOffscreenPlainSurface(1360,768,D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT,F3D3Surf9_A,nil);
D3DXLoadSurfaceFromFile(F3D3Surf9_A,nil,nil,'D:\Images\Pillar.bmp',nil,
D3DX_DEFAULT,0,nil);
FDirect3DDevice9.CreateOffscreenPlainSurface(1360,768,D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT,F3D3Surf9_B,nil);
D3DXLoadSurfaceFromFile(F3D3Surf9_B,nil,nil,'D:\Images\Niagra.bmp',nil,
D3DX_DEFAULT,0,nil);
FDirect3DDevice9.CreateOffscreenPlainSurface(Screen.Width,Screen.Height,D3DFMT_A8R8G8B8,
D3DPOOL_SCRATCH,F3D3Surf9_SS,nil);
Here is the code I use to grab and then render the screenshot
FDIrect3DDevice9.BeginScene;
FDirect3DDevice9.Clear(0,0,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),0,0);
FDirect3DDevice9.GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO, BackBuffer);
FDirect3DDevice9.GetFrontBufferData(0,F3D3Surf9_SS); //Get the screen shot
FDirect3DDevice9.StretchRect(F3D3Surf9_SS,nil,BackBuffer,nil,D3DTEXF_NONE); //Draw it
FDIrect3DDevice9.EndScene;
FDirect3DDevice9.Present(nil,nil,0,nil);
However this does not work.
The image does not get drawn to screen. If I draw surface A or B to screen, that works but it doesn't work for Surface SS. However I know Surface SS has the screenshot in it since if I call D3DXSaveSurfaceToFile the resulting bitmap I put on the hard disk is a valid screen shot.
Any thoughts on the proper way to do this?
The reason this would not work is that the F3D3Surf9_SS was declared in system memory by D3DPOOL_SCRATCH and cannot be drawn directly to the back buffer as I was trying to.
So my solution was to use the F3D3Surf9_A surface and use UpdateSurface to copy the screenshot in system memory into the surface A in video memory.
The only other change I had to make to get this to work was create Surface A in the same format as the screenshot surface: D3DFMT_A8R8G8B8. Also had to make sure the the destination surface in UpdateSurface was larger than the source surface.
NOTE:
This is slow since we are reading from video memory to system memory and then right back to video memory.
I needed this for my application since I want to capture everything the OS and other application put on screen but if you are just worried about your own application then there are better alternatives.
If you know of a way to GetFrontBufferData without putting it to system memory (which is the only way I could see it working) please let me know.
I wanted to know how should I use high res images in iOS4 sdk using UIImaageView.
blackBox = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"alert_bg.png"]];
blackBox.frame = CGRectMake(98.0f, 310.0f, 573.0f, 177.0f);
When I use this code I get strange results... the image does not get the correct size. It is looking very big on iPhone 4 screen.
Should I use 326 ppi images?
I have read http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/SupportingResolutionIndependence/SupportingResolutionIndependence.html this but I am very confuse.
Thanks
Saurabh
The key thing to understand about supporting the Retina Display is that, in your code, the screen is always 320x480. You don't need to double the resolution of anything but your image resources themselves. In this case, you just need to put two resources in your app bundle: an alert_bg.png that fits on a 320x480 screen—in this case, I'd guess that'd be 286x88—and an alert_bg#2x.png, exactly double the size of the other, that fits on a 640x960 one. If you ask UIKit for [UIImage imageNamed:#"alert_bg"], it'll automatically pick the correct-resolution resource for the current screen.
You should provide a 480x320 pixels image for the 3G, 3GS and original iPhone, named "alert_bg.png" and another 960x640 px one, named "alert_bg#2x.png" for the iPhone 4.
The "#2x" in the name is automatically added by iOS and loads the image automatically if it finds it, instead of the standard resolution one.