MKMapView addAnnotation not on the MapView - objective-c

I need some help because i can't to display annotation in my mapView.
I'm trying to update the annotations with this function :
- (void)addAnnotationsInMap:(NSMutableDictionary *)dico
{
NSLog(#"Agences Dictionary dico4324 : %#", dico);
if ([dico count] > 0)
{
NSLog(#"Count : %d", [dico count]);
for(int i = 0; i < [dico count]; i++)
{
CGFloat latDelta = [[[dico objectForKey:[NSString stringWithFormat:#"%d", i]] objectForKey:#"latitude"] floatValue];
CGFloat longDelta = [[[dico objectForKey:[NSString stringWithFormat:#"%d", i]] objectForKey:#"longitude"] floatValue];
CLLocationCoordinate2D newCoord =
{
(latDelta),
(longDelta)
};
MapPointAnnotations *mp = [[MapPointAnnotations alloc]
initWithCoordinate:newCoord
title:[[dico objectForKey:[NSString stringWithFormat:#"%d", i]] objectForKey:#"name"]
subTitle:[[dico objectForKey:[NSString stringWithFormat:#"%d", i]] objectForKey:#"street"]];
[agenceMapView addAnnotation:mp];
}
}
}
If i call my function in the same class (LocalizeViewController) with [self addAnnotationsInMap:Dico], the annotations are on the mapView (agenceMapView).
I need to call my function from an other class (RightSideBarViewController), but the annotations not display on the mapView if i call on the RightSideBarViewController class.
Where i call the function addAnnotationsInMap (Class RightSideBarViewController) :
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = #"LocaliserTop";
UIStoryboard *storyboard;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
storyboard = [UIStoryboard storyboardWithName:#"iPhone" bundle:nil];
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
storyboard = [UIStoryboard storyboardWithName:#"iPad" bundle:nil];
}
LocalizeViewController *localizeViewController = (LocalizeViewController *)[storyboard instantiateViewControllerWithIdentifier:identifier];
[self.slidingViewController anchorTopViewOffScreenTo:ECLeft animations:nil onComplete:^{
CGRect frame = self.slidingViewController.topViewController.view.frame;
self.slidingViewController.topViewController = localizeViewController;
self.slidingViewController.topViewController.view.frame = frame;
[self.slidingViewController resetTopView];
}];
[localizeViewController addAnnotationsInMap:agencesDictionary];
}
Do you have some ideas ?

You should not call
[localizeViewController addAnnotationsInMap:agencesDictionary];
right after
LocalizeViewController *localizeViewController = (LocalizeViewController *)[storyboard instantiateViewControllerWithIdentifier:identifier];
because agenceMapView is still nil. So you are basically doing
[nil addAnnotation:mp];
To correct that, you should wait until the localizeViewController loads from the nib file (which take some time).
For example, you can put
localizeViewController.annotations = agencesDictionary;
instead of
[localizeViewController addAnnotationsInMap:agencesDictionary];
Then in viewDidLoad
[self addAnnotationsInMap:annotations];

Related

Set TV Menu Button To Go Back One Screen

My Apple TV app lists a collection of PDFs, and clicking one draws it on the screen. For some reason, though, it exits the app completely when someone hits the < / Menu button on the Apple TV Remote. What is going on to cause it to do that?
Up first is the code where it pulls up the list of all the PDFs, followed by the code for displaying the PDF.
-(void)viewDidLoad {
[super viewDidLoad];
self.definesPresentationContext = YES; // know where you want UISearchController to be displayed
}
- (void)viewWillAppear:(BOOL)animated {
if (self.searchControllerWasActive) {
self.searchController.active = self.searchControllerWasActive;
_searchControllerWasActive = NO;
if (self.searchControllerSearchFieldWasFirstResponder) {
[self.searchController.searchBar becomeFirstResponder];
_searchControllerSearchFieldWasFirstResponder = NO;
}
}
NSBundle *bundle = [NSBundle mainBundle];
self.files = [bundle pathsForResourcesOfType:#"pdf" inDirectory:#"AIMPDF"];
NSString *documentsDirectoryPath = [self.files objectAtIndex:thepath.row];
self.title = #"Devo Songs";
self.filenames = [[documentsDirectoryPath lastPathComponent] stringByDeletingPathExtension];
NSLog(#"%#", filenames);
NSMutableArray *names = [NSMutableArray arrayWithCapacity:[self.files count]];
for (NSString *path in self.files) {
[names addObject:[[path lastPathComponent] stringByDeletingPathExtension]];
}
self.files = names;
self.files = [names sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
self.tableView.backgroundColor = [UIColor whiteColor];
self.parentViewController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"iphonebackground.png"]];
[super viewDidLoad];
[super viewWillAppear:animated];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// update the filtered array based on the search text
NSString *searchText = searchController.searchBar.text;
NSMutableArray *searchResults2 = [self.files mutableCopy];
// strip out all the leading and trailing spaces
NSString *strippedString = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// break up the search terms (separated by spaces)
NSArray *searchItems = nil;
if (strippedString.length > 0) {
searchItems = [strippedString componentsSeparatedByString:#" "];
}
// build all the "AND" expressions for each value in the searchString
//
NSMutableArray *andMatchPredicates = [NSMutableArray array];
for (NSString *searchString in searchItems) {
NSPredicate *sPredicate =
[NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchString];
[searchResults2 filterUsingPredicate:sPredicate];
// at this OR predicate to our master AND predicate
// NSCompoundPredicate *orMatchPredicates = [NSCompoundPredicate orPredicateWithSubpredicates:searchItemsPredicate];
//[andMatchPredicates addObject:orMatchPredicates];
}
// match up the fields of the Product object
// NSCompoundPredicate *finalCompoundPredicate =
//[NSCompoundPredicate andPredicateWithSubpredicates:andMatchPredicates];
//searchResults2 = [[searchResults filteredArrayUsingPredicate:finalCompoundPredicate] mutableCopy];
// hand over the filtered results to our search results table
APLResultsTableController *tableController = (APLResultsTableController *)self.searchController.searchResultsController;
tableController.filteredProducts = searchResults2;
[tableController.tableView reloadData];
}
- (void)handleSearchForTerm:(NSString *)searchTerm
{
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
array = nil;
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (NSString *currentString in [self files])
{
if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
{
[[self searchResults] addObject:currentString];
}
}
}
}- (void)viewDidUnload
{
[super viewDidUnload];
// Save the state of the search UI so that it can be restored if the view is re-created.
[self setSavedSearchTerm:[[[self searchDisplayController] searchBar] text]];
[self setSearchResults:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
// The device is an iPad running iPhone 3.2 or later.
return YES;
}
else
{
// The device is an iPhone or iPod touch.
return YES;
}
#else
// iPhone simulator
return YES;
#endif
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSInteger rows;
rows = [[self files] count];
return rows;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *filename = [[[self.files objectAtIndex:indexPath.row] lastPathComponent] stringByDeletingPathExtension];
NSInteger row = [indexPath row];
NSString *contentForThisRow = nil;
contentForThisRow = filename;
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[[cell textLabel] setText:contentForThisRow];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:90];
cell.textLabel.textColor = [UIColor blackColor];
cell.backgroundColor = [UIColor lightGrayColor];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
return 80;
}
else {
return 120;
}
}
- (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
//this gives you the indexpath of the focused cell
NSIndexPath *nextIndexPath = [context nextFocusedIndexPath];
NSLog(#"Do Something");
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedCountry = (tableView == self.tableView) ?
self.files[indexPath.row] : self.resultsTableController.filteredProducts[indexPath.row];
[self performSegueWithIdentifier:#"ShowSong" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"ShowSong"])
{
NSLog(#"Selecting %#", self.selectedCountry);
FirstViewController* userViewController = [segue destinationViewController];
userViewController.selectedCountry = self.selectedCountry;
//if you need to pass data to the next controller do it here
}
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)dealloc {
}
#end
And now the code for opening:
#implementation FirstViewController
- (CGPDFDocumentRef)openPDFLocal:(NSString *)pdfURL {
NSURL* NSUrl = [NSURL fileURLWithPath:pdfURL];
return [self openPDF:NSUrl];
}
- (CGPDFDocumentRef)openPDFURL:(NSString *)pdfURL {
NSURL* NSUrl= [NSURL URLWithString:pdfURL];
return [self openPDF:NSUrl];
}
- (CGPDFDocumentRef)openPDF:(NSURL*)NSUrl {
CFURLRef url = (CFURLRef)CFBridgingRetain(NSUrl);
CGPDFDocumentRef myDocument;
myDocument = CGPDFDocumentCreateWithURL(url);
if (myDocument == NULL) {
NSLog(#"can't open %#", NSUrl);
CFRelease (url);
return nil;
}
CFRelease (url);
if (CGPDFDocumentGetNumberOfPages(myDocument) == 0) {
CGPDFDocumentRelease(myDocument);
return nil;
}
return myDocument;
}
- (void)drawDocument:(CGPDFDocumentRef)pdfDocument
{
// Get the total number of pages for the whole PDF document
int totalPages= (int)CGPDFDocumentGetNumberOfPages(pdfDocument);
self.pages = totalPages;
NSMutableArray *pageImages = [[NSMutableArray alloc] init];
// Iterate through the pages and add each page image to an array
for (int i = 1; i <= totalPages; i++) {
// Get the first page of the PDF document
CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, i);
CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
// Begin the image context with the page size
// Also get the grapgics context that we will draw to
UIGraphicsBeginImageContext(pageRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// Rotate the page, so it displays correctly
CGContextTranslateCTM(context, 0.0, pageRect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, pageRect, 0, true));
// Draw to the graphics context
CGContextDrawPDFPage(context, page);
// Get an image of the graphics context
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[pageImages addObject:image];
}
// Set the image of the PDF to the current view
[self addImagesToScrollView:pageImages];
}
-(void)addImagesToScrollView:(NSMutableArray*)imageArray {
int heigth = 0;
for (UIImage *image in imageArray) {
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
imgView.frame=CGRectMake(200, heigth, 1520, 1080);
[_scrollView addSubview:imgView];
heigth += imgView.frame.size.height;
}
}
-(void)viewDidLayoutSubviews {
NSLog(#"%ld", (long)self.pages);
_scrollView.contentSize = CGSizeMake(1920, 1080*self.pages);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"DOCUMENTS%#", self.selectedCountry);
NSString *testing = [self.selectedCountry stringByAppendingString:#".pdf"];
//This is passed in from a tableview after selecting the PDF needed.
_scrollView.panGestureRecognizer.allowedTouchTypes = #[ #(UITouchTypeIndirect) ];
NSString *Documents = [[NSBundle mainBundle] pathForResource:self.selectedCountry ofType:#"pdf" inDirectory:#"AIMPDF"];
NSLog(#"OKOKOK%#", Documents);
NSURL *url = [NSURL fileURLWithPath:Documents];
self.view.backgroundColor = [UIColor blackColor];
CGPDFDocumentRef pdfDocument = [self openPDF:url];
[self drawDocument:pdfDocument];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
In your case the searching view controller stays on the top level of your app that's why the app is closed by pressing Menu button instead of returning to your start screen. On tvOS you should not use UISearchController directly and call
[self.searchController.searchBar becomeFirstResponder]; or self.searchController.active = YES; to present searching because it breaks a stacked view hierarchy that allows you to navigate upper by presented view controllers.
On Apple TV, people typically navigate by moving through stacked screens of content. Each screen may present entry points to other screens, and provides a way — through the remote — to return to the previous screen or main menu.
https://developer.apple.com/design/human-interface-guidelines/tvos/app-architecture/navigation/
There is UISearchContainerViewController view controller that manages the presentation of search results in your interface and you can use it for searching:
In tvOS, rather than push a UISearchController onto a navigation controller’s stack or use one as a child of another container view controller, embed an instance of this class and let it manage the presentation of the search controller’s content. https://developer.apple.com/documentation/uikit/uisearchcontainerviewcontroller
For instance:
UITableViewController* searchTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SearchTableViewController"];
UISearchController* searchController = [[UISearchController alloc] initWithSearchResultsController:searchTableViewController];
searchController.delegate = self;
searchController.searchResultsUpdater = self;
searchController.searchBar.delegate = self;
self.searchContainerViewController = [[UISearchContainerViewController alloc] initWithSearchController:searchController];
// Show searching
[self presentViewController:self.searchContainerViewController animated:YES completion:nil];

UITableView reloadData lose elements from cell

I have a UITableView and his datasource is an NSMutableArray declared in my interface:
#property (strong, nonatomic) NSMutableArray *arrElements;
Now I implemented a simple "load more" in this way:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
if (endScrolling >= scrollView.contentSize.height)
{
//only if i have others results i will call load more
if([self.items_amount integerValue] > self.arrElements.count) {
if(DEBUG_MODE == 1) {
NSLog(#"Load more");
}
//get start param from array size and call load more
NSNumber *start = [NSNumber numberWithInteger:([self.arrElements count]+1)];
NSArray *passParams = [NSArray arrayWithObjects:self.menuItem,start,[NSNumber numberWithInteger:NUM_RESULTS_FOR_PAGE], nil];
[self performSelector:#selector(loadMore:) withObject:passParams afterDelay:0.1];
}
}
}
and this is my loadMore method:
//load more elements
- (void)loadMore:(NSArray *)arrParams {
//(MenuItem *)menuItem startingFrom:(NSNumber *)start numResults:(NSNumber *)results;
MenuItem *menuItem = [arrParams objectAtIndex:0];
NSNumber *start = [arrParams objectAtIndex:1];
NSNumber *results = [arrParams objectAtIndex:2];
if(DEBUG_MODE == 1) {
NSLog(#"Before load more %lu", (unsigned long)[self.arrElements count]);
}
//call API and parse it
WebServicesClient *restClient = [[WebServicesClient alloc] init];
NSData *data = [restClient callWorkAPI:[menuItem pathAPI] inLanguage:[[NSLocale preferredLanguages] objectAtIndex:0] withLat:self.latitude withLng:self.longitude startingFrom:start numRows:results];
for(Work* work in [[restClient parseWorks:data] objectForKey:#"items"]) {
[self.arrElements addObject:work];
}
if(DEBUG_MODE == 1) {
NSLog(#"After load more %lu", (unsigned long)[self.arrElements count]);
}
[self.tableElem reloadData];
}
And this is my custom cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier;
CellIdentifier = #"HomeCell";
HomeCell *cell = (HomeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Work *work = (Work *)[[self arrElements] objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor clearColor];
cell.labelTitleItem.text = [work title];
cell.labelSubtitleItem.text = #"my category"
//if exists image
if([[work image] isKindOfClass:[NSString class]] && [[work image] length] > 0) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:[work image]]];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageItem.image = [UIImage imageWithData: data];
});
});
} else {
//remove image setting height to 0
[cell.imageItem setFrame:CGRectMake(cell.imageItem.frame.origin.x, cell.imageItem.frame.origin.y, cell.imageItem.frame.size.width, 0)];
}
if([[work distance] isKindOfClass:[NSString class]]) {
[cell.imagePriority setBackgroundColor:[UIColor lightGrayColor]];
cell.labelDistanceItem.text = [self convertDistance:[work distance]];
cell.labelDistanceItem.textColor = [UIColor whiteColor];
} else {
//remove image setting height to 0
[cell.imagePriority setFrame:CGRectMake(cell.imagePriority.frame.origin.x, cell.imagePriority.frame.origin.y, cell.imagePriority.frame.size.width, 0)];
//remove label distance setting height to 0
[cell.labelSubtitleItem setFrame:CGRectMake(cell.labelSubtitleItem.frame.origin.x, cell.labelSubtitleItem.frame.origin.y, cell.labelSubtitleItem.frame.size.width, 0)];
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self arrElements] count];
}
Now the problem is that after reloadData i lose the text of a UILabel (my category) of my CustomCell
please, Any suggests?
I've had similar problems with TalbeViews. Try using the method
- (void) tableView:(UITableView *)tableView willDisplayCell:(RCGameTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
to add the elements that you want. Keep the cell initialization that you do at the beginning of cellForRowAtIndexPath, but then return the cell right after and set the background color, labels, images, etc. in the willDisplayCell delegate function I mentioned.

pushViewController:detail not pushing detailView

I had my app navigating views perfectly. Now, for some reason that I can't figure out, my detailView is not presenting on the pushViewController:detail method in my modal view.
I cannot figure out why it's not working any more. Any help would be appreciated. Thanks.
Here's the method:
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 1){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 2){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 3){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 4){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
}
Here's the class code. I'm not sure if I need to pass in a navigationController with modalView:
//
// ModalView.m
// DiningLog
//
// Created by Eric Rea on 10/10/11.
// Copyright 2011 Avid. All rights reserved.
//
#import "ModalView.h"
#import "DetailView.h"
#implementation ModalView
#synthesize tableView, excersizeName, numSets, time, restTime, dateFormatter, rating, excersizeArray, plistArray, numberWithBool;
-(IBAction) cancel:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
-(IBAction) save:(id)sender{
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"ExcersizeList.plist"];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"Excersizes" ofType:#"plist"];
}
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property list into dictionary object
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp)
{
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
// assign values
self.plistArray = [NSMutableArray arrayWithArray:[temp objectForKey:#"Excersizes"]];
NSLog(#"The contents of plistArray is%#", plistArray);
// set the variables to the values in the text fields
self.excersizeArray = [[NSMutableArray alloc] initWithCapacity:4];
[excersizeArray addObject:excersizeName];
[excersizeArray addObject:numSets];
[excersizeArray addObject:time];
[excersizeArray addObject:restTime];
[plistArray addObject:excersizeArray];
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: plistArray, nil] forKeys:[NSArray arrayWithObjects: #"Excersizes", nil]];
NSString *error = nil;
// create NSData from dictionary
// NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
// check is plistData exists
if(plistDict)
{
// write plistData to our Data.plist file
[plistDict writeToFile:plistPath atomically:YES];
}
else
{
NSLog(#"Error in saveData: %#", error);
[error release];
}
[self dismissModalViewControllerAnimated:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tView {
// Return the number of sections.
return 1;
}
-(void)setObject:(id)object forNum:(int)num{
if(num == 0){
self.excersizeName = object;
NSLog(#"res %#", self.excersizeName);
}else if(num == 1){
self.numSets = object;
NSLog(#"res %#", self.numSets);
}else if(num == 2){
self.time = object;
NSLog(#"res %#", self.time);
}else if(num == 3){
self.restTime = object;
NSLog(#"res %#", self.restTime);
}else if(num == 4){
self.rating = [object floatValue];
}
[tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 5;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
}
if(indexPath.row == 0){
cell.textLabel.text = #"Excersize";
cell.detailTextLabel.text = excersizeName;
}
if(indexPath.row == 1){
cell.textLabel.text = #"Sets";
cell.detailTextLabel.text = numSets;
}
if(indexPath.row == 2){
cell.textLabel.text = #"Time";
cell.detailTextLabel.text = time;
}
if(indexPath.row == 3){
cell.textLabel.text = #"Rest";
cell.detailTextLabel.text = restTime;
}
if(indexPath.row == 4){
cell.textLabel.text = #"Rating";
cell.detailTextLabel.text = [NSString stringWithFormat:#"%f",rating];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (NSDateFormatter *)dateFormatter {
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
}
return dateFormatter;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 1){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 2){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 3){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 4){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
}
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (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)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Have you debugged and checked that your navigationController isn't nil ?
I figured it out. I accidentally erased the method insertNewObject in my rootViewController. When I rewrote it, I forgot to add in ModalView * modal = [[ModalView alloc] init];. That was the problem.
Here's what the method looks like now that it's working:
- (void)insertNewObject {
ModalView * modal = [[ModalView alloc] init];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:modal];
[self presentModalViewController:controller animated:YES];
}

how to put MKAnnotation without affecting the MKMapView performance

I have more than 2800 locations to be put on my map.
But when i am putting them the map is freezing. i can do nothing but wait until all the annotation data is available.
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
NSAutoreleasePool *pool_mr = [[NSAutoreleasePool alloc] init];
NSLog(#"mapView:regionDidChangeAnimated:");
NSLog(#"latitude: %f, longitude: %f", regionsMapView.centerCoordinate.latitude, regionsMapView.centerCoordinate.longitude);
NSLog(#"latitudeDelta: %f, longitudeDelta: %f", regionsMapView.region.span.latitudeDelta, regionsMapView.region.span.longitudeDelta);
if (regionsMapView.region.span.latitudeDelta < 0.007) {
NSLog(#"SHOW ANNOTATIONS");
NSArray *annotations = [regionsMapView annotations];
AddressAnnotation *annotation = nil;
for (int i=0; i<[annotations count]; i++)
{
NSLog(#"%i", i);
annotation = (AddressAnnotation*)[annotations objectAtIndex:i];
[[regionsMapView viewForAnnotation:annotation] setHidden:NO];
}
}else {
NSLog(#"HIDE ANNOTATIONS");
NSArray *annotations = [regionsMapView annotations];
AddressAnnotation *annotation = nil;
for (int i=0; i<[annotations count]; i++)
{
NSLog(#"%i", i);
annotation = (AddressAnnotation*)[annotations objectAtIndex:i];
[[regionsMapView viewForAnnotation:annotation] setHidden:YES];
}
}
[pool_mr release];
}
And the Another method is like below:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation, AddressAnnotation>) annotation {
//NSAutoreleasePool *pool5 = [[NSAutoreleasePool alloc] init];
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]]){
NSLog(#"MKUserLocation");
return nil;
}
else {
NSLog(#"mapView:viewForAnnotation>>>");
NSLog(#"%#", [annotation markerColor]);
NSLog(#"image: %#", [NSMutableString stringWithFormat:#"MKPinAnnotationView_%#.png",[annotation markerColor]]);
MKPinAnnotationView *annView=[[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:[annotation markerColor]] autorelease];
//annView.pinColor = MKPinAnnotationColorPurple;
UIImage *annotationImage = [[UIImage imageNamed:[NSMutableString stringWithFormat:#"MKPinAnnotationView_%#.png",[annotation markerColor]]] autorelease];
annView.image = annotationImage;
annView.animatesDrop = NO;
annView.canShowCallout = YES;
//annView.draggable = NO;
//annView.highlighted = NO;
annView.calloutOffset = CGPointMake(-5, 5);
return annView;
}
//[pool5 release];
NSLog(#"<<<mapView:viewForAnnotation");
return nil;
}
With that number of annotations, I would cluster them so as you zoom in, you get more detail. I put several thousand on a map that way and it works a treat. There is lots of information about map pin clustering if you search for it.
Here's one commercial option for example (no connection, haven't used) but if you look around you'll see plenty of information on how to implement it yourself.

Problems Removing Annotations from a MKMapView

I am trying to remove all the annotations of a map. The class that contains the MKMapView implements the MKMapViewDelegate. I am calling the remove all annotations method when a button (displayed in a modal view) is clicked. I am using the next code to remove all the annotations.
- (void)removeAllAnnotations {
NSMutableArray *annotationsToRemove = [NSMutableArray arrayWithCapacity:[self.mapView.annotations count]];
for (int i = 0; i < [self.mapView.annotations count]; i++) {
if ([[self.mapView.annotations objectAtIndex:i] isKindOfClass:[AddressAnnotation class]]) {
[annotationsToRemove addObject:[self.mapView.annotations objectAtIndex:i]];
}
}
[self.mapView removeAnnotations:annotationsToRemove];
}
The code works right but after calling the method, and when I try to add new annotations to the empty map, the class does not call to the viewForAnnotations method and the annotations do not drop down and do not show a disclosure button into the annotation view. Why is this happening?
Thanks for reading.
Edited:
The annotations are shown but with out calling the view for annotation method (with out dropping down and with out including a disclosure button into the annotation view). Here is the method that I use to add the annotations and the viewForAnnotation method.
- (void)loadAnnotations:(NSString *)type {
NSString *path = [[NSBundle mainBundle] pathForResource:#"PlacesInformation" ofType:#"plist"];
NSMutableArray *tmpArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
for (int i = 0; i < tmpArray.count; i++) {
// Breaks the string down even further to latitude and longitude fields.
NSString *coordinateString = [[tmpArray objectAtIndex:i] objectForKey:#"coordinates"];
NSString *option = [[tmpArray objectAtIndex:i] objectForKey:#"type"];
if ([option isEqualToString:type]) {
CLLocationCoordinate2D currentCoordinate = [self stringToCoordinate:coordinateString];
AddressAnnotation *annotation = [[[AddressAnnotation alloc] initWithCoordinate:currentCoordinate] autorelease];
[self.mapView addAnnotation:annotation];
}
}
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
else { // Handles the other annotations.
// Try to dequeue an existing pin view first.
static NSString *AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView) {
// If an existing pin view was not available, creates one.
MKPinAnnotationView *customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
// Adds a detail disclosure button.
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
} else
pinView.annotation = annotation;
}
return nil;
}
In viewForAnnotation, in the case where you are reusing a view, you are currently returning nil.
This else part:
} else
pinView.annotation = annotation;
Should probably be:
} else {
pinView.annotation = annotation;
return pinView;
}