MASPreferences choose view - objective-c

I am using MASPreferences in my app, I was able to set up everything correctly, with 3 different views (preferences, login and about).What I would like to do is to choose which panel gets shown when the window is opened. This is so that when the user clicks on about, the about panel is shown, etc. instead of the last panel shown being the one displayed. As of now I have tried modifying the entry in the plist file, but it does not seem to work. Is there any other way?

So after a bit of trying, and by using #Jasper's answer, I came up with the following:
-(void)openPreferencesWindowWithIdentifier:(NSString *)identifier {
[NSApp activateIgnoringOtherApps:YES];
[[NSUserDefaults standardUserDefaults] setValue:identifier forKey:#"MASPreferences Selected Identifier View"];
// Create the preferences window
NSViewController *generalViewController = [[GeneralPreferencesViewController alloc]initWithNibName:#"GeneralPreferencesViewController" bundle:nil];
NSViewController *loginViewController = [[PushoverLoginViewController alloc]initWithNibName:#"PushoverLoginViewController" bundle:nil];
NSViewController *aboutViewController = [[AboutPreferencesViewController alloc]initWithNibName:#"AboutPreferencesViewController" bundle:nil];
NSArray *controllers = [[NSArray alloc]initWithObjects:generalViewController,loginViewController,[NSNull null],aboutViewController, nil];
NSString *windowTitle = NSLocalizedString(#"Preferences", #"Comon title for preferences window");
_preferencesWindowController = [[MASPreferencesWindowController alloc]initWithViewControllers:controllers title:windowTitle];
[self.preferencesWindowController showWindow:nil];
}
Essentially this method writes the required "tab" on the plist file, and then initalizes a new instance everytime. By doing so, the correct view is loaded. The identifier parameter is the one you set up for each of the views. Thanks again to Jasper for his answer, really helped me understand how to figure this one out!

MASPreferences remembers the last opened 'tab'
Change in the order in your array when passing it to your MASPreferencesWindowController should work to change the order of your tabs.
-(NSWindowController *)preferencesWindowController
{
if (_preferencesWindowController == nil)
{
NSViewController *generalViewController = [[GeneralPreferencesViewController alloc] init];
NSViewController *accountViewController = [[AccountPreferencesViewController alloc] init];
NSViewController *troubleshootingViewController = [[TroubleShootingPreferencesViewController alloc] init];
//Change the order here
NSArray *controllers = [[NSArray alloc] initWithObjects:accountViewController, generalViewController, troubleshootingViewController, nil];
NSString *title = NSLocalizedString(#"Preferences", #"Common title for Preferences window");
_preferencesWindowController = [[MASPreferencesWindowController alloc] initWithViewControllers:controllers title:title];
}
return _preferencesWindowController;
}
Have a look inside MASPReferencesWindowController.m line 6. There is a static NSString key which handles the logic to show the last selected tab
static NSString *const kMASPreferencesSelectedViewKey = #"MASPreferences Selected Identifier View";
The key is used in:
- (void)windowDidLoad
{
if ([self.title length] > 0)
[[self window] setTitle:self.title];
if ([self.viewControllers count])
self.selectedViewController = [self viewControllerForIdentifier:[[NSUserDefaults standardUserDefaults] stringForKey:kMASPreferencesSelectedViewKey]] ?: [self firstViewController];
NSString *origin = [[NSUserDefaults standardUserDefaults] stringForKey:kMASPreferencesFrameTopLeftKey];
if (origin)
[self.window setFrameTopLeftPoint:NSPointFromString(origin)];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(windowDidMove:) name:NSWindowDidMoveNotification object:self.window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(windowDidResize:) name:NSWindowDidResizeNotification object:self.window];
}
TL;DR
Look for the method - (void)setSelectedViewController:(NSViewController <MASPreferencesViewController> *)controller inside MASPreferencesWindowController.m
Comment this line:
// Record new selected controller in user defaults
[[NSUserDefaults standardUserDefaults] setObject:controller.identifier forKey:kMASPreferencesSelectedViewKey];
Now change the way you initialise your NSWindowController so you create a new instance every time, otherwise it will still remember the last selected tab:
-(NSWindowController *)preferencesWindowController
{
NSViewController *generalViewController = [[GeneralPreferencesViewController alloc] init];
NSViewController *accountViewController = [[AccountPreferencesViewController alloc] init];
NSViewController *troubleshootingViewController = [[TroubleShootingPreferencesViewController alloc] init];
//NSArray *controllers = [[NSArray alloc] initWithObjects:generalViewController, accountViewController, troubleshootingViewController, nil];
NSArray *controllers = [[NSArray alloc] initWithObjects:accountViewController, generalViewController, troubleshootingViewController, nil];
// To add a flexible space between General and Advanced preference panes insert [NSNull null]:
// NSArray *controllers = [[NSArray alloc] initWithObjects:generalViewController, [NSNull null], advancedViewController, nil];
NSString *title = NSLocalizedString(#"Preferences", #"Common title for Preferences window");
_preferencesWindowController = [[MASPreferencesWindowController alloc] initWithViewControllers:controllers title:title];
return _preferencesWindowController;
}

Related

Why would a property essentially disappear? Obj-C, Cocoa

I am quite stumped. I have an app with a class for storing item details. Called LEItem. Those items are stored in a store with a class labeled LEItemStore. I have a view with a table of all items. This works fine. If you tap on a row, it sends this message to LogbookFirstViewController.
LogbookFirstViewController *logController = [[LogbookFirstViewController alloc] initForNewItem:NO];
NSArray *items = [[LEItemStore sharedStore] allItems];
LEItem *selectedItem = [items objectAtIndex:[indexPath row]];
NSString *description = [selectedItem description];
NSLog(#"%#", description);
[logController setItem:selectedItem];
[self dismissViewControllerAnimated:YES completion:nil];
That is in a TableView class. In the LogbookFirstViewController.m I have
-(void)setItem:(LEItem *)i{
item = i;
NSString *t = [item description];
NSLog(#"In LogbookFirstViewController, returning %#", t);
}
This is where it gets odd. That works. It outputs the correct item, therefore I would think everything would be okay. But it's not. item is a class-level property, so it should stay, but it doesn't. In the same class, I have overrode this method.
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//NSString *string = [item description];
//NSLog(#"Item = %#", string);
NSLog(#"View did Appear:animated");
int glucoseValue = [item glucose];
NSString *glucoseString = [NSString stringWithFormat:#"%d", glucoseValue];
[glucoseField setText:glucoseString];
int proteinValue = [item protein];
NSString *proteinString = [NSString stringWithFormat:#"%d", proteinValue];
[proteinField setText:proteinString];
int carbsValuue = [item carbs];
NSString *carbsString = [NSString stringWithFormat:#"%d", carbsValuue];
[carbsField setText:carbsString];
int insulinValue1 = [item insulin];
NSString *insulin1String = [NSString stringWithFormat:#"%d", insulinValue1];
[insulinField1 setText:insulin1String];
int insulinValue2 = [item insulin2];
NSString *insulinString2 = [NSString stringWithFormat:#"%d", insulinValue2];
[insulinField2 setText:insulinString2];
//NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
//[dateFormatter setDateStyle:NSDateFormatterShortStyle];
//[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
//NSLog(#" The item was created on %#", [dateFormatter stringFromDate:[item dateCreated]]);
//[dateButton setTitle:[dateFormatter stringFromDate:[item dateCreated]] forState:UIControlStateNormal];
NSString *t = [item description];
NSLog(#"Loading view... Returns: %#", t);
}
I know that it isn't the cleanest code, but the idea is the same. It uses exactly the same code as the setItem: method. However, this always returns (null). Why? The property appears to go missing at viewWillAppear.
Thanks.
EDIT
I solved the problem. As you can see, the checked answer below did give the right idea, here is what I did to solve it. The problem was that when I sent setItem: I used this code to get LogbookFirstViewController
LogbookFirstViewController *logController = [[LogbookFirstViewController alloc] initForNewItem:NO];
As I know see, that created a new instance of LogbookFirstViewController, so therefore, the existing one did not change it's Item property, as properties are assigned to one instance. Therefore, I was only changing the value of Item for this "invisible" property.
To solve this, one must get the existing instance of the viewController. To do this I did the following:
In LogbookFirstViewController.h I added this property
#property (assign) LogbookFirstViewController *instance;
Then, synthesize instance in your .m and in the same placed I added this to viewDidLoad
- (void)viewDidLoad
{
instance = self;
...
Then, in the other viewController, entriesViewController, I added this too the .h
#property (nonatomic, strong) LogbookFirstViewController *logController;
Synthesize it. Then, I just used my didSelectRowAtIndexPath the same way, just using the existing logController
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *items = [[LEItemStore sharedStore] allItems];
LEItem *selectedItem = [items objectAtIndex:[indexPath row]];
NSString *description = [selectedItem description];
NSLog(#"%#", description);
NSLog(#"Setting controller: %#", logController);
[logController setItem:selectedItem];
[self dismissViewControllerAnimated:YES completion:nil];
}
Then it works!
You have a line where you create the LogbookFirstViewController but you don't actually cause it to display anything (push or present). Since it's a local variable, it would appear that whatever instance of that controller is loading its view is not the same one that you initialize in the code you've shown.
You can verify this by adding a couple of NSLog lines, such as:
NSLog(#"Setting controller: %#", logController); // Insert before existing line
[logController setItem:selectedItem];
...and...
[super viewWillAppear:animated];
NSLog(#"Viewing controller: %#", self); // Insert after existing line
For things to work the way you want, those have to print the same address.
You should retain when assigning object to property without ARC:
-(void)setItem:(LEItem *)i{
_item = [i retain];
...
}
If you use property with ARC, then write _item = i;:
-(void)setItem:(LEItem *)i{
_item = i;
...
}

Pushing UITableViewControllers and filtering/reloading the data

I think this is probably a simple problem that I am not understanding but I have spent a lot of time on it and it is holding up my work.
I have a UITableViewController that displays 4 rows of "topics". When you touch one, it creates an instance of my UITableViewController class, set's the data source array to the array of "subtopics" and pushes the controller onto the nav stack. When I go to my "All" topics page with say 10 rows, I have a segmented control for filtering the results. I am able to successfully filter the array but when I assign it to my self.topicsDataSource and call [self.tableView reloadData], nothing happens. The delegate methods numberOfSections and numberOfRowsInSection, but cellForRowAtIndexPath is not. When I press the navigation back button it goes back to and the previous table is now the filtered results I wanted in the top table.
So here's what I think is happening.
1. I am actually altering the data source of the previous table, and self.tableView.reloadData is being called on that table.
2. cellForRowAtIndexPath is not called because the tableview being reloaded is not visible at that time.
Here is where I am instantiating an pushing the table views. This class is called TopicsViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *idtopic = [[self.topicsDataSource objectAtIndex:indexPath.row] idtopic];
NSArray *subtopics = [DataManager getSubtopicsForTopic:idtopic];
if ([subtopics count] > 0) {
TopicsViewController *topicsVC = [[TopicsViewController alloc ] init];
topicsVC.tableView.rowHeight = 106;
topicsVC.parentTopicId = idtopic;
topicsVC.topicsDataSource = [NSMutableArray arrayWithArray:subtopics];
topicsVC.diseaseStateId = self.diseaseStateId;
topicsVC.title = [[self.topicsDataSource objectAtIndex:indexPath.row] topic];
[self.navigationController pushViewController:topicsVC animated:YES];
}
else if (![[self.topicsDataSource objectAtIndex:indexPath.row] topic]) {
//all topics was selected
TopicsViewController *topicsVC = [[TopicsViewController alloc] initWithNibName:nil bundle:nil];
topicsVC.tableView.rowHeight = 106;
NSMutableArray *mArray = [[NSMutableArray alloc] initWithArray:[DataManager getTopicsAtEndOfTree]];
topicsVC.allTopics = mArray;
topicsVC.topicsDataSource = topicsVC.allTopics;
topicsVC.diseaseStateId = self.diseaseStateId;
topicsVC.parentTopicId = [NSNumber numberWithInt:100];
UISegmentedControl *segControl = [[UISegmentedControl alloc] initWithItems:[[NSArray alloc] initWithObjects:#"All", #"Speaker Direct", #"Live Meeting", nil]];
[segControl addTarget:self action:#selector(segControlChanged:) forControlEvents:UIControlEventValueChanged];
[segControl setSegmentedControlStyle:UISegmentedControlStyleBar];
[segControl setSelectedSegmentIndex:0];
topicsVC.navigationItem.titleView = segControl;
topicsVC.tableView.dataSource = topicsVC;
[self.navigationController pushViewController:topicsVC animated:YES];
}....
and here is where I am filtering the data and reloading the tableView:
- (void)segControlChanged:(UISegmentedControl *)sender
{
self.allTopics = [NSMutableArray arrayWithArray:[DataManager getTopicsAtEndOfTree]];
if (sender.selectedSegmentIndex == 1) {
NSPredicate *pred = [NSPredicate predicateWithFormat:#"type == 2"];
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[self.allTopics filteredArrayUsingPredicate:pred]];
self.topicsDataSource = mArr;
}
else if (sender.selectedSegmentIndex == 2) {
NSPredicate *pred = [NSPredicate predicateWithFormat:#"type == 1"];
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[self.allTopics filteredArrayUsingPredicate:pred]];
self.topicsDataSource = mArr;
}
else {
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[DataManager getTopicsAtEndOfTree]];
self.topicsDataSource = mArr;
}
[self.tableView reloadData];
}
Any help would be appreciated. Thanks!
- (void)segControlChanged:(UISegmentedControl *)sender
{
self.allTopics = [NSMutableArray arrayWithArray:[DataManager getTopicsAtEndOfTree]];
if (sender.selectedSegmentIndex == 1) {
NSPredicate *pred = [NSPredicate predicateWithFormat:#"type == 2"];
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[self.allTopics filteredArrayUsingPredicate:pred]];
self.topicsDataSource = mArr;
}
else if (sender.selectedSegmentIndex == 2) {
NSPredicate *pred = [NSPredicate predicateWithFormat:#"type == 1"];
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[self.allTopics filteredArrayUsingPredicate:pred]];
self.topicsDataSource = mArr;
}
else {
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[DataManager getTopicsAtEndOfTree]];
self.topicsDataSource = mArr;
}
[tableView reloadData]; //
}
It's very difficult to tell what your question is and what is happening - I'd suggest next time asking a question with much less random code, more explanation, and a more obvious question (also better formatting). Anyway.
As best as I can tell, self is still referring to the original view controller. I'm not sure what classes your code is coming from but if you want this to work you need to
Write a custom class for TopicsViewController
Push it/etc
Inside the custom class, define datasource, reloading, etc
Call the change datasource method inside of the custom class
Call the reloadData method on the tableView of the custom class.
The point is, make sure that all of your work happens inside of the class for your custom table view data controller.

playing second Sound

am trying to do a simple AVAudioPlayer based application to play 2 different music upon button pressed, there is 2 views, the first is the home view contains 2 buttons,each button set a song which is named as integer(1.mp3, 2.mp3.....etc)and here'e the code
#import "podHome.h"
#import "podMusic.h"
#import "ArabAppDelegate.h"
#implementation podHome
#synthesize song1;
#synthesize tabi;
int CurrentPlay;
NSString *Currenttxt;
-(IBAction)uae{
CurrentPlay=1;
Currenttxt=#"uae";
podMusic *newContro=[[podMusic alloc] init];
[newContro setCurrentPlay1:CurrentPlay setCurrentText:Currenttxt];
ArabAppDelegate *theDelegate = (ArabAppDelegate*)[[UIApplication sharedApplication] delegate];
tabi = theDelegate.tabcontrolPod;
tabi.selectedIndex = 1;
[newContro release];
}
-(IBAction)libya{
CurrentPlay=2;
Currenttxt=#"uae";
podMusic *newContro=[[podMusic alloc] init];
[newContro setCurrentPlay1:CurrentPlay setCurrentText:Currenttxt];
ArabAppDelegate *theDelegate = (ArabAppDelegate*)[[UIApplication sharedApplication] delegate];
tabi = theDelegate.tabcontrolPod;
tabi.selectedIndex = 1;
[newContro release];
}
these tow (IBActions) are linked to the two buttons when pressing on one of them it will change to the other view and start playing the song
- (void)viewWillAppear:(BOOL)animated {
if((played == 1)&&(isBacked==FALSE)){
NSString *filePath = [[NSBundle mainBundle] pathForResource:texting
ofType:#"txt"];
NSString *filenameString = [NSString stringWithContentsOfFile:filePath usedEncoding:nil error:nil];
CurrentTex.text = filenameString;
AudioSessionInitialize(NULL, NULL, NULL, NULL);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,sizeof(sessionCategory), &sessionCategory);
AudioSessionSetActive(YES);
playBtnBG = [[UIImage imageNamed:#"play-pod.png"] retain];
pauseBtnBG = [[UIImage imageNamed:#"pause-pod.png"] retain];
[playButton setBackgroundImage:pauseBtnBG forState:UIControlStateNormal];
[self registerForBackgroundNotifications];
updateTimer = nil;
duration.adjustsFontSizeToFitWidth = YES;
currentTime.adjustsFontSizeToFitWidth = YES;
progressBar.minimumValue = 0.0;
NSString *path=[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%d",CurrentPlay] ofType:#"mp3"];
self.player=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[player stop];
//self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
if (self.player)
{
[self updateViewForPlayerInfo:player];
[self updateViewForPlayerState:player];
player.numberOfLoops = 0;
player.delegate = self;
}
[self startPlaybackForPlayer:player];
fileName.text= [[NSString alloc]initWithFormat:#"%#", songName];
// [fileURL release];
// CurrentPlay = 0;
isBacked = TRUE;
}
[super viewWillAppear:animated];
}
- (void)setCurrentPlay1:(int)varP setCurrentText:(NSString *)varT{
CurrentPlay = varP;
texting = varT;
played = 1;
isBacked = FALSE;
}
but the problem is that when the song is playing and am back to home view and pressing on the other song's button, it starts to play with the first one at the same time, i think the first should stop to begin the other, what should i release to do that???
My guess is that you have two instances of the AVAudioPlayer, and when you set them both to play, they both do!
One solution would be to tell other players to stop when you activate a new one, but that will quickly become troublesome as the number of players increases.
Instead you;'d be better of just setting up one player, and change it's song in accordance to what button was pressed. That way, there is no chance that two music tracks will play at the same time.
In your first button action write like this.
if(player2.isPlaying)
{
[player2 stop];
}
in the same way do the same thing in second button action like this.
if(player1.isPlaying)
{
[player1 stop];
}

UITableView returns null?

I have spent many hours looking into this and I still can't find a solution. Here's a chart on what the user goes through:
The user takes a picture or takes one from their camera roll
As soon as they take (or select) one, the captionView closes
As soon as the captionView closes, startUploads from a different view starts
If the user decides to open the view that startUploads is in, they can see what has been uploaded
Now that you know a little bit about the process, I have a few issues. When uploads finish I want them to fade out. I know how to do that, but for some reason when I call to, the self.theTableView returns null. I have a #property (nonatomic, retain)... in my .h and I have a #sythesize theTableView; in my .m.
In a different question, I found out that when doing the startUploads, my NSMutableArray needed to be initiated in here (so I thought that it would do the same with my UItableView). Here's what I have:
- (id)initWithNibNamed:(NSString *)nibName bundle:(NSBundle *)bundle {
self = [super initWithNibNamed:nibName bundle:bundle];
if (self) {
processList = [[NSMutableArray alloc] init];
self.theTableView = [[UITableView alloc] init];
NSLog(#"thetableview: %#", theTableView);
}
return self;
}
Just in case you want to see how startUploads is called, here's the code:
processViewController *testtest = [[processViewController alloc] initWithNibName:#"processView.xib" bundle:nil];
//testtest.processList = [[NSMutableArray alloc] initWithNig];
NSLog(#"Different:displayProcessVC BEFORE STARTING UPLOAD, processList = %#", testtest.processList);
NSLog(#"Different:displayProcessVC BEFORE STARTING UPLOAD, theTableView = %#", testtest.theTableView);
[testtest startUploads];
NSLog(#"Different:displayProcessVC AFTER STARTING UPLOAD, processList = %#", testtest.processList);
NSLog(#"Different:displayProcessVC AFTER STARTING UPLOAD, theTableView = %#", testtest.theTableView);
[testtest release];
However it still shows (null) in the console.
Please help!Coulton
EDIT 1:
Here's where it's being nil:
- (void)deleteOneRow: (NSString *)theString {
int theInt = [processList indexOfObject:theString];
[processList removeObjectAtIndex:theInt];
NSArray *deleteIndexPaths = [[NSArray alloc] initWithObjects: [NSIndexPath indexPathForRow:theInt inSection:0], nil];
NSLog(#"theTableView: %#", self.theTableView);
[self.theTableView beginUpdates];
[self.theTableView deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.theTableView endUpdates];
}
The designated initializer for UITableView is -initWithFrame:style: and you're leaking. Try this in -viewDidLoad instead.
self.theTableView = [[[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain] autorelease];

Get & Edit NSMutableArray from different class file

I am trying to access and change a array from a different class file. When using a NSLog, I get a result of (null). Below is my code:
RootViewController.h
NSMutableArray *listOfItems;
#property (nonatomic, retain) NSMutableArray *listOfItems;
RootViewController.m
#synthesize listOfItems;
listOfItems = [[NSMutableArray alloc] init];
[listOfItems addObject:#"One"];
[listOfItems addObject:#"Two"];
[listOfItems addObject:#"Three"];
SecondViewController.m
RootViewController *test = [[RootViewController alloc] init];
NSLog(#"Results: %#", test.listOfItems);
I get the following results in my console: Results: (null)
Thanks in advance,
Coulton
P.S. Obviously I have left out a bunch of code. I just tried to make it easier to read. If you need to see anything else, I would be more than happy to post more. Just ask
EDIT #1:
I am getting hundreds of NSLog Messages that look something like this:
*** __NSAutoreleaseNoPool(): Object 0x4e39020 of class __NSArrayI autoreleased with no pool in place - just leaking
And here's my init code:
- (id) init {
//NSLog(#"%#", theUserID);
// Set up database connection
NSString *myDB = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"database.db"];
database = [[Sqlite alloc] init];
[database open:myDB];
//Initialize the array.
listOfItems = [[NSMutableArray alloc] init];
// Add to array to display in the tableView
NSArray *listOfItemsTwo = [database executeQuery:#"SELECT * FROM albums"];
for (NSDictionary *rowone in listOfItemsTwo) {
NSString *getName = [rowone valueForKey:#"name"];
if (getName != NULL) {
[listOfItems addObject:getName];
[getName release];
}
}
return self;
}
I guess you reversed RootViewController.m and RootViewController.h snippets right?
Are you sure that the
listOfItems = [[NSMutableArray alloc] init];
gets called? Maybe you can put a breakpoint there.
EDIT: Order of RootViewController.m and RootViewController.h has been fixed in the question. It's not clear from the question where the above line is in the code. That's a important piece of information.
EDIT2: Example of init method.
#implementation RootViewController
- (id) init
{
listOfItems = [[NSMutableArray alloc] init];
[listOfItems addObject:#"One"];
return self;
}
#end