SWRevealViewController Different Content based on Current View - ios

I'm using SWRevealViewController to get the side menu to show different content based on which tab the user is currently on. I've created a global variable in called location in AppDelegate to find out where the user is. For my sidebar, I'm using this condition to change the content:
- (void)viewWillAppear:(BOOL)animated {
[super viewDidAppear:animated];
AppDelegate *del=(AppDelegate*)[[UIApplication sharedApplication] delegate];
if ([del.location isEqualToString: #"Secure"]){
self.menu = [NSMutableArray
arrayWithObjects:#"secure1",#"secure2",#"secure3",#"secure4",#"secure5", nil];
self.menu2 = [NSMutableArray
arrayWithObjects:#"s1",#"s2",#"s3",nil];
NSLog(#"THIS IS %# menu",del.location);
}
else if ([del.location isEqualToString: #"Employee"]){
self.menu = [NSMutableArray
arrayWithObjects:#"emp1",#"emp2",#"emp3",#"emp4",#"emp5",#"emp6", nil];
self.menu2 = [NSMutableArray
arrayWithObjects:#"e1",#"e2",#"e3",nil];
NSLog(#"THIS IS %# menu",del.location);
}
else if ([del.location isEqualToString: #"Patient"]){
self.menu = [NSMutableArray
arrayWithObjects:#"patient1",#"patient2",#"patient3",#"patient4",#"patient5",#"patient6", nil];
self.menu2 = [NSMutableArray
arrayWithObjects:#"p1",nil];
NSLog(#"THIS IS %# menu",del.location);
}
}
It seems to be working as the NSLog statements all come out correctly, but the content for menu and menu2 still do not change. Where am I going wrong?

I wasn't adding the
[self.tableView reload];
after closing the if-statement, and instead added it under cellForRowAtIndexPath (which lead the cells to constantly reload, but not the table -- if my understanding is correct.)
Added it in the viewWillAppear after closing my if-statement and problem solved.
Thanks to Anbu.Karthik for pointing it out!

Related

Correct way to handle application launching with quick actions

I am having a hard time figuring out how to get my quick actions working when I launch my app with a quick action.
My quick actions work, however, if the app was in the background and re-launched with the quick action.
When I try to launch the app straight from the quick action, the app opens as if it was launched by simply tapping the app icon (i.e. it does nothing).
Here is some code from my App Delegate.
In didFinishLaunchingWithOptions:
UIApplicationShortcutItem *shortcut = launchOptions[UIApplicationLaunchOptionsShortcutItemKey];
if(shortcut != nil){
performShortcutDelegate = NO;
[self performQuickAction: shortcut fromLaunch:YES];
}
The method called:
-(BOOL) performQuickAction: (UIApplicationShortcutItem *)shortcutItem fromLaunch:(BOOL)launchedFromInactive {
NSMutableArray *meetings = [self.fetchedResultController.fetchedObjects mutableCopy];
[meetings removeObjectAtIndex:0];
unsigned long count = meetings.count;
BOOL quickActionHandled = NO;
if(count > 0){
MainViewController *mainVC = (MainViewController *)self.window.rootViewController;
if(launchedFromInactive){
mainVC.shortcut = shortcutItem;
}
else{
UINavigationController *childNav;
MeetingViewController *meetingVC;
for(int i = 0; i < mainVC.childViewControllers.count; i++){
if([mainVC.childViewControllers[i] isKindOfClass: [UINavigationController class]]){
childNav = mainVC.childViewControllers[i];
meetingVC = childNav.childViewControllers[0];
break;
}
}
self.shortcutDelegate = meetingVC;
if ([shortcutItem.type isEqual: #"Meeting"]){
NSNumber *index = [shortcutItem.userInfo objectForKey:#"Index"];
[self.shortcutDelegate switchToCorrectPageWithIndex: index launchedFromInactive:NO];
quickActionHandled = YES;
}
}
}
The only action that needs to be performed is that my page view controller (which is embedded inside the meetingVC) should switch to a certain page with respect to the shortcut chosen.
Any ideas on what causes the shortcut to not do anything when using it to launch as opposed to re-opening the app from the background??
I came to realize I was trying to call my methods on a view controller that was not in memory yet. This was causing bizarre behavior in my app. I did have the correct approach to getting access to the view controller and then it dawned on me the possibility of trying to execute the code using GCD.
__block MeetingViewController *safeSelf = self;
contentVC = [self initializeContentViewController: self.didLaunchFromInactive withPageIndex: intIndex];
NSArray *viewControllers = #[contentVC];
dispatch_async(dispatch_get_main_queue(), ^{
[safeSelf.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
});
The above worked like magic, and the shortcuts are leading to the correct page. Using a similar approach to mine hopefully yields the desired results for anyone else who wanted to get their shortcuts working by launching the app.

APNS to open a certain part of an application

I've just implemented a commenting feature in my app. Ideally when someone leaves a comment, I'd like all notified people be able to swipe the push notification and open the app on that post.
I assume you want to open the concerned page directly. There are many ways to go about this, and it depends on how your app is laid out.
If you want to open an inner page upon app launch, you can programmatically trigger the segues that the user would otherwise need to make manually. (this ensures the back/home buttons work as opposed to loading the desired page directly).
Here's an excerpt from one of my own code, your use case may not be the same, but this is all i can do unless you give us more details.
- (BOOL) navigateToRespectiveSectionforPushNot:(NSDictionary*)pushNot
{
id rootVC = self.window.rootViewController;
NSLog(#"ROOT CLASS : %#", [rootVC class]);
if ([rootVC isKindOfClass:[SWRevealViewController class]])
{
NSLog(#"Root Class looking good... mission Navigate!!");
SWRevealViewController *homeVC = (SWRevealViewController*) rootVC;
NSString *category = [[pushNot objectForKey:pushPayloadKeyaps] objectForKey:pushPayloadKeyCategory];
NSString *subCat = [[pushNot objectForKey:pushPayloadKeyaps] objectForKey:pushPayloadKeySubCategory];
NSLog(#"category : %# , subcat : %#",category,subCat);
//The code for the page to which i'm supposed to navigate to is contained in the push notification payload
if ([category isEqualToString:pushCategoryItemChat])
{
[homeVC.rearViewController performSegueWithIdentifier:#"chatPush" sender:nil];
UINavigationController *nc = (UINavigationController*)homeVC.frontViewController;
NSLog(#"FrontView Class : %#",[nc.viewControllers[0] class]);
UITableViewController *tvc = (UITableViewController*)nc.viewControllers[0];
NSDictionary *send = #{chatPushTargetUserId:subCat,chatPushTargetUserName:#"",chatPushTargetUserImage:#""};
[tvc performSegueWithIdentifier:#"seguePushDemoVC" sender:send];
return YES;
}
//communityPush historyPush
else if ([category isEqualToString:pushCategoryItemCommunity])
{
if ([subCat isEqualToString:pushSubCatItemNewRequest])
{
[homeVC.rearViewController performSegueWithIdentifier:#"communityPush" sender:nil];
return YES;
}
else if ([subCat isEqualToString:pushSubCatItemAccepted])
{
[homeVC.rearViewController performSegueWithIdentifier:#"communityPush" sender:nil];
return YES;
}
}
else if ([category isEqualToString:pushCategoryItemHistory])
{
[homeVC.rearViewController performSegueWithIdentifier:#"historyPush" sender:nil];
return YES;
}
}
else
{
UIAlertView *whoa = [[UIAlertView alloc] initWithTitle:#"WHOA!!" message:#" That wasn't supposed to happen. You are not even logged in. Call 911..." delegate:nil cancelButtonTitle:#"mmKay.." otherButtonTitles:nil, nil];
[whoa show];
}
return NO;
}
I hope the code is self explanatory. cheers

ivar for view controller in appdelegate.m

edit 1
I am adding some code to indicate its state after I have tried to work with codeInOrange's answer so far which so far behaves like my code originally behaved, that is sample link shows up at first in the text field and can be altered by the user, but when the user returns to the VC, any new link text has been replaced by the original sample link. My reason for posting this additional code is to try to reconnect with codeInOrange's promising answer because I am misunderstanding the logical flow of his original suggestions and his later comments.
In the current Storyboard I am leaving the Text field and the Placeholder Text empty because the sample link seems to be adequately supplied by the viewDidLoad method below.
- (void)viewDidLoad
{
[super viewDidLoad];
self.urlNameInput.text = #"sample http";
// Do any additional setup after loading the view, typically from a nib.
self.urlNameInput.clearButtonMode = UITextFieldViewModeAlways;
self.urlNameInput.clearsOnBeginEditing = NO;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == self.urlNameInput) {
[textField resignFirstResponder];
[self processPbn];
}
return YES;
}
- (void)viewDidAppear:(BOOL)animated
{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
// self.urlNameInput.text = appDelegate.stringForTextField;
appDelegate.stringForTextField = self.urlNameInput.text;
}
- (void) processPbn
{
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:self.urlNameInput.text] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[NSURLConnection sendAsynchronousRequest:theRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *connection, NSData *data, NSError *error)
{
// lots of detail code has been elided in this method
self.iboard = 0;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:toMatch options:NSRegularExpressionDotMatchesLineSeparators error:&error];
for (NSTextCheckingResult* board in [regex matchesInString:string options:NSRegularExpressionDotMatchesLineSeparators range:NSMakeRange(0, [string length])])
{
if (self.iboard>0) {
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.stringForTextField = self.urlNameInput.text;
}
}];
}
edit 1
edit 0
I do not want to preserve the text between application shutdowns and launches, so the answer using NSUserDefaults is not quite what I need.
Also, it appears from my trials that the solution suggested by Michael Dautermann which suggests either putting my intialization text in viewDidLoad or in the Xib or Storyboard, does not work because the text always returns to its initial value upon return to the VC (likely because the viewDidLoad method is triggered), so I think I do need to create an ivar in my AppDelegate.m as I asked in my original question, and not in my ViewController.m viewDidLoad, to get the desired result, apparently. Perhaps it would be easier to create a B00L ivar in AppDelegate.m which is a flag that tells whether original text or current text is desired. But I cannot figure out how to do that, either. So, please consider this edit in your answer.
edit 0
My AppDelegate.m contains the following code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
BDViewController *vc = [sb instantiateInitialViewController];
self.viewController = (id)vc;
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
In the VC I want an ivar, an NSString, to be set at launch so that it can be the example text in my UITextField. Later I want that UITextField to be adjusted to an new value when the user supplies valid text into a UITextField.
Currently in my VC.h, the text field is declared and is synthesized in VC.m as follows .
#property (nonatomic, strong) UITextField *urlNameInput;
#synthesize urlNameInput;
I have tried putting the following code into didFinishLaunchingWithOptions: but do not see the desired text when I run the app.
self.viewController.urlNameInput.text = #"example http";
How can I programmatically accomplish my goal of initializing the UITextField?
Put that "urlNameInput.text =" bit into your view controller's "viewDidLoad" method, instead of the "didFinishLaunchingWithOptions:" method (where your view controller is not likely yet instantiated.
Even better than that, just set the initial text in your storyboard or XIB file and then you can programmatically adjust it later on.
Ok I'm having a hard time understanding what you're trying to do but creating an NSString iVar on your app delegate (although there are many other solutions) will allow you to set the textfield text to whatever you want when that VC comes back on the screen.
In your AppDelegate.h
#property (strong, nonatomic) NSString *stringForTextField;
This way you can initialize your textfield text when the view is loaded (viewDidLoad)
self.urlNameInput.text = #"example http";
then whenever that text value needs to be changed (say for example in textFieldShouldReturn in the other view controller. I'm assuming you have another textfield based on your question)
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.stringForTextField = textField.text;
and in viewDidAppear in the VC with the textField set that value.
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
self.urlNameInput.text = appDelegate.stringForTextField;
probably not the best way to go about it, but it will work.
EDIT
Ok in viewDidAppear:
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
if ([appDelegate.stringForTextField isEqualToString:#""]){
self.urlNameInput.text = #"example http";
} else {
self.urlNameInput.text = appDelegate.stringForTextField;
}
Now what this will do is if the user goes to another view controller, and comes back, the text field text will be what the user last entered, unless in another view controller, stringForTextField is updated to some new value. If this still does not work, look at your processPbn method to make sure the if clause is entered and that value is set. Otherwise it will always say "example http"
I'm not understanding why it's unimportant to persist the previous value across application launches, especially when it is beneficial to your users to have it persist only during the application lifecycle. codeInOrange's answer works by adding a property to the AppDelegate. The only thing I would add to his answer is a conditional if() . If you want to do it without any properties, you can still use the NSUserDefaults.
At the top of your ViewController.m file
#define SetHTTPString(string) [[NSUserDefaults standardUserDefaults]setObject:string forKey:#"HTTPString"] //no semicolon
#define GetHTTPString() [[NSUserDefaults standardUserDefaults]objectForKey:#"HTTPString"] //no semicolon
Then, in viewWillAppear...
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSString *httpString = GetHTTPString();
if (httpString) {
self.urlNameInput.text = httpString;
} else {
self.urlNameInput.text = #"Example http";
}
}
Next, in the method where the user enters text and "enters it"
...methodToEnterURL {
SetHTTPString(self.urlNameInput.text);
}
Finally, if you absolutely want to destroy the value in the NSUserDefaults, add this method to your AppDelegate's didEnterBackground method:
[[NSUserDefaults standardUserDefaults]setObject:#"Example http" forKey:#"HTTPString"];
This is a perfect usage for NSUserDefaults. When the user enters something just store it in NSUserDefaults. Check to see if the NSUserDefaults entry is blank on each launch, and if so just display the original string.
Save the text in NSUserDefaults with something like:
[[NSUserDefaults standardUserDefaults]setObject:#"yourNewString" forKey:#"userTextEntered"];
And then just check it on each launch:
if([[NSUserDefaults standardUserDefaults] objectForKey:#"userTextEntered"])
{
//display the user entered string
}
else
{
//display the string that you want to display prior to text being entered
}
However, this solution is only necessary if you want to preserve the text between application shutdowns and launches.
The code below assumes that the Storyboard contains the initial, default Text (of at least 3 characters length).
I really appreciated the help I got from others, especially from codeInOrange . I actually believe this is codeInOrange's solution, but I was never able to quite put his pieces together until I finally stumbled upon this one.
I hope this is really a valid answer, and apologize to all if I did not state my question clearly or if I mistook others' valid answers, especially codeInOrange.
//
// ViewController.m
// StickyPlaceholder
//
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize textInput;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
if (!appDelegate.stringForTextField)appDelegate.stringForTextField = self.textInput.text ;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
if (textField == self.textInput) {
[textField resignFirstResponder];
// next line is dummy processing
if (self.textInput.text.length>2)appDelegate.stringForTextField = self.textInput.text;
}
return YES;
}
- (void)viewDidAppear:(BOOL)animated
{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
self.textInput.text = appDelegate.stringForTextField;
}
#end

How to reset UISearch from Appdelegate method applicationWillEnterForeground

I want to reset my UISearch when app is entering background, or entering foreground again. It would be enough when the tableview from UISearch gets hidden.
But when I try to hide it from AppDelegate.m it doesn't work. I have also logged the UIElements, there are also (null).
Here is how I try to access it:
- (void)applicationWillEnterForeground:(UIApplication *)application
{
XLog(#"");
/*
Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
*/
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
XLog(#"");
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController_iPad" bundle:[NSBundle mainBundle]];
} else {
XLog(#"");
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController_iPhone" bundle:[NSBundle mainBundle]];
}
XLog(#"searchViewController.searchBar.text: %#", searchViewController.searchBar.text);
searchViewController.tableViewSearch.hidden = YES; // is (null)
XLog(#"searchViewController.tableViewSearch: %#", searchViewController.tableViewSearch); // is (null)
}
How can I access that? Do I something wrong here, or is it not allowed to access elements from other classes thru appdelegate.m?
NSArray *ary_navigationControllerViews = [[NSArray alloc] initWithArray:[self.navigationController viewControllers]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.class.description == %#", [[SearchViewController class] description]];
NSArray *ary_viewController = [[NSArray alloc] initWithArray:[ary_navigationControllerViews filteredArrayUsingPredicate:predicate]];
if ([ary_viewController count] > 0)
{
SearchViewController *sVw = (SearchViewController*) [ary_viewController objectAtIndex:0] ;
sVw.tableViewSearch.hidden = YES;
}
You are initializing new instance of your view controller, instead you need to get existing instance of your view controller and hide your view. Hope this helps.

NSFilemanager doesn't save file when textFieldDidEndEditing is called a second time

I am having trouble with updating my tableView.
In the tableView of the popover managed by the rootviewcontroller, some items in my documents directory are displayed. In the detailViewcontroller, i change the names of those files by using the NSFilemanager. Regardless what I do, the tableView won't display the new ones. I get to see them if i close the app and open it again. At the moment, i try using notifications, but it doesn't work …
EDIT
I logged my documents directory, its definitely not a tableView problem, moreover, it works out well, but the second time I enter some text, nothing happens…
DetailViewController
- (void)textFieldDidEndEditing:(UITextField *)tf
{
textLabel.text = textField.text;
NSString* newName = textLabel.text;
newName = [newName stringByAppendingPathExtension:#"txt"];
NSString* newPath = [[currentFilePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName];
NSLog(#"%#",newPath);
[[NSFileManager defaultManager] moveItemAtPath:currentFilePath toPath:newPath error:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"DataSaved" object:nil];
}
RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView initWithFrame:self.tableView.frame style:UITableViewStyleGrouped];
self.clearsSelectionOnViewWillAppear = NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(dataSaved:) name:#"DataSaved" object:nil];
}
- (void)dataSaved:(NSNotification *)notification
{
[self loadDirectoryContents];
[self.tableView reloadData];
}
[self.tableView initWithFrame:self.tableView.frame style:UITableViewStyleGrouped];
This line looks a bit suspicious. How are you constructing your tableview?
It works out when I type in something. But if i type in something the second time without having anything selected in the tableView, the fileManager doesn't move the item to the path. Any suggestions? It doesnt seem to be a tableView related Problem.
I also thought I needed to set:
currentFilePath = newPath;
But that gave me a EXC_BAD_ACCESS.

Resources