MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Objective-C 项目架构设计与优化

2021-07-044.4k 阅读

一、Objective-C 项目架构基础

1.1 面向对象编程原则

在 Objective-C 项目架构设计中,遵循面向对象编程(OOP)的原则是至关重要的。这些原则包括封装、继承和多态。

1.1.1 封装

封装是将数据和操作数据的方法捆绑在一起,隐藏对象的内部实现细节,只对外提供公共的接口。这样可以提高代码的安全性和可维护性。例如,我们有一个 Person 类,它包含姓名和年龄属性,以及设置和获取这些属性的方法:

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

- (void)setName:(NSString *)name andAge:(NSInteger)age;
- (void)printInfo;

@end

@implementation Person

- (void)setName:(NSString *)name andAge:(NSInteger)age {
    self.name = name;
    self.age = age;
}

- (void)printInfo {
    NSLog(@"Name: %@, Age: %ld", self.name, (long)self.age);
}

@end

在上述代码中,nameage 属性的直接访问被封装起来,外部只能通过 setName:andAge:printInfo 方法来操作和获取相关信息。

1.1.2 继承

继承允许一个类从另一个类获取属性和方法,从而实现代码的复用。例如,我们创建一个 Student 类,它继承自 Person 类,并添加了学号属性和相关方法:

@interface Student : Person

@property (nonatomic, copy) NSString *studentID;

- (void)setStudentID:(NSString *)studentID;
- (void)printStudentInfo;

@end

@implementation Student

- (void)setStudentID:(NSString *)studentID {
    self.studentID = studentID;
}

- (void)printStudentInfo {
    [super printInfo];
    NSLog(@"Student ID: %@", self.studentID);
}

@end

Student 类继承了 Person 类的 nameage 属性以及 setName:andAge:printInfo 方法,同时添加了自己特有的 studentID 属性和相关方法。

1.1.3 多态

多态是指同一个方法调用,根据对象类型的不同而有不同的行为。在 Objective-C 中,通过动态绑定实现多态。例如,我们有一个 Animal 类及其子类 DogCat,每个类都有 makeSound 方法:

@interface Animal : NSObject

- (void)makeSound;

@end

@implementation Animal

- (void)makeSound {
    NSLog(@"Animal makes a sound.");
}

@end

@interface Dog : Animal

- (void)makeSound {
    NSLog(@"Dog barks.");
}

@end

@interface Cat : Animal

- (void)makeSound {
    NSLog(@"Cat meows.");
}

@end

然后在使用时:

Animal *animal1 = [[Dog alloc] init];
Animal *animal2 = [[Cat alloc] init];

[animal1 makeSound];
[animal2 makeSound];

这里 animal1animal2 虽然声明为 Animal 类型,但实际分别指向 DogCat 对象,调用 makeSound 方法时会根据实际对象类型执行相应的方法,体现了多态性。

1.2 模块划分

合理的模块划分是良好项目架构的基础。在 Objective-C 项目中,可以根据功能、业务逻辑等进行模块划分。

1.2.1 功能模块

例如,一个社交应用可以划分为用户模块、聊天模块、动态模块等。用户模块负责处理用户的注册、登录、个人信息管理等功能;聊天模块负责即时通讯相关的功能,如消息发送、接收、会话管理等;动态模块负责展示和管理用户发布的动态内容。

以用户模块为例,我们可以创建一个 UserModule 类来封装相关功能:

@interface UserModule : NSObject

- (BOOL)registerUserWithUsername:(NSString *)username password:(NSString *)password;
- (BOOL)loginUserWithUsername:(NSString *)username password:(NSString *)password;
- (void)updateUserProfile:(NSDictionary *)profileInfo;

@end

@implementation UserModule

- (BOOL)registerUserWithUsername:(NSString *)username password:(NSString *)password {
    // 实际的注册逻辑,例如向服务器发送请求
    NSLog(@"Registering user %@ with password %@", username, password);
    return YES;
}

- (BOOL)loginUserWithUsername:(NSString *)username password:(NSString *)password {
    // 实际的登录逻辑,例如验证用户名密码
    NSLog(@"Logging in user %@ with password %@", username, password);
    return YES;
}

- (void)updateUserProfile:(NSDictionary *)profileInfo {
    // 实际的更新用户资料逻辑,例如向服务器发送更新请求
    NSLog(@"Updating user profile with %@", profileInfo);
}

@end

1.2.2 业务逻辑模块

