Hatena::Groupiphone-dev

iPhoneアプリ開発まっしぐら★ このページをアンテナに追加 RSSフィード

引っ越し後の日記はコチラです

tokoromのその他の日記

2011-11-27

MacアプリでもUIKitを使ってみる with Chameleon

| 10:42 | はてなブックマーク -  MacアプリでもUIKitを使ってみる with Chameleon - iPhoneアプリ開発まっしぐら★

Chameleon

Chameleon - UIKit for Mac development

このChameleonを使うとMacアプリの開発でもUIKitを使えるようになるとのこと。

前々から気になっていたので少し試してみた。

Chameleon自体はBigZaphod/Chameleon - GitHubからダウンロード可能。

また、Chameleonを試用した本記事のソースコード一式はtokorom/ChameleonUIKitDemo - GitHubからダウンロード可能。

今回は、UIViewControllerで画面を1つ作り、そこにUIImageViewやUIButtonを貼りつけて動かしてみるところまで実験。


まずはプロジェクトにChameleonを取り込む

※上記サイトからあらかじめChameleonをダウンロードしておくこと

まずはXcodeで空のMacアプリのプロジェクトを作成する。

そのプロジェクトにChameleonの中のUIKit.xcodeprojだけ追加する。

次に、Build PhasesのLink Binary With LibrariesUIKit.frameworkを追加する。

↓このあたりの実施後の画面が↓になります↓

f:id:tokorom:20111128103910p:image


UIKitを他のコードから使えるようにimport

■ChameleonUIKitDemo-Prefix.pch

プロジェクトの中にはじめからあるプリコンパイル済みヘッダで、上記のように

UIKit/UIKit.h

UIKit/UIKitView.h

をimportしておく。

もちろん、各ソースコードから個別にimportしても構わない。


UIKit用のAppDelegateを作っておく

■ChameleonAppDelegate.h

■ChameleonAppDelegate.m


ここは普段のiOS用アプリ開発とほぼ同じでOK!

唯一違うのは、windowやViewControllerのautoresizingMaskを明示的に指定するコードを追加するくらい。

UIViewControllerがそのまま使えるというのは素晴らしい!


はじめに表示するRootViewControllerを作っておく

ここはiOS用アプリ開発と全く同じ!

ここではUIImageViewとUIButtonを追加している。

※必要な画像はあらかじめプロジェクトに追加しておくこと

■RootViewController.h

■RootViewController.m


Mac用のAppDelegateをUIKit用AppDelegateに接続

■AppDelegate.h

■AppDelegate.m


ここでは、UIKitViewと先ほど作成したChameleonAppDelegate(UIKit用のAppDelegate)を追加する。

UIKitViewは後ほどInterface Builderで接続するためIBOutletを付けておく。

そして、applicationDidFinishLaunchingの中で、UIKit用AppDelegateに移管するため、UIKitViewのインスタンスに対してlaunchApplicationWithDelegateをコールして引数にUIKit用AppDelegateのインスタンスを指定する。


Interface Builder で最後の仕上げ

f:id:tokorom:20111128104037p:image

最後に、Interface BuilderでMainMenu.xibを開き、WindowsのメインViewにUIKitViewを追加する。

UIKitViewというオブジェクトはツール上は存在しないので、代わりにCustom Viewというのを貼り付ける。

そして、そのClass名をUIKitViewに変更する。

※このあたりは↑のスクリーンキャプチャのとおりです


これができたら、そのUIKitViewをApp Delegateに作っておいたOutlet(chameleonView)に接続する。

以上で完了。


ビルド&ラン!

f:id:tokorom:20111128103636p:image

実行してみたところUIImageViewUIButtonもきっちり動き、ボタン押下のアクションも問題なくハンドリングされていました。

なかなか面白いですね!

UIKit.frameworkをappの中に含める設定

なお、このままだとappとして出力した後にUIKit.frameworkが見つからなくて動作しなくなってしまう。

