我需要与我的服务器建立连接以获取一些JSON
数据,我必须同时支持iOS 6
和iOS 7
。
我应该创建两个类吗?一个NSURLSession
iOS 7
和NSURLConnection
iOS 6
一个?或者我应该只使用NSURLConnection
吗?
答案 0 :(得分:3)
通过创建两个基本相同的单独类,您会获得什么好处?如果您不能使用NSURLSession,因为它仅在iOS 7中受支持,并且您可以使用同时适用于两者的NSURLConnection获得相同的功能,那么只需使用NSURLConnection即可。您将需要维护更少的代码。
答案 1 :(得分:3)
好问题。事实上,我有同样的问题,并对它进行了相当多的研究,我认为这是使用协议(其他语言中的a.k.a.界面)的好地方。这是基于着名的“四人帮”模式书中的“程序到界面而不是实现”的引用。我认为最好为将来尝试编码,所以如果他们决定弃用某些东西我就不会受到打击(这不是这种情况,但你永远不知道)。
编写一个定义要使用的方法的协议,然后创建两个实现这些方法的不同类,而不是编写类。在你的应用程序中,你将创建一个指针,指向任何实现所有协议方法的类,然后每个实现类可以使用他们想要发生的任何框架/库/其他代码。
例如,您可以创建如下的服务器协议:
// Server.h
@protocol Server <NSObject>
@required
- (void)callService:(NSString *)service withData:(NSData *)data;
@end
然后创建一个这样的RestServer类:
// RestServer.h
#import "Server.h"
@interface RestServer : NSObject <Server>
@end
// RestServer.m
#import "RestServer.h"
@implementation RestServer
- (void)callService:(NSString *)service withData:(NSData *)data {
// Code using REST
}
@end
然后创建另一个类,如SoapServer:
// SoapServer.h
#import "Server.h"
@interface SoapServer : NSObject <Server>
@end
// SoapServer.m
#import “SoapServer.h"
@implementation SoapServer
- (void)callService:(NSString *)service withData:(NSData *)data {
// Code using SOAP
}
@end
将您的主应用程序编码为只使用指向界面的指针,现在您可以交换类而无需更改主代码:
// SomeViewController.m
#import “Server.h”
#import “RestServer.h”
#import “SoapServer.h”
…
- (void)someMethod() {
id<Server> myServer;
if ([self shouldIUseSoap])
myServer = [[SoapServer alloc] init];
else
myServer = [[RestServer alloc] init];
[myServer callService:@"loginUser" withData:[self getData]];
}
现在,您可以随时更改服务器类,而无需在代码中调用callService:withData:的所有位置。这是对接口进行编程的好处!
我使用了Rest vs Soap,因为我认为Objective-C更新的人可能会更好地理解,但在你的情况下,你可能会有一个ConnectionServer vs SessionServer或类似的东西。
关于接口/协议编程的另一个好读物可以在这里找到:https://stackoverflow.com/a/384067/504873
答案 2 :(得分:0)
如果必须进入Windows身份验证网络,则必须使用NSURLCredentialPersistenceForSession
...然后使用NSURLConnection
将为您创建多个问题。我现在正在经历痛苦并得出结论,我需要两者都支持iOS 7.基本上,如果你使用NSURLConnection
和willSendRequestForAuthenticationChallenge
,你会发现在iOS 7中,你的会话将以自己的想法结束(似乎是30秒的思维范围)。因此,如果你必须坚持使用凭证来访问更多的SOAP或其他什么,欢迎来到恐怖的圆顶!如果我找到一个顺利的解决方案,我会用代码向您报告。
答案 3 :(得分:0)
在撰写本文时,NSURLConnection已在OS X 10.11和iOS 9.0中弃用,但我的Apps需要支持OS X 10.7和iOS 6。 因此,现在您必须将NSURLSession用于正在进行的项目,但也支持现已弃用的NSURLConnection类,以支持旧版OS!
我现在会投票支持TenaciousJay解决方案,并在NSURLConnection类实现中使用编译器警告抑制。
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
/* NSURLConnection code here */
#pragma GCC diagnostic pop
通过创建两个基本相同的单独类,您将获得的好处是,当您最终可以放弃对旧版操作系统版本的支持时,您最终可以删除旧的,已弃用的解决方案。
我的代码决定使用一个类或另一个类不会基于某些类属性,而是基于宏的结果:
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
适用于iOS或OS X:
NSString *systemVersion = nil;
if ([[NSProcessInfo processInfo] respondsToSelector:NSSelectorFromString(@"operatingSystemVersion")]) {
NSOperatingSystemVersion operatingSystemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
systemVersion = [NSString stringWithFormat:@"%ld.%ld.%ld", (long)operatingSystemVersion.majorVersion, (long)operatingSystemVersion.minorVersion, (long)operatingSystemVersion.patchVersion];
} else {
SInt32 versionMajor=0, versionMinor=0, versionPatch=0;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Gestalt(gestaltSystemVersionMajor, &versionMajor);
Gestalt(gestaltSystemVersionMinor, &versionMinor);
Gestalt(gestaltSystemVersionBugFix, &versionPatch);
#pragma GCC diagnostic pop
systemVersion = [NSString stringWithFormat:@"%ld.%ld.%ld", (long)versionMajor, (long)versionMinor, (long)versionPatch];
}
NSLog(@"[Line %d] %s OS X Runtime Version: '%@'", __LINE__, __PRETTY_FUNCTION__, systemVersion);