Author Archives

raizan2ame

Swift4:viewを中心に置く

iPhoneとiPadの機種毎のサイズに適合するようにviewを中心に置く方法をあれこれ考えました。

最初、すべてのオブジェクトを配列に定義し、x / yで動かしてみたのですが、よくよく考えたらUIViewで定義しておけば、個々のオブジェクトを動かす必要がありません。

しかし、iPadの場合、画面サイズが大きいのでローテーションに対応すべきで、そうなるとLandscapeだけに対応すればいいという安直回答は不適です。そう思いながら実装してみると、ローテーションするたびにシフト幅が加算されてしまうバグが出てしまい、結局、オブジェクトの全体サイズを知る必要がありました。

ない知恵を絞った結果、見えないUIButtonを下側に設置し、これから計算すれば面倒な計算をしなくていいとわかりました。

Screenshot 2018-06-03 10.35.01

Screenshot 2018-06-03 10.51.27

Screenshot 2018-06-03 11.03.05

Swift:modal delegate vs. storyboard ID

iOSの画面遷移の仕方がよくわかっていないという根本的な問題は一旦横に置いて、結局、storyboard IDで遷移した方が簡単です。

それに、独立性が高いので、書き方・考え方だけでなく、呼び出しも簡単です。結局、全部、storyboard IDで遷移する方法に書き換えました。もうひとついい点は、entry pointを設定しなくても遷移できるので、UIを一箇所にまとめて管理できます。

Screenshot 2018-05-30 21.27.23

Swift4:UITextView文字列へのリンク設定

UITextViewの文字列にリンク(URL)を設定する方法は、基本的には、色付の機能と同じ手順になります。

注意点は次の通りでした。

  • UITextViewの選択された文字列を覚えておく。
  • リンクを入力してもらう。
  • 選択された文字列にリンクを設定し、色付を行う。
    • ここでは、NSMutableAttributedStringでハンドリングする必要があり、UITextView⇆UILabel間で変換しないと、うまくいきません。
    • また、リンクを取得したあと、どこでその処理をキックするかにより色の制御ができません。

Screenshot 2018-05-29 07.10.38

Swift4:UIImageのリサイズ

リサイズするとボケる、あるいはリサイズの仕方はどうすればいいの?

スクリーンショットを撮ってリサイズする機能を実装してはじめて成程と納得しました。ボケることについては、画像が粗くなる(画像が劣化する)!?で言及されています。

実際のリサイズのコードについては、【Swift4】UIImageで画像のサイズ変更、指定した倍率で拡大/縮小に書いてある通りです。そのままで動きます。

注意:拡大・縮小比率を求めるとき、結果から-0.002すれば、該当図形枠からはみださずに収まりました。高さからマイナスして計算したのですが、それではうまく行きませんでした。参考まで。

Screenshot 2018-05-29 01.18.53

Swift4:サブスレッドで同期処理

iOSの同期処理の仕方をそもそもわかっていないこともあり、少し苦労しました。

訂正:サンプルプログラムへの影響はありませんが、画像で貼り付けたコードは正しく動作していないことが判明しました。呼び出されたB側でExecLink()を呼び出していたため、同期処理をしないものと同様の動作になってしまい、正しい結果が得られていました。

しかし@shtnkgmさんに助けて頂きました。感謝です。参照したページはSwiftで複数の非同期処理の完了時に処理を行うです。

そもそも根本的につまづいた点は、main threadでないと同期がうまくいかない(暴走してしまう)という点です。これは2行追加すればいいと教えてもらい、すぐにやってみたのですが、ロジックはうまく通っているのですが、UIに結果が反映されません。バグだとわかっていても、すぐに検出できず、一晩寝て、今朝、1行削除し過ぎたことに気づきました。

やりたかったこと:

  • 「UITextViewの選択された文字列にリンクを入れる」とき、リンクを予め用意したUITextFieldに入れるのでなく、ポップアップ画面を出して入れるようにしたい。
  • そうすれば、UITextFieldを画面に用意しなくてすみます。

Screenshot 2018-05-24 19.38.46

Xcode9.3.1サンプルコードはここにあります。コードは基本的に@shtnkgmさんがアップされているものと同じです。

 

 

 

Swift4:UITextViewにリンクを設定

UITextViewの選択されたテキストにURLリンクを設定できるようにしました。