そのため、Builde PhasesCopy Filesという項を追加し、そこにUIKit.frameworkを設定しておく必要がある。

f:id:tokorom:20111130030943p:image

2010-10-02

UIScrollViewを絶対に斜めにスクロールさせない方法

| 14:52 | はてなブックマーク -  UIScrollViewを絶対に斜めにスクロールさせない方法 - iPhoneアプリ開発まっしぐら★

UIKit本追加/補足 > UIKit本の内容自体への補足/訂正 > UIScrollViewを絶対に斜めにスクロールさせない方法


UIScrollViewにはdirectionalLockEnabledというプロパティがあり、ここにYESを設定すると、上下にスクロールしはじめたら上下固定、左右にスクロールしはじめたら左右に固定となるため、斜めにスクロールできないようにしたい場合に便利です。

しかし、これには重大な欠陥(仕様?)があり、はじめから斜めにスクロールしはじめると斜めにスクロールできてしまうのです*1

そのため、斜めに絶対にスクロールさせないためには、自分で制御しなければなりません。


具体的には、以下のストーリーで制御を行ないます。

1. スクロール前のスクロール位置を保存しておく
2. スクロールしはじめたら、それが上下方向か左右方向かを判別して記憶する
3. 上下方向なら、それ以降のスクロールで左右に移動してしまったぶんを無理やり元に戻す
4. 左右方向なら、それ以降のスクロールで上下に移動してしまったぶんを無理やり元に戻す

スクロールの検知はUIScrollViewDelegateのscrollViewDidScroll:メソッド、スクロール位置の矯正はUIScrollViewのsetContentOffset:メソッド*2でそれぞれ行ないます。


具体的なコードは以下のとおり。

これをUIScrollViewを継承したクラスかUIScrollViewを管理しているクラスに追記します。

【interface側】

typedef enum
{
  kILScrollViewDirectionNone = 0,
  kILScrollViewDirectionHorizontal = 1,
  kILScrollViewDirectionVertical = 2,
} ILScrollViewDirection;

@property (nonatomic, assign) ILScrollViewDirection direction;
@property (nonatomic, assign) CGPoint beganPoint;

【implementation側】

@synthesize direction = direction_;
@synthesize beganPoint = beganPoint_;

