我是Objective-C的新手,我想知道我的方法是否合理。
我的应用程序是基于选项卡视图。每个标签都会向服务器发出请求。
appDelegate
中,我创建了一个与我的服务器的异步套接字连接的实例。TableViewController
,我需要在其中创建内部请求消息并将其发送到服务器。我的问题是我无法访问TableViewController
中的套接字,因此我可以通过appDelegate sharedApplication
访问套接字,然后将请求消息发送给服务器。 / p>
由于我使用异步套接字模型,接收服务器响应的委托是appDelegate
本身,现在我需要以某种方式将响应传播回“获取状态”TableViewController
。< / p>
我的问题是如何做到这一点??
也许我的方法不好开始,我需要使用同步套接字模型。 或者我可能需要将套接字连接作为上下文传递给我打开的每个视图控制器。
我错过了什么?如何从我发送的View中轻松访问服务器的响应?任何帮助将不胜感激!!
谢谢!
答案 0 :(得分:1)
我建议采用不同的设计。产生请求的东西应该是任何VC可以实例化并用于发出请求的类,可能是NSURLRequest的子类。
因为它是一个单身人士,所以很容易让应用程序委托全球数据和行为的持有者,但这不是它的工作。
如果您要为服务器请求做很多自定义工作,请继承NSURLRequest。使用NSURLConnection的sendAsynchronousRequest:方法运行它。它允许调用者在完成后传递一个块来执行请求结果。
e.g。 MyRequest.h
@interface MyRequest : NSMutableURLRequest
- (id)initWithParams:(NSDictionary *)params;
- (void)runWithCompletion:(void (^)(id result, NSError *error))completion;
@end
e.g。 MyRequest.m
@implementation MyRequest
- (id)initWithParams:(NSDictionary *)params {
self = [self init];
if (self) {
// do custom init here, e.g.
self.URL = @"http://www.myservice.com/myrequest.json"
[self setValue:@"bar" forHTTPHeaderField:@"foo"]; // more realistically, using key value pairs in the params dictionary
// and so on
}
return self;
}
- (void)runWithCompletion:(void (^)(id result, NSError *error))completion {
[NSURLConnection sendAsynchronousRequest:self
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data) {
// do something custom with the received data here,
// like convert to a string and parse as json, etc.
completion(data, nil);
} else {
completion(nil, error);
}
}];
}
@end
现在,任何VC - 或任何其他类 - 可以创建其中一个并使用它:
// in MyVC.m
MyRequest *myRequest = [[MyRequest alloc] initWithParams:[NSDictionary dictionary]];
[myRequest runWithCompletion:^(id result, NSError *error) {
// do main thread ui stuff with the result in hand, e.g.
[self.tableView reloadData];
}];
答案 1 :(得分:0)
您可以让您的代表在通知中心发布通知。然后您的表视图控制器注册到该通知,它可以接收信息。
像
这样的东西在您的AppDelegate 中,收到套接字响应时
NSDictionary * userInfo = @{@"socketResponse" : response}; // assuming that response is the object to pass around
[[NSNotificationCenter defaultCenter] postNotificationName:@"kDidReceiveSocketResponse"
object:self
userInfo:userInfo
在您的UITableViewController
中- (void)viewDidLoad {
[super viewDidLoad];
//...
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(socketResponseReceived:)
name:@"kDidReceiveSocketResponse"
object:nil];
//...
}
- (void)socketResponseReceived:(NSDictionary *)userInfo {
id response = userInfo[@"socketResponse"];
// do whatever you like
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
答案 2 :(得分:0)
我同意Talha对此的评论,不建议使用通知中心。最好创建一个继承自NSObject的新类来处理套接字事件,但如果需要,还可以使用app delegate使其工作。为了方便你...
创建从套接字类到视图控制器的链接
将TableViewSocketEventsDelegate定义为两个文件都可以看到的地方。您可以创建公共Constants.h或其他东西。
@protocol TableViewSocketEventsDelegate <NSObject>
@required
- (void) someSocketEvent:(int)statusCode;
//TODO: Add callbacks that make sense here
@end
给socket类(在你的情况下是app delegate .h文件)一个对最终处理动作的东西的引用(在你的情况下是表视图控制器)
@property (nonatomic, assign) id<TableViewSocketEventsDelegate> socketDelegate;
在.m中确保合成socketDelegate并将其分配给适当的视图控制器。
接下来告诉视图控制器它可以处理这些委托回调。
在.h:
ViewController : UITableViewController<TableViewSocketEventsDelegate>
in .m:
#pragma mark - TableViewSocketEventsDelegate
- (void) someSocketEvent:(int)statusCode
{
NSLog(@"Some socket event happened %I", statusCode);
}
现在你所要做的就是改变app委托中现有的处理套接字以调用新方法的方法
if (self.socketDelegate) {
[self.socketDelegate someSocketEvent:2];
}
这对你有用吗?我还建议为所有选项卡视图控制器创建一个基类,如果它们都需要处理这个相同的委托。
祝你好运!