所以我试图以编程方式从一个视图控制器转换到另一个视图控制器,以便我只能在用户需要登录时对其进行初始化。但是,xcode 不断给我一个错误,即它不在视图层次结构中并拒绝加载它。
视图控制器.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
视图控制器.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(调用我的网络服务)
#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(调用我的网络服务)
#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