Two Categories on the same Class with the same met

2019-03-15 10:31发布

问题:

I've noticed that the AFNetworking and SDWebImage categories on UIImageView have the same method name.

AFNetworking:

- (void)setImageWithURL:(NSURL *)url {
    [self setImageWithURL:url placeholderImage:nil];
}

- (void)setImageWithURL:(NSURL *)url 
       placeholderImage:(UIImage *)placeholderImage
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPShouldHandleCookies:NO];
    [request addValue:@"image/*" forHTTPHeaderField:@"Accept"];

    [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
}

- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest 
              placeholderImage:(UIImage *)placeholderImage 
                       success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
                       failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure
{
...
}

and SDWebImage

- (void)setImageWithURL:(NSURL *)url
{
    [self setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
}

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder
{
    [self setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
}

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options
{
    [self setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
}

...

In Xcode when I command-click the SDWebImage method it redirects me to the AFNetworking method and vice-versa.

Which behavior can I expect where? Should I only include the header for the the appropriate category in a class I'd like to use it in? What if a same class needs to use both implementations of the category?

Another related question "What happens if two ObjC categories override the same method?" isn't quite the same as this because both AFNetworking and SDWebImage are adding Categories onto the same class not a subclass. In this case only once class is being used and 2 categories seem to be in conflict.

回答1:

Name collision is indeed something that can happen in Objective-C runtime... Apple advises the use of 'prefix' on methods names.

The expected behaviour : only the last category/method loaded by the runtime will be effective. Which one is it ? Bad question !

My advice : rename !



回答2:

Rename doesn't seem to be the best way to resolve the problem,

just use :

[cell.imageView setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:@"placeholder"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {

}];

from SDWebImage which doesn't exist in AFNetworking



回答3:

For anyone looking to use both SDWebImage and AFNetworking as-is, here's my caveman solution to discourage use of the colliding methods:

https://gist.github.com/sibljon/5957892

It's obviously not future proof, and is prone to breaking if the implementation of these methods changes in AFNetworking or SDWebImage. It's far from an ideal solution. In other words, at your own risk!