开源 Objective-C IOS 应用开发(十一)数据持久化--sqlite

  文章的目的为了记录使用Objective-C 进行IOS app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

 相关链接:

开源 Objective-C IOS 应用开发(一)macOS 的使用

开源 Objective-C IOS 应用开发(二)Xcode安装

开源 Objective-C IOS 应用开发(三)第一个iPhone的APP

开源 Objective-C IOS 应用开发(四)Xcode工程文件结构

开源 Objective-C IOS 应用开发(五)iOS操作(action)和输出口(Outlet)

开源 Objective-C IOS 应用开发(六)Objective-C 和 C语言

开源 Objective-C IOS 应用开发(七)Objective-C核心代码示例

开源 Objective-C IOS 应用开发(八)常见控件UI

开源 Objective-C IOS 应用开发(九)复杂控件-tableview

开源 Objective-C IOS 应用开发(十)数据持久化--文件

开源 Objective-C IOS 应用开发(十一)数据持久化--sqlite

开源 Objective-C IOS 应用开发(十二)通讯--ble

开源 Objective-C IOS 应用开发(十三)通讯--Http访问

开源 Objective-C IOS 应用开发(十四)传感器--陀螺仪和gps

开源 Objective-C IOS 应用开发(十五)通讯--蓝牙ble扫描

开源 Objective-C IOS 应用开发(十六)Storyboard模式下的纯代码界面

开源 Objective-C IOS 应用开发(十七)CAF音频的录制

开源 Objective-C IOS 应用开发(十八)音频的播放

开源 Objective-C IOS 应用开发(十九)视频的播放

开源 Objective-C IOS 应用开发(二十)多线程处理

开源 Objective-C IOS 应用开发(二十一)自定义控件--示波器

开源 Objective-C IOS 应用开发(二十二)自定义控件--车速仪表盘

 推荐链接:

开源 Arkts 鸿蒙应用 开发(一)工程文件分析-优快云博客

开源 Arkts 鸿蒙应用 开发(二)封装库.har制作和应用-优快云博客

开源 Arkts 鸿蒙应用 开发(三)Arkts的介绍-优快云博客

开源 Arkts 鸿蒙应用 开发(四)布局和常用控件-优快云博客

开源 Arkts 鸿蒙应用 开发(五)控件组成和复杂控件-优快云博客

开源 Arkts 鸿蒙应用 开发(六)数据持久--文件和首选项存储-优快云博客

开源 Arkts 鸿蒙应用 开发(七)数据持久--sqlite关系数据库-优快云博客

开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机-优快云博客

开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端-优快云博客

开源 Arkts 鸿蒙应用 开发(十)通讯--Http-优快云博客

开源 Arkts 鸿蒙应用 开发(十一)证书和包名修改-优快云博客

开源 Arkts 鸿蒙应用 开发(十二)传感器的使用-优快云博客

开源 Arkts 鸿蒙应用 开发(十三)音频--MP3播放_arkts avplayer播放音频 mp3-优快云博客

开源 Arkts 鸿蒙应用 开发(十四)线程--任务池(taskpool)-优快云博客

开源 Arkts 鸿蒙应用 开发(十五)自定义绘图控件--仪表盘-优快云博客

开源 Arkts 鸿蒙应用 开发(十六)自定义绘图控件--波形图-优快云博客

开源 Arkts 鸿蒙应用 开发(十七)通讯--http多文件下载-优快云博客

开源 Arkts 鸿蒙应用 开发(十八)通讯--Ble低功耗蓝牙服务器-优快云博客

推荐链接:

开源 java android app 开发(一)开发环境的搭建-优快云博客

开源 java android app 开发(二)工程文件结构-优快云博客

开源 java android app 开发(三)GUI界面布局和常用组件-优快云博客

开源 java android app 开发(四)GUI界面重要组件-优快云博客

开源 java android app 开发(五)文件和数据库存储-优快云博客

开源 java android app 开发(六)多媒体使用-优快云博客

开源 java android app 开发(七)通讯之Tcp和Http-优快云博客

开源 java android app 开发(八)通讯之Mqtt和Ble-优快云博客

