我在服务器中存储了一些图像。我使用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
类型存储图像。但在我的阵列中,我什么也没有显示。应用程序正在运行但图像不是从数据库中显示的。
答案 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相关的问题
一个问题是您有一行SQL:
SELECT id FROM categories where cat_id = '%@'
但是你继续尝试读取四列数据(即使你只返回了一列)。即使您将SQL更改为实际返回四列数据,您也应该检查sqlite3_column_blob
和sqlite3_column_bytes
调用,以确保填充NSData
。
顺便说一下,在构建SQL语句时不使用stringWithFormat
通常更安全,而是使用?
占位符而不是printf-formatters,然后使用sqlite3_bind_xxx
函数。
您getMysofas
重复打开数据库,但从未关闭它。每{{}}}次呼叫都有一个sqlite3_close
。同样,对于每个sqlite3_open
行,您应该有一个sqlite3_finalize
语句。
除此之外,您必须使用exception breakpoint,在调试器中单步执行此代码,或在其中放置一堆sqlite3_prepare_v2
语句来确定崩溃的来源。参见Ray Wenderlich的系列My App Crashed, Now What?。但是您确实需要确定导致问题的代码行。