Reading and Saving an Array of Structures with Objective-C

Hi,

Today I’m reading a good book called Pragmatic Programmer, and in this book there are some challenges. One is about how to save a simple “data base” record using binary data in you preferred programming language, so I decided do this using Objective>-C. The challenge is very simple, it involves to write a name and a phone number of your contacts.

For me to acomplish this task,  I need to create a structure comprised of two fields (name and phone). See code bellow:

typedef struct
{
  char name[255];
  char phone[11];
} User;

Now, you must create a vector of User and populate it.

User users[2] = {
  {"Sergio Vieira>\0", "(00)123456\0"},
  {"Alexandra Vieira\0", "(01)987654\0"}
};

After that, you must to create a  NSData object which is typically used for data storage.

NSData *data = [NSData dataWithBytes:&users length:sizeof(users)];

The method dataWithBytes:lenght creates and returns a data object containing a given number of bytes copied from a given buffer (Reference).

To write the contact list I decided to use a NSUserDefaults class which provide us a interface to easily save data in the system.

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

[userDefaults setObject:data forKey:@"users"];
[userDefaults synchronize];

The methods setObject:forKey: sets the value of the specified default key in the standard application domain (Reference)

With this, all data is saved. To read the sctructure you must to load NSData using NSUserDefaults.

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSData *data = [userDefaults objectForKey:@"users"];
User records[2];

[data getBytes:&records length:sizeof(records)];

and now you can show all stored values.

for (NSUInteger i = 0; i < 2; i++)
{
  printf("Name:%s Phone:%s\n", records[i].name, records[i].phone);
}

That’s all. 🙂

Aprendendo Objective-C – Parte 5

Projetando uma Interface de Classe

A sintaxe do Objective-C para criar uma classe é muito simples. Ela geralmente vem em duas partes.
A interface de classe geralmente vem armazenada no arquivo ClassName.h, e nela podem ser definidas variáveis de instância e métodos públicos.A implementação da classe fica no arquivo ClassName.m onde ficam o código destes métodos. Lá também podem existir métodos privados que não podem ser acessados pelos clientes da classe.Abaixo vemos como uma interface se parece. A classe é chamada Photo, portanto o nome do arquivo deve ser Photo.h:
#import <Cocoa/Cocoa.h> 

@interface Photo : NSObject { 
NSString* caption; 
NSString* photographer; 
} 
@end
Primeiro, importamos a biblioteca Cocoa.h, para podermos acessar todas as classe básicas para o aplicativo Cocoa. A diretiva #import automaticamente impede que a bliblioteca seja incluída várias vezes.

A palavra reservada @interface indica o início da delcaração da classe Photo. O dois pontos especifica a superclasse, neste caso NSObject.

Entre as chaves, existem duas variáveis de instância: caption e photographer. Ambos do tipo NSString, mas elas podem ser qualquer tipo de objeto, incluindo id.

Finalmente, o símbolo @end finaliza a declaração da classe.

Adicionar Métodos

Vamos adicionar alguns getters para as variáveis de instância.
#import <Cocoa/Cocoa.h> 
@interface Photo : NSObject { 
  NSString* caption; 
  NSString* photographer; 
} 
  - caption; 
  - photographer;
@end

Lembre-se, os métodos do Objective-C tipicamente dispensão o prefixo “get”. Um traço simples antes do nome do método significa que ele é um método de instância. Já um + antes do nome do método significa que ele é um método de classe.

Por padrão, o compilador assume que o retorno do método é um objeto id, e que todos os valores de entrada são do tipo id. O Código acima é tecnicamente correto, mas não é comum. Vamos adicionar os tipos específicos para os valores de retorno.

#import <Cocoa/Cocoa.h> 

@interface Photo : NSObject { 
  NSString* caption; 
  NSString* photographer; 
} 
  - (NSString*) caption;
   - (NSString*) photographer;
@end
Vamos adicionar os “setters“:
#import <Cocoa/Cocoa.h> 

@interface Photo : NSObject { 
  NSString* caption; 
  NSString* photographer; 
} 
  - (NSString*) caption; 
  - (NSString*) photographer; 
  - (void) setCaption: (NSString*)input; 
  - (void) setPhotographer: (NSString*)input; 
@end
Setters” não precisam de um valor de retorno, portanto vamos especificá-los como sendo do tipo void.

Aprendendo Objective-C – Parte 4

Gerenciamento Básico de Memória

Se você está escrevendo uma aplicação para o Mac OS X, você tem a opção de tivar o garbage collection. Em geral, isto significa que você não tem que se preocupar com o gerenciamento de memória a não ser que você precise de algo mais complexo.
Entretanto, você pode nem sempre está trabalhando em um ambiente que suporta o garbage collection. Neste caso, você precisa saber alguns conceitos básicos.
Se você criar um objeto utilizando o alloc, você precisa liberar (release) o objeto depois. Você não deve explicitamente liberar um objeto autorelease pois sua aplicação irá apresentar um mal funcionamento.
Veja estes dois exemplos:
// string1 will be released automatically 
NSString* string1 = [NSString string]; 
// must release this when done 
NSString* string2 = [[NSString alloc] init]; 
[string2 release];
Neste tutorial, você pode assumir que um objeto automático irá ser desalocado da memória quando a função atual terminar.
Existem mais coisas para aprender sobre gerenciamento de memória, mas isto irá fazer mais sentido depois que aprendermos mais alguns conceitos da linguagem.

Aprendendo Objective-C – Parte 3

Criando Objetos

Existem duas formas principais de criar um objeto. A primeira você já nos posts anteriores.

