↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

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

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])
							
		

まとめ

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

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


2021-05-14 14:21:41

WatchOSのwatchconnectivityのFiletransferの落とし穴。と、避け方。

AppleWatch 実機だと成功するんだけど、シュミレーターだと失敗するという、、、 昔作成してた時は成功してたのになーと思って調べると、どうやら昔は成功してたみたい。watchOS6以降は...

2021-05-06 14:04:37

LINEのアニメーションスタンプ制作の落とし穴、、、失敗談

ゴールデンウィークにLINEスタンプを作成してみました。 作り切って申請も通したんですが、意図したアニメーションと違う、、、、 LINEクリエーターの画面だと、アニメーションのプレビュー...

2021-05-01 18:05:35

久しぶりのAdmobをobjective-cに実装。コンパイルエラーだらけ。バーミッション不具合でエミュレータにインスコできない。

忘れないようにメモ エミュレータにアプリをインストールする際にパーミッション系のエラーがでた時、また、iphone実機にインストールする際にも権限系のエラーが出る場合。 ターゲット→ex...
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!