Objective-C 项目架构设计与优化
一、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
在上述代码中,name
和 age
属性的直接访问被封装起来,外部只能通过 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
类的 name
、age
属性以及 setName:andAge:
和 printInfo
方法,同时添加了自己特有的 studentID
属性和相关方法。
1.1.3 多态
多态是指同一个方法调用,根据对象类型的不同而有不同的行为。在 Objective-C 中,通过动态绑定实现多态。例如,我们有一个 Animal
类及其子类 Dog
和 Cat
,每个类都有 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];
这里 animal1
和 animal2
虽然声明为 Animal
类型,但实际分别指向 Dog
和 Cat
对象,调用 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
在这种情况下,ClassA
和 ClassB
的实例会一直存在,不会被释放。解决方法是将其中一个属性改为 weak
或 unsafe_unretained
,例如:
@interface ClassA : NSObject
@property (nonatomic, strong) ClassB *classB;
@end
@interface ClassB : NSObject
@property (nonatomic, weak) ClassA *classA;
@end
3.1.2 手动内存管理(非 ARC 环境)
在非 ARC 环境下,需要手动调用 retain
、release
和 autorelease
方法来管理对象的引用计数。例如:
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
作为控制器,负责处理用户界面的交互和调用业务逻辑。UITextField
和 UIButton
等视图负责展示界面元素,而 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 项目的功能,提高开发效率和项目质量。在结合过程中,要注意遵循相关的规范和最佳实践,确保代码的可维护性和稳定性。