1

我在我的服务器中存储了一些图像。我使用 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();
?>

NS日志:

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类型存储图像。但是在我的数组中,我什么也没显示。应用程序正在运行。但是图像没有从数据库中显示。

4

1 回答 1

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同样,每一sqlite3_prepare_v2行都应该有一个语句。


除此之外,您必须通过使用异常断点、在调试器中单步执行此代码或在其中放置一堆NSLog语句来确定崩溃的根源。请参阅 Ray Wenderlich 的系列我的应用程序崩溃了,现在怎么办?. 但是您确实需要确定导致问题的代码行。

于 2013-08-16T07:31:28.003 回答