-(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 中定義跟 .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 int (^myblock)(int);
void printout(myblock b){
int total = myblock(6);
NSLog(@"%i = ", total)
}
//然後在執行中:
printout(^(int count){
//就是直接帶一個 block
return 10 * count;
});
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
需要避免互相參照[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
判斷是否同一個物件是用 [object isEqual:anotherObject]
##Automatic Reference Counting
###臨時變數關鍵字
-
__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);
-(NSString *)stringTest {
NSString *retStr = [NSString stringWithString:@"test"];
return [[retStr retain] autorelease];
}
-(NSString *)stringTest {
__autoreleasing NSString *retStr = @"test";
return retStr;
}