iOSアプリからカレンダーに予定を追加する方法

メモメモ。

#import <EventKit/EventKit.h>
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

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

    EKEventStore *eventStore = [[EKEventStore alloc] init];
    // weakつけるとブロックの中で参照がなくなってたので、ダメみたい。でもselfは大丈夫
    // でもつけないとリークしちゃうよね?
//    __weak EKEventStore *__eventStore = eventStore;
    __weak ViewController *__self = self;
    [eventStore requestAccessToEntityType:EKEntityTypeEvent
      completion:^(BOOL granted, NSError *error) {
          // なので、ブロックの中で再生成してみた
          EKEventStore *__eventStore = [[EKEventStore alloc] init];

          NSLog(@"__eventStore = %@", __eventStore.description);
          NSLog(@"__self = %@", __self.description);

          // カレンダーへのアクセスが許可された場合
          // 一度拒否を選んでしまうと二度とアクセスできないっぽい
          // ユーザーに設定からリセットしてもらう必要がある
          // via http://d.hatena.ne.jp/appbakery/20130327/p2
          // via http://program.station.ez-net.jp/special/handbook/objective-c/iphone/grant/reset.asp
          if (granted == NO) {
              // ここはmainキューでないので、UIの操作はdispatch_get_main_queueを使ってmainキューの中でやる必要がある
              // via http://d.hatena.ne.jp/zentoo/20121028/1351443185
              dispatch_async(dispatch_get_main_queue(), ^{
                  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"お知らせ" message:@"カレンダー操作の許可をくださいちょんまげ"
                                        delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
                  [alert show];
              });
              return;
          }

          //アクセス許可後の処理はここで
          EKEvent *event = [EKEvent eventWithEventStore:__eventStore];
          event.title = @"ひささんピースDay";
          event.timeZone = [NSTimeZone defaultTimeZone];
          event.notes = @"ひささんを楽しませる会";
          event.startDate = [[NSDate alloc] init];
          event.endDate = [[NSDate alloc] initWithTimeInterval:6000 sinceDate:event.startDate];
          event.calendar = __eventStore.defaultCalendarForNewEvents;
          [event setCalendar:[__eventStore defaultCalendarForNewEvents]];

          NSError *err;
          BOOL result = [__eventStore saveEvent:event span:EKSpanThisEvent error:&err];
          NSString *message = nil;
          if (result) {
              message = [NSString stringWithFormat:@"イベントの保存が完了しました。"];
          } else {
              message = [NSString stringWithFormat:@"イベントの保存ができませんでした。 : %@", error];
          }
          __weak NSString *__message = message;
          dispatch_async(dispatch_get_main_queue(), ^{
              UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:__message
                                    delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
              [alert show];
          });
      }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

iOSのWebViewで外部リンクをネイティブブラウザで開く場合の注意点

以下のメソッド内で外部リンクかどうか判断し、外部リンクの場合はネイティブブラウザを開くようにできるのですが、iOSのWebViewはややこしいことにiframeのリクエスト時もここに入ってきてしまいます。

  - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:  (NSURLRequest *)request navigationType:  (UIWebViewNavigationType)navigationType {-

これだと計測用のiframeのリクエストもこのメソッド内に入るので、外部URLだった場合にネイティブブラウザで開くという挙動を入れると、このiframeのリクエスト時にも反応してしまいます。

そこで方法としては、クリックした場合にのみ外部リンクかどうかを判断するようにするという方法があります。

シンプルなサンプルですが、以下のような雰囲気。

  NSString *absoluteUrl = request.URL.absoluteString;

  // 外部リンクをクリックした場合には、デバイスのデフォルトブラウザを起動する
  NSRange range = [absoluteUrl rangeOfString:@'domain'];
  if (range.location == NSNotFound) {
      if (navigationType == UIWebViewNavigationTypeLinkClicked) {
          [[UIApplication sharedApplication] openURL:request.URL];
          return NO;
      }
  }

そして、WebView側のコードに以下のようにクリックイベントをfireするコードで置き換えます。
もしもアンカーリンクなどをクリックする場合は以下のコードは不要ですが、何かしらJavaScriptでURLを作ってlocation.hrefに入れている場合には置き換えが必要になります。

  $("#hoge")[0].dispatchEvent(click());

  function click(){
    var event = document.createEvent("HTMLEvents");
    event.initEvent('click', true, false);
    return event;
  };

AndroidのWebViewはiframeなどはshouldOverrideUrlLoadingメソッドの中に入ってこないので、楽なのですが、
iOSは結構ややこしいですね。

iPhoneアプリの申請方法、iTunesConnectからXCodeへ(2013/03/18時点)

だいたいの手順はアプリ申請まとめ(2012/3現在)|iPhoneアプリ開発日誌 -ZERO-が参考になりました。
また、iTunesConnectでの作業はiTunes ConnectでiPhone/iPadアプリの新規登録を行う手順(2013年1月現在)が良い感じ。
ただ、やはりiTunesConnectでの入力項目はしょっちゅう変わるようなので、以下に2013/03/18時点の内容を書いておきます。

iTunesConnect

iTunesConnectでアプリ情報を入力する。

iTunes Connect

アプリケーション情報の入力

Default Language
App Name
SKU Number(UTF-8の英数字で表されたアプリケーションの一意の識別子)
Bundle ID(AppId)

地域、価格、公開の設定

Availability Date
公開日は先にしておかないとリリース日順検索で上位に表示されないらしい。
リジェクトされた場合に、公開日がすぎると過去日になってしまうので新着で引っかからない可能性がある。
なので、少し先にしておいて公開後に調整すればよいみたい。
[via]
iPhoneアプリ申請時に知っておくと良いこと – されど空の青さを知る
【開発】利用開始日(Availability Date)の設定は戦略的に!申請したiPhoneアプリ「e-スペル」がReady for Sale(販売中)に – creativi.tea

Price Tier
Discount for Educational Institutions
Custom B2B App
App Store Worldwide

バージョン情報の入力

Version Number
Copyright
Primary and Secondary Category(カテゴリは選んだらあとで修正できないと聞いたことがある)
Subcategory
Rating

メタデータ

Description
Keywords
Support URL(ティザーサイトでなくてもよい)
Marketing URL(非必須)
Privacy Policy URL(非必須)

App Review Information

レビュー後のAppleからの連絡用。

First Name
Last Name
Email Address
Phone Number
Review Notes(非必須)

画像のアップロード

Large App Icon
1024 x 1024

3.5-Inch Retina Display Screenshots(iPhone4)
960×640, 960×600, 640×960 or 640×920
3枚設定した

4-Inch Retina Display Screenshots(iPhone5)
1136×640, 1136×600, 640×1136 or 640×1096
3枚設定した

iPad Screenshots
1024×768, 1024×748, 768×1024, 768×1004, 2048×1536, 2048×1496, 1536×2048 or 1536×2008
3枚設定した

Routing App Coverage File(非必須)

Done!!

iTunesConnectでView Detailをクリック。

Ready to Upload Binaryをクリック。

暗号化についての回答

ここで、ややこしい英語が出てきた。
ググりながら回答した。

「Is your product designed to use cryptography or does it contain or incorporate cryptography?」

httpsを使っている場合はYESを選択。

「Does your product qualify for any of the exemptions provided in Category 5 part 2?

You are responsible for the proper classification of your product; make certain that it meets the criteria of the exemption (listed here). Otherwise you may be in violation of the US export laws and could be subjected to penalties including delisting of your app from App Store. Please go through the FAQ page thoroughly before attempting to answer the question.

You can answer “YES” to question #2, if the encryption in your app is: (a) is specially designed for medical end-use; (b) is limited to intellectual property or copyright protection; (c) is limited to authentication, digital signature or the decryption of data or files; (d) is specially designed and limited for banking use or ‘money transactions’; (e) is limited to “fixed” data compression or coding techniques; or (f) if your app meets the descriptions provided in Note 4 to Category 5 Part 2.

Please visit the FAQ for additional guidance on the exemptions.」

YESを選択。

[via]
HTTPS を使ってるアプリを AppStore や Android Market で配信するときの輸出手続きについて(その2) – 規制対象になるかどうかの判断 – むらかみの雑記帳

Saveをクリック。

アプリのStatusがWaiting For Uplaodになっているのを確認する。

XCodeからアプリをアップロードする

Archiveでビルドする
Organizerが立ち上がるので、Distributeをクリック。

「Submit to the iOS App Store」をチェック。

iTunesConnectでログインしたアカウントを入力する。

アプリのDistribution用のプロビジョニングプロファイルを選択する。
(注意:ここでAdHoc用のプロビジョニングプロファイルも選べるので間違えないように、というかAppStoreへの申請なのになんでAdHocのほうが出てくるんだ!)

Nextをクリック。

15分ほど掛かる。

No issues were found in “アプリ名”がでたらOK!

Finishをクリック。

オーガナイザ画面のアプリのStatusが、Submittedになっていることを確認します。

iTunesConnectを見てみると「Waiting For Upload」から「Waiting For Review」に変わります。

やったーーーー!

おつかれさまでした!

.dSYMファイルを控えておく

あとあとクラッシュログを読めるようにしておくため、
「~/Library/Developer/Xcode/DerivedData」の下の該当のアプリディレクトリで、
.dSYMファイルを検索し、リリースビルドしたファイルをバックアップしておく。

via iOSデバイスのクラッシュログを読むには – Awaresoft

余談 – お客さんのiTunesConnectアカウントにログインして申請を代行する方法

iPhoneアプリの申請を自分のAppleアカウントからやる場合は、ごくごく普通にiTunesConnectから行えばいいのですが、
お客さんのiOS Developer Centerに登録されたアカウントからやる場合はちょっとややこしい。

まず、iOS Developer Programに登録されていないAppleアカウントを作る必要がある。
つまり普通にiTunesを使う用途としてAppleアカウントを作成して、そのアカウントをお客さんのiTunesConnectにAddしてもらう。
これで、お客さんのiTunesConnectにログインできて申請作業が行える。

こんな方法があるなんて初めて知りました!

よくわかるiPhoneアプリ開発の教科書【iOS 5&Xcode 4.2対応版】
森 巧尚
マイナビ
売り上げランキング: 7,831

Push通知をまとめてみた(PushNotification) – iOS and Android

hisasann/PushNotification-iOSandAndroid · GitHubにあげておきました。
iOSとAndroidはディレクトリを分けて各ファイルを置いておきました。

プロジェクト自体は重いのでpushしていないです。
README.mdに基本的なことを記載。

iOS

PushNotification-iOSandAndroid/iOS at master · hisasann/PushNotification-iOSandAndroid · GitHub

release用のPush通知証明書ファイルでためす場合は、AdHocとして入れればOK!

Android

PushNotification-iOSandAndroid/Android at master · hisasann/PushNotification-iOSandAndroid · GitHub

はじめてのAndroidアプリ開発―Android4対応版 (TECHNICAL MASTER)
山田 祥寛
秀和システム
売り上げランキング: 10,811

UIViewのbackgroundImageをrepeatする方法

すんごく簡単なんだけど、忘れそうなのでメモメモ。

self.view.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:@"hoge.png"]];