除了功能模块,还可以按照业务逻辑进行模块划分。例如,在一个电商应用中,下单业务逻辑可以单独划分成一个模块。这个模块可能涉及到购物车数据处理、商品库存检查、订单生成等一系列操作。

@interface OrderModule : NSObject

- (BOOL)placeOrderWithCartItems:(NSArray *)cartItems;

@end

@implementation OrderModule

- (BOOL)placeOrderWithCartItems:(NSArray *)cartItems {
    // 检查商品库存
    for (NSDictionary *item in cartItems) {
        NSString *productID = item[@"productID"];
        NSInteger quantity = [item[@"quantity"] integerValue];
        // 假设这里有一个检查库存的方法
        if (![self checkStockForProduct:productID withQuantity:quantity]) {
            return NO;
        }
    }
    // 生成订单
    NSLog(@"Placing order with cart items: %@", cartItems);
    return YES;
}

- (BOOL)checkStockForProduct:(NSString *)productID withQuantity:(NSInteger)quantity {
    // 实际的库存检查逻辑,例如查询数据库
    NSLog(@"Checking stock for product %@ with quantity %ld", productID, (long)quantity);
    return YES;
}

@end

二、Objective-C 项目架构设计模式

2.1 单例模式

单例模式确保一个类只有一个实例,并提供一个全局访问点。在 Objective-C 中,实现单例模式通常有以下方式:

@interface AppSettings : NSObject

@property (nonatomic, strong) NSString *appTheme;
@property (nonatomic, assign) NSInteger fontSize;

+ (instancetype)sharedSettings;

@end

@implementation AppSettings

static AppSettings *sharedInstance = nil;

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

@end

通过 dispatch_once 确保 sharedInstance 只被初始化一次。在整个应用中,可以通过 [AppSettings sharedSettings] 来获取唯一的实例,例如:

AppSettings *settings1 = [AppSettings sharedSettings];
AppSettings *settings2 = [AppSettings sharedSettings];
NSLog(@"settings1 == settings2: %d", settings1 == settings2); // 输出 1,说明是同一个实例

单例模式适用于管理应用的全局配置、数据库连接等场景,避免了重复创建实例带来的资源浪费。

2.2 代理模式

代理模式定义了一种对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。在 Objective-C 中,通常通过协议(protocol)来实现代理模式。

例如,我们有一个 DownloadManager 类负责下载文件,并且需要在下载完成时通知其他对象:

@protocol DownloadManagerDelegate <NSObject>

- (void)downloadManagerDidFinishDownload:(NSString *)filePath;

@end

@interface DownloadManager : NSObject

@property (nonatomic, weak) id<DownloadManagerDelegate> delegate;
- (void)startDownloadWithURL:(NSURL *)url;

@end

@implementation DownloadManager

- (void)startDownloadWithURL:(NSURL *)url {
    // 模拟下载过程
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSString *filePath = @"/tmp/downloadedFile.txt";
        if ([self.delegate respondsToSelector:@selector(downloadManagerDidFinishDownload:)]) {
            [self.delegate downloadManagerDidFinishDownload:filePath];
        }
    });
}

@end

然后有一个 ViewController 作为代理来处理下载完成的通知:

@interface ViewController : UIViewController <DownloadManagerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    DownloadManager *downloadManager = [[DownloadManager alloc] init];
    downloadManager.delegate = self;
    NSURL *url = [NSURL URLWithString:@"http://example.com/file.txt"];
    [downloadManager startDownloadWithURL:url];
}

- (void)downloadManagerDidFinishDownload:(NSString *)filePath {
    NSLog(@"Download finished. File path: %@", filePath);
}

@end

代理模式使得 DownloadManager 与它的使用者解耦,提高了代码的可维护性和扩展性。

2.3 策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。在 Objective-C 中,可以通过协议和类的组合来实现策略模式。

假设我们有一个支付模块,支持多种支付方式,如支付宝、微信支付、银行卡支付等。我们可以定义一个支付协议和具体的支付策略类:

@protocol PaymentStrategy <NSObject>

- (BOOL)payWithAmount:(NSDecimalNumber *)amount;

@end

@interface AlipayStrategy : NSObject <PaymentStrategy>

- (BOOL)payWithAmount:(NSDecimalNumber *)amount {
    // 实际的支付宝支付逻辑
    NSLog(@"Paying %@ with Alipay", amount);
    return YES;
}

@end

@interface WeChatPayStrategy : NSObject <PaymentStrategy>

- (BOOL)payWithAmount:(NSDecimalNumber *)amount {
    // 实际的微信支付逻辑
    NSLog(@"Paying %@ with WeChat Pay", amount);
    return YES;
}

