1

我正在开发一个使用 ASIHTTPRequest 显示各种提要的应用程序。用户可以将新的源添加到存储在 SQLite 数据库中的应用程序中。目前,我在 FeedsViewController 的 viewDidLoad 方法中将提要提供给应用程序,但我希望能够检索包含源链接的数据并将其存储在数组中以使用它。

目前,该应用程序看起来类似于当前代码并低于当前代码:

这个

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.title =@"Lajmet";
    self.navigationController.navigationBar.tintColor = [UIColor blackColor];
    //self.tabBarController.tabBar.tintColor = [UIColor blackColor];
    self.allEntries = [NSMutableArray array];
    self.queue = [[NSOperationQueue alloc] init];
    self.feeds = [NSMutableArray arrayWithObjects:@"http://pcworld.al/feed",@"http://geek.com/feed", @"http://feeds.feedburner.com/Mobilecrunch",@"http://zeri.info/rss/rss-5.xml",
                  nil];


    [self.tableView reloadData];

    [self refresh];


}

我的视图包含添加和删除新源的函数 (AddSourcesViewController),如下所示,代码如下:

- (void)viewDidLoad
{
    [super viewDidLoad];
    arrayOfSource = [[NSMutableArray alloc]init];
    [[self myTableView]setDelegate:self];
    [[self myTableView]setDataSource:self];
    [self createOrOpenDB];

    // Display sources in table view
    sqlite3_stmt *statement;

    if (sqlite3_open([dbPathString UTF8String], &sourceDB)==SQLITE_OK) {
        [arrayOfSource removeAllObjects];

        NSString *querySql = [NSString stringWithFormat:@"SELECT * FROM SOURCES"];
        const char* query_sql = [querySql UTF8String];

        if (sqlite3_prepare(sourceDB, query_sql, -1, &statement, NULL)==SQLITE_OK) {
            while (sqlite3_step(statement)==SQLITE_ROW) {
                NSString *name = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
                NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
                NSString *category = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];

                SourceDB *source = [[SourceDB alloc]init];

                [source setName:name];
                [source setLink:link];
                [source setCategory:category];

                [arrayOfSource addObject:source];
            }
        }
    }
    [[self myTableView]reloadData];
}

- (void)createOrOpenDB
{
    NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docPath = [path objectAtIndex:0];

    dbPathString = [docPath stringByAppendingPathComponent:@"sources.db"];

    char *error;

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:dbPathString]) {
        const char *dbPath = [dbPathString UTF8String];

        //creat db here
        if (sqlite3_open(dbPath, &sourceDB)==SQLITE_OK) {
            const char *sql_stmt = "CREATE TABLE IF NOT EXISTS SOURCES (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, LINK TEXT, CATEGORY TEXT)";
            sqlite3_exec(sourceDB, sql_stmt, NULL, NULL, &error);
            sqlite3_close(sourceDB);
        }
    }
}

- (IBAction)addSourceButton:(id)sender
{
    char *error;
    if (sqlite3_open([dbPathString UTF8String], &sourceDB)==SQLITE_OK) {
        NSString *inserStmt = [NSString stringWithFormat:@"INSERT INTO SOURCES(NAME,LINK,CATEGORY) values ('%s', '%s','%s')",[self.nameField.text UTF8String], [self.linkField.text UTF8String],[self.categoryField.text UTF8String]];

        const char *insert_stmt = [inserStmt UTF8String];

        if (sqlite3_exec(sourceDB, insert_stmt, NULL, NULL, &error)==SQLITE_OK) {
            NSLog(@"Source added");

            SourceDB *source = [[SourceDB alloc]init];

            [source setName:self.nameField.text];
            [source setLink:self.linkField.text];
            [source setCategory:self.categoryField.text];

            [arrayOfSource addObject:source];
        }
        sqlite3_close(sourceDB);
    }
}

- (IBAction)deleteSourceButton:(id)sender
{
    [[self myTableView]setEditing:!self.myTableView.editing animated:YES];
}

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        SourceDB *s = [arrayOfSource objectAtIndex:indexPath.row];
        [self deleteData:[NSString stringWithFormat:@"Delete from sources where name is '%s'", [s.name UTF8String]]];
        [arrayOfSource removeObjectAtIndex:indexPath.row];

        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}

-(void)deleteData:(NSString *)deleteQuery
{
    char *error;

    if (sqlite3_exec(sourceDB, [deleteQuery UTF8String], NULL, NULL, &error)==SQLITE_OK) {
        NSLog(@"Source deleted");
    }
}

