视图控制器不在视图层次结构?

所以我想通过编程方式从一个视图控制器转换到另一个视图控制器,以便我只能在用户需要login时初始化它。 但是,xcode不断给我的错误,它不是在视图层次结构,并拒绝加载到它。

ViewController.h

#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end 

ViewController.m

 #import "ViewController.h" #import "API.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; if (![[API sharedInstance] isAuthorized]) { [self performSegueWithIdentifier:@"ShowLogin" sender:nil]; }// Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end 

LoginScreen.h(控制器不在层次结构中)

 #import <UIKit/UIKit.h> @interface LoginScreen : UIViewController { //the login form fields IBOutlet UITextField *fldUsername; IBOutlet UITextField *fldPassword; } //action for when either button is pressed -(IBAction)btnLoginRegisterTapped:(id)sender; @end 

LoginScreen.m(控制器显然不在层次结构中)

 #import "LoginScreen.h" #import "UIAlertView+error.h" #import "API.h" #include <CommonCrypto/CommonDigest.h> #define kSalt @"(protected value)" @implementation LoginScreen -(void)viewDidLoad { [super viewDidLoad]; } #pragma mark - View lifecycle - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } -(IBAction)btnLoginRegisterTapped:(UIButton*)sender { //form fields validation if (fldUsername.text.length < 4 || fldPassword.text.length < 4) { [UIAlertView error:@"Enter username and password over 4 chars each."]; return; } //salt the password NSString* saltedPassword = [NSString stringWithFormat:@"%@%@", fldPassword.text, kSalt]; //prepare the hashed storage NSString* hashedPassword = nil; unsigned char hashedPasswordData[CC_SHA1_DIGEST_LENGTH]; //hash the pass NSData *data = [saltedPassword dataUsingEncoding: NSUTF8StringEncoding]; if (CC_SHA1([data bytes], [data length], hashedPasswordData)) { hashedPassword = [[NSString alloc] initWithBytes:hashedPasswordData length:sizeof(hashedPasswordData) encoding:NSASCIIStringEncoding]; } else { [UIAlertView error:@"Password can't be sent"]; return; } //check whether it's a login or register NSString* command = (sender.tag==1)?@"register":@"login"; NSMutableDictionary* params =[NSMutableDictionary dictionaryWithObjectsAndKeys:command, @"command", fldUsername.text, @"username", hashedPassword, @"password", nil]; //make the call to the web API [[API sharedInstance] commandWithParams:params onCompletion:^(NSDictionary *json) { //result returned NSDictionary* res = [[json objectForKey:@"result"] objectAtIndex:0]; if ([json objectForKey:@"error"]==nil && [[res objectForKey:@"IdUser"] intValue]>0) { [[API sharedInstance] setUser: res]; [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; //show message to the user [[[UIAlertView alloc] initWithTitle:@"Logged in" message:[NSString stringWithFormat:@"Welcome %@",[res objectForKey:@"username"]] delegate:nil cancelButtonTitle:@"Close" otherButtonTitles: nil] show]; } else { //error [UIAlertView error:[json objectForKey:@"error"]]; } }]; } @end 

API.h(调用我的Web服务)

 #import "AFHTTPClient.h" #import "AFNetworking.h" typedef void (^JSONResponseBlock)(NSDictionary* json); @interface API : AFHTTPClient @property (strong, nonatomic) NSDictionary* user; +(API*)sharedInstance; //check whether there's an authorized user -(BOOL)isAuthorized; //send an API command to the server -(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock; -(NSURL*)urlForImageWithId:(NSNumber*)IdPhoto isThumb:(BOOL)isThumb; @end 

API.m(调用我的Web服务)

 #import "API.h" //the web location of the service #define kAPIHost @"(protected web address)" #define kAPIPath @"" @implementation API @synthesize user; #pragma mark - Singleton methods /** * Singleton methods */ +(API*)sharedInstance { static API *sharedInstance = nil; static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, ^{ sharedInstance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kAPIHost]]; }); return sharedInstance; } #pragma mark - init //intialize the API class with the deistination host name -(API*)init { //call super init self = [super init]; if (self != nil) { //initialize the object user = nil; [self registerHTTPOperationClass:[AFJSONRequestOperation class]]; // Accept HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 [self setDefaultHeader:@"Accept" value:@"application/json"]; } return self; } -(BOOL)isAuthorized { return [[user objectForKey:@"IdUser"] intValue]>0; } -(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock { NSData* uploadFile = nil; if ([params objectForKey:@"file"]) { uploadFile = (NSData*)[params objectForKey:@"file"]; [params removeObjectForKey:@"file"]; } NSMutableURLRequest *apiRequest = [self multipartFormRequestWithMethod:@"POST" path:kAPIPath parameters:params constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) { if (uploadFile) { [formData appendPartWithFileData:uploadFile name:@"file" fileName:@"photo.jpg" mimeType:@"image/jpeg"]; } }]; AFJSONRequestOperation* operation = [[AFJSONRequestOperation alloc] initWithRequest: apiRequest]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { //success! completionBlock(responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { //failure :( completionBlock([NSDictionary dictionaryWithObject:[error localizedDescription] forKey:@"error"]); }]; [operation start]; } -(NSURL*)urlForImageWithId:(NSNumber*)IdPhoto isThumb:(BOOL)isThumb { NSString* urlString = [NSString stringWithFormat:@"%@/%@upload/%@%@.jpg", kAPIHost, kAPIPath, IdPhoto, (isThumb)?@"-thumb":@""]; return [NSURL URLWithString:urlString]; } @end 

问题是viewDidLoad被调用的时候,你的初始视图控制器的视图还没有被添加到窗口中。

将该呼叫移至viewDidAppear:

 -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (![[API sharedInstance] isAuthorized]) { [self performSegueWithIdentifier:@"ShowLogin" sender:self]; } }