1

The situation is very similar to that described by this my other question, except that the delegation seems to work fine. I'm providing some more detail about my code. I'm just striping out non-relevant/trivial parts.

ReportScreen.h

@interface ReportScreen : UIViewController <UIImagePickerControllerDelegate, UITextViewDelegate, MBProgressHUDDelegate, SoapDelegate, MapLocationChoiceDelegate>
// ...
@property (nonatomic, retain) MKPointAnnotation *annotation;
@property (nonatomic, retain) IBOutlet UITextView *textView;
@property (nonatomic, retain) IBOutlet UIButton *cameraButton;
@property (nonatomic, retain) IBOutlet UIButton *libraryButton;
@property (nonatomic, retain) IBOutlet UIButton *locationButton;
@property (nonatomic, retain) IBOutlet UIButton *sendButton;

@end

ReportScreen.m

@implementation ReportScreen

@synthesize annotation;
@synthesize textView;
@synthesize cameraButton;
@synthesize libraryButton;
@synthesize locationButton;
@synthesize sendButton;

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Here I used to store the VC's state to a file but it shouldn't be needed now that I'm assigning it as delegate and said delegate seems to still be there even after a memory warning.
}

- (void)viewDidLoad {
    [super viewDidLoad];

    placeholderText = @"Tell us what's wrong…";
    textView.text = placeholderText;
    self.annotation = nil;
    [self isReadyToSubmit];

    hud = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
    [self.navigationController.view addSubview:hud];
    hud.delegate = self;
    hud.labelText = @"Invio in corso…";
    hud.dimBackground = YES;
}

- (void)viewDidUnload {
    [super viewDidUnload];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // Here I used to restore the state of the VC from file but… y'know.
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self isReadyToSubmit];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:@"goToMap"]) {
        MapScreen *vc = (MapScreen *)segue.destinationViewController;

// HERE's the magic
        vc.mapLocationChoiceDelegate = self;
// MAGIC ends

        if(self.annotation != nil) {
            vc.annotations = [[NSMutableArray alloc] init];
            [vc.annotations addObject:self.annotation];
        }
    }
}

- (BOOL)isReadyToSubmit {
    if(self.annotation != nil) {
        locationButton.highlighted = YES;
    }
    if(![textView.text isEqualToString:placeholderText] && self.annotation != nil) {
        [sendButton setEnabled:YES];
    } else {
        [sendButton setEnabled:NO];
    }
    return [sendButton isEnabled];
}

- (void)textViewDidBeginEditing:(UITextView *)theTextView {
    if([theTextView.text isEqualToString:placeholderText]) {
        theTextView.text = @"";
    }
    UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(didFinishEditing:)];
    [self.navigationItem setRightBarButtonItem:done animated:YES];
}

- (void)textViewDidEndEditing:(UITextView *)theTextView {
    if([theTextView.text isEqualToString:@""]) {
        theTextView.text = placeholderText;
    }
    [self isReadyToSubmit];
}

- (void)didFinishEditing:(id)sender {
    [self.navigationItem setRightBarButtonItem:nil animated:YES];
    [self.textView resignFirstResponder];
}

// THIS is my delegate protocol's method
- (void)locationChosen:(MKPointAnnotation *)theAnnotation {
    self.annotation = theAnnotation;
    NSLog(@"R: %@", textView.text);
}

@end

MapScreen.h

@protocol MapLocationChoiceDelegate <NSObject>
- (void)locationChosen:(MKPointAnnotation *)annotation;
@end

// ---

@interface MapScreen : UIViewController <MKMapViewDelegate>

- (void)handleLongPress:(id)sender;

@property (nonatomic, retain) NSMutableArray *annotations;
@property (nonatomic, retain) IBOutlet MKMapView *mapView;

@property (weak) id<MapLocationChoiceDelegate> mapLocationChoiceDelegate;

@end

MapScreen.m

@implementation MapScreen

@synthesize annotations;
@synthesize mapView;
@synthesize mapLocationChoiceDelegate;

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidLoad {
    [super viewDidLoad];

    UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
    lpgr.minimumPressDuration = 1.0;
    [self.mapView addGestureRecognizer:lpgr];

    [mapView addAnnotations:self.annotations];
}

