寺子屋管理者

  • アバター画像

教えて!Xcodeエラーメッセージとその解決策

公開寺子屋 2 年と 7 か月前に活動

Xcodeのエラーメッセージとその解決策についての寺子屋です。

メモリーリークについて教えてください。 (8件の投稿)

← 寺子屋講義   寺子屋講義案内
  • アバター画像 catiapple による3 年と 10 か月前の発言:

    instrumentsを使いメモリーリークの見方やメモリーリークについて勉強中なのですが、
    いざやってみると、どうおかしいのか分りません。

    アプリは時計で決めた時間によって時計のデザインが変わるようになっています。
    ViewControllerがそれぞれの画面に一つずつあり

    [self presentViewController:secondViewController animated:YES completion:nil];
    によって画面遷移をおこなっています。(この方法が正しいのかもわかりませんが。)

    リークされているだろうところを見ても、何がおかしくてなっているのかが、
    理解できずにいます。

    是非教えて頂きたいのですが。
    よろしくお願いいたします。

  • アバター画像 reborn による3 年と 10 か月前の発言:

    SecondViewControllerを作成し、そのviewを-presentViewController: animated: completion:で画面に表示させているだけで、-dismissViewControllerAnimated:completion:での取り外しをしていないのではないですか。

    タイマーが実行されるたびに
    SecondViewControllerのview
      その上に
    SecondViewControllerのview
      その上に
    SecondViewControllerのview
      その上に
    SecondViewControllerのview
    というように積み重なっているのでないかと思います。

    -presentViewController: animated: について、以下で「iOS View Controller プログラミングガイド」を読んでみてください。
    https://developer.apple.com/jp/devcenter/ios/library/japanese.html

  • アバター画像 catiapple による3 年と 10 か月前の発言:

    reborn先生いつも有り難うございます。
    iOS View Controller プログラミングガイド」読みました。
    まだ自分には意味難解な部分はありますが、ぼんやりとですが理解しました?

    -タイマーを使って時間によって時計のデザイン(色とか)を変えようと思いました。
    -storyboardで最初の画面(FirstViewController)ともう一つのデザイン画面(SecondViewController)をsegueで繋ぎました。
    -二つのViewControllerは時間の取得など全部同じコードにして画面遷移によって
    デザインが変わって現れるようにしました。
    このやり方で問題ないのか、まだ自分には判断できませんが、メモリーリークに関しては、FirstViewControllerのタイマーで毎回取得してSecondViewControllerに遷移するこーどになっていたようで、

    if (lastHour != hour) {
    lastHour = hour;

    if ((lastHour >=22)||(lastHour <= 23)) {
       [self performSegueWithIdentifier:@"nightMode" sender:self];
       }
    }
    としてみたところ、メモリーリークが無くなった感じです。

    SecondViewControllerでも同じようにして
    if (lastHour != hour) {
    lastHour = hour;
    if ((lastHour = 0)) {
    [self dismissViewControllerAnimated:YES completion:nil];
    }
    }
    とすれば良いと思っていますが、このように考えて問題ないでしょうか?

    気になるポイント等アドバイスを頂けたらと思います。

    よろしくお願いいたします。

  • アバター画像 reborn による3 年と 10 か月前の発言:

     -performSegueWithIdentifier:sender:や-presentViewController: animated: completion:(モーダル指定)で表示したUIViewControllerとそのビューは役目が終わった時点で-dismissViewControllerAnimated:completion:を使って表示を終わらせるのが重要なんで、その考え方自体は間違いではないんですが、SecondViewControllerでNSTimerを起動するタイミングとかNSTimerがターゲットを所有している点を考慮したプログラミングになるんで結構めんどくさいと思います。

     画面を操作する事が無く、単純に表示の切り替えだけなら、SecondViewControllerを使わずFirstViewControllerとNSTimerだけで、自分のビュー(FirstViewController のself.view)内で任意のビューの表示を切り替えるようプログラムするのが適切です。 

     例えばstoryboardでFirstViewControllerが持つビューに A と Bというビューを同じ大きさ、同じ位置に配置し、片方のalpha属性を0にして見えないようにしておき、NSTimerで時間ごとにAとBのalphaプロパティを0と1に切り替える方法です。
     そのさいにUIViewの+ animateWithDuration:animations:などを使ってalphaプロパティの変更をアニメーション化するといいでしょう。

  • アバター画像 catiapple による3 年と 10 か月前の発言:

    reborn先生 ありがとうございます。

    なるほど、そう言うやり方がある訳ですね。
    早速、トライしてみます。

    こういう発想は経験が無いと、なかなか思い浮かばないもんですよね。
    なんかスッキリした気分です。
    ちなみに

    if (hour == 21){
    firstView . alpha = 1.0;
    firstView . hidden = YES;
    [UIView beginAnimation : nil contex : NULL];
    [ UIView setAnimationDuration : 0.5];
    firstView . alpha = 0.0;
    secondView . alpha = 0.0;
    secondView . hidden = NO;
    [UIView beginAnimation : nil contex : NULL];
    [ UIView setAnimationDuration : 0.5];
    secondView . alpha = 1.0;
    }
    このようなかんじでしょうか?

    それぞれのViewにいくつかのUIImageがある場合(時計の針とか)
    それらのUIImageをグループ化してfirstViewまたはsecondViewとすればいいと
    いう事でしょうか?
    先生の言われる、”A と Bというビューを同じ大きさ、同じ位置に配置し”の”ビュー”とは
    UIViewのビューという事でしょうか?
    UIViewのAと言うビューとBと言うビューをViewControllerに作り、
    それぞれにImageViewでパーツをのせて行く感じでよいでしょうか?

    よろしくお願いいたします。

  • アバター画像 reborn による3 年と 10 か月前の発言:

     プロパティhiddenはアニメーションに対応していないので即座に消えてしまう事になります。alphaだけ変更すればいいでしょう。画面上はalpha==0でhidden==YESと同じ状態です。
     beginAnimationは今はiOS 4以降はお勧めではないので+ animateWithDuration:animations:系を使うといいですよ。hiddenやbeginAnimationについての説明はいずれもUIView Class Referenceに書かれています。英語ですけど。
    XcodeのHelp>Documention and API Referenceメニューで探せます。

    if (hour == 21){
       [UIView animateWithDuration:0.5 animations:^(
          firstView . alpha = 0.0;
          secondView . alpha = 1.0;
        }];
    }
    

    >それらのUIImageをグループ化してfirstViewまたはsecondViewとすればいいと
    >いう事でしょうか?

     そうです。
     ストーリボードのエディタでUIViewの上にUIImageViewを置けば、そのUIViewのサブビューとしてUIImageViewがグループ化されます。

     この状態でUIViewのalphaを0にすれば、それだけでサブビュー側のUIImageViewも消えます。

    >UIViewのビューという事でしょうか?
    >UIViewのAと言うビューとBと言うビューをViewControllerに作り、
    >それぞれにImageViewでパーツをのせて行く感じでよいでしょうか?

    そうです。
     ビューの階層化については「iOS Viewプログラミングガイド」(View ControllerではなくViewの方)で学習するといいでしょう。

  • アバター画像 catiapple による3 年と 10 か月前の発言:

    reborn先生 
    「iOS Viewプログラミングガイド」読みました。
    何度か読み返さないと,まだまだぼんやりとした所はありますが,
    大体の仕組みが分かりました。

    コードのほうも2つのUIViewで作り直し,無事動きました。
    2つのUIView上で時計の針もカラーを変えているため
    alphaを0にしている方も動いているかと思うと,やや非効率的かと
    思われますが、問題なく動作しています。

    大変有り難うございました。
    今後ともよろしくお願い致します。

  • アバター画像 reborn による3 年と 10 か月前の発言:

     そうですね〜、効率的なというレベルまでいきたいですね。
     針だけを回転させる事も可能で、その場合、紹介したView、View Controller プログラミングガイドの他に、Core Animationプログラミングガイドなんかも役立つでしょう。
     XcodeのHelp→Documentation and API Referenceで表示される画面でCGAffineTransformMakeRotationをキーワードにしてサンプルコードを検索するのもいいでしょう。

     ではでは。