How do I create a mutable array of CGImageRefs? - iphone

I want to keep a mutable collection of CGImageRefs. Do I need to wrap them in NSValue, and if so how do I wrap and unwrap them properly? Can I get away with using a C array? If so how do I construct it and how do I add elements to it later? Is it significantly more costly to use UIImages instead of CGImageRefs as the elements of the collection?

You can directly add CGImage to NSMutableArray. You will need to cast to (id) to avoid compiler warnings.
CFType is bridged to NSObject. You can send any message NSObject responds to to any CFType. In particular, -retain and -release work as normal.

2011: just in case someone's still looking
You can wrap CGImageRef in NSValues by using
+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type
hence:
CGImageRef cgImage = [self cgImageMethod];
NSValue *cgImageValue = [NSValue valueWithBytes:&cgImage objCType:#encode(CGImageRef)];
[array addObject:cgImageValue];
to retrieve:
CGImageRef retrievedCGImageRef;
[[array objectAtIndex:0] getValue:&retrievedCGImageRef ];
hope this helps somebody

Getting the CGImageRef out of an UIImage via image.CGImage can be costly. From the documentation:
If the image data has been purged because of memory constraints, invoking this method forces that data to be loaded back into memory. Reloading the image data may incur a performance penalty.
If you feel comfortable with mixing C++ and Objective-C, you can use a std::vector for storing the CGImageRef. Rename your source file from .m to .mm and try this:
#include <vector>
...
CGImageRef i;
...
std::vector<CGImageRef> images;
images.push_back(i);
If you want to keep the vector as a member of a Objective-C class, you should allocate it on the heap, not the stack:
Header file:
#include <vector>
using std;
#interface YourInterface : ...
{
vector<CGImageRef> *images;
}
and in the implementation file:
images = new std::vector<CGImageRef>();
images->push_back(i);
...
//When you're done
delete images;
images = NULL;

Related

Add GLKVector3 to an NSMutableArray

I am trying to add a GLKVector3 object into an NSMutableArray. I understand that NSMutableArrays will only accept certain objects so what would be the best way for me too add a GLKVector3 to an array.
Here is a sample of code:
for(id basenormal in [jsnmvtx objectForKey:#"baseNormals"]){
[basenormalsVectorArrays addObject:GLKVector3MakeWithArray(basenormal)];
}
Thanks
The issue is that GLKVector3 is a C-style struct, not an object. So it doesn't know how to respond to retain or release and therefore won't work with an NSArray.
What you can do is wrap each one into an NSValue as that's an object type and it knows how to keep arbitrary C types inside it. It's not especially neat because you're straddling the border between C and Objective-C but e.g.
GLKVector3 someVector;
[array addObject:[NSValue valueWithBytes:&someVector objCType:#encode(GLKVector3)]];
...
GLKVector3 storedVector;
NSValue *value = ... something fetched from array ...;
[value getValue:&storedVector];
// storedVector now has the value of someVector
That'll copythe contents of someVector into the NSValue and then copy them out again into storedVector.
You can use valueWithPointer: and pointerValue if you'd prefer to keep a reference to someVector in your array rather than copying contents, though then you'll need to be careful about manual memory management, so a better solution might be to use NSData as in:
// we'll need the vector to be on the heap, not the stack
GLKVector3 *someVector = (GLKVector3 *)malloc(sizeof(GLKVector3));
[array addObject:[NSData dataWithBytesNoCopy:someVector length:sizeof(GLKVector3) freeWhenDone:YES]];
// now the NSData object is responsible for freeing the vector whenever it ceases
// to exist; you needn't do any further manual management
...
GLKVector3 *storedVector = (GLKVector3 *)[value bytes];

Static UIImage in whole application

I want to have an static UIImage so I could access it from different classes. I've tried this way, but didn't worked:
Made Constans.h file with:
static UIImage *myImage;
And after that I import this header where it's needed. I thought that at this moment myImage was static and any changes made on this object would be visible everywhere. But it looks like every class is working on it's own myImage instance. Is there any way to have such static UIImage?
Edit:
Property in AppDelegate works fine. I have now static UIImage, but still I don't have effect I was expecting.
I have an UIImageView in ViewController. I load an image to my delegate.myImage and after I do:
delegate.myImage = [UIImage imageNamed:#"blah.png"];
myImageView.image = delegate.myImage;
Image is loaded, but after I want to change it in AppDelegate, but when I change myImage this way:
delegate.myImage = [UIImage imageNamed:#"blah2.png"];
nothing change in myImageView. It's like myImageView.image = delegate.myImage copied memory address of myImage so after if I change reference of myImage it's not affecting myImageView.image. I wanted to have an UIImage that after any changes it would also affect myImageView.
Is there other way than having an reference to myImageView in AppDelegate?
Rather than making an explicitly application-wide image, just use [UIImage imageNamed:]. This handles caching of the image for you! Whereever you need to use the image, just access it like so:
[UIImage imageNamed:#"imageName.png"]
Note: this will cause there to be a single copy of the image in memory. You can't unload it -- but newer versions of iOS may unload it behind the scenes upon low memory conditions.
See also the API docs for [UIImage imageNamed:].
Btw, imageNamed is often used for small images that get used multiple times -- e.g. table cell images -- but there's no reason to not use it on large images if you genuinely want a static app-wide image.
The keyword static makes a variable local to the compilation unit where it id defined. This means you can safely have the same symbol defined in multiple .c files; all those declarations will not collide and each file will have its own private symbol.
Put simply, if you really want to define a global variable that is accessed by any part of your program, you do not need the static keyword. In this case, though, the "trick" is declaring the variable in a header file (that you include everywhere the global should be visible) like this:
extern UIImage *myImage;
and then provide a definition for that variable in one single place (.c file) without the static keyword. The extern keyword tells the compiler that the definition for that symbol is not found inside of the current compilation unit (.c file), but in a different one.
Now, as many others have pointed out, you could better do that by means of a singleton, although it is usually recognized that using a singleton to mask a global variable is usually a way to mask a design problem.
That's a C problem (not specifically related to Objective-C or iOS)
The static keyword make the variable sticky inside its compilation unit.
When you #include (or #import in ObjC) a header, that's like if its content were copied & pasted into the file that includes it. As a reminder, ".h" files are not compiled (they are just included in ".m" files that themselves compile)
So that works exactly the same way as if you were typing the same lines of code you have in your .h in any file that #include it.
This explains why in each of your source files that #include "Constants.h" they each see a different instance of the myImage variable.
Instead you should:
Use the Singleton Pattern, that is specifically made for such cases
Or use the static keyword in an implementation file ("Constants.m") to make this variable sticky inside the compilation unit of this "Constants.m" file
I highly recommand to go with the Singleton Pattern for such cases anyway. More info on Singleton Pattern here in the Apple official DevPedia
You can create a #property (nonatomic, retain) UIImage *image; in your app delegate and in every class you want to use the image you can create AppDelegate *delegate=(AppDelegate *)[[UIApplication sharedApplication] delegate]; and then access to the UIImage from the delegate object like this :
[imageView setImage:[delegate image]];
Or you can use a class like this :
header file
#interface Data : NSObject
#property (nonatomic, strong) UIImage *image;
+ (Data *)sharedInstance;
+ (id)allocWithZone:(NSZone*)zone;
- (id)init;
- (id)copyWithZone:(NSZone *)zone;
#end
implementation file
#implementation Data
#synthesize image;
static Data *sharedInstance=nil;
+ (Data *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}
+ (id)allocWithZone:(NSZone*)zone {
return [self sharedInstance];
}
- (id)init
{
self = [super init];
if (self) {
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
#end
Then, you have to import Data.h in every class you want and then use :
UIImageView *imageView=[[UIImageView alloc] init];
[imageView setImage:[[Data sharedInstance] image]];
This works great for me :)
Use the singleton pattern.
If your code is ARC follow this link http://lukeredpath.co.uk/blog/a-note-on-objective-c-singletons.html
In iPhone the AppDelegate class Acts a Static Class. so you can do the same thing which you have done in Constant.h in the YourAppDelegate Class. But dont use Static Keyword.
I am not very Sure but thinks it will work. :)
You can use UIImage category as example to get this picture.
In your .h file just add your static method.
#import <UIKit/UIKit.h>
#interface UIImage (StaticImage)
+(UIImage *)staticImage;
#end
And in your .m file do following steps:
#import "UIImage+StaticImage.h"
//This is your static image
static UIImage *myStaticImage;
#implementation UIImage (StaticImage)
+(void)initialize{
//Important to add this condition, because this method will be called for every
//child class of UIImage class
if (self == [UIImage class]){
myStaticImage = [[UIImage alloc] init];
}
}
+(UIImage *)staticImage{
//Just return your existing static image
return myStaticImage;
}
#end

How can we limit the capacity of an NSMutableDictionary?

Is there any way to create a mutable dictionary with a capacity limit rather than an initial capacity?
Say you want to create a dictionary that will only ever have, at most, 100 entries.
The capacity argument for the dictionary is an initial capacity that will be simply increased if you add more elements than you want so it's not suitable.
Subclass it and override addObject to check count before adding? No built-in way.
Here is a basic example... not tested, missing init etc, but this is the core. You should also override setValue:forKey: in a similar manner.
#interface MyMutableDictionary: NSMutableDictionary
- (BOOL) setObject:(id)anObject forKey:(id)aKey;
#end
#implementation MyMutableDictionary
- (BOOL) setObject:(id)anObject forKey:(id)key {
if ([self count] < yourLimit) {
[super setObject:anObject forKey:key];
return YES;
}
return NO;
}
#end
There is no API for this, but the code to do so is fairly simple:
void AddObjectToArray(NSMutableArray *array, id obj, NSUInteger maxCount) {
if ([array count] < maxCount)
[array addObject: obj];
}
Note that the above code is not thread-safe, but making it thread safe is about as simple as wrapping the function's contents in a #synchronized (array) directive.
If you want an array that can be bandied about and have this limit built-in, don't subclass the NSMutableArray class cluster. NSMutableArray's contract (the "agreement" it has with calling code) says that a call to -addObject: will add that object to the array, not that it will if the array is under a limit.
Rather, an array with a maximum length behaves differently enough from the standard behaviour that it ought not to be a subclass of NSMutableArray. This may seem like a contrivance--it's an array and you can mutate it, therefore it should be treatable as an NSMutableArray. But calling code has no way to know that its modifications will fail silently on your subclass, and will probably not be designed with such failures in mind.
If the calling code is yours, you can use the helper function defined above--you know the objects might not be added and you can code appropriately. If the calling code comes from elsewhere (e.g. Cocoa or other Apple frameworks), use a normal NSMutableArray, and cull it when the calling code is done adding objects.

iphone NSString Array

I declared
NSString *dayinfield[43];
and fill it in
-(void)DrawDemo {
dayinfield[2] = #"hallo";
dayinfield[3] = #"test";
// also i can read it
NSLog (#"show: %#",dayinfield[2]);
//works fine
}
but when i like to read its content in another function (same class)
-(void)ReadData
{
NSLog (#"show: %#",dayinfield[2]);
// I get random infos or “EXC_BAD_ACCESS
}
How do I initialize the NSString Array correct so I can reach its content in each of my functions??
Thanks
chris
If you only assign literals to the array elements, this should not be a problem. But if you use other strings, you have to retain the instances manually when using a C array.
By the way: Objective-C methods start with a lowercase letter.
This would happen if you never initialized the array (or the parts of it you are accessing) - if you haven't called -DrawDemo before -ReadData or used different indices than the ones posted here, the array would simply contain garbage values.
Try to initialize the array contents to nil or #"" in your initializer method and see if the problem persists.
Alternatively consider using a suitable Cocoa container.
It's memory is probably being released before your second call. Assuming you have declared dayinfield as an ivar (and the fact that you don't get bad access all the time) your string aren't properly retained.
Initialise the strings like this:
dayinfield[2] = [[NSString alloc] initWithString:#"hallo"];
dayinfield[3] = [[NSString alloc] initWithString:#"test"];
and you should release them after you're class is being deallocated (See Memory Management Guide).
Also, obviously it depends on what you want to do, but it might be easier if you use NSArray instead of C arrays.
What you have in the OP should work although it is an exercise in sheer masochism to use old school C arrays with objects.
I ran this code:
#interface TestClass : NSObject {
NSString *a[1];
}
- (void) drawDemo;
- (void) readData;
#end
#implementation TestClass
- (void) drawDemo{
a[0]=#"A Zero";
a[1]=#"A One";
}//------------------------------------- (void) drawDemo------------------------------------
- (void) readData{
NSLog(#"a[0]=%#,a[1]=%#",a[0],a[1]);
}//------------------------------------- (void) readData------------------------------------
#end
TestClass *tc=[[TestClass alloc] init];
[tc drawDemo];
[tc readData];
... and got this output:
a[0]=A Zero,a[1]=A One
Your problem is elsewhere in your code. There is no compelling reason to use C arrays with objects. You gain nothing and you have to watch them like a hawk to prevent errors.

Objective-C: how to allocate array of GLuint

I have an array of GLuint with fixed size:
GLuint textures[10];
Now I need to set a size of array dynamically. I wrote something like this:
*.h:
GLuint *textures;
*.m:
textures = malloc(N * sizeof(GLuint));
where N - needed size.
Then it used like this:
glGenTextures(N, &textures[0]);
// load texture from image
-(GLuint)getTexture:(int)index{
return textures[index];
}
I used the answer from here, but program fell in runtime. How to fix this?
Program is written on Objective-C and uses OpenGL ES.
I figured out this issue.
This code is valid but seems like not working. This problem is described here, but it's not so clear.
The solution that works for me is to create separate class with GLuint property:
#interface Texture : NSObject
GLuint texture;
#end
#property (nonatomic, readwrite) GLuint texture;
Then we can create NSMutableArray of Textures:
NSMutableArray *textures;
In *.m file we should fill our array:
for(int i=0;i<N;i++){
Texture *t = [[Texture alloc] init];
t.texture = i;
GLuint l = t.texture;
[textures addObject:t];
glGenTextures(1, &l);
}
If you use other array(s) with textures you have to shift GLuint indexes, e.g.:
t.texture = i+M;
where M - size of earlier used array of GLuint's.
Then getTexture will be rewritten as following:
-(GLuint)getTexture:(int)index{
return textures[index].texture;
}
I am not excited with this approach but it's a single one I make work.
If you set the value of N to 10, then the behavior of the two methods will be identical. You should therefore look for the reason for the failure in different places.
void glGenTextures( GLsizei n,
GLuint * textures);
accepts an array of unsigned ints, and it looks like you are passing a pointer to the first element in the array, which I think is not what you want to do or what the function accepts
maybe just try
glGenTextures(N, textures);