[via]
cocoa touch – Repeating background image in native iPhone app – Stack Overflow

ASIHTTPRequestに必要なframeworkたち

iPhoneアプリでHttpリクエストを使う場合には必須なライブラリ、ASIHTTPRequestの必須frameworkがオフィシャルのサイトに書いてあるのだけでは動かないのでメモメモ。

もう毎回忘れちゃうんですが、
How to use ASIHTTPRequest in your projects – All-Seeing Interactive
に書かれている、

Repeat the last two steps to add the following: SystemConfiguration.framework, MobileCoreServices.framework, CoreGraphics.framework and libz.dylib.

via: How to use ASIHTTPRequest in your projects – All-Seeing Interactive

これだけでは実際には動かないです。

  1. SystemConfiguration.framework
  2. MobileCoreServices.framework
  3. CoreGraphics.framework
  4. libz.dylib
  5. CFNetwork.framework

最後のCFNetwork.frameworkがないと動かないのです!

ファミ通App iPhone&Android NO.004 (エンターブレインムック)
エンターブレイン (2012-10-18)
売り上げランキング: 22

WebViewのCookieをネイティブ側のリクエストで使う方法(iPhone・Android)

iPhone版

CookieをiPhone側でセット/削除する方法 – 風日記
iphone – Where are an UIWebView’s cookies stored? – Stack Overflow
を見た。

iPhone側はすごく簡単で、WebViewでリクエストを投げると、それだけでASIHTTPRequest(ネイティブ)のリクエストと共有されていた。
Cookieの内容を確認するにはNSHTTPCookieStorageを使うとすぐに見ることができる。

サンプル・コード

NSHTTPCookie *cookie;
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [cookieJar cookies]) {
    NSLog(@"%@", cookie);
    if ([@"lab.hisasann.com" isEqualToString:cookie.domain]) {
        NSLog(@"name - %@", cookie.name);
        NSLog(@"value - %@", cookie.value);
    }
}

gist

iPhoneでWebViewのCookieを共有する方法 — Gist


Android版

Androidのほうはやや複雑、WebViewのリクエストが完了するイベントで、すでにインスタンス化してあるHttpClientに対して、Cookieをaddしないといけない。
これをしないと、HttpClient(ネイティブ)のリクエストにCookieが乗ってくれない。

サンプル・コード

webview.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
  System.out.println("onPageFinished - " + url);
  super.onPageFinished(view, url);

  // Cookieの保存が予想されるURLの場合
  if (url.indexOf("http://lab.hisasann.com/") > -1) {
      // WebViewのCookieを取得
      String cookie = CookieManager.getInstance().getCookie(url);
      System.out.println("cookie - " + cookie);
      String[] cookies = cookie.split(";");
      for (String keyValue : cookies) {
    keyValue = keyValue.trim();
    String[] cookieSet = keyValue.split("=");
    // Cookieを作成
    BasicClientCookie bCookie = new BasicClientCookie(cookieSet[0], cookieSet[1]);
    bCookie.setDomain("lab.hisasann.com");
    bCookie.setPath("/");
    // CookieStoreを取得
    CookieStore store = httpClient.getCookieStore();
    // Cookieを追加
    store.addCookie(bCookie);
      }
  }
    }
});

