Skip to content

Instantly share code, notes, and snippets.

@erinlin
Created December 17, 2013 07:45
Show Gist options
  • Save erinlin/8001454 to your computer and use it in GitHub Desktop.
Save erinlin/8001454 to your computer and use it in GitHub Desktop.
Objective-C學習筆記

Objective-C note

初始化 function

-(id) 就是 Objective-C 中的 object, 本身就是帶一個 pointer 所以不用再加 *

-(id)initWithName:(NNString *)name andAge:(int)age{
    id result = [super init];
    if(result){
        self.name = name;
        self.age = age;
    }
    return result;
}

也可以在子類別中直接 overwrite

 -(id)initWithName:(NNString *)name andAge:(int)age{
    id result = [super initWithName:name andAge:age];
    if(result){
        //self.name = name;
        //self.age = age;
        //do Something
    }
    return result;
}

##變數繼承 如果直接在 interface 內宣告 instance variable 在子類別都可以直接引用,如果是宣告在 .m 中的話,就抓不到,可以拿來當 private 用

protocol

protocol 中定義跟 .h 差不多 create instance from protocol

id<IPerson> teacher = [[Teacher alloc] init ]; // or [Teacher new];
teacher.name = @"Bill";
[teacher sing];

###optional method 關鍵字 @optional,沒有實作做執行的話也會出問題

@optional //這段後面宣告的都是 optional
-(void)doSomething;

##取址運算子 &, 取值運算子 *