开源 java android app 开发(九)后台之线程和服务-优快云博客

开源 java android app 开发(十)广播机制-优快云博客

开源 java android app 开发(十一)调试、发布-优快云博客

开源 java android app 开发(十二)封库.aar-优快云博客
 

本章内容主要是完整的 iOS 客户管理应用,使用 SQLite 数据库进行数据存储。

目录:

1.手机演示

2.所有源码

3.源码分析

一、手机演示

二、所有源码

需添加修改这4个文件

1. 数据库管理类 (DatabaseManager.h)

#import <Foundation/Foundation.h>
#import <sqlite3.h>

NS_ASSUME_NONNULL_BEGIN

@interface Customer : NSObject
@property (nonatomic, assign) NSInteger customerId;
@property (nonatomic, copy) NSString *customerName;
@property (nonatomic, copy) NSString *contactPerson;
@property (nonatomic, copy) NSString *address;
@property (nonatomic, copy) NSString *phone;
@end

@interface DatabaseManager : NSObject

+ (instancetype)sharedInstance;
- (BOOL)openDatabase;
- (BOOL)createTable;
- (BOOL)addCustomerWithName:(NSString *)name contactPerson:(NSString *)contact address:(NSString *)address phone:(NSString *)phone;
- (BOOL)updateCustomer:(Customer *)customer;
- (BOOL)deleteCustomerWithId:(NSInteger)customerId;
- (NSArray<Customer *> *)getAllCustomers;
- (NSArray<Customer *> *)searchCustomersWithKeyword:(NSString *)keyword;

@end

NS_ASSUME_NONNULL_END

2. 数据库管理类实现 (DatabaseManager.m)

#import "DatabaseManager.h"

@implementation Customer
@end

@interface DatabaseManager()
@property (nonatomic, assign) sqlite3 *database;
@property (nonatomic, copy) NSString *databasePath;
@end

@implementation DatabaseManager

+ (instancetype)sharedInstance {
    static DatabaseManager *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init {
    if (self = [super init]) {
        [self setupDatabasePath];
    }
    return self;
}

- (void)setupDatabasePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths firstObject];
    self.databasePath = [documentsDirectory stringByAppendingPathComponent:@"customers.db"];
}

- (BOOL)openDatabase {
    if (sqlite3_open([self.databasePath UTF8String], &_database) == SQLITE_OK) {
        return [self createTable];
    }
    return NO;
}

- (BOOL)createTable {
    NSString *createTableSQL = @"CREATE TABLE IF NOT EXISTS Customers ("
                               "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                               "customer_name TEXT NOT NULL, "
                               "contact_person TEXT, "
                               "address TEXT, "
                               "phone TEXT);";
    
    char *errorMessage;
    if (sqlite3_exec(self.database, [createTableSQL UTF8String], NULL, NULL, &errorMessage) == SQLITE_OK) {
        return YES;
    } else {
        NSLog(@"创建表失败: %s", errorMessage);
        sqlite3_free(errorMessage);
        return NO;
    }
}

