Objective-C Cheat Sheet


頻繁に使う割には覚えていられない。たまにしか使わないんだけど探すのが面倒。そんなSnippet Codeだけを集めています。
#Size

##構造体のシリアライズ
`CGRect` `CGSize` `CGPoint`のシリアライズ方法。

```objectivec
NSLog(@"%@", NSStringFromCGRect(self.view.frame));
NSLog(@"%@", NSStringFromCGPoint(self.view.frame));
NSLog(@"%@", NSStringFromCGSize(self.view.frame));
```

`NSStringFromXXX` で `NSString` に変換したものは `XXXFromString` で逆変換ができる。

```objectivec
CGRect  theRect  = CGRectFromString(rectString);
CGRect  theSize  = CGSizeFromString(sizeString);
CGPoint thePoint = CGPointFromString(pointString);
```

#Device

##Main ScreenのCGRectを得る
```objectivec
CGRect  deviceScreenRect = [[UIScreen mainScreen] bounds];
```

##Deviceの向きをチェックする
```objectivec
UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if ( UIInterfaceOrientationIsPortrait(interfaceOrientation) ){
    // portrate
}
else if( UIInterfaceOrientationIsLandscape(interfaceOrientation) ){
    // landscape
}
```

##3.5inch判定
```objectivec
CGRect deviceScreenRect = [[UIScreen mainScreen] bounds];
BOOL inch35 = (deviceScreenRect.size.height == 480)? YES : NO;
```
##起動時の言語環境チェック
```objectivec
NSString *lang = [[NSLocale preferredLanguages] objectAtIndex:0];
```

