2014年8月19日星期二

NSDictionary key sort

NSDictionary 似乎無法sort, 要轉成 Array.

example 1:
NSArray *keys = [myDictionary allKeys];
keys = [[keys mutableCopy] sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
上面這個 example 會 show error, 什麼 _strong 之類的 error.


example 2:
NSArray* sortedKeys = [myDict keysSortedByValueUsingSelector:@selector(comparator)];
這個範例是OK, for non-object value.
for Object Value 會 show error:

Exception: -[MyObject comparator]: unrecognized selector sent to instance 0x156a9ec0

example 3:
下面的範例,如果 dictionary 裡放的是 object, 使用 allValues 會比較有問題。
NSArray *sortedValues = [[yourDictionary allValues] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSMutableDictionary *orderedDictionary=[[NSMutableDictionary alloc]init];
for(NSString *valor in sortedValues){
    for(NSString *clave in [yourDictionary allKeys]){
        if ([valor isEqualToString:[yourDictionary valueForKey:clave]]) {
            [orderedDictionary setValue:valor forKey:clave];
        }
    }
}


取object 的 sample:

MyObject *data = [[myDictionary allValues] objectAtIndex:accessIndex];


NSDictionary如同hash table,它的key是沒排序過,查了下,其實可以用變通方式

Step 1: 先將Key排序做成一個array
NSArray * sortedKeys = [[keys allKeys] sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)]; 

Step 2: 使用時用做出來的array來遞迴取出
for( Object *ob in sortedKeys ) {
    //你想做的事

這樣就是排好的了.

結論就是,透過objectAtIndex 來存取 dictionary 一定會是亂的!
要馬就是把 dictionary 先 sort 好存到一個 Array,放 table view access, 或是每次在 table view 裡 access 亂亂的 dictionary 時都 sort 一次。

2014年8月18日星期一

NSMutableString

寫了1年的Objective-C 程式才發現 string 分2種 NSString &NSMutableString,在class 裡 access 呼叫主程式裡的 memory 需要主程式變數加 __block, 或是傳回一個新的 string memory address 回去主程式。

NSMutableString 的 sample.

1. string to NSMutableString:
NSMutableString *string1;

string1 = [NSMutableString stringWithString: @"This is a string"];


2. search:
NSString *string1 = @"The quick brown fox jumped";

NSRange match;

match = [string1 rangeOfString: @"brown fox"];

NSLog (@"match found at index %lu", match.location);
NSLog (@"match length = %lu", match.length);


check  NSNotFound:
NSString *string1 = @"The quick brown fox jumped";

NSRange match;

match = [string1 rangeOfString: @"brown dog"];

if (match.location == NSNotFound)
          NSLog (@"Match not found");
else
          NSLog (@"match found at index %lu", match.location);


3 Replace:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];

[string1 replaceCharactersInRange: NSMakeRange(16, 3) withString: @"squirrel"];

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


4 Delete:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];

[string1 deleteCharactersInRange: [string1 rangeOfString: @"jumped"]];

由於是使用 Range, 所以也可以直接使用:NSMakeRange(from index, to index), ex:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];
NSString *string2;

string2 = [string1 substringWithRange: NSMakeRange (4, 5)];

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


5 Insert:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];

[string1 insertString: @"/" atIndex: 0];


6 Append:
NSMutableString *string1 = [NSMutableString stringWithString: @"The quick brown fox jumped"];

[string1 appendString: @" over the lazy dog"];

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



2014年8月13日星期三

Clear app cache and temp files from iOS devices

用了一陣子 iOS App Document 目錄只有 39mb, 但 /tmp 居然長大到800mb. 試看看下面的解法:

+ (void)clearTmpDirectory
{
    NSArray* tmpDirectory = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL];
    for (NSString *file in tmpDirectory) {
        [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), file] error:NULL];
    }
}

只清 JPG 格式的範例:
NSString *tempPath = NSTemporaryDirectory();
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:tempPath];
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self ENDSWITH '.jpg'"]];

NSFileManager *fileManager = [NSFileManager defaultManager];