- (BOOL)addCustomerWithName:(NSString *)name contactPerson:(NSString *)contact address:(NSString *)address phone:(NSString *)phone {
    NSString *insertSQL = @"INSERT INTO Customers (customer_name, contact_person, address, phone) VALUES (?, ?, ?, ?);";
    
    sqlite3_stmt *statement;
    if (sqlite3_prepare_v2(self.database, [insertSQL UTF8String], -1, &statement, NULL) == SQLITE_OK) {
        sqlite3_bind_text(statement, 1, [name UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 2, [contact UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 3, [address UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 4, [phone UTF8String], -1, SQLITE_TRANSIENT);
        
        if (sqlite3_step(statement) == SQLITE_DONE) {
            sqlite3_finalize(statement);
            return YES;
        }
    }
    sqlite3_finalize(statement);
    return NO;
}

- (BOOL)updateCustomer:(Customer *)customer {
    NSString *updateSQL = @"UPDATE Customers SET customer_name = ?, contact_person = ?, address = ?, phone = ? WHERE id = ?;";
    
    sqlite3_stmt *statement;
    if (sqlite3_prepare_v2(self.database, [updateSQL UTF8String], -1, &statement, NULL) == SQLITE_OK) {
        sqlite3_bind_text(statement, 1, [customer.customerName UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 2, [customer.contactPerson UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 3, [customer.address UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 4, [customer.phone UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_int(statement, 5, (int)customer.customerId);
        
        if (sqlite3_step(statement) == SQLITE_DONE) {
            sqlite3_finalize(statement);
            return YES;
        }
    }
    sqlite3_finalize(statement);
    return NO;
}

- (BOOL)deleteCustomerWithId:(NSInteger)customerId {
    NSString *deleteSQL = @"DELETE FROM Customers WHERE id = ?;";
    
    sqlite3_stmt *statement;
    if (sqlite3_prepare_v2(self.database, [deleteSQL UTF8String], -1, &statement, NULL) == SQLITE_OK) {
        sqlite3_bind_int(statement, 1, (int)customerId);
        
        if (sqlite3_step(statement) == SQLITE_DONE) {
            sqlite3_finalize(statement);
            return YES;
        }
    }
    sqlite3_finalize(statement);
    return NO;
}

- (NSArray<Customer *> *)getAllCustomers {
    NSMutableArray *customers = [NSMutableArray array];
    NSString *querySQL = @"SELECT * FROM Customers ORDER BY id;";
    
    sqlite3_stmt *statement;
    if (sqlite3_prepare_v2(self.database, [querySQL UTF8String], -1, &statement, NULL) == SQLITE_OK) {
        while (sqlite3_step(statement) == SQLITE_ROW) {
            Customer *customer = [[Customer alloc] init];
            customer.customerId = sqlite3_column_int(statement, 0);
            customer.customerName = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
            customer.contactPerson = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
            customer.address = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
            customer.phone = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
            
            [customers addObject:customer];
        }
    }
    sqlite3_finalize(statement);
    return [customers copy];
}

- (NSArray<Customer *> *)searchCustomersWithKeyword:(NSString *)keyword {
    NSMutableArray *customers = [NSMutableArray array];
    NSString *querySQL = @"SELECT * FROM Customers WHERE customer_name LIKE ? OR contact_person LIKE ? OR address LIKE ? OR phone LIKE ? ORDER BY id;";
    
    sqlite3_stmt *statement;
    if (sqlite3_prepare_v2(self.database, [querySQL UTF8String], -1, &statement, NULL) == SQLITE_OK) {
        NSString *searchPattern = [NSString stringWithFormat:@"%%%@%%", keyword];
        
        sqlite3_bind_text(statement, 1, [searchPattern UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 2, [searchPattern UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 3, [searchPattern UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(statement, 4, [searchPattern UTF8String], -1, SQLITE_TRANSIENT);
        
        while (sqlite3_step(statement) == SQLITE_ROW) {
            Customer *customer = [[Customer alloc] init];
            customer.customerId = sqlite3_column_int(statement, 0);
            customer.customerName = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
            customer.contactPerson = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
            customer.address = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
            customer.phone = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
            
            [customers addObject:customer];
        }
    }
    sqlite3_finalize(statement);
    return [customers copy];
}

- (void)dealloc {
    if (self.database) {
        sqlite3_close(self.database);
    }
}

@end

3. 主视图控制器 (ViewController.h)

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate>

@end

4. 主视图控制器实现 (ViewController.m)

#import "ViewController.h"
#import "DatabaseManager.h"

@interface ViewController ()
{
    NSArray<Customer *> *_customers;
    Customer *_selectedCustomer;
}

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) UITextField *nameTextField;
@property (nonatomic, strong) UITextField *contactTextField;
@property (nonatomic, strong) UITextField *addressTextField;
@property (nonatomic, strong) UITextField *phoneTextField;
@property (nonatomic, strong) UITextField *searchTextField;

@property (nonatomic, strong) UIButton *addButton;
@property (nonatomic, strong) UIButton *updateButton;
@property (nonatomic, strong) UIButton *deleteButton;
@property (nonatomic, strong) UIButton *searchButton;
@property (nonatomic, strong) UIButton *clearButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setupDatabase];
    [self setupUI];
    [self loadData];
}

- (void)setupDatabase {
    DatabaseManager *dbManager = [DatabaseManager sharedInstance];
    if (![dbManager openDatabase]) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"错误" 
                                                                       message:@"数据库初始化失败" 
                                                                preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
        [self presentViewController:alert animated:YES completion:nil];
    }
}

- (void)setupUI {
    self.view.backgroundColor = [UIColor whiteColor];
    self.title = @"客户管理";
    
    // 创建输入框
    [self createTextFields];
    
    // 创建按钮
    [self createButtons];
    
    // 创建表格
    [self createTableView];
    
    // 布局
    [self setupLayout];
}

- (void)createTextFields {
    // 搜索框
    _searchTextField = [[UITextField alloc] init];
    _searchTextField.placeholder = @"搜索客户名、联系人、地址、电话";
    _searchTextField.borderStyle = UITextBorderStyleRoundedRect;
    _searchTextField.delegate = self;
    _searchTextField.returnKeyType = UIReturnKeySearch;
    [self.view addSubview:_searchTextField];
    
    // 客户名
    _nameTextField = [[UITextField alloc] init];
    _nameTextField.placeholder = @"客户名";
    _nameTextField.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:_nameTextField];
    
    // 联系人
    _contactTextField = [[UITextField alloc] init];
    _contactTextField.placeholder = @"联系人";
    _contactTextField.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:_contactTextField];
    
    // 地址
    _addressTextField = [[UITextField alloc] init];
    _addressTextField.placeholder = @"地址";
    _addressTextField.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:_addressTextField];
    
    // 电话
    _phoneTextField = [[UITextField alloc] init];
    _phoneTextField.placeholder = @"电话";
    _phoneTextField.borderStyle = UITextBorderStyleRoundedRect;
    _phoneTextField.keyboardType = UIKeyboardTypePhonePad;
    [self.view addSubview:_phoneTextField];
}

- (void)createButtons {
    _addButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [_addButton setTitle:@"添加" forState:UIControlStateNormal];
    [_addButton addTarget:self action:@selector(addButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_addButton];
    
    _updateButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [_updateButton setTitle:@"修改" forState:UIControlStateNormal];
    [_updateButton addTarget:self action:@selector(updateButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_updateButton];
    
    _deleteButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [_deleteButton setTitle:@"删除" forState:UIControlStateNormal];
    [_deleteButton addTarget:self action:@selector(deleteButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_deleteButton];
    
    _searchButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [_searchButton setTitle:@"查询" forState:UIControlStateNormal];
    [_searchButton addTarget:self action:@selector(searchButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_searchButton];
    
    _clearButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [_clearButton setTitle:@"清空" forState:UIControlStateNormal];
    [_clearButton addTarget:self action:@selector(clearButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_clearButton];
}

- (void)createTableView {
    _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    _tableView.delegate = self;
    _tableView.dataSource = self;
    _tableView.tableFooterView = [[UIView alloc] init];
    [self.view addSubview:_tableView];
}

- (void)setupLayout {
    CGFloat padding = 10;
    CGFloat fieldHeight = 40;
    CGFloat buttonHeight = 44;
    CGFloat screenWidth = self.view.bounds.size.width;
    
    // 搜索框
    _searchTextField.frame = CGRectMake(padding, 100, screenWidth - 2 * padding, fieldHeight);
    
    // 按钮行1
    CGFloat buttonWidth = (screenWidth - 3 * padding) / 2;
    _searchButton.frame = CGRectMake(padding, 150, buttonWidth, buttonHeight);
    _clearButton.frame = CGRectMake(padding * 2 + buttonWidth, 150, buttonWidth, buttonHeight);
    
    // 输入框
    _nameTextField.frame = CGRectMake(padding, 210, screenWidth - 2 * padding, fieldHeight);
    _contactTextField.frame = CGRectMake(padding, 260, screenWidth - 2 * padding, fieldHeight);
    _addressTextField.frame = CGRectMake(padding, 310, screenWidth - 2 * padding, fieldHeight);
    _phoneTextField.frame = CGRectMake(padding, 360, screenWidth - 2 * padding, fieldHeight);
    
    // 按钮行2
    _addButton.frame = CGRectMake(padding, 420, buttonWidth, buttonHeight);
    _updateButton.frame = CGRectMake(padding * 2 + buttonWidth, 420, buttonWidth, buttonHeight);
    _deleteButton.frame = CGRectMake(padding, 480, screenWidth - 2 * padding, buttonHeight);
    
    // 表格
    CGFloat tableY = 540;
    _tableView.frame = CGRectMake(0, tableY, screenWidth, self.view.bounds.size.height - tableY);
}

- (void)loadData {
    _customers = [[DatabaseManager sharedInstance] getAllCustomers];
    [self.tableView reloadData];
}

- (void)clearInputFields {
    _nameTextField.text = @"";
    _contactTextField.text = @"";
    _addressTextField.text = @"";
    _phoneTextField.text = @"";
    _selectedCustomer = nil;
}

#pragma mark - Button Actions

- (void)addButtonTapped {
    if (_nameTextField.text.length == 0) {
        [self showAlertWithTitle:@"提示" message:@"请输入客户名"];
        return;
    }
    
    DatabaseManager *dbManager = [DatabaseManager sharedInstance];
    BOOL success = [dbManager addCustomerWithName:_nameTextField.text
                                   contactPerson:_contactTextField.text
                                         address:_addressTextField.text
                                           phone:_phoneTextField.text];
    
    if (success) {
        [self showAlertWithTitle:@"成功" message:@"客户添加成功"];
        [self clearInputFields];
        [self loadData];
    } else {
        [self showAlertWithTitle:@"错误" message:@"添加客户失败"];
    }
}

- (void)updateButtonTapped {
    if (!_selectedCustomer) {
        [self showAlertWithTitle:@"提示" message:@"请先选择要修改的客户"];
        return;
    }
    
    if (_nameTextField.text.length == 0) {
        [self showAlertWithTitle:@"提示" message:@"请输入客户名"];
        return;
    }
    
    Customer *customer = [[Customer alloc] init];
    customer.customerId = _selectedCustomer.customerId;
    customer.customerName = _nameTextField.text;
    customer.contactPerson = _contactTextField.text;
    customer.address = _addressTextField.text;
    customer.phone = _phoneTextField.text;
    
    DatabaseManager *dbManager = [DatabaseManager sharedInstance];
    BOOL success = [dbManager updateCustomer:customer];
    
    if (success) {
        [self showAlertWithTitle:@"成功" message:@"客户修改成功"];
        [self clearInputFields];
        [self loadData];
    } else {
        [self showAlertWithTitle:@"错误" message:@"修改客户失败"];
    }
}

- (void)deleteButtonTapped {
    if (!_selectedCustomer) {
        [self showAlertWithTitle:@"提示" message:@"请先选择要删除的客户"];
        return;
    }
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"确认删除" 
                                                                   message:@"确定要删除这个客户吗?" 
                                                            preferredStyle:UIAlertControllerStyleAlert];
    
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
    [alert addAction:[UIAlertAction actionWithTitle:@"删除" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        DatabaseManager *dbManager = [DatabaseManager sharedInstance];
        BOOL success = [dbManager deleteCustomerWithId:self->_selectedCustomer.customerId];
        
        if (success) {
            [self showAlertWithTitle:@"成功" message:@"客户删除成功"];
            [self clearInputFields];
            [self loadData];
        } else {
            [self showAlertWithTitle:@"错误" message:@"删除客户失败"];
        }
    }]];
    
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)searchButtonTapped {
    if (_searchTextField.text.length == 0) {
        [self loadData]; // 如果搜索框为空,显示所有数据
        return;
    }
    
    _customers = [[DatabaseManager sharedInstance] searchCustomersWithKeyword:_searchTextField.text];
    [self.tableView reloadData];
    [self.view endEditing:YES];
}

- (void)clearButtonTapped {
    _searchTextField.text = @"";
    [self loadData];
}

#pragma mark - UITableView DataSource & Delegate

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _customers.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"CustomerCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
    }
    
    Customer *customer = _customers[indexPath.row];
    cell.textLabel.text = [NSString stringWithFormat:@"%@ - %@", customer.customerName, customer.contactPerson];
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ | %@", customer.address, customer.phone];
    cell.detailTextLabel.numberOfLines = 2;
    
    // 标记选中的行
    if (_selectedCustomer && _selectedCustomer.customerId == customer.customerId) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        cell.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:1.0 alpha:1.0];
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
        cell.backgroundColor = [UIColor whiteColor];
    }
    
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
    _selectedCustomer = _customers[indexPath.row];
    
    // 填充数据到输入框
    _nameTextField.text = _selectedCustomer.customerName;
    _contactTextField.text = _selectedCustomer.contactPerson;
    _addressTextField.text = _selectedCustomer.address;
    _phoneTextField.text = _selectedCustomer.phone;
    
    [tableView reloadData];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 70;
}

#pragma mark - UITextField Delegate

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    if (textField == _searchTextField) {
        [self searchButtonTapped];
        return YES;
    }
    return NO;
}

#pragma mark - Helper Methods

- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title 
                                                                   message:message 
                                                            preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

@end

三、源码分析

1. 数据库管理类 (DatabaseManager)

1.1 数据模型 (Customer)

objc

@interface Customer : NSObject
@property (nonatomic, assign) NSInteger customerId;
@property (nonatomic, copy) NSString *customerName;
@property (nonatomic, copy) NSString *contactPerson;
@property (nonatomic, copy) NSString *address;
@property (nonatomic, copy) NSString *phone;
@end

  • 使用 copy 属性确保字符串不可变

  • customerId 作为主键,对应数据库中的自增 ID

1.2 单例模式实现

objc

+ (instancetype)sharedInstance {
    static DatabaseManager *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

  • 使用 dispatch_once 确保线程安全的单例

  • 整个应用共享同一个数据库实例

1.3 数据库路径设置

objc

- (void)setupDatabasePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths firstObject];
    self.databasePath = [documentsDirectory stringByAppendingPathComponent:@"customers.db"];
}

  • 数据库文件保存在 Documents 目录,确保数据持久化且可备份

  • 文件名为 customers.db

1.4 数据库表结构

sql

CREATE TABLE IF NOT EXISTS Customers (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    customer_name TEXT NOT NULL,
    contact_person TEXT,
    address TEXT,
    phone TEXT
);

  • 使用 IF NOT EXISTS 避免重复创建

  • id 作为自增主键

  • customer_name 为必填字段

1.5 CRUD 操作实现

添加客户:使用参数化查询防止 SQL 注入

objc

sqlite3_bind_text(statement, 1, [name UTF8String], -1, SQLITE_TRANSIENT);

查询操作:使用 sqlite3_step 遍历结果集

objc

while (sqlite3_step(statement) == SQLITE_ROW) {
    // 处理每一行数据
}

搜索功能:使用 LIKE 模糊查询

objc

NSString *searchPattern = [NSString stringWithFormat:@"%%%@%%", keyword];

2. 界面控制器 (ViewController)

2.1 UI 组件

  • 输入框:客户名、联系人、地址、电话、搜索框

  • 功能按钮:添加、修改、删除、查询、清空

  • 表格视图:显示客户列表

2.2 核心功能实现

数据加载

objc

- (void)loadData {
    _customers = [[DatabaseManager sharedInstance] getAllCustomers];
    [self.tableView reloadData];
}

添加客户

  • 验证客户名不能为空

  • 调用数据库管理器的添加方法

  • 成功后清空输入框并刷新列表

修改客户

  • 需要先选择客户(设置 _selectedCustomer

  • 使用选中客户的 ID 进行更新

删除客户

  • 添加确认对话框,防止误操作

  • 使用 UIAlertController 提供取消选项

搜索功能

  • 支持多字段模糊搜索

  • 空搜索时显示所有数据

2.3 表格交互

objc

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    _selectedCustomer = _customers[indexPath.row];
    // 填充数据到输入框
    _nameTextField.text = _selectedCustomer.customerName;
    // ... 其他字段
}

  • 点击行时选中客户并填充表单

  • 使用 accessoryType 和背景色显示选中状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值