Objective-C: a essência da linguagem e seu lugar no desenvolvimento iOS

Autor: IT Sectr Publicado: 2026-02-09 Tempo de leitura: 8 min

Objective-C é uma linguagem de programação com despacho dinâmico de mensagens, criada por Brad Cox na década de 1980. A Apple escolheu Objective-C como linguagem principal para NeXTSTEP e, posteriormente, para o iOS SDK. Programming With Objective-C — uma introdução à sintaxe de mensagens e gerenciamento de memória.

Pontos principais

  • Objective-C — um superconjunto estrito de C com sintaxe de mensagens entre colchetes e um runtime dinâmico
  • Message passing — chamadas de método via [object selector:argument] com busca dinâmica de implementação através de objc_msgSend
  • Categories — mecanismo para adicionar métodos a classes existentes sem herança e sem acesso ao código-fonte
  • Blocks — funções anônimas com closures, predecessor dos closures do Swift
  • ARC vs MRC — contagem automática e manual de referências para gerenciamento de memória

O que é Objective-C?

Objective-C é uma linguagem de programação que estende C com capacidades de programação orientada a objetos no estilo Smalltalk. O código Objective-C é compilado via LLVM ou GCC em código de máquina nativo, mantendo compatibilidade reversa total com C — qualquer código C é válido em Objective-C.

A Apple adquiriu a NeXT (junto com Objective-C) em 1997. A linguagem tornou-se a base do Cocoa e Cocoa Touch — frameworks para macOS e iOS. Desde 2014, a Apple promove Swift como substituto, mas Objective-C continua sendo criticamente importante para projetos legados e alguns frameworks do sistema. De acordo com a Apple (WWDC 2024), cerca de 35% dos aplicativos na App Store ainda contêm código Objective-C.

A principal característica é o runtime dinâmico. Ao contrário do Swift, onde as chamadas de método são resolvidas em tempo de compilação, Objective-C envia mensagens em tempo de execução através da função objc_msgSend. Isso permite sobrescrever métodos em tempo real (method swizzling), adicionar classes dinamicamente e usar forward invocation para seletores inexistentes.

Sintaxe: C + extensão orientada a objetos

Qualquer código C é válido em Objective-C. A extensão orientada a objetos adiciona classes (@interface/@implementation), categorias, protocolos (@protocol) e tipagem dinâmica (id). Os arquivos têm extensões .m (implementação) e .h (cabeçalhos).

Sintaxe de mensagens e despacho dinâmico

A sintaxe de mensagens é a principal diferença entre Objective-C e linguagens similares ao C. Em vez de object.method(argument), usa-se [object method:argument]. Cada mensagem passa pelo objc_msgSend, que busca dinamicamente a implementação do método no runtime.

objective-c
// Sintaxe de mensagens com parâmetros nomeados
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];

// Mensagens aninhadas
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];

// Verificação de tipo via introspection
if ([object isKindOfClass:[UIView class]]) {
    UIView *view = (UIView *)object;
    view.backgroundColor = [UIColor redColor];
}

O despacho dinâmico permite sobrescrever métodos em tempo de execução (method swizzling) — uma técnica poderosa mas perigosa. Por exemplo, frameworks como AFNetworking e Aspects usam swizzling para interceptar chamadas URLSession. A Apple alerta: swizzling pode quebrar frameworks do sistema se usado incorretamente.

Categorias e extensões de classe

As Categorias são uma característica única do Objective-C que permite adicionar métodos a classes existentes (incluindo classes do sistema como NSString e UIView) sem herança e sem acesso ao código-fonte. As categorias são declaradas através de @interface ClassName (CategoryName).

objective-c
// Arquivo UIColor+Hex.h — categoria para UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end

// Arquivo UIColor+Hex.m — implementação
@implementation UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex {
    CGFloat r = ((hex >> 16) & 0xFF) / 255.0;
    CGFloat g = ((hex >> 8) & 0xFF) / 255.0;
    CGFloat b = (hex & 0xFF) / 255.0;
    return [self colorWithRed:r green:g blue:b alpha:1.0];
}
@end

As Extensões (Class Extension) são um tipo especial de categoria declarada em um arquivo .m sem nome: @interface ClassName (). Ao contrário das categorias, as extensões podem adicionar não apenas métodos, mas também ivar (variáveis de instância) e propriedades. Extensões são usadas para ocultar API interna de módulos externos.

Blocos (Blocks) — funções anônimas com closures

Os Blocos são funções anônimas em Objective-C que capturam variáveis do escopo externo. Sintaxe de blocos: ^(int x) { return x * 2; }. Blocos são usados em UIKit para handlers de callback, em Grand Central Dispatch para tarefas assíncronas e em coleções NSArray/NSDictionary para operações funcionais.

objective-c
// Declaração de tipo de bloco
typedef void (^CompletionBlock)(BOOL success, NSError *error);

// Bloco como parâmetro
- (void)fetchDataWithCompletion:(CompletionBlock)completion {
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        BOOL result = [weakSelf processData];
        if (completion) {
            completion(result, nil);
        }
    });
}

O gerenciamento de memória em blocos é criticamente importante. Blocos capturam self com uma referência forte, criando um retain cycle quando usados diretamente. A solução é __weak typeof(self) weakSelf = self, seguida de uma verificação dentro do bloco. Este problema está completamente resolvido em Swift através de capture lists [weak self].

ARC e MRC: gerenciamento de memória

Objective-C evoluiu de MRC (Manual Reference Counting) para ARC (Automatic Reference Counting). Em MRC, o desenvolvedor chamava manualmente retain (incrementar contador), release (decrementar) e autorelease (liberação adiada). Erros nessas chamadas levavam a vazamentos de memória ou crashes devido a ponteiros pendentes.

OperaçãoMRCARC
Criação de objeto[[Object alloc] init][[Object alloc] init]
Retenção de referência[object retain]Automaticamente
Liberação[object release]Automaticamente
Autoliberação[object autorelease]Automaticamente (não necessário)
Referência fraca__weak não existia__weak (nil automático)

ARC foi introduzido no Xcode 4.2 e LLVM 3.0 (2011). O compilador insere automaticamente retain/release em tempo de compilação analisando o tempo de vida dos objetos. ARC não é coleta de lixo — é análise estática com inserções automáticas. ARC do Objective-C é compatível com ARC do Swift: ambos usam o mesmo sistema de contagem de referências no nível do runtime.

Interoperabilidade com Swift via Bridging Header

O uso conjunto de Objective-C e Swift em um mesmo projeto é uma prática comum para projetos legados. A Apple fornece o Bridging Header — um arquivo gerado automaticamente através do qual Swift vê as classes Objective-C, e Objective-C vê as classes Swift que herdam de NSObject.

objective-c
// ProjectName-Bridging-Header.h
// Swift vê estes cabeçalhos automaticamente
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"

A migração de Objective-C para Swift é um processo gradual. Novos arquivos são escritos em Swift, os antigos são gradualmente refatorados. O Bridging Header é gerado automaticamente ao adicionar o primeiro arquivo Swift a um projeto Objective-C. Para visibilidade reversa (ObjC → Swift), o Xcode gera um arquivo <ProjectName>-Swift.h contendo declarações @interface para classes Swift marcadas com @objc.

swift
// Classe Swift visível do Objective-C
@objc class SwiftRouter: NSObject {
    @objc func navigateToProfile(userId: Int) {
        // implementação
    }
}

Limitações: tipos valor do Swift (struct, enum) não são visíveis diretamente do Objective-C — precisam ser encapsulados em uma classe com @objc. Os genéricos do Swift têm acessibilidade limitada do Objective-C. A abordagem recomendada é escrever código novo em Swift e refatorar o código Objective-C existente apenas ao alterar a funcionalidade correspondente.

