2014年5月28日 星期三

把NSString宣告為常數

錯誤的宣告方式
會出現warning:(Sending 'const NSString *__strong' to parameter of type 'NSString *' discards qualifiers)
.h
extern NSString * SelectionSort;
.m
const NSString *InsertionSort = @"SelectionSort";


正確的宣告方式
.h
extern NSString *const SelectionSort;
.m
NSString *const SelectionSort = @"SelectionSort";

2014年5月27日 星期二

亂數取法

  1. arc4random() 回傳 int 的任意整數
    • int value = arc4random() % x; // 回傳 0 ~ x-1 之間的任意整數
  2. CCRANDOM_0_1() ; //在cocos2D中使用,回傳0 ~ 1之間的任意浮點數
    • float random = CCRANDOM_0_1() * 5; //回傳0~5間的任意浮點數
  3. random()可以輸入亂數種子的任意數
    • random((unsigned int)time(time_t *)NULL);//輸入時間種子

2014年5月26日 星期一

(id)sender

//從UI中拉線所生成的方法中,sender永遠是主動呼叫這個方法的那個UI物件
- (IBAction)unitValueChanged:(id)sender
{
    UISegmentedControl *sc = (UISegmentedControl*)sender;
    _settingEntity.unit = [NSNumber numberWithInteger:sc.selectedSegmentIndex];
    [_settingEntity update];

}

2014年5月22日 星期四

確認objective c方法參數的指標是assign或copy

//結論:method的參數是assign,也就是不做copy直接傳入指標

//確認參數的指標為copyassign
    NSMutableArray *array = [@[@1,@2] mutableCopy];
    [concept checkParameterPointer:array];
    NSLog(@"array : %@", array);

+ (void) checkParameterPointer:(NSMutableArray *)array{
    NSMutableArray *a = array;
    NSLog(@"1. a=%@", a);
    [a addObject:@5];
    NSLog(@"2. a=%@", a);

}

//執行結果
2014-05-22 18:15:40.349 ConceptComfirm[47546:60b] viewDidLoad
2014-05-22 18:15:40.362 ConceptComfirm[47546:60b] class : Concepts
2014-05-22 18:15:40.363 ConceptComfirm[47546:60b] 1. a=(
    1,
    2
)
2014-05-22 18:15:40.363 ConceptComfirm[47546:60b] 2. a=(
    1,
    2,
    5
)
2014-05-22 18:15:40.363 ConceptComfirm[47546:60b] array : (
    1,
    2,
    5
)
2014-05-22 18:15:40.389 ConceptComfirm[47546:60b] viewWillAppear
2014-05-22 18:15:40.448 ConceptComfirm[47546:60b] viewDidAppear

確認objective c的物件指標是assign或copy

//結論
對不能改變內容的物件(NSString, NSArray...)沒有差別,因為都是new一個新的;
對能改變內容的物件(NSMutableString, NSMutableArray...)差很多,如果assign是指到同一個記憶體位置,copy的話才會複製成另外一份。

//測試方法
    NSString *a = @"a";
    NSLog(@"1. a=%@",a);
    NSString *b = [a copy];
    NSString *c = a;
    b = @"b";
    a = @"c";
    NSLog(@"2. a=%@  b=%@  c=%@", a, b, c);
    
    NSMutableArray *aa = [@[@1,@2] mutableCopy];
    NSLog(@"1. aa=%@",aa);
    NSArray *bb = [aa copy];
    NSMutableArray *cc = aa;
    bb = @[@3,@4];
    [cc addObject:@5];

    NSLog(@"2. aa=%@  bb=%@  cc=%@", aa, bb, cc);

//執行結果
2014-05-22 17:26:25.285 ConceptComfirm[46837:60b] viewDidLoad
2014-05-22 17:26:25.286 ConceptComfirm[46837:60b] class : Concepts
2014-05-22 17:26:25.286 ConceptComfirm[46837:60b] 1. a=a
2014-05-22 17:26:25.286 ConceptComfirm[46837:60b] 2. a=c  b=b  c=a
2014-05-22 17:26:25.286 ConceptComfirm[46837:60b] 1. aa=(
    1,
    2
)
2014-05-22 17:26:25.286 ConceptComfirm[46837:60b] 2. aa=(
    1,
    2,
    5
)  bb=(
    3,
    4
)  cc=(
    1,
    2,
    5
)
2014-05-22 17:26:25.287 ConceptComfirm[46837:60b] viewWillAppear
2014-05-22 17:26:25.514 ConceptComfirm[46837:60b] viewDidAppear

盡量不要用#define來定義key的文字

應該要改用const NSString以避免可能發生文字覆蓋的錯誤
例如:
.h檔
#import <Foundation/Foundation.h>
extern NSString *SelectionSort;
extern NSString *InsertionSort;
extern NSString *BubbleSort;
@interface Algorithm : NSObject
@end

.m檔
#import "Algorithm.h"
@implementation Algorithm
const NSString *SelectionSort = @"SelectionSort";
const NSString *InsertionSort = @"InsertionSort";
const NSString *BubbleSort    = @"BubbleSort";

@end

以NSString形式寫入NSData

