gpt4 book ai didi

iphone - 这是好的编程风格吗?这样使用类方法是否有效?

转载 作者:行者123 更新时间:2023-11-28 20:31:10 26 4
gpt4 key购买 nike

我对 Objective-C 和 iOS 开发有些陌生(使用它大约 1.5 年,实际上只是在过去 8 个月左右的时间里大量参与)。我已经编写了一个自定义类来处理我所有的网络服务请求。我用 AFNetworking对于这些请求(并且喜欢它),但我想确保我正在做的事情是有效的并且不会在以后引起问题。

从我对 Instruments 的观察以及应用程序的执行方式来看,这似乎是一个很好的方法,但我真的不是专家,希望得到一些反馈和/或建议。

这是我的 NetworkClient 类:

网络客户端.h:

#import <Foundation/Foundation.h>

extern NSString * const APIKey;

@interface NetworkClient : NSObject

+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
block:(void (^)(id obj))block;

+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
block:(void (^)(id obj))block;

+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
alertUserOnFailure:(BOOL)alertUserOnFailure
block:(void (^)(id obj))block;

+(void)handleNetworkErrorWithError:(NSError *)error;

+(void)handleNoAccessWithReason:(NSString *)reason;

@end

网络客户端.m:

#import "NetworkClient.h"
#import "AFHTTPClient.h"
#import "AFHTTPRequestOperation.h"
#import "SBJson.h"

NSString * const APIKey = @"MyAPIKeyThatIsDefinedInDatabasePerApplication";

@implementation NetworkClient

+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
block:(void (^)(id obj))block {

[self processURLRequestWithURL:url andParams:params syncRequest:NO alertUserOnFailure:NO block:^(id obj) {
block(obj);
}];
}

+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
block:(void (^)(id obj))block {
[self processURLRequestWithURL:url andParams:params syncRequest:syncRequest alertUserOnFailure:NO block:^(id obj) {
block(obj);
}];
}


+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
alertUserOnFailure:(BOOL)alertUserOnFailure
block:(void (^)(id obj))block {

// Default url goes here, pass in a nil to use it
if (url == nil) {
url = @"https://MyURLToWebService";
}

// Add in our API Key
NSMutableDictionary *newParams = [[NSMutableDictionary alloc] initWithDictionary:params];
[newParams setValue:APIKey forKey:@"APIKey"];

NSURL *requestURL;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:requestURL];

NSMutableURLRequest *theRequest = [httpClient requestWithMethod:@"POST" path:url parameters:newParams];

__block NSString *responseString = @"";

AFHTTPRequestOperation *_operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
__weak AFHTTPRequestOperation *operation = _operation;

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
responseString = [operation responseString];

id retObj = [responseString JSONValue];

// Check for invalid response (No Access)
if ([retObj isKindOfClass:[NSDictionary class]]) {
if ([[(NSDictionary *)retObj valueForKey:@"Message"] isEqualToString:@"No Access"]) {
block(nil);
[self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:@"Reason"]];
}
} else if ([retObj isKindOfClass:[NSArray class]]) {
if ([(NSArray *)retObj count] > 0) {
NSDictionary *dict = [(NSArray *)retObj objectAtIndex:0];
if ([[dict valueForKey:@"Message"] isEqualToString:@"No Access"]) {
block(nil);
[self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:@"Reason"]];
}
}
}
block(retObj);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Failed with error = %@", [NSString stringWithFormat:@"[Error]:%@",error]);
block(nil);
if (alertUserOnFailure) {
// Let the user know something went wrong
[self handleNetworkErrorWithError:operation.error];
}

}];

[operation start];

if (syncRequest) {
// Process the request syncronously
[operation waitUntilFinished];
}


}


+(void)handleNetworkErrorWithError:(NSError *)error {
NSString *errorString = [NSString stringWithFormat:@"[Error]:%@",error];

// Standard UIAlert Syntax
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:@"Connection Error"
message:errorString
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];

[myAlert show];

}

+(void)handleNoAccessWithReason:(NSString *)reason {
// Standard UIAlert Syntax
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:@"No Access"
message:reason
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];

