Three20 这系列的文章也好久没更新了,学习的路上是阻挡不了我们程序猿的,哇咔咔~~ 今天我们主要学习一下 ASI 与 JSON 针对向服务端请求数据的知识。以前MOMO就给大伙说过没事多去GitHub去看看老外写的东西,这个网站真的特别好玩。今天说的AIS 与JSON都是GitHub上老外写的开源库。本文开始我在罗嗦一下,使用Three20开发时我的建议是 Three20 + FMDB + ASI + JSON 。 FMDB是数据库操作的类库,ASI全称是ASIHTTPRequest,可与服务器进行数据的交互 或者是2进制文件的交互包括断点续传等等非常强大的一个类库, 客户端与服务器都是以字符串的形式在做交互,以前在使用XML的时候开发者需要对大量的节点之间做解析,即使网上有现成的解析库但是MOMO觉得还是不好用。还是觉得JSON比较好用!~!! JSON就好比在本地维持一个字典对象,向服务器请求时将字典对象转换成字符串发给服务器,当服务器返回时在将字符串转换成字典对象,通过键值对的形式 对数据进行操作真的非常好用。然而这一切的一切JSON库都帮我们完成了。
首先我们学习在Three20之上构建ASI环境,ASI的下载地址是 https://github.com/pokeb/asi-http-request 。下载完毕后解压,在你的工程中将Class文件全部导入进来。如下图所示引入相应的类库,这里大家请和MOMO的保持一致。
下面就是最重要的一部,也是非常蛋疼的一部。当初学的时候就因为没加上这个导致我半个多小时才吧环境搭上,MOMO请大家一定要淡定!!如下图所示,在Header Search Paths中一定要加入 /usr/include/libxml2 切记!切记! 不然有一个错找不到头文件。。
OK 这一步你的ASI环境就配置OK啦。然后我们开始配置JSON,下载地址:https://github.com/stig/json-framework 和ASI一样,下载完后请把Classes文件夹中的文件拷贝至工程当中,为了区分开大家可为它们换个名称,下一步我们开始编写代码。
AppDelegate.m 这是入口类,应该没问题吧,这里我们写了两个页面 一个用来登录,一个显示登录结果。
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize window = _window;
- (void)dealloc
{
[_window release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//创建导航条
TTNavigator* navigator = [TTNavigator navigator];
navigator.persistenceMode = TTNavigatorPersistenceModeAll;
navigator.window = [[[UIWindow alloc] initWithFrame:TTScreenBounds()] autorelease];
//TTURLMap 非常重要的一个属性
//界面的点击切换完全取决与它的设定
TTURLMap* map = navigator.URLMap;
//如果须要访问wab页面的话 就必需添加
[map from:@"*" toViewController:[TTWebController class]];
//拼一个url 意思是如果访问 "tt://Login" 会进入 MyViewController class
[map from:@"tt://Login" toSharedViewController:[LoginViewController class]];
[map from:@"tt://Main" toViewController:[MainViewController class]];
if (![navigator restoreViewControllers]) {
//打开上面设置的url
[navigator openURLAction:[TTURLAction actionWithURLPath:@"tt://Login"]];
}
return YES;
}
@end
LoginViewController.h 首先是登录界面 这里将ASIHTTPRequest.h 与 JSON.h引入,登录页面是仿照FaceBook的在输入框中MOMO选择的是TabView。
#import <Three20/Three20.h>
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
#import "JSON.h"
@interface LoginViewController : TTTableViewController<UITextFieldDelegate>
{
//输入用户名
UITextField* userName;
//输入密码
UITextField* passWord;
//登录按钮
UIButton* keyDone;
//登录时动画
UIActivityIndicatorView *activity;
//登录半透明背景
UITextView *textView;
}
@end
LoginViewController.m 大量的逻辑都在这里面,请大家仔细看这个类,MOMO已经添加了详细的注释噢。。
#import "LoginViewController.h"
@implementation LoginViewController
- (id)initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
if (self = [super init]) {
//设置TabView的风格
self.tableViewStyle = UITableViewStyleGrouped;
//设置背景图片
self.view.backgroundColor=[UIColor colorWithPatternImage:TTIMAGE(@"bundle://Default.png")];
//用户名输入框
userName = [[[UITextField alloc] init]autorelease];
//这里设置它的代理在本类中
userName.delegate = self;
//默认灰色的文字,写入后会消失
userName.placeholder = @"请输入用户名";
//这里设置为true表示
//当IOS软键盘抬起后,输入框中若没有输入内容,右下角按钮将呈灰色状态
userName.enablesReturnKeyAutomatically = true;
//在这里设置IOS软键盘右下角文字显示内容为完成,这里还有很多选项。
userName.returnKeyType= UIReturnKeyDone;
//设置字体
userName.font = TTSTYLEVAR(font);
//设置IOS软键盘抬起后首字母不大写
userName.autocapitalizationType = UITextAutocapitalizationTypeNone;
//密码输入框
passWord = [[[UITextField alloc] init]autorelease];
//这里设置它的代理在本类中
passWord.delegate = self;
//默认灰色的文字,写入后会消失
passWord.placeholder = @"请输入密码";
//在密码输入框中右侧添加整体清除按钮
passWord.clearButtonMode = UITextFieldViewModeWhileEditing;
//在这里设置IOS软键盘右下角文字显示内容为完成,这里还有很多选项。
passWord.returnKeyType = UIReturnKeyDone;
//设置字体
passWord.font = TTSTYLEVAR(font);
//当IOS软键盘抬起后,输入框中若没有输入内容,右下角按钮将呈灰色状态
passWord.enablesReturnKeyAutomatically = true;
//输入后字符串显示为*符号
passWord.secureTextEntry =YES;
//在这里创建一个按钮,点击按钮后开始登录
keyDone = [UIButton buttonWithType:UIBarStyleBlack] ;
keyDone.frame = CGRectMake(10, 150, 300, 40);
[keyDone setTitle:@"登录" forState:UIControlStateNormal];
[keyDone addTarget:self action:@selector(ButtonPressed) forControlEvents:UIControlEventTouchUpInside];
//将按钮加入视图中
[self.view addSubview:keyDone];
//设置tableView的显示区域
self.tableView.frame = CGRectMake(0, 30, 320, 100);
//TabView默认触摸时可以上下滑动
//这里禁止它上滑滑动
self.tableView.scrollEnabled = NO;
//设置TableView背景颜色为透明状态
self.tableView.backgroundColor = [UIColor clearColor];
//将用户名与密码输入框加入视图中
self.dataSource = [TTListDataSource dataSourceWithObjects:
userName,
passWord,
nil];
}
return self;
}
//页面每次进入时都会调用这里的方法,
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//在这里将标题栏Navigation隐藏。
self.navigationController.navigationBarHidden=YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)dealloc
{
[super dealloc];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
//当用户点击IOS软键盘右下角完成按钮 此时关闭软键盘
[textField resignFirstResponder];
return YES;
}
//登陆时弹出窗口来显示loading动画
- (void)addLoading
{
//关闭软键盘
[userName resignFirstResponder];
[passWord resignFirstResponder];
//写入动画视图
textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 130, 130)];
//设置背景颜色为黑色
[textView setBackgroundColor:[UIColor blackColor]];
//正在登录
[textView setText:@"正在登录"];
//设置文字的颜色
[textView setTextColor:[UIColor whiteColor]];
//这里表示让文字居中显示
[textView setTextAlignment:UITextAlignmentCenter];
//字体大小
[textView setFont:[UIFont systemFontOfSize:15]];
//设置背景透明度
textView.alpha = 0.8f;
//设置view整体居中显示
textView.center = self.view.center;
//创建Loading动画视图动画有三个状态可供选择
activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
//设置动画视图的风格,这里设定它位白色
activity.activityIndicatorViewStyle=UIActivityIndicatorViewStyleWhiteLarge;
//设置它显示的区域 这里设置为整个手机屏幕大小
//为了避免登录动画播放时用户还能点击动画后面的高级控件
activity.frame = self.view.frame;
//动画居中显示
activity.center = self.view.center;
//开始播放动画
[activity startAnimating];
//将动画于与文字视图添加在窗口中
[self.view addSubview:textView];
[self.view addSubview:activity];
//释放
[activity release];
[textView release];
}
//关闭登录动画
-(void)removeLoading
{
//结束动画
[activity stopAnimating];
//删除动画视图
[activity removeFromSuperview];
//删除文字视图
[textView removeFromSuperview];
}
//点击登录按钮时
- (void)ButtonPressed
{
//判断用户名与密码长度是否大于0
if(userName.text.length == 0 ¦¦passWord.text.length == 0)
{
//创建对话框 提示用户重新输入
UIAlertView * alert= [[UIAlertView alloc] initWithTitle:@"用户名或密码不能为空" message:nil delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil];
//将这个UIAlerView 显示出来
[alert show];
//释放
[alert release];
}else
{
//开始播放loading动画
[self addLoading];
//下面这里就需要使用ASI的东东啦。
//服务器 访问地址
NSString *Server_Host = @"http://192.168.1.1:3000";
//地址的后缀, 这里应当与服务器约定好
NSString *server_base = [NSString stringWithFormat:@"%@/abc.json", Server_Host];
//设置ASI向服务器请求
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:server_base]];
//这是一个字典对象, 这里我把用户名与密码写入字典中
NSMutableDictionary *dictRequest = [NSMutableDictionary dictionaryWithObjectsAndKeys:
userName.text,@"userName",
passWord.text,@"password",
nil];
//当用户登陆时禁止状态栏中出现动画
//ASI底层会默认在状态栏中加入动画
[ASIHTTPRequest setShouldUpdateNetworkActivityIndicator: NO];
//这里就比较重要的
//[ dictRequest JSONFragment] 的意思是把字典对象变成一个string
//还记得开始MOMO说的 客户端与服务器之间的交互就是字符串
//服务器拿到这个字符串在做解析
[request setPostValue:[ dictRequest JSONFragment] forKey:@"request"];
//设置在本类中代理
[request setDelegate : self];
//开始一个异步请求
[request startAsynchronous];
}
}
//请求失败
- (void)requestFailed:( ASIHTTPRequest *)request
{
NSError *error = [request error ];
NSLog ( @"%@" ,error. userInfo );
//因为这里的IP我乱写的所以肯定会失败,
//在这里我直接让程序进入登录成功状态
[self LoginSuccess];
}
- (void)requestFinished:( ASIHTTPRequest *)request
{
//如果请求成功,它就是服务器返回的字符串
//如果使用JSON 服务器应当是在这里返回一个json类型的字符串
NSString *responseString = [request responseString ];
//因为我们拿到的是字符串,所以我们通过JOSN 中的方法把字符串在变成字典对象
//这样在使用起来就方便很多噢。。
NSMutableDictionary *dictRequest = [responseString JSONValue];
//因为服务器请求的地址有误,所以请求不到任何东东
[self LoginSuccess];
}
//登录成功
-(void) LoginSuccess
{
//删除登录动画
[self removeLoading];
//下面我们学习320页面之间切换数据的传递
//这里我取得当前用户在输入框中输入的用户名与密码
//将它们写入一个字典中
NSArray * key = [NSArray arrayWithObjects:@"userName",@"passWord", nil];
NSArray * obj = [NSArray arrayWithObjects:userName.text,passWord.text, nil];
//页面切换时 将字典对象传入下一个页面
TTURLAction *action = [[[TTURLAction actionWithURLPath:@"tt://Main"]
applyQuery:[NSDictionary dictionaryWithObjects:obj forKeys:key]]
applyAnimated:NO];
TTNavigator* navigator = [TTNavigator navigator];
//切换至登录成功页面
[navigator openURLAction:action];
}
@end
MainViewController.h 登录成功页面, 很简单 就是将用户在上个页面中输入的信息显示在这个页面中。
#import <Three20/Three20.h>
@interface MainViewController : TTViewController
{
NSString* userName;
NSString* userPassword;
UIButton* reLogin;
}
@end
MainViewController.m 这里应当比较好理解了吧?
#import "MainViewController.h"
@implementation MainViewController
//这个方法就比较重要的。
//默认320在页面切换时都会调用这个方法,
//参数2 就是上个页面过来时附带的字典对象
//我们在这里把用户在上个页面中输入的信息取出来
- (id)initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query
{
if ( self = [super init])
{
NSLog(@"%@" , query);
userName = [query objectForKey:@"userName"];
userPassword = [query objectForKey:@"passWord"];
}
return self;
}
-(void)viewWillAppear:(BOOL)animated
{
//隐藏标题栏
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden=NO;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationItem setHidesBackButton:YES];
self.title =@"登录成功";
UILabel* textName = [[UILabel alloc] initWithFrame:CGRectMake(180, 50, 100, 20)];
textName.text = [NSString stringWithFormat:@"%@%@",@"用户名:",userName];
UILabel* textPassword = [[UILabel alloc] initWithFrame:CGRectMake(180, 80, 100, 20)];
textPassword.text = [NSString stringWithFormat:@"%@%@",@"密码:",userPassword];
reLogin = [UIButton buttonWithType:UIBarStyleBlack] ;
reLogin.frame = CGRectMake(10, 150, 300, 40);
[reLogin setTitle:@"重新登录" forState:UIControlStateNormal];
[reLogin addTarget:self action:@selector(ButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:reLogin];
[self.view addSubview:textName];
[self.view addSubview:textPassword];
}
-(void) ButtonPressed
{
//当用户点击按钮时重新登录
TTURLAction *action = [[TTURLAction actionWithURLPath:@"tt://Login"]
applyAnimated:NO];
TTNavigator* navigator = [TTNavigator navigator];
[navigator openURLAction:action];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
@end
感觉本章的内容不是很难,所以我就不做过多的解释。唯一感觉比较恶心的就是搭建ASI的环境,最后雨松MOMO祝大家学习愉快、一起进步哇咔咔~~
下载地址:http://vdisk.weibo.com/s/ab-Id
大家下载以后是不能直接运行的,可以在工程中将红色的Three20相关的文件删除,然后重新直接一下搭建Three20环境的python语句即可。祝大家学习愉快,不早了晚安~~~
- 本文固定链接: https://www.xuanyusong.com/archives/1281
- 转载请注明: 雨松MOMO于 雨松MOMO程序研究院 发表






momo 啥时候写一片关于unity在ios中内置购买道具的例子啊?
等有时间了一定哈。。。 最近真心有点忙碌啊。。
楼主的队伍很强大
回头也得搭建一个才行,学习ing..加油。
其实博主说得也很有道理
Three20很强大…MOMO写了这样的文章可以在IOS群里告知下的,有N多人在学这个,说不会的…