zoukankan      html  css  js  c++  java
  • iphone开发我的新浪微博客户端用户登录准备篇(1.1)

          首先说一下我这个的实现思路,登录支持多个账号,也就是说可以保存多个微博账号登录的时候选择其中一个登录。多个账号信息保存在sqlite的数据库中,每一个账号信息就是一条记录, 当用户启动微博客户端的时候去取保存在sqlite数据库中的账号记录信息,然后把这些在界面中以列表的形式展示出来,用户可以点击其中的一个账号进入微博,如果如果启动微博客户端的时候检查到sqlite数据库中一个账号都没有的时候,程序自动显示用户授权认证页面,本客户端是基于oauth认证实现的,所以使用新微博账号前需要进行授权认证,一个账号只需要第一次做一下授权认证然后会把user_id、Access Token和Access Secret以及用户名称和头像小图标一起保存到sqlite的数据库中,下次登录的时候可以不在需要输入账号和密码,直接在界面中点击已经选择的用户小图标进入微博。关于Access Token和Access Secret这个我就不解释了,不懂的可以google一下oauth的知识,其实我前面做android版本的微博客户端的时候写过一篇比较详细的介绍过关于oauth的随笔可以翻出来参考一下。

         从上面的思路来看用户登录有两种可能性,第一种数据库中尚无任何账号信息;第二种数据库中已经包含了一个或以上的账号信息。这两种情况显示不同的用户界面,两种情况的实现过程看下面的描述。

          

          第一种情况实现过程:1.查询sqlite数据库 -->2.无账号记录显示需要进行授权认证的提示信息界面(上图6) -->3.在上一步界面中点击开始按钮进入用户授权界面-->4.用户输入自己的微博账号和密码点击确定然后关闭用户授权界面(上图7)-->5.程序根据用户的授权获取这个账号的信息保存到sqlite库-->6.显示用户登录选择界面默认账号就是用户刚刚授权的账号

         

         第二种情况实现过程:1.查询sqlite数据库 -->2.已有账号记录获取所有账号信息并且显示用户登录选择界面 -->3.读取上一次登录的账号作为界面的默认选择用户显示(如上图2)-->4.点击添加按钮显示账号添加界面(如上图4)-->5.点击切换按钮显示账号选择列表界面(如下图3)-->6.点击删除按钮显示账号删除确认界面(如下图5)

         

          从上面的实现过程看涉及到的主要知识点:1.sqlite数据库操作(创建数据库、创建数据表、插入数据记录、读取数据记录);2、oauth授权认证(已经由sdk实现了调用相关方法即可);3、NSUserDefaults存取(用来记录上一次的登录账号)

         现在正式开始动手做一一些准备工作:

         一、到 http://code.google.com/p/minblog4sina/(关于这个可以参看:iphone开发我的新浪微博客户端-开篇)把我的这个sdk项目源代码checkout到本地,然后用xcode打开这个工程,在这个sdk工程的基础上开发微博客户端应用。

         二、设计sqlite数据库用来保存用户账号信息,我是用firefox的一个名为SQLite Manager的插件来创建sqlite数据库,这个使用非常简单就不介绍了自己装起来就知道怎么使用,我用它创建了一个名为weibo.sqlite的数据库,然后这这个数据库中创建了一个名为loginUser的表用来保存账号信息,loginUser表的,这个表包含5个字段分别用来保存user_id、账号昵称、Access Token、Access Secret、账号小图标,具体如下图:


         三、用xcode打开工程,然后把上一步完成的weibo.sqlite文件添加到工程的Resources文件夹中.

         四、在工程中添加类型为Objective-C class名为Sqlite的类用来负责sqlite库的创建、记录的读取、记录的添加等操作,同时在Xcode的左边树Frameworks右键添加名为libsqlite3.dylib的Framework,这个类库封装了sqlite库的操作。

        五、打开Sqlite.h添加如下代码,在这个文件中首先import了sqlite3.h,这个就是Frameworks中的libsqlite3.dylib类库,然后又import了User.h,这个是MinBlog4Sina的sdk中的用户账号对象类。又声明的4个方法分别是数据库初始化、获取用户记录列表、添加用户记录、删除用户记录。

    #import <Foundation/Foundation.h>
    #import <sqlite3.h>
    #import "User.h"

    @interface Sqlite : NSObject {
    sqlite3
    *database;
    }

    -(Sqlite *)init;
    -(NSMutableArray *)getUserList;
    -(BOOL)addUser:(User *)user;
    -(BOOL)delUser:(NSString *)name;

    @end

         六、打开Sqlite.m添加如下代码,这个文件里实现了上述的几个方法,所谓的数据库创建其实就是把上面第三个步骤中添加到工程的weibo.sqlite文件拷贝到本软件的目录中,在下面的-(Sqlite *)init方法中进行了拷贝操作。还有就是用户记录读取和添加中关于BLOB类型的数据处理,这里存储的是图片数据了,在添加的时候把图片转换成bytes类型,读取的时候把bytes类型转换成图片。

    #import "Sqlite.h"

    @interface Sqlite(private)

    -(void)createDatabaseIfNeeded:(NSString *)filename;
    -(NSString *)dataFilePath;
    -(BOOL)openDatabase;
    -(void)closeDatabase;

    @end

    @implementation Sqlite
    //初始化数据库
    -(Sqlite *)init
    {
    if (self= [super init]) {
    [self createDatabaseIfNeeded:
    @"weibo.sqlite"];
    }
    return self;
    }

    -(BOOL)delUser:(NSString *)name
    {
    BOOL sucess
    =[self openDatabase];
    if (sucess) {
    NSString
    *sql=[[NSString alloc] initWithFormat:@"delete from loginUser where screen_name='%@'",name];
    char *errorMsg;
    if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, &errorMsg)!=SQLITE_OK) {
    NSLog(
    @"del User error:%s",errorMsg);
    sqlite3_free(errorMsg);
    }
    else {

    }
    [sql release];
    }
    [self closeDatabase];
    return sucess;

    }

    //添加用户记录
    -(BOOL)addUser:(User *)user
    {
    BOOL sucess
    =[self openDatabase];
    if (sucess) {
    NSString
    *sql=[[NSString alloc] initWithFormat:@"insert into loginUser(user_id,screen_name,key,secret,icon)values(?,?,?,?,?)"];
    sqlite3_stmt
    *statement;
    if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &statement, nil)==SQLITE_OK)
    {

    NSString
    *uid=[NSString stringWithFormat:@"%@",user.userId];
    const char *user_idChar=[uid UTF8String];
    sqlite3_bind_text(statement,
    1, user_idChar, strlen(user_idChar), NULL);

    const char *screen_nameChar=[user.screen_name UTF8String];
    sqlite3_bind_text(statement,
    2, screen_nameChar, strlen(screen_nameChar), NULL);

    const char *keyChar=[user.key UTF8String];
    sqlite3_bind_text(statement,
    3, keyChar, strlen(keyChar), NULL);

    const char *secretChar=[user.secret UTF8String];
    sqlite3_bind_text(statement,
    4, secretChar, strlen(secretChar), NULL);

    NSData
    *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:user.profile_image_url]];
    sqlite3_bind_blob(statement,
    5, [imageData bytes], [imageData length], NULL);

    if(sqlite3_step(statement)==SQLITE_DONE)
    {
    NSLog(
    @"done");
    }
    else {
    NSLog(
    @"error");
    }
    sqlite3_finalize(statement);
    }
    [sql release];

    }
    [self closeDatabase];
    return sucess;
    }

    //获取用户记录列表
    -(NSMutableArray *)getUserList
    {
    NSMutableArray
    *list;
    BOOL sucess
    =[self openDatabase];
    if (sucess) {
    NSString
    *query=@"select * from loginUser";
    sqlite3_stmt
    *statement;
    if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil)==SQLITE_OK)
    {
    list
    =[[[NSMutableArray alloc] init]autorelease];
    while (sqlite3_step(statement)==SQLITE_ROW) {
    char *user_idChar=(char *)sqlite3_column_text(statement, 0);
    char *screen_nameChar=(char *)sqlite3_column_text(statement, 1);
    char *keyChar=(char *)sqlite3_column_text(statement, 2);
    char *secretChar=(char *)sqlite3_column_text(statement, 3);
    int bytes = sqlite3_column_bytes(statement, 4);
    const void *value = sqlite3_column_blob(statement, 4);

    NSString
    *user_id=[[NSString alloc] initWithUTF8String:user_idChar];
    NSString
    *screen_name=[[NSString alloc] initWithUTF8String:screen_nameChar];
    NSString
    *key=[[NSString alloc] initWithUTF8String:keyChar];
    NSString
    *secret=[[NSString alloc] initWithUTF8String:secretChar];
    UIImage
    *icon;
    if( value != NULL && bytes != 0 ){
    NSData
    *data = [NSData dataWithBytes:value length:bytes];
    icon
    =[UIImage imageWithData:data];
    }
    User
    *user=[[User alloc] init];
    user.userId
    =user_id;
    user.name
    =screen_name;
    user.key
    =key;
    user.secret
    =secret;
    if (icon) {
    user.icon
    =icon;
    }

    [list addObject:user];
    [user release];
    [user_id release];
    [screen_name release];
    [key release];
    [secret release];
    }
    sqlite3_finalize(statement);
    }
    }
    [self closeDatabase];

    return list;
    }


    //根据是否已经存在数据库决定是否要创建数据库
    -(void)createDatabaseIfNeeded:(NSString *)filename
    {

    NSAutoreleasePool
    *pool=[[NSAutoreleasePool alloc] init];
    NSFileManager
    *filemanage=[NSFileManager defaultManager];
    NSArray
    *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString
    *documentsDirectory=[paths objectAtIndex:0];
    NSString
    *writableDBPath=[documentsDirectory stringByAppendingPathComponent:filename];
    BOOL sucess
    =[filemanage fileExistsAtPath:writableDBPath];
    if (sucess) {
    return;
    }
    NSString
    *defaultDBPath=[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:filename];
    NSError
    *error;
    sucess
    =[filemanage copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
    if (!sucess) {
    NSLog(
    @"create Database rror:%@",[error localizedDescription]);
    }
    [pool release];
    }

    //获取数据库文件路径
    -(NSString *)dataFilePath
    {
    NSArray
    *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString
    *documentPath=[[paths objectAtIndex:0] stringByAppendingPathComponent:@"weibo.sqlite"];
    return documentPath;
    }

    //打开数据库
    -(BOOL)openDatabase
    {
    int returnValue=sqlite3_open([[self dataFilePath] UTF8String], &database);
    if (returnValue!=SQLITE_OK) {
    sqlite3_close(database);
    NSLog(
    @"open Database error:%@",sqlite3_errmsg(database));
    return NO;
    }
    else {
    return YES;
    }

    }

    //关闭数据库
    -(void)closeDatabase
    {
    if (sqlite3_close(database)!=SQLITE_OK) {
    NSLog(
    @"close Database error:%@",sqlite3_errmsg(database));
    }
    }

    @end

        七、在工程中添加类型为Objective-C class名为Global的类用来提供一些非常常用的公用方法。

        八、打开Global.h添加如下代码,声明了2个方法,一个是获取png的图片资源、另外一个是进行时间格式化输出的方法,这2个方法都是被声明成+类型,这样方便使用,这2个方法在后面篇章中经常会用到。

    #import <Foundation/Foundation.h>


    @interface Global : NSObject

    +(UIImage *) pngWithPath:(NSString *)path;
    +(NSString *) dateInFormat: (time_t)dateTime format:(NSString*) stringFormat;
    @end

        九、打开Global.m添加如下代码

    #import "Global.h"


    @implementation Global

    +(UIImage *) pngWithPath:(NSString *)path
    {
    NSString
    *fileLocation = [[NSBundle mainBundle] pathForResource:path ofType:@"png"];
    NSData
    *imageData = [NSData dataWithContentsOfFile:fileLocation];
    UIImage
    *img=[UIImage imageWithData:imageData];
    return img;
    }

    +(NSString *) dateInFormat: (time_t)dateTime format:(NSString*) stringFormat
    {
    char buffer[80];
    const char *format = [stringFormat UTF8String];
    struct tm * timeinfo;
    timeinfo
    = localtime(&dateTime);
    strftime(buffer,
    80, format, timeinfo);
    return [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding];
    }

    @end

          到处准备篇的工作就已经算是完成了,主要的编码工作就是sqlite的数据库操作了,在下一篇中我们会在这个基础上开始用户功能的开发。

  • 相关阅读:
    MySQL性能优化的最佳经验
    18个网站SEO建议
    sql之left join、right join、inner join的区别
    PHP与MYSQL事务处理
    Firefox上Web开发工具库一览
    SphinxSE的安装
    python XML
    python yaml
    C语言文本处理
    Linux strace命令
  • 原文地址:https://www.cnblogs.com/hll2008/p/2061211.html
Copyright © 2011-2022 走看看