Objective-C'de bir nesne nasıl yapılır


123

Nesnelerin nesnel-c'de dönüştürülmesinin, nesnelerin VB.NET'te olduğu gibi bir yolu var mı?

Örneğin, şunları yapmaya çalışıyorum:

// create the view controller for the selected item
FieldEditViewController *myEditController;
switch (selectedItemTypeID) {
    case 3:
        myEditController = [[SelectionListViewController alloc] init];
        myEditController.list = listOfItems;
        break;
    case 4:
        // set myEditController to a diff view controller
        break;
}

// load the view
[self.navigationController pushViewController:myEditController animated:YES];
[myEditController release]; 

Bununla birlikte, 'list' özelliği SelectionListViewController sınıfında mevcut olduğu, ancak SelectionListViewController FieldEditViewController'dan devraldığı halde FieldEditViewController'da olmadığı için bir derleyici hatası alıyorum.

Bu mantıklı, ancak myEditController'ı bir SelectionListViewController'a çevirmenin bir yolu var mı, böylece 'list' özelliğine erişebilirim?

Örneğin VB.NET'te şunu yapardım:

CType(myEditController, SelectionListViewController).list = listOfItems

Yardım için teşekkürler!

Yanıtlar:


216

Unutmayın, Objective-C, C'nin bir üst kümesidir, bu nedenle tipleme, C'de olduğu gibi çalışır:

myEditController = [[SelectionListViewController alloc] init];
((SelectionListViewController *)myEditController).list = listOfItems;

21
Veya "Unutmayın, Objective-C Java gibi çalışır, Obj-C nesnelerine işaret eden değişkenlere yıldız işareti eklemeyi unutmayın."
Dan Rosenstark

1
Mükemmel cevap. Oyuncu kadrosunu ve atamayı iki satıra bölerek biraz daha net hale getirebilirsiniz.
Guido Anselmi

1
Objective-C'de Typecasting, Java'dan çok eski C'ye benziyor. Java bunun çoğunu kullanıcıdan gizler, bu nedenle ilk dil olarak Java yerine C'nin öğretilmesi gerektiği argümanları.
csmith

11
((SelectionListViewController *)myEditController).list

Daha fazla örnek:

int i = (int)19.5f; // (precision is lost)
id someObject = [NSMutableArray new]; // you don't need to cast id explicitly

7
Genel olarak bu doğrudur; mesaj ifadelerinde id yazmanıza gerek yoktur. Ancak özelliklere erişmek ve ayarlamak için nokta sözdizimini kullanırken, yalnızca kimlik değil, somut bir tür kullanmanız gerekir, böylece derleyici gerçekte hangi yöntem çağrısını üreteceğini bilir. (Aynı ada sahip mülkler için farklılık gösterebilir.)
Chris Hanson

9

Objective-C'de yazı yazmak şu kadar kolaydır:

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

Ancak, ilk nesne değilse UIViewve onu kullanmaya çalışırsanız ne olur :

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

Çarpacak. Ve bu durum için böyle bir çökme bulmak kolay, ama ya bu satırlar farklı sınıflardaysa ve üçüncü satır 100 durumda yalnızca bir kez çalıştırılırsa. Bahse girerim müşterileriniz bu kazayı bulur, siz değil! Akla yatkın bir çözüm, şu şekilde erken çökmek :

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

Bu iddialar pek hoş görünmüyor, bu yüzden onları bu kullanışlı kategori ile geliştirebiliriz:

@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

Bu çok daha iyi:

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

PS Koleksiyonlar için güvenlik türü Xcode 7, yazımdan çok daha iyi - jenerikler


4

Elbette, sözdizimi C ile tamamen aynıdır - NewObj* pNew = (NewObj*)oldObj;

Bu durumda, bu listeyi kurucuya bir parametre olarak sağlamayı düşünebilirsiniz, örneğin:

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

  if ( self ) {
    [self setList: anItemList];
  }

  return self;
}

O zaman şu şekilde kullanın:

myEditController = [[SelectionListViewController alloc] initWith: listOfItems];

0

Dahil etme için döküm, bir C ++ programcısı için dışlama için döküm kadar önemlidir. Tür atama, bir nesneyi herhangi bir türe dönüştürebileceğiniz ve sonuçta ortaya çıkan işaretçi sıfır olmayacağı için RTTI ile aynı değildir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.