Comparing class is giving incorrect output - ios

I am using below code to check view controllers.
NSLog(#"addProductClicked 1===%#", self.class);
NSLog(#"addProductClicked 2===%#", [CategoriesViewController class]);
if ([self.class isKindOfClass:[CategoriesViewController class]]) {
NSLog(#"you go it right");
} else {
NSLog(#"you go it wrong");
}
The output I get is as below.
addProductClicked 1===CategoriesViewController
addProductClicked 2===CategoriesViewController
you go it wrong
Any idea what is going wrong?
Just to update, below is what I have defined my view controller...
#interface CategoriesViewController : GlobalViewController {
Now in GlobalViewController I have method where I am checking above...

The variable you want to class check should be passed in as an object, not as a class.
if ([self isKindOfClass:[CategoriesViewController class]]) {
NSLog(#"you go it right");
} else {
NSLog(#"you go it wrong");
}

Thats is wrong comparison. You call isKindOfClass: on the object of that class. Something like this:
CategoriesViewController *obj = [[CategoriesViewController alloc] init];
[obj isKindOfClass:CategoriesViewController];
In your case you probably want to put a check on self.

Related

UIPopoverController isPopoverVisible returns wrong value

if([messageNotification isPopoverVisible])
[messageNotification dismissPopoverAnimated:YES];
I have the above two lines of code in my project where message_Notification is a UIPopovercontroller's object.
The problem is isPopoverVisible returns false when my Popover actually presented on the main viewController. Any idea about this??
Check that message_Notification is available or not and then check for visiblity
And I think there is some inconsistency because messageNotification and message_Notification should be same as I have done in my code
if(messageNotification)
{
if([messageNotification isPopoverVisible])
{
[messageNotification dismissPopoverAnimated:YES];
}
}
else
{
NSLog(#"Not availble");
}

isKindOfClass Bool if statement logging NO

I'm checking if toViewController, which is the 2nd Tab in my tabBar, is of the class MatchCenterViewController, but the else statement is running instead, which tells me that it's not of that class.
I'm positive that the UIViewController in that tab is connected to MatchCenterViewController, so what else could cause this if statement to not work?
NSLog(#"numberOfMatches is 1");
UIViewController *toViewController = [self.tabBarController viewControllers][1];
NSLog(#"toViewController: %#", toViewController);
if ([toViewController isKindOfClass:[MatchCenterViewController class]]) {
NSLog(#"2nd matchcenter if statement works");
MatchCenterViewController *matchViewController = (MatchCenterViewController *)toViewController;
matchViewController.didAddNewItem = YES;
NSLog(#"alright they're set, time to switch");
}
else {
NSLog(#"toViewController is not MatchCenterViewController");
}
[self.tabBarController setSelectedIndex:1];
You can add NSLog(#"toViewController is of class: %#", NSStringFromClass([toViewController class]); and see the actual view controller class.
Or if didAddNewItem is a property that only MatchCenterViewController has, you can try this way:
if ([toViewController respondsToSelector:#selector(setDidAddNewItem:)]) {
// this is MatchCenterViewController
} else {
// this is not MatchCenterViewController
}

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

Check if a Specific Instance of class already exists

is there anyway to check if a specific instance of a class has already been created. I feel like it is hard to check if the instance already exists when there is a chance you may not have created it yet.
Here is my code:
-(IBAction)done:(id)sender
{ //I want to figure out how to check if 'newWindow' already exists before I create another 'newWindow'
SimpleTableView *newWindow = [self.storyboard instantiateViewControllerWithIdentifier:#"SimpleTableView"];
[self.navigationController pushViewController:newWindow animated:YES];
}
Thanks for all the help guys.
Yes, there is a simple way to do it.
You just need to have some reference to it (for example create a property) and check whether it is nil (not initialized) or not. You can do it like this:
if(!myReference){
//if you get here it means that it hasn't been initialized yet so you have to do it
}
First make newWindow an ivar or a property.
Then:
if (!newWindow){
newWindow = [self.storyboard instantiateViewControllerWithIdentifier:#"SimpleTableView"];
}
I wrote you a method that checks all viewControllers in UINavigationController:
- (BOOL)classExistsInNavigationController:(Class)class
{
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:class])
{
return YES;
}
}
return NO;
}
Use it like this:
- (IBAction)done:(id)sender
{
//I want to figure out how to check if 'newWindow' already exists before I create another newWindow
if (![self classExistsInNavigationController:[SimpleTableView class]])
{
SimpleTableView *newWindow = [self.storyboard instantiateViewControllerWithIdentifier:#"SimpleTableView"];
[self.navigationController pushViewController:newWindow animated:YES];
}
}
You can also do something like this:
- (UIViewController *)classExistsInNavigationController:(Class)class
{
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:class])
{
return controller;
}
}
return nil;
}
And use it like this if you want to pop to the viewController that exists already:
- (IBAction)done:(id)sender
{
//I want to figure out how to check if 'newWindow' already exists before I create another newWindow
UIViewController *controller = [self classExistsInNavigationController:[SimpleTableView class]];
if (!controller)
{
SimpleTableView *newWindow = [self.storyboard instantiateViewControllerWithIdentifier:#"SimpleTableView"];
[self.navigationController pushViewController:newWindow animated:YES];
}
else
{
[self.navigationController popToViewController:controller animated:YES];
}
}
You can use if/else to check newWindow exists or not.
if (newWindow) { // newWindow is exist to do something
// Do something.
} else { // newWindow is not exist to do something
// Do something.
}
You can implement an instance counter (https://stackoverflow.com/a/30509753/4647396) in the class you want to track.
Then just check if the counter is greater than 0.
If I interpret your question correctly you just want to know wether an instance exists and dont need a reference to it.

IOS UIMenuController UIMenuItem, how to determine item selected with generic selector method

With the following setup
....
MyUIMenuItem *someAction = [[MyUIMenuItem alloc]initWithTitle : #"Something" action : #selector(menuItemSelected:)];
MyUIMenuItem *someAction2 = [[MyUIMenuItem alloc]initWithTitle : #"Something2" action : #selector(menuItemSelected:)];
....
- (IBAction) menuItemSelected : (id) sender
{
UIMenuController *mmi = (UIMenuController*) sender;
}
How to figure out which menu item was selected.
And don't say that you need to have two methods... Thanks in advance.
Okay, I've solved this one. The solution isn't pretty, and the better option is "Apple fixes the problem", but this at least works.
First of all, prefix your UIMenuItem action selectors with "magic_". And don't make corresponding methods. (If you can do that, then you don't need this solution anyway).
I'm building my UIMenuItems thus:
NSArray *buttons = [NSArray arrayWithObjects:#"some", #"random", #"stuff", nil];
NSMutableArray *menuItems = [NSMutableArray array];
for (NSString *buttonText in buttons) {
NSString *sel = [NSString stringWithFormat:#"magic_%#", buttonText];
[menuItems addObject:[[UIMenuItem alloc]
initWithTitle:buttonText
action:NSSelectorFromString(sel)]];
}
[UIMenuController sharedMenuController].menuItems = menuItems;
Now your class that catches the button tap messages needs a few additions. (In my case the class is a subclass of UITextField. Yours might be something else.)
First up, the method that we've all been wanting to have but that didn't exist:
- (void)tappedMenuItem:(NSString *)buttonText {
NSLog(#"They tapped '%#'", buttonText);
}
Then the methods that make it possible:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
NSString *sel = NSStringFromSelector(action);
NSRange match = [sel rangeOfString:#"magic_"];
if (match.location == 0) {
return YES;
}
return NO;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
if ([super methodSignatureForSelector:sel]) {
return [super methodSignatureForSelector:sel];
}
return [super methodSignatureForSelector:#selector(tappedMenuItem:)];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
NSString *sel = NSStringFromSelector([invocation selector]);
NSRange match = [sel rangeOfString:#"magic_"];
if (match.location == 0) {
[self tappedMenuItem:[sel substringFromIndex:6]];
} else {
[super forwardInvocation:invocation];
}
}
One would expect that the action associated with a given menu item would include a sender parameter that should point to the chosen menu item. Then you could simply examine the title of the item, or do as kforkarim suggests and subclass UIMenuItem to include a proeprty that you can use to identify the item. Unfortunately, according to this SO question, the sender parameter is always nil. That question is over a year old, so things may have changed -- take a look at what you get in that parameter.
Alternately, it looks like you'll need to a different action for each menu item. Of course, you could set it up so that all your actions call a common method, and if they all do something very similar that might make sense.
Turns out it's possible to obtain the UIButton object (which is actually UICalloutBarButton) that represents UIMenuItem if you subclass UIApplication and reimplement -sendAction:to:from:forEvent:. Although only -flash selector goes through UIApplication, it's enough.
#interface MyApplication : UIApplication
#end
#implementation MyApplication
- (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event
{
// target == sender condition is just an additional one
if (action == #selector(flash) && target == sender && [target isKindOfClass:NSClassFromString(#"UICalloutBarButton")]) {
NSLog(#"pressed menu item title: %#", [(UIButton *)target titleLabel].text);
}
return [super sendAction:action to:target from:sender forEvent:event];
}
#end
You can save target (or any data you need from it) in e.g. property and access it later from your UIMenuItem's action.
And to make your UIApplication subclass work, you must pass its name as a third parameter to UIApplicationMain():
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, NSStringFromClass([MyApplication class]), NSStringFromClass([YOUR_APP_DELEGATE class]));
}
}
This solution works on iOS 5.x-7.0 as of post date (didn't test on older versions).
ort11, you might want to create a property of myuimenuitem and set some sort of Tag. Thay way the object of sender could be recognized by its tag it. In Ibaction then you can set a switch statement that can correspond to each sender.tag and work throught that logic. I guess thats the simplest way to go.

Resources