Sean's Note: iOS
顯示具有 iOS 標籤的文章。 顯示所有文章
顯示具有 iOS 標籤的文章。 顯示所有文章

2016年12月4日 星期日

要怎麼查看 iOS Simulator 上 App 的 NSUserDefault?

~Library/Developer/CoreSimulator/Devices/{Simulator Id}/data/Containers/Data/Application/{Application Id}/Library/Preferences/{App name}.plist

2016年3月23日 星期三

在 didFinishLaunchingWithOptions 時不使用 storyboard 直接載入 nib 檔

  
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] ;

     // Override point for customization after application launch.

     MyViewController *test = [[MyViewController alloc]     initWithNibName:@"MyViewController" bundle:nil];
     UINavigationController *nav = [[UINavigationController alloc]  initWithRootViewController:test];
     self.window.rootViewController = nav;

     [self.window makeKeyAndVisible];

     return YES;
  }

2016年2月11日 星期四

什麼是 Outlets 和 Referencing Outlets

在 IB 裡的 Show the Connections inspector 頁面,可以看到 Outlets 和 Referencing Outlets,每次基本一定要設定的就是 UIViewController 與 UIView 與之間的連接。

對於 UIViewController 來說,Outlets 可以說是底下的 view 和為 IBOutlet 的那些 properties,所以從圖1 中可以看到 UIViewController 有兩個 Outlets 分別為 view 和 simpleTableView 對應著這個 nib 檔中別名為 View 和 Simple Table View 的元件。而 Referencing Outlets 則為自己被外部的哪些 Objects 所引用,以圖1來說,因為這個 UIViewController 放了一個 UITableView,而 UITableView 擁有 dataSource 和 delegate 的 properties,需要讓他們引用 UIViewController,這也是為什麼需要讓 UIViewController 實作 UITableViewDelegate 和 UITableViewDataSource 。

圖1. File's Owner Connections

另外從 UITableView 的角度來看,他的 Outlets 則是 dataSource 和 delegate,而 Referencing Outlets 則是 simpleTableView。

圖2. UITableView Connections

2015年4月9日 星期四

Calculate UILabel for proper height

在多國語言中,最常見發現的問題就是字串 truncated,所以在拉 UILabel 時,
高就不能設死,如果設太小,落落長的語言如西文和德文,就會 truncated,
設太多又會讓簡短的繁簡中留有太多空白,這時就可以用計算的方式來設得剛剛好。
NSString 底下有個方法可以用來計算:

- boundingRectWithSize:options:attributes:context:

+ (CGFloat)getMaximalHeightForText:(NSString *)text withFont:(UIFont *)font withWidth:(CGFloat)width {
    CGRect frame = [text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) // Give CGFLOAT_MAX for height to calculate desired height.
                                      options:(NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) 
                                   attributes:@{NSFontAttributeName:font}
                                      context:nil];
    return frame.size.height+5; // 5 is added for compensation.
}

2015年3月27日 星期五

[iOS8] 隱私權設定

iOS 的隱私權,譬如說“相機”,一但被應用程式請求過,
在“設定”->“隱私權”-> “相機”的列表就會出現該應用程式,
而下次應用程式就無法在請求權限,使用者只能到設定去更改,
即使重新安裝也一樣。若開發時,想要測試,可以到“設定”->“一般”->“重置”->
“重置定位服務與隱私權”去重置設定,這樣應用程式就可以再次請求使用者。

2015年2月17日 星期二

initWithNibName 和 loadNibNamed 方法的區別

initWithNibName 和 loadNibNamed 都可以用來建立 Custom ViewController,
// 延遲載入,用到時才會值
MyViewController *viewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];

MyViewController *viewController = [[[NSBundle mainBundle] loadNibNamed:@"MyViewController" owner:self options:nil] objectAtIndex:0];

但是在 NIB 上的設定會有不同:
用 initWithNibName 的 XIB 需要在 Placeholders 設置 File's Owner 的 Custom Class,
View Controller 則不須設置 Custom Class。而且拉的元件是 UIView。
反之,用 loadNibNamed 的 XIB 不能在 Placeholders 設置 File's Owner 的 Custom
Class,而 View Controller 則須設置 Custom Class。而且拉的元件是 UIViewController。
若兩者誤用,就會跑出 setValue:forUndefinedKey 的錯誤。

2015年2月10日 星期二

Core Data framework

Managed Objects and Contexts

