I need to create a rich text editor (for text alignment, fonts, bold, italics, underlining etc) for an iPhone app. I have heard of storing the data as HTML and rendering it in a UIWebView. I want to allow the user to edit the data and in my app I am using TapDetectingWindow to detect touches on a UIWebView (exactly as detailed here).
- (id)init {
self = [super init];
if (self) {
tapDetectingWindow = (TapDetectingWindow *)[[UIApplication sharedApplication].windows objectAtIndex:0]; //mWindow, variable reference to TapDetectingWindow
tapDetectingWindow.viewToObserve = webView;
tapDetectingWindow.controllerThatObserves = self;
webView = [[UIWebView alloc] init];
[webView setFrame:CGRectMake(0, 0, 340, 1900)];
[webView setTag:1];
[webView addSubview:keyboardText];
[webView setDelegate:self];
[webView setOpaque:0.0];
[webView loadHTMLString:htmlString baseURL:NULL];
[self.view addSubview:webView];
keyboardText = [[UITextField alloc] init];
keyboardText.autocorrectionType = UITextAutocorrectionTypeNo;
[keyboardText setDelegate:self];
[self.view addSubview:keyboardText];
}
return self;
}
But my app is crashing, with the message
tapDetectingWindow.viewToObserve = webView
and a report
* -[UIWindow setViewToObserve:]: unrecognized selector sent to instance 0x4a26b90
After a few hours of hair pulling, here's the answer: you need to edit your AppDelegate's .m file to get the TapDetectingWindow to work properly:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIViewController* vc = self.window.rootViewController;
self.window = [[TapDetectingWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = vc;
return YES;
}
I tried this and it's working perfectly with the rest of the TapDetectingWindow tutorial!
Related
Currently working on two introduction pages (First shows an image, second should show a website) for my iPhone app (like Pocket, for the user a little hands-on after first start).
Came across Matthew York's GitHub project which works perfectly with images and text.
Additionally I like to show a website as a part of the introduction but I can't get it working. My programmatically created UIWebView just doesn't show up.
Matthew York's GitHub Project:
https://github.com/MatthewYork/iPhone-IntroductionTutorial
Complete code for showing the two introduction pages is shown below.
Please mind that panelImage works as expected but not panelView.
I see the second page show up but without the UIWebView.
I think I add the subview to a view not visible on the screen therefore I don't see it. Am I right? Can you please have a look at: [view addSubview:aWebView]; in method: showWebView
ViewController.m
- (void)showIntro
{
MYIntroductionPanel *panelImage = [[MYIntroductionPanel alloc] initWithimage:[UIImage imageNamed:#"img.jpg"] description:#"TEST: IMAGE"];
MYIntroductionPanel *panelView = [[MYIntroductionPanel alloc] initWitView:[self showWebView] description:#"TEST: VIEW"];
MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) headerText:#"TESTING" panels:#[panelImage, panelView] languageDirection:MYLanguageDirectionLeftToRight];
introductionView.BackgroundImageView.image = [UIImage imageNamed:#"BG_iPad_1024.png"];
introductionView.delegate = self;
[introductionView showInView:self.view];
}
- (UIView *)showWebView
{
UIWebView *aWebView= [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 290)];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"]];
[aWebView loadRequest:requestObj];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 300)];
[view addSubview:aWebView];
return view;
}
MYIntroductionPanel.m
-(id)initWitView:(UIView *)view description:(NSString *)description{
if (self = [super init]) {
self.view = [[UIView alloc] init];
self.Description = [[NSString alloc] initWithString:description];
}
return self;
}
-(id)initWithimage:(UIImage *)image title:(NSString *)title description:(NSString *)description{
if (self = [super init]) {
self.Image = [[UIImage alloc] init];
self.Image = image;
self.Title = title;
self.Description = [[NSString alloc] initWithString:description];
}
return self;
}
The view to which you are adding your UIWebView is never added to the view hierarchy itself. You appear to be passing the UIWebView's superview to MyIntroductionPanel's initWithView:description: method, but that method just ignores its input view and creates a new one with self.view = [[UIView alloc] init]. Try setting self.view = view in your initWithView:description: method instead.
I didn't love all of the author's decisions, but followed his pattern to achieve what you're looking for.
Added the following:
// MyIntroductionPanel.h
#property (nonatomic, retain) NSURL *url;
-(id)initWithURL:(NSURL *)url;
// MyIntroductionPanel.m
-(id)initWithURL:(NSURL *)url {
if (self = [super init]) {
_url = url;
}
return self;
}
That was easy. This was less easy - hacking the layout method to deal with panels with urls. I didn't try too hard to understand this method, just added what I could to get it working. My additions are marked with // DANH
// MYIntroductionView.m
-(UIView *)PanelViewForPanel:(MYIntroductionPanel *)panel atXIndex:(CGFloat*)xIndex{
// snipped original code
NSInteger descriptionHeight = panelDescriptionTextView.contentSize.height;
int contentWrappedScrollViewHeight = 0;
if ((imageHeight + descriptionHeight + panelTitleLabelFrame.size.height) > maxScrollViewHeight) {
contentWrappedScrollViewHeight = maxScrollViewHeight;
imageHeight = contentWrappedScrollViewHeight-descriptionHeight - panelTitleLabelFrame.size.height - 10;
}
else if ((imageHeight+descriptionHeight + panelTitleLabelFrame.size.height) <= maxScrollViewHeight){
contentWrappedScrollViewHeight = imageHeight + panelTitleLabelFrame.size.height + descriptionHeight;
}
// DANH
if (panel.url) {
contentWrappedScrollViewHeight = 300;
// you can certainly do a better job than I did here, but just to get going
}
panelView.frame = CGRectMake(*xIndex, 0, self.ContentScrollView.frame.size.width, contentWrappedScrollViewHeight);
//Build image container
UIImageView *panelImageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, 0, self.ContentScrollView.frame.size.width - 10, imageHeight)];
panelImageView.contentMode = UIViewContentModeScaleAspectFit;
panelImageView.backgroundColor = [UIColor clearColor];
panelImageView.image = panel.Image;
panelImageView.layer.cornerRadius = 3;
panelImageView.clipsToBounds = YES;
[panelView addSubview:panelImageView];
// DANH
// add webview on top if we have a url
if (panel.url) {
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.ContentScrollView.frame.size.width, 300)];
[webView loadRequest:[NSURLRequest requestWithURL:panel.url]];
[panelView addSubview:webView];
}
// snipped original code
}
Now, to call it with example code....
// MYViewController.m
MYIntroductionPanel *panel3 = [[MYIntroductionPanel alloc] initWithURL:[NSURL URLWithString:#"http://www.google.com"]];
// ...
MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) headerText:#"MYIntroductionView" panels:#[panel, panel2, panel3] languageDirection:MYLanguageDirectionLeftToRight];
I have an application which is bascially a TabBar where the tabs are UINavigationControllers which move back and forth between different ViewControllers containing UIWebViews. My problem is that although I can click on the buttons for the UIWebViews, I can't scroll the content when it is larger than the screen.
Am creating the TabController
tabBarController = [[MainTabBarController alloc] init];
[tabBarController setDelegate:self];
When switching between tabs, I have this code:
WebViewController *wvc = [[WebViewController alloc] initWithNibName:#"WebController" bundle:nil];
UIWebView *wv = [[UIWebView alloc] init];
[wv setUserInteractionEnabled:YES];
[wvc setTitle:[nc title]];
[wv setDelegate:self];
[wv loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:requestURL]]];
[wvc setWebpage:wv];
[wvc setView:wv];
[nc pushViewController:wvc animated:NO];
NSLog(#"NC.viewcontroller count: %d", [nc.viewControllers count]);
[nc setLastURL:requestURL];
[wvc startLoaderIndicator];
[wv release];
[wvc release];
requestOk = YES;
And when a link within one of the UIWebViews is clicked, I have this:
ItemNavigationController *nc = (ItemNavigationController *)[tabBarController selectedViewController];
WebViewController *wvc = [[WebViewController alloc] initWithNibName:#"WebController" bundle:nil];
UIWebView *wv = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,320,480)];
//wvc.view = wvc.sView;
[wvc setTitle:[nc title]];
[wv setDelegate:self];
[wv loadRequest:request];
[wvc setWebpage:wv];
[wvc setView:wv];
[nc pushViewController:wvc animated:NO];
NSLog(#"NC.viewcontroller count: %d", [nc.viewControllers count]);
[nc setLastURL:request.URL.absoluteString];
[wvc startLoaderIndicator];
[wv release];
[wvc release];
requestOk = YES;
Everything works perfectly, except that the WebViews don't scroll. It looks something like this:
First thing I don't like in this code block...
WebViewController *wvc = [[WebViewController alloc] initWithNibName:#"WebController" bundle:nil];
UIWebView *wv = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,320,480)];
wvc.view = wvc.sView;
Instead create and add the subView to the view in the viewDidLoad block of the view controller. Furthermore, avail yourself of IB and add the WebView via the XIB and simply connect the IBOutlet and delegate.
If you insist upon doing it this way don't overwrite the view,
[wvc.view addSubview:wv];
I wrote this in a simple WebViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
webView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self.view addSubview:webView];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://news.google.com"]]];
}
and called it from a AppDelegate like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.backgroundColor = [UIColor whiteColor];
CPWebController *webController = [[CPWebController alloc] init];
CPNavController *navController = [[CPNavController alloc] initWithRootViewController:webController];
[self.window addSubview:navController.view];
[self.window makeKeyAndVisible];
return YES;
}
It sizes correctly, has a navbar, and scrolls correctly. Please forgive the lack of releases for code brevity.
From what I can see you're setting it with a fixed height here:
UIWebView *wv = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,320,**480**)];
So the content size is only going to be 480 so there's nowhere to scroll.
Try something like (0,0,320,1000); to test if that is the issue
If so set the height to be the cotent size so it's dynamic
Create WebViewController class and inside .m in viewDidLoad add:
- (void)viewDidLoad
{
[super viewDidLoad];
UIWebView *wv = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,320,480)];
[wv setDelegate:self];
NSURL*url = [NSURL URLWithString:#"http://www.link.com/twitter_iPhone.php"];
[wv loadRequest:[NSURLRequest requestWithURL:url]];
[self.view addSubview:wv];
}
I have taken a imageview in applicationDidFinishLaunching as shown below.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIImageView* imageBg = [[UIImageView alloc]initWithFrame:CGRectMake(0, 20, 320, 460)];
imageBg.image = [UIImage imageNamed:#"AppBG.png"];
[self.window addSubview:imageBg];
[self.window sendSubviewToBack:imageBg];
}
Now In rootViewController I have one button
My need is that on press of button in RootViewController I want to change the image from AppBG.png to AppBG1.png
//add a tag to your imageview
imageBg.tag = 1001;
//fetch the imageview from window like this
UIImageView *imgView = [self.window viewWithTag:1001];
//use this imageView to replace existing image like this
imageView.image = [UIImage imageNamed:#"newimg.png"];
Make your UIImageView, imageBg an property, synthesize it.
Then Use following code on button click:
MyAppdelegate *appdelegate = (MyAppdelegate *)[[UIApplication sharedApplication] delegate];
appdelegate.imageBg.image = [UIImage imageNamed:#"AppBG1.png"];
Easy! Just make imageBg a local property and instance in the AppDelegate. Don't forget to synthesize your properties. And in RootViewController class put this code in a button IBAction that is connected to a UIButton:
- (IBAction)buttonWasPressed {
AppDelegate *delegate = [[AppDelegate alloc] init];
delegate.imageBg.image = [UIImage imageNamed: #"AppBG1.png"];
// Don't forget memory management!
[delegate release];
}
Another method you could do this is add a method in the app delegate:
- (void)changeImage {
self.imageBg.image = [UIImage imageNamed: #"AppBG1.png"];
}
And in RootViewController call this method:
- (IBAction)buttonWasPressed {
AppDelegate *delegate = [[AppDelegate alloc] init];
[delegate changeImage];
// Don't forget memory management!
[delegate release];
}
Just simple Objective-C!
In my app I am using TapDetectingWindow to detect touches on a UIWebView (exactly as detailed on http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way).
I used it in one View Controller as suggested with a reference in the header file and the following in the implementation file like
- (id)init {
self = [super init];
if (self) {
tapDetectingWindow = (TapDetectingWindow *)[[UIApplication sharedApplication].windows objectAtIndex:0]; //mWindow, variable reference to TapDetectingWindow
tapDetectingWindow.viewToObserve = webView;
tapDetectingWindow.controllerThatObserves = self;
webView = [[UIWebView alloc] init];
[webView setFrame:CGRectMake(0, 0, 340, 1900)];
[webView setTag:1];
[webView addSubview:keyboardText];
[webView setUserInteractionEnabled:NO];
[webView setDelegate:self];
[webView setOpaque:0.0];
[webView loadHTMLString:htmlString baseURL:NULL];
[self.view addSubview:webView];
keyboardText = [[UITextField alloc] init];
keyboardText.autocorrectionType = UITextAutocorrectionTypeNo;
[keyboardText setDelegate:self];
[self.view addSubview:keyboardText];
}
return self;
}
but my app is crashing at
"tapDetectingWindow.viewToObserve = webView "
with a report * -[UIWindow setViewToObserve:]: unrecognized selector sent to instance 0x4a26b90
Can Any one help me out ...
The problem is not in the above code. Its due to new property introduction in iOS 5.0 with name window under UIApplicationDelegate protocol.
Change your window name in appdelegate file.
In .h file
#class WebViewController;
#class TapDetectingWindow;
#interface test_touchAppDelegate : NSObject <UIApplicationDelegate>
{
TapDetectingWindow *myWindow;
WebViewController *viewController;
}
#property (retain, nonatomic) TapDetectingWindow *myWindow;
#property (retain, nonatomic) WebViewController *viewController;
#end
In .m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.myWindow = [[TapDetectingWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[WebViewController alloc] init];
self.myWindow.rootViewController = self.viewController;
[self.myWindow makeKeyAndVisible];
return YES;
}
Hope this will help.
what Apurv told you is correct and work like a charm. I see you ask for alternate method to recognise gestures on a webview (I assume that it means click on UIWebView.). The answer is yes, you have to use " UIWebView delegate method ".
#pragma mark -
#pragma mark uiwebview delegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if(navigationType==UIWebViewNavigationTypeLinkClicked){
NSURL *URL = [request URL];
if(URL){
[[UIApplication sharedApplication] openURL:URL];
return NO;
}
}
return YES;
}
The code above, when you click on UIWebView, it will open the link of UIWebView that you clicked. Good luck.
I've to switch a part of my app: I will implement a web view insread of a picture (imageview).
So I tried to make it with the interface builder but there is too many errors so I prefer to use code!
for the pictures, I user those lines :
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
self.imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(0,64,320,367);
[self.view addSubview:imageView];
[self.imageView release];
Now, I tried to use this code but nothing's showed:
#property (nonatomic, retain) IBOutlet UIWebView *webView;
...
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.fr"]]];
[self.view addSubview:webView];
If you know how to make .... would be nice for me,
THANKS!
Declare in your h file:
UIWebView *contentWebView;
And also tell to your viewController that you will implement <UIWebViewDelegate>
In viewDidLoad Add:
contentWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
contentWebView.delegate = self;
contentWebView.multipleTouchEnabled = YES;
contentWebView.scalesPageToFit = NO;
[self.view addSubview:contentWebView];
In dealloc don't forget to release the webView:
[contentWebView release];
And implement the delegate methods:
#pragma mark -
#pragma mark WebViewDelegates
- (void)webViewDidStartLoad:(UIWebView *)webView{
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
}
And also you need to load an request. You can doit in viewDidLoad after you have added the webView to your view:
[contentWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.apple.com/"]]];
adjust the frame as u needed and if add anything like imageview as subview to webview then u have to use bringsubviewtofront function.
- (void) initUIWebView {
NSLog(#"DetailViewController->initUIWebView {");
UIWebView *aWebView;
// init and create the UIWebView
aWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 400)];
aWebView.autoresizesSubviews = YES;
aWebView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
//set the web view delegates for the web view to be itself
[aWebView setDelegate:self];
//Set the URL to go to for your UIWebView
NSString *urlAddress = #”http://www.google.com”;
//Create a URL object.
NSURL *url = [NSURL URLWithString:urlAddress];
//URL Requst Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//load the URL into the web view.
[aWebView loadRequest:requestObj];
//add the web view to the content view
[self.view addSubview:aWebView];
[aWebView release], aWebView = nil;
}
- (void)viewDidLoad {
[self initUIWebView]; // <<<<<<<<<<<< this calls the UIWebView Function
[super viewDidLoad];
}