2015年6月11日 星期四

NSData , NSMutableData 互相轉換

由於是接別人的 code, 我也不知道 mutable 和 immutable 的差別, 目標就是把程式改到沒有 warning. 最後還是算了, warning 是一件正常的事情, 假裝沒看到.


NSData to NSMutableData:


NSData *_data = [[NSData alloc] init];
NSMutableData *_mdata = [NSMutableData dataWithData:_data];


NSMutableData to NSData:

NSMutableData *mutData = [[NSMutableData alloc] init];
//Giving some value to mutData
NSData *immutableData = [NSData dataWithData:mutData];
上面這樣子寫, 會有 warning, 因為 muData 是 NSMutableData, NSData input要的資料是 NSData.

這篇文章, 有講直接轉和使用 object copy 的差別, 差在 lifetime,
http://stackoverflow.com/questions/6835884/is-it-okay-to-call-nsdata-datawithdata-with-an-nsmutabledata-object

This is completely okay, and is in fact one of the primary uses of dataWithData: -- to create an immutable copy of a mutable object.*
NSData also conforms to the NSCopying protocol,** which means you could instead use [mutData copy]. The difference is that dataWithData: returns an object you do not own (it is autoreleased), whereas per memory management rulescopy creates an object for whose memory you areresponsible. dataWithData: is equivalent in effect to [[mutData copy] autorelease].
So you can choose either dataWithData: or copy, dependent upon your requirements for the lifetime of the resulting object.

*This also applies to similar methods in other classes which have a mutable subclass, e.g., +[NSArray arrayWithArray:].
**See also "Object Copying" in the Core Competencies Guide.




NSData的創建:實例與class方法


  • data:創建一個不包​​含任何數據的空的NSData對象
  • dataWithBytes:length:/initWithBytes:length::複製C數組所包含的數據來初始化NSData的數據
  • dataWithBytesNoCopy:length:/initWithBytesNoCopy:length:直接利用C數組所包含的數據來初始化NSData對象。當該對像被執行malloc方法銷毀自己時,程序會釋放該C數組
  • dataWithBytesNoCopy:length:freeWhenDone:/initWithBytesNoCopy:length:freeWhenDone::直接利用C數組所包含的數據來初始化NSData對象,只有當最後一個參數為YES,且該對像被執行malloc方法銷毀自己時,程序才會釋放該C數組
  • dataWithContentsOfFile:/initWithContentsOfFile::直接讀取文件內容,並利用文件內容來初始化NSData
  • dataWithContentsOfURL:/initWithContentsOfURL::直接讀取URL關聯內容,並利用該URL關聯的內容來初始化NSData
  • dataWithData:/initWithData::直接使用另一個NSData所包含的數據來初始化新創建的NSData


訪問NSData數據內容


  • bytes:返回該NSData所包含的數據
  • getBytes:length:獲取NSData所包含的指定長度的數據
  • getBytes:range::獲取NSData所包含的指定範圍的數據
  • subdataWithRange::獲取NSData所包含的指定範圍的數據組成的NSData對象
  • writeToFile:atomically::將NSData數據寫入文件
  • writeToURL:atomically::將NSData數據寫入指定URL的資源



ex:
#import <Foundation/Foundation.h>

int main(int argc , char * argv[])
{
@autoreleasepool{
NSData* data = [NSData dataWithContentsOfURL:
[NSURL URLWithString:@"http://tw.yahoo.com"]];
NSLog(@"%ld" , [data length]);
char buffer[100];
[data getBytes:buffer range: NSMakeRange(103, 100)];
NSLog(@"%s" , buffer);
NSString* content = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"----------輸出網頁內容---------");
NSLog(@"%@" , content);
}
}



2015年6月10日 星期三

Cenerate App Icons 產生App需要的圖示

這個  Makeappicon 網站真的很棒, 完全是寫給工程師用的, 省下了很多去 resize icon 的時間.

隨手選一張圖片上傳到網頁裡.


過幾秒後, 輸入 eMail 給他, 檔案就會寄到 email 裡了. 真的很貼心, 還把我們的icon 放到 apple watch 還有iphone 裡preview.


