【问题标题】:parse a NSURL mailto解析一个 NSURL mailto
【发布时间】:2016-05-20 04:46:41
【问题描述】:

如何解析 mailto 请求?

'mailto:someone@example.com?cc=someone_else@example.com&subject=This%20is%20the%20subject&body=This%20is%20the%20body'

我想从这个 NSURL 中提取收件人、主题和正文。我该怎么办?

谢谢

【问题讨论】:

    标签: iphone ios parsing


    【解决方案1】:

    这里有一些代码可以解析任何 URL 并返回一个字典,其中包含参数和字典中的相关对象。它也适用于mailto URL。
    请注意:此代码假定您使用的是 ARC

    @interface NSString (URLDecoding)  
    
    - (NSString *) URLDecodedString;
    
    @end
    

    @implementation NSString (URLDecoding)
    
    - (NSString *) URLDecodedString {
        NSString *result = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, (__bridge CFStringRef)self, CFSTR(""), kCFStringEncodingUTF8);
        return result;
    }
    
    @end
    

    - (NSDictionary *) parameterDictionaryFromURL:(NSURL *)url {
        NSMutableDictionary *parameterDictionary = [[NSMutableDictionary alloc] init];
        if ([[url scheme] isEqualToString:@"mailto"]) {
            NSString *mailtoParameterString = [[url absoluteString] substringFromIndex:[@"mailto:" length]];
            NSUInteger questionMarkLocation = [mailtoParameterString rangeOfString:@"?"].location;
            [parameterDictionary setObject:[mailtoParameterString substringToIndex:questionMarkLocation] forKey:@"recipient"];
    
            if (questionMarkLocation != NSNotFound) {
                NSString *parameterString = [mailtoParameterString substringFromIndex:questionMarkLocation + 1];
                NSArray *keyValuePairs = [parameterString componentsSeparatedByString:@"&"];
                for (NSString *queryString in keyValuePairs) {
                    NSArray *keyValuePair = [queryString componentsSeparatedByString:@"="];
                    if (keyValuePair.count == 2)
                        [parameterDictionary setObject:[[keyValuePair objectAtIndex:1] URLDecodedString] forKey:[[keyValuePair objectAtIndex:0] URLDecodedString]];
                }
            }
        }
        else {
            NSString *parameterString = [url parameterString];
            NSArray *keyValuePairs = [parameterString componentsSeparatedByString:@"&"];
            for (NSString *queryString in keyValuePairs) {
                NSArray *keyValuePair = [queryString componentsSeparatedByString:@"="];
                if (keyValuePair.count == 2)
                    [parameterDictionary setObject:[[keyValuePair objectAtIndex:1] URLDecodedString] forKey:[[keyValuePair objectAtIndex:0] URLDecodedString]];
            }
        }
    
        return [parameterDictionary copy];
    }
    

    这是你如何使用它的:

    NSURL *mailtoURL = [NSURL URLWithString:@"mailto:foo@example.com?cc=bar@example.com&subject=Greetings%20from%20Cupertino!&body=Wish%20you%20were%20here!"];
    NSDictionary *parameterDictionary = [self parameterDictionaryFromURL:mailtoURL];
    
    NSString *recipient = [parameterDictionary objectForKey:@"recipient"];
    NSString *subject = [parameterDictionary objectForKey:@"subject"];
    NSString *body = [parameterDictionary objectForKey:@"body"];
    

    编辑:
    我更新了代码以使用任何 URL,并且收件人现在在 mailto URL 的字典中。

    【讨论】:

    • 非常优雅的解决方案。我喜欢抽象。
    • 如何附加文本文件?
    • 这是为了获取查询的内容,而不是附加任何东西。
    • 这没有得到收件人
    • 正如 user102008 指出的那样,收件人实际上并不包含在 URL 的查询部分中。
    【解决方案2】:

    我会像这样从中提取电子邮件:

    NSString * mailToString = @"'mailto:someone@example.com?cc=someone_else@example.com&subject=This%20is%20the%20subject&body=This%20is%20the%20body'";
    
    NSArray *tempArray = [mailToString componentsSeparatedByString:@"?"];
    
    //get email address from array
    NSString * emailString = [[tempArray objectAtIndex:0]description];
    
    //clean up string
    emailString = [emailString stringByReplacingOccurrencesOfString:@"'mailto:" withString:@""]; 
    
    //and here is your email string
    NSLog(@"%@",emailString);
    

    【讨论】:

    • 使用-description 是非常糟糕的做法。
    • 为什么使用-description 是非常糟糕的做法?
    【解决方案3】:

    从 iOS 7 开始,这可以通过 NSURLComponents 轻松实现。您可以使用以下命令创建该对象:

    if let components = NSURLComponents(URL: url, resolvingAgainstBaseURL:false) { ...
    

    然后就可以让接收者访问NSURLComponents的path属性了;以及带有 queryItems 属性的参数。例如,如果我们想要获取主题,这样的事情就可以完成我们的工作

    let queryItems = components.queryItems as? [NSURLQueryItem]
    let subject = queryItems?.filter({$0.name == "subject"}).first?.value
    

    【讨论】:

    • queryItemsNSURLQueryItem 类本身仅在 iOS 8.0 之后才可用。
    【解决方案4】:

    仅用于 mailto 的 NSURL 类别:此方法还修复了上面 Fabian 的答案中的崩溃错误,当时 mailto: url 不包含?。它也不需要 URLDecodedString 类别方法。

    @implementation NSURL (Additions)
    
    - (NSDictionary *) parameterDictionaryForMailTo {
        NSMutableDictionary *parameterDictionary = [[NSMutableDictionary alloc] init];
        NSString *mailtoParameterString = [[self absoluteString] substringFromIndex:[@"mailto:" length]];
        NSUInteger questionMarkLocation = [mailtoParameterString rangeOfString:@"?"].location;
        if (questionMarkLocation != NSNotFound) {
            [parameterDictionary setObject:[mailtoParameterString substringToIndex:questionMarkLocation] forKey:@"recipient"];
            NSString *parameterString = [mailtoParameterString substringFromIndex:questionMarkLocation + 1];
            NSArray *keyValuePairs = [parameterString componentsSeparatedByString:@"&"];
            for (NSString *queryString in keyValuePairs) {
                NSArray *keyValuePair = [queryString componentsSeparatedByString:@"="];
                if (keyValuePair.count == 2)
                    [parameterDictionary setObject:[[keyValuePair objectAtIndex:1] stringByRemovingPercentEncoding] forKey:[[keyValuePair objectAtIndex:0] stringByRemovingPercentEncoding]];
            }
        }
        else {
            [parameterDictionary setObject:mailtoParameterString forKey:@"recipient"];
        }
    
        return [parameterDictionary copy];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-04
      • 2011-04-29
      • 1970-01-01
      • 2019-06-21
      • 1970-01-01
      • 2013-01-16
      • 2010-12-30
      相关资源
      最近更新 更多