- (IBAction)showSourceButton:(id)sender
{
    sqlite3_stmt *statement;

    if (sqlite3_open([dbPathString UTF8String], &sourceDB)==SQLITE_OK) {
        [arrayOfSource removeAllObjects];

        NSString *querySql = [NSString stringWithFormat:@"SELECT * FROM SOURCES"];
        const char* query_sql = [querySql UTF8String];

        if (sqlite3_prepare(sourceDB, query_sql, -1, &statement, NULL)==SQLITE_OK) {
            while (sqlite3_step(statement)==SQLITE_ROW) {
                NSString *name = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
                NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
                NSString *category = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];

                SourceDB *source = [[SourceDB alloc]init];

                [source setName:name];
                [source setLink:link];
                [source setCategory:category];

                [arrayOfSource addObject:source];
            }
        }
    }
    [[self myTableView]reloadData];
}

现在我在我的 FeedsViewConrtoller 中创建了一个方法:

-(void)ReadData
{
    [self createOrOpenDB];

    feedsArray = [[NSMutableArray alloc] init];

    const char *dbPath = [dbPathString UTF8String];

    if (sqlite3_open(dbPath, &sourceDB)==SQLITE_OK)
    {
        const char *sqlstmt = "SELECT LINK FROM SOURCES";
        sqlite3_stmt *completedstmt;

        if (sqlite3_prepare_v2(sourceDB, sqlstmt, -1, &completedstmt, NULL)==SQLITE_OK)
        {

            while(sqlite3_step(completedstmt)==SQLITE_ROW)
            {

                NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 2)];

                SourceDB *source = [[SourceDB alloc]init];

                [source setLink:link];

                [feedsArray addObject:link];




            }
        }
    }
}

当我改变

self.feeds = [NSMutableArray arrayWithObjects:@"http://pcworld.al/feed",@"http://geek.com/feed", @"http://feeds.feedburner.com/Mobilecrunch",@"http://zeri.info/rss/rss-5.xml",
                  nil];

至:

self.feeds = [NSMutableArray arrayWithArray:feedsArray];

我收到以下错误:

2013-08-14 15:03:55.328 ShqipCom[3128:c07] (null)

我在这里做错了什么?

非常感谢!

花岗岩

4

2 回答 2

1

ReadData中,您将返回一列,然后使用以下命令检索第三列:

NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 2)];

那应该是:

NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 0)];

其他一些想法:

  1. 我们很难回答这个问题的部分原因是您没有报告 SQLite 错误。我建议在 SQLite 测试失败时进行记录,例如:

    if (sqlite3_prepare_v2(sourceDB, sqlstmt, -1, &completedstmt, NULL)==SQLITE_OK
    {
        while(sqlite3_step(completedstmt)==SQLITE_ROW)
        {
            NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 2)];
    
            SourceDB *source = [[SourceDB alloc]init];
    
            [source setLink:link];
    
            [feedsArray addObject:link];
        }
    }
    

    而您可能想要类似的东西:

    if (sqlite3_prepare_v2(sourceDB, sqlstmt, -1, &completedstmt, NULL)!=SQLITE_OK
    {
        NSLog(@"%s: prepare error: %s", __FUNCTION__, sqlite3_errmsg(sourceDB));
        return;
    }
    
    int rc;
    while ((rc = sqlite3_step(completedstmt)) == SQLITE_ROW)
    {
        NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 2)];
    
        SourceDB *source = [[SourceDB alloc]init];
    
        [source setLink:link];
    
        [feedsArray addObject:link];
    }
    
    if (rc != SQLITE_DONE) 
    {
        NSLog(@"%s: step error: %s", __FUNCTION__, sqlite3_errmsg(sourceDB));
        return;
    }
    

    您确实应该检查每个 SQLite 调用的结果,如果不成功则报告错误消息。否则你就瞎了。

  2. 在您的 INSERT 语句中,您是否 100% 确定这三个字段中永远不会有撇号?(此外,如果用户正在输入任何此类数据,则必须担心 SQL 注入攻击。)通常?,您会在 SQL 中使用占位符,使用 准备 SQL sqlite3_prepare_v2,然后使用sqlite3_bind_text将文本值绑定到这些占位符,然后您将sqlite3_step确认返回值SQLITE_DONE.

请注意,检查每个sqlite3_xxx函数调用的返回结果并执行所有必要的sqlite3_bind_xxx调用有点麻烦。在您的下一个项目中,如果您想简化 SQLite 代码,您可能需要考虑使用FMDB

于 2013-08-14T13:48:28.473 回答
0

NSMutableArray您可以添加任何对象

[myArray name addObject:mYString]; // add whatever object here;

如果你想给你添加 ArrayNSMutableArray

[myArray addObjectsFromArray:anOtherArray];
于 2013-08-14T13:18:49.683 回答