@end

@interface PaymentContext : NSObject

@property (nonatomic, strong) id<PaymentStrategy> paymentStrategy;

- (void)setPaymentStrategy:(id<PaymentStrategy>)strategy;
- (BOOL)executePaymentWithAmount:(NSDecimalNumber *)amount;

@end

@implementation PaymentContext

- (void)setPaymentStrategy:(id<PaymentStrategy>)strategy {
    self.paymentStrategy = strategy;
}

- (BOOL)executePaymentWithAmount:(NSDecimalNumber *)amount {
    return [self.paymentStrategy payWithAmount:amount];
}

@end

在使用时:

PaymentContext *context = [[PaymentContext alloc] init];
AlipayStrategy *alipayStrategy = [[AlipayStrategy alloc] init];
[context setPaymentStrategy:alipayStrategy];
NSDecimalNumber *amount = [NSDecimalNumber decimalNumberWithString:@"100.00"];
BOOL result = [context executePaymentWithAmount:amount];
NSLog(@"Payment result: %d", result);

WeChatPayStrategy *weChatPayStrategy = [[WeChatPayStrategy alloc] init];
[context setPaymentStrategy:weChatPayStrategy];
result = [context executePaymentWithAmount:amount];
NSLog(@"Payment result: %d", result);

策略模式使得支付方式的切换变得非常容易,符合开闭原则,提高了代码的可维护性和灵活性。

三、Objective-C 项目架构优化

3.1 内存管理优化

在 Objective-C 中,合理的内存管理是优化项目性能的关键。自从引入 ARC(自动引用计数)后,内存管理变得相对简单,但仍有一些需要注意的地方。

3.1.1 ARC 原理与使用

ARC 会自动管理对象的内存,当对象的引用计数变为 0 时,ARC 会自动释放对象所占用的内存。例如:

NSString *string = @"Hello, World!";
// 此时 string 有一个引用
{
    NSString *newString = string;
    // newString 也引用了 string 指向的对象,引用计数加 1
}
// newString 作用域结束,引用计数减 1,string 仍有一个引用

在使用 ARC 时,要注意避免循环引用。例如,两个对象相互持有对方的引用就会导致循环引用:

@interface ClassA : NSObject

@property (nonatomic, strong) ClassB *classB;

@end

@interface ClassB : NSObject

@property (nonatomic, strong) ClassA *classA;

@end

在这种情况下,ClassAClassB 的实例会一直存在,不会被释放。解决方法是将其中一个属性改为 weakunsafe_unretained,例如:

@interface ClassA : NSObject

@property (nonatomic, strong) ClassB *classB;

@end

@interface ClassB : NSObject

@property (nonatomic, weak) ClassA *classA;

@end

3.1.2 手动内存管理(非 ARC 环境)

在非 ARC 环境下,需要手动调用 retainreleaseautorelease 方法来管理对象的引用计数。例如:

NSString *string = [[NSString alloc] initWithString:@"Hello"];
[string retain];
// 引用计数为 2
[string release];
// 引用计数为 1
[string autorelease];
// 引用计数为 1,在自动释放池被销毁时会被释放

手动内存管理需要非常小心,避免内存泄漏和悬空指针的问题。

3.2 性能优化

3.2.1 优化数据存储与读取

在 Objective-C 项目中,数据的存储和读取方式会影响性能。例如,对于大量数据的存储,使用 SQLite 数据库比使用文件存储更高效。

假设我们要存储用户的订单信息,可以使用 FMDB 库来操作 SQLite 数据库:

#import "FMDB.h"

@interface OrderDatabaseManager : NSObject

@property (nonatomic, strong) FMDatabase *database;

- (BOOL)openDatabase;
- (BOOL)saveOrder:(NSDictionary *)order;
- (NSArray *)fetchAllOrders;

@end

@implementation OrderDatabaseManager

- (BOOL)openDatabase {
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *databasePath = [documentsPath stringByAppendingPathComponent:@"orders.db"];
    self.database = [FMDatabase databaseWithPath:databasePath];
    return [self.database open];
}

- (BOOL)saveOrder:(NSDictionary *)order {
    NSString *insertSQL = @"INSERT INTO orders (order_id, order_amount, order_date) VALUES (?,?,?)";
    FMResultSet *resultSet = [self.database executeUpdate:insertSQL, order[@"order_id"], order[@"order_amount"], order[@"order_date"]];
    return resultSet != nil;
}

