Reputation: 54212
I try to load an array of UIWebView with delegate associated.
for (GDataXMLElement *post in array) {
NSString *msg = [[[post elementsForName:@"message"] objectAtIndex:0] stringValue];
UIWebView *web_view = [[UIWebView alloc] initWithFrame:CGRectZero];
web_view.delegate = self;
[web_view loadHTMLString:msg baseURL:nil];
NSLog(@"Msg: %@", msg);
}
where msg
is some HTML codes reading from XML. XML is loaded properly (verified by the NSLog
line). Then in my webViewDidFinishLoad:
:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
NSLog(@"WebView Height: %.1f", webView.frame.size.height);
[webviews addObject:webView];
}
I auto resize the web views and add them to a NSMutableArray
called webviews
. However, webViewDidFinishLoad
is not called.
In the header .h
file, the interface is defined as:
@interface ViewController : UIViewController<UIWebViewDelegate>
What did I miss? Is the web_view
in the loop get disposed ?
p.s. It looks like a duplicate of this question, but it isn't.
Alternate Approach 1
Declared at .h
:
@property (nonatomic, weak) NSMutableArray *webviews;
Then for implementation:
for (GDataXMLElement *post in array) {
NSString *msg = [[[post elementsForName:@"message"] objectAtIndex:0] stringValue];
UIWebView *web_view = [[UIWebView alloc] initWithFrame:CGRectZero];
web_view.delegate = self;
[web_view loadHTMLString:msg baseURL:nil];
NSLog(@"Msg: %@", msg);
[self.webviews addObject:web_view];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
NSLog(@"WebView Height: %.1f", webView.frame.size.height);
}
Alternate Approach 2
Instead of instantiating UIWebView
in for-loop
, I put it in header file.
@interface ViewController : UIViewController<UIWebViewDelegate> {
UIWebView *web_view;
}
Then change the for-loop:
for (GDataXMLElement *post in array) {
NSString *msg = [[[post elementsForName:@"message"] objectAtIndex:0] stringValue];
web_view = [[UIWebView alloc] initWithFrame:CGRectZero];
web_view.delegate = self;
[web_view loadHTMLString:msg baseURL:nil];
NSLog(@"Msg: %@", msg);
[self.webviews addObject:web_view];
}
In this approach, only the delegate of last message gets called.
Summary & Highlights:
My objectives:
UIWebView
with variable-size contentswebViewDidFinishLoad
is required.UIScrollView
) in order to make it not overlapped.Upvotes: 0
Views: 4580
Reputation: 54212
Here is my final solution ( hope it is useful for others ):
In Storyboard, I added a UIScrollView
in the view controller, and link it with the IBOutlet
.
Header file:
#import <UIKit/UIKit.h>
#import "GDataXMLNode.h"
@interface ViewController : UIViewController<UIWebViewDelegate> {
IBOutlet UIScrollView *scroll_view;
}
@property (nonatomic, strong) UIWebView *web_view;
@end
Implementation file:
float currentY;
NSArray *array;
int count;
GDataXMLDocument *doc;
- (void)viewDidLoad
{
[super viewDidLoad];
currentY = 0;
count = 0;
[self loadXML];
}
- (void)loadXML {
// Some codes to load the XML contents into array variable
[self loadWebView];
}
- (void)loadWebView {
if(count < array.count) {
GDataXMLElement *post = [array objectAtIndex:count];
NSString *msg = [[[post elementsForName:@"message"] objectAtIndex:0] stringValue];
count++;
self.web_view = [[UIWebView alloc] initWithFrame:CGRectMake(10, currentY, 300, 1.0f)];
self.web_view.delegate = self;
[self.web_view setHidden:YES];
[self.web_view loadHTMLString:msg baseURL:nil];
[scroll_view addSubview:self.web_view];
} else {
// end the process
[scroll_view setContentSize:CGSizeMake(320, currentY + 30)];
return;
}
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
[webView setHidden:NO];
currentY += webView.frame.size.height + 20.0f; // 20.0f is spaces between posts
NSLog(@"WebView Height: %.1f", webView.frame.size.height);
[self loadWebView];
}
Upvotes: 0
Reputation: 1299
You should do like this,
@interface UIViewController <UIWebViewDelegate>
{
}
@property(nonatomic, strong)NSMutableArray *webViews;
@end
////////////////
@implementation UIViewController
-(void)viewDidLoad
{
[super viewDidLoad];
webViews = [[NSMutableArray alloc] init];
for (GDataXMLElement *post in array)
{
NSString *msg = [[[post elementsForName:@"message"] objectAtIndex:0] stringValue];
UIWebView *web_view = [[UIWebView alloc] initWithFrame:CGRectZero];
web_view.delegate = self;
[web_view loadHTMLString:msg baseURL:nil];
NSLog(@"Msg: %@", msg);
[self.webViews addObject:web_view];
//i don't know why would you not add these web-views on the view controller,
// but still, here is the addition of these.
[self.view addSubView:web_view];
}
}
@end
This should make the web-views call the delegate properly on load.
Upvotes: 1
Reputation: 4813
If you're using ARC, the web_view is deallocated at the end of the for loop.
Upvotes: 0