图像不是从数据库中获取的

时间:2013-08-16 03:49:22

标签: iphone json parsing uiimageview exc-bad-access

我在服务器中存储了一些图像。我使用JSON从服务器获取远程数据。当我在本地数据库中存储图像时,它正在工作。当我使用json url时,它无法正常工作。我收到EXC_BAD_ACCESS错误。

代码:

Mysof.h文件:

@interface Mysof : NSObject{
    NSInteger sofaId;
    NSString *sofa;
    NSString *rating;
    UIImage *photo;
}

@property (nonatomic,retain)NSString *sofa;
@property (nonatomic, assign) NSInteger sofaId;
@property (nonatomic, retain)NSString *rating;
@property (nonatomic, retain) UIImage *photo;

@end

Mysof.m文件:

@implementation Mysof

@synthesize sofId;
@synthesize sofa;
@synthesize rating;
@synthesize photo;

@end

Sofalistsql.h文件:

@interface Sofalistsql : NSObject

{
    sqlite3 *db;
}

- (NSMutableArray *) getMysofas;

@end

.m文件:

 @implementation Sofalistsql

    - (NSMutableArray *) getMysofas{


     NSMutableArray *sofArray = [[NSMutableArray alloc] init];

    NSFileManager *fileMgr = [NSFileManager defaultManager];
    NSError *err;

    NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Empty" ofType:@"sqlite"];
    //NSLog(@"bundlePath %@", bundlePath);


    //call update function to check any data updated,
    //if there is a version difference
    //update the data base with all the required fileds.



    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    //NSLog(@"docs dir is %@", documentsDirectory);

    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:@"App6.sqlite"];

    [fileMgr copyItemAtPath:bundlePath toPath:appFile error:&err];


    NSURL *URL = [NSURL URLWithString:@"http://server.net/projects/mobile/jsonstring.php"];

    NSLog(@"URL is %@", URL);


     NSError *error;
     NSString *stringFromFileAtURL = [[NSString alloc]
     initWithContentsOfURL:URL
     encoding:NSUTF8StringEncoding
     error:&error];

     //NSLog(@"response is %@", stringFromFileAtURL);

     NSString *path = [documentsDirectory stringByAppendingPathComponent:@"App6.sqlite"];


     NSArray *userData = [stringFromFileAtURL JSONValue];

     // NSArray *skarray = [[NSArray alloc]init];



    NSLog(@"userdata is %@", userData);

   // int  i = 0;
    BOOL notExist = TRUE;


     for (NSArray *skarray in userData) {

     for (NSDictionary *tuser in skarray) {


           //if already exists in data base id then overwrite the name 

         if (sqlite3_open([path UTF8String], &db) == SQLITE_OK) {


      const char *sql = [[NSString stringWithFormat:@"SELECT id FROM categories where id = '%@'",[tuser objectForKey:@"id"]] cStringUsingEncoding:NSUTF8StringEncoding];     

     //NSLog(@"check stmt is %s", sql);

     sqlite3_stmt *sqlStatement,*addStmt;

     if (sqlite3_prepare_v2(db, sql, -1, &sqlStatement, NULL) == SQLITE_OK) {

       notExist = TRUE;

     while (sqlite3_step(sqlStatement) == SQLITE_ROW) {

        notExist = FALSE;


     Mysof *Mylist = [[Mysof alloc]init];
     Mylist.sofaId = sqlite3_column_int(sqlStatement, 0);
     Mylist.sofa = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
     Mylist.rating = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 2)];
     const char *raw = sqlite3_column_blob(sqlStatement, 3);
     int rawLen = sqlite3_column_bytes(sqlStatement, 3);
     NSData *data = [NSData dataWithBytes:raw length:rawLen];
     Mylist.photo = [[UIImage alloc] initWithData:data];
     [sofArray addObject:Mylist];



     }

         if(notExist){
             //NSLog(@"cat id does not exist");

             const char *sqlInsert = [[NSString stringWithFormat:@"insert into categories (id, cat_name,order_by) values ('%@', '%@', '%@')", [tuser objectForKey:@"id"], [tuser objectForKey:@"cat_name"],[tuser objectForKey:@"order_by"]] cStringUsingEncoding:NSUTF8StringEncoding];
             //NSLog(@"stmt is %s", sqlInsert);

             if(sqlite3_prepare_v2(db, sqlInsert, -1, &addStmt, NULL) != SQLITE_OK)
                 NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(db));

             if(SQLITE_DONE != sqlite3_step(addStmt))
                 NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(db));

         }


     }

     }

     }

     }

    return sofArray;


}

   @end

