简体   繁体   English

从PHP / MySQL / JSON到iOS / Objective-C / SQLite

[英]From PHP/MySQL/JSON to iOS/Objective-C/SQLite

I'm trying to create an iOS application which upon loading, will initially connect via HTTP back to a PHP web service which will output data as JSON from a MySQL database. 我正在尝试创建一个iOS应用程序,在加载时,最初将通过HTTP连接回PHP Web服务,该服务将从MySQL数据库输出数据作为JSON。 I would then like it to import this data into a local SQLite database within the iOS app. 然后,我希望它将此数据导入iOS应用程序中的本地SQLite数据库。 I've already downloaded the JSON-Framework for Objective-C. 我已经下载了Objective-C的JSON-Framework。

My question is two fold. 我的问题是双重的。

1) What is the best way to output the JSON from PHP so that I can send multiple database tables in the same JSON file? 1)从PHP输出JSON的最佳方法是什么,以便我可以在同一个JSON文件中发送多个数据库表? I have 4 tables of data that I'm trying to send (user, building, room, device). 我有4个数据表,我正在尝试发送(用户,建筑物,房间,设备)。 Here is how I am currently outputting the JSON data: 以下是我当前输出JSON数据的方式:

    // Users
    $query = "SELECT * from user";
    $result = mysql_query($query,$conn) or die('Errant query:  '.$query);

    $users = array();
    if(mysql_num_rows($result)) {
      while($user = mysql_fetch_assoc($result)) {
      $users[] = array('user'=>$user);
      }
    }

    // Buildings
    $query = "SELECT * from building";
    $result = mysql_query($query,$conn) or die('Errant query:  '.$query);

    $buildings = array();
    if(mysql_num_rows($result)) {
      while($building = mysql_fetch_assoc($result)) {
       $buildings[] = array('building'=>$building);
     }
    }

    // Rooms
    $query = "SELECT * from room";
    $result = mysql_query($query,$conn) or die('Errant query:  '.$query);

    $rooms = array();
    if(mysql_num_rows($result)) {
     while($room = mysql_fetch_assoc($result)) {
      $rooms[] = array('room'=>$room);
     }
    }

    // Devices
    $query = "SELECT * from device";
    $result = mysql_query($query,$conn) or die('Errant query:  '.$query);

    $devices = array();
    if(mysql_num_rows($result)) {
     while($device = mysql_fetch_assoc($result)) {
      $devices[] = array('device'=>$device);
     }
    }

    header('Content-type: application/json');
    echo json_encode(array('users'=>$users));
    echo json_encode(array('buildings'=>$buildings));
    echo json_encode(array('rooms'=>$rooms));
    echo json_encode(array('devices'=>$devices)); 

I fear that this method isn't the right way to send multiple objects. 我担心这种方法不是发送多个对象的正确方法。

2) In the iOS app, how can I automatically take this JSON data and insert it into the corresponding local database tables in SQLite? 2)在iOS应用程序中,如何自动获取此JSON数据并将其插入SQLite中相应的本地数据库表?

Thanks for any help. 谢谢你的帮助。

On 1. Instead of JSOn you could use binary Property lists they are natively implemented on the iPhone and there is a library to turn PHP into binary Plist https://github.com/rodneyrehm/CFPropertyList 在1.而不是JSOn你可以使用二进制属性列表,它们在iPhone上原生实现,并且有一个库将PHP转换为二进制Plist https://github.com/rodneyrehm/CFPropertyList

There are many benefits to using binary property lists, they are probably 1/5 of the size of JSON, you don't need a external library to parse them, therefore all code is much simpler, etc. 使用二进制属性列表有很多好处,它们可能是JSON大小的1/5,您不需要外部库来解析它们,因此所有代码都更简单,等等。

On 2. There is no easy way to take the JSON/Plist structure and insert it to a SQL database, because JSON/Plist allow much more flexibility then SQL tables. On 2.没有简单的方法来获取JSON / Plist结构并将其插入SQL数据库,因为JSON / Plist比SQL表具有更大的灵活性。 So you would have to first create the right tables in your SQLite DB and then use normal INSERT to insert the data one by one into the database exactly like you would do with PHP. 因此,您必须首先在SQLite DB中创建正确的表,然后使用普通的INSERT将数据逐个插入到数据库中,就像使用PHP一样。

Yeah Luke's recommendation is good but you will be fine with the way you are exporting your tables. 是的卢克的建议是好的,但你对出口表的方式会很好。 You may just have to dig "deeper" into the structure to get what you want - ie your output with return a "dictionary of dictionaries of arrays" which will then contain the data for each table. 你可能只需要深入挖掘结构以获得你想要的东西 - 即你的输出返回一个“数组字典词典”,然后它将包含每个表的数据。

As for downloading them first: 至于先下载它们:

1) NSURLConnection and its delegate methods - you can send asynchronous request to your webserver to get this file and get notified when the data has been downloaded so the user interface is never blocked in your app. 1)NSURLConnection及其委托方法 - 您可以向您的网络服务器发送异步请求以获取此文件,并在下载数据时收到通知,因此用户界面永远不会在您的应用中被阻止。

Here's the documentation with some good examples from Apple: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html 以下是来自Apple的一些优秀示例的文档: http//developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html

At the end of the download, you will have an NSData object which can then be converted back to a string using NSString *jsonContents = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding . 在下载结束时,您将拥有一个NSData对象,然后可以使用NSString *jsonContents = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding将其转换回字符串。

You can then use a JSON parser library - I recommend SBJSON https://github.com/stig/json-framework - which will parse the data and return it as a dictionary or array depending on your structure. 然后,您可以使用JSON解析器库 - 我建议使用SBJSON https://github.com/stig/json-framework - 它将解析数据并将其作为字典或数组返回,具体取决于您的结构。

From there you can access your tables and value with valueForKey in dictionaries or objectAtIndex: in arrays and then map it into your chosen local storage, for which I recommend Coredata (or you could use sqlite if you are familiar with it too). 从那里你可以使用字典中的valueForKey或者数组中的objectAtIndex:来访问你的表和值,然后将它映射到你选择的本地存储中,我推荐使用Coredata(或者如果你熟悉它也可以使用sqlite)。

Hope it helps. 希望能帮助到你。 Rog ROG

I can't speak to 2), but for 1), I would recommend combining your JSON into a single array. 我不能说2),但对于1),我建议将你的JSON组合成一个数组。 One of the nice things about JSON (and arrays) is the ability to nest elements as deeply as you like. JSON(和数组)的一个好处是可以根据需要嵌套元素。

echo json_encode(array(
    'users'=>$users,
    'buildings'=>$buildings,
    'rooms'=>$rooms,
    'devices'=>$devices,
)); 

What about preparing the SQLite database on the webserver and downloading that to the iOS application? 如何在Web服务器上准备SQLite数据库并将其下载到iOS应用程序? This way, you do the heavy lifting on the PHP side. 这样,你就可以在PHP端完成繁重的任务。 If the data is relatively static, you can even setup a scheduled task to generate the SQLite database on a regular interval. 如果数据是相对静态的,您甚至可以设置计划任务以定期生成SQLite数据库。

We've done this for one of our apps and it worked very well. 我们已经为我们的一个应用程序完成了这项工作,并且它运行良好。

One thing to keep in mind then is that you should enable gzip compression on the webserver to minimize the data transfer. 要记住的一件事是,您应该在Web服务器上启用gzip压缩以最小化数据传输。 Remember that you have to do some extra stuff to use gzip compression with NSURLConnection: 请记住,你必须做一些额外的东西来使用NSURLConnection进行gzip压缩:

http://www.bigevilempire.com/codelog/entry/nsurlconnection-with-gzip/ http://www.bigevilempire.com/codelog/entry/nsurlconnection-with-gzip/

您可以使用REST服务器和RESTKit。

If you would like a more full-featured solution that what is offered by a standalone parsing library, you may want to take a look at RestKit: http://restkit.org/ 如果您想要一个功能更全面的独立解析库提供的解决方案,您可能需要查看RestKit: http: //restkit.org/

The framework wraps the operations of fetching, parsing, and mapping JSON payloads into objects. 该框架包含了获取,解析和将JSON有效负载映射到对象的操作。 It can handle deeply nested structures and can map directly back to Core Data for persistence. 它可以处理深层嵌套结构,并可以直接映射回Core Data以实现持久性。

At a high level, here's what your fetch & post operations would feel like in RestKit: 在较高的层次上,这是您在RestKit中的fetch和post操作的感觉:

- (void)loadObjects {
  [[RKObjectManager sharedManager] loadObjectsAtResourcePath:[@"/path/to/stuff.json" delegate:self];
}

- (void)objectLoader:(RKObjectLoader*)loader didLoadObjects:(NSArray*)objects {
  NSLog(@"These are my JSON decoded, mapped objects: %@", objects);

  // Mutate and PUT the changes back to the server
  MyObject* anObject = [objects objectAtIndex:0];
  anObject.name = @"This is the new name!";
  [[RKObjectManager sharedManager] putObject:anObject delegate:self];
}

The framework takes care of the JSON parsing/encoding on a background thread and let's you declare how attributes in the JSON map to properties on your object. 该框架负责后台线程上的JSON解析/编码,让您声明JSON中的属性如何映射到对象的属性。 A number of people in the community are working with PHP backends + RestKit with great success. 社区中的许多人正在使用PHP后端+ RestKit取得巨大成功。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM