Giáo dục > đào tạo trực tuyến > E-learning > Lập trình di động > Lập trình IOS

Ojective-C là ngôn ngữ lập trình  hướng đối tượng thường được dùng để viết các ứng dụng cho Mac OS X, iOS. Được thiết kế từ ngôn ngữ C bổ sung kiểu gọi hàm của ngôn ngữ Smalltalk. Được phát triển vào đầu những năm 80 bởi công ty NeXT (công ty của Steve Jobs khi ông rút lui khỏi Apple) Objective-C (obj-C) mở rộng từ ngôn ngữ C cho nên những thuộc tính, đặc điểm định nghĩa khái niệm của C nó đều có đủ.

Ngôn ngữ lập trình Objective-C là gì? | Lập trình ios

Ngôn ngữ lập trình Objective-C là gì? | Lập trình ios

Do đó mình không nhắc lại các khái niệm của C nữa. Bạn có thể tìm hiểu thông qua các tài liệu về ngôn ngữ lập trình C. Trong bài viết này mình sẽ trình bày những khái niệm cơ bản và thường gặp trong Objective-C. Nhưng nếu có những nội dung liên quan đến C mình sẽ cố gắn giải thích nếu có thể.

Ngôn ngữ lập trình Objective-C là gì?

Objective-C là ngôn ngữ lập trình như thế nào ? Hiểu một cách nôm na như mọi người vấn nói đó là ngôn ngữ C được thêm vào phần hướng đối tượng. Giống như C Plus Plus (C++) ấy. Với kinh nghiệm và hiểu biết của mình thì Obj-C có những ưu việt sau:

Biên dịch nhanh và mềm mại: Bản thân trình biên dịch C cũng là huyền thoại tốc độ rồi :DObj-C còn được trang bị thêm nhiều đặc điểm ngôn ngữ uyển chuyển (Dynamic Script Language) nữa. Ví dụ bạn có thể sử dụng kiểu tĩnh cho mọi biến nhưng những kiểu này lại không bị xử ký quá cứng nhắc…

Tương thích với C và C++: Bạn có thể sử dụng, khai báo tất cả các kiểu dữ liệu của C, C++. Trong thực tế có rất nhiều thư viện framework của Obj-C được viết bằng C, C++.

Tích hợp Cocoa: Cocoa được thiết kế cho Obj-C, đây là thư viện mạnh mẽ cho các ứng dụng cảm ứng..

Phương thức và cách gọi

Cú pháp khai báo hàm

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

1
-(kiểu dữ liệu)tên hàm:(kiểu dữ liệu)tham số 1 <tên tham số>:(kiểu dữ liệu)tham số 2;

Như đã nói, Obj-C có cách gọi phương thức (gọi hàm) của ngôn ngữ Smalltalk) cho nên trông nó khác hẳn C,C++ hay Java. Để đơn giản bạn đối chiếu hai ngôn ngữ Java và Obj-C

//Java

 
1
2
3
4
displayNames();
displayNamesWithPrefix( prefix );
addressBook.displayNames();
addressBook.displayNamesWithPrefix( prefix );

//Obj-C

 
1
2
[addressBook displayNames];
[addressBook displayNamesWithPrefix: prefix];

Tức là cú pháp

1
2
[object method];
[object methodWithInput: inputValue];

đối với hàm trả về giá trị thì..

1
2
names = [addressBook names];
names = [addressBook namesWithPrefix:prefix];

 

Khởi tạo đối tượng:

Lớp NSString:

Đây là một lớp dữ liệu trường đc sử dụng trong các chương trình obj-C, nó tương tự kiểu chuỗi trong các ngôn ngữ C++,Java, PHP…

ví dụ: NSString *blogname = @”Xcode Blog chấm com”;

Khởi tạo đối tượng

Trong C++, Java khái niệm này trương tự “Constructor”. Nghĩ là cấp phát mới vùng nhớ cho đối tượng và init các thuộc tính của đối tượng đó.

 
1
NSString* myString = [NSString string];

Obj-C chia làm hai loại khởi tạo:

Autorelase: đối tượng được khởi tạo dạng này thì bộ nhớ của chúng sẽ được quản lý 1 tự động. Tức là hệ thống sẽ tự thu hồi vùng nhớ của đối tượng khi nó không được dùng nữa.

ví dụ:

 
1
NSString* myString = [NSString string];
Manualrelase: Các biến này cần phải được quản vùng nhớ bởi “chính bạn”. Tức là phải gọi hàm destroy (trong Obj-C nó là hàm release) khi mà đối tượng không còn được dùng nữa.

ví dụ:

 
1
NSString* myString = [[NSString alloc] init];

Xây dựng lớp: Declaring a Class

Thông thường trong Obj-C class được xây dựng trên 2 file .h (header file) và .m (implement file). Header file chứa phần interface của class, implement file chứa phần implementation của các phương thức.

Tên file đặt theo tên class ví dụ lớp “ClassName” sẽ có 2 file ClassName.h và ClassName.m

