2009-11-05 3 views
6

J'écris une application Cocoa, qui utilise des NSURL - j'ai besoin de supprimer la partie fragment de l'URL (la partie #BLAH).Suppression du fragment d'URL de NSURL

exemple: http://example.com/#blah devrait se terminer comme http://example.com/

J'ai trouvé un peu de code dans WebCore qui semble le faire en utilisant la fonctionnalité de CFURL, mais il ne trouve jamais la partie de fragment dans l'URL. Je l'ai encapsulé dans une catégorie d'extension:

-(NSURL *)urlByRemovingComponent:(CFURLComponentType)component { 
    CFRange fragRg = CFURLGetByteRangeForComponent((CFURLRef)self, component, NULL); 
    // Check to see if a fragment exists before decomposing the URL. 
    if (fragRg.location == kCFNotFound) 
     return self; 

    UInt8 *urlBytes, buffer[2048]; 
    CFIndex numBytes = CFURLGetBytes((CFURLRef)self, buffer, 2048); 
    if (numBytes == -1) { 
     numBytes = CFURLGetBytes((CFURLRef)self, NULL, 0); 
     urlBytes = (UInt8 *)(malloc(numBytes)); 
     CFURLGetBytes((CFURLRef)self, urlBytes, numBytes); 
    } else 
     urlBytes = buffer; 

    NSURL *result = (NSURL *)CFMakeCollectable(CFURLCreateWithBytes(NULL, urlBytes, fragRg.location - 1, kCFStringEncodingUTF8, NULL)); 
    if (!result) 
     result = (NSURL *)CFMakeCollectable(CFURLCreateWithBytes(NULL, urlBytes, fragRg.location - 1, kCFStringEncodingISOLatin1, NULL)); 

    if (urlBytes != buffer) free(urlBytes); 
    return result ? [result autorelease] : self; 
} 
-(NSURL *)urlByRemovingFragment { 
    return [self urlByRemovingComponent:kCFURLComponentFragment]; 
} 

Il est utilisé en tant que tel:

NSURL *newUrl = [[NSURL URLWithString:@"http://example.com/#blah"] urlByRemovingFragment]; 

malheureusement, newUrl finit par être "http://example.com/#blah" parce que la première ligne urlByRemovingComponent retourne toujours kCFNotFound

Je suis perplexe. Y a-t-il une meilleure façon d'y parvenir?

Code de travail, grâce à Nall

-(NSURL *)urlByRemovingFragment { 
    NSString *urlString = [self absoluteString]; 
    // Find that last component in the string from the end to make sure to get the last one 
    NSRange fragmentRange = [urlString rangeOfString:@"#" options:NSBackwardsSearch]; 
    if (fragmentRange.location != NSNotFound) { 
     // Chop the fragment. 
     NSString* newURLString = [urlString substringToIndex:fragmentRange.location]; 
     return [NSURL URLWithString:newURLString]; 
    } else { 
     return self; 
    } 
} 

Répondre

7

Que diriez-vous ceci:

NSString* s = @"http://www.somewhere.org/foo/bar.html/#label"; 
NSURL* u = [NSURL URLWithString:s]; 

// Get the last path component from the URL. This doesn't include 
// any fragment. 
NSString* lastComponent = [u lastPathComponent]; 

// Find that last component in the string from the end to make sure 
// to get the last one 
NSRange fragmentRange = [s rangeOfString:lastComponent 
           options:NSBackwardsSearch]; 

// Chop the fragment. 
NSString* newURLString = [s substringToIndex:fragmentRange.location + fragmentRange.length]; 

NSLog(@"%@", s); 
NSLog(@"%@", newURLString); 
+0

près. apparemment lastPathComponent retourne le fragment et est une méthode NSString. J'ai posté le code final à la question. – pixel

+0

NSURL dispose également d'un composant lastPathComponent qui ne renvoie pas le fragment, mais il est 10.6+ http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/Reference/Reference.html# // apple_ref/doc/uid/20000301-SW22 – nall

+0

Quel est le problème avec url.fragment? – Sam

1

Ceci est tout à fait une vieille question, et il a déjà répondu, mais pour une autre option simple cette est comment je l'ai fait:

NSString* urlAsString = [myURL absoluteString]; 
NSArray* components = [urlAsString componentsSeparatedByString:@"#"]; 
NSURL* myURLminusFragment = [NSURL URLWithString: components[0]]; 

s'il y a est aucun fragment, urlMinusFragment sera le même que myURL

+0

Belle solution simple, mais vous pouvez passer à l'utilisation de components.firstObject si votre version iOS/OSX le supporte. C'est plus sûr que d'accéder explicitement aux composants [0], même si componentsSeparatedByString: * devrait toujours retourner un tableau non vide. –

0

Swift 3.0

cela supprimera le fragment

if let fragment = url.fragment{ 
    url = URL(string: url.absoluteString.replacingOccurrences(of: "#\(fragment)", with: "")! 
}