removeFromSuperview is not working if it is called from another class - ios

I have one main view as shown in picture. I add 2 subviews into that and each has their own view controller.
In ipadMainViewController,
self.dTVC= [[dialoguesTableViewController alloc] initWithNibName:#"dialoguesTableViewController" bundle:nil];
[self.dTVC.view setFrame:rectFordTVC];
[self.view addSubview:self.dTVC.view];
After that, I want to remove the view of dialoguesTableViewController if I press a button in CategoriesViewController. But, I can't remove it.
In CategoriesViewController, I write like this but dialoguesTableViewController can't be removed from ipadMainViewController. How shall I do this?
In CategoriesViewController, I write code like this but it is not working.
self.dTVC= [[dialoguesTableViewController alloc] initWithNibName:#"dialoguesTableViewController" bundle:nil];
[self.dTVC.view removeFromSuperview];

So there are few ways how to do it:
First way:
Add observer to ipadMainViewController initialization method or viewDidLoad method it depends on your needs.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(buttonPressed)
name:#"kNotificationDidPressedButon"
object:nil];
Add -buttonPressed method to ipadMainViewController controller for removing your view or other your purposes.
- (void)buttonPressed
{
// remove view here
}
in the CategoriesViewController in the method where you tap on the appropriate button add this code:
[NSNotificationCenter defaultCenter] postNotificationName:#"kNotificationDidPressedButon"
object:self];
Second way:
Add delegate property to CategoriesViewController. you can find info how to make delegate for example here: link
Third way:
Use objective-c blocks
Initial advice as for beginner:
I suggest you to start from first way, because it is most simplest for understanding. Also you have to remove observer in ipadMainViewControllerr in -dealloc or -viewWillDisapper method, it depends of where you have add observer e.g. in -init method or in -viewDidLoad or -viewWillAppear callback;
[[NSNotificationCenter defaultCenter] removeObserver:self];

try this....
add below code where you can remove view
-(void)viewDidLoad{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(removeFromSuperview) name:#"REMOVE" object:nil];
}
-(void)removeFromSuperviev{
[view removeFromSuperview];
}
add below code form you need to remove
[[NSNotificationCenter defaultCenter] postNotificationName:#"REMOVE" object:nil];

Related

Reload TableView from different ViewController using Objective-C

I'm not sure about how to achieve this and hence i'm asking this question.
I have 2 ViewController(VC) named abVC and xyVC.
abVC contains only TableView and xyVC contains only a button.
When i tap a button on xyVC, it should reload tableview inside abVC without moving to that abVC.
Is it possible ? If yes.. then please help me,How to do that?
You can do it with both block and NSNotification.
With block you can implement it as follows:
make a property as follows in xyzVC.h:
#property(strong,nonatomic)void(^callBack)();
Synthesize this property in xyzVC.m
#synthesize callBack
Call this block in Buttons click event
- (IBAction)btnClick:(UIButton *)sender {
if (callBack)
{
callBack();
}
}
Implement it in abcVC where you want call back:
[abVC setCallBack:^{
//reload your tableview here
}];
With NSNotification you can implement it as follows:
Register for receiving notification in abcVC.m
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTableView) name:#"ReloadTable" object:nil];
- (void)reloadTableView{
// Reload your tableview here
}
Now post the notification from xyzVC
- (IBAction)btnClick:(UIButton *)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTable" object:nil];
}
Note: If you are using NSNotification then don't forget to remove it when your view controller is dismissed
I hope this will help you :)
Add this line in your button action method
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTable" object:nil];
Add this code where you have implemented table, so in abVC:
inside viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTableViewData) name:#"ReloadTable" object:nil];
Add following method
- (void)reloadTableViewData{
[self.myTableView reloadData];
}
Implement dealloc method (to prevent crash)
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"ReloadTable" object:nil];
}

Issue while calling NSNotificationCenter