// スクロール管理の初期化
- (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView {
  self.direction = kILScrollViewDirectionNone;
  // スクロールしはじめのoffset管理
  self.beganPoint = [scrollView contentOffset];
}

// スクロール位置の矯正
- (void)scrollViewDidScroll:(UIScrollView*)scrollView {
  CGPoint currentPoint = [scrollView contentOffset];
  if ( kILScrollViewDirectionNone == self.direction ) {
    // スクロール方向の決定
    if ( !CGPointEqualToPoint( currentPoint, self.beganPoint ) ) {
      CGFloat moveHorizontal = ABS( currentPoint.x - self.beganPoint.x );
      CGFloat moveVertical = ABS( currentPoint.y - self.beganPoint.y );
      if ( moveHorizontal < moveVertical ) {
        NSLog( @"direction = Vertical" );
        self.direction = kILScrollViewDirectionVertical;
      } else {
        NSLog( @"direction = Horizontal" );
        self.direction = kILScrollViewDirectionHorizontal;
      }
    }
  }
  if ( kILScrollViewDirectionVertical == self.direction ) {
      currentPoint.x = self.beganPoint.x;
      [scrollView setContentOffset:currentPoint];
  } else if ( kILScrollViewDirectionHorizontal == self.direction ) {
      currentPoint.y = self.beganPoint.y;
      [scrollView setContentOffset:currentPoint];
  }
}

この他、UIScrollViewDelegateには、

  • (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView;

で、慣性のアニメーションも含めてスクロールが完全に終わるのを検知する機能なども備わったりしています。

*1:iOS4.1現在

*2:contentOffsetプロパティ

DiosmaryDiosmary2012/02/07 02:19I feel saistfied after reading that one.

afkzorrxsliafkzorrxsli2012/02/07 17:36YwRFJD <a href="http://hfvnyjmaylup.com/">hfvnyjmaylup</a>

ryzvrizlxryzvrizlx2012/02/09 20:49YePVl1 , [url=http://ilafqvobogzb.com/]ilafqvobogzb[/url], [link=http://extouivsybdi.com/]extouivsybdi[/link], http://xivfvtxrgpua.com/

omjjiaxomjjiax2012/02/11 02:20GJQx3W <a href="http://vxlrpnigxovg.com/">vxlrpnigxovg</a>

czzqjeuczzqjeu2012/02/12 03:44rtKW1V , [url=http://dtzinzwejddp.com/]dtzinzwejddp[/url], [link=http://tabyjeeqfmpb.com/]tabyjeeqfmpb[/link], http://hpmxkcvmlqes.com/

CharlieCharlie2013/10/13 10:57Thinking like that is really imvisserpe

MarijanaMarijana2013/10/14 14:21You've hit the ball out the park! Inebcdirle!

KatrinaKatrina2013/10/15 04:02You <a href="http://ztpyupaomw.com">co'ulndt</a> pay me to ignore these posts!

StivenStiven2013/10/15 15:38That's a wise answer to a tricky quitseon http://jrqfcy.com [url=http://cvnkfkniwt.com]cvnkfkniwt[/url] [link=http://nlqktxnjnah.com]nlqktxnjnah[/link]

KahlouchaKahloucha2013/11/03 18:13Kewl you should come up with that. <a href="http://uacatmwe.com">Exltlcene!</a>

SluxzSluxz2013/11/12 23:30Check that off the list of things I was <a href="http://ynmgjzxubtd.com">coeunsfd</a> about.

ElenaElena2013/11/14 12:03At last, soenome who comes to the heart of it all http://hkvjrzl.com [url=http://vfqzwh.com]vfqzwh[/url] [link=http://wzkeisopfj.com]wzkeisopfj[/link]

HeberHeber2013/11/16 03:22That's a brilliant answer to an <a href="http://imsxwdeie.com">intsreeting</a> question

ToshihideToshihide2013/11/18 02:51I'm quite pleased with the inorfmation in this one. TY! http://pvoitao.com [url=http://ykoqymm.com]ykoqymm[/url] [link=http://ifhsrbz.com]ifhsrbz[/link]

2010-09-07

self.view.centerを指定すると20px下にずれる?

| 03:44 | はてなブックマーク -  self.view.centerを指定すると20px下にずれる? - iPhoneアプリ開発まっしぐら★

こんなことがよくあります。

画面のど真ん中に、画面より少し小さな四角形を表示しようと思い、以下のようなコードを書きました。

  UILabel* label = [[[UILabel alloc] init] autorelease];
  label.backgroundColor = [UIColor redColor];
  label.frame = CGRectInset( self.view.bounds, 30.0, 30.0 ); //< 背景より少し小さく
  label.center = self.view.center; //< ど真ん中に配置するつもり
  [self.view addSubview:label];

しかし実際に実行してみると、

f:id:tokorom:20100908034000p:image

こんな感じにステータスバーの20pxぶん下にずれて表示されてしまいます。これを見ると、

  • labelのcenterをself.view.centerに合わせているのになぜ?
  • self.view.centerは画面のど真ん中じゃないの?

と不信に思ってしまいます。


が、このカラクリは以下です。

1. self.view.center は、self.viewの親Viewの座標系である

2. label.center は、label.viewの親View(self.view)の座標系である


つまり、違う座標系であるがためにずれるのは当然といえば当然です。

ちょっと分かりづらいかもしれないので図に示します。

f:id:tokorom:20100908034001p:image

この図の青の枠がself.view.centerで使われる座標系で、緑の枠がlabel.centerで使われる座標系です。

つまり、self.view.centerが ( 50, 50 ) だとして、label.centerに同じ ( 50, 50 ) を設定した場合、緑の枠の座標系は青の枠の座標系と比較して下に20pxずれているので、実際の画面におけるlabel.centerの実座標は ( 50, 70 ) となるわけです。


これが、ど真ん中にしているつもりなのに、ど真ん中にならないカラクリです。

それでは、実際にどうやってど真ん中に表示すれば良いのかというと、label.centerの座標系(self.view)における中心点を地道に計算するしかありません。

※labelの親ViewがUIViewControllerのviewでない場合、convertPoint:toView:メソッドを使う手もあります。


具体的なコードを以下に示します。

  UILabel* label = [[[UILabel alloc] init] autorelease];
  label.backgroundColor = [UIColor redColor];
  label.frame = CGRectInset( self.view.bounds, 30.0, 30.0 );
  CGSize boundsSize = self.view.bounds.size; //< self.viewのサイズを取得
  label.center = CGPointMake( boundsSize.width / 2, boundsSize.height / 2 ); //< 単純にそのサイズの中間点を設定
  [self.view addSubview:label];

これを実行すると、四角形は綺麗にself.viewのど真ん中に表示されます。

f:id:tokorom:20100908034002p:image

ころんころん2013/01/29 14:00四角形を真ん中に配置する方法ですが、
単にCGRectInsetを使うに留めればOKではないでしょうか?

UILabel* label = [[[UILabel alloc] init] autorelease];
label.backgroundColor = [UIColor redColor];
label.frame = CGRectInset( self.view.bounds, 30.0, 30.0 ); //< 背景より少し小さく
// label.center = self.view.center; //< この文を使わない
[self.view addSubview:label];

ちなみに、3行目を
label.frame = CGRectInset( self.view.frame, 30.0, 30.0 ); //< boundsをframeにした場合
とすると、やはり下に20pixcelずれますが。

- - + - - + - - + - - + - - + - - + - - + - - + - - + - -
UIKit本には大変お世話になってます。素晴らしい本をありがとうございます。

2010-03-12

UIActionSheetをaddTargetでコーディングできるようにしたい

| 01:51 | はてなブックマーク -  UIActionSheetをaddTargetでコーディングできるようにしたい - iPhoneアプリ開発まっしぐら★

UIActionSheetを使っていて、ちょっとだけ不満だったことがあります。

それは、1つの画面で複数のUIActionSheetを使った時のactionSheet:clickedButtonAtIndex:メソッドのコードについてです。

UIActionSheetのボタンの押下をハンドリングするメソッドは1つなので、以下のようにif文やswitch文の入れ子にせざるを得ません。

- (void)showActionSheet1 {
  self.actionSheet1 = [[[UIActionSheet alloc] init] autorelease];
  self.actionSheet1.delegate = self;
  [self.actionSheet1 addButtonWithTitle:@"Action1"];
  [self.actionSheet1 addButtonWithTitle:@"Action2"];
  [self.actionSheet1 addButtonWithTitle:@"Cancel"];
  self.actionSheet1.cancelButtonIndex = 2;
  [self.actionSheet1 showInView:self.view];
}

- (void)showActionSheet2 {
  self.actionSheet2 = [[[UIActionSheet alloc] init] autorelease];
  self.actionSheet2.delegate = self;
  [self.actionSheet2 addButtonWithTitle:@"Action1"];
  [self.actionSheet2 addButtonWithTitle:@"Action3"];
  [self.actionSheet2 showInView:self.view];
}

- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
  if ( buttonIndex == actionSheet.cancelButtonIndex ) {
    // キャンセルされたとき
  } else {
    if ( actionSheet1 == actionSheet ) {
      // アクションシート1
      switch ( buttonIndex ) {
        case 0:
          // 1番上のボタンが押されたんならこんな処理
          break;
        case 1:
          // 2番めのボタンが押されたんならこんな処理
          break;
        default:
          break;
      }
    } else if ( actionSheet2 == actionSheet ) {
      // アクションシート2
      switch ( buttonIndex ) {
        case 0:
          // 1番上のボタンが押されたんならこんな処理
          break;
        case 1:
          // 2番めのボタンが押されたんならこんな処理
          break;
        default:
          break;
      }
    }
  }
}

こういった書き方は個人的にはあまり好きではありません。

できれば、UIButtonへactionを登録するようなイメージで、こんな感じで書きたいところです。

- (void)showActionSheet1 {
  self.actionSheet = [[[UIActionSheet alloc] init] autorelease];
  [self.actionSheet addButtonWithTitle:@"Action1"];
  [self.actionSheet addButtonWithTitle:@"Action2"];
  [self.actionSheet addButtonWithTitle:@"Cancel"];
  [self.actionSheet addTarget:self action:@selector(action1)];
  [self.actionSheet addTarget:self action:@selector(action2)];
  self.actionSheet.cancelButtonIndex = 2;
  [self.actionSheet showInView:self.view];
}

- (void)showActionSheet2 {
  self.actionSheet = [[[UIActionSheet alloc] init] autorelease];
  [self.actionSheet addButtonWithTitle:@"Action1"];
  [self.actionSheet addButtonWithTitle:@"Action3"];
  [self.actionSheet addTarget:self action:@selector(action1)];
  [self.actionSheet addTarget:self action:@selector(action3)];
  [self.actionSheet showInView:self.view];
}

- (void)action1 {
  // Action1 にたいするアクション
}

- (void)action2 {
  // Action2 にたいするアクション
}

- (void)action3 {
  // Action3 にたいするアクション
}

ということで、この書き方で使えるようILActionSheetという名前でUIActionSheetを継承した子クラスを作成して使うことにしました。

そのコードは、参考までに

に置いてあります。

また、このクラスを実際に使ってみたサンプルコードも、

に置いてみました。

paellapaella2010/03/15 14:23UIActionSheetは文字列の配列を使った初期化が出来ないのも面倒ですね。
配列を数え上げてaddButtonWithTitle:すればよいのですが、それはUIActionSheet側で行えばよいのでは?と思っています。
(初期化した後に配列を使って…というのはややこしくなってしまいますが)

tokoromtokorom2010/03/16 04:11おお、たしかに配列で指定できたほうが、コードがすっきりする場面がありそうですねー^^

harahara2010/03/17 18:25UIActionSheetを状態によって数パターン用意したときのclickedButtonAtIndexが嫌だったんですよね。これはいいですね便利。

stormstorm2010/08/13 19:41iPhoneソフトの開発法を調べていたらたどり着きました。
ものすごく便利なクラスを作られたんですねー。

よろしかったら商用アプリでコード使わせてもらっても問題ないですか?

tokoromtokorom2010/08/13 21:35まったく問題ないです!かわいがってやってください。

stormstorm2010/08/23 13:53ありがとうございます。
急な出張があったものですから、お礼が遅れて申し訳ありません。

それでは早速 使わせていただきます。 ソース今よりがスッキリしそうな予感です。

tokentokentokentoken2011/03/16 23:27確かにILActionSheetは便利です。ありがとうございました!

2010-02-14

UITableViewで移動不可のセルを設定する方法の訂正

| 13:03 | はてなブックマーク -  UITableViewで移動不可のセルを設定する方法の訂正 - iPhoneアプリ開発まっしぐら★

UIKit本追加/補足 > UIKit本の内容自体への補足/訂正 > UITableViewで移動不可のセルを設定する方法の訂正


※Twitterで @pactii さんにご指摘いただいての訂正です。@pactiiさん、ありがとうございました!

UIKit本の 9.3.6 セルの移動 (P.301) で一番下のセルを移動不可にする方法として以下のコードを紹介しています。

- (BOOL)tableView:(UITableView*)tableView canMoveRowAtIndexPath:(NSIndexPath*)indexPath {
  // 最後のセル以外ならYES
  return ( dataSource_.count > indexPath.row + 1 );
}

これは、UITableViewDataSourceプロトコルのtableView:canMoveRowAtIndexPath:メソッドで、任意のrowに対する戻り値をNOとすることでそのrowの置き換えを制限するものです。これを利用することで、特定のセルが置き換えできないように指定することができます。9.3.6のサンプルコードでは、一番下の「新規追加」というセルを移動不可に設定しています(図.A)。


◆図.A

f:id:tokorom:20100214130121p:image


しかし、これだけだと、「新規追加」のセルを移動することはできなくても、他のセルを「新規追加」のセルの下に移動することができてしまうことが発覚しました。今回、この点を訂正しお詫びさせていただきます。

他のセルを「新規追加」の下に移動できなくするには、UITableViewDelegateのtableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:メソッドを使います。

- (NSIndexPath*)tableView:(UITableView*)tableView
    targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath*)sourceIndexPath
    toProposedIndexPath:(NSIndexPath*)proposedDestinationIndexPath
{
  if ( dataSource_.count > proposedDestinationIndexPath.row + 1 ) {
    return proposedDestinationIndexPath;
  } else {
    return sourceIndexPath;
  }
}

これは、セルの移動の挙動を細かく設定するためのメソッドで、

  • 移動前の場所がsourceIndexPath
  • 移動予定の場所がproposedDestinationIndexPath

にそれぞれ渡されてきます。

このメソッドの戻り値に指定した場所が実際の移動先になるため、特に挙動を変更しない場合はproposedDestinationIndexPathをそのまま返します。逆に言えば、移動を許可したくない場合にsourceIndexPathを返してやれば、移動がされなかったという扱いにすることが可能です。

今回で言えば、移動予定の場所(proposedDestinationIndexPath)が「新規追加」の場所よりも下だった場合にsourceIndexPathを返すようにすることで、「新規追加」の場所を常に一番下に保つことが可能になります。



全ての読者の皆様、至らない点があり申し訳ありませんでした。


UITableViewCellにコントロールを追加する方法の訂正

| 13:40 | はてなブックマーク -  UITableViewCellにコントロールを追加する方法の訂正 - iPhoneアプリ開発まっしぐら★

UIKit本追加/補足 > UIKit本の内容自体への補足/訂正 > UITableViewCellにコントロールを追加する方法の訂正


※Twitterで @ytka さんにご指摘いただいての訂正です。@ytkaさん、ありがとうございました!

UIKit本の 9.4.8 セルにコントロールを追加 (P.319) でセルのカスタマイズについて以下のようなコードを紹介しています。


■誤ったコード

- (UITableViewCell*)tableView:(UITableView*)tableView
  cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
  static NSString* identifier = @"basis-cell";
  UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
  if ( nil == cell ) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:identifier];
    [cell autorelease];
  }
  cell.textLabel.text =
    [[dataSource_ objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
  switch ( indexPath.section ) {
    case 0: //< セルにUIImageViewを追加
      [cell.contentView addSubview:[self imageViewForCell:cell withFileName:@"Samurai.png"]];
      break;
    case 1: //< セルにUISwitchを追加
      [cell.contentView addSubview:[self switchForCell:cell]];
      break;
    case 2: //< セルにUISliderを追加
      [cell.contentView addSubview:[self sliderForCell:cell]];
      break;
    default:
      break;
  }
  return cell;
}

これは、図.Bのようにセルに様々なコントロールを追加するためのサンプルコードです。

図.B

f:id:tokorom:20100214133638p:image


これは誤ったコードで、この例のようにセルの再利用が発生しにくいケースでこそ問題は顕在化しませんが、セルの再利用が発生したときに、その再利用されたセルに次々とコントロールがaddSubviewされて画面がぐちゃぐちゃになってしまいます。

このように、dequeueReusableCellWithIdentifier:メソッドで取得したセルに対してコントロールを追加することは基本的にやってはいけません。dequeueReusableCellWithIdentifier:メソッドで取得したセルに対しては、値の変更のみ行うのが正しいやりかたです。

修正したサンプルコードを以下に添付させていただきます。

ここではセルを作成する流れがわかる箇所のみ抜粋しています。全てのコードは、

に置いてありますので、全体が必要な場合にはお手数ですがこちらをご参照ください。

UIKit本をお持ちのかたは、Subversionから更新していただくことで、この修正を含めた全サンプルコードをダウンロードいただけます。

□修正後のサンプルコード

- (UITableViewCell*)tableView:(UITableView*)tableView
  cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
  // カスタムセルの種類によって再利用のためのIDを変えること
  static const id identifiers[3] = { @"image-cell", @"switch-cell", @"slider-cell" };
  NSString* identifier = identifiers[ indexPath.section ];
  UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
  if ( nil == cell ) {
    // セルにコントロールを追加する場合は、セルの作成時に行う
    // ここでは各カスタムセルごとにUITableViewCellのサブクラスを定義して使っている
    // 各サブクラスの実装は http://iphone-book-sample.googlecode.com/svn/trunk/Chapter9/TableSample/Classes/SampleForCustomizedCell.m 参照
    // なお、各initXXXメソッド内でそれぞれのセルに必要なコントロールをaddSubviewしている
    switch ( indexPath.section ) {
      case 0:
        cell = [[[CellWithImageView alloc] initWithReuseIdentifier:identifier] autorelease];
        break;
      case 1:
        cell = [[[CellWithSwitch alloc] initWithReuseIdentifier:identifier] autorelease];
        break;
      case 2:
      default:
        cell = [[[CellWithSlider alloc] initWithReuseIdentifier:identifier] autorelease];
        [(CellWithSlider*)cell setDelegate:self];
        break;
    }
  }
  // 再利用のときにも通るコードでは、各コントロールの値の変更のみ行う
  switch ( indexPath.section ) {
    case 0:
      [[cell imageView] setImage:[UIImage imageNamed:@"Samurai.png"]];
      break;
    case 2:
      {
        // UISlider付のセルなら値を設定
        NSNumber* value = [self.sliderValues objectAtIndex:indexPath.row];
        CellWithSlider* cellWithSlider = (CellWithSlider*)cell;
        cellWithSlider.slider.value = [value floatValue];
        cellWithSlider.row = indexPath.row;
      }
      break;
    default:
      break;
  }
  cell.textLabel.text =
    [[self.dataSource objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
  return cell;
}

全ての読者の皆様、至らない点があり申し訳ありませんでした。

notoroidnotoroid2010/03/29 18:12楽しく拝見させていただきました。ドロップ中に「新規追加」の場所を維持する場合、sourceIndexPath ではなく[NSIndexPath indexPathForRow:proposedDestinationIndexPath.row-1 inSection:proposedDestinationIndexPath.section] を返すのはいかがでしょう?

tokoromtokorom2010/03/29 22:21なるほど、そうすると(一番下の)新規追加のところに移動できなくても、そのすぐ上に移動することになるわけですね^^
名案ありがとうございます!

muriyarikayomuriyarikayo2011/08/03 19:36こんにちは。
画面に表示しきれない数のCellがある場合は、notoroidさんのおっしゃるように、
現在表示されているCellのindexPathを返さないと、非表示のCellのキャッシュが出来てしまいUIが崩壊します。

grxqcblnwpgrxqcblnwp2014/02/04 23:06fyixpjqipof.efw, <a href="http://www.djlxctovam.com/">slmmwekfjh</a> , [url=http://www.cjdqexhwco.com/]yvkvuhadyt[/url], http://www.rmwwdekfmq.com/ slmmwekfjh