Is it possible to call a performSegueWithIdentifier from another class? - ios

I just build a class to manage correctly my database and JSON request. The problem is that now, how can I perform the segue ?
Here is my code
In my view :
- (IBAction)loginClick:(id)sender
{
NSString *post = [NSString stringWithFormat:#"username=test&password=test"];
[[DataManagement sharedManager] WebServiceLogin:post];
}
- (void) showTypeView
{
[self performSegueWithIdentifier:#"showTypeView" sender:nil];
}
In my class :
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
...
switch ([[response valueForKey:#"success"] intValue])
{
case 0:
{
NSLog(#"error: %# error Description: %#", [response valueForKey:#"success"], [response valueForKey:#"error_message"]);
break;
}
case 1:
{
LoginViewController *showView = [LoginViewController new];
[showView showTypeView];
break;
}
default:
break;
}
...
}
When I launch, I have an error :
**
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<LoginViewController: 0x165afd30>) has no segue with identifier 'showTypeView''
*** First throw call stack:
(0x2592e2eb 0x250fadff 0x29e2b037 0xe1819 0xdb64f 0x25f64de1 0x25f64d99 0x25f64e8d 0x25e261ef 0x25edf04f 0xa77cab 0xa7f835 0x25e171e3 0x258415f9 0x25e170cb 0x25e16f95 0x25e16e29 0x258f1257 0x258f0e47 0x258ef1af 0x25841bb9 0x258419ad 0x26abbaf9 0x29b2dfb5 0xe3ea9 0x254f4873)
libc++abi.dylib: terminating with uncaught exception of type NSException
**

If you're using segueWithIdentifier then you need to already have the segue built in Storyboard and labeled correctly as "showTypeView". Otherwise you should use a navigation controller to push a view controller or use self presentViewController to show a modal view controller.
EDIT:
Building off of Larme's comment, you can build a delegate like this:
// In your class.h file
#property (weak, nonatomic)id<SegueDelegate> delegate;
// In class.m file
LoginViewController *showView = [LoginViewController new];
self.delegate = showView;
[self.delegate segue];
// In LoginViewController.h
#protocol SegueDelegate
-(void)segue;
#end
#interface LoginViewController: UIViewController <SegueDelegate>
-(void)segue;
#end
// In LoginViewController.m
#implementation LoginViewController
-(void)segue
{
[self performSegueWithIdentifier:#"showTypeView" sender:nil];
}
#end

Related

How to identify custom classes vs Framework Classes in Objective-C

I am working on an Analytics Project by Swizzling UIViewController methods viewDidAppear and viewDidAppear, code snippet as follows,
- (void) swizzledViewDidAppear : (BOOL)animated {
if ([UA isAppInitialized]) { // Check if Analytics Initialized
if ([[self class] isSubclassOfClass:[UIViewController class]]) {
[UA startPage:[NSString stringWithFormat:#"%#", NSStringFromClass ([self class])]];
}
}
[self swizzledViewDidAppear:animated];
}
- (void) swizzledViewDidDisappear : (BOOL)animated {
if ([UA isAppInitialized]) { // Check if Analytics Initialized
if ([[self class] isSubclassOfClass:[UIViewController class]]) {
[UA endPage:[NSString stringWithFormat:#"%#", NSStringFromClass ([self class])]];
}
}
[self swizzledViewDidDisappear:animated];
}
This is the code snippet where I want to track only the Custom ViewController, ex: MyViewController or FooViewController...etc and not Framework related classes like UICompatibilityInputViewController, UIInputWindowController...etc.
Please let me know how can I achieve this. I tried to check for Subclass but still at one point Framework classes are getting recorded.
Thanks,
Vijay
you can get a class's NSBundle and check if that bundle is yours.
swift example using an extension:
//code
extension NSObject {
static var isOurClass: Bool {
let appBundle = Bundle.main
let clsBundle = Bundle(for: self.self);
return clsBundle.bundlePath.hasPrefix(appBundle.bundlePath)
}
}
//test
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("appdelegate class ours? \(AppDelegate.isOurClass)")
print("NSString class ours? \(NSString.isOurClass)")
return true
}
}
basic objc example:
#import <Foundation/Foundation.h>
#interface T : NSObject
#end
#implementation T
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
NSBundle *bundleOfApp = [NSBundle mainBundle];
NSLog(#"%#", bundleOfApp.bundlePath);
//ours
T *t = [T new];
NSBundle *bundleOfT = [NSBundle bundleForClass:t.class];
NSLog(#"%#", bundleOfT.bundlePath);
if([bundleOfT.bundlePath hasPrefix:bundleOfApp.bundlePath]) {
NSLog(#"ours");
}
//theirs
bundleOfT = [NSBundle bundleForClass:NSString.class];
NSLog(#"%#", bundleOfT.bundlePath);
if([bundleOfT.bundlePath hasPrefix:bundleOfApp.bundlePath]) {
}
else {
NSLog(#"theirs");
}
}
}
In this case you have make instance of your class like and check it like
MyViewController *myVcntrl = [[MyViewController alloc]init];
if ([myVcntrl isKindOfClass:[MyViewController class]]) {
NSLog(#"Class is of MyViewController type");
}
else {
NSLog(#"Not of MyViewController type");
}
I was swizzling viewDidLoad, loadView and awakeFromNib for measuring load times and there is some strange behavior I've noticed.
For framework classes like UIInputWindowController, UIKeyboardCandidateGridCollectionViewController : awakeFromNib or loadView doesn't get called. They immediately appear after viewDidLoad has been called.
So the following lines of codes:
- (void)swizzled_awakeFromNib
{
NSLog(#"*** Awake from nib %#", NSStringFromClass(self.class));
[self swizzled_awakeFromNib];
}
- (void)swizzled_viewDidLoad
{
NSLog(#"*** View did load %#", NSStringFromClass(self.class));
[self swizzled_viewDidLoad];
}
- (void)swizzled_loadView
{
NSLog(#"*** Load view %#", NSStringFromClass(self.class));
[self swizzled_loadView];
}
Prints:
*** Awake from nib UINavigationController
*** View did load UINavigationController
*** Load view MyLoginViewController
*** View did load UIInputWindowController
*** View did load UIKeyboardCandidateGridCollectionViewController
*** View did load UIInputWindowController
*** View did load UIApplicationRotationFollowingControllerNoTouches
*** View did load MyLoginViewController
So maybe you can add a property to your category and set it to YES if awakeFromNib and/or loadView has called. Then check that bool in your viewDidLoad method to see if its a framework class.

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
}

-[__NSArrayM insertObject:atIndex:]: object cannot be nil when calling addChildBehavior:

There are 3 behaviors in my method, I'm pretty sure animationOptions is the one causing bug. AnimationOptions is only used to ban rotation.If i delete this behavior,my code work fine.
Here is my bug.Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil’
After I add a exception breakpoint, the breakpoint stay at this line:
[self addChildBehavior:self.animationOptions];
If i delete this line, my code work fine.
But how can i fix this bug, I can not find where is this line mistake
Here is my DropitBehavior.m
#import "DropitBehavior.h"
#interface DropitBehavior()
#property(strong,nonatomic) UIGravityBehavior *gravity;
#property(strong,nonatomic) UICollisionBehavior *collider;
#property(strong,nonatomic) UIDynamicItemBehavior *animationOptions;
#end
#implementation DropitBehavior
-(UIGravityBehavior *)gravity
{
if (!_gravity) {
_gravity=[[UIGravityBehavior alloc]init];
_gravity.magnitude=0.90;
}
return _gravity;
}
-(UICollisionBehavior *)collider
{
if (!_collider) {
_collider=[[UICollisionBehavior alloc]init];
_collider.translatesReferenceBoundsIntoBoundary=YES;
}
return _collider;
}
-(UIDynamicItemBehavior *)animationOptions
{
if (_animationOptions) {
_animationOptions=[[UIDynamicItemBehavior alloc]init];
_animationOptions.allowsRotation=NO;
}
return _animationOptions;
}
-(void)additem:(id <UIDynamicItem>)item
{
[self.gravity addItem:item];
[self.collider addItem:item];
[self.animationOptions addItem:item];
}
-(void)removeitem:(id <UIDynamicItem>)item
{
[self.gravity removeItem:item];
[self.collider removeItem:item];
[self.animationOptions removeItem:item];
}
-(instancetype)init
{
self=[super init];
[self addChildBehavior:self.gravity];
[self addChildBehavior:self.collider];
[self addChildBehavior:self.animationOptions];
return self;
}
#end
a NSMutable array doesn't accept a "nil" to be added to itself
"self.animationOptions" will call the
-(UIDynamicItemBehavior *)animationOptions
method and the method will return only "nil" all the time.
-(UIDynamicItemBehavior *)animationOptions
{
if (_animationOptions) {
_animationOptions=[[UIDynamicItemBehavior alloc]init];
your logic in this piece of code doesn't allow the system to construct "_animationOptions" object.
if (!_animationOptions)
{
..code..
}
would help

SIGABRT thread error running simple ios app

Ok so there have been a lot of answers to questions like this but none of them have worked for me. Basically i have written a very simple iOS app that has a label and a button. click the button and the label changes. Here is the code
//ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
- (IBAction)buttonPressed:(id)sender;
#property (strong, nonatomic) IBOutlet UILabel *predictionLabel;
#end
//
// ViewController.m
// CrystalBall
//
//
//
#import "ViewController.h"
#implementation ViewController
#synthesize predictionLabel;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setPredictionLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (IBAction)buttonPressed:(id)sender {
self.predictionLabel.text = #"Definitley Yes!";
}
#end
And when i run it in the simulator the app opens fine and then i click the "Predict" button and then it freezes and this is the error that shows up in green
Thread 1: Program recieved signal: "SIGABRT".
that is along a line that reads
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
The debugger says:
2013-01-19 22:53:30.511 CrystalBall[441:f803] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setText:]: unrecognized selector sent to instance 0x6a19c70'
* First throw call stack:
2013-01-19 22:53:30.511 CrystalBall[441:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setText:]: unrecognized selector sent to instance 0x6a19c70'
*** First throw call stack:
(0x13b9052 0x154ad0a 0x13baced 0x131ff00 0x131fce2 0x2385 0x13baec9 0x135c2 0x1355a 0xb8b76 0xb903f 0xb82fe 0x38a30 0x38c56 0x1f384 0x12aa9 0x12a3fa9 0x138d1c5 0x12f2022 0x12f090a 0x12efdb4 0x12efccb 0x12a2879 0x12a293e 0x10a9b 0x1da8 0x1d05)
terminate called throwing an exception(gdb)
Hopefully that is enough information. Thank you!
'-[UIView setText:]: unrecognized selector sent to instance 0x6a19c70'
means that you are trying to send the setText message to a UIView instance, which does not have any such method.
This possibly comes from the statement:
self.predictionLabel.text = #"Definitley Yes!";
so you should review how you defined predictionLabel and make sure that it is of the correct type.
About the fact that you the debugger is showing you the line:
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
you should define an exception breakpoint in Xcode to catch all exceptions:
go to the breakpoints tab in the left-hand pane;
at the bottom of the pane, you will find a + icon;
click it and the select Add exception breakpoint;
confirm and it's done.
Now, the debugger shall stop on the actual line causing sigabrt so you can inspect your objects' state.

IOS i got [UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] error

The error is not every time.
i had try to clean and rebuild app,but it is also.
error:
*** Assertion failure in -[UIWindowController
transition:fromViewController:toViewController:target:didEndSelector:],
/SourceCache/UIKit_Sim/UIKit-2372/UIWindowController.m:211
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Attempting to begin a modal transition from
<UINavigationController: 0x9190730> to <UINavigationController: 0x83a9dc0>
while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear
to know the current transition has completed'
*** First throw call stack:
(0x213d012 0x1e85e7e 0x213ce78 0x191bf35 0x10b8d05 0xeb74f3 0xeb7777 0x10be033f
0xeb77b7 0x104f0 0x1e996b0 0x18c6035 0x20c0f3f 0x20c096f 0x20e3734 0x20e2f44
0x20e2e1b 0x36437e3 0x3643668 0xdcd65c 0x1133f2 0x25c5)
libc++abi.dylib: terminate called throwing an exception
BaseController.h:
#class LoginViewController;
#interface BaseController:UIViewController
//...
#end
BaseController.m
#implement BaseController
//...
-(void)showLoginForm
{
UIViewController* loginx =(UIViewController*) [[LoginViewController alloc] init];
UINavigationController* navx = [[UINavigationController alloc] initWithRootViewController:loginx];
[navx.navigationBar setBackgroundImage:[UIImage imageNamed:#"title_bar.png"] forBarMetrics:UIBarMetricsDefault];
//added
//i can use #try to catch it
[self presentModalViewController:navx animated:YES];//<====it is error
[loginx release];
[navx release];
}
LoginViewController:
#interface LoginViewController:BaseController
//...
#end
otherViewController:
i will judge the user is login or not in this controller.if it is not login,i will call showLoginForm
//#interface otherViewController:BaseController
//......
-(void)viewDidLoad
{
//make a thread to call isLogin
}
-(void)isLogin
{
BOOL logined = YES;
//......
if(!logined)//i take this on MainThread,it has error also.
[super showLoginForm];
}
MainViewController:(it is the Main ViewController to show otherViewController)
//#interface MainViewController:BaseController
//......
-(void)buttonAction
{
otherViewController* other = [[otherViewController alloc] init];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:other];
[self presentModalViewController:navigation animated:YES];
//release
}
so ,Who knows how this is going on?
In otherViewController.m you should move the code that calls the isLogin method to
- (void)viewDidAppear:(BOOL)animated
This will make sure that the transition for the presentation of the otherViewController will have finished when [self presentModalViewController:navx animated:YES]; is called.

Resources