`lang` は `ISO 639-x/IETF BCP 47` [http://www.rfc-editor.org/rfc/bcp/bcp47.txt](http://www.rfc-editor.org/rfc/bcp/bcp47.txt) に基づいた言語コードである。

#File Management
##Directory
絶対パスを使って複数の階層のディレクトリをワン・メソッドで作る。

```objectivec
NSFileManager *manager = [NSFileManager defaultManager];
if ( ! [manager fileExistsAtPath:[url path] isDirectory:NULL]) {
    NSError *error;
    [manager createDirectoryAtURL:url withIntermediateDirectories:YES attributes:nil error:&error];
    if (error != nil) {
        return;
    }
}
```

#String

##format書式制御
|%@|文字|
|----|----|
|%c|一つの文字|
|%d|intを符号付き10進数で表示|
|%o|intを符号付き8進数で表示|
|%u|intを符号なし10進数で表示|
|%x|intを符号なし16進数で表示「abcdef」を使用|
|%X|intを符号なし16進数で表示「ABCDEF」を使用|
|%e|doubleを[-]d.dddd e [+/-]dddの指数表示|
|%f|doubleを[-]dddd.ddddで表示|
|%.2f|doubleを小数点第２位まで表示する|
|%.1f	|doubleを小数点第１位まで表示する|
|%g|doubleをeかfのうち、表現できる制度で短い方で表示|
|%s|文字列を最初のNULL文字まで表示|
|\n|改行|
|\r|　|

```objectivec
NSString *timetamp = [NSString stringWithFormat:@"%d/%02d/%02d %02d:%02d:%02d",
                                   	compo.year, compo.month,  compo.day,
                                   	compo.hour, compo.minute, compo.second];
```

##NSStringの指定した一文字を得る。
`NSString` から `characterAtIndex:` メソッドを使って指定した位置の一文字を取得したい。

```objectivec
NSString *anyCharacter = [NSString stringWithFormat:@"%C", [anyString characterAtIndex:7]];
```


#Date

##NSDateFormatter


|Symbol|Description|Symbol|Description|
|----|----|----|----|
|yy|年（下2桁）|H|時（ゼロ埋めなし）|
|yyyy|年（4桁）|HH|時（2桁ゼロ埋めあり）|
|MM|月（1〜12）|m|分（ゼロ埋めなし）|
|MMM|月（Jan）|mm|分（2桁ゼロ埋めあり）|
|MMMM|月（Janualy）|s|秒（ゼロ埋めなし）|
|d|日（ゼロ埋めなし）|ss|秒（2桁ゼロ埋めあり）|
|dd|日（2桁ゼロ埋めあり）|z|タイムゾーン|


```objectivec
- (NSString *)timeStamp
{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"HH:mm:ss / EEEE, MMMM d, yyyy"];
    NSString *dayString = [dateFormatter stringFromDate:[NSDate date]];
    
    return dayString;
}
```

Result:

```
16:47:54 / Monday, August 4, 2014
```


```objectivec
- (NSString *)timeStamp
{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy_MM_dd_EEEE HH_mm_ss"];
    NSString *dayString = [dateFormatter stringFromDate:[NSDate date]];
    
    return dayString;
}
```

Result:

```
2014_08_04_Monday 16_47_54
```




#Appearance

##Layerに影を付ける
```objectivec
CALayer *subLayer  = self.layer;
UIBezierPath *path = [UIBezierPath bezierPathWithRect:
                      CGRectMake(0, 0, subLayer.bounds.size.width, subLayer.bounds.size.height)];
subLayer.shadowOffset  = CGSizeMake(2.5, 2.5);
subLayer.shadowColor   = [[UIColor blackColor] CGColor];
subLayer.shadowOpacity = 0.1;
subLayer.masksToBounds = NO;
subLayer.shadowPath    = [path CGPath];
```

`masksToBounds` が `NO` の場合はフレームからはみ出している部分の陰も描画される。

##CoreGraphicsでの色指定
UIColorの色成分をそれぞれ取り出して `CGContextSetRGBFillColor ` 関数で設定してもよいが、

```objectivec
CGFloat red, green, blue, alpha;
[anyColor getRed:&red green:&green blue:&blue alpha:&alpha];
CGContextSetRGBFillColor(context, red, green, blue, alpha);
```

`CGContextSetFillColorWithColor` なら一行で書ける。

```objectivec
CGContextSetFillColorWithColor(context, anyColor.CGColor);
```
##TabBar Appearance強制アップデート
```objectivec
// Forcible update UITabBar.
UIView *view = self.tabBarController.view;
UIView *superview = view.superview;
[view removeFromSuperview];
[superview addSubview:view];
```

#UIView and UIImage

##UIViewアニメーション
```objectivec
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatAutoreverses:NO];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationDidStopSelector:nil];
[UIView setAnimationDelegate:self];

self.descriptionView.alpha = 0.7f;

[UIView commitAnimations];
```

##UIImageのリサイズ
```objectivec
- (UIImage*)resizeImage:(UIImage *)img rect:(CGRect)rect
{
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
    [img drawInRect:rect];
    UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return resizedImage;
}
```

#UIStoryboardSegue
画面遷移する時に異動先のコントローラーへデータを渡したいときの処理。
`Storyboard`で`identifier`の設定をすること。

```objectivec
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    anyController *controller = (anyController *)[segue destinationViewController];
    if ([[segue identifier] isEqualToString:@"Apple"]) {
        controller.fruit = @"Apple";
    }
    else if([[segue identifier] isEqualToString:@"Orange"]) {
        controller.fruit = @"Orange";
    }
}
```

#Class

##Application Delegate Class

```objectivec
MYAppDelegate *appDelegate = (MYAppDelegate *)[[UIApplication sharedApplication] delegate];
```

##クラスの名前を取得する

```objectivec
NSString *selfClassName = NSStringFromClass( [self class] );
```

##クラスを変数指定で得る

```objectivec
Class anyClass = NSClassFromString(@"anyClass");
```

#misc.

##NSTimeZoneの作り方
Library: [APTimeZones](https://github.com/Alterplay/APTimeZones "APTimeZones")

```objectivec
CLLocation *theLocation = placemark.location;
NSString   *countryCode = placemark.addressDictionary[@"CountryCode"];
NSTimeZone *theTimeZone = [[APTimeZones sharedInstance] timeZoneWithLocation:theLocation
                                                                 countryCode:countryCode];
[NSTimeZone setDefaultTimeZone:theTimeZone];
```


##ARCと非ARCの混在

`-fobjc-arc`
`-fno-objc-arc`


##プリプロセッサ
```
#define ANY_FLAG
```

```
#ifdef ANY_FLAG
...
#else
...
#endif
```