Lấp trình ios
Trang 11 Một vài dòng về lịch sự ra đời và sự phát triển.
Sự kế tiếp của Steve Jobs
Cái tên này đã chở nên qua nổi tiếng từ cuộc đời ông cho đến sự nghiệp lẫy lừng và cả việc ông làm điên đảo cộng đồng IT thế giới cho đến chính bạn (chẳng phải bạn cũng đang diên đảo vì IPhone đây !_! )
Khi bi out khỏi Apple, năm 1988 Steve Jobs đã mua lại bản quyên của Obejctive - C từ Stepstone để viết cho ứng dụng phần cứng của mình vọi là NeXTstep hay còn gọi là
OpenStep công ty lúc này của Jobs là NeXT
Cho đến 1996 khi Apple mua lại NeXT thì họ tiếp tục sử dụng công nghệ OpenStep để phát triên hệ điều hành Mac của họ và xây dựng một loạt công cụ XCode, Interface Builder và các Cocoa API ra đời
Đến giờ thì đã hiểu là tại sao lại là Objective - C chứ không phải bất cứ ngôn ngữ nào khác
để build các App trên nền Apples
2 Tìm hiểu ngôn ngữ Ob-c
Đặc điểm cơ bản.
- Là ngôn ngữ hướng đối tượng
- Mở rộng từ C
- Nhẹ nhàng (không VM - không quá thực tạp với friend virtuals với template với )
- Mềm dẻo (mở rộng từ C nên bạn có thể dùng C thuần cấu trúc ngoài ra đây là ngôn ngữ run-time)
- Reflection (có hỗ chợ)
- nil thay thế cho NULL trong C, bởi vì bạn có thể gửi thông điệp cho nil, nhưng không thể làm như vậy với NULL
- BOOL có 2 giá trị là YES và NO chứ không phải là true và false nữa
- Khái niệm methods và message đc sử dụng mang ý nghĩa như nhau đối với ObC theo đó message có những thuộc tính đặc biệt Mọto message có thể chuyền động từ obj tới một objkhác Việc gọi thông điệp trên một obj không có nghĩa là obj đó sẽ thực hiện message nó cóthể chuyển tiếp tới một obj khác chưa biết trước tóm lại có khả năng đáp trả thông điệp không trực tiệp thì gián tiếp
Khi làm việc với Objective C bạn cần chú ý là bởi vì nó dc base trên nền của C cho nên việc bạn sử dụng cú pháp C chộn lẫn với cú pháp chính thống của Objective C là hoàn toàn chấp nhận, tuy nhìn có vẻ hơi củ chuối
Phương thưc.
Cách khai báo phương thức trong Objective - C
Không tham số :
PHP Code:
Trang 2-(void) setDenominator: (int) d;
Lời gọi phương thức:
Mã:
không trả về: [<đối tượng> ];
[<đối tượng> :<(kiểu)> ];
[<đối tượng> :<(kiểu)> :<(kiểu)> ];
Trả về kết quả: = [<đối tượng> ];
= [<đối tượng> :<(kiểu)> :<(kiểu)> ];
Lớp và đối tượng
Ob-C sử dụng khái niệm Interface và Implementation để phân biêt file Header và file Sourcecủa C (*.h và *.c) một lớp trong ObC định nghĩa là trên một giao diện (.h) còn phần thực thitrên file m các bạn chú ý là m vì nó khác với C và C++
-(void) setNumerator: (int) n
-(void) setDenominator: (int) d
Trang 3printf( "%i/%i", numerator, denominator );
- Các thuộc tính dc khái báo trong cặp { } và khai báo phương thức ở bên ngoài
- Nếu phương thức bắt đâu bằng "+" có nghĩa nó là thuộc phạm vi lớp (static), còn nếu "-" thì nó ở phạm vi object
- Các phạm vi truy xuất public,protected và private giống như C++ mặc định là protected
- Các truy nhập phần tử cũng sử dụng toán tử "." đối với object và "->" nếu là con trỏ
- không có các tầm vực truy xuất đối với phương thức (tức là trong ObC các phương thức có cùng một tầm vực là public)
Exception và handler.
Ngôn ngữ cũng hỗ chợ các cấu trúc try - catch - throw - finally giống như ngôn C++ @try -
@catch - @throw - @finally cách thức sử dụng cũng hoàn toàn tương tự
Categories
Là đặc điểm nếu bạn muốn mở rộng lớp bằng cách thêm mới vào lớp một phương thức Khi bạn làm việc quen với OOP thì bạn sẽ thấy đây là một trong những thuộc tính vô cùng hữu ích của Objective C, kể cả ngay khi bạn không có mã nguồn của lớp nhưng bạn vẫn hoàn toàn có thể thêm phương thức cho lớp như thường thông qua thuộc tính này Đặc điểm này làm giảm đi đáng kể sự kế thừa phức tạp trong C++ khi việc kế thừa chỉ để phục vụ cho việc thêm mới một phương thức Mặt khăc việc chia mã nguồn trên nhiều files cũng giúp íchđáng kể trong việc phát triên
Code:
PHP Code:
#import "Fraction.h"
@interface Fraction (Math)
-(Fraction*) add: (Fraction*) f
-(Fraction*) mul: (Fraction*) f
-(Fraction*) div: (Fraction*) f
Trang 4-(Fraction*) sub: (Fraction*) f
@implementation Fraction (Math)
-(Fraction*) add: (Fraction*) f {
return [[Fraction alloc] initWithNumerator: numerator * [f denominator] +denominator * [f numerator]
denominator: denominator * [f denominator]];
}
-(Fraction*) mul: (Fraction*) f {
return [[Fraction alloc] initWithNumerator: numerator * [f numerator]denominator: denominator * [f denominator]];
}
-(Fraction*) div: (Fraction*) f {
return [[Fraction alloc] initWithNumerator: numerator * [f denominator]denominator: denominator * [f numerator]];
}
-(Fraction*) sub: (Fraction*) f {
return [[Fraction alloc] initWithNumerator: numerator * [f denominator] denominator * [f numerator]
-denominator: denominator * [f denominator]];
}
@end
- Tên của category phải là duy nhất
- Có thể thêm bao nhiêu lần mở rộng lơp từ category là không giới hạn nhưng với tên là duy nhất
- Thông thể bổ xung biến thành phần bằng category
- Có thể sử dụng category để tạo ra các phương thức private Nếu cần
Trang 5printf( "public method\n" );
int main( int argc, const char *argv[] ) {
MyClass *obj = [[MyClass alloc] init];
Protocals: Giao diện.
Đây hoàn toàn tương đồng với khái miện lớp ảo trong C++ hoặc gọi là giao diện trong C#
và Java Bản thân @protocals không có sự thực thi Nếu lớp nào cam kết thực thi nó thì trong phần thực thi sẽ implement các phương thức mà protocals khai báo
Trang 6int numerator;
int denominator;
}
-(Fraction*) initWithNumerator: (int) n denominator: (int) d;
-(void) setNumerator: (int) d;
-(void) setDenominator: (int) d;
-(void) setNumerator: (int) n andDenominator: (int) d;
-(Fraction*) copyWithZone: (NSZone*) zone {
return [[Fraction allocWithZone: zone] initWithNumerator: numeratordenominator: denominator];
Trang 7-(void) setImaginary: (double) i
-(void) setReal: (double) r andImaginary: (double) i
Trang 8int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] initWithNumerator: 3 denominator: 10];Complex *comp = [[Complex alloc] initWithReal: 5 andImaginary: 15];
if ( [frac conformsToProtocol: @protocol( NSCopying )] == YES ) {
printf( "Fraction conforms to NSCopying\n" );
}
// false
if ( [comp conformsToProtocol: @protocol( NSCopying )] == YES ) {
printf( "Complex conforms to NSCopying\n" );
}
// free memory
[frac release];
[comp release];
Trang 9return 0
}
Properties
Thuộc tính gần như bất cứ một ngôn ngữ mới hiện đại nào cũng hỗ chợ khái niệm này, đây
là một khái niệm bảo toàn tính đóng gói của tư tưởng OOP
Đối vơi ngôn ngữ ObC có mốt số những hỗ chợ đặc biệt hơn một chút bạn khai báo sử dụng bằng @properties cũng giống như những ngôn ngữ khác khi bạn sử dụng thuộc tính với ObCbạn sẽ có 2 lựa chọn là @synthesize và @dynamic, với lựa chọn là @synthesize thì mặc nhiên trình biên dịch sẽ giúp bạn sinh ra các phương thức set và get trên thuộc tính nhưng nếu bạn lựa chọn là @dynamic thì mọi việc bạn phải tự làm lấy
hãy xem code
- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;
@property (retain) NSString* caption;
@property (retain) NSString* photographer;
@end
Kiểu id
id trong ObC gần tương tự như void* trong C bạn không cần phải biết rõ kiểu của object khibạn gọi phương thức trong ObC điều này hoàn toàn khác với C++ bơi đơn giản khi gọi phương thức cũng giống như bạn truyền thông điệp trong ObC Nếu đối tượng nó có phươngthức thì sẽ đáp lại thông điệp mà bạn truyền (gọi phương thức) và phương thức đc gọi Cũng nguy hiểm đây chứ
DE XEM LINK VA HINH ANH BAN CAN CO NHIEU HON 10 BAI VIET NHUNG HIEN TAI BAN CHI CO 0 BAI VIET.
Ép kiểu động.
những phương thức dưới đây dùng để kiểm tra kiểu
Trang 10Trích dẫn:
- (BOOL) isKindOfClass: classObj >> đối tượng là hậu duệ hoặc thể hiện của classObj
- (BOOL) isMemberOfClass: classObj >> là một thành phần của objClass
- (BOOL) respondsToSelector: selector >> đối tượng có phương thức bởi selector
+ (BOOL) instancesRespondToSelector: selector >> đối tượng đc tạo bởi lớp có đáp ứng selector
- (id) performSelector: selector >> triệu gọi chính sách selector trên đối tượng
Constructors - hàm khỏi tạo:
Vấn đề là với một lớp thì hàm khởi tạo dùng để sinh đối tượng và cũng là chỗ để tư duy về hàm hủy và cách thức lưu trong bộ nhớ của đối tượng Về vấn đề hủy đối tượng ta sẽ có một phần riêng và nó hoàn toàn khác biệt với việc viết hàm hủy trong C++ và các ngôn ngữkhác Tất nhiên không có gì là không thể viết khi bạn đã hiểu rõ và thông thạo ngôn ngữ Vàhẳn nhiên bạn có thể quên hết những luật về khởi tạo đối tượng hàm tạo và hàm hủy của C++ vơi ObC bạn hoàn toàn có thể tự mình chế biến những hàm đó theo ý thích và cũng không có quy luật gì về tên tuổi của hàm, tuy nhiên theo thoi quen truyền thông để giúp style - code chở nên sáng sủa nên dùng bằng các từ như init hoặc tương tự để định nghĩa hàm khởi tạo
-(Fraction*) initWithNumerator: (int) n denominator: (int) d {
self = [super init];
int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] init];
Fraction *frac2 = [[Fraction alloc] init];
Fraction *frac3 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];
Trang 11// set the values
- Từ khóa supper để tham chiếu tới lớp cha
- Từ khóa self tác dụng tương đương như this trong C++ (chính bản thân đang thể hiện củalớp - object hiện tại)
- Kết thúc hàm khởi tạo (init) sẽ trả về chính đối tượng dc tạo ra thông qua từ khóa self
- Mặc định trong ObC hàm khỏi tạo là - (id) init;
- Trong ObC hàm khởi tạo chỉ có ý nghĩa về mặt tư duy, nó không đc đối sử đặc biết giống như C++
2 Quá trình tạo mối liên hệ giữa thể hiện của ObC và phương thức sẽ đc gọi là thời điểm run-time Điểu này hoàn toàn có ý nghĩa nếu bạn gọi một phương thức mà bản thân đối tượng không có cũng không có lỗi gì Lỗi chỉ xảy ra khi lời gọi đó dc thực hiện Tuy nhiên ban cũng dc cung cấp những cơ chế để kiểm soát việc này đây cũng là một đặc tính Run-Time của ObC nếu bạn quan tâm có thể tìm kiếm thông tin từ việc chuyển tiếp thông điệp (forward) tới một đối tượng khác
Quản ly bộ nhớ.
ObC có 2 lựa chọn cho việc quản lý bộ nhớ Thông thường bộ nhớ dc quản lý bởi lập trình
Trang 12viên, ObC có trình biên dịch chỉ thị nhứ "release", "retain", "autorelease" là những chỉ thị hỗ chợ lập trình viên mạnh mẽ trong việc quản lý bộ nhớ.
ObC sử dụng một tham chiếu đếm để dò tìm ra những thay đổi trên một đối tượng Biến đếm này sẽ tăng lên một khi đối tượng dc cấp phát bộ nhớ bằng phương thức alloc, biến đếm này sẽ giảm đi một khi đối tượng dc giải phóng bằng phương thức dealloc Như vậy nguyên lý cấp phát và duy trì bộ nhớ của đối tượng trong ObC dc sử dụng thông qua
phương thức alloc và dealloc
Mặt khác tiện ích khác từ kiểu dữ liệu nil đã nói ở trên đó việc giải phóng bộ nhơ Trong ngữ cảnh một đối tượng của bạn là bao gồm nhiều những đối tượng khác những đối tượng khác
đó có thể đã dc giải phóng hoặc chưa như thế bạn sẽ thực hiện lời gọi dealloc trên tập đối tượng mà bạn có, nếu con thì nó sẽ thực hiện giải phóng trong trường hợp bằng nil cũng ok không vấn đề gì (no error) vì nil cũng có thể truyền thông điệp
-(void) setFirst: (NSString*) f
-(void) setLast: (NSString*) l
-(void) setEmail: (NSString*) e
-(void) setFirst: (NSString*) f
Trang 14int main( int argc, const char *argv[] ) {
NSString *first =[[NSString alloc] initWithCString: "Tom"];
NSString *last = [[NSString alloc] initWithCString: "Jones"];
NSString *email = [[NSString alloc] initWithCString: "
DE XEM LINK VA HINH ANH BAN CAN CO NHIEU HON 10 BAI VIET NHUNG HIEN TAI BAN CHI CO 0 BAI VIET.
// print to show the retain count
printf( "Retain count: %i\n", [[tom first] retainCount] );
và sự đóng mở hợp lý (giống như thẻ đóng và mở của XML đó) tự nhiên ObC sẽ đẩy các lời gọi pool sau xuống stack và đặt pool mới trên cùng sau đó nhét các object dc tạo ra trong lòng nó vào cái pool vừa mới tạo nếu song thì giải phóng rồi lại đẩy tiếp thằng pool ở dưới lên cứ thế kinh chưa
Trang 15key: khóa của liên kết Khóa này thường là đối tượng static.
value: giá trị liên kết với khóa cho đối tượng Đưa giá trị nil để xóa một liên kết đã tồn tạipolicy: các policy cho liên kết
static char overviewKey;
mã nguồn được biên dịch
Selector khi được biên dịch có kiểu là SEL Tất cả các phương thức có cùng tên thì có cùng selector Ta có thể sử dụng một selector để triệu gọi một phương thức trên một đối tượng, điều này thể hiện khá căn bản mẫu thiết kế target-action trong Cocoa
Trang 16assign cho biến SEL là setWidthHeight.
Ở trên trường hợp ta tham chiếu đến một selector thông qua chỉ thị @selector, trong một sốtrường hợp ta có thể chuyển từ một chuỗi ký tự thành một selector trong thời điểm runtime bằng phương thức NSSelectorFromString
Một selector đã biên dịch chị định một tên phương thức chứ không thực thi phương thức Ví
dụ, có một phương thức Display cho một lớp, có nhiều selector giống nhau cho phương thức Display ở các lớp khác, với mục đích đa hình và ràng buộc động Nếu có một selector cho mỗi phương thức thực thi, thì một thông điệp sẽ không khác một lời gọi phương thức
Một phương thức lớp và một phương thức thể hiện có cùng tên được assign bởi một selector.Tuy nhiên, bởi vì 2 phương thức này phân biệt domain (phạm vi lớp, phạm vi đối tượng của lớp) nên sẽ không có sự nhầm lẫn giữa 2 phương thức này
Việc định tuyến một thông điệp truy xuất vào một phương thức chỉ thông qua một selector duy nhất, vì vậy nó đối xử như nhau đối với các phương thức có cùng selecor Nó phát hiện kiểu trả về của phương thức và kiểu dữ liệu của các tham số thông qua selector Vì vậy, ngoại trừ thông điệp truyền vào các bộ nhận kiểu tĩnh, còn lại với các ràng buộc động nó yêu cầu tất cả các tên phương thức thực thi phải có cùng kiểu trả về và có tham số cùng kiểu (các bộ nhận kiểu tĩnh là ngoại lệ, trình biên dịch có thể biết về các phương thức thực thi từ kiểu lớp)
Mặc dù định danh của phương thức lớp và phương thức thể hiện là cùng một selector, nhưngchúng có thể có kiểu trả về và kiểu của các tham số khác nhau
Ba phương thức performSelector:, performSelector:withObject:, và
performSelector:withObject:withObject:, định nghĩa trong protocol NSObject lấy các định danh SEL như là các tham số khởi tạo Tất cả các phương thức này ánh xạ trực tiếp vào thông điệp phương thức Ví dụ:
Trang 17Lưu ý, khi một bộ nhận buộc phải thực hiện một phương thức mà không thuộc phạm vi của mình thông qua selector thì đương nhiên sẽ xuất hiện lỗi Vì những công việc này thực thi ở thời điểm runtime nên hiển nhiên lỗi sẽ chỉ xuất hiện tại thời điểm chương trình được thực thi.
@catch (NSException *ne) { // 2
// Perform processing necessary at this level
Trang 18mutableCopy…) hoặc gửi một thông điệp retain, bạn phải có trách nhiệm giải phóng quyền
sở hữu đối tượng đó bằng cách sử dụng release hoặc autorelease Bất kỳ khi nào bạn nhận được một đối tượng (không phải tự mình khởi tạo), bạn không được release nó
Các nguyên tắc khác
Khi bạn cần lưu trữ một đối tượng được nhận như một property trong một biến thể hiện, bạn phải retain hoặc copy nó (Điều này không đúng cho cho tham khảo yếu, nhưng đây là điển hình hiếm)
Một đối tượng được nhận thường đảm bảo vẫn có hiệu lực trong phương thức mà nó đã đượcnhận (ngoại trừ trong các ứng đa luồng và vài trường hợp Distributes Objects) Phương thức
đó có thể trả về an toàn đối tượng mà nó được triệu gọi Sử dụng retain trong việc kết hợp với release hoặc autorelease khi cần thiết để bảo vệ một đối tượng khỏi hiệu lực của các thông điệp không hợp lệ bên ngoài
autorelease có nghĩa là “gửi một thông điệp release sau đó
1.4.2 Vấn đề khi khởi tạo đối tượng
Xét đoạn code khởi tạo đối tượng sau
Khi đó, đoạn code sau sẽ giải quyết được khả năng lỗi ở trên
Code:
PHP Code:
TestClass *ptr = [[TestClass alloc] init];
// Do something with the object
if (ptr)