Cookieの内容を確認するにはCookieStoreを使うとすぐに見ることができる。

サンプル・コード

CookieStore store = httpClient.getCookieStore();
List<Cookie> cookies = store.getCookies();
for (Cookie cookie : cookies) {
    // クッキーの設定
    if ("lab.hisasann.com".equals(cookie.getDomain())) {
  // クッキーを再設定
  System.out.println(cookie.getName() + "=" + cookie.getValue());
  break;
    }
}

つまり、ひとつのHttpClientインスタンスにCookieをセットしているので、複数のHttpClientをnewする場合は、それぞれにCookieを入れないとダメっぽい。

gits

AndroidでWebViewのCookieを共有する方法 — Gist

どうでもいいことだが

iPhoneの

NSURL *url = [NSURL URLWithString:@"http://lab.hisasann.com/cookie/setcookie.php"];

http:/でも動いた。つまりスラッシュが一個足りない!

Androidではダメでした。

iOS6から搭載されたUIRefreshControl(PullToRefresh)がかっこいい!

iOS6のメーラーを使っていると、PullToRefreshがプニョ〜っと伸びる感じが気持ちいいなーと思っていたら、UIRefreshControlという名前だった。

iOS6から搭載されたUIRefreshControl(PullToRefresh)がかっこいい!

サンプルコード

