iOS/iPhone Search Bar (UISearchBar) Data from Web Server Using JSON |
iOS/iPhone Search Bar (UISearchBar) Data from Web Server Using JSON การ Search ข้อมูลจะมีความจำเป็นในกรณีที่ข้อมูลเยอะ ๆ และเราอาจจะคุ้นเคยกับการ Search ค้นหา ข้อมูลเช่นรายชื่อ Contact List ใน iPhone App โดยในระบบการ Search จะมีช่องสำหรับการ Search ข้อมูล และ Result ที่ได้จากการ Search จะแสดงผลบน Table View หรือเราอาจจะประยุกต์ใช้กับข้อมูลที่อยู่ในรูปแบบอื่น ๆ ก็ได้เช่นเดียวกัน เช่นการค้นหาข้อมูลในรูปแบบของ JSON ที่ได้จาก Web Server ผ่าน PHP และ MySQL เป็นต้น
iOS/iPhone Search Bar (UISearchBar) Data from Web Server Using JSON
ตัวอย่าง SearchBar ของ Contact List บน App ของ iPhone
สำหรับตัวอย่างนี้จะเป็นการอ่านข้อมูลจาก Web Server ทีทำงานด้วย PHP กับ MySQL โดยใช้ JSON เป็นช่องทางสำหรับการแลกเปลี่ยนข้อมูล และ iOS จะทำข้อมูลเหล่านั้นมาเก็บไว้ใน Array เพื่อที่จะ Filter ตามรูปแบบการค้นหา
พื้นฐานเกี่ยวกับ SearchBar (UISearchBar) แนะนำให้อ่าน 2 บทความนี้
iOS/iPhone Search Bar (UISearchBar) and Table View (UITableView)
iOS/iPhone Search and Bar Display Controller (UISearchDisplayController)
Web Server โครงสร้างของ PHP และ MySQL Database บน Web Server
CREATE TABLE `province` (
`ProvinceID` int(2) NOT NULL auto_increment,
`ProvinceName` varchar(100) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`ProvinceID`)
) ENGINE=MyISAM AUTO_INCREMENT=78 ;
--
-- Dumping data for table `province`
--
INSERT INTO `province` VALUES (1, 'Bangkok');
INSERT INTO `province` VALUES (2, 'Samut Prakan');
INSERT INTO `province` VALUES (3, 'Nonthaburi');
INSERT INTO `province` VALUES (4, 'Pathum Thani');
INSERT INTO `province` VALUES (5, 'Phra Nakhon Si Ayutthaya');
INSERT INTO `province` VALUES (6, 'Ang Thong');
INSERT INTO `province` VALUES (7, 'Loburi');
INSERT INTO `province` VALUES (8, 'Sing Buri');
INSERT INTO `province` VALUES (9, 'Chai Nat');
INSERT INTO `province` VALUES (10, 'Saraburi');
INSERT INTO `province` VALUES (11, 'Chon Buri');
INSERT INTO `province` VALUES (12, 'Rayong');
INSERT INTO `province` VALUES (13, 'Chanthaburi');
INSERT INTO `province` VALUES (14, 'Trat');
INSERT INTO `province` VALUES (15, 'Chachoengsao');
INSERT INTO `province` VALUES (16, 'Prachin Buri');
INSERT INTO `province` VALUES (17, 'Nakhon Nayok');
INSERT INTO `province` VALUES (18, 'Sa Kaeo');
INSERT INTO `province` VALUES (19, 'Nakhon Ratchasima');
INSERT INTO `province` VALUES (20, 'Buri Ram');
INSERT INTO `province` VALUES (21, 'Surin');
INSERT INTO `province` VALUES (22, 'Si Sa Ket');
INSERT INTO `province` VALUES (23, 'Ubon Ratchathani');
INSERT INTO `province` VALUES (24, 'Yasothon');
INSERT INTO `province` VALUES (25, 'Chaiyaphum');
INSERT INTO `province` VALUES (26, 'Amnat Charoen');
INSERT INTO `province` VALUES (27, 'Nong Bua Lam Phu');
INSERT INTO `province` VALUES (28, 'Khon Kaen');
INSERT INTO `province` VALUES (29, 'Udon Thani');
INSERT INTO `province` VALUES (30, 'Loei');
INSERT INTO `province` VALUES (31, 'Nong Khai');
INSERT INTO `province` VALUES (32, 'Maha Sarakham');
INSERT INTO `province` VALUES (33, 'Roi Et');
INSERT INTO `province` VALUES (34, 'Kalasin');
INSERT INTO `province` VALUES (35, 'Sakon Nakhon');
INSERT INTO `province` VALUES (36, 'Nakhon Phanom');
INSERT INTO `province` VALUES (37, 'Mukdahan');
INSERT INTO `province` VALUES (38, 'Chiang Mai');
INSERT INTO `province` VALUES (39, 'Lamphun');
INSERT INTO `province` VALUES (40, 'Lampang');
INSERT INTO `province` VALUES (41, 'Uttaradit');
INSERT INTO `province` VALUES (42, 'Phrae');
INSERT INTO `province` VALUES (43, 'Nan');
INSERT INTO `province` VALUES (44, 'Phayao');
INSERT INTO `province` VALUES (45, 'Chiang Rai');
INSERT INTO `province` VALUES (46, 'Mae Hong Son');
INSERT INTO `province` VALUES (47, 'Nakhon Sawan');
INSERT INTO `province` VALUES (48, 'Uthai Thani');
INSERT INTO `province` VALUES (49, 'Kamphaeng Phet');
INSERT INTO `province` VALUES (50, 'Tak');
INSERT INTO `province` VALUES (51, 'Sukhothai');
INSERT INTO `province` VALUES (52, 'Phitsanulok');
INSERT INTO `province` VALUES (53, 'Phichit');
INSERT INTO `province` VALUES (54, 'Phetchabun');
INSERT INTO `province` VALUES (55, 'Ratchaburi');
INSERT INTO `province` VALUES (56, 'Kanchanaburi');
INSERT INTO `province` VALUES (57, 'Suphan Buri');
INSERT INTO `province` VALUES (58, 'Nakhon Pathom');
INSERT INTO `province` VALUES (59, 'Samut Sakhon');
INSERT INTO `province` VALUES (60, 'Samut Songkhram');
INSERT INTO `province` VALUES (61, 'Phetchaburi');
INSERT INTO `province` VALUES (62, 'Prachuap Khiri Khan');
INSERT INTO `province` VALUES (63, 'Nakhon Si Thammarat');
INSERT INTO `province` VALUES (64, 'Krabi');
INSERT INTO `province` VALUES (65, 'Phangnga');
INSERT INTO `province` VALUES (66, 'Phuket');
INSERT INTO `province` VALUES (67, 'Surat Thani');
INSERT INTO `province` VALUES (68, 'Ranong');
INSERT INTO `province` VALUES (69, 'Chumphon');
INSERT INTO `province` VALUES (70, 'Songkhla');
INSERT INTO `province` VALUES (71, 'Satun');
INSERT INTO `province` VALUES (72, 'Trang');
INSERT INTO `province` VALUES (73, 'Phatthalung');
INSERT INTO `province` VALUES (74, 'Pattani');
INSERT INTO `province` VALUES (75, 'Yala');
INSERT INTO `province` VALUES (76, 'Narathiwat');
INSERT INTO `province` VALUES (77, 'Bungkan');
โครงสร้างของ MySQL Database ซึ่งในตัวอย่างนี้สมมุติรายชื่อจังหวัด
getProvince.php ไฟล์ PHP สำหรับอ่านข้อมูลของ MySQL Database จะส่งออกเป็น JSON
<?php
$objConnect = mysql_connect("localhost","root","root");
$objDB = mysql_select_db("mydatabase");
$strSQL = "SELECT * FROM province WHERE 1 ORDER BY ProvinceName ";
$objQuery = mysql_query($strSQL);
$intNumField = mysql_num_fields($objQuery);
$resultArray = array();
while($obResult = mysql_fetch_array($objQuery))
{
$arrCol = array();
for($i=0;$i<$intNumField;$i++)
{
$arrCol[mysql_field_name($objQuery,$i)] = $obResult[$i];
}
array_push($resultArray,$arrCol);
}
mysql_close($objConnect);
echo json_encode($resultArray);
?>
คำสั่งของ PHP กับ MySQL Database
เมื่อทดสอบเรียกไฟล์ php จะได้ผลลัพธ์ JSON ดังรูป
และจากโครงสร้างของ PHP กับ MySQL เมื่อเราได้ JSON ไฟล์เราจะสามารถแปลง Code ทั้งหมดให้อยู่ในรูปแบบของ Array บน Objective-C ดังนี้
NSMutableArray *allObject;
NSMutableArray *displayObject;
// A dictionary object
NSDictionary *dict;
// Define keys
NSString *provinceid;
NSString *provincename;
// Define keys
provinceid = @"ProvinceID";
provincename = @"ProvinceName";
// Create array to hold dictionaries
allObject = [[NSMutableArray alloc] init];
NSData *jsonData = [NSData dataWithContentsOfURL:
[NSURL URLWithString:@"https://www.thaicreate.com/url/getProvince.php"]];
id jsonObjects = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
// values in foreach loop
for (NSDictionary *dataDict in jsonObjects) {
NSString *strProvinceID = [dataDict objectForKey:@"ProvinceID"];
NSString *strProvinceName = [dataDict objectForKey:@"ProvinceName"];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
strProvinceID, provinceid,
strProvinceName, provincename,
nil];
[allObject addObject:dict];
}
displayObject =[[NSMutableArray alloc] initWithArray:allObject];
การอ่าน JSON และ การแปลงข้อมูล JSON ให้อยู่ในรูปแบบของ Array บน NSMutableArray ด้วยภาษา Objective-C
Example การทำ SearchBar (UISearchBar) ข้อมูลจาก JSON ที่ได้มาจาก URL Web Server (PHP กับ MySQL)
เริ่มต้นด้วยการสร้าง Application แบบ Single View Application แบบง่าย ๆ บน Xcode
เลือกและไม่เลือกดังรูป
ตอนนี้หน้าจอ View ของเราจะยังว่าง ๆ
ให้ลาก Object ที่มีชื่อว่า Search Bar and Search Display Controller มาวางไว้บนหน้าจอ View
จากนั้นตามด้วย Table View
ใน Class ของ .h ให้ทำการ delegate คลาส <UITableViewDataSource,UITableViewDelegate,UISearchBarDelegate>
และให้เชื่อม IBOutlet ให้เรียบร้อย
คลิกวาที่ Table View ให้ทำการเชื่อม delegate และ dataSource กับ File's Owner
และ Search Bar ก็เช่นเดียวกัน ให้คลิกขวาและเชื่อม delegate กับ File's Owner และที่เหลือจะเป็น Code ของ Objective-C ดังนี้
ViewController.h
//
// ViewController.h
// searchBarPHPMySQLJSON
//
// Created by Weerachai on 12/4/55 BE.
// Copyright (c) 2555 Weerachai. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate,UISearchBarDelegate>
@property (retain, nonatomic) IBOutlet UITableView *tableViewObj;
@end
ViewController.m
//
// ViewController.m
// searchBarPHPMySQLJSON
//
// Created by Weerachai on 12/4/55 BE.
// Copyright (c) 2555 Weerachai. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
{
NSMutableArray *allObject;
NSMutableArray *displayObject;
// A dictionary object
NSDictionary *dict;
// Define keys
NSString *provinceid;
NSString *provincename;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Define keys
provinceid = @"ProvinceID";
provincename = @"ProvinceName";
// Create array to hold dictionaries
allObject = [[NSMutableArray alloc] init];
NSData *jsonData = [NSData dataWithContentsOfURL:
[NSURL URLWithString:@"https://www.thaicreate.com/url/getProvince.php"]];
id jsonObjects = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
// values in foreach loop
for (NSDictionary *dataDict in jsonObjects) {
NSString *strProvinceID = [dataDict objectForKey:@"ProvinceID"];
NSString *strProvinceName = [dataDict objectForKey:@"ProvinceName"];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
strProvinceID, provinceid,
strProvinceName, provincename,
nil];
[allObject addObject:dict];
}
displayObject =[[NSMutableArray alloc] initWithArray:allObject];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return displayObject.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// Use the default cell style.
cell = [[[UITableViewCell alloc] initWithStyle : UITableViewCellStyleSubtitle
reuseIdentifier : CellIdentifier] autorelease];
}
NSDictionary *tmpDict = [displayObject objectAtIndex:indexPath.row];
NSString *cellValue = [tmpDict objectForKey:provincename];
cell.textLabel.text = cellValue;
return cell;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
if([searchString length] == 0)
{
[displayObject removeAllObjects];
[displayObject addObjectsFromArray:allObject];
}
else
{
[displayObject removeAllObjects];
for(NSDictionary *tmpDict in allObject)
{
NSString *val = [tmpDict objectForKey:provincename];
NSRange r = [val rangeOfString:searchString options:NSCaseInsensitiveSearch];
if(r.location != NSNotFound)
{
[displayObject addObject:tmpDict];
}
}
}
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
searchBar.text=@"";
[searchBar setShowsCancelButton:NO animated:YES];
[searchBar resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[_tableViewObj release];
[super dealloc];
}
@end
สำหรับ Code นั้นไม่มีอะไรมากมาย สามารถอ่านแล้วเข้าใจได้ หรือไม่ลองกลับไปอ่านพื้นฐานของ Search Bar ตามข้อความที่ได้แนะนำหว้ก่อนหน้านี้
Screenshot
แสดงข้อมูลทั้งหมดบน Table View (UITableView)
เมื่อคลิกที่ช่อง Search
ตัวอย่างการ Search
ตัวอย่างการ Search
เพื่มเติม
ตัวอย่างและวิธีนี้เหมาะสำหรับข้อมูลที่ไม่ค่อยจะมีปริมาณมาก เพราะจะใช้การอ่านข้อมูลจาก Web Server มาเก็บไว้ใน Array ทั้งหมด แล้วค่อยทำการ Filter เพื่อแสดงผลบน Table View ซึ่งเมื่อข้อมูลจาก Web Server มีเป็นหมื่น หรือ แสน Record จะมีปัญหาเรื่องการทำงาน เช่นใช้ Memory สูง หรือทำงานช้า ซึ่งวิธีที่ดีกว่า คือการส่ง keyboard ไป Search ค้นหาบน Web Server แล้วค่อยนำข้อมูลเฉพาะที่ต้องการที่ได้มาแสดงผลอีกที ซึ่งจะมีประสิทธิภาพมากกว่า สำหรับวิธีนี้จะได้ทำตัวอย่างไว้ในหัวข้อถัดไป
|