【问题标题】:Profile screen by using core data使用核心数据的配置文件屏幕
【发布时间】:2015-03-23 15:21:33
【问题描述】:

嘿,首先让大家知道我是 Core-Data 的新手,所以和我一起做文章, 好的,我有一个非常基本的登录系统,我有一个名为 "Account" 的实体和 2 个名为:"email"“密码”

让我们从问题开始,然后继续:

现在我能够将数据上传/插入到 sqlite 数据库中,并在用户尝试登录时使用“NSpredicate”来授权用户和密码。 该应用程序有3个窗口首页,登录,注册;我现在的问题是: 检索特定用户(即已登录)"email" 以显示到 "UIlabel"主页屏幕。

我为此创建了一个数组来存储结果,请看这里(这是在 “主页” 屏幕上):

NSArray *results = [context executeFetchRequest:request error:&error];

for (AccountBase *account in results) {

        _label.text = [NSString stringWithFormat:@"%@", account.email];

    }

问题:

我只得到最后一个注册“电子邮件”的用户,例如,如果现在新用户注册并且电子邮件是 “mail.com” 然后,他会看到一封名为“gmail.com”的旧邮件。

我的注册码:

-(IBAction)signup:(id)sender{

NSManagedObjectContext *context = [self managedObjectContext];

if (self.contactdb) {
    // Update existing device
   // [self.contactdb setValue:self.fullname.text forKey:@"fullname"];
    //[self.contactdb setValue:self.email.text forKey:@"email"];
    //[self.contactdb setValue:self.phone.text forKey:@"phone"];

} else {
    // Create a new device
    NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:context];
    [newDevice setValue:self.email.text forKey:@"email"];
    [newDevice setValue:self.password.text forKey:@"password"];

    NSLog(@"%@",newDevice);
    //[newDevice setValue:self.phone.text forKey:@"phone"];
}
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
    NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
}

[self dismissViewControllerAnimated:YES completion:nil];

}

问题:

没问题,据我所知,信息已经很好地发送到数据库了。

我的登录代码:

    - (IBAction)processLogin:(id)sender {



     NSManagedObjectContext *context = [self managedObjectContext];

    // CORE DATA
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Account" inManagedObjectContext:context];

    // set entity for request
    [request setEntity:entity];

    // filter results using a predicate
    NSPredicate *pred =[NSPredicate predicateWithFormat:(@"email = %@"), _emailfld.text];
    NSPredicate *pred2 =[NSPredicate predicateWithFormat:(@"password = %@"), _passwordfld.text];

    // set predicate for the request
    [request setPredicate:pred];
    [request setPredicate:pred2];

    NSError *error = nil;

    // store DB usernames in results array
    NSArray *results = [context executeFetchRequest:request error:&error];

    NSLog(@"The returned results are %@",results);

    // check text field against results stored in DB
    for (Account *anAccount in results) {
        if ([anAccount.email isEqualToString:_emailfld.text] || [anAccount.password isEqualToString:_passwordfld.text]){
           // NSLog(@"Your username exists");
             NSLog(@"Your pin is correct"); 
 [self performSegueWithIdentifier:@"showhome" sender:sender];

        }

        else if (![anAccount.email isEqualToString:_emailfld.text] || [anAccount.password isEqualToString:_passwordfld.text]){

          [self dismissViewControllerAnimated:YES completion:nil];

           NSLog(@"Your username is bad"); 
        }

        else{
            [self dismissViewControllerAnimated:YES completion:nil];
           NSLog(@"Username dosent exitst");
        }

    }


}

问题:

如果用户输入正确的信息,他被移动到主屏幕,则没有问题代码工作。

但是,这是一个很大的问题,但问题是我需要一个唯一标识符来处理内部核心数据,而且我知道它不像 mysql 数据库那样具有主键。我也听说过 Object-ID,但我不知道如何使用它。 发现零信息有助于谷歌和零示例。

主要问题:

我需要的是在用户登录后获取是电子邮件的对象 ID,然后在 Home 屏幕中获取此 ID,然后打印是电子邮件“UIlabel”

现在我不知道核心数据如何与唯一标识符一起工作,所以我需要一种方法来完成这项任务,并将我的 sqlite 数据库中的所有“电子邮件”与正确的用户区分开来。

【问题讨论】:

  • 您可以将 Account 对象存储到 AppDelegate 的属性中,然后您可以从应用程序的任何位置访问它。无需使用 objectids - 您拥有 Account 对象,因此您可以访问其电子邮件地址属性
  • 你能告诉我如何做到这一点,我对核心数据真的很陌生。就像你刚才说的陈尼斯
  • 嘿,如何使谓词同时检查(电子邮件和密码)?抱歉,我还不能投票,我对这个网站太陌生了..
  • NSPredicate *pred =[NSPredicate predicateWithFormat:(@"email = %@ and password=%@"), self.emailfld.text,self.passwordfld.text];养成使用 self. 而不是 _ 的习惯,除非你特别想绕过 setter/getter
  • OHHH 欺骗我 :) 谢谢你做得很好我现在将继续修复密码和钥匙串谢谢。

标签: ios objective-c xcode core-data nsmanagedobjectid


【解决方案1】:

你有一些你没有意识到的问题。首先,您不应该将密码存储在核心数据中,因为它不安全。此外,当您在获取请求上设置谓词时,它会替换任何现有的谓词,因此您的登录检查只会查看密码,而不是电子邮件地址(因为该谓词已被替换)。

对于您第一个陈述的问题,您看不到最后一个注册用户,除非您在获取请求上有日期或计数和排序描述符。您实际上会看到一个随机用户。您真正应该做的是使用表格视图来显示登录时的所有用户电子邮件地址(或不显示任何电子邮件地址)。

如果登录获取返回某些内容,则不需要检查它,因为您已经断言它是正确的。

登录后,您应该返回用户或将其存储在某个地方。另一个答案在应用程序委托中说,这将起作用,但这是不好的做法。您可能想要创建一个单例用户控制器来保存登录用户(并控制对它的访问)。

如果您需要在应用程序中为每个用户设置一个唯一的 Id,那么您应该创建一个 UUID 并将其添加到您实体的新属性中。

【讨论】:

  • 你说得对,这只是我的基本经验/核心数据的试验和错误,我知道密码应该首先在钥匙串中,然后才在核心数据中,我也会把你的非常认真的建议谢谢你!!。
  • 没问题。请记住,您可以投票并勾选有助于解决您的问题的答案;-)
【解决方案2】:

您可以向AppDelegate 类添加一个属性来存储登录用户的Account 对象-

AppDelegate.h

@property (strong,nonatomic) Account *currentUser;

然后你可以在你对用户进行身份验证时设置这个 -

- (IBAction)processLogin:(id)sender {



     NSManagedObjectContext *context = [self managedObjectContext];

    // CORE DATA
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Account" inManagedObjectContext:context];

    // set entity for request
    [request setEntity:entity];

    // filter results using a predicate
    NSPredicate *pred =[NSPredicate predicateWithFormat:(@"email = %@"), _emailfld.text];
    NSPredicate *pred2 =[NSPredicate predicateWithFormat:(@"password = %@"), _passwordfld.text];

    // set predicate for the request
    [request setPredicate:pred];
    [request setPredicate:pred2];

    NSError *error = nil;

    // store DB usernames in results array
    NSArray *results = [context executeFetchRequest:request error:&error];

    NSLog(@"The returned results are %@",results);

    // check text field against results stored in DB
    for (Account *anAccount in results) {
        if ([anAccount.email isEqualToString:_emailfld.text] || [anAccount.password isEqualToString:_passwordfld.text]){
           // NSLog(@"Your username exists");
             NSLog(@"Your pin is correct"); 
           AppDelegate *app=(AppDelegate *)[UIApplication sharedApplication].delegate;
           app.currentUser=anAccount;
 [self performSegueWithIdentifier:@"showhome" sender:sender];

        }

        else if (![anAccount.email isEqualToString:_emailfld.text] || [anAccount.password isEqualToString:_passwordfld.text]){

          [self dismissViewControllerAnimated:YES completion:nil];

           NSLog(@"Your username is bad"); 
        }

        else{
            [self dismissViewControllerAnimated:YES completion:nil];
           NSLog(@"Username dosent exitst");
        }

    }

}

然后,你可以在任何需要访问当前用户的地方使用

*AppDelegate *app=(AppDelegate *)[UIApplication sharedApplication].delegate;
self.sometextfield.text=app.currentUser.email;

【讨论】:

  • 嘿 Paulw 你能帮我解决一下我现在注意到的事情吗?只有当用户按下“登录”时,他们才能看到他们的“电子邮件”,所以基本上使用应用程序委托并不是一个好主意,因为除非他们点击登录,否则用户无法在他们的“个人资料”中看到他们的“电子邮件”但是如果我希望能够向他们展示他们的个人资料而不让他们每次都一遍又一遍地登录我应该怎么做才能通过它?
  • 我不明白您的评论 - 您可以使用我的答案中的代码从应用程序中的任何对象访问应用程序委托。如果您想在应用程序执行之间存储用户的成功登录状态,那么您将需要使用一些本地存储来执行此操作 - NSUserDefaults(不是很安全)或 Keychain(更安全)
  • 我在 NSUserDefaults 中有一个 -bool 用于用户登录时,但这不是问题,我也可以成功访问应用程序委托。对不起,让我更好地解释一下我自己。问题只是当您实际上已经登录到应用程序并通过“登录”屏幕时,您现在有了您的个人资料屏幕。您可以在个人资料屏幕中看到您的“电子邮件”,但在应用程序退出并重新打开应用程序后,您只记得您已登录,因为 nsuserdfuealts 的 -bool 并且您在个人资料屏幕中的信息未保存.
  • 您可以将CoreData配置文件对象的URI保存在NSUserDefaults - cocoawithlove.com/2008/08/…
  • 我似乎无法从本教程中理解任何内容。我尝试在登录屏幕中执行此操作: NSURL *uri = [[app.currentUser objectID] URIRepresentation]; NSData *uriData = [NSKeyedArchiver archivedDataWithRootObject:uri];但我对此不太确定,我只是不知道我需要做什么以及要查找/获取哪个对象 id。
猜你喜欢
  • 2012-05-24
  • 2018-11-24
  • 2014-07-30
  • 1970-01-01
  • 2015-03-09
  • 1970-01-01
  • 2023-04-10
  • 2019-05-17
相关资源
最近更新 更多