在viewController.m文件中:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.


    Sofalistsql * mysofs =[[Sofalistsql alloc] init];
    self.sofas = [mysofs getMysofas];



}

按钮单击以显示来自服务器的图像:

-(void)click:(id)sender{


 scrollview=[[UIScrollView alloc]initWithFrame:CGRectMake(0,500,320,200)];

        scrollview.showsVerticalScrollIndicator=NO;
          scrollview.showsHorizontalScrollIndicator=NO;

      scrollview.scrollEnabled=YES;

        int Width = 0;      

     //   Width = Width + 20+(i*74);


  for (int i = 0; i<[self.sofas count]; i++ ) {
            NSLog(@"index %d",i);



          //  imgView1=[[UIButton alloc]initWithFrame:CGRectMake(20+(i*74), 500, 72, 72)];

            imgView1=[[UIButton alloc]initWithFrame:CGRectMake(20+(i*74), 0, 72, 72)];

            Width = Width + 20+(i*74);

            [imgView1 setTag:i+1];

            [imgView1 addTarget:self action:@selector(dbsofaClicked:) forControlEvents:UIControlEventTouchUpInside];

            [imgView1 setImage:((Mysof *)[self.sofas objectAtIndex:i]).photo forState:UIControlStateNormal];

            [scrollview addSubview:imgView1];

          //  [myScroll addSubview:imgView1];



        }

        [scrollview setContentSize:CGSizeMake(Width,imgView1.frame.size.height+20)];

        [self.view addSubview:scrollview];



}

jsonstring.php文件:

<?php 
    require_once('database_connection.php');
    $i = 0;
    $j = 0;
    $k = 0;
    $l = 0;
    mysql_query('SET CHARACTER SET utf8') or die("MYSQL character set error: ".mysql_error());
    $result = array();
        $sql=mysql_query("SELECT * FROM categories ORDER BY id ASC") or die(mysql_error());
        if(mysql_num_rows($sql) > 0) {
            while($res=mysql_fetch_array($sql, MYSQL_ASSOC)){
                $result[0][$i] = $res;

                $art_sql=mysql_query("SELECT * FROM product WHERE cat_id=" .$res['id']. " ORDER BY id ASC") or die(mysql_error());
                if (mysql_num_rows($art_sql) > 0){
                    while($art_res=mysql_fetch_array($art_sql, MYSQL_ASSOC)){
                        //$art_res['art_details'] = (utf8_encode(htmlentities($art_res['art_details'])));
                        //$art_res['art_details'] = htmlentities($art_res['art_details']);
                        //echo $art_res['art_details'];
                        $result[1][$k] = $art_res;
                        //print_r($art_res);    
                        $k = $k+1;  
                    }   
                }
                $i= $i+1;
            }
            $version_sql = mysql_query("SELECT * FROM version_app order by product_id desc limit 1") or die(mysql_error());
            $row = mysql_fetch_array($version_sql);
            $last_version = $row['product_id'];
            $result['2'][$l] = array('product_id' => $last_version);
            $l = $l+1;
        }


        /*echo "<pre>";
            print_r($result);
        echo "</pre>";exit;*/

    $str_enc = json_encode($result);
    //print_r($str_enc); exit;
    $str=str_replace('\r','',$str_enc);
    $str=str_replace('\t','',$str);
    $str=str_replace('\n','',$str);
    $str = stripslashes($str);
    //$str_renc = json_encode(json_decode($str));

    echo $str;

mysql_close();
?>

的NSLog:

userdata is (
        (
                {
            "cat_name" = Table1;
            id = 1;
            "order_by" = 1;
        },
                {
            "cat_name" = Table2;
            id = 2;
            "order_by" = 2;
        },
                {
            "cat_name" = test;
            id = 3;
            "order_by" = 3;
        }
    ),
        (
                {
            "cat_id" = 1;
            id = 2;
            "order_by" = 1;
            "product_image" = "img.png";
        },
                {
            "cat_id" = 1;
            id = 3;
            "order_by" = 2;
            "product_image" = "img1.png";
        },
                {
            "cat_id" = 1;
            id = 4;
            "order_by" = 3;
            "product_image" = "img2.png";
        },
                {
            "cat_id" = 1;
            id = 5;
            "order_by" = 4;
            "product_image" = "img3.png";
        },
                {
            "cat_id" = 1;
            id = 6;
            "order_by" = 5;
            "product_image" = "img4.png";
        },
                {
            "cat_id" = 1;
            id = 7;
            "order_by" = 6;
            "product_image" = "img5.png";
        },

    )
)