NSString* myString = [NSString string];
Esta é a forma mais conveniente de fazer isto. Neste caso, você está criando um objeto autorelease, no qual veremos mais detalhes depois. Em muito casos, ao meu ver, você deve criar um objeto de forma manual.
NSString* myString = [[NSString alloc] init];
Esta é uma chamada aninhada de método. A primeira é o método alloc chamado através de NSString. Esta é uma chamada relativamente de baixo nível na qual reserva um espaço de memória e instancia um objeto.
A segunda é uma chamada ao método init do novo objeto. A implementação de init geralmente realiza um ajuste básico no objeto, como criar as variáveis de instância. Os detalhes disto não precisam ser conhecidos por você como cliente da classe.
Em alguns casos, você pode usar uma versão diferente de init, no qual toma um valor de entrada:
NSNumber* value = [[NSNumber alloc] initWithFloat:1.0];

Sincronizando Legenda e Fala

Olá a todos,

Tenho trabalhado em um projeto para Iphone, e neste projeto vou precisar sincronizar um texto com uma narração. Tive a ideia de criar um aplicativo em java que me ajudasse durante esse processo. Passei esse fim de semana programa tal aplicativo e daí surgiu o Clacket. Seu funcionamento é bastante simples. Você basicamente digita uma frase e especifica quanto tempo ela permanece visível. Quando tiver feito todos os ajuster de tempo e tiver clicado em iniciar, as frases aparecerão ao mesmo tempo que o aplicativo grava o que for dito no microfone, desta forma a aplicação vai sincronizar automaticamente o texto a fala. Este é um projeto opensource e ele está hospedado no github. Caso queira acompanhar seu desenvolvimento, aqui está o link https://github.com/sergiosvieira/Clacket

Valeu…

Aprendendo Objective-C – Parte 2

Modificadores de Acesso

Todas as variáveis de instância são privadas em Objective-C por padrão, portanto, você deve utilizar os modificadores de acesso para acessar (get) e definir (set) os valores das variáveis na maioria das vezes. Existem duas sintaxes. Esta é a sintaxe tradicional utilizada na versão 1.x:

[photo setCaption:@"Day at the Beach"]; 
output = [photo caption];

O código na segunda linha não está lendo a variável de instância diretamente. Ele está chamando um método nomeado caption. Na maioria das vezes, você não adiciona o prefixo “get” na assinatura dos métodos em Objective-C.

Sempre que existir um código dentro de colchetes, ele estará enviando uma mensagem para um objeto ou uma classe.

O Uso do Ponto

O uso do ponto para os “getters” e “setters” é novo no Objective-C 2.0, que é parte integrante do Mac OS X 10.5:

photo.caption = @"Day at the Beach";
output = photo.caption;

Você pode usar um estilo ou outro, mas escolha apenas um por projeto. O uso do ponto só deve ser utilizado por métodos “getters” e “setters”, ele não deve ser utilizado por métodos com outros propósitos.

 

Aprendendo Objective-C – Parte 1

Caros, como estou estudando mais uma nova linguagem vou postar uma tradução da página http://cocoadevcentral.com/d/learn_objectivec/ onde o autor mostra de forma rápida e didática as principais características da linguagem.

APRENDA OBJECTIVE-C

Objective-C é a principal linguagem utilizada para programar software para MAC. Se você se sente confortável com o básico dos conceitos de programação orientada a objetos e linguagem C, Objective-C fará muito sentido para você. Se você não sabe C, então você deveria ler este tutorial de C primeiramente.

Este tutorial é escrito e ilustrado por Scott Stevenson e foi traduzido por Sérgio Vieira.

MÉTODOS

Para iniciar rapidamente, vamos dar uma olhada em alguns exemplos simples. A sintaxe básica para chamar um método de um objeto é o seguinte:

[object method]
[object methodWithInput: input]

Além disso, os métodos podem retornar valores:

output = [object methodWithOutput];
output = [object methodWithInputAndOutput: input];

Você pode chamar métodos em classes também, que é como você cria objetos. No exemplo abaixo, chamamos o método string da classe NSString, que retorna um novo objeto NSString:

id myObject = [NSString string];

O tipo id significa que a variável myObject refere-se a qualquer tipo de objeto, então a classe atual e os métodos que ele implementa não são conhecidos quando você compila o aplicativo.

Neste exemplo, o tipo do objeto será um NSString, portanto podemos mudar seu tipo:

NSString* myString = [NSString string];

Agora a variável é do tipo NSString, então o compilador irá nos avisar se tentarmos usar um método do objeto que NSString não suporta.

Note que existe um asterisco a direita do tipo de objeto. Todas as variáveis de objetos do Objective-C são do ponteiros. O tipo id é predefinido com um tipo pnteiro, portanto não há necessidade de adicionar um asterisco.

Mensagens Aninhadas

Em muitas linguagem, uma chamada de método aninhado ou função é parecida com isto:

function1 ( function2() );

O resultado de function2 é passado como entrada para function1. Em Objective-C, mensagens aninhadas parecessem com isto:

[NSString stringWithFormat:[prefs format]];

Tente evitar mais de duas mensagens aninhadas por linha, pois assim evita-se que ela se torne difícil de entender.

Método com Múltiplas Entradas

Alguns métodos usam múltiplos valores de entrada. Em Objective-C, o nome de um método pode ser dividido em vários segmentos. No cabeçalho, um método com múltiplas entradas é parecido com isto:

-(BOOL)writeToFile: (NSString *)path atomically: (BOOL)useAuxiliaryFile;

Você pode chamar o método desta forma:

BOOL result = [myData writeToFile:@"/tmp/log.txt" atomically:NO];

Estes não são apenas argumentos nomeados. O nome do método é
writeToFile:atomically: em tempo de execução.