How to update other view controllers based on an action from a base view

On my base view controller, I have a map with the user's location attached to it, which is then saved to NSUserdefaults

. I also have a delete option where the user can delete their attached annotation. The app is launched by the tab controller, so the first tab is the pinned location and the second tab is the detailed view of the pinned location. However, when I remove the annotation from first view controller

, the old location is still at detailed view controller

.

Is there anyway I can update / reload the detail view controller based on the actions of the underlying VC?

Thank!

+3


source to share


3 answers


You can use NSNotifications

for this.

In your first view controller, you really want to be notified, not set up a notification.

Second view controller

override func viewDidLoad() {

    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "resetData:", name: "reloadData", object: nil);

      

and then you have a method for your selector ...

func resetData(notification:NSNotification) {
    smallMapView.removeAnnotations(smallMapView.annotations);
    smallMapView.showsUserLocation = true;
    var location = locationManager.location;
    var latitude = location.coordinate.latitude;
    var longitude = location.coordinate.longitude;
    var latDelta:CLLocationDegrees = 0.001;
    var longDelta:CLLocationDegrees = 0.001;

    var span: MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta);
    var overallLoc = CLLocationCoordinate2DMake(latitude, longitude);
    var region:MKCoordinateRegion = MKCoordinateRegionMake(overallLoc, span);
    self.smallMapView.setRegion(region, animated: true)

}

      



This will reset the pin and center on your detailed map to the user's current location (you can change this functionality if you need).

Controller at a glance

I assume you used NSAlertView

here ...

@IBAction func trashButtonSelected(sender: AnyObject) {
    // Remove from NSDefaults
    // Show alertview
    let alertController = UIAlertController(title: "Are you Sure?", message: "Do you wish to delete your pinned Location?", preferredStyle: .ActionSheet);
    let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (Action) in
        // Cancel
    }
    let deleteButton = UIAlertAction(title: "Delete", style: .Destructive) { (Action) in
        NSUserDefaults.standardUserDefaults().removeObjectForKey("pinnedLocation");
        NSNotificationCenter.defaultCenter().postNotificationName("reloadData", object: nil);
        self.map.removeAnnotations(self.map.annotations);
        self.pinLocationButton.enabled = true;
    }
}

      

This should do the job :)

+2


source


You can use NSNotificationCenter

to achieve this.

Basically NSNotificationCenter

stores a reference to any object that is registered as an observer. With this link, it also keeps track of what notifications objects want. When an object sends a notification, the center sends it to each registered observer by sending a message to the observer with this selector.

Let's say you have two view controllers

  • First View Controller
  • Second view controller

Now you want to take some action in the First View Controller based on some actions in the Second View Controller. Then in FirstViewController, you just register that view controller as an observer and implement the method where you want to handle the notification. From the SecondViewController, you must send a notification.

FirstViewController.m

In controller of the first kind, you have to register the observer like this.



- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(performAction) name:@"reload_data" object:nil];
}

      

This will be called when you receive a notification from the SecondViewController.

- (void)performAction {
    NSLog(@"Do whatever you want to do");
}

      

SecondViewController.m

I send a notification from SeconViewController.

- (IBAction)buttonClick:(id)sender {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"reload_data" object:self];

      

}

+3


source


This is a conical problem of object oriented programming, how do you inform the objects that some event has happened?

One good article on this topic When to Use Delegation, Notification, or Observation in iOS . (As you might expect, each of these three patterns has its own pros and cons.) You can also "spin your" solution by implementing some variation of the Observer Pattern . There are also several "out-of-band" solutions as well as ReactiveCocoa and RxSwift (both on github and available via cocoapods).

I am under the impression that you are new to programming. So I suggest you implement the Notification Center solution shown in other answers here, but then re-implement the solution using Key Value Observing and then implement it again using delegation. This way you will get an idea of ​​all these important patterns and get a good idea of ​​what is best for your particular situation. If you consider yourself adventurous, you can also explore one of the reactive solutions ... the learning curve above, but they are powerful tools that can be used in many disparate situations.

+1


source







All Articles