Class interface

xem ví dụ:

 
1
2
3
4
5
6
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
id caption;
id photographer;
}
@end

Line #1: giống với included của C, C++ hay import của Java :D

Line #2: Khai báo lớp Photo, thừa kế từ lớp NSObject. (NSObject là lớp “tổ tiên” trong Obj-C mọi lớp khác đều thừa kế từ nó).

Line  #3,#4: khai báo 2 đối tượng con trỏ kiểu “id” (id là từ khóa, con trỏ có thể trỏ đến mọi đối tượng).

Khai báo phương thức:

Có hai loại phương thức:

Phương thức lớp (Class Method): phương thức này được gọi thông qua tên lớp được khai báo với dấu +

 
1
+ (kiểu dữ liệu)tên phương thức :(kiểu dữ liệu) tên tham số thứ nhất...
Phương thức đối tượng: được gọi qua tên đối tượng
 
1
- (kiểu dữ liệu)tên phương thức :(kiểu dữ liệu) tên tham số thứ nhất...

 
1
2
3
4
5
6
7
8
9
10
11
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- (NSString*) caption;
- (NSString*) photographer;
- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;
@end

Cài đặt/hiện thực lớp : Implement Class

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#import "Photo.h"
@implementation Photo
- (NSString*) caption {
return caption;
}
- (NSString*) photographer {
return photographer;
}
- (void) setCaption: (NSString*)input {
[caption autorelease];
[input retain];
caption = input;
}
- (void) setPhotographer: (NSString*)input {
[photographer autorelease];
[input retain];
photographer = input;
}
@end

Quản lý bộ nhớ : Memory Management

Quan_Ly_Bo_Nho_ObjectiveC

Mình chỉ xét đến trường hợp project/file ở dạng nonARC thôi nhé, tức là những phương thức quản lý này chỉ áp dụng cho project hoặc file không hỗ trợ ARC (Automatic Reference Counting) thôi. Khi nào viết bài về ARC mình sẽ nói về cách quản lý vùng nhớ của các project file dạng đó.

Release

Cơ bản nhất của quản lý bộ nhớ là: biến nào mà bạn khởi tạo bằng method aloc thì khi nào kô dùng biến đó nữa bạn phải gọi hàm release.

ví dụ:

1
2
3
4
5
NSString *stringA = [[NSString alloc] initWithString:@"http://xcodeblog.com"];
NSString *stringB = [NSString string];
//bạn phải release stringA
[stringA release];

Nếu bạn copy 1 đối tượng thì đối tượng copy phải đc relase khi không dùng đến nữa.

 
1
2
3
4
5
6
NSString *stringA = [[NSString alloc] initWithString:@"http://xcodeblog.com"];
NSString *stringB = [stringA copy];
//bạn phải release stringA và stringB
[stringA release];
[stringB release];

 

Retain

Obj-C sử dụng một biết đếm “retainCount” để quản lý các tham chiếu đến chính đối tượng đó. Các phương thức alloc, new, copy sẽ tăng biến này lên 1, phương thức release sẽ giảm xuống 1.

Khi retainCount của đối tượng có giá trị là 0 lúc đó đối tượng sẽ bị dealloc (tự hủy). Do đó khi đối tượng được dùng trong một phương thức của đối tượng khác chúng ta cần gọi retain để tăng retain count của đối tượng lên 1 dĩ nhiên phải giảm nó 1 khi không dùng nữa.

Ý nghĩa của retain là đảm bảo cho đối tượng đc retain không bị hủy trong khi nó đang bị trưng dụng bởi đối tường khác.

 
1
2
3
4
- (void) setTotalAmount: (NSNumber*)input {
[totalAmount autorelease];
totalAmount = [input retain];
}

 

Dealloc

Đây là phương thức hủy của đối tượng, bạn  phải gọi release các đối tượng khác mà đối tườn của bạn đang dùng.

Property và các option

Đây là 1 đặc tính của Obj-C cho phép tự động tạo ra các phương thúc setter và getter

ví dụ thay vì định nghĩa lớp như code sau đây

 
1
2
3
4
5
6
7
8
9
10
11
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
+ (Photo*) photo;
- (NSString*) caption;
- (NSString*) photographer;
- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;
@end

ta có thể dùng code sau

 
1
2
3
4
5
6
7
8
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
+ (Photo*) photo;
@property (retain) NSString* caption; @property (retain) NSString* photographer;
@end

 

Các Options

readwrite(mặc định): cho phép đọc và ghi(get/set)
read-only: chỉ có thể đọc (get)
assign(mặc định) dùng với các kiểu vô hướng: NSString, NSInteger, CGFloat…
retain: thường được sử dụng cho đối tượng
copy: tạo một bản sao lưu của đối tượng
attomic (mặc định) thực hiện đồng bộ hoá
nonattomic: ngược lại với attomic

Category

