【问题标题】:Is it possible to just get the domain and TLD from an NSURL? No www or anything else?是否可以从 NSURL 获取域和 TLD?没有www或其他什么?
【发布时间】:2013-12-06 18:04:24
【问题描述】:

假设我有http://www.youtube.comhttp://youtube.comhttps://www1.youtube.com/moretext。我将如何编写检查以查看所有这些 URL 是否都来自 youtube.com?

我尝试了url.host,它似乎保留了www. 之类的东西,这不是我想要的。

我基本上只想说:

if ([url isFromWebsite:@"youtube.com"]) {
    // Do things.
}

这可能吗?

【问题讨论】:

  • url.host,调用-[NSString componentsSeparatedByString:],查看数组的最后两个元素。
  • @bdesham 你应该把这个作为答案。
  • @JesseRusak 即使您的代码在 youtube.commydomain.com 上也会失败!此外,它将进行更多的字符串操作,首先是提取 url.host,然后是数组,然后实际检查 2 个元素,这些元素太难编码最后两个。
  • @GauravGoyal 我不确定你的意思是“我的代码”,但我认为几个字符串操作可能非常无关紧要,除非这个函数被调用数千次。跨度>
  • @bdesham YouTube.co.uk

标签: ios objective-c nsurl


【解决方案1】:

这是NSURL 上的一个未经测试的类别,它将提供您想要的方法。

@implementation NSURL (IsFromWebsite)

- (BOOL) isFromWebsite:(NSString *)domain
{
    NSArray *selfHostComponents = [[self host] componentsSeparatedByString:@"."];
    NSArray *targetHostComponents = [domain componentsSeparatedByString:@"."];

    NSInteger selfComponentsCount = [selfHostComponents count];
    NSInteger targetComponentsCount = [targetHostComponents count];
    NSInteger offset = selfComponentsCount - targetComponentsCount;

    if (offset < 0)
        return NO;

    for (NSUInteger i = offset; i < selfComponentsCount; i++) {
        if (![selfHostComponents[i] isEqualToString:targetHostComponents[i - offset]])
            return NO;
    }

    return YES;
}

@end

编辑:按照 Jesse Rusak 的建议,另一种(也未经测试的)方法来做同样的事情:

@implementation NSURL (IsFromWebsite)

- (BOOL) isFromWebsite:(NSString *)domain
{
    NSArray *selfComponents = [[self host] componentsSeparatedByString:@"."];
    NSArray *targetComponents = [domain componentsSeparatedByString:@"."];
    NSInteger sizeDifference = [selfComponents count] - [targetComponents count];

    if (sizeDifference < 0)
        return NO;

    return [[selfComponents subarrayWithRange:NSMakeRange(sizeDifference, [targetComponents count])]
            isEqualToArray:targetComponents];
}

@end

【讨论】:

  • 从 selfHostComponents 获取 targetComponentsCount 大小的子数组并检查 isEqual: 与 targetHostComponents 会更容易。
  • @JesseRusak 好主意。我继续在我的答案中添加了这样一个版本。
  • 这看起来很可靠。一个想法:您可能需要考虑使比较不区分大小写。
【解决方案2】:

NSURL——实际上是一般的 URL——不太关心 URL 主机部分的实际内容;由客户来解释和处理。因此,您可以自行处理这些信息。

这是一个不错的简单方法:

- (BOOL)isYouTubeURL:(NSURL *)url;
{
    NSString *host = url.host;

    // Test the simple case of the domain being a direct match
    // Case-insensitive, as domain names are defined to be
    if ([host caseInsensitiveCompare:@"youtube.com"] == NSOrderedSame) {
        return YES;
    }

    // And now the more complex case of a subdomain
    // Look back from just the end of the string
    NSStringCompareOptions options = NSBackwardsSearch|NSAnchoredSearch|NSCaseInsensitiveSearch;
    NSRange range = [host rangeOfString:@".youtube.com" options:options];
    return (range.location != NSNotFound);
}

如果需要,您可以通过仅搜索域来优化这一点,然后查看前一个字符是否不存在(上面的案例#1),或者前面有一个.(上面的案例#2)。更进一步,CFURL 有 API 可以告诉您主机在原始字符串中的位置,并且可以直接搜索。

【讨论】:

    【解决方案3】:

    如果有人需要bdesham 在 Swift 3 中的回答。

    extension URL {
        func isFromWebsite(domain: String) -> Bool {
            var selfHostComponents = self.host!.components(separatedBy: ".")
            var targetHostComponents = domain.components(separatedBy: ".")
            let selfComponentsCount = selfHostComponents.count
            let targetComponentsCount = targetHostComponents.count
            let offset = selfComponentsCount - targetComponentsCount
            if offset < 0 {
                return false
            }
            for i in offset..<selfComponentsCount {
                if !(selfHostComponents[i] == targetHostComponents[i - offset]) {
                    return false
                }
            }
            return true
        }
    }
    

    【讨论】:

      【解决方案4】:

      您可以使用以下代码作为 NSString 类别

      - (BOOL)isFromWebsite: (NSString *)website {
           NSRange searchResult = [self rangeOfString:website];
           if (searchResult.location != NSNotFound) {
               return YES;
           }
           return NO;
      }
      

      如果这是一个用例,您也可以使用不区分大小写的比较。 希望这会有所帮助。

      【讨论】:

      • 这也将匹配youtube.commydomain.com,这可能是不希望的。
      • 据我所知,这是现实世界场景中最优化的解决方案。
      • -1 因为在比较域名的情况下,像这样草率的“优化”会导致巨大的安全漏洞。
      • 没错,这可能会给我的应用程序带来很大的安全问题,因此非常危险。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-17
      • 2013-03-31
      相关资源
      最近更新 更多