Como converter um objeto no Objective-C

123

Existe uma maneira de converter objetos no objetivo-c, assim como os objetos são convertidos no VB.NET?

Por exemplo, estou tentando fazer o seguinte:

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

No entanto, estou recebendo um erro de compilador, pois a propriedade 'list' existe na classe SelectionListViewController, mas não no FieldEditViewController, embora o SelectionListViewController seja herdado do FieldEditViewController.

Isso faz sentido, mas existe uma maneira de converter myEditController em um SelectionListViewController para que eu possa acessar a propriedade 'list'?

Por exemplo, no VB.NET, eu faria:

CType(myEditController, SelectionListViewController).list = listOfItems

Obrigado pela ajuda!

Billy
fonte

Respostas:

216

Lembre-se de que o Objective-C é um superconjunto de C; portanto, a conversão de texto funciona como em C:

myEditController = [[SelectionListViewController alloc] init];
((SelectionListViewController *)myEditController).list = listOfItems;
Jim Puls
fonte
21
Ou "Lembre-se, o Objective-C funciona como Java, lembre-se de adicionar asteriscos às variáveis ​​que apontam para objetos Obj-C".
Dan Rosenstark
1
Ótima resposta. Você pode deixar um pouco mais claro dividindo o elenco e a tarefa em duas linhas.
Guido Anselmi
1
A conversão de texto no Objective-C é muito mais parecida com o antigo C do que com o Java. Java oculta a maior parte disso do usuário, daí os argumentos de que C ainda deve ser ensinado em vez de Java como primeira linguagem.
precisa
11
((SelectionListViewController *)myEditController).list

Mais exemplos:

int i = (int)19.5f; // (precision is lost)
id someObject = [NSMutableArray new]; // you don't need to cast id explicitly
Sijmen Mulder
fonte
7
Em geral, isso está correto; você não precisa converter o ID nas expressões da mensagem. Porém, ao usar a sintaxe de ponto para acessar e definir propriedades, você deve usar um tipo concreto, não apenas um ID, para que o compilador saiba qual chamada de método realmente gerar. (Ele pode diferir para propriedades com o mesmo nome.)
Chris Hanson
9

A tipografia no Objective-C é fácil como:

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

No entanto, o que acontece se o primeiro objeto não estiver UIViewe você tentar usá-lo:

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

Vai falhar. E é fácil encontrar essa falha neste caso, mas e se essas linhas estiverem em classes diferentes e a terceira linha for executada apenas uma vez em 100 casos. Aposto que seus clientes encontram essa falha, não você! Uma solução plausível é travar mais cedo , assim:

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

Essas afirmações não parecem muito boas, então podemos melhorá-las com esta categoria útil:

@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

Isto é muito melhor:

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

PS Para coleções, digite security Xcode 7 tem muito mais do que typecasting - genéricos

Alexander Vasenin
fonte
4

Claro, a sintaxe é exatamente a mesma que C - NewObj* pNew = (NewObj*)oldObj;

Nesta situação, você pode considerar o fornecimento dessa lista como um parâmetro para o construtor, algo como:

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

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

  return self;
}

Em seguida, use-o assim:

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

A conversão para inclusão é tão importante quanto a exclusão para um programador de C ++. A conversão de tipo não é igual à RTTI, no sentido de que você pode converter um objeto em qualquer tipo e o ponteiro resultante não será nulo.

Stephen
fonte