Abedjoud
Abedjoud

Reputation: 23

iOS Pointer Issue

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

Answers (3)

iDev
iDev

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

Daij-Djan
Daij-Djan

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

Anoop Vaidya
Anoop Vaidya

Reputation: 46543

Why did you put * again, here CompiledImage itself is a pointer.

Simply use Target=CompiledImage;

Upvotes: 0

Related Questions