使い方はすごく簡単で、UITableViewControllerのrefreshプロパティかUIScrollViewにaddSubviewするかみたい。
今回はUIScrollViewのほうで書いてみました。

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *string = @"PullToRefresh";

    _refreshControl = [[UIRefreshControl alloc] init];
    [_refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];

    // 色
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    [dictionary setObject:[UIColor whiteColor] forKey:NSForegroundColorAttributeName];
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string attributes:dictionary];

    // Font
    [attributedString addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica-Bold" size:30.0f] range:NSMakeRange(0, string.length)];
    [attributedString addAttribute:NSStrokeColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, string.length)];
    [attributedString addAttribute:NSStrokeWidthAttributeName value:[NSNumber numberWithFloat:3.0] range:NSMakeRange(0, string.length)];
    _refreshControl.attributedTitle = attributedString;

    [self.scrollView addSubview:_refreshControl];
    self.scrollView.contentSize = CGSizeMake(320, 2000);
}

リフレッシュが起動したときのタイミングでこのメソッドが呼ばれます。

- (void)refresh:(id)sender {
    [NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(endRefresh) userInfo:nil repeats:NO];
}

んで、何かリクエストして、そのコールバックあたりで以下を呼び出せばいいのではないでしょうか。

- (void)endRefresh {
    [_refreshControl endRefreshing];
}

簡単ですね!

関連リンク

iPhoneプログラミングUIKit詳解リファレンス
所 友太
リックテレコム
売り上げランキング: 13490

AppとWebViewの相互の機能の呼び方、そしてhistory.back()について(iPhone・Android)

history.back()が出来る状況が毎度毎度分からなくなってしまうので、ここにまとめておきます。
また、AppからWebViewの機能を呼ぶ、WebViewからAppの機能を呼ぶということもどうゆう状況だとできるのかもまとめておきます。
むしろこっちのほうが忘れやすい。

history.back()

ローカルHTMLファイルの場合

iPhone 動かない
Android 動く

リモートHTMLファイルの場合

iPhone 動く
Android 動く

なので、history.back()を前提にしているjQueryMobileを使うサイトは、ローカルではなくリモートを参照したほうがいいでしょう。


Titanium.App.fireEvent

ここはTitaniumのfireEventが動く範囲をまとめてみました。

ローカルHTMLファイルの場合

iPhone 動く
Android 動く

リモートHTMLファイルの場合

iPhone 動かない
Android 動かない

iPhoneとWebView

ここからはネイティブの話しになります。

iPhoneでアプリ側からWebViewに対してJavaScriptを実行する方法

「App → WebView」

WebViewをもつViewControllerのヘッダファイルにて、UIWebViewDelegateプロトコルを指定しておく。

@interface ViewController : UIViewController <UIWebViewDelegate>

すると以下のメソッドたちが使えるので、準備しておく。

- (void)webViewDidStartLoad:(UIWebView *)webView {
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    return YES; // Return YES to make sure regular navigation works as expected.}
}

あとはstringByEvaluatingJavaScriptFromStringを呼び出すだけ。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSString *title = [self.webView stringByEvaluatingJavaScriptFromString:@"$.method()"];
    NSLog(@"title - %@", title);
}

このメソッドの便利なところは、returnがあるところ、後述するがAndroidのほうだとreturnが返ってこないので、少し強引に取得する必要があったりする。

WebViewからiPhoneアプリ側に処理を通知する方法

「WebView → App」

こっちはURLのリクエスト時に、自分宛、つまり自分のアプリ内で処理して欲しいURLを渡して、それを監視している。
結果、ルールにのっとったURLの場合は、適切な処理を呼べば良い。

面白いところは、自分宛のリクエストはreturn NOを返してなかったことにしている。
これをしないと、真っ白な画面に遷移してしまう。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
  NSString *requestString = [[request URL] absoluteString];
  NSArray *components = [requestString componentsSeparatedByString:@":"];

  if ([components count] > 1 &&
        [(NSString *) [components objectAtIndex:0] isEqualToString:@"myapp"]) {
    if ([(NSString *) [components objectAtIndex:1] isEqualToString:@"myfunction"]) {
      // ここで何か処理
      NSLog(@"%@", [components objectAtIndex:2]); // param1
      NSLog(@"%@", [components objectAtIndex:3]); // param2
    }
    return NO;
  }

  return YES; // Return YES to make sure regular navigation works as expected.}
}

