stackmob用法

 

前言,数据的增删改查很简单请到https://developer.stackmob.com/ios-sdk/developer-guide#Datastore查看。

1、只进行一次请求,创建多个关联的表

NSDictionary *classW = [NSDictionary dictionaryWithObjectsAndKeys:@"wangluo101",@"className" ,nil];
         NSDictionary *classJ = [NSDictionary dictionaryWithObjectsAndKeys:@"jisuanji101",@"className" ,nil];
        NSDictionary *DepartmentW = [NSDictionary dictionaryWithObjectsAndKeys:@"网络系",@"departmentName",classW,@"class", nil];
        NSDictionary *DepartmentJ = [NSDictionary dictionaryWithObjectsAndKeys:@"计算机系",@"departmentName",classJ,@"class", nil];
        NSArray *departments = [NSArray arrayWithObjects:DepartmentW,DepartmentJ, nil];
        NSDictionary *academy = [NSDictionary dictionaryWithObjectsAndKeys:@"信息学院",@"academyName",departments,@"department", nil];
        SMRequestOptions *option = [SMRequestOptions options];
        [option associateKey:@"department" withSchema:@"department"];
        [option associateKey:@"department.class" withSchema:@"class"];
        [[[SMClient defaultClient]dataStore] createObject:academy inSchema:@"academy" options:option onSuccess:^(NSDictionary *object, NSString *schema_) {
            NSLog(@"success");
        } onFailure:^(NSError *error, NSDictionary *object, NSString *schema_) {
            NSLog(@"error");
        }];

 //以上代码执行后,数据库会生成三个表,一个是academy,一个是department,一个是class。并且三个表之间的关联关系已经指定好。也就是academy下的department字段保存了两个department纪录的id,department表下的class字段保存了一个class表的一条纪录的id。这段代码既有一对多又有一对一,注意写法的区别。

 

2、创建用户并登陆

 

 SMRequestOptions *option = [SMRequestOptions optionsWithHTTPS];
        NSDictionary *user = [NSDictionary dictionaryWithObjectsAndKeys:[[alertView textFieldAtIndex:0] text],@"username",@"123321",@"password", nil];
        [[[SMClient defaultClient]dataStore] createObject:user inSchema:@"user" options:option onSuccess:^(NSDictionary *object, NSString *schema_) {
            NSLog(@"注册成功");
            [[SMClient defaultClient]loginWithUsername:[[alertView textFieldAtIndex:0] text] password:@"123321" onSuccess:^(NSDictionary *result) {
                NSLog(@"登陆成功");
            } onFailure:^(NSError *error) {
                 NSLog(@"登陆失败");
            }];
        } onFailure:^(NSError *error, NSDictionary *object, NSString *schema_) {
            NSLog(@"error");
        }];

 //需要注意的是,user表必须是Created as a User Object = YES,否则登陆失败。

 

3、检索当前登陆用户的信息

 

 [[SMClient defaultClient] getLoggedInUserOnSuccess:^(NSDictionary *result) {
                    NSLog(@"%@",result);
                } onFailure:^(NSError *error) {
                }];

 这个主要是从服务端的角度来看用户是登陆了。

 

4、用户登陆与被踢

       当一个用户登陆成功的时候,response会包含两个token,一个是access token,一个是refresh token。access toke用来对后续的request进行身份的识别,但是access token有过期的机制,当access token过期的时候,我们可能需要进行输入用户名、密码等等。但是,有了refresh token之后,一切都变的简单了。我们只需要用refresh token进行一次新的request。如果request成功返回了,我们会得到一个新的access token 和新的refresh token。

 

需要我们注意的是,一个用户先在一台设备上进行了登陆,然后又在第二台设备上进行了登陆。那么,第一台设备上的refresh token就invalid。这意味着,当第一台设备尝试进行刷新登陆的时候,服务器会拒绝这个请求,并给出refresh token invalid的提示。如果你想尽可能的无缝处理这个事件,你需要做的事是设置刷新失败的block.

 

[[SMClient defaultClient] setTokenRefreshFailureBlock:^(NSError *error, SMFailureBlock originalFailureBlock){
 
    // You are given the refresh error as well as the failure callback from the original request if you choose to call it.
    // We recommend logging in again by presenting a temporary login screen to the user, then picking up where they left off in the UI.
  // Optionally, you can store the username and password in the app's keychain and use it to refresh the login without any user interaction.
 
}];

 

 5、退出登陆

[[SMClient defaultClient]logoutOnSuccess:^(NSDictionary *result) {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"下线成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    } onFailure:^(NSError *error) {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"下线失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }];

 6、重置密码

重置密码需要以下几个步骤

1)页面上有一个忘记密码的按钮

2)当用户点击了忘记密码,那么提示用户输入忘记密码的用户名,实际上,这个用户名可以是邮箱,这样会减少user表的字段。

3)当用户名输入完成之后,点击提交,那么在你填的邮箱里会收到一个临时密码。

5)用临时密码登陆。如果你会捕捉到错误,这个error的code是-101,表示这是个临时密码,你应该跳转到修改密码页面。

6)跳转到修改密码页面之后,设置新密码点击登陆后,新密码设置成功。

 

以上几步用到的函数

登陆

 

[[SMClient defaultClient] loginWithUsername:usernamestr password:passwordstr onSuccess:^(NSDictionary *result) {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"登陆成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];

    } onFailure:^(NSError *error) {
        if (error.code == -101)//用的是临时密码
        {
            NewPasswordController *newPassword = [[NewPasswordController alloc]initWithUser:usernamestr tempPassword:passwordstr];
            [self.navigationController pushViewController:newPassword animated:YES];
            return ;
        }
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"登陆失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }];

 获得临时密码

 

 [[SMClient defaultClient] sendForgotPaswordEmailForUser:passwordModel.email onSuccess:^(NSDictionary *result) {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"新密码已经发送到邮箱" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    } onFailure:^(NSError *error) {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"修改密码失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }];

 修改密码

 

[[SMClient defaultClient]loginWithUsername:user temporaryPassword:temp settingNewPassword:passwordModel.password onSuccess:^(NSDictionary *result) {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"新密码登陆成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
            [alert show];
        } onFailure:^(NSError *error) {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"新密码登陆失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
            [alert show];
        }];

 7、密保

StackMob提供了锁定访问的功能,你可以禁止增删改查。甚至你可以在用户的级别上严格的控制这些权利,例如:



 选择最右第一项之后,只允许登陆用户进行增进行create。

8、地理位置服务

StackMob提供了一个类,叫GeoPoint,在这个类de一个实例当中你可以保存经纬度坐标。在服务端有这个数据类型,也就是说在表中你可以存这种数据类型。

开始定位

 

 [[[SMLocationManager sharedInstance] locationManager] startUpdatingLocation];

 

设置定位成功回调的block

 

 [SMGeoPoint getGeoPointForCurrentLocationOnSuccess:^(SMGeoPoint *geoPoint) {
}];

 SMGeoPoint从NSDictnory继承。里面包含了经纬度。

在回调当中我们可以做如下的处理

 

 [[[SMLocationManager sharedInstance]locationManager] stopUpdatingLocation];
        CLLocation *location = [[CLLocation alloc]initWithLatitude:[[geoPoint objectForKey:@"lat"] doubleValue] longitude:[[geoPoint objectForKey:@"lon"] doubleValue]];
        CLGeocoder *encoder = [[CLGeocoder alloc]init];
        [encoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
            if(placemarks.count <= 0) return ;
            CLPlacemark *placemark = [placemarks objectAtIndex:0];
            NSDictionary *addressdictionary = placemark.addressDictionary;
            NSString *address =[addressdictionary objectForKey:(NSString*)kABPersonAddressStreetKey];
            address = address==nil?@"":address;
            
            NSString *state = [addressdictionary objectForKey:(NSString*)kABPersonAddressStateKey];
            state = state == nil?@"":state;
            
            NSString *city = [addressdictionary objectForKey:(NSString*)kABPersonAddressCityKey];
            city = city == nil?@"":city;
            NSString *locationStr = [NSString stringWithFormat:@"你在%@省%@市%@街",state,city,address];
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"定位成功" message:locationStr delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
            [alert show];

 也就是把经纬度反编码为实际的地理位置。

9、查看附近的人

 

- (void)checkNear :(id)sender
{
    [[[SMLocationManager sharedInstance]locationManager] startUpdatingLocation];
    [SMGeoPoint getGeoPointForCurrentLocationOnSuccess:^(SMGeoPoint *geoPoint) {
        SMQuery *query = [[SMQuery alloc]initWithSchema:@"location"];
        [query where:@"coordinate" isWithin:5 milesOfGeoPoint:geoPoint];
        [[[SMClient defaultClient]dataStore] performQuery:query onSuccess:^(NSArray *results) {
            for (NSDictionary *point in results)
            {
                NSLog(@"%@",[point objectForKey:@"username"]);
            }
        } onFailure:^(NSError *error) {
            
        }];
    } onFailure:^(NSError *error) {
        
    }];
}

 10、文件的存储

 

- (void)setHeadAction: (id)sender
{
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSString* pathToImageFile = [bundle pathForResource:@"head" ofType:@"png"];
    NSData *data = [[NSData alloc]initWithContentsOfFile:pathToImageFile];
    NSString *dataStr = [SMBinaryDataConversion stringForBinaryData:data name:@"[email protected]" contentType:@"image/png"];
    [[SMClient defaultClient] getLoggedInUserOnSuccess:^(NSDictionary *result) {
        NSDictionary *imageDic = [NSDictionary dictionaryWithObjectsAndKeys:dataStr,@"picture", [result objectForKey:@"username"],@"username",nil];
        
        SMQuery *query = [[SMQuery alloc]initWithSchema:@"location"];
        [query where:@"username" isEqualTo:[result objectForKey:@"username"]];
        [[[SMClient defaultClient]dataStore] performQuery:query onSuccess:^(NSArray *results) {
            
            [[[SMClient defaultClient]dataStore] updateObjectWithId:[results[0] objectForKey:@"location_id"] inSchema:@"location" update:imageDic onSuccess:^(NSDictionary *object, NSString *schema) {
                NSLog(@"头像设置成功");
            } onFailure:^(NSError *error, NSDictionary *object, NSString *schema) {
                NSLog(@"头像设置失败");
            }];
        } onFailure:^(NSError *error) {
            
        }];
        
       
        
    } onFailure:^(NSError *error) {
        
    }];
    
    
}

 把NSData转换为NSString,然后在保存到服务器上去。有一个我问题需要注意的是picture的字段必须是Binary,这时候StackMob会提醒你去注册s3,这个是要花钱的。

 

9、检查网络状态

SMNetworkStatus status = [[SMClient defaultClient].networkMonitor currentNetworkStatus];
    if(status == SMNetworkStatusReachable)
    {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"网络畅通" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }
    if(status == SMNetworkStatusNotReachable)
    {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"无网络" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }
    if(status == SMNetworkStatusUnknown)
    {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"未知的网络" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }

 10、进行推送。

stackmob 推送是收费的,每月399$,我没有进行测试,测试不起,这里不再详细讲解。

你可能感兴趣的:(stack)