[EDIT]
Ok I found the problem, I was just calling the bad connection request of my web service. So downloading a blog would erase the articles list content. Time for a break :p
#
I'm upgrading an old app which is a simple RSS reader with a list of articles and a list of blogs. Each of these is a UITableView with its own UITableViewController.
Both of them retrieve data from a JSON file on my server.
At the end of the JSON parsing I update the dataSources and then call the reloadData method on both tableviews. The problem is that the articles list is filled with the blogs and the blog list isn't filled at all.
If I don't call reloadData on the blog tableview, the article one is filled correctly and works well. As seen on an other post I've tried with the tableview.tag identifier but it doesn't work.
Note: I'm not using IB.
Here is the code for the BlogTableViewController:
#implementation BlogsTVC
#synthesize dataSourceForBlogs;
#synthesize blogRec;
- (id)initWithStyle:(UITableViewStyle)style
{
if ((self = [super initWithStyle:style])) {
self.title = #"Blogs";
self.tableView.tag = 2;
self.tableView.delegate = self;
dataSourceForBlogs = [[NSMutableArray alloc] init];
// Register to notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(callback_blogs:) name:#"blogs" object:nil ];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(connection_error:) name:#"connection_error" object:nil];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self refreshBlogs];
}
-(void)callback_blogs:(NSNotification *)notification
{
if([self.dataSourceForBlogs count] > 0)
{
NSInteger i, count = [self.dataSourceForBlogs count];
for(i=0; i < count; i++)
{
[[self.dataSourceForBlogs objectAtIndex:i] release];
}
[self.dataSourceForBlogs removeAllObjects];
}
//remplissage
NSArray *receivedDatas = [[notification userInfo] objectForKey:#"data"];
NSUInteger i, count = [receivedDatas count];
for(i=0; i<count; i++)
{
self.blogRec = [[BlogRecord alloc] init];
self.blogRec.blog_id_auteur = [[receivedDatas objectAtIndex:i] objectForKey:#"id"];
self.blogRec.blog_auteur = [[receivedDatas objectAtIndex:i]objectForKey:#"auteur"];
self.blogRec.blog_url = [[receivedDatas objectAtIndex:i]objectForKey:#"url"];
self.blogRec.blog_date = [[receivedDatas objectAtIndex:i] objectForKey:#"date"];
self.blogRec.blog_nb_pub = [[receivedDatas objectAtIndex:i] objectForKey:#"nb_publication"];
self.blogRec.blog_url_image = [[receivedDatas objectAtIndex:i] objectForKey:#"theme"];
[self.dataSourceForBlogs addObject:self.blogRec];
self.blogRec = nil;
}
[self.tableView reloadData];
}
Here is the code for the Articles:
#implementation ActualiteTVC
#synthesize dataSource;
#synthesize artRec;
#pragma mark -
#pragma mark Initialization
- (id)initWithStyle:(UITableViewStyle)style {
// Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
if ((self = [super initWithStyle:style])) {
// Titles
self.title = #"Actualités";
self.tableView.tag = 1;
// Register to notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(callback_general:) name:#"general" object:nil ];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(connection_error:) name:#"connection_error" object:nil];
self.dataSource = [[NSMutableArray alloc] init];
}
return self;
}
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[self refreshNews];
}
-(void)callback_general: (NSNotification *) notification
{
if ([self.dataSource count] > 0) {
NSUInteger i, count = [self.dataSource count];
for (i = 0; i < count; i++) {
[[self.dataSource objectAtIndex:i] release];
}
[self.dataSource removeAllObjects];
}
NSArray *receivedDatas = [[notification userInfo] objectForKey:#"data"];
NSUInteger i, count = [receivedDatas count];
for (i = 0; i < count; i++) {
self.artRec = [[ArticleRecord alloc] init];
self.artRec.art_id = [[receivedDatas objectAtIndex:i] objectForKey:#"id"];
self.artRec.art_auteur = [[receivedDatas objectAtIndex:i] objectForKey:#"auteur"];
self.artRec.art_categorie = [[receivedDatas objectAtIndex:i] objectForKey:#"categorie"];
self.artRec.art_date = [[receivedDatas objectAtIndex:i] objectForKey:#"date"];
//self.artRec.art_texte = [[receivedDatas objectAtIndex:i] objectForKey:#"texte"];
self.artRec.art_titre = [[receivedDatas objectAtIndex:i] objectForKey:#"titre"];
self.artRec.art_url_auteur = [[receivedDatas objectAtIndex:i] objectForKey:#"url_auteur"];
self.artRec.art_url = [[receivedDatas objectAtIndex:i] objectForKey:#"url"];
self.artRec.art_url_img = [[receivedDatas objectAtIndex:i] objectForKey:#"image"];
[self.dataSource addObject:self.artRec];
self.artRec = nil;
}
[self.tableView reloadData];
}
Finally here is how I add these TableViews in the TabBar:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 0
//articles
ActualiteTVC *actualiteTVC = [[ActualiteTVC alloc] init];
UINavigationController *actualiteNC = [[UINavigationController alloc] initWithRootViewController:actualiteTVC];
[actualiteTVC release];
actualiteNC.tabBarItem.title = #"Actualités";
actualiteNC.tabBarItem.image = [UIImage imageNamed:#"08-chat.png"];
[actualiteNC.navigationBar setBarStyle:UIBarStyleBlack];
//1
//blogs
BlogsTVC *blogsTVC = [[BlogsTVC alloc] init];
UINavigationController *blogsNC = [[UINavigationController alloc] initWithRootViewController:blogsTVC];
[blogsTVC release];
blogsNC.tabBarItem.title = #"Blogs";
blogsNC.tabBarItem.image = [UIImage imageNamed:#"balance.png"];
[blogsNC.navigationBar setBarStyle:UIBarStyleBlack];
// myTabBarController
myTabBarController = [[UITabBarController alloc] init];
[myTabBarController setViewControllers:[NSArray arrayWithObjects:actualiteNC, blogsNC, nil]];
[actualiteNC release];
[blogsNC release];
/*
//fullscreen
CGRect frame = [[UIScreen mainScreen] applicationFrame];
frame.origin.x = 0;
frame.origin.y = 25;
//[baseViewCtrl.view setFrame:frame];
[myTabBarController.view setFrame:frame];
*/
/*
// window
//[window addSubview:myTabBarController.view];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleRemoveLoading:) name:#"removeLoading" object:nil];
loading = [[LoadingVC alloc] init];
[window addSubview:loading.view];
*/
[window addSubview:baseViewCtrl.view];
[window makeKeyAndVisible];
return YES;
}
Related
I am trying to add Carousel on the View as follows. As I testing it, nothing happens, it does not even hit any of carousel delegate method.
ViewController.h
#property (nonatomic, strong) iCarousel *carousel;
ViewController.m
carousel = [[iCarousel alloc] initWithFrame:CGRectMake(25, 50, self.view.frame.size.width-50, self.view.frame.size.height-75)];
[self.view addSubview:carousel];
carousel.delegate = self;
carousel.dataSource = self;
self.carousel.type = iCarouselTypeCoverFlow2;
self.items = [NSMutableArray array];
for (int i = 0; i < 100; i++)
{
[carouselItems addObject:#(i)];
}
[carousel reloadData];
Replace your code with this
self.carousel = [[iCarousel alloc] initWithFrame:CGRectMake(25, 50, self.view.frame.size.width-50, self.view.frame.size.height-75)];
self.carousel.delegate = self;
self.carousel.dataSource = self;
self.carousel.type = iCarouselTypeCoverFlow2;
[self.view addSubview:self.carousel];
self.items = [NSMutableArray array];
for (int i = 0; i < 100; i++)
{
[carouselItems addObject:#(i)];
}
[self.carousel reloadData];
I want to create a quick picture/movie viewer - for a birthday celebration.
First I want to show some pictures - then a movie - and then some pictures again. The first picture animation shows up fine, movie starts fine and catching AVPlayerItemDidPlayToEndTimeNotification just fine to launch pictures again, - but second animation never starts - I cannot work this out ?? - DoShow1 is not working - please advice anybody out there ??
- (void)DoShow
{
NSArray *imageNames = #[#"1.jpg", #"2.jpg", #"3.png", #"4.png",
#"5.png", #"6.png",#"7.png", #"8.png",
#"9.png", #"10.png", #"11.png",#"12.png",
#"13.png"];
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i = 0; i < imageNames.count; i++) {
[images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
_imageview.animationImages = images;
_imageview.animationDuration = 10;
_imageview.animationRepeatCount = 1;
[_imageview startAnimating];
[self performSelector:#selector(playmovie) withObject:nil afterDelay: 10];
}
- (void)DoShow1
{
NSArray *imageNames = #[#"14.jpg", #"16.jpg", #"18.jpg", #"19.jpg",
#"20.jpg", #"22.jpg",#"23.jpg", #"24.jpg"];
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i = 0; i < imageNames.count; i++) {
[images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
_imageview2.animationImages = images;
_imageview2.animationDuration = 2;
_imageview2.animationRepeatCount = 100;
[_imageview2 startAnimating];
}
- (void) playmovie
{
MyMusicPlayerManager *sharedManager = [MyMusicPlayerManager sharedManager];
[sharedManager ChkPaused];
NSBundle *Bundle = [NSBundle mainBundle];
NSString *moviePath = [Bundle pathForResource:#"stine_ane" ofType:#"mp4"];
NSLog(#"String is %#", moviePath);
NSURL *url = [NSURL fileURLWithPath:moviePath];
AVPlayerItem *video = [[AVPlayerItem alloc] initWithURL:url];
AVQueuePlayer *queue = [[AVQueuePlayer alloc] initWithItems:#[video]];
video = [[AVPlayerItem alloc] initWithURL:url];
[queue insertItem:video afterItem:nil];
self.avmovieplayer = [[AVPlayerViewController alloc] init];
self.avmovieplayer.player = queue;
[self presentViewController:self.avmovieplayer animated:YES completion:nil];
self.avmovieplayer.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myMovieFinishedCallback:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[avmovieplayer.player currentItem]];
[self.avmovieplayer setShowsPlaybackControls:YES];
[self.avmovieplayer.player play];
}
- (void)myMovieFinishedCallback:(NSNotification *)notification {
[self dismissViewControllerAnimated:YES completion:Nil];
[self DoShow1];
}
- (IBAction)DoStart:(id)sender {
[self DoShow];
}
[self dismissViewControllerAnimated:YES completion:Nil];
[self DoShow1];
this is probably calling in succession and animation doesnt start at the same time the view is being dismissed.
try it in the completion handler which is called after the view is
dismissed
[self dismissViewControllerAnimated:YES completion:^{
[self DoShow1];
}];
Does anyone know why is appearing white part? My View is already gray, but gets two white pieces
whites: Arrow and final Popover!
[UPDATE]
this is the code that calls the popover and makes the arrow points to the button that was clicked!
- (void) buttonFilter {
if (viewFilter == #"Artistas") {
content = [self.storyboard instantiateViewControllerWithIdentifier:#"TipoArtistaViewController"]; // MUDAR PARA O NOVO FILTRO DE ARTISTAS
} else if (viewFilter == #"Músicas") {
content = [self.storyboard instantiateViewControllerWithIdentifier:#"CategoriaViewController"];
}
[self callFilter:btnFilter Filter:content];
}
- (void)callFilter:(id)sender Filter:(UIViewController *) content{
self.currentPop = popoverController;
popoverController = [[WYPopoverController alloc] initWithContentViewController:content];
UIButton * bt = (UIButton * )sender;
UIView *view = [bt valueForKey:#"view"];
popoverController.popoverContentSize = CGSizeMake(320, 180);
popoverController.delegate = self;
[popoverController presentPopoverFromRect:view.bounds inView:view permittedArrowDirections:WYPopoverArrowDirectionAny animated:YES];
}
the next is where to mount the session:
//extend and collpase
- (void)setupViewController {
categoriaBD = [categoriaDAO selectCategoria];
self.data = [[NSMutableArray alloc] init];
for (int i = 0; i < [categoriaBD count]; i++)
{
NSMutableDictionary * teste = [categoriaBD objectForKey:[NSString stringWithFormat:#"%i", i]];
ID = [[teste objectForKey:#"1"] integerValue];
subcategoriaBD = [categoriaDAO selectSubCategoriaByCategoriaID:ID];
NSMutableArray* section = [[NSMutableArray alloc] init];
for (int j = 0; j < [subcategoriaBD count]; j++)
{
NSMutableDictionary * subCat = [subcategoriaBD objectForKey:[NSString stringWithFormat:#"%i", j]];
[section addObject:[NSString stringWithFormat:[subCat objectForKey:#"1"]]];
}
[self.data addObject:section];
}
self.headers = [[NSMutableArray alloc] init];
for (int i = 0; i < [categoriaBD count]; i++)
{
NSString *inStr = [NSString stringWithFormat: #"%i", (int)i];
nomeCategoria = [categoriaBD objectForKey:inStr];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 310, 40)];
[label setText:[nomeCategoria objectForKey:#"2"]];
UIView* header = [[UIView alloc] init];
[header setBackgroundColor:[UIColor colorWithRed:(226/255.0) green:(226/255.0) blue:(226/255.0) alpha:1]];
[header addSubview:label];
[self.headers addObject:header];
}
}
You can to create a custom UIPopoverBackgroundView subclass that sets the properties of the arrow you want.
popoverController.popoverBackgroundViewClass = [MyPopoverBackgroundView class];
First off: My project is ARC enabled and I'm using storyboard.
I have a view controller that pushes a segue (modal),
[self performSegueWithIdentifier: #"goInitialSettings" sender: self];
there i'm setting some parameters and store them. When the parameters are stored (true a button tap), the app should return to the original viewcontroller.
This i am doing with this command:
[self.presentingViewController dismissViewControllerAnimated:NO completion:^{}];
I'm noticing that the viewcontroller that i dismiss, never deallocs. How does this come?
I'm adding the code of the 'presented viewcontroller' below:
#interface CenterChoiceController ()
{
UIView* _titleBackground;
UILabel* _lblTitle;
UIButton* _btnGaVerder;
UIPickerView* _myPickerView;
NSArray* _centers;
UILabel* _adresLine;
UILabel* _cityLine;
MKPointAnnotation* _point;
MKMapView* _mapView;
UIActivityIndicatorView* _indicator;
UIAlertView* _alert;
GCenter* _center;
DataManager* _dm;
}
#end
#implementation CenterChoiceController
-(void)dealloc
{
NSLog(#"Centerchoice deallocs");
_titleBackground = nil;
_lblTitle = nil;
_btnGaVerder = nil;
_myPickerView = nil;
_point = nil;
_mapView = nil;
_indicator = nil;
_alert = nil;
_centers = nil;
_adresLine = nil;
_cityLine = nil;
_center = nil;
_dm = nil;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_dm = [[DataManager alloc]init];
if([_dm hasConnectivity])
{
[_dm fetchCentersForController:self];
}
else
{
[self pushErrorMessage:NSLocalizedString(#"nointernetconnection", nil)];
}
CAGradientLayer *bgLayer = [BackgroundLayer blueGradient];
bgLayer.frame = self.view.bounds;
[self.view.layer insertSublayer:bgLayer atIndex:0];
_titleBackground = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
_titleBackground.backgroundColor = [GColor blueColor];
[self.view addSubview:_titleBackground];
_lblTitle = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width - 10, 44)];
_lblTitle.textAlignment = NSTextAlignmentRight;
_lblTitle.textColor = [GColor whiteColor];
_lblTitle.text = NSLocalizedString(#"bioscoopkeuze", nil);
[self.view addSubview:_lblTitle];
_btnGaVerder = [[UIButton alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 54, self.view.frame.size.width, 54)];
[_btnGaVerder setTitle:NSLocalizedString(#"gaverder", nil) forState:UIControlStateNormal];
_btnGaVerder.titleLabel.font = [_btnGaVerder.titleLabel.font fontWithSize:12];
_btnGaVerder.backgroundColor = [GColor blueColor];
[_btnGaVerder setTitleColor:[GColor whiteColor] forState:UIControlStateNormal];
[_btnGaVerder setShowsTouchWhenHighlighted:YES];
[_btnGaVerder addTarget:self action:#selector(gaVerder) forControlEvents:UIControlEventTouchUpInside];
_myPickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 44, self.view.frame.size.width, 200)];
}
-(void)showLoading
{
NSLog(#"shows loading");
_indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
CGPoint cntr = self.view.center;
_indicator.center = cntr;
[_indicator startAnimating];
[self.view addSubview:_indicator];
}
-(void)hideLoading
{
NSLog(#"hides loading");
[_indicator removeFromSuperview];
_indicator = nil;
}
-(void)pushData:(NSArray *)data
{
[self.view addSubview:_btnGaVerder];
[self.view addSubview:_myPickerView];
_centers = data;
_myPickerView.delegate = self;
_myPickerView.dataSource = self;
_dm = [[DataManager alloc]init];
GSettings* settings = [_dm loadSettings];
if(settings == nil)
{
settings = [[GSettings alloc]init];
settings.chosenCenter = [_centers objectAtIndex:0];
settings.loadedCenter = [_centers objectAtIndex:0];
_center = settings.chosenCenter;
settings.notificationsEnabled = YES;
[self changeAddressLines];
}
/*if(settings != nil)
{
GCenter* loaded = settings.loadedCenter;
int i = 0;
BOOL found = NO;
while(i < [_centers count] && !found)
{
GCenter* center = (GCenter*)[_centers objectAtIndex:i];
if(settings.loadedCenter.iD == center.iD)
{
_center = center;
settings.chosenCenter = center;
[_dm storeSettings:settings];
found = YES;
}
i++;
}
//[self.myPickerView selectRow:i-1 inComponent:0 animated:NO];
loaded = nil;
[self changeAddressLines];
}
*/
}
-(void) pushErrorMessage: (NSString*) errorMessage
{
_alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"fout", nil) message:errorMessage delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
_alert.delegate = self;
[_alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)
{
if(self.navigationController != nil)
{
[self.navigationController popViewControllerAnimated:YES];
}
else
{
//[self initializeData];
}
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewWillDisappear:(BOOL)animated
{
[_dm cancelCenterRequest];
/*if(self.tabBarController != nil)
{
dm = [[DataManager alloc]init];
settings = [dm loadSettings];
if([dm hasConnectivity])
{
settings.lastUpdated = nil;
[dm storeSettings:settings];
}
if(settings.loadedCenter.centerCode != settings.chosenCenter.centerCode)
{
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SplashScreenController *controller = [mystoryboard instantiateViewControllerWithIdentifier:#"root"];
[self presentViewController:controller animated:YES completion:nil];
}
dm = nil;
settings = nil;
}
*/
}
-(void)gaVerder
{
_dm = [[DataManager alloc]init];
GSettings* settings = [_dm loadSettings];
if(settings == nil)
{
settings = [[GSettings alloc]init];
settings.notificationsEnabled = YES;
}
if(_center != nil)
{
settings.chosenCenter = _center;
}
[_dm storeSettings:settings];
[_mapView removeFromSuperview];
_mapView = nil;
_titleBackground = nil;
_lblTitle = nil;
_btnGaVerder = nil;
_myPickerView = nil;
_point = nil;
_indicator = nil;
_alert = nil;
_centers = nil;
_adresLine = nil;
_cityLine = nil;
_center = nil;
_dm = nil;
[self.presentingViewController dismissViewControllerAnimated:NO completion:^{}];
//DEZE BLIJFT HELAAS IN HET GEHEUGEN HANGEN... GEEN OPLOSSING GEVONDEN
//[self.navigationController popViewControllerAnimated:NO];
}
//PICKERVIEWDELEGATE EN DATASOURCE
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [_centers count];
}
- (UILabel *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
GCenter* center = (GCenter*)[_centers objectAtIndex:row];
NSString* string = center.name;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, 44)];
label.textColor = [GColor blueColor];
label.font = [label.font fontWithSize:18];
label.text = string;
label.textAlignment = NSTextAlignmentCenter;
return label;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
_center = (GCenter*)[_centers objectAtIndex:row];
[self changeAddressLines];
}
-(void)changeAddressLines
{
if (_mapView != nil)
{
[_mapView removeAnnotation:_point];
}
[_adresLine removeFromSuperview];
[_cityLine removeFromSuperview];
_adresLine = nil;
_cityLine = nil;
CGRect rctAdres = CGRectMake(0, _myPickerView.frame.origin.y + _myPickerView.frame.size.height -10, self.view.frame.size.width, 20);
_adresLine = [[UILabel alloc]initWithFrame:rctAdres];
_adresLine.textAlignment = NSTextAlignmentCenter;
_adresLine.textColor = [GColor greyColor];
_adresLine.text = _center.street;
CGRect rctCity = CGRectMake(0, rctAdres.origin.y + rctAdres.size.height, self.view.frame.size.width, 20);
_cityLine = [[UILabel alloc]initWithFrame:rctCity];
_cityLine.textAlignment = NSTextAlignmentCenter;
_cityLine.textColor = [GColor greyColor];
_cityLine.font = [_cityLine.font fontWithSize:14];
_cityLine.text = _center.city;
[self.view addSubview:_adresLine];
[self.view addSubview:_cityLine];
if(_mapView == nil)
{
double height;
height = _btnGaVerder.frame.origin.y - _cityLine.frame.origin.y - _cityLine.frame.size.height;
CGRect mapRect = CGRectMake(0, _cityLine.frame.origin.y+3 + _cityLine.frame.size.height, self.view.frame.size.width, height);
_mapView = [[MKMapView alloc]initWithFrame:mapRect];
[self.view addSubview:_mapView];
}
CLLocationCoordinate2D punt;
punt.latitude = _center.latitude;
punt.longitude = _center.longitude;
_point = [[MKPointAnnotation alloc] init];
[_point setCoordinate:punt];
_mapView.centerCoordinate = punt;
_point.title = _center.name;
[_mapView addAnnotation:_point];
[_mapView setCenterCoordinate:punt animated:YES];
MKCoordinateRegion theRegion = _mapView.region;
theRegion.span.longitudeDelta = 0.005;
theRegion.span.latitudeDelta = 0.005;
[_mapView setRegion:theRegion animated:YES];
}
#end
In my case it was a little more complicated. I don't have any variable that has strong reference to my view controller, and my view controller is not a strong delegate to any property/variable contained inside this class itself. After some hard thinking and trials, I found my issue was caused by a NSTimer object defined in the interface. The timer object itself is non-repeatable, but the method invoked by it will schedule the timer again at the end, which as you can imagine would reference this method defined in my view controller again, thus causing circular references. To break out of this loop, I had to invalidate the timer before I dismiss my view controller.
As a summary, these are cases when a view controller can be blocked from deallocating after it is dismissed:
The view controller is being strongly referenced by some outside object;
The view controller is a strong delegate referenced by some object defined within the view controller itself
The dismissViewControllerAnimated:completion: block may reference to self or it has some other code block that may cause a circular references
The view controller has NSTimer objects which can invoke some methods which re-schedules the timer
There could be more, but hopefully we can capture a lot of cases with the above cases.
If your view controller is not deallocated after it is dismissed, there's probably a strong reference to that view controller somewhere in your code. ARC will always deallocate objects that doesn't have strong reference anymore.
When my view is trying to load, the applications crashes and i get this stack:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter'
This is my code, i don't really know where to look when this crash is occurred:
#import "Itineraire.h"
#import "SBMapView.h"
#import "SBRouteAnnotation.h"
#import "City.h"
#import "UICGRoutes.h"
#import "SBCheckPointViewController.h"
//#import "SBRouteDetailView.h"
#interface Itineraire(Private)
-(void)customInitialization;
#end
#implementation Itineraire(Private)
-(void)customInitialization
{
// do the initialization of class variables here..
mDirections = [UICGDirections sharedDirections];
mDirections.delegate = self;
}
#end
#implementation Itineraire
#synthesize map = mMap;
#synthesize startPoint = mStartPoint;
#synthesize endPoint = mEndPoint;
#synthesize loadBtn = mLoadBtn;
#synthesize annotationArray = mAnnotationArray;
#synthesize travelMode = mTravelMode;
#synthesize destination;
#synthesize routes;
#synthesize mAnnotations;
#synthesize mRouteArray;
#synthesize mRouteDetail;
//Invoked when the class is instantiated in XIB
-(id)initWithCoder:(NSCoder*)aDecoder
{
self = [super initWithCoder:aDecoder];
if( self)
{
[self customInitialization];
}
return self;
}
// 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 {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
[self customInitialization];
}
return self;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Google Maps";
self.map = [[SBMapView alloc] initWithFrame:CGRectMake(0, 49, self.view.frame.size.width, self.view.frame.size.height)];
//self.map = [[SBMapView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 381)];
[self.view addSubview:mMap];
self.view.backgroundColor = [UIColor blackColor];
self.annotationArray = [[NSMutableArray alloc]init];
self.routes = [[UICGRoutes alloc]init];
if (mDirections.isInitialized) {
[self updateRoute];
}
}
/*
// 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];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
}
- (void)viewWillDisappear:(BOOL)animated;
{
[super viewWillDisappear:YES];
}
#pragma mark -
#pragma mark Instance Methods
- (void)updateRoute
{ /*
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
UICGDirectionsOptions *options = [[[UICGDirectionsOptions alloc] init] autorelease];
options.travelMode = mTravelMode;
City *mFirstCity = [[[City alloc]init] autorelease];
mFirstCity.mCityName = #"Paris";//mStartPoint;
//[mDirections loadWithStartPoint:mFirstCity.mCityName endPoint:destination options:options];
//added
NSMutableArray * DestinationCityArray = [[NSMutableArray alloc]init];
[DestinationCityArray addObject:#"Berlin"];
[mDirections loadWithStartPoint:mFirstCity.mCityName endPoint:destination options:options];
*/
//
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
UICGDirectionsOptions *options = [[UICGDirectionsOptions alloc] init] ;
options.travelMode = mTravelMode;
City *mFirstCity = [[City alloc]init];
mFirstCity.mCityName = #"Amsterdam";//mStartPoint;
NSMutableArray *dest=[[NSMutableArray alloc]init];
[dest addObject:#"Berlin"];
[mDirections loadWithStartPoint:mFirstCity.mCityName endPoint:dest options:options];
}
-(void)loadRouteAnnotations
{
self.mRouteArray = [mDirections routeArray];
NSLog(#"mRouteArray %#",mRouteArray);
self.mAnnotations = [[NSMutableArray alloc]init];
for (int idx = 0; idx < [mRouteArray count]; idx++) {
NSArray *_routeWayPoints1 = [[mRouteArray objectAtIndex:idx] wayPoints];
NSArray *mPlacetitles = [[mRouteArray objectAtIndex:idx] mPlaceTitle];
self.annotationArray = [NSMutableArray arrayWithCapacity:[_routeWayPoints1 count]-2];
mLoadBtn.title = #"OFF";
mLoadBtn.target = self;
mLoadBtn.action = #selector(removeRouteAnnotations);
for(int idx = 0; idx < [_routeWayPoints1 count]-1; idx++)
{
mBetweenAnnotation = [[SBRouteAnnotation alloc] initWithCoordinate:[[_routeWayPoints1 objectAtIndex:idx]coordinate]
title:[mPlacetitles objectAtIndex:idx]
annotationType:SBRouteAnnotationTypeWayPoint];
[self.annotationArray addObject:mBetweenAnnotation];
}
[mAnnotations addObject:mAnnotationArray];
[self.map.mapView addAnnotations:[mAnnotations objectAtIndex:idx]];
NSLog(#"map %#",mMap);
}
}
-(void)showCheckpoints
{
SBCheckPointViewController *_Controller = [[SBCheckPointViewController alloc]initWithNibName:#"SBCheckPoints" bundle:nil];
[self.navigationController pushViewController:_Controller animated:YES];
NSMutableArray *arr = [[mDirections checkPoint] mPlaceTitle];
_Controller.mCheckPoints = arr ;
}
//
-(void)removeRouteAnnotations
{
NSMutableArray *mTempAnnotation;// = [mAnnotations retain];
for (int idx = 0; idx < [mTempAnnotation count]; idx++) {
[mMap.mapView removeAnnotations:[mTempAnnotation objectAtIndex:idx] ];
}
mLoadBtn.title = #"ON";
mLoadBtn.target = self;
mLoadBtn.action = #selector(loadRouteAnnotations);
}
#pragma mark <UICGDirectionsDelegate> Methods
- (void)directionsDidFinishInitialize:(UICGDirections *)directions {
[self updateRoute];
}
- (void)directions:(UICGDirections *)directions didFailInitializeWithError:(NSError *)error {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Map Directions" message:[error localizedFailureReason] delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alertView show];
}
- (void)directionsDidUpdateDirections:(UICGDirections *)indirections {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
UICGPolyline *polyline = [indirections polyline];
NSArray *routePoints = [polyline routePoints];
[mMap loadRoutes:routePoints]; // Loads route by getting the array of all coordinates in the route.
UIToolbar *tools = [[UIToolbar alloc]
initWithFrame:CGRectMake(0.0f, 0.0f, 103.0f, 44.01f)]; // 44.01 shifts it up 1px for some reason
tools.clearsContextBeforeDrawing = NO;
tools.clipsToBounds = NO;
tools.tintColor = [UIColor colorWithWhite:0.305f alpha:0.0f]; // closest I could get by eye to black, translucent style.
// anyone know how to get it perfect?
tools.barStyle = -1; // clear background
NSMutableArray *buttons = [[NSMutableArray alloc] initWithCapacity:2];
// Create a standard Load button.
self.loadBtn = [[UIBarButtonItem alloc]initWithTitle:#"ON"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(loadRouteAnnotations)];
[buttons addObject:mLoadBtn];
// Add Go button.
UIBarButtonItem *mGoBtn = [[UIBarButtonItem alloc] initWithTitle:#"Go"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(showCheckpoints)];
[buttons addObject:mGoBtn];
// Add buttons to toolbar and toolbar to nav bar.
[tools setItems:buttons animated:NO];
UIBarButtonItem *twoButtons = [[UIBarButtonItem alloc] initWithCustomView:tools];
self.navigationItem.rightBarButtonItem = twoButtons;
//Add annotations of different colors based on initial and final places.
SBRouteAnnotation *startAnnotation = [[SBRouteAnnotation alloc] initWithCoordinate:[[routePoints objectAtIndex:0] coordinate]
title:mStartPoint
annotationType:SBRouteAnnotationTypeStart];
SBRouteAnnotation *endAnnotation = [[SBRouteAnnotation alloc] initWithCoordinate:[[routePoints lastObject] coordinate]
title:mEndPoint
annotationType:SBRouteAnnotationTypeEnd];
[mMap.mapView addAnnotations:[NSArray arrayWithObjects:startAnnotation, endAnnotation,nil]];
}
- (void)directions:(UICGDirections *)directions didFailWithMessage:(NSString *)message {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Map Directions" message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alertView show];
}
#pragma mark -
#end
I tried to put my code on a new project (empty application) and it worked fine, i didn't understand that error and its possible causes.
EDIT:
I tried to track the problem by elimination,and my code worked fine when i remove this method:
//Invoked when the class is instantiated in XIB
-(id)initWithCoder:(NSCoder*)aDecoder
{
self = [super initWithCoder:aDecoder];
if( self)
{
[self customInitialization];
}
return self;
}
However, when i run, my app doesn't display me the route between the two points (The purpose of the app). So this method seems important for the whole class because without it, i couldn't get the route and in the other side when it's there, the app crashes. How should i deal with this contradiction?
#Vince is putting you on the right track. Since the problem is in an NSURL method being called by a framework (Google Maps in this case) you need to debug what you are passing to the framework. You have the source for the framework also right? You can set breakpoints in loadWithStartPoint:endPoint:options:] to see what's going on.
One thing I did notice is you are passing an NSMutableArray as the endPoint param when I believe it expects an NSString.