if (onlyJPGs) { 
    for (int i = 0; i < [onlyJPGs count]; i++) {
    NSLog(@"Directory Count: %i", [onlyJPGs count]);
    NSString *contentsOnly = [NSString stringWithFormat:@"%@%@", tempPath, [onlyJPGs objectAtIndex:i]];
    [fileManager removeItemAtPath:contentsOnly error:nil];
}

White Space and Dot in file system

沒有遇到過, 還不知道空格(Space) 和 點(Dot) 在 windows file system 裡這麼有趣, 是trim right, 真是有夠雞婆的 Microsoft.

透過 mkdir ".../" & mkdir " a /" 可以建立出 "..." 資料夾和空格結尾的資料夾, 要移除就是 rmdir 就可以了.


This fore case make you easy understand the file system difference:

  • ex1: user-portal allow create "...." folder name, but windows will fail and cause many problems, in Mac, prefix "." means hidden file or folder, by default user is not able to see .
  • ex2: Mac allow create "?" in filename, Windows not allow.
  • ex3: Mac allow create " b ", Windows only allow " b".
  • ex4: Mac allow create ".a.", Windows only allow ".a"


user is able to create prefix with white space in windows and mac.

The behavior of "rename and create item on windows explorer GUI interface is trim left and right  white spaces.

Mac allow to create " a " folder, but when user create (or rename as) " a " folder in dropbox sync folder, dropbox will rename " a " as " a" (trim right space) for reducing the conflict or for Windows version able to sync more file.

About dot symbol in postfix in Dropbox, Mac version, dropbox do nothing under sync folder, so " a" and " a." is different folder.Windows version, dropbox will ignore any item that dot symbol in postfix.

這個bug 比想像中的有趣, 如果下這行指令:
rm C:\Users\max\myRoot\...

被刪除的並不是 \myRoot\...\, 而是整個 \myRoot\ 全部不見!

2014年8月11日星期一

__block

原來,如果外部的變數,要該 funtion block access 要在型別之前,多加一個 __block.

ex:
    __block NSUInteger failedAttempts = 0;
    return (BZPasscodeViewControllerHandler)^(NSString *enteredPasscode, NSString **text, NSString **detailText, BOOL *detailTextHighlighted) {
        if (![enteredPasscode isEqualToString:passcode]) {

            failedAttempts++;

        };
    );

2014年8月10日星期日

MS-FAT time in Mac OS

遇到很有趣的bug, 在 Mac OS 開始 copy 檔案進去儲存裝置(HD/USB/Samba)時, 如果是64位元的檔案系統, 在檔案還沒被完全寫入時, Mac 會先給暫存檔的檔案日期為 1904-01-01 00:00:00, 如果是32位元的檔案系統會寫入 2040-02-06 06:28:16 +0000. 萬一檔案的日期是 2041年之後的話, 是無法寫入 32位元的檔案系統, 會寫成 2038年.

在解問題時才發現檔案系統的極限. MS-FAT 32位元檔案系統的日期區間: 1904-01-01 00:00:00 ~ 2040-02-06 06:28:16.



相關文章:

2014年8月6日星期三

UIActionSheet - Dynamic Button Titles

滿實用的寫法, 動態增加 ActionSheet buttons.


The easiest way to do this that I have found is initially create your action sheet with no buttons, including no cancel or destructive button:
UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle:@"Dynamic"
                                                        delegate:self
                                               cancelButtonTitle:nil
                                          destructiveButtonTitle:nil
                                               otherButtonTitles:nil];
Then add a load of buttons as needed:
if(buttonX)
{
    [actionSheet addButtonWithTitle:@"Button X"];
}
if(buttonY)
{
    [actionSheet addButtonWithTitle:@"Button Y"];
}
if(buttonZ)
{
    [actionSheet addButtonWithTitle:@"Button Z"];
}
Then finally add the cancel button at the end and set the cancel button index:
[actionSheet addButtonWithTitle:@"Cancel"];
actionSheet.cancelButtonIndex = actionSheet.numberOfButtons - 1;
Of course you can add both a cancel button and/or a destructive button in this way.