Swift転職なら=>【LevTech】
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

頭痛が減ったので共有です!

rebuild.fmを応援しています!

HOME > UnmanagedとUnSafePointer

UnmanagedからUnSafePointer移管によるpassRetainedエラー対応

悩まされ続けております。CoreTextで文字を縦書きにしたいのですがSwift2のコードを3に移管する際にUnmanaged CFStringRefでつまづきました。 解決するまでの流れを記載します。

サンプル画像

参考:UnsafeRawPointer Migration
参考:swift3 で UnsafePointer
参考:https://swift.org/migration-guide/se-0107-migrate.html
参考:ルビを振る
参考:How to use CTRubyAnnotationRef in Swift
参考:How to convert Unmanaged to Swift 3
参考:swift3 で UnsafePointer
参考:インスタンスをUnsafeMutablePointerに変換して扱う
参考:How to use CTRubyAnnotationRef in Swift
参考:lingochamp/FuriganaTextView

やってみた

以下が問題のコンパイルエラーの行。↓以下はSwift2の箇所。


var text = [.passRetained(ruby) as Unmanaged?, .None, .None, .None]
let annotation = CTRubyAnnotationCreate(.Auto, .Auto, 0.5, &text)

↓Swift3の自動変換によって以下に変換されましたがエラーが保持されている状態(UnmanagedがUnsafePointerに変換されていますが、 passRetainedがメンバ関数に無いですとのエラー)


var text = [.passRetained(ruby) as UnSafePointer?, .None, .None, .None]
let annotation = CTRubyAnnotationCreate(.Auto, .Auto, 0.5, &text)

passRetainedとは一体何なのか?

Appleの公式サイトには、Creates an unmanaged reference with an unbalanced retain. と記載されている。アンバランスのretainでマネージされていない参照を作成する。はて、、、わからん。

どうやら retainは「保持」の意味でありObjectiveCでもでていた安全面での記載。Apple公式サイトの下の方にはインスタンスは漏れ出す可能性が あるとのことですので、Swift以外の参照を利用した「部外者」的なものでSwiftが管理しきれないデータを取り出す為の 参照ポイントを作りだす。といったところとの認識です。


参考:passRetained(_:)

履歴

↓Swift3の自動変換によって以下に変換されましたがエラーが保持されている状態(UnmanagedがUnsafePointerに変換されていますが、 passRetainedがメンバ関数に無いですとのエラー)


var text = [Unmanaged.passRetained(ruby) as UnsafeMutablePointer, .None, .None, .None]
let annotation = CTRubyAnnotationCreate(.Auto, .Auto, 0.5, &text)

このようにすると、Cannot convert call result type 'Unmanaged<_>' to expected type 'UnsafeMutablePointer<_>' のエラー。。。。

サンプル画像



要は文字列NSStringのポインタをUnmangedのものを渡せばよいので、、、、


	   
	   var text = [Unmanaged.passUnretained(ruby as CFString).toOpaque(), .None, .None, .None]
                        let annotation = CTRubyAnnotationCreate(.Auto, .Auto, 0.5, &text)
	

↑この上のtoOpaqueはこのインスタンスをUnSafeMutableRawPointerにする。でもまだダメだ。。。

格闘の結果、、、、


このサイトを元に作業How to use CTRubyAnnotationRef in Swift
		
	   let kanji = (x as NSString).substring(with: pair.rangeAt(1))
       let hiragana = (x as NSString).substring(with: pair.rangeAt(2)) as CFString;
       let furigana: UnsafeMutablePointer<Unmanaged<CFString>>! = UnsafeMutablePointer<Unmanaged<CFString>>.allocate(capacity:4)
       furigana[0] = Unmanaged.passUnretained(hiragana)
       let annotation: CTRubyAnnotation = CTRubyAnnotationCreate(CTRubyAlignment.auto, CTRubyOverhang.auto, 0.5, furigana)
		

ひとまずこれでコンパイルエラーが消えた。が確認できていないので再度進捗はアップしていく。サンプルではfurigana[1-3]をnullで初期化していたが 方法がわからず、何もセットしない、で処理している。


追記。やっぱり解決できていない。2017年2月17日

このコードでコンパイルは通るようになったがやはりエラー(CTFramesetterCreateWithAttributedString時にNSExceptionの エラーが)が発生している。対処のメモを残しておきます。Objective C の関数で対応したメモがあった。

	2017-02-17 05:46:39.428 testSwift3[970:17985] -[NSNull length]: unrecognized selector sent to instance 0x1097ad130
2017-02-17 05:46:39.435 testSwift3[970:17985] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x1097ad130'
	

参考:Unsafe Swift: Using Pointers And Interacting With C
参考:クックパッド開発者ブログ
参考:Swift UITextViewにて単語の上にルビを付ける方法

最終落ち着いたのは以下です。

			let kanji = (x as NSString).substring(with: pair.rangeAt(1))
			let furigana = (x as NSString).substring(with: pair.rangeAt(2))
                        
			var text: [Unmanaged?] = [Unmanaged.passRetained(furigana as CFString) as Unmanaged, .none, .none, .none]
			let annotation = CTRubyAnnotationCreate(.auto, .auto, 0.5, &text[0]!)
                        
			return NSAttributedString(
				string: kanji,
				attributes: [kCTRubyAnnotationAttributeName as String: annotation])
							
		

まとめ

紆余曲折してやっと落ち着きました。。。

↓こんな記事もありますよ!

のんでいるくすり: 3.11震災時の体験から開発されたお薬アプリ。無料

今日は薬を便利にかつ守秘的にメモできるアプリのんでいる薬をご紹介します。 実はアプリレビューは初めて。 SwiftサラリーマンのFBページを経由して開発者でもあり薬剤師のBlueRoy(ブルーロワ・インク) Inc. のShige様とお知り合いになる事ができて、是非レビューさせて下さいと私からお願いした経緯で今回レビュー記事に繋がりました。 Shige様、快く了承頂き本当にありがとうございました!

Pintoを1年利用してほんとにプログラマーの背筋がピンとなった(P!nto)

猫背どうにかならないかな、、、、。プログラマーとしての職業上日中8割9割は画面と押し問答している私は、 熱中すればするほど画面に食い入り知らず知らずに前のめりの姿勢に。姿勢が悪い、、、、分かってるんだけど、やめられない。

アプリから電話をかける

Objective-Cではサンプルがありましたが日本語では無かったので共有です!
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!