Objective-C không có đa thừa kế như Java nghĩa là bạn không thể tạo 1 lớp mới thừa kế 1 lúc nhiều lớp khác. Nhưng bạn có thể mở rộng một lớp nào đó bất kỳ. Khái niệm này là Category, bạn có thể thêm vào 1 lớp nào đó các phương thức, biến..

 
1
2
3
@interface NSString (Utilities)
- (BOOL) isXcodeBlogUrl;
@end

 

 
1
2
3
4
5
6
7
@implementation NSString (Utilities)
- (BOOL) isURL {
if ( [self hasPrefix:@"http://xcodeblog.com"] )
return YES;
else
return NO;
}

 

Protocol

Đây là một đặc điểm tuyệt vời của Objectice-C,  cho phép các lớp/đối tượng khác biệt (không thừa kế) nhau có thể sử dụng phương thức ủa nhau mà không cần phải thừa kế

Đây là một ví dụ trong đó mình sử dụng pro tocol của lớp UITableView trong lớp UIViewController :

Load json feed lên UITableView sử dụng AFNetworking

Khái niệm này nói thì khó và dài dòng nhưng, sử dụng thì rất dễ và hiệu quả. Ý nghĩa của nó là cho phép bạn implement các phương thức của một lớp (phương thức này thuộc protocol) trong phần implement của một lớp khác.

 
1
2
3
4
5
6
@protocol IconViewInfo
- (NSString*) title;
- (NSString*) fileName; - (NSString*) summary;
@optional
- (NSString*) author;
- (id) previewData; @end

Từ khóa @optional ( mặc định) nghĩa là cái protocol methods này không bawtsc buộc phải implement trong lớp “thừa kế” protocol.

 
1
2
3
4
@interface Photo : Media
@property (copy) NSString* caption;
@property (copy) NSString* photographer;
@end

Các methods của protocol IconViewInfo sẽ đc implement trong phần thân của class Photo

 
1
2
3
4
5
6
7
8
9
10
@implementation Photo
@synthesize caption; @synthesize photographer;
-(NSString *) title {
return self.caption; }
-(NSString *) fileName {
return [self.caption stringByAppendingPathExtension:@"jpg"]; }
-(NSString *) summary {
return [NSString stringWithFormat:
}
} @end

Mình sẽ nói rõ hơn khi gặp vấn đề liên quan, chú ý rằng đây là một đặc điểm dùng nhiều trong ứng dụng iOS/Mac OS nên bạn “phải” hiểu nó.

Thông điệp động Dynamic Message

Như đã nói Obj-C là ngôn ngữ động – mềm mại – uyển chuyển. Và đây là đặc điểm đó, Obj-C bạn có thể lưu giữ tên hàm như 1 biến và truyền chúng giữa các đối tượng khác nhau :D. Phương thức này là “selector” và kiểu dữ liệu của nó là “SEL”

 
1
2
3
4
5
SEL homeSelector = @selector( loadHomeScreen: );
NSString* selectorName = @"loadPreviewScreen:";
SEL previewSelector = NSSelectorFromString( selectorName );
//multiple inputs
SEL compareSelector = @selector(compare:options:range:);

ví dụ về cách sử dụng

 
1
2
3
4
5
6
7
@interface Photo : NSObject
- (NSString*) caption;
- (void) setAlbum:(Album*)album;
@end
@interface Album : NSObject + (id) defaultAlbum;
@end

 

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Photo* myPhoto = [[Photo alloc] init]; Album* myAlbum = [[Album alloc] init];
SEL captionSelector = @selector( caption );
SEL albumSelector = @selector( setAlbum: );
SEL unknownSelector = @selector( yeahThisMethodDoesntActuallyExist );
if ([myPhoto respondsToSelector: captionSelector]) {
NSLog (@"Calling '%@'", NSStringFromSelector( captionSelector ));
NSString* caption = [myPhoto performSelector:captionSelector];
NSLog (@"Photo caption: '%@'", caption);
}
if ([myPhoto respondsToSelector: albumSelector]) {
NSLog (@"Calling '%@'", NSStringFromSelector( albumSelector ));
[myPhoto performSelector:albumSelector withObject:myAlbum]; }
if ([myPhoto respondsToSelector: unknownSelector]) {
NSLog (@"Calling '%@'", NSStringFromSelector( unknownSelector ));
[myPhoto performSelector:unknownSelector];
}
[myPhoto release]; [myAlbum release];

 

Ngoại Lệ : Exceptions

Tương tự C++ hay  Java :D bạn chỉ cần xem qua ví dụ là hiểu

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
NSString* myString = [[NSString alloc] init];
@try {
char firstChar = [myString characterAtIndex:0]; int length = [myString length];
NSLog( @"Length is: %i", length );
}
@catch (NSException * e) {
NSLog( @"Caught an NSException, returning." ); NSLog( @"Name: %@", e.name );
NSLog( @"Reason: %@", e.reason );
return;
}
@finally {
// will still get called, even if above returns. NSLog( @"Releasing string.");
[myString release];
}