針對 Android 的用戶, 下面這個 tab 是做假的, 寄到 email 裡的 zip 檔, 有3個 folder, 分別是給  iOS/AppleWath 和 Android.


get the current version of my ios project in code?

You can try using the infoDictionary
NSDictionary *infoDictionary = [[NSBundle mainBundle]infoDictionary];

NSString *build = infoDictionary[(NSString*)kCFBundleVersionKey];
NSString *bundleName = infoDictionary[(NSString *)kCFBundleNameKey]; 

相關文章:

How to get app's product name at runtime


2015年6月8日 星期一

Fix "Open In..." not work bug

現在部門的主管, 在使用自家開發的App時發現, 別的App要上傳檔案到自家App時, 這個功能失效.

我立馬拿 device (iPad/iPhone) 出來 reproduce, 結果都試不出來. @_@; (汗)

最後找出原因了, 由於用 xcode build & run application 時, 我們的 app 已 launch, 這個bug 是發生在, 透過 Open In... (OpenURL) 的方式, 把 App 叫起來時, 會造成, 解法有2:

1. 比較萬無一失的 (優良解法):

弄一個 UINavigationContorller 呼叫其 popToRootViewController, 再存取其 FileUploadViewController 執行 upload 的動作.


2. 懶人解法.

2-1. 把 openurl 的 temp 檔案 copy 進去 sandbox 的 cache 目錄.
(這個很神奇, copy 進 tmp 目錄, 會顯示 file not found)
2-2. delay 1 second 後, 再 pop upload file dialog.
(這個也很神奇, 我試過很多數字, 不 delay 會造成 dialog 太早彈出被蓋過去)

還有要注意的是, 要 dispatch to main queue 裡來 pop.


相關文章:

https://github.com/haiwen/seafile-iOS

2015年5月22日 星期五

UIPageControl 使用心得

這個元件用起來真方便, 一般的情況下, 就是設個總筆數, 目前筆數, 給他就做完了. 進階一點點需要修改, 作用中 indicatore 顏色, 非作用中的顏色, 還有設定其大小.

在 Mac App 的 xcode 裡, 預設沒有這個元件, 但有很多人做了類似的元件, 可以直接拿來用.



修改顏色, 最佳解法參考看看:
Create a UIColor from a hex string
http://ios-imaxlive.blogspot.tw/2015/04/create-uicolor-from-hex-string.html



2015年5月11日 星期一

Ineligible Devices section appeared in Xcode 6.3

之前用的好好的 Device (iPad), 在 xcode 升級到 v6.3.1後, 居然顯示為不能用(ineligible device), 如下圖:



Step 1: 重開 Mac, 還有 iPad, 結果一樣.
Step 2: 升級 iPad 裡的 iOS 版本到最新版, 結果一樣.
Step 3: Go to the Product Menu > Destination and select your device. It will be listed under "Ineligible", but you will still be able to select it. After doing this, I was able to build and deploy to my device.



這個部驟, 應該可以解決大多的情況, 但我還是不行.

結果, 拿掉 device (iPad), 單純按 Command+B, 來 build build 看, 發現是因為在實作了 FileProvider, 所以有額外的2個 code signing 還要去設定, 一次要設定3組 target (主程式一組, FileProvder 有2組), 都設定為讓 xcode automatic 去 select 就OK了.



相關文章:

Ineligible Devices section appeared in Xcode 6.x.x
http://stackoverflow.com/questions/24039010/ineligible-devices-section-appeared-in-xcode-6-x-x/29538173#29538173

Xcode 6.3 showing Ineligible Device
http://stackoverflow.com/questions/29667752/xcode-6-3-showing-ineligible-device

2015年5月3日 星期日

How to get app's product name at runtime

由於經常需要修改App名稱, 而且在程式裡多處都需要顯示 App Product name, 在程式裡動態取得Product name 方法如下, 比較懶的人, 可以使用一行的這個版本:


[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];

分解開來的版本:
    NSBundle *bundle = [NSBundle mainBundle];
    NSDictionary *info = [bundle infoDictionary];
    NSString *prodName = [info objectForKey:@"CFBundleDisplayName"];



Facebook 留言