Reputation: 23
I seem to have a pointer problem and I can't seem o fix it. Could someone help me, please?
-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"Finished Downloading Image: %@" ,[connection.originalRequest.URL absoluteString]);
UIImage *CompiledImage=[UIImage imageWithData:ImageData];
SEL selector=@selector(ImageDownloadingCompleted:Image:);
if([[self Delegate] respondsToSelector:selector]){
[[self Delegate] ImageDownloadingCompleted:self Image:CompiledImage];
}
else{
if(Target){
*Target=CompiledImage;
}
}
// NSLog(@"Image Size:%i", [ImageData length]);
}
Target
is a private variable of type UIImage
(declared: UIImage *Target;
)
CompiledImage
is a UIImage
as well. What I want to do is set the contents of the address of target to be the Contents of CompiledTarget. This results in the following error:
Assigning to 'UIImage' from incompatible type 'UIImage *__strong'
I tried :
memccpy(__bridge Target, &CompiledImage, sizeof(Target),sizeof(Target));
and I get this error:
Expected expression
Upvotes: 2
Views: 417
Reputation: 23278
You need to just set it as,
Target = CompiledImage;
No need of *
. Since both are pointers basically you are assigning the memory address and not copying the contents if you use the above code.
On a side note, please start variable names with lowercase letters. Target
normally represents a class name. As per apple coding conventions, it should be target
.
As per your comment, you can do the following,
In ViewController class, declare a UIImage
as @property
,
@property (nonatomic, retain) UIImage *downloadedImage;
While doing URL call,
NSImageLoader *imageLoader = [[NSImageLoader alloc] init];
[imageLoader setTarget:self];//setting current viewController as target instead of UIImage
When image is downloaded,
-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"Finished Downloading Image: %@" ,[connection.originalRequest.URL absoluteString]);
UIImage *CompiledImage=[UIImage imageWithData:ImageData];
SEL selector=@selector(ImageDownloadingCompleted:Image:);
if([[self Delegate] respondsToSelector:selector]){
[[self Delegate] ImageDownloadingCompleted:self Image:CompiledImage];
}
else{
if(Target){
Target.downloadedImage = CompiledImage;//or [Target setDownloadedImage:CompiledImage];
}
}
// NSLog(@"Image Size:%i", [ImageData length]);
}
In your ViewController class, now you can access image as, self.downloadedImage
which will have same as in CompiledImage
with same memory address pointing to the same location.
An alternative way is to declare UIImage *Target
as UIImage **Target
in your NSImageLoader
class. And while calling setTarget
method, use [imageLoader setTarget:&Target];
. Inside this method you need to set target as Target = Target;
Update: Based on your comments it should be like this,
for( NSDictionary *CurrentActivity in [Profile UserActivities]) {
...
UIImage *WineImage = [UIImage imageNamed:@"loader.gif"];
NSImageLoader *loader=[[NSImageLoader alloc] initWithURLString:[NSString stringWithFormat:@"%@%@",[TempSettings URL],[CurrentActivity objectForKey:@"ImageURL"]]];
[loader setTarget:&WineImage];
[loader startDownloading];
[self addSubview:Activity];
Counter++;
}
Then in NSImageLoader.h file @interface,
__strong UIImage **Target; //This should be strong not autoreleasing
In NSImageLoader.m file,
- (void)setTarget:(UIImage *__strong *)iTarget{ //change here also
Target = target;
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"Finished Downloading Image: %@" ,[connection.originalRequest.URL absoluteString]);
UIImage *CompiledImage=[UIImage imageWithData:ImageData];
SEL selector=@selector(ImageDownloadingCompleted:Image:);
if([[self Delegate] respondsToSelector:selector]){
[[self Delegate] ImageDownloadingCompleted:self Image:CompiledImage];
}
else{
if(Target){
*Target = CompiledImage;
}
}
// NSLog(@"Image Size:%i", [ImageData length]);
}
Update2:
Using the approach of passing UIImageView, you can do the following,
for( NSDictionary *CurrentActivity in [Profile UserActivities]) {
...
UIImage *WineImage = [UIImage imageNamed:@"loader.gif"];
NSImageLoader *loader=[[NSImageLoader alloc] initWithURLString:[NSString stringWithFormat:@"%@%@",[TempSettings URL],[CurrentActivity objectForKey:@"ImageURL"]]];
[loader setTarget:Activity];//pass imageview and let the delegate method set image
[loader startDownloading];
[self addSubview:Activity];
Counter++;
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"Finished Downloading Image: %@" ,[connection.originalRequest.URL absoluteString]);
UIImage *CompiledImage=[UIImage imageWithData:ImageData];
SEL selector=@selector(ImageDownloadingCompleted:Image:);
if([[self Delegate] respondsToSelector:selector]){
[[self Delegate] ImageDownloadingCompleted:self Image:CompiledImage];
}
else{
if(Target){
Target.image = CompiledImage;
}
}
// NSLog(@"Image Size:%i", [ImageData length]);
}
Here pass imageview and let the delegate method set image in that once you have downloaded the image.
Upvotes: 5
Reputation: 50089
Make Target is pTarget? a pointer to a pointer then it makes sense
*pTarget = compiledImage
(as it is done with NSErrors often .. e.g. in core data)
you cant just memcpy the stuff since target has not the correct size allocated on the heap.
you cant Copy the real UIImage bytes in the memory because that isnt known to you and an implementation detail. you dont even know how big it is!
BUT you can copy the pointer to the image -- its memory address
UIImage *pointer1 = [UIImage imageWithFoo];
UUImage *pointer2 = pointer1;
now you can also declare an empty pointer and fill it later
UIImage *target = nil;
UIImage *pointer1 = [UIImage imageWithFoo];
target = pointer1;
so far so good but what if you want to PASS target to a function and THAT should fill it?
target = [self calculateImage];
but now you have it in asynchronous function
[self asyncCalculateImage:&target]; // you pass it a POINTER to the POINTER to fill :)
...
- (void)asyncCalculateImage:(UIImage**)pTarget {
UIImage *pointer1 = [UIImage imageWithFoo];
*pTarget = pointer1; //DEREFERENCE and fill pTarget
}
Upvotes: 1
Reputation: 46543
Why did you put * again, here CompiledImage itself is a pointer.
Simply use Target=CompiledImage;
Upvotes: 0