2013年12月27日 星期五

在yourApp-Prefix.pch中加入你要引用的.h檔,即可以自動引用到每一個Class中

#import <Availability.h>

#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>

#include "Define.h"    //<===加在這
#include "KSMacros.h"  //<===加在這
#include "Singleton.h" //<===加在這


#endif

2013年12月25日 星期三

可以在關閉App後仍能保存物件的NSUserDefaults


//儲存到NSUserDefaults 
-(void)saveNSUserDefaults 
NSString *myString = @"enuola"; 
int myInteger = 100; 
float myFloat = 50.0f; 
double myDouble = 20.0; 
NSDate *myDate = [NSDate date]; 
NSArray *myArray = [NSArray arrayWithObjects:@"hello", @"world", nil]; 
NSDictionary *myDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"enuo", @"20", nil] forKeys:[NSArray arrayWithObjects:@"name", @"age", nil]]; 

//將上面的物件儲存到NSUserDefaults中 
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 
//除NSNumber需用對應的型別以外,其他的都是使用setObject:forKey: 
[userDefaults setInteger:myInteger forKey:@"myInteger"]; 
[userDefaults setFloat:myFloat forKey:@"myFloat"]; 
[userDefaults setDouble:myDouble forKey:@"myDouble"]; 

[userDefaults setObject:myString forKey:@"myString"]; 
[userDefaults setObject:myDate forKey:@"myDate"]; 
[userDefaults setObject:myArray forKey:@"myArray"]; 
[userDefaults setObject:myDictionary forKey:@"myDictionary"]; 

//建議同步,但是不是必須的 
[userDefaults synchronize]; 


//從NSUserDefaults讀取資料 
-(void)readNSUserDefaults 
NSUserDefaults *userDefaultes = [NSUserDefaults standardUserDefaults]; 

//讀取數據到各個label中 
//讀取整型int類型的數據 
NSInteger myInteger = [userDefaultes integerForKey:@"myInteger"]; 
txtInteger.text = [NSString stringWithFormat:@"%d",myInteger]; 

//讀取浮點型float類型的數據 
float myFloat = [userDefaultes floatForKey:@"myFloat"]; 
txtFloat.text = [NSString stringWithFormat:@"%f",myFloat]; 

//讀取double類型的數據 
double myDouble = [userDefaultes doubleForKey:@"myDouble"]; 
txtDouble.text = [NSString stringWithFormat:@"%f",myDouble]; 

//讀取NSString類型的數據 
NSString *myString = [userDefaultes stringForKey:@"myString"]; 
txtNSString.text = myString; 

//讀取NSDate日期類型的數據 
NSDate *myDate = [userDefaultes valueForKey:@"myDate"]; 
NSDateFormatter *df = [[NSDateFormatter alloc] init]; 
[df setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; 
txtNSDate.text = [NSString stringWithFormat:@"%@",[df stringFromDate:myDate]]; 

//讀取數組NSArray類型的數據 
NSArray *myArray = [userDefaultes arrayForKey:@"myArray"]; 
NSString *myArrayString = [[NSString alloc] init]; 
for(NSString *str in myArray) 
NSLog(@"str= %@",str); 
myArrayString = [NSString stringWithFormat:@"%@ %@", myArrayString, str]; 
[myArrayString stringByAppendingString:str]; 
// [myArrayString stringByAppendingFormat:@"%@",str]; 
NSLog(@"myArrayString=%@",myArrayString); 
txtNSArray.text = myArrayString; 

//讀取字典類型NSDictionary類型的數據 
NSDictionary *myDictionary = [userDefaultes dictionaryForKey:@"myDictionary"]; 
NSString *myDicString = [NSString stringWithFormat:@"name:%@, age:%d",[myDictionary valueForKey:@"name"], [[myDictionary valueForKey:@"age"] integerValue]]; 
txtNSDictionary.text = myDicString; 
}

在block中要使用self的正確方式

//在進去之前要把它設為weak,讓self消失時,block中的self也跟著消失
//在進之之後要把它設為strong,讓self在block執行時,不會自行消失
__weak typeof(self) weakSelf = self;
    [_bleManager setReadingValueCompletion:^(NSData *responseData) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        strongSelf.showResult.text = [NSString stringWithFormat:@"%@",responseData];
        [strongSelf.receivedData appendData:responseData];

    }];

//在swift中使用
weak let weakSelf = self
或者在closure開頭加上[weak self]
在closure裡就直接使用self?
例如
dispatch_async(dispatch_get_main_queue(), { [weak self] () -> Void in
            self?.chatMessageTableView.reloadData()

        })

2013年12月24日 星期二

從某字串以後重新抓取字串

NSRange search = [value rangeOfString:@"#*s$"];
value = [value substringFromIndex:search.location];

直接宣告為singleton的.h

到時只要import這個.h,就可以用這個方法宣告

