Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 5 của 5
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Lập trình Objectice C - Cùng trao đổi kinh nghiệm về lập trình IOS



    Chào mọi người !
    Em là người đang có xu hướng nhảy sang mảng IOS, nên đang học hỏi kinh nghiệm .
    Muốn lên 4rum để học hỏi kinh nghiệm lập trình về Objective - C của mọi người .
    Ai đã , đang và sẽ làm về mảng này thì vào topic trao đổi mọi người nhé .
    Ai có tài liệu gì hay bất cứ gì liên quan đến lập trình IOS thì share mọi người nhé. Em rất cần điều đó ở mọi người [IMG]images/smilies/smile.png[/IMG]
    Rất mong Topic sẽ bổ ích cho mọi người .

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    1. Giới thiệu
    Ngôn ngữ lập trình Objective-C là một ngôn ngữ lập trình hướng đối tượng được xây dựng chủ yếu dựa trên nền tảng ANSI C, và ngoài ra nó còn được mở rộng từ Smalltalk, một trong những ngôn ngữ lập trình hướng đối tượng đầu tiên. Objective-C được thiết kế với mục đích đưa vào C các tính năng hướng đối tượng một các đơn giản và dễ hiểu nhất.

    Objective-C là ngôn ngữ chính được Apple chọn để viết các ứng dụng cho hệ điều hành MAC, iPod và iPhone.

    Như vậy, để nắm được Objective-C bạn phải có kinh nghiệm về ngôn ngữ C. Nếu bạn có kiến thức tốt về C thì bạn có thể nắm nhanh Objective-C và có thể bắt đầu phát triển các ứng dụng cho iPhone và hệ điều hành MAC. Nếu không, bạn nên dành thời gian tìm hiểu thêm về ngôn ngữ C trước khi tìm hiểu Objective-C.


    1. Cơ bản về Objective-C
    1.1. Từ khóa
    1.1.1. Khai báo class, category và protocol
    @interface: khai báo class hoặc interface.
    @implementation: định nghĩa class hoặc category.
    @protocol: khai báo protocol
    @end: kết thúc trong việc khai báo, định nghĩa category hoặc protocol.
    @private: giới hạn phạm vi trong lớp mà biến thể hiện được khai báo.
    @protected: giới hạn phạm vi trong lớp và lớp con kế thừa mà biến thể hiện được khai báo.
    @public: không giới hạn phạm vi truy xuất.
    Mặc định là @protected
    @try
    @throw
    @catch
    @finally
    @class: khai báo trước một tên lớp đã được định nghĩa ở một nơi khác.
    @selector(method_name): trả về một selector đã được biên dịch mà được định nghĩa thông qua method_name.
    @protocol(protocol_name): trả về một protocol protocol_name (một thể hiện của một lớp Protocol). @protocol là hợp lệ (không có protocol_name) trong trường hợp khai báo trước
    @synchronized: định nghĩa một block mã nguồn trong nó phải được thực hiện đồng bộ
    #import: dùng để include một file, tương tự include trong C, C++.
    Một số từ khóa khác
    1.1.2. Phạm vi truy xuất các biến thể hiện
    1.1.3. Xử lý ngoại lệ
    1.1.4. Các mục đích cụ thể khác
    1.1.5. Một số từ khóa khác
    alloc retain release autorelease in out inout bycopy byref oneway super self

    1.2. Câu lệnh trong Objective-C
    Các câu lệnh điều khiển if, switch và các câu lệnh lặp for, while… tương tự như C/C++ hoặc Java

    Các câu lệnh rẽ nhánh:

    if (<condition>) {

    <statements>

    } else if (<condition>) {

    <statements>

    } else {

    <statements>

    }

    switch (<expression>) {

    case <constant>:

    <statements>

    break;

    default:

    break;

    }

    Các câu lệnh lặp:

    for (<initial>; <condition>; <increment>) {

    <statements>

    }

    while (<condition>) {

    <statements>

    }

    do {

    <statements>

    } while (<condition>)

    1.3. Đối tượng
    Một chương trình hướng đối tượng được xây dựng từ các đối tượng. Mỗi đối tượng bao gồm dữ liệu và các phương thức để sử dụng hoặc tương tác trên các dữ liệu đó.

    Objective-C cho phép định danh một đối tượng mà không cần phải chỉ ra một lớp cụ thể của đối tượng đó, điều này cho phép định kiểu động.

    Trong chương trình thì ta phải luôn đảm bảo rằng ta phải luôn xử lý các đối tượng không còn cần thiết nữa.

    1.3.1. Id
    Trong Objective-C, định danh đối tượng là một kiểu dữ liệu khác biệt: id. Kiểu này được định nghĩa như là một con trỏ trỏ đến một đối tượng, trong thực tế, một con trỏ trỏ đến các biến thể hiện của một đối tượng, với dữ liệu duy nhất. Giống như hàm hoặc mảng trong C, một đối tượng được định danh bởi một địa chỉ. Tất cả các đối tượng, bất kể là biến thể hiện hay phương thức, đều có kiểu là id.

    id anObject;

    1.3.2. Định kiểu động
    Kiểu id là một kiểu hoàn toàn không hạn chế. Bản thân nó không mang thông tin về một đối tượng, ngoài trừ nó là một đối tượng.

    Nhưng các đối tượng lại không giống nhau. Tại một vài thời điểm, chương trình cần biết rõ các thông tin đặc tả của một đối tượng, các biến thể hiện mà nó chứa, các hàm mà nó có thể thực hiện, kiểu id khi được thiết kế ra không hỗ trợ được điều này.

    Để hỗ trợ điều này, mỗi đối tượng được thiết kế mang trong nó một biến thể hiện isa với mục đích định danh lớp của đối tượng, cho biết đối tượng đó thuộc loại nào. Nhưng vậy tại mỗi thời điểm runtime, đối tượng là các kiểu động. Bất cứ lúc nào cần, hệ thống runtime có thể biết chính xác lớp mà đối tượng đó thuộc về, bằng cách hỏi ngay đối tượng đó.

    Con trở isa cho phép các đối tượng tìm các thông tin về bản thân chúng. Trình biên dịch ghi nhận các thông tin về định nghĩa lớp vào các cấu trúc dữ liệu để hệ thống runtime sử dụng. Các hàm của hệ thống runtime sử dụng isa để tìm ra các thông tin này tại thời điểm runtime.

    1.3.3. Bộ nhớ
    Trong lập trình Objective-C, một điều quan trọng là phải giải phóng các đối tượng không còn sử dụng, nếu không bộ nhớ sẽ tràn. Và một điều quan trọng không kém đó là không được giải phóng đối tượng khi nó đang được sử dụng.

    ================================================== ==================================

    Phần tiếp theo :
    1.1. Lớp
    1.1.1. Các khái niệm cơ bản
    1.1.1.1. Định nghĩa lớp
    Một lớp trong Objective-C được định nghĩa gồm 2 file thành phần tương tự C, C++. Một file *.h định nghĩa trước các biến thành phần và tên các phương thức, file *.m định nghĩa phần thực thi cho các phương thức trong file *.h

    File ClassName.h

    #import <headerFile.h>

    @interface ClassName {
    variable1 declaration;
    variable2 declaration;
    }
    method1 declaration;
    method2 declaration;
    @end

    Objective-C sử dụng từ khóa @interface để khai báo một tên lớp trong file h. Từ khóa @end được sử dụng ở cuối phần khai báo.

    File ClassName.m
    #import “ClassName.h”
    @implementation ClassName
    -method 1 //triển khai phương thức 1
    -method 2 // triển khai phương thức 2
    @end


    Objective-C sử dụng từ khóa @implementation để khai báo phần thực thi thực sự của lớp trong file m. Từ khóa @end được sử dụng ở cuối phần khai báo.

    Ví dụ:

    MyClass.h
    @interface MyClass {
    int a;
    int b;
    }

    -(void) setvara : (int) x;
    -(void) setvarb : (int) y;
    -(int) add;
    @end

    MyClass.m
    #import”MyClass.h”
    @implementation MyClass
    -(void) setvara int) x {
    a=x;
    }

    -(void) setvarb int) y {
    b=y;
    }
    -(int) add {
    return a+b;
    }
    @end


    1.1.1.2. Thuộc tính
    Cú pháp khai báo thuộc tính:

    [Access Privilege] TypeName varName;

    Ví dụ

    @private
    int att1;
    NSString str1;
    @protected
    int att2;
    @public
    NSString str2;
    int att3;


    Mặc định khi không sử dụng từ khóa quyền truy xuất là @protected

    1.1.1.3. Phương thức
    Cú pháp định nghĩa một phương thức
    [Access Privilege](return_type) methodname: (type1) para1 : (type2) para2 (…);

    Gọi phương thức
    [object methodnameara1 : para2…];

    Ví dụ:

    Khai báo
    -(MyClass*) constructor: (int) a : (int) b;

    Triển khai

    -(MyClass*) constructor: (int) a : (int) b {

    self = [super init];
    if(self) {
    var1 = a;
    var2 = b;
    }

    return self;

    }

    }

    Lời gọi phương thức như sau

    [myClassObject constructor: 100 : 200];

    Trong Objective-C chỉ có 2 khái niệm quyền truy xuất đến phương thức: truy xuất hoàn toàn qua lớp (public static) và truy xuất hoàn toàn qua đối tượng (public)

    Objective-C qui định phần định nghĩa truy xuất như sau
    Phương thức truy xuất thông qua tên lớp sẽ có ký hiệu là dấu +
    Phương thức truy xuất thông qua đối tượng sẽ có ký hiệu là dấu –

    @interface MyClass: NSObject
    -(MyClass*) staticMethod: (int) a : (int) b;
    -(MyClass*) publicMethod: (int) a : (int) b;
    @end

    Trong trường hợp phương thức có nhiều tham số, và để thể hiện được ý nghĩa của các tham số trong lời gọi phương thức, Objective-C cho phép một cú pháp khai báo khác cho phương thức như sau:

    [Access Privlilege](return_type) methodPara1: (type) para1 andPara2: (type) para2;

    Lời gọi phương thức khi đó sẽ như sau:

    [object methodPara1: value1 andPara2: value2];

    Ví dụ:
    -(void) setX: (int) x Y: (int) y;
    -(void) setX: (int) x Y: (int) y {
    var1 = x;
    var2 = y;
    }
    [myObject setX: 15 Y: 20];

    1.1.2. Kế thừa
    Tính kế thừa trong Objective-C tương tự trong các ngôn ngữ khác như C++,…
    #import “SuperClass.h”
    #import <headerFile.h>
    @interface ClassName:SuperClass {
    variable1 declaration;
    variable2 declaration;
    }

    method1 declaration;
    method2 declaration;
    @end

    Ví dụ:
    #import<Foundation/NSObject.h>
    @interface MyClass:NSObject {
    int a;
    int b;
    }

    -(void) setvara : (int) x;
    -(void) setvarb : (int) y;
    -(int) add;
    @end

    Trong Objective-C, thực sự tất cả các lớp khi tạo ra đều kế thừa từ lớp NSObject.

    1.1.3. Phương thức tạo
    Trong Objective-C không có khái niệm phương thức tạo cho một lớp. Tất cả các đối tượng của một lớp phải được cấp phát thông qua phương thức alloc và init.
    MyClass *myObject = [[MyClass alloc]init];
    Trong đó phương thức alloc là cấp phát vùng nhớ, còn phương thức init như là một phương thức tạo mặc định trong Objective-C, được định nghĩa trong lớp NSObject.

    -(id) init;

    Ta thường định nghĩa lại phương thức tạo có tham số của một lớp như sau:
    #import “SuperClass.h”
    #import <headerFile.h>

    @interface MyClass: NSObject {
    int var1;
    int var2;
    }

    -(MyClass*) constructor: (int) a : (int) b;
    @end

    #import “MyClass.h”
    @implementation MyClass
    -(MyClass*) constructor: (int) a : (int) b {
    self = [super init];
    if(self) {
    var1 = a;
    var2 = b;
    }
    return self;
    }
    @end

    Từ khóa super con trỏ trỏ đến lớp cha của lớp hiện tại, tương tự như base trong C++ hoặc super trong Java.

    Từ khóa self là con trỏ đại diện cho lớp hiện tại, tương tự con trỏ this trong C++ hay Java.

    1.1.4. Properties
    Trong Objective-C hỗ trợ tính năng Properties, cho phép chúng ta định nghĩa các bộ truy xuất (setter/getter) vì vậy sẽ có nhiều lợi ích sử dụng khi truy xuất đến các biến thể hiện của đối tượng.

    Định nghĩa trong file.h: @property (<attributes>) type propertyName;

    Thực thi trong file.m: @synthesize propertyName;

    Truy xuất đến properties thông qua cú pháp object.property

    #import <Foundation/Foundation.h>
    @interface Address : NSObject {

    int countryCode;
    int cityCode;
    }

    @property (readonly) int countryCode;
    @property int cityCode;
    @end

    #import “Address.h”
    @implementation Address
    @synthesize countryCode;
    @synthesize cityCode;

    @end

    Address *address = [[Address alloc] init];
    Int code = address.countryCode;
    address.cityCode = 99;


    Các thuộc tính cho Properties
    Writability
    readwrite: chỉ ra Properties có thể đọc và ghi, thuộc tính này là mặc định
    read-only: chỉ ra Properties chỉ có thể đọc.
    Setter Semantics
    assign: là thuộc tính mặc định. Ta thường sử dụng assign cho các kiểu vô hướng như NSInteger, CGRect…
    Ta có thể hình dung như sau

    @interface Test5 : NSObject {
    @private NSString *sVar;
    }
    @property (readwrite, assign) NSString *sVar;
    @end

    Properties này tương tự như settor sau

    -(void)setSVarNSString*)inSVar {
    if (self->sVar != inSVar){
    [self->sVar release];
    self->sVar = [inSVar retain];
    }
    }

    retain: retain nên được triệu gọi trên đối tượng được chỉ định.
    copy: một bản sao của đối tượng sẽ được sử dụng cho đối tượng chỉ định.


    Ta có thể hình dung như sau

    @property (readwrite, copy) NSString *sVar;

    Properties này tương tự như settor sau

    -(void)setSVarNSString*)inSVar {

    if (self->sVar != inSVar){

    [self->sVar release];
    self->sVar = [inSVar copy];
    }
    }

    Ta sử dụng chỉ định copy khi mà có khả năng tham số sVar là đối tượng có thể thay đổi
    Những ràng buộc phụ thuộc vào việc bạn chọn sử dụng hoặc không sử dụng bộ thu gom rác

    Nếu bạn không sử dụng bộ thu gom rác, với Properties của đối tượng bạn phải chỉ rõ assign, retain hay copy, nếu không trình biên dịch sẽ cảnh báo
    Nếu bạn sử dụng bộ thu gom rác, bạn sẽ không bị cảnh báo nếu không chỉ định assign, retain hay copy (mặc định khi đó là assign), trừ khi kiểu của Properties là một lớp thích hợp với NSCopying. Để mặc định thường là những gì bạn muốn, tuy nhiên, nếu đối tượng có thể sao chép thì để bảo tồn tính bao đóng bạn thường muốn làm một bản sao chép riêng cho đối tượng.
    Nếu bạn sử dụng bộ thu gom rác thì assign và retain có hiệu lực như nhau
    Atomicity: thuộc tính này chỉ ra Properties là không atomicity với từ khóa nonatomic. Việc này tương tự như đồng bộ hóa trong khái niệm Thread, Properties này sẽ bị block và thực hiện đồng bộ. Mặc định là atomic.


    1.2. Category
    Khi ta muốn thêm một số phương thức vào một lớp có sẵn, thông thường ta sẽ mở rộng lớp đó bằng cách viết lại mã nguồn. Objective-C cung cấp tính năng Category cho phép ta mở rộng lớp mà không cần phải viết lại mã nguồn của lớp cũ. Category cho phép ta mở rộng lớp cũ trong một bộ thực thi khác.

    Giả sử ta có một lớp MyClass đã định nghĩa



    MyClass.h

    @interface MyClass
    -(void) print;
    @end



    MyClass.m

    #import “MyClass.h”
    @implementation MyClass

    -(void) print {
    //to do print
    }


    Ta muốn thêm một một phương thức newMethod, ta sử dụng tính năng Category của Objective-C như sau

    MyCategory.h

    #import “MyClass.h”
    @interface MyClass (MyNewCategory)
    -(void) newMethod;
    @end

    MyCategory.m

    #import “MyCategory.h”

    @implementation MyClass (MyNewCategory)
    -(void) newMethod {
    //to do new method
    }



    Sử dụng như sau

    #import “MyClass.h”
    #import “MyCategory.h”

    int main(int argc, const char *argv) {
    MyClass *myObject = [[MyClass alloc] init];
    [myObject print];
    [myObject newMethod];
    }


    Tên của Category là duy nhất, có thể thêm nhiều Category nhưng không được trùng tên.
    Trong Category không cho phép thêm các biến thể hiện
    Ngoài mục đích mở rộng, Category thường được sử dụng để “định nghĩa” các phương thức “private” (không được hỗ trợ trong Objective-C)

    // ===========================
    // = File: SomeClass.m
    // ===========================
    #import “SomeClass.h”
    // =================================
    // = Interface for hidden methods
    // =================================
    @interface SomeClass (hidden)

    +(void) hiddenClassMethod;
    -(void) hiddenInstanceMethod;

    @end


    // =====================================
    // = Implementation of hidden methods
    // =====================================

    @implementation SomeClass (hidden)

    +(void) hiddenClassMethod {
    printf( “Hidden class method.
    ” );
    }

    -(void) hiddenInstanceMethod {
    printf( “Hidden instance method
    ” );
    }
    @end


    // ================================
    // = Implementation for SomeClass
    // ================================
    @implementation SomeClass

    -(void) msg {
    printf(“Inside msg()…
    ”);

    [self hiddenInstanceMethod];
    [SomeClass hiddenClassMethod];
    }


    +(void) classMsg {
    printf(“Inside classMsg()…
    ”);
    }
    @end


    Khi đó, ta sử dụng lớp SomeClass với phương thức msg() mà không biết đến các phương thức “hidden” như là các phương thức private

    // ===========================
    // = File: Main.m
    // ===========================

    #import “SomeClass.h”
    int main (int argc, char *argv[]){
    SomeClass *ptr = [[SomeClass alloc] init];

    // Display message (including messages from hidden methods)
    [ptr msg];

    // Call a class method
    [SomeClass classMsg];

    return 0;
    }



    1.3. Posing
    Pose là một tính năng của Objective-C cho phép lớp con thay thế (pose – in place of) lớp cha mà nó kế thừa trong một ngữ cảnh nhất định.

    @interface Fraction
    -(void) print;
    @end

    #import “Fraction.h”

    @implementation Fraction
    -(void) print {
    printf( “printf of Fraction”);
    }
    @end





    #import “Fraction.h”
    @interface FractionA : Fraction
    -(void) print;
    @end


    #import “FractionA.h”

    @implementation FractionA
    -(void) print {
    printf( “new printf of FractionA”);
    }
    @end



    #import “Fraction.h”
    #import “FractionB.h”

    int main( int argc, const char *argv[] ) {
    Fraction *frac = [[Fraction alloc] init];

    // print it
    printf( “The fraction is: ” );
    [frac print];
    printf( “
    ” );

    // FractionA pose as Fraction
    [FractionA poseAsClass: [Fraction class]];

    Fraction *frac2 = [[Fraction alloc] init];

    // print it
    printf( “The fraction is: ” );
    [frac2 print];
    printf( “
    ” );

    // free memory
    [frac release];
    [frac2 release];

    return 0;
    }


    Kết quả là

    The fraction is: printf of Fraction
    The fraction is: new printf of FractionA

    Phương thức poseAsClass là một phần của protocol NSObject

    1.4. Protocol
    Protocol định nghĩa một danh sách các phương thức bắt buộc hoặc tùy chọn mà các lớp chấp nhận (adopt) protocol bắt buộc phải thực thi.

    @protocol MyProtocol
    - (void)requiredMethod;
    @optional
    - (void)anOptionalMethod;
    - (void)anotherOptionalMethod;

    @required
    - (void)anotherRequiredMethod;
    @end

    Các phương thức khai báo trong Protocol cũng có thể là các khai báo Properties. Các từ khóa @optional và @required thể hiện theo đúng ý nghĩa của nó, nếu không sử dụng 2 từ khóa này thì mặc định là @required.


    @protocol NSCoding
    - (void)encodeWithCoderNSCoder *)aCoder;
    - (id)initWithCoderNSCoder *)aDecoder;
    @end


    // Interface
    @interface SomeClass : NSObject <NSCoding> {
    }


    // Implementation
    @implementation SomeClass
    -(void)encodeWithCoderNSCoder *)aCoder{

    }

    -(id)initWithCoderNSCoder *)aDecoder{

    }

    SomeClass triển khai Protocol NSCoding theo cú pháp <Protocol>

    @interface ClassName : ItsSuperclass < protocol list >
    @interface ClassName ( CategoryName ) < protocol list >

    Ví dụ:

    @interface Formatter : NSObject < Formatting, Prettifying >


    Protocol được sử dụng trong các trường hợp:

    - Khai báo các phương thức dự kiến sẽ được thực thi

    - Khai báo một interface cho một đối tượng trong khi ẩn đi lớp của nó

    - Khảo sát tương đồng giữa các lớp mà không phải liên quan đến cấu trúc thứ bậc

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    tại sao trong objective C người ta lại viết hàm init như thế này:

    Mã:
    - (id)init
    {
           if( self = [super init] ) { ... }
    }

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Mình mới tò te học cái objc này, xin trả lời thử nhé ^^

    Theo mình hiểu thì khi 1 class thừa kế 1 class cha, nó sẽ thừa kế luôn cả các instance variables (ivar) của lớp cha (superClass).

    Nếu trong hàm init mình chỉ lo khởi tạo các ivar của lớp hiện tại, thì các ivar của lớp cha sẽ ko được khởi tạo, và nhiều trường hợp sẽ gây ra lỗi khi chạy chương trình.

    Bởi vậy 1 thói quen tốt khi init cho lớp con, là send 1 message init tới lớp cha để nó khởi tạo các ivar của nó trước đã, sau đó mới khởi tạo ivar của lớp con.
    Sau khi gọi self = [super init], self sẽ chứa con trỏ đến đối tượng đã được lớp cha khởi tạo, và nhiều trường hợp khởi tạo ko thành công thì self sẽ mang giá trị nil. Mình nên xét giá trị của self trước khi send bất cứ message nào cho self để tránh lỗi.

    Tương tự như init, trong phương thức dealloc để hủy đối tượng, mình cũng nên chiếu đến lớp cha:

    (void) dealloc
    {
    // huy cac ivar cua lop con, cac ket noi mang....
    [super dealloc]; // roi de lop cha giai phong cac ivar cua no
    }

    Xin được học hỏi thêm ^^

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    self giống với this trong c++ đó bạn, còn super là rootclass, bạn phải hiểu rõ điều này trước khi đó nhé.[IMG]images/smilies/dont_know.gif[/IMG]

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •