スマートフォンアプリ作成

SwiftとObjcとKotlinとJavaとの対照表

結論

SwiftとKotlinはObjcやJavaの記述の冗長さ(いわゆる「おまじない」と表現される言語特有の呪文)を縮小し、lambda記述はパワフルで生産的だ。

ただし、Kotlinはプリミティブやオブジェクトの配列の扱いが特殊で直観的でない。
Swiftはframework実装のpropertyにoptionalが多用されているため、プログラムソースが「?(クエスチョンマーク)」「!(ビックリマーク)」だらけになってしまいマンガかラノベを見ているようだ。

更新履歴
2018.8.29更新
2018.7.18更新

Kotlinスコープ関数(let run apply by lazy also with 拡張関数)はいったい何が異なるのか
Swiftとkotlinの⁉(optional型、nullable)の考察

SwiftとObjcとKotlinとJavaとの対照表

  Objc Swift (4以降) Java Kotlin (1.2以降) C++
抽象クラス 抽象クラスはない。 抽象クラスはない。

abstract  class AbstractClass {
  abstract  type methodName();
}

abstract  class AbstractClass {
  abstract  fun methodName()
}

class AbstractClass {
  public:
  virtual void methodName() = 0
}
具象クラス

@implementation ConcreteClass {
  type privateInstanceVarName;
}
- (type)methodName:(type)paramA rabel:(type)paramB {
...
}
@end

class ConcreteClass : superClass ,interfaceName {
  accessLevel var vName:type
  accessLevel methodName() -> type {
    ...
  }
}

public class className extends superClass implements interfaceName {
  accessLevel type vName;
  accessLevel type methodName() {
    ...
  }
}

class className : superClass() {
  accessLevel var vName:type
  accessLevel methodName() : type {
    ...
  }
}

class concreteClass : public abstractClass {
  public:
  virtual void methodName() {
  }
  private:
  int i;
}
クラス規約定義
                    
@protocol ProtocolName 
  - (void)method;
@end

protocol ProtocolName {
  var protocolVar : type
  func protocolFunc -> Int
}

interface interfaceName {
  void methodName();
}

interface interfaceName {
  var vName:type
  fun methodName() : type {
    // default action
  }
}
クラス規約定義はない。
相互運用性   bridgeファイルにObjcのヘッダーを記載することでアクセス可能となる。 JavaからKotlinクラスにアクセスするには、Kotlinの変数やメソッドの宣言にJVM修飾子を用いる必要がある。 Javaクラスにアクセスできる。  
定数 #define CONSTANT 13 static public let CONSTANT = 13 // classの外で定義してもよい final static int CONSTANT =13
class className {
   companion object {
      const val CONSTANT = 13
      // const修飾はJavaと相互運用する場合のみ付ける
   }
}
 
定数(literal) 0.1f 0.1 0.1f 0.1  

変数宣言時に値をセットしない変数


*nib outlet などあとで絶対に値がセットされる変数
*型変換が自動的に行われる

var initOnLaterVar : View! lateinit var initOnLaterVar : View

変数宣言時に値をセットしない変数
*なるべく使わない

 

(nil)を状態フラグとして用いる場合のみ

var nullAbleVar : Int?

 

この変数型を使う場合には、次のif letブロック内で参照や代入を行う。

if let _ = nullAbleVar {} else {}

var nullAbleVar : Int?

 

この変数型を使う場合には、次のletブロック内で参照や代入を行う。

nullAbleVar?.let {} ?: run {}

変数宣言時に値をセットする変数


なるべくこれを使って、すぐに初期化するか、lazyに初期化する

var nonNullVar : String = " "

var nonNullVar : String = " "

 

初回アクセス時に値をセットする
lazy var viewController:MyViewController = {
	return self.storyboard?.instantiateViewController(withIdentifier:"MyView") as! MyViewController
}()
val viewInstance:MyView by lazy {
	findViewById () as MyView
}
型変換する(String? → String) var nonNullVar: String = nullAbleVar! var nonNullVar: String = nullAbleVar!!
型変換(String? → String)してproperty やmethod をinvoke する var abc: String? = nullAbleVar?.init() var abc: String? = nullAbleVar?.init()

Smart Cast

nil判定と型変換(アンラップ・String! → String)を異常終了をともなわずに行う

let nonnullabelVar = nullableVar?.property ?? "" 

or

let nonnullabelVar = nullableVar != nil ? nullableVar! : ""

or

if let _ = optionVar { 
	// non null 
	// optionVarはnilでない 
} else { 
	// null 
}

or

if optionVar != nil { 
	// non null  
  optionVar.method()
} else { 
	// null 
}
 
val nonnullabelVar = nullableVar ?: "" 

or

val nonnullabelVar = nullableVar ?: run { 
	ErrorLog() 
}

or

nullAbleVar?.let {
	// nullAbleVarはnullでない
	val varA = it
} ?: run {
    // null
}

 

or

if (nullAbleVar != null) {
  // nullAbleVarはnullでない
  nullAbleVar.method()
} else {
    // null
}
文字列の連結 NSString *newString = [@"あ" stringByAppendingString:@"い"] var newString = "あ" + "い"

or

var newString = "\(varA)\(varB)"

*stringByAppendingString呪文からの解放
"あ" + "い" "あ" + "い"

or

var newString = "${stringA}${stringB}"
 
コンストラクタ - (id)init
- (id)initWithNibName:
init() {
}


override init(frame:CGRect) {
  super.init(frame:frame)
}

*classメンバ変数は宣言時に初期化できる。
*オーバロードできる

クラス名と同じ名前のメソッド
public ClassName()

*classメンバ変数は宣言時に初期化できる。
// class定義にコンストラク引数を含める
class MyContView(context:Context) : ViewGroup(context) {


  // primary constructor
  init {
    // コンストラクタで手続きを行う場合はここで行う
  }


  // secondary constructor
  constructor(c:Content, str:String) : this(c) {
    // インスタンス生成時の引数を変える
    // 戻り値にprimary constructorを指定する
  }

}


*classメンバ変数は宣言時に初期化できる。
*オーバロードできる

 
デストラクタ - (void)dealloc deinit {
}
Javaの言語としてのデストラクタはない

androidライフサイクルとしてのデストラクタ
Activity#onDestroy()
デストラクタはない。  
メソッド(関数) - (void) method:(type)var label:(type)var{
} ​
func method(label:type, label:type) -> Void {
} ​

*Objcのlabelと変数名が統合された。
void method(type var, type var) {
} ​
fun method(var:type, var:type) : Unit {
}
 