可以把 managed objects contexts 想像成是智慧型的便條紙,
當從 persistent store 獲取資料時,這些資料的副本就會記錄在便條紙上,
並形成 object graph,這些副本可以被修改,直到儲存後 persistent store
也才會真的改變。
Model objects(詳見 MVC Pattern) 在 Core Data framework 中即是
managed objects,所有的 managed objects 都須向 managed object context
註冊,不管新增或移除 objects 都是透過 context。
每個 Application 可以有多個 managed object context 。

參考: http://www.cocoanetics.com/2012/07/multi-context-coredata/

Fetch Requests

可以建立 fetch requests(NSFetchRequest) 向 managed object context 擷取資料,
由於所有的 managed objects 都須向 managed object context 註冊,所以這些回
傳的 objects 將自動與請求的 context 註冊。

Persistent Store Coordinator

介於 managed objects contexts 和 persistent object stores 的是 persistent store
coordinator(圖1),

圖1. (來源: iOS Developer Library)



2014年11月18日 星期二

[iOS8] How to show menu(Cut, Copy, Paste or custom action) when long pressing the cell of UITableView?

如果是用 UITableViewCell,只需要 override 三個方法:

//
// CustomUITableView.m
//

- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

//
// CustomUITableView.m
//

- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

-(BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    return YES;
}

//  Need to override even perform nothing.
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    if (action == @selector(copy:)) {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];
        [pasteBoard setString:cell.textLabel.text];
    }
}

長按 cell 後就會跳出 Cut, Copy 和 Paste:

圖1. UIMenuController

但如果要設定自己的 menu item 如果不 subclass UITableCellView,長按 cell 也只會跳出 

Cut, Copy 和 Paste,不會看到自己透過 setMenuItems 所加入的 UIMenuItem。

這時就需要 subclass UITableCellView:

//
// CustomUITableView.m
//

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    UIMenuItem *testMenuItem = [[UIMenuItem alloc] initWithTitle:@"Test" action:@selector(test:)];    
    [[UIMenuController sharedMenuController] setMenuItems: @[testMenuItem]];
    [[UIMenuController sharedMenuController] update];
}

//
// CustomUITableViewCell.m
//

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
     NSLog(@"CustomTableViewCell: %@\n", NSStringFromSelector(action));
    // There will be lots of default items if don't check.
    if (action == @selector(copy:) || action == @selector(test:))
        return YES;
    return NO;
}

// It's said need to be overrode from forums, but test ok without overriding it.
//-(BOOL)canBecomeFirstResponder {
//    return YES;
//}

/// this methods will be called for the cell menu items
-(void) test: (id) sender {
    NSLog(@"CustomTableViewCell: test!");
}

2014年11月12日 星期三

How to get asset's information from the device?

在 iOS 4.0 之後,ALAsset 這個類別提供了 - valueForProperty 方法來取得 asset 的資訊,

文件裡定義了八種:

NSString *const ALAssetPropertyType ;
NSString *const ALAssetPropertyLocation ;
NSString *const ALAssetPropertyDuration ;
NSString *const ALAssetPropertyOrientation ;
NSString *const ALAssetPropertyDate ;
NSString *const ALAssetPropertyRepresentations ;
NSString *const ALAssetPropertyURLs ;
NSString *const ALAssetPropertyAssetURL;
咦?怎麼沒有名稱 Name 呢?

想要取得名稱和檔案大小其他的資訊得透過 ALAssetRepresentation 來取得。

ALAssetRepresentation *rep = [asset defaultRepresenttion];
[rep filename];
[rep size];

2014年11月11日 星期二

[Xcode 6.1] Be careful with the order of "First Item" and "Second Item" when editing constraint

根據官方的文件, space constraint 的數學公式如下:

FirstItem.Attribute1 = (SecondItem.Attribute2 * Multiplier) + Constant

所以對調 "First Item" 跟 "Second Item" 的結果將會不同,

以圖1 為例 Superview.Trailing = (Text Filed.Trailing * 1 ) + 10,

代表有一個 Text Filed 元件的右邊將會置於父視圖的右邊數來 10 個單位距離。

圖1. Space Constraint
但若將兩者對調,將變成 Text Filed.Trailing = ( Superview.Trailing* 1 ) + 10,

最後的結果,Text Filed 元件右邊的位置將會超出父視圖的範圍。

Ref: https://developer.apple.com/library/ios/recipes/xcode_help-IB_auto_layout/chapters/EditingConstraintAttributesintheAttributesInspector.html

[Xcode Common Errors] Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' ...

當 console 出現下列訊息時:

Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set?

檢查看看第一個 View Controller 的 Attributes Inspector 頁面 "Is Initial View Controller"

是否忘了勾選?

圖1. Attributes Inspector