I want to call a method from another class via NSNotificationCenter.Everything is working fine.
The problem is my method called up two times.
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(removeAllSubViews:) name:#"getTheRequest" object:nil];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)removeAllSubViews:(NSNotification *)notification
{
NSLog(#"%#",notification.object);
NSLog(#"Print");
}
ViewController2.m
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] postNotificationName:#"getTheRequest" object:#"mySite"];
// Do any additional setup after loading the view.
}
When I run, I get this in console:
Why my method is called up two times ?
Edit
When I use this code in ViewController2.m it works fine. But Why?? **
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"getTheRequest" object:nil];
You have to remove observer after use of it inside the method.
- (void)removeAllSubViews:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver("getTheRequest")]
NSLog(#"%#",notification.object);
NSLog(#"Print");
}
I've seen this before when I had a retain cycle in my view controller, so every time a instance of this view controller was created, it was added as an NSNotificationCenter observer, but because of the retain cycle when the view controller was dismissed, it was never actually deallocated/released from memory, so technically it was still an observer.
You might want to try to add the following to your view controller:
- (void)dealloc {
NSLog(#"Dealloc called.");
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
This should remove your view controller as an observer when it is dismissed, if there is no retain cycle, and if there is the NSLog will never be called - which is indicative of a larger memory-related issue, where what you're seeing is just a side-effect.
You are probably seeing multiple calls to that method, because you register the observer multiple times (e.g. you have navigated to that view controller before), but did not remove it again at the appropriate places. Anyways, viewDidLoad is very likely not the ideal place to register an observer. A common place to do this is the designated initializer, and removing it again in dealloc.
As a side note (and without seeing enough code for a very informed opinion), your use case ("remove all subviews") does not sound like notifications are a good approach. Have you considered using delegation?
It is possible that there is a double NSNotificationCenter registration.
I think you have declared another:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(removeAllSubViews:) name:#"getTheRequest" object:nil];
somewhere.. trying finding the other one..
And just a tip, when you register for NSNoticationCenter try removing first the observer like:
// removes the observer
[[NSNotificationCenter defaultCenter] removeObserver:YourObserver name:YourName object:YourObject];
followed by:
// register
[[NSNotificationCenter defaultCenter] addObserver:YourObserver selector:YourSelector name:YourName object:YourObject];
Just to remove the existing one, if any..

Remove notification observer from another view controller

Hi I am developing Iphone application in which am registering one notification observer for UIApplicationWillEnterForegroundNotification. Now I want to remove that one from another view controller. My code looks like
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(applicationBecomeActive)
name:UIApplicationWillEnterForegroundNotification
object:nil];
And I am creating one method for removing observer:
-(void) removeObserver
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
and I am calling this method from other view controller but its not working. I think I have to store observer. But I don't know how to do this. Need help. Thank you.
The second view controller needs a reference to the instance of the first view controller. Let's assume it is hold in a property:
#property (nonatomic, strong) FirstViewControler *firstViewController;
Then your code to remove the fist view controller as an observer would look like this:
- (void)removeObserver
{
[[NSNotificationCenter defaultCenter] removeObserver:self.firstViewController];
}
The missing part is: You have to set the property somewhere. Where to do that depends on your code.

How to tell a viewcontroller to update its UI from another class

I am trying to understand how updating of a viewController that is currently visible works.
I have ViewControllerA and ClassA. I want to tell ViewControllerA to reloadData on the tableview from ClassA. What is the best way to go about doing this?
I have found this question and answer but I dont think this will work in my situation or I am not understanding it correctly.
The easiest way without knowing your setup would be to use NSNotificationCenter. Here is what you could do:
In ViewControllerA add in hooks for NSNotificationCenter:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//Register for notification setting the observer to your table and the UITableViewMethod reloadData. So when this NSNotification is received, it tells your UITableView to reloadData
[[NSNotificationCenter defaultCenter] addObserver:self.table selector:#selector(reloadData) name:#"ViewControllerAReloadData" object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
//Need to remove the listener so it doesn't get notifications when the view isn't visible or unloaded.
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Then in ClassA when you want to tell ViewControllerA to reload data just post the NSNotification.
- (void)someMethod {
[[NSNotificationCenter defaultCenter] postNotificationName:#"ViewControllerAReloadData" object:nil];
}
Answers here about using NSNotificationCenter are good. Be aware of a few other approaches:
A common one is the delegate pattern (see here and here).
Another is that the view controller observes the model change using KVO. (see here and here).
Another good one, often overlooked, which can probably be used in your case is the "do almost nothing" pattern. Just reloadData on your table view when viewWillAppear.
Key value Coding , NSNotificationCentre and Delegates are preferred. But NSNotificationCentre is easiest in your case.
The UIViewController that contains UITableView must add observer like this :
Init :
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(methodToReloadTable:)
name:#"TABLE_RELOAD"
object:nil];
In delloc method :
[[NSNotificationCenter defaultCenter] removeObserver:self];
Post it from any XYZ class like on any UIButton action :
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TABLE_RELOAD"
object:self];
Advantage of NSNotificationCentre is that they can add observers in multiple classes ..

How to pick a selector inside a class for NSNotification?

keyboard = [[FTKeyboardHelper alloc] init];
I have a keyboard helper class, and would like to call the method keyboardShow that is defined inside the keyboard.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboard.keyboardShow:)
name:UIKeyboardWillShowNotification
object:nil];
However I get the error message Excepted :
Any advice?
What about
[[NSNotificationCenter defaultCenter] addObserver:keyboard
selector:#selector(keyboardShow:)
name:UIKeyboardWillShowNotification
object:nil];
I'm not sure you can "." Separate the selector, it's not a key path.
But I think that would be bad design, you should probably put that code inside your helper.
In the - init and unregister in the - dealloc or use a pair of - register and - unregistermethod to control this outside of the normal life cycle of your object.
But don't forget to unregister before the helper is deallocated, if not, you will crash the next time the keyboard shows up.

Resources