So wandeln Sie ein Objekt in Objective-C

123

Gibt es eine Möglichkeit, Objekte in Objective-C umzuwandeln, ähnlich wie Objekte in VB.NET umgewandelt werden?

Zum Beispiel versuche ich Folgendes zu tun:

// 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]; 

Es wird jedoch ein Compilerfehler angezeigt, da die Eigenschaft 'list' in der SelectionListViewController-Klasse vorhanden ist, jedoch nicht im FieldEditViewController, obwohl SelectionListViewController von FieldEditViewController erbt.

Dies ist sinnvoll, aber gibt es eine Möglichkeit, myEditController in einen SelectionListViewController umzuwandeln, damit ich auf die Eigenschaft 'list' zugreifen kann?

Zum Beispiel würde ich in VB.NET Folgendes tun:

CType(myEditController, SelectionListViewController).list = listOfItems

Danke für die Hilfe!

Billy
quelle

Antworten:

216

Denken Sie daran, dass Objective-C eine Obermenge von C ist, sodass die Typumwandlung wie in C funktioniert:

myEditController = [[SelectionListViewController alloc] init];
((SelectionListViewController *)myEditController).list = listOfItems;
Jim Puls
quelle
21
Oder "Denken Sie daran, Objective-C funktioniert wie Java. Denken Sie daran, Variablen, die auf Obj-C-Objekte verweisen, Sternchen hinzuzufügen."
Dan Rosenstark
1
Gute Antwort. Sie könnten es etwas klarer machen, indem Sie die Besetzung und die Zuordnung in zwei Zeilen aufteilen.
Guido Anselmi
1
Typografie in Objective-C ähnelt weit mehr dem alten C als Java. Java verbirgt das meiste davon vor dem Benutzer, daher Argumente, dass C weiterhin gelehrt werden sollte und nicht Java als Muttersprache.
Schmied
11
((SelectionListViewController *)myEditController).list

Mehr Beispiele:

int i = (int)19.5f; // (precision is lost)
id someObject = [NSMutableArray new]; // you don't need to cast id explicitly
Sijmen Mulder
quelle
7
Im Allgemeinen ist dies richtig; Sie müssen keine ID in Nachrichtenausdrücken umwandeln. Wenn Sie jedoch die Punktsyntax verwenden, um auf Eigenschaften zuzugreifen und diese festzulegen, müssen Sie einen konkreten Typ verwenden, nicht nur id, damit der Compiler weiß, welcher Methodenaufruf tatsächlich generiert werden soll. (Es kann für Eigenschaften mit dem gleichen Namen unterschiedlich sein.)
Chris Hanson
9

Typografie in Objective-C ist einfach wie folgt:

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

Was passiert jedoch, wenn das erste Objekt nicht vorhanden ist UIViewund Sie versuchen, es zu verwenden:

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

Es wird abstürzen. Und es ist leicht, einen solchen Absturz für diesen Fall zu finden, aber was ist, wenn diese Zeilen in verschiedenen Klassen sind und die dritte Zeile in 100 Fällen nur einmal ausgeführt wird. Ich wette, Ihre Kunden finden diesen Absturz, nicht Sie! Eine plausible Lösung ist ein frühzeitiger Absturz wie folgt :

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

Diese Behauptungen sehen nicht sehr gut aus, daher könnten wir sie mit dieser praktischen Kategorie verbessern:

@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

Das ist viel besser:

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

PS Für Sammlungen Typensicherheit Xcode 7 hat eine viel bessere als Typecasting - Generika

Alexander Vasenin
quelle
4

Sicher, die Syntax ist genau die gleiche wie bei C - NewObj* pNew = (NewObj*)oldObj;

In dieser Situation möchten Sie möglicherweise erwägen, diese Liste als Parameter an den Konstruktor anzugeben, z. B.:

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

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

  return self;
}

Dann benutze es so:

myEditController = [[SelectionListViewController alloc] initWith: listOfItems];
Andrew Grant
quelle
0

Das Casting für den Einschluss ist für einen C ++ - Programmierer genauso wichtig wie das Casting für den Ausschluss. Das Typumwandeln ist nicht dasselbe wie bei RTTI, da Sie ein Objekt in einen beliebigen Typ umwandeln können und der resultierende Zeiger nicht Null ist.

stephen
quelle