- (void)viewDidUnload {
    [super viewDidUnload];
}


#pragma mark - Map handling

- (void)handleLongPress:(id)sender {
    if(![sender isKindOfClass:[UILongPressGestureRecognizer class]]) {
        return;
    }

    UILongPressGestureRecognizer *gr = (UILongPressGestureRecognizer *)sender;
    if (gr.state != UIGestureRecognizerStateBegan) {
        return;
    }

    CGPoint touchPoint = [gr locationInView:self.mapView];   
    CLLocationCoordinate2D touchMapCoordinate = [self.mapView convertPoint:touchPoint toCoordinateFromView:self.mapView];

    MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
    annotation.coordinate = touchMapCoordinate;
    self.annotations = [NSMutableArray arrayWithArray:[mapView annotations]];
    for(id a in self.annotations) {
        if(![a isKindOfClass:[MKUserLocation class]]) {
            [mapView removeAnnotation:a];
        }
    }
    [mapView addAnnotation:annotation];
    self.annotations = [NSMutableArray arrayWithArray:[mapView annotations]];
    // NSDictionary *userInfo = [NSDictionary dictionaryWithObject:annotation forKey:@"annotation"];
    // [[NSNotificationCenter defaultCenter] postNotificationName:@"PositionChosen" object:nil userInfo:userInfo];
    [self.mapLocationChoiceDelegate locationChosen:annotation];
    NSLog(@"M: %@", ((ReportScreen *)self.mapLocationChoiceDelegate).textView.text);
}

- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if([annotation isKindOfClass:[MKUserLocation class]]) {
        return nil;
    }
    static NSString *AnnotationIdentifier = @"Annotation";
    MKPinAnnotationView* pinView = (MKPinAnnotationView *)[theMapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
    if (!pinView) {
        pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
        pinView.pinColor = MKPinAnnotationColorRed;
        pinView.canShowCallout = YES;
        pinView.animatesDrop = YES;
    } else {
        pinView.annotation = annotation;
    }
    return pinView;
}

@end

The issue is:

  • ReportScreen pushes (performs segue to, actually) the MapScreen.
  • If I have some data in the UITextView or if I set some state to the buttons in the ReportScreen and I get a memory warning while the MapScreen is pushed, once I go back to the ReportScreen, all those fields don't show those settings. Apparently textView.text is still set, and so are the states of the buttons, they're just not shown.

Question: why?

Community
  • 1
  • 1
Morpheu5
  • 2,730
  • 5
  • 29
  • 64
  • Are there times your don't get a memory warning and it works properly? I also added mapkit as a tag to your question. – T.J. Feb 20 '12 at 18:56
  • Yes, if I don't get memory warnings, it works perfectly. The problem is that MapKit almost always makes the app receive memory warnings. Thanks for the tag :) – Morpheu5 Feb 20 '12 at 19:47
  • I'm beginning to suspect it may be because I do all those things in ReportScreen::viewDidLoad and ReportScreen::isReadyToSubmit… it's just that I don't know where else to perform all those tricks. Anyway, here's a video http://www.youtube.com/watch?v=F5_8MU83r3M that shows the misbehaviour. It's still processing but it should become available soon. – Morpheu5 Feb 20 '12 at 20:15
  • Nearly all the properties I create with ARC are "@property (strong, non atomic)". Why are you using "@property (nonatomic, retain)"? – T.J. Feb 20 '12 at 20:55
  • Old habits I guess. I used to do that back in the days before ARC, then I dived into ARC and Storyboards. I should try changing them. **EDIT** Just tried that, didn't make any difference… **MORE EDIT** http://stackoverflow.com/questions/7796476/property-definitions-with-arc-strong-or-retain This says retain equals strong. – Morpheu5 Feb 20 '12 at 20:58
  • Of course I forgot to mention that if I comment the [super didReceiveMemoryWarning] I don't lose anything, though I think this is bad behaviour. – Morpheu5 Feb 21 '12 at 19:51

0 Answers0