我需要连接到我的服务器以获取一些JSON
数据,并且我必须同时支持iOS 6
和iOS 7
.
我应该创建两个类吗?一个带有NSURLSession
foriOS 7
一个带有NSURLConnection
for iOS 6
?还是我应该同时使用NSURLConnection
它们?
我需要连接到我的服务器以获取一些JSON
数据,并且我必须同时支持iOS 6
和iOS 7
.
我应该创建两个类吗?一个带有NSURLSession
foriOS 7
一个带有NSURLConnection
for iOS 6
?还是我应该同时使用NSURLConnection
它们?
通过创建两个本质上做同样事情的独立类,你会获得什么好处?如果您不能使用 NSURLSession,因为它仅在 iOS 7 中受支持,并且您可以使用 NSURLConnection 获得相同的功能,这两者都适用,那么只需使用 NSURLConnection。您将需要维护的代码更少。
好问题。事实上,我有同样的问题并对其进行了相当多的研究,我认为这是使用协议(也称为其他语言的接口)的好地方。这是基于著名的“Gang of Four” Patterns Book 中的引用“Program to an interface, not an implementation”。我认为最好尝试为未来编写代码,所以如果他们决定弃用某些东西,我永远不会受到打击(这里不是这种情况,但你永远不知道)。
不要编写类,而是编写一个协议来定义您要使用的方法,然后创建 2 个不同的类来实现这些方法。在您的应用程序中,您将创建一个指针,该指针可以指向实现所有协议方法的任何类,然后每个实现类都可以使用他们想要实现的任何框架/库/其他代码。
例如,您可以像这样创建服务器协议:
// 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
如果你必须使用NSURLCredentialPersistenceForSession
如果你必须进入 Windows 身份验证网络......那么使用NSURLConnection
会给你带来多个问题。我现在正在经历痛苦并得出结论,我需要两者都支持 iOS 7。基本上,如果您使用NSURLConnection
and willSendRequestForAuthenticationChallenge
,您会发现在 iOS 7 中,您的会话将以自己的想法结束(似乎是 30 秒的思维跨度)。因此,如果您必须持有凭证才能访问更多 SOAP 或其他任何东西,欢迎来到恐怖穹顶!如果我找到一个顺利的解决方案,我会用代码向你报告。
在撰写本文时,NSURLConnection 已在 OS X 10.11 和 iOS 9.0 中弃用,但我的应用程序需要支持 OS X 10.7 和 iOS 6。所以现在您必须将 NSURLSession 用于正在进行的项目,但也支持现在已弃用的 NSURLConnection 类以支持旧版操作系统发布!
这些天,我会投票支持在 NSURLConnection 类实现周围使用编译器警告抑制的 TenaciousJay 解决方案。
#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);