この実装でひとつだけ注意するべきことがありました。次のエラーが出てしまうのです。

@IBOutlet weak var yUserNote:UITextView!
@IBOutlet weak var yLink:UITextField!

yUserNote.linkTextAttributes    = [NSAttributedStringKey.foregroundColor.rawValue:  colorLiteral(red: 1, green: 0.2527923882, blue: 1, alpha: 1)]

Cannot assign value of type ‘[NSAttributedStringKey : UIColor]’ to type ‘[String : Any]!’

これはSwift4.0からのようです。
参考:Swift 4.0でNSAttributedStringの装飾属性Dictionaryがエラーになる件

結局、次のようにしたらこの文法エラーは消えました。

yUserNote.linkTextAttributes    = [NSAttributedStringKey.foregroundColor.rawValue:  colorLiteral(red: 1, green: 0.2527923882, blue: 1, alpha: 1)] as [String:Any]

Screenshot 2018-05-18 11.20.48

 

 

Swift4:文字列に色付(ソースコード)

UITextViewの任意の文字列をユーザーが選択し、色をつけることができる機能を実装しました。ソースコードはここ

文字数の問題:

最初、UITextViewの.textを選択された文字列、その前の文字列、その後の文字列に分けて抽出し、NSMutableAttributedStringで色付けしたものと合成する方法で実装を進めました。しかし、この方法だと、yUserNote.selectedRangeで入ってくる選択範囲に絵文字が含まれると、文字数ではなく、バイト数で入ってくることがわかりました(参考:文字列の長さを取得)。ソースコードの最後にあるCallGetStringByNSRangeを参考にしてください。

  • 重要:文字列に2バイトコードが含まれる場合、pString.utf16.count のような表現にしないと、yUserNote.attributedTextと生合成が保てない。

文字属性の設定の仕方:

そこで、抽出合成方法を放棄し、次の通り、UITextViewをNSMutableAttributedStringでUILabelに取り出し、選択文字列だけを色付けし、UILabelからUITextViewに戻す実装にしました。wAtt = yUserNote.attributedText as! NSMutableAttributedStringとすると、Xcodeのバグと思われるのですが、この命令で以上してしまうため、その迂回作としてUILabel➡︎UITextViewとしました。

  • 重要:UITextViewは直接NSMutableAttributedStringをハンドリングできないが、UILabelを仲介すれば、うまくいく。

import UIKit                                                        //
import WebKit                                                       //
class MesaNote: UIViewController, WKNavigationDelegate, WKUIDelegate {//
    @IBOutlet weak var  yUserNote:UITextView!                       //Note area
    var wRangeOrg:NSRange               = NSRange()                 //
    var wAtt:NSMutableAttributedString  = NSMutableAttributedString()//
    var wLabel:UILabel                  = UILabel()                 //
    override func viewDidLoad() {                                   //
        super.viewDidLoad()                                         //
        let wkString2:String        = “012345678900️⃣1️⃣abcde”        //
        yUserNote.attributedText    = NSAttributedString(string: wkString2,//
          attributes:[.foregroundColor :UIColor.blue, .font :UIFont(name: “Arial-BoldMT”, size:15)!])//
    }//============================================================//

    @IBAction func ExecIBAColor(){                                  //<*Add color to the selected text*>
        wRangeOrg                   = yUserNote.selectedRange       //
        wLabel.attributedText       = yUserNote.attributedText      //
        wAtt                        = wLabel.attributedText as! NSMutableAttributedString//
        wAtt.addAttributes([.foregroundColor : UIColor.red], range: wRangeOrg)//
        yUserNote.attributedText    = wAtt
    }//============================================================//

    override func didReceiveMemoryWarning() {                       //
        super.didReceiveMemoryWarning()                             //
        // Dispose of any resources that can be recreated.          //
    }//=============================================================//

 func CallGetStringByNSRange(_ pString:String, pRange:NSRange) -> String {//<*NSRange指定範囲の文字列を抽出する*>
        if pRange.location >= pString.utf16.count || pRange.location < 0
           || pRange.length <= 0 || pRange.location+pRange.length > pString.utf16.count { return “” }
        return String(pString[Range(pRange, in: pString)!])         //
    }//=============================================================//
}

Screenshot 2018-05-16 23.59.29