How to Use Objective-C Categories

2019-04-05 18:17发布

问题:

When you implement a category of a class in a file, will all the instances of that class be of the category by default?

I'm new to Objective-C and I'm trying to make my uneditable UITextView non-selectable. I came across this answer using a category: https://stackoverflow.com/a/8013538/1533240

Which has the following solution:

@implementation UITextView (DisableCopyPaste)

-(BOOL) canBecomeFirstResponder
{
    return NO;
}
@end

I added the snippet to my code, but it doesn't seem to be working in that I can still select the text. My declaration of the UITextView is the usual:

titleLabel = [[UITextView alloc] initWithFrame:frame];

I tried changing the declaration to [DisableCopyPaste alloc] but that didn't seem to work.. haha.

Thanks!

回答1:

You misunderstand the point of categories. Categories add methods to an existing class. They must never be used to override existing methods. Doing so is undefined behavior (technically only undefined in one case, but you can't predict that case, so you must assume it applies).

If you need to override methods, you must subclass, not use categories. See the top answer to the question you linked.



回答2:

When you implement a category of a class in a file, will all the instances of that class be of the category by default?

Yes. If you create a category, the methods in that category are added to the class. For example, if you create a category on NSString that returns the checksum of a string, you can use that method on any instance of NSString.

I added the snippet to my code, but it doesn't seem to be working in that I can still select the text.

Don't use categories to override existing methods.

For one thing, it's bad form. You're effectively changing the behavior of the class in a way that the author didn't expect. For another thing, you can't count on the override to work -- the order in which categories are added to classes isn't defined, so you never know if some other category might come along and replace the method that you tried to replace. It's simply not reliable. If you need to override methods, create a subclass instead.



回答3:

What you need to do is to declare category in header .h file:

such as:

@interface UITextView (DisableCopyPaste)
-(BOOL) methodName
@end

then in .m define as

@implementation UITextView (DisableCopyPaste)
-(BOOL) methodName
{
    return NO;
}
@end

You can do two thing,

  1. You can write it in a class and import that to all classes you need this functionality.
  2. Or write these lines eachs .h and .m (respectively) you need it.