Initializing a UIViewController correctly and passing in properties - ios

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.)

Related

self.delegate is always nil

I saw similar questions like this. In all the place they said to use className.delegate = self or other similar solutions. But i already checked i have did everything correctly. Then also i am facing self.delegate is nil problem.
I am trying to pass data from MyViewController to NextViewController on Button Click
I did,
1.Created Protocol in MyViewController
2.Created delegate Instance in MyViewController
3.Wrote this code in Button Click Event
-(void)buttnPressed:(id)s{
NextViewController* d=[[NextViewController alloc]init];
if(self.delegate){
NSLog(#"D");
}
if (self.delegate && [self.delegate respondsToSelector:#selector(groupSelected:)]) {
[self.delegate groupSelected:#"df"];
}
[self.navigationController pushViewController:d animated:YES];
}
4.Implemented FirstViewController in NextViewController and set it's delegate
5.Created FirstViewController's instance (inside NextVC) and using that instance i set it's delegate as self
6.Implemented the delegate method in NextVC
I did everything correctly to my knowledge but i did not get the solution. Please help. Thanks for the time. (:
Here is my code
MyViewController.h
#import <UIKit/UIKit.h>
#protocol WatchListDelegate <NSObject>
-(void)groupSelected:(NSString *)grouDetails;
#end
#interface MyViewController : UIViewController
#property (strong,nonatomic) id<WatchListDelegate> delegate;
#end
MyViewController.m
#import "MyViewController.h"
#import "NextViewController.h"
#interface MyViewController ()
#property UIButton *buttonPopUp;
#end
#implementation MyViewController
-(id)init{
self = [super init];
return self;
}
-(void)loadView{
[super loadView];
self.buttonPopUp=[UIButton buttonWithType:UIButtonTypeCustom];
[self.buttonPopUp addTarget:self
action:#selector(buttnPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self.buttonPopUp setTitle:#"Press ME" forState:UIControlStateNormal];
[self.buttonPopUp setBackgroundColor:[UIColor blueColor]];
self.buttonPopUp.frame=CGRectMake(80,180,80,40);
[self.view addSubview:self.buttonPopUp];
}
-(void)buttnPressed:(id)s{
if(self.delegate){
NSLog(#"D");
}
if (self.delegate && [self.delegate respondsToSelector:#selector(groupSelected:)]) {
[self.delegate groupSelected:#"df"];
}
NextViewController* d=[[NextViewController alloc]init];
[self.navigationController pushViewController:d animated:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
#end
NextViewController.h
#import <UIKit/UIKit.h>
#import "MyViewController.h"
#interface NextViewController : UIViewController<WatchListDelegate>
#end
NextViewController.m
#import "NextViewController.h"
#interface NextViewController ()
#end
#implementation NextViewController
-(id)init{
self = [super init];
if(self){
MyViewController *m=[[MyViewController alloc]init];
m.delegate = self;
}
return self;
}
-(void)loadView{
[super loadView];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
-(void)groupSelected:(NSString *)grouDetails{
NSLog(#"groupSelected");
}
#end
Thanks for the time (:
Try This:
-(void)buttnPressed:(id)s{
NextViewController* d= [self.storyboard instantiateViewControllerWithIdentifier:#"VCidentiferFromStoryBoard"];
self.delegate = d;
[self.navigationController pushViewController:d animated:YES];
if (self.delegate && [self.delegate respondsToSelector:#selector(groupSelected:)]) {
[self.delegate groupSelected:#"df"];
}
}
I don't think you need a delegate to pass data, you're trying to pass the string value 'df'? If so you could just create a public property in NextViewController and assign it a value when you create NextViewController in MyViewController?
The delegate is nil, because it does not look like you set it, so in the button pressed logic you would do self.delegate = d;, don't assign the delegate or create MyViewController in the init of NextViewController, then check the delegate and it won't be nil, but I don't think you need the delegate pattern in this case?
Let me know if you need me to clarify or there is something else in particular you need to pass.
Edit your MyViewController.m
#implementation MyViewController
{
NextViewController* nextViewController;
}
Then rewrite the buttnPressed method like below:
-(void)buttnPressed:(id)s
{
if(!nextViewController) // this way only one time NextVC will be created
{
nextViewController = [[NextViewController alloc]init];
[self.navigationController pushViewController:nextViewController animated:YES];
self.delegate = nextViewController;
}
if (self.delegate && [self.delegate respondsToSelector:#selector(groupSelected:)]) {
[self.delegate groupSelected:#"df"];
}
}

ios custom delegate is null after second click in navigation controller

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];
}

Push ViewController

I have added UINavigationBar in appDelegate method. Please check my atatched screen shots. In bottom is i have used UINavigationBar. In middel of the page history button is there.
Here when i click the history button its cant go to historyviwcontrooler. Because i cant push the view. Can you please tell me how i can push here. When i click history its called only one calls after only thet called another class there only i given UI. How i handel here . please help me
#import "UICallButton.h"
#import "LinphoneManager.h"
#import <CoreTelephony/CTCallCenter.h>
#implementation UICallButton
#synthesize addressField;
#pragma mark - Lifecycle Functions
- (void)initUICallButton {
[self addTarget:self action:#selector(touchUp:) forControlEvents:UIControlEventTouchUpInside];
}
- (id)init {
self = [super init];
if (self) {
[self initUICallButton];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initUICallButton];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
[self initUICallButton];
}
return self;
}
- (void)dealloc {
[addressField release];
[super dealloc];
}
#pragma mark -
- (void)touchUp:(id) sender {
NSString *address = [addressField text];
NSString *displayName = nil;
ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:address];
if(contact) {
displayName = [FastAddressBook getContactDisplayName:contact];
}
[[LinphoneManager instance] call:address displayName:displayName transfer:FALSE];
}
#end
Basically, you must have a UINavigationController, and not just a UINavigationBar, in order to be able to perform a push transition to one UIViewController to another.
I'm not explaining how to do that because it's very basic, you should study and read some books/tutorials before begin a real project.
Here's some links to help you:
A nice tutorial
How to use navigation controllers (from apple)
Navigation Controller class reference

popoverControllerDidDismissPopover NOT doing what I think it should

So, I think that when I click outside of a popover, the method popoverControllerDidDismissPopover should be called. I know this isn't called when dismissPopoverAnimated is called.
I have a simple project that I have setup that shows popoverControllerDidDismissPopover just isn't called:
#import "ViewController.h"
#import "PopoverViewController.h"
#interface ViewController ()
{
PopoverViewController *controller;
UIPopoverController *popoverController;
}
#end
#implementation ViewController
#synthesize button;
- (IBAction)showPopover:(UIButton *)sender
{
if ([popoverController isPopoverVisible]) {
[popoverController dismissPopoverAnimated:YES];
} else {
CGRect popRect = CGRectMake(self.button.frame.origin.x,
self.button.frame.origin.y,
self.button.frame.size.width,
self.button.frame.size.height);
[popoverController presentPopoverFromRect:popRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
controller = [[PopoverViewController alloc] initWithNibName:#"PopoverViewController" bundle:nil];
popoverController = [[UIPopoverController alloc] initWithContentViewController:controller];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
NSLog(#"Why am I never called!!!!");
}
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return true;
}
#end
Please tell me where I'm going wrong or how I can detect when a popover is dismissed.
The whole project is here:
https://rapidshare.com/files/3182903825/PopoverDemo.zip
You never set the delegate for your popoverController to self.
_popoverController.delegate = self;
You didn't set the delegate of your popoverController. Add the following code to the end of the viewDidLoad method:
popoverController.delegate = self;

why the method for delegate can't be called

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

Resources