[myAlert show];

}

@end

我是这样调用它的:

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
@"GetApplications", @"Command",
userInfo.networkID, @"NetworkID",
nil];

[NetworkClient processURLRequestWithURL:nil andParams:params block:^(id obj) {
[MBProgressHUD hideHUDForView:self.view animated:YES];

if ([obj isKindOfClass:[NSArray class]]) {
myTableViewData = (NSArray *)obj;
[self.myTableView reloadData];
}
}];

所以我的网络服务可以发送回字典结构的 JSON 响应和数组格式的 JSON 响应。 NetworkClient 方法将获取两者并发回它所获得的内容(我将其留给调用代码以确保它返回预期的内容)。我使用 APIKey 作为额外的安全措施来确保只有我的应用程序可以访问 Web 服务资源(在发回数据之前我检查的第一件事是 APIKey 与我在数据库中为该应用程序拥有的相匹配)。

这是做这种事情的有效方法吗?有什么办法可以让它变得更好?

最佳答案

我不明白你为什么要使用 processURLRequestWithURL:nil 因为这是为了处理特定的服务。也是一头雾水,只告诉我别处有魔法,跟根本没有一样。我会使用单例:

extern NSString * const kBaseURL;

@interface NetworkClient : AFHTTPClient
+ (NetworkClient *) sharedClient;
@end

NSString* const kNodeApiURL = BASE_URL;

@implementation NetworkClient

+ (NetworkClient*) sharedClient
{
static NetworkClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[NetworkClient alloc] initWithBaseURL:[NSURL URLWithString:kBaseURL]];
});
return _sharedClient;
}

- (id)initWithBaseURL:(NSURL*)url
{
if (self = [super initWithBaseURL:url]) {
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:@"Accept" value:@"application/json"];
}
return self;
}

-(id) init {
error(@"Use initWithBaseURL: instead.");
[super doesNotRecognizeSelector:_cmd];
return nil;
}

@end

然后在PCH上

#define BASE_URL  @"https://MyURLToWebService"

当您添加一个参数来显示弹出窗口时,您也将 GUI 与服务器 API 混合在一起。我不认为服务器 API 应该阻止线程。编写纯异步代码,让调用者从他自己的一端阻止 GUI。

与 handleNoAccessWithReason 相同。 API 不处理任何事情,它吸收输入并产生输出。您编写的每一段代码都应该做一 (1) 件事。它将更容易测试、理解和重用。

我不知道你为什么用 __weak 限定操作。

你传递的那些参数,如果你使用像 User 和 Command 之类的域对象,它会更容易理解。好吧,“命令”很臭。你的使用代码后面真的有一个名字有意义的方法吗?因为当我调试代码时,我必须打印参数来告诉我发生了什么事,我很生气。如果您正在编写服务器 API(如果您想要干净的代码,默认情况下您应该这样做),您应该公开有意义的名称。

我会以不同的方式编写代码,例如,我想为给定用户从服务器获取一头奶牛:

typedef void (^AFJSONSuccess)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON);
typedef void (^AFJSONFailure)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON);

+(void) cowForUser:(User*)user callback:(void(^)(Cow *cow, NSError *error))callback {

AFJSONSuccess success = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// turn JSON into a cow
callback(cow,nil);
};

AFJSONFailure failure = ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
// create a custom NSError
callback(nil,error);
};

NetworkClient *client = [NetworkClient sharedClient];
NSMutableURLRequest *request = [client requestWithMethod:@"GET" path:kCowPath parameters:jsonDic];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:sucess failure:failure];
[client enqueueHTTPRequestOperation:operation];
}

现在在使用中启动 hud,并在回调 block 中调用停止 hud 并检查 cow 是否为 nil。我认为 HUD 不应该遮挡屏幕(就像您等待操作完成一样),如果用户决定移动到另一个屏幕或取消查询怎么办?

我投票关闭这个问题,因为它属于代码审查。

关于iphone - 这是好的编程风格吗?这样使用类方法是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12063060/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com