#define SYNTHESIZE_SINGLETON_FOR_HEADER(className) \
\
+ (className *)shared##className;

#define SYNTHESIZE_SINGLETON_FOR_CLASS(className) \
\
+ (className *)shared##className { \
static className *shared##className = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
shared##className = [[self alloc] init]; \
}); \
return shared##className; \

}

iOS7似乎是little-endian

因為我一開始想對<dd07>做swap之後再印出數值,結果是65XXX多少的,後來把swap拿掉,就印出我真正想要的數字2013

//以下為程式碼
    NSData *myData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Test" ofType:@"bin"]];
    
    NSLog(@"myData:%@",myData);
    NSRange range = NSMakeRange(0, 2);
    NSLog(@"year data:%@",[myData subdataWithRange:range].description);
    NSData* yearData = [myData subdataWithRange:range];
    unsigned short x;
    [yearData getBytes:&x length:sizeof(x)];
    NSLog(@"x:%x",x);
    //unsigned short year = [self swap:x];
    NSLog(@"year:%hu",x);

year data:<dd07>
x:7dd
year:2013

-(UInt16) swap:(UInt16)s {
    NSLog(@"swap");
    UInt16 temp = s << 8;
    NSLog(@"%x",temp);
    temp |= (s >> 8);
    NSLog(@"%x",temp);
    return temp;
}

//20140207發現
iOS7在寫入時,不會自動換成little-endian
所以結論是,
讀取時,是以little-endian的方式直接讀取data
寫入時,是以data的格式直接寫入,所以要先swap成little-endian的排列,再寫入。

用NSData直接操作binary data

//下列這五個是你會用到的NSData方法
//將另一個NSData加到原來的NSData後面
-(void)appendData:(NSData*)otherData

//將bytes直接加入NSData,參數為1.bytes的起始位置(要加&),2.bytes的長度
-(void)appendBytes:(const void*)bytes length:(NSUInteger)length

//截取其中某一段NSData
-(NSData*)subdataWithRange:(NSRange)range

//從你的NSData中copy某段bytes出來,存到你新建的buffer(要加&)中(存數值資料,而非NSData)
-(void)getBytes:(void*)buffer range:(NSRange)range

//從你的NSData中從頭copy某段指定長度的bytes出來,存到你新建的buffer(要加&)中(存數值資料,而非NSData)
-(void)getBytes:(void*)buffer length:(NSUInteger)length

//底下是一些範例
//直接取得binary檔案
NSURL *imgPath = [[NSBundle mainBundle] URLForResource:@"yourBinary" withExtension:@"bin"];
        NSString *stringPath = [imgPath absoluteString];

        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:stringPath]];

//要把NSData轉回NSNumber時(這裡是以short為範例)
  short s;
  [yourData getBytes:&s range:range];
  NSNumber* stepCount = [NSNumber numberWithUnsignedShort:s];


// low level read method - read data while there is data and space available in the input buffer
- (void)_readData
{
    uint8_t buf[EAD_INPUT_BUFFER_SIZE];
    while ([[_session inputStream] hasBytesAvailable])
    {
        NSInteger bytesRead = [[_session inputStream] read:buf maxLength:EAD_INPUT_BUFFER_SIZE];
        if (_readData == nil)
        {
            _readData = [[NSMutableData alloc] init];
        }
        [_readData appendBytes:(void *)buf length:bytesRead];
        //NSLog(@"read %d bytes from input stream", bytesRead);
    }
    
    [[NSNotificationCenter defaultCenter] postNotificationName:EADSessionDataReceivedNotification object:self userInfo:nil];

    //清空_readData
    if( _readData )
    {
        [_readData setLength:0];
    }
}


// high level read method
// 這裡輸入的參數為你想要切的長度。
- (NSData *)readData:(NSUInteger)bytesToRead
{
    NSData *data = nil;
    if ([_readData length] >= bytesToRead)
    {
        NSRange range = NSMakeRange(0, bytesToRead);
        data = [_readData subdataWithRange:range];
        [_readData replaceBytesInRange:range withBytes:NULL length:0];
    }
    return data;
}

// get number of bytes read into local buffer

-(NSUInteger)readBytesAvailable
{
    return [_readData length];

}

//自己寫的切封包
+ (NSArray*)splitDataIntoChunks:(NSData*)data size:(NSUInteger)bytesPerChunk{
    
    if(!data) return nil;
    
    NSMutableArray* array = [[NSMutableArray alloc]init];
    NSUInteger dataLength = [data length];
    NSUInteger chunkCount = 0;
    while (chunkCount < dataLength)
    {
        NSRange range = NSMakeRange(chunkCount, bytesPerChunk);
        NSData* chunk = [data subdataWithRange:range];
        [array addObject:chunk];
        chunkCount += 2;
    }

    return array;

}