Looking quickly, I cannot find a trivial way to copy a cairo_t including the entire stack of saved graphics states.
Is there one?
This is needed because a certain API that I need to provide an implementation for requires this mechanic: copying a stack of saved graphics states.
Alternatively, is it possible to "peek" at a state below the tip of the cairo_t stack when using getter functions?
Sorry, but nope, there is no way for either of those.
Related
I'm building a UIView with a custom drawRect function. This is a fairly complex view, with a number of different items that need to be drawn. I've basically broken it down into one function per item that needs to be drawn.
What I'm wondering is should I pass my CGContextRef, obtained from UIGraphicsGetCurrentContext(), as a parameter to each function, or can I just call it at the start of each function? The latter option looks neater to me, but I am wondering if there is much of a performance penalty?
It's the same, unless you are saving/restoring context all around. In any way, getting the context from that method will, most probably, never be the bottleneck.
I suggest that if you are not saving and restoring states, you could use the UIGraphicsGetCurrentContext(). However, if you are indeed saving state, you should pass this one since it would be easier to read your code.
It's a matter of style I guess...
Pier-Olivier's response is good, and just grazes the key issue: don't worry about it until you have to. This is a case of premature optimization. Before spending a lot of time deciding whether to pass around your CGContextRef, you should write your application and then look at the performance. Using Instruments can help you figure out where your real bottlenecks are. If it turns out this is causing problems (which I highly doubt), then you can optimize it.
just profile after it's implemented correctly and well tested.
if it really shows up as a hotspot, then your problem is likely best divided, and/or rendered to an offscreen context... or by using lower level rendering.
My model object has a UIImage *iconImg that is often updated asynchronously. I want to allow instances of other classes to observe any changes to myModel.iconImg elegantly. Right now, my asynchronous image fetch class takes a UIImage** (yes, ugly, but it's working). The problem, however, is that messing with the UIImage via pointers bypasses any KVO I might have enjoyed using properties, so I have to use NSNotification which I'm not a big fan of. Here are the main requirements:
I want to be able to load iconImg even when no views are ready to display it (ie no UIImageView is ready)
Ideally, only the instances that have elected to observe the specific myModel.iconImg instance will be made aware of changes (unlike with Notifications where I currently have to filter)
I have several model classes with iconImg properties that all need to work this way, not just one
I can change my image fetcher class if necessary (here's current signature):
+ (BOOL)asyncImageFetch:(UIImage**)anImagePtr withURL:(NSURL*)aUrl;
Not sure how clear that is, so let me know if I can elaborate on anything.
Thanks,
Steve
For anyone looking with similar requirements, take a look at SDWebImage (looks like Olivier Poitrey is the original author). Github repository here: https://github.com/rs/SDWebImage.
I've been using it and it's very nice.
I'm making an iPhone game in which I have two main views, the planning stage and the action stage. Both of these will have different graphics etc, but I'll obviously need to pass information between them. I've pretty much finished programming the planning stage, and I know how to switch between views, but I'm a little fuzzy on how exactly I should be setting the whole thing up. Should my SwitchViewController, which handles the switching between the two views, also control the passing of the game state and the game moves between the two views? Or is there a better way to do this? Thanks for reading!
It would probably make sense to package all your game information up into a single 'gameState' object, and attach that to your app delegate (or some other 'non transient' object).
If you pass it all back and forth, you can run into problems if you ever change your flow, or add a variable and forget to pass it. This approach avoids both those issues.
I would suggest setting up a sharedInstance which will allow you to use data between the two screens.
I am just wondering is there a way to convert nib/xib file to ojbective C code? I just want to find the equivalent code to the nib/xib file (I've tried nib2objc, seems the result is not what I am after).
Actually I want to compile this example
http://developer.apple.com/iphone/library/samplecode/TableSearch/index.html
without nib/xib file (I want it exactly the same with original), any idea about doing this?
Check out nib2objc:
nib2objc converts NIB files (or XIB ones) into Objective-C code, including all the properties of each instance, the documented constructor calls, and also the view hierarchy.
nib2objc yourfile.xib > code.m
In the general case, I think the answer is no. Nibs are not code; they're archives of serialized objects. So what you're asking is, "Given a graph of arbitrary serialized objects, can I generate some source code that might create such a graph without using serialization?" Without special support for such a process in all classes involved, I don't see how you could.
It would probably be more beneficial to ask about what you actually need to accomplish rather than this specific way of doing whatever it is.
To all the 'There shouldn't be any reason to not use a nib/xib' type responses here, let me provide a concrete example as a counterpoint.
[iPhone OS 3.1.3, 3.2]
iPhone OS apps have a limited amount of memory to work with. If you use too much your app is automatically terminated by the OS.
Interface builder loads images referenced in a nib/xib into a cache using [UIImage imageNamed...], which uses up memory and does not automatically release that memory. There is also no way for you to request those images in that shared cache be released.
Lay out some large images in nib/xib files (i.e. - backgrounds), in an app with multiple nib/xib files, and you will very quickly have an app which gobbles up memory quickly (3mbs per full size png background on iPad), that you have no control over releasing. Any doubts about this, check the documentation for [UIImage imageNamed] and do some googling to verify that is what is used.
That's a case for not using a xib/nib.
I think it makes sense to do this if you just want to create a starting point for a view that is created programmatically in a way that isn't easy or possible to do with Interface Builder. It is also convenient if you want to bundle the view hierarchy in to a static library so that it is fully self-contained. Ideally you want to use nibs if possible though. It will make internationalization easier. However you can still support internationalization with a strings file.
I'm drawing offscreen to a CGContext created using CGBitmapContextCreate, then later generating a CGImage from it with CGBitmapContextCreateImage and drawing that onto my view in drawRect (I'm also drawing some other stuff on top of that - this is an exercise in isolating different levels of variability and complexity).
This all works fine when it's all running on the main thread. However one of the motivations for splitting this out this way was so that the offscreen part could be run on a background thread (which I had thought should be ok since it's not rendering to an onscreen context).
However, when I do this the resulting image is empty! I've checked over the code, and placed judicious NSLog's to verify that everything is happening in the right order.
My next step is to boil this down to the simplest code that reproduces the issue (or find some silly thing I'm missing and fix it) - at which point I'd have some code to post here if necessary. But I first wanted to check here that I'm not going down the wrong path with this. I couldn't find anything in my travels around the googlesphere that sheds light either way - but a friend did mention that he ran into a similar issue while trying to resize images in a background thread - suggesting there may be some general limitation here.
[edit]
Thanks for the responses so far. If nothing else they have told me that at least I'm not alone in not having an answer for this - which was part of what I wanted to find out. At this point I'm going to put the extra work into getting the simplest possible example and may come back with some code or more information. In the meantime keep any ideas coming :-)
One point to bring up: A couple of people have used the term thread safety with respect to APIs. It should be noted that there are two types of thread safety in this context:
Threadability of the API itself - ie can it be used at all from more than one thread (global state and other re-entrancy issues such as C's strtok are common reasons that an API might not be thread safe too).
Atomicity of individual operations - can multiple threads interact with the same objects and resources through API without application level locking?
I suspect that mention so far has been of the first type, but would appreciate if you could clarify.
[edit2 - solved!]
Ok, I got it all working. Executive summary is that the problem was with me, rather than bitmap contexts themselves.
In my background thread, just before I drew into the bitmap context, I was doing some preparation on some other objects. It turns out that, indirectly, the calls to those other objects where leading to setNeedsDisplay being called on some views!
By separating the part that did that out to the main thread it now all works perfectly.
So for anyone who hits this question wondering if they can draw to a bitmap context on a background thread, the answer is you can (with the caveats that have been presented here and in the answers).
Thanks all
Just a guess, but if you are trying to call setNeedsDisplay from another thread, you need to call it via performSelectorOnMainThread instead.
What you're doing should work if you're working with the CGContextRef in one and only one thread. I've done this before with 8 cores working on 8 different parts of an image and then compositing the different resultant CGImageRefs together and drawing them onscreen.
Apple don't say anything about thread safety on iPhone but Cocoa (as opposed to UIKit) is generally thread safe for drawing. As they share a lot of drawing code, I would assume drawing on iPhone is threadsafe.
That said, your experience would imply there are problems. Could it be that you are using your image before it is rendered?
Not all APIs are thread-safe. Some require locking or require that they be run on the main thread. You may want to scour the documentation. I believe there is a page that summarizes which parts of the SDK are thread-safe and which aren't.
In case anyone is/was searching for exactly how to do this i've written a blog post that describes how to do this, and wraps the whole thing in a NSOperation subclass.