- (NSArray *)fetchAllOrders {
    NSMutableArray *orders = [NSMutableArray array];
    NSString *selectSQL = @"SELECT * FROM orders";
    FMResultSet *resultSet = [self.database executeQuery:selectSQL];
    while ([resultSet next]) {
        NSMutableDictionary *order = [NSMutableDictionary dictionary];
        [order setObject:[resultSet stringForColumn:@"order_id"] forKey:@"order_id"];
        [order setObject:[resultSet stringForColumn:@"order_amount"] forKey:@"order_amount"];
        [order setObject:[resultSet stringForColumn:@"order_date"] forKey:@"order_date"];
        [orders addObject:order];
    }
    return orders;
}

@end

通过合理设计数据库表结构和使用高效的查询语句,可以提高数据存储和读取的性能。

3.2.2 优化网络请求

在网络应用中,网络请求的优化至关重要。可以使用 AFNetworking 库来简化和优化网络请求。例如,进行一个 GET 请求:

#import "AFNetworking.h"

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];

NSDictionary *parameters = @{@"param1": @"value1", @"param2": @"value2"};
[manager GET:@"http://example.com/api" parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    NSLog(@"Request success: %@", responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    NSLog(@"Request failed: %@", error);
}];

为了优化网络请求,可以设置合理的超时时间、缓存策略等。例如,设置缓存策略为只从缓存读取数据:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.requestCachePolicy = NSURLRequestReturnCacheDataDontLoad;
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];

3.3 代码结构优化

3.3.1 重构重复代码

在项目开发过程中,很容易出现重复代码。例如,在多个视图控制器中都有获取用户信息的代码:

// ViewController1.m
- (void)fetchUserInfo {
    NSString *urlString = @"http://example.com/api/userinfo";
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (!error && data) {
            NSDictionary *userInfo = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
            NSLog(@"User info: %@", userInfo);
        }
    }];
    [task resume];
}

// ViewController2.m
- (void)fetchUserInfo {
    NSString *urlString = @"http://example.com/api/userinfo";
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (!error && data) {
            NSDictionary *userInfo = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
            NSLog(@"User info: %@", userInfo);
        }
    }];
    [task resume];
}

可以将这部分重复代码提取到一个单独的类或方法中:

@interface UserInfoFetcher : NSObject

+ (void)fetchUserInfoWithCompletion:(void(^)(NSDictionary *userInfo, NSError *error))completion;

@end

@implementation UserInfoFetcher

+ (void)fetchUserInfoWithCompletion:(void(^)(NSDictionary *userInfo, NSError *error))completion {
    NSString *urlString = @"http://example.com/api/userinfo";
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (!error && data) {
            NSDictionary *userInfo = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
            completion(userInfo, nil);
        } else {
            completion(nil, error);
        }
    }];
    [task resume];
}

@end

然后在视图控制器中调用:

// ViewController1.m
- (void)viewDidLoad {
    [super viewDidLoad];
    [UserInfoFetcher fetchUserInfoWithCompletion:^(NSDictionary *userInfo, NSError *error) {
        if (!error && userInfo) {
            NSLog(@"User info: %@", userInfo);
        }
    }];
}

// ViewController2.m
- (void)viewDidLoad {
    [super viewDidLoad];
    [UserInfoFetcher fetchUserInfoWithCompletion:^(NSDictionary *userInfo, NSError *error) {
        if (!error && userInfo) {
            NSLog(@"User info: %@", userInfo);
        }
    }];
}

3.3.2 优化类的设计

确保类的职责单一,避免一个类承担过多的功能。例如,一个类既负责网络请求,又负责数据存储和界面更新,这会导致类的代码变得复杂且难以维护。应该将这些功能拆分到不同的类中,使每个类专注于自己的职责。

同时,要合理控制类的继承层次,避免继承层次过深。继承层次过深会导致代码的可读性和维护性变差,并且可能引发一些难以调试的问题。如果发现继承层次过深,可以考虑使用组合等方式来重构代码。

四、Objective-C 项目架构与其他技术的结合

4.1 与 iOS 框架的结合

Objective-C 是 iOS 开发的主要编程语言,与 iOS 框架紧密结合。例如,UIKit 框架用于构建用户界面,Core Data 框架用于数据持久化,MapKit 框架用于地图相关功能等。

4.1.1 与 UIKit 的结合

在使用 UIKit 构建界面时,要遵循 MVC(Model - View - Controller)架构模式。例如,创建一个简单的登录界面:

// LoginViewController.h
@interface LoginViewController : UIViewController

@property (nonatomic, weak) IBOutlet UITextField *usernameField;
@property (nonatomic, weak) IBOutlet UITextField *passwordField;
- (IBAction)loginButtonTapped:(id)sender;

@end

// LoginViewController.m
@implementation LoginViewController

- (IBAction)loginButtonTapped:(id)sender {
    NSString *username = self.usernameField.text;
    NSString *password = self.passwordField.text;
    // 调用登录逻辑,例如调用 UserModule 的登录方法
    UserModule *userModule = [[UserModule alloc] init];
    if ([userModule loginUserWithUsername:username password:password]) {
        NSLog(@"Login successful");
    } else {
        NSLog(@"Login failed");
    }
}

@end

在这个例子中,LoginViewController 作为控制器,负责处理用户界面的交互和调用业务逻辑。UITextFieldUIButton 等视图负责展示界面元素,而 UserModule 作为模型,负责处理登录的业务逻辑。

4.1.2 与 Core Data 的结合

Core Data 提供了一种面向对象的数据持久化方式。例如,要存储用户的笔记信息:

// 创建 Managed Object Model
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];

// 创建 Persistent Store Coordinator
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *storePath = [documentsPath stringByAppendingPathComponent:@"notes.db"];
NSError *error = nil;
if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:storePath] options:nil error:&error]) {
    NSLog(@"Failed to add persistent store: %@", error);
}

// 创建 Managed Object Context
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[context setPersistentStoreCoordinator:coordinator];

// 创建和保存笔记
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:context];
NSManagedObject *note = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
[note setValue:@"My first note" forKey:@"title"];
[note setValue:@"This is the content of my first note" forKey:@"content"];
if (![context save:&error]) {
    NSLog(@"Failed to save note: %@", error);
}

Core Data 简化了数据持久化的过程,并且提供了强大的查询和数据管理功能。

4.2 与第三方库的结合

在 Objective-C 项目中,经常会使用第三方库来扩展功能。例如,AFNetworking 用于网络请求,SDWebImage 用于图片加载等。

4.2.1 与 AFNetworking 的结合

前面已经介绍了 AFNetworking 的基本使用。在实际项目中,可以对 AFNetworking 进行封装,以适应项目的特定需求。例如,创建一个 NetworkManager 类来统一管理网络请求:

@interface NetworkManager : NSObject

+ (instancetype)sharedManager;
- (void)getWithURL:(NSString *)url parameters:(NSDictionary *)parameters success:(void(^)(id responseObject))success failure:(void(^)(NSError *error))failure;
- (void)postWithURL:(NSString *)url parameters:(NSDictionary *)parameters success:(void(^)(id responseObject))success failure:(void(^)(NSError *error))failure;

@end

@implementation NetworkManager

static NetworkManager *sharedInstance = nil;

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

- (void)getWithURL:(NSString *)url parameters:(NSDictionary *)parameters success:(void(^)(id responseObject))success failure:(void(^)(NSError *error))failure {
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    [manager GET:url parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        failure(error);
    }];
}

- (void)postWithURL:(NSString *)url parameters:(NSDictionary *)parameters success:(void(^)(id responseObject))success failure:(void(^)(NSError *error))failure {
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    [manager POST:url parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        failure(error);
    }];
}

@end

在视图控制器中使用:

@interface ViewController : UIViewController

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *url = @"http://example.com/api";
    NSDictionary *parameters = @{@"param1": @"value1"};
    [[NetworkManager sharedManager] getWithURL:url parameters:parameters success:^(id responseObject) {
        NSLog(@"Response: %@", responseObject);
    } failure:^(NSError *error) {
        NSLog(@"Error: %@", error);
    }];
}

@end

4.2.2 与 SDWebImage 的结合

SDWebImage 用于异步加载和缓存图片。在视图控制器中使用:

#import "SDWebImage/SDWebImage.h"

@interface ViewController : UIViewController

@property (nonatomic, weak) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *imageURLString = @"http://example.com/image.jpg";
    NSURL *imageURL = [NSURL URLWithString:imageURLString];
    [self.imageView sd_setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:@"placeholder"]];
}

@end

SDWebImage 会自动处理图片的下载、缓存和显示,提高了图片加载的效率和用户体验。

通过合理结合 iOS 框架和第三方库,可以丰富 Objective - C 项目的功能,提高开发效率和项目质量。在结合过程中,要注意遵循相关的规范和最佳实践,确保代码的可维护性和稳定性。