クラスメソッド + (void) classMethod {
} ​
class func classMethod() -> Void {
} ​
public static void classMethod() {
} ​
class className {
companion object { @JvmStatic fun classMethod() : Unit { } // @JvmStatic修飾はJavaと相互運用する場合のみ付ける } }
 
lambda(blocks, closure)
[self method:^(NSInteger argA, BOOL argB) {
    ...
}];
method(label:a, label:b) {
	(argA, argB) in
    ...
}

or

let variableA:Array<Int>? = [100]
let variableB:Int? = variableA?.map({ $0 + $0 }) 	// variableB は [200]

or

let variableA:Array<Int>? = [100]
let variableB:Int? = variableA?.map() { $0 + $0 }	// variableB は [200]

or

let variableA:Array<Int>? = [100]
let variableB:Int? = variableA?.map { $0 + $0 }	// variableB は [200]
androidSDK(Java)にはlambdaは採用されていない。
method(a, b) {
	argA, argB ->
    ...
}
 
spawn(メインスレッド)
dispatch_async(dispatch_get_main_queue(), ^{
  // メインスレッド
});
DispatchQueue.main.async {
}
runOnUiThread(new Runnable() {
  public void run() {
    // メインスレッド
  }
});
runOnUiThread {
   // メインスレッド
}
 
spawn(サブスレッド)
dispatch_async(dispatch_get_global_queue(), ^{
  // サブスレッド/バックグランドスレッド
});
DispatchQueue.global(qos: .default).async {
}
new Thread(new Rannable() {
  @Override public void run() {
    // サブスレッド
  }
}.start();
thread {
   // サブスレッド
}
 
配列 int var[3]; var variable:[Int] = [] // 初期化
variable = [1, 3, 5]
int[] array_var = new int[3];
int array_var[] = new int[3];
どっちでもよい。
プリミティブ・クラス
var variable:IntArray = IntArray(3)

Arrayクラス
var variable:Array<Int> = Array(3, x -> x)
 
ポインタ(参照、エイリアス、アドレスポインタ) 基本データ型
int *pointer_var = address;


オブジェクト
オブジェクトはすべてポインタ
var variable:UnsafePointer<Int>


メソッド引数へのポインタ渡し(参照渡し)

func method(label:inout type) -> Void {
}

method(&var)
基本データ型
int[] pointer_var = new int[1];
*メソッド引数へのポインタ渡し(参照渡し)に配列を使う。

オブジェクト
オブジェクトはすべてポインタ
var parameter:IntArray = intArrayOf(1)
print "$parameter[0]" // 1
method(parameter)
print "$parameter[0]" // 2


fun method(pointer_var:IntArray) : Unit {
   pointer_var[0] = 2
}

*メソッド引数へのポインタ渡し(参照渡し)に配列を使う。
 
ポインタ表現 ポインタ
*variable
var variable:UnsafePointer<Int>

variable.pointee
配列にする
int[] pointer_var
配列にする
val pointer_var:Array<Int>
val pointer_var:Array<String>
 
クラス配列の使い方 [C++]
CGPoint **var = new CGPoint*[count];
  CGPoint var[] = new CGPoint[count];
var[i] = new CGPoint();
   
インスタンス生成
(ビュー、ウィジェット、コントローラ、クラスなど)
ViewClassName *obj = [[ViewClassName alloc] init];

UIButton view = [[UIButton alloc] initWithFrame:CGRectMake()];

nibファイルから生成
ViewController *vc = [[ViewController alloc] initWithNibName:@"nibName" bundle:nil]:

let obj:ViewClassName = ViewClassName()

or

let obj = ViewClassName()

 

let view:UIButton = UIButton(frame:CGRect())

ViewClassName obj = new ViewClassName();

別の方法 Activity#findViewById, View#findViewById
Button view = (Button)findViewById(R.id.btn);

次の2通りのView生成方法は全く同じこと
LinearLayout view = (LinearLayout)View.inflate(activity, R.layout.viewName, null);

LinearLayout view = (LinearLayout)getLayoutInflator().inflate(R.layout.viewName, null);

val obj:ViewClassName = ViewClassName()

or

val obj = ViewClassName()

 
(Sub)View表示 [view addSubView:subView]; view.addSubView(subView) ViewGroup#addView(subView);
*ViewGroup(LayoutView)だけaddViewできる

Activity#addContentView()
*R.layoutをinflateしてaddContentViewする
   
(Sub)Viewを非表示にする [subView removeFromSuperview];

*Viewのvisible属性をfalseしてもOK
  ViewGroup viewParent = (ViewGroup)this.subView.getParent();
viewParent.removeView(this.subView);

*Viewのvisible属性をfalseしてもOK
  view.setVisibility(View.GONE);
   
  クラス名は大文字始まり   クラス名は大文字始まり    
  変数名は小文字始まり   変数名は小文字始まり    
フレームワークで定義されているクラス名 cocoaフレームワークで定義されているクラス名はプレフィックスがついていて何に使うクラスなのかが一目瞭然(ex. UIView, NSData)   Android SDKで定義されているクラス名にプレフィックスが全くないので調べないと何に使うクラスなのかわからない(ex. View, Data)    
リソースファイル名 パソコンで使えるファイル名ならOK   小文字と数字だけ。大文字が使えない    
  [UIColor whiteColor]   Color.WHITE
又は
R.color.white
   
文字定数の国際化 NSLocalizedString(@"name", @"comment")

定数はLocalizable.strings(Localization)で定義する
  getResources().getString(R.string.name)

定数は
res/values/strings.xml
res/values-ja/strings.xml
で定義する
   
  @“文字定数” “文字定数” “文字定数” “文字定数”  
  nibでもコードでも画面作れる   xmlでもコードでも画面作れる    
  application:didFinishLaunchingWithOptions:   onCreate()    
メソッドスコープ .hの@interface class に定義   public type methodName()    
  .mの@interface class (private)に定義   private type methodName()    
変数スコープ .hの@interface className にプロパティ定義
@property (assign, readwrite) type varName;
これによりセッター、ゲッター、インスタンス変数(_varName)を生成する
  public type varName;    
  .mの@implementation className {}内にインスタンス変数定義
type _varName;
  private type varName;    
  [instanceVariable methodName]   instanceVariable.methodName()    
  self.instanceVariable   this.instanceVariable
*this.はつけてもつけないくても同じ意味
   
  [array objectAtIndex:0]   array.get(0)    
  NSInteger, int   int    
  IBOutlet *view or [topView viewWithTag:]   findViewById()    
  @interface subClass : superClass {   class subClass extends superClass {    
  #import "importFileName.h"
or
@import className;
import className
(importするのはフレームワークのみ/自動)
import packageName.className
(importするのはフレームワークのみ/自動)
import packageName.className
(importするのはフレームワークのみ/自動)
 
  クラス名はプロジェクトで一意   .javaでpackage名を定義すると同じクラス名でもOK、別スコープとなる    
ライフサイクル AppDelegateとviewControllerライフサイクル   ActivityとFragmentライフサイクル    
  didFinishLaunchingWithOptions(appDelegate)   onCreate    
  applicationDidBecomeActive(appDelegate)   onStart    
  applicationWillEnterForground(appDelegate)   onResume    
  applicationDidEnterBackground(appDelegate)   onPause    
  applicationWillTerminate(appDelegate)   onStop    
  applicationDidBecomeActive(appDelegate)   onRestart    
  dealloc   onDestroy    
バンドル情報(パッケージ情報)取得 productName-Info.plist で定義した値

[[NSBundle mainBundle] infoDictionary]
 setObject, objectForKey etc.
  AndroidManifest.xml で定義した値

PackageInfo
 #packageName etc.
   
keyValue persistentストア(アプリ内共通preference)に保存・読み出し preferenceファイルは1つ

書込み
[[NSUserDefaults standardUserDefaults] setObject:data forKey:keyName];

読み出し
NSInteger value = [[NSUserDefaults standardUserDefaults] objectForKey:keyName];

*設定アプリのアプリ設定情報読み出しも同じ方法(NSUserDefaults)
  書込み
SharedPreferences settings = getSharedPreferences("prefName", 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("key", value);
editor.commit();

読み出し
Activity#getSharedPreferences("prefName", 0).getInt("key", 0);

*アプリのSetting(設定情報)は PreferenceManager で読み出す
   
スマートフォン設定情報取得(ネットワーク接続) [[UIDevice currentDevice] networkAvailable];
  ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

ConnectivityManager#getActiveNetworkInfo();
NetworkInfo#getType(); // ConnectivityManager.TYPE_WIFI
   
画面の向きを固定する plistのUISupportedInterfaceOrientations   AndroidManifestのscreenOrientation    
アプリ設定情報(Setting)の取得
*iOSは設定アプリ、androidはアプリ内のActionBarButtonから設定した値
設定アプリに設定項目を設定する
Settings.bundle (Root.plist, Root.strings) に設定項目(key)を定義する

NSInteger value = [[NSUserDefaults standardUserDefaults] objectForKey:keyName];
  ActionBarButton(アプリ内のOptionMenu)表示用Activityを設定する
startActivity(new Intent(getBaseContext(), PreferenceActivity.class));


PreferenceManager.getDefaultSharedPreferences(this).getString("key", "defaultValue");
   
フェッチ機構 NSFetchedResultController   LoaderManager
CursorAdapter (SimpleCursorAdapter)
   
DBインタフェース NSManagedObjectContext   ContentResolver    
データ管理 NSManagedObject   Cursor    
画面遷移(画面表示) pushViewController, presentModalViewController   startActivity()    
viewController間の値の受け渡し allocしたインスタンスのインスタンス変数に値をセットしてから表示(pushViewController etc.)する。

protocol定義のdelegateメソッド引数にセットして呼び出す。
  Intentのdata,extrasにセットしてstartActivity()する。    
画面閉じる(非表示) dismissModalViewController
dismissPopOver とか
  Activity#finish()    
  Controller - NSManagedObjectContext - CoreDataModel   Controller -> Bean -> DTO <- DAO (sql)-> DB(Entity定義)
*Bean:画面UIのためのデータを扱う 
 DTO : テーブル操作のためのデータを扱う
   
クラス定義(継承) .h
@interface className : superClass <protocolName>
@property (retain, nonatomic) type publicVarName;
- (type)publicMethodName:(type)paramA rabel:(type)paramB;
@end
.swift
class className : superClass ,interfaceName {
  accessLevel var vName:type
  accessLevel methodName() -> type {
  ...
  }
}
.java
public class className extends superClass implements interfaceName {
  accessLevel type vName;
  accessLevel type methodName() {
  ...
  }
}
.kt
class className : superClass() {
  accessLevel var vName:type
  accessLevel methodName() : type {
  ...
  }
}
 
クラス実装

.m
@implementation className {
   type privateInstanceVarName;
}
- (type)methodName:(type)paramA rabel:(type)paramB {
...
}
@end

定義と実装は同じファイル(.swift)で行う 定義と実装は同じファイル(.java)で行う 定義と実装は同じファイル(.kt)で行う  
コールバック Delegate (デリゲート)   Interface (インタフェース)
Listener (リスナー)
   
デリゲート(リスナー)機能実装 プロトコルを宣言して
@interface className : superClass <UISearchBarDelegate>

nibでデリゲートクラスを定義して

クラスにメソッドを実装する
- (void)finishSearchWithString:
  インターフェースを宣言して
public class className extends superClass implements SearchView.onQueryTextListener

コールバッククラスを定義して
SearchView.setOnQueryTextListener(this);

クラスにメソッドを実装する
public boolean onQueryTextChange() {}
   
 
インナークラスで実装することもできる
*インターフェース宣言(implements)はしなくてよい
*1箇所への記述だけでよいため手軽だが分かりにくくなる恐れあり

SearchView.setOnQueryTextListener(new SearchView.onQueryTextListener() {
   public boolean onQueryTextChange() {};
});
 
クラスのインスタンスが持つ変数 インスタンス変数   プロパティ、フィールド、メンバ変数
などいろんな呼称がある
   
インスタンス変数の初期化 initとかのコンストラクタで行う   クラス定義で初期値を設定できる    
インスタンス変数使用方法 _iVarName = someOne; // setterは走らない
             // retainカウント増えない
self.iVarName = someOne; // setterが実行される
             // retainカウント増える
iVarName = someOne
self.iVarName = someOne
iVarName = someOne;
this.iVarName = someOne;
// 全く同じ意味
   
ObjectiveCの@property指定方法 何も指定しないと、
クラス変数デフォルト(atomic, strong)
プリミティブ変数(intなど)のデフォルト(atomic, assign)
strong // このクラスで管理するインスタンス変数
weak // 他クラスで管理しているインスタンスを参照するためのインスタンス変数
nonatomic // 非スレッドセーフ(通常この指定)
       
           
デバッグ時だけログ出力

*通常appName_Prefix.pchでプリプロセッサ定義して利用する


#ifdef DEBUG
#define FBLog(fmt,...) NSLog((@"%s l.%d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define FBLogErr(fmt,...) NSLog((@"[ERROR]%s l.%d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define FBLog(fmt,...) ;
#define FBLogErr(fmt,...) NSLog((@"[ERROR]%s l.%d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
 

public class AALog {
  public static void v(String message) {
    if(BuildConfig.DEBUG) {
      if (message.isEmpty()) {
        message = "...";
      }
      StackTraceElement ste = Thread.currentThread().getStackTrace()[4];
      Log.v(ste.getClassName() + "#" + ste.getMethodName() + ":" + ste.getLineNumber, String.format("%f", floatVal));
} } }


   
変数(valiable) aValiable   aVariable    
クラスのインスタンス変数 ClassName *instance   ClassName instance    
アクセスレベル(スコープ)デフォルト 継承クラス内(protected)   パッケージ内    
サーバからアプリへのプッシュ通知(リモート通知) RemoteNotification

証明書と鍵をサーバーに置く→アプリがデバイストークンを取得→アプリからデバイストークンをサーバに送信→サーバは(APNS)Apple Push Notification Serviceに通知をプッシュ→APNSからアプリ(デバイス)に通知送信

文字列で通知する

通知形式は設定アプリでユーザが決定する
 

GCM(Google Cloud Messaging for Android)

ServerAPIKeyとProjectIDをサーバーに置く→アプリがRegistrationIDを取得→アプリからRegistrationIDをサーバに送信→サーバはGoogleAPIサーバに通知をプッシュ→GoogleAPIサーバからアプリ(デバイス)に通知送信→BroadcastReceiverクラスで受信してNotificationManagerで通知表示(ステータスバー表示のとき)

json形式で通知する

通知形式はアプリが決定する

   
ローカル通知(アプリがローカルデバイスに対して通知する) UILocalNotification

通知はOSが受け取り表示する

文字列で通知する
通知形式は設定アプリでユーザが決定する
  AlarmManager 指定時間後にブロードキャストインテント発行
PendingIntent
BroadcastReceiver ブロードキャストインテント受信
NotificationManager ステイタスバーに通知を表示

PendingIntent(文字列)で通知する
通知形式はアプリが決定する
   
  plist - CFBundleURLTypes, CFBundleDocumentTypes   AndroidManifest - intent-filter    
  UIGestureRegognizer   GestureDitector    
  @interface myView : UIView <UIGestureRecognizerDelegate> {   public class myView extends Activity implements OnGestureListener {    
  CoreGraphics   Canvas    
リソースファイル読み出し glTexImage2D(),
CGContextDrawImage
  R.idを指定するだけ    
Assetファイルのファイル・コピー NSFileManager#copyItemAtURL を呼ぶだけ  

InputStream#read して
OutputStream#write するのを ファイルサイズ/bufferサイズ回数ループしなければファイルコピーひとつできない。Javaのメモリ管理の脆弱さが理由だと思われるが低水準すぎる。これがフレームワークと言えるのか?
ANSI Cを思い出した。

 

*FileChannel#transferTo というメソッドもあるが、Assetファイル(AssetManager)などをパスに変換するメソッドが用意されていないため使えない。

   
UI操作はメインスレッドで行う
dispatch_async(dispatch_get_global_queue(), ^{
  // サブスレッド/バックグランドスレッド
  dispatch_async(dispatch_get_main_queue(), ^{
    // メインスレッド
  });
});


UIView#performSelectorOnMainThread
 
Activity.this.runOnUiThread(new Runnable() {
  public void run() {
    // メインスレッド
  }
});

or

// メインスレッドを指定してHandlerを生成
new Handler(); // 引数を省略するとメインスレッドに紐づく
new Handler(Handlerに紐づくThreadのLooperを指定);
*紐づくとはHandler#postする先のスレッドのQueueを規定するということ。

AsyncTask#doInBackground() { // バックグランド
 Handler#post(new Runnable() {
   @Override
   public void run() {
    // イベントキューに登録する
   }
 });
}
   
非同期実行 iOSはGCDのおかげでサブスレッド作成実行が簡単

dispatch_async(dispatch_get_global_queue(), ^{
  // サブスレッド
});

or

NSThread detachNewThreadSelector

or

UIView#performSelectorOnMainThread
UIView#performSelectorInBackground

  androidのサブスレッド作成実行手続きはiOSに比べて複雑

HandlerThread subThread = new HandlerThread("threadName");
subThread.start();
Handler handlerWithSubThread = new Handler(subThread.getLooper());
handlerWithSubThread.post(new Rannable() {
  @Override public void run() {
    // サブスレッド
  }
});

or

AsyncTask を継承してインナークラスを作る
class AsyncTaskClass extends AsyncTask<...> {
}
そして、非同期実行する
new AsyncTaskClass().execute();

or

(new Thread(new Rannable() {
  @Override public void run() {
    // サブスレッド
  }
})).start();

or

class Rannable
・自分自身をスレッド実行開始するとき
public class RannableClassName implements Runnable {
  public RannableClassName() {
    Thread thread = new Thread(this);
    thread.start();
  }

  public void run() {
    // サブスレッド
  }
}


・別クラスのインスタンスをスレッド実行開始するとき
public class ClassName extends Activity {
  RannableClassName rannableClassInstance = new RannableClassName();
  Thread thread = new Thread(rannableClassInstance);
  thread.start();
}
   
static変数(ヒープ領域にメモリ領域を確保する) メソッド中に定義できる   クラスメンバ変数として定義する    
配列初期化 type var[10];
*var = malloc(10*sizeof(type))
  type[] var = new type[10];    
  NSFileManager   File (ContentWrapperを継承したクラスで使う)    
オリエンテーション取得 // デバイスの向き
UIDeviceOrientation = [[UIDevice currentDevice] orientation];

// 描画されている画面の向き
UIInterfaceOrientation = [UIAppliation sharedApplication].statusBarOrientation;
  this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT    
オリエンテーションイベント取得 UIViewController#viewWillTransitionToSize: withTransitionCoordinator:

iOS7まで
willRotateFromInterfaceOrientation:
didRotateFromInterfaceOrientation:
  manifestに
Activity android:configChanges="orientation|keyboardHidden"すると
onConfigurationChanged()が呼ばれる
   
テーブル(リスト)表示管理 UITableViewController   ListActivity
ListFragment
*テーブルUI+表示データの管理
   
セクション(グループ)数 tableView:numberOfSectionInTableView:   CursorAdapter#getViewTypeCount()    
セクション・ヘッダー表示 tableView:titleForHeaderInSection:   CursorAdapter#newView()    
テーブル(リスト)表示内容設定 tableView:cellForRowAtIndexPath:  

CursorAdapter#newView()
CursorAdapter#bindView()

   
コレクション(配列) NSArray *vName = @[]; // 空の配列
NSMutableArray *vName = [@[ @"val1", @"val2" ] mutablecopy]; // 配列の初期化
  List<ObjectType> vName = new ArrayList<ObjectType>(); // 空の配列
List<ObjectType> vName = Arrays.asList("value1", "value2", "value3"); // 配列の初期化

   
コレクション(連想配列) NSDictionary *vName = @{};  // 空の連想配列

NSMutableDictionary *vName = [@{ @"key1" : @"val1", @"key1" : @"val1" } mutablecopy]; // 連想配列の初期化
 

Map<ObjectType, ObjectType> vName = new Hashtable<ObjectType, ObjectType>(); // 空の連想配列

Map<Integer, String> vName = new Hashtable<Integer, String>({ // 連想配列の初期化
  put(0, "value1");
  put(1, "value2");
put(2, "value3");
});
   
メソッド・オーバーライド 普通にsuperClassやプロパティのメソッドを再定義すればOK   @Override public void superClassMethod() {}
@Override public void otherClassMethod() {}
   
いろいろ使うAppDelegateやMainActivityの求め方 [[UIApplication sharedApplication] delegate]で求める   MainActivityのonCreateでGlobalクラスのクラス変数に保存しておく
*所属するFragmentやView以外からは求めるしくみは用意されていない
   
FragmentからActivityの求め方     Fragment#getActivity();    
ViewからActivityの求め方     View#getContext();    
変数型(データ型) 変数型を見ただけで何に使われる変数かが分かる。
ex. UIDeviceOrientation orientation
  Java標準のデータ型しかない。
ex. int orientation
*Javaにはプリプロセッサー(#define)やtypedefが無いため
   
  YES, NO   true, false    
配列領域確保 float var[4];   float[] var = new float[4];    
国際化(文字定数、画面レイアウト)

文字定数を国際化するとき
Localizable.stringsに値を定義して
NSLocalizedString(@"key", @"comment")で呼び出す

画面ごとに国際化するとき
className.xib
xcodeの右ペインのLocalization

  文字定数を国際化するとき
res/values-ja/strings.xmlに値を定義して
getResources().getString(R.string.name)で呼び出す


画面ごとに国際化するとき
res/layout-ja/activity_main.xml
   
機種判定 UIViewController#UITraitCollectionで判定

if (self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) {

        // iPad

} else {

        // iPhone

}


iOS7以下
UI_USER_INTERFACE_IDIOM()
  res/layout/activity_main.xml
res/values/dimens.xml
↑と↓で画面サイズによって、レイアウトやパディング値を切り替える
res/layout-w820dp/activity_main.xml
res/values-w820dp/dimens.xml
   
OSバージョンチェック if (IOS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
  // iOS6以上
}
  if (Build.VERSION.SDK_INIT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
  // android 4以上
}
   
文字列数値変換 NSString *text = [[NSNumber numberWithInt:intVal] stringValue];
or
NSString *text = [NSString stringWithFormat:@"%d", intVal];

NSString *text = @"1";
int intVal = [text intValue];
  String text = Integer.toString(intVal);





int intVal = Integer.parseInt(text);
   




スマートフォンアプリ作成