array (
)
2013-08-16 13:19:53.044 App[3395:c07] scroll is <UIScrollView: 0x9de7cb0; frame = (0 300; 320 200); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x9de60e0>; layer = <CALayer: 0x9de4bc0>; contentOffset: {0, 0}>

我在本地数据库中存储了相同的表名。并使用覆盖数据库。在本地数据库中,我以BLOB类型存储图像。但在我的阵列中,我什么也没有显示。应用程序正在运行但图像不是从数据库中显示的。

1 个答案:

答案 0 :(得分:0)

现在你已经包含了你的JSON示例,我可以看到另一个问题:你的JSON是一个由三个数组组成的数组,一个类别数组,一个产品数组和一个版本数组。这是一个有问题的结构(通常一个阵列将是相同类型的同类物品)。我不是一个数组数组,而是将它作为数组字典。

您的JSON中这种令人困惑的结构会在您的Objective-C代码中体现出来。你试图遍历userdata数组,但你不能,因为这三个项目中的每一个都是不同的。

因此,我建议两个可能的修复方法。首先,如果你坚持你的数组数组(我不是很疯狂),你不能用for循环遍历那个数组,但是你可以像这样提取它包含的三个数组:

NSArray *categories = userdata[0];
NSArray *products = userdata[1];
NSArray *versions = userdata[2];

现在你可以遍历这三个数组中的每一个。

就个人而言,我会更进一步,并改变生成JSON的PHP以生成顶级字典,例如:

<?php 
    require_once('database_connection.php');
    $i = 0;
    $j = 0;
    $k = 0;
    $l = 0;
    mysql_query('SET CHARACTER SET utf8') or die("MYSQL character set error: ".mysql_error());
    $result = array();
        $sql=mysql_query("SELECT * FROM categories ORDER BY id ASC") or die(mysql_error());
        if(mysql_num_rows($sql) > 0) {
            while($res=mysql_fetch_array($sql, MYSQL_ASSOC)){
                $result['categories'][$i] = $res;

                $art_sql=mysql_query("SELECT * FROM product WHERE cat_id=" .$res['id']. " ORDER BY id ASC") or die(mysql_error());
                if (mysql_num_rows($art_sql) > 0){
                    while($art_res=mysql_fetch_array($art_sql, MYSQL_ASSOC)){
                        $result['products'][$k] = $art_res;
                        $k = $k+1;  
                    }   
                }
                $i= $i+1;
            }
            $version_sql = mysql_query("SELECT * FROM version_app order by product_id desc limit 1") or die(mysql_error());
            $row = mysql_fetch_array($version_sql);
            $last_version = $row['product_id'];
            $result['versions'][$l] = array('product_id' => $last_version);
            $l = $l+1;
        }

    $str_enc = json_encode($result);

    // note, these str_replace lines are not needed

    // $str=str_replace('\r','',$str_enc);
    // $str=str_replace('\t','',$str);
    // $str=str_replace('\n','',$str);

    // this stripslashes is a really bad idea, though

    // $str = stripslashes($str);

    // you echoed `$str`, but I'll obviously echo @str_enc    
    echo $str_enc;

    mysql_close();
?>

如果你这样做,你可以用

检索你的三个数组
NSArray *categories = userdata[@"categories"];
NSArray *products = userdata[@"products"];
NSArray *versions = userdata[@"versions"];

这不是一个关键任务变化,但它是三个异构项目的更合理的表示。但是这个想法是一样的:从你的JSON中提取你的三个数组,现在你可以分别遍历它们。


我发现了一些与SQLite相关的问题

  1. 一个问题是您有一行SQL:

    SELECT id FROM categories where cat_id = '%@'
    

    但是你继续尝试读取四列数据(即使你只返回了一列)。即使您将SQL更改为实际返回四列数据,您也应该检查sqlite3_column_blobsqlite3_column_bytes调用,以确保填充NSData

    顺便说一下,在构建SQL语句时不使用stringWithFormat通常更安全,而是使用?占位符而不是printf-formatters,然后使用sqlite3_bind_xxx函数。

  2. getMysofas重复打开数据库,但从未关闭它。每{{}}}次呼叫都有一个sqlite3_close。同样,对于每个sqlite3_open行,您应该有一个sqlite3_finalize语句。


  3. 除此之外,您必须使用exception breakpoint,在调试器中单步执行此代码,或在其中放置一堆sqlite3_prepare_v2语句来确定崩溃的来源。参见Ray Wenderlich的系列My App Crashed, Now What?。但是您确实需要确定导致问题的代码行。