int i = 20;
NSLog(@"&i= %p", &i); //取得記憶體位置 是一個 pointer
NSLog(@*&i= %d", *&i ); //取得記憶體位置的值, * 是取值運算子

int *j = &i; //這樣才合法,指向整數值的記憶體位置,所以 j 是 pointer
NSlog(@"j= %p", j); // pointer

int k = *j; //取出記憶體位置的整數所以是 20
NSlog(@"k= %d", k); // 20

*j = 30;
NSlog(@"when *j = 30, then i = %d", i); // 記憶體值變更,所以 i = 30

k=40;
NSlog(@"when k = 40, then i = %d", i); // 因為 k 單純數值,所以不會被變更記憶體原本的數值

##Class extenstion

Person.m

#import "Person.h"
@interface Person()
    //這段就是 class 的外掛
    //如果要針對 class 用 readonly 值做初始化
    //就可以在這將 property 設出來
    @property int myReadOnly;
@end

@implementation
    ---
    @synthesize myReadOnly = _myReadOnly;

    -(void)setInitSomething{
        self.myReadOnly = 100;
    }

@end

##避免循環參照

如果有兩個物件需要彼此參照的話(如 delegate ),必須要將一個改為 weak,否則會 memory leak

NSTableView 中
@property (weak) id delegate;

##Block 可以指向變數、函式類似 pointer 應該是用來放在 function 傳入值中的 callback

//定義一個 block 變數
//assign the value of the block variable
int(^countAll)(int) = ^(int num){
    int unitPrice  = 10;
    return unitPrice * num;
}
//
int total = countAll(5); //
NSLog(@"total = %i", total);

###Block scope

//關鍵字 __block 只要在 block 內的都抓的到
__block int unitPrice  = 10;
int(^countAll)(int) = ^(int num){
    //設定 __block 後這邊才能用
    unitPrice = 20;
    return unitPrice * num;
}
//
int total = countAll(5); //
NSLog(@"total = %i", total);

typedef

typedef int (^myblock)(int);

void printout(myblock b){
    int total = myblock(6);
    NSLog(@"%i = ", total)
}

//然後在執行中:

printout(^(int count){
    //就是直接帶一個 block
    return 10 * count;
});

callback 應用

Person.h

#import ----

typedef void (^DoSomethingCallBack)(NSString *thing);

@interface Person:NSObject

@property (nonatomic) NSString *name;

-(void) sing:(NSString *)song;
-(void) registAfterSingingHandler:(DoSomethingCallBack) handler;

@end

Person.m

#import "Person.h"

@interface Person(){
    DoSomethingCallBack _handler;
}
@end

@implementation

-(void)sing(NString *)song{
    NSLog(@"%@ us singing %@", self.name, song);
    if(_handler) _handler(@"done");
}

-(void)registAfterSingingHandler:(DoSomethingCallBack)handler{
    _handler = handler;
}
@end

Block-Cycle

需要避免互相參照[gcd-block-cycle-retain] (http://tanqisen.github.io/blog/2013/04/19/gcd-block-cycle-retain/)

感覺是Block 內要用 self 的話最好要設定

MyClass* weakSelf = self;

##String String Format Specifiers

Specifier Description
%@ Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function.
%% '%' character.
%d, %D Signed 32-bit integer (int).
%u, %U Unsigned 32-bit integer (unsigned int).
%x Unsigned 32-bit integer (unsigned int), printed in hexadecimal using the digits 0–9 and lowercase a–f.
%X Unsigned 32-bit integer (unsigned int), printed in hexadecimal using the digits 0–9 and uppercase A–F.
%o, %O Unsigned 32-bit integer (unsigned int), printed in octal.
%f 64-bit floating-point number (double).
%e 64-bit floating-point number (double), printed in scientific notation using a lowercase e to introduce the exponent.
%E 64-bit floating-point number (double), printed in scientific notation using an uppercase E to introduce the exponent.
%g 64-bit floating-point number (double), printed in the style of %e if the exponent is less than –4 or greater than or equal to the precision, in the style of %f otherwise.
%G 64-bit floating-point number (double), printed in the style of %E if the exponent is less than –4 or greater than or equal to the precision, in the style of %f otherwise.
%c 8-bit unsigned character (unsigned char), printed by NSLog() as an ASCII character, or, if not an ASCII character, in the octal format \ddd or the Unicode hexadecimal format \udddd, where d is a digit.
%C 16-bit Unicode character (unichar), printed by NSLog() as an ASCII character, or, if not an ASCII character, in the octal format \ddd or the Unicode hexadecimal format \udddd, where d is a digit.
%s Null-terminated array of 8-bit unsigned characters. Because the %s specifier causes the characters to be interpreted in the system default encoding, the results can be variable, especially with right-to-left languages. For example, with RTL, %s inserts direction markers when the characters are not strongly directional. For this reason, it's best to avoid %s and specify encodings explicitly.
%S Null-terminated array of 16-bit Unicode characters.
%p Void pointer (void *), printed in hexadecimal with the digits 0–9 and lowercase a–f, with a leading 0x.
%a 64-bit floating-point number (double), printed in scientific notation with a leading 0x and one hexadecimal digit before the decimal point using a lowercase p to introduce the exponent.
%A 64-bit floating-point number (double), printed in scientific notation with a leading 0X and one hexadecimal digit before the decimal point using a uppercase P to introduce the exponent.
%F 64-bit floating-point number (double), printed in decimal notation.

###indexOf

NSString *str = @"This is Objective-C";
NSRange range = [str rangeOfString:@"is" options:NSCaseInsensitiveSearch];
if(range.location!=NSNotFound){
    // found
    NSLog(@"Found is in %@ at location %lu", str, (unsigned long)range.location);
}

###字串相加

//stringByAppendingString
NSString *firstName = @"Erin";
NSString *lastName = @"Lin";
NSString *fullName = [[firstName stringByAppendingString: @" "] stringByAppendingString: lastName];
NSLog(@"my name is %@\n", fullName);

//stringWithFormat
NSString *fullName = [NSString stringWithFormat: @"%@ %@", firstName, lastName];

##NSObject

isEqual

判斷是否同一個物件是用 [object isEqual:anotherObject]


##Automatic Reference Counting

arc入門1

IOS5 ARC unsafe_unretained等說明

###臨時變數關鍵字

  • __string

  • __weak

  • __unsafe_unretained

  • __autoreleasing

      __strong NSString *yourString = @"Your String";
      __weak  NSString *myString = yourString;
      __unsafe_unretained NSString *theirString = myString;
    

####strong 黏到了就不會被清掉...

Test.h

@property (nonatomic, string) NSString *str1;
@property (nonatomic, string) NSString *str2;

Test.m

self.str1 = @"String1";
self.str2 = self.str1;
self.str1 = nil;

NSLog("str2 = %@", self.str2);
//str2 = String1

####weak 當傳值的物件 = nil 後,也會跟著掛掉

Test.h

@property (nonatomic, string) NSString *str1;
@property (nonatomic, weak) NSString *str2;

Test.m

self.str1 = @"String1";
self.str2 = self.str1;
self.str1 = nil;

NSLog("str2 = %@", self.str2);
//str2 = (nil)

####unsafe_unretained 不安全也不保存,當 str1 = nil 後它也不會知道,這樣 app 在背景執行的時候如果引用的話會 crush,感覺是奇怪的指定,還是少用好了...

Test.h

@property (nonatomic, strong) NSString *str1;
@property (nonatomic, unsafe_unretained) NSString *str2;

Test.m

self.str1 = @"String1";
self.str2 = self.str1;

//NSLog(@"&string1= %p", &_str1);
self.str1 = nil;

NSLog(@"string2 = %@", self.str2);
//NSLog(@"&string2= %p", &_str2);

###__autoreleasing 在c/c++,objective-c內存管理中有一條是:誰分配誰釋放。內存管理用來延遲釋放的關鍵字,通常用在傳給函式用的 reference,然後在函式內 alloc and init

- (void) generateErrorInVariable:(__autoreleasing NSError **)paramError{   
    NSArray *objects = [[NSArray alloc] initWithObjects:@"A simple error", nil];  
    NSArray *keys = [[NSArray alloc] 
        initWithObjects:NSLocalizedDescriptionKey, nil];  

    NSDictionary *errorDictionary = [[NSDictionary alloc]
        initWithObjects:objects 
        forKeys:keys];  

    *paramError = [[NSError alloc] 
        initWithDomain:@"MyApp" 
        code:1 
        userInfo:errorDictionary];  
} 

//testing

NSError *error = nil;   
[self generateErrorInVariable:&error];  
NSLog(@"Error = %@", error);  

回傳值建立物件(MRC寫法)

-(NSString *)stringTest {  
    NSString *retStr = [NSString stringWithString:@"test"];   
    return [[retStr retain] autorelease];  
}  

回傳值建立物件(ARC寫法)

-(NSString *)stringTest {  
    __autoreleasing NSString *retStr = @"test";     
    return retStr;  
}  
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment