How could I pass a parameter between views

1060
5
09-15-2010 10:53 PM
KOLDODUARTE
New Contributor
Hi guys,

I have a simple problem, I tell you:

I have 2 views: One is a map View and the other is a simple table with a different cells, each cell has a URL (mapServer (imagery, street and topography)). I would like to pass to map view when I do click on the cell in the second view (this already I have achieved it) but I don´t know how to pass the parameter (URL imagery, or URL street...) to a Map View.
I have read, the best option for do this is, converter a mapview class to singleton class, but I don´t know how can I do this.

Can someone help me?

Best Regards,
Koldo
0 Kudos
5 Replies
JeremyBixby
New Contributor III
Koldo,

You could create a singleton class and dump all of your data there, or you could set the parameter as a property on the view before you load it.  I use the singleton method, but the easiest way is probably setting the property on the view before loading it.  You could also define a message to pass the variable in through.

I have pasted some code below from both the singleton and the property-set methods, use as you see fit.

Here is the header file from my model singleton.  Note that the sharedModel method declaration is denoted with a plus sign.
#import <Foundation/Foundation.h>
#import "iLenexaMapView.h"
#import "ArcGIS.h"

@interface iLenexaModel : NSObject {

 iLenexaMapView *lenMapView;
 AGSTiledMapServiceLayer *basemap;
 AGSTiledMapServiceLayer *crimemap;
 AGSTiledMapServiceLayer *parksmap;
 
 AGSTiledMapServiceLayer *aerials;
 
 AGSGraphicsLayer *serviceRequests;
 
 AGSPoint *currLocation;
 
 NSString *lyrName;
 NSString *lyrURL;
 NSString *lyrType;
 NSString *basemapName;
}

@property (nonatomic,retain) iLenexaMapView *lenMapView; 
@property (nonatomic, retain) AGSTiledMapServiceLayer *basemap;
@property (nonatomic, retain) AGSTiledMapServiceLayer *crimemap;
@property (nonatomic, retain) AGSTiledMapServiceLayer *parksmap;
@property (nonatomic, retain) AGSTiledMapServiceLayer *aerials;
@property (nonatomic, retain) AGSPoint *currLocation;

@property (nonatomic, retain) AGSGraphicsLayer *serviceRequests;

@property (nonatomic, retain) NSString *basemapName;
@property (nonatomic, retain) NSString *lyrName;
@property (nonatomic, retain) NSString *lyrURL;
@property (nonatomic, retain) NSString *lyrType;

//note the plus sign in from of this method.  We are going to need to call this from wherever we //want to collect the property from
+ (id)sharedModel;

@end


Here is the implementation file:
#import "iLenexaModel.h"

static iLenexaModel *sharedMyModel = nil;

@implementation iLenexaModel

@synthesize lenMapView, crimemap, basemap,parksmap,serviceRequests, aerials;
@synthesize lyrType, lyrName, lyrURL, currLocation;
@synthesize basemapName;

+(id)sharedModel{

 @synchronized(self){
  if (sharedMyModel==nil) {
   [[self alloc] init];
  }
 }
 return sharedMyModel;
}

+ (id)allocWithZone:(NSZone *)zone{

 @synchronized(self){
  if (sharedMyModel == nil) {
   sharedMyModel = [super allocWithZone:zone];
   return sharedMyModel;
  }
 }
 return nil;
}



-(id)copyWithZone:(NSZone *)zone{
 return self;
}

-(id)retain{
 return self;
}

-(unsigned)retainCount{
 return UINT_MAX;
}

-(void)release{}

-(id)autorelease{
 return self;
}

-(id)init{
 if (self=[super init]) {
  NSLog(@"Jeremy's rad singleton");
 }
}
 
-(void)dealloc {
 
 [lenMapView release];
 [super dealloc];
 
}



@end


Setting a property in the model singleton (this one from a UIView):
 iLenexaModel *myModel = [iLenexaModel sharedModel];
 myModel.lenMapView = self;


Another example of using/setting properties in a singleton:

 iLenexaModel *myModel = [iLenexaModel sharedModel];
 
 mapViewer.myBasemap = myBasemap;
 
 [mapViewer changeBasemap];
 
 [self.navigationController pushViewController:mapViewer animated:YES];
 
 if ([lyrType isEqualToString:@"Tiled"]) {
  [mapViewer addLenexaTiledMapLayer:lyrURL :myModel.lyrName];
 }
   
 else if([lyrType isEqualToString:@"Dynamic"]){
  [mapViewer addLenexaDynamicMapLayer:lyrURL :myModel.lyrName];
 }
   
 else if([lyrType isEqualToString:@"Graphic"]){
  [mapViewer addLenexaGraphicsMapLayer:lyrURL :myModel.lyrName];
 }
   
   else{
    NSLog(@"Something is wrong here!!!!");
   
   }
 
 mapViewer.lyrName = myModel.lyrName;
//and so on...
}


Setting properties on the view as a method of passing parameters between them is just a variant of this method, where you identify your properties in the view's header, set them, and then add the view to the user interface.  In this brief example, I set the properties on the subTable view and then push it to the user:

 if([lyrName isEqualToString:@"Economic Development"]){
  NSLog(@"Economic Development");
  iLenexaTableSubView *subTable = [[iLenexaTableSubView alloc] initWithNibName:@"iLenexaTableSubView" bundle:[NSBundle mainBundle]];
  
  NSString *path3 = [[NSBundle mainBundle] pathForResource:@"econDevelopment" ofType:@"plist"];
  NSMutableArray* myarr2 = [[NSMutableArray alloc] initWithContentsOfFile:path3];

  subTable.myVarArray = myarr2;
  subTable.mapViewer = mapViewer;
  subTable.myBasemap = myModel.basemap;
  
  [myarr2 release];
  
  [self.navigationController pushViewController:subTable animated:YES];
  
  [subTable release];
 }


Finally, you can also specify methods (I think in the iOS world they're called "messages") through which you can identify methods to pass and set variables after instantiating the view but before trying to use the properties you are trying to set:

So you would first identify the method in your header file, then implement it in the implementation file.  This is from the header file in my appDelegate:

- (void) collectCrimeData;


And this is from the implementation file:

-(void) collectCrimeData{

 NSLog(@"We collect the crime data!!!");

}


If you wanted to modify this to pass in a parameter, your header code should declare the message to take a variable of a specific type.  Modified, we see that it would look like this, also from my appDelegate header file:

- (IBAction) addNewServiceRequest:(id) sender;


Here we identify a method to be implemented in the .m file which takes one variable, called "sender" of type id.  This is the implementation of this method, also from my appDelegate:

-(IBAction)addNewServiceRequest:(id)sender{

 //record the currPoint in here
 iLenexaModel *myModel = [iLenexaModel sharedModel];
 myModel.currLocation = myModel.lenMapView.mapView.gps.currentPoint;
 
 iLenexaServiceRequestDetail *srRequest = [[iLenexaServiceRequestDetail alloc] initWithNibName:@"iLenexaServiceRequestDetail" bundle:[NSBundle mainBundle]];
 [self.tabbarcontroller presentModalViewController:srRequest animated:YES];
 [srRequest release];
}


By denoting it as a method of type IBAction, we are in effect tying it to a button in the nib.

Edit: You are NOT tying the method to the nib just by typing your return value as IBAction; you have to go into InterfaceBuilder and connect the event to the method.  The cool thing about InterfaceBuilder is that it will automatically recognize methods that the event can by bound to.
0 Kudos
KOLDODUARTE
New Contributor
Thank you very much jdb1a1 !

This weekend I will try it.

BR
Koldo.
0 Kudos
KOLDODUARTE
New Contributor
Hi jdb1a1,

I am trying your steps but I don´t finish to clearing.

Could you me a favour, please? Could you implement one these methods in the project attached you?

This project has 2 views, one with table and the second with a simple label. I try to put in this label the value of the row in the first view, and I don´t get it.

Thanks again.

BR,
Koldo!
0 Kudos
JeremyBixby
New Contributor III
I have pasted the relevant code below, and I have also attached the zip.  This is the "setting properties on the view" method I detail in my previous post (as opposed to messages or the singleton method).  When you run it in debug mode, touch the cell a few different times to see it work.  You have some other default string value in the Label's text property that isn't getting overridden by handler the first time you load it.  I would find it for you, but I have a pretty tight schedule.

Best,
Jeremy

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 //collect the string from the indexPath before you set the current viewcontroller
    NSString *selectDay = [NSString stringWithFormat:@"%d", indexPath.row];
 
 //instantiate a new variable that is typed SecondView, set the textLabel property on it.
 SecondView *myView = [self.tabBarController.viewControllers objectAtIndex:1];
 [myView.myLabel setText:selectDay];
 
 //now set the selectedViewController to the SecondView instance we just made
 self.tabBarController.selectedViewController = myView;
 
 
}
0 Kudos
KOLDODUARTE
New Contributor
Hi Jeremy,

Now yes, I have obtained it ! yeahh!

With a simple NSString in the first view, I convert it in a property, and then, in the other view you can change the value for this. Now is very simple, jeje.

Thanks again!

BR,
Koldo.
0 Kudos