File:PeopleLinkEditViewController.h
#protocol PeopleLinkEditViewControllerDelegate<NSObject>
#optional
-(void)headerInfoEditFinish;
#end
#interface PeopleLinkEditViewController : UITableViewController
{
id<PeopleLinkEditViewControllerDelegate> delegate;
}
#property (nonatomic, retain) id<PeopleLinkEditViewControllerDelegate> delegate;
-(IBAction)doneEdit:(id)sender;
#end
File:PeopleLinkEditViewController.m
#implementation PeopleLinkEditViewController
...
#synthesize delegate = _delegate;
...
- (void)viewDidLoad
{
...
headerView = [[PeopleLinkHeaderView alloc] initWithFrame:CGRectMake(0, 0, 320, 286)
passData:headerDic];
...
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if(section == 0)
{
return headerView;
}
return nil;
}
-(IBAction)doneEdit:(id)sender
{
if ([delegate respondsToSelector:#selector(headerInfoEditFinish)])
{
NSLog(#"%d", __LINE__);
[delegate headerInfoEditFinish];
}
}
#end
File:PeopleLinkHeaderView.h
#import "PeopleLinkEditViewController.h"
#interface PeopleLinkHeaderView : UIView<PeopleLinkEditViewControllerDelegate>
{
}
#end
File:PeopleLinkHeaderView.m
#interface PeopleLinkHeaderView()
#property (nonatomic, retain) PeopleLinkEditViewController *edit;
#end
#implementation PeopleLinkHeaderView
- (id)initWithFrame:(CGRect)frame passData:(NSDictionary *)data
{
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle:nil];
PeopleLinkEditViewController *edit = [sb instantiateViewControllerWithIdentifier:#"PeopleLinkEditController"];
edit.editDelegate = self;
}
-(void)headerInfoEditFinish
{
[baseInfo setValue:baseInfoValue forKey:#"value"];
[dataPass writeHeaderValueToPlist:baseInfo];
}
the method for delegate can't be called. And when I debug it, I find delegate is nil in editcontroller. and editcontroller is created by storyboard. Headerview is a subview of edit controller.
The problem is that the Instance you are sending the action to and the one you have declared the delegate for are not the same.
I can tell by looking at this
edit = [[PeopleLinkEditViewController alloc] init];
edit.delegate = self;
This is a newly created instance and you are not displaying or presenting it in any way. Perhaps this is form a different View Controller made on the storyboard? If it is one you specified in the storyboard you should retrieve THAT one and assign its delegate.
Use this to retrieve the correct instance
#import ViewController.h
Then on the place where you want to set the delegate.
ViewController *tmp = [[self storyboard] instantiateViewControllerWithIdentifier:#"ViewControllerIdentifier"];
tmp.delegate = self;
Dont forget to change to include the header for the class and change to the correct tag.
Retrieved from here:
https://stackoverflow.com/a/11931714/1068522
Related
I have a custom UIWebView (EpubWebView), with a custom NSURLCache (EpubCache) for handling requests.
i created a custom delegate for handling request.
EpubCache.h
#protocol EpubCacheDelegate <NSObject>
#required
- (NSCachedURLResponse *)hadleRequest:(NSURLRequest *)request;
#end
#interface EpubCache : NSURLCache
#property (nonatomic, weak) id <EpubCacheDelegate> cacheDelegate;
#end
EpubCache.m
import "EpubCache.h"
#interface EpubCache ()
#end
#implementation EpubCache
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
{
return [self.cacheDelegate hadleRequest:request];
}
#end
EpubWebView .h
#interface EpubWebView : UIWebView <UIWebViewDelegate, EpubCacheDelegate>
#property (strong, nonatomic) EpubCache *mLocalCache;
#end
EpubWebView.m
- (void) localInit
{
self.mLocalCache = [[EpubCache alloc] init];
self.mLocalCache.cacheDelegate = self;
[NSURLCache setSharedURLCache:self.mLocalCache];
}
- (NSCachedURLResponse *)hadleRequest:(NSURLRequest *)request
{
// return handled request
}
on the other hand i have a navigationcontroller with a tableview and the destination view controller have this webview.
when i ran the app and click on an item in tableview, everything is fine and delegate works as expected.
if i click back and click on other item in tableview, things goes wrong, the cachedResponseForRequest getting called but the hadleRequest wont, i checked and findout that the delegate is null!
i can not figure out what is happening here.
any help would be appreciated.
UPDATE 1
EpubWebView.m
- (id)init
{
self = [super init];
if (self)
{
[self localInit];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
[self localInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if(self)
{
[self localInit];
}
return self;
}
UPDATE 2
the segue of the tableview that bring up the view controller that contain EpubWebView
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.collectionView indexPathForCell:sender];
BookViewController *bookController = segue.destinationViewController;
bookController.mBook = booksList[indexPath.row];
}
and BookViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
mWebView = [[EpubWebView alloc] initWithFrame:self.mainView.frame];
[self.mainView addSubView:mWebView];
[mWebView setBook:self.mBook];
}
You need to make a few modifications. First, remove your "localInit" method, then create a new function in EPubWebView:
- (void) setCache: (EpubCache *)localCache
{
localCache.cacheDelegate = self;
}
Now, you can create and hold onto your cache in your BookViewController via these lines in the .m file:
#interface BookViewController ()
#property (strong, nonatomic) EpubCache *mLocalCache;
#end
and change your BookViewController's viewDidLoad method to look like:
- (void) viewDidLoad {
self.mLocalCache = [[EpubCache alloc] init];
// only need to do this once, at viewDidLoad time
[NSURLCache setSharedURLCache:self.mLocalCache ];
[super viewDidLoad];
mWebView = [[EpubWebView alloc] initWithFrame:self.mainView.frame];
[mWebView setCache:self.mLocalCache];
[self.mainView addSubView:mWebView];
[mWebView setBook:self.mBook];
}
I have a UIViewController called TestViewController.h/.m:
Header file has:
#property (nonatomic, assign) BOOL isTested;
Implementation file has:
#implementation TestViewController
- (void)viewDidLoad
{
if (_isTested)
{
[self postNotification];
[self listenToNotifications];
}
}
I have a view that has this:
- (void) replyTapPressed
{
TestViewController *test = [[TestViewController alloc] init];
test.isTested = NO;
[_parent.navigationController pushViewController:test animated:YES];
}
Through the app's life cycle, the TestViewController's property starts off as YES; but when the view about gets called, it should set the property to NO; - which it does.
But _parent (which is the parent UIViewController) and test are both NULL.
Am I initializing and implementing it wrong?
Thanks.
You may try in below ways -
TestViewController.m
- (id)initWithTested:(BOOL)value
{
if (self = [super init])
{
self.isTested = value;
}
return self;
}
- (void) replyTapPressed
{
TestViewController *test = [[TestViewController alloc] initWithTested:NO];
[_parent.navigationController pushViewController:test animated:YES];
}
The view will "load" during initialization of your controller. To achieve what you want, implement viewWillAppear and move
if (_isTested) {
[self postNotification];
[self listenToNotifications];
}
there. (You could also put this in viewDidAppear, depending on what you are doing.)
ContainerViewController delegate the method -delegateMethod to ChildViewController.
But in the following code, -delegateMethod is not called.
I think it's because _childViewController has been released.
How do I fix it to make run -delegateMethod?
ContainerViewController.h
#protocol ContainerViewDelegate <NSObject>
- (void)delegateMethod;
#end
#interface ContainerViewController : UIViewController
#property (nonatomic, assign) id<ContainerViewDelegate> delegate;
#end
ContainerViewController.m
#interface ContainerViewController () {
ChildViewController *_childViewController;
}
//...
- (void)viewDidLoad
{
_childViewController = [[WeeklyViewController alloc]init];
[self addChildViewController:_childViewController];
[self.view addSubview:_childViewController.view];
[_childViewController didMoveToParentViewController:self];
}
- (void)buttonAction {
[self.delegate delegateMethod];
}
ChildViewController.m
#interface ChildViewController () <ContainerViewDelegate>
//...
- (void)delegateMethod {
NSLog(#"succeed!");
}
You never set the delegate, so self.delegate will be nil. You should do this,
- (void)viewDidLoad
{
_childViewController = [[WeeklyViewController alloc]init];
self.delegate = _childViewController;
[self addChildViewController:_childViewController];
[self.view addSubview:_childViewController.view];
[_childViewController didMoveToParentViewController:self];
}
So I am trying to display a UITableView inside a UIPopoverController using the piece of code shown below
vc = [[ActionsViewController alloc] init];
initWithContentViewController:vc];
actionsController = [[UIPopoverController alloc] initWithContentViewController:vc];
actionsController.delegate = self;
NSLog(#"Try to sho it ");
[actionsController presentPopoverFromBarButtonItem:(UIBarButtonItem*)sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
And this is ActionsViewController.m which is a subclass of UITableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray* list = [[NSMutableArray alloc] initWithCapacity:4];
self.actionList = list;
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 400.0);
[self.actionList addObject:#"Print as book"];
[self.actionList addObject:#"Print page"];
[self.actionList addObject:#"Save Page"];
[self.actionList addObject:#"Share"];
}
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"in number of section");
return 1;
}
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString* lab = [self.actionList objectAtIndex:indexPath.row];
NSLog(#"here in there");
cell.textLabel.text = lab;
return cell;
}
- (NSInteger)numberOfRowsInSection:(NSInteger)section
{
return [self.actionList count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.delegate != nil) {
[self.delegate actionSelected:indexPath.row];
}
}
The corresponding .h file
#import <UIKit/UIKit.h>
#protocol KLActionsViewControllerDelegate
- (void)actionSelected:(NSInteger)index;
#end
#interface KLActionsViewController : UITableViewController <UITableViewDataSource,UITableViewDelegate>
#property (nonatomic, retain) NSMutableArray* actionList;
#property (nonatomic, assign) id<KLActionsViewControllerDelegate> delegate;
#end
Also, I don't think the functions cellForRowAtIndexPath and numberOfSectionsInTableView are getting called because I don't see any console output.
EDIT: This is what I see in the popover
:
In viewDidLoad I added self.tableView = [[UITableView alloc] init]
I guess, the problem would be in that line:
vc = [[ActionsViewController alloc] init];
if you have a NIB file, you should load the UIViewController with using it.
vc = [[ActionsViewController alloc] initWithNibName:#"ActionViewController" bundle:nil];
// the NibName must be the exact name of XIB file without extension.
OR/AND
you should set the popoverContentSize:
[actionController setPopoverContentSize:vc.view.frame.size];
I hope it helps a bit for you.
UPDATE:
it seems it is not an UIPopoverController problem, just a simple UITableViewController delegate issue.
in that line:
actionsController.delegate = self;
you should set that class as delegate which implements the UITableViewDelegate. basically it is the UITableViewController itself like
actionsController.delegate = actionController;
therefore you should not replace this in that case if you haven't implemented the delegate callback methods in the self which the new delegate class is. you simple steal the chance from the class which was really delegated to answer the callbacks, and in you new delegate class you don't answer the callbacks.
this would be the reason why you are seeing the empty table, without the datas.
You need to load the table view via (last line of viewdidload :
[self.tableView reloadData];
that will trigger the table view methods to action. Put a breakpoint in the various tableview methods particularly in -
(NSInteger)numberOfRowsInSection:(NSInteger)section
{
return [self.actionList count];
}
If this does not get called your tableview is not loaded.
UITableViewController is implicit set datasource and delegate, there is no need to set explicitly datasource and delegate.
Remove UITableViewDataSource,UITableViewDelegate from .h file
#import <UIKit/UIKit.h>
#protocol KLActionsViewControllerDelegate
- (void)actionSelected:(NSInteger)index;
#end
#interface KLActionsViewController : UITableViewController
#property (nonatomic, retain) NSMutableArray* actionList;
#property (nonatomic, assign) id<KLActionsViewControllerDelegate> delegate;
#end
and also remove this line **actionsController.delegate = self;
vc = [[ActionsViewController alloc] init];
actionsController = [[UIPopoverController alloc] initWithContentViewController:vc];
[actionsController presentPopoverFromBarButtonItem:(UIBarButtonItem*)sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
I need to call a method in the viewcontroller that creates a popupviewcontroller, from the created popupviewcontroller.
For iPad I create it like this:
if (!self.flipsidePopoverController) {
FlipsideViewController *controller = [[[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil] autorelease];
controller.delegate = self;
self.flipsidePopoverController = [[[UIPopoverController alloc] initWithContentViewController:controller] autorelease];
}
if ([self.flipsidePopoverController isPopoverVisible]) {
[self.flipsidePopoverController dismissPopoverAnimated:YES];
}
else
{
/// The important part ///
[self.flipsidePopoverController presentPopoverFromRect:CGRectMake((self.view.frame.size.width-320), 0, (self.view.frame.size.width), 10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
Now I wish to call a method in my main view controller from within the popup. How can I achieve that?
My iPhone equivalent is this:
// Creating it //
FlipsideViewController *controller = [[[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil] autorelease];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
Calling a method from within the popup:
if ([self.presentingViewController isKindOfClass:[MainViewController class]])
[(MainViewController*)self.presentingViewController resetClock];
Give the displayed view controller a reference to your main view controller. Eg:
#class MainViewController;
#interface FlipsideViewController : UIViewController
{
}
#property (nonatomic, assign) MainViewController *mainController;
#end
(Don't forget the #synthesize in the implementation!)
Later when you present the popover, just set the property:
[controller setMainController:self];
.h
#import <UIKit/UIKit>
#import AppDelegate.h"
#interface FlipsideViewController : UIViewController
{
}
#property (nonatomic, assign) MainViewController *mainController;
#end
.m
#import "FlipsideViewController.h"
#import "MainViewController.h"
#interface FlipsideViewController ()
#end
#implementation FlipsideViewController
#synthesize mainController = _mainController;
// methods
#end