UIWebView calling custom method? - iphone

I am having trouble in calling a method that I defined screenCap by a UIWebView. Basically, I have two UIWebView declared: firstWebView and secondWebView.
I ran a javascript to extract some HTML loaded by the firstWebView and display it to the secondWebView by calling [secondWebView loadHTMLString: extractString baseURL:nil];
What I want to do is after secondWebView is loaded, I want to call
[secondWebView screenCap: self];
The screenCap method is defined by:
-(void) screenCap: (UIWebView *)webView; {
UIGraphicsBeginImageContext(webView.frame.size);
[webView.layer renderInContext: UIGraphicsGetCurrentContext()];
viewImage; = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
theImageView.image = viewImage;
NSLog(#"write Image done!");
I, however got a warning "UIWebView may not respond to '-screenCap' and of course the screenCap never got called. can anyone direct me how to fix this problem?

There's nothing wrong in the code of the ScreenCap method.
But instead of doing
[secondWebView screenCap: self];
write
[self screenCap:secondWebView];

Related

Error 133000 when using multiple contexts with core data

I've spent days trying every possible solution I can think of to this problem, but nothing seems to be working.
I run a background thread like this:
[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {
Media *localMedia = [media inContext:localContext];
UIImage *image = localMedia.thumbnail;
dispatch_async(dispatch_get_main_queue(), ^{
[thumbnails setObject:image forKey:[NSNumber numberWithInt:i]];
[contentDict setObject:thumbnails forKey:#"MediaItems"];
[cell.entryView setNeedsDisplay];
});
}];
Or like this:
dispatch_queue_t cellSetupQueue = dispatch_queue_create("com.Journalized.SetupTimelineThumbnails", NULL);
dispatch_async(cellSetupQueue, ^{
NSManagedObjectContext *newMoc = [[NSManagedObjectContext alloc] init];
NSPersistentStoreCoordinator *coordinator = [NSManagedObjectContext contextForCurrentThread].persistentStoreCoordinator;
[newMoc setPersistentStoreCoordinator:coordinator];
NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];
[notify addObserver:self
selector:#selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:newMoc];
Media *localMedia = [media inContext:[NSManagedObjectContext contextForCurrentThread];
UIImage *image = localMedia.thumbnail;
dispatch_async(dispatch_get_main_queue(), ^{
[thumbnails setObject:image forKey:[NSNumber numberWithInt:i]];
[contentDict setObject:thumbnails forKey:#"MediaItems"];
[cell.entryView setNeedsDisplay];
});
}];
Both of these give me a crash with UIImage returning as nil object, and a Cocoa Error 133000.
I've removed every other piece of background threading code, and have saved on the main thread directly before this just to make sure. Running the code above on the main thread also works, but freezes up my UI. Despite all of these efforts, the above code crashes every time.
I'm not sure what to do to make this work.
Edit:
My question, specifically, is how do I make this work without crashing? It seems to be a problem with objects from 1 context not existing in another, but how do i make them exist in another context?
Remember, the MR_inContext: method is using [NSManagedObjectContext objectWithID: ] method under the covers. You should look in there to make sure your object has:
1) Been saved prior to entering into the background context/block in your first code block
2) This method is returning something useful
I'm also not sure how you set up your thumbnail attribute. Ideally it shouldn't matter as long as you have the NSTransformable code write (there are samples on the internets that show you how to save a UIImage in core data using the transformable attribute)
Also, your code should look like this:
UIImage *image = nil;
[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {
Media *localMedia = [media inContext:localContext]; //remember, this looks up an existing object. If your context is a child of a parent context that has contains this, the localContext should refresh the object from the parent.
//image processing/etc
image = localMedia.thumbnail;
} completion:^{
[thumbnails setObject:image forKey:#(i)]; //new literals are teh awesome
contentInfo[#"MediaItems"] = thumbnails; //as is the new indexer syntax (on the latest compiler)
[cell.entryView setNeedsDisplay];
}];
Fast answer:
NSManagedObjectReferentialIntegrityError = 133000,
// attempt to fire a fault pointing to an object that does not exist (we can see the store, we can't see the object)
EDIT:
It's pretty difficult to see something from the code. What is a managed object there?
I suppose the problem is that you are using temporary objects from one context in another context.

Getting an image from a remote server

In my iPhone app I have to show the preview of the thumbnail image. That preview image actually we will get from remote server. Before loading that big image on screen I have to show preloading view but actually this preloading view is not appearing on the screen.
The code I used is:
zoomview=[[UIView alloc]initWithFrame:CGRectMake(0,0,320,460)];
imageloadview.backgroundColor=[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
[self.view addSubview:imageloadview];
[activity startAnimating];
[self loadimageview];
Here instead of loading the zoom view on screen this loading view method is executing but I want to display preloading view before getting the big image from the server.
-(void)loadimageview
{
imageloader.image=[UIImage imageNamed:#""];
[self loadimage];
}
-(void)loadimage
{
NSData *data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[picfullarray objectAtIndex:0]]];
if([data length]==0)
{
NSLog(#"data");
}
else
{
UIImage *image1=[UIImage imageWithData:data];
imageloader.image=image1;
[activity stopAnimating];
[loadlabel1 setText:#""];
}
}
How do I show preloaded view on iPhone screen before getting the big image from the server?
You have to load the image asynchronously with NSURLRequest.
Make the class implement NSURLRequestDelegate protocol. In the function - (void)connectionDidFinishLoading:(NSURLConnection *)connection of NSURLRequestDelegate, add the code to update the view when the loading is completed.
// You must declare NSMutableData somewhere to write received data in delegate method
// - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
// I assume the instance of NSMutableData is named data
// If you want to load multiple images, it is a bit tricky, but doable.
// I'll post the code if that is what you need.
- (void) connectionDidFinishLoading: (NSURLConnection *) connection {
// You may want to declare a instance member to store the image (UIImage*), so that you can restore the view if the view is unloaded due to memory warning.
UIImage* image = [UIImage imageWithData: data];
data = nil; // Important. You should clean the data, or it will take up space.
// You may want to check whether image != nil, since the incoming data may not be image
[self displayImage: image];
}
- (void) displayImage: (UIImage*) aImage {
imageloader.image = aImage;
// Depending on how UIImageView is initialized, you may need to call sizeToFit.
// Or set the frame accordingly
[activity stopAnimating];
[loadlabel1 setText: #""];
}
I'd suggest using SDWebImage framework. It already has async image loading capability, and it's super easy to use.
[imageView.image setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
You don't have to worry about messing with NSURLConnection, maintaining NSData, etc..
There is also AFNetworking which has a way to do this easily.
https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking
Check out the "Download and Display Images" section.

Application crashing in the imagePickerController:didFinishPickingMediaWithInfo method inside UIImagePickerController

I am a beginner in iOS development, I tried to make an application to select an image from the UIImagePickerController which is displayed inside a UIImageView object. The problem I am facing is inside this method
-(void)imagePickerController:(UIImagePickerController*)Picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
NSLog(#"Inside dismiss modal view delegate 2");
UIImage * image = [info objectForKey:UIImagePickerControllerOriginalImage];
selectedImage.image = [image retain];
NSLog(#"Inside the did pickerController method");
}
When I select an image from the UIImagePickerController, the image gets selected but the application crashes. I tried debugging, and the first NSLog statement gets displayed on the console, but the 2nd one does not get displayed.
I am trying to load an image from the Photos library inside the simulator. I am using XCode 3.2.5 and the simulator is 4.2. This might men the error is there in between the two NSLog statements. But, I have tried my best to find out the error, but without any success. Can you please help me out.
NSData *dataImage = UIImageJPEGRepresentation([info objectForKey:#"UIImagePickerControllerOriginalImage"],1);
imgPicture.image = [[UIImage alloc] initWithData:dataImage];
[picker dismissModalViewControllerAnimated:YES];
Put this code in method

Objective C: EXC_BAD_ACCESS when generating a UIImage

I have a view that generates an image based on a series of layers. I have images for the background, for the thumbnail, and finally for an overlay. Together, it makes one cohesive display.
It seems to work a dream, except for when it doesn't. For seemingly no reason, I get an EXC_BAD_ACCESS on the specified line below after it's generated somewhere between 8 and 20 images. I've run it through the memory leak tool and allocation tool, and it's not eating up tons of memory and it's not leaking. I'm totally stumped.
Here's the relevant code:
- (UIImage *)addLayer:(UIImage *)layer toImage:(UIImage *)background atPoint:(CGPoint)point {
CGSize size = CGSizeMake(240, 240);
UIGraphicsBeginImageContext(size);
[background drawAtPoint:CGPointMake(0, 0)]; // <--- error here
[layer drawAtPoint:point];
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
// Build the layered image -- thingPage onto thingBackground,
// then the screenshot on that, then the thingTop on top of it all.
// thingBackground, thingPage and thingTop are all preloaded UIImages.
-(UIImage *)getImageForThing:(Thing *)t {
[self loadImageCacheIfNecessary];
if (!t.screenshot) {
return [UIImage imageNamed:#"NoPreview.png"];
} else {
UIImage *screenshot = t.screenshot;
UIImage *currentImage = [self addLayer:thingPage toImage:thingBackground atPoint:CGPointMake(0, 0)];
currentImage = [self addLayer:screenshot toImage:currentImage atPoint:CGPointMake(39, 59)];
currentImage = [self addLayer:thingTop toImage:currentImage atPoint:CGPointMake(0, 1)];
return currentImage;
}
}
I can't find anywhere that this is going wrong, and I've been tearing my hair out for a couple of hours on this. It's the final known bug in the system, so you can imagine how antsy I am to fix it! :-)
Thanks in advance for any help.
As to me, I always use -(void)drawInRect: instead of -(void)drawAtPoint:
CGRect rtDraw;
rtDraw.origin = CGPointZero;
rtDraw.size = size;
[background drawInRect:rtDraw];
[layer drawInRect:rtDraw];
And ....
The paint method with UIGraphicsBeginImageContext(size) and UIGraphicsEndImageContext() is not thread-safe.
Those functions will push or pop a context with stack struct, which is managed by system.
EXC_BAD_ACCESS is almost always due to accessing an object that has already been released. In your code this seems to be t.screenshot. Check creation (and retaining if it is an instance variable) of the object returned by Thing's screenshot property.
As it turns out, the error wasn't in the code I posted, it was in my caching of the thingBackground, thingPage and thingTop images. I wasn't retaining them. Here's the missing code, fixed:
-(void)loadImageCacheIfNecessary {
if (!folderBackground) {
thingBackground = [[UIImage imageNamed:#"ThingBack.png"] retain];
}
if (!folderPage) {
thingPage = [[UIImage imageNamed:#"ThingPage.png"] retain];
}
if (!folderTop) {
thingTop = [[UIImage imageNamed:#"ThingTop.png"] retain];
}
}
I will admit I'm still not comfortable with the whole retain/release/autorelease stuff in Objective C. Hopefully it'll sink in one day soon. :-)

Replacing a calloutaccessoryview in mkannotationview

In my viewForAnnotation delegate, I create a MKAnnotationView with leftCalloutaccessory as a info button. When the info button is tapped, I want to replace it with a UIActivityIndicator. So in the calloutAccessoryTapped delegate, I wrote
view.leftCalloutaccessoryView = [UIActivityIndicator indicatorWithStyle:UIActivityIndicatorWhite];
The callout accessory seems to change, but it seems like the view doesn't get updated immediately.
That's when the callout accessory gets hidden (by tapping another pin) and is re-opened, I see a spinner. But otherwise, I don't.
I tried calling [view setNeedsdisplay] and [view setNeedsLayout] and [view layoutsubviews] as well but in vain.
Any suggestions/pointers?
I would consider removing and re-adding your annotation. It seems a little heavy handed, but might work.
I was having a similar problem -- I needed to display an image for the leftCalloutAccessoryView if there was one associated with the annotation. Try setting it in mapView:didSelectAnnotationView instead of in mapView:viewForAnnotation
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)annotView
{
...
if(imgURL.length>1){
// set a thread that will load the image
// but don't set the leftCalloutAccessoryView until the image is loaded
dispatch_queue_t downloader = dispatch_queue_create("annotation image downloader",NULL);
dispatch_async(downloader, ^{
NSURL* photoURL = [NSURL URLWithString:imgURL];
NSData* photoData = [NSData dataWithContentsOfURL:photoURL];
UIImage* photoImage = [UIImage imageWithData:photoData];
dispatch_async(dispatch_get_main_queue(), ^{
annotView.leftCalloutAccessoryView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
[(UIImageView *) annotView.leftCalloutAccessoryView setImage:photoImage];
});
});
}
}