WebViewからの呼び出し方。

location.href = "myapp:" + "myfunction:" + param1 + ":" + param2;

比較的にシンプルにできるが、ディレクトリトラバーサルなど、セキュリティに気をつける必要がある。


AndroidとWebView

Androidでアプリ側からWebViewに対してJavaScriptを実行する方法

iPhone型と違って、view.loadUrlにjavascriptスキームを渡してもreturnが得られません。
なので、ハックに近いですが、あえてalertを実行させ、そのアラートが出る前のイベントonJsAlertでメッセージから情報を取得します。
そのあとに、result.confirm()をすることで、アラートがなかったことにできるようです。

なかなか面白いですね。

WebView webview = (WebView) findViewById(R.id.webView1);
webview.getSettings().setJavaScriptEnabled(true);

webview.setWebViewClient(new WebViewClient() {
  @Override
  public void onPageFinished(WebView view, String url) {
    view.loadUrl("javascript:alert($.method())");
  }
});
webview.setWebChromeClient(new WebChromeClient() {
  @Override
  public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
    try {
      System.out.println("onJsAlert - " + message);

      return true;
    } finally {
      // アラートが出ないようにしている
      result.confirm();
    }
  }
});

webview.loadUrl("http://lab.hisasann.com/appEval/");

WebViewからAndroidアプリ側に処理を通知する方法 – その1

WebViewからAndroidアプリ側に情報を渡すのは以下の感じで、iPhone側とすごく似ていますね。
ただ、Androidのほうは直接JavaScriptコードからAndroid側のアプリをキックできるようです。

それは後述します。

webview.setWebViewClient(new WebViewClient() {
  @Override
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
    String[] components = url.split(":");

    // 特定のURLの場合、ダイアログを表示する等
    if (components[0].length() > 1 && "myapp".equals(components[0])) {
        if ("myfunction".equals(components[1])) {
          System.out.println(components[2]);
          System.out.println(components[3]);

          return true;
        }
    }

    return false;
  }
});

WebViewからの呼び出し方。

location.href = "myapp:" + "myfunction:" + param1 + ":" + param2;

WebViewからAndroidアプリ側に処理を通知する方法 – その2

先ほどのwebview変数にJavascriptInterfaceをセットします。

webview.addJavascriptInterface(new JavascriptAdapter(), "android");

そのアダプターの中で、JavaScriptから呼び出されるメソッドを定義しておきます。

package com.example.sample_webvieweval;

import android.os.Handler;

public class JavascriptAdapter {
  private Handler handler = new Handler();

  // JavaScriptから呼び出されるメソッド
  public void getFromJS(final String s) {
    handler.post(new Runnable() {
        public void run() {
          System.out.println(s);
        }
    });
  }
}

WebViewからの呼び出し方。

// Javaのメソッドを呼び出す
window.android.getFromJS("called getFromJS");

するとこのようにwindowオブジェクトの中にJavascriptInterfaceの名前空間が追加されているので、そこから呼びたいメソッドをコールできます。

すごく簡単!
すごく簡単なんだけど、やっぱりこれもセキュリティをかなり意識しないといけないですね。

参考リンク

本格アプリを作ろう! Androidプログラミングレシピ
Dave Smith Jeff Friesen
インプレスジャパン
売り上げランキング: 13499

AppCodeメモ – ショートカットなどなど

option + enter

コンパイルは通って実行もできるんだけど、ちょっとアレだよと教えてくれるAppCodeの機能でCheckStyleのように黄色い下線が表示される場合があるんですが、
この場合、自動で最適な状態にしてくれます。

この機能を呼び出すショートカット。

// CGFloatが返ってくると過程すると、キャストしてくれと忠告がでる
NSInteger width = image.size.width / 2;

自動で (NSInteger) を付けてくれる。

// NSIntegerでキャストする
NSInteger width = (NSInteger) image.size.width / 2;
詳解 Objective-C 2.0 第3版
詳解 Objective-C 2.0 第3版
posted with amazlet at 12.10.16
荻原 剛志
ソフトバンククリエイティブ
売り上げランキング: 7060