How to cast an object in Objective-C

后端 未结 5 759
死守一世寂寞
死守一世寂寞 2020-12-04 09:14

Is there a way to cast objects in objective-c much like the way objects are cast in VB.NET?

For example, I am trying to do the following:

// create t         


        
相关标签:
5条回答
  • 2020-12-04 09:37

    Typecasting in Objective-C is easy as:

    NSArray *threeViews = @[[UIView new], [UIView new], [UIView new]];
    UIView *firstView = (UIView *)threeViews[0];
    

    However, what happens if first object is not UIView and you try to use it:

    NSArray *threeViews = @[[NSNumber new], [UIView new], [UIView new]];
    UIView *firstView = (UIView *)threeViews[0];
    CGRect firstViewFrame = firstView.frame; // CRASH!
    

    It will crash. And it's easy to find such crash for this case, but what if those lines are in different classes and the third line is executed only once in 100 cases. I bet your customers find this crash, not you! A plausible solution is to crash early, like this:

    UIView *firstView = (UIView *)threeViews[0];
    NSAssert([firstView isKindOfClass:[UIView class]], @"firstView is not UIView");
    

    Those assertions doesn't look very nice, so we could improve them with this handy category:

    @interface NSObject (TypecastWithAssertion)
    + (instancetype)typecastWithAssertion:(id)object;
    @end
    
    
    @implementation NSObject (TypecastWithAssertion)
    
    + (instancetype)typecastWithAssertion:(id)object {
        if (object != nil)
            NSAssert([object isKindOfClass:[self class]], @"Object %@ is not kind of class %@", object, NSStringFromClass([self class]));
        return object;
    }
    
    @end
    

    This is much better:

    UIView *firstView = [UIView typecastWithAssertion:[threeViews[0]];
    

    P.S. For collections type safety Xcode 7 have a much better than typecasting - generics

    0 讨论(0)
  • 2020-12-04 09:42

    Remember, Objective-C is a superset of C, so typecasting works as it does in C:

    myEditController = [[SelectionListViewController alloc] init];
    ((SelectionListViewController *)myEditController).list = listOfItems;
    
    0 讨论(0)
  • 2020-12-04 09:42

    Casting for inclusion is just as important as casting for exclusion for a C++ programmer. Type casting is not the same as with RTTI in the sense that you can cast an object to any type and the resulting pointer will not be nil.

    0 讨论(0)
  • 2020-12-04 09:45

    Sure, the syntax is exactly the same as C - NewObj* pNew = (NewObj*)oldObj;

    In this situation you may wish to consider supplying this list as a parameter to the constructor, something like:

    // SelectionListViewController
    -(id) initWith:(SomeListClass*)anItemList
    {
      self = [super init];
    
      if ( self ) {
        [self setList: anItemList];
      }
    
      return self;
    }
    

    Then use it like this:

    myEditController = [[SelectionListViewController alloc] initWith: listOfItems];
    
    0 讨论(0)
  • 2020-12-04 09:50
    ((SelectionListViewController *)myEditController).list
    

    More examples:

    int i = (int)19.5f; // (precision is lost)
    id someObject = [NSMutableArray new]; // you don't need to cast id explicitly
    
    0 讨论(0)
提交回复
热议问题