Why is shouldStartLoadWithRequest only being invoked the first time through? - uiwebview

I'm trying to display a list of web pages the user can switch between in my app. I've done this successfully with documents. however, I don't want the user to be able to navigate from these pages. I found out how to do this by looking it up. The problem is that it only executes on the first page. When I switch to another page shouldStartLoadWithRequest stops working even when I go back to the first page. (This is all done with my specially designed back and forward buttons.) How can I fix this so that it will be invoked every single time and prevent the user from clicking links and navigating away from my set pages? I'm new to objective-c. All the relevant code is below. Some things were declared globally in the .h. Sorry it's kind of rough. I tabbed over only what was needed to make it into code formatting. Thanks!
My .h file:
#import <UIKit/UIKit.h>
#interface learnViewController : UIViewController <UINavigationControllerDelegate>
{
IBOutlet UIWebView *web;
UIButton *backButton;
UIButton *forButton;
}
#end
My .m file
#import "learnViewController.h"
#import "ViewController.h"
static NSString* links[] =
{
#"http://www.nlm.nih.gov/medlineplus/ency/article/000141.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000065.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/001087.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000091.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/007270.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000145.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000093.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000087.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000140.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000132.htm"
};
int numlinks = 10;
int i = 0;
#interface learnViewController ()
#end
#implementation learnViewController
- (void)viewDidLoad
{
[super viewDidLoad];
float viewWidth = self.view.frame.size.width;
float viewHeight = self.view.frame.size.height;
self.view.multipleTouchEnabled = true;
//Background
UIImageView *backgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, viewWidth, viewHeight)];
backgroundView.image = [UIImage imageNamed:#"Background.png"];
[self.view addSubview:backgroundView];
//Show Portal
web = [[UIWebView alloc]initWithFrame:CGRectMake(0.0, viewHeight/34.0, viewWidth, (viewHeight - viewHeight/6.4))];
self->web.delegate = self;
web.scrollView.scrollEnabled = TRUE;
web.scalesPageToFit = TRUE;
[self loadDocument:links[i] inView:web];
[self.view addSubview:web];
//Buttons
UIButton *homeButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth/2.0 - viewWidth/6.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/6.0/2.0), (viewWidth/6.0), (viewWidth/6.0))];
[homeButton
setBackgroundImage:[UIImage imageNamed:#"Home.png"]
forState:UIControlStateNormal];
[homeButton addTarget:self action:#selector(homePressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:homeButton];
backButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth/2.0/3.5 - viewWidth/9.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/9.0/2.0), (viewWidth/9.0), (viewWidth/9.0))];
[backButton
setBackgroundImage:[UIImage imageNamed:#"Back.png"]
forState:UIControlStateNormal];
backButton.enabled = FALSE;
[backButton addTarget:self
action:#selector(backPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:backButton];
forButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth/2.0/3.5*2.0 - viewWidth/9.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/9.0/2.0), (viewWidth/9.0), (viewWidth/9.0))];
[forButton
setBackgroundImage:[UIImage imageNamed:#"Forward.png"]
forState:UIControlStateNormal];
[forButton addTarget:self
action:#selector(forPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:forButton];
UIButton *refButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth - viewWidth/2.0/3.5*2.0 - viewWidth/9.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/9.0/2.0), (viewWidth/9.0), (viewWidth/9.0))];
[refButton
setBackgroundImage:[UIImage imageNamed:#"Scale.png"]
forState:UIControlStateNormal];
[refButton addTarget:self
action:#selector(refPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:refButton];
UIButton *webButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth - viewWidth/2.0/3.5 - viewWidth/9.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/9.0/2.0), (viewWidth/9.0), (viewWidth/9.0))];
[webButton
setBackgroundImage:[UIImage imageNamed:#"Web.png"]
forState:UIControlStateNormal];
[webButton addTarget:self
action:#selector(webPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:webButton];
}
//Button presses
-(void)homePressed:(id)sender
{
ViewController *home = [[ViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:home animated:YES completion:NULL];
}
- (void) refPressed:(id)sender
{
[self loadDocument:links[i] inView:web];
}
-(void)backPressed:(id)sender
{
float viewWidth = self.view.frame.size.width;
float viewHeight = self.view.frame.size.height;
if (i > 0)
{
[web removeFromSuperview];
i--;
web = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, viewHeight/34.0, viewWidth, (viewHeight - viewHeight/6.4))];
[self loadDocument:links[i] inView:web];
web.scrollView.scrollEnabled = TRUE;
web.scalesPageToFit = TRUE;
[self.view addSubview:web];
forButton.enabled = TRUE;
}
if (i == 0)
{
backButton.enabled = FALSE;
}
}
-(void)forPressed:(id)sender
{
float viewWidth = self.view.frame.size.width;
float viewHeight = self.view.frame.size.height;
if (i < numlinks - 1)
{
[web removeFromSuperview];
i++;
web = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, viewHeight/34.0, viewWidth, (viewHeight - viewHeight/6.4))];
[self loadDocument:links[i] inView:web];
web.scrollView.scrollEnabled = TRUE;
web.scalesPageToFit = TRUE;
[self.view addSubview:web];
backButton.enabled = TRUE;
}
if (i == numlinks - 1)
{
forButton.enabled = FALSE;
}
}
-(void)loadDocument:(NSString*)documentName inView:(UIWebView*)webView
{
NSString *url = links[i];
NSURL *nsurl = [NSURL URLWithString:url];
NSURLRequest *nsrequest = [NSURLRequest requestWithURL:nsurl];
[webView loadRequest:nsrequest];
}
-(void)webPressed:(id)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:links[i]]];
}
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSRange range = [urlString rangeOfString:links[i]];
if (range.location != NSNotFound)
{
return YES;
}
else
{
return NO;
}
}
- (void)viewDidUnload
{
[self->web stopLoading];
self->web.delegate = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

Okay, I figured it out through trial and error since no one wanted to help me. I tried looking for answers to similar questions, but nothing actually worked for me. If you're reading this and having the same problem, this is how you fix it. All you have to do is reset the web delegate to nil then back to self as so:
self.webView.delegate = nil;
self.webView.delegate = self;
I don't know why everyone else's code was so complex, and I can only speculate as to why this works. I just got lucky honestly, but I think it maybe clears the cache when you do this, thus making each page fresh to the program. That's what other people were talking about. However, their methods did not work for me either because of my lack of experience or because they do not fit my particular case. This is much simpler and is guaranteed to work as long as you make sure it does this each time you load one of your designated web pages. You're welcome if you're reading this. If anyone would so kindly as to look at my post and explain why this works in better detail, please feel free to do so!

Related

CoreDataTableViewController does not reload on return from segue

I have several CoreDataTableViewControllers that utilize the helper class from Paul Hegarty's course. Everyone of them works except this one, and I cannot see a difference.
When the table first comes up, it is correctly populated and the segue executes properly when a cell is selected. However when I hit the back button, the table displays (null), (null) everywhere.
I have tried every variant of calling [self useDocument] that I can think of, still to no avail. Any thoughts? Thanks in advance.
//
// TeamTableViewController.m
//
#import "TeamTableViewController.h"
#import "iTrackAppDelegate.h"
#import "CoreDataTableViewController.h"
#import "SchoolRecords.h"
#import "ScheduleViewController.h"
#interface TeamTableViewController ()
#property NSInteger toggle;
#end
#implementation TeamTableViewController
#synthesize iTrackContext = _iTrackContext;
#synthesize schoolSelected = _schoolSelected;
-(void) setSchoolSelected:(SchoolRecords *)schoolSelected
{
_schoolSelected = schoolSelected;
}
-(void) setITrackContext:(NSManagedObjectContext *)iTrackContext
{
if(_iTrackContext != iTrackContext){
if (!iTrackContext) {
MyCoreDataHandler* cdh =
[(iTrackAppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
_iTrackContext = cdh.context;
} else {
_iTrackContext = iTrackContext;
}
}
[self useDocument];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)setupFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"SchoolRecords"];
// no predicate because we want ALL the Athletes
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"schoolName" ascending:YES],
nil];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.iTrackContext
sectionNameKeyPath:nil
cacheName:nil];
__block NSInteger myCount;
int64_t delayInSeconds = 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.iTrackContext performBlock:^(void){NSError* requestError = nil;
myCount = [self.iTrackContext countForFetchRequest:request error:&requestError];
NSLog(#"In %# and count of iTrackContext = %lu", NSStringFromClass([self class]),(unsigned long)myCount);
}];
if (!myCount || myCount == 0) {
[self displayAlertBoxWithTitle:#"No Teams" message:#"Have you added athletes yet? \nPlease go to Add Athletes" cancelButton:#"Okay"];
}
});
}
- (void)useDocument
{
if (self.iTrackContext) {
[self setupFetchedResultsController];
} else {
NSString* errorText = #"A problem arose opening the search results database of Athletes.";
[self displayAlertBoxWithTitle:#"File Error" message:errorText cancelButton:#"Okay"];
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.iTrackContext) {
MyCoreDataHandler* cdh =
[(iTrackAppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
[self setITrackContext:cdh.context];
} else {
NSLog(#"In %# of %#. Getting ready to call useDocument",NSStringFromSelector(_cmd), self.class);
[self useDocument];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// If divide into sections use line below otherwise return 1.
// return [[self.fetchedResultsController sections] count];
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Do not really need this with only one section, but makes code usable if add sections later.
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"teamInformation";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
SchoolRecords *schoolResults = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString* titleText = schoolResults.schoolName;
cell.textLabel.text = titleText;
cell.detailTextLabel.text = [NSMutableString stringWithFormat:#"%#, %#", schoolResults.schoolCity, schoolResults.schoolState];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
# pragma navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
[self setSchoolSelected:[self.fetchedResultsController objectAtIndexPath:indexPath]];
// be somewhat generic here (slightly advanced usage)
// we'll segue to ANY view controller that has a photographer #property
if ([segue.identifier isEqualToString:#"scheduleDetailSegue"]) {
// use performSelector:withObject: to send without compiler checking
// (which is acceptable here because we used introspection to be sure this is okay)
NSLog(#"Preparing to passing school with schoolID = %#", self.schoolSelected.schoolID);
[segue.destinationViewController convenienceMethodForSettingSchool:self.schoolSelected];
}
}
- (void) displayAlertBoxWithTitle:(NSString*)title message:(NSString*) myMessage cancelButton:(NSString*) cancelText
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:myMessage
delegate:nil
cancelButtonTitle:cancelText
otherButtonTitles:nil];
[alert show];
}
#end
Well, I am not certain what the problem was. I ended up deleting the "offending" TableViewControllers in StoryBoard and recreated them. That did the trick. In retrospect, I wonder if I did not specify the wrong type of segue from my tabViewController. But I deleted it before I thought of that possibility.

Mail composer didn't display under my UIWebView

I have a MainController and detailedcontroller. When I popover the Book selection and select a Book, the detailcontroller display an UIWebView with the book articles :
#interface IpadBooksViewController : UITableViewController {
SearchResult *searchResult;
IpadArticleViewController *detailController;
IpadMainViewController *mainController;
UIPopoverController *popover;
}
Into the UIWebView, I display an Email icon and catch the scheme :
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSURL *url = [request URL];
NSString *scheme = [url scheme];
NSString *host = [url host];
if ([[url description] hasSuffix:#"next"]) {
NSLog(#"next Show");
}
BOOL isShareLinks = [host isEqualToString:#"displayShareLinks"];
BOOL isFavoriteLinks = [host isEqualToString:#"displayFavoriteLinks"];
if ([#"myappurl" isEqualToString:scheme] && (isShareLinks || isFavoriteLinks)) {
self.selectedArticleNumber = [url.path lastPathComponent];
if (isShareLinks) {
[self sendMailArticleNumber:selectedArticleNumber];
} else if (isFavoriteLinks) {
NSLog(#"ipad favorite clicked");
[self toggleFavorite:selectedArticleNumber];
Broker *broker = [[Broker alloc] init];
[broker loadProjects:self];
[broker release];
}
}
return [super webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
}
Action is supposed to display the MFMailController under my UIWebView, but nothing is displayed without error message :
- (void) sendMailArticleNumber:(NSString *)articleNumber {
MFMailComposeViewController* composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = self;
[composer setSubject:#"Article"];
NSString *messageBody = [Article fetchBody:articleNumber bookId:bookId];
[composer setMessageBody:messageBody isHTML:YES];
[self presentModalViewController:composer animated:YES];
[composer release];
}
Any help will be welcomed. I did try creating a popover, addView atIndex without success ... Let me know if you need more code.
David
I did solve the issue by loading the controller into the delegate as following :
[((PublilexAppDelegate*)[[UIApplication sharedApplication] delegate]) sendMailArticleNumber:selectedArticleNumber bookId:self.bookId];
And then into the Delegate :
- (void) sendMailArticleNumber:(NSString *)articleNumber bookId:(NSString*)bookId {
MFMailComposeViewController* composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = self;
[composer setSubject:#"Article"];
NSString *messageBody = [Article fetchBody:articleNumber bookId:bookId];
[composer setMessageBody:messageBody isHTML:YES];
[self->navigationController presentModalViewController:composer animated:YES];
[composer release];
}
And to dismiss and comeback to the previous view :
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self->navigationController dismissModalViewControllerAnimated:YES];
// [self dismissViewControllerAnimated:YES completion:nil];
// [((PublilexAppDelegate*)[[UIApplication sharedApplication] delegate]) navigateToIpadMain];
}

mkannotation automatic/default callout not happening

i added an annotation and in viewforannotation i set canshowcallout and selected the annotation as well but it aint getting selected...
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
currentCoordinates = newLocation.coordinate;
ParkPlaceMark *pa = [[ParkPlaceMark alloc] init];
pa.coordinate = currentCoordinates;
pa.title = #"POI";
pa.title2 = #"CUrrent Locn";
pa.subtitle = #"Drag and drop to adjust the position if necessary";
[mapView addAnnotation:pa];
[pa release];
}
- (MKAnnotationView *)mapView:(MKMapView *)map
viewForAnnotation:(ParkPlaceMark*)annotation {
MKAnnotationView *test=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"parkingloc"];
if([annotation.title caseInsensitiveCompare:#"POI"] == NSOrderedSame)
{
test.annotation = annotation;
test.userInteractionEnabled = YES;
test.draggable = YES;
// test.pinColor = MKPinAnnotationColorRed;
[test setImage:[UIImage imageNamed:#"marker3.png"]];
[test setEnabled:YES];
[test setCanShowCallout:YES];
[test setDragState:MKAnnotationViewDragStateEnding animated:YES];
[self.mapView selectAnnotation:test.annotation animated:YES];
return test;
}
}
I had added custom animation so
[self.mapView selectAnnotation:test.annotation animated:YES];
was not working . The correct code is :
[self.mapView selectAnnotation:test.annotation animated:NO];

Proper release of UIImagePickerController

I'm a bit confused with this as I've seen way too many different variants and not sure which one is the correct way. Currently I have:
- (IBAction)pickImageFromLibrary:(id)sender
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:picker animated:YES];
// [picker release];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0.0f, 10.0f, 320.0f, 264.0f)];
self.studyView = imageView;
[imageView release];
[self.tableView setTableHeaderView:studyView];
self.fitImage = [ImageHelper image:image fitInView:studyView];
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera)
{
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
studyView.image = self.fitImage;
[self dismissModalViewControllerAnimated:YES];
[picker release];
}
I'm allocating the UIImagePickerController in the first method but wouldn't it be logical to only release it in the 2nd method when I dismiss it?
No, because it's retained when presented modally, via presentModelViewController. This is the common pattern you'll find when presenting new view controllers, whether modally, custom view controllers or not. This is fine:
- (IBAction)pickImageFromLibrary:(id)sender
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:picker animated:YES];
[picker release];
}

CoverFlow multiple Views

Good Morning at all,
i have a big problem in the following code and no solution, so i hope someone could
help me:
- (IBAction)goToChart {
[rootViewController switchViews];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *weiter = [UIButton buttonWithType:UIButtonTypeRoundedRect];
weiter.frame = CGRectMake(100, 400, 120, 40);
[weiter addTarget:self action:#selector(goToChart) forControlEvents:UIControlEventTouchUpInside];
NSString *ansicht = #"Weiter";
[weiter setTitle:ansicht forState:UIControlStateNormal];
[self.view addSubview:weiter];
// loading images into the queue
loadImagesOperationQueue = [[NSOperationQueue alloc] init];
NSString *imageName;
for (int i=0; i < 10; i++) {
imageName = [[NSString alloc] initWithFormat:#"cover_%d.jpg", i];
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
UIImage *aktuellesImage = imageView.image;
UIImage *scaledImage = [aktuellesImage scaleToSize:CGSizeMake(100.0f, 100.0f)];
[(AFOpenFlowView *)self.view setImage:scaledImage forIndex:i];
[imageName release];
NSLog(#"%d is the index",i);
}
[(AFOpenFlowView *)self.view setNumberOfImages:10];
}
So you can see there 10 Images in this CoverFlowView, but how could i find out the ACTUAL picture that is in front, to use this in another view??
Could someone help me, please?
Greetings Marco
-(void)openFlowView: (AFOpenFlowView *)openFlowView imageSelected:(int)index
{
AppDelegate_iPhone *appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication]delegate];
db_detail = (DB_data *)[self.GalleryArray objectAtIndex:index];
appDelegate.Id = db_detail.Id;
// NSLog(#"id: value is %d",db_detail.Id);
// NSLog(#"Name vlaue is: %#",db_detail.Name);
appDelegate.title = db_detail.Name;
DetailMovieViewController *ViewController = [[DetailMovieViewController alloc]init];
[self.navigationController pushViewController:ViewController animated:YES ];
[ViewController release];
[db_detail release];
}

Resources