我要寫入Ble時,會先用文字格式給出命令,再轉為NSData寫入device
-(void) setGSensorParameter:(NSString*)parameter completion:(WriteValueResponse)completion{
    if (![_bleManager isConnected]) {
        return;
    }
    NSUInteger len = parameter.length;
    NSString* dataString = [[NSString alloc]initWithString:parameter];
    
    NSMutableData* data = [[NSMutableData alloc]init];
    if (dataString.length % 2 != 0) {
        dataString = [NSString stringWithFormat:@"0%@",dataString];
    }
    //逐字轉成Bytes
    for (int i = 0; i < len; i = i + 2)
    {
        NSRange range = NSMakeRange(i, 1);
        NSString *firstString = [dataString substringWithRange:range];
        range = NSMakeRange(i + 1, 1);
        NSString *secondString = [dataString substringWithRange:range];
        NSNumber* firstDigit = [NSNumber numberWithInt:[[DataManager unitDigitFromHexString:firstString] intValue] * 16];
        NSNumber* secondDigit = [DataManager unitDigitFromHexString:secondString];
        NSNumber* number = [NSNumber numberWithInt:[firstDigit intValue] + [secondDigit intValue]];
        
        unsigned char charNumber = [number charValue];
        [data appendBytes:&charNumber length:1];
        
    }
    //NSLog(@"data:%@",data);
    [_bleManager writeValueWithWithData:data
                         forServiceUUID:@"XXXX"
                     characteristicUUID:@"YYYY"
                           withResponse:completion];

}


+ (NSNumber *) unitDigitFromHexString:(NSString *)unitDigit{
    int number = 0;
    if ([unitDigit isEqualToString:@"a"] || [unitDigit isEqualToString:@"A"]) {
        number = 10;
    }
    else if ([unitDigit isEqualToString:@"b"] || [unitDigit isEqualToString:@"B"]) {
        number = 11;
    }
    else if ([unitDigit isEqualToString:@"c"] || [unitDigit isEqualToString:@"C"]) {
        number = 12;
    }
    else if ([unitDigit isEqualToString:@"d"] || [unitDigit isEqualToString:@"D"]) {
        number = 13;
    }
    else if ([unitDigit isEqualToString:@"e"] || [unitDigit isEqualToString:@"E"]) {
        number = 14;
    }
    else if ([unitDigit isEqualToString:@"f"] || [unitDigit isEqualToString:@"F"]) {
        number = 15;
    }
    else if (0 <= [unitDigit intValue] < 10)
    {
        NSNumber *result = [NSNumber numberWithInt:[unitDigit intValue]];
        return result;
    }
    else
    {
        return nil;
    }
    
    NSNumber *result = [NSNumber numberWithInt:number];
    return result;

}

2014年5月20日 星期二

iOS7 的main thread只是UI預設的執行緒,不是code的

為了要檢查get main queue的順序與值的對應關係,我寫了下列程式碼
__block int i = 1;
    NSLog(@"1. normal 1  i=%i",i);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"2. after two seconds  i=%i",i);
        i = 2;
    });
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"3. main thread 1  i=%i",i);
        i = 3;
    });
    NSLog(@"4. normal 2  i=%i",i);
    i = 4;
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"5. main thread 2  i=%i",i);
        i = 5;
    });

    NSLog(@"i =%i",i);

得到的結果如下,
2014-05-20 16:45:00.513 ConceptComfirm[25891:60b] viewDidLoad
2014-05-20 16:45:00.513 ConceptComfirm[25891:60b] class : Concepts
2014-05-20 16:45:00.514 ConceptComfirm[25891:60b] 1. normal 1  i=1
2014-05-20 16:45:00.514 ConceptComfirm[25891:60b] 4. normal 2  i=1
2014-05-20 16:45:00.514 ConceptComfirm[25891:60b] i =4
2014-05-20 16:45:00.515 ConceptComfirm[25891:60b] viewWillAppear
2014-05-20 16:45:00.652 ConceptComfirm[25891:60b] viewDidAppear
2014-05-20 16:45:00.652 ConceptComfirm[25891:60b] 3. main thread 1  i=4
2014-05-20 16:45:00.653 ConceptComfirm[25891:60b] 5. main thread 2  i=3
2014-05-20 16:45:02.516 ConceptComfirm[25891:60b] 2. after two seconds  i=5

結論是,iOS7已經不再將code預設執行的main thread
而是把UI用main thread去跑,你想要跑在main thread的code要自行宣告使用。

Note.
//創造一個新的執行緒
dispatch_queue_t _newQueue   = dispatch_queue_create("forCentralManagerOnly", DISPATCH_QUEUE_SERIAL);

2014年5月17日 星期六

在runtime決定你要用的class

Class concept = NSClassFromString(@"Concept");
    NSLog(@"class : %@", concept);
//如果找到了,會回傳class name;如果沒有,則回傳null

NSBundle的-classNamed:也是類似相同的功能。

2014年5月14日 星期三

如果只有開始跟結束的小時,要如何判斷是今日或昨日

NSCalendar *cal = [NSCalendar currentCalendar];
            NSDateComponents *sleepComps = [cal components:NSHourCalendarUnit | NSMinuteCalendarUnit fromDate:se.sleepDate];
            NSDateComponents *wakeUpComps = [cal components:NSHourCalendarUnit | NSMinuteCalendarUnit fromDate:se.wakeUpDate];
            date = [_displayDate startDayDate];
            if (sleepComps.hour > wakeUpComps.hour)

                date = [date dateByAddingTimeInterval:-86400];

2014年5月10日 星期六

在OS X Mavericks中打開FTP Server

//打開FTP
sudo -s launchctl load -w /System/Library/LaunchDaemons/ftp.plist
//關閉FTP
sudo -s launchctl unload -w /System/Library/LaunchDaemons/ftp.plist

2014年5月7日 星期三

簡述雜湊hash

把你的key經過hash function運算之後,會得到一個長度固定的數值,存入該數值編號的桶(bucket)中,如果有二個key以上的運算到相同的雜湊值,那就叫碰撞(collision),這時的解決方式就是存放在桶中另一個槽(slot),如果桶中的槽都滿時,又遇到碰撞,就叫溢位(over flow)