26

有没有简单的方法来改变 a 的方案NSURL?我确实意识到这NSURL是不可变的。我的目标是将 URL 的方案更改为“https”(如果Security.framework已链接),如果未链接框架则更改为“http”。我确实知道如何检测框架是否已链接。

如果 URL 没有参数(例如“?param1=foo¶m2=bar”),则此代码可以很好地工作:

+(NSURL*)adjustURL:(NSURL*)inURL toSecureConnection:(BOOL)inUseSecure {
    if ( inUseSecure ) {
        return [[[NSURL alloc] initWithScheme:@"https" host:[inURL host] path:[inURL path]] autorelease];
    }
    else {
        return [[[NSURL alloc] initWithScheme:@"http" host:[inURL host] path:[inURL path]] autorelease];
    }    
}

但如果 URL 确实有参数,则[inURL path]删除它们。

除了自己解析 URL 字符串之外还有什么建议(我可以这样做,但我想尝试不这样做)?我做了什么能够将带有 http 或 https 的 URL 传递给此方法。

4

6 回答 6

52

更新的答案

NSURLComponents是你的朋友吗?您可以使用它来将http方案换成https. 唯一需要注意的是NSURLComponents使用 RFC 3986 而NSURL使用较旧的 RFC 1738 和 1808,因此在边缘情况下存在一些行为差异,但您极不可能遇到这些情况(并且NSURLComponents无论如何都有更好的行为)。

NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
components.scheme = inUseSecure ? @"https" : @"http";
return components.URL;

原始答案

为什么不做一些字符串操作呢?

NSString *str = [url absoluteString];
NSInteger colon = [str rangeOfString:@":"].location;
if (colon != NSNotFound) { // wtf how would it be missing
    str = [str substringFromIndex:colon]; // strip off existing scheme
    if (inUseSecure) {
        str = [@"https" stringByAppendingString:str];
    } else {
        str = [@"http" stringByAppendingString:str];
    }
}
return [NSURL URLWithString:str];
于 2013-01-18T05:57:37.957 回答
29

如果您使用的是 iOS 7 及更高版本,则可以使用NSURLComponents,如图所示

NSURLComponents *components = [NSURLComponents new];
components.scheme = @"http";
components.host = @"joris.kluivers.nl";
components.path = @"/blog/2013/10/17/nsurlcomponents/";

NSURL *url = [components URL];
// url now equals:
// http://joris.kluivers.nl/blog/2013/10/17/nsurlcomponents/
于 2014-06-17T18:18:05.310 回答
5

斯威夫特5

extension URL {
    func settingScheme(_ value: String) -> URL {
    let components = NSURLComponents.init(url: self, resolvingAgainstBaseURL: true)
    components?.scheme = value
    return (components?.url!)!
}

}

用法

if nil == url.scheme { url = url.settingScheme("file") }
于 2020-02-28T15:51:07.547 回答
1

也许使用resourceSpecifier会有所帮助:

return [[[NSURL alloc] initWithString:[NSString stringWithFormat:@"https:%@", [inURL resourceSpecifier]]]];
于 2014-07-02T11:17:44.557 回答
0
NSString *newUrlString =  [NSString stringWithFormat:@"https://%@%@", 
                          inURL.host, inURL.path];
if (inURL.query) {
    newUrlString = [newUrlString stringByAppendingFormat:@"?%@", inURL.query];
}
return [NSURL URLWithString:newUrl];

[注意] 为简单起见,删除了与端口和其他字段处理相关的代码。

于 2013-01-18T06:13:15.503 回答
0

我这样做了,resourceSpecifier在 NSURL 中 使用一个变量

迅速

var resourceSpecifier: String? { get } 

目标-C

@property(readonly, copy) NSString *resourceSpecifier Discussion 

此属性包含资源说明符。例如,在 URL http://www.example.com/index.html?key1=value1#jumplink中,资源说明符是 //www.example.com/index.html?key1=value1#jumplink (后面的所有内容冒号)。

  -(NSURL*) URLByReplacingScheme
    {
        NSString *newUrlString = kHttpsScheme;

        if([self.scheme isEqualToString:kEmbeddedScheme])
            newUrlString = kHttpScheme;

        newUrlString = [newUrlString stringByAppendingString:[NSString stringWithFormat:@":%@", self.resourceSpecifier]];

        return [NSURL URLWithString:newUrlString];
    }
于 2014-10-17T10:08:58.843 回答