Runtime e Method Swizzling em Objective-C

A principal vantagem do Objective-C sobre o Swift é o acesso completo ao runtime. O method swizzling, substituindo implementações de métodos em tempo de execução, permite sobrescrever métodos do sistema sem herança. Bibliotecas como Aspects e JRSwizzle usam esta capacidade para AOP (programação orientada a aspectos) — monitoramento, análise e registro.

Forward invocation é outro recurso do runtime: se um objeto não responde a um seletor, o sistema chama forwardInvocation:, permitindo encaminhar a mensagem para outro objeto. Esta é a base do padrão Proxy em Objective-C (NSProxy), usado para inicialização preguiçosa e objetos distribuídos.

A Apple recomenda minimizar o uso de truques de runtime em código novo, preferindo a tipagem estática do Swift. No entanto, em projetos legados, o conhecimento de objc_msgSend, method_exchangeImplementations e objc_getAssociatedObject é necessário para manter a base de código existente.

Propriedades e Key-Value Observing

Objective-C suporta propriedades como açúcar sintático sobre ivar com getters/setters. Os modificadores atomic/nonatomic, strong/weak/copy, readonly/readwrite e assign/retain determinam o comportamento de memória e a segurança de threads. Key-Value Observing (KVO) é um mecanismo para observar mudanças em propriedades, incorporado no runtime: qualquer objeto pode se inscrever em mudanças nas propriedades de outro objeto via addObserver.

Perguntas frequentes

O que é a sintaxe de mensagens em Objective-C?

Uma chamada de método se parece com [object selector:argument]. A mensagem passa pelo objc_msgSend, que encontra dinamicamente a implementação no runtime. Um seletor é um nome de método (@selector(methodName)), não um ponteiro de função. Isso permite swizzling e forward invocation.

Como as Categorias diferem das Extensões?

Uma Categoria (@interface ClassName (Name)) adiciona métodos a qualquer classe (incluindo classes do sistema) sem herança. Uma Extensão (@interface ClassName ()) é declarada em um arquivo .m e pode adicionar propriedades e ivars. Uma Categoria não pode adicionar ivars, mas uma Extensão pode.

O que são Blocos (Blocks) em Objective-C?

Blocos são funções anônimas com sintaxe ^(parâmetros) { corpo }, capturando variáveis do contexto. São análogos a lambdas em C++ e closures em Swift. Requerem __weak para prevenir retain cycles ao capturar self. São usados em UIKit, GCD e Foundation.

Qual é a diferença entre ARC e MRC?

MRC é contagem manual de referências: o programador chama retain, release, autorelease. ARC é automático: o compilador insere retain/release baseado em análise estática. ARC não é GC — objetos são liberados imediatamente quando o contador chega a zero. ARC suporta modificadores __weak e __strong.

Pode-se usar Objective-C e Swift no mesmo projeto?

Sim, através de um Bridging Header. Swift vê Objective-C através deste cabeçalho, Objective-C vê Swift através de <ProjectName>-Swift.h. Classes Swift devem herdar de NSObject e ser marcadas com @objc. Structs e enums do Swift não são diretamente visíveis ao Objective-C.

Resumo

  • Objective-C — um superconjunto estrito de C com runtime dinâmico e sintaxe de mensagens para Cocoa/Cocoa Touch
  • Message passing — chamadas via [object method] com despacho dinâmico através de objc_msgSend e capacidade de swizzling
  • Categorias — adição de métodos a classes existentes sem herança, incluindo classes do sistema da Apple
  • Blocos — funções anônimas com closures, exigindo __weak para prevenir retain cycles
  • ARC vs MRC — evolução de retain/release manual para contagem automática de referências via compilador
  • Bridging Header — mecanismo para Swift e Objective-C trabalharem juntos em um projeto para migração gradual
  • Importância legada — cerca de 35% dos aplicativos da App Store contêm código Objective-C que requer manutenção

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também