Guild icon
swift-developers-japan
archived / beginner-help-archived
初心者が質問をして誰かが助ける部屋 質問テンプレ [発生環境] Xcode 13.5 iOS 15.5 iPhone 13 Pro Simulator [解決したい問題] xxxが表示されない xxxが表示されるようにしたい [発生手順] 1. Aボタンをタップする 2. Bボタンをタップする [コード] コードを見せても問題ない人はリンクは貼ったり、記述したり 最小限で発生するコードだと尚望ましい
Avatar
ぼっちなう
Avatar
Deleted User 3/14/2017 2:17 PM
🤔
Avatar
Deleted User 3/14/2017 3:43 PM
🐶
Avatar
Deleted User 3/16/2017 2:23 AM
Avatar
🐍
🐳 1
Avatar
☔
🌈 1
Avatar
Deleted User 3/26/2017 7:58 AM
🐤
🐔 1
Avatar
beginner 🤗
Avatar
😽
😇 2
Avatar
omochimetaru 4/27/2017 4:04 AM
ちょっと趣旨変えてみた
👍 1
😀 1
Avatar
今UIWebviewを敢えて使うメリットって何かありますかね?単純に疑問に、思ったんですけど
Avatar
omochimetaru 4/27/2017 4:16 AM
UIWebView / WKWebView / SFSafariViewController の選択肢があるんだっけ。
Avatar
僕の専門だ
4:16 AM
お答えします。
👀 4
😆 1
4:17 AM
SFSafariViewController、こいつは要はSafariです。SafariExtensionsが使える他、Safariとクッキーキャッシュ共有している、プロセスも別という優れもの。
4:18 AM
しかし、任意のJavaScriptを実行できない、一度インスタンスを生成したら外からURLを差し込めないなど
4:18 AM
カスタマイズ性に乏しい。
4:19 AM
次WKWebView、こいつはJavaScriptが速いWebViewです(雑) APIも比較的ナウな感じでヤングなんですが、幾つかの機能(JavaScriptからTextAreaをアクティブにしてOKのプロパティ)が未実装だったり、通信フックができないのでProxy指したりアレヤコレヤは出来ません。
4:19 AM
なので
4:20 AM
纏めると、UIWebViewを使うメリット、通信フックしたい、JavaScriptからTextAreaをアクティブにしたい、等の、穿った需要がある場合に使います。どうしようもないから。
😯 2
😲 5
💯 1
Avatar
なるほど。 普通に使うぶんには使うことなさそうですねー。 ありがとうございます‼️ 🤗
😁 1
Avatar
Interface Builderで未だWKWebViewがない理由って何かあるんですか🙄
Avatar
import WebKitが必要だからだと思いますよ
Avatar
あー…Interface BuilderはUIKitで扱えるものだけなんですねー…。 なるほろ…
Avatar
あれ?GLKViewとか普通にあるな
4:52 AM
なんでだろ
Avatar
omochimetaru 4/27/2017 4:53 AM
SpriteKitのSKViewとかも置けるんだっけ
Avatar
designated initializer に以降変更不可の configuration 渡さなきゃいけないからだと思ってた。
💡 2
👏 1
Avatar
キーボードの上にToolbarを表示しようとしているんですが、IMEの予測補完周りの挙動がおかしくて困っています
8:23 AM
通常時は
8:23 AM
8:23 AM
こうなるのですが
8:24 AM
予測変換が消えると予測変換のスペース分下に下がらなかったり
8:24 AM
予測変換が消えた後予測変換がもう一回出ると
8:24 AM
8:24 AM
このように予測変換に隠れてしまったりして困っています
Avatar
UITextViewのinputAccessoryViewにUIToolbarを入れてやると良いですよ
Avatar
Notification.Name.UIKeyboardWillChangeFrame これが足りてないですね。
Avatar
UITextViewのinputAccessoryViewに何も考えずにUIToolBarを入れたらクラッシュしてしまいました(親viewを変えないといけない?) Notification.Name.UIKeyboardWillChangeFrameを足しても変わらないですね... コールバックはUIKeyboardWillShowと同じにしてますが、これがいけないんでしょうか
Avatar
うーん、ぱっと見ただけだとよくわからない、
8:46 AM
えっと、notification.userInfoの中にアニメーションの指定があるはずなので、それは参照した方が良いです
8:48 AM
もう一つ、keyboardのrectは、画面に対する相対位置になっているので、heightは見た目の高さと必ず等しくなるわけでは無いです
8:48 AM
でもこの2つは今の問題とは直接関係なさそう
8:53 AM
UIKeyboardFrameBeginUserInfoKey
8:53 AM
これ、変化前の高さですね
8:53 AM
UIKeyboardFrameEndUserInfoKeyがあるはず
Avatar
あ、動きました
8:55 AM
ありがとうございます!
😁 2
Avatar
普段はStoryboardを使わずにコードでアプリを開発しているのですが、Storyboardも使いこなさないといけないと思い今回はStoryboardで開発しています。そこでStoryboard上でのローカライズの質問なんですが、UILabelのAttributedTextがstringsでローカライズされないことに悩んでまして、これはコード上で解決するしかないのでしょうか?
Avatar
omochimetaru 4/30/2017 4:43 AM
無いと思っています・・・ ストーリーボード自体をローカライズできるけど、それやるとビュー自体を共通に保つのが大変すぎるし 方法があれば知りたい
Avatar
返信ありがとうございます。やっぱりそうですか。
4:47 AM
となると、viewDidLoadなりで、textやtitleに文字列を入れるときにNSLocalizedStringでローカライズするのがいいのかな。
4:47 AM
悩ましい。
Avatar
swiftなら、@IBOutletのdidSetに書くのが良いですね
4:49 AM
StoryboardにIBInspectableとか使って機能追加するのも出来るんですが、コード側でやった方が楽だなと言う印象があります。
Avatar
なるほど、ありがとうございます
Avatar
こんな感じでやれば出来ましたので一応共有
Avatar
NSLocalizedStringの引数のCommentの必要性が未だわからないです😩
Avatar
omochimetaru 4/30/2017 6:15 AM
""にしてる
Avatar
ですよね〜defaultで""にしていてほしい・・・
Avatar
omochimetaru 4/30/2017 6:25 AM
自分で func LSTR()を定義するとか?
Avatar
やはりそれですねー
Avatar
NSLocalizedString、素で使うの辛すぎてSwiftGenに頼ってます
Avatar
omochimetaru 4/30/2017 6:37 AM

SwiftGen とは

SwiftGen は、iOS / macOS アプリ開発の補助ツールです。リソース(アプリ内の画像やテキストなど)の扱...
6:37 AM
リソース定義をコードにしてくれるやつか
Avatar
ほぉ〜いいですね
Avatar
Safariの<input type="file">をタップすると出てくるファイルソースアプリ(?)一覧ってWebkit使わず出せますか?
10:15 AM
これです
🤔 2
Avatar
omochimetaru 5/1/2017 4:17 AM
iOSでリソースに静的型付けする系のプリプロセッサってどれがいいんですか? とりあえずSwiftGenとR.swiftが人気なのかなと思っていますが https://github.com/SwiftGen/SwiftGen https://github.com/mac-cain13/R.swift
SwiftGen - The Swift code generator for your assets, storyboards, Localizable.strings, … — Get rid of all String-based APIs!
R.swift - Get strong typed, autocompleted resources like images, fonts and segues in Swift projects
Avatar
R.swiftは、全部Rから始まるのがなんか微妙ですねー。なので個人的にはSwiftGen一択になりそう・・・ (edited)
3:54 PM
Pods嫌いな自分としては、Carthageに対応して欲しいです😭
Avatar
@tarunon これですね、ありがとうございます!
Avatar
@ありぜ ( SwiftGen については知りませんが普通は)Carthage 対応は簡単なんで、 fork して対応しちゃうといいかもですね。依存ライブラリが Carthage 対応してないと面倒ですが・・・。
Avatar
@koher そうなんですねー。ありがとうございます。試してみます。
Avatar
↓です。 "Archive prebuilt frameworks into one zip file" と "Declare your compatibility" はやらなくてもいいですし、タグもつけなくても Carthage でブランチ直指定できるので、依存ライブラリがなければ実質 Xcode で scheme の Shared にチェックを入れるだけですね。 https://github.com/Carthage/Carthage/blob/master/README.md#supporting-carthage-for-your-framework
Carthage - A simple, decentralized dependency manager for Cocoa
Avatar
swiftgenのcocoapodsって
4:57 AM
コードじゃなくてバイナリが降ってきてますよね、carthageでその仕組み出来るのかな
Avatar
"Archive prebuilt frameworks into one zip file" をやればできますね。
4:58 AM
ただ、僕は SwiftGen を使ってないので、あくまで Carthage 一般論のことしかわかりません。
Avatar
swift testで走らせないテストの指定ってできないですか? Xcodeだとdisableできるので重宝するのですが
Avatar
僕は知らないですが、 swift package generate-xcodeproj して Xcode 上で実行はダメですか?
Avatar
基本はそっちなんですがswift testもやらないで良いわけじゃないですよね? パフォーマンステスト等機能に直結しないものは走らせたくないという状況です。
Avatar
うーん、パフォーマンステストも走るのが正しい状態なんじゃないでしょうか?何かミスって計算量がおかしくなってて組み合わせ爆発したりするとダメなわけですし。
Avatar
機能改修によるパフォーマンスの向上を測るために設置してるので計算量的な問題は考えてないんですよね。
9:41 AM
とりあえずはswift testを極力しないという方針で回避が良いか。
Avatar
#if とかでできないかな?
Avatar
norio_nomura 5/2/2017 9:43 AM
一時的に走らせない?それとも SwiftPM では常に走らせない?
Avatar
常にですね
Avatar
norio_nomura 5/2/2017 9:44 AM
ならばテストメソッド定義自体を #if !SWIFT_PACKAGE で囲ってしまうのが良いのでは。 (edited)
👍 1
Avatar
お、それは良さそうですね
9:45 AM
SWIFT_PACKAGEの存在自体知らなかったです。
Avatar
norio_nomura 5/2/2017 9:46 AM
generate-xcodeproj で生成されたプロジェクトには何故か SWIFT_PACKAGE 定義が含まれているので、それを消した方が良いです。
Avatar
いいかんじになりました。ありがとうございます。
🙂 1
Avatar
omochimetaru 5/2/2017 12:09 PM
@ありぜ なるほど〜ありがとうございます
😀 1
Avatar

これはなに

  • 独自の拡張メソッドを認識しやすく、かつ名前が被らないようにするため、ex をもつプロトコロルを作成してそれに準拠させるという実装スタイルがある
  • その実装をするときにハマったので共有
# モダンなSwif...
12:34 PM
こんな記事書いたのですが、原因がよく分かっておらず、もし詳しく分かる方がいたら嬉しい
Avatar
norio_nomura 5/20/2017 1:22 PM
@sutokuro NonError_1_Contents.swiftNonError_2_Contents.swiftassociatedtype CompatibleTypeassociatedtype CompatibleTyp になっていますよ。
1:23 PM
でtypoを直すとError_Contents.swiftと同じ状態になります。
Avatar
なんと、ありがとうございます
3:38 PM
確かに、NonError_1_Contents.swiftはtypoを直すと、Error_Contents.swiftと同じエラーになりました
3:38 PM
NonError_2_Contents.swift はtypoを直すと正常に動作しました。
Avatar
Error_Contents.swift において、 extension String: ACompatible { } から推測される String. associatedtype の型はAExample<Self> extension String: BCompatible { }から推測される String. associatedtype の型はBExample<Self> で、型が一致していないのでエラーになりますね。 (edited)
11:46 PM
Playgroundのコンソール Playground execution failed: error: 20170520-221301.xcplaygroundpage:42:1: error: type 'String' does not conform to protocol 'BCompatible' extension String: BCompatible { } // ここで error: type 'String' does not conform to protocol 'BCompatible' が出る 20170520-221301.xcplaygroundpage:24:9: note: protocol requires property 'bEx' with type 'String.CompatibleType' (aka 'AExample<String>'); do you want to add a stub? var bEx: CompatibleType { get } ^ 20170520-221301.xcplaygroundpage:36:9: note: candidate has non-matching type 'BExample<Self>' [with CompatibleType = String.CompatibleType] var bEx: BExample<Self> { ^
Avatar
ありがとうございます。エラーの意味は理解できました。まだちょっと自分のなかで腑に落ちない部分が残っていますが、いったん置いておきます。
5:19 AM
ありがとうございました。
Avatar
今更見たんですが、SwiftGenのCarthage対応というのはナンセンスというかできないですね。tarunonさんが言っているようにCocoaPodsではCLIツールのバイナリを配布してて、Carthageが対応してるのはあくまでビルド済みのframeworkのバイナリなので、CLIツール用の仕組みではないです。
12:26 PM
なんかそういうissueが上がってるのを見た気がする。
Avatar
SwiftLintだけどこんなの https://github.com/realm/SwiftLint/issues/1481
Goals I would like to install a specific version of Swiftlint as a dependency to my iOS project using Carthage. Currently, this works perfectly with Cocoapods: pod 'SwiftLint', '0.18.1' As result, ...
12:52 PM
CocoaPodsやらBundlerやらnpmとか考えれば機能としてはおかしくはなさそう
12:53 PM
けどそこまでやるリソースはないのが現状
Avatar
SwiftPM対応すれば https://github.com/vknabel/Rock とか https://github.com/JohnSundell/Marathon こんなのもある
With Rock you can easily install CLIs built with Swift Package Manager.
Marathon makes it easy to write, run and manage your Swift scripts 🏃
Avatar
やっぱSwiftGenのCarthage対応むりなんですねぇ・・🙄残念
Avatar
Kotlin派からこれできないのかと質問を投げかけられ、確かにできないぐぬぬとなりました class Digest { let str: String init() { str = makeString() } private func makeString() -> String { return "hoge" } } error: use of 'self' in method call 'makeString' before all stored properties are initialized
Avatar
これは出来ないほうが安全です
8:04 AM
あーprivateか
Avatar
ただ、 private とはいえ、そこから public 呼べますからね。
Avatar
ですね
Avatar
仰る通りでまずこの使い方が微妙なのはありつつも
Avatar
funcは全てのフィールドと全てのfuncにアクセス可能
8:05 AM
そもそもそのfuncはinstance methodである必要が無いので
8:05 AM
staticで宣言したほうが良さそう
Avatar
omochimetaru 5/26/2017 8:06 AM

kotlinで本物のヌルポを出す方法

kotlinではnull安全ですからヌルポとは出会えません。でも、kotlinのnull安全機構においてクラッシュするケースがあります。 !! 演算子で明示的にクラッシュケースを書いた場...
👍 1
8:06 AM
これなげつけといて
Avatar
Kotlin版 class Digest() { val str: String init { str = makeString() } private fun makeString(): String { return "hoge" } }
Avatar
代理戦争で草
Avatar
omochimetaru 5/26/2017 8:08 AM
僕もはじめKotlinの経験があったんで、swiftの仕様はつらいなあと思ったんですけど、詳しく調べてみたら、それが原因でkotlinはヌルセーフじゃなくなってたんです
8:08 AM
今はSwiftのほうがマシだと思っています
Avatar
initとstatic funcの中では、static funcが型省略して書けるようになれば
8:09 AM
まあ良さそう、でもinitは完了後と完了前とで意味が変わってくるのは微妙かなー
8:10 AM
static funcはそもそも省略可能だった
Avatar
僕、最近 Kotlin の人化してますけどねw < 代理戦争で草
Avatar
omochimetaru 5/26/2017 8:10 AM
さりげなくdisりつつ解説しているので良い感じ @koher
Avatar
トロイの木馬じゃないか
Avatar
omochimetaru 5/26/2017 8:11 AM
www
Avatar
誠実であろう
Avatar
そんな dis ってたかな。検査例外がないのとか?
Avatar
omochimetaru 5/26/2017 8:12 AM
僕は、この点については List を実装した ImmutableList クラスを別に作って、 Scala のように厳密に区別すべきだったと思います。
8:12 AM
僕は、検査例外に関してはこちらのような考えなので、検査例外をなくしてしまったこと Kotlin の言語仕様の中で一番イケてないところだと考えています。
8:13 AM
前者は Scala 方式もまだイマイチで、 letvar でゼロコストでミュータビリティを変えられる Swift 最強
Avatar
omochimetaru 5/26/2017 8:13 AM
ですね
Avatar
let var, 一番最初のArray壊れてたときはどうなるかと思ったけどめちゃくちゃ良くなってるの感慨深い
Avatar
最初の壊れ方はひどかったですね。
Avatar
関数型界隈からすごい突っ込まれてましたね
Avatar
omochimetaru 5/26/2017 8:18 AM
その関数型界隈からのツッコミというのは知らなかったです これの事かと思った http://qiita.com/koher/items/6f54eafac59793e7c364
(2015.11.18に追記) __「Swift List」 で検索するとこの投稿にたどり着いてしまいますが、関数型言語でいうところのリストをお求めの方は ["Swiftでhead、tailにパターンマッチできる遅延リスト"]...
Avatar
あったなあ…
Avatar
昔の投稿が晒されると恥ずかしい・・・
Avatar
omochimetaru 5/26/2017 8:20 AM
冒頭でもう治ったって書いてあるしまあ
Avatar
以下の、Appleが最近発表したSwiftという言語の、面白い(?)仕様が話題になってますが、 twitter:476310789..
開発者アカウントに金が出せない貧乏人の方々が、次の Apple の Swift のコードの挙動がわからない、という..
Avatar
omochimetaru 5/26/2017 8:22 AM
古いパラダイムだなw
8:23 AM
8:23 AM
let a = [1,2] // a = [1,2] var b = a; // b = [1,2] b[1] = 3; // a = [1,3] b = [1,3] b.append(5); // a = [1,3] b = [1,3,5] b[1] = 4; // a = [1,3] b = [1,4,5]
8:23 AM
これは完全に壊れてたやつだ
Avatar
www
Avatar
omochimetaru 5/26/2017 8:23 AM
Avatar
Swift でもできた! class Digest { let str: String init(item: Digest) { str = item.makeString() } func makeString() -> String { return "test" } convenience init() { self.init(item: self) } } print(Digest().str) 完全にだめなやつw
Avatar
ンヒィ
Avatar
omochimetaru 5/26/2017 8:25 AM
んごwww
Avatar
おもちくん待望の本物のぬるぽかな?
Avatar
omochimetaru 5/26/2017 8:25 AM
お、これ利用すればヌルセーフ破壊dけいそう
8:25 AM
きたか
Avatar
ぜんぜんいけますよw
Avatar
omochimetaru 5/26/2017 8:25 AM
ヌルポじゃないよ、Swiftはunmanagedだから EXC_BAD_ACCESSが来るぞ
Avatar
画面越しに超喜んでるのが想像出来て草
Avatar
omochimetaru 5/26/2017 8:26 AM
www
Avatar
すごい、↓こんなの思いつかないw convenience init() { self.init(item: self) }
Avatar
self.initselfが渡せるのがもうおかしい気が
Avatar
それ通っちゃうんか...
Avatar
omochimetaru 5/26/2017 8:26 AM
この前のvar self書き換えに通じるテクニックですね
Avatar
バグですねー
Avatar
class Digest { let str: String let hello: String init(item: Digest) { str = item.makeString() hello = "test" } func makeString() -> String { return hello } convenience init() { self.init(item: self) } } print(Digest().str) // "" <- ?
8:26 AM
ん?
8:27 AM
Stringは、あれかw
8:27 AM
真にnullだったら""に化ける
8:27 AM
@ezura がこの辺は詳しかったはず
8:32 AM
できた。
8:33 AM
多分Stringの場合はそれ自体が値型で、メモリはゼロクリアされているんで、内部バッファへのポインタがnilとかサイズとか0とかいろいろ、ゼロ値でうまくうごく
8:33 AM
参照型のフィールドを初期化済み扱いで受け取れば壊せる
Avatar
オレオレStructでも落ちた Foo() 1(75709,0x70000aac2000) malloc: *** error for object 0x6180000129ec: Invalid pointer dequeued from free list *** set a breakpoint in malloc_error_break to debug
8:33 AM
見たことのないエラーだw
Avatar
omochimetaru 5/26/2017 8:33 AM
やばそうw
Avatar
not nullsafe より null unsafe の方がいいかも
Avatar
omochimetaru 5/26/2017 8:34 AM
かえといた
Avatar
Foo()はnilからうまいこと推測されて出てきたは良いものの、その後の諸々でぶっ壊れてる
8:40 AM
この間の @rintaro  のself書き換えでNib/Stroyboardのinstantiateが書けたけど
8:40 AM
やっぱりpropertyとしてletを置けないので価値はそこまで高くない感じ
8:40 AM
こうなる
Avatar
やばい、チャネルの内容が #beginner-help-archived じゃなくていつもの #swift モードになってるw
Avatar
あっ
Avatar
omochimetaru 5/26/2017 8:40 AM
あ、まちがえた
Avatar
#swiftじゃなかった
8:41 AM
気がついてなかった、すみません
Avatar
話が弾んじゃいましたねw
Avatar
では話題を戻して モダンなSwiftのExtension ですけど、 UIColor.hogeview.backgroundColor = .hoge できるけど UIColor.ex.hogeview.backgroundColor = .ex.hoge できないってどうなんですかね?
Avatar
omochimetaru 5/26/2017 6:24 PM
そのパターンって 1段しか推論できないんですっけ
6:25 PM
左辺値の型に対して探索する事は決まってるはずだから、右辺の式が多段になっててもできていい気がする(言語仕様の改善として
6:25 PM
両辺が不定のまま推論でガッチャンコするようなパターンもあるんだろうか、あまり書かなくてわからない
Avatar
それ#beginner-help-archivedの話題でいいの?
Avatar
むむ どこまでbigginerなのか悩ましいですね
Avatar
omochimetaru 5/27/2017 8:40 AM
質問する人が「広く答えが知られた問題であろうが自分が詳しくないためわからない」と感じるのが初心者質問のイメージ。
8:42 AM
ただ、本人がそう思っていても、高度なトピックだと思われる場合、そういうのが頻発すると、本当の初心者にとっては「ここは自分のような本当の初心者が発言するには場違いだ」と萎縮してしまうのは本意ではないので
8:42 AM
回答しようとした時に回答者がチャンネルを移動するのが良いかも?
8:43 AM
他にも、UIKitチャンネルとか、内容に即したチャンネルに移動するなり。
8:43 AM
ちょっとしたことでも以外とピンポイントだと知らない人も多かったりすることがあるんでトピックチャンネルのほうが知見が集約できて良いと思います
8:45 AM
話題を投稿する時点で「どこが適切だろう?」というのを気にしすぎてめんどくさくなるのは残念なので、まあ気軽に書き込んでもらって、
8:45 AM
回答する人が交通整理していくのが良さそう。
👍 5
Avatar
func mockFetch() -> Observable<Bool> { return Observable.create { observer in observer.on(.next(true)) observer.on(.completed) return Disposables.create() } }
2:41 AM
mockFetch().subscribe(onNext: { _ in print("done") }).disposed(by: disposeBag)
2:41 AM
↑の返り値が必要ない時に使えるSubject?とかコードの書き方とかってあるのでしょうか?
Avatar
返り値はこの場合何を指してますか?
Avatar
終了したことを教えたいだけです
2:44 AM
Emits zero elements Emits a completion event, or an error Doesn't share side effects
2:44 AM
CompletableならNext0個で、.subscribe(onComplete: {}) で拾うという手があるかも?
Avatar
もともとのモチベーションがcompletionHandlerをRxで書き換えたいという感じです
Avatar
completeが欲しいだけなら、ignoreElementsが使えそう
Avatar
ありがとうございますm( )m
Avatar
omochimetaru 5/29/2017 2:45 AM
それならSingleのほうが良い気も?Nextの型パラは <Void> にして気にしないとか
Avatar
たしかに、Voidで大丈夫ですね、、、
Avatar
今はcompleteだけで良いかもしれないけど、他でそうかという問題があるので、
2:47 AM
Single<Bool>にして値は適当に無視するのが良さそう。
👌 1
2:48 AM
さっきのmockみたいにnext, completeしたいだけなら create で書かずに .just でもかけますよ。下請けに本当の非同期処理がある場合は create ですね
Avatar
了解です!
Avatar
cocoapods(1.2.1)を使って開発してるんですが、写真のエラー出てしまい、解決できなくて困ってます。このエラーに出会った方とかいらっしゃいますか?再起動とかpod install とか Podsフォルダとか消していろいろ試しても無理でして。
12:08 PM
[CP] Check Pods Manifest.lock の内容は下記のとおり
12:08 PM
diff "${PODS_PODFILE_DIR_PATH}/Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null if [ $? != 0 ] ; then # print error to STDERR echo "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." >&2 exit 1 fi
Avatar
I'm currently working on an objective c project where we are trying to now incorporate swift into the project. When I add a Swift unit test to the project I get the following prompt: I create the
2:00 PM
差し支えなければPodfileとPodfile.lockの内容は上げれますか?
Avatar
platform :ios, '9.0' target 'XXXXX' do pod 'CorePlot', '2.2' pod 'Google-Mobile-Ads-SDK', '7.20.0' pod 'FBSDKCoreKit', '4.23.0' pod 'FBSDKLoginKit', '4.23.0' pod 'FBSDKShareKit', '4.23.0' pod 'Flurry-iOS-SDK/FlurrySDK', '8.1.0' pod 'Fabric', '1.6.11' pod 'TwitterKit', '2.8.1' pod 'TwitterCore', '2.8.0' pod 'Crashlytics', '3.8.4' pod 'SVProgressHUD', '2.1.2' pod 'Realm', '2.7.0' pod 'Repro', '2.4.0' pod 'SwiftLint', '0.19.0' end post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['CLANG_WARN_DOCUMENTATION_COMMENTS'] = 'NO' end end end
4:25 PM
PODS: - Bolts (1.8.4): - Bolts/AppLinks (= 1.8.4) - Bolts/Tasks (= 1.8.4) - Bolts/AppLinks (1.8.4): - Bolts/Tasks - Bolts/Tasks (1.8.4) - CorePlot (2.2) - Crashlytics (3.8.4): - Fabric (~> 1.6.3) - Fabric (1.6.11) - FBSDKCoreKit (4.23.0): - Bolts (~> 1.7) - FBSDKLoginKit (4.23.0): - FBSDKCoreKit - FBSDKShareKit (4.23.0): - FBSDKCoreKit - Flurry-iOS-SDK/FlurrySDK (8.1.0) - Google-Mobile-Ads-SDK (7.20.0) - Realm (2.7.0): - Realm/Headers (= 2.7.0) - Realm/Headers (2.7.0) - Repro (2.4.0) - SVProgressHUD (2.1.2) - SwiftLint (0.19.0) - TwitterCore (2.8.0): - Fabric - TwitterKit (2.8.1): - TwitterCore (>= 2.8) DEPENDENCIES: - CorePlot (= 2.2) - Crashlytics (= 3.8.4) - Fabric (= 1.6.11) - FBSDKCoreKit (= 4.23.0) - FBSDKLoginKit (= 4.23.0) - FBSDKShareKit (= 4.23.0) - Flurry-iOS-SDK/FlurrySDK (= 8.1.0) - Google-Mobile-Ads-SDK (= 7.20.0) - Realm (= 2.7.0) - Repro (= 2.4.0) - SVProgressHUD (= 2.1.2) - SwiftLint (= 0.19.0) - TwitterCore (= 2.8.0) - TwitterKit (= 2.8.1)
4:26 PM
SPEC CHECKSUMS: Bolts: 8a7995239dbe724f9cba2248b766d48b7ebdd322 CorePlot: cbe0c6e14220705e32e06a89c7d6a5a908b7d7d8 Crashlytics: 79e236942ca1e7fc641df1feb9a275360a78ab6a Fabric: 5911403591946b8228ab1c51d98f1d7137e863c6 FBSDKCoreKit: d7829f5a69901cd7296105328e4c3c3fc7da6518 FBSDKLoginKit: 6b92bd65f319d669d2b0730e49db495ef1660566 FBSDKShareKit: 65751c3b9937ab9d594e6c37611ecc115ceeb448 Flurry-iOS-SDK: 51065be4436f3e21fc8d3d7bb0b7d6869df6333d Google-Mobile-Ads-SDK: 168312cdc167fa22746d4ea8e839fc4825dd2966 Realm: 07e5d3a9e0e41d65fd5f9f05150ed6295d0f093b Repro: e69274efa79b1e8f25ec14177356968d9a8e8224 SVProgressHUD: c404a55d78acbeb7ebb78b76d3faf986475a6994 SwiftLint: 3537a05b34060e78e7510f04fb7537d738247803 TwitterCore: e959987be23c767004d29eb7fab8d85d8585a2e5 TwitterKit: 3b6044a7320340326a4098f3e37aa1dbaeb94942 PODFILE CHECKSUM: 47c07dc78a6793f29d1576ffa394f4c5e5b5076e COCOAPODS: 1.2.1
4:26 PM
ありがとうございます。Podfile.lockはDiscordの文字数制限でエラーになったので分割しました。
Avatar
上記の件、再起動して、Derived Dataをけしてクリーンしてビルドしたら正常に動作しました。金曜日にも同じ手順でやっても駄目だったんですが、今日やるとできました。
Avatar
おっ、再現できなくて参っていました、お力添えできずすみません。
Avatar
いえ、反応していただいただけでも、とても嬉しかったです。ありがとうございます。これで安心してWWDC見れます。
🎉 1
Avatar
くっ、ビルドはできたけど、アーカイブが同じエラーで止まってしまった
4:38 AM
辛い
Avatar
omochimetaru 6/5/2017 4:39 AM
~/Library/Developer/Xcode/Archivesも消してみては?
4:40 AM
Xcodeを Cmd + Q で終了してから以下を削除 ~/Library/Developer/Xcode/Derived Data ~/Library/Developer/Xcode/Archives
Avatar
~/Library/Developer/Xcode/Archivesも消して空です
Avatar
omochimetaru 6/5/2017 4:41 AM
むむむ
4:42 AM
そもそもCocoapodsの利用をやめることは難しいですか?
4:42 AM
僕はCocoaPodsもCarthegoも、オレオレビルドプロセスを取るのが嫌いで、使ってないんですよね こういう問題が起こった時に困る
Avatar
検討してますが、上記のPodfileを見るとおわかりかと思うのですが、coreplotを切ってから全てをCarthageに移行しようかと思ってまして。
Avatar
omochimetaru 6/5/2017 4:43 AM
なるほど
Avatar
あ、Cartheageもですか、では、自分でプロジェクトに手動で追加してると
Avatar
omochimetaru 6/5/2017 4:43 AM
はい。
4:43 AM
xcworkspaceで作業場を作って、ライブラリはxcodeprojをそれに追加する形にして、
4:44 AM
embedded libraryの依存を組んでビルド
4:44 AM
基本的にgit submoduleでやってます
4:44 AM
でも、kuroさんのケースだと使用数が多いから、carthageでcheckoutだけやって、ビルドだけxcodeに登録するのが良さそうな気もします
Avatar
embedded libraryの依存を組んでビルドして git submoduleでビルドする構成をやったことがないので知識が乏しいですが、その方法も考えて今後対応してみます。
4:48 AM
実は今回のエラーは、ビルド用、アーカイブ用のiMacでのみエラーが起きてて、普段開発で利用しているMBPでは特にエラーが発生せずにビルドできています。今回は、MBPの方でアーカイブ作成して申請することにしました。
4:48 AM
でも、今までとくにエラーもなくiMacでもビルドできていたので、なんでエラーが出てるのか正直よくわからなくて困っています。
Avatar
omochimetaru 6/5/2017 4:48 AM
なるほど・・・
Avatar
iMacとMBPのOSバージョンやXcodeのバージョンはもちろん同じなので
4:49 AM
cocoapodsも同じ
4:49 AM
なので、どこが問題の原因になっているのか特定できずうーんて感じです。
Avatar
omochimetaru 6/5/2017 4:50 AM
diff "${PODS_PODFILE_DIR_PATH}/Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null if [ $? != 0 ] ; then # print error to STDERR echo "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." >&2 exit 1 fi
4:50 AM
このエラーメッセージが出てるってことは、 ${PODS_PODFILE_DIR_PATH}/Podfile.lock と ${PODS_ROOT}/Manifest.lock の間に diff があるということですけど
4:50 AM
どんな差分だったんですか?
Avatar
あ、いや echo "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. このメッセージは出て無くて、差分はないと思います。
Avatar
omochimetaru 6/5/2017 4:52 AM
ああ、なるほど
4:52 AM
[CP] Check Pods Manifest.lock < これは 緑のアイコンだった。
Avatar
このエラー
4:52 AM
なので、unknown reasons なのでわからんいんです。
4:53 AM
うーん、やっぱりomochimetaruさんのビルド方法を検討するほうが、無駄な問題に悩むずに済むような気がしてきました。
Avatar
omochimetaru 6/5/2017 4:53 AM
console.app に関係ありそうなログは出てませんか?
4:54 AM
individual build tasks 達が内部で抱えたエラーについての情報が集められないと厳しそう (edited)
Avatar
ほう、console.appですか、見てみます。
Avatar
omochimetaru 6/5/2017 4:55 AM
はい、一部のプロセスやデーモンはここにエラー吐いてる事があります。
4:58 AM
ビルド方法
1. xcworkspaceを作る。(これ自体はただのxcodeprojの配列のようなもの) 2. ライブラリとアプリのxcodeprojをxcworkspaceに追加する 3. アプリの ターゲット の General / Embedded Frameworks and Libraries の一覧の「+」を押してダイアログを出す。 4. ダイアログの中に、xcworkspaceに入れてあるxcodeprojのライブラリターゲットが並んでるので、それを選ぶ 5. アプリをビルドすると依存ビルドされる という感じ
5:00 AM
デメリットとしては ・ライブラリのバージョン合わせについては手動でがんばる(か、carthageをそのチェックアウトだけに使うなど) 工夫が必要 ・xcodeの schema リストに、入れてある全てのxcodeprojのターゲットが突っ込まれるので、めちゃくちゃターゲット数が多くなって気持ち悪い。これは心の目で無視する。 ・普段はキャッシュされるのでアプリ部分だけのリビルドで済むけど、何かが壊れた時にはクリーンする必要があって、その場合ライブラリ全部リビルドになるので待ち時間が長い。
Avatar
ありがとうございます。涙が出ます。
5:01 AM
console.app を開けながら
5:02 AM
再度Xcodeでアーカイブして失敗したのですが、どこにエラーらしきログが出ているのか
5:02 AM
把握するのが難しい。
Avatar
omochimetaru 6/5/2017 5:03 AM
macOS Sierraだとして、デバイスのとこでマシン名出てるの選んで、上部のバーで「エラーと失敗」のタブを開いておく
Avatar
ああ、デバイスを選ぶと「エラーと失敗」のタブが選択できるんですね。できた。
Avatar
コンソールのエラータブに出てたエラー
5:14 AM
Xcodeでアーカイブしているときに出たエラーは、これだけでした。
5:15 AM
でも、あまり関係なさそうな。
Avatar
エラーの詳細
5:24 AM
skylight framework ? 初めて聞く名前
Avatar
omochimetaru 6/5/2017 5:57 AM
Skylight.frameworkでググるとSierraにしたらクラッシュするようになった、みたいなイシュー報告と共に出てきますね
5:58 AM
いまいちわからないですねえ
Avatar
ぐぐると、でますね。もう少し色々ためして様子を見ます。omochimetaruさん色々反応してくださりありがとうございます。
Avatar
omochimetaru 6/5/2017 6:05 AM
はいー
Avatar
Alamofire(HTTPリクエストを簡単にするラッパーのライブラリ)でAPIにリクエストした結果を、どうしてもストレージにキャッシュさせたくないんですが、いい方法はないでしょうか。 https://stackoverflow.com/questions/32199494/how-to-disable-caching-in-alamofire を参考にしてみたのですが、どうやらこれは「現在のリクエストについて、キャッシュされていたデータを利用するかしないか」という設定なのか(これは勝手な推測です)、iPhone SimulatorのLibrary/Cachesの中にはAPIリクエストの結果が保存されてしまいます。 (edited)
When I send a GET request twice with Alamofire I get the same response but I'm expecting a different one. I was wondering if it was because of the cache, and if so I'd like to know how to disable it.
Avatar
URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil) で解決しました(この方法だとアプリ全体でキャッシュが効かなくなりますが、画像周りは独自のキャッシュを実装していたので今回は影響がなかった
🙂 2
🙃 1
Avatar
HTMLから変換したNSAttributedStringで、リンクをタップした際の挙動をSafariを開く挙動から自分で定義した挙動に変更するにはどうしたらいいのでしょう
Avatar
delegate実装すれば拾えますよ
Avatar
なるほどdelegate
12:32 AM
ありがとうございます
3:37 AM
上記のエラーに悩まされていまして,
3:37 AM
Xcodeビルドできない状態が続いています。
3:37 AM
Clean Clean build folder Quit Xcode Open Finder then go to ~/Library/Developer/Xcode/DerivedData then deleated everything inside Open Xcode Build
3:37 AM
一通り試したのですが、エラーが解消できず。
3:38 AM
同じエラーに遭遇した方いらっしゃいますか?
3:38 AM
ちなみにobjcのファイルをswiftにリファクタリングしているときに起こります。
3:38 AM
Xcodeは8.3.3です。
Avatar
上記の件、一応解消できたので報告。Macの初期化までして色々試してもだめでしたが、cocoapodsやfastlaneを管理するGemfileやvendor/bundleフォルダを削除すると正常にビルドできるようになりました。fastlaneをつかったモダンなデプロイ環境は一旦諦めることになってしまいました。なぜ、Gemfileやvendor/bundleフォルダがあると、上記のエラーが頻発する(エラーがでないときもある)のかはわからなかったです。いつもswiftのコンパイルが始まると上記のエラーになるので、もしかするとswiftのコンパイラーと私のGemfile等の設定の相性が悪いのかもしれません。どこかのブログでobjcとswiftの混合プロジェクトにおいて、swiftファイル数が多くなるとビルドに失敗することが多くなるといった記事を見かけたので、それも原因の一つかもしれません。ちなみに、エラーの起きていたプロジェクトの構成は objc (1194ファイル)でswift(378ファイル)あります。全てswiftにするまでの道のりは結構険しい。
4:56 AM
長文失礼しました!
Avatar
omochimetaru 6/21/2017 4:56 AM
お疲れ様です・・ 長文気にしなくて大丈夫です
Avatar
そう言っていただけるとありがたいです
😀 2
4:57 AM
なんか質問しかしてないアカウントになりつつあるので、ちゃんと何かしらの形で貢献しないと!(できるのか笑)
Avatar
omochimetaru 6/21/2017 4:59 AM
質問をすると他の人が質問をする心理的ハードルが下がるという貢献があります
😀 4
Avatar
rbenv, rbenv-gemset, bundler併用するとどうなるでしょう、環境汚さないでgemの管理ができるようになるので何か変わるかもしれません
Avatar
rbenvでrubyのバージョンを固定して bundle install --path vendor/bundle して bundle exec fastlane ios staging とか bundle exec pod install とかしてました。 rbenv-gemset (edited)
5:04 AM
は知らなかったので今度試します。
Avatar
なるほど...問題なさそうな構成ですね 手元でcocoapods、fastlane動いてるGemfileになります、お役に立つか分からないですが # frozen_string_literal: true # A sample Gemfile source "https://rubygems.org" gem "fastlane" gem 'cocoapods' gem 'cocoapods-keys'
Avatar
ありがとうございます。ほぼ一緒ですね
5:08 AM
source "https://rubygems.org" gem "cocoapods", '1.2.1' gem "fastlane", '2.11.0'
🤔 1
5:08 AM
fastlaneのバージョンが古いのは
5:08 AM
New Issue Checklist Updated fastlane to the latest version I have read the Contribution Guidelines Issue Description I updated fastlane(2.11.0) to the latest version(2.23.0) by bundle update fa...
5:09 AM
このエラーに悩まされて、fastlaneにissueを投げた当時から固定してたからです。
5:09 AM
当時の構成とはまたcocoapodsとかコードの構成が変わっているのでまたやると同じかどうかわからないですが。
Avatar
これから取り急ぎiOSアプリ開発を始める人に向けて、本を2冊だけ紹介しようとしてます。 1冊は言語周りということでSwift実践入門を薦めようと思ってます。 ただ、もう1冊どうしようかなと悩んでます。 内容的にはUI周りを含めた現段階でのプラクティス本を薦めたいのですが、心当たりある方いらっしゃいませんか? 昔でいうとtokoromさんのiPhoneプログラミングUIKit詳解リファレンスみたいなのの現代版があるとウレシィのですが。。
Avatar
プログラミングの経験はどのぐらいある方ですか?
Avatar
4年目Androidエンジニアです。 職場のコードがレガシーMVCだらけな中、自分からRxJavaとMVVMに挑戦中のモチベーション高めなエンジニアですー
Avatar
そういった本がSwiftになってからでてないのがほんとに寂しいんですけど、僕が前新卒に課題図書として出した本の中から1冊だけ紹介しておきます。2冊出したんですけど、もう一冊はプログラミングの初歩から書いてある本で、4年目の方だとつまんなく感じてしまうと思うので。 本気ではじめるiPhoneアプリ作り Xcode 8.x+Swift 3.x対応 (ヤフー黒帯シリーズ) 西 磨翁 https://www.amazon.co.jp/dp/4797389826/ref=cm_sw_r_tw_dp_x_FBivzbQ7Z4187
😊 1
Avatar
おお、ありがとうございます。良さそうですね!
5:20 AM
ボソッ (アフィ付きでいただければそこからポチりますよ〜)
Avatar
(クッソそういうの持ってない😇
😇 2
Avatar
ではこのままポチらせていただきますw d_dateさんありがとうー
Avatar
omochimetaru 7/7/2017 2:15 AM
あれ?
2:15 AM
なんか今ファントム投稿あった?
Avatar
ファントム投稿w
2:15 AM
読んでたら消滅した
Avatar
ファントムしましたw 途中でなげてしまったので、今やりなおしてますw
Avatar
omochimetaru 7/7/2017 2:15 AM
「幻影だ」
Avatar
Enter で投稿するシステム、人権侵害なので国連で規制議論されてほしい
Avatar
iPhone版なら改行は改行だよ
Avatar
あー、モバイル版は人権守られてますね
Avatar
omochimetaru 7/7/2017 2:17 AM
Enter押すな
Avatar
Shift + Enter できないから
2:17 AM
SKK 過激派か?
Avatar
iPadはEnterで飛んでいきますね
2:17 AM
どこに投げていいかわからないトピックなので、とりあえずここに投げてみます。 VCのViewDidLoadで、あるメソッドを通過していないときにエラーを吐かせたいと思ってるんですけど、assertを書くことにすると、そもそもassertを書く人はそのメソッドを呼ぶのが必要だと認知しているので、assertはいらないことになります。 具体的には、Clean Architectureで、画面遷移前にpresenterをinjectするようなケースです。presenterはIUOで定義しているので、セットしていないpresenterにアクセスした時点でクラッシュするのでランタイムでは検知できますが、ビルドエラーで検知できたらベストだと思っています。このあたりみなさんどんなふうにやってますか?
Avatar
VCにカスタムinit定義するのがはやいんじゃ
Avatar
omochimetaru 7/7/2017 2:19 AM
同じような悩みを抱えたことがある気がする
2:19 AM
コンストラクタが使えれば解決するけどXIBとの兼ね合いでできず
Avatar
こういう便利なものがありまして(ステマ) https://github.com/tarunon/Instantiate
Instantiate - Type-safe and constructor injectable InterfaceBuilder protocols.
Avatar
omochimetaru 7/7/2017 2:19 AM
このViewControllerはこのプロパティを埋めてからpresentしろってなる
2:20 AM
injectって言ってるからこの場合はプロパティを埋めるんじゃなくて初期設定メソッドを呼ぶみたいな感じだろうけどまあsetter呼び出しもメソッドと考えると同じ
2:20 AM

as is

let storyboard = UIStoryboard(name: "ViewController", bundle: Bundle.main) let vc = storyboard.instantiateInitialViewController() as! ViewController vc.inject([1, 2, 3])

to be

import Instantiate import InstantiateStandard extension ViewController: StoryboardInstantiatable {} let vc = ViewController(with: [1, 2, 3])
Avatar
そのまま使うとviewを先にloadしちゃうけど、ちょっと拡張すればview後にloadも出来るから多分大丈夫じゃないかな
Avatar
omochimetaru 7/7/2017 2:22 AM
これってこの ViewController.init(with:) を 呼ぶことを忘れなければうまくいくけど
2:22 AM
それを呼ぶのを忘れない仮定をおけるのであれば
2:22 AM
規定の初期化処理をするのを忘れないと言えそうな気が。
2:23 AM
もちろん、忘れない前提において、tarunonのやつのほうがスッキリするところは旨味だけど
2:23 AM
相談内容の前提は解決してない気がする。
Avatar
他のinitをunavailableすればオッケーですね
Avatar
omochimetaru 7/7/2017 2:23 AM
お、なるほど・・・
Avatar
overrideでunavailableできますよ
Avatar
omochimetaru 7/7/2017 2:24 AM
Instantiateの内部で他のinit呼んでてそこでunavaiable警告出たりしないの?
Avatar
nib/sbから取り出してるからinitは存在しない
Avatar
omochimetaru 7/7/2017 2:24 AM
確かに!!!!!
2:24 AM
そうですね。
Avatar
そもそもassertを書く人はそのメソッドを呼ぶのが必要だと認知しているので、assertはいらないことになります。
これって VC を実装する人目線ですか?使う人目線ですか?↑の @omochimetaruinject みたいに「あるメソッドを通過」が外から呼び出すことを意図しているなら、 assert を書く人と呼び出す人が別な気がするので「assertはいらない」ことにならない気がするんですが・・・。
(edited)
Avatar
自分は遷移処理を抽象化してVrewController用のRouter書いてしまってます requestに対してrouterがviewControllerのインスタンスを返す、みたいな
Avatar
inject関数が型として抽象化されていて、viewControllerのタスクも同様に抽象化されていれば
2:30 AM
injectの引数からviewControllerのタスクの結果を取り出すRouterみたいなのも普通に出来ますね
Avatar
omochimetaru 7/7/2017 2:31 AM
@moaible ナマのstoryboardメソッドや生のコンストラクタは触らない規約でやっていくってことですか?
Avatar
@omochimetaru ViewControllerにrouterに適合させるためのstaticな関数を置いて、そこに問い合わせるのでその中なら生のコンストラクタを使ってもいいですし、storyboardから生成してもいいしって感じにしてます
Avatar
omochimetaru 7/7/2017 2:33 AM
なるほど
Avatar
案の定だけど議論の中身が #swift みてきた
Avatar
omochimetaru 7/7/2017 2:35 AM
@unavailable をある特定の呼び出しにおいてだけ警告抑制できれば
2:35 AM
staticメソッドおいておいて他のファクトリ経由を矯正することがある程度できそうですね
Avatar
ちょっと話かけられて離れてる間にすごい進んでました😇 ありがたいです
Avatar
omochimetaru 7/7/2017 2:35 AM
@moaible のRouter や @tarunon のInstantiateと同じように
Avatar
Instantiateはinitアレするので、alloc/deallocが一回ずつ余分に発生するけどね。
2:36 AM
@rintaro 先生ソース
Avatar
omochimetaru 7/7/2017 2:36 AM
storyboardから取り出すメソッドを利用禁止するのは無理かなあ
Avatar
スコープ対象の unavailable が欲しい時がある。 @available(*, unavailable, scope: public) 的な (edited)
Avatar
あるある
2:37 AM
storyboard自体は禁止しなくても流石にinitとかfactoryメソッド生えてたら間違えないとは思うけど
2:43 AM
overrideせずにprotocol生えてたらこのメソッド禁止!トかやりたいけど出来ない。
Avatar
みなさんありがとうございます。どれも良さそうなんですけど、tauronさんのInstantiateを採用するのが今のソースコードには合ってそうな感じがしました。 (にしてもこのあたりもうちょっと簡単にできたらいいなー…)
Avatar
norio_nomura 7/7/2017 12:26 PM
githubのリポジトリへのアクセスにsshをあえて使う理由って何があるのでしょう?
Avatar
二段階認証してると、HTTPSでpushするときにgithubのアカウントのパスワードが使えないとかですかね
Avatar
トークンで良いはず
12:53 PM
何もかもが面倒臭くてhttpsを使いがち。
Avatar
あーたしかに
12:53 PM
あとはgithubのパスワードをローカルのストレージに保存しなくていいとかですかね
12:54 PM
(それもtoken使えばいいか)
Avatar
omochimetaru 7/7/2017 1:22 PM
@norio_nomura pushするために自分のリポジトリはそうしてます。認証機構としてssh-agentなのも安心感がある。
1:22 PM
httpsだとコンソールでuseridとpassword聞かれるけどそれはどうなるんだろ
1:23 PM
githubにかぎらず普通にssh先のサーバーにリポジトリ設置したりした場合も
1:23 PM
httpsよりそっちのほうが素直に構築できるし。
1:24 PM
僕も push するリポジトリは ssh です。
Avatar
norio_nomura 7/7/2017 1:24 PM
パーソナルトークンをそれでkeychainへ入れてますね。
Avatar
omochimetaru 7/7/2017 1:26 PM
なんかすでにそれもセットアップしてあった
1:26 PM
たしかgithubってHTTPSでリードしかしてなくても
1:26 PM
たくさんやってるとブロックされた気がする
1:27 PM
このマニュアル見る限りあそこでコンソールでパスワードいれたら保存されるのか・・・?
Avatar
norio_nomura 7/7/2017 1:27 PM
パーソナルトークン使ってるとその制限は緩くなったはずです。>アクセス権限 (edited)
Avatar
omochimetaru 7/7/2017 1:28 PM
はい。リードでブロックされて、調べて、これをセットアップしたような記憶がありまsj
1:31 PM
うーんそうするとhttpsでもいいのかなあ。
Avatar
norio_nomura 7/7/2017 1:31 PM
このマニュアル見る限りあそこでコンソールでパスワードいれたら保存されるのか・・・?
キーチェーンに保存されます。
Avatar
omochimetaru 7/7/2017 1:31 PM
gitプロトコルについてよくしらないんですけど
1:31 PM
sshでパイプで相互IOつないで
1:31 PM
差分計算とかいろいろやってるけど
1:31 PM
httpsのときも
1:31 PM
トランスポートが違うだけで同等なことができているのか
1:32 PM
httpsだと簡易的な(効率の悪い)プロトコルになるのか
1:32 PM
そういうのが気になる。
1:32 PM
思い出してきた、昔読んだ何かにそんな話題があったようななかったような
Avatar
norio_nomura 7/7/2017 1:33 PM
sshの場合、ちゃんと設定しないとhttpsより遅かったはずです。
1:33 PM
>SSH : 最後に、HTTP/S、Git、Local プロトコルと同程度に効率的です。転送するデータを可能な限りコンパクトにすることができます。
1:34 PM
しかしバージョン 1.6.6 でより高機能なプロトコルが導入されました。これは、SSH の場合と同じように、HTTP でのデータのやりとりも Git が賢く処理できるようにするためのものでした。 ここ数年で、新しいほうの HTTP プロトコル はとても多く使われるようになりました。ユーザーからすればこちらのほうがシンプルですし、通信方法としても優れているからです。 新しいほうは “smart” HTTP プロトコルと呼ばれていて、古いほうは「ダム」(dumb)HTTP プロトコルと呼ばれています。 まずは “smart” HTTP プロトコルのほうから説明しましょう。
1:34 PM
HTTPS上のgitに2種類あって、1.6から smart HTTP というのができて
1:34 PM
これが効率的らしい
1:35 PM
自分がgit勉強したときこの記述なかった気がするし知識が古かったのか
1:36 PM
1.6が 2010年9月だしそんなこともなさそう・・・
1:42 PM
Username for 'https://github.com': omochi Password for 'https://omochi@github.com': remote: Invalid username or password.
1:42 PM
パスワード通らない・・・
1:43 PM
ああ、2FAの場合の設定は別口からやるのか
Avatar
norio_nomura 7/7/2017 1:56 PM
If you have enabled two-factor authentication, or if you are accessing an organization that uses SAML single sign-on, you must provide a personal access token instead of entering your password for HTTPS Git.
https://help.github.com/articles/which-remote-url-should-i-use/
Avatar
omochimetaru 7/7/2017 1:56 PM
セットアップできました。
Avatar
omochimetaru 7/11/2017 2:14 AM
Via HTTPS For those checking out sources as read-only, HTTPS works best: git clone https://github.com/apple/swift.git ./swift/utils/update-checkout --clone Via SSH For those who plan on regularly making direct commits, cloning over SSH may provide a better experience (which requires uploading SSH keys to GitHub): git clone git@github.com:apple/swift.git ./swift/utils/update-checkout --clone-with-ssh
2:14 AM
swiftのリポジトリにも、sshのほうが may provide a better experience って書いてあるけど
2:15 AM
この前のからするとそうでもなさそう
Avatar
import UIKitしてるファイルで、UI系のクラスを使っていなくて、import Foundationで事足りる場合、Foundationに変更した方がいいですよね? UIKitのままにしておくメリットってないですよね?
Avatar
僕の知る限りはないように思います。
Avatar
ありがとうございます!
Avatar
import UIKit let numbers = (1...5).map(String.init) print(numbers) // ["1", "2", "3", "4", "5"] var a: [String] = [] // No Error a = Array(numbers.prefix(3)).map { $0 } print(a) // ["1", "2", "3"] // No Error let arraySlice: ArraySlice<String> = numbers.prefix(3) a = arraySlice.map { $0 } print(a) // ["1", "2", "3"] // Error(error: ambiguous use of 'prefix')→ なぜエラーに? // a = numbers.prefix(3).map { $0 }
4:27 AM
最後の numbers.prefix(3).map { $0 } ambiguous use of 'prefix' になる理由がわからず。
Avatar
前に #swift 部屋で話題になったやつだ
Avatar
あ、既出ですか
4:28 AM
出遅れた
Avatar
要約するとたしか、prefixはoverloadになっていて、その両方Sequence型でmapを持っているため
4:29 AM
だったかな
Avatar
#swift 部屋を遡ってみます
Avatar
prefixで検索すると見つかります
Avatar
ありがとうございます。
Avatar
5月23日ですね
4:31 AM
パーマリンクほしいなぁw
Avatar
(同じく検索してパーマリンク取ろうとしたけどできなかった)
Avatar
ジャンプボタンが存在するんで、内部的にはありそう(作れそう)なんですけどね
Avatar
t.aeさんの話ですね
Avatar
ArraySliceにおいてprefixはAnySequenceとArraySliceのoverloadで、これのどちらであるかを判別できなくなるのが原因ですね。
😃 1
4:34 AM
evolutionにはSequenceのassociatedtypeにSubSequence型を追加して解決しようよという提案があった記憶があります、どうなったかは追いかけれていない。
4:35 AM
あれ、入ってるな
4:35 AM
何かと勘違いしていたみたいです、すみません。
Avatar
ArraySliceにおいてprefixはAnySequenceとArraySliceのoverloadで、これのどちらであるかを判別できなくなるのが原因ですね
👍 1
4:36 AM
納得しました!ありがとうございます。
Avatar
RGBA のピクセル列から NSImage を生成して tiffRepresentation を呼ぶと nil が返ってきてしまうんですが、解決策をご存知の方はいませんか? 今やっているのは↓で、 let image = NSImage(cgImage: cgImage, size: NSSize.zero) image.tiffRepresentation // nil この cgImage は↓のように生成されています。 extension Image where Pixel == RGBA { public var cgImage: CGImage { let length = count * 4 // count == width * height var data = Data(capacity: length) data.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) -> Void in // 略 } let provider: CGDataProvider = CGDataProvider(data: data as CFData)! return CGImage(width: width, height: height, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: width * 4, space: Image.colorSpace, bitmapInfo: Image.bitmapInfo, provider: provider, decode: nil, shouldInterpolate: false, intent: CGColorRenderingIntent.defaultIntent)! } fileprivate static var colorSpace: CGColorSpace { return CGColorSpaceCreateDeviceRGB() } fileprivate static var bitmapInfo: CGBitmapInfo { return CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue) } } tiffRepresentation のドキュメントには↓のようにありますが、特に PDF や EPS のようなベクター形式の representation にはなっていないと思います。 "if the TIFF data cannot be created" の原因がわからず・・・。 If one of the receiver's image representations does not support the creation of TIFF data natively (PDF and EPS images, for example), this property creates the TIFF data from that representation's cached content. This property contains nil if the TIFF data cannot be created. https://developer.apple.com/documentation/appkit/nsimage/1519841-tiffrepresentation なお、同様の手法↓で生成されたグレースケールの CGImage から作られた NSImage や、 PNG ファイルを読み込んで生成された NSImagetiffRepresentation は正しく動作します。 https://github.com/koher/EasyImagy/blob/05db8c28d034a36cef3a8271d2daa214c8ad5ee4/EasyImagy/ImageCoreGraphics.swift#L133-L147
EasyImagy - Makes it easy to deal with images in Swift
8:44 AM
Avatar
@koher まずいのはここだと思います。
10:55 AM
var data = Data(length: length) で初期化しないと、capacity あっても直接イニシャライズすると length は 0 のままなので。 (edited)
10:57 AM
それか、init(capacity:) で生成して、 data.length = length で拡張するか。← データ突っ込んだ後にやると 0 で初期化されるので注意 (edited)
😲 2
11:01 AM
あ、Data.init(count:) だ。 issue からリンクされているプロジェクトでは NSMutableData だった。
Avatar
NSMutableData(length:)で正常に取得できることを確認しました。
12:31 AM
僕もソースは読んでたんですがcapacitylength/countは盲点でした…… ポインタと合わせる場合は特に要注意ですね
Avatar
おおお、そんなところをミスってるとは・・・。完全に盲点でした・・・。ありがとうございます!!
1:06 AM
CoreGraphics と AppKit の方ばっかり調べて Data の使い方を間違えている可能性をまったく考えませんでした・・・。
Avatar
@rintaro おかげで fix できました!ありがとうございました。 https://github.com/koher/EasyImagy/pull/16
👍 1
Avatar
SwiftLintを0.22.0に上げるとデフォルトで2つ目のクロージャー引数に警告が出るようになりました。新しいルールの詳細はこのissueのようです。https://github.com/realm/SwiftLint/issues/1801
New Issue Checklist Updated SwiftLint to the latest version I searched for existing GitHub issues Rule Request In many cases, the trailing closure syntax can make code clearer by reducing boile...
7:25 AM
UIView.animate(withDuration: 1.0, animations: { someView.alpha = 0.0 }) { _ in someView.removeFromSuperview() }
7:26 AM
これを警告を出さずに同じことを0.22.0でも書こうとすると、どのように書くべきなのかわからず。
7:28 AM
アニメーションが完了した後の処理を2つ目のクロージャーで処理したいのに警告が出て困る。issueの作成者が言う、2つめのクロージャーの処理が曖昧だというのはラベルが省略されているからまだ理解できますが、多くの場合は不要と言っている意味がよくわからず。 (edited)
7:30 AM
なぜこのルールがデフォルトで警告になったのか…。 (edited)
Avatar
Deleted User 9/3/2017 7:49 AM
クロージャを2つ以上引数に渡す場合はTrailing Closuresを使わずに、分かりやすくちゃんとラベルを付けましょうってことですよね? UIView.animate( withDuration: 1.0, animations: { someView.alpha = 0.0 }, completion: { _ in someView.removeFromSuperview() } )
🙏 1
Avatar
ありがとうございます。2つ目のラベル名をいつも省略して書いてたので、ラベル名を付けたまま書くスタイルがわからず困ってました。ありがとうございました! (edited)
👍 3
Avatar
もう少しで iOS 11 の GM 版がリリースされそうですが、 GM 版でアプリを申請して審査に通った場合、 App Store から配信されるのはどの時点になるのでしょうか? 正式版がリリースされるタイミングですか?それとも GM 版 iOS が入った端末であれば審査に通った時点からインストールできるようになるのでしょうか? Deplayment Target は新しくリリースされるバージョン(今回であれば iOS 11 )を想定しています。 これまでに GM 版で申請した経験がないためよくわからず、ご存知の方がいれば教えていただけると助かります🙏
Avatar
@koher 過去のバージョンでiOSxx対応みたいなのがリリース前に出ていたのは覚えていて、それに習うなら配信されるのはリリース前も有り得ると思います。
👏 1
Avatar
なるほど。ありがとうございます!
Avatar
var dict1 = ["May 21": [1,2], "May 22": [3,4]] var dict2 = ["May 22": [5,6], "May 23": [7,8]] dict1.merge(dict2, uniquingKeysWith: +) print(dict1) // ["May 22": [3, 4, 5, 6], "May 23": [7, 8], "May 21": [1, 2]]
6:13 AM
uniquingKeysWith に + を書くことてswift4で可能ですか? (edited)
6:14 AM
Xcode9でやるとエラーになるのですが。
6:16 AM
あ、わかりました。valueの型が一致してないと駄目なのか、失礼しました。
Avatar
Pythonの基本がわかってDjangoを使っている程度の中学生がiOS+Swiftプログラミングに入門するにはまず何から始めたらいいでしょう。おすすめの書籍などあれば教えて欲しいです。Playgroundで学んでいける課題でも良いかなと思ってます。私は一応SwiftでiOSアプリの開発はできるので教えることはできると思うのですが、やはり教材があると教えやすいかなと感じてます。
Avatar
最初のGettingStartedなかなか良いですね。中2なので英語だとちょっと時間がかかるかもしれませんが。
Avatar
おっさんでも英語だと時間掛かる人いるし問題ないですよ
😅 1
Avatar
うーん、さすがに中2だと英語はきつそうな気もしますけどね〜。
Avatar
逆に学習の動機づけとしてはよいのでは
1:57 AM
目的が倒錯した
Avatar
塾講師してたとき高校入試の英語長文読みましたが、中学生当時難しいと思ってた英文が簡単すぎて
1:58 AM
日本語のように読めておどろいたので、中学のときの英語力って今の僕らの感覚からすると相当低いかと。
1:59 AM
動機づけとしては良いとしても、階段のステップが大きすぎると壁になって登れずに挫折してしまうので、日本語でカバーできる範囲はまず日本語がいいような気がします。
Avatar
中学校英語とは全く語彙が違うので最初は難しく感じそうですね
Avatar
Pythonは日本語の資料を参照した感じですか? @rizumita
Avatar
Pythonは日本語の資料ですね。
2:01 AM
Djangoの情報は日本語の情報が少なかったのですが、英語の資料を読むのは中1だったのもあって無理でした。
2:02 AM
@tarunon
Avatar
英語問題は結構難しいと思っていて、ドキュメントが日本語だとしてもクラス名、メソッド名とかが英語なので小中学生くらいだとそこに辛さがありそうです。僕が小4でプログラミングを始めたときは、変数名は a とか b とか付けてたので。概念自体は理解できると思いますが、(自然)言語の壁がありそうです・・・。
Avatar
僕が中学生の時はコンパイラと戯れて理解してたな、ドキュメント参照しようにもダイヤルアップだからそれすら難しかった
2:07 AM
自然言語による理解を諦めてコンパイラと戯れよう
Avatar
前に小3にSwift教えようとしたら、アルファベットの大文字は読めるけど小文字が読めないという事案が発生しました。
Avatar
ゴールとしてはiOSアプリ自体の開発ですか?
Avatar
なかなかiOSのアプリ開発を初級者向けに抑えた日本語の本って聞かないな あるのかもしれんけど
Avatar
Udemyとかだとそういうのもあるのかなぁ?
2:10 AM
↑ここにもいっぱいありそう 英語だけど
Avatar
あ、日本語初心者向けコンテンツが、ね。 (edited)
Avatar
@tarunon ゴールはiOSアプリの開発だと思います。
Avatar
やっぱり早く SWIFT QUEST を作らねば・・・。
Avatar
Swift QuestはiOSアプリなんですか?
Avatar
基本は iOS 関係なく純粋 Swift だけど、発展系として Playground + UIKit もできないかなぁとは思ってる。
Avatar
なるほど。
Avatar
おじさんたちはSwiftの楽しさに触れて欲しいけど本人の希望ではなさそう
2:13 AM
GithubあさってサンプルコードやらOSSやらこねくり回してスパゲッティでもいいから動くもの出来ると楽しいのかな
Avatar
手っ取り早く楽しさを体験できる環境としては、 Playgrounds はいい気がしますけどね。
Avatar
私もSwift学習始めたばかりなので、この話題はとても気になります。 Swift Playgroundsって日本語対応していたかと思うのですが、これって他言語経験者も学習対象になっている感じなのでしょうか。 私はあいにくiPadを所持していないのでやったことがないのですが、これが完全初心者でなくてもかなり参考になるようなら、ここから始めてみるのもありなような気がします。
Avatar
Swiftにも興味はあるみたいです。Python以外の言語もやってみたいという動機もあるみたいなので。
Avatar
やっぱりビジュアルだと楽しいし。
Avatar
iPadのSwift Playgroundsはどっちかというと ノンプログラマー向けに プログラミングの楽しさを伝えるって感じで
2:15 AM
開発者が言語学習目的でやるとダレるかもしれない?
Avatar
初めて FLASH + ActionScript 触ったとき、楽しすぎて大学にも行かず 3 日くらいずっとそれやってました。 < ビジュアルだと楽しい
Avatar
参考書として http://gihyo.jp/book/2017/978-4-7741-8730-3 この書籍は良さそうな気がしますね。これ進めるだけだと中学生には退屈そうかも?なので、補助として。
本書は,Swiftの言語仕様と実践的な利用方法を解説した入門書です。 Swiftは簡潔な言語ですが,その言語仕様を理解し,正しく使うことはけっして容易ではありません。Appleの公式ドキュメントをはじめとして,どんな言語仕様があり,それらをどのように使うかに関しては豊富な情報源があります。しかし,それらがなぜ存在し,いつ使うべきかについてまとまった情報があるとは言えません。本書は,読者のみなさんの「なぜ」や「いつ」を解消することにも主眼を置いています。 本書では,はじめにSwiftの標準的な機能を一通り解説し,続いて型の設計指針や非同期処理,エラー処理などの実装パターンを説明します。最後に,実践的なSwiftアプリケーションの開発を通じて,それまでに説明した機能と実装パターンの具体的な活用方法を示します。
Avatar
Playgrounds は、 Mac の方の意図でした。
Avatar
ああそこ紛らわしいんですよね さっき僕が言ったのは iPadアプリの「Swift Playgrounds」は、プログラミング学習ゲームの事です
Avatar
二つは違うもののようで、 Mac の Playgrounds と同じような機能を iOS アプリの方も備えているからさらにややこしい・・・。
2:18 AM
↓のゲームみたいなのは、 Swift Playgrounds のコンテンツの一形態である Playground Book の、 "Learn to Code" というコンテンツです。 https://www.apple.com/jp/swift/playgrounds/
Swift Playgroundsは、楽しくインタラクティブな方法でSwiftのコードの書き方を学べるiPad用のアプリケーションです。アプリケーション上で直接ロボットやドローンを動かすプログラムを作れます。
Avatar
息子が第1回try! Swiftと一緒にあった子供向けワークショップに参加した時に、MacのPlaygroundsで教材が作ってあって楽しく学べたみたいなので、ああいう教材でより深く学べたらいいなぁと思いました。
🙂 1
Avatar
あ、そうか、Swift Playgroundsの中の、あくまで1つのコンテンツだった。
Avatar
何歳くらいのときですか?結構小さくてもできるものですか?
Avatar
@koher 小6の時ですね。
2:21 AM
もっと小さい子もいました。スーパー小学生だったので、その子は参考にならなそうですがw
Avatar
iPadの方のPlaygroundsで実際のアプリのコーディングをやっているという人もいて、実際にやっている人から気軽にやれておすすめとも聞いているので、ちょっと気になっています。
Avatar
なるほど。小6くらいならできるかもですね😃 天才児は参考にならないですねw (edited)
2:23 AM
iPadは入力が苦行なので個人的にはオススメできないです。。。
Avatar
ソンソンさんはキーボード並用してましたね。iPadと。 (edited)
Avatar
iPadは持ってないので…
Avatar
MacがあるならMacでやるのが楽だと思います。
2:25 AM
Swiftの勉強なら、英語さえ読めれば公式の↓を読むのが早いと思います。 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/index.html
2:25 AM
(iBooks版もあります)
2:26 AM
Read a free sample or buy The Swift Programming Language (Swift 4) by Apple Inc.. You can read this book with iBooks on your iPhone, iPad, iPod touch, or Mac.
Avatar
Mac向けにもああいうのを出してくれたらなやってみたいところです。 公式サイト見ながら、Playgroundでやっていけば良いのだとは思うのですが。 ちなみにiPadの方のPlaygroundsは入力補助が優秀で、あまりキーボードで打たなくてもいけるそうです。
Avatar
うーん、その辺りは感じ方に個人差があるかもです。僕は結構 iPad 版の入力補助がストレスフルでした・・・。
Avatar
やはり実際に触ってみないと分からないものですね。 日本語版の書籍と言うことなら、11月にSwift4の本がいくつか出るみたいですが、同シリーズのSwift3までの本を見てよさそうなのを見繕っておくというのもありでしょうか。
Avatar
たしかに、もうすぐ発売みたいですね。
Avatar
書籍は読んだことがないからわからないです😅
Avatar
私も読んだことがないので、書籍がいくつか出た頃に息子を書店に連れていくのが良いのかも?
Avatar
プログラミング初心者向けというのでなければ、↑で @masaichi さんが挙げていた「 Swift実践入門」はいいんじゃないでしょうか。
Avatar
僕は中学生の時ヨドバシカメラの技術書コーナーに行くのが好きで
2:41 AM
お小遣いが貯まると買ってた
Avatar
Swift実践入門は手元にあるので、Swiftに関してはそれを渡せばいいかもしれませんね。あとはiOSアプリの作り方の書籍を入手すれば。
Avatar
ドットインストールのiPhoneアプリ開発入門は、Xcodeの使い方を手っ取り早く知るには便利でした。 https://dotinstall.com/lessons/basic_iphoneapp_v3
iOSアプリの統合開発環境であるXcodeについて解説しつつ、簡単なアプリ開発の流れを見ていきます。
Avatar
@Puramu Xcodeだけじゃなく簡単なアプリの作成まで解説があるんですね。
Avatar
@rizumita Xcode上からプロジェクトを作ってシミュレータ上で動かすところまでの解説が動画であるので、個人的にはアプリ開発のイメージはつかみやすいなと思いました。
Avatar
問題はすぐに古くなってしまうことですねぇ☹
Avatar
古いのは残念なところ。
Avatar
一応 Xcode 9 で Swift 3.2 なら似たような環境で動かせる?
3:01 AM
ただ、問題が起きたときに初心者だと解決不能になりそうですね。
Avatar
私の場合、あえてXcode9でSwift4で同じように動かしてみましたが、問題なく動かせました。 バージョンが上がって暫くすると、最新バージョンに対応した講座がいつの間にか作られていたりするので、ちょこちょこ見てみるのも良いのかもしれません。
Avatar
なるほど。メンテされていて追従してくれるならいい感じそうですね。
Avatar
@Puramu それは良い情報。ありがとうございます!
Avatar
@rizumita 有料会員になると、もっと他の講座も見られるんですが、そちらだと実際にちょっと遊べそうなアプリ作成の例が結構あります。 有料講座も最初の数回は無料になっているやつもあるので、良さそうなのがあるのか先に見てみると良いと思います。
Avatar
@Puramu 見てみます!
Avatar
iBooksのApple Educationに日本語の教材があるみたいですよ。 https://itunes.apple.com/jp/author/apple-education/id939801385?mt=11
「教育者のためのリサーチアイデア集」、「Swiftによるアプリケーション開発:入門編」、「Swift Playgrounds: コードを学ぼう1&2」を含む、Apple Educationのブックをプレビュー、ダウンロード。
Avatar
おお、すごい。
Avatar
Apple Educationの「Swiftによるアプリケーション開発:入門編」の無料サンプルを閲覧または購入。このブックは iPhone、iPad、iPod touch、または Mac 上で iBooks を使って読むことができます。
Apple Educationの「Swiftによるアプリケーション開発:入門編」の無料サンプルを閲覧または購入。このブックは iPhone、iPad、iPod touch、または Mac 上で iBooks を使って読むことができます。
Avatar
@norio_nomura おぉそんなものが。ありがとうございます!早速ダウンロードしてみます。
Avatar
凄いです。私も後で見てみたいと思います。
Avatar
@tarunon #swift でちょいちょい話題に上がるboxingってなんすか
Avatar
えーっと、Swift2以前でstructをNotificationCenterに流せなかったときに
9:19 AM
class Box<T>って使いませんでした?まさにアレです (edited)
9:20 AM
これはコンパイラの中でboxingやってますよねということか
Avatar
そうそう
Avatar
わかり++
Avatar
値型はそのままだとメモリレイアウトも違うのでクラス型としての互換性はないので、AnyObjectへのキャスト時にラップするオブジェクトがいる。Swift3からコンパイラ側が勝手にBoxingしてくれるようになりました。
Avatar
omochimetaru 11/1/2017 9:20 AM
値型のオブジェクトを参照型のオブジェクトに包む事で、 JavaのListは、参照型しか格納できないので、 int とかが class Integer に包まれたりする ObjectiveC でも、 NSArray は参照型しか格納できないから、 NSValue で包む
Avatar
Java で intInteger
9:21 AM
って書いてたら @omochimetaru が。
Avatar
互換性のあるものだと、NSString, NSArray, NSDictionary, NSNumber, NSValue(もかな?)へ変換されて
9:21 AM
そうじゃないものは一括で、、SwiftValueなんすかね @omochimetaru @rintaro
Avatar
omochimetaru 11/1/2017 9:22 AM
ObjectiveCでは昔は [NSValue valueWithInt: 3] とかやってたけど、 iOS5ぐらいから @(5) って、アット丸括弧構文でboxingできるようになったとか、昔はあった
Avatar
昔の Java では↓みたいなことをしてて、 // Java List<Integer> list = new ArrayList<Integer>(); list.add(new Integer(42)); // boxing
Avatar
ははん
Avatar
omochimetaru 11/1/2017 9:22 AM
@tarunon これまでに見てきた感じだとSwiftの都合で必要になるやつは SwiftValueっぽいね
Avatar
今の Java はこれを自動でやってくれるから↓のように書けるけど( auto boxing )、あくまで自動なだけで boxing 自体は行われてます。 // Java List<Integer> list = new ArrayList<Integer>(); list.add(42); // auto boxing
9:23 AM
int に対して Integer をラッパークラスと言います。
Avatar
SwiftValueはObjcからは見えないSwiftに閉じた型の値?
Avatar
で、 Swift でも裏側で似たようなことをしているはずの部分を boxing と呼んでるけど、それが Java 由来なのか一般的な用語なのかは知りません。
👌 1
Avatar
SwiftValue、愚直に考えるならSwiftObjectのサブクラス
9:27 AM
SwiftObjectはNSObject互換で、動きを見る限りはサブクラスじゃないと思うけどObjective-C界から見たらNSObjectに見えそう。 (edited)
Avatar
SwiftValueとSwiftObjectは値型と参照型ってことではないのか、な
9:29 AM
サブクラスとのことだし
Avatar
さっきの C.self is AnyObject 問題があったから、 Swift の型システムとして表現したい世界と、 ObjC 互換のために現実的にどうなってるかとを区別して考えないといけないかも?
9:29 AM
おや、、、
Avatar
omochimetaru 11/1/2017 9:29 AM
struct S{} var s = S() print(type(of: s as AnyObject)) // _SwiftValue var f: () -> Int = { 33 } print(type(of: f as AnyObject)) // _SwiftValue ↑SwiftValueの例
9:30 AM
普段は見えないけど型名を動的に取得してprintすると出て来る。
Avatar
#if __OBJC__ @class _SwiftValue; #else typedef struct _SwiftValue _SwiftValue; #endif
Avatar
あー なんか見たことあると思ったらそれか
9:30 AM
こっちのほうが良さそう
9:30 AM
というか_SwiftValueはNSObjectのサブクラスじゃん
Avatar
なるほどー、 #if SWIFT_OBJC_INTEROP@interface _SwiftValue : NSObject <NSCopying> だから is AnyObject が Mac だと true になるんだ。 (edited)
9:33 AM
ん??
9:33 AM
それだと S.self でもそのはず?
Avatar
#swift じみてきた
Avatar
またわからんことがあったらここに書くのでまた教えてください
🙋 2
9:34 AM
ドラゴンは巣#swiftにおかえり
🍀 1
Avatar
少し話は戻りますが、JavaのListに参照型しか格納できないのってなんでですかね?
Avatar
omochimetaru 11/1/2017 9:36 AM
Genericsが型ごとに異なる実装を持てないからですね
Avatar
全部Objectとして持つのが前提じゃないかな
Avatar
omochimetaru 11/1/2017 9:37 AM
そうそう。List内部のストレージの実体が、ルートクラスのObjectの配列になってる。 (edited)
Avatar
つまり、Swiftっぽく示すと class List<T: AnyObject> {} これがJavaのListの定義
9:37 AM
本当はアブストラクトクラスだけど…
9:38 AM
後は型システムの制約とかあるはずだけど、そこは明るくないです。
Avatar
元々ジェネリクスもなくて、 class ArrayList { private Object[] elements; } こんな風になってたのを
9:38 AM
ジェネリクスを使って class ArrayList<E> { private E[] elements; } と書いているだけなので、
Avatar
omochimetaru 11/1/2017 9:39 AM
言語仕様としては、 int[] とか float[] みたいな、値型の配列も作れるんだけど、 List<int> のときにそれを内部で使わせる記法も仕組みもない あと、これは鶏卵だけど、ジェネリクスの型パラメータのところに値型が書けない・・・
Avatar
そもそも Java のジェネリクスが Object で持ってるのと同じです。コンパイル時に型チェックできるようになっただけで、実行時の挙動はジェネリクス以前と同じで Object です。
Avatar
Erasure ですからねぇ
Avatar
ジェネリクス以前の実装は参照型なら任意の型が入りうる感じですか?
Avatar
確か Java でも値型とか List<int> を導入する話が出てたような?
Avatar
なんか出来るようにするけどいつになるだろうみたいなのを聞きましたね
Avatar
@Yuta Saito そうです。 < ジェネリクス以前の実装は参照型なら任意の型が入りうる感じですか?
Avatar
危険だ。。。
Avatar
ListList<Object> と書いてるのと同じですね。
Avatar
omochimetaru 11/1/2017 9:42 AM
Javaコンパイラのその振る舞いをするモジュールが type erasure って名前 https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
Avatar
omochimetaru 11/1/2017 9:42 AM
To implement generics, the Java compiler applies type erasure to:
Avatar
Javaのジェネリクスは後付け仕様で、コンパイル時のエラーチェックしかできないから、ジェネリクス使ってたとしても、明示的にキャストすれば任意の参照型が入った気がします。
Avatar
Obj-C はつい最近までそういう状態でした。 < 危険だ。。。
Avatar
omochimetaru 11/1/2017 9:43 AM
危険だ。。。
AndroidがJava6を書いているころ、iOSでは NSMutableArray に ジェネリクスも何もなくやってたね
Avatar
全部 id 型
Avatar
@hironytic
明示的にキャストすれば任意の参照型が入った気がします。
そんな気もしたんですが、キャストでエラーになるような気もして自信が持てず・・・。
Avatar
omochimetaru 11/1/2017 9:44 AM
明示的にキャストすれば任意の参照型が入った気がします。
List<Integer> a = new ArrayList<Integer>(); List<String> s = (List<String>)(List<Object>)a;
😩 1
9:44 AM
たしかこんな感じのダブルキャストするとコンパイルできる
Avatar
さてここで
Avatar
omochimetaru 11/1/2017 9:45 AM
実行時に add した瞬間に runtime exception だった気がする。
Avatar
僕が [Int]() as? [String] これを嫌がる理由が
9:45 AM
runtime exceptionではないけどじゃばみを感じる
Avatar
Java だと↓のようなオーバーロードもできなかったはず。 int foo(List<Integer> list) { ... } int foo(List<Double> list) { ... }
Avatar
#java
Avatar
どちらも List なので。
Avatar
omochimetaru 11/1/2017 9:47 AM
できないですね、それがtype erasureの仕事・・・
Avatar
Kotlin とかもその制約を受けてて辛い。
Avatar
omochimetaru 11/1/2017 9:48 AM
コンパイル時にジェネリックパラメータについての型チェックができる、はそうなんだけど、型システムのかなり前段で行われちゃうんですよね (edited)
9:48 AM
Java5からJava4に型検査+ダウントランスパイルしてから実際のコンパイルするような感じ。
Avatar
うん、そんなイメージ。
Avatar
そうですね
Avatar
たしかにキャストでエラーになりますね。。。
Avatar
@omochimetaru ownershipっていつ入るんですか Swift5?
Avatar
omochimetaru 11/2/2017 5:02 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
5:02 AM
Swift5でやりたい事がここにかいてあって
Avatar
5.0か
5:03 AM
1年後か
Avatar
omochimetaru 11/2/2017 5:03 AM
Swift5の大きなテーマがABIなので、Ownershipもそれに引っ張られてABIに関するやつはやるぞって書いてある
5:03 AM
Memory ownership model. An (opt-in) Cyclone/Rust-inspired memory ownership model is strongly desirable for systems programming and for other high-performance applications that require predictable and deterministic performance. Part of this model was introduced in Swift 4 when we began to enforce exclusive access to memory. In Swift 5 our goal is to tackle the pieces of the ownership model that are key to ABI stability.
5:03 AM
pieces of the ownership model that are key to ABI stability.
5:04 AM
ABI安定性のカギとなるオーナーシップの一部分
Avatar
ABIの規格にownershipも含めとかないとってことか
Avatar
omochimetaru 11/2/2017 5:04 AM
ですね ABIは関数呼び出し仕様も絡むので
5:04 AM
shared引数ってどういう呼び出しになるのか、とか芋づる式に決めないといけない
Avatar
ふむふむ
5:05 AM
Rust-inspiredってことは今のうちにRustのownershipと戯れておくのは無意味じゃないってことでいいんでしょうか
Avatar
omochimetaru 11/2/2017 5:06 AM
むしろRustやっておくと楽勝だと思う
Avatar
ナルホディウス
Avatar
omochimetaru 11/2/2017 5:06 AM
Rustよりちょっと小さい仕様で入れようぜって感じだから。
5:06 AM
Rustの機能全部パクると使いにくくなっちゃうからSwiftでは使いやすさと安全性の両立できるラインにとどめようという方針
Avatar
Rust、ドキュメント一通り読んでサンプル動かして脳内インデックス作ったつもりだったけど全然難解すぎて脳が育たない
Avatar
ジェネリクスと関連型が同時に存在するところわからない
Avatar
Genericsと associatedType
Avatar
rustのGenerics protocolなら前に議論があった (edited)
Avatar
rust の type と Generics の話ですね @lovee
Avatar
失礼しました🙃
👌 1
Avatar
UITableViewCellを再利用するとき、styleがdefault以外の場合、皆さんどうしてますか? ① UITableViewCellのサブクラスをつくって、UITableViewにregisterする ② iOS6以前の方式で書く let cell = tableView.dequeueReusableCell(withIdentifier: "hogeCell", for: indexPath) ?? UITableViewCell(style: .subtitle, reuseIdentifier: "hogeCell") ③ その他 ただstyleが違うだけなのにイニシャライザだけ定義した、UITableViewCellのサブクラスつくるのが面倒なので良い方法があったりしないかな…と思った感じです。 (edited)
Avatar
Kishikawa Katsumi 11/7/2017 3:25 AM
よほどのことがなければ1がテッパンですね。
Avatar
やっぱりそうですか。
Avatar
omochimetaru 11/7/2017 3:26 AM
サブクラス作るのが面倒な時、サブクラス作るのが面倒な言語仕様がおかしいんだ!って気持ちを高めて頑張ってサブクラス書いてます。(そこで楽しようとすると型的に面倒な事があとあと起きてきがち (edited)
Avatar
Kishikawa Katsumi 11/7/2017 3:27 AM
ただstyleが違うだけなのにイニシャライザだけ定義した、UITableViewCellのサブクラス という気持ちはわかりますが、それで済むのはほんの最初のうちなので、結局セルの種類ごとにクラスで名前をつけるのがわかりやすいです。
3:27 AM
同じスタイルでも違う種類のセルなら違う名前のクラスにしたほうがいいです。
Avatar
納得、ありがとうございます!
Avatar
Kishikawa Katsumi 11/7/2017 3:30 AM
ちなみに indexPath を2番目の引数に取る dequeueReusableCell() はnilを返さないので、2の書き方はindexPath を取らない方のメソッドを呼ぶ必要があります。細かいツッコミですけど。
😱 1
Avatar
あ、そうですね、適当すぎました
Avatar
前のxcodeだとlinked frameworkで入ったフレームワークを左ペインでグループにまとめるとかしてましたけど 今のバージョンだとグループ作ってD&Dで移動すると実体が移動してしまう気がしてます。(New Group, New Group without Folder問わず) 何か方法あるんでしょうか?
Avatar
omochimetaru 11/9/2017 8:15 AM
わかる・・・俺諦めた。しまいたい。
😢 1
Avatar
norio_nomura 11/9/2017 8:38 AM
プロジェクトの直下に入ってしまう件?
Avatar
omochimetaru 11/9/2017 8:38 AM
直下に入ってしまって、それを、グループを作ってグループの中に隠そうとしても
8:38 AM
うまくいかない。
Avatar
norio_nomura 11/9/2017 8:40 AM
Embedded Binariesにいきなり入れると直下に置かれるけど、Linked Frameworks and Librariesに入れるとFrameworksの下に参照が作られるから、それをEmbedded~へ入れる様にしてる。
Avatar
omochimetaru 11/9/2017 8:41 AM
今度試してみます。
Avatar
Linked Frameworks and Librariesの+からやるとFrameworksってグループができてその下に入るんですね。これで耐えられそうです。ありがとうございます。
🎉 1
Avatar
Dictionaryのキーを変換して [Int: Any][String: Any] にしたいみたいなときってどう書くのが一番綺麗なんでしょう
Avatar
let source = [1: "1", 2: "2", 3: "3"] Dictionary(uniqueKeysWithValues: source.map { ("\($0.key)", $0.value) }) こう?
Avatar
おっ ためしてみる
Avatar
おそらく初歩な内容だと思われるのですが、質問させていただきます。 1. ボタンを押す 2. 「ダウンロード中」というUILabelをつけたUIViewを表示させる 3. ダウンロードタスクが始まる 4. そのダウンロードタスクが終了したときにUIViewを削除する という処理を行う場合、どのように書けばよいのでしょうか? 現在、以下のように書いているのですが、 @IBAction func tapDownloadButton(){ let uiView = UIView(frame: CGRect(x:0,y:0, width:100, height:100)) uiView.backgroundColor = UIColor.white self.view.addSubview(uiView) //このタイミングでビューを表示したいができない download() uiView.removeFromSuperView() } ボタンに紐づけられた関数tapDownloadButton()の処理が全て終わったタイミングでUIの処理が始まるためか、見た目上、UIViewが表示されずにダウンロードが終わってしまいます・・・
Avatar
Kishikawa Katsumi 11/18/2017 9:25 AM
@TetsuFe 期待した通りに動かない理由はお書きになった通りです。UIが更新されるためにはイベントループに処理を戻す必要があるので、一連のメソッドの間でaddSubview(_:)removeFromSuperView()をしてしまうと、結果としてビューが外された最後の状態でUIが更新されます。
9:27 AM
download()は同期的な処理ですか?最も望ましいと思われる解決はdownload()メソッドを非同期処理にして完了時点でコールバックを受け取れるようにして、addSubview(_:) を呼んでからdownload()、ここまでは同じで、removeFromSuperView()をダウンロード完了のコールバック内で呼ぶことです。
9:28 AM
それが難しければ、addSubview(_:)の直後に一度イベントループに処理を戻してUIを更新して、download()removeFromSuperView()を呼びます。
9:32 AM
view.addSubview(uiView) DispatchQueue.main.async { self.download() uiView.removeFromSuperView() }
9:33 AM
後者の方法はこんな感じですね。簡単ですけど良いコードではないのでオススメしませんが、元のコードがなぜ期待した通りに動かなかったのかはよくわかると思います。
Avatar
ありがとうございます。 丁寧な説明でとても助かりました。 downloadを非同期的な処理に変えてコールバックでremoveFromSuperViewを実行することで、期待通りの挙動になりました。 後者の方法は、なぜかうまくいきませんでしたが、これはダウンロードを行う関数が同期処理になっているためでしょうか?
Avatar
download関数がダウンロード処理を実行し即座にVoidを返すためだと思います
12:54 AM
処理の進捗や結果如何に関わらず、実行の次にreturn Voidですね
Avatar
@tarunon ありがとうございます。 なるほど、そういうことだとすると、納得できます。 まだ理解が追いついていないですが、結果的にどういう流れになっているかは分かりました。もっと勉強しないといけないですね。
Avatar
それぞれ別のassociatedtypeを持つprotocol A, B に適合したprotocol Cを作成した場合についての質問です。 protocol A, BそれぞれのassociatedtypeのTypeは同一なので、 struct適合時にはどちらか一つのみtypealiasを定義したいです。 しかし、protocol Cにてwhereで条件を書いても どちらか一方のprotocolに適合していないとコンパイルエラーが出てしまいます。。 この場合、何か策はあるのでしょうか? protocol A { associatedtype TypeA } protocol B { associatedtype TypeB } protocol C: A, B where TypeA == TypeB { } struct Hoge: C { // error: type 'Hoge' does not conform to protocol 'A' typealias Type2 = String }
Avatar
struct Hoge: C { typealias TypeA = String typealias TypeB = String } これなら通りますね。TypeAとTypeBが別々だと通らなくなるので同一チェックもされてるようです。
Avatar
そうですね、ただTypeAとTypeBを毎度同じ型を定義するのがしんどいので protocol Cを定義してTypeA == TypeBであることを担保しておき、C適合時にはどちらかのみ書けばいい状態にしたいです
Avatar
うーん、両方書かないと通らないですね。一応、実用的には↓のように何らかのメソッドがあると思うので、明示的に typealias を書かなくてもコンパイルは通ります。 protocol A { associatedtype TypeA func foo() -> TypeA } protocol B { associatedtype TypeB func bar() -> TypeB } protocol C: A, B where TypeA == TypeB { } struct Hoge: C { func foo() -> Int { return 2 } func bar() -> Int { return 3 } }
Avatar
protocol A { associatedtype TypeA } protocol B { associatedtype TypeB } protocol C: A, B { associatedtype TypeB = TypeA } struct Hoge: C { typealias TypeA = String }
Avatar
assoctypeの上書きできるんですね……
Avatar
where句を書くのはextension、protocolはassociatedtypeに制約を記述します
Avatar
おお、 C のそこ associatedtype になるんですね。 typealias で書いてエラーになってあきらめてました。
Avatar
同じく
Avatar
@t.ae そろそろRecursive Constraintsも来るので色々出来るようになりますよ
Avatar
レベル高い
Avatar
なるほど!
Avatar
個人的には逆をやりたいのですが出来なくて困っています
3:27 AM
protocol A { associatedtype E } protocol B { associatedtype E } struct C: A, B { typealias A.E = Int typealias B.E = String } これはどうあがいてもムリです。 (edited)
Avatar
associatedtypeで制約を書けばよかったんですね・・ @t.ae#5802 @koher @tarunon ありがとうございます!
Avatar
associatedtypeの 名前が かぶっちゃいけないってこと?
Avatar
associatedtypeの名前がかぶると同じ型にしかならない
3:28 AM
ネームスペース気にしなきゃいけなくなって苦痛
Avatar
わかる
Avatar
それひどい仕様ですね・・・。
Avatar
古き良きベンダープリフィクス
Avatar
プロトコルつくるときにはローカルな名前つけたいんだけど、あっちのあれとぶつかるかも、みたいな。
Avatar
Shitだ
Avatar
HogeProtocol.FugaAssocType みたいな書き方ができれば解決?
Avatar
そのあたりってどういう整理なんでしょう?たまたまそういう実装になってる?or意図的な仕様?
Avatar
#swift でよさそう
Avatar
#ios#beginner-help-archived か迷ったのですが、こっちで質問してみます iOS11のみで起きる CFNetwork URLResponse::guessMIMETypeCurrent(__CFData const*) のバグに苦しめられてまして、どなたか同じような現象に出くわした方いらっしゃいませんか。 MIMETypeについてなので、URLResponseをNSHTTPURLResponseにキャストしてMIMETypeの中身を見てるんですが、たまにnullが返ってくるのが問題かなと思ったのですが、iOS10や9でもnullで返ってくるので、特にこれが原因でクラッシュするわけではないような…。 ググっても同じような問題に悩んでいる人が見つからなかった…。 Crashed: com.apple.NSURLSession-work SIGABRT ABORT 0x0000000180ded348 -------------------------------------------- libsystem_kernel.dylib __pthread_kill + 8 CoreFoundation _CFRelease + 1252 CFNetwork URLResponse::guessMIMETypeCurrent(__CFData const*) + 1548 CFNetwork -[__NSCFURLLocalSessionConnection _tick_sniffNow] + 348 libsystem_pthread.dylib start_wqthread + 4
Avatar
コードが欲しい…
Avatar
ですよね
7:28 AM
しばしお待ちを
Avatar
objcのコードで辛い感じですが、マルチパートを自作してPOSTするメソッドです。
3.59 KB
Avatar
``` でくくってここに貼れませんか?
Avatar
それが長すぎて
Avatar
ならgistとかのほうがみんな見やすいと思います
Avatar
投稿できなかったのファイルになりました
7:41 AM
あ、確かに
Avatar
objcをシンタックスハイライトなしで見るのは大変なのでw (edited)
Avatar
すみません,
🙆 1
7:43 AM
これでどうでしょうか。
Avatar
どこでクラッシュしてるんだろ
7:46 AM
(objcだと思ってなかったw)
😭 1
Avatar
Kishikawa Katsumi 11/22/2017 7:46 AM
コードは問題ないように見えます。
Avatar
ちょっとわかんないですけど、構築してるリクエストに何かしらの問題があって、NSURL系のドライバが内部で死んじゃうんだと予想します
Avatar
レビューありがとうございます。たぶん、なんですがcrashlyticsにログは来てますが、クラッシュしてるわけではないようなんですが、iOS11のみログが送られてきてまして
Avatar
Content-Type: が multipart/form-data; のときって、 charset は要らないようなきがするのと
7:48 AM
Content-Length: が無いのが気になるけど
7:48 AM
クラッシュしちゃうほどのことでも無さそう・・・
7:49 AM
Content-Length: は NSURLRequestが勝手に付け足す気もするな。HTTPBodyに入れてるのがNSDataだし。うーん、なんだろう・・・
Avatar
なるほど、ちょっとそこを変更してみると、「構築してるリクエストに何かしらの問題があって、NSURL系のドライバが内部で死んじゃう」可能性を想定してもう一度コードを見てみます
7:50 AM
ありがとうございます
Avatar
Kishikawa Katsumi 11/22/2017 7:50 AM
guessMIMETypeCurrent だからContent-Typeを付け足してみて試すとか。
Avatar
あ、ほんとだ、含めてるオブジェクトの方が無いですね15行目あたり
7:51 AM
26行目のほうはContent-Typeついてるけど、こっちは画像添付で別フローだ。
Avatar
むむ
Avatar
Kishikawa Katsumi 11/22/2017 7:51 AM
再現できないと難しいので、再現方法を探りつつ、クラッシュがそれほど多くないのであれば、勘で色々な対策を通常のアップデートに紛れて入れていくくらいしか思いつかないですね。
Avatar
あ、いや、いいのか。こっちはFORM VALUEなのか
7:52 AM
https://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean POST / HTTP/1.1 [[ Less interesting headers ... ]] Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150 Content-Length: 834 -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="text1" text default -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="text2" aωb -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="file1"; filename="a.txt" Content-Type: text/plain Content of a.txt. -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="file2"; filename="a.html" Content-Type: text/html <!DOCTYPE html><title>Content of a.html.</title> -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="file3"; filename="binary" Content-Type: application/octet-stream aωb -----------------------------735323031399963166993862150--
What does enctype='multipart/form-data' mean in an HTML form and when should we use it?
Avatar
Kishikawa Katsumi 11/22/2017 7:52 AM
if (image){ のとこではContent-Type指定してあるんですね。
Avatar
↑のstackoverflowにMIMEなリクエストの例が載ってて、それと見比べてたんですけど、怪しいところみつけられず。
Avatar
みなさんの意見参考に、もうちょっと再現方法を探りつつ頑張ってみます。
Avatar
100%クラッシュなのであれば (edited)
Avatar
そこまで大きくないバグですが、iOS11のユーザーが増えつつあるので、気になる数にはなっています
Avatar
MIMEリクエストを行う他のライブラリをいくつかためしてみて
7:56 AM
自前実装では問題が起きて、他のライブラリなら大丈夫、ってところまでいければ
7:56 AM
実際に飛ばしてるリクエストを見比べて絞りこめると思います
7:57 AM
HTTPリクエスト内容とは全然違う制御系の部分のバグだったらダメですけど・・・ (edited)
Avatar
100%じゃないと真っ先にスレッド周り疑いたくなりますね
7:57 AM
非同期のタイミングで落ちる系のやつ
Avatar
なるほど・・・ライブラリと比べるのも手ですね
Avatar
100%ではないにしろSIGABORTなのでアプリクラッシュは起きてそう。
Avatar
そもそもの話になってしまうのですが、 CFNetwork -[__NSCFURLLocalSessionConnection _tick_sniffNow] + 348 でNSのプレフィックスが付いているのでobjcから呼ばれた通信でバグっているのはあっているのでしょうか?
8:00 AM
このメソッドは廃止予定のものなのですが、まだSwiftに置き換えられてないといった状況でして
Avatar
CoreFoundation _CFRelease + 1252 こっちじゃないかなあ
Avatar
Swiftから呼ばれていたとしても、内部は __NSCFURL... とかが動いてると思うんで
8:00 AM
ObjCから呼ばれてる通信が原因とは限らないかと。
Avatar
むーそうですか・・・。
Avatar
CFReleaseで落ちるってことはオーバーリリースだと思うので
Avatar
ObjcとSwiftが混在してるプロジェクトなのかな?
Avatar
生きてないといけないオブジェクトがリクエストの稼働中に消えちゃってるんじゃないだろうか
Avatar
オーバーリリースというのがあるのか
Avatar
リクエストではなくレスポンスに問題あるのでは?
Avatar
そうです、objcとSwiftが今のところ5:5てきな感じです
8:02 AM
生きてないといけないオブジェクトがリクエストの稼働中に消えちゃってるんじゃないだろうか
Avatar
@omochimetaru そのオーバーリリースってARCの環境でも起きるもんなんスカ
Avatar
むー、問題の特定が難しい
Avatar
@hiragram Swiftだとweakがあるから大丈夫だけど昔の ObjC だと弱参照じゃなくて生ポインタだから、Delegateがもう死んじゃってるとよくおきた
Avatar
CF某は自分でやってなかったっけ、あれはもうなくなった?
Avatar
After you create a task, you start it by calling its resume method. The session then maintains a strong reference to the task until the request finishes or fails; you do not need to maintain a reference to the task unless it is useful to do so for your app’s internal bookkeeping purposes. 大丈夫そうだなあ・・・
Avatar
Kishikawa Katsumi 11/22/2017 8:05 AM
確かにレスポンスの問題っぽいですよね。
Avatar
@omochimetaru オーバーリリースっていうとretain countが0なのにreleaseしようとしたっぽい感じに聞こえたけど、実際は解放済みのメモリにアクセスしたから落ちたってことかしら
Avatar
NSURLProtocol実装してたりします?
Avatar
@hiragram そうだね。実際は解放済みメモリへのアクセスが起きる。
🆗 1
Avatar
NSURLProtocolはつかってないです
8:07 AM
レスポンスの問題だとサーバー側にも何か原因があったりするのでしょうか
Avatar
Kishikawa Katsumi 11/22/2017 8:08 AM
コードは問題なさそうですし、100%起こらないというのもそれなら納得できるし、クラッシュのメソッドはURLResponseというオブジェクトのメソッドなので、何かレスポンスの処理なんでしょう。
8:09 AM
CFNetworkのコードを探したけどそのメソッドは見つかりませんでした。CFNetwork外か新しく追加されたものか。
Avatar
特に、responseに関しては、statusCodeを見るぐらいにしか使用していないつもりなのですが・・・。どこかでつかってるのかな。
Avatar
Kishikawa Katsumi 11/22/2017 8:09 AM
あ、いや、レスポンスの内容です。サーバーから返ってくるレスポンスのデータ。
Avatar
あ、なるほど
Avatar
再現性ないとなると、レスポンスデータのロード中の read の区切れ具合で運が悪いとクラッシュしたりとかありそう。
Avatar
雲をつかむような質問を投げてしまった。みなさんありがとうございます。もうちょっと色々、探ってみます。
Avatar
まあ逆に尻尾つかめたときには質問することはなくなってますからねだいたいw
Avatar
確かにw
Avatar
Kishikawa Katsumi 11/22/2017 8:15 AM
あ、場所がわかってるということなら、クラッシュレポートに、ここのコードに送信してる内容のログを含めるようにしたら再現に役立ちませんかね。レスポンスが動的だったらあまり意味はないかもしれませんが。
Avatar
ユーザーから、通信が切れるから困るみたいな問い合わせが増えてるわけではないので、本当にこのバグは起きているのか少し疑問でもあります。
Avatar
多分ですけどNSURLSessionのinternalで起きていてどのreq/resかすら掴めないのでは
Avatar
いい機会と捉えてSwiftに書き換えてみては
Avatar
Contribute to iOS9-SpringBoard-Headers development by creating an account on GitHub.
Avatar
なんかワーカースレッドがタスク探してディスパッチしそうなメソッド名だよね
Avatar
あ、すでに同じメソッドをSwiftに置き換えているのですが、最初のログでNSのプレフィックスがついてたから、objcの古いコードから起きてるのかなと、勝手に予測してしまいました。
Avatar
なるほど
Avatar
問題のありそうなところに、詳細なログを送るように色々しこんでみるしかないですね
Avatar
Crashlyticsのレポートってアプリのバージョンがいくつかって含まれてなかったでしたっけ
Avatar
含まれてまして、iOS11に対応したときから、このバグが出現しはじめてまして
8:22 AM
iOS11にアップデートしたユーザーが増えるにつれて、少しづつバグの件数が増加している感じです、まだそこまで多くないのですが。
Avatar
レポートが上がってきているバージョンのアプリは、上述のobjcからswiftへの置き換えをする前のものですか?
8:23 AM
kuroさんがおっしゃっているバージョンというのはiOSのバージョンのことかな・・
Avatar
あ、すみません。段階的にobjcからSwiftに移行してまして、iOS11に対応してバージョンのときぐらいに、このバグがで始めたと言った感じです。
8:26 AM
NSURLSessionのinternalで起きていてどのreq/resかすら掴めないのでは
8:27 AM
これもそのとおりで、どのリクエストでこのバグが起きているのか特定できていないので、通信するクラスに詳細なログを取れるようになにか手を打って、バグの再現に努めます
Avatar
1 はじめに Burp Suiteは、Webの脆弱性診断を行う製品です。 XSSや、その他の脆弱性であるreflectedやstoredのDOMベースの検査パターンを有しています。 今回は、この製品の機能のうちの一つであ […]
8:27 AM
↑こういうのを使って
8:27 AM
できるかわからないけど、リクエスト、レスポンスを、
8:28 AM
一個ずつ時間をあけてしか通さないようにプロキシを設定できれば
8:28 AM
落ちたときに、飛んでいたレスポンスが、捕捉できるかも。
Avatar
https://qiita.com/hiragram/items/195c7117fb6ebd50653e Charlesなら通信にブレークポイントを貼れますぞ〜!
この記事はSpeee Advent Calendar 2日目の記事です。 前日の記事はこちら [Ruby力を高めるためには標準メソッドを学べ...
Avatar
Burpでの通信の監視自体はやったことがあって、結構よかったです。
Avatar
手元で再現できてないと使えないのでは
Avatar
手元で再現できてないと使えないのでは
それはそう
Avatar
CharlesとBurpちょっとためして、手当たりしだい見てみます
8:29 AM
ありがとうございます
Avatar
URLSessionから実行中のtask一覧取り出せるけどあれは非同期だからクラッシュ時に埋め込むのは無理かなぁ
Avatar
URLSessionから実行中のtask一覧取り出せる
8:32 AM
知らなかったです、それも試してみます
8:32 AM
ありがとうございます
8:37 AM
大掛かりだけど、自前で実行中のreqをリストで持てるように改修して、クラッシュ時に全部取ってくるようにするのが確実な気がしますね。急がば回れです (edited)
8:37 AM
非同期でリストいじって死なないようにだけ注意しないとダメですけど
Avatar
なるほど・・・それを仕込んでリリースしてリクエストの特定をするのがまずは先な感じがしてきました。実装が大変そうですが、トライしてみます。
Avatar
サーバー側のログと照らし合わせて特定とか出来ないかな?
8:43 AM
もし可能ならそっちは今すぐ出来るかもしれない。 (edited)
Avatar
たしかに、iOS内でしかまだ問題を共有してなかったので、レスポンスが問題ならサーバー側のログにも当たってみます
Avatar
UIImage の↓の二つのプロパティは、ドキュメントを素直に読めば片方が nil のときはもう片方は nil でないということになると思うんですが、それは保証されているんでしょうか? var cgImage: CGImage? { get }
If the UIImage object was initialized using a CIImage object, the value of the property is NULL.
https://developer.apple.com/documentation/uikit/uiimage/1624147-cgimage var ciImage: CIImage? { get }
If the UIImage object was initialized using a CGImage, the value of the property is nil.
https://developer.apple.com/documentation/uikit/uiimage/1624129-ciimage
4:16 PM
たとえば、↓のようなコードは正当な(決して ! に失敗しない)んでしょうか?より良い書き方がありますか? if let cgImage = uiImage.cgImage { // `cgImage` を使う処理 } else { let ciImage = uiImage.ciImage! // forced unwrap // `ciImage` を使う処理 } (edited)
Avatar
if let ... else if let ... else fatalErrorの方が良さそう
Avatar
これで Playground で再現するのですが、 UIImage のインスタンスがあっても どっちも nil の場合はあるみたいですね let image = UIImage() switch (image.ciImage, image.cgImage) { case (let ciImage?, nil): print("ciImage: \(ciImage)") case (nil, let cgImage?): print("cgImage: \(cgImage)") default: print("none") } // none CIImage, CGImage において、 どちらかで init すると片方が nil になるとは書いてありますが、 それ以外の関係性が書いてないので
ドキュメントを素直に読めば片方が nil のときはもう片方は nil でないということになると思うんですが
これは少し憶測が入ってるかも switch で書いたのは単純に好みなのですが、 こっちの方が網羅性があるので CIImage, CGImage どっちかがあれば とう意味では読みやすいかなと思います
🙏 1
Avatar
おおお、ほんとだ、両方 nil になりますね・・・。
1:26 AM
それ以外の関係性が書いてないので
なるほど。 "If the UIImage object was initialized using a CIImage object, the value of the property is NULL." だけど、それ以外で NULL / nil にならないとは言ってないってことですね。
Avatar
もしかして UIImageinit() ってObj-C の NSObject 由来で、 public に使われることは想定されてないんでしょうか?ドキュメントにも記載されてない・・・。 https://developer.apple.com/documentation/uikit/uiimage
Avatar
確か昔のとあるプロジェクトで空のイメージを UIImage() 作って渡してた記憶が…
1:56 AM
ああ確か何かのUIKitコンポネント作って、ボタンか何かの設定の時に nil 渡すとデフォルト画像が使われちゃうので UIImage() で渡してたはず、なんのコンポネントかは忘れたけど
Avatar
UINavigationBarのshadowImageあたりとかそんな感じ
Avatar
なるほど、普通に使用することがあるんですね。
2:15 AM
とりあえず↓のような感じになりました。 extension Image where Pixel == RGBA<UInt8> { public init(uiImage: UIImage) { #if os(iOS) || os(tvOS) if let cgImage = uiImage.cgImage { self.init(cgImage: cgImage) } else if let ciImage = uiImage.ciImage { let context = CIContext() // This `guard` can be replaced with `!` if you are sure that the `createCGImage` below never fails. guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { fatalError("Failed to create a `CGImage` from an internal `CIImage` object from this `UIImage` instance: \(uiImage)") } self.init(cgImage: cgImage) } else { // This `gurad` can be replaced with `assert` if you are sure that the `size` is always equal to `.zero`. guard uiImage.size == .zero else { fatalError("The `size` of this `UIImage` instance (\(uiImage)) is not equal to `.zero` though both `cgImage` and `ciImage` of the instance are `nil`.") } self.init(width: 0, height: 0, pixels: []) } #else if let cgImage = uiImage.cgImage { self.init(cgImage: cgImage) } else { // This `gurad` can be replaced with `assert` if you are sure that the `size` is always equal to `.zero`. guard uiImage.size == .zero else { fatalError("The `size` of this `UIImage` instance (\(uiImage)) is not equal to `.zero` though `cgImage` of the instance is `nil`.") } self.init(width: 0, height: 0, pixels: []) } #endif } #if} else if ... { を落とすことができなくて悲しい・・・。
2:17 AM
そして、 CoreImage 使ったことなかったんですが、↓を発見して頭を抱えてます😂
Initializes an image of infinite extent whose entire content is the specified color.
https://developer.apple.com/documentation/coreimage/ciimage/1437947-init
(edited)
Avatar
大きさが規定されない場合はfatalErrorにするか、引数を追加して大きさも同時に指定したらvalidというAPIにするのが良さそう (edited)
Avatar
public init(uiImage: UIImage, clampedTo rect: CGRect? = nil) とかはありかもしれないけど、 fatalError が順当そう。
Avatar
確かにそれっぽい気が
UINavigationBarのshadowImageあたりとかそんな感じ
Avatar
先日、ここでiOS11のみで起きる CFNetwork URLResponse::guessMIMETypeCurrent(__CFData const*) のバグを質問したものですが、バグの解消できました!いろいろアドバイスくれた方々、本当にありがとうございました!いろいろ対策をしたのでどれが解決になったのかわかりませんが、おそらく URLSessionをsharedで呼べばいいのに不要にConfigurationを組み立てたり、奇妙なタイミングで finishTasksAndInvalidate している通信クラスがあり、そいつが原因だったように思います。お騒がせしました! (edited)
🎉 3
Avatar
iOS11でAppStoreのアプリのアップデートが手動で取らないとうまく出なかったりすると思うんですが、作成したアプリを強制バージョンアップしたい場合にStoreへ飛ばしてもアップデートへ遷移して手動で引っ張るみたいな事しないといけないといけないと思うですが これを回避してアップデート正常に出す方法とかありますかね?
Avatar
アップデートタブではなく、アプリ自体のページに飛ばしてしまえばいいのでは?
Avatar
アプリ自体のページに飛ぶとまだアップデートになってないから結果 アップデート→引っ張るってなってしまうんですよね かつアプリのページは引っ張ってもプルリフレッシュしないできなという。。。 (edited)
Avatar
iOS11で仕様どうなったかわからんですけど、以前なら個別ページが最速でアップデート表示されてたような?(記憶違い?
2:57 PM
仕様とか変わってたらわからんすなー😑
Avatar
iOS11からですね。AppStoreの更新の動きがおかしくなったのは😂
Avatar
もしかして段階的appdateの設定がonとかでしょうか?
Avatar
にはしてないですね。 http://sbapp.net/appnews/app/upinfo/ios11/app-store-8-72913 この現象の時に引っ張れば既に出る状態だけどアプリページに飛ばすとアップデートボタンになってないから更新できないって感じです
これまでApp Storeでアプリをアップデートするには、アップデート画面を開くだけでアップデートのあるアプリが表示されていましたが、iOS11ではアプリのアップデートの確認方法が変更され、アップデート画面を開いただけではアプリが表示されず...
Avatar
力技でやるなら、アプリ自体のページ情報からversion取ってきて、今のversionと比較して大きかったらStoreに飛ばす あーこれでも、結局ストアに飛んだらアップデートになってないやんけーってなる場合もあるか… (edited)
Avatar
たぶんそうなりますね。。。。
Avatar
超力技でやるなら、リリースした翌日とかの確実にアップデートがきてるタイミングで、サイレントプッシュとかを使って強制アップデート (万策尽きたので、他妙案、正攻法ご存知の方お願いします🙇 (edited)
Avatar
はじめまして。未使用のメンバ変数 (グローバル変数?)を検出することは出来ないでしょうか?よく消し忘れてしまうので自動的に見つけられると嬉しいのですが 😱
7:05 AM
自分なりに探したところ、今はその機能がなさそうなのでライブラリやAppCodeのプラグインを使うしかないのかなと思っています https://bugs.swift.org/browse/SR-3721
Avatar
Swiftlintの導入をオススメします。 Build scriptに swiftlint autocorrect と書いておけば、autocorrect可能なルールについてはビルド時に修正されます。 https://github.com/realm/SwiftLint/
SwiftLint - A tool to enforce Swift style and conventions.
7:08 AM
単純にwarningだけでよければ、swiftlint と書けばwarningが出ます。僕はautocorrectしたあとに再度swiftlintを呼びます
Avatar
omochimetaru 12/5/2017 7:09 AM
[omochi@omochi-iMac tt]$ cat a.swift let a: Int = 3 let b: Int = 2 print(b) [omochi@omochi-iMac tt]$ swiftlint Linting Swift files in current working directory Linting 'a.swift' (1/1) /Users/omochi/temp/tt/a.swift:1:1: error: Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'a' (identifier_name) /Users/omochi/temp/tt/a.swift:3:1: error: Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'b' (identifier_name) Done linting! Found 2 violations, 2 serious in 1 file.
7:09 AM
@d_date 未使用グローバル定数は検出されなかった
Avatar
マジか
7:11 AM
完全
7:11 AM
にいける頭でいたわ。失礼しました🙇‍♀️
7:13 AM
そっかーと思ってググってたらこんなのみつけた https://bugs.swift.org/browse/SR-3721
Avatar
欲しいよねこの機能、作ったけどいらなくなったメソッドとかも消したい
🙏 2
Avatar
omochimetaru 12/5/2017 7:14 AM
ローカル変数であれば未使用のものを見つけてくれるけどグローバルやメンバは反応しないなあ
Avatar
メンバはinitializerと絡むからあんまり困ってないな。
Avatar
omochimetaru 12/5/2017 7:17 AM
Xcodeの左のペインの左から3番目のタブを開いて
7:17 AM
Hierarchical表示にした上で
7:18 AM
下部の [C] のチェックを外すと
Avatar
おおー!
Avatar
omochimetaru 12/5/2017 7:18 AM
Classes Protocols, Functions, Structs, Unions, Enums, Types, Globals と
7:18 AM
シンボル種類ごとに整理されたツリーが表示されるので
7:18 AM
ここからGlobalsを開いて
7:18 AM
目で一個ずつ確認する・・・とか・・・
Avatar
OSSのも出てくるの、絞りたい…
Avatar
omochimetaru 12/5/2017 7:20 AM
現在のモジュールだけに絞り込みたいけど見当たらんなあ
Avatar
Prefixついてるの多いし、まだなんとかなるか。それでもターゲットの数だけ重複してでちゃうのね
7:23 AM
同じファイルを複数のターゲットに含めてる、という意味ね
Avatar
皆さん、ありがとうございます。 @d_date SwiftLintは使ってましたが、SwiftLintで出来ないと改めてわかったのはありがたいです🙏
7:28 AM
@omochimetaru この機能は触ったことなかったです。 試してみます、ありがとうございます!
🙂 2
Avatar
改めてプロジェクト見渡したけど、自分が書いたグローバル変数は1つもなかったので勘違いしたっぽい🙃
🐧 1
😆 2
Avatar
今のところ、その変数を右クリックして、 Find Call Hierarchyで呼ばれてる?ところが出て来るので、それで探してみるのがいいかなと思いました (edited)
Avatar
omochimetaru 12/5/2017 7:30 AM
@available(*, unavailable) let a: Int = 3 print(a)
🙏 1
7:30 AM
こうやって、 @available(*, unavailable) をつけてみると
7:30 AM
使っていればエラーになるので
7:31 AM
エラーが出なければ不要ってわかりますよ
Avatar
@d_date レビュアーの方にもグローバル変数はそもそもゼロを目指してほしいと言われました
7:32 AM
@omochimetaru おお!試してみます!ありがとうございます
Avatar
全部まずは@available(*, unavailable)つけて、エラーが出たものを@available(*, deprecated)に置き換えて残ったものを消す、deprecatedは使ってる箇所でwarningになるのでグローバル変数を減らしていく、とするとうまくいくのかな
Avatar
お〜確かにエラーになりました
Avatar
@tarunon それはとても良さそうです コミットする前はそうやって確認してみます! ありがとうございます🙏
Avatar
特定のViewの高さとか色とか、そういうのは定数で管理すると良いので然るべき場所で管理したいですね。レビュアーの方と相談してみると良いと思います。
Avatar
あ、たしかに定数はいいと言われました。丁寧にありがとうございます 〜
Avatar
使ってないメソッド問題は確かになんとかしたい
Avatar
Coverage?で出てくるみたいですが、これだとTest走らせないといけないし、全部のクラス見て回るのも面倒ですね
12:36 PM
試してみました
Avatar
https://bugs.swift.org でも https://bugreport.apple.com でも、どんどん要望あげましょう。
Avatar
norio_nomura 12/5/2017 1:07 PM
XcodeのFind Call Hierarchyがどの様にSourceKitを使っているか観察する事で、全てのグローバルメソッドの利用状況をチェックするツールを作れないか?と思ったのだけど、想像以上にめんどくさそうだった…
🙏 1
1:08 PM
オープンソースになっていないSourceKitの機能が使われてるし。
Avatar
ちなみに Xcode の Build Settings > Apple LLVM 9.0 - Warnings - All languages に GCC_WARN_UNUSED_FUNCTION GCC_WARN_UNUSED_LABEL GCC_WARN_UNUSED_PARAMETER GCC_WARN_UNUSED_VALUE GCC_WARN_UNUSED_VARIABLE っていう設定がありますが、 Swift には効かないです。
Avatar
Swiftは効かないんですね。。。残念(´・ω・`)
Avatar
初めまして、teratailに質問を投げたのですが回答がつかず涙を流しております 環境はxcode7.3.1、swift2です 助けていただけましたらありがたいです>< 何卒よろしくお願いします https://teratail.com/questions/103813
swiftでiOSアプリの開発をしているのですがBackボタンでの画面遷移がうまく行かず困っております。 画面遷移Aから順に画面遷移していき、C’でBackボタンを押した際にBに遷移させたいと思っています。また、BでBackボタンを押した際にはAに戻したいと思っています。EからC'に遷移
😢 1
Avatar
ありがとうございます!試してみます!!
Avatar
正規表現で半角@だけ通したいのに、パターンマッチで@の全角半角が区別されてないのって仕様なんすかね?
Avatar
最近話題のメールアドレスの正規表現かな
Avatar
まさにそれ…
Avatar
パターンマッチで@の全角半角が区別されてない
なんかunicodeの同じような文字同じとみなすモードみたいなのになってそう
3:05 AM
半角 aと 全角 みたいな。 (edited)
🤔 1
Avatar
Swiftがそういう風にみなしてる可能性があると…
Avatar
正規表現はNSですよね?
Avatar
です
3:23 AM
だからiOSがそもそも?というかApple全般で同じか (edited)
Avatar
[dc] 的な
Avatar
let stringA = "123@456" let stringB = "123@456" let rangeA = stringA.range(of: "@[0-9]", options: .regularExpression, range: nil, locale: nil) //.some let rangeB = stringB.range(of: "@[0-9]", options: .regularExpression, range: nil, locale: nil) //nil .range ならNS通らなくて済むからできそうですね
Avatar
おー。良さそう。ありがとうございます🤗
Avatar
山田パーだ!
Avatar
えっ、Stringの下請けもNSRegularExpressionではないのか??
Avatar
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
6:20 AM
OpenSource版ですけど調べてみたら
6:20 AM
range(of:options:range:)は、最終的に内部的には NSRegularExpressionを呼び出していました。
6:20 AM
internal func _rangeOfRegularExpressionPattern(regex pattern: String, options mask: CompareOptions, range searchRange: NSRange, locale: Locale?) -> NSRange { var matchedRange = NSRange(location: NSNotFound, length: 0) let regexOptions: NSRegularExpression.Options = mask.contains(.caseInsensitive) ? .caseInsensitive : [] let matchingOptions: NSRegularExpression.MatchingOptions = mask.contains(.anchored) ? .anchored : [] if let regex = _createRegexForPattern(pattern, regexOptions) { matchedRange = regex.rangeOfFirstMatch(in: _swiftObject, options: matchingOptions, range: searchRange) } return matchedRange }
6:23 AM
↑呼び出し方としてはこの通りなので、 regexOptions と machingOptions は、 mask 引数で決まってて、
6:23 AM
これは @lovee さんのサンプルだと .regularExpression しか与えてないから (edited)
6:23 AM
謎になった
6:24 AM
@ありぜ さんが元々書いた NSRegularExpression はどんなコードだったんでしょう?
Avatar
@omochimetaru こんなメソッドで判定してますね func isValidEmailFormat(string: String) -> Bool { let emailReg = "[a-zA-Z0-9._%+-/:~$^()&!']+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" let predicateMail = NSPredicate(format:"SELF MATCHES %@", emailReg) return predicateMail.evaluate(with: string) } (edited)
8:12 AM
hoge@gmail.comでもhoge@gmail.comでもtrueになる
Avatar
NSPredicate(format:"SELF MATCHES %@", emailReg) おおNSPredicate式だ
8:14 AM
func isValidEmailFormat2(string: String) -> Bool { let emailReg = "[a-zA-Z0-9._%+-/:~$^()&!']+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" // valid regexp let regexp = try! NSRegularExpression.init(pattern: emailReg, options: []) let nsString = string as NSString let matchRet = regexp.firstMatch(in: string, options: [], range: NSRange.init(location: 0, length: nsString.length)) return matchRet != nil } isValidEmailFormat2(string: "aaa@aaa.com") isValidEmailFormat2(string: "aaa@aaa.com")
8:15 AM
これでうまくいくようです
8:15 AM
NSPredicateよりNSRegularExpressionのほうが標準的だと思います。
Avatar
@omochimetaru .init は消せそう。
Avatar
コードレビューはいった
Avatar
最近は.init書く派です
Avatar
あえてなのか。
Avatar
というかxcode補間が安定する (edited)
Avatar
それはある < 補間が安定
8:16 AM
補間してから消す派
Avatar
左辺に型書いて = 書いて 右辺に .init ってのが最近のお気に入りです 安定する
Avatar
[a-zA-Z0-9._%+-/:~$^()&!']. と (最後の)- をエスケープしないと意図とちがうことになりそう (edited)
Avatar
左側で型推論、オシャンティーだけど引数とか返り値になった時に型が見えにくくなるのが弱点
Avatar
// valid regexptry! にかかってるのか
Avatar
はい > try!
Avatar
個人的にはこれ表示するのはIDEの仕事だと思ってるけど、JetBrainsはAppCodeに実装してるのかな
Avatar
ただなんか一部 .init だとだめなケースがあるんだよね rawValue enum で
Avatar
>rintaro ですね…前任者が適当だから(責任逃れ
Avatar
あー古い稼働コードなのか
8:19 AM
NSRegularExpressionに変更して他にも挙動の変化があるとアレですね
8:19 AM
まあでも ↑ で出てた String.range... にしても内部では結局これになってます。
Avatar
プロジェクト的には弄るの難しいかもだけど、自分の知見としてありがたい話だったので助かりました。ありがとうございます😊 (edited)
😃 1
Avatar
左辺に型書いて = 書いて 右辺に .init ってのが最近のお気に入りです 安定する
わかる、最近この書き方気に入ってる
🙂 1
🤗 1
Avatar
良さそなので暫く真似してみる
Avatar
FirebaseのRTDBやFirestoreをSwiftで使う場合に既にDictionaryになって値が取得出来るかと思いますが、既にDictionaryになってしまっている値でCodableを簡潔に使える方法無いですかね? すぐに思いついて簡単なのは JSONSerialization で一度 Data 化してから JSONDecoder を利用する方法かなと思いますが JSONDecoder 内で JSONSerializationDictionary というか Any 化されてるんですね。 https://github.com/apple/swift/blob/5836ea4d11ff5eb66f9c74ec1c0202585a467a9d/stdlib/public/SDK/Foundation/JSONEncoder.swift#L1060 なんか非効率だなーと感じるので、他に良い方法があれば知りたいです。最悪 JSONDecoder を丸々コピって DictionaryDecoder みたいなものを作る事になるのかなと思うんですが JSONDecoder が同じ処理をしてると思うとそれも非効率に感じます。。
swift - The Swift Programming Language
Avatar
@かっくん 同じことを思ってました。 [String: T] where T : Codable に encode/decode するライブラリとかあるといいのになと思います。
2:06 AM
ただ、僕は Codable にあまり詳しくないので、何かいい方法があるかもしれません。 @norio_nomura さんとか詳しそうです。
Avatar
以前何かその手の、ObjectEncoderみたいなのが出てきた気がする
2:07 AM
Codable DictionaryあたりでDicordを検索すると出てくるかもしれません (edited)
Avatar
ObjectEncoder - Swift Encoders implementation using [String: Any], [Any] or Any as payload.
👌 1
Avatar
norioさんだった・・・
Avatar
さすがだ。。w
Avatar
まさにこれっぽい
Avatar
試して見ます!ありがとうございます! @koher @tarunon @omochimetaru
👍 1
Avatar
まさに ObjectEncoder 使わせてもらおうとしたんですが、
2:57 AM
JSONEncoder.DateEncodingStrategyに相当するものが無いのに気づき
2:58 AM
結局 JSONEncoder.swift を本家からコピーして適当にリネームして (edited)
2:58 AM
Anyを食わせるようにしてしまいました。。
Avatar
特定の型のエンコード戦略の変更をエンコーダー側でサポートしないと注入できないの微妙なんですよね
3:00 AM
キーのsnake_case化の機能もJSONEncoderに入りそうだけど、JSONにかぎらずニーズありそう
3:00 AM
(って話をのむらさんがそのPR上で投げてたけどJSON固有の話だし〜みたいな感じになってた
Avatar
えー
Avatar
このへんの流れですかね
3:08 AM
(メーリングリストの正しいリンク先がわからない・・)
3:11 AM
PRがすでにあった
3:11 AM
In some cases, it's possible to have a Foundation object (either NSArray or NSDictionary) that produce a valid JSON. The current implementation of JSONDecoder allows decoding only from Data. This p...
3:13 AM
↑これです
3:14 AM
(メーリングリストの正しいリンク先がわからない・・)
そろそろフォーラムに移行されるからわからないままで大丈夫!w
😀 1
Avatar
ぬ、やっぱりDateEncodingStrategyとか要りますかね。僕の用途では不要だったので付けなかったのですが…
Avatar
PRの流れ
Avatar
僕の場合は、既存コードのAPIレスポンス処理部分を部分的にCodable対応して行こうと思い、特定のkey以下をJSONDecoderでデコードさせたかった、という用途でした (edited)
Avatar
そのまま使うとDate型のオブジェクトがそのまま入るんじゃなくて、Date型自体のencodeメソッドのデフォルトの挙動ベースで、 DictionaryだかArrayだか + パラメータの形になっちゃうのかな?
Avatar
DateDecodingStrategyの方か。
Avatar
そうですね、たしか2001/1/1 originでDateが作られるんだったかな
Avatar
オフセット秒数になるのか・・・
Avatar
DateDecodingStrategy .deferredToDate 扱いか (edited)
Avatar
StringからDate?を作るメソッドを指定できる仕組みがあれば良いのかな?
4:05 AM
あいやAnyからか。
Avatar
JSONDecoderはstrategyによって、生成方法を指定できるようになってるみたいですね
4:20 AM
そっか iso8601 だとStringからDate、になるんか (edited)
Avatar
お、keyEncodingStrategyとかも既にSwift 4.1に入ってるのか。 import Foundation let encoder = JSONEncoder() encoder.keyEncodingStrategy = .convertToSnakeCase
😍 1
Avatar
ObjectEncoderで任意の型にCoding Strategyを設定できる様になりそう。 https://github.com/norio-nomura/ObjectEncoder/pull/11 var encoder = ObjectEncoder() encoder.encodingStrategies[Date.self] = .iso8601 let encoded = try encoder.encode(Date(timeIntervalSince1970: 1000)) encoded == "1970-01-01T00:16:40Z" // true var decoder = ObjectDecoder() decoder.decodingStrategies[Date.self] = .iso8601 let decoded = try decoder.decode(Date.self, from: encoded) decoded == Date(timeIntervalSince1970: 1000) // true (edited)
Add ObjectEncoder.EncodingStrategy and ObjectDecoder.DecodingStrategy that creating strategy Add ObjectEncoder.encodingStrategies and ObjectDecoder.decodingStrategies th...
👏 3
Avatar
おお、型をキーに。
Avatar
やったーあとで試してみます!
Avatar
Swiftでフレームワークを作っています. フレームワーク内で,自分で作ったObjective-Cのクラスを使うには,どうすればいいですか? Swiftでアプリケーションを作っているときは,bridge-headerを使って,そこにObjective-Cのヘッダファイルをインポートすればいいのはわかるのですが・・・. フレームワークでは,bridge-headerがサポートされないので困っています・・・・.
4:40 AM
っていうか,前にも同じところでハマった気がする
Avatar
modulemapこねこねしたんだっけ、、、
Avatar
同じことちょうど昨日はまって、おもち先生からはフレームワーク分けたら?と (edited)
Avatar
フレームワークからCommonCrypto.hを参照したくて困ったことがありますが解決しなかった
Avatar
moulemap で module 作るのもいけるとのことだけど、詳細は追えてない
Avatar
システムヘッダーかフレームワーク内のヘッダーなのか、で違って来ますね。
Avatar
既に閲覧済みかもしれませんが、
4:57 AM
It's already 2 years of Swift and its interoperability with Objective-C as well. When app extensions were released we've got a way to share our code across targets using frameworks. I used to build lots of frameworks since then, sometimes I even worked full-time just on frameworks. But as I
👏 1
Avatar
mixed-swift-objc-framework - Shows how to mix Swift and Objective-C code inside a framework target
5:06 AM
これが参考になるかも。
Avatar
Kishikawa Katsumi 12/16/2017 5:14 AM
インポートしたいライブラリ用のmodulemapを作るのがオーソドックスな方法ですね。相手がどんなライブラリかにもよるのでサンプルプロジェクトかそのものを見せてもらえたら解決しますよ。リモートでやるには情報が足りない。最低限何のライブラリをリンクしようとしてるかが必要です。 @sonson
Avatar
フレームワーク内で,自分で作ったObjective-Cのクラスを使うには,どうすればいいですか?
「自分で作った」、だから、CommonCryptをリンクするようなパターンじゃなくて、自作のライブラリがSwiftとObjC両方のソースを抱えてるパターンの話な気がしますね。
Avatar
Kishikawa Katsumi 12/16/2017 5:20 AM
ああ、なるほど。ちゃんと読めてなかったですね。それなら上におもちさんが貼ったリンクのプロジェクトが参考になると思いますね。
5:21 AM
そのプロジェクトで説明すると、
5:25 AM
1. ライブラリのディレクトリ Foo を作って 2. module.modulemap ファイルを作って、アンブレラヘッダー( <Foundation/Foundation.h>のようなもの)を作って参照できるように書く module Foo { header "../Foo.h" export * } 3. SWIFT_INCLUDE_PATHSにモジュールまでのパス(Fooディレクトリまでのパス)を設定する 4. import FooできればOK
5:26 AM
っていうのが基本です。そのFooライブラリがさらにStaticライブラリに依存してるとかだとmodulemapにリンクの設定とかが必要になります。
5:27 AM
ライブラリの書くクラス等はアンブレラヘッダーでimportしておきます。アンブレラヘッダーがブリッジヘッダーのような役割をしますね。
🙏 2
Avatar
SwiftPMとの共存に困る場合があるのでmodule.modulemapは極力使わない様にしてる。SwiftPM対応しないなら関係ないけど。
Avatar
ただいまー
5:55 AM
みなさんありがとうございます
5:56 AM
modulemap,なんだか面倒だなぁ・・・・.
Avatar
modulemap によって C言語の #include の世界が シンボルベースの世界に変換されて
5:57 AM
健全な時代になりそうで僕は好き
Avatar
自動でやってほしいw
Avatar
Xcodeは適切に設定すればビルド時にmodule.modulemapを自動生成します。 (edited)
Avatar
includeするけどライブラリとしてはexportしない、とか細かい制御ができるっぽいですよ、modulemapのところで
Avatar
Kishikawa Katsumi 12/16/2017 5:59 AM
あ、よく考えたら自分で作ったフレームワークをインポート、ってことだからインポートする側じゃなくてされる側のObjCフレームワークの方で設定すれば簡単だ。
5:59 AM
野村さんのいう通り。
Avatar
される側です
6:00 AM
すみません,それはどのドキュメントを読めばよいでしょう・・・・・か,サンプルか
Avatar
Kishikawa Katsumi 12/16/2017 6:01 AM
RealmSwiftがRealmをインポートしてるのと同じ関係なので、ちょっと大きいけどRealmのプロジェクトを見るとわかりますよ。
Avatar
ドキュメントは知らないです。経験として知ってるだけ。
Avatar
あう・・・・
Avatar
Kishikawa Katsumi 12/16/2017 6:01 AM
Realmはmodulemapを自動生成じゃないけど、逆に仕組みはわかりやすいと思います。
6:02 AM
ドキュメントはたぶんClangのmoduleのところがそうだと思います。
6:03 AM
ただそれはSwiftでどうかということは書いてない。
Avatar
うーむ・・・・clangのドキュメント・・・・つらいw
Avatar
Swiftは clang module を読み込めるんだと思ってる
Avatar
今は,Objective-CのコードをSwiftに書き直した方が早いし,将来性あるんじゃないかと考え始めている
Avatar
Swiftの package 機能は clang module を限定的に使うやつで
6:04 AM
swift の @_exported import の裏技とかは、
6:04 AM
仕組み上 clang module が取り扱える基盤があるから動いてそう。
Avatar
SwiftPMでビルド可能にした後にXcodeプロジェクトを作るのがやっぱりオススメかな。
6:07 AM
OSSならばSwiftPMでビルド可能、の時点で公開できれば、具体的なアドバイスが出来る。
Avatar
Kishikawa Katsumi 12/16/2017 6:07 AM
そのフレームワークがiOS用だったらSwiftPMでビルドするまでが結構大変じゃないです?
Avatar
僕も結構ビルド芸やってるのでモノがあれば助けられると思います
Avatar
芸ってw
Avatar
Kishikawa Katsumi 12/16/2017 6:09 AM
ビルドとかコード署名とか環境周りの問題は見ればそこそこ短時間に解決できると思うけど、リモートで解決するのは難しいですね。 😄 (edited)
Avatar
サンプルというか,切り出したいObjective-Cのコードは別にオリジナリティないんで,公開できます
6:10 AM
今は,そのコードをSwiftに移植しようかと思っていますが,後学とコミュニティのためにどうすればいいか議論していい気がしています
6:13 AM
っていうか,めっちゃしょうもないサンプルプロジェクトになってしまった
6:15 AM
Contribute to ObjCInSwiftFramework development by creating an account on GitHub.
6:16 AM
状況. やりたかったのは,iconvでデコードする昔書いたobjective-cのコードをswiftから呼びたいということです. ただし,swiftのコードは,frameworkで,applicationではありません. このサンプルコードのsampleがアプリケーションで,sample2がフレームワークになっております. sampleでは,objective-cのコードがswiftのコードから見えません.
Avatar
やってみます
Avatar
ありがとうございまする
Avatar
なるほど、システムヘッダ依存なのね。
6:25 AM
^ とりあえず、絶対パスとかで書いてるけどこれがImportする側を変更する場合の基本ですね。相手がベンダーライブラリとかでインポート側を訂正できない場合に使います。
6:26 AM
次、インポートされる側でモジュールをエクスポートする方法をやってみます。
6:27 AM
と、思ったけど、今はsample2.framework自体にSwiftとObjCが混ざってるからたぶん無理ですね。
6:28 AM
そうするにはObjCのコードを分けて、iconvのラッパーライブラリとして作る、みたいなことが必要。
6:28 AM
そうすると、Swiftのフレームワーク(sample2.framework)でそれがインポートできる。
6:32 AM
^ の変更は stringByDefaultEncodingWithData の呼び出しまでしか確認してないけど、modulemapファイルにlibiconvをリンクする設定がいるかも。
6:35 AM
6:37 AM
^ Importされる側を修正するバージョン。ObjCのコードNSString+iconv.h/mを1つのモジュール(IconvWrapper.framework)にしてそれをsample.framework(およびTestApp)からインポート。
Avatar
Contribute to ObjCInSwiftFramework development by creating an account on GitHub.
6:37 AM
できた
Avatar
Kishikawa Katsumi 12/16/2017 6:37 AM
元ライブラリに手を入れられるならこっちの方が’簡単。実質的にObjCのCocoa Frameworkのプロジェクトを作ってソースファイルをコピーするだけなので。 (edited)
Avatar
リポジトリルートにあるxcworkspaceを開いて作業するようになってて、 ObjCのstatic libraryのプロジェクト Swiftのdynamic libraryのプロジェクト SwiftのiOSアプリのプロジェクト の3つが入っててそれぞれ依存設定してあります。
6:38 AM
import IconvSwift class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let data = Data.init(bytes: [0x82, 0xA0]) // SJIS で "あ" let str = NSString.init(byDefaultEncodingWith: data) print(str) } ↑で、これが動いたので、OK
6:39 AM
ObjCのやつをSwiftから読み込むために src/IconvObjC/module.modulemap ファイルと Swiftのプロジェクト側の BuildSettings の Import Paths が設定してあります
Avatar
ふーむ
Avatar
Kishikawa Katsumi 12/16/2017 6:42 AM
おもちさんのと私の2つ目との違いはIconvObjC(=IconvWrapper)がStaticフレームワークかDynamicフレームワークかというところですね。
6:43 AM
いずれにしても、言語Mixの1つのフレームワーク、よりは言語ごとの複数のフレームワークを作る方が簡単だと思います。
6:43 AM
言語Mixの1つのフレームワークの場合は内部でモジュールを作ってインポートする。
Avatar
構成のバリエーションがいくつかあってそれぞれに特性があるのでややこしいですね・・・
Avatar
言語ミックスは辞めときます
Avatar
Kishikawa Katsumi 12/16/2017 6:45 AM
そうですね。例えばIconvをSwiftから使いやすいラッパーを提供したいということなら、内部でIconvを使う1つのSwiftフレームワークで提供した方が、ユーザーにとってはわかりやすい。
6:46 AM
ここからは、全然別の仮の話ですけどFramework in FrameworkがAppStoreに出せるなら上記の色々な方法はほとんど必要なくて、たいていはFramework in Frameworkの方法をよかった。 (edited)
6:47 AM
IconvObjCをIconvSwiftに組み込んでしまうということ。技術的には全然可能で問題なく動くけど、ただこれはAppStoreに出せないので実質意味がない。 (edited)
Avatar
そのサンプルに限って言うなら、iconvはDarwin, (LinuxならGlibc)をインポートすれば使えるのでSwiftに書き直すのが良いと思う。
👍🏻 1
Avatar
sample2をXcodeとSwiftPMの両方に対応させた https://github.com/sonsongithub/ObjCInSwiftFramework/compare/master...norio-nomura:support-both-of-swiftpm-and-xcode (compare branchesのリンクに差し替え) (edited)
Contribute to ObjCInSwiftFramework development by creating an account on GitHub.
8:22 AM
Xcodeプロジェクトはswift package generate-xcodeprojで再生成したものを修正してる。
Avatar
ありがとうございます!
8:39 AM
色々選択肢があって・・・結局,swiftに移植する道を選びますたw
8:39 AM
でも,とりあえず参考にして,どっかにまとめたいと思います
Avatar
最低限の変更にしてXcodeプロジェクトの編集ステップ毎にコミットを別けた。 https://github.com/sonsongithub/ObjCInSwiftFramework/compare/master...norio-nomura:support-both-of-swiftpm-and-xcode-take2
Contribute to ObjCInSwiftFramework development by creating an account on GitHub.
Avatar
Cのライブラリが,処理に失敗した時にポインタの代わりに-1を返すのをSwiftでチェックする場合,以下のコードでよいのかしら? let intIconv: iconv_t = iconv_open("UTF-16//IGNORE", "SHIFT-JIS") guard Int(bitPattern: intIconv) != -1 else { throw EncodingErrors.invalidEncodingName }
Avatar
良いと思います〜
👍 1
Avatar
@omochimetaru thx
Avatar
すみません、質問させてください。 Swiftってこんな風に、structのletに初期値を代入しておいて、それ用に中ではletに代入を行わないinit作った場合に以下のことをしたら勝手にletに代入されたんだけど、こんな言語仕様でしたっけ? struct Card { enum Suit { case spade case heart case club case diamond } enum Rank { case one case two case three case four case five case six case seven case eight case nine case ten case j case q case k } let suit: Suit = .heart let rank: Rank = .j init(suit: Suit, rank: Rank) {} } let card = Card(suit: .spade, rank: .k)
12:53 PM
普通こんな風には書かないと思いますが、TDDの説明用の資料として作っていたので、言語仕様の確認がしたかっただけと理解いただけるとありがたいです。m( )m
Avatar
Kishikawa Katsumi 12/24/2017 12:54 PM
合ってると思いますよ。むしろ let suit: Suit = .heart と書くと init では代入できない。
Avatar
a,
Avatar
Kishikawa Katsumi 12/24/2017 12:54 PM
init(suit: Suit, rank: Rank) {} で渡しているパラメータは self.suit には代入できないので別のことに使うしかない。
Avatar
letで書いているのでinitで代入できない問題は、仮実装中のコードとして置いていたからです。この後一般化しようと思っています。
12:56 PM
あー、やはりそうですよね;
Avatar
Kishikawa Katsumi 12/24/2017 12:56 PM
initで代入したいなら、let で初期値は渡せないです。
12:56 PM
letで初期値を書かないなら、initで代入する、どちらか。
Avatar
あ、ああ、やはりそうですよね。理解しました🙇
12:58 PM
・letに初期値を入れずにinitで代入するようにする ・letに初期値を代入しておく この二つは用途が違う
Avatar
Kishikawa Katsumi 12/24/2017 1:00 PM
そうですね。指定されなかった場合のデフォルトはあるけど、最初に任意に指定して変更できるようにしたいという場合はプロパティに代入する形では書けないです。
Avatar
ありがとうございます😀
Avatar
Kishikawa Katsumi 12/24/2017 1:00 PM
それができたら揃ってキレイなんだけど、、、みたいに思うことはよくあります。
1:00 PM
というかそうやって書いて、initに書き直すとかよくやってる気がする。
Avatar
それができたら揃ってキレイなんだけど、、、みたいに思うことはよくあります。
なるほど、これは確かにありそうですね🤔
Avatar
init側のデフォルト引数にするとやりたいことは出来そう?
Avatar
Kishikawa Katsumi 12/24/2017 4:33 PM
そうだと思います。
Avatar
SwiftのArrayとかから,ポインタにするコード,いつまでたっても,空でコード書けない
7:25 AM
普段から書かないもんなぁ・・・・・
Avatar
全然覚えられない
7:29 AM
毎回,コピペしてる気がする
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
7:06 AM
これ関連でよくわからない挙動が有りまして
7:06 AM
import UIKit class ViewController: UIViewController { var provider = Provider() override func viewDidLoad() { super.viewDidLoad() provider.reload { self.provider.layout() // 1) Simultaneous access ! } } struct Provider { let cache = Cache() // 2) comment out mutating func reload(completion: @escaping ()->Void) { // 3) remove mutating keyword completion() } func layout() { } } class Cache { } } (edited)
7:07 AM
このコード自体に特に意味は無いんですが、適当なiOSプロジェクトを作ってiOS Simulatorで実行すると 1) で例外?が発生します
7:08 AM
3) の mutating を外すと正常に動くので、SE-0176 関連の挙動かなとは思うんですが
7:08 AM
謎なのは、2) の行をコメントアウトするだけで、例外が発生しなくなるという点です
7:10 AM
手元の再現環境は、macOS 10.13.1 + Xcode 9.2 + iPhone 8 Plus Simulator + デバッグ実行で再現しました。 (edited)
7:11 AM
何かご存知の方いらっしゃいますか?
Avatar
omochimetaru 1/9/2018 7:13 AM
バグか仕様か悩ましいですねこれは
7:14 AM
例外というか実行時クラッシュのはずです 排他則の動的検出にひっかかっていて
7:14 AM
reloadメソッドがmutatingなのでProviderのインスタンスは書き込みアクセスされているんですが
7:15 AM
completionブロックの中で provider.layoutを呼んでいるので、これは読込アクセスなんで
7:15 AM
書き込みアクセス保護中のオブジェクトにたいして読込アクセスをしてはいけないので
7:15 AM
クラッシュするっていうのがまず基本で
7:16 AM
で、// 2 をコメントアウトするとクラッシュしなくなる理由については予想ですが
7:16 AM
stored propertyを1つも持たないstructに関しては
7:16 AM
書き込みアクセスがあろうが実際に書き込みの影響を受けるメモリ領域を持っていないので
7:16 AM
同時アクセスをしても問題ないはずです
7:16 AM
だからクラッシュが発生しなくなるんだと思います
7:17 AM
ただそれが仕様上許された例外的な挙動なのか、実装の都合でたまたまそうなっているのかはわかりません。
7:17 AM
3でmutatingを外すと動くようになるのは、 reloadが読込アクセスに降格するからで
7:18 AM
読み込みアクセスは重複が許されてるのでこれはLoE違反しないです。
Avatar
あーなるほど
7:20 AM
>stored propertyを1つも持たないstructに関しては 書き込みアクセスがあろうが実際に書き込みの影響を受けるメモリ領域を持っていないので 同時アクセスをしても問題ないはずです
Avatar
omochimetaru 1/9/2018 7:20 AM
これは予想ですけど、//2 をコメントアウトしても、代わりに var hoge:String = "" とか
7:20 AM
つけたすと
7:20 AM
同じようにクラッシュするんじゃないですかね〜
Avatar
たしかにクラッシュしました
Avatar
omochimetaru 1/9/2018 7:23 AM
おー じゃあやはり 「stored property が 0個 の場合」にまつわる挙動っぽいですね。
Avatar
なるほどー!
7:23 AM
ちなみに
7:23 AM
override func viewDidLoad() { super.viewDidLoad() provider.reload() } struct Provider { var cache = Cache() mutating func reload() { layout() } func layout() { } }
7:23 AM
これだとクラッシュしないのは
7:24 AM
LoE違反ではない、ってことですかね?
7:24 AM
closureがからむとNG..?
Avatar
問題になるのはlayoutを呼ぶ対象とreloadした結果のProviderが食い違うことで、この場合はプログラマが明示的にどれなのかを管理できるから問題ない (edited)
Avatar
omochimetaru 1/9/2018 7:25 AM
それだと、reloadメソッドが所有してるアクセス権の範囲内で layout を呼び出しているのでOK
Avatar
なるほど、reloadの中で処理が閉じているから問題なしで、元コードはclosure経由で外部から読まれてしまうので問題ありと・・ (edited)
7:36 AM
理解できました、ありがとうございます!
🙂 1
Avatar
>おー じゃあやはり 「stored property が 0個 の場合」にまつわる挙動 はSE-0176 Proposed solutionの No enforcement is required for immutable memory, like a let binding or property, because all accesses must be reads.
7:55 AM
の仕様によるものですかねー (edited)
Avatar
omochimetaru 1/9/2018 7:57 AM
そのセンテンスは、 letでのローカル変数定義やclass/structのletで定義されるpropertyのような、immutableなメモリについてはLoE強制処理は必要ない ってことを言っていると思います
7:57 AM
言語仕様の時点でletに対しては読込アクセスしかできないからです
7:58 AM
「immutable memory」に、カンマ以降の like ... がかかっているので。 「0 propertyの場合」が「immutable memory」とみなされるかどうかは別の議論だと思います
Avatar
stored property が 0個 = immutable memory
7:58 AM
なるほど
Avatar
omochimetaru 1/9/2018 7:58 AM
「1個追加したら壊れる」っていう仕様だと、逆にこういう混乱が起きたり、後から追加してバグらせたりしかねないので
7:58 AM
0個であっても保守的にエラーにしておくほうがいいんじゃないかと個人的には思います
Avatar
たしかに!
Avatar
omochimetaru 1/9/2018 7:59 AM
bugsに投げてみた方がいいかな・・・うーん・・・。。
Avatar
Int.advanced(by:)Array.filter(_:) のような、同じ型の新しいインスタンスを返すメソッドのことを、ゲッター、セッター、ミューテーターみたいな分類でいうと何と言いますか? (edited)
Avatar
トランスフォーマー?(違
Avatar
アリかも!
Avatar
「トランスフォーム」は「変形」だから型が変わるイメージがなきにしもあらず… 🤔
🤔 2
Avatar
高階関数とは別ってことだとなんだろう…
Avatar
変質が近いニュアンス?deterioratorとかalterationerとか?
Avatar
extension UIView { var ii : Int { get { return 0 } set(i) { // hogehoge } } } let v = UIView() v.ii = 3 propertyがこんがらがってしまって、Stored property と Computed propertyがあって上のコード内のiiはComputed propertyであってますでしょうか🙇
Avatar
はい、ii は Computed Property です。
Avatar
ありがとうございます。
Avatar
// Stored property. var p1: Int = 1 // Computed property. var p2 Int { get { return 1 } set { /* ... */ } } // Computed property ( 暗黙のgetのみ ) var p3: Int { return 1 } (edited)
Avatar
ありがとうございます!
9:07 AM
つまり、これはだめだということですね extension UIView { var a = 0 }
Avatar
ですね。 extension に Stored property は追加できない。
✋ 1
Avatar
もう1つ質問なのですが、setterの中で extension UIView { var ii : Int { get { return 0 } set(i) { backgroundColor = UIColor.red } } } と、classにある値を変更するのは、よくないでしょうか?
Avatar
「classにある値を変更」自体は問題無いと思いますが、 set した値を get で取り出せるようにすべきだと思いますよ。
Avatar
ありがとうございます。そうですよね。setterのことだけ気になっていたのですみません。
Avatar
getterが無意味なら普通に一引数のfunctionにしたほうが良いですよ
Avatar
いまのところgetterが無意味なのですよね・・・
9:17 AM
Computed PropertyとSetterのことがわかったのでありがとうございます。functionも考えてみます
Avatar
func example<T>と定義したのって、example<Int>()で呼べましたっけ?
Avatar
そう言う呼び方はできなかった気がする
1:44 PM
そもそもシグネチャの引数か返り値にT使ってないとコンパイル通らないような
Avatar
引数に型情報与えないとやはりダメなのかなー。
Avatar
どういうことがやりたいんですか?
Avatar
型で、なんかコンパイラに証明させようかと思ったんですよ。
Avatar
ほう
1:50 PM
func example<T>(_ type: T.Type) { } example(Int.self)
1:50 PM
これしかないよーな
Avatar
ですね、ちょっとなんかそれだと、エレガントじゃないなぁという感じですが、仕方ないですねぇー。
Avatar
example<Int>() こう呼べても良いような気もちょっとだけする
1:55 PM
何か不都合があるのかな
Avatar
エレガントじゃない方法で良ければ、高階関数にして(T.Type) -> (T) -> ()でexample(Int)とかできませんかね
2:03 PM
できたぞ
2:03 PM
func example<T>(type: T.Type=T.self) -> (T) -> () { return { arg in print(arg) } } let intE = example(type: Int.self)
Avatar
目がチカチカするコードきた
Avatar
慣れて
Avatar
あー
2:04 PM
ん?
2:05 PM
intEInt が引数の関数でしょ
2:05 PM
これやりたかったことなのか?
2:06 PM
もしかしてこれ example<Int>() で呼べるのか
Avatar
example()(1)が出来る
Avatar
それは @Nobkz さんやりたかったことなんか…?w
Avatar
本質的に欲しいのは、Intで確定したexampleを使いまわしたいということなのでコレで可
2:08 PM
仕方ねぇな~~~~
Avatar
壊すなよ〜
2:09 PM
あーこれもしかして別スレの文脈があるのか ここしか見ていなかった
Avatar
func example<T>(arg: T) -> () { print(arg) } func example<T>(type: T.Type=T.self) -> (T) -> () { return example } let intE = example(type: Int.self)
2:09 PM
ほれ、オーバーロード編だ
Avatar
まぁ、なんだ、やりたいことがなんかできそーだからちょっとやってみるかね。10分くらいまて。
Avatar
Xcode落ちたんだがww
Avatar
『僕は悪くない』
Avatar
絶対言うと思った
Avatar
できたぞ。
3:37 PM
ここに流すより、mathに流したほうがええか。1 + 1 = 2の証明っぽいの。
Avatar
おやつだ
Avatar
そのざっくりとして申しわけないんですが、Swiftで、Listっぽいことやりたいのですが、みなさんどうしてますかね?
Avatar
ListってJavaのLinkedListみたいな感じですよね
Avatar
どっちかというと、HaskellのListっぽいやつ。
5:29 AM
あ、でも遅延はしなくてよい。
Avatar
Kishikawa Katsumi 1/30/2018 5:29 AM
SwiftもObjective-Cも標準のデータ構造は貧弱なんですよね。自分でチョチョっと書くことになると思います。
5:30 AM
ただまあ"Swift data structure"とかで検索したら出てくることはでてくる。
5:30 AM
ただそういうのはSwift 2あたりで更新が止まってることが多い。
Avatar
indirect enumでtailとnextのケースを書くのがよく見る奴
Avatar
なんか自分で書くかんじなんすかねー。
5:32 AM
それが分かれば、かくかーって感じでわかりますた。
Avatar
Sequenceに適合すると便利です
5:33 AM
あでもmapしたらArrayになるのは微妙いかな
5:34 AM
@koher が遅延評価なやつ作ってた
Avatar
SequenceTypeだからswift2かな (edited)
Avatar
SequenceはmapしたらArrayになるんか....うーむ。
Avatar
HigherKindedTypeないねん、ごめんな
Avatar
Swiftz - Functional programming in Swift
5:36 AM
これとかじゃダメです?
5:37 AM
だいたい欲しいものが揃ってるので満足してました
Avatar
揃ってそうですね
5:37 AM
いきはよいよいかえりはこわひ
Avatar
Kishikawa Katsumi 1/30/2018 5:37 AM
確かに、Haskellっぽいことをするなら。
Avatar
後戻りできなくなるのでプロダクトに入れるのは悩むやつです
Avatar
Kishikawa Katsumi 1/30/2018 5:38 AM
プロダクトに導入するにはエクストリームすぎるかな。。。
Avatar
まあでも大体のライブラリはそうか
5:38 AM
チームメンバーが全員パワー系なら入れたい
Avatar
たしかに満足しますね。
Avatar
チームメンバーがパワー系、未来永劫そうであるかという問題もあって難しい
Avatar
個人的には Either, Monoid, Functor ぐらいは使っても理解は容易なので害はないだろう、と思っていたりします
👀 1
5:43 AM
Monad あたりから敬遠する人が増えてくると思いますが、まあ上記のものぐらいは最悪自前実装にも簡単に変えられますしね
Avatar
mapとflatMapがわからん人間がいてabuseするのでcompactMapに名前を変更するのが現実ですよ
5:43 AM
現実を見て
5:43 AM
理想は
Avatar
現実は厳しいw
Avatar
Kishikawa Katsumi 1/30/2018 5:44 AM
世の中にはmapとflatMapがあればいいやんみたいな人もいるから大丈夫。
Avatar
(ちなみに、プロダクトの話がありましたが、うちはプロダクトに Either と Monoid は持ち込みましたね)
Avatar
お忙しいところすみません>< 困っていることがありましてお助けいただけましたら幸いです objectMappingを使ってjsonに変換しているのですが、例えば下記のようなことは可能でしょうか? サンプル userId = 100 --- Int userName = "gabacho" --- String honest = nil --- Bool tel = nil --- Int この際にtelは含めず、honestだけnilもjsonの中に含めたいです 例えば、最初はhonestをtrueにしてたけどやっぱりどっちでもないnilに変更したいと言った場合などです そもそもBool型でなくすという手もあるとは思うのですが、既存アプリの改修のためできれば型を変えずにできるとありがたいです 理想のjson {"user"=>100, "name"=>"gabacho", "honest"=>nil} 何卒よろしくお願いします!
Avatar
API絡みの話題と推測しますがリクエストとレスポンスどちらの話でしょうか?
Avatar
はい、APIがらみです! アプリで編集してその結果をサーバーに送信するのでリクエストかと思います (単語の意味から送信がリクエストで、受信がレスポンスと解釈しましたが間違っておりましたらすみません)
Avatar
ObjectMapperは結構自前でマッピング処理書けたんでなんとかなるとは思います、レスポンスの場合は型を変えると既存のアプリが壊れるから確認しました。リクエストなら古いバージョンのアプリから古い型でAPIが叩かれるのを考慮する必要がありますね。
Avatar
既存のコードで honest がすでにBool型なところにnilを入れたいということなら Bool? なり適切なモデル型なりに型を変える必要ありそう
Avatar
@tarunon ありがとうございます! 法人向けアプリのためバージョンはこちらで一律管理できるので古いバージョンから送信されることはないので大丈夫です!
Avatar
Boolにnilは無理なのでBool?にするのは必須ですね
Avatar
@hiragram @tarunon 確かにそうですね、ありがとうございます! ざっくりとした質問で申し訳ないのですが、マッピング処理はどのあたりでやってるのでしょうか? (コード読めという話だと思うのですがお助けいただけるとありがたいです...)
Avatar
マッピングというのがオブジェクトからJSONへの変換という意味だったら、プロジェクト内を JSONSerialization とかでgrepしてみたらどうでしょうか
3:18 AM
個別のライブラリでラップされてたらなんとも言えないですね
Avatar
ライブラリはObjectMapperであってますよね?
Avatar
あとは通信呼び出してる処理から辿るとか、、、?
Avatar
それならモデルのコードに入ってるはず
Avatar
Kishikawa Katsumi 1/31/2018 3:18 AM
モデルにinit(from)かmappingみたいなメソッドがあるはずです。
Avatar
個別のプロパティのマッピングは<=だったかな、うろ覚えですが
3:20 AM
ObjectMapperのドキュメントを読むのが良いです
Avatar
@tarunon 念のため確認いたしましたがObjectMapperでした!
3:21 AM
@hiragram JSONSerialization見てみます!
Avatar
@tarunon@Kishikawa Katsumi が言ってるのはJSON→オブジェクトのマッピングじゃないですか?リクエスト側とのことなので逆方向な気がする
3:22 AM
(ObjectMapper使ったことないので正しかったらすません
Avatar
ObjectMapperはどっちも共通なんす
3:23 AM
たしか
Avatar
そうなんや
Avatar
@Kishikawa Katsumi ありがとうございます! 調べてみます!! @tarunon ありがとうございます! みなさんに教えていただいたヒント参考にドキュメント探ってみます
3:30 AM
@hiragram ありがとうございました!
👌 1
3:32 AM
またご報告にまいります! 前任者の引き継ぎでやってるのですが、前任者がすでに退職していてiOSわかる人間が社内にいないというなんともな環境でして...w またここでご質問させていただけましたら幸いです
😨 4
Avatar
上記の件ですが、コメントいただきありがとうございました! 現在ですが userId = 100 --- Int userName = "gabacho" --- String honest = nil --- Bool? tel = nil --- Int? に対してできたJSONが {"user"=>100, "name"=>"gabacho"} となっておりnilが無視されている状態です 別作業も挟まってきておりますが、継続して解決策を探していければと思っており、見つかりましたらまた報告いたします!!
Avatar
そのJSONのオブジェクトがSwiftのDictionaryだとしたらnil代入はキーの削除と同じってことになってキーごと消えるのはまあわかる
Avatar
ObjectMapperに手を入れないとnull入れるのは実現できない気がしてきた
Avatar
SwiftyJSONにはSwiftyJSON.nullみたいなのがあった気がするからその辺がObjectMapperにも無いかなって感じ
6:58 AM
@tarunon ↑こういうのない?
7:13 AM
NSNullを特別扱いしてるっぽいですねぇ
7:13 AM
NSNullならkey付きのnullになってくれるかも
7:13 AM
key付きのnullとkey削除の区別をしないとAPIが壊れるのかどうかによると思います。
Avatar
@hiragram @tarunon ありがとうございます! ObjectMapperのコードで下記があって、そこに入ってきているので 「keyがhonestかつnilだったらnull入れて」みたいなことしようとしてたのですがうまく実装できず、別作業が差し込みで入ってきたのでそっちに移ってしまいました ちなみにignoreNilにはfalseが渡されています ここいじれば行けそうでしょうか? public subscript(key: String, nested nested: Bool, ignoreNil ignoreNil: Bool) -> Map { // save key and value associated to it currentKey = key keyIsNested = nested // check if a value exists for the current key // do this pre-check for performance reasons if nested == false { let object = JSONDictionary[key] let isNSNull = object is NSNull print(object) isKeyPresent = isNSNull ? true : object != nil currentValue = isNSNull ? nil : object } else { // break down the components of the key that are separated by . (isKeyPresent, currentValue) = valueFor(ArraySlice(key.componentsSeparatedByString(".")), dictionary: JSONDictionary) } // update isKeyPresent if ignoreNil is true if ignoreNil && currentValue == nil { isKeyPresent = false } return self }
Avatar
ignoreNilがあるのか、それfalseなら行けそうな気がするんですけどね
Avatar
名前的には行けそうだなと僕も思いました
Avatar
先週はお世話になりました。 ご相談させていただいていた件なのですが、アプリ側で対応するよりサーバー側で要素がなければnilにするという処理の方が早かったためをサーバー側で対処することになりました。 せっかくお力お借りしたのに答え出すまでやりきることができずすみませんでした。 次回こそは!と思っておりますので、また顔だした時にお力お借りできましたら幸いです。 何卒宜しくお願いいたします
💪 2
✨ 1
Avatar
がんばって
Avatar
ありがとうございます!!
Avatar
https://stackoverflow.com/questions/48478143/app-submission-failed-1-corrupted-binaries-non-public-api-usage-and-no-additi/48512154
Non-public API usage: The app contains one or more corrupted binaries. Rebuild the app and resubmit
1月26日以降、このエラーに遭遇するようになった方いますか?
I’ve been submitting my app to the App Store for test flight and after build 11, I’ve been getting failures via email from Apple: Non-public API usage: The app contains one or more corrupted binar...
7:11 AM
いろんなワークアラウンドが提示されていて、結局なにをどうすればいいのか分からず
👀 1
7:13 AM
(遭遇してない方は遭遇してないリアクション絵文字もらえると、ありがたいです!)
Avatar
どうやらウチの場合はbitcodeの有無が効いていたようです
7:59 AM
ちょうど運よく(&珍しく?)、bitcode有効にできるのに無効だったアプリを1月24日にTestFlightしたときは成功していて、おなじコミットで今日rebuildすると Non-public API usage で、bitcode有効にすると通りました
8:04 AM
アナウンス出てないと思うのですこし様子見してみます...
Avatar
extension<T: SomeProtocol> Array where Element == T みたいなジェネリックなエクステンションってまだできないですよね?
Avatar
@Taketo Sano できないです。
7:00 AM
これは Swift に欠けてる言語機能なので早くできるようになってほしいですね。 Parameterized Extensions はまだですが、まずは 4.1 から Conditional Conformance が使えるようになります。
Avatar
ありがとうございます!Conditional Conformance は心から心待ちにしてます😸
7:58 AM
4.1 っていつ出るか明らかになってます?
Avatar
春だと思ってましたが、今ぱっと探した限りでは公式情報は↓しか見つけられませんでした。
Swift 4.1 is intended to be released in the first half of 2018.
https://swift.org/blog/swift-4-1-release-process/
This post describes the goals, release process, and estimated schedule for Swift 4.1.
Avatar
norio_nomura 2/12/2018 8:31 AM
Xcode 9.3と同時だろうから3月?
👀 2
Avatar
楽しみですね 👺
Avatar
Read a free sample or buy The Swift Programming Language (Swift 4.1 beta) by Apple Inc.. You can read this book with iBooks on your iPhone, iPad, iPod touch, or Mac.
6:00 AM
4.1の本はあるのか。betaだけど。
Avatar
もう更新されてたのか。 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/index.html Revisionはここ。 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/RevisionHistory.html#//apple_ref/doc/uid/TP40014097-CH40-ID459 - Added the Conditionally Conforming to a Protocol section with information about conditional protocol conformance. - Added information about recursive protocol constraints to the Using a Protocol in Its Associated Type’s Constraints section. - Added information about the canImport() and targetEnvironment() platform conditions to Conditional Compilation Block.
Avatar
そういえば、「空」でないことをどう表現するんだ?と思いまして、型で表現できねーかとか考えてまして、
Avatar
それで、まぁPhantom Typeが書ければいいかーってなってまして、SwiftでPhantom Typeって例ありますかね??
Avatar
omochimetaru 2/19/2018 9:38 AM

はじめに

Swiftの界隈ではPhantom Type(幽霊型)という、型に状態をエンコードする手法がある。この記事ではまずこのPhantom Typeを用いた手法について解説し、この方法よりも著者がよいと思うLIO...
Avatar
社内の「Scala 勉強会」で Phantom Type (幽霊型) という厨二心をくすぐる感じのデザインパターンを教えてもらったので、同じことを Swift でもやってみました。 インスタンスの状態を変数ではなく **型パ...
Avatar
Kishikawa Katsumi 2/19/2018 9:39 AM
NotAutoLayout is a framework to help you layout subviews without Auto Layout constraints.
SpreadsheetView - Full configurable spreadsheet view user interfaces for iOS applications. With this framework, you can easily create complex layouts like schedule, gantt chart or timetable as if y...
Avatar
Kishikawa Katsumi 2/19/2018 9:42 AM
数個以上の複数の状態の組み合わせがあるけど、なってはいけない状態の組み合わせがある、みたいなときに状態を型にエンコードすると、おかしな状態を排除できるので、そういう場合に使っています。
Avatar
おお、参考になります。
9:46 AM
RxSwiftでSingleとMayBeがファントムタイプになってます。
9:46 AM
Single(1)をfilterするとMayBe(1 or 0)になる。これってまさに「空」のエンコーディングの実用例かも。
Avatar
あ、NotAutoLayout紹介されて光栄です☺
Avatar
Kishikawa Katsumi 2/19/2018 10:26 AM
NotAutoLayoutは中途半端な制約にならないように使われてましたね。片方だけしか制約がないといった不完全な状態の時は違う型を返して、制約が全部ついたら初めてコンパイルが通るという感じ。
☺ 1
Avatar
ですです
Avatar
omochimetaru 2/22/2018 6:26 AM
|[ A ] [ B ]| | [ C ]| こういう感じで、BとCがそれぞれ可変サイズだとして、Aの右端が、BかCのどちらかより長い方の左端にくっつく ってAutoLayoutでどうやって書くんです? (edited)
Avatar
まかせて
Avatar
omochimetaru 2/22/2018 6:28 AM
A <= B , A <= C って不等号条件を2つ並べるところまでは思いついたけど、それだと、Aの幅にまだ自由度があって駄目だ
Avatar
BとCを詰めたViewを一個作って
6:30 AM
priority 750の [B&C].width == [B].width, [B&C].width == [C].width priority 1000の [B&C].width >= [B].width, [B&C].width >= [C].width
Avatar
omochimetaru 2/22/2018 6:32 AM
それだと
Avatar
後は[A]と[B&C]の隙間をよしなに設定すればオッケーだよ。Aの中身も幅が可変ならAのContentなんちゃらPriority下げればいい
Avatar
omochimetaru 2/22/2018 6:32 AM
[B&C] が B よりも C よりも長い可能性を許さない?
6:32 AM
あ〜端っこくっつければそれは無いのか。
6:33 AM
ん、でも端っこくっつけるのも1000だと矛盾するか
Avatar
てかB&Cをstackviewで作れば
6:33 AM
よしなにいけると思うけど
Avatar
omochimetaru 2/22/2018 6:34 AM
B.width = 100 ; C.width = 200; のとき、 B&C.width = 300 でもprio1000の解は満たす(曖昧になってる
6:34 AM
stackviewは独自ロジックも持ってるから、AutoLayoutだけでできるのか興味ある
Avatar
B&CはBとCからしか決まらないから、300はあり得ない
Avatar
omochimetaru 2/22/2018 6:34 AM
そこは、Edgeをくっつけるってことだよね?
6:35 AM
そのEdge吸着の優先度はいくつ?
6:35 AM
両方1000にするとやっぱり駄目な気が prio750と共存できる方だけが残るのか・・・?
Avatar
上と左をはっつけて、高さと幅を計算するようにしてだな
6:37 AM
grater thanとweak equalで最大値をとるテクを使う
Avatar
|[A]-(>=10@1000)-[B]| |[A]-(>=10@1000)-[C]| |[A]-(0@750)-| ではだめですかね? (edited)
Avatar
この場合高さが可変じゃないなら、上左下貼り付けでいい
Avatar
omochimetaru 2/22/2018 6:39 AM
↑0@750が、「目一杯広がる」を意味しないと思ってて。
Avatar
ああ、高さは普通でよかった
Avatar
omochimetaru 2/22/2018 6:39 AM
「ルール3つで矛盾が起きたら750のルールが取り除かれる」だけですよね
6:40 AM
そうすると不等号2つだけが残るけど、不等号制約は別に、 >= の 「境界値に近づく」ように制約解決する方向付けの作用って無いんじゃないかと(あるのかな
6:41 AM
とりあえず試してみます
Avatar
「取り除かれる」なんでしたっけ。それを知らなかったです。
Avatar
omochimetaru 2/22/2018 6:47 AM
Even if an optional constraint cannot be satisfied, it can still influence the layout. If there is any ambiguity in the layout after skipping the constraint, the system selects the solution that comes closest to the constraint. In this way, unsatisfied optional constraints act as a force pulling views towards them.
6:48 AM
これか。例えスキップされた制約であっても、レイアウトが曖昧な場合にはできるだけ近づくように影響を与える。
👍 2
6:49 AM
rintaroさんの3条件のやつでうまくいきました、警告も無し
Avatar
おー
Avatar
omochimetaru 2/22/2018 6:49 AM
B&Cの包みView無しでできたわ。
6:49 AM
そうすると、iOSDCでinamyさんが作ってたやつは (edited)
6:50 AM
ここらへんの機能が無かったりしそうだ (edited)
6:50 AM
Cassowary - An incremental linear constraint-solving algorithm (Auto Layout) in Swift.
6:50 AM
priorityあるしあるのかな
6:52 AM
あ〜、priority1000の不等式条件は前提条件とした上で、750の等式条件を、誤差最小化問題として解けばこういう動きになるのか。
Avatar
要件勘違いしてた
6:54 AM
勝手にBとCはそれぞれ大きい方にサイズを合わせるみたいなのが脳内補完されていたw
6:54 AM
(よくあるので)
Avatar
omochimetaru 2/22/2018 6:54 AM
ああ、BとCは完全に独立ににょきにょきするイメージ。
Avatar
りんたろ先生の、BとCの大きい方が入れ替わると
6:57 AM
ニョッキキしてる片方のサイズがおかしくなる気が
Avatar
omochimetaru 2/22/2018 6:57 AM
BとCの大きい方を入れ替えてもちゃんと解決されたよ。
Avatar
B, C の width の制約次第だと思いますよ。
Avatar
omochimetaru 2/22/2018 6:57 AM
ああ、うん、BとCの幅は別途の事情で決まるっていう想定。
6:58 AM
BとCが何かしか決まってて、その上でAをどちらかにくっつける。
Avatar
B, C の width が何らか priority 1000 で決まれば破綻はしないはず。
Avatar
いけたっぽい
7:01 AM
最大値と合わせる~みたいな話は結構Autolayoutであるので
7:01 AM
スッと設定する方法が欲しい
7:03 AM
7:03 AM
逆におもちの本当にやりたかったことはStackViewだとできなさそう?
Avatar
omochimetaru 2/22/2018 7:04 AM
StackViewの場合、StackViewに縦にBとCを並べてやれば、StackViewの幅はBとCのでかい方に・・・
7:04 AM
StackViewの幅をBとCのでかい方に合わせる方法が無い??
Avatar
StackView の width 制約明示しなければ自動的にそうなりませんか?
Avatar
なる、ついでに中身は広がる
Avatar
コードレイアウトなら blue.right = max(stack.left, long.left, greater.left, long2.left) 的な感じで書けそう (edited)
Avatar
omochimetaru 2/22/2018 7:09 AM
そうなんですよね。 https://github.com/robb/Cartography ↑いまこれ使ってるんだけど、 max 関数をこういうDSL上に導入して
Cartography - A declarative Auto Layout DSL for Swift 📱📐
7:09 AM
blue.right = max(stack.left, long.left, greater.left, long2.left) ってかいたらそのまんまやりたいことがAutoLayout制約としてセットアップされたら一番嬉しい
Avatar
AutoLayoutが嬉しいのはコンテンツが動的に書き換わってレイアウト計算が自動で走るところなのだけど
7:10 AM
今日ではコンテンツ書き換わるの川で表現してるなら、Layout計算に流せばまあ動くし…というのもあって実際はそこまで優位ポイントではなくなってきてる可能性がある (edited)
Avatar
コードでも layoutSubviews() の中に書いとけばあとは自動でやってくれるじゃん?
7:11 AM
UIViewのサブクラスやらなきゃいけないけど
Avatar
そこがネックなんですよね~
Avatar
omochimetaru 2/22/2018 7:11 AM
layoutSubviews、びみょ〜な実行順の問題とかでハマるからできれば避けたい
Avatar
実行順番ってのは親ビューのlayoutSubviewsと子ビューのlayoutSubviewsの実行順番のこと?
Avatar
omochimetaru 2/22/2018 7:12 AM
それとか、 VC.viewDidLayoutSubviewsとか、viewDidAppearとか。
7:13 AM
あとなんかlayoutSubviewsの処理がレイアウトを発火しちゃって無限ループしたり。
Avatar
自分は基本UIViewのサブクラス大体自分でやってるからviewDidLayoutSubviews内にさらに別のレイアウト作業やるとか基本ないですね 🤔
Avatar
omochimetaru 2/22/2018 7:14 AM
SO見てると「最初にlayoutIfNeed呼べば直る」とか書いてあったりしてとりあえず書いたら直ったり・・・
Avatar
Kishikawa Katsumi 2/22/2018 7:14 AM
最大値に合わせるっていう場面は私もけっこうあって、モデル側で最大値はこれで持ってるのはこいつだっていうのを取得するやつを作った方がだいたいスッキリするんじゃないかと思っています。
Avatar
layoutSubviewsの処理がレイアウトを発火しちゃって無限ループしたり。
それlayoutSubviewsの中に自分のサイズとか自分の親のサイズとかさえ触らなければ基本ないはずじゃん?
Avatar
Kishikawa Katsumi 2/22/2018 7:14 AM
レイアウト側では単にそいつに合わせる。
Avatar
フォントサイズの違う二つのラベルで大きいのはどっち?(ドン)みたいなやつだと悲しみが
Avatar
Kishikawa Katsumi 2/22/2018 7:17 AM
ああ、それは面倒ですね。そういうのは考えてなかったな。。。
7:18 AM
AutoLayoutで複数のビューと1つのビューで制約が付けられたら、と思うことはあるけど、今でも複雑なのに手に負えなくなるかな?
Avatar
両方の label.sizeThatFits(label.size) を取れば大きい方はわかる…はず
Avatar
大凡StackViewでなんとかするのが思考停止で解決できて手っ取り早くてラクのイメージありますね
Avatar
+1
Avatar
UILabelのsizeはフォント次第でバグるの、マジで許さないからな
Avatar
AutoLayoutで複数のビューと1つのビューで制約が付けられたら、と思うことはあるけど、今でも複雑なのに手に負えなくなるかな?
いなみさん(ry
7:19 AM
ああフォントによってバグるのは確かによくある
Avatar
Kishikawa Katsumi 2/22/2018 7:23 AM
どちらかというとフォントの問題であって、UILabelやNSStringのメソッドは正しい値を返すはず。
7:24 AM
UILabelはフォントがはみ出すのとかは考慮してくれないけど、それはまた別として、、、 (edited)
7:24 AM
挙動は一貫していたはず。
Avatar
フォントをきちんと考慮したサイズを取りたいならやはりCoreTextとか触るしかないですかね… 🤔
Avatar
Kishikawa Katsumi 2/22/2018 7:26 AM
TextKit以降(iOS 6-8のどこか、忘れた)はCoreTextを直接触る必要はほとんどないです。Stringその他のメソッドで同じ値が取れるので、メソッドの仕様とパラメータの意味を理解して正しく使っていれば、よほどのエッジケースを除いて、意図した通りに合わせることは可能。 (edited)
🙇 1
Avatar
TextKitの存在、完璧に忘れていた 😇
Avatar
UILabelが
7:35 AM
なんだっけ、frameの外のレンダを許可するOp入れてもその通りに動かないのが一番悪い
7:35 AM
それさえできれば、多少計算がおかしいのはなんとかカバーできるんですけどね。
7:35 AM
clipsToBoundsかlayerのmasksToBounds?この辺。
Avatar
Kishikawa Katsumi 2/22/2018 7:45 AM
UILabelのサイズはフォント全体のメトリクスから決まるので(どこからどこまでの間かは忘れた)それよりもはみ出るようなフォントの場合(極端に斜体のフォントとか)は実際に文字の組み合わせがレンダリングするサイズに合わせてラベルの大きさを調整する方がいいと思います。
7:46 AM
自身のフレームの外に描画させるのは切れないというだけで、コントロールするのは無理なので。
Avatar
Codableなclassのプロパティに初期値付きletを使うとDecoder.decodeで読むデータにそのプロパティに対応するものがあってもなくても初期値が入る(例外も出ない)、という挙動を見つけたのですが、この挙動ってどうなんでしょうか 🤔
10:05 PM
10:07 PM
import Foundation class Hoge: Codable { let fuga = "default value" private(set) var privateSet = "default value" } let decoder = JSONDecoder() decoder.decode(Hoge.self, from: "{\"fuga\": \"json value\", \"privateSet\": \"json value\"}".data(using: .utf8)!)
10:10 PM
とりあえずprivate(set) varを使えば想定する動きをすることがわかったのでそちらを使っているのですが、初期値なしletは正常に動作するので、そちらと混ぜるとコードがデコボコして見栄えがよろしくないことになってしまってさらに 🤔 しています
Avatar
Kishikawa Katsumi 2/22/2018 10:19 PM
@rinsuki それはデフォルト値のせいではなくて、letのためですね。letでデフォルト値が与えられているのでそれ以上代入することができないのです。
10:20 PM
varにして試してみてください。たぶん、init(decoder:)を書いてみるとわかると思います。
Avatar
@Kishikawa Katsumi なるほど、letで初期値を与えるとコンストラクタでもその初期値が変更できないんですね...。ありがとうございます。 余談ですが、この書き方をしてしまったときにWarningやErrorを出す方法ってないでしょうか。鳥頭なので、できれば機械に指摘してもらいたいのですが...。
Avatar
Kishikawa Katsumi 2/22/2018 10:54 PM
この書き方をしてしまったときにWarningやErrorを出す方法
10:54 PM
たぶん無いと思います。
10:54 PM
私もlet x = "..."とした後にやっぱり外から与えられるようにしようとinitを書いた時点で、コンパイルエラーということがよくあります。
Avatar
なるほど、ありがとうございます。
Avatar
swift のランタイム時の関数呼び出しの上限数って増やせますか?
Avatar
スタックの容量を増やしたいという意味ですか?
Avatar
はい。
8:32 AM
僕は実際には試したことないです。
Avatar
Add -Wl,-stack_size,1000000 to the Other Linker Flags field of the Build Styles pane.
これですね👍 ありがとうございます!
8:37 AM
ld: -stack_size option can only be used when linking a main executable clang: error: linker command failed with exit code 1 (use -v to see invocation) なるものが出てしまった…😯 もう少し調べます🙇
Avatar
omochimetaru 2/26/2018 8:38 AM
main executableというのはアプリ本体のことですよ ライブラリのコンパイルに指定しているように思います
Avatar
ライブラリのテストに指定したいんですが、TestTarget の方に指定したら上のエラーになりました…😥
Avatar
Kishikawa Katsumi 2/26/2018 8:47 AM
テストバンドルはまた特殊で、ホストアプリを作ってそれを使うようにして、ホストアプリに指定したらどうなります?
Avatar
omochimetaru 2/26/2018 8:48 AM
なるほど。ライブラリのテストの場合ってメインはどうするんだろう・・・、わからないです。。 @Kishikawa Katsumi の言うように、アプリ+アプリテストの形ならできそう
Avatar
Kishikawa Katsumi 2/26/2018 8:51 AM
8:52 AM
^ のHost Applicationてとこ。TestHost.appは何の実装もないAppDelegateだけの空っぽのアプリで構わないです。テスト中に生きてさえいればいい。
Avatar
おぉ、なるほど!ありがとうございます😃
Avatar
Kishikawa Katsumi 2/26/2018 8:53 AM
swift testの場合はわからないです。HOST_APPっていう環境変数がきくかもしれない(たぶんきかない)。 (edited)
8:55 AM
KeychainAccessの場合はKeychain APIはデバイスとシミュレータで挙動が異なるのでデバイスでテストしたい、Frameworkはデフォルトでロジックテストなのでデバイスでは動かない、というのと、キーチェーンの共有などをテストするにはProvisioning ProfileやEntitlementsが必要でそれはテストバンドルでは指定できない、という問題を解決するためにホストアプリを使用したテストを行っています。
Avatar
Framework を TimeProfile に繋いでデバッグできるようにするために別の Workspace を作って command-line アプリを置いていたのですが、project 設定を色々変えた影響からか動作がおかしくなってしまいました😥 objc[29923]: Class _TtC8Dispatch16DispatchWorkItem is implemented in both /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftDispatch.dylib (0x1018f7530) and /Users/taketo1024/Library/Developer/Xcode/DerivedData/TimeProfile-aryrvmqtlkmqgqbautymimyzbktk/Build/Products/Debug/TimeProfile (0x1005c6820). One of the two will be used. Which one is undefined. こういうのがたくさん出て実行はできるのですが print の結果がおかしくなります😥 workspace は SwiftyAlgebra/Workspace/Sandbox/TimeProfile/ 下にあります。 https://github.com/taketo1024/SwiftyAlgebra/tree/TimeProfile (edited)
Contribute to SwiftyAlgebra development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 3/12/2018 10:41 AM
@Taketo Sano Command Line Toolはバンドルを持てないので、DynamicFrameworkを自身に持つことはできないところを、Run Pathを変更してリンクできるようにしているという状況ですね。でSwift Standard LibraryがSwiftyAlgebraとTimeProfileのそれぞれにStatic LinkしているのでDuplicatedということです。
😃 1
10:42 AM
とりあえず問題の切り分けのために TimeProfileターゲットでSWIFT_FORCE_DYNAMIC_LINK_STDLIB=YESSWIFT_FORCE_STATIC_LINK_STDLIB=NOをUser Defined Settingで追加してみてください。
10:43 AM
で、プロファイルを取りたいということで配布したいというわけじゃなさそうなので上記の方法でもまあいいと思うんですけど、基本的にはCommand Line ToolじゃなくてMac AppにしてそれにDynamicLinkする形で使う方が素直な挙動になります。
Avatar
なるほど、やってみます、ありがとうございます🙇
10:52 AM
ちなみに MacApp にすれば Workspace を別にする必要もないんでしょうか?
Avatar
Kishikawa Katsumi 3/12/2018 10:56 AM
Workspace を別にするっていうのはどっちにしろ必要なさそうですけど、何が問題でそうしたんですか?Workspaceも場合によっては不要です。少し上に書いてあるようなホストAppを使ってUnitTestがしたいというくらいの用途なら同じプロジェクトでターゲットを増やすだけでもOKです。
10:57 AM
デモアプリとかPlaygroundを用意する場合はWorkspaceあった方がいいです。
Avatar
おぉなるほど😵
10:58 AM
あ、はい、Playground を置くために workspace にしています。
Avatar
Kishikawa Katsumi 3/12/2018 10:58 AM
でも別に複数のWorkspaceを使い分ける必要はないと思います。
10:59 AM
Workspace SwiftAlgebra.xcproj HostApp Playground.playground DemoApp.xcproj (edited)
10:59 AM
^ こんな感じのでいいと思いますよ。
Avatar
了解です、やってみます😄
Avatar
Kishikawa Katsumi 3/12/2018 11:01 AM
上の図でいうと、Playground.playgroundとDemoApp.xcprojは単体で実行するものなので独立させてWorkspaceに入れる、HostAppはユニットテストの一部みたいなものでユーザーは意識する必要ないので、本体プロジェクトに入れてしまえ、という意図があります。
Avatar
おぉ、 UserSetting を変更する方法で動きました、ありがとうございます!!!
Avatar
Kishikawa Katsumi 3/12/2018 3:13 PM
上の説明、正しくないですね。正確にはCommand Line Toolはバンドルを持てないのでSwiftの「標準ライブラリ」をバンドルに含むことができなくて、SwiftyAlgebraが標準ライブラリを参照しようとして見つからないのが最初のエラー。rpathをXcodeの/usr/libに向けてSwiftyAlgebraが標準ライブラリを見つけられるようにしたのが佐野さんの対処で、それだと動くけどCommand Line Toolに静的リンクされている標準ライブラリと衝突するのでそのエラーのログが出てしまうという状態(移植性も失われる)。
Avatar
Kishikawa Katsumi 3/13/2018 3:56 AM
最近関わりを持ったプロジェクトで、Model、ViewModel、ViewControllerがあり、それぞれModelの変更をViewModelが、ViewModelの変更をViewControllerが監視していて、ReactiveCocoaによってバインディングされています。 ViewModelの変更によって呼ばれるメソッドがちょっと長くて、 func updateTableView() { ... tableView.reloadData() // 1 ... tableView.scrollTo(latestIndexPath) // 2 ... } のようになっています。
3:56 AM
このとき、(おそらく)1と2の間にModelが更新されて、2のメソッド呼び出しでIndexPathが合わなくてクラッシュするということが起こっています。 (おそらく、と書いたのは再現できたわけじゃないけど、コードを見る限りそうとしか思えない。)
3:56 AM
updateTableView()はメインスレッドで呼ばれるけど、Modelの変更はバックグラウンドスレッドで頻繁に変更される。
3:57 AM
私はViewModelをイミュータブルにして、変更通知と変更通知の間で変わらないようにすべし(変更通知のたびにイミュータブルなViewModelを生成して渡す)、とアドバイスしたのですが、他に良い方法ありますか?
Avatar
omochimetaru 3/13/2018 4:00 AM
とりあえずスレッド問題なら Model <- ViewModel の購読を .observeOn(MainScheduler.instance) はさんで、メインスレでしか事が起こらないようにすれば問題は解決しませんか?
Avatar
RACでtableViewは沼だなぁ、、
Avatar
omochimetaru 3/13/2018 4:01 AM
1と2の間に別スレッドからindexPathがずれてるとするとそもそもUIKit系に非メインスレから干渉してるってことでそれ自体規約違反な気がしますが何か勘違いしてるかな
Avatar
単純に、tableView delegateが取りに行くタイミングと、indexPathの参照のタイミングの間に
4:02 AM
dataSourceが変更されてるという話で
Avatar
Kishikawa Katsumi 3/13/2018 4:02 AM
updateTableViewはメインスレッドでしか動かないんですけど、そこから参照しているViewModel(Modelは切れてるはず)がどんどん更新されているという。
Avatar
dataSourceの変更はそれだけで毎回reloadするようにして、そのほかの処理とは分離するのが賢そうです (edited)
Avatar
Kishikawa Katsumi 3/13/2018 4:04 AM
で、それでいうとModel->ViewModel
4:05 AM
間をメインスレッドでしか呼ばれないようにするというのはそれはアリな気がします。
Avatar
omochimetaru 3/13/2018 4:05 AM
似たようなシチュエーションで、アーキテクチャは昔ながらの方法だったけど、TableViewのいろんなタイミング問題が出て、最後のスクロールする処理を、なんとかフラグとか立てて後回しにするようにしたりしたことはありますね
Avatar
Kishikawa Katsumi 3/13/2018 4:05 AM
ただまあなんとなくそれは直し方が一時しのぎ的かなあという。
4:07 AM
全体的にこのプロジェクト、マルチスレッド系のよくわからないバグをロックを取るなどの一時的な対処で複雑にしてる感があって、それよりはイミュータブルを積極的に使った方が根本的に簡単になるんじゃないか、と考えています。
Avatar
あるある
4:08 AM
わかるわかる
Avatar
Kishikawa Katsumi 3/13/2018 4:10 AM
良い例がないかと思ってKickstarterのOSS版を調べると
4:11 AM
https://github.com/kickstarter/ios-oss/blob/master/Kickstarter-iOS/Views/Controllers/ActivitiesViewController.swift#L80-L85 ViewModelの更新ではDataSourceというまた別のデータを更新していて、tableView.reload()はその後でいつ呼んでもいい感じになっていたので、こういう方式が良いんじゃないかと。
ios-oss - Kickstarter for iOS. Bring new ideas to life, anywhere.
Avatar
reactive+table/collection viewはとにかく難易度が高くて
4:12 AM
基本的にはまずtable/collection使わなくて出来ないかを考えるべきだと思っています
Avatar
Kishikawa Katsumi 3/13/2018 4:13 AM
一般的なiOSアプリでUITableViewを使わないのは難しくないですか。
Avatar
無限長データはもうどうしようもないので、そういうのが出てきてから
4:14 AM
使うべきところと使うべきでないところがあるので
Avatar
Kishikawa Katsumi 3/13/2018 4:15 AM
Reactiveと組み合わせると難しいというのは同意します。 少しそこから議論を進めて、
4:16 AM
UITable/CollectionViewの場合はViewModelとUIコンポーネントを直接バインディングするのは問題があることが多い、ということじゃないですかね。
Avatar
そうですね
Avatar
Kishikawa Katsumi 3/13/2018 4:16 AM
ビューと直接バインディングするんじゃなくてデータソースとバインディングするのがベターなのでは。
Avatar
そもそもcellの生成時しかアクセスが保証できないものなので
4:17 AM
そこの性質を間違えると大変なことになります
Avatar
omochimetaru 3/13/2018 4:17 AM
綺麗にやるんだったら、 scrollToの宛先をViewModelのパラメータとして常に持つ?
4:18 AM
その宛先もビュー側のインデックスパスじゃなくて、エントリを特定できるモデル側のキーで持つ。
Avatar
因みにRxSwiftはまさしく、dataSourceとバインディングする仕組みになっていて
4:19 AM
RxDataSourcesは良く出来ています
Avatar
Kishikawa Katsumi 3/13/2018 4:25 AM
@omochimetaru scrollTo()のタイミングで補正するってことですかね。
Avatar
omochimetaru 3/13/2018 4:34 AM
岸川さんの言う通り、ViewModelをイミュータブルにして、どんどん新しい塊で流すようにするなら、 その情報だけからビューの命令を発行する必要があるので、 scrollToの宛先をそこでビューモデルのプロパティの一つとして持つ必要があると思ったんですが
4:34 AM
それだったらリストの要素も塊に入ってるから、やっぱりインデックスで持てばよいですね。
4:37 AM
その、テーブルビューと対応したデータソースを持つってパターンを想像してます UITableViewへの実際の操作は必ずそれを経由するようにする
4:37 AM
@tarunon RxDataSourcesでお行儀よくスクロールコントロールするときはどうなるの?
Avatar
indexPath→モデルの取得のみ出来る構造になっていて、あんまりそういうことをするようには出来ていないように感じるなぁ
5:17 AM
dataSource.sectionModelsに格納されているモデル群があるから
5:17 AM
必要があるならExtension生やして出来るようにする感じだと思う
5:17 AM
中身がEquatableなら処理追加してモデルからindexPath引く実装とかは作れる
Avatar
omochimetaru 3/13/2018 5:18 AM
なるほど
5:20 AM
この話しばらく考えてたんだけど、 UITableViewからすると、reloadData()とscrollTo()がメインスレッドから立て続けに呼ばれた場合、 tableView.dataSourceのデリゲートメソッドを呼び出してセルを引っ張ったり、 内部でrowからscroll座標を計算したりする一連の手続きの間に、 tableView.dataSourceのデータは変化しちゃいけない ってのがまずある話よね
Avatar
例えばTwitterのTLでセルのモデルとしてTweetとクリックするとあいだのツイートを読み込むアレとがあったとして、 アレまでスクロールする機能を作りたいなら、アレのindexPathをdataSourceに問い合わせてあればスクロールする(その間ロックする)みたいな機構を作る
5:21 AM
まあ結構泥臭くなると思うよ
Avatar
Kishikawa Katsumi 3/13/2018 5:21 AM
そうですね。言い換えるとdataSourceに変更があったらreloadData()(またはinsert/removeRows)を呼んで同期しなければならない。 (edited)
👀 1
Avatar
omochimetaru 3/13/2018 5:22 AM
でも今は、dataSourceとして見てるオブジェクトが、VCなのかproxyなのかわからんけど、とにかく、その先のViewModelオブジェクトのプロパティを参照する形で実現されていて、 その一連のタイムシーケンスの間に変更が起きてしまう
5:22 AM
まず第一にそういう割り込み変更が起こらないアーキテクチャにはなっている必要があって(そうじゃないと個別にケアしないといけなくなる)
5:25 AM
そうするとDataSourceオブジェクトを一個定義して、そこに一任するのは筋が良いと思う。
Avatar
Kishikawa Katsumi 3/13/2018 6:53 AM
私の中では以前より整理できました。どうもありがとうございます。 リアクティブプログラミングとイミュータブルはセットだと考えてるんですけどあまりそれを示した記事が見つからなくて、どう話したものか、
6:53 AM
と思ってまして。
Avatar
条件付き extension でより強い型の場合にオーバーライドしたいケースが割とあるんですが、こういうのってできないんでしょうか。 例えば行列式の計算で、一般の環では置換を使って定義しておいて、体の場合は掃き出しを使う、というようにより強い型で実装をオーバーライドしたいケースがあります。
8:53 AM
(あれ、もしかして普通にできる?)
Avatar
protocol extensionだと、三角継承問題が発生する(superが何かわからない)のもあって今はできないです。protocol extensionのfuncのimplを、global funcとして切り出せば、やりたいことは出来ると思います。あくまでextensionはエイリアスとして働く、みたいな感じ。
11:33 AM
「今は」なのかそもそもそういう指針なのかはどっちだったかな、
Avatar
なるほど、struct ではできて protocol ではできないんですね、ありがとうございます。
4:24 PM
protocol extensionのfuncのimplを、global funcとして切り出せば
おぉ、やってみます😺
Avatar
protocol A where Y.X == Self, Y.Z == Z { // Redundant same-type constraint 'Self.Z' == 'Self.Y.Z' associatedtype Y: B associatedtype Z } protocol B where X.Y == Self, X.Z == Z { // Redundant same-type constraint 'Self.Z' == 'Self.X.Z' associatedtype X: A associatedtype Z } struct AA: A { typealias Y = BB typealias Z = Int } struct BB: B { typealias X = AA typealias Z = String // !? } このコードが通ってしまうんですが(本来は BB.Z == AA.Z == Int でなければいけない)protocol の associatedType の相互参照周りはまだバグバグしいんでしょうか? (edited)
Avatar
しかも B, BB のペアを別ファイルに置くとコンパイルできない😨
Avatar
バグってますねー。ABAABB で循環しているので、循環まわりはまだまだ安定していない印象
7:39 AM
一応 4.1 だと
7:39 AM
test.swift:11:8: error: 'A' requires the types 'AA.Z' (aka 'Int') and 'BB.Z' (aka 'String') be equivalent struct AA: A { ^ test.swift:11:8: note: requirement specified as 'Self.Z' == 'Self.Y.Z' [with Self = AA] struct AA: A { ^
Avatar
@Taketo Sano プレリリースの Swift を手軽に試すなら↓便利ですよ。現状なら、 Languages から Swift 選んで Swift HEAD 4.2-dev (LLVM ... を選択です。 https://wandbox.org/ (edited)
🙏 1
Avatar
おぉ、ありがとうございます!
Avatar
wandboxってメンテされてない印象がある。
Avatar
Xcode 9.2使用中なのですが、コメントに書いたクラス名にジャンプ出来るようにする書き方ってありますか?
Avatar
目的としてはViewModelとViewControllerを簡単に行き来したかったのですが
8:16 AM
takasek/XCJumpToTests: the Xcode Source Editor Extension / AppleScript to jump files of Implementation⇄Tests https://github.com/takasek/XCJumpToTests こちらのAppleScriptを改変したら目的は達成出来ましたm( )m (edited)
XCJumpToTests - the Xcode Source Editor Extension / AppleScript to jump files of Implementation⇄Tests
🙌 3
👏 2
swift 1
Avatar
ご活用いただきありがとうございます!
🙏 1
Avatar
@takasek おお、こちらにいらっしゃるとは!かなり快適になりました!ありがとうございます〜🙏
😉 1
Avatar
protocol ViewProtocol: class { associatedtype Presenter: PresenterProtocol var presenter: Presenter! { get } } protocol PresenterProtocol: class { associatedtype View: ViewProtocol weak var view: View? { get } } 1ファイルにこれ書くとbuild通るんですけど、それぞれのprotocolを別のファイルに書くとbuild通らないのがよくわからないんですがどうしてなんでしょう? (edited)
Avatar
型の相互参照?
9:07 AM
型Aを書いたファイルAをビルドするのに型Bを定義したファイルBが必要、でも型Bを定義したファイルBをビルドするのに型Aを定義したファイルAが必要的な?
Avatar
あーそうか😩
Avatar
Kishikawa Katsumi 3/28/2018 9:09 AM
私の環境(Xcode 9.2、適当なiOSプロジェクト)では別のファイルにプロトコルを書いてもビルドできましたね。
9:10 AM
念のため、プロトコルを実装するクラスも別のファイルに書いてみましたけどエラーは起こらなかったです。
Avatar
ありゃ?同じくXcode9.2でSwift4.0で新規プロジェクトにさっきのコードを別ファイルで書いてエラーになってるんですよね、自分の環境は
Avatar
試しにBuild Phaseでファイルのビルド順番を変えてみたらどうでしょう?
Avatar
順番変えてもエラーのままですね
Avatar
Kishikawa Katsumi 3/28/2018 9:14 AM
私の方は変わらずエラーなしです。ついでにDebug/Release構成も切り替えて試しました。
Avatar
Cross-reference to module 'Protocol'
こうあるから出来なそう
9:15 AM
@Kishikawa Katsumi クリーンしてビルドしなおしたら通らなくなったりしませんか?
Avatar
Kishikawa Katsumi 3/28/2018 9:15 AM
すみません。ツールチェーンが4.1でした😅
Avatar
Avatar
4.1ならいける!ということ? (edited)
Avatar
なんでいけるんだろ
Avatar
Kishikawa Katsumi 3/28/2018 9:16 AM
4.1なら通りますね。
Avatar
そういうもん?
Avatar
omochimetaru 3/28/2018 9:16 AM
バグがなおったからでは。
Avatar
そうか。
Avatar
なるほど
Avatar
なるほど
Avatar
omochimetaru 3/28/2018 9:17 AM
コンパイラがクラッシュするのは単純にコンパイラのバグで
9:17 AM
ただそれが直る過程で、できるようになるものと、できないようになるものは、ある
Avatar
ありがとうございます🙇
Avatar
protocol A where Y.X == Self, Y.Z == Z { // Redundant same-type constraint 'Self.Z' == 'Self.Y.Z' associatedtype Y: B associatedtype Z } protocol B where X.Y == Self, X.Z == Z { // Redundant same-type constraint 'Self.Z' == 'Self.X.Z' associatedtype X: A associatedtype Z } struct AA: A { typealias Y = BB typealias Z = Int } struct BB: B { typealias X = AA typealias Z = String // !? } ↑こちら Xcode 9.3 beta で試してみたらちゃんとエラーになりました👍
Avatar
Taketo Sano 4/1/2018 1:13 PM
protocol A, B で同じメソッド名のデフォルト実装があって、それを conform する struct X がどっちのものを使うかを指定するのってできないですよね?(明示的にオーバーライドしないといけない?)
1:13 PM
protocol は associatedtype つきのものです。
Avatar
出来ないですね、extensionの実装は、条件が厳しいものが優先され、同じである場合はambiguousで失敗します
Avatar
Taketo Sano 4/1/2018 1:14 PM
了解です、ありがとうございます🙏
Avatar
Swift repl で変数に値を代入するとき、複雑な struct だと中身丸ごとダンプしたような出力がされますが、この表示を抑えたりカスタマイズしたりってできるんでしょうか?(既出でしたらすみません)
Avatar
CustomDebugStringConvertibleとかどうでしょ?できるのかな
Avatar
@swiftbot CustomDebugStringConvertibleでいけるっぽいですね struct A { var name = "a" } print(A()) struct B { var name = "b" } extension B: CustomDebugStringConvertible { var debugDescription: String { return "{\(name)}" } } print(B())
Avatar
swiftbot BOT 4/4/2018 1:05 PM
Swift version 4.1 (swift-4.1-RELEASE)
1:05 PM
A(name: "a") {b}
Avatar
CustomPlaygroundLookableというのもあって、いじって遊んでたけど多分deprecatedになるw(もうなったかな?)
Avatar
CustomDebugStringConvertible とは別に CustomStringConvertible というのもありますので用途によって使い分けてください。
Avatar
Taketo Sano 4/4/2018 2:34 PM
おぉ、CustomDebugStringConvertible ってそのためのものだったのですか…!ありがとうございます🤗
2:36 PM
4> let a = A() a: A = { name = "a" } 5> struct B { 6. var name = "b" 7. } 8. 9. extension B: CustomDebugStringConvertible { 10. 11. var debugDescription: String { 12. return "{\(name)}" 13. } 14. } 15> let b = B() b: B = { name = "b" } あれ、REPL だとやっぱり変わらないような🤔
Avatar
REPLはだめなんですねぇ
Avatar
Taketo Sano 4/4/2018 2:36 PM
あ、そうなんですか😥
Avatar
他に何かないかな
Avatar
Taketo Sano 4/4/2018 2:37 PM
大きめの struct だとドバーッって出て来て困りますよね🎅
Avatar
Kishikawa Katsumi 4/4/2018 3:50 PM
REPLやPlaygroundはMirror使ってるんじゃなかったかな。
Avatar
Kishikawa Katsumi 4/4/2018 3:58 PM
うーん、customMirrorは使われなかったです。。。
Avatar
お手上げ感
Avatar
Taketo Sano 4/4/2018 4:07 PM
When using Swift REPL, every time I assign a value to a variable, it displays a whole dump of the value. I want to suppress this, because when it is an instance of a large struct, it completely blo...
Avatar
:set set print-decls false で行けるそうです😆
👍 6
Avatar
Taketo Sano 4/7/2018 2:12 PM
SwiftyMath というものを作っていて、REPL を使ってインタラクティブに計算を走らすようなことができるようになりました👍
2:14 PM
Windows ユーザにも気軽に使ってもらえるように、Web IF を用意してサーバ側で Swift REPL を動かすというようなことをしてみたいと思うのですが、そういうことは可能なのでしょうか?
Avatar
omochimetaru 4/7/2018 2:14 PM
できると思いますよ
2:14 PM
プロセスを立てて
2:14 PM
stdin/stdout/stderrをストリームとして制御することができるので
2:15 PM
サーバサイドでそういうサービスを回せば。
Avatar
Taketo Sano 4/7/2018 2:15 PM
なるほど!
Avatar
omochimetaru 4/7/2018 2:15 PM
ただswiftbotみたいな一発実行だと
Avatar
Taketo Sano 4/7/2018 2:15 PM
今時のイケてる構成だとどんな風にするのがいいんでしょう?
Avatar
omochimetaru 4/7/2018 2:15 PM
Dockerに閉じ込めてタイムアウトもつけてってやってリソース制限できるけど
2:16 PM
REPLだとプロセスが生きてる必要があるからそこらへんのリソースクォータの制御がどうやるのがいいのかパッと思いつかない・・・
Avatar
Taketo Sano 4/7/2018 2:16 PM
ふむふむ
Avatar
omochimetaru 4/7/2018 2:16 PM
一発実行ならDockerはまさにそういう使い捨ての仮想環境を作って捨てるためのしくみなのでちょうどよいのですけど。
2:17 PM
まーやるとしたらその制御側で、REPLの行の応答にタイムアウト制御するのを自分で書くとかかな・・
Avatar
Taketo Sano 4/7/2018 2:17 PM
今作っているものを、研究室の先生や他大の学生にも使ってもらおうとしているのですが、非エンジニアにとってインストールのハードルがあることや windows しかもってなかったりということがあるので、web で動かしたい気持ちが高まっています。
2:17 PM
↑プロセス制御はFoundationのこれでできます。
2:18 PM
うーんそれだったら
2:18 PM
BashOnWindowsで動かすのが手っ取り早いとは思います。
2:18 PM
インストールの手間はあるけど。
Avatar
Taketo Sano 4/7/2018 2:18 PM
それが結構なハードルでしてw
2:18 PM
僕が苦労する分には構わないというスタンスで、他の人にはできるだけ楽させてあげたいw
Avatar
omochimetaru 4/7/2018 2:19 PM
なるほど・・・
2:19 PM
まあそういう身内の展開だったら
2:19 PM
とりあえずクォータとか無視して
2:19 PM
↑のProcessとかで作ってみるのが早いかも?
Avatar
Taketo Sano 4/7/2018 2:19 PM
ふむふむ!
Avatar
omochimetaru 4/7/2018 2:19 PM
ようするに問題になるのはAWSとかでホストしてるとして
2:19 PM
無限ループを書かれただけで
2:19 PM
CPU課金が死んじゃうってことですね
2:19 PM
あとは無限にファイルを書き出すループとか。
Avatar
Taketo Sano 4/7/2018 2:19 PM
はいはい、それは避けたいですね。
2:20 PM
でも悪意なくそういうコードを書いてしまうリスクはありますねw
Avatar
omochimetaru 4/7/2018 2:20 PM
そうなんだよなあw
Avatar
Taketo Sano 4/7/2018 2:21 PM
ちなみに severside swift をホストするのは IBM のやつがいいんでしょうか?(その辺りも全然知らない)
Avatar
omochimetaru 4/7/2018 2:21 PM
Vaper + VaperCloudが楽というのは聞きますね
Avatar
Taketo Sano 4/7/2018 2:21 PM
ほほぅ!
Avatar
omochimetaru 4/7/2018 2:22 PM
Simple and flexible Vapor hosting, Built for Vapor by Vapor. One command to get your Vapor app running in the Cloud.
Avatar
Taketo Sano 4/7/2018 2:23 PM
全編mac版。Vaporのバージョンは2.0.4 Vaporの始め方やHello Worldまでの手順は記事がいっぱいあるので割愛します。 サーバーサイドに慣れてないSwift開発者だけど、自分でもできそう! ...
Avatar
omochimetaru 4/7/2018 2:23 PM
ひろしさんだ。
2:26 PM
あーそっか
2:26 PM
別にウェブ側もSwiftで作る必要はないですね
2:26 PM
REPLプロセスとの媒介は別にNodeJSとかRubyでも作れるし。
Avatar
Taketo Sano 4/7/2018 2:26 PM
そうですね
Avatar
omochimetaru 4/7/2018 2:27 PM
Contribute to swift-playground development by creating an account on GitHub.
2:27 PM
岸川さんのplaygroundはnodeだった。
Avatar
Taketo Sano 4/7/2018 2:27 PM
おぉ、こんなものが。
2:28 PM
デプロイされてるのはこっち。
Avatar
Taketo Sano 4/7/2018 2:28 PM
axa,
2:28 PM
なるほど。
2:28 PM
REPL でなくてもこういう形式でもいいのかもですね。
Avatar
omochimetaru 4/7/2018 2:30 PM
それならこれをほぼそのままデプロイしつつ
2:30 PM
SwiftyMathをもったコンテナをDockerで用意して
Avatar
Taketo Sano 4/7/2018 2:30 PM
https://repl.it/site/languages/swift こんなのもあるんですね。
Swift Compiler, REPL, and IDE. Compile and run code online. Host and share your code.
Avatar
omochimetaru 4/7/2018 2:31 PM
最初からimportできるようにしておくのが手っ取り早いですね
2:31 PM
おお。
Avatar
Taketo Sano 4/7/2018 2:34 PM
while true { } って書いてみましたがずっと動いてるようですw
Avatar
omochimetaru 4/7/2018 2:35 PM
マジか・・
Avatar
Taketo Sano 4/7/2018 2:42 PM
とりあえず色々とありがとうございます、もう少し自分でも調べてみます 🙌
Avatar
@Taketo Sano なんとタイムリーな😀 https://swift-tweets.github.io/#timetable Swift Tweets 2018 Spring 2018-04-14 21:00 JST "Swift Playgroundを作ろう" @k_katsumi
😆 1
Avatar
Kishikawa Katsumi 4/7/2018 10:18 PM
@taketo1024#1158 私の中期的な展望をいうと、おそらく私のも含めて今の現存するSwiftのWeb SandboxはXcodeのPlaygroudやSwift REPLのように1行ごとに評価するようにはなってないはずなので、そういう風に結果を返せるようにしたい。 ただ、Swift REPLのような対話的な環境を用意するのは解決する問題が多いので(オンラインシェルとかターミナルというのはすでにあるのでそれと同じような仕組みでいけるなとも思っていますが。無限ループ対策は一定のレスポンスや操作がなかったら切れるとかそういうの)とりあえず毎回入力されたコードを最初から実行しなおす、そして各行を全部評価するという方法にすれば、実際は対話的実行じゃないけどそういう風に見えるはず、みたいな。
10:19 PM
@taketo1024#1158 あとSwiftbotに適当にフレームワーク足してもいいなと思ってるんで試しにSwiftMath足してみましょうか? (edited)
Avatar
エクセレント🤩👉👉
11:06 PM
@Kishikawa Katsumi おぉ、是非お願いします😆
11:08 PM
自分のケースで REPL にしたいのは、一行の実行にそれなりに時間がかかることが想定されるためです。
Avatar
Kishikawa Katsumi 4/7/2018 11:10 PM
なるほど。
Avatar
まとまった情報を持ったものをドガッと計算して、そこから色々調べるというような。
Avatar
Kishikawa Katsumi 4/7/2018 11:11 PM
それなら、単に現在の仕組みで実行結果を前のに積み上げて(下げて?)表示していくだけで良い感じになりそうです。
😆 1
Avatar
preconditionFailureやfatalErrorを使った場合に、そこを通るテストを書きたい場合ってどうしてますか?
Avatar
これ絶対絶対beginner-helpに書く内容じゃないだろw
Avatar
Kishikawa Katsumi 4/9/2018 7:10 AM
私はそれはテストしないで諦めています。諦めているというのはたまにテストしたいことはあるということです。 解決策はpreconditionFailureをラップするか条件によって分岐するくらいしかないと思います。
7:11 AM
たまにテストしたいことはありますが、preconditionFailureやfatalErrorの部分をややこしくするのもアレだなあと思って、諦めています。
Avatar
テスト対象のコードに直接fatalError書くのやめてthrowしてcatchした所でfatalErrorするようにするくらいしか思い浮かばないけどオーバーキル感ある
7:20 AM
enum UnrecoverableError: Error { case preconditionFailure } struct Hoge { func テストしたいメソッド() throws { if true { throw UnrecoverableError.preconditionFailure } } } let hoge = Hoge() do { try hoge.テストしたいメソッド() } catch let error as UnrecoverableError { switch error { case .preconditionFailure: preconditionFailure() } } うーんやりたくない
Avatar
Kishikawa Katsumi 4/9/2018 7:21 AM
自分のコードの実行結果でFatalErrorに落ちる可能性がある部分で不安なところは、それまでに至る部分でテストを書くって感じかなあ。
Avatar
func hoge() -> Never { return unsafeBitCast((), to: Never.self) } guard 1 == 0 else { hoge() } print("離脱してないよー")
7:23 AM
Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT). The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation. * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) * frame #0: 0x00007fffaba7aa9b libobjc.A.dylib`_objc_msgSend_uncached + 11 frame #1: 0x00007fff9865d231 Foundation`-[NSPlaceholderString initWithString:] + 107 frame #2: 0x000000010c5d4007 PlaygroundLogger`function signature specialization <Arg[0] = Dead> of static PlaygroundLogger.LoggingPolicyStack.get() -> PlaygroundLogger.LoggingPolicyStack + 151 frame #3: 0x000000010c5cdf22 PlaygroundLogger`function signature specialization <Arg[1] = Owned To Guaranteed and Exploded> of playground_log_hidden + 98 frame #4: 0x000000010c5cd65b PlaygroundLogger`playground_log_hidden + 27 frame #5: 0x000000010c5fc094 $__lldb_expr82`hoge() at MyPlayground.playground:2
7:23 AM
コンパイルは通って実行時に死んだ
7:25 AM
unsafeBitCast((), to: Never.self) これでNever型のインスタンス作れるの @Yuta Saito が気づいた
Avatar
Xcode でカバレッジ見れるじゃないですか、容赦なく preconditionFailure のところでお前テストしてないやんけってお怒りになってしまったので
7:26 AM
いいway有るかなーと思った次第
Avatar
カバレッジ太郎だ
Avatar
Kishikawa Katsumi 4/9/2018 7:27 AM
それはしょうがないので基本的には気にしない。カバレッジマニアでもなければ。。。
Avatar
本気でやろうとはあんまり思ってなくてふと気になったのでここに書きました
7:27 AM
↑それ最初に書けって話やな、すみません
Avatar
Kishikawa Katsumi 4/9/2018 7:28 AM
私もまあ89%みたいな時にそこを通せれば、、、みたいに思うことはあるんですけど、無意味やなと思ってやめます。
Avatar
それはそれとして、Xcodeのカバレッジはこれ直接Function呼んでなかったら怒ってるのかしら、ブレークポイント貼れば通ってるのに怒り心頭みたいなの結構ある
Avatar
Kishikawa Katsumi 4/9/2018 7:29 AM
^ 通ってるはずなので通ってないと表示されてる? (edited)
Avatar
異常系のユニットテストの書き方のコツみたいなのはありますか?
8:51 AM
Coredataのデータファイルがぶっ壊れてた時に正しく終了できるようにしたものをテストするとかってどうしてます?
8:52 AM
壊れたデータファイルを用意したりするんでしょうか?
Avatar
Kishikawa Katsumi 4/9/2018 8:53 AM
壊れたものを用意する必要があるならそうします。が、アプリケーションの場合はそこまでする必要はないと思います。 開けなかった場合に返ってくる状態、エラーなりnilなり、を与えて、それが意図した通りに処理されるかどうかを確認します。
😀 1
8:54 AM
CoreDataそのもののテスト、みたいな場合は壊れたファイルを用意することは妥当だと思います。
8:55 AM
あと、CoreDataのファイルをダウンロードしてくるとか、そういう場合も妥当かもしれません。
8:55 AM
大抵はアプリケーションで生成したファイルを使う、ということだろうから、そうそう壊れたものが存在することはないとして扱うと思います。
Avatar
Kishikawa Katsumi 4/9/2018 9:04 AM
まあ蛇足なんですけど、基本的にユニットテストは外部に依存しないほうがいい、というのにくわえて、あまり大がかりだったりややこしい仕組みにしないほうがいいです。 というのはプロダクトコードと一緒に継続的にメンテナンスしていくものなので、めっちゃテストできるすごい仕組みのユニットテスト、みたいなのは作ったきりになりがちです。
😀 1
Avatar
例えば func coodinator() -> NSPersistentStoreCoordinator { do { return try makeCoodinator() } catch { //エラー処理 アラートを出してterminate } } という関数であった場合 func coodinator(_ f: () throws -> NSPersistentStoreCoordinator) -> NSPersistentStoreCoordinator { do { return try f() } catch { //エラー処理 アラートを出してterminate } } にしてテスト時にthrowする関数を与えるような感じ? だとおかしいですね... ちょっと考えてみます
Avatar
こうゆう部分をテストしたいと思ったのは「アラート出してterminate」の処理が間違っていたために、「原因不明のクラッシュをしてした」という報告をユーザーさんからもらってしまったためです
Avatar
Kishikawa Katsumi 4/9/2018 9:33 AM
ユニットテストで防止するのはあまり向いてないように見えますね。間違ってたっていうのは具体的にどんな感じですか?
Avatar
メインスレッドでないスレッドでNSAlertをmodalで表示してしまった
9:36 AM
です
Avatar
Kishikawa Katsumi 4/9/2018 9:37 AM
その間違いをユニットテストで防止するのは向いてないですね。
9:37 AM
一般的に。
9:38 AM
重要な画面で「こういう場合には必ずこういう画面が出なければならない」みたいなものはやる価値がありそうですが。
9:39 AM
今ならメインスレッドチェッカーがあるから、自動化するとしたら、UI Testを使ってすべての画面を経由するような操作のテストを定期的に実行するとか、ですかねえ。
Avatar
omochimetaru 4/9/2018 9:39 AM
やったことないけどiOSのUIテスト機能とかで画面操作のレベルでシナリオ書いて、ダイアログが出ることって検証できるのかな?
Avatar
Kishikawa Katsumi 4/9/2018 9:40 AM
^ できますよ。
Avatar
XCUITestでボタン操作は割りと出来る雰囲気
Avatar
omochimetaru 4/9/2018 9:40 AM
おー、じゃあ、関数の粒度じゃなければ、この話自体の再発防止テストは書けそう。
Avatar
Kishikawa Katsumi 4/9/2018 9:41 AM
そうですね。この例のような、手作業の操作では確認しにくい、ユニットテストもしにくい、ものはUIテストは向いてると思います。
9:42 AM
ただUITestはユニットテストと違って、テスト対象のプログラムは全く操作できないので、意図的にエラーになる状態を用意するのが難しいです。
9:42 AM
壊れたファイルを用意する必要があります。
Avatar
omochimetaru 4/9/2018 9:45 AM
なるほど。
Avatar
KIFみたいなのを使えば,ユニットテストなので壊れたファイルを差し込みつつ,画面操作のあとアラートにある文字がstaticTextで出ていてOKが押せる,みたいなのそこそこ書けます
Avatar
今のこれに限定するなら「Errorを受け取ってメインスレッドでNSAlertだしてteminateする」関数をつくってそれをテストすればいいのかな?
9:55 AM
メインスレッド以外から呼び出すテスト付きで
9:58 AM
UIテストはなにをテストすればいいのかというところからわからない
Avatar
Kishikawa Katsumi 4/9/2018 10:03 AM
UIテストはユニットテストより難しいです。
UIテストはなにをテストすればいいのかというところからわからない
というのは真理をついていて、UIテストはどういう状態になったら成功か失敗かをまず定義するのが難しいです。
10:04 AM
XcodeのUIテストでいうと、Assertメソッドもないので、^で正しい(間違い)状態を定義した上で、どうAssertionすべきか、というところから始めないといけないので、大変です。
Avatar
後出しですみません アプリケーションは 1、起動したら第三者が提供しているサーバーからデータを取ってくる 2、変換してCoreDataに突っ込む 3、CoreDataの変化を受けてデータが表示/更新される というものです 今回の件ではユーザーさんは起動後何もしていない段階でクラッシュしています
10:09 AM
なのでUIテストではどうにもならない?のかな?
10:12 AM
発言遅くてすみません理解が追い付いてないのでじっくり考えてます
Avatar
Kishikawa Katsumi 4/9/2018 10:14 AM
全然非同期のやりとりで構わないですよ 😄 私もちょうど帰るのでしばらく離れますし。
Avatar
!!!!
11:59 AM
terminateしたらテスト通らないじゃん!
11:59 AM
根本的なところを見落としてた
Avatar
#if TEST func myPrecondition() -> Never { ... } #else func myPrecondition<T: FatalObjectCompatible>() -> T { return T.fatal() } #endif
1:08 PM
こういうの使ってTest側にFatalObjectCompatibleの実装を作って、後は呼び出したことを検知できればまあなんとかなるかなー
1:09 PM
書くところはreturn myPreconditionみたいにして
1:14 PM
preconditionは有り得ない状態なのでproductionコードを多少汚しても許されるのではという気持ちが発生している
Avatar
ビルドに時間かかってるとこの特定ってどうやってます?
Avatar
The Swift type-checker remains a performance bottleneck for compile times, though it has improved tremendously over the past two years. You could even say the type-checker has gone from being drunk to sober. To help users debug these issues, awhi...
12:15 PM
これで設定した閾値以上コンパイル時間かかっている箇所に警告が出るようになるはずです。
12:18 PM
コマンドラインからのビルドで、もっと網羅的に見たいなら、 https://github.com/apple/swift/blob/master/docs/CompilerPerformance.md#how-to-diagnose-compilation-performance-problems-Xfrontend -debug-time-function-bodies-Xfrontend -debug-time-expression-type-checking が使えます。
swift - The Swift Programming Language
Avatar
BuildTimeAnalyzer-for-Xcode - Build Time Analyzer for Swift
Avatar
おぉ、ありがとうございます!
Avatar
ちょうど、改善していきたいなって思っていたところだったので参考にします!!
Avatar
@giginet って人がこんなのも作ってますね http://techlife.cookpad.com/entry/2016/12/28/112806
技術部モバイル基盤グループの@giginetです。 我々のチームでは、iOS/Androidアプリの認証、決済、ロギングと言った基幹部分の開発のほか、各事業部のモバイルエンジニアの開発効率を...
Avatar
手前味噌ですがBuildTimeAnalyzer-for-Xcodeより便利だと思います 😎
😁 2
5:08 AM
まあやってることは同じなんだけど
Avatar
お助け願います 🙇 import Foundation public protocol MapType { associatedtype Domain associatedtype Codomain init(_ fnc: @escaping (Domain) -> Codomain) func applied(to x: Domain) -> Codomain } public struct Map<Domain, Codomain>: MapType { internal let fnc: (Domain) -> Codomain public init(_ fnc: @escaping (Domain) -> Codomain) { self.fnc = fnc } public func applied(to x: Domain) -> Codomain { return fnc(x) } } public protocol EndType: MapType where Domain == Codomain { static var identity: Self { get } func composed(with f: Self) -> Self } public extension EndType { public static var identity: Self { return Self{ x in x } } public func composed(with g: Self) -> Self { return Self { x in // ココで EXC_BAD_ACCESS self.applied(to: g.applied(to: x)) } } } extension Map: EndType where Domain == Codomain { } public extension Array where Element: EndType { func composed() -> Element { return self.reduce(Element.identity) { (res, f) in res.composed(with: f) } } } let f = Map { x in 2 * x } let g = [f, f].composed() print(g.applied(to: 0)) 関数(写像)を抽象化した MapType と、具体型の Map: MapType を作り、特に Domain(定義域) と Codomain(値域) が一致している場合に EndType: MapType という subprotocol を用意して、配列に入った関数をまとめて合成できるようにしたいと思って上のようなコードを書いたのですが、実行時に EXC_BAD_ACCESS が出てしまいます 👼 protocol で関数値を取る init を置いてるのがまずいんでしょうか…?わかる方いたら教えてください 🙏 (edited)
Avatar
@Taketo Sano 本質的な回答ではないですが、最近の Swift では FooType より FooProtocol という命名の方が主流だと思います。標準ライブラリがそのように変わったので。↓など。 https://developer.apple.com/documentation/swift/iteratorprotocol
Avatar
omochimetaru 4/16/2018 9:56 AM
@swiftbot import Foundation public protocol MapType { associatedtype DomainType associatedtype CodomainType init(_ fnc: @escaping (DomainType) -> CodomainType) func applied(to x: DomainType) -> CodomainType } public struct Map<Domain, Codomain>: MapType { internal let fnc: (Domain) -> Codomain public init(_ fnc: @escaping (Domain) -> Codomain) { self.fnc = fnc } public func applied(to x: Domain) -> Codomain { return fnc(x) } } public protocol EndType: MapType where DomainType == CodomainType { static var identity: Self { get } func composed(with f: Self) -> Self } public extension EndType { public static var identity: Self { return Self { x in x } } public func composed(with g: Self) -> Self { return Self { x in // ココで EXC_BAD_ACCESS self.applied(to: g.applied(to: x)) } } } extension Map: EndType where Domain == Codomain { } public extension Array where Element == Map<Int, Int> { func composed() -> Element { return self.reduce(Element.identity) { (res, f) in res.composed(with: f) } } } let f: Map<Int, Int> = Map { x in 2 * x } let fs: Array<Map<Int, Int>> = [f, f, f] let g: Map<Int, Int> = fs.composed() let t: Int = g.applied(to: 1) print(t)
Avatar
swiftbot BOT 4/16/2018 9:56 AM
Swift version 4.1 (swift-4.1-RELEASE)
9:56 AM
8
Avatar
omochimetaru 4/16/2018 9:57 AM
Arrayのwhereを concrete type で書いたら動く・・・
9:58 AM
@Taketo Sano コンパイラのバグな気がしますが踏む条件がまだわからないです 直感的には Self.init のところでバグを踏んでそうだけど、コードやアイデア自体は特にまずいことはやってないように見えます。
😥 1
Avatar
@swiftbot import Foundation public protocol EndType where DomainType == CodomainType { associatedtype DomainType associatedtype CodomainType init(_ fnc: @escaping (DomainType) -> CodomainType) func applied(to x: DomainType) -> CodomainType static var identity: Self { get } func composed(with f: Self) -> Self } public extension EndType { public static var identity: Self { return Self { x in x } } public func composed(with g: Self) -> Self { let fnc: (DomainType) -> DomainType = { x1 in let x2: DomainType = g.applied(to: x1) let x3: DomainType = self.applied(to: x2) return x3 } return Self.init(fnc) } } public struct Map<Domain>: EndType { internal let fnc: (Domain) -> Domain public init(_ fnc: @escaping (Domain) -> Domain) { self.fnc = fnc } public func applied(to x: Domain) -> Domain { return fnc(x) } } public extension Array where Element: EndType { func composed() -> Element { return self.reduce(Element.identity) { (res, f) in res.composed(with: f) } } } let f: Map<Int> = Map { x in 2 * x } let fs: Array<Map<Int>> = [f, f, f] let g: Map<Int> = fs.composed() let t: Int = g.applied(to: 1) print(t)
Avatar
Swift version 4.1 (swift-4.1-RELEASE)
10:06 AM
8
Avatar
EndTypeとMapTypeの分離をやめてEndTypeだけで書くとこれも動く。
10:08 AM
[omochi@omochi-iMac-PC43 et]$ swift a.swift 0 swift 0x00000001062c5ffa PrintStackTraceSignalHandler(void*) + 42 1 swift 0x00000001062c53b6 SignalHandler(int) + 966 2 libsystem_platform.dylib 0x00007fff55398f5a _sigtramp + 26 3 libsystem_platform.dylib 0x000000000000ffff _sigtramp + 2865197247 4 libsystem_platform.dylib 0x0000000109f2a4fb _sigtramp + 3032028603 5 libsystem_platform.dylib 0x0000000109f2a7c4 _sigtramp + 3032029316 6 libsystem_platform.dylib 0x0000000109f2a922 _sigtramp + 3032029666 7 libsystem_platform.dylib 0x0000000109f2ac61 _sigtramp + 3032030497 8 libswiftCore.dylib 0x000000010c0a894b _T0s8SequencePsE6reduceqd__qd___qd__qd___7ElementQztKctKlF + 603 9 libswiftCore.dylib 0x0000000109f2a8a7 _T0s8SequencePsE6reduceqd__qd___qd__qd___7ElementQztKctKlF + 4259848631
10:08 AM
10 libswiftCore.dylib 0x0000000109f2a187 _T0s8SequencePsE6reduceqd__qd___qd__qd___7ElementQztKctKlF + 4259846807 11 swift 0x0000000103606c0a llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) + 362 12 swift 0x000000010360d30c llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 1004 13 swift 0x0000000102928735 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 48709 14 swift 0x000000010291ae64 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 7908 15 swift 0x00000001028cf8b5 main + 18917 16 libdyld.dylib 0x00007fff5508a015 start + 1 17 libdyld.dylib 0x000000000000000a start + 2868338678 Stack dump: 0. Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret a.swift -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk -color-diagnostics -module-name a Segmentation fault: 11
Avatar
むむぅ
Avatar
omochimetaru 4/16/2018 1:06 PM
本命はバグ報告+修正待ちとして、その場しのぎで書き方を工夫すれば動く方法があるかも?
Avatar
ConditionalConformanceって確か、ExistentialへのCastはFailしますよね
1:42 PM
そのあたりでしくじってる気がします
1:47 PM
@swift-4.1.3 // // main.swift // Math // // Created by tarunon on 2018/04/16. // Copyright © 2018年 tarunon. All rights reserved. // import Foundation public protocol MapType { associatedtype Domain associatedtype Codomain init(_ fnc: @escaping (Domain) -> Codomain) func applied(to x: Domain) -> Codomain } public struct Map<Domain, Codomain>: MapType { internal let fnc: (Domain) -> Codomain public init(_ fnc: @escaping (Domain) -> Codomain) { self.fnc = fnc } public func applied(to x: Domain) -> Codomain { return fnc(x) } } public protocol EndType: MapType where Domain == Codomain { static var identity: Self { get } func composed(with f: Self) -> Self } public extension EndType { public static var identity: Self { return _identity(of: Self.self) } public func composed(with g: Self) -> Self { return _composed(with: self, g) } } func _identity<E: EndType>(of type: E.Type = E.self) -> E { return E { x in x } } func _composed<E: EndType>(with f: E, _ g: E) -> E { return E { x in f.applied(to: g.applied(to: x)) } } extension Map: EndType where Domain == Codomain { } public extension Array where Element: EndType { func composed() -> Element { return self.reduce(_identity(of: Element.self)) { (res, f) in _composed(with: res, g: f) } } } let f = Map { x in 2 * x } let g = [f, f].composed() print(g.applied(to: 1)) (edited)
Avatar
4
Avatar
@Taketo Sano
1:48 PM
global func 作ってProtocol Extensionはそこのエイリアスにすると通りました (edited)
Avatar
@swift-4.1.3 import Foundation public protocol MapType { associatedtype Domain associatedtype Codomain init(_ fnc: @escaping (Domain) -> Codomain) func applied(to x: Domain) -> Codomain } public struct Map<Domain, Codomain>: MapType { internal let fnc: (Domain) -> Codomain public init(_ fnc: @escaping (Domain) -> Codomain) { self.fnc = fnc } public func applied(to x: Domain) -> Codomain { return fnc(x) } } public protocol EndType: MapType where Domain == Codomain { static var identity: Self { get } func composed(with f: Self) -> Self } public extension EndType { public static var identity: Self { return Self { x in x } } public func composed(with g: Self) -> Self { return Self { x in // ココで EXC_BAD_ACCESS self.applied(to: g.applied(to: x)) } } } extension Map: EndType where Domain == Codomain { public static var identity: Map<Domain, Codomain> { return Map { x in x } } public func composed(with g: Map<Domain, Codomain>) -> Map<Domain, Codomain> { print("Map.composed self: \(type(of: self))") return Map { x in exit(0) // return self.applied(to: g.applied(to: x)) } } } public extension Array where Element: EndType { func composed() -> Element { return self.reduce(Element.identity) { res, f in print("Array.composed res: \(type(of: res))") return res.composed(with: f) } } } let f = Map<Int, Int> { x in 2 * x } let g = [f, f].composed() print(g.applied(to: 0))
Avatar
Array.composed res: Map<Int, Int> Map.composed self: Map<Map<Int, Int>, Map<Int, Int>> Array.composed res: Map<Int, Int> Map.composed self: Map<Map<Int, Int>, Map<Int, Int>>
Avatar
↑これヤバくないですか? res.composed の直前の resMap<Int, Int> なのに、直後の composed の中の selfMap<Map<Int, Int>, Map<Int, Int>> になってる。
🙄 2
Avatar
これなんでPrint2回ずつ走ってるんだ
3:05 PM
あ、一回目は通るのか
Avatar
global func作る方は壊れてなかった
3:51 PM
conditional conformanceを別のconditionに利用すると崩壊なのかな
3:54 PM
+ Selfかな
Avatar
再現できた
Avatar
@swift-4.1.3 protocol A { static func foo() } extension Dictionary: A where Key == Value { static func foo() { print(type(of: self)) } } extension Array where Element: A { static func foo() { Element.foo() } } [String: String].foo() [[String: String]].foo()
Avatar
Dictionary<String, String>.Type Dictionary<Dictionary<String, String>, Dictionary<String, String>>.Type
Avatar
2つのGenericsパラメータを==で束縛してConditional Conformanceを使い、それを他のGenerics ParameterのConditionに利用して関数を呼ぶとTypeが壊れる (edited)
Avatar
むむむ…
1:24 AM
なるほど 😮
1:25 AM
単純なケースで再現できてよかったです(どこで壊れるのか分からないといつ世界が崩壊するか分からず不安なので 😅
1:28 AM
でも == 束縛パターン結構使ってるから不安だなぁ 😵
Avatar
omochimetaru 4/17/2018 1:28 AM
global func 作ってProtocol Extensionはそこのエイリアスにすると通りました
とりあえずこれでその場はしのげた?
Avatar
今からやってみます > global func
Avatar
omochimetaru 4/17/2018 1:29 AM
@swiftbot help
Avatar
swiftbot BOT 4/17/2018 1:29 AM
Usage: @swiftbot [--version=SWIFT_VERSION] [--command={swift, swiftc}] [--options=SWIFTC_OPTIONS] `​`​` [Swift Code] `​`​` Examples: @swiftbot `​`​` print("Hello world!") `​`​` @swiftbot --version=4.0.3 `​`​` print("Hello world!") `​`​` @swiftbot --command=swiftc --options=-dump-parse `​`​` print("Hello world!") `​`​` Subcommands: @swiftbot versions: show available Swift toolchain versions @swiftbot contribute: show repository URLs @swiftbot help: show help
Avatar
omochimetaru 4/17/2018 1:29 AM
@swiftbot --version=latest import Foundation public protocol MapType { associatedtype Domain associatedtype Codomain init(_ fnc: @escaping (Domain) -> Codomain) func applied(to x: Domain) -> Codomain } public struct Map<Domain, Codomain>: MapType { internal let fnc: (Domain) -> Codomain public init(_ fnc: @escaping (Domain) -> Codomain) { self.fnc = fnc } public func applied(to x: Domain) -> Codomain { return fnc(x) } } public protocol EndType: MapType where Domain == Codomain { static var identity: Self { get } func composed(with f: Self) -> Self } public extension EndType { public static var identity: Self { return Self{ x in x } } public func composed(with g: Self) -> Self { return Self { x in // ココで EXC_BAD_ACCESS self.applied(to: g.applied(to: x)) } } } extension Map: EndType where Domain == Codomain { } public extension Array where Element: EndType { func composed() -> Element { return self.reduce(Element.identity) { (res, f) in res.composed(with: f) } } } let f = Map { x in 2 * x } let g = [f, f].composed() print(g.applied(to: 0))
Avatar
swiftbot BOT 4/17/2018 1:29 AM
Swift version 4.2-dev (LLVM d14a2b25f2, Clang c38020c511, Swift 22530b922f)
1:29 AM
/usr/bin/swift[0x41336e4] /usr/bin/swift[0x4133a26] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fd883d3e390] /usr/lib/swift/linux/libswiftCore.so(+0x42ea92)[0x7fd87eefca92] /usr/lib/swift/linux/libswiftCore.so(swift_getGenericMetadata+0x687)[0x7fd87eef6f87] [0x7fd88416d90a] [0x7fd88416d296] [0x7fd88416d35c] [0x7fd88416d41c] [0x7fd88416d65c] [0x7fd88416d715] [0x7fd88416d15e] /usr/bin/swift[0x10335de] /usr/bin/swift[0x1037702] /usr/bin/swift[0x4f21d2] /usr/bin/swift[0x4d9b77] /usr/bin/swift[0x4d503c] /usr/bin/swift[0x48a3ad] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fd882468830] /usr/bin/swift[0x487c09] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main Segmentation fault (core dumped)
Avatar
omochimetaru 4/17/2018 1:29 AM
最新でもだめか。
Avatar
Kishikawa Katsumi 4/17/2018 1:50 AM
いつのスナップショットか表示した方がいいかな。今は2018-04-15のスナップショット。
Avatar
omochimetaru 4/17/2018 1:54 AM
それが出たほうがうれしいです。
Avatar
global func でやれば確かに通るようになりました。
1:56 AM
2つのGenericsパラメータを==で束縛してConditional Conformanceを使い、それを他のGenerics ParameterのConditionに利用して関数を呼ぶとTypeが壊れる
1:56 AM
これを気をつけるのかなり難しい…😥
Avatar
omochimetaru 4/17/2018 2:01 AM
早く直るように祈るしか無いですね tarunonのissueスレッドにSwiftyMathのリンク貼って、実際困る!って書き込むとか。
Avatar
ワロタ
Avatar
「いま俺もそれで困ってたんだよ!」的なw
Avatar
マッチポンプ感が半端ないですが、困ってるのは事実だしりんたろさんが見てるなので問題はないと思いますw
😳 2
Avatar
問題を簡易化してくれて助かります🙇‍♂️Map のままのバグレポだと優先度かなり下がりそうなのでw
Avatar
コメントしときました 👍
👍 2
Avatar
@Taketo Sano これ困ってるのどっちかといえば7450の方じゃないですか?Crash側は7450です
Avatar
原因は同じっぽいってことで…w
Avatar
masterで https://bugs.swift.org/browse/SR-7450 がクラッシュしなくなっていることを確認しました。
👏 3
💖 1
Avatar
はやい、昨日コメントついてましたね
2:25 AM
丁度話をしていたとか
Avatar
omochimetaru 4/18/2018 2:51 AM
はや!
Avatar
エクセレント!!!!!
Avatar
これを使うために @Taketo Sano さんもSwiftコンパイラをビルドすることに…😁 (↓この手順に従うだけで簡単にコンパイラをビルドできます。) https://qiita.com/rintaro/items/2047a9b88d9249459d9a
Swift がオープンソースになってしばらく経ちます。 コンパイラや標準ライブラリの開発に手を出してみたいけど、リポジトリを落とした後どうしていいかわからない!という方のた...
Avatar
おw
Avatar
omochimetaru 4/18/2018 1:40 PM
使うだけなら一晩待ってればswift.orgからdaily snapshotがダウンロードできますよ
Avatar
omochimetaru 4/19/2018 5:33 AM
@Taketo Sano April 18, 2018のsnapshotをxcodeでtoolchain設定したら動きました https://swift.org/download/#snapshots Trunk Development (master) > Download > Xcode
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
conditional extensionに生やした関数が、conditionの外でも補完出ちゃうんですが同じ人いませんか? & 対策あれば教えてください。
Avatar
struct拡張だと出てprotocol拡張だと出ない気がしてきた
Avatar
↑予想通りstruct拡張をやめてprotocol拡張にしたら出なくなりました。🙋
Avatar
GomaIsNiceGuy 4/27/2018 12:42 AM
こんにちは。Swiftでコマンドライン引数を取得したい場合、どうゆう書き方をすればいいのですか??
Avatar
CommandLine.arguments で配列取れませんでしたっけ?
12:43 AM
CommandLine.argumentsですね
Avatar
GomaIsNiceGuy 5/1/2018 3:34 AM
ありがとうございます
Avatar
GomaIsNiceGuy 5/6/2018 6:58 AM
An internal error occurred. Editing functionality may be Limited というエラーが出ました。初めて見るエラーで、全くわからないです。
6:59 AM
I just created one new cordova ios project via CLI, and i opened that project in Xcode 7.1 and while running on simulator am getting some error on mainViewController.xib, if we clicked on that erro...
7:00 AM
このサイトの1番上の答えを翻訳しながら行ったのですが、trash it. で、どれをどう消せばいいかわからないです。下の追記みたいな所にファイル自体は消すなって書いてあることはわかるんですが、、、
Avatar
Developers.IOは、AWS、iOS/Androidアプリ、ビッグデータ、Alexa等の最新技術情報からリモートワークや働き方に関する記事まで多彩なトピックを紹介するクラスメソッドのオウンドメディア...
Avatar
GomaIsNiceGuy 5/6/2018 7:06 AM
試してみますありがとうございます🙇‍♂️
Avatar
Kishikawa Katsumi 5/6/2018 7:07 AM
開発に支障がなければ気にしなくてもいいです。
Avatar
GomaIsNiceGuy 5/6/2018 7:16 AM
出来ましたー!!
😁 1
7:17 AM
storyboardが青色の枠線だけになってしまってすごいことになってました、、
Avatar
1つのStoryboardファイルに大量のViewControllerとかAutoLayoutの制約があるとよく起きますね、それ。
Avatar
GomaIsNiceGuy 5/6/2018 8:04 AM
そうなんですね、、 開発初めてすぐなのでボタンとかしか置いてないんですけどねwwww なんで起きたのかイマイチわかんないです、、
Avatar
MacがStoryboardを画面に表示するときスペック的に時間かかる場合も出たりしたので、まぁ出るときは出るとしかw (edited)
Avatar
GomaIsNiceGuy 5/6/2018 9:49 AM
なるほど ありがとうございます🙏
Avatar
swift package generate-xcodeproj で作ったプロジェクトでフォルダの順番を入れ替えたりすると Xcode クラッシュしません? 😥
Avatar
omochimetaru 5/15/2018 2:15 AM
フォルダ並び替えるとクラッシュするxcodeprojは僕も踏んだことあります
2:15 AM
SwiftPMから作った時だったかどうか覚えてないですが
2:16 AM
なんかいろいろ消したり作り直してるうちに治っちゃった記憶がある
Avatar
is辛い 😥
Avatar
Folder reference使ってますか?
Avatar
Folder reference …とは何かを知りません 😅 generate-xcodeproj で作ったばかりのプロジェクトでフォルダの順番を変えようとすると落ちます 😥
Avatar
Folder ReferenceとそうじゃないGroupがあって怪しいファイル移動をするとすぐ落ちるみたいなのはよく踏みます。
2:17 AM
ファイルツリーに出てるフォルダのアイコンが水色だったらFolder referenceですが
Avatar
あぁ、それは確かにあります。
Avatar
Folder reference経由だとビルドターゲットに含められなかったから違うかも。
2:17 AM
おっ。
Avatar
generate-xcodeproj で勝手に追加されます。
Avatar
Kishikawa Katsumi 5/15/2018 2:18 AM
Xcode 9からのXcodeのグループを実際のディレクトリ構造に反映する機能が怪しいんじゃないかな。
2:18 AM
リネームとか中途半端に終わることがたまにある。
😇 2
Avatar
青い奴を外してから移動してみましたが、やはり落ちました 💣
Avatar
辛い
Avatar
pbxproj 直接編集で頑張りますw
Avatar
omochimetaru 5/15/2018 2:19 AM
リネームといえばクラス名をリネームする時に ClassName.swift もリネームされかけるけど絶対失敗する
Avatar
ファイル名も変えてくれるのか
2:20 AM
いや、変えてくれないのかw
Avatar
omochimetaru 5/15/2018 2:20 AM
最近はファイル名を手動で直してからrefactorしている
2:20 AM
一度も成功したことが無いw
Avatar
Kishikawa Katsumi 5/15/2018 2:20 AM
よく失敗するね。だいたい実際のリネームは成功するけどプロジェクトのファイル名がそのままで赤くなることが多いです。
😇 1
Avatar
omochimetaru 5/15/2018 2:20 AM
それですそれです。
Avatar
Kishikawa Katsumi 5/15/2018 2:20 AM
私の場合。
Avatar
渋い
Avatar
それなんかいけるパターンもあって謎すぎる
Avatar
リネーム機能、使ったこと無いな。。
2:21 AM
Find and replaceでやっちゃう
Avatar
omochimetaru 5/15/2018 2:21 AM
いけることもあるのか。
Avatar
あるね
Avatar
Kishikawa Katsumi 5/15/2018 2:22 AM
失敗するのはともかく中途半端な状態で終わるのなんとかしてほしい。失敗なら全部失敗で。。。 (edited)
Avatar
自分の場合は XVim2 のかみ合わせもあって入力モードのままだと落ちるとかもあったけど…
2:22 AM
そうですね。いっそ失敗してロールバックしてほしい…
Avatar
omochimetaru 5/15/2018 2:22 AM
あー、リネームは成功してるのか。
2:23 AM
プロジェクトの方のエントリ情報が更新されてないから
2:23 AM
赤くなるのか。
2:23 AM
いや、逆か?どっちかだけが変わる。
Avatar
Kishikawa Katsumi 5/15/2018 2:23 AM
そうそう、ロールバック。老化で言葉出てこない。。。
Avatar
omochimetaru 5/15/2018 2:23 AM
@hiragram Refactor > Rename 便利だよ
Avatar
ちゃんと動いてない報告受けまくったあとその凶悪なレコメンドやばない
Avatar
omochimetaru 5/15/2018 2:24 AM
「ファイル名を先に手動で変更する」だけでちゃんと使えるぜ。
Avatar
草草の草
Avatar
omochimetaru 5/15/2018 2:24 AM
コードの書き換えの方はちゃんと動く。
Avatar
Kishikawa Katsumi 5/15/2018 2:24 AM
実際のファイル名が変更される部分以外はかなり感動的に動作します。
Avatar
たしかにファイル名以外はちゃんと動いてる
Avatar
Kishikawa Katsumi 5/15/2018 2:25 AM
Storyboardの中の変更もばっちりだし。
Avatar
あ゛
Avatar
それめっちゃ便利
Avatar
それはうれしい
Avatar
omochimetaru 5/15/2018 2:25 AM
たしかに。自作Viewとかちゃんとなる。
Avatar
typealias でRename動かなかったり、 func test() { typealias Alias = String _ = Alias(12) // こっちをリネーム } (edited)
😇 1
2:27 AM
結構バグはあります。
2:28 AM
ユーザ側ではなく、いったん宣言側に移動して、そこからリネームかけると正常に動きやすい。
😃 1
Avatar
metal 2 やってい方いますかね?
Avatar
Realm databaseのSwift版って開発遅れてたり、放置されてたりするんです・・・?
というのを聞かれまして、何か知っている方いましたらよろしくお願いします。 その理由として、 ・Documentに書いてあるSwiftのバージョンが1.2ぽい ・LatestのDocumentにあるリンクからダウンロードできるサンプルソースを解凍してできあがる realm-swift-3.5.0/examples/ios/swift-4.1 のディレクトリ内にあるProjectの設定がSwift3.3 らしいです。
🤔 1
Avatar
Kishikawa Katsumi 5/18/2018 8:53 AM
@shunkun 先月に3.5 https://github.com/realm/realm-cocoa/releases/tag/v3.5.0 がリリースされているので特に放置されてることはないですね。 根拠とされているドキュメントについては、更新もれなどはまあRealmに限らず割とよくある話かと思います。
realm-cocoa - Realm is a mobile database: a replacement for Core Data & SQLite
Avatar
ありがとうございます! ドキュメントは割とよくある話ですよね。 更新されていると言ってみます!
Avatar
どなたかご存知な方がいらっしゃれば相談させていただきたいです。 Cocoapodsライブラリに依存したCarthageライブラリを配布することはできないのでしょうか? Carthageでpodsライブラリの依存関係の解消まではできないため、podsライブラリもgitにプッシュしたところ、Carthageライブラリのcheckout、buildまではできました。しかし、そのCarthageライブラリを利用しようとすると、podsライブラリが参照できなかったという旨のdyld: Library not loadedの実行時エラーが出ます。
Avatar
できなそうな印象です
12:22 PM
そういうことを試したことないな、、
Avatar
pods対応しかされてないライブラリに依存するcarthageライブラリを提供するために、自前フォークしてCartfileを追加してる例を見たことがある気がします
Avatar
フォークしてCarthage対応すればできますね
Avatar
やはり自前で対応するしかなさそうですね。該当ライブラリはGPUImage、SwiftLint、SwiftGenなので SwiftLint、SwiftGenはCarthage移行はできないのでhomebrewのものを使うとしてGPUImageをなんとかできるかチャレンジしてみます。
Avatar
あれ、GPUImageってCarthage対応してなかったっけ。昔使った記憶が
12:31 PM
いや、むかしCocoaPodsつかってたかも
Avatar
swiftlintはそもそもシステムインストールするものだと思いますが、リント定義のバージョンズレなどを避けたいからですか? それともそれを使った自前の前処理ツールみたいなものを作るため?
Avatar
対応しているはずなんですが、carthage updateでエラーがでてしまうようで、、、
12:32 PM
こちらの理由です
リント定義のバージョンズレなどを避けたいからですか?
👌 1
Avatar
どんなエラーじゃろ。
Avatar
こんなエラーです $ carthage update --platform ios *** Fetching GPUImage *** Checking out GPUImage at "0.1.7" *** xcodebuild output can be found in /var/folders/62/nrp34pc96t550_hhml86hmwrr_q2rc/T/carthage-xcodebuild.MYLmCm.log *** Building scheme "GPUImageFramework" in GPUImage.xcodeproj Failed to write to /Users/snakagam/Desktop/MyLibrary/Carthage/Build/iOS/GPUImage.framework: Error Domain=NSCocoaErrorDomain Code=260 "The file “GPUImage.framework” couldn’t be opened because there is no such file." UserInfo={NSURL=file:///Users/snakagam/Desktop/MyLibrary/Carthage/Checkouts/GPUImage/build/ArchiveIntermediates/GPUImageFramework/BuildProductsPath/Release-iphoneos/GPUImage.framework, NSFilePath=/Users/snakagam/Desktop/MyLibrary/Carthage/Checkouts/GPUImage/build/ArchiveIntermediates/GPUImageFramework/BuildProductsPath/Release-iphoneos/GPUImage.framework, NSUnderlyingError=0x7f870a806a90 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
12:34 PM
“GPUImage.framework” couldn’t be opened
Avatar
うーん?
12:35 PM
なんだろう
12:36 PM
デスクトップでやってるのとか関係ないよなあ
Avatar
こちらの事例と似ているのですが、SYMROOTの削除では解決できませんでした https://github.com/Carthage/Carthage/issues/2389
carthage install method: [ ] .pkg, [ ] homebrew, [ ] source which carthage:/usr/local/bin/carthage carthage version: 0.29.0 xcodebuild -version: Xcode 9.2 Build version 9C40b Are you using --no-bui...
Avatar
Podsまで突っ込んでおいたりすればいけなくはないかもです (edited)
12:58 PM
でも場合によるかもしれない
1:02 PM
SYMROOTの件は、そのライブラリ側で削除する話なので、
1:03 PM
チェックアウトされてるGPUImageの0.1.7ではそれが対応されていないとかではないでしょうか (edited)
Avatar
SYMROOT消したら通りました
1:04 PM
あと、Podを使いたくない理由がxcodeprojに手を入れられたくない、っていう話なら参考になるかもしれないです https://qiita.com/kateinoigakukun/items/c9062caea630c71b4fc1
リポジトリのswiftlintのバージョンを固定したい時に。 Carthageはバイナリの配布をサポートしていないのでCocoaPodsで管理する。 が、他のライブラリをCarthageで管理している場合、バイ...
Avatar
お、ほんとですか
1:08 PM
SYMROOTの件は、そのライブラリ側で削除する話なので、 チェックアウトされてるGPUImageの0.1.7ではそれが対応されていないとかではないでしょうか
フォークして対応した方は新しいバージョンのタグを切りました
SYMROOT消したら通りました
こちらの差分と同様の対応でしょうか https://github.com/shtnkgm/GPUImage/commit/5e179f80b84837b38a8da731032c6ccc0df6ed02#diff-756457dc85f13450b3dfba2cbc1465e5
(edited)
Avatar
僕はそれで通りました
Avatar
なにかやり方がおかしいのかな。。。
Avatar
うーむ 🤔
1:21 PM
shtnkgm/GPUImage0773513209ae9f066db82497fd2342e0241d4fa2は通りました
Avatar
なんと!ちなみにcarthageバージョンはいくつでしょうか?
Avatar
0.29.0ですー
Avatar
同じですね
1:24 PM
違いがわからない 😇
Avatar
ちなみにXcodeのバージョンいくつですか?
Avatar
Version 9.3 (9E145)です
Avatar
同じだ。。。
Avatar
うーむ、 *** Cloning GPUImage *** Checking out GPUImage at "0.1.10" *** xcodebuild output can be found in /var/folders/62/nrp34pc96t550_hhml86hmwrr_q2rc/T/carthage-xcodebuild.5AWMmm.log *** Building scheme "GPUImageFramework" in GPUImage.xcodeproj Failed to write to /Users/snakagam/Desktop/MyLibrary/Carthage/Build/iOS/GPUImage.framework: Error Domain=NSCocoaErrorDomain Code=260 "The file “GPUImage.framework” couldn’t be opened because there is no such file." UserInfo={NSURL=file:///Users/snakagam/Desktop/MyLibrary/Carthage/Checkouts/GPUImage/framework/build/ArchiveIntermediates/GPUImageFramework/BuildProductsPath/Release-iphoneos/GPUImage.framework, NSFilePath=/Users/snakagam/Desktop/MyLibrary/Carthage/Checkouts/GPUImage/framework/build/ArchiveIntermediates/GPUImageFramework/BuildProductsPath/Release-iphoneos/GPUImage.framework, NSUnderlyingError=0x7fa56e662420 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
Avatar
あとはCarthageのDerivedDataを消すくらい??
Avatar
ちなみにこれは問題ないでしょうか https://github.com/Carthage/Carthage/issues/2220#issuecomment-377465217
BranchMetrics/ios-branch-deep-linking carthage package (https://github.com/BranchMetrics/ios-branch-deep-linking) seems to have trouble with 0.26.2, it builds fine, but the final copy step fails. I...
Avatar
ありがとうございます。uniqueに設定されていましたので問題なさそうです (edited)
1:33 PM
DerivedData削除しても同様のエラーでした🙇 rm -rf ~/Library/Developer/Xcode/DerivedData/
Avatar
Kishikawa Katsumi 5/21/2018 1:38 PM
Xcodeのビルドフェーズでpod installしたらいいんじゃないかな。 話を戻しちゃうけど。
Avatar
ライブラリ側のRun Scriptでpod installを実行する形でしょうか?
Avatar
Kishikawa Katsumi 5/21/2018 1:41 PM
いや、自分のプロジェクトです。
Avatar
うーんそもそも https://github.com/shtnkgm/GPUImage/commit/5e179f80b84837b38a8da731032c6ccc0df6ed02#diff-756457dc85f13450b3dfba2cbc1465e5 このコミットは関係なさそうです。変更してるのが、deploymen targetが4.3のターゲット(おそらくstatic library)なので、frameworkのターゲットではないので。 (edited)
Avatar
なるほど、、、ほかにSYMROOTの設定はなさそうです
Avatar
Kishikawa Katsumi 5/21/2018 2:46 PM
最初の議論から読みました。 1) 別のCocoaPodsでしか配布されてないライブラリB, C ,Dに依存した自分のライブラリAをCarthageで配布することは可能だと思いますが、 2) B, C, Dの依存の解決は使うプロジェクト自身でやってもらう必要がある、 というのが基本的な回答になるんじゃないでしょうか。 2の部分を頑張ろうとしてるように見えます。
Avatar
はい、 B, C, Dの依存の解決を行う方法がわからず、B,C,Dをpodsでの導入ではなくhomebrewやcarthage導入にする方法を検討していましたが、そのうちのGPUImageのCarthage対応がうまくできずという感じです。 B, C, Dの依存の解決は使うプロジェクト自身でやる方法が具体的にまだ理解できてないです。プロジェクトのビルド前にライブラリA側のpodfileを参照してpod installできればよさそうなのですが。 podsライブラリをすべてライブラリAのリポジトリにpushしておくという方法の場合、利用時に実行時エラーとなりました。
Avatar
Kishikawa Katsumi 5/22/2018 1:58 AM
B, C, Dの依存は実行時には存在しないので、そうなると思います。 そして、私はその解決は利用者がやるべきとする方が普通だと思います。 なので、そのライブラリAのセットアップ手順として、別途CocoaPods/Carthage/ビルド済みフレームワークなどで、B, C, Dをリンクしてください、と書いておく、とかがまあ基本かと思います。 そうはしたくないというのであれば、Carthageだとそれ以上は難しいと思います。 CocoaPodsだと任意のスクリプトを動かせる仕組みがあるのでなんとでもできますけど。
Avatar
ありがとうございます。まだ手動でリンクさせる方法が分かっていないので調べてみます。
Avatar
初めまして.Swift初心者の者です.よろしくお願いいたします! discord初心者でもありましたので使い方がおぼつかないかも知れませんがご容赦ください. Slackの方にも流させていただきましたが,Alamofireを用いてwikipediaから特定のタイトルのデータをJsonで取得しようとしましたが,エラーが発生してしまいました. 以下がSwiftのプログラムです. //parametersを定義 var parameters: Parameters = [ "action":"query", "prop":"revisions", "rvprop":"content", "format":"json", "titles":"tennis" ] var urlString = "https://en.wikipedia.org/w/api.php" //WikipediaAPIを通信する func getWiki() { Alamofire.request(urlString, method: .get, parameters: parameters, encoding: JSONEncoding.default,headers:nil) .responseJSON { response in debugPrint(response) } } 以下が出力されたエラーの部分です [Result]: FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.})) [Timeline]: Timeline: { "Request Start Time": 548742968.775, "Initial Response Time": 548742970.085, "Request Completed Time": 548742970.088, "Serialization Completed Time": 548742970.106, "Latency": 1.309 secs, "Request Duration": 1.312 secs, "Serialization Duration": 0.018 secs, "Total Duration": 1.330 secs } Restlet client でAPIの動作自体を確認しましたが,上のパラメーターで無事にテニスに関する記事が取得できたので,おそらくAlamofireの使い方が間違っている可能性が高いと考えています. どなたかご教授いただけますと幸いです.どうぞよろしくお願いいたします. (edited)
Avatar
omochimetaru 5/23/2018 4:45 AM
(コードブロックはシングルクォート( ' ) ではなくバッククォート(`)ですよ。)(あ、治った) (edited)
Avatar
すみません,研究室のPCがENキーボードでバッククォートがどこかわかりませんでしたorz
Avatar
omochimetaru 5/23/2018 4:53 AM
同じクエリをCURLで発行してからjqにかけてみましたが、 ちゃんと動きますね。 プログラム自体に何か問題がありそう。 curl "https://en.wikipedia.org/w/api.php" -G -d action=query -d prop=revisions -d rvprop=content -d format=json -d titles=tennis > a.json cat a.json | jq
Avatar
同じくPlaygroundで実行してみましたが、貼られたコードは正常に動きましたね。 (edited)
Avatar
omochimetaru 5/23/2018 4:56 AM
あ〜AlamofireのPlaygroundとかあるのか。
Avatar
いや、自分はgithubからalamofireのproject取って来て、そこにPlaygroundぶち込んでimportしましたw (公式Playgroundあるのかな…) (edited)
Avatar
omochimetaru 5/23/2018 4:59 AM
なるほど
Avatar
QiitaのAPIにクエリを投げた時は日本語がエンコードされてない状態でしたがゲットすることができました.ここら辺が混乱している原因の一つでした...
👍 1
Avatar
先ほどの問題解決しました!多分JSONの形式ではなくStringないしはXMLのような構造でエンコーディングする必要があるみたいでした.おそらくオープンソースのサイトなのでそこまでかっちり構造決まってないようでした.
Avatar
omochimetaru 5/23/2018 7:11 AM
wikipediaのapi.phpは "format":"json"を与えることでJSONで落ちてくるみたいですけど (edited)
7:12 AM
具体的には上記のコードをどのように修正したら解決しました?
Avatar
encodingを消してresponseJSONの部分をresponseStringに変更しました.
Avatar
omochimetaru 5/23/2018 7:15 AM
なるほど。
Avatar
レスポンスは汚い形でしたが記事の内容が帰ってきました.もう少しencodingの部分を考慮すればもっと綺麗な形でレスポンスが得られると思います.もう少しやってみようと思います.
Avatar
あーこれわかった [Result]: FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(...
9:19 AM
encoding:部分不要ぽいですね。 func getWiki() { Alamofire.request(urlString, method: .get, parameters: parameters) .responseJSON { response in debugPrint(response) } } これで正しくJSON返ってくる
Avatar
ほんとですね!!試したと思っていたのですが,やっていなかったようでした.ありがとうございます!!
👍 1
Avatar
16777216 個の要素の配列を作ろうとしたら EXC_BAD_ACCESS で落ちてしまうのですが、どうしたらいいでしょう 😅
Avatar
すいません、前にも似たような質問してこちらを教えて頂いてました 🙇 https://developer.apple.com/library/content/qa/qa1419/_index.html
QA1419: Describes methods for setting the stack size of a process and/or thread.
Avatar
GomaIsNiceGuy 5/30/2018 10:29 AM
folding-cell - :octocat: 📃 FoldingCell is an expanding content cell with animation inspired by folding paper card material design. Swift UI Library by @Ramotion
10:30 AM
Developers.IOは、AWS、iOS/Androidアプリ、ビッグデータ、Alexa等の最新技術情報からリモートワークや働き方に関する記事まで多彩なトピックを紹介するクラスメソッドのオウンドメディアです。
10:31 AM
このライブラリを使って下のサイトの解説付きで作ろうと思ってるのですが、Outlet接続の項目でつまずきました。
10:32 AM
10:34 AM
10:35 AM
4つとも同じエラーが出てしまいました。
10:35 AM
よろしければ教えていただきたいです。よろしくおねがいします
Avatar
Kishikawa Katsumi 5/30/2018 10:37 AM
直接のエラーの原因はもともとweakが付いていないプロパティを、weakにしてオーバーライド(再定義)できないというものですが、 (edited)
10:38 AM
Cellを継承したViewControllerを作ろうとしているので、その辺から何か間違えてないですか?
Avatar
GomaIsNiceGuy 5/30/2018 10:52 AM
参考のサイト通りの手順で行ったのでよくわからないです..
Avatar
Kishikawa Katsumi 5/30/2018 10:57 AM
@GomaIsNiceGuy サイトの内容も確認しましたけど、上のようなコードになる手順ではないので、間違えていると思いますよ。 もう一度サイトの内容を見直してゆっくりやってみたらどうでしょうか? 特に
  • FoldingCellを継承したクラスの作成
  • Outlet接続
のセクションを読み間違えていると思います。
(edited)
Avatar
GomaIsNiceGuy 5/30/2018 11:01 AM
11:03 AM
この画面の右側が上の画像のようにバーって表示されてないのは何故なのですか??
11:04 AM
右クリック→Refarencing Outletで表示出来ました
11:04 AM
ありがとうございます
Avatar
Kishikawa Katsumi 5/30/2018 11:30 AM
Xcodeの操作は初見ではわかりにくいので、その辺が解説されている入門書を読まれると良いかもしれません。
Avatar
GomaIsNiceGuy 5/30/2018 2:04 PM
2:04 PM
なんどもすいません。このエラーはどうゆうものですか??
Avatar
omochimetaru 5/30/2018 2:36 PM
SampleCell型がselectedAnimationメソッドを持ってないって書いてあります
Avatar
Kishikawa Katsumi 5/31/2018 2:41 AM
^ となる理由はおそらくSampleCellがFoldingCellを継承できていないのだと思います。
Avatar
omochimetaru 5/31/2018 4:40 AM
(記事が古いのでライブラリのバージョンが上がっててメソッド名が変更されてるとかもありえそう)
Avatar
(1個目の引数名がデフォルトでラベルとして使うかどうかとかか
Avatar
GomaIsNiceGuy 5/31/2018 5:25 AM
解決しました。問題はメソッド名が変更されていたことでした。ありがとうございました。
5:39 AM
5:40 AM
このソースをそのまま貼って足りないライブラリimportしたんですけど、このエラーは一体なんなのでしょうか??
Avatar
Kishikawa Katsumi 6/1/2018 6:04 AM
Init(...)という関数が見つからないというエラーです。Use of unresolved identifier Initなので、Initを呼び出しているけどどこにも見つからなかった、というエラーです。 ConfigurationBlock.swiftで定義されている関数なのでそのファイルを忘れてませんか? (edited)
Avatar
GomaIsNiceGuy 6/1/2018 6:24 AM
6:24 AM
これですか??
Avatar
Kishikawa Katsumi 6/1/2018 6:26 AM
はい、そのファイルです。
Avatar
GomaIsNiceGuy 6/1/2018 6:28 AM
あ、Initありますね!
6:32 AM
加えたところAttribute can only be applied to types, not declarations
6:33 AM
to
6:33 AM
と、出てきました。
Avatar
2016年のソースだからSwift 2文法ののソースですね
6:45 AM
定義が Init(value: になっているから、使う側も今のSwiftの文法なら Init(value: で呼び出す必要がありますね、昔Swift 2までは一つめの引数がデフォルトでラベルとして使わなかったので
Avatar
omochimetaru 6/1/2018 6:46 AM
@noescape が怒られてるんじゃないか?
Avatar
Kishikawa Katsumi 6/1/2018 6:47 AM
@GomaIsNiceGuy たぶん古い解説記事やソースコードを見るより、 https://github.com/Ramotion/folding-cell 本体のリポジトリのDemoやREADMEをみた方が良いと思います。
folding-cell - :octocat: 📃 FoldingCell is an expanding content cell with animation inspired by folding paper card material design. Swift UI Library by @Ramotion
Avatar
omochimetaru 6/1/2018 6:47 AM
今だと @escaping ってクロージャ型の左側(コロンの右側)に書くけど
6:47 AM
Swift2だとラベルの左側に書いてたんだよね。
Avatar
Kishikawa Katsumi 6/1/2018 6:47 AM
Swift 2, 3, 4の違いを直していくのはまだ無理だと思います。
Avatar
GomaIsNiceGuy 6/1/2018 6:47 AM
そこは標準でついているとwarning出てたので外しました
Avatar
GomaIsNiceGuy 6/1/2018 9:08 AM
Demo見ながらやっていきます。ありがとうございました
Avatar
Swiftは,クラス変数のオーバライドはできないんですよね・・・・? 毎回言ってる気がする.
Avatar
出来るのでは
Avatar
セルのデザインを何種類か試したい時とかに使いたいんですが・・・・・.
1:42 AM
え?できんの?
Avatar
元々がget onlyならget only、 setもあるならsetも書けば出来るはず
Avatar
class ResCell: UITableViewCell { static var textViewLeftMargin: CGFloat { return 16 } } class ResCell2: ResCell { /// override static var textViewLeftMargin: CGFloat { return 8 } } これ書いたら,怒られた.static varはoverrideできんと.
1:44 AM
これ間違ってますか?
Avatar
Kishikawa Katsumi 6/2/2018 1:44 AM
static変数とclass変数は違います。
1:45 AM
staticは継承されない。
Avatar
あ、そっちか。class varにすればできるはず
Avatar
classとstaticは違うのか
1:45 AM
ごめんなさい,全然理解してない
Avatar
Kishikawa Katsumi 6/2/2018 1:46 AM
class変数は実質クラスメソッドみたいなものですね。
Avatar
今試してるんですがなんか怒られますね
Avatar
なんだろう,これはstaticは,継承によって挙動が左右されないことを保証するためにあるってことですかね
Avatar
Kishikawa Katsumi 6/2/2018 1:46 AM
上の例はComputed propertyだからclassにしたらできそうに見えますね。
Avatar
あいやいけた
1:47 AM
typoしてた、すません
Avatar
classにしたらいけました
1:47 AM
なんだろう,これはstaticは,継承によって挙動が左右されないことを保証するためにあるってことですかね 心は,こういうこと?
Avatar
Kishikawa Katsumi 6/2/2018 1:47 AM
「継承によって挙動が左右されないことを保証するためにある」かどうかはわからないですね。
Avatar
ぬう
Avatar
どっちかといえばstaticの方が使う気がする
1:48 AM
継承とかやりたい場合だけclassが出てきますけど、あんまり継承使わないから殆どstaticです
Avatar
なるほど
Avatar
class ResCell: UITableViewCell { class let textViewLeftMargin: CGFloat = 16 } classでもlet宣言はoverrideできないとかある
Avatar
ありがとうございましたー 勉強になりました.
Avatar
norio_nomura 6/2/2018 1:55 AM
class内のstaticfinal classですよね。
Avatar
意味的にも完全に一致してるのかな
Avatar
static = final class で納得
Avatar
Taketo Sano 6/2/2018 2:52 AM
(今別の質問しても大丈夫な流れです?)
Avatar
いいんじゃないですか
2:53 AM
だいたい終わったような
Avatar
Taketo Sano 6/2/2018 2:53 AM
恐縮です 🙇
2:54 AM
parametrized conformance を実現するために protocol をでっち上げて後付けで conform させるというのをやっているのですが、それを入れたことで元々問題なかったところにおかしなエラーが出て困っています 😟 https://github.com/taketo1024/SwiftyMath/blob/WTF/Sources/SwiftyHomology/Basics/ModuleObject.swift#L279 (edited)
SwiftyMath - Pure Math in Pure Swift.
2:56 AM
public protocol IntModuleObjectType: ModuleObjectType where R == 𝐙 { ... } extension ModuleObject: IntModuleObjectType where R == 𝐙 {} この 297 行目でコメントアウトしてる部分を外すと、 100 行目で Binary operator '==' cannot be applied to operands of type '_Matrix<Dynamic, Dynamic, R>' and '_Matrix<Dynamic, Dynamic, ModuleObject.R>' (aka '_Matrix<Dynamic, Dynamic, Int>') と勝手に R == Int と仮定されて怒られているようです 😟 (edited)
2:58 AM
原因や回避策など分かる方いたらご教示ください 🙇
Avatar
ブランチ名w
3:12 AM
IntModuleObjectTypeがModuleObjectTypeのconditionを持っているのが原因ぽいすね、独立させればコンパイルは通りました
3:13 AM
protocolで継承関係作ると色々なところで罠を踏むので、二つのprotocolは独立に作って、両方実装することでデフォルト実装が使えるようになる、みたいな形にしておくと罠を踏まずに済むことが多い印象があります
Avatar
Taketo Sano 6/2/2018 3:18 AM
おぉッ、やってみます。
3:21 AM
おぉ、ほんとですね…!
3:21 AM
protocol の継承使いまくってるのでいつ世界が崩壊するか分からないのは不安です 😂
Avatar
使わないようには出来ませんか?
Avatar
Taketo Sano 6/2/2018 3:23 AM
このケースでは問題ないですが、プロジェクト全体でたくさん使ってます。
Avatar
関数の宣言や実装は_Fieldみたいにアンスコつきにしておいて、利用者側に晒すprotocolをField: _Field, _EuclideanRing...のようにするとかで
3:24 AM
罠を回避しつつ使い勝手は変わらない世界を構築できるかも
Avatar
Taketo Sano 6/2/2018 3:27 AM
うーむ、なるほどです…
3:27 AM
あまり裏技使い過ぎると自分でも分からなくなりそうなので、いずれ治ることを望みつつ世界が崩壊したら随所対応してく感じにします… 😂
Avatar
Taketo Sano 6/2/2018 4:12 AM
問題なく直せました!感謝ですswiftswift
swift 1
Avatar
GomaIsNiceGuy 6/2/2018 11:36 AM
//#selectorはovjective-cだから頭に@objcをつける @objc func refreshHandler() { //deadlineTimeに1秒の遅延を追加 let deadlineTime = DispatchTime.now() + .seconds(1) DispatchQueue.main.asyncAfter(deadline: deadlineTime, execute: { [weak self] in if #available(iOS 10.0, *) { self?.tableView.refreshControl?.endRefreshing() } self?.tableView.reloadData() }) }
11:36 AM
11:36 AM
DispatchQueue.main.asyncAfter(deadline: deadlineTime, execute: { [weak self] in if #available(iOS 10.0, *) { self?.tableView.refreshControl?.endRefreshing()
11:37 AM
ってどうゆう意味ですか??
Avatar
@GomaIsNiceGuy deadline で指定された時間に main キューで execute のクロージャ式の中身を実行という意味ですね。 (edited)
2:20 PM
DispatchQueue についてちゃんと理解するためには↓あたりを読むと確実です。(もし並行処理について詳しくなければ Introduction から読んだ方が良いです。が、並行処理はそれだけで本が一冊書けるような分野なので、まずは日本語で並行処理について書かれた本を読んで概念を習得した方が良いかもしれません。) https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1
Explains how to implement concurrent code paths in an application.
Avatar
norio_nomura 6/2/2018 2:27 PM
Concurrency Programming Guideは日本語版PDFがあります。 https://developer.apple.com/jp/documentation/ConcurrencyProgrammingGuide.pdf
🙏 1
👍 1
Avatar
ここのチャンネルで聞くべきかどうか迷いましたが、iOSアプリ開発・配布が初めてなのでここで質問させていただきます。 お客様の社内アプリをinHouse配布するのに、お客様に『iOS Developer Enterprise Program』のライセンスを取っていただいて行う予定です。 このときに、お客様の許可が得られるか、アプリがどのようなものなのか、またお客様側の知識・技術がどのくらいあるかにもよると思いますが、どのように配布すればいいか色々調べてもわかり辛く、迷っています。 サポートセンターに聞いた例を見てみても、堂々巡りになっていることもあるようなので、一度こちらでお伺いさせていただきたいと思いました。 (1)自社のアカウントをチーム管理者として登録していただいて、こちら側から定期的に更新を行う (2)ソースをそのままお渡しして、お客様側端末でコンパイルしていただく (3)証明書情報などをコンパイル時に教えていただいて、こちらでコンパイルを行う 調べてみた結果、方法としては以上のものくらいかなと考えているのですが、皆様はどのような方法を取られていらっしゃいますか。 ちなみに今回配布する予定のものは、元々Androidアプリとして作成しているものをiOS端末の普及に伴いiOS用にも移植するもので、Android版は既に6年程使っていただいています。またAndroid版は、何度か業務変更による改修も入っています。 今回のiOS版も、同じく長期間使っていただく・時折改修が入ると思うので、理想としては(1)の方法なのかなと考えてはいます。
Avatar
クライアントさんが将来的に開発ベンダーを切り替える可能性も考えると、クライアントさんにEnterpriseプログラムに入っていただいて、御社のアカウントををDeveloperとしてチームに追加していただくのがおそらく双方にとって一番楽な方法かと思います
1:54 PM
Enterpriseで配布まで試したことがまだないので具体的にどうすればいいかアドバイスできませんが、おそらくDeveloperとして追加してもIn House Distributionはできるはずかと思います 🤔
Avatar
状況とお客様側の知識とかで変わるけど、個人的に自分が楽できる方法を選ぶなら(2) お客様が「よくわからん!ビルドってなんだアーカイブってなんだ!エラー出たどうしたらいい!?」みたいな知識であれば(1)。ただこの場合、知識なくてもipa作れるように手順書作ったり、サポートすること考えると別途費用請求したい… (edited)
Avatar
(1)は(お客さんに承認はとるとして)自分で実機をDevicesに追加できるというメリットがありますね。実機デバッグで困りにくい。アプリの更新環境を作る作業はそこそこの手間なので、そこは見積もりに入れるとして。
Avatar
CI系のサービス使えるなら自動でipa作成とかまでやりたい系の内容だなー
Avatar
ご回答、有難うございます。 @lovee 証明書とかプロビジョニングプロファイルのことを考えると管理者じゃないと無理なのかと思っていたのですが、開発者でもIn House Distribution 出来るのですね。 https://developer.apple.com/jp/documentation/IDEs/Conceptual/AppDistributionGuide/ManagingYourTeam/ManagingYourTeam.html ここを見た感じだと、開発者はプロビジョニングプロファイルについては開発用のものは作れないけれども、チームのものは作れるようなので、これが配布のときに使えるんですね。 @ありぜ 今のところ、お客様の側にもシステム系の方がいらっしゃるのは把握しているのですが、どの程度なのかが微妙でして。今までのシステムに関しても、環境構築とかリリースとか保守とか完全にこちらがごっそり受け持っているため、やはり(1)が可能ならば無難なのかもしれないです。 ipa作成手順書、作ることも考えないといけなさそうです。 @hirobe 実機デバッグに関しては、基本的には開発時にこっちで端末を直接つないで落としてきてやれば良いかなと思っていたので、あまり重要視していませんでした。 ADEPでのIn Houseでの配布について、自社の場合はともかく顧客側のものを配布するとなると、証明書などを定期的に更新する必要がある部分がやはりネックになってきますね。
アプリケーションを開発、テスト、配布する作業の流れを説明しています。
Avatar
omochimetaru 6/10/2018 2:53 PM
内部利用アプリをEnterpriseビルドで提供するのはうちの会社もよくやっていますが1年に1回のリビルドが必要で、そのときにSwiftやXcodeが新しくなってるので、対応と動作チェックが必要なのは面倒ですねえ。
Avatar
証明書とかプロビジョニングプロファイルのことを考えると管理者じゃないと無理なのかと思っていたのですが、開発者でもIn House Distribution 出来るのですね。
管理者じゃないと配布用証明書が作成できないので、管理者以上の権限付与してもらわないと無理ですね。 まぁこれに関しては別途お客様に証明書作ってもらって、開発機にインポートするという手もあります。
(edited)
Avatar
配布用証明書の作成、そういえば以前調べたときにここがあって管理者にしてもらわないとと思ったような気がします。 結構前だったので、すっかり忘れておりました。 証明書やプロビジョニングプロファイルをお預かりできるなら、これらの作成手順書を作って、必要なとき(1年毎)にこれらのファイルを毎度送っていただくことになるんですよね。 omochimetaruさんがおっしゃっているように、結局毎回新しいSwift・XCodeで動作確認しなくてはいけませんし、仕方がないとはいえ手間がかかりますね。
Avatar
うちはApp Storeに出しているアプリを一部カスタマイズしたものをお客様のIn Houseで提供することがあるのですが、その時はだいたい (3) みたいですね。カスタマイズ部分以外の既存開発部分については、ライセンス的にお客様に提供できないソースもあって (2) はできないんですよね。
Avatar
今回のアプリは完全にお客様の業務内容に特化したもので、ソースを丸々渡すのは特にライセンス的にも問題ない感じです。 どの方法で配布を行うかは、やはりケースバイケースということですよね。 皆様、ご意見本当にありがとうございます。
Avatar
私も(3)にしてます。お客様のEnterpriseアカウントで複数アプリ・複数ベンダーとなったときに個々のアプリの都合で証明書いじられると困りそうなので、証明書管理はお客様にがんばってもらうようにしています(支援はしますが)。 更新時の新しいSwift, Xcodeについては、本当に期限の延長だけで改修がないなら、前の納品に署名だけ(+あとビルド番号とか)つけかえて出すというのができます(基本的にはfastlane sigh resignとかなんですが、罠はあるので注意が必要、、、)。
Avatar
確かに現時点だとそもそもiOS機を取り入れたばかりでうちの会社しかアプリを納品する予定がない状態ですが、今後増えたときのことも考える必要がありますね。 こちらを見ると配布用証明書は複数生成できるとのことなのですが、アプリごとに証明書を分けて生成するということはできないんでしょうか。 https://developer.apple.com/jp/documentation/IDEs/Conceptual/AppDistributionGuide/DistributingEnterpriseProgramApps/DistributingEnterpriseProgramApps.html
アプリケーションを開発、テスト、配布する作業の流れを説明しています。
Avatar
あれっ配付用証明書は複数作れない認識で(期限近いときにダブらせられるだけと思っていた)、そうしていたんですが、もしかして好きなだけ作れるんですかね・・・
Avatar
Distribution証明書は最大3つまでだったはずです なので、Expireしないように更新用で2枠は基本使いたいところ… (edited)
😮 3
Avatar
>Distribution証明書は最大3つまでだったはずです そうだったのですね。証明書の最大数についての情報を見かけたことがなくて、アプリごとにそれぞれ発行していけるのかなと思っていました。
Avatar
専用アプリの配信にはVPP Custom B2Bという方法もあり、そちらを使うと証明書のやりとりや、プロビジョニングプロファイルの期限切れなどに悩まされることはなくなります。 (ただし、ストア経由にはなるのでAppleの審査が入ります) こちらは検討されましたか?
4:04 AM
↑もとのAndroid版が完全な社内アプリだと審査を通すための手間の方が大変かもしれないですね・・
Avatar
VPP Custom B2BだとAppleの審査が入るので、おっしゃる通り完全な社内アプリのため断念致しました。
Avatar
配布方法はMDMでのIn-house配布(Push配布もしくはStore形式でのpull配布)などでしょうか?アプリの配信だけでなくプロビジョニングプロファイルのみのリモート更新も可能なMDMもあるかと思います。
Avatar
配布方法は、今回のアプリとも連動するWebアプリケーション(こちらもAndroid版と一緒に6年前に作成したシステムです)がありまして、そちらでダウンロードページを用意して行うようにする予定です。 Android版は既にそのようにしているので、出来るだけ揃えたいと考えています。 (edited)
Avatar
https://github.com/taketo1024/SwiftyMath 今まで普通にビルドが通っていたものが、 1. While running pass #509 SILModuleTransform "Mandatory Inlining of Transparent Functions". <unknown>:0: error: unable to execute command: Abort trap: 6 <unknown>:0: error: compile command failed due to signal 6 (use -v to see invocation) と出て通らなくなってしまいました 😵 コミットを過去まで遡ってもダメなので、恐らく Xcode のバージョンをあげたことによるものだと思うのですが、原因のわかる方いたらお助けください 🙏 (edited)
SwiftyMath - Pure Math in Pure Swift.
Avatar
最近 mac の調子が悪いし僕の xcode が壊れてるのかもしれません 😫 (edited)
Avatar
omochimetaru 6/12/2018 3:15 AM
Cleanはしましたか?
Avatar
はい、xcode で clean build folder してビルドしても、 swift package clean して swift build してもダメでした orz
Avatar
omochimetaru 6/12/2018 3:17 AM
Abort trap: 6ってことはコンパイラがクラッシュしてるので、コンパイラのバグを踏んだかもしれませんね、環境はXcode Version 9.4 (9F1027a)?
Avatar
Version 9.4 (9F1027a)
3:17 AM
です。
3:17 AM
昨日は普通にできてたんですが…
3:22 AM
ホントはやっちゃいけない、generic type つき typealias の extension をやってるのが原因かもしれません(これまでビルド通ってたので放置してた)
Avatar
norio_nomura 6/12/2018 3:25 AM
クラッシュ再現しないです。
Avatar
omochimetaru 6/12/2018 3:25 AM
[omochi@omochi-iMac-PC43 SwiftyMath (master=)]$ swift build Compile Swift Module 'SwiftyMath' (70 sources) Compile Swift Module 'SwiftyLieGroups' (12 sources) Compile Swift Module 'SwiftyHomology' (10 sources) Compile Swift Module 'SwiftyKnots' (9 sources) Compile Swift Module 'SwiftyTopology' (15 sources) Linking ./.build/x86_64-apple-macosx10.10/debug/libdSwiftyMath.dylib Compile Swift Module 'Sample' (1 sources) Linking ./.build/x86_64-apple-macosx10.10/debug/Sample [omochi@omochi-iMac-PC43 SwiftyMath (master=)]$ swift --version Apple Swift version 4.1.2 (swiftlang-902.0.54 clang-902.0.39.2) Target: x86_64-apple-darwin17.6.0
3:25 AM
こちらもビルドできた。
Avatar
げげ😫
3:28 AM
やっぱ本格的に mac が壊れてきてるのかな…
Avatar
Kishikawa Katsumi 6/12/2018 3:29 AM
とりあえずDockerでビルドしてみては。
Avatar
norio_nomura 6/12/2018 3:29 AM
Swift 4.2だとクラッシュはしないけどビルド出来ない。 (edited)
Avatar
4.2 だとダメなんですかね…
3:32 AM
Group.swift のコンパイルでコケてるのですが、 https://github.com/taketo1024/SwiftyMath/blob/824225ca51c1fdeb15c3fe089d1ebcc2f954b9ce/Sources/SwiftyMath/Abstract/Group.swift#L89-L91 この3行をコメントアウトして fatalError() にするとそのファイルでコケるのは無くなりました。
SwiftyMath - Pure Math in Pure Swift.
3:32 AM
var unions: Set<Set<Self>> = Set() ... return unions .sorted{ $0.count < $1.count } .map{ FiniteSubgroupStructure(allElements: $0) } (edited)
Avatar
omochimetaru 6/12/2018 3:32 AM
Xcode9.4はSwift4.1じゃない?
Avatar
あ、ほんとだ、4.1 でした。
Avatar
norio_nomura 6/12/2018 3:34 AM
とりあえずswift-4.2-DEVELOPMENT-SNAPSHOT-2018-06-11-aだと $ docker run --privileged -it -v `pwd`:`pwd` -w `pwd` --rm norionomura/swift:swift-4.2-branch swift test Compile Swift Module 'SwiftyMath' (70 sources) /Users/norio/github/SwiftyMath/Sources/SwiftyMath/Matrix/SquareMatrix.swift:18:1: error: conditional conformance of type '_Matrix<n, m, R>' to protocol 'Ring' does not imply conformance to inherited protocol 'Monoid' extension SquareMatrix: Ring where n == m { ^ /Users/norio/github/SwiftyMath/Sources/SwiftyMath/Matrix/SquareMatrix.swift:18:1: note: did you mean to explicitly state the conformance like 'extension _Matrix: Monoid where ...'? extension SquareMatrix: Ring where n == m { ^ error: terminated(1): /usr/bin/swift-build-tool -f /Users/norio/github/SwiftyMath/.build/debug.yaml test output: になります。 (edited)
Avatar
むむむ…
3:35 AM
それはまた原因が違いそうな…
3:37 AM
それはきっとこれですね
ホントはやっちゃいけない、generic type つき typealias の extension をやってるのが原因かもしれません(これまでビルド通ってたので放置してた)
(edited)
Avatar
昨日は普通にできてたんですが… クラッシュ再現しないです。 こちらもビルドできた。 Abort trap: 6ってことはコンパイラがクラッシュしてるので、コンパイラのバグを踏んだかもしれませんね コンパイラのメモリ関連バグ?マシン再起動したら直ったりしませんか? (edited)
Avatar
お、そうだ、それを試してみます(基本的なとこ抜けてました)
Avatar
norio_nomura 6/12/2018 3:40 AM
とりあえずリポジトリにCIを設定した方がいいんじゃないかな。
3:42 AM
CIが設定してあれば、ローカルマシンの問題なのかどうか直ぐにわかる。
Avatar
再起動したらコンパイル通りました 😂 お騒がせしてすみません 🙇
3:43 AM
なるほどです > リポジトリにCIを設定
Avatar
omochimetaru 6/12/2018 3:43 AM
マシン再起動で治るの・・・
3:43 AM
そういう事もあるのか。
Avatar
最近だいぶ壊れてきてるっぽいです。夜な夜なハードな計算回しすぎたかな… 😫
3:45 AM
NVRAMリセット、SMCリセット、Disk の First Aid は試してみたんですが、相変わらず突然ブラックスクリーンになったりします…
Avatar
メモリが部分的に逝ってそうな気配
Avatar
CI は Travis CI が良いんでしょうか(何も知らない)
Avatar
omochimetaru 6/12/2018 3:46 AM
Travisだけならやったことあるけど簡単だしおすすめです
Avatar
おっしゃ、入れてみます💪🏿
3:48 AM
https://support.apple.com/kb/PH25696?viewlocale=ja_JP&locale=fr_FR とりあえず Apple 診断 やってみます。
macOS を使用して Mac が起動しない場合でも、「Apple 診断」または「Apple Hardware Test」を使用して起動できる場合があります。
Avatar
Kishikawa Katsumi 6/12/2018 3:49 AM
OpenSourceプロジェクトならTravisはもっとも柔軟性が高いという意味で最強だと思います。MacとLinux同時に使えるし。 (edited)
Avatar
norio_nomura 6/12/2018 3:53 AM
そういえば少し前にtravis.comが対応したGitHubのchecksってまだ試したことがないな。
3:54 AM
新規でリポジトリにTravis-CIを設定しようとすると、以前のtravis.orgではなくtravis.comになるのかな?
3:57 AM
確か、OSS向けもtravis.comになったんだよね。
Avatar
Hardware Test も起動しないのでもうダメっぽいです🙅‍♂️とりあえず色々ありがとうございました🙇‍♂️
6:53 AM
唐突にすいません TableViewCellにマージンをかける方法とかってありますか? 理想は上の画像みたいにしたいです
Avatar
Kishikawa Katsumi 6/12/2018 6:54 AM
簡単でおすすめなのはTableViewCellに一回り小さなビューを載せることです。
Avatar
オートレイアウトなら layoutMarginsGuide があります
6:56 AM
というか通常ならCellに contentView があって、それはlayoutMarginsの中にあるじゃなかったっけ 🤔 詳しい仕様忘れましたが (edited)
Avatar
お二人とも、ありがとうございます! 早速試してみます!
Avatar
し、しんでる
Avatar
先ほどの問題ですが、やはりハードウェアに問題があるようでした😑
3:52 PM
これはハードウェアテストモードです😑
Avatar
TestResultにerrorって書いてますね
Avatar
はい😑w
3:53 PM
ハードウェアがイカれてビルドが通らないケース初めてだったので良い経験になりました😂
3:59 PM
4MEM というエラーコードはメモリが一部死んでる系のエラーのようです。@ありぜ さんの言う通りでした😂
😱 4
😂 1
Avatar
omochimetaru 6/12/2018 4:00 PM
こんなことあるんですね
😂 2
Avatar
protocol HogeProtocol { } struct Hoge: HogeProtocol { func setHoge() {} } struct Fuga: HogeProtocol { func setFuga() {} } enum Foo { case hoge case fuga func getHogeProtocol() -> HogeProtocol { switch self { case .hoge: return Hoge() case .fuga: return Fuga() } } } // use let hoge = Foo.hoge.getHogeProtocol() // HogeProtocol型 hoge.setHoge() // NG FoogetHogeProtocol() の返り値で各structの型を返したいのですが、HogeProtocol型になってしまいます。 各structの型を返す方法はありますでしょうか。
Avatar
@swiftbot protocol HogeProtocol { } struct Hoge: HogeProtocol { func setHoge() {} } struct Fuga: HogeProtocol { func setFuga() {} } enum Foo { case hoge case fuga func getHogeProtocol<T : HogeProtocol>() -> T { switch self { case .hoge: return Hoge() as! T case .fuga: return Fuga() as! T } } } // use let hoge: Hoge = Foo.hoge.getHogeProtocol() // HogeProtocol型 hoge.setHoge() // OK
🛠 1
Avatar
swiftbot BOT 6/15/2018 8:16 AM
Author icon
koher
protocol HogeProtocol { } struct Hoge: HogeProtocol { func setHoge() {} } struct Fuga: HogeProtocol { func setFuga() {} } enum Foo { case hoge case fuga func getHogeProtocol<T : HogeProtocol>() -> T { switch self { case .hoge: return Hoge() as! T case .fuga: return Fuga() as! T } } } // use let hoge: Hoge = Foo.hoge.getHogeProtocol() // HogeProtocol型 hoge.setHoge() // OK
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
@shunkun ↑これが良い設計だとは思いませんが、↑のようにできないことはありません。
8:17 AM
せめて func getHogeProtocol<T : HogeProtocol>() -> T? にして as? T にすべきだとは思いますが。
Avatar
ジェネリクスにするとできるのですね!ありがとうございます。 設計の問題ですかね...
Avatar
omochimetaru 6/15/2018 8:20 AM
protocol HogeProtocol { } struct Hoge: HogeProtocol { func setHoge() {} } struct Fuga: HogeProtocol { func setFuga() {} } enum Foo { case hoge case fuga func getHogeProtocol() -> FooHogeProtocolValue { switch self { case .hoge: return FooHogeProtocolValue.hoge(Hoge()) case .fuga: return FooHogeProtocolValue.fuga(Fuga()) } } } enum FooHogeProtocolValue { case hoge(Hoge) case fuga(Fuga) } @shunkun こうするのはどうですか
8:20 AM
switch foo.getHogeProtocol() { case .hoge(let hoge): // なにかする case .fuga(let fuga): // なにかする } これで型安全です
Avatar
型安全は魅力的なのですが、 enum Foo { case hoge case fuga } で、どっちかを最初に選んで使うので、選んだ後に場合分けが入ってしまうと使うの側のコードが増えてしまうなと言う印象なのです... (edited)
Avatar
omochimetaru 6/15/2018 8:23 AM
「各structの型を返したい」時点で場合分けは必要な気がします。
8:24 AM
protocolで返すなら共通の処理がその後ろに書けます。
8:25 AM
ちなみに、enum FooHogeProtocolValueHogeProtocol に準拠させれば、分岐消せますね。 (edited)
Avatar
omochiさんので大丈夫そうでした!
8:28 AM
教えてもらった方法でやって見ます!ありがとうございます!
✌ 1
Avatar
@shunkun >> これが良い設計だとは思いませんが
設計の問題ですかね...
ジェネリックにするとタイプセーフにならないので、の意でした。
Avatar
そうですね。一応、T が HogeProtocolに準拠したものしか取らないので少しは安全ではありますね。
Avatar
omochimetaru 6/15/2018 8:52 AM
caseとの組み合わせが違う場合もクラッシュしまっせ
😳 1
Avatar
設計の問題かと思って見直した結果、enumで返すメソッド持つのやめました😇
🙂 1
8:53 AM
たしかに let hoge: Fuga = Foo.hoge.getHogeProtocol() だとクラッシュですね...
Avatar
素朴な疑問なんですが、Storyboard で View を Freeform で編集する方法ってないんでしょうか?画面からはみ出すようなコンテンツ量になった場合死ぬしかない?
10:30 AM
Storyboard で VC 選択して metrics を Freeform にしても特に View の拡大とかできなさそうにみえる
Avatar
Kishikawa Katsumi 6/15/2018 10:36 AM
Freeformにしたら自由な大きさにできると思いますね。
10:37 AM
Xcode no
Avatar
巨大なVCを1storyboardで作ったらその時点で死んでるのでは… 表題は普通にできたと思う
😇 1
Avatar
Kishikawa Katsumi 6/15/2018 10:37 AM
のバージョンいくつですか?
Avatar
Xcode 9.4 ですね
10:38 AM
xib を編集するときはもちろん Freeform でサイズ変えられるんですが
Avatar
Kishikawa Katsumi 6/15/2018 10:42 AM
できますね。サイズの方(定規のアイコン)でFreeform にしてます? @Biacco42
🙏 1
10:44 AM
Avatar
できました!こっちで変えられるんですね…!
10:45 AM
これ、数値でしか変えられないですか…?
Avatar
Kishikawa Katsumi 6/15/2018 10:47 AM
そうかも。。。
Avatar
やはりそうでしたか…まぁ、実用上は問題ないといえばないですが…なるほど
10:47 AM
ありがとうございます
Avatar
xibだとドラッグアンドドロップ出来るけど、もしかしてsbだと出来ない?
Avatar
xib のような枠とかハンドルは出なくて試しにやってみたけれどできなかった
Avatar
VPPで購入してApple Configurator 2経由でデバイスにインストールすると、インストールしたアプリが起動しない(起動しそうだけどすぐにホーム画面に戻る)という現象で困っているんですが、同様の経験のある方いらっしゃいますか?
6:47 AM
同じアプリをApp Storeで購入してApple Configurator 2経由でデバイスにインストールしても、そっちは問題なく起動します。VPPとApp Storeで何か違うのかな…。
Avatar
Selectタグを含んだWebコンテンツをWebViewで開き、Selectタグ部分タップしてOS判断で出たPickerが制約エラーでるんですけど、これって回避方法とか何か情報持ってるかたいませんか?(iOS 11のみで起こる)
Avatar
iOSってキーボードは基本制約壊れてませんか
Avatar
omochimetaru 6/20/2018 5:26 AM
デバッガで見てるとメモリリークもしてるよね
Avatar
色々アレだよね
Avatar
@hironytic 解決されましたか?助けになるかはわかりませんが、VPP と Apple Configurator 2 でハマったことがあります。今思いつくのは、 VPP ストアで購入したアプリを最初にインストールしたデバイス以外にインストールしている または、私の場合は Apple Configurator 2 経由 で VPP アカウントを設定してインストールしたので、購入したアカウントの設定であるとするとそれが問題になっているのかもしれません。 ちなみに Apple Configurator 2 に VPP アカウントを関連づけると・・・ 『警告: VPP アカウントがすでに Apple Configurator 2 の別のインスタンスまたは MDM ソリューションに関連付けられている場合、それらの以前の関連付けによる App の割り当てがすべて取り消されます。』 ということなので、ご注意ください。
Avatar
@KNT 全く解決してません 😇 なので、情報はとてもありがたいです。 えーと、VPPストアで購入したアプリを最初にインストールしたデバイス以外にインストールしたらダメなものなんですか? VPPストアで10本とか購入して、Apple Configurator 2でそれぞれの端末に追加していく、っていう使い方でいいのかなと思っていたんですが。
Avatar
@hironytic すでに手離れしてしまっていて確認する術がないので、思いついたことだけですみません。私の場合、最終的には 購入アカウントではなく、VPP アカウントを Apple Configurator 2 に設定することで解決しました。
Avatar
あ、ぼくがVPPをちゃんと理解できてない気がします。
10:25 AM
購入アカウントとVPPアカウントって別なんでしょうか。
10:32 AM
ぼくがやったのは、VPPアカウントでVPPのストアにログインして、無料App(自社製品)を10本購入。で、Apple Configurator 2でそのVPPアカウントでサインインして、「追加」で購入したAppを選択してデバイスに追加なんです。で、いきなり、そのアプリの起動ができなかった 😢
Avatar
@hironytic なるほど・・・力になれずすみません。
Avatar
@KNT いえいえ、ありがとうございます。
10:45 AM
@KNT 解決した……かもです!
10:46 AM
追加先のデバイスでは、別のApple IDでApp Storeにサインインしていたのですが、通常、VPPで配布するときは、Apple IDなしでいいはずなので、もしかして逆にサインインしているといけないのかなと思い、デバイスではApp Storeからサインアウトしてみました。
10:47 AM
この状態で、起動しなくなっていたアプリはいったんアンインストールして、もう一度、Apple Configurator 2から追加を行ったところ、今度は起動しました!
Avatar
@hironytic おぉぉ、よかった!おかげで私も学べました。
Avatar
実際にはお客様のところで発生している問題なので、お客様のところでもうまくいけばいいのですが…
Avatar
悲報:お客様はサインインしてなかった(でも、サインインして行ったというメールもあって情報錯綜・・・)
11:41 AM
サインインは関係ないかもしれません。
11:44 AM
あと、ぼくの知らないところで、今日、検証端末のOSが11.3.1から11.4に上げられてたりとか。それによりデバイスが再起動したからうまくいくようになっただけ?とか(お客様はもともと11.4で発生している)。いくらでも憶測はできるのですが、原因はわからず。
11:45 AM
あと、再度サインインして配布しても起動しました。というわけで、今言えることは、ぼくは手元の再現環境を失ったということだけです 😢
😥 3
Avatar
@KNT お客様のところもサインアウトして配布したらうまくいったそうで、原因はさっぱりわからないんですがとりあえずクローズできました。ありがとうございました 🙂
😃 1
Avatar
@hironytic 私はなんの役にもたてませんでしたが、クローズしてよかったですw 原因不明なものの一つの解決方法としてあげられるので、またあれば私も注意してみます。
Avatar
Xcodeのスキーマを複数作成したとき、そのスキーマのアプリ画像(ファビコン)はどこで変更可能でしょうか。コンフィグレーションごとにスキーマを複数作成して、コンフィグレーションごとにアプリのアイコン(ASSETCATALOG_COMPILER_APPICON_NAME)を変更するようにしてるのですが、全てのスキーマのアプリ画像が同じアプリ画像になってしまいます。スキーマのアプリ画像をASSETCATALOG_COMPILER_APPICON_NAMEにそって切り替えることは可能でしょうか。
Avatar
Kishikawa Katsumi 6/22/2018 11:51 AM
たぶん無理です。Xcodeに機能リクエストすることになると思います。
Avatar
やはりそうですか、ありがとうございます 。
Avatar
unowned let hoge: Hoge という宣言をしているコードを見かけたのですが、これってどういう挙動のものなんでしょうか そのクラスにはインスタンスは保持されずに他で保持されてなければhogeは即解放されてしまう…?
Avatar
@noppe 「保持」というのがリファレンスカウント的な話だとそうですが、そのインスタンスへの参照を保持するための領域は確保されます。
4:31 AM
weak の場合は解放されたときに nil にしてくれますが、 unowned の場合はそういう安全機構がありません。
Avatar
リファレンスカウントは変更されずに対象インスタンスの参照だけを宣言するイメージでしょうか?
Avatar
代入してもリファレンスカウントが変更されないプロパティと考えるといいと思います。
4:33 AM
その代わり、参照先が解放されてしまっている危険性があります。
4:33 AM
なので、循環参照を避けたくて、絶対に解放されないことがわかっている場合に使います。
Avatar
ありがとうございます、確かに解放した後にアクセスしようとするとSIGABRT吐いちゃいますね…。 これがweakの場合はnilになっていると
Avatar
万が一解放された後でアクセスしてしまった場合は、実行時エラーだったか未定義動作だったかどういう言語仕様になってたか自信がありません。 (edited)
❤ 1
4:36 AM
Use an unowned reference only when you are sure that the reference always refers to an instance that has not been deallocated. If you try to access the value of an unowned reference after that instance has been deallocated, you’ll get a runtime error.
Avatar
unowned(unsafe) の場合は未定義ですね。普通の unowned はドキュメントの通り、実行時エラーが保証されています。
Avatar
omochimetaru 7/27/2018 4:39 AM
unowned(unsafe)っていつからあったんですか?
4:39 AM
最近見かける。
Avatar
-Ounchecked のときは普通の unowned でも未定義に・・・。 $ cat unowned.swift class A {} class B { unowned let a: A init(a: A) { self.a = a } } let b = B(a: A()) print(b.a) $ swift -Ounchecked unowned.swift unowned.A (edited)
Avatar
記憶の限りずっとあったと思いますよ。
Avatar
omochimetaru 7/27/2018 4:40 AM
マジか。知らなかった・・・
Avatar
This was part of the original weak design that there was never any particular reason to rush the implementation for. It's convenient to do this now so that we can use it to implement Unmanaged...
Avatar
omochimetaru 7/27/2018 4:40 AM
本当だ。
Avatar
2014/04/23 、 Swift 発表以前だ・・・
Avatar
omochimetaru 7/27/2018 4:41 AM
意外と知らない基礎知識あるんだよなあ
Avatar
unowned(unsafe) の有用性を認めるのであれば、 unsafePrecondition とかも認めないといけないような🤔
4:42 AM
そこを -Ounchecked でコントロールスタイルじゃないのかな・・・。
Avatar
-Ounchecked 自体deprecatedじゃないかな。。。
Avatar
omochimetaru 7/27/2018 4:42 AM
え!
Avatar
え、そうなんですか?
Avatar
omochimetaru 7/27/2018 4:43 AM
-OuncheckedはC言語に勝つために必須な気がする
4:44 AM
deprecated とは明言されていないか。
Avatar
omochimetaru 7/27/2018 4:44 AM
でも、ベンチマークから削除されてるのは、すごいことですね
Avatar
うーーん
Avatar
omochimetaru 7/27/2018 4:44 AM
Ouncheckedはパフォーマンス特化のモードだから、まさにベンチマークすべきモードだと思う
4:45 AM
それがSwiftのポテンシャルだから・・・
Avatar
-Ounchecked を使わないと、十分に安全性が確保されたパフォーマンスを追求するコードで一体どうやって precondition のチェックを無効化したらいいんでしょう?
4:45 AM
assert で書く?
Avatar
omochimetaru 7/27/2018 4:45 AM
それでもOsizeにするってことはOuncheckedを捨てていく意図を感じる
Avatar
どういう判断なんだろう?
Avatar
omochimetaru 7/27/2018 4:47 AM
フォーラムになんかあるかな?
Avatar
Hi, I’d like to propose to deprecate the -Ounchecked swift optimization mode. The -Ounchecked mode actually contradicts one of the main goals of swift: to be a safe language. In the past we didn’t see lot of significant performance differences compared to -O (there wer...
Avatar
omochimetaru 7/27/2018 4:47 AM
Hi, I’d like to propose to deprecate the -Ounchecked swift optimization mode. The -Ounchecked mode actually contradicts one of the main goals of swift: to be a safe language. In the past we didn’t see lot of significant performance differences compared to -O (there wer...
4:47 AM
あったわ
4:47 AM
同じだ。
4:48 AM
Hi, I’d like to propose to deprecate the -Ounchecked swift optimization mode.
4:48 AM
www
4:48 AM
とりあえず #swift に移動しましょう。
Avatar
たとえばキャッシュ用の private プロパティなどを Codable の対象から外す簡単な方法ってありましたっけ?
Avatar
cache用のフィールドを固めて無にエンコードする、を思いつきました
Avatar
omochimetaru 7/27/2018 8:35 AM
そのプロパティをCodableでない型にするか、CodingKeysを書くしかなさそう
Avatar
@tarunon それでもそのプロパティをキーとして書き出されませんか?
8:37 AM
@omochimetaru Codable でない型にしたら encode init(from:) を自前実装しないといけないのでは?
Avatar
omochimetaru 7/27/2018 8:37 AM
あ、そうか、全部Codableじゃないとダメか。 (edited)
Avatar
CodingKeysを書くしかなさそう
CodingKeys だけ書いたら encodeinit(from:) は自動生成されるんだっけ?
(edited)
Avatar
omochimetaru 7/27/2018 8:38 AM
CodingKeysだけ書いて、encodeとinit(from)はオマカセは、できたような・・・?
Avatar
実際のプロパティとの関連付けは名前で解決される??
Avatar
omochimetaru 7/27/2018 8:39 AM
そうそう。
Avatar
とりあえずやってみよう
8:40 AM
だめそう・・・
Avatar
omochimetaru 7/27/2018 8:41 AM
うわ、ほんとうだ
8:41 AM
全部caseが対応してるときに、キー文字列を変えられるだけか。
Avatar
@swiftbot struct Foo: Codable { private enum CodingKeys: CodingKey { case a } var a: Int private var _b: String }
🛠 1
Avatar
swiftbot BOT 7/27/2018 8:42 AM
Author icon
koher
struct Foo: Codable { private enum CodingKeys: CodingKey { case a } var a: Int private var _b: String }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:1:8: error: type 'Foo' does not conform to protocol 'Decodable' struct Foo: Codable { ^ Swift.Decodable:2:12: note: protocol requires initializer 'init(from:)' with type 'Decodable' public init(from decoder: Decoder) throws ^ /usercode/main.swift:6:17: note: cannot automatically synthesize 'Decodable' because '_b' does not have a matching CodingKey and does not have a default value private var _b: String ^
Avatar
うー、 encode, decode を自前実装しないといけないのか・・・。面倒だなぁ。
Avatar
多分ある程度うまくいく方法があるので続きは #swift (edited)
Avatar
TestFlightで内部のテスト配信したのですが、assertionFailureが有効になっているのか、該当行でCrashしてしまいます。 Appleのドキュメントを読むと、optimization levelが-Oの時には評価されないと記載されています。 ArchiveはRelease Build Configurationになっていたので、評価されないはずなのですが…。 下記が公式ドキュメントです。 https://developer.apple.com/documentation/swift/1539616-assertionfailure この辺り、ご存知の方がいたらご教授くださると嬉しいです
7:15 AM
Crash検知はcrashlyticsを利用しています
Avatar
-O なら assetionFailure は有効にならないはずです。
7:39 AM
プロジェクト設定(Build Settings)の、Swift Compiler - Code GenerationのOptimization Levelでは、Releaseが -O (Optimize for Speed)になってるんですよね。
Avatar
omochimetaru 7/31/2018 7:41 AM
とりあえずちゃんと -O による assertion の除去がされているか確認するために、 おしたら assertionFailure するだけのボタンをアプリに置いてみるなどはどうでしょう。
Avatar
@hironytic 念のため確認しましたがなってました…。 @omochimetaru ボタン置いて確認してみます!
🙂 1
Avatar
ボタン置いて確認したところ、assertionfailureは評価されませんでした。 ということは、元のコードに問題がありそうなので調査します。 アドバイスありがとうございました🙇‍♂️
Avatar
@swift-4.1.3 import Foundation var array = Array(repeating: 1, count: 100000) DispatchQueue.global().async { array.insert(3, at: 99999) print("inserted") } print("start") let total = array.reduce(0, +) print(total) print(array.count)
Avatar
start inserted 100003 100001
Avatar
あれ?
4:08 AM
@swift-4.2.4 import Foundation var array = Array(repeating: 1, count: 100000) DispatchQueue.global().async { array.insert(3, at: 99999) print("inserted") } print("start") let total = array.reduce(0, +) print(total) print(array.count)
Avatar
start inserted 100000 100001
Avatar
よし! わからん
4:09 AM
4.2で何かが変わったのかな???
4:09 AM
単なるタイミングの問題か
Avatar
dispatchMain()とかで待たないと、実行されない場合がありますよ。
Avatar
そもそもArrayはスレッドセーフじゃないから、 これだと何が起きてもおかしくないです
Avatar
横から質問ですみませんが、qos が global の queue ってひとつじゃないんでしょうか
4:15 AM
もし一つなら、global async は serial に実行されるのかな、と思っていました
Avatar
オブジェクトが1つでもglobal queueはconcurrent queueだったと思います。
Avatar
なるほど、であれば確かに順序は不定ですね
Avatar
それと、let total = ... の行については、そのキューの中では実行されてないです。
4:18 AM
Command line executableの場合、main() は生のmainです。 @norio_nomura のゆうように、dispatchMain を自分で呼ぶなどしないと
4:18 AM
DispatchQueueの支配するメインスレッドになりません。
Avatar
スレッドセーフでないから100003になる(ことがある)と思われるのに4.2でやると100000で安定してるので何か変わったのかと
4:26 AM
dispatchMain()知りませんでした
Avatar
@masakihori それでいうと、DispatchQueue.asyncの並列実行は、発火しても、スケジュールされるかどうかは運次第なので、asyncが実行される前にarray.reduceが終わってしまう可能性があります。
Avatar
@omochimetaru
Arrayはスレッドセーフじゃない
前にも聞いた気がするんですけど(履歴検索してもうまくひっかからなかったので)、これってどこかに仕様として明記されてましたっけ? Array の API リファレンスも The Swift Programming Language にも書かれてなさそう( thread で検索してみただけだけど)。標準ライブラリのコードから実態としてスレッドセーフじゃないということでしょうか?
(edited)
4:29 AM
スレッドセーフだと書かれてないものはスレッドセーフでないと考えるのが良いかもですが。
Avatar
デフォルトが「非スレッドセーフ」で、特に書かれてないから、そう考えてます。
👌 2
Avatar
ここで書かれたロジックがスレッドセーフではないだけで、Array自体はスレッドセーフなのでは?
Avatar
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
4:32 AM
The most important consequence of this is that two different array elements cannot be simultaneously accessed. This will interfere with certain common idioms for working with arrays, although some cases (like concurrently modifying different slices of an array) are already quite problematic in Swift.
Avatar
Kishikawa Katsumi 10/23/2018 4:33 AM
いや、Arrayはスレッドセーフじゃないですよ。
Avatar
少なくとも、arrayの異なるsubscriptにconcurrentにアクセスするのがダメ、という話は、OwnershipManifestoにも出てきます。
Avatar
Kishikawa Katsumi 10/23/2018 4:33 AM
デフォルトが「非スレッドセーフ」で、特に書かれてないから、そう考えてます。
^ この解釈があってると思います。
👌 1
4:33 AM
Arrayは複数スレッドから変更しようとしたら容易にクラッシュするのはすぐ確かめられます。
Avatar
「Swiftのデフォルトが非スレッドセーフである」という明確な言明があるテキストは知らないので探してみます。
Avatar
Kishikawa Katsumi 10/23/2018 4:35 AM
一般的にスレッドセーフにするのは余分なコストがかかるし難しいのでデフォルトがスレッドアンセーフというのは合理的だと思います。
4:40 AM
import Foundation let semaphore = DispatchSemaphore(value: 0) var array = [Int]() DispatchQueue.global().async { for i in 0...1000 { array.append(i) } print("end 1") } DispatchQueue.global().async { for i in 0...1000 { array.append(i) } print("end 2") } DispatchQueue.global().async { for i in 0...1000 { array.append(i) } print("end 3") } semaphore.wait()
4:40 AM
^ Botだとよくわからなかったけど、こういうコードはArrayはクラッシュします。
Avatar
全然見つからないですw
Avatar
すみません Swift42 bot 落としちゃったかも
4:54 AM
@swift-4.1.3 import Foundation var array = Array(repeating: 1, count: 100000) DispatchQueue.global().async { array.insert(3, at: 99999) print("inserted") } print("start") let total = array.reduce(0) { t, c in if t % 100 == 0 { print(".", terminator: "") } return t + c } print("") print(total) print(array.count)
Avatar
start ....................................inserted .................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 100000 100001
Avatar
マルチスレッド怖い
Avatar
すみません Swift42 bot 落としちゃったかも 受け取ったコードは別プロセスで実行されるので、ボット自体が落ちることはあまりないです。
Avatar
僕がやってるやつはマルチスレッド関係ない気がしてきた
Avatar
受け取ったコードは別プロセスで実行されるので、ボット自体が落ちることはあまりないです。 あいや落ちてHerokuが復帰させてた… 😅 (edited)
Avatar
makeIterator というか Iterator の実装がみそ の気がする
Avatar
我的API始終返回[{},{},{}]一個Json數組,如何使用swift 4.2解碼它,如果有人已經有這種情況我正在聽。我的方法點擊了GET請求。 Wǒ de API shǐzhōng fǎnhuí [{},{},{}] yīgè Json shùzǔ, rúhé shǐyòng swift 4.2 Jiěmǎ tā, rúguǒ yǒurén yǐjīng yǒu zhè zhǒng qíngkuàng wǒ zhèngzài tīng. Wǒ de fāngfǎ diǎnjīle GET qǐngqiú.
Avatar
どなたか CoreBluetooth 周りに詳しい方おりませんでしょうか…?
Avatar
Deleted User 11/2/2018 7:04 AM
「The project "プロジェクト名‘’ is damaged and cannot be opened due to a parse error. Examine the project file for invalid edits or unresolved source control conflicts. Path: /Users/自分の名前/Code/iOSapps/プロジェクト/プロジェクト名.xcodeproj」 ローカルでmasterとマージさせた後xcodeproj/project.pbxprojのコンフリクトを解消して、いざプロジェクトを開こうとすると上記エラーを吐くのですが、どう解決すればよろしいでしょうか???
Avatar
Kishikawa Katsumi 11/2/2018 7:06 AM
マージした結果、正しいProjectファイルではなくなってる感じですね。 1. 直接project.pbxprojをテキストエディタで編集して直すか、
7:06 AM
2. マージする前の状態に戻してやり直す、とかくらいしかないかなあ。
Avatar
omochimetaru 11/2/2018 7:07 AM
コンフリクトがすべて解消してないのかもしれません、pbxprojをエディタで開いて 「====」で検索するとヒットしませんか?
Avatar
Deleted User 11/2/2018 7:08 AM
@omochimetaru コンフリに関しては全て解消しました。「====」で検索してもヒットはないです。
🙃 1
7:09 AM
@Kishikawa Katsumi 素早い回答ありがとうございます。もう何度もマージする前の状態に戻して、やり直しては繰り返しており詰まってしまったので質問させていただきました。
Avatar
Kishikawa Katsumi 11/2/2018 7:09 AM
project.pbxprojは難しいので、数行程度で何が起こっているのかわかってるくらいのDiffならマージ操作でなんとかなりますが、そうでなければ私は諦めて手作業でやりますね。
Avatar
omochimetaru 11/2/2018 7:10 AM
そうしたら僕なら、oursをチェックアウトしてから、マージしようとしてるtheirs側の変更をdiffで生で見て、手動で同じ事をxcode上でやり直します
Avatar
Kishikawa Katsumi 11/2/2018 7:10 AM
project.pbxprojに変更が入るということはファイル、ライブラリの追加・削除、ビルド設定の変更など限られているので、材料と変更のDIffがあれば手作業の方が楽です。
Avatar
Deleted User 11/2/2018 7:12 AM
なるほど、お二方リプありがとうございます☺️諦めて手作業でやってみようと思います。
🙂 1
Avatar
Deleted User 11/6/2018 1:37 AM
こちらGithub上のxmlファイルをコピーする形で手作業で直りました!ありがとうございました😄
Avatar
たぶんコンフリクト解消したあと、解消した変更差分をstageに移してcommitしていないのでエラー出てますね。GUIのGit Client使ってると似たようなことよくやります
Avatar
naomichiさんの
どなたか CoreBluetooth 周りに詳しい方おりませんでしょうか…?
がスルーされてるぽいけど、これは解決したんだろうか?
Avatar
New iPadProのネイティブ対応、色々確かめてるんですが、10.1で新規アプリ作っても黒帯表示されて詰んでしまいました。上手くいった方いますか?
Avatar
ネイティブ対応は、基本対応アイコンとSplashが揃ってる状態でビルドしたらいけるはずだけど…
8:38 AM
両方揃っててもダメってことです?
Avatar
新規アプリで作って、LaunchScreen.storyboardなんでSplashはOK、アイコンはなくてもiPhoneXRとかはネイティブ対応になるが、iPadだけが上下に黒帯出ちゃうんですよね
8:42 AM
他に何か足りないのかな
Avatar
アイコンありは試してないってこと?
Avatar
アイコンありも試したけど同じ。
Avatar
あらま
Avatar
うまくいってるプロジェクトがあるならそれ参照したい、新規プロジェクトはダメでした 😿 (edited)
Avatar
Kishikawa Katsumi 11/8/2018 8:49 AM
念のためなんですけど、Xcodeで作ったばかりの何も手を加えてないプロジェクトでもダメですか?
Avatar
そうなんです
8:50 AM
真っ白のLaunchScreenと一枚VCの上下に黒帯がある
Avatar
Kishikawa Katsumi 11/8/2018 8:50 AM
デバイスだけ?シミュレータも?
Avatar
シミュレーターで発生してる
8:50 AM
実機は試してないですが概ねそうなりそう
Avatar
Kishikawa Katsumi 11/8/2018 8:50 AM
それはなんだろう。Xcodeのセットアップが壊れてるとかそんな感じな気がする。
Avatar
自分の方では起きないな…帯でない…
Avatar
え。
8:51 AM
環境破壊かぁ、承知ですありがとうございます
8:51 AM
DerivedData消してみよう
8:51 AM
XcodeSelectもやっておこう
Avatar
Kishikawa Katsumi 11/8/2018 8:51 AM
問題の切り分けとして、Xcodeが作ったばかりのプロジェクトを11inchのシミュレータで開いた場合、
8:51 AM
8:52 AM
^ これが正しいはず。
Avatar
岸川さんと同じ表示だった
Avatar
Xcode再インストールで治りました。ありがとうございます!
😃 4
Avatar
Kishikawa Katsumi 11/8/2018 11:36 AM
😄
Avatar
@ありぜ さん、こちら一旦解決していました…!ありがとうございます。
🙂 1
👍 1
Avatar
let array: [Array<Any>] = [Array<Int>(), Array<String>()] は可能だが struct Hoge<T> {} let array: [Hoge<Any>] = [Hoge<Int>(), Hoge<String>()] はダメだということは分かったのですが、これは何らかのテクニックで解消できるのでしょうか? それともコンパイラが何かやってる?
Avatar
Kishikawa Katsumi 11/20/2018 12:27 PM
それともコンパイラが何かやってる?
こっちが正しいです。 SwiftのGenericsは原則としてInvariantですが、Standard Libraryの一部はCovariantになります。 自分で定義した型は今のところどうやってもInvariantにしかなりません。
Avatar
ありがとうございます
Avatar
セミモーダルを実装したいのですが、参考になるような実装例をご存知の方いらっしゃれば教えてくださると幸いです。 (edited)
Avatar
https://github.com/SCENEE/FloatingPanel この前見つけたもの @Deleted User (edited)
A clean and easy-to-use floating panel UI component for iOS - SCENEE/FloatingPanel
Avatar
@cookiezby ドンピシャです!ありがとうございます!!
Avatar
こちらFloatingPanelのようにスクロールで3段階に分かれるもの以外で2段階にViewを変えられるライブラリや参考になるような実装例ございましたら大変、恐縮ですがリプライくださいますと嬉しいです。
Avatar
README にある var supportedPositions でカスタマイズできそうな雰囲気ですが、それはダメでしたか?
Avatar
2段階ってAirPods繋ぐときのみたいな感じですかね? https://github.com/antoniocasero/Panels これかな
Panels is a framework to easily add sliding panels to your application - antoniocasero/Panels
Avatar
@nekonoki var supportedPostionsを.half と.fullの値だけ指定し.tipをnilにしてから[.full, .half]をreturn で返すと固まってしまうなど実装したいデザインに準拠できなかったです。
5:33 AM
@noppe noppeさんのApple MusicKit入門、購入し読ませていただいております。まさに、この2段階の切り替えです。補足すると、height:100のmodal viewをボタンをタップすると出し、詳細を見る場合、より大きくなる。そして消したい場合はdismissを押すか初期サイズのviewから下にスクロールするというものです。文章で分かりにくくてすいません。上記ライブラリ試させていただきます。noppeさん、ありがとうございます。
Avatar
読んでいただいてありがとうございますmm セミモーダルですが、その挙動だとSCENEE/FloatingPanel の方が近そうですね 🤔 これ系結構色んな人が作っていた気がするので他にもありそうです
swift 1
Avatar
もうちょっと頑張ってみます、皆様ありがとうございます😊
Avatar
@Deleted User なるほど 例えば、 insetFor(position:) で返す値を .tip: 0, .half: 100, .full: 400 initialPosition.tip とし コードで表示・非表示を行う場合は func show() { fpc.move(to: .half) } func hide() { fpc.move(to: .tip) } とすれば、それっぽい動きになりそうですね。 (このやり方だと隠れていても FloatingPanel 自体は存在する形になってしまいますが)
Avatar
supportedPositionsを[.full, .half]、insetFor(position:)でcase .full: return 105.0 ・ case .half: return 256.0・default: return nilでFloatingPanel自体はremovePanelFromParentのみで削除する方法と、教えてくださったFloatingPanel自体は存在する方法どちらがいいか検討しますね! @nekonoki さん、ありがとうございます
Avatar
このライブラリがとても興味深かったので使ってみたのですが、 iOSでは動きませんでした。。。(macOSでは動いた) 使われたことのある方いますか? https://github.com/johnno1962/Fortify
Making Swift more robust. Contribute to johnno1962/Fortify development by creating an account on GitHub.
7:43 AM
fatal errorだろうがcatchしてしまう、とんでもないヤツです。 死ぬ前にログを吐かせるのに使えるかなと思ったのですが、 iOSではfatal error後即座に死んでしまいました。
Avatar
これiOSの場合はなんかオプションを有効にしないといけなかった気が
Avatar
お、おー!そうなんですね!Xcode側の設定ですか?
Avatar
ですです
8:15 AM
Edit SchemeからDebug executableをアンチェックですね
8:16 AM
Avatar
ありがとうございます!さっそくやってみます 💨
Avatar
実機ではだめでしたがシミュレータで動きました! 一歩前進できました。ありがとうございます!
Avatar
はじめまして。 配列の比較について質問させていただきたいのですが、 let a = [1] let b = [1] if a == b {} // コンパイル通る if [1] == [1] {} // コンパイル通らない このように配列を比較したときに、 一旦定数に入れたものと、そうでないものとで結果が違うのは何故でしょうか??
Avatar
Kishikawa Katsumi 12/15/2018 7:11 AM
おもしろいですね。 問題を整理すると、 a, b は型が Array<Int> に確定しているので、 if a == b {} は問題ないのですが、 リテラルを直接書いた場合( if [1] == [1] {} )は、 演算子 == リテラルをどの型として評価すべきか1つに定まらないから、ですね。 ちなみに問題は == に配列リテラルを渡したときに、配列リテラルからインスタンスできる型が複数あるからですね。(IndexzSetとIndexPath?) 例えばFoundationをImportしなければそれは存在しないので、上記のコードもコンパイルできます。 (edited)
Avatar
@Kishikawa Katsumi 回答ありがとうございます!とても腑に落ちました! UIKitをimportしていたので外したところ、通りました Intではない他のstructを作成して、配列に入れてみるとコンパイルが通るのも、 Intではどの型として評価すべきか1つに定まらないが 他の型ではArrayに定まるからなんですね
7:45 AM
コードを書いていて気がついたことなのですが、 if [1] as IndexPath == [1] {} このように左側だけキャストしてもコンパイルが通るのは、 勝手に右側も合わせてくれるからなのですか??
Avatar
Kishikawa Katsumi 12/15/2018 9:17 AM
代入と違うところは演算子も関数扱いなので、右辺と左辺はそれぞれ関数の引数に与えるのと同じです。 なのでリテラルからどう型推論が解決されるかは演算子(関数)の引数がとりうる型にもよります。 ==static func == (Self, Self) -> Bool なので、どちらか一方が決まるともう片方も決まることになります。
👀 1
Avatar
回答ありがとうございます! どちらか一方をちゃんと指定すれば、もう片方は型推論で決まってくれるんですね
Avatar
importしてきたFrameworkのpublicなstruct, class, funcなどを全てwrapする方法はありますか? 今は以下のように一つずつtypealiasでwrapしようかと考えています。 import SomeFramework public typealias Dog = SomeFramework.Dog public typealias Cat = SomeFramework.Cat
Avatar
wrapするとは違いますが名前を全部展開したいのなら @_exported import SomeFramework という記述ができますよ、非公式仕様ですが
Avatar
ありがとうございます! まさに欲しかったやつでした・・・!
😃 1
Avatar
https://github.com/t-ae/memory-crash-test 最小構成作ったんですが上のパッケージをリリースビルドでテストを走らせるとクラッシュします。 この行をコメントインすることでクラッシュしなくなるのでどこかで不当にメモリが開放されてそうです。 https://github.com/t-ae/memory-crash-test/blob/master/Sources/memory-crash-test/Broadcast.swift#L22 printデバッグした感じではtestExampleの終了周りでクラッシュしてるみたいです。 https://github.com/t-ae/memory-crash-test/blob/master/Tests/memory-crash-testTests/memory_crash_testTests.swift#L5-L15 $ swift test -c release [3/3] Linking ./.build/x86_64-apple-macosx/release/memory-crash-testPackageTe… Test Suite 'All tests' started at 2019-03-29 18:38:34.556 Test Suite 'memory-crash-testPackageTests.xctest' started at 2019-03-29 18:38:34.556 Test Suite 'memory_crash_testTests' started at 2019-03-29 18:38:34.556 Test Case '-[memory_crash_testTests.memory_crash_testTests testExample]' started. broadcast: start broadcast: end will exit testExample Exited with signal code 11 誰かなにか分かりませんでしょうか? 環境 $ swift --version Apple Swift version 5.0 (swiftlang-1001.0.69.5 clang-1001.0.46.3) Target: x86_64-apple-darwin18.5.0 $ swift package --version Apple Swift Package Manager - Swift 5.0.0 (swiftpm-14490.60.2)
Contribute to t-ae/memory-crash-test development by creating an account on GitHub.
Contribute to t-ae/memory-crash-test development by creating an account on GitHub.
Contribute to t-ae/memory-crash-test development by creating an account on GitHub.
9:42 AM
アップデート前は動いてたはずなのでswift5コンパイラのバグじゃないかなぁと疑っています。 (edited)
Avatar
swift-DEVELOPMENT-SNAPSHOT-2019-03-26-aでは直ってるみたいですね。
Avatar
じゃあとりあえず様子見ですね
12:08 PM
確認ありがとうございます。
Avatar
norio_nomura 3/29/2019 1:00 PM
swift-5.0-branchでは直ってないので、放っておくと5.1まで直らないのでは。
Avatar
報告だけでもしておいたほうがいいですかね。 原因が全く分かってないのがちょっとあれですが……
Avatar
@omochimetaru 先日のに関連してもう一つ質問よろしいですか? Routing <- Vapor <- MyProjectのように、MyProjectがVaporに依存し、VaporがRoutingに依存しています。 そして、 ParameterというprotocolがRoutingの中で宣言されています。 Vaporというpackageの中で先日お聞きしたような@_exportedやtypealiasは使われていなかったのですが、MyProjectで import Vaporとしただけで、Parameterという名前を使えるのが不思議です。 SwiftPMで依存しているライブラリの名前は全て展開されるということなのでしょうか? https://github.com/vapor/routing.git https://github.com/vapor/vapor.git
🚍 High-performance trie-node router. Contribute to vapor/routing development by creating an account on GitHub.
💧 A server-side Swift web framework. Contribute to vapor/vapor development by creating an account on GitHub.
Avatar
https://github.com/vapor/vapor/blob/master/Sources/Vapor/Exports.swift @_exported import CryptoKit @_exported import HTTPKit @_exported import RoutingKit @_exported import ServiceKit @_exported import ConsoleKit @_exported import Foundation
💧 A server-side Swift web framework. Contribute to vapor/vapor development by creating an account on GitHub.
11:25 AM
↑ここでexported importされているからだと思います。
Avatar
@omochimetaru あああ本当ですね!GitHub上で "@_exported"で検索したら出なかったのでないものと思い込んでいました。ありがとうございます!すごくスッキリしました!
Avatar
omochimetaru 4/2/2019 3:20 AM
@_exported で検索すると多分アットマークがユーザー名の意味とかになってしまいますね、exportedで検索したら出ました。
Avatar
本当ですね。いい学びになりました!ありがとうございます。
🙂 1
Avatar
vicktorManuel 4/13/2019 2:08 AM
What arquitectura is best
2:09 AM
Mvc , clean architecture, mvvm?
Avatar
There is no sliver bullet in the architecture, each of them has weakness and strength. If you want to know more information about each architecture, you can check this book, https://www.objc.io/books/app-architecture/ (edited)
iOS Application Design Patterns in Swift
👌🏾 1
Avatar
Frameworkの中でCocoa Touch FrameworkやCocoa Touch Static Libraryを使って切り分けているのですが、これらをUIKit.UITableView などのようにSubmodule化することはできるのでしょうか? http://nsomar.com/modular-framework-creating-and-using-them/ この記事を読んでみたのですが、理解できていません。 (modulemapというのはObjective-Cなどで書かれたFrameworkの内部を切り分けるために使われるものでSwiftオンリーで書かれたものにはあまり関係ないのかなと朧げに理解しています) (edited)
How to create and use modular framework in IOS and Macosx.
Avatar
omochimetaru 4/17/2019 2:53 AM
Swift自体にはsubmoduleの機構は無いという理解です。 modulemap自体にはsubmoduleの機構があって、Swiftはそれをサポートしてるから、 C/ObjCのモジュールを取り込むときに限ってSwiftはsubmoduleを扱える。
Avatar
お返事ありがとうございます。なるほどです。 それでは、下記のようにHogeという名前が競合しそうな時にはどのように整理するのがいいのでしょうか? MyFramework.Sub1.Hoge MyFramework.Sub2.Hoge
3:01 AM
MyFrameworkの中にexports.swiftのようなものを用意して import Sub1 import Sub2 public typealias Sub1 = Sub1 public typealias Sub2 = Sub2 みたいに書いたり import Sub1 import Sub2 public struct Sub1 { public typealias Hoge = Sub1.Hoge } public struct Sub2 { public typealias Hoge = Sub2.Hoge } みたいに書いたりできないかなーと模索しているのですが。structの名前とsub frameworkの名前をずらせばこれでも書けない事はないのですが、全部aliasを貼るのもすごく面倒なのでもっといいやり方があるのではないかと思っています。
Avatar
omochimetaru 4/17/2019 3:08 AM
そういう場合MyFrameworkのユーザ側では Sub1.Hoge と Sub2.Hoge で扱うか、 ソースファイルごとに import MyFramework fileprivate typealias Hoge = Sub1.Hoge とかやるしか無いと思います。 それかパッケージをわけてMyFrameworkSub1とMyFrameworkSub2を作る。 その上でMyFrameworkも作って、MyFrameworkSub1とMyFrameworkSub2をexportすれば、 ユーザ側で import MyFrameworkSub1 とできるようになります。
Avatar
やりたい事と合致するかはわかりませんが、classだけimportする、とかはできるようです。 import class UIKit.UITableViewController https://thoughtbot.com/blog/swift-imports
How to be a Swift importer (and possibly exporter).
Avatar
お二人ともありがとうございます。 @omochimetaru さんのコメントを見て気づいたのですが、 MyFrameworkのなかで以下のようにしておけば @_exported import Sub1 @_exported import Sub2 MyFrameworkのユーザー側で下記のようにSub1, Sub2を使えるのですね。 let hoge1 = Sub1.Hoge() let hoge2 = Sub2.Hoge() 名前の衝突が問題だったので、やりたかった事はこれで解決できました。ありがとうございます。 (@_exported importをすると、Sub1やSub2などの名前空間は消失してしまうのかと思っていました。)
Avatar
omochimetaru 4/17/2019 4:56 AM
そうですそうです。
Avatar
Kishikawa Katsumi 4/17/2019 4:59 AM
@_exported ってそんなに便利なものじゃないのでこの場合だと MyFramework と Sub1、Sub2をそれぞれ個別に、あるいはSub1、Sub2のフレームワークとして提供する方がいいと思いますよ。
Avatar
ありがとうございます。 意味の分解やまとめ方やレイヤーをいろいろ考えてFrameworkをまとめたり、バラしたりを繰り返しています笑
Avatar
Kishikawa Katsumi 4/17/2019 8:30 AM
基本的には使う側が依存関係も含めてセットアップして、使うものをその都度具体的に指定(=import)が良いと思います。 (依存のやつを本当に見せたくない・意識させたくないというのはあるとは思うんですけど、隠す場合衝突とか他の問題も出てくるので、この原則に従う方が(使う人のスキルも必要になるけど)大抵は良いはず。。。)
Avatar
結局岸川さんのご意見を聞いた後、検討した結果おっしゃる通りバラすことにしました。結果的にはこの方がスッキリしました。良かったです!
😄 1
Avatar
メインスレッドでDispatchQueue.main.async(execute workItem: DispatchWorkItem)を呼んだ場合のworkItemの実行タイミングはどのように決まるのでしょうか? DispatchQueue.main.asyncをメインスレッドでworkItemを実行する程度にしか考えていなかったので // on main thread print("1") DispatchQueue.main.async { print("2") } print("3") のようなコードの実行順序が1,3,2になることに気がつけずにハマってしまい気になりました。
Avatar
Kishikawa Katsumi 4/21/2019 4:44 PM
1, 3, 2は自然な順序にみえます。 1, 3は1つのスレッドで3の方が下にあるので1より後、2はこのメインループでキューに追加されるので1, 3より後の次のメインループ以降に実行される、キューに追加されたものはキューというからには先に追加されたものが先に実行される、だと思います。
Avatar
メインループでキューに追加される
ありがとうございます!キューの解説で理解できました 具体的に上の事象はviewDidLoadでmain.asyncした場合にlayoutSubViews相当のタイミングで呼ばれるということから興味を持ったのですが、viewDidLoad以降は連続してメインループでレイアウトあたりまで行なっていると考えると合点が行きました。
(edited)
Avatar
余談ですが、似たような話で JS の Promisethenresolve 済でも同期的に実行されない仕様なことに気づかずハマったことがあります。 console.log("1"); new Promise(resolve => { resolve(42); }).then(value => { console.log("2"); }); console.log("3"); 1 3 2 (edited)
Avatar
JavaScriptのPromiseを使った非同期処理の書き方、テスト、アンチパターンについて解説した無料の電子書籍
👍 1
Avatar
です。 Swift の Promise を自作したときは同期として実装していたので騙されました。 Swift の async/awaitasync -> Foo でも同期であり得るという認識。 (edited)
Avatar
上に挙げたリンクの少し下に書かれている、 非同期コールバックを同期的に呼び出してはいけない の部分は、わかりやすくていいなと思っているんですが、ただし多用すると遅くなる 😟
Avatar
Protocolに対してRxSwiftのpropertyを定義しているのですが、使うタイミングでProtocolのままだと使えず困っています。どうしたら解決できるかご存知ありませんでしょうか? public protocol AppConfigProvider: NSObject { var config: AppConfig { get set } } // MARK : - Rx properties extension Reactive where Base: AppConfigProvider { /// Reactive wrapper for `config` property. public var config: Observable<AppConfig?> { return base.rx.observe(AppConfig.self, "config") } }
7:49 AM
7:50 AM
使うタイミングではDI用に、Protocolで変数を宣言しています。 var environment: AppConfigProvider
Avatar
omochimetaru 4/22/2019 8:20 AM
一応 TypeErasureを定義すれば問題は回避できますが、それが正しいアプローチかどうか自信無いです。 ↓回避例 // Type Erasure public class AnyAppConfigProvider : NSObject, AppConfigProvider { public var config: AppConfig { get { return base.config } set { base.config = newValue } } private let base: AppConfigProvider public init<X: AppConfigProvider>(_ base: X) { self.base = base } } // 実際の具体的なAppConfigProvider public class ACP : NSObject, AppConfigProvider { public var config: AppConfig public init(config: AppConfig) { self.config = config } } // 利用時 var a: AnyAppConfigProvider = AnyAppConfigProvider(ACP(config: AppConfig())) print(a.rx.config) (edited)
8:21 AM
受け取る側で AppConfigProvider で受け取るのではなくて、 AnyAppConfigProvider で受け取るようにします。 代入するときは AnyAppConfigProvider.init<X> で明示的に包み込みます。
8:26 AM
Member 'slf' cannot be used on value of protocol type 'ProtoA'; use a generic constraint instead
↑この種のエラーメッセージが出るのは、 RxSwift.ReactiveCompatiblevar rx: Reactive<Self> のところで、 プロトコル型それ自身を Self として使おうとしているからです。
Avatar
なるほど、TypeErasureってこういうときに使えるんですね。 この場合、もしAppConfigProviderのpropertyが増えていったらその分AnyAppConfigProviderを定義する時にwrapするものが増えていくというイメージでしょうか?
Avatar
omochimetaru 4/22/2019 8:58 AM
そうなります。面倒なので避けたいですねえ。
Avatar
なるほどです。。。 今は、ちょっとダサいんですが下記のように対応しています。 public protocol AppConfigProvider { var config: AppConfig { get set } var rx_config: Observable<AppConfig> { get } } public class ACP : AppConfigProvider { public var configSubject: PublishSubject<AppConfig> public var config: AppConfig { return try! configSubject.value()} public var rx_config: Observable<AppConfig> { return configSubject } }
9:03 AM
本当は a.config a.rx.config みたいに分けたいのですが、難しいですかね・・・?
Avatar
@swift-5.0.3 struct Reactive<Base> {} protocol ReactiveExtensionCompatible { associatedtype Target var rx: Reactive<Target> { get } } extension ReactiveExtensionCompatible { var rx: Reactive<Self> { fatalError() } } struct Observable<T> {} import Foundation extension NSObject: ReactiveExtensionCompatible {} // ここまでRx struct AppConfig {} protocol AppConfigProvider: NSObject { var config: AppConfig { get set } } extension AppConfigProvider { var rx: Reactive<AppConfigProvider> { fatalError() } } extension Reactive where Base == AppConfigProvider { var config: Observable<AppConfig?> { fatalError() } } func useConfig(_ provider: AppConfigProvider) { _ = provider.rx.config } (edited)
Avatar
no output (edited)
Avatar
@usatie どうでしょう?
Avatar
omochimetaru 4/22/2019 9:19 AM
おー!
Avatar
ミソはAppConfigProviderのextensionでrxのオーバーロードを定義するのと、Base == AppConfigProviderでexistentialに対して生やすところです
👏 3
Avatar
これって、 rx のオーバーロード定義の fatalError() のところは実際には return Reactive(self) とする必要ありですか? (edited)
Avatar
そうです
Avatar
omochimetaru 4/22/2019 9:21 AM
2点目の方も必要?
9:21 AM
.rxのオーバーロードだけで行けそうな気がした
Avatar
self conformしないので無理だと思ったんですが
Avatar
omochimetaru 4/22/2019 9:23 AM
(外出中で今実験できない
Avatar
(僕も携帯で書いてました…
9:24 AM
@swift-5.0.3 struct Reactive<Base> {} protocol ReactiveExtensionCompatible { associatedtype Target var rx: Reactive<Target> { get } } extension ReactiveExtensionCompatible { var rx: Reactive<Self> { fatalError() } } struct Observable<T> {} import Foundation extension NSObject: ReactiveExtensionCompatible {} // ここまでRx struct AppConfig {} protocol AppConfigProvider: NSObject { var config: AppConfig { get set } } extension AppConfigProvider { var rx: Reactive<AppConfigProvider> { fatalError() } } extension Reactive where Base: AppConfigProvider { var config: Observable<AppConfig?> { fatalError() } } func useConfig(_ provider: AppConfigProvider) { _ = provider.rx.config }
Avatar
exit status: 1 with stderr:<stdin>:39:21: error: protocol type 'AppConfigProvider' cannot conform to 'AppConfigProvider' because only concrete types can conform to protocols _ = provider.rx.config ^
Avatar
なるほど!
Avatar
omochimetaru 4/22/2019 9:29 AM
ああ、そうか。
Avatar
@Yuta Saito おおおー!なるほどです!!!やってみます!
Avatar
compile通りました!ありがとうございます!
🎉 2
Avatar
このように書いて、コンパイルは通りました。 public protocol AppConfigProvider: NSObject { var config: AppConfig { get set } } extension AppConfigProvider { var rx: Reactive<AppConfigProvider> { return Reactive(self) } } extension Reactive where Base: AppConfigProvider { var config: Observable<AppConfig?> { return base.rx.observe(AppConfig.self, "config") } } a.rx.configを呼ぼうとすると下記のエラーが出てしまいました。 KVC-compliantにするためには何が必要なのでしょうか? Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<App.AppEnvironment 0x282777d20> addObserver:<_TtC7RxCocoaP33_F7515DBB13B60709A3CB25DD19EDD11D11KVOObserver 0x280d28690> forKeyPath:@"config" options:5 context:0x0] was sent to an object that is not KVC-compliant for the "config" property.'
Avatar
なんとなくこれは extension Reactive whare Base == AppConfigProvider にしていないから、KeyPath版の方にfallしたんじゃないですかね。== にしてみたらどうでしょう?
Avatar
(protocol型がObjC Classに対応していない予感
Avatar
今やってみたのですが、そうすると下記のエラーが出ます。 Ambiguous reference to member 'observe(_:_:options:retainSelf:)'
Avatar
違うのか。
Avatar
プロパティに@objcつけたらいけるんかな
Avatar
ただつけるだけだと下記のエラーが出てしまいますが、そんな気がします・・・! @objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
10:08 AM
public protocol AppConfigProvider: NSObject { @objc var config: AppConfig { get set } var rx_config: Observable<AppConfig> { get } }
10:11 AM
しかし @objc protocolにしてみると Property cannot be a member of an @objc protocol because its type cannot be represented in Objective-CProtocol 'AppConfigProvider' is '@objc' and cannot have a superclass constraint が出てしまいます。 public @objc protocol AppConfigProvider: NSObject { var config: AppConfig { get set } var rx_config: Observable<AppConfig> { get } }
Avatar
objc protocolなら NSObjectじゃなくてNSObjectProtocolに適合すればOKぽい
Avatar
このように書いて、コンパイルは通りました。
これだと、AppConfigProviderを値に代入できないはず。。 observe を使いたい場合は (base as NSObject).rx.~~~ でできると思います
Avatar
ありがとうございます。以下のコードでやっと動くようになりました! public final class AppConfig: NSObject { public init() {} } @objc public protocol AppConfigProvider: NSObjectProtocol { @objc var config: AppConfig { get set } } extension AppConfigProvider { var rxoriginal: Reactive<AppConfigProvider> { return Reactive(self) } } extension Reactive where Base: AppConfigProvider { var config: Observable<AppConfig?> { return (base as! NSObject).rx.observe(AppConfig.self, "config") } }
10:28 AM
structにしたかったのですが、AppConfigもNSObjectにするとビルドが通るようになって動きました。
Avatar
あー、==じゃなくてもいいのは
10:30 AM
protocol extrnsionのSelf openか
10:31 AM
ん?いや、違うか
10:31 AM
objc protocol特有の自動self conformanceか
Avatar
なるほど!!!! 確かに! > @objcのself conformance
Avatar
objc絡むとめんどい
Avatar
NSObjectにしてObserveするとstructを使えず、AppConfigのpropertyを変更しただけだとObservableに流れてこないので、変更を通知するためにはインスタンスごと変更するなど、ちょっとコツが必要でした。そのため、名前をわかりやすいように分けるだけなら下記のような実装でもいいかなと思って、今はこんな感じで実装しています。 protocol AppConfigProvider { var rx: RxEnvironmentProvider { get } var config: AppConfig { get set } } protocol RxAppConfigProvider { var config: Observable<AppConfig> { get } } final class AppEnvironment: AppConfigProvider { private var rx: RxAppEnvironment var config: AppConfig { get { return try! configSubject.value() } set { rx.configSubject.onNext(newValue) } } } struct RxAppEnvironment: RxAppConfigProvider { let configSubject: BehaviorSubject<Entity.AppConfig> var config: Observable<AppConfig> { return configSubject } }
Avatar
どこに投稿すればいいかわからなかったのですが、Default Protocol Extension の優先順位ってどうやって決まってるんでしょうか? 下記の例の場合、やりたいことはできているのですがルールがよくわかっていないため不安でして・・・ @swift-5.0.3 protocol Foo { associatedtype Bar func hoge() } extension Foo where Bar: Decodable { func hoge() { print("Decodable.hoge") } } extension Foo where Bar == String { func hoge() { print("String.hoge") } } struct FooImpl1: Foo { typealias Bar = [String] } struct FooImpl2: Foo { typealias Bar = String } let foo1: FooImpl1 = FooImpl1() let foo2: FooImpl2 = FooImpl2() foo1.hoge() foo2.hoge()
Avatar
Decodable.hoge String.hoge
Avatar
StringもDecodableなので、どちらの実装が適応されてもおかしくない気がしています。
Avatar
omochimetaru 4/24/2019 7:41 AM
==のほうが強い、みたいな規則があります
7:41 AM
強さが同じものが複数ある場合、曖昧であるとしてコンパイラエラーになった気がします。
Avatar
なるほど・・・!
7:43 AM
@swift-5.0.3 import Foundation protocol Foo { associatedtype Bar func hoge() } extension Foo where Bar: Decodable { func hoge() { print("Decodable.hoge") } } extension Foo where Bar: Encodable { func hoge() { print("Encodable.hoge") } } struct FooImpl1: Foo { typealias Bar = String } struct FooImpl2: Foo { typealias Bar = String } let foo1: FooImpl1 = FooImpl1() let foo2: FooImpl2 = FooImpl2() foo1.hoge() foo2.hoge()
Avatar
exit status: 1 with stderr:<stdin>:20:8: error: type 'FooImpl1' does not conform to protocol 'Foo' struct FooImpl1: Foo { ^ <stdin>:5:10: note: multiple matching functions named 'hoge()' with type '() -> ()' func hoge() ^ <stdin>:9:10: note: candidate exactly matches func hoge() { ^ <stdin>:15:10: note: candidate exactly matches func hoge() { ^ <stdin>:24:8: error: type 'FooImpl2' does not conform to protocol 'Foo' struct FooImpl2: Foo { ^ <stdin>:5:10: note: multiple matching functions named 'hoge()' with type '() -> ()' func hoge() ^ <stdin>:9:10: note: candidate exactly matches func hoge() { ^ <stdin>:15:10: note: candidate exactly matches func hoge() { ^ <stdin>:31:1: error: ambiguous use of 'hoge()' foo1.hoge() ^ <stdin>:9:10: note: found this candidate func hoge() { ^ <stdin>:15:10: note: found this candidate func hoge() { ^ <stdin>:32:1: error: ambiguous use of 'hoge()' foo2.hoge() ^ <stdin>:9:10: note: found this candidate func hoge() { ^ <stdin>:15:10: note: found this candidate func hoge() { ^
Avatar
そもそも二つ競合してる時は、どちらも適応されないことになるのか
7:46 AM
@swift-5.0.3 import Foundation protocol Foo { associatedtype Bar func hoge() } extension Foo where Bar: Decodable { func hoge() { print("Decodable.hoge") } } extension Foo where Bar: Encodable { func hoge() { print("Encodable.hoge") } } struct DecodableBar: Decodable {} struct EncodableBar: Encodable {} struct FooImpl1: Foo { typealias Bar = DecodableBar } struct FooImpl2: Foo { typealias Bar = EncodableBar } let foo1: FooImpl1 = FooImpl1() let foo2: FooImpl2 = FooImpl2() foo1.hoge() foo2.hoge()
Avatar
Decodable.hoge Encodable.hoge
Avatar
entry point (_main) undefined. for architecture x86_64
11:54 AM
このエラー見覚えある方いませんか??
Avatar
iOSなら @UIApplicationMain がなくなってる とか?
Avatar
あります..
Avatar
Recently I downloaded Xcode 9 and created one sample iPhone app but the app is not able to build as it shows the following error: ld: entry point (_main) undefined. for architecture x86_64 I se...
Avatar
現在、Cocoa Touch Frameworkを使って責務を分割して、iOSアプリを作っています。アプリ本体以外のFrameworkにおいて、CocoaPodsで入れたFrameworkを使おうとすると No such module と言われてしまい、対処法がわかりません。 App : アプリ本体のFramework。他の全てのFrameworkに依存。 Feature1 : ある機能の画面やロジックなどが入ったFramework Feature2 : ある機能の画面やロジックなどが入ったFramework AppCore : AppFeature1Feature2などが依存するFramework こんな感じの構成でして、 AppからはCPのframeworkを使用できるのですが、その他のFrameworkでは使えなくて困っています。
5:25 AM
対処法がわかる方がいらっしゃいましたら教えていただけないでしょうか?
5:27 AM
Podfileはこのようになっています。 workspace 'App.xcworkspace' project 'Sources/App/App.xcodeproj' target 'App' do use_frameworks! pod 'Firebase/Core' pod 'Fabric', '~> 1.10.0' pod 'Crashlytics', '~> 3.13.0' target 'AppTests' do inherit! :search_paths end end
Avatar
すみません、自己解決できました。このように、Podfileを書くときに各Target内でどのprojectなのか明記してあげればよかったみたいです。 workspace 'App.xcworkspace' target 'App' do project 'Sources/App/App.xcodeproj' use_frameworks! install_pods target 'AppTests' do inherit! :search_paths end end target 'Feature1' do project 'Sources/Features/Feature1/Feature1.xcodeproj' install_pods target 'Feature1Tests' do inherit! :search_paths end end def install_pods use_frameworks! pod 'Firebase/Core' pod 'Fabric', '~> 1.10.0' pod 'Crashlytics', '~> 3.13.0' end
Avatar
突然失礼します🙇‍♂️どなたかお助けいただけると嬉しいです😭🥺 環境はXcode ver.10.2.1 (Swift 5)です。 現在 iOS アプリ作成中の超初心者です。🙇‍♀️ 画面遷移について質問です! (画像はストーリーボードの略図です) Delete sc. から、segue で一切繋がっていないlaunch sc. まで戻りたいのですが(コードで)、これって一気に行けますか? 段階を踏んで戻ればいけますか?? 補足 Launch sc. と cover sc. はsegue では繋がってないです。コードで遷移させてます。(図では繋がってますが、cover sc. から main sc.も時間で遷移するようにコーディングしてます) (edited)
Avatar
omochimetaru 5/22/2019 6:43 AM
presentが重なって遷移しているのであれば、dismiss一発でいけますよ https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss
6:43 AM
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack.
Avatar
@omochimetaru 重なってなくて、dismiss で一発で行けなかったクチです🥶
Avatar
omochimetaru 5/22/2019 6:47 AM
コードで遷移させてます。
これがどういう方法でやってるかで状況が変わってきそうです。 NavigationControllerのpushだったら、NavigationController自体はpresentのスタックにおいてある1段だけを維持してますが
6:47 AM
window.rootViewController = vc とかをやっていると、
6:48 AM
その時点で過去の遷移スタックがなくなってたりします。
Avatar
@omochimetaru Cover sc.→ main sc. へはコードで nextView = storyboard.instantiateViewController 使ってやってます! 他はストーリーボード上でsegue で繋いでます!
Avatar
omochimetaru 5/22/2019 6:54 AM
そのnextViewって present(nextView) で表示してますか? (edited)
Avatar
あ、です!
Avatar
omochimetaru 5/22/2019 6:55 AM
それなら全部遷移スタックに載ってそうなので、
6:55 AM
dismissを呼び出す対象のオブジェクトが間違ってるかもしれません。
6:56 AM
例えば上の図によるとInfo画面はNavigationControllerの中にあるので、 infoViewController.dismiss() とやってもうまくいきません.
Avatar
self.navigationController?.popToViewController(...)でやっても、結局行けるのがnavigation controller入れてるinfo画面までなので、それよりも前の最初のlaunch画面まで行ける方法があれば教えていただきたいです🙇‍♂️
Avatar
Kishikawa Katsumi 5/22/2019 9:19 AM
できるかできないで言えばできる(正確にはやる方法はある)、んですけど、画面の構成によってはメソッド1つ呼ぶだけ、だと無理かもしれません。 今までも情報をまとめると、おそらくPushとPresent(モーダル)の遷移が混ざってると思うので、 popとdismissを組み合わせてがんばって戻るか、 ちょっと設計を見直してPushあるいはPresentだけにする、としてもいいかもしれないです。 ちょっと余談ですが、画面遷移の方法と見た目は分離されているので、Pushでもモーダルのような表示(あるいはその逆)というのも可能です。
Avatar
segueの動きがどうなってるのかわからないので推測でしか言えないのですが、 self.navigationController?.dismiss() を呼ぶとどうなるんですか?
Avatar
@Kishikawa Katsumi 余談の、気になります😂 Popとdismiss、前回試したときは書き方が悪かったんでしょう、うまく動いてくれなかったのでまた考え直してみます😭 ありがとうございます!
9:41 PM
@lovee それはやったか記憶がないので今日やってみます!
🤗 1
9:41 PM
皆様助言ありがとうございます!!
Avatar
@lovee self.navigation controller?.dismiss呼んだ結果、何も起こりませんでした。
Avatar
あ、何も起こらないんですね。。。 self.navigationController?.dismiss()self がDelete sc.と表現されているViewControllerなら、Cover sc.のViewControllerまでは戻りそうな気がぼくもしてたんですけど。
Avatar
@hironytic ()の中って当然animated: trueなど書きますよね? Dismissで使う()の中身で書いてやった結果なにもならなかったです。
Avatar
omochimetaru 5/24/2019 5:48 AM
たぶん何か齟齬が生じていそうです、コードが公開できれば解決できると思います。
Avatar
@omochimetaru すみません꒰༎ຶ﹏༎ຶ๑꒱ありがとうございます! 画像送ります!! Self.naviC?.dismiss( )でならなかったので、一旦info画面まで戻るコードに戻してます。
Avatar
omochimetaru 5/24/2019 5:52 AM
いえ、「戻るコード」だけの問題ではなく、「他の画面の遷移がどうなっているか」も絡む問題なので、 Storyboardとか他の画面のコードとか、全部みないと多分わからないです。
Avatar
あーなるほど。 ちょっとまってくださいね…
5:54 AM
コード全部は難しいかと。 ストーリーボードのあげます!
Avatar
ああ、下方向の矢印がpresentで右方向の矢印がpushなのかと勝手に思ってたんですが、そういうわけでもないんですかね。少なくとも各画面の遷移に絡む部分がきちんとわからないと答えようがなさそうです。
5:58 AM
赤: delete sc. 黄: normal launch sc. 緑: cover sc. 青: login sc. です🙇‍♂️
5:59 AM
@hironytic 申し訳ありません… 矢印の書き方に普通はこう、みたいなのがあったのですね… 不勉強で申し訳ありません…
Avatar
あ、ごめんなさい、普通はこうというのはないと思います。ぼくが勝手にそう解釈してしまっただけです 🙏
Avatar
@hironytic あ、そうなのですね! 重ね重ねすみません😭
Avatar
omochimetaru 5/24/2019 6:02 AM
self.navigationController?.presentingViewController?.presentingViewController?.dismiss(animated: true)
6:02 AM
これだとどうなりますか?
Avatar
cover→normal L :presentモーダリー info→delete: show(e.g. push) で繋がってます。
6:03 AM
@omochimetaru ありがとうございます! やってみます!
6:09 AM
@omochimetaru cover画面まで戻りました!
Avatar
omochimetaru 5/24/2019 6:10 AM
self.navigationController?.presentingViewController?.presentingViewController?.presentingViewController?.dismiss(animated: true)
6:10 AM
もういっこ増やすといけます?
Avatar
ログイン画面から来てたらログイン画面には戻れます。 私も以前omochimetaru さんが仰っているようにpresentingVC?を増やすやり方やったんですけど、これだと、ログイン画面から来た場合はログイン画面に戻りますが、create account sc.からcover画面行ってdelete 画面に来てたらcreateA sc.に戻ります。 つまり、どこから来たかに依存しますね。ほかの画面でもモーダリーやnavigationC使ってる所があるので、そこから来てたらそっちに戻っちゃうと思います🙇‍♂️
Avatar
omochimetaru 5/24/2019 6:19 AM
はい、なので、AppDelegateのプロパティとかにloginVCをプロパティで持っておいて
6:19 AM
(UIApplication.shared.delegate as! AppDelegate).loginVC?.dismiss(animated: true)
6:19 AM
などとやると、どっからでも戻ってこれます。
Avatar
なるほど!!😍 didFinishLaunchingWithOptions 使うやつも教えていただいたので、omochimetaru さんの仰ってるやり方とdidF~のやり方と、試してみて設計によりマッチングする方で仕上げてみます!! 本当に皆様ご助言ありがとうございます!!助かりました🙏😭✨✨
🎉 2
6:26 AM
あと、同じアプリの別疑問なのですが、textFieldタップしたらkeyboardが出てくると思うのでそれを閉じたいです。 色んなところにtext fieldあって一個一個にUITextDelegate 書いて、override func touchesBegan と func textFieldShouldReturn など書いてってしていくのが面倒です。 そこでキーボード閉じる↑を書く別クラス作って、必要クラスで呼び出す方法で書きたいのですが、これって可能ですか?
6:27 AM
クラスのviewDidLoad に別クラスを呼び出す方法がわかりません💦 ご教授いただけると幸いです🙇‍♂️
Avatar
画面戻すのに関しては Unwind Segue を使うのが一番お手軽だと思いますよ。PushとPresent混在していても特に意識せずいけますし。 (edited)
Avatar
omochimetaru 5/24/2019 6:54 AM
そこでキーボード閉じる↑を書く別クラス作って、必要クラスで呼び出す方法で書きたいのですが、これって可能ですか? クラスのviewDidLoad に別クラスを呼び出す方法がわかりません
↑この文の日本語の解釈が正確にできなかったんですが、例えば下記のような実装は可能です↓ class ViewController : UIViewController { @IBOutlet var textField: UITextField! let keyboardCloseHelper = KeyboardCloseHelper() override func viewDidLoad() { super.viewDidLoad() keyboardCloseHelper.add(textField) } }
6:55 AM
キーボードを閉じる別クラス(KeyboardCloseHelper)を作って必要クラスで(ViewController)で呼び出す
Avatar
@rintaro !!👀 そういうのがあるんですね! 調べてみます! ありがとうございます😊
12:44 PM
@omochimetaru いつもありがとうございます🙇‍♂️ なるほど。 別クラス作って呼び出すにしても、そこまでコード書かないといけないんですね🤔 ありがとうございます!
Avatar
@omochimetaru めっちゃ因みになのですが… .add メソッドなかったです…
Avatar
omochimetaru 5/27/2019 4:43 AM
あ、KeyboardCloseHelperというクラスは標準ライブラリには存在しません、自作しよう、という意味です
Avatar
@omochimetaru はい。KeyboardCloseHelper は自作されているのはわかっていたので、そこは自分のクラス名にしてインスタンス化まではしました。 ViewDidLoad に書いた時に.add というのが存在しないみたいで、エラーが出ました。addChildView...ですかね?子ビューのなら出てきました。
Avatar
omochimetaru 5/27/2019 5:04 AM
KeyboardCloseHelperにaddメソッドを自作するのです。
Avatar
なるほど!!?!👀 そうことでございましたか👀 今日後ほど、もしくは明日やってみます😭
Avatar
Kishikawa Katsumi 5/27/2019 2:03 PM
キーボードを閉じるならtextFieldを保持していなくても self.view.endEditing(true) でそのビューに乗っているビュー全部に対して resignFirstResponder を呼んでくれるので、それを適当なタイミングで呼んだらいいと思いますよ。
Avatar
@Kishikawa Katsumi ふぉぉ! ありがとうございます!😳🥺
8:46 AM
諸事情によりまだキーボード閉じるのできてないので、また後日、結果ご報告させていただきます🙇‍♂️皆様本当にいつもありがとうございます!!😭
Avatar
SwiftPM で Swift のバージョンを指定するのってどうやるんでしょう?何もなしに generate-xcodeproj すると Swift 4.0 が指定されているようで、やり方を調べてみたのですが分かりませんでした 🙇 (edited)
Avatar
omochimetaru 5/29/2019 8:48 AM
Package.swiftの1行目のコメントの
8:48 AM
// swift-tools-version:5.0
Avatar
おぉ、コメントを書き換えるんですね、ありがとうございます。
Avatar
どっちかというと https://github.com/apple/swift-package-manager/blob/master/Documentation/PackageDescription.md の swiftLanguageVersions じゃないでしょうか? (edited)
The Package Manager for the Swift Programming Language - apple/swift-package-manager
Avatar
omochimetaru 5/29/2019 9:50 AM
おお。知らなかったです。
Avatar
おぉ、ありがとうございます!
1:48 PM
これまで一個の repository の中に複数の library を入れてたんですが、コード量も増えてきて Swift のバージョンが上がるたびにまとめて修正するのが結構大変なので repo ごと細かく分割してこうかなと思ってます。 この場合パッケージ名は、 SwiftyMathCore, SwiftyMathAlgebra, SwiftyMathTopology などという風に、プロジェクト名の prefix をつける感じにするのが良いんでしょうか? おすすめのやり方などあれば教えて下さい🙇
Avatar
omochimetaru 5/29/2019 2:28 PM
そうですね、僕はよくそういう命名をしてます。 Mathは自明なので SwiftyAlgebraとSwiftyTopology でも良いかもしれませんが。
😀 1
Avatar
こんにちは🌞 またまた質問です🙇‍♂ TextViewで textDidChangeNotification を使いたいのですが可能でしょうか? (Swift5) TextView ではなくても、文字を何行も入力できるものであればよいのですが…(イメージとしては、メールの内容部分を書く所です。)(本当はtextField でしたかったのですが、文字量に合わせて改行が難しいようだったのでTextView にしました) どなたか宜しくお願い致します🙇‍♂️
Avatar
使えるはずかと 🤔 一応UITextViewもtextDidChangeNotificationがありますので https://developer.apple.com/documentation/uikit/uitextview/1618609-textdidchangenotification
Avatar
なるほど…🤔 でしたら他の部分が違うのかもしれないです! ありがとうございます!!!
Avatar
先程の続きなのですが、うまく動かなかったので教えてください🙏 下手な関数で誠に申し訳ないのですが、textField(title)とtextView(detail)のある画面にON OFFが切り替わるdraftButton, registerButtonがあります。 ・title, detailどちらも空→ボタン2つともOFF ・title, detailどちらも記入→ボタン2つともON ・title, detailどちらかが空→draftButtonのみON の挙動にしたいのですが、現状: ・title 入れない限りdetailに文字入れてもボタンOFFのまま ・detailに文字ありでtitle入れる→ボタンどちらもON ・detailに文字ありでtitle入れて消して空にする→draftButtonのみON ・↑の状態からdetail消す→draftButton ONのまま という感じです… titleいれるまでif文内を走ってくれません。 どうしたら良いでしょうか(´°̥̥̥ω°̥̥̥`)どなたかご教授お願い致します○rz
8:00 AM
8:00 AM
Avatar
恐縮なんですが、正しいAPIがどれか、というより先にデバッグの手順について学んだほうが良いかもしれません。
  • 理想的な挙動は何か
  • 現状起きていることの正確な理解と分解
  • その差を埋めるために何が必要か考える 例えばfunctionが呼ばれないのであれば、繋ぎ込みが間違えているので、
  • どこまで動いているのか、途切れている箇所を特定する
  • 途切れている箇所が自分の責任なら直す
  • 違うなら代替となる手段を探す
このような事をご自身で試していく必要があります。
Avatar
@tarunon ありがとうございます。 「現状起きていることの正確な理解と分解」、特に分解が凄く苦手なのは把握しているので、そこら辺をもっと勉強します!🙇‍♂️
Avatar
デバッグはコーディング同様に色々なテクニックがあるのですが、学べるようにはなっていないので(美しいコードはgithubで見れるが、デバッグは否) 参考になるサイトとかあると良いんですけどね
😭 1
8:27 AM
textFieldとtextViewで共通した処理を書いていると思うのですが、最後の判定まで共通化せずに書くと、途中の関数の疎通確認がやりやすくなると思います
8:27 AM
まず問題を分解してみましょう
Avatar
@tarunon ありがとうございます! やってみます!🙏
Avatar
ぼくがやるとしたら、とりあえず buttonItemsStatus の先頭あたりでいったん titleTextField.textdetailTextView.text の値を、それぞれ別の変数に入れてみてデバッガで止めるなり、ログに出すなりしてその値がどうなってるか見てみるとかしますね。
8:44 AM
それぞれの値が自分が想定していたものになっているかどうかと、思ったタイミングで buttonItemsStatus が呼ばれているだろうか?というあたりですかね。
Avatar
@hironytic なるほどですね。🤔 ありがとうございます!!!🙏😭
Avatar
@hironytic @tarunon お二方のおかげで無事解決しました!!分解して細かくして見ていくの大切ですね…!!! 本当にありがとうございます!!🙏✨✨
🎉 3
👍 1
Avatar
classにdebugQuickLookObject生やすとXcode上でプレビューを表示する機能ありますけど これってstructでも同様にプレビュー表示したい場合なにか対応方法あるでしょうか? classに生やす場合@objc func debugQuickLookObject() -> AnyObject?で定義するため、structだとそもそも宣言できません。
8:40 AM
ObjectiveCとして - (id)debugQuickLookObject メソッドで実現されてるので無理そうじゃない?
Avatar
無理そうだなーとは思ってるんですがstruct用の他の方法が提供されててもいいんじゃないかと思ったので。
Avatar
omochimetaru 6/17/2019 8:42 AM
これとは別にSwift向けのREPL連携用のprotocolなかったっけ
Avatar
これはPlaygroundっぽいですよね? 今やりたいのはブレークポイント貼って止めたところでQuickLookするという用途なのでちょっと違いそうです。
Avatar
omochimetaru 6/17/2019 8:48 AM
そうですねえ
Avatar
@_specialize で複数の型パラメータを特殊化するのってできないでしょうか? 行列の計算を @_specialize(where R == Int, Double) のようにして、頻用されるものについては特殊化して高速化したいのが目的です。
Avatar
@_specialize(exported: true, kind: full, where K == Int, V == Int) @_specialize(exported: false, kind: partial, where K: _Trivial64) func dictFunction<K, V>(dict: Dictionary<K, V>) { }
10:36 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
10:36 AM
specializeアトリビュート自体を複数書くとできると思います。
Avatar
おぉ、ありがとうございます!
10:40 AM
型を丸ごと specialize するのもできるんですかね(いま電車なので後で試してみる予定です)
Avatar
前試したけどできなかった気がします、funcにつけまくらないといけないような
Avatar
なるほどなるほど。
Avatar
別の質問なんですが、() 演算子を定義する感覚で dynamicCallable を使いたいのですが、普通のメソッド呼び出しに比べて動的呼び出しのオーバーヘッドが出てしまったりするでしょうか?
10:53 AM
いま f.applied(to: x) のように書いてるものを f(x) としたい。
10:53 AM
f は関数をラップした struct です。
Avatar
それはオーバーヘッドが出ますね dynamicCallableじゃなくてstaticCallableが出るのでそれを待ったほうがいいです https://forums.swift.org/t/se-0253-static-callables/22243
The review of SE-0253: Static callables begins now and runs through April 5, 2019. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as t...
Avatar
おぉ!!!
11:04 AM
まさにそれが欲しかった🤩
Avatar
ちなみに、Swift for Tensorflowにはもう入ってます
Avatar
早く使いたい😍
Avatar
不勉強すぎてお恥ずかしいのですが、ここの名前を教えていただけないでしょうか… 変更できなくてシュミレーターが表示されなくなってしまいした…꒰꒪꒫꒪⌯꒱
Avatar
あ、シュミレーター出すのはできました🙇‍♂️
Avatar
omochimetaru 6/20/2019 4:37 AM
そこは Scheme です
Avatar
ありがとうございます!!!!!
Avatar
UnsafeMutablePointer を alloc した後の initialize / deinitialize は、値型の場合でも呼ばないといけないんでしょうか?
5:18 AM
pointee に直接入れるのと何が違うのか分かってません🙄
5:20 AM
struct の中で参照型を保持してるような場合に、それをちゃんとやらないと参照カウントがおかしくなるとか?
Avatar
omochimetaru 6/21/2019 5:22 AM
呼ばないといけません
5:22 AM
Swiftのメモリモデルでは、メモリ領域は、「初期化済み」と「未初期化」があって、
5:23 AM
UnsafeMutablePointer.allocateしたメモリ領域は「未初期化」であり、
5:23 AM
.pointeeにアクセスしてよいのは「初期化済み」のときだけです。
5:23 AM
pointeeに直接入れるのと何が違うのかというと
5:24 AM
pointeeへの書き込みは「既存の値の破棄」と「新しい値の構築」の2つの手順を含むからです これは通常の変数への代入のときも同じことです
5:24 AM
initializeによる書き込みは、書き込み先メモリが未初期化であることを仮定しているので
5:24 AM
「既存の値の破棄」がスキップされて「新しい値の構築」だけが実行されます。
5:25 AM
もし、未初期化のメモリ領域 に対して、「既存の値の破棄」を行ってしまうと
5:26 AM
例えば、その型が参照型のstored propertyを含む場合に、 ランダムなアドレスに対してアクセス(参照カウンタのdecrement)する事になって、ランタイムクラッシュするなどの可能性があります。
5:26 AM
「struct の中で参照型を保持してるような場合」 ↑それであってます。
Avatar
ふーむ、なるほど。
Avatar
omochimetaru 6/21/2019 5:28 AM
つまり、Swiftの値型というのは、それのもつメモリ領域に対して書き込みをするときに、適切な関数呼び出しをセットにして様々な処理をしないといけない、ということです。
5:28 AM
C言語でmemcpyするみたいに、メモリ領域をそのままコピーできるような型の事を、 C++の用語で bitwise copyableとかbitwise takableとか言うんですが
5:29 AM
Swiftのstructはbitwiseではない、という言い方もします。
5:29 AM
ただ、実際にstored propertyがIntみたいな型しか持っていないときは、
5:29 AM
実際のところはbitwise copyableであるため、問題が起きない、という事はあります。
Avatar
ふむふむ、なるほど。
Avatar
omochimetaru 6/21/2019 5:30 AM
bitwise copyable以外にも、そうした性質を「trivial」って呼ぶこともありますね。
Avatar
よく分かりました!
5:35 AM
もう一つ質問させてください🙇‍♂️ alloc の方は引数で長さを指定するのに対して、dealloc は引数なしになってるんですが、これは alloc 時にメモリ何個分を確保したかを UnsafeMutablePointer の内部で保持してるからなんでしょうか…? 感覚的には dealloc 時も同じ個数を指定しないと正しく動作しなそうな気がして🤔 (edited)
Avatar
Kishikawa Katsumi 6/21/2019 5:35 AM
allocの引数って長さでしたっけ?
Avatar
omochimetaru 6/21/2019 5:36 AM
長さじゃなくて要素数ですかね
5:36 AM
質問の答としては内部で保持しているからです。 でも、保持する場所はUnsafeMutablePointerの内部ではないです。
Avatar
Kishikawa Katsumi 6/21/2019 5:36 AM
なるほど。
Avatar
omochimetaru 6/21/2019 5:37 AM
Swiftのallocateを解析してないので予想ですが、 こういったメモリアロケータは、一般的なテクニックとしては
Avatar
すみません、要素数です。
Avatar
omochimetaru 6/21/2019 5:37 AM
メモリ確保するときに、 要求されているメモリサイズに加えて、少し多めの領域をメモリ確保していて
5:38 AM
その多めの領域に、サイズとか、その他メモリアロケータ管理用の情報を仕込んでます
5:38 AM
その領域は先頭にあって、ユーザに返ってくるポインターは
5:38 AM
その先頭領域からオフセットされたストレージの部分を指しています
Avatar
ふむふむ。
Avatar
omochimetaru 6/21/2019 5:38 AM
言い方を変えると、返ってきたポインタのマイナスのオフセットのところに、メタデータがあるってことです。
Avatar
はー、なるほど。
Avatar
omochimetaru 6/21/2019 5:39 AM
メモリ確保のときに容量を与えて、解放時はポインターだけで良いのは、 C言語のmallocとfreeの時代から、そういうスタイルですね https://linuxjm.osdn.jp/html/LDP_man-pages/man3/malloc.3.html
Avatar
dealloc を呼ぶポインタは、返ってきたポインタを使わないといけないんですよね? 例えば capacity:10 で alloc して返ってきたポインタの、次のポインタに対して dealloc を呼んだりしたら壊れるという認識で合ってそうですか?
Avatar
omochimetaru 6/21/2019 5:40 AM
あってます。
Avatar
よく分かりました!!!
Avatar
omochimetaru 6/21/2019 5:40 AM
4つ分確保しておいて、後ろ2つ分だけ解放するとかはできません。 (edited)
Avatar
おっしゃおっしゃ
5:45 AM
ありがとうございます、とてもスッキリしました😌
😁 1
Avatar
毎度恐れ入ります🙇‍♂️ 色々調べたのですが原因がわからなかったので、もしどなたか他に調べた方が良い箇所あれば教えていただきたいです! TextView 内に placeholder 設置してます。 何故か、”Comment “が “Comme” + “ nt “ で改行されます😫 検証内容は↓ ・eとnの間に空白ある→❌ ・eとnの間に\n 入ってる→❌ ・6文字英単語”anchor”入れても改行されない ・8文字英単語”arguably”入れたら途中で改行される ・adjustFontSizeToFitWidth = true ・他のサイズ決めてるコードは写真の通り です… label幅の問題なのかなとも思いますが、sizeToFit() になってます… SizeThatFit()のほうでしょうか…
Avatar
label.numberOfLines = 1 にしてからもう一回 sizeToFit() してみましょうか? sizeToFit() はラベルのサイズを動的に調節するメソッドではなく、ラベルのサイズを呼び出された時点のコンテンツに合わせて調節するメソッドです
9:48 AM
ちなみに sizeThatFits(_:) メソッドは親ビューにこのメソッド呼ばれた時の返してあげたいサイズを返すメソッドですので、それ呼ばれても特にサイズの変更はありません
Avatar
@lovee ご返答ありがとうございます!!! やってみます!!
Avatar
並列可能な処理を非同期化してみようと思っているのですが、一つの配列に並列で値を書き込むということはできないんでしょうか?以下のコードは leave のとこで EXC_BAD_INSTRUCTION が出てしまいます。count1 にすると通るのですが。 var a = Array(repeating: 0, count: 10) let group = DispatchGroup() group.enter() for i in a.indices { DispatchQueue.global().async { a[i] = i group.leave() // EXC_BAD_INSTRUCTION } } group.wait() print(a) // [0, 1, ..., 9] と出て欲しい (edited)
Avatar
omochimetaru 6/23/2019 5:03 PM
だめです
Avatar
おぉ、ダメなんですね。
Avatar
omochimetaru 6/23/2019 5:03 PM
「SwiftのArrayの要素のindex違いに対して並列なアクセスができる」というのは
5:03 PM
「よくある間違い」として挙げられています
Avatar
なーるほど。
Avatar
omochimetaru 6/23/2019 5:05 PM
var a = Array(repeating: 0, count: 10) let q = DispatchQueue(label: "array") let group = DispatchGroup() group.enter() for _i in a.indices { let i = _i DispatchQueue.global().async { q.sync { a[i] = i } group.leave() // EXC_BAD_INSTRUCTION } } group.wait() print(a) // [0, 1, ..., 9] と出て欲しい
5:06 PM
↑対応としてはこうやってArrayへのアクセスを直列化するキューを別にもつのが多分簡単です タスクそれ自体は並列化してるので効果はでるはずです。
5:06 PM
(あとforのiをキャプチャするのが怖かったのでいったん_iに置いてみました
Avatar
なるほどなるほど。
5:07 PM
書き込むとこだけ同期化すれば、書き込む値を計算するところは並列可能ということですね。
Avatar
omochimetaru 6/23/2019 5:08 PM
そです!
Avatar
あれ、上のコードをそのまま貼り付けて実行してみたのですが、やはり leave のとこで クラッシュしてしまうようです。
Avatar
omochimetaru 6/23/2019 5:11 PM
enterが一回なのが変ですね
Avatar
あっ、なるほど!
Avatar
omochimetaru 6/23/2019 5:11 PM
forループの中で開始するときに呼ぶ
Avatar
できました!!!
5:14 PM
async って例えば 1万回 呼んだりしても、内部でよしなに計らってくれるんですかね?
Avatar
omochimetaru 6/23/2019 5:15 PM
はい、globalさんは良きにやる
5:15 PM
↑こういうのもありますよ
Avatar
これは同じ処理を繰り返す時に使うものですかね?
5:16 PM
ループの回数も受け取れるのか
Avatar
omochimetaru 6/23/2019 5:16 PM
いえ、並列にやる
Avatar
var a = Array(repeating: 0, count: 10) let q = DispatchQueue(label: "array") DispatchQueue.concurrentPerform(iterations: 10) { i in q.sync { a[i] = i } } print(a) // [0, 1, ..., 9] と出て欲しい (edited)
5:18 PM
できました!
5:18 PM
こりゃいいですね、enter /leave や wait もいらないんですね。
Avatar
omochimetaru 6/23/2019 5:19 PM
そですそです
Avatar
素晴らしすぎる
5:20 PM
同期は書き込みだけすればよくて、読み込みは並列にやっても大丈夫という認識であってますか?
5:21 PM
var a = Array(repeating: 0, count: 10) let b = Array(0 ..< 10) let q = DispatchQueue(label: "array") DispatchQueue.concurrentPerform(iterations: 10) { i in let x = b[i] * 2 q.sync { a[i] = x } } (edited)
5:21 PM
例えばこういう。
5:21 PM
あ、間違えたw 直しました (edited)
5:22 PM
let x = ... のところに、重い処理が入る予定。
Avatar
omochimetaru 6/23/2019 5:52 PM
読み込みはよくわかんないです 多分大丈夫だけど僕だったら同期とります
Avatar
norio_nomura 6/23/2019 9:34 PM
SwiftLintで書き込み時の同期を無くしたparallelMap実装を1年以上使ってます。 https://github.com/realm/SwiftLint/blob/740e398f9115f1f16048ea6979060f4e83a36b1c/Source/SwiftLintFramework/Extensions/Array%2BSwiftLint.swift#L56-L64 (edited)
A tool to enforce Swift style and conventions. Contribute to realm/SwiftLint development by creating an account on GitHub.
Avatar
enum Enum: Equatable { case a case b(Int) } let a = Enum.a print(a == Enum.a) let b = Enum.b(1) //print(b is Enum.b)??? assocvalue付きのケースについてある変数があてはまるか確認する式ってないんですっけ? assertに書こうとしたら詰まったんですが。 (edited)
Avatar
omochimetaru 6/25/2019 1:38 AM
式は無い
1:38 AM
if case文になる
1:38 AM
てかそれEquatableつけられたっけ?
Avatar
手元ではコンパイルできてますね
1:40 AM
@swiftbot enum Enum: Equatable { case a case b(Int) } let a = Enum.a print(a == Enum.a) let b = Enum.b(1) print(b == Enum.b(2))
🛠 1
Avatar
swiftbot BOT 6/25/2019 1:40 AM
Author icon
t.ae
enum Enum: Equatable { case a case b(Int) } let a = Enum.a print(a == Enum.a) let b = Enum.b(1) print(b == Enum.b(2))
Version:
swift-4.2.1-RELEASE
Output:
true false
Error:
Avatar
omochimetaru 6/25/2019 1:41 AM
個人的にはcaseプロパティ生やしてる
1:41 AM
インナータイプとしてCase型を定義して。
1:42 AM
そうすれば.case同士の==で書ける
Avatar
enumが二重になるつらみはありますね。 assertだけなので最適化で消えることを祈りつつif caseで書いておきます。
Avatar
@lovee 遅くなりましたが、number of lines = 1 にしたらできました! ご丁寧な回答ありがとうございます!!助かりました😭
🎉 3
1:49 AM
(会話遮ってしまって申し訳ありません🙇‍♂️)
Avatar
失礼します! 前回解決したと思われたplaceholder の件です🙇‍♂️ 別画面でまさかのplaceholder が見切れている問題を発見してしまいまして…(┐「﹃゚。) NumberOfLine を1にしようが0にしようが見切れております… Placeholder のクラスを作り、それを必要画面のtextViewで INOutlet weak var textView: PlaceHolderTextView! で呼び出して使っています。 Placeholder クラスはちゃんと呼ばれていますし中身も走ってますし、おそらくplaceholder のwidthがtext view のwidthとうまく繋がっていないのかなぁとは予想付けているのですが、ここ数日調べてみましたが見つけられず。。 予想される原因や解決方法等ご教示いただけると幸いです(´°̥̥̥ω°̥̥̥`) RxSwiftでやってます。
1:42 AM
Avatar
layoutSubviews で label の frame を更新するか、 AutoLayout を使うといいですよ
Avatar
@nanasi ご返答ありがとうございます!! 返答いただいてから、layoutSubviewsのほうで試行錯誤してやっております。中々うまくいきませんが🤣 昨日autolayoutの方でやっててうまく実行できなかったので諦めていたのですが、やり方さえ間違えなければいけるんですね! ありがとうございます!!!!
Avatar
とりあえず単純なものであれば、これで実現できるとおもいます (sizeToFit はこの場合不要です) class PlaceHolderTextView: UITextView { override func layoutSubviews() { super.layoutSubviews() placeHolderLabel.frame = bounds.insetBy(dx: 6, dy: 6) } }
10:05 AM
ただTextViewがプレースホルダより小さい場合は結局はみ出てしまうので、その場合はAutoLayoutでやったほうが簡単です
Avatar
@nanasi ありがとうございます!! 返信滞ってしまってすみません💦 勉強不足で申し訳ないのですが、良ければご教授いただけると幸いです。そもそも、なぜTextView よりもplaceholder が大きくなるのでしょうか?? Placeholder とtextViewのwidthを同じに設定するようにコードを書いているつもりなのですが…🙇‍♂️
Avatar
例えばTextViewを w: 240, h: 44 とレイアウトして、プレースホルダの文章がそれを超えるような長い文字列の場合、TextView自体は↑のコードではサイズが変わらないためです。
4:17 AM
なのでデザイン上そういったことがなければ問題はないです 👌
Avatar
あーなるほど(?) TextViewのサイズが変わらない=それを参照している(?)placeholder のサイズも変わらない という事ですかね!?! textViewのwidth よりplaceholder の文字量が多くて大きいので、もう一度auto layout で設定してみようと思います。 ありがとうございます🙇‍♂️
Avatar
TextViewのサイズが変わらない=それを参照している(?)placeholder のサイズも変わらない
というより (親の)TextViewのサイズが変わらない=(子の)placeholderのサイズはそれを超えるとはみ出てしまう といった感じですね
5:22 AM
なので親のTextViewのサイズが十分なら先のlayoutSubviewsでも問題は解決できます
5:24 AM
プレースホルダ付きのTextViewは大抵誰もが作ったことがあるものなのでGitHubで探して参考にしてみるのもいいかもです😀 (edited)
Avatar
んーなるほど。
(子の) placeholder のサイズはそれを超えるとはみ出てしまう
のはわかりました。 しかし、はみ出た場合ははみ出る直前で改行する ためにnumber of lines や size to fitのメソッドがあるのかと思ってました。。
5:59 AM
以前nanasi さんが送ってくださったbounds.insetBy()のメソッドで、textView 内に収まってはくれたのですが、上にも空白ができてしまい(insetByが中心点の~...メソッドなので仕方ないですよね🤣)、それが解決できなければやはりauto layout をしようと思います🙇‍♂️ いつも本当にありがとうございます!!!!
Avatar
number of linesは十分なサイズが与えられたときに何行表示させるかのプロパティなので、自身のサイズが小さい場合はそれに何を設定しても関係なく、そのサイズ内でクリッピングされます(デフォルトなら ...
6:16 AM
size to fitは親ビューに関係なく自身のコンテンツがちょうど表示される大きさにframeを更新するメソッドなので、TextViewが w: 240 だったとしてもプレースホルダの文章が長いならプレースホルダのラベルは w: 400 になったりします (edited)
Avatar
うわぁぁぁぁ どちらもそういう事だったのですね…!!!! ご教授いただきありがとうございます😭😭😭✨✨
😉 1
Avatar
上にも空白ができてしまい(insetByが中心点の~...メソッドなので仕方ないですよね🤣)
その空白がどのくらいのものかですが、6ptなら指定通りです insetByは中心点は関係なく、例えば CGRect(x: 0, y: 0, width: 100, height: 50).insetBy(dx: 5, dy: 5) とすれば {x 5 y 5 w 90 h 40}と内側に dx, dy分インセットした領域を返す関数です
6:32 AM
6ptなのはスクショにあったcreateLabelのoriginを持ってきたからです😇
6:33 AM
厳密に合わすとなったらAutoLayoutでfirstBaselineなど駆使する感じですね
Avatar
なるほどですね! 空白はこんな感じです🤣 思いっきり中心にきてます。 ということはcreateLabelの設定からいじるべきですかね🤔
Avatar
そういえばラベルは縦方向は真ん中寄せでしたね😅
6:46 AM
上のコードならinsetByのあとにplaceholderLabel.sizeToFit()を付け足せばうまくいきそうです
Avatar
うわぁぁぁぁ!!! ありがとうございます!! なりました!😭 スゴイ…👼
👏 2
Avatar
Taketo Sano 7/4/2019 1:34 AM
いつの間にか Array や Dictionary も conditional に Hashable に conform するようになってたんですね 😃 Array や Dictionary 型の Key をもたせたいときに、別に struct 作ったりしてたのが面倒でした 😃 (edited)
Avatar
omochimetaru 7/4/2019 1:35 AM
Swift4.2でconditional conformanceが入った時に対応されてた気がします
Avatar
Taketo Sano 7/4/2019 1:41 AM
結構前からあったんですね😂 is便利
Avatar
Taketo Sano 7/5/2019 3:42 AM
parameterized extension がほしくて震えます😖 実現の目処って立ってるんでしょうか?
Avatar
僕の観測範囲では立ってないと思います。 ↓参照 (edited)
3:42 AM
前の裏技は難しいケースですよね?
3:43 AM
複雑なジェネリックライブラリだとぶっ壊れそうですしね・・・。
Avatar
omochimetaru 7/5/2019 3:43 AM
Parameterized Extensions Proposal: SE-NNNN Author: Alejandro Alonso Review Manager: TBD Status: Awaiting Review Implementation: apple/swift#25263 Introduction Hello Evolution, this is my first draft at a proposal for Parameterized Extensions. I would greatly appreciate ...
3:43 AM
天才のAzoy少年が
3:43 AM
最近実装してて
3:43 AM
PItchも自分で投げてた。
Avatar
お、最近だ。
3:44 AM
これはうれしい、けど、今から実装されても最速で来年( 5.2 か 6.0 )かな?
Avatar
omochimetaru 7/5/2019 3:45 AM
5.1はもうXcodeBeta3だし最速でも5.2でしょうね〜
Avatar
ほぇー、すごい。
Avatar
すえたく 7/9/2019 12:45 PM
いきなり質問失礼します spotifyのSDKを使ったiosとspotifyとの連携について質問したいです。 今、iosアプリからspotifyが公開しているSDKを使って音楽を流そうとしています。(公式tutorial: https://developer.spotify.com/documentation/ios/quick-start/ ) (SDKのgithub: https://github.com/spotify/ios-sdk) 公式のチュートリアルを読みつつ進めているのですが、herokuを使ったクライアントIDのswap/tokenとrefresh/tokenの取得が理解できずにハマってしまっています。 特に、herokuとiosアプリとのやり取りの部分で、herokuでなにを設定すればいいのか、それに伴ってiosアプリ側でなにをすればspotifyとの連携ができるようになるのかがわかりません。 もしよければ教えてください (edited)
Create a simple iOS application that uses the Spotify iOS SDK to play a track and respond to changes in playback state.
Avatar
呼んでみましたけど、Herokuは単純にtoken swapに使ってるだけで、そのロジックはローカルでも持てるので必須ではないと読み取れます、あくまで strongly discourage (非常に非推奨)だけですので
Avatar
すえたく 7/9/2019 4:02 PM
@lovee 返信ありがとうございます! 確かにその通りなのですが、最終的にgithub等でアプリを公開することを考えいて、そのためにherokuを使ったtoken swapをしたいと思っています。。。
Avatar
@すえたく なるほど、それはまあ面倒な話ですね 🤔 どっちかと言うとiOS/Swiftの領域を超えてるような…最低限のServer-Sideの知識が必要になるので、多分herokuとかのチュートリアルを探したほうがいいかもしれないです(自分もherokuのデプロイはすっごい昔に一回だけ試してみただけで完全に忘れてるので… 😓
Avatar
すえたく 7/10/2019 8:06 AM
@lovee なるほど……一度heroku関連の情報漁ってみます!ありがとうございます!
Avatar
@すえたく Document読んだ感じ One-click with Heroku とあるので 下記リンクのDeploy to HerokuをクリックするだけでHeroku側の設定は完了するかと。 https://github.com/bih/spotify-token-swap-service#one-click-with-heroku
Swap tokens for using Spotify APIs and SDKs, made really simple 🔑 ⛓ - bih/spotify-token-swap-service
Avatar
補足すると、 Herokuサーバを用意してまでやりたいことは、 Client IDClient Secret をアプリに持たせると解読等された場合に悪用される可能性あるから、 Client Secret はサーバ側に持たせることで、サーバ経由のToken更新を行い、セキュアな状態にするためみたい
Avatar
すえたく 7/10/2019 2:17 PM
@ありぜ 返信ありがとうございます! なるほど…。そうなると、herokuで何かを設定するというよりは、アプリケーション側の設定(callback用のURL等)を適切に設定すればOK。。。? クイックスタートには/api/tokenや/api/refresh_tokenを入れることになってますが、それもheroku側が自動的に設定していることになるんでしょうか?
Avatar
@すえたく
そうなると、herokuで何かを設定するというよりは、アプリケーション側の設定(callback用のURL等)を適切に設定すればOK。。。?
あーすみません、heroku側で一部だけ設定してやる必要ありました。なので手順は、下記でした。 1. Deploy to Herokuをクリック 2. https://github.com/bih/spotify-token-swap-service#configuration の環境変数項目のRequiredを最低限設定する ---
クイックスタートには/api/tokenや/api/refresh_tokenを入れることになってますが、それもheroku側が自動的に設定していることになるんでしょうか?
/api/token/api/refresh_token はHerokuサーバに対して行います。 つまり、Heroku設定後、quick-startの続きにあるコードの [my token swap app domain] をherokuのアドレスに置き換えてiOSアプリを実装したらOKです。 仮にHerokuサーバのアドレスが https://swap.heroku.com/ であれば… // Swiftコード lazy var sessionManager: SPTSessionManager = { if let tokenSwapURL = URL(string: "https://swap.heroku.com/api/token"), let tokenRefreshURL = URL(string: "https://swap.heroku.com/api/refresh_token") { self.configuration.tokenSwapURL = tokenSwapURL self.configuration.tokenRefreshURL = tokenRefreshURL self.configuration.playURI = "" } let manager = SPTSessionManager(configuration: self.configuration, delegate: self) return manager }() のように書いて、quick-startを進めていけば大丈夫かと思います
(edited)
Avatar
すえたく 7/10/2019 3:32 PM
@ありぜ なるほど! 一度その方法で動かしてみます!ありがとうございます!
👍 1
Avatar
typealias した型に対して extension や conditional conformance するのって公式にはサポートされてないんでしたっけ?以下の書き方でコンパイルも通るし,こう書いて良いのなら書きたいんですが. protocol X { static func hello() } typealias IntArray = [Int] extension IntArray: X { // typealias した型に対して extension static func hello() { print("hello") } } [Int].hello() // OK [String].hello() // ちゃんとエラーになる: Referencing static method 'hello()' on 'Array' requires the types 'String' and 'Int' be equivalent (edited)
5:04 AM
typealias してる元の型が複雑な場合,そう書けた方が読みやすいので. typealias GridChainComplex = ChainComplex1<FreeModule<TensorGenerator<MonomialGenerator<_Un>, GridDiagram.Generator>, 𝐙₂>> extension GridChainComplex { // こう書きたい }
Avatar
omochimetaru 7/11/2019 5:06 AM
それはできた気がしますね
5:07 AM
公式サポートかどうかは調べたことないですが
5:07 AM
ただ似たようなのでダメなパターンが会って
5:07 AM
public typealias Single<Element> = PrimitiveSequence<SingleTrait, Element>
5:07 AM
こういう、エイリアス側にジェネリックパラメータがあるようなやつは
5:07 AM
うまく動かなかった気がする
Avatar
なるほどなるほど.
5:09 AM
ありがとうございます🙏
5:12 AM
ちゃんと動いてそうな感じはします🤔 protocol Helloable { static func hello() } struct Something<A, B> {} typealias Something_Int<B> = Something<Int, B> extension Something_Int: Helloable where B == Int { static func hello() { print("hello") } } Something<Int, Int>.hello() // OK Something_Int<Int>.hello() // OK Something_Int<String>.hello() // NG
5:14 AM
でも前にこういう書き方でもっと複雑なことやって Seg Fault 地獄に陥った気もするので,避けといた方がいいのかな🤔 (edited)
Avatar
omochimetaru 7/11/2019 5:15 AM
Something_Intもいけてる?
Avatar
はい,いけてます.
5:15 AM
(Xcode 11 beta 3 で動かしてます)
Avatar
omochimetaru 7/11/2019 5:16 AM
そのへん直してた頃があった気もするので今はいけるのかも。
Avatar
おっ,そうなんですね.
Avatar
macOS の selectAll(_:) の iOS版 メソッドって存在しますか??💦
Avatar
Kishikawa Katsumi 7/18/2019 2:58 AM
UIResponderがselectAllメソッドを持っています。 TextViewなどに呼べば動きます。 https://developer.apple.com/documentation/uikit/uiresponderstandardeditactions/2354200-selectall
Avatar
@Kishikawa Katsumi ありがとうございます!😭
3:05 AM
すみません、書き忘れておりました。 tableView内で使っています。 allowMultipleSelectionDuringEditing メソッドを使用していて、table view cell を複数選択することはできます。 やりたい事は、存在するtable view cell をボタンタップで一気に全選択することです。🙇‍♂️ select Allのメソッドだったらそれはできるのかなーと思い、iOS版で同じようなメソッドがあるか探しています。(現在 for in 文でできるか検証中です)🙇‍♂️
Avatar
Kishikawa Katsumi 7/18/2019 3:15 AM
TableViewでしたか。それは自分で書くしかないです。
Avatar
@Kishikawa Katsumi そうなのですね! ご教授くださりありがとうございます!!!✨✨
Avatar
Swift 5.1 だと Python.import って動かないですか?
4:29 PM
Swift REPL でやろうとしてます。
Avatar
omochimetaru 7/18/2019 4:29 PM
import Python書けば使えるような気が
Avatar
あれれ
4:29 PM
1> import Python 2> let numpy = Python.import("numpy") error: repl.swift:2:13: error: module 'Python' has no member named 'import' let numpy = Python.import("numpy") ^~~~~~ ~~~~~~ (edited)
4:29 PM
こうなってしまいまして🙄
Avatar
omochimetaru 7/18/2019 4:30 PM
あれー。モジュールはあるんですね。
4:30 PM
モジュールの中身をダンプするREPLコマンドがなんかあるから
4:31 PM
Pythonに何があるか確認するとよさそう
4:32 PM
なんだったかな・・・
Avatar
swift -frontend -replで起動して、インポートして:print_module <モジュール名>ですね。
11:46 PM
xcode-selectXcode-beta.appを選択していない場合、-sdkパラメータも追加で渡す必要があるぽい。
11:46 PM
こんな感じ。 $ DEVELOPER_DIR=/Applications/Xcode-beta.app swift -frontend -repl -sdk $(DEVELOPER_DIR=/Applications/Xcode-beta.app xcrun -sdk macosx -show-sdk-path) *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) (edited)
Avatar
おっ、ありがとうございます!
Avatar
omochimetaru 7/19/2019 1:31 AM
:print_module Pythonしたら4000行ぐらい出てきた
1:37 AM
@_exported import Python.import_ これは見えるけど import_は無いなあ
1:42 AM
これPython.frameworkが見えてるだけでSwiftバインディングじゃないっぽいな
1:44 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
1:44 AM
S4TFからこのディレクトリのソースコピペしてきて、まずそれを読み込めば行ける気がします。
Avatar
importのあるPythonはSwift for Tensorflowにしかないと思います。Swift for Tensorflowを入れるのが早そうな気が。 https://github.com/tensorflow/swift/blob/master/Installation.md
Swift for TensorFlow Project Home Page. Contribute to tensorflow/swift development by creating an account on GitHub.
3:38 AM
S4TF入れるなら、numpyの代わりにTensorで済むかも?目的によりますが&numpyを使いたいわけではないかもですが。 https://www.tensorflow.org/swift/api_docs/Structs/Tensor
Avatar
iOS13やiPad OSからサードパーティ製クッキー周りの仕様変更ってあったんでしょうか。。。 WKWebViewにユーザーのクッキーを使ってコンテンツ表示していて、このコンテンツの中にはiframeでサードパーティ製のコンテンツも表示しています。 このiframe内にも仕込んだクッキーをセットしてるはずなのですが、iOS13やiPad OSでのみクッキーがセットされていない状況です。 macos版Safariがサードパーティクッキーを制限したときと同種のものと思っているのですが、そういった情報を検索してもでてこないので、困っている状況です。
Avatar
(入れ違いすみません) @koher さん、コメントありがとうございます、普通の Swift ではまだ Python.import はできないんですね。
Avatar
すみません、Xcode をアップデートしたらstoryboardがおかしくなるエラーが解決できずどなたかにお助け願いたいのですが、ここで質問してもよろしいでしょうか? Xcodeチャンネルもしくはその手の質問受け付けてません!という感じでしたら教えてください🙇‍♂️😭
Avatar
多分最新のXcodeだと、急ぎでは殆どの方が触ってないので自分で解決するしかないです。
2:53 AM
情報が出揃うまでバージョンアップを避けるのも手ですね。
Avatar
Kishikawa Katsumi 7/23/2019 2:54 AM
チャンネルはどっちでもいいのでどんなエラーが出てるのかを共有してください。
Avatar
流れてしまう前に @takenoko ちゃんと調査した訳ではないのですが、macos版Safariで過去に同じことがあったのであれば、OSのアップデートと共にWKWebViewにパッチが当てられていると考えるのが自然だと思います。(だいたい1,2世代遅れで反映されるイメージ)
😫 1
Avatar
会話の途中に申し訳ありません🙇‍♂️ 私のググり力の無さで既に既出エラーでしたら誠に申し訳ありません!!! Xcode のエラーメッセージです。 file:///Users/otoyamisato/Mydictionary/MyDictionary/Base.lproj/Main.storyboard: error: IB Designables: Failed to render and update auto layout status for NewNoteViewController (iIJ-cw-XLr): Failed to launch designables agent. Check the console for a more detailed description and please file a bug report at bugreport.apple.com. (edited)
3:09 AM
Avatar
IBDesignableが壊れてますね
Avatar
そうなんですよね…😭
Avatar
iPhoneXs かつ iOS12.4のSimulatorが見つけられないと書いてるように見えるのですが
Avatar
それの見つけ方がいまいちよくわかりませんでした…💧 Simulator も iOS devices から変えられなかったです。
Avatar
Failed to find a suitable device for the type iPhoneXs with runtime iOS 12.4 と書いてあるので
3:18 AM
Simulatorが見つからない場合にどうするのかは検索したら出てくると思います
3:19 AM
だいたいこの手合いは、経験則では、再起動、OS再起動、Xcode再インストールの順番で試すと治ることが多いです。
😳 1
Avatar
Pc再起動で治りました!!!😭 すいません!ありがとうござます🙇‍♂️🙇‍♀️
Avatar
エラーメッセージは、出てきたものを全て上から下まで読みましょう
Avatar
はい、すみません🙇‍♀️ お手数おかけしました💦
Avatar
OSのアップデートと共にWKWebViewにパッチが当てられていると考えるのが自然だと思います。
そうなのですね。。。たるのんさん回答ありがとうございます。
Avatar
norio_nomura 7/23/2019 4:07 AM
サードパーティークッキーの変更はセッションで言及されてますね。これが該当するものかどうかわかりませんが。 https://developer.apple.com/videos/play/wwdc2018/234/?time=548 (edited)
Safari and WebKit are continually evolving with new features, APIs, and cutting edge web standards. Learn about this year's biggest...
4:07 AM
あ、これ2018だった…
4:12 AM
あとはSafari Technology Previewのリリースノートを見てみるとか。 https://developer.apple.com/safari/technology-preview/release-notes/
Avatar
ざっくりした質問ですみません、 allowsMultipleSelectionDuringEditingメソッドで、タップをしたらチェックマークがつくのって、どういう仕組みなのでしょうか? https://developer.apple.com/documentation/uikit/uitableview/1614944-allowsmultipleselectionduringedi (edited)
3:22 AM
詳細がわかるページ等ありましたら教えていただけると幸いです。
Avatar
Kishikawa Katsumi 7/24/2019 9:24 AM
そういう風にUIKitが実装しているから、、、という答えになると思うんですけど、 聞きたいことは、同じようなビューを自分で実装したいから仕組みを知りたい、ってことですか?
9:24 AM
要するに選択したらチェックマークがつくようものを作るにはどうしたらいいか?という質問でしょうか。
Avatar
@Kishikawa Katsumi 返信遅くなりました💦
11:58 PM
>要するに選択したらチェックマークがつくようものを作るにはどうしたらいいか?という質問でしょうか。
11:58 PM
はい!そうです!!
Avatar
度々申し訳ありません💦 一応、全選択をするのはfor in文でselectRowメソッドを使用して解決致しました。💦 💦
5:11 AM
UIKitが実装しているものと同様のものを自作するのは100万年くらい早いので、そういう時はいろんなメソッドを駆使してやっていこうと思いますorz
Avatar
Swift (& C++) 製のプログラムを高速に走らせたいので EC2 でやるのがいいかなと考えているのですが、他にオススメの方法や環境などはあるでしょうか? (edited)
Avatar
GCP で試してみることにしました 💪
12:08 PM
インストールめっちゃ簡単ですね,もっと色々難しいことやらないといけないのかと思ってた 😆
Avatar
バイナリ配布があるので対応OSのLinuxなら簡単ですねー
Avatar
ありがたや 🙏
Avatar
純 Swift の package は実行できたんですが,下の C++ と混合してるのを build しようとすると謎の文字列を吐いて死んでしまいます…🙄 原因のわかる方いらっしゃいますか? https://github.com/taketo1024/ClosedRegion/blob/master/Package.swift $ swift build --verbose lsb_release -r /home/taketo1024/swift-5.0.2-RELEASE-ubuntu18.04/usr/bin/swiftc --driver-mode=swift -L /home/taketo1024/swift-5.0.2-RELEASE-ubuntu18.04/usr/lib/swift/pm/4_2 -lPackageDescription -swift-version 5 -I /home/taketo1024/swift-5.0.2-RELEASE-ubuntu18.04/usr/lib/swift/pm/4_2 -sdk / /home/taketo1024/ClosedRegion/Package.swift -fileno 7 which clang /home/taketo1024/swift-5.0.2-RELEASE-ubuntu18.04/usr/bin/clang -target x86_64-unknown-linux --sysroot / -fPIC -g -O0 -DSWIFT_PACKAGE=1 -DDEBUG=1 -fblocks -fmodules -fmodule-name=LinBoxWrapper -I /home/taketo1024/ClosedRegion/Sources/LinBoxWrapper/include -fmodules-cache-path=/home/taketo1024/ClosedRegion/.build/x86_64-unknown-linux/debug/ModuleCache -framework Accelerate -MD -MT dependencies -MF /home/taketo1024/ClosedRegion/.build/x86_64-unknown-linux/debug/LinBoxWrapper.build/LinBoxWrapper.mm.d -c /home/taketo1024/ClosedRegion/Sources/LinBoxWrapper/LinBoxWrapper.mm -o /home/taketo1024/ClosedRegion/.build/x86_64-unknown-linux/debug/LinBoxWrapper.build/LinBoxWrapper.mm.o : .
Contribute to taketo1024/ClosedRegion development by creating an account on GitHub.
Avatar
あ,Swift 5.1 でビルドしてみたら fatal error: 'Foundation/Foundation.h' file not found #import <Foundation/Foundation.h> ^~~~~~~~~~~~~~~~~~~~~~~~~ と出ました。Obj-C をビルドするのに何かがいるのかな🙄
Avatar
sudo apt-get install gnustep gnustep-devel gobjc/usr/include/GNUstep/ 下に Foundation/ が入りましたが,これはどうやって SwiftPM で指定するのかしら🙄 (edited)
Avatar
Kishikawa Katsumi 8/20/2019 1:45 PM
とりあえず "-I", " /usr/include/GNUstep" をcxxSettingsに追加したらどうなります?
Avatar
ありがとうございます,今それをやってました!
1:52 PM
In file included from /home/taketo1024/ClosedRegion/Sources/LinBoxWrapper/LinBoxWrapper.mm:8: In file included from /home/taketo1024/ClosedRegion/Sources/LinBoxWrapper/include/LinBoxWrapper.h:8: In file included from /usr/include/GNUstep/Foundation/Foundation.h:30: /usr/include/GNUstep/GNUstepBase/GSVersionMacros.h:361:16: fatal error: 'objc/blocks_runtime.h' file not found # include <objc/blocks_runtime.h> ^~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
1:53 PM
objc/blocks がないと怒られてます 😅
Avatar
Kishikawa Katsumi 8/20/2019 1:54 PM
libDispatchかな
1:56 PM
^ GCDのライブラリ
Avatar
A tiny shell script for installing GNUstep and libobjc2 automatically on Ubuntu 12. I recommend that you download this script to a distinct folder &quot;gnustep-installer&quot;. It will dow...
1:57 PM
とりあえず libdispatch 入れてみます
1:58 PM
ダメでしたw
1:58 PM
上の sh をブチ込んでみます✊
Avatar
omochimetaru 8/20/2019 2:10 PM
そもそも、Linux向けのSwiftはObjective-C対応してないですよ
2:11 PM
Avatar
omochimetaru 8/20/2019 2:11 PM
GNUStepとかでがんばったとしても、
2:11 PM
少なくとも、Swift言語のObjective-C Interopが無いです。
Avatar
ぬぉー
Avatar
omochimetaru 8/20/2019 2:11 PM
そういうことかあ。
Avatar
じゃあ Linux では Swift と C++ バインドできない?
Avatar
omochimetaru 8/20/2019 2:11 PM
C言語使ってバインドするしかないです。
Avatar
😂😂😂
Avatar
Kishikawa Katsumi 8/20/2019 2:13 PM
C++ -> C -> SwiftだからObjCをちょっと書き直せば行けそう。
Avatar
omochimetaru 8/20/2019 2:15 PM
やったことはありますけどまあがんばればいけますね
2:15 PM
メソッド全部C言語の関数でexportし直す必要があるので単純に筋力が必要です
Avatar
.h を C オンリーにすればいいんです?
Avatar
omochimetaru 8/20/2019 2:15 PM
量によってはスクリプトで生成したほうが早い。
2:16 PM
えーっと
2:16 PM
関数とかのシンボルに関しては extern "C" { } で包むのと
2:16 PM
C++のclassやstructは使えないので、前方宣言して名前だけ渡す。
Avatar
ふむふむ
2:17 PM
量はそんなにないです,基本的には Swift との間で C-type の struct に変換して配列ポインタをガーッと渡してるだけなので。
2:18 PM
ちょっと Obj-C 風に書き直したりしてましたが,無駄でしたね😂
Avatar
omochimetaru 8/20/2019 2:18 PM
それなら手書きで必要なものだけブリッジするので行けそうですね
Avatar
よっしゃぁ…💪
Avatar
omochimetaru 8/20/2019 2:18 PM
😅
2:18 PM
なんか仕組みとしては
Avatar
Contribute to taketo1024/ClosedRegion development by creating an account on GitHub.
Contribute to taketo1024/ClosedRegion development by creating an account on GitHub.
Avatar
omochimetaru 8/20/2019 2:19 PM
hファイルっていうのはヘッダーなので、本体となるcファイルかcppファイルにincludeされるわけですけど
2:19 PM
cファイルにincludeされてるときはC言語としてコンパイルされてて
2:19 PM
cppファイルからincludeされてるときはC++言語としてコンパイルされてて
2:20 PM
で、C++だとABIが全部C++仕様になっちゃうんだけど、 C言語と互換性のある状態にするために使うのが extern "C" { } です
2:20 PM
ただそこでややこしいのが、 extern "C" { } は C++の中で使うC言語対応させる文法なので
Avatar
ほほー
Avatar
omochimetaru 8/20/2019 2:21 PM
C言語自体にはextern C という文法が存在しないから、そのヘッダーをCから読めない。
2:21 PM
そこでどうするかっていうと
2:21 PM
C++のときは extern "C" になって、Cのときは無になるマクロを作る、っていうのをみんなやってます。
Avatar
https://stackoverflow.com/a/12994075/1249157 ここに書かれてることですかね
What exactly does putting extern "C" into C++ code do? For example: extern "C" { void foo(); }
Avatar
omochimetaru 8/20/2019 2:23 PM
まさにこれっぽい。
Avatar
おぉ-…
2:23 PM
#ifdef __cplusplus extern "C" { #endif // ここに Swift に expose する struct や関数を書く #ifdef __cplusplus } #endif
2:23 PM
って感じで合ってますかしら?
Avatar
omochimetaru 8/20/2019 2:24 PM
そうですね。
Avatar
ありがとうございます,やってみます!
2:24 PM
こんなの絶対一人じゃわからなかったw
2:27 PM
C++のclassやstructは使えないので、前方宣言して名前だけ渡す。
これが分からなかったのですが,これはどういうときに必要になるものですか?
2:27 PM
前方宣言すれば C++ の class や struct を Swift から使える?
Avatar
omochimetaru 8/20/2019 2:34 PM
名前だけ使えるようになります
2:35 PM
OpaquePointerとかUnsafePointer<Hoge>とか。 (edited)
2:36 PM
あとstructだったらメソッドがなければそのままSwiftから使えますね。
Avatar
名前だけ使えるというのはどういうことです…?
2:38 PM
Hoge は C++ の struct ?
2:40 PM
hoge.h #ifdef __cplusplus extern "C" { #endif void hehe(); #ifdef __cplusplus } #endif hoge.cpp #include "hoge.h" void hehe() { std::cout << "hehe" << std::endl; } これが動いたのであとは頑張れば行けそうです💪 (edited)
Avatar
omochimetaru 8/20/2019 2:40 PM
名前だけってのはポインタとかは使えるけどそれ自体は使えないって事です
2:41 PM
Hogeはcppのクラスか構造体。
Avatar
ふーむ…それができて嬉しいケースってあるんですか?
2:41 PM
Swift が C++ から受け取って,それをまた C++ に渡す場合とか?
Avatar
omochimetaru 8/20/2019 2:42 PM
Hogeのポインタを受け取る関数に対して、 間違ってFugaのポインタを渡すと型チェックでエラー検知できます
Avatar
なるほどっ
2:43 PM
例えば C++ から Swift へ smart pointer を渡すみたいなこともできる…?
2:43 PM
swift では直接それに触れず,また別の関数に回すだけ
Avatar
omochimetaru 8/20/2019 2:44 PM
そうそう、回すだけ。
2:44 PM
でもstd::shared_ptrとかは、それ自体がcppの型だから、swiftから受け渡しできません。
2:45 PM
shared_ptrのポインタ、なら扱えます。ややこしいのでやめた方がいいですが。
Avatar
なるほどw
2:46 PM
とりあえずは生 C 丸出しな感じで,大量の引数つきグローバル関数をたくさん生やそうと思います!
2:47 PM
色々と教えて頂きありがとうございました 🙇
Avatar
omochimetaru 8/20/2019 2:51 PM
🤚
Avatar
bool solve(size_t rows, size_t cols, const LBMatrixComponent *Acomps, size_t Acomps_cnt, const LBMatrixComponent *bcomps, size_t bcomps_cnt, LBMatrixComponent *xcomps, size_t *xcomps_cnt); 生々 C
Avatar
omochimetaru 8/20/2019 3:00 PM
あるある
swift 1
Avatar
Cでも_Nullable, _Nonnullとか使えるので、その辺りをちゃんと使うとSwift側でのポインタの扱いを簡単に出来たりします。
Avatar
まさにそれを今やろうとしてました! const Hoge *const *xcomps が Swift では UnsafePointer<UnsafePointer<Hoge>?>! となるようで、この内側の ? を取りたくて const Hoge *const _Nonnull *xcomps としたら求める形にできたのですが,Pointer is missing a nullability type specifier という警告がたくさん出てしまいました。 NS_ASSUME_NONNULL_BEGIN ... END で囲めば消せるようなのですが、これを使うには Foundation を import する必要があるらしいんですが、それ以外の方法はあるでしょうか?(Linux で動かしたいので Foundation free にしたい)
1:09 AM
#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnullability-completeness" ... #pragma clang diagnostic pop これで行けました👍 (このやり方で大丈夫でしょうか?) (edited)
Avatar
omochimetaru 8/21/2019 1:09 AM
LinuxでもFoundationは使えますよ。
1:11 AM
Nullableは一つつけたら全部つけることを求められる仕様で(君この機能知ってるね?的な)、警告はプラグマで消すのもいいですが、全部つける方が望ましいです
1:12 AM
include先のヘッダーとかにはつけられないですが、 そういうライブラリはcpp側でincludeするようにするとか工夫して、 余計なものを露出しないヘッダーが作れます。
1:13 AM
Linux用のFoundationはObjCを使わずに書かれてるのです。
Avatar
norio_nomura 8/21/2019 1:13 AM
CoreFoundationはこんな感じですね。 #if __has_feature(assume_nonnull) #define CF_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #define CF_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") #else #define CF_ASSUME_NONNULL_BEGIN #define CF_ASSUME_NONNULL_END #endif
Avatar
うーむ,なるほど… この警告のためだけに Foundation を入れなきゃいけないのはちょっと抵抗が…🙄
Avatar
norio_nomura 8/21/2019 1:18 AM
CoreFoundationに倣って、ASSUME_NONNULL_BEGINとかを自前で定義してしまえば良いのでは。 (edited)
Avatar
#ifndef で同じものを定義する感じですかね
Avatar
omochimetaru 8/21/2019 1:32 AM
定義するのは#defineですね。
Avatar
あ、すみません、 #if __has_feature(assume_nonnull) #ifndef NS_ASSUME_NONNULL_BEGIN #define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #endif #endif こういう感じにするのかなと思ってました(将来的に衝突が起きると面倒なので) (edited)
Avatar
omochimetaru 8/21/2019 1:36 AM
ああそういう意味ですか、NS_はFoundation用のprefixなので、NS_をつけないのが望ましいですね。
1:36 AM
代わりにライブラリ固有のprefixをつけるのがベストです。他の関数名とかと同じようにしましょう。
Avatar
あ,なるほど,そういうことか!
1:37 AM
自前で同じ _Pragma を定義すればいいってことですね. (edited)
Avatar
omochimetaru 8/21/2019 1:37 AM
_Pragmaは単に #pragma に展開されるマクロだと思うので、
1:37 AM
_Pragmaを定義する必要は無いですね
Avatar
ありゃw
Avatar
omochimetaru 8/21/2019 1:37 AM
まあ、ClangとGCCの両方に対応したいなら定義しても良いですが。
Avatar
#if __has_feature(assume_nonnull) #define SANO_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #define SANO_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") #endif SANO_ASSUME_NONNULL_BEGIN bool solve(..., const LBMatrixComponent *const _Nonnull *xcomps, ...); SANO_ASSUME_NONNULL_END (edited)
Avatar
omochimetaru 8/21/2019 1:38 AM
個人的にはSwiftから使う時点で __has_feature(assume_nonnull) も絶対YESなのでいらないきがしますが
Avatar
↑ こうであってます?
Avatar
omochimetaru 8/21/2019 1:41 AM
#if __has_feature(assume_nonnull) #define SANO_ASSUME_NONNULL_BEGIN #pragma clang assume_nonnull begin #define SANO_ASSUME_NONNULL_END #pragma clang assume_nonnull end #endif SANO_ASSUME_NONNULL_BEGIN bool solve(..., const LBMatrixComponent *const _Nonnull *xcomps, ...); SANO_ASSUME_NONNULL_END (edited)
1:41 AM
こうだけど
Avatar
ほうほう,なるほど
Avatar
omochimetaru 8/21/2019 1:41 AM
#define SANO_ASSUME_NONNULL_BEGIN #pragma clang assume_nonnull begin #define SANO_ASSUME_NONNULL_END #pragma clang assume_nonnull end SANO_ASSUME_NONNULL_BEGIN bool solve(..., const LBMatrixComponent *const _Nonnull *xcomps, ...); SANO_ASSUME_NONNULL_END これでいいと思います。
Avatar
ふむふむ。
Avatar
omochimetaru 8/21/2019 1:41 AM
ここまでやるとマクロ定義してる意味もよくわからないから#pragma直接書けばいい気もする
Avatar
将来的に Swift と切り離して使う可能性も意識するなら __has_feature もつけといた方がいいって感じですかね。
1:42 AM
理解しました > pragma
Avatar
omochimetaru 8/21/2019 1:43 AM
そうですね。 assume_nonnull機能をもたないコンパイラにも対応したいならhas_featureが必要で
1:43 AM
clangじゃないコンパイラにも対応したいなら _Pragmaが必要ですね
1:43 AM
いずれにしても対応していないコンパイラだったら無にしたいってことです
Avatar
ほほー
Avatar
omochimetaru 8/21/2019 1:43 AM
clangじゃないコンパイラというとgccとかMSVC++とか。
Avatar
_Pragma は他のコンパイラでも定義されてるんですか?
Avatar
omochimetaru 8/21/2019 1:44 AM
ちゃいます
Avatar
それも #ifndef で定義する?
Avatar
omochimetaru 8/21/2019 1:44 AM
#ifdef __CLANG__ #define _Pragma(x) #pragma x #else #define _Pragma(x) #endif
Avatar
はぁはぁ,なるほど。
Avatar
omochimetaru 8/21/2019 1:44 AM
↑こういうイメージです(__CLANG__は今適当に書いた) (edited)
Avatar
理解しました!
Avatar
omochimetaru 8/21/2019 1:46 AM
でもそういえば #pragma onceはgccでもvcでも使えるな。 #pragma clang assume_nonnull beginは使えないと思いますけど(clangって入ってるし・・・)
Avatar
norio_nomura 8/21/2019 1:46 AM
_Pragmaを使わない#defineは利用時にエラーになるよ。 … .h:17:1: error: expected unqualified-id SB_ASSUME_NONNULL_BEGIN ^ … .h:6:33: note: expanded from macro 'SB_ASSUME_NONNULL_BEGIN' #define SB_ASSUME_NONNULL_BEGIN #pragma clang assume_nonnull begin ^ (edited)
Avatar
omochimetaru 8/21/2019 1:46 AM
ほう
1:48 AM
普通のマクロじゃなくて専用の言語機能だったのか・・・
1:48 AM
さっきの説明は間違ってました、すいません。
Avatar
おぉ,ありがとうございます。
1:51 AM
#pragma を #define に入れちゃいけない的な制約があるんです?
Avatar
omochimetaru 8/21/2019 1:52 AM
そうみたいですね。
Avatar
norio_nomura 8/21/2019 1:52 AM
定義だけなら問題なかったです。
1:53 AM
ああ、エラーをちゃんと引用してなかった。 (edited)
Avatar
結局こういう感じになりました: bool solve(..., LBVectorComponent **xcomps, size_t *xcomps_cnt); var xcomps_ptr: UnsafeMutablePointer<LBVectorComponent>? = nil var xcomps_c = 0 if LinBoxWrapper.solve(..., &xcomps_ptr, &xcomps_c) { guard let xcomps_ptr = xcomps_ptr else { fatalError() } let buff = UnsafeBufferPointer(start: xcomps_ptr, count: xcomps_c) defer { xcomps_ptr.deallocate() } return DVector(size: size.cols, components: buff) } else { ... (edited)
2:03 AM
呼び出し側から dealloc を呼ばないといけないので Mutable じゃなきゃいけなくて,はじめに nil を入れた状態で渡したいので _Nonnull にもできなそうでした。
Avatar
omochimetaru 8/21/2019 2:03 AM
xcomps_ptrの型は UnsafeMutablePointer<LBVectorComponent>?にしたほうが良いのでは
Avatar
_Nullable を明示してってことです?
Avatar
omochimetaru 8/21/2019 2:05 AM
むむ、その2つは独立な話ですね
Avatar
あれれ、
Avatar
omochimetaru 8/21/2019 2:05 AM
nullabilityの指定がC側でされていなかったとしても、Swift側は?を使いたい、!型は避けたい。
2:05 AM
それとは別に、C側で _Nullableは明示したい。
Avatar
あ,そっか,Swift 側で ! に暗黙キャストしちゃってたのか.
2:08 AM
Swift の方を直しました!
🙂 1
2:08 AM
少しコツが分かってきました😆
Avatar
C で並列処理をするための OpenMP というライブラリがあるようで、clang でビルドするときは clang -Xpreprocessor -fopenmp -lomp myfile.c という風にオプションをつけるとできるそうなのですが,swift build や Xcode からのビルドでこのオプションを設定するのはどうやったらいいか分かりますか?
Avatar
omochimetaru 8/21/2019 2:31 PM
-lompのところはlibompのリンク指定ですね
Avatar
はい,そちらは library search path への指定で行けました.
Avatar
omochimetaru 8/21/2019 2:32 PM
Xpreprocessorでプリプロセッサにfopenmpを渡してるところは、Xccでいけるかなあ?
2:32 PM
-Xcc -Xpreprocessor -Xcc -fopenmp
Avatar
swift build -Xcc -Xpreprocessor -Xcc -fopenmp これは通ってるっぽいです(°_°)
2:35 PM
swift build で -lomp 指定するのはどうしたらいいんでしょう?
Avatar
omochimetaru 8/21/2019 2:35 PM
-Xlinker -lomp
Avatar
おぉ
2:38 PM
ld: library not found for -lomp って言われてしまいます… export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/usr/local/lib してみたんですがダメでした。 (edited)
2:41 PM
swift run -Xcc -Xpreprocessor -Xcc -fopenmp -Xlinker -L/usr/local/lib -Xlinker -lomp これで実行はできました!…が並列処理は効いてなさそう🤔
Avatar
omochimetaru 8/21/2019 2:42 PM
-dか-vかなんかをつけるとswiftpmの内部のビルドコマンドが表示されるので
2:42 PM
それでC言語のコンパイルのところが望んだコマンドになっているかを確認する
2:43 PM
のが次のステップですかね、、
Avatar
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -fobjc-arc -target x86_64-apple-macosx10.10 -isysroot /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -F /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -g -O0 -DSWIFT_PACKAGE=1 -DDEBUG=1 -fblocks -index-store-path /Users/taketo/Projects/spasm/.build/x86_64-apple-macosx/debug/index/store -fmodules -fmodule-name=spasm -I /Users/taketo/Projects/spasm/src/include -fmodules-cache-path=/Users/taketo/Projects/spasm/.build/x86_64-apple-macosx/debug/ModuleCache -Xpreprocessor -fopenmp -MD -MT dependencies -MF /Users/taketo/Projects/spasm/.build/x86_64-apple-macosx/debug/spasm.build/spasm_util.c.d -c /Users/taketo/Projects/spasm/src/spasm_util.c -o /Users/taketo/Projects/spasm/.build/x86_64-apple-macosx/debug/spasm.build/spasm_util.c.o ちゃんと -Xpreprocessor -fopenmp は入ってそう (edited)
Avatar
omochimetaru 8/21/2019 2:47 PM
中身はopenmpを使ってかいてるんですか-
2:47 PM
Avatar
はい
2:47 PM
試しに無理やり入れてみました.
2:47 PM
#pragma omp for for(int n=0; n<1000; ++n) { printf(" %d", n); } printf(".\n"); ↑ この謎の pragma を入れるだけで並列処理になるというw
2:48 PM
実行結果がバラバラなら効いてるはずなんですが,綺麗に 0 から順番に出てしまうんですよね.
Avatar
omochimetaru 8/21/2019 2:49 PM
なるほど。そのコードは-fopenmpを渡さない場合は正しくコンパイルエラーになるんですか? (edited)
Avatar
渡さないと直列になるんだと思います。
Avatar
omochimetaru 8/21/2019 2:51 PM
それだと
2:51 PM
コンパイラがそのオプションに反応したのかどうかすら
2:51 PM
コンパイル時に確認できないので厄介ですね
Avatar
そうなんですよねw
Avatar
omochimetaru 8/21/2019 2:51 PM
うーむ。
Avatar
あっ,できてるっぽいです
Avatar
omochimetaru 8/21/2019 2:58 PM
並列な結果が出ました?
Avatar
export OMP_NUM_THREADS=100 これを叩いてから実行したら, 1 65 49 33 13 4 17 77 97 3 9 81 5 73 68 2 69 67 66 45 61 57 41 53 52 37 51 29 36 50 35 21 25 19 20 18 34 6 16 84 46 48 63 59 60 58 56 55 44 54 43 42 40 39 32 38 31 30 28 27 26 24 23 22 15 14 98 99 11 12 8 93 89 10 7 85 80 82 83 76 78 79 75 74 71 72 70 62 64 47 96 95 94 92 90 88 91 87 86 と出ました😂
Avatar
omochimetaru 8/21/2019 2:59 PM
おお。
Avatar
めちゃめちゃデバッグしづらそうw
Avatar
omochimetaru 8/21/2019 2:59 PM
外から与えるのか。
2:59 PM
並列数。
Avatar
ウケますね
Avatar
omochimetaru 8/21/2019 3:00 PM
完全に元のforループとは異なる何かになっててウケる
😂 1
Avatar
というかもはや Swift の話じゃないですね,すみません 🙇
Avatar
omochimetaru 8/21/2019 3:00 PM
other-langチャンネルもありますよ
👌 1
Avatar
Xcode の方は Other C Flags で -Xpreprocessor -fopenmp と指定すればいけました👍
Avatar
上の話ですが、Swift PM にこう指定するだけで行けました(もうこの話は終わりにします) .target( name: "...", cSettings: [ .unsafeFlags(["-Xpreprocessor", "-fopenmp"]) ], linkerSettings: [ .unsafeFlags(["-L/usr/local/lib"]), .linkedLibrary("omp") ] ), (edited)
Avatar
あー、そっか、その方が便利ですね
Avatar
自作の command line ツールを走らせていて realloc failed: Cannot allocate memory と最後の言葉を残して終了したのですが、こういうメモリエラーをキャッチする方法ってあるんでしょうか? (アプリなら didReceiveMemoryWarning 系のものがあるけど)そもそも RuntimeException 的な仕組みがないのでどう対処したものかと🙄
Avatar
Kishikawa Katsumi 8/29/2019 6:52 AM
reallocが死ぬのは起こってしまったら基本的にどうしようもないですね。起こらないようにするというのが対策ですけど、実際めっちゃメモリを必要とする感じですか?それともリークとかがありそうですか?
Avatar
めっちゃ必要な感じです、対策の余地はまだまだあると思いますが。 Leak は instrument で調べてみましたが起きてなさそうです。
6:53 AM
memory 7GB の VM で走らせてるので、まずこれを増やそうとは思います。
6:54 AM
どこで死んだかだけでも知れたらいいなと思ったんですが,キャッチはできないんですかね。
Avatar
Kishikawa Katsumi 8/29/2019 7:26 AM
bad_allocとかが飛んでたら catch (...) { <= この ... は文字どおり ... です、とかで捕まえられるかも。 それかreallocを入れ替えるとか。
Avatar
realloc 入れ替えるのはビビりますw 了解です,ありがとうございます🙏
7:45 AM
Xcode の allocations って具体的にどの class / struct が容量を消費してるかまでは可視化できないですよね。
Avatar
Kishikawa Katsumi 8/29/2019 7:52 AM
C++に使ったことないですけどわかるんじゃないですかね。。。?
Avatar
omochimetaru 8/29/2019 8:03 AM
具体的にどの class / struct が容量を消費してるか
出ますよ
Avatar
ありゃっ?
Avatar
omochimetaru 8/29/2019 9:27 AM
インスタンスの数とかも出るので
9:28 AM
それで絞り込んだりをよくします
9:28 AM
どこで死んだか
9:29 AM
メモリ確保失敗したときはシグナルが飛んでるのでスタックトレースが得られてるはずです
9:29 AM
普通にやるとstderrに出てるんじゃないか・・・?
9:29 AM
Linuxだとシンボル名が出なくて関数アドレスが16進数で出るだけだったりしますが、
9:30 AM
そういうときは野村さんのライブラリで表示できたりするかも。DiscordのSwift botがまさにそれをやっている
Avatar
norio_nomura 8/29/2019 9:47 AM
DiscordのSwift botがまさにそれをやっている
あ、ボットには自動でSwiftBacktraceを有効にする仕組みは入れていません。ボットのスタックとレースは/usr/bin/swiftが請け負ってくれているので。
(edited)
9:49 AM
import SwiftBacktraceを出来るようにはしてありますが。 (edited)
Avatar
omochimetaru 8/29/2019 9:50 AM
ありゃ
9:51 AM
あ、C関数の中のクラッシュだとswift runtimeじゃないから出ないのかな・・・?
9:51 AM
コアダンプをどうこうするやつか
Avatar
norio_nomura 8/29/2019 9:55 AM
Linuxの場合は、実行ファイルが自前でスタックトレースを出力、プロセスが死んでからcoreを使ってスタックトレースを出力、lldb下で実行して出力、が取れる選択肢かな。
9:59 AM
dockerとかでcore出力を制限されていたりlldbを使えなかったりする場合は実行ファイルが自前で出力するしかないので、SwiftBacktraceを作りました。
Avatar
omochimetaru 8/29/2019 9:59 AM
あーなるほど、コアが出せない状況というのがあるんですね
Avatar
そう、ボットはHerokuで動いていますがcore出力もlldbも使えません。そのため、ボットが受け取ったコードの実行には使っていませんが、ボット自身のクラッシュを解析する用途としてはSwiftBacktraceを使っています。
10:13 AM
SSWGでも話題になったから、もう少し選択肢は増えてたはず。 https://forums.swift.org/t/crash-backtraces/25021
When we were discussing the Charter of the SSWG last year, one area several people mentioned they were interested in collaborating on is improving the experience of deploying Swift applications and managing them at scale. A critical part of that is ensuring that Swift has a ...
10:15 AM
僕のも含めいくつかのスタックトレース用ライブラリを評価した上で、IanPartridgeさんが新しいのを作ってたと記憶。
Avatar
おお
Avatar
いつもすみません。picker がXR以外、画面サイズに合うように表示されず原因もわからないのでどなたかご教示いただけないでしょうか?💦
10:35 AM
見辛いかもしれませんが、詳細は以下のリンクにあります🙏
10:35 AM
やりたいことiOS XR 以外の機種でも、pickerが画面に収まるように表示させたい。 現状RxSwift で書いており、基本的に storyboard を使用しています。picker は呼び出されてはいるのですが、XR以外の機種だと画
Avatar
pickerの横幅の制約が正しくない気がします。 このpickerはStoryboard上で実装していますか?codeで実装していますか? pickerにつけている制約はどういったものになっていますか? (edited)
11:13 AM
あぁ…これが原因な気が…widthの制約がついていないので、Storyboardで表示されている仮想端末が基準のサイズで初期化されるため、iPhone XRの横幅でpickerが作られて見切れているかと
autolayout での制約は、上下左右につけています。heightの制約はつけていますがwidthの制約はつけていません。
Avatar
ありぜさん、ありがとうございます!widthの制約をつけてしまうと、多画面での対応ができないのかな、と思ってつけなかったのですがいじってみます!!🙏
👍 1
Avatar
width弄ってみましたが、なりませんでした。
🙇 1
11:33 AM
左右を"="ではなく”不等号”にもしてみましたが、変化なしです...😢
Avatar
あっ画像見るとpickerの問題じゃなく、その下のUIView側の制約の問題でした…(doneボタンとかツールバーもはみ出してるの見落としてました) pickerの乗っているxibは、どうやって読みだしていますか? Storyboardの上にUIViewを配置してCustom Viewとしてですか? それともコードでxibをUIViewとして読み出し、addSubViewしている感じですか? (edited)
11:37 AM
<呼び出しているuiviewについて> autolayoutでの制約は、下・左右とheightにつけています。
これが機能していれば正しく表示されそうなんですが…制約が衝突して正しくない状態になっている??
Avatar
pickerの乗っているxibは、どうやって読みだしていますか? コードでxibをUIViewとして読み出し、addSubViewしている感じ
です!
11:40 AM
制約が衝突して正しくない状態になっている??
その可能性はあるかもしれません。 呼び出し先のUIView自体の制約の衝突はなさそうなのですが、ほかのものと衝突しているかもです!もう一度みてみます!ありがとうございます!!
Avatar
現時点で考えられる原因は…以下あたりかと 1. pickerの乗っているUIViewに対して制約のコードを記述し忘れている 2. pickerの乗っているUIViewに対して制約コードを記述している位置が悪く実行されるタイミングに問題がある 3. 前述した制約の衝突 (edited)
Avatar
xibのpickerの制約と呼び出し先のuiviewの制約が衝突しているのでしょうか? 呼び出し先の画面の制約はみた感じ衝突してないかなと思ったのですが... こちら、呼び出し先の制約です
11:44 AM
現時点で考えられる原因は…以下あたりかと
1. pickerの乗っているUIViewに対して制約のコードを記述し忘れている 2. pickerの乗っているUIViewに対して制約コードを記述している位置が悪く実行されるタイミングに問題がある 3. 前述した制約の衝突 なるほど...
11:45 AM
みてみます😭 ありがとうございます!!!
Avatar
やっと解決いたしました_:(´ཀ`」 ∠): autoresizing の制約の付け忘れでした。 お手数おかけいたしました🙇‍♂️
Avatar
コンパイル時に特定のファイルだけ optimazation を無効にすることってできるんでしょうか?
Avatar
Kishikawa Katsumi 9/10/2019 11:26 PM
Swiftはたぶん無理ですね。ファイルごとのCompiler Flagsをセットしても無視されてしまうし。。。
11:26 PM
Xcodeで、ってことですよね?他の方法もありですか?
Avatar
Swift PM を使ったビルドならアリです.
6:59 AM
あるいは特定の target 下だけ optimization を無効にする,でもいいです.
Avatar
Kishikawa Katsumi 9/11/2019 7:00 AM
ターゲットを分けられるならターゲットを分けるのがわかりやすいですね。
7:01 AM
Xcodeプロジェクトならビルド設定でコントロール可能、SPMは調べないとわからないですね。
Avatar
ふむふむ
7:14 AM
#other-lang に書いた C ライブラリとの連携で,別ターゲットとして埋め込んで使っているので,その部分だけ最適化をオフにすると正常に動作するようになるかなと思いまして🙄
7:19 AM
また別の質問なんですが,DispatchWorkItem って cancel 呼んでも止められる訳ではないんですね.「一つの処理に時間がかかりすぎてる場合に停止する(メモリとかも解放する)」って,プロセスそのものを分けないと無理なんでしょうか? let semaphore = DispatchSemaphore(value: 0) let mainTask = DispatchWorkItem { while true { print("working...") sleep(1) } } let bgTask = DispatchWorkItem { for i in 0 ..< 3 { print(i) sleep(1) } semaphore.signal() } DispatchQueue.global(qos: .userInitiated).async(execute: mainTask) DispatchQueue.global(qos: .background).async(execute: bgTask) semaphore.wait() mainTask.cancel() bgTask.cancel() print("canceled") sleep(10) // まだ working... が出続ける
7:21 AM
上の例なら mainTask の while 時に !isCancelled としたりできますが,僕が扱いたいのはここがループではなくてとても重くなる可能性のある長い処理です.
Avatar
Kishikawa Katsumi 9/11/2019 7:21 AM
すでに実行されてしまったのはそうですね。 isCancelled みたいなプロパティがあるのでそれを見て自分でキャンセルします。
Avatar
うーむ,なるほど.
Avatar
Kishikawa Katsumi 9/11/2019 7:23 AM
長い処理の間を適当に分けて、 if isCanceled { // cleanup etc. return } // 処理A if isCanceled { // cleanup etc. return } // 処理B ...
7:23 AM
^ のような感じですね。
7:24 AM
考え方でいうと。
Avatar
了解です!
7:25 AM
mainTask の中身は切り出しやすいものなので,上のようにしたければ subprocess として立ち上げる感じがよさそうですね.
Avatar
Kishikawa Katsumi 9/11/2019 7:27 AM
プロセスまで作るのはやりすぎかもしれないので、取りあえず関数やらオブジェクトくらいに分けて、前のタスクが正常に終わっていたら次、みたいなのでいいんじゃないですかね。
Avatar
ライブラリで走ってる異常にデカイ行列の処理を途中で止めるようなことをしたいので,サブプロセスを切ってしまった方が楽そうですw
7:30 AM
計算対象がたくさんあってそれらを順番に計算していきながら,時間がかかりすぎていたりメモリを食い過ぎていたりしたら中断する,というようなことをやろうとしています.
Avatar
CLI ツールが out of memory で勝手に落ちてしまうのが困るので(ログを残して正常に終了したい),iOS の memory warning のような仕組みを作りたいと思っています.メモリ情報を監視するスレッドを立てて,↓ の方法でメモリ情報を 1 秒おきとかで取得し続けるのがいいかなと思っているのですが,もっといい方法はあるでしょうか?(あと mach は linux では動かないですよね?) https://stackoverflow.com/a/30435804
I need to get Memory usage information like(available RAM, available internal storage).
Avatar
This article provides cross-platform functions to get the peak (maximum) and current resident set size of a process, and explains what works on what OS.
Avatar
上のライブラリを使って,こういう感じに実装することにしました: let semaphore = DispatchSemaphore(value: 0) var exceedMemory = false DispatchQueue.global(qos: .userInitiated).async { main() semaphore.signal() } DispatchQueue.global(qos: .background).async { while true { let mem = getCurrentRSS() if mem > self.config.maxMemory { exceedMemory = true semaphore.signal() } sleep(10) } } if semaphore.wait(timeout: .now() + timeout) == .timedOut { throw AppError.timeout(sec: config.timeout) } if exceedMemory { throw AppError.exceedMemory(limit: config.maxMemoryGB) }
Avatar
色々な型を Global に ExpressibleByIntegerLiteral 適合させると予期できない暗黙キャストが起きてカオスになるので、特定の型を fileprivate に ExpressibleByIntegerLiteral に適合できたらいいと思ったのですが、 conditional conformance があると fileprivate extension できないんですね… これは何故なのでしょう🙄 特に ExpressibleByIntegerLiteral な型を wrap する型を再び ExpressibleByIntegerLiteral にして、init では内部の型に丸投げする多くて,↓ こういう protocol を作って必要に応じて適合させられたらいいと思ったのですが…🙄 public protocol InheritingIntegerLiteralExpression: ExpressibleByIntegerLiteral where IntegerLiteralType == Inheritee.IntegerLiteralType { associatedtype Inheritee: ExpressibleByIntegerLiteral init(_ inheritee: Inheritee) } extension InheritingIntegerLiteralExpression { public init(integerLiteral value: IntegerLiteralType) { self.init(Inheritee(integerLiteral: value)) } } (edited)
1:45 PM
使うときは fileprivate extension Polynomial: ExpressibleByIntegerLiteral, InheritingIntegerLiteralExpression where BaseRing: ExpressibleByIntegerLiteral { typealias Inheritee = BaseRing } とするイメージ. (edited)
1:48 PM
conditional conformance つきだと extension にアクセス修飾子がつけられないのは前向きな理由があるんでしょうか? (edited)
Avatar
(Inherit というより Delegate の方が適切な気がしてきました)
Avatar
昔できたらいいのにな~と議論した記憶があるのですが、確か可能だと破綻するよね、という話題になった記憶があります。
2:15 PM
// ファイル A public func something<T: SomeProtocol>(_ value: T) { ... } // ファイルB private extension Foo: SomeProtocol { ... } something(Foo()) 最も単純な例はこれですかね、somethingの実装側からはFooのSomeProtocolに対する実装は見えていないはずなので、実行できなくなりそうです。(できると可視性がおかしなことになってくる)
Avatar
はー,なるほど.よくわかりました 🙇
Avatar
Xcode11のSwiftPMについて質問なのですが、SwiftPMでSwiftLintを導入して、Build Phaseでlintを実行するのは可能でしょうか? 現状は下記のような感じでCocoaPodsを使ってSwiftlintを入れているのですが、このためだけにCPを使うのがいやだなーと思って、SwiftPMを使いたいと思っています。 "${PODS_ROOT}/SwiftLint/swiftlint"
Avatar
Kishikawa Katsumi 10/2/2019 10:14 AM
Xcode 11のSwiftPMだと無理だと思います。CocoaPodsを使いたくないならHomebrewかMintを使っていれる、じゃないでしょうか。
Avatar
なるほど、そうなんですね。とはいえ、チームで共有したかったので、今の所はCPを使うのが一番目的には合ってそうです。 ありがとうございます!
Avatar
Thread safe な dictionary を作ろうとしているのですが,dead lock になってしまうようです.何がまずいかわかりますか? public class SynchronizedDictionary<Key: Hashable, Value> { private var dictionary: [Key: Value] = [:] private let queue = DispatchQueue(label: "hoge", qos: .default, attributes: .concurrent) public subscript(_ key: Key) -> Value? { get { queue.sync { dictionary[key] } } set { queue.async(flags: .barrier) { self.dictionary[key] = newValue } } } } var a = SynchronizedDictionary<Int, Int>() let n = 100000 DispatchQueue.concurrentPerform(iterations: n) { i in a[i] = i } print(a[n-1]) write のところは sync ではなく async(flags: .barrier) とした方が良いという記事をいくつか見てそうしてます.
Avatar
Kishikawa Katsumi 10/7/2019 2:08 PM
キューを concurrent にしたらダメじゃないですか?
Avatar
https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2 concurrent にした上で write を async(flags: .barrier) にすると write で sync を待たなくて済むのでより良い,というようなことが書かれてたもので🙄 正しく理解できてないのかもです.
Learn all about multithreading, dispatch queues, and concurrency in the first part of this Swift 4 tutorial on Grand Central Dispatch.
2:11 PM

経緯

普段使っているのに全体像があまり見えていないものとして Grand Central Dispatch (GCD)とOperationQueueが 自分の中にあり色々と調べてみました。 調べていけばいくほど新しいことがど...
Avatar
Kishikawa Katsumi 10/7/2019 2:12 PM
write/write が待つのはしょうがないけどread/writeとかread/readは待ちたくないと、そういう要件なんですね。
Avatar
write 処理は同期されるけど,write 呼び出しはすぐ抜けられる,という感じなのかと理解してます.
2:13 PM
deadlock なんじゃなくて単純に処理にめっちゃ時間かかってるのかも…🙄
2:15 PM
しばらく待ったら出力されました.そして両方 sync するように書き直したら一瞬で終わりましたw public class SynchronizedDictionary<Key: Hashable, Value> { private var dictionary: [Key: Value] = [:] private let queue = DispatchQueue(label: "shit", qos: .default) public subscript(_ key: Key) -> Value? { get { queue.sync { dictionary[key] } } set { queue.sync { self.dictionary[key] = newValue } } } } var a = SynchronizedDictionary<Int, Int>() let n = 100000 DispatchQueue.concurrentPerform(iterations: n) { i in a[i] = i } (edited)
2:16 PM
書き込みにそれなりに時間かかるようなケースじゃないとむしろオーバーヘッドになるってことなのかな…🙄 (edited)
Avatar
Kishikawa Katsumi 10/7/2019 2:18 PM
動かしてみました。これはデッドロックですね。
Avatar
うーむ…なんでデッドロックしちゃうんでしょう?
2:22 PM
ここにもほぼ同様のコードがあります: https://medium.com/@oyalhi/dispatch-barriers-in-swift-3-6c4a295215d6
Dispatch barriers can be used to speed serial queues for read write operations.
Avatar
Kishikawa Katsumi 10/7/2019 2:29 PM
.async(flags: .barrier) が良くわかってないんですよね。。。
2:30 PM
最初のコードでも a[i] = i print(a[i]) のようにgetが呼ばれるコードを後に足すと終了すると思います。
Avatar
そうなんですよね.print によるラグでうまいことデッドロックをすり抜けてるのかなと思いましたw
Avatar
並列処理の達人の方がいたら是非教えてください🙏
Avatar
omochimetaru 10/8/2019 2:08 AM
1つ目のコードについては
2:09 AM
concurrentキューなので
2:09 AM
投入されるタスク同士は並行に動いちゃいます
2:10 AM
Dictionaryに対する並行アクセスが、readだけでも並行アクセスしても大丈夫なのかがそもそもわからないので、get側のsyncだけでも怪しい気はしますが、それは別にしても
2:10 AM
set側のasync(barrier)は、バリアされたタスク同士の同時実行を防ぐものなので https://developer.apple.com/documentation/dispatch/dispatchworkitemflags/1780674-barrier
2:11 AM
書き込み操作同士は直列化されますが (edited)
2:11 AM
読み込み操作とは(多分)排他されないので (edited)
2:11 AM
Dictionaryに対して書き込みと読み込みを同時に行う可能性のあるコードになってます (edited)
2:12 AM
これは明確にDictionaryに対する違反なので暴走して未定義状態になってると思います。 (edited)
2:12 AM
2つ目のコードについては、デッドロックしてないと思います。
2:12 AM
nを10000x1から10000x10まで順番に増加させていくと (edited)
2:13 AM
だんだん処理時間が増加していって、6,7,8ぐらいで急激に増加してました (edited)
2:13 AM
なので、x10のときも時間がかかってるだけに思います。 (edited)
2:14 AM
急激に増加するのはおそらくDictionaryのrehashが発生するからだと思います。 (edited)
2:14 AM
ちなみに1つ目のコードに関しても、 個人的には書き込みをasyncで後回しにするのはあまりやらないほうが良いと思っていて
2:15 AM
その理由は、後回しにする事自体がDispatchQueue側のリソースを食うからです。
2:15 AM
めちゃくちゃたくさん使われるプリミティブなところでそういう処理を書くと、ちょっとしたスケジューリングのブレとかで、
2:15 AM
一瞬で10000タスクがDispatchQueueに乗って待機しちゃうことがありえます
2:16 AM
そうすると普通にそれだけの要素数の配列を読み書きするコストがDispatchQueue内部でかかるし、メモリも食うので、
Avatar
ふむふむ
Avatar
omochimetaru 10/8/2019 2:16 AM
爆弾を抱えてるようなロジックというか・・・
2:17 AM
普通にその場でsyncで書き込んでおくほうが、余計な予測不能要素が増えなくてよいかと。
Avatar
急激に増加するのはおそらくDictionaryのrehashが発生するからだと思います
set の async を sync にすると一瞬で終わるようになるんですが,rehash が原因だとしたら sync でも同様に遅くなりそう…?
Avatar
omochimetaru 10/8/2019 2:18 AM
一瞬で終わるようになる
こっちだと10000x7で20秒ぐらいかかりますね デバッグビルドですか?
Avatar
はい,そのはずです.もう一度やってみます.
Avatar
omochimetaru 10/8/2019 2:19 AM
あ、barrierの仕様読み間違えたかな、
2:19 AM
Work items submitted prior to the barrier execute to completion, at which point the barrier work item executes. Once the barrier work item finishes, the queue returns to scheduling work items that were submitted after the barrier.
2:19 AM
バリア中は他のタスクは走ってないからread/writeの同時実行は生じていないのか。
2:20 AM
concurrent queueをbarrierで同期するコストのほうが、serial queueより重いというのがあるかもしれません。
2:20 AM
内部的にserial queueがsyncされるとき、実際にスレッドリソースとかは使っていなくて
2:21 AM
キューの投入エントリが0個/1個だけのときは、mutexでロックするだけになるんですよね。
Avatar
sync にしたものを Debug build / n = 100_000 で 600 msec で終わりました.
Avatar
omochimetaru 10/8/2019 2:23 AM
なので2つめのコードはロックだけで動いていて、1つめのコードは、たとえreadが生じていなかったとしても、barrierのための同期のオーバーヘッドが高いとか・・・?
2:23 AM
start end: 0.481503963470459 Program ended with exit code: 0
Avatar
ふーむ,書き込みが一気に 100_000 個ブチ込まれるようなケースでは async barrier の方が高コストって感じなんですかね.
Avatar
omochimetaru 10/8/2019 2:23 AM
ああ、ぼくもそのくらいでした、いじってるうちにsetがasyncになってた。
Avatar
はい,print(a[n-1]) のところを消しても同じぐらいかかりますね.
2:25 AM
挙動が予期できないのは気持ち悪いし,僕のケースではこの方法は使わない方がよさそうですね.
Avatar
omochimetaru 10/8/2019 2:25 AM
あ、ひとつ発見しました
2:26 AM
concurrent queue + async(barrier)だと、
2:26 AM
async(barrier)の中身のタスクを実行するスレッドは、asyncを呼び出して投入したスレッドとは別になってますね
2:26 AM
つまり、asyncを呼び出した側はスレッドセーフな内部データ構造にタスクを登録してすぐに抜けていて
2:27 AM
asyncを処理する側は内部のスケジュールの後で同期を取ってほかを排他してから実行する、って挙動を必ず取るっぽい。
2:27 AM
syncの場合はsyncを呼び出したスレッドでそのままロックして待って、スレッドは切り替わらないので、
2:28 AM
やっぱり仕組み上のオーバーヘッドの差がかなりありそうです。
2:29 AM
concurrent+barrierでmulti-read/single-writeな構造を作るのが良いのはアプリとかで負荷のオーダーの見積もりが立つ場合だけじゃないすかねえ
Avatar
僕の理解では, public class SynchronizedDictionary<Key: Hashable, Value> { private var dictionary: [Key: Value] = [:] private let queue = DispatchQueue(label: "shit", qos: .default, attributes: .concurrent) public subscript(_ key: Key) -> Value? { get { queue.sync { dictionary[key] } } set { queue.async(flags: .barrier) { [weak self] in self?.dictionary[key] = newValue } } } } var a = SynchronizedDictionary<Int, Int>() let n = 100000 DispatchQueue.concurrentPerform(iterations: n) { i in a[i] = i } print("HELLO?") print(a[n-1]) 上のコードは HELLO? はすぐ出力されて,次の a[n - 1] の読み取りで待たされるはずだと思ったんですが,HELLO? も待たされるんですよね. (edited)
Avatar
omochimetaru 10/8/2019 2:29 AM
サーバーとかで使ったら、高負荷状況でDispatchQueue内部でのリソース枯渇とかが予測不能・デバッグ不能で詰みそう。
2:29 AM
それは普通に理解が違いますね
Avatar
おぉ
Avatar
omochimetaru 10/8/2019 2:30 AM
concurrentPerformというAPIは、全部終わるのを待ちます。仕様として。
2:30 AM
ああ、書き込みがasyncなのに、ってことか。
Avatar
はい.(コード全部入れ直しました) (edited)
Avatar
omochimetaru 10/8/2019 2:31 AM
単純にタスクの登録作業自体が終わってないんじゃないすかねえ。 (edited)
Avatar
ってことはやっぱ登録に時間がかかってるってことなんでしょうね.
2:32 AM
駆け込み乗車状態🚃 (edited)
Avatar
omochimetaru 10/8/2019 2:32 AM
キューの配列のexpandとかも生じちゃってそう
2:33 AM
配列がでかくなりすぎて。
Avatar
あー,なるほど.
Avatar
omochimetaru 10/8/2019 2:33 AM
試しにsetのasyncの内部でsleepをいれても
2:33 AM
n=10とかならすぐぬけてくる。
Avatar
なるほどなるほど.
2:33 AM
queue を作るとこは sync なはずですもんね.
2:33 AM
納得できました!
2:35 AM
確かに,n = 10 とかにして sleep(3) とかを入れると,HELLO? はすぐに出てそのあとの read で 3×10 秒 書き込み終了を待つ様子が観察できますね! (edited)
Avatar
omochimetaru 10/8/2019 2:36 AM
仕様理解はあってそうですね、n=10000とかになってくるといろんな見えなかったオーバーヘッドが育ってくるということで良さそう (edited)
2:37 AM
DispatchQueueのasyncで非同期処理で繋がったサービスメッシュみたいなことをうかつにやると
2:37 AM
fast-producer/slow-consumerのときにasyncで積んだタスクがどんどん積み上がっていってよくわからん負荷が増えていくみたいな沼が。 (edited)
Avatar
行列の要素セットにこれを使おうか検討してたんですが,やめた方が良さそうですね😂(特に行列のサイズが数十万とかの場合)
Avatar
omochimetaru 10/8/2019 2:40 AM
そうですね
Avatar
norio_nomura 10/8/2019 2:41 AM
syncの場合はsyncを呼び出したスレッドでそのままロックして待って、スレッドは切り替わらない…
以前調べた時は、syncが呼び出しスレッドで実行されるのはqueueに実行待ちのアイテムが無い時で、asyncでアイテムが登録されてるとasyncで登録されたアイテムが実行されるスレッドで実行されるのをsyncが待つ様な実装になってたと記憶。
(edited)
Avatar
omochimetaru 10/8/2019 2:43 AM
asyncの実行を全部待ち終えた後で、syncを呼び出したスレッドでsyncの処理をする?
Avatar
norio_nomura 10/8/2019 2:47 AM
あ、.concurrentだと違うのかな? (edited)
2:48 AM
プライオリティが変わらなければ、queueから取り出される順番は変わらないよね。
Avatar
omochimetaru 10/8/2019 2:49 AM
concurrentですか?そう書いてあるのを見た記憶あります。
2:50 AM
でも、取り出される順番が保証されてても、
2:50 AM
個別のアイテムのスケジューリングが並行なので
2:50 AM
その保証になんか意味あるのかは疑問です
2:50 AM
後から取り出されたほうが先に実行される可能性がありますよね。
Avatar
norio_nomura 10/8/2019 2:55 AM
asyncの実行を全部待ち終えた後で、syncを呼び出したスレッドでsyncの処理をする?
詳細な条件は覚えていませんが、呼び出したスレッドで実行する場合と、async用のスレッドで実行する場合があったかと。
Avatar
omochimetaru 10/8/2019 2:55 AM
なるほど。
2:56 AM
まあいずれにせよスレッド仕様の保証は無いと思って書かないといけないですね。
2:56 AM
思って、と言うか、無いので。
Avatar
素人質問で恐縮なんですが、Swift PM から GPL ライセンスの外部ライブラリに依存させる場合、こちらのライブラリも GPL にしないといけないんですよね?(バイナリだけでなく) (edited)
Avatar
GPLはそうだったと思います
6:39 AM
LGPLだと動的リンクならアプリ側は別ライセンスで良いこちらのライブラリはしなくても良いとも言える、みたいな感じだったかと。 (edited)
6:39 AM
あいや、明確にそうか。曖昧になるのはJava言語での解釈の話だ。
Avatar
ですよね、ありがとうございます🙇‍♂️
Avatar
UIScrollViewの上にtableViewをのせて一定のスクロール値超えたらスクロールする対象をscrollViewからtableVIewに切り替えたいのですが、切り替える時につっかかってしまいます。scrollViewの慣性をtableViewに伝えつつ切り替える方法はないでしょうか? override func viewDidLoad() { super.viewDidLoad() self.tableView.isScrollEnabled = false } ​ func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { ​ if scrollView == self.scrollView { tableView.isScrollEnabled = (self.scrollView.contentOffset.y >= 200) } ​ if scrollView == self.tableView { self.tableView.isScrollEnabled = (tableView.contentOffset.y > 0) } }
Avatar
@mtoyooka table viewの一つ目のsectionにscroll viewに入れたかった内容を入れて、二つ目のsection以降で元々table viewに入れたかった内容を表示するのはいかがでしょうか?
2:11 PM
僕はUIKitのエキスパートではないのでもっと良い方法があるかもしれませんが。
Avatar
@koher 回答ありがとうございます。 説明不足で申し訳ないです。最終的にはXLPagerTabStripを使って動画のようにしたいです。
Avatar
同じようなことを自社アプリでやっています。 私達の場合は、scrollViewの慣性をtableViewに伝えるのではなく、 tableViewのスクロール量をscrollViewに伝えています。 一定量までスクロールしたらscrollViewのスクロールを止め、tableViewだけスクロールするようなイメージです。 そうすることで、XLPagerTabStripのタブの部分を画面に残しつつ、タブの下部だけスクロールさせることが可能になります
1:37 AM
👍 2
Avatar
アル入れていじってみました TableViewの一番上に、辻褄を合わせるための固定幅のセルがあるんですか?
🙏 1
Avatar
contentInsetでもいけそう
3:05 AM
or header
Avatar
スクロールバーが一番上の領域の下側?に入り込んでいくように見えるので。
3:07 AM
それにレイヤーを重ねる形でScrollViewがあって、 そのまま重ねるか、タブだけ上に残る位置になるかを、ScrollViewのスクロール量で制御
Avatar
因みにScrollViewの中にTableViewを入れて、AutolayoutをTableViewとScrollViewのframeで合わせると、スクロールバーが減り込まなくなります
😀 1
Avatar
frameで合わせる
どういう制約?
Avatar
contentじゃなくて外側に制約を合わせると、スクロールしなくなります
3:32 AM
contentSizeにも影響を出さなくなる
Avatar
しばらく考えたけどどういう構成なのか全然わからない・・・
Avatar
アル入れていただいてありがとうございます。 まさに tableview contentInset でつじつまを合わせていました。 そのため、スクロールバーが少し妙な動きをしています😅
4:18 AM
そのまま重ねるか、タブだけ上に残る位置になるかを、ScrollViewのスクロール量で制御
これもおっしゃるとおりですね
Avatar
ああこれセルがあるんじゃなくてcontentInsetなんですね。
Avatar
そうなんです。上のプロフィール領域分、予め contentInset で確保しています
Avatar
なるほどなるほど。とても参考になります。
👍 1
4:21 AM
スクロールバーのところって、
4:21 AM
scrollBarInset?みたいなやつscrollIndicatorInset設定したら、滑り込まなくできませんか? (edited)
4:21 AM
それはそれで変なふうになるんかな
Avatar
あぁ、たしかにそんなプロパティがありましたね
Avatar
スクロールバーが自然な感じになりました 🎉
👏 3
4:31 AM
scrollIndicatorInsets をセットした↑
Avatar
おお
Avatar
これは思いつきませんでした。ありがとうございます 😃
✌ 1
Avatar
@koogawa 一定量スクロールする前はtableViewのisScrollEnabledをfalseにしているんでしょうか?
Avatar
@mtoyooka いえ、true のままですね。false にしてしまうと、おそらく scrollViewDidEndDecelerating が拾えなくなってしまうと思います
🙌 1
Avatar
@koogawa すみません、あまり理解しきれていないのでいくつかお聞きしたいことがあります ・tableViewをscrollViewに伝える場合、どのタイミングで何を伝えていますか? ・tableViewのスクロール量をscrollViewに伝えた場合、スクロールが2倍なりませんでしょうか?そのさいtableViewのスクロールをどのように止めていますか? (edited)
Avatar
@mtoyooka ButtonBarPagerTabStripViewController を継承した ViewController にて次のようにしています。スクロールは2倍にはなりませんでした。 実装例: class ExampleViewController: ButtonBarPagerTabStripViewController, UITableViewDelegate { (中略) override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { let child_1 = TableChildExampleViewController(style: .plain, itemInfo: IndicatorInfo(title: "FRIENDS")) child_1.tableView.contentInset.top = kHeaderHeight child_1.tableView.delegate = self let child_2 = TableChildExampleViewController(style: .plain, itemInfo: IndicatorInfo(title: "FEATURED")) child_2.blackTheme = true return [child_1, child_2] } (中略) override func scrollViewDidScroll(_ scrollView: UIScrollView) { let acutualY = scrollView.contentOffset.y + kHeaderHeight buttonBarView.frame.origin.y = 200 - acutualY } ※例なので 200 とか数値をそのまま埋め込んじゃってます (edited)
Avatar
SwiftPackageManger に入ってる ArgumentParser (コマンドライン引数パーサー)が便利なので使ってたのですが、パッケージ名が SPMUtility から TSCUtility に変わったようです🙄
Avatar
TSCってなんだ?
Avatar
Tools Support Core だそうですw
Avatar
ホゲー
4:24 AM
むむっ、もしかして、
Avatar
ArgumentParser 一個使うのに、このパッケージを丸ごと持ってこなきゃいけないのアレなんですよねw
Avatar
swift-driverプロジェクトでも使ってる?
Avatar
お、やっぱりそうだ
4:26 AM
Swift compiler driver reimplementation in Swift. Contribute to apple/swift-driver development by creating an account on GitHub.
4:26 AM
↑最近できたswift-driverプロジェクトと
4:26 AM
Contains common infrastructural code for both SwiftPM and llbuild. - apple/swift-tools-support-core
4:26 AM
↑そこから依存されてるtools-support-coreライブラリがありますね
4:26 AM
ArgumentParserもこの中に入っているので、
4:26 AM
SwiftPMに依存させず、tools-support-coreに依存させると良いかも? (edited)
Avatar
こんなのあったのか < tools-support-core
Avatar
3月からあったんですねえ。知らんかった。
7:47 AM
あれ?最初のコミットは3月だけどinitial commitと書いてあるコミットは9月だなw (edited)
7:49 AM
Contains common infrastructural code for both SwiftPM and llbuild.
Avatar
おぉ、なるほど、やってみます > tools-support-core に依存させると良いかも?
3:46 AM
withUnsafeMutableBufferPointer を使った書き換え処理で、内部でスライスを作って書き換えるのはダメだと知ったのでシェアします😕 var a = ContiguousArray(repeating: 1, count: 10) a.withUnsafeMutableBufferPointer { buff in for i in 3 ..< 6 { buff[i] *= 2 // 問題なし } } a.withUnsafeMutableBufferPointer { buff in var sub = buff[3 ..< 6] for i in 0 ..< sub.count { sub[i] *= 2 // EXC_BAD_ACCESS } } (edited)
Avatar
スライスはインデックスが0始まりではないからですね。
3:48 AM
a.withUnsafeMutableBufferPointer { buff in var sub = buff[3 ..< 6] for i in sub.indices { sub[i] *= 2 } }
Avatar
あーおッ
3:49 AM
index はそのままなのか、知りませんでした😇
3:49 AM
ありがとうございます!
Avatar
a[3..<6].withUnsafeMutableBufferPointer { buff in for i in 0..<buff.count { print(i) buff[i] *= 2 } } こういうのもできます。
Avatar
omochimetaru 11/8/2019 3:50 AM
This review ended on October 21st, but because of the LLVM conference, the Core Team didn't have an opportunity to discuss it until last week. Swift's indexing model is based on solid concepts that have held up well over the years, but the verbosity of expressing positions a...
3:50 AM
↑つい最近それを buff[.start + i] って書けるようにする案が審査落ちしました。
Avatar
なるほどw
Avatar
ToolsSupportCore の件ですが、Package.swift は let package = Package( name: ... dependencies: [ .package(url: "https://github.com/apple/swift-tools-support-core", .branch("master")) ], targets: [ .target( name: "...", dependencies: ["SwiftToolsSupport"] ), で、 ArgumentParser を使いたいとこで import TSCUtility でいけました🙌 (edited)
Avatar
omochimetaru 11/8/2019 6:54 AM
おお。
Avatar
DispatchQueue.concurrentPerform を使った並列処理で、各イテレーションの中で配列を作ると無駄が大きいからスレッド毎に使い回すようなことをしたいんですが、どうやるのがいいんでしょう🤔
Avatar
スレッドローカルストレージ?
Avatar
上の withUnsafeMutableBufferPointer を使ったやり方では、最初から let threads = 8 とか決めうちしちゃって、大っきな ContiguousArray 作ってスライスしたものを各スレッド(もどき)で使い回す、というようなことをしたのですが。
Avatar
Thread.current.threadDictionaryとか DispatchQueue.getSpecificとか。
Avatar
お、どちらも見たことないものです。調べてみます。
Avatar
一般的にはTLSって言葉で調べると出ます
Avatar
おー、なるほど、スレッド別に辞書を関連づけられるんですね。
10:17 AM
concurrentPerform の中から俺 Queue を指定するみたいなこともできるのかしら。
Avatar
concurrentPerformのクロージャの中がDispatchQueue的にどういう扱いなのかわからないんですが、現在のQueueって取得できないので
10:18 AM
この場合Threadのほうが良い気がしますね
Avatar
おぉ、なるほど、了解です👍
Avatar
少なくとも同じスレッドが同時に走ってる事は原理上無いので、それで目的は果たせそう。
Avatar
ありがとうございます😄
👍 1
Avatar
https://github.com/nvzqz/Threadly こんなの見つけました。
Type-safe thread-local storage in Swift. Contribute to nvzqz/Threadly development by creating an account on GitHub.
Avatar
それ昔なんかの依存先になってて使ったんですがビルドとかあんまりキレイになってなくて微妙な思い出
10:52 AM
あ、僕の1年以上前のPR残ってますね。
Avatar
おぉw
Avatar
ErrorプロトコルのlocalizedDescriptionを上書きたいのですが、うまくいきません。 以下では"hoge"と表示されてほしいのですが、"操作を完了できませんでした。"となってしまいます。 enum hogeError: Error { case hoge var localizedDescription: String { "hoge" } } func sayError(_ e: Error) { print(e.localizedDescription) } sayError(hogeError.hoge) sayErrorメソッド内でhogeErrorにキャストすれば実現できますが、 発生し得るエラーの種類が多いため、すべて列挙するのはあまり現実的でありません。 うまい解決方法はないでしょうか。
Avatar
@watanave import Foundation enum hogeError: LocalizedError { case hoge var errorDescription: String? { "hoge" } } func sayError(_ e: Error) { print(e.localizedDescription) } sayError(hogeError.hoge)
7:53 AM
Errorの代わりにFoundation.LocalizedErrorに準拠して、errorDescriptionの実装を与えると、 .localizedDescriptionが変更できますよ。
Avatar
ありがとうございます!感激です!🙇
Avatar
この謎の方法は
7:58 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
7:58 AM
Swift.ErrorをFoundation.NSErrorに自動変換する挙動に関係してて
7:59 AM
その証拠(?)に、
7:59 AM
import Foundationimport UIKitなどを書かなければ
7:59 AM
func sayError(_ e: Error) { print(e.localizedDescription) } ↑これがそもそもコンパイルエラーになります
7:59 AM
.localizedDescriptionFoundation.NSErrorのメソッドで、Swift.Errorには無いメソッドだからです。
8:00 AM
import Foundationすると、ErrorからNSErrorへの暗黙の変換が起こるようになって、呼び出せるようになる。
Avatar
おー本当だ! そんな型変換が行われてるなんでぜんぜん知りませんでした。
😁 1
Avatar
SwiftUIのTextに表示させる値に、非同期処理の繰り返し処理の結果を順次反映させたいのですが、どうすれば実現できるでしょうか。
Avatar
Kishikawa Katsumi 11/21/2019 7:22 AM
非同期処理の結果を保持する変数を @Binding@ObservedObject で用意して、TextのBindingにその変数を指定します。 これで変数として持っている状態がTextに自動的に反映されるようになります。 あとは非同期処理が完了するタイミングで適宜その変数を更新します。
😃 1
Avatar
Taihei Mishima 11/21/2019 7:40 AM
SwiftGenを導入しようと思ってcocoapodsでinstallすると, build時に下記のようなwarningが出るようになってしまいました. 解決方法が思い浮かぶ方いらっしゃいますでしょうか? ld: warning: Could not find or use auto-linked library 'swiftDarwin' ld: warning: Could not find or use auto-linked library 'swiftCoreFoundation' ld: warning: Could not find or use auto-linked library 'swiftObjectiveC' ld: warning: Could not find or use auto-linked library 'swiftDispatch' ld: warning: Could not find or use auto-linked library 'swiftCoreImage' ld: warning: Could not find or use auto-linked library 'swiftQuartzCore' ld: warning: Could not find or use auto-linked library 'swiftCoreGraphics' ld: warning: Could not find or use auto-linked library 'swiftCore' ld: warning: Could not find or use auto-linked library 'swiftMetal' ld: warning: Could not find or use auto-linked library 'swiftFoundation' ちなみに, 同様のMac, Xcodeの環境で新規プロジェクトを作成してSwiftGenをpod installした場合は上記のwarningは出ません. どこから手をつけたら良いか, どこの部分の理解が足りてなくて解決できないのかわからずという状態です. (edited)
Avatar
Twitterのprofileのようにheader?の部分をスクロールしても、tableViewに慣性が伝わっている?ように見せる方法はありませんでしょうか?
8:09 AM
Avatar
Kishikawaさん、回答ありがとうございました! いただいた情報から https://qiita.com/shiz/items/6eaf87fa79499623306a に行きつきました。 (edited)
  • 2019/7/17 @GestureStateについて追記しました。
  • 2019/7/19 BindableObjectがdidChange->willChangeなど変更されていたので修正しました。
https://...
Avatar
@Taihei Mishima エラーメッセージでGoogle検索などしてみましたか?或いはSwiftGenのgithubに同様の問題のissueは上がっていなかったでしょうか。 経験則としてはこのメッセージが出てくる時は、ライブラリのリンク周りで問題が起きていることが多いです。 検索で何も見つからなかったなら、新規のプロジェクトとフレームワークの設定周りで注意深くプロジェクトの差分を見比べると、答えが見つかるかもしれません。 (edited)
2:38 AM
@mtoyooka 丁度すぐ上の方で似た質問がありましたので、ここの過去ログを検索してみるとよさそうです。
Avatar
同じ人でした。 didScrollは慣性は通知されていない(指が触れてる間のみ流れている)関数になるので、他の実装も必要になります。 方法としては二つあると思います。 1. willEndDraggingを実装して慣性を計算する https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619385-scrollviewwillenddragging 2. scrollViewのsetContentOffsetをオーバーライドする/KVOで監視する 1番だと何かと細かい制御が難しくなるので2番がお手軽でしょうか。 (edited)
Avatar
はじめまして。swiftサーバに最近参加したにーの( @n_shhhin )と申します。 今現在バックグラウンドで加速度を取得したい状況で、Background系の開発に疎いので手助けが欲しいです。AppStoreにリリースするのは目的ではないので、プロトでできればいい程度に思っています そこで質問なのですが、 iOS13で導入されたBackgroundTaskは BackgroundTask、 ●Background Processing Tasks - 数分かかる処理 - 延期可能なメンテ処理やCoreMLによるトレーニングを想定 ●Background App Refresh Tasks - 30秒のランタイム - アプリを最新の状態に保つための用途を想定 - performFetchのAPI が代わりにdeprecatedに みたいな感じの仕様らしいのですが、background processの数分ってのは実際どれぐらい処理が続く感じなんでしょうか。 また BackgroundTask では実現できないなら他の案をご教授いただきたいです。 既存アプリのGoogleフォトとかはバックグラウンドで常に写真のアップロードを監視してたりするのでできないことはないと思うのですが、どうやってバックグラウンドで常時処理をするのかが気になりました。よかったらどなたか強い人回答お願いします。 https://github.com/nshhhin/Background-Accel-Swift
バックグラウンドで加速度を取るプログラムSwift. Contribute to nshhhin/Background-Accel-Swift development by creating an account on GitHub.
3:20 AM
一応wipなGitHubレポジトリも載せておきます。宜しくお願いします
Avatar
@わをさん 案内だけして放置してしまい申し訳ありません。 BackgroundTaskはおそらくiOS13から使えるようになったものだと思うのですが、registerをBackGroundProcessの中で呼ぶ事で処理時間を延長するテクニックが使えるのではないか?それを使えばある程度は自由に動かせるのでは?と予想しています。https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler/3180427-register 途切れた場合はsilent pushから起こす事も出来そうですね。 一方で、バックグラウンド処理はユーザーから認識しづらく、一定のリソースには制限がかかっている可能性があると思います。特に位置情報はかなり大きなアラートが出ています。 もし素直な方法でうまくいかない場合は、制限がかかっている可能性もあると思うので(加速度センサーのデータは位置情報に次いでそれなりにセンシティブな情報だと思います)、公式ドキュメントの制限の項を参照してみるとよいかもしれません。 現状もし加速度センサーがBGTaskから使えない場合は、まともな代替手段は無いものと思います。
4:38 PM
再起呼び出し
コードを見てみたらそういう感じの処理が書いてありますね、失礼しました
Avatar
@tarunon 返信ありがとうございます。なるほど参考にさせていただきます。
Avatar
SwiftPM の SystemLibrary 機能を使って C ライブラリを Swift から使おうとしているのですが,うまく行かずに困っています. ライブラリは: https://github.com/malb/m4ri これを使いたい Package の方で,targets に .systemLibrary( name: "Cm4ri", path: "Libraries/Cm4ri" ), を追加し, dependencies に "Cm4ri" を追加した上で, Libraries/Cm4ri/module.modulemap module Cm4ri [system] { header "/usr/local/include/m4ri/m4ri.h" link "m4ri" export * } を追加しました.コマンドラインから "swift run" すると通るのですが,generate-xcodeproj して実行しようとすると,include される m4ri.h の中で "'m4ri/mzp.h' file not found" というエラーが出てビルドできません😓 (edited)
Avatar
omochimetaru 12/6/2019 4:26 AM
swift runで通ってgenerate-xcodeprojで通らない場合、 (edited)
4:26 AM
生成されたxcode projのbuild settingsに問題があるので、
4:27 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
4:27 AM
Package.swiftでunsafeFlagsとかheaderSearchPathを設定してやれば
4:27 AM
その設定がxcodeprojにも生成時にコピーされるので
4:27 AM
解決できることがあります。
Avatar
ふむふむ,やってみます.
Avatar
omochimetaru 12/6/2019 4:28 AM
SystemLibraryの構成として正しいかどうかは経験不足ですぐわかりません。
Avatar
headerSearchPath は絶対パス指定できないですよね,確か
Avatar
omochimetaru 12/6/2019 4:28 AM
unsafeFlagsしか使ったことないw
Avatar
Kishikawa Katsumi 12/6/2019 4:35 AM
私も最近のは詳しくないんですけどこれそもそもSystemLibraryにするものなんですか? Cm4riを依存ターゲットに指定するんじゃないのかな。
Avatar
system module ってのをやろうとしたら deprecated って出て,system library にせよと言われたので,こちらを参考にやってみました https://troubled.pro/2018/09/shim.html
With Swift 4.2 the Package Manager introduces System Library Targets.
4:41 AM
このライブラリは make install すると,/usr/local/include/m4ri/ ってディレクトリができて,そこにたくさんヘッダファイルが置かれるんですが,その中の m4ri.h だけを modulemap で指定してるからいけないのかなぁ🙄 (modulemap の仕組み全くわかってない) (edited)
4:43 AM
umbrella ってのを使えばできるのかも
Avatar
あれれ,新規 package 作ってやり直したら swift run でも動かなくなった orz
4:56 AM
https://github.com/taketo1024/shit サンプルプロジェクトをこちらに置きました
Contribute to taketo1024/shit development by creating an account on GitHub.
Avatar
Kishikawa Katsumi 12/6/2019 4:56 AM
ひどい名前 😓
4:57 AM
m4riってどうやってインストールしてます?
Avatar
https://github.com/malb/m4ri こちらを clone して, autoreconf --install ./configure --enable-openmp make make check make install しました. (edited)
Avatar
Kishikawa Katsumi 12/6/2019 5:00 AM
そうですよね。それだったら(Homebrewでインストールとかじゃなければ) make install のインストール先をプロジェクト内にしてしまって、
5:00 AM
そうするとmodulemapの解決も簡単だし。SystemLibraryじゃなくて単なるライブラリとして使えると思うんですよね。
5:01 AM
ちょっとやってみますか。 m4riが私の環境ですんなりビルドできなかったら解決は週末で。。。
Avatar
すみません,助かります 🙇
5:02 AM
brew install libomp libtool もしました.
Avatar
Kishikawa Katsumi 12/6/2019 5:03 AM
libtoolはautoconfですよね。
5:03 AM
libompはm4riが依存してますか?m4ri自体はOpenMPなしでビルドできます? (edited)
5:05 AM
ああ、READMEに載ってましたね。依存してるけどなしでもビルドはできるっぽいですね。
Avatar
あ,そうですね.なしでもできると思います.
5:08 AM
omp は並列処理のためのライブラリです.
Avatar
Kishikawa Katsumi 12/6/2019 5:17 AM
./configure --prefix=$PWD/dist make install ^ のようにすると$PWD/distにライブラリがインストールされます。
5:19 AM
OpenMPも有効にするなら ./configure --prefix=$PWD/dist --enable-openmp ビルドが終わるとdistは以下のようになります。 dist ├── include └── lib
5:20 AM
これはだいたい標準的なAutotoolsを使ったCライブラリのビルドの成果物で、 lib以下にライブラリ本体、includeにライブラリを使用するために必要なヘッダファイルがコピーされます。
5:21 AM
dist ├── include │   └── m4ri │   ├── brilliantrussian.h │   ├── debug_dump.h │   ├── djb.h │   ├── echelonform.h │   ├── graycode.h │   ├── io.h │   ├── m4ri.h │   ├── m4ri_config.h │   ├── misc.h │   ├── mmc.h │   ├── mp.h │   ├── mzd.h │   ├── mzp.h │   ├── parity.h │   ├── ple.h │   ├── ple_russian.h │   ├── ple_russian_template.h │   ├── solve.h │   ├── strassen.h │   ├── triangular.h │   ├── triangular_russian.h │   ├── xor.h │   └── xor_template.h └── lib ├── libm4ri-0.0.20140914.dylib ├── libm4ri.a ├── libm4ri.dylib -> libm4ri-0.0.20140914.dylib ├── libm4ri.la └── pkgconfig └── m4ri.pc
5:23 AM
^ 全部出すとこう。今回は必要なのはlibm4ri.aだけなんですけど、 ^ のdistディレクトリを自分のプロジェクトの中に入れてしまって (configureでそうなるようにして)SwiftPMからはそれを参照するようにすると、SystemLibraryとか気にせずに単にプロジェクト内にあるStatic Libを参照するだけ、となるはず。(というのを今試しています)
Avatar
おぉ,なるほど,これを丸ごと Package に入れる感じですね…
Avatar
Kishikawa Katsumi 12/6/2019 5:31 AM
. ├── Libraries │   └── Cm4ri │   ├── include │   │   └── m4ri │   ├── lib │   │   └── libm4ri.a │   └── module.modulemap ├── Package.swift ├── README.md ├── Sources │   └── shit │   └── main.swift └── Tests ├── LinuxMain.swift └── shitTests ├── XCTestManifests.swift └── shitTests.swift リポジトリの構成をこのようにするとして
5:32 AM
そうするとmodulemapは例えばこうなる module Cm4ri { header "include/m4ri.h" link "m4ri" } (modulemapはいろんな解があるんでいったん簡単なやつで試す) (edited)
5:35 AM
Xcodeだったらこれでビルドするやり方はわかるけどSwiftPMのやり方を調べ中。。。
Avatar
近い将来ソースコードを公開したいと思っているので,できれば外部のライブラリを参照する形にしたいのですが… 難しそうですかね…😔
6:00 AM
(なんで外部ライブラリを使うだけのことでこんなに苦労するのか…😔
Avatar
omochimetaru 12/6/2019 6:01 AM
なんで外部ライブラリを使うだけのことで
SwiftPMの設計哲学とC言語の慣習的な設計哲学が噛み合ってないから、と理解している
Avatar
Kishikawa Katsumi 12/6/2019 6:12 AM
Macの調子が悪くて一向に進まない。。。
Avatar
omochimetaru 12/6/2019 6:12 AM
ライブラリとして再配布するのであれば、system libraryで組むほうが今回は良さそうに思う
6:13 AM
バイナリとして取り込んじゃうとそれの管理が自己管理になっちゃうから
Avatar
Kishikawa Katsumi 12/6/2019 6:14 AM
今回のはどうせ手元でビルドするわけだからビルドスクリプトを含めて配布する方が私は良いと思う。
6:14 AM
ビルドスクリプト内でgit cloneしたらいいわけだし。
6:15 AM
どちらかというとグローバルにインストールしたくなくないですか?
Avatar
omochimetaru 12/6/2019 6:17 AM
そうですねえ、ローカルインストールのほうが望ましい ローカルインストールでもグローバルインストールでも使えてユーザーが決定できるのが理想
Avatar
make install のときに作られる pkg-config ファイルをコピーするとうまくいくのかもです(試し中)
Avatar
omochimetaru 12/6/2019 6:18 AM
末端のアプリプロジェクトのビルド時に、 -Xcc -Xlinker / もしくはunsafeFlags でローカルパスを指定したら、
6:18 AM
システムライブラリでもローカルを参照させるとか、
6:18 AM
コントロールできないのかなあ
6:19 AM
結局コンパイル時とリンク時にオプションが渡ってれば良い話だから。
Avatar
うーむ,なるほど > ローカルインストールの方が望ましい (edited)
Avatar
omochimetaru 12/6/2019 6:22 AM
今、SwiftPM CUI, SwiftPM generate-xcodeproj, Xcode SwiftPM Support, Xcode Package.swift open の4環境あるから (edited)
6:22 AM
その全部で安定してできる方法を探すのもしんどいんですよね。
6:23 AM
Xcode SwiftPM Supportの場合って、コンパイラ・リンカフラグを依存先に与える方法あんのかな。
6:24 AM
よく考えたら4環境だ
6:24 AM
ちなみに
6:24 AM
これ系で一番安定するのは
6:24 AM
CソースをそのままSwiftPMでコンパイルさせる、SwiftPMのC Targetを採用する事だと思ってます
6:25 AM
もともとのCライブラリとディレクトリ構造とか、include文の相対パスとかが、 そのまま打ち込めばいける場合と、それなりに手直しが必要な場合があって、
6:25 AM
万能な方法ではないけど
Avatar
https://github.com/taketo1024/shit/commit/28a5184eba2701167095a6daecccac451ef4aa42 とりあえずこの方法で swift run, Xcode の両方でビルドできるようになりました! systemLibrary を使う場合は pkgConfig ファイルを一緒に入れとく必要があるようです.
Avatar
Kishikawa Katsumi 12/6/2019 6:26 AM
お、なるほど
Avatar
SwiftやiOS開発の学習コンテンツでオススメとかあれば、教えてほしいです🧐 最近Udemyの英語コンテンツとかはトライしてみてるのですが...
Avatar
Kishikawa Katsumi 12/9/2019 4:44 AM
https://www.raywenderlich.com/ はいいと思います。
High quality programming tutorials: iOS, Android, Swift, Kotlin, Flutter, Server Side Swift, Unity, and more!
Avatar
ありがとうございます、まさにこういうの探してました...
Avatar
初めまして質問させて頂く「やました」と言います! よろしくお願いいたします! 現在SNSアプリでよく見かける、リストの途中に動画が挟み込んで自動再生するUI(Twitterアプリを参考)を作成しています! 以下の構成で作成しているのですが、動画セルを再利用した時に動画を途中から再生を行いたいのですが、Twitterアプリに比べると動画がスムーズ(URL設定→seekで指定時に側反映されないためDispatchで遅延処理をしている)に再生することができません...。 皆さんどうやってあんなにスムーズに途中から再生できてるんだ...!🧐 何か参考のサイトや、アドバイス頂けますと幸いです🥺 よろしくお願いいたします! # 構成 ├── UITableView │ └── VideoCell(UITableViewCell継承のCustomClass) │ ├── currentTime(動画再生時間を保持するメンバ) │ ├── VideoView(UIView継承のCustomClass) │ │ └── AVPlayer │ │ └── AVPlayerItem │ │ └── AVPlayerLayer # 作りたいもの Twitterアプリのタイムラインで表示される動画のUI # 機能 UITableView上で動画を再生・一時停止   1. スクロール時、動画のcellが画面内に収まっている場合は動画を再生   2. スクロール時、動画のcellが画面外に出ている場合は動画を一時停止 # やっている事 スクロール時に再生・一時停止の処理   1. ScrollViewのdelegate `scrollViewDidScroll` で最上部・最下部のCGPointを取得   2. 1で取得したCGPointからindexPathを取得   3. 2で取得したindexPathからcellを取得   4. 3で取得したcellのframeと画面上部、画面下部のcontentOffset.yを計算して、収まっている or 収まっていないを判定   5. 判定結果により、動画を再生 or 一時停止 # うまくいかない所 一度再生した動画セルが画面外に行き、再度画面内に来た時にスムーズに続きから再生されない   a. AVPlayerItemに動画URLを設定   b. AVPlayerのreplaceCurrentItemで設定   c. AVPlayerのseekで保持していた再生時間を指定(そのまま指定すると反応しない?のでDispatchで遅延実行しています)
Avatar
Kishikawa Katsumi 12/9/2019 3:42 PM
一部のセルが動画というだけならセルの再利用をやめて(セルは再利用してもいいけどその上のVideoViewの再利用はしない)みたらどうなります?
3:43 PM
全部のセルが動画ならしょうがないけど一部ならそれで状態の復帰とかしなくて良くなるし、普通に途中から再生されるんじゃないですかね。
Avatar
@Kishikawa Katsumi ご返信ありがとうございます! セルの再利用をしないなんて事が可能なんですか...!? 一部のセルが動画のイメージなため、確かに再利用をしなければ状態復帰の必要がなくなりますね。 再利用をしない場合って dequeueReusableCell を使用せずに、cellを生成すれば良いのでしょうか?
Avatar
Kishikawa Katsumi 12/9/2019 4:32 PM
VideoViewを別に持っておけばいいです。
4:33 PM
セルは再利用されるけど、VideoViewは生き続けるようにします。
Avatar
なるほど! 動画がいくつかある場合は、動画の数だけVideoViewを生成して配列で持っておいて、cellForRowのタイミングで当て込めば良い、って感じでしょうか?
Avatar
Kishikawa Katsumi 12/9/2019 4:44 PM
はい。動画のセルがそれほど多くならないならそれがいいと思います。
Avatar
おぉ!さっそく試してみます☺️ ご教授して頂きありがとうございました!
Avatar
それするなら動画のセルのreuseIdentifierを増やして再利用の頻度を減らした方が良さそうな気がしますがそうでもないです?
Avatar
Swift 初心者です。ある型の実装を限定することってできるんでしょうか。例えば、protocol Cat があって KawaiiNeko: CatCuteNaNeko: Cat は作ってあるけど勝手に KawaikunaiNeko: Cat は作られたくないんです。
3:27 AM
protocl じゃなくてもなんらかの表現でこの制約が与えられた良いのですが...
Avatar
できないです、protocolの代わりにenumを使うと良いと思います。
Avatar
enumは近そうなんですがちょっとキツい感じが。
3:28 AM
というのも、stored valueをswitchで取り出してなにかするみたいなfuncが大変なことになりそうで...
Avatar
enum Cat { case kawaiiNeko(KawaiiNeko) case cuteNaNeko(CuteNaNeko) } protocol CatProtocol { } struct KawaiiNeko: CatProtocol {}
3:28 AM
こうやっといてCatで受ける感じです。
Avatar
ああ、なるほど
3:29 AM
これは賢い
Avatar
enum Cat に対して CatProtocol のメソッドを全部実装しちゃえば、
3:30 AM
使う側でのswitchは回避できますね。
3:30 AM
定義はめんどうだけど。。
3:30 AM
CatProtocolがPAT(Self, associated type)ではないなら
3:30 AM
extension Cat { func asCatProtocol() -> CAtProtocol }
Avatar
そうなんです、誰か(作る側、使う側)がめんどうなことをしないといけないようですよね...
Avatar
↑これ作っておくと楽
Avatar
なるほど.
3:32 AM
試してみます...!
Avatar
誰か(作る側、使う側)がめんどうなことをしないといけない
Swiftにときどきありがち
Avatar
たくさん出てくるなら、自分で定義かいて自動生成するとか、 SwiftSyntaxで構文解析して自動生成するとか、
3:33 AM
そういう感じになってきますね・・・
Avatar
現在は自動生成ルートに向かう方向性になってます
Avatar
はや
Avatar
でも、そうする前に知らない、なにか素敵な解があるかなって思ったのでした。
Avatar
ああ、なるほど。。
3:35 AM
長期的にはforumで提案して言語仕様拡張で解決するのが一番いいやつですね。
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
3:36 AM
プロパティ限定になっちゃうかもだけど。
Avatar
ふむー、できれば避けたい...
3:37 AM
ちょっと試してみます。ありがとうございます!
👍 1
Avatar
class でいいならopen classではなくpublic classでサブクラス化を抑制できそうですね
Avatar
たしかに。
Avatar
こんにちは。SwiftUI でButtonを設置せずに指定条件下(classでデータのやりとりをしており、ObservableObjectで監視?繋げて?ます)で自動で画面遷移する方法を探しています。 (edited)
7:53 AM
どなたかいいサイト等ご存知でしたら教えていただきたいです🙇‍♂️
Avatar
別途で教えていただき解決いたしました。申し訳ありません。お騒がせいたしました🙇‍♂️
Avatar
自己解決したときは、その方法を記載しておくと後の人のためになるのでオススメです
🙏 2
Avatar
https://github.com/t-ae/tensorboardS/blob/master/Sources/TensorBoardS/Writers/SummaryWriter.swift#L124-L149 ロガーの実装ですが、ログを書く関数内にtryがあります。 このような場合インターフェースとしてはどのようなものが好ましいと思いますか? 1. throwsにする ユーザー側で毎回ハンドリングが必要なのでロガーとしてはいまいちな気がします。 2. 中でcatchして別途設定したハンドラに渡す 今はこれになっています。ハンドラはエラーだけを取っていますが、コールスタック等の情報も入れたほうがいいのかと考えています。 (edited)
TensorBoard event writer for Swift for TensorFlow. Contribute to t-ae/tensorboardS development by creating an account on GitHub.
Avatar
omochimetaru 1/20/2020 4:20 AM
たしかにログを追加することでthrowsになるのは嫌だから2で良さそう
4:21 AM
do-catch { errorHandler() } が何度も出現してるから、実装は高階関数にしたほうが良さそうと思った あと合成する場合は一番上だけでcatch
Avatar
>合成する場合 合成ってなんでしょう?
Avatar
omochimetaru 1/20/2020 4:23 AM
addJSONTextの中でaddTextを呼んでるところは
4:23 AM
例外を投げる版のaddTextOrThrowを作ってそっちを呼び出したい。
Avatar
ああ、そうですね。ここdoがネストになってますね。
Avatar
omochimetaru 1/20/2020 4:24 AM
今回はギリギリ問題は起きないけど、 f1, f2, f3が f1 { f2, f3 } って合成されてるときに、 f2がエラーでもf3が実行されるなどは不自然に思う
Avatar
ユーザーが呼ぶ関数が非throwsであれば良いので、その関数でcatchしてハンドラに投げれば良いからinternal関数は全部throwsにして垂れ流しでも問題ない?
Avatar
インターナルは基本throwsにしてますね。
Avatar
omochimetaru 1/20/2020 4:27 AM
addTextはユーザにも見せたいだろうから、 public addTextとinternal addTextOrThrowが必要と思った (edited)
4:27 AM
それか俺だったら型を分けちゃうかも。
Avatar
ThrowableSummaryWriterのような?
Avatar
omochimetaru 1/20/2020 4:28 AM
そう
4:29 AM
それでSummaryWriterは全部 func addText(...) { wrap { try w.addText(...) } }
4:29 AM
のスタイルだけで書ける
Avatar
SummaryWriter自体にデータ処理する箇所が少なからずあるのでそれは良さそうですね。
Avatar
omochimetaru 1/20/2020 4:30 AM
try wrap(w.addText(:))(...) こういうのもできるかもw
4:30 AM
関数変換にする。 文字数が少し減るけど まあデバッグしづらいから自分はやらないかな。 (edited)
Avatar
とりあえずthrowsなクラスに分けてみます。
4:33 AM
あとコールスタックですけど、do中にtryが二個あった場合catchでどちらか判別できますっけ? Thread.callStackSymbolsで取るとcatchした関数までのコールスタックになっちゃうと思いますが。
4:34 AM
ユーザーの興味はどこのwrite関数の呼び出しかなのであんまり重要じゃない気もしますが (edited)
Avatar
omochimetaru 1/20/2020 4:35 AM
どちらか判別できますっけ?
できないと思う。例外を作る関数を一個ラップすればわかるようになるかな。
4:35 AM
ん、Thread.callStackSymbolsがエラーの型のinitの中にあるなら
4:35 AM
わかりそう
Avatar
JSONEncoderとかのなのでどうでしょう・・・ (edited)
Avatar
omochimetaru 1/20/2020 4:39 AM
あーなるほど。
4:39 AM
自前の例外じゃないのか。それだとcatchで作る事になって、ユーザの呼び出しポイントしかわからないね。
Avatar
https://github.com/t-ae/tensorboardS/blob/master/Sources/TensorBoardS/Writers/SummaryWriter.swift 分けてみました。最終的には自動生成したいところですね。
TensorBoard event writer for Swift for TensorFlow. Contribute to t-ae/tensorboardS development by creating an account on GitHub.
4:52 AM
今気づいたんですがこれ分けることによってコールスタック取るのがSummaryWriterの関数内までになっちゃいますね。
Avatar
omochimetaru 1/20/2020 5:00 AM
まあユーザーは関心無いのでは
5:00 AM
Loggerの内部実装に依存してる部分の情報は
5:01 AM
ユーザーからすると役に立たないし。
Avatar
@tarunon
自己解決したときは、その方法を記載しておくと後の人のためになるのでオススメです
すみません、今頃気がつきました🙇‍♂️
4:55 AM
01/15/2020 に質問して自己(?)解決した件について、今更になったのと質問内容がよろしくなかったりしたのでリンクのみで失礼いたします。 https://teratail.com/questions/235289 簡潔に言うと、 NavigationLinkのパラメータのisActiveの中身の書き方でした。
指定条件下で画面遷移するように実装したいSwiftUIで、coreBluetoothを使用したiOSを作成しております。画面はstoryboardを使わずSwiftUIのstruct XXX: Viewで作成しており、画面以外のデータ等はclassでObservableObjec
👏 1
Avatar
解決編の投稿ありがとうございます! Discordは過去の投稿の全文検索も使えるので、活用できると嬉しいですね☺ (edited)
Avatar
そうなんですね!いつもありがとうございます!!✨
Avatar
値型はCoWがあるとは言えループを伴うmutatingでは極端に遅くなる傾向があるので工夫が必要だと思います
4:36 AM
#swift でも良さそう。
Avatar
Taketo Sano 2/4/2020 4:37 AM
すみません, #swift に再投稿します🙇
Avatar
投稿へのリファレンスが貼れるようになってるので
4:37 AM
それでよさそう。お待ちを〜
4:38 AM
おそかったw
Avatar
Taketo Sano 2/4/2020 4:38 AM
おっとw
4:38 AM
原始的なやり方しか知らずすみませんw
Avatar
プロモーションオファーの調査をしているんですが、調べてもあまり分からず知見がある方がいましたら教えてほしいです 🙇
  • 過去にプロモーションオファー(初月無料)を利用したことのあるユーザーも、再度プロモーションオファーで初月無料で利用可能か また それは同じプロモーションオファーIDでも有効か
  • 初月無料(プロモーションオファー)を利用して解約後、◯ヶ月経過したら再度プロモーションオファーで初月無料で利用するといったことが可能か
イマイチいくつかの記事を見ても上記ができるのかどうかが分からず。。。 https://developer.apple.com/documentation/storekit/in-app_purchase/subscriptions_and_offers/implementing_subscription_offers_in_your_app
Avatar
Swift & SwiftUIを初めて触り SwiftUIのチュートリアルをやっていて不明な点があったので質問させてください! 質問: 以下のcategories, featured の変数宣言の仕方が複雑でどうなってるのでしょうか?宣言時にクロージャをつけると代入になる模様です。いまいち仕組みがわかりません、、 解説もしくは何かリファレンスになるリンクを頂けると嬉しいです。 struct CategoryHome: View { var categories: [String: [Landmark]] { Dictionary( grouping: landmarkData, by: { $0.category.rawValue } ) } var featured: [Landmark] { landmarkData.filter { $0.isFeatured } } ... }
Avatar
Kishikawa Katsumi 3/20/2020 5:36 PM
https://docs.swift.org/swift-book/LanguageGuide/Properties.html# ^ 参考にできるドキュメントとしては上記のPropertiesを読むと良いです。 Swiftは同じ意味でも省略が可能だったりして記述が異なる場合があり、今回のケースで理解に悩まれているのは省略によって別の記法と混同してしまっている、などが原因に見えます。 なのでまずできるだけ省略せずに書いてみます。
5:38 PM
struct CategoryHome: View { var categories: [String: [Landmark]] { get { return Dictionary( grouping: landmarkData, by: { $0.category.rawValue } ) } } var featured: [Landmark] { get { return landmarkData.filter { $0.isFeatured } } } ... }
5:38 PM
^ 省略されている部分を書き足しました。
5:40 PM
このcategories, featured はComputed Propertyと呼ばれるもので、Property(プロパティ、メンバ変数、インスタンス変数)の一種ですが、実際の値を変数に保持しているわけではなく、アクセスがあったときに書かれている処理を実行して動的に値を返すことができる、というものです。
5:42 PM
利用側は let home = CategoryHome() let categories = home.categories このように通常のプロパティと同じようにアクセスしますが、 Computed Propertyはアクセスされたときに書かれている処理(ここでは get { ... } の中カッコの部分)を実行して値を返します。
5:43 PM
詳しくは先のリンクのドキュメントを見ると良いですが、 Computed Propertyはgetset の両方を定義できて、この例ではget の場合だけが定義されています。 (edited)
5:44 PM
このとき、getしかない場合はget { ... } と書くのを省略できて、中カッコだけにできます。 (edited)
5:47 PM
struct CategoryHome: View { var categories: [String: [Landmark]] { return Dictionary( grouping: landmarkData, by: { $0.category.rawValue } ) } ... }
5:48 PM
さらに、処理がreturn 文1行しかない場合はreturnを省略できます。(これはComputed Propertyだけでなくメソッドやfunction、クロージャでも当てはまります。)
5:49 PM
struct CategoryHome: View { var categories: [String: [Landmark]] { Dictionary( grouping: landmarkData, by: { $0.category.rawValue } ) } ... }
5:49 PM
^ return まで省略すると、最初の例と同じになります。どういう構造の文法で書かれているかわかりましたでしょうか?
Avatar
早速で詳しい回答ありがとうございます!正体は computed Property だったのですね、、助かりました!
Avatar
MVVMの勉強をしたいのですが、参考になるサンプルなど紹介していただきたいです。現状としては「iOSアプリ設計パターン入門」を購入して、この本のMVVMの章のソースを写経しました。swift-zoominチャンネルで話題になっている https://github.com/refactoring-challenge/reversi-ios をMVVMで作る挑戦してみようかと思いました。
Contribute to refactoring-challenge/reversi-ios development by creating an account on GitHub.
Avatar
@ktanaka117 もし良いものがあればお願いします🙇‍♂️
9:44 AM
とりあえず、まずはアニメーションを諦めてみるとデータバインディングで簡単にできそうなので、その上でどうアニメーションに取り組むかを考えてみても良いかもしれません。
Avatar
@koher ありがとうございます。まず、コマを置くためのボタンを押した処理がどれなのか分からないので、その辺りから見てみます。 (edited)
Avatar
↓に解説のある https://github.com/refactoring-challenge/reversi-ios/blob/master/README.md#boardviewswift func boardView(_ boardView: BoardView, didSelectCellAtX x: Int, y: Int) ですね。
Avatar
おお!ありがとうございます😄
Avatar
Contribute to refactoring-challenge/reversi-ios development by creating an account on GitHub.
Avatar
なるほど、ありがたいです🙇‍♂️
Avatar
はじめまして。こちらでAVFoundation, CoreAnimationのことについて質問してもいいでしょうか。
Avatar
多分大丈夫
5:55 AM
#uikitとかのような気がしなくもないですが...
5:55 AM
あるいは#macos/#ios?まあ厳密じゃないと思うので...
Avatar
ありがとうございます。動画生成時にCALayer, CoreAnimationを適用してテロップのようなものを表示させたいのですがうまくいかなくて。後ほど投稿させてください。
Avatar
AVAssetWriterInput とかですかねー。
Avatar
動画の上に、CALayer, CoreAnimationを使い、動画に右から左へ1文字ずつ文字が流れるようにしたいと思っています。具体的には、(1)1文字ずつCALayerを作る。(2)CAKeyframeAnimation(keyPath : "position.x")で右から左に移動させるアニメーションを定義してCALayerに適用する。 、(3)そのCALayer達をAVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer) でAVVideoCompositionCoreAnimationTool を生成し、AVMutableVideoCompositionのanimationToolに設定して、AVAssetExportSessionでexportする処理を書きました。これで実行すると、同じバイナリで動かしているのに、アニメーションが動作する場合とアニメーションが一切動作しない場合があり、これはどうデバッグしたものかと悩んでおりました。 (edited)
Avatar
AVVideoCompositionCoreAnimationTool かあ...
8:14 AM
exportには成功するんですか?
Avatar
exportは成功します。
Avatar
なるほど
8:17 AM
一般的なあれですが、動作したりしなかったりはなんかオブジェクトのライフタイムが切れちゃってるとか、そんな感じがしますね
8:17 AM
完全に同じ条件で実行するたびに挙動が変わる、ということなら。
8:21 AM
あと、多分調べられたと思いますが、これにいろいろハマりポイントが書いてあります (edited)
Avatar
ちなみに想像していたのは(1)iOSのリソースが足りなくて内部でエラーも出ず落ちている (2)アニメーションが早すぎてcoreAnimationの定義が無視されてる とか考えてました (edited)
Avatar
p56から
8:22 AM
AVAssetExportSession はバグ多いんですが、
Avatar
@niw ありがとうございます。この資料は初見です。
Avatar
エラーが出なくて書き出せてしまう、でも結果がヘン、で、compositionを指定してるっていうのだと、オリジナルのビデオにscaleが入ってる場合があったと思います (edited)
8:25 AM
asset sizeとnatural sizeが違うビデオですね
8:25 AM
有名なやつだと、Live Photo にくっついてるやつです
8:25 AM
あれは composition つけると export できない
Avatar
assetsizeとnaturalsizeが違うビデオ、がよく分かってないです。ちなみにベースとなるビデオは自前のコードで生成しています。(AVAssetWriter使用
8:34 AM
ありがとうございます 離席いたします
Avatar
だろしたらそこは問題ではないかも。サイズが違うってのは、録画時のピクセルと、表示する際のピクセルが一致してないビデオのことです。Live Photo についてるのは、高解像度な写真と同じサイズになるように実際の動画が引き延ばされるようなアファイン行列がヘッダーに入っていて、それをうまく処理できません。
Avatar
なるほど、Live Photoは元のアセットではないです
Avatar
calayer core animationをせっかく学んだのですが、解決しないようなら、一枚一枚画像を作ってそれを元にアニメーションにしようと思います
Avatar
@niw ググってもこのドキュメント一度もヒットしなかったのですが、この手のドキュメントをどうして知れたのですか。https://docs.huihoo.com/apple/wwdc/2011/session_415__working_with_media_in_av_foundation.pdf あと、PDFに書かれてるサンプルコードはどこかに公開されているのでしょうか? (edited)
Avatar
@niw 理屈がわからないのですが、CAKeyframeAnimationクラス等、アニメーションを司っているクラスのisRemovedOnCompletionをfalseに設定したところ、今のところアニメーションが有効に表現されるようになりました。 (edited)
Avatar
あー、それはそうしろと書いてありますね。removeOnCompletion が YES だと、CA的には終了時にモデルの値になるのですが、多分 composition はpresentationしかみないとかそういう制約があるのかも。
2:34 PM
ちなみに、サンプルコードは多分当時WWDCに参加した人のみがアクセスできたんだと思います。
2:34 PM
2011年とかだと、そういう運用だったとかだと思います。
Avatar
諸々ありがとうございました @niw
👍 1
Avatar
dicklessgreat 5/18/2020 2:24 PM
はじめまして。 Xcodeプロジェクトから出力した.frameworkをiOS開発のプロジェクトに埋め込むことができず困っています。 「iOSアプリ設計パターン」という本のサンプルコード をGitHubからダウンロードし、「GitHub.xcodeproj」を開き、特に設定は変更せずにそのままビルドしました。 出来上がった「Github.framework」をMedia⁩ ▸ ⁨アプリケーション⁩ ▸ ⁨Xcode⁩ ▸ ⁨Contents⁩ ▸ ⁨Developer⁩ ▸ ⁨Platforms⁩ ▸ ⁨iPhoneOS.platform⁩ ▸ ⁨Developer⁩ ▸ ⁨SDKs⁩ ▸ ⁨iPhoneOS.sdk⁩ ▸ ⁨System⁩ ▸ ⁨Library⁩ ▸ ⁨Frameworks⁩に配置しました。 このGithub.frameworkを使用したいプロジェクトをXcodeで開き、プロジェクトのGeneral → Framework, Libraries and Embedded codeにGithub.frameworkを追加しました ビルドすると、以下のエラーが出ました GitHub is not available when building for iOS Simulator. Consider using #if os(iOS) to conditionally import this framework when building for iOS. No such module 'GitHub' Xcodeを使ってライブラリをリンクさせたことがありませんので、何か基本的な事を間違えているのだと思いますが、どなたか教えていただけると幸いです。
swift 1
2:27 PM
すみません、一つ付け足しです。#import GitHub と書いた部分にエラーが出ました
Avatar
omochimetaru 5/18/2020 2:35 PM
1. システムのiPhoneOS.platform領域に配置しているのが変です。 取り込むフレームワークはシステムには入れずにアプリのプロジェクトのところに配置します。 ただ、これは慣習の話で、エラーとは関係ないかもしれません。 2.フレームワークがiPhone実機用にビルドされていて、 取り込んでいるアプリをiPhoneシミュレーター用にビルドしようとしていて、 そのエラーメッセージが出ているのかもしれません。 フレームワークが実機用にビルドされているときは、 アプリも実機ビルドしかできません。 フレームワークを実機とシミュレーターの両対応にする方法はありますが複雑で面倒なのでいったん省略。 (edited)
Avatar
dicklessgreat 5/18/2020 2:37 PM
ありがとうございます。確かにシミュレーターで動かそうとしていました。実機で確認してみます。
2:39 PM
実機でビルドしてみたところ、エラーが変化しました。 エラーがでた場所は同じです。 Could not find module 'GitHub' for target 'arm64-apple-ios'; found: x86_64-apple-ios-simulator, x86_64
2:39 PM
アプリのプロジェクトに配置して、シミュレーターで実行してみます。
Avatar
Kishikawa Katsumi 5/18/2020 2:42 PM
エラーの内容はおもめたさんが書いた通りなんですけど、このサンプルコードのGitHub.framework
Avatar
フレームワークを実機とシミュレータ両方に対応させるのは面倒なので、GitHub.xcodeprojをアプリのxcodeprojに追加するのが一番簡単な解決法だと思います。
Avatar
Kishikawa Katsumi 5/18/2020 2:45 PM
^  そうですね。このようにプロジェクトにプロジェクト参照の形で取り込んでしまうか、サンプルの14, 15にあるようにCocoaPodsを使うのが簡単だと思います。
Avatar
dicklessgreat 5/18/2020 2:47 PM
アプリのプロジェクトのところに配置してみましたが、結果はシミュレーターでも実機でも変わりませんでした。 kateinoigakukunさまのやり方もやってみます。プロジェクトにプロジェクトの追加・・・やった事ないですけど笑、ちょっと頑張ってみますw
Avatar
こんな感じの構成にすると Link Binary With Libraries セクションでGitHub.frameworkが選べるようになると思います。
Avatar
Kishikawa Katsumi 5/18/2020 2:49 PM
置き場所はどこでもいいです。プロジェクト外に配置すると、プロジェクトのディレクトリを移動したら参照先が辿れなくなるので、普通はプロジェクト内のディレクトリに置いて相対パスで参照する方が一般的、ということです。
Avatar
dicklessgreat 5/18/2020 2:51 PM
kateinoigakukunさま、ありがとうございます!やってみます。 Kishikawa Katsumiさま、わかりました。ありがとうございます。
👍 1
Avatar
omochimetaru 5/18/2020 2:51 PM
う〜んなんだろう。 フレームワークが実機armv7ターゲット限定でビルドされているけど、 アプリは実機arm64,シミュレーターx86_64でビルドしようとしている? あと、GitHubGithub で H の大文字小文字がときどきブレてるのが気になります。 家庭くんと岸川さんの書いてるように、 フレームワークファイルを手作りしないで済む方法(プロジェクト依存またはCocoaPods)のほうが無難です。
Avatar
dicklessgreat 5/18/2020 2:58 PM
omochimetaruさま すみません。ただの僕の書き間違いです。 サンプルコードから一切書き直していないので、そのままビルドは通る・・・はずなんですが・・・。
Avatar
dicklessgreat 5/18/2020 4:17 PM
すみません、格闘してみたのですが僕にはどうしてもビルドする事ができませんでした。サンプルコードが実際にどのように
4:19 PM
動いているのか確かめたいだけなので、.frameworkのビルドをiOSシミュレーター用に設定することはできませんか?もしできるなら、どこを設定すればいいのかも教えていただけませんか?
Avatar
Contribute to peaks-cc/iOS_architecture_samplecode development by creating an account on GitHub.
4:24 PM
これのことですかね
Avatar
dicklessgreat 5/18/2020 4:25 PM
はい、それです。 あ、ReadMe読んでなかった笑
Avatar
これのことなら、 GitHub.xcworkspace ひらけば何もせずにGitHub scheme一回ビルドしてから palygorundのやつ全部動くと思いますよ
Avatar
omochimetaru 5/18/2020 4:25 PM
Avatar
xcodeprojじゃだめ
Avatar
omochimetaru 5/18/2020 4:26 PM
↑のGeneric iOS Device のところをシミューレータにするとシミュレーター向けのビルドになります
Avatar
いま git clone --depth=1 https://github.com/peaks-cc/iOS_architecture_samplecode.git して試したので。macOS 11.15.4, Xcode 11.4.1。 (edited)
Avatar
dicklessgreat 5/18/2020 4:31 PM
niwさま すみませんちょっと今戦慄みたいなものが…笑全然知りませんでした笑
4:31 PM
使い方調べてみます。
Avatar
白いアイコンのほうです、青い方じゃなくて。
Avatar
dicklessgreat 5/18/2020 4:34 PM
はい、開くと…左側にプロジェクトの一覧が出てくるんですが…これをどう実行するんでしょうか?
Avatar
↑ omochimetaru さんのいうように、
4:34 PM
停止ボタンの右にあるやつが GitHub > Generic iOS Device
4:35 PM
になってたら、そこを iPhone 11 Pro Max とかに変えて
4:35 PM
いちど再生ボタンおして GitHub.framework をビルドしてください
Avatar
dicklessgreat 5/18/2020 4:35 PM
ああ!ビルドできました!! 後ろで他のXCodeプロジェクトが走っていました。
Avatar
で、そのあとは、左側の Playground の下にあるやつ
4:35 PM
いろいろ試してみてください
Avatar
dicklessgreat 5/18/2020 4:35 PM
それを消せばビルドできました。
Avatar
ああ、同時に同じものは二箇所でひらけません。
Avatar
dicklessgreat 5/18/2020 4:36 PM
なんですねぇ、それすら知りませんでした。 お騒がせいたしました。 (edited)
✅ 1
Avatar
dicklessgreat 5/18/2020 5:12 PM
xcworkspaceのことを知る以前にやっていた作業によってプロジェクトが壊れており、結局GitHubからもう一度ダウンロードし直してビルドし直せば問題なく実行できたという顛末でした。 上記作業のため少し遅くなりましたが、ご協力いただいた皆様、ありがとうございました。勉強を進めてみます。
💯 2
Avatar
delegateをイニシャライザでDIするのはアンチパターンですか
Avatar
omochimetaru 5/21/2020 4:35 AM
どういうコード?
Avatar
class SomeClass { private weak var delegate: SomeViewDelegate! init(delegate: SomeViewDelegate) { self.delegate = delegate } } (edited)
4:36 AM
エンター押しちゃった
4:37 AM
完了、こういう風にできるんだったらdelegateのしわすれぼうしできるかなあっておもいました
Avatar
omochimetaru 5/21/2020 4:38 AM
私は普通にやるよ。 Delegateよりクロージャのほうが良いと思うけど・・・ (edited)
Avatar
なるほど、(諸事情によりDelegate)
Avatar
omochimetaru 5/21/2020 4:38 AM
initなら忘れないというのも同意。 (edited)
Avatar
諸事情っていうのはだいたい説明コストですが(Delegateのほうが説明できる) (edited)
4:39 AM
ありがとうございます!
4:39 AM
クロージャの場合だとどんな感じになるんですかね
Avatar
omochimetaru 5/21/2020 4:40 AM
class SomeClass { init(cancelHandler: (() -> Void)?, submitHandler: (() -> Void)?) { } }
❤️ 1
Avatar
あ、そのままクロージャ渡すって感じですね
Avatar
イニシャライザで渡すのは別にアンチパターンだとは思わないですが、現実問題としてもし総合参照する設計なら、お互いのイニシャライザにお互いが必要になってきてデッドロックが発生する問題があるんですよね
Avatar
お互いのイニシャライザにお互いが必要
それは、それぞれのイニシャライザの引数にお互いを載せないとイカンくなるってことですか
Avatar
class Parent { var child: Child init(child: Child) } extension Parent: Autohority {} protocol Authority: AnyObject {} class Child { weak var autority: Authority? init(authority: Authoority) } こうかですね↑ (edited)
5:05 AM
Parent 作るのに Child 必要、でも Child を作るのに Authority として Parent が必要
Avatar
ふむう
Avatar
omochimetaru 5/21/2020 5:05 AM
循環関係はinitだけで作れないので、どっちかのプロパティをvarかつOptionalにして、 後から繋げる必要がありますね。
5:05 AM
それでも、initには引数として定義しておいて、 「循環で困ってから」プロパティでつなぐようにすれば
5:06 AM
そもそもつなぐことを忘れる心配は減らせると思う。
Avatar
そういうときは大体lazy varで解決できるのでは
Avatar
片方のTestable性が失われていますね
Avatar
そもそもdelegateパターンならほぼ確実にclassだし
Avatar
ん、なるほど
Avatar
omochimetaru 5/21/2020 5:06 AM
別にnilも許すように作っておけば壊れてはいないと思う。
5:07 AM
そもそもweakが出てくるからどっちかはOptionalになってそうだし。
Avatar
ですね
5:08 AM
class ViewController: SomeViewDelegate { private lazy var presenter = Presenter(delegate: self) } class Presenter { private weak var delegate: SomeViewDelegate! init(delegate: SomeViewDelegate) { self.delegate = delegate } } ちなこんなの作ってました ViewController の方のlazy varのprivateを外すといいのかな (edited)
5:10 AM
access level警察に怒られそうだけど
Avatar
omochimetaru 5/21/2020 5:10 AM
うん。
5:10 AM
別に、途中で変更できてもおかしくなくない?
Avatar
別に private つけて動くなら全部 private つけちゃえと思う
👍 1
Avatar
omochimetaru 5/21/2020 5:10 AM
「その時セットしてるオブジェクトに対して委譲される」という仕様なだけかと。
Avatar
presenter を替えてたらTestableにもできるから private はずしてもええかなっておもったです (edited)
Avatar
omochimetaru 5/21/2020 5:11 AM
button.tapHandler = { ... } を状態遷移に連動して書き換えるとかやらないこともないよ。
Avatar
なるなる
5:12 AM
それだったらdelegateよりも楽にできそう
Avatar
初めましてこんばんは。 RxSwiftを勉強中なのですが、書き方がわからなかったので教えて頂きたいです。 やりたい事は、2つの通信処理を直列に叩いて、それぞれのレスポンスの中の ある値に応じて処理をさせたいです。 具体的には、レスポンスはエラーが返ってこないことを前提として requestAを実行 -> responseAがエラーでなければrequestBを実行 -> ResponseA.isHoge==trueかつResponseB.str=="xxx"であれば処理をする 上記の流れで処理を行いたいです。ご教示頂けると助かります。 struct ResponseA { let isHoge:Bool } struct ResponseB { let str:String } func requestA() -> Observable<ResponseA> { //通信処理 } func requestB() -> Observable<ResponseB> { //通信処理 }
Avatar
omochimetaru 5/27/2020 1:54 PM
class ViewController: UIViewController { let disposeBag: DisposeBag = DisposeBag() @IBAction func onButton() { requestA().flatMap({ (responseA) -> Observable<Void> in requestB().map({ (responseB) -> Void in if responseA.isHoge, responseB.str == "xxx" { accept(responseA, responseB) } return () }) }).disposed(by: disposeBag) } }
1:55 PM
こんな感じです。
Avatar
早速ご回答頂きありがとうございます! rx以前の話でしたら恐縮なんですが1点質問させて下さい。 accept(responseA, responseB)の行は何をしてるんでしょうか・・・? ここにやりたい処理を実装するって意味合いで合ってますか?
Avatar
omochimetaru 5/27/2020 2:02 PM
はい。
であれば処理をする
↑の部分が func accept(responseA: ResponseA, responseB: ResponseB) { ... } だったとしたら、という擬似コードでした。
Avatar
納得しました! 早速試してみます。非常に助かりました!
👍 1
Avatar
教えていただきたいのですが、 struct DirectProduct<Left: Sequence, Right: Sequence> { let left: Left let right: Right } このようなstructをSequenceにしたいと思うのですが、この時Left, Rightの型によってIterator#next()の実装を変えたいと思うのですが、これは可能でしょうか? 考えているのはLeft,RightがCollectionの時とLeft,RightがCollectionでIndex == Intの時に実装を切り替えることです。 いろいろ試しているのですがうまくいきません。 方法があれば教えてください。
Avatar
こんな感じのことをやりたいですか? struct DirectProduct<Iterator, Element, Left: Sequence, Right: Sequence> where Left.Element == Element, Right.Element == Element, Left.Iterator == Iterator, Right.Iterator == Iterator { let left: Left let right: Right } extension DirectProduct: Sequence where Left: Collection, Right: Collection { func makeIterator() -> Iterator { if left.startIndex is Int, right.startIndex is Int { // return iterator } else { // return another iterator } } }
Avatar
試してみましたが extension ではできなさそうですね。 @swift-5.2.5 struct DirectProduct<Left: Sequence, Right: Sequence> { let left: Left let right: Right init(_ left: Left, _ right: Right) { self.left = left self.right = right } } extension DirectProduct: Sequence { func makeIterator() -> Iterator { print("makeIterator A") return Iterator(left, right) } class Iterator: IteratorProtocol { fileprivate let left: Left fileprivate let right: Right init(_ left: Left, _ right: Right) { self.left = left self.right = right } func next() -> (Left.Element, Right.Element)? { nil } } } extension DirectProduct where Left: Collection, Right: Collection, Left.Index == Int, Right.Index == Int { func makeIterator() -> Iterator { print("makeIterator B") return Iterator2(left, right) } class Iterator2: Iterator { override init(_ left: Left, _ right: Right) { super.init(left, right) } override func next() -> (Left.Element, Right.Element)? { nil } } } do { let p = DirectProduct([2, 3, 5], ["X", "Y", "Z"] as Set<String>) for (_, _) in p {} _ = p.makeIterator() } print() do { let p = DirectProduct([2, 3, 5], ["X", "Y", "Z"]) for (_, _) in p {} _ = p.makeIterator() }
Avatar
makeIterator A makeIterator A makeIterator A makeIterator B
Avatar
Collection 限定なら lovee さんの戦略は良さそうな気が。
Avatar
あー、分岐した後がうまくいかない?
Avatar
お、いけるかも?
3:00 AM
@swift-5.2.5 struct DirectProduct<Left: Collection, Right: Collection> { let left: Left let right: Right let iteratorType: DirectProductIterator<Left, Right>.Type init(_ left: Left, _ right: Right) { self.left = left self.right = right iteratorType = DirectProductIterator.self } } extension DirectProduct where Left.Index == Int, Right.Index == Int { init(_ left: Left, _ right: Right) { self.left = left self.right = right iteratorType = DirectProductIterator2.self } } extension DirectProduct: Sequence { func makeIterator() -> DirectProductIterator<Left, Right> { iteratorType.init(left, right) } } class DirectProductIterator<Left: Collection, Right: Collection>: IteratorProtocol { fileprivate let left: Left fileprivate let right: Right required init(_ left: Left, _ right: Right) { self.left = left self.right = right } func next() -> (Left.Element, Right.Element)? { print("DirectProductIterator") return nil } } class DirectProductIterator2<Left: Collection, Right: Collection>: DirectProductIterator<Left, Right> where Left.Index == Int, Right.Index == Int { required init(_ left: Left, _ right: Right) { super.init(left, right) } override func next() -> (Left.Element, Right.Element)? { print("DirectProductIterator2") return nil } } do { let p = DirectProduct([2, 3, 5], ["X", "Y", "Z"] as Set<String>) for (_, _) in p {} } print() do { let p = DirectProduct([2, 3, 5], ["X", "Y", "Z"]) for (_, _) in p {} }
Avatar
DirectProductIterator DirectProductIterator2
Avatar
@masakihori ↑これでどうでしょう? for では無理だったのでイニシャライザで型情報を埋め込みました。
Avatar
Iterator も実装してみた例です。 https://gist.github.com/koher/550ea1e9625e66758bac85eb5063196f
3:36 AM
スーパークラスにサブクラスでは不要なプロパティがあるのと、イニシャライザで makeIterator を無駄に呼んでるのが気持ち悪いですが・・・。
3:37 AM
共通の抽象スーパークラスを作ればいいのか。
Avatar
大分きれいになった気がする。
3:51 AM
こういうイテレータの実装だと LeftRight に参照型のコレクション渡されると壊れるけど。
Avatar
あー、説明がダメでした
4:14 AM
LeftとRightが両方Sequenceの実装に加えて両方がCollectionの時の実装を別に設けたかったんです
Avatar
↑の方法なら SequenceCollection でもいける気がしますね。
4:18 AM
SequenceIterator1Collection where Element == IntIterator2 が返されるようにしました。 https://gist.github.com/koher/550ea1e9625e66758bac85eb5063196f
Avatar
なるほど、分かりました
4:22 AM
Iterator.Typeをもってinitもoverrideしちゃうのか。なるほど
4:23 AM
ありがとうございます
🙂 1
4:29 AM
structの名前しか書いてないのに実装が僕が書いたものとほぼほぼ同じなのでちょっと笑いましたw
Avatar
多分こういうことがやりたいのかなとw
Avatar
SwiftUIを勉強中なのですが、「Unable to infer complex closure return type; add explicit type to disambiguate」というエラー文が解決できずに躓いています。このエラー文はどういったときに出るものなのか、教えていただけると助かります。
11:14 AM
Google翻訳で直訳すると「複雑なクロージャーの戻り値の型を推測できません。 明確にするために明示的な型を追加する」となるようです。
Avatar
Kishikawa Katsumi 5/31/2020 11:30 AM
コードが複雑すぎてコンパイルがいつまで経っても終わらないからコンパイラが途中で処理を中止してるんですね。 複雑すぎて、といっても見た目にはさほど複雑ではないコードでも起こるので大変です。 典型的には、クロージャを入れ子にしたり、Modifierをドットで繋いでメソッドチェーンをすると途中経過の戻り値や引数の型の関係をコンパイラがうまく推測できずに失敗するという事象です。
11:31 AM
解決するにはほとんどの場合、入れ子やメソッドチェーン(ドットで繋いで続けてメソッドを呼び出す)を分解してコンパイラに一つ一つの簡単なものとして与えるようにします。
11:32 AM
例でいうと import SwiftUI struct ContentView: View { var body: some View { VStack { Text("Hello SwiftUI Playground!") .font(.largeTitle) .foregroundColor(.blue) .padding() Button(action: {}) { HStack { Image(systemName: "suit.heart.fill") .foregroundColor(.red) Text("Let's Get Started!") .font(.headline) .foregroundColor(.white) } .padding(12) .background(Color.orange) .cornerRadius(8) } } } }
11:33 AM
^ こういう元のコードがあるとして、これは1つの大きなクロージャで中のクロージャは全部外側のクロージャの入れ子になっています。これがもっと多くの入れ子を含んだりするとそのエラーが起こります。
11:35 AM
なのでそうなったら、 import SwiftUI struct ContentView: View { var body: some View { let button = Button(action: {}) { HStack { Image(systemName: "suit.heart.fill") .foregroundColor(.red) Text("Let's Get Started!") .font(.headline) .foregroundColor(.white) } .padding(12) .background(Color.orange) .cornerRadius(8) } let text = Text("Hello SwiftUI Playground!") .font(.largeTitle) .foregroundColor(.blue) .padding() return VStack { button text } } } このように入れ子になっているクロージャを取り出していったん変数に格納してそれを同じように最後に組み合わせるようにします。 こうすると、もともと入れ子になっていた1つ1つのクロージャは簡単なクロージャでいったん型の推測が可能になるのでだいたい問題が解決します。無理な場合はもっと細かく分解します。
11:37 AM
SwiftUIでありがちなパターンだと、そのエラー以外でもどうせ10個以上のクロージャを入れ子に持つことはできないので、ちょっとした部品を作るだけでもすぐに制限に引っかかります。 なので上記の例にあげたくらいのコードになったらカスタムビューとしてコードを切り出すほうがうまくいきます。 ちょっとひとかたまりのコードができたら再利用するかどうかはあまり気にせず名前をつけてカスタムビューにしてしまうのがいいです。
Avatar
回答ありがとうございます!カスタムビューで分解したら、エラーは解決しました!ありがとうございます!
Avatar
初めまして。 printでDebug consoleに表示させようとしても何も表示されません。 表示させる方法を教えください。 お願いします。
10:04 PM
Avatar
omochimetaru 6/9/2020 10:06 PM
プレビューではなくアプリとして実行した場合は表示されますか? Xcodeの左上にある右三角のボタンです
Avatar
表示されました。
Avatar
omochimetaru 6/9/2020 10:09 PM
それならコードは正しそうです。 Preview Canvasにはデバッガがアタッチされないために表示されない、という仕様だと思います。詳しくないですが。 (edited)
Avatar
仕様ですか。 朝はやくにありがとうございました! (edited)
Avatar
すみません Xcodeのストーリーボードでエディタモード起動したんですが ViewController.swift とは違うのが出て ファイル検索かけても ViewController.swift がなかったのですがどうすれば良いですか;
1:09 PM
説明にはViewController.swiftが出ているんですが;; (edited)
Avatar
ここ右クリックするとデバッガにアタッチできるかと思います @ryota2357
Avatar
@kenmaz. デバッガにアタッチできて、ログも表示されました。ありがとうございます!
👀 1
👍 1
Avatar
Kishikawa Katsumi 6/14/2020 12:49 AM
@hogehoge もう少しそこに至るまでの手順を具体的に何をしたか、というのを教えてください。あと、現在の状況がどうなってるかをスクリーンショットで共有してもらえるとわかりやすいかも。
Avatar
アドバイス頂きありがとうございます ストーリーボードでボタン等のパーツを配置した後、 ViewController.swift にそれを関連付けしたく探したのですが ViewController.swift が見つからずいろいろ調べてました 先程、言語をSwiftUIからStoryboardに変更したところ自己解決できました ありがとうございました (edited)
Avatar
Kishikawa Katsumi 6/14/2020 12:57 AM
なるほど。SwiftUIを選ぶとデフォルトのコードが変わるのでViewController.swiftはセットアップ時に作られない、ってことですね。
Avatar
参考になります! (edited)
Avatar
こんばんは 座標の取得方法について質問させて下さい やりたいことは、指定したy座標の位置まで UIScrollViewを縦スクロールさせたくて、スクロール方法は scrollView.setContentOffset にスクロールさせたい 座標をCGPointで渡せばいいことまではわかったのですが xib内のUIコンポーネントの座標を渡してみたところ 常にその座標が(x:0.0,y:0.0)になってしまい 自分が想定しているところまでスクロール出来ず困っています 具体的に、スクリーンショットの Second Input Viewの黒字のタイトルと書かれている UILabelの上までスクロールさせたいのですが この座標を取得するにはどうしたら宜しいでしょうか? 黄色塗りされている部分がxibとなっております。 ご教示頂けると幸いです。宜しくお願いします。 (edited)
Avatar
Kishikawa Katsumi 6/14/2020 11:37 AM
let frame = secondInputView.titleLabel.convert(secondInputView.titleLabel.bounds, to: scrollView) print(frame) ^ このコードを追加して値を調べてみてください。
11:39 AM
要は titleLabel.frame はSuper Viewからの相対座標なので、secondInputViewから見た座標になります。 Scroll Viewでどの位置か、というのはScrollViewから見た座標に変換する必要があります。
11:39 AM
というのをやってるつもりなのが上のコードです。
11:39 AM
合ってるかどうか微妙なので実行した結果を教えてください。
Avatar
早速ご回答頂きありがとうございます! 出力は(20.0, 174.66666666666669, 63.66666666666666, 20.333333333333343) になり frame.origin.y を渡してあげたら、想定した位置までスクロールしました! 調べた中でconvertは出てきたんですけど、ややこしくていまいち理解が出来ずに 避けてしまったので、もう一度ドキュメントをよく見てみます。 非常に助かりましたありがとうございました! (edited)
Avatar
質問させてください! NewsPicksのようなタブをUIPageViewControllerで実現していて、viewcontrollersのUICollectionViewを持つUIViewControllerが複数あります。 そのうちの初期で表示されるVCのUICollectionViewのセルとして、横スクロールできるカルーセルのUICollectionViewを表示させたのですが、そのカルーセルをスクロールしようとするとUIPageViewControllerがスクロールされてしまいます。 また、一度UIPageViewControllerがスクロールされたあと、再度カルーセルをスクロールするとスクロールが可能になります。初期状態でもカルーセルをスクロール可能にする方法を知りたいです。 よろしくお願いいたします🙇‍♂️
Avatar
UIGestureRecognizerdelegate設定したいいんじゃないでしょうか? (edited)
3:31 AM
(これは逆もある)
Avatar
ありがとうございます! これは、カルーセルのUICollectionViewのGestureを制御するということですか?
Avatar
そっちを勝たせないといけないので
3:35 AM
そう言う感じにしないといけないんだと思います。
3:36 AM
UICollectionViewは(UITableViewとかも)コンテンツへのタップデフォルトでは遅らせるようになっていて(だからスクロール中にボタンとかに反応せずにスクロールがスムーズにできる) (edited)
3:37 AM
逆にそれが望ましくないケース、たとえば今回のような、コンテンツ側でジェスチャーを認識しないといけない場合などで支障が出ます。 (edited)
Avatar
こんにちは!1点質問させて下さい ViewController A → ViewController Bに画面遷移をする際に modalTransitionStylecrossDissolve を指定してpresent で遷移したときの フワッと遷移する際の、durationの値を変更することは可能でしょうか? また不可能な場合、代替策としてどのような実装がありますでしょうか・・・? ご教示頂けると幸いです。
Avatar
Kishikawa Katsumi 6/15/2020 5:26 AM
durationの変更はできないです。 viewController.modalPresentationStyle = .custom viewController.transitioningDelegate = self としてカスタムトランジションを実装するのが一般的な方法です。 クロスディゾルブくらいなら遷移元と先でalphaを1=>0/0=>1するだけなので実装も難しくないです。
Avatar
ご回答頂きありがとうございます カスタムトランジションですね。実装したことがないので 調べてチャレンジしてみます。詰まったらまた質問させて下さい・・・!
Avatar
@niw ありがとうございました。やってみます!
💯 1
Avatar
@飯塚 できる
7:08 AM
けど、だいぶキモい方法になります
👀 1
7:09 AM
@Kishikawa Katsumi さんの回答は多分正攻法として正しい
7:10 AM
端的に言うと、CATransactionで時間を遅らせます
7:10 AM
これは interactive transitionが内部でやってる実装で
7:11 AM
transactionの時間を進めたり戻したりしてトランジションをコントロールできます
7:12 AM
だいぶアレなので、まあ、自分でtransitionアニメーションを作った方が安心感はあります
7:14 AM
CATransaction.setAnimationDuration()あたりでまずは試してみると雰囲気わかるかも
Avatar
Kishikawa Katsumi 6/15/2020 7:22 AM
なるほど。たしかにそのあたりの方法でいうと、layer.speedを変えるという手もありますね。
Avatar
それですねー、それがまさにinteractive transitionがやってるやつ (edited)
7:26 AM
まああんまりおすすめはできないけれど、CoreAnimationを愛せれば
7:27 AM
これ系の手法でほとんどを手中に納められるので
7:27 AM
なかなか良いかなあと言う感じ
7:27 AM
ただし、UIViewのアニメーションは厄介なのでそれとの兼ね合いはなかなかキビしい
Avatar
Kishikawa Katsumi 6/15/2020 7:28 AM
そうか、interactive transitionはスピードゼロでアニメーションをスタートして時間を外から割合で与えるのか
Avatar
そうです
7:29 AM
いやそうでなくてもいいんだけど、implicitなのはそういう実装になってる
Avatar
こんばんはー githubのalarm-ios-swift(https://github.com/natsu1211/Alarm-ios-swift) を使って開発をしています。 しかし、ios13以降で設定したアラームのtableviewが反映されず困っています。 tableView.reloadDataをアラームのsave処理の場面で試したり、画面の再描画などを試しましたが結果は変わりませんでした。 同コードを使ったことがある方など、ご教授いただけるととても助かります。よろしくお願いします。
3:20 PM
ios12では通常通り動作します。
Avatar
Masashi Aso 7/1/2020 1:09 AM
iOS 13以降のSheetに関する問題に見えます。去年の https://developer.apple.com/wwdc19/224 あたりが参考になるかと。
iOS 13 combines powerful new multitasking and productivity technologies with a refreshed look and feel for all applications. Familiarize...
👀 1
👍 1
Avatar
https://qiita.com/lanches_hiromi/items/39c5d390b45943c0b1d8 モーダルが閉じたときに遷移元のviewWillAppear、viewDidAppearが呼ばれないのが原因ですかね....?
はじめに iOS13からシートモーダル表示(セミモーダル表示)がデフォルトスタイルになりました。 iOS13で新たなモーダルスタイルが登場したのをきっかけにモーダル画面について調べたことを 記載したいと思います。 そもそもモ...
Avatar
presentationをfullscreenにしたらいけました! ありがとうございます!
👍 1
Avatar
こんばんは textField及びtextViewを使用した際に、入力時に 入力欄がキーボードに被ってしまう際の、回避方法について ベストプラクティスをご教示頂きたく質問させて下さい。 回避する方法自体は、調べればいくつかパターンが出てきて ScrollViewを敷いてズラす方法や、キーボードの高さを計算して画面自体を上にズラす方法など様々あるのですが 画像のような、スクロールを前提としていなくて画面下部に textField及びtextViewが配置されているような画面を考えたときに、どのようにキーボードが隠れて入力できなくなってしまう 現象を回避するのが良いのでしょうか?ご教示頂けると幸いです。 (edited)
Avatar
ScrollView使うのが楽だと思います
Avatar
早速ご回答ありがとうございます 例えば縦長にスクロールを前提にしてない画面でも キーボードが被るようなレイアウトであれば下にScrollViewを敷いておくってことでしょうか?
Avatar
ちゃんと説明すると結構な長文になるんですが、幾つかの理由からキーボードの有無に関わらず「例え現段階ではScrollしない画面でもUIScrollViewを仕込んでおく」というのは有効なプラクティスだと考えています。 理由について代表的なものは以下のものでしょうか。 1. 端末サイズが多岐に渡るので、フルフルに使ったデザインでは4インチの端末でスクロールが必要になるケースが多い 2. スクロール無しでDynamicTypeに対応することが困難である 3. SafeAreaの取り扱いは手動でAutolayoutを設定するよりもcontentInsetAdjustmentBehavior = automatic, alwaysBouncesVertical = trueの組み合わせに頼ったほうが遥かに楽である もちろん、フルスクラッチのデザインでSafeAreaもDynamicTypeも関係ない!ということもありますので、100%適応可能である、というわけでは無いです。
Avatar
僕は使ったことがないのでよくわかってないですが、↓多分そういう目的で使えるライブラリなんじゃないかと思ってます。 https://github.com/niw/KeyboardGuide
A modern, real iOS keyboard system notifications handler framework that Just Works. - niw/KeyboardGuide
😆 1
Avatar
@tarunon なるほどですねScrollViewを敷いておくことのメリットはすごく納得できました! 具体的に、キーボードが出現時、入力部分に被らないようにスクロールさせるの部分は フォーカスされてるtextField及びtextViewの座標とキーボードの高さから どれくらいスクロールさせればいいかを計算して、計算した分scrollViewをスクロールさせるって流れになる認識であってますか・・・?
1:09 PM
@koher コメントありがとうございます! こちらは拝見させて頂いたことあります!ライブラリを使わずに 自分で実装してみようと思ったのですが、いざ実装してみると様々な実装方法があり ベストプラクティス的な物があれば知りたいなと思い質問させて頂いた次第です
🙂 1
Avatar
実際にはKeyboardの表示された領域を計算してその分contentInsetに足す、という作業になるんですが、これは結構大変なので、koherさんの上げてくれたライブラリを使うのが楽かなぁと思います。
1:17 PM
ちなみに、UITableViewController(UICollectionViewControllerもだったかな?)はキーボードに対するinsetを付与する機能が含まれているので、特段何もしなくても期待通りに動作します
Avatar
思った以上に複雑なのですね・・・。 使わせて頂くことを検討してみます!ご回答頂きありがとうございました!
Avatar
それつくったひとですが
3:36 AM
キーボードを正しく扱うのはすごい大変です
3:37 AM
A modern, real iOS keyboard system notifications handler framework that Just Works. - niw/KeyboardGuide
3:38 AM
ベストプラクティスは、これを使うことですね...
👍 2
3:39 AM
という冗談はさておき、状況によるとしか言えないのでなんともです。ScrollViewのinsetを変えるとかが基本ですが、そのinset画面にたいして絶対値になるので、正しく算出するのはかなり大変です。
Avatar
今や Xcode からポチポチっとやれば SwiftPM でライブラリ入れられますから、実務的にはほんとにライブラリ使うのベストプラクティスだと思うんですよね。
Avatar
引き続きalarm-ios-swiftで開発をしていますが、アラームにライブラリの曲を使用する機能の開発で、tableviewに曲が追加されず困っています。 以下の二つを参考にしました。 https://stackoverflow.com/questions/49384705/mpmediapickercontroller-closes-after-startup-swift https://chat.stackoverflow.com/rooms/167182/discussion-between-ppl-and-b2fq
When I click on the cell to open the MPMediaPickerController it opens when it starts up. class MediaViewController: UITableViewController, MPMediaPickerControllerDelegate override func tableView(_
Avatar
コードは以下のようになっています。 MediaViewController.swift import UIKit import MediaPlayer var printnumber: Int = 1 class MediaViewController: UITableViewController, MPMediaPickerControllerDelegate { fileprivate let numberOfRingtones = 3 var mediaItem: MPMediaItem? var mediaLabel: String! var mediaID: String! override func viewDidLoad() { super.viewDidLoad() } override func viewWillDisappear(_ animated: Bool) { //performSegue(withIdentifier: Id.soundUnwindIdentifier, sender: self) } ... func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection:MPMediaItemCollection) -> Void { if !mediaItemCollection.items.isEmpty { let aMediaItem = mediaItemCollection.items[0] self.mediaItem = aMediaItem mediaID = (self.mediaItem?.value(forProperty: MPMediaItemPropertyPersistentID)) as? String self.dismiss(animated: true, completion: nil) } } func mediaPickerDidCancel(_ mediaPicker: MPMediaPickerController) { self.dismiss(animated: true, completion: nil) } } AlarmAddEditViewController.swift @IBAction func unwindFromMediaView(_ segue: UIStoryboardSegue) { let src = segue.source as! MediaViewController segueInfo.mediaLabel = src.mediaLabel segueInfo.mediaID = src.mediaID } (edited)
Avatar
んーこれだけではなんとも... UITabelViewDataSouce で調べてみてください
12:08 PM
あと、なんというか、参考にするのは apple.com が良いと思います。stackoverflow は個人の日記みたいなものなんで... ちょっと嘘が多い。 (edited)
👀 1
👍 1
Avatar
stackoverflowの内容が 「pick a song 押したけどUnbalanced calls to begin/end appearance transitions forが出てきて叶わん、なんとかしてくれ」 「 override func viewWillDisappear(_ animated: Bool) { performSegue(withIdentifier: Id.soundUnwindIdentifier, sender: self)消したら?」 「performSegue(withIdentifier: Id.soundUnwindIdentifier, sender: self)コメントしたらできたわ。ありがとう」 みたいな感じでした。 コメント化したらtableviewに曲が追加されず、func mediaPickerにperformSegue(withIdentifier: Id.soundUnwindIdentifier, sender: self)を追加したら func unwindFromMediaViewのsegueInfo.mediaID = src.mediaIDにnilが出てきた...という感じですね
12:22 PM
もう少し調べてみます
Avatar
MediaViewControllerUITableViewControllerとして作られているので、それ自身がUITableViewDataSourceになっています。
👀 1
12:26 PM
使い方はここの載っていますが、この辺は実装されていると考えていいでしょうか?
12:30 PM
MPMedoaPickerControllerで選択されたMPMediaItemを誰かがUITabelViewCellにしないと結果として表示されません...
👀 1
12:31 PM
その部分が ... で省略されている部分にあるのであればごめんなさい、この指摘は関係がないかも。 (edited)
Avatar
tableviewは大体実装されています mediaviewcontrollerがこんな感じです
12:35 PM
mediaviewcontroller全体がこんな感じになります
12:39 PM
MPMedoaPickerControllerで選択されたMPMediaItemを誰かがUITabelViewCellにしないと結果として表示されません...
@niw 多分それが出来てないかもですね....!
12:41 PM
mediaidをUITabelViewCellにすればいいのかな? (edited)
Avatar
そうですね。tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCellで、なにかしらする必要があります。
👍 1
12:44 PM
この中で表示したいものをcellに設定する感じかと思います。
Avatar
ありがとうございます、やってみますね!
Avatar
titleとかですね。
12:47 PM
mediaIDは多分なんか識別用の内部的なヤツで表示しても意味ないかも。 (edited)
Avatar
var title: String?って override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{} の中でどう書けばいいですかね....? var songTitle: String songTitle = mediaItem!.value( forProperty: MPMediaItemPropertyTitle ) as String とか試してるんですけどうまくいかなくて... (edited)
Avatar
cell.titleLabel.text = mediaItem.title じゃダメですかね
Avatar
こんばんは 私はcallkitを用いて音声通話アプリを作っています。 その上で原因がつかめない現象に遭遇してまして質問させていただきます。 まず、遭遇している原因までの実行手順を説明させてください。 • 実行手順 1, iPhoneの電源をoffにする 2, iPhoneの電源をonにする 3, 端末がオンラインになったタイミングで別端末から電源on/offにした端末に対して発信処理をします。 4, 着信側の端末がvoip pushを受信して Callkit UI(端末非ロックバージョン)を表示します。 5, 拒否ボタンをタップします。 ここまでが実行手順です。 その上で その拒否ボタンタップ時に実行されるデリゲートメソッド内で URLSessionを用いてAPI通信して いるのですがrequestが必ずタイムアウトしてしまいます。 電源onにしてからの初回起動直後に起きます。それ以外では起きません。 また、iOS12で同様の操作手順を実行しましたがrequestがタイムアウトになることはありませんでした。 OS差があることまでは特定出来ているのですが原因が掴みきれていません。 iOS13.5.1とiOS12.3ではURLSession周りでの仕様変更などありましたでしょうか?
Avatar
iOS 13では必ずvoip pushは同期的にreportNewIncomingCallなどを呼び出しコール画面を表示するのみに使いそれ以外の用途に使用できなくなっています 日本語の資料としてはここに詳しく書かれていました(Appleの公式ドキュメントもqiitaの方を参考にしてみてください https://qiita.com/sunskysoft/items/34665541d9bec438ee36
注意:この記事はAppleのドキュメントを参照して書きました。実際に実装していないので間違いがあるかもしれません。 VoIP Push は CallKit とともに!(iOS13) iOS 13 SDK でビルドしたアプリを i...
2:48 PM
なんでこうした措置がとたれたかはここに書いてあります https://japanese.engadget.com/2019/08/06/ios-13-voip-whatsapp-fb-messenger/
iOS 13では、アプリによるバックグラウンドでのVoIP(Vioce over Internet Protocol)が使えなくなります。たとえばこの機能を利用しているFacebookのMessengerやWhatsAppといったアプリに影響が出ることが予想されます。 米ニュースメディアThe Informati...
Avatar
ありがとうございます。 ですが、本件はvoip pushは正常に受信できており、reportNewIncomingCallをコールし、コール画面(callkit ui)を表示したあとに起きる現象についての質問です。
Avatar
なるほど。拒否ボタンを押した時の挙動なのですね。 iOS 12, 13のCallKit周りの変更だとvoip pushでバックグラウンド周りの規制が強くなったのでその影響かと思いましたが違うかもですね。 電源on直後かそうでないかではなく、フォアグラウンドでのvoip受けた時はAPI通信できてバックグラウンドでvoip push受けた時はAPI通信できないのであればドキュメント通りな気はします。 自分が開発した時はバックグラウンドでvoip push受けた時に裏でアプリが生きている状態か死んでいる状態かで違ってくるとかあった気もしなくもないですが具体的なことは忘れてしましました 🙇‍♂️ (edited)
Avatar
電源on直後(ネットワークは繋がってる状態)のアプリがkill status時にこの問題が起きておりまして、、 それ以降のkill status, foreground,backgroundでは再現しなくて悩んでおります。 😓
Avatar
質問です。 EnvironmentObjectで作成した配列をForm内のPickerで選択できるようにしたいのですが、動作がうまくいきません。 シミュレータで動かそうとすると、エラーが起きてしまいます。 エラー文 '''Thread 1: Fatal error: No ObservableObject of type HistoryEntity found. A View.environmentObject(_:) for HistoryEntity may be missing as an ancestor of this view.''' コード //Data.swift import SwiftUI import Combine class HistoryEntity: ObservableObject{ @Published var UserName:[String] = [] } //AddView.swift @EnvironmentObject var histroy: HistoryEntity var body: some View { NavigationView { Form { Picker(selection: $Selection, label: Text("name")) { ForEach(0..<histroy.UserName.count){ Text(self.histroy.UserName[$0]) } } } } (edited)
Avatar
Kishikawa Katsumi 7/9/2020 6:45 AM
histroy: HistoryEntity を渡してないと思います。 使ってる方のコード、SceneDelegate.swiftのコードを載せてください。
Avatar
let contentView = ContentView().environmentObject(HistoryEntity())
6:46 AM
書き忘れてました。。
6:49 AM
すみません。「使っている方のコード」というのは、どういった意味でしょうか。
Avatar
Kishikawa Katsumi 7/9/2020 6:50 AM
let contentView = ContentView().environmentObject(HistoryEntity())
この部分の話です。 ContentViewはどれですか?
Avatar
ContentViewの2つ下の階層にAddViewを作成しました (edited)
Avatar
Kishikawa Katsumi 7/9/2020 7:00 AM
コードを載せてください。
Avatar
omochimetaru 7/9/2020 7:06 AM
シミュレータで動かそうとすると
Preview Canvasの事?それともiPhone simulatorの事?実機では動くんですか?
(edited)
Avatar
//ContentView.seift struct ContentView: View { @EnvironmentObject var histroy: HistoryEntity var body: some View { NavigationView { List { ForEach(histroy.UserName, id: \.self){ user in NavigationLink(destination: HistoryView(name: user)){ Text(user) } } } } //HistroyView.swift struct HistoryView: View { @State private var isShowingSheet: Bool = false var name: String = "" var body: some View { List { VStack { Text("") } NavigationLink(destination: DetailsView()) { HistroyRowView() } .navigationBarTitle(name) .navigationBarItems(trailing:HStack { Button(action: { self.isShowingSheet = true }) { Text("") } .sheet(isPresented: $isShowingSheet){ AddView(isShowingSheet: self.$isShowingSheet) } } } }
7:10 AM
iPhone simulatorの方です
7:10 AM
実機では試せていません。
Avatar
omochimetaru 7/9/2020 7:13 AM
なるほど。Preview用のコードの方で.environmentObjectを忘れてるのかなと予想したんですが違いました。一見正しそうです、どこが間違っているのかわからなかった。
Avatar
「Form内でPickerを使うと画面遷移されるので、その遷移先ではEnvironmentObjectの値を取得できない」みたいなことって起きますか?
Avatar
Kishikawa Katsumi 7/9/2020 7:18 AM
Thread 1: Fatal error: No ObservableObject of type HistoryEntity found. A View.environmentObject(_:) for HistoryEntity may be missing as an ancestor of this view.''' これはどこで起こってるんですか?
Avatar
ForEach(0..<histroy.UserName.count){ ←この行に表示されています (edited)
Avatar
Kishikawa Katsumi 7/9/2020 7:25 AM
起動して初期表示はうまくいくけど、何か操作をしてそのあとでクラッシュする、ということで合ってますか?
Avatar
初期起動は問題なく、このボタンを押してAddViewを表示しようとするとクラッシュします Button(action: { self.isShowingSheet = true })
Avatar
Kishikawa Katsumi 7/9/2020 7:34 AM
AddViewにenvironmentObjectを渡してないからじゃないですか?
Avatar
//AddView.swift @EnvironmentObject var histroy: HistoryEntity これでは渡せていないということでしょうか
Avatar
Kishikawa Katsumi 7/9/2020 7:38 AM
それはEnvironmentObjectを受け取れるという意味ですね。 渡す、というのは let contentView = ContentView().environmentObject(HistoryEntity()) ContentViewに渡してるようなこういうenvironmentObjectのModifierを使ってる部分です。
Avatar
EnvironmentObject って自動的に共有されるんじゃないですっけ?
7:46 AM
SwiftUI was built from the ground up to let you write beautiful and correct user interfaces free of inconsistencies. Learn how to connect...
7:47 AM
(僕はいつも @ObservedObject 使ってるのであまり自信ないですが)
7:49 AM
もし実行可能な状態でコードを共有可能なら、共有してもらった方が早そうな気がします( .xcodeproj 含めて丸ごと GitHub に push とか)。
Avatar
https://github.com/KentaMaeda0916/FormInPicker GitHubを初めて使うので正しくできているかわかりませんが、これでいいのでしょうか。
EnvironmentObjectで作成した配列をForm内のPickerで選択できるようにしたいのですが、動作がうまくいきません。 - KentaMaeda0916/FormInPicker
Avatar
I'm building an app with SwiftUI. When I was trying to display a sheet (previously Modal), this error message appears: Thread 1: Fatal error: No observable object of type
8:22 AM
sheetはEnvironmentObjectを共有していないみたいですね。
8:23 AM
これが仕様なのかバグなのかわかりませんが…
Avatar
Kishikawa Katsumi 7/9/2020 8:26 AM
AddView(isShowingSheet: self.$isShowingSheet).environmentObject(self.histroy) なのでこう書くとまあ解決します。 サブビューなら伝播してくれるんですけど、sheetは別のビュー階層扱いなんでしょうね。
Avatar
ほんとですね。こちらでも同様でした。
8:30 AM
NavigationLink は大丈夫なのに .sheet はダメなんですね・・・。
Avatar
``` AddView(isShowingSheet: self.$isShowingSheet).environmentObject(self.histroy) ``` なのでこう書くとまあ解決します。 サブビューなら伝播してくれるんですけど、sheetは別のビュー階層扱いなんでしょうね。
@Kishikawa Katsumi
8:32 AM
これを追加したら解決しました!
8:32 AM
本当にありがとうございました!
🙌 1
Avatar
API 的にも、 NavigationLink は引数に渡すからつながってるけど、 .sheet はクロージャだから途切れてるのか。
Avatar
Kishikawa Katsumi 7/9/2020 8:34 AM
去年のWWDCでゆってたかもしれない。
Avatar
ところで、この HistoryEntityAddView から先で使わないなら、 AddView@EnvironmentObject じゃなくて @ObservedObject で持ってもいいかもしれませんね。
8:47 AM
struct AddView: View { @ObservedObject var histroy: HistoryEntity ... } Text("追加") } .sheet(isPresented: $isShowingSheet){ AddView(histroy: self.histroy, isShowingSheet: self.$isShowingSheet) }})
8:48 AM
histroyhistory の typo だと思いますが元のままにしてます・・・)
Avatar
誤字指摘ありがとうございます
9:05 AM
私の勉強不足で恐縮なのですが、@EnvironmentObject ではなく@ObservedObject を採用する意図はなにかあるのでしょうか
Avatar
@EnvironmentObject は複数の View の間で広く(暗黙的に)共有するためのもので、 @ObservedObject は必要なときに明示的に渡すものです。この場合、 .sheet@EnvironmentObject が途切れてしまうようなので、 AddView にだけ渡すのであれば @ObservedObject で十分かなと思いました。 AddView から先でも広く共有したい種類のものであれば @EnvironmentObject が良いと思います。
9:14 AM
@EnvironmentObject だからといって大きな不利益があるわけではないですが、必要なものは必要最小限のスコープで狭く使っておいた方が管理が簡単だと思うので、 @EnvironmentObject である必要がないのであれば @ObservedObject でもいいのかなと思いました。 (edited)
Avatar
なるほど。共有は必要最小限の範囲であるほうがいいということですね。 ありがとうございます!
🙂 1
Avatar
質問させてください。 SwiftUIでCoreDataに["A","B","C"]のような文字配列を保存したいのですが、やり方がわかりません。 一応解答らしき記事を見つけはしたのですが、なかなか解読できずにいます。 https://stackoverflow.com/questions/29825604/how-to-save-array-to-coredata 「If keeping it simple and store an array as a string」あたりだと思うのですが、 ・このコードをどこに書けばいいのか ・「xcdatamodel」でどの型を宣言すればいいのか 教えていただけると助かります。
I need to save my array to Core Data. let array = [8, 17.7, 18, 21, 0, 0, 34] The values inside that array, and the number of values are variable. 1. What do I declare inside my NSManagedObject...
Avatar
実際にproductionコードで使ったことは無いですが、こんな感じで Transformable 型の attribute を追加して、Custom Class に [Int] など指定すれば動きましたー
Avatar
あとはコードで file.foo = [1,2,3,4] みたいな感じで書けます
Avatar
String型の配列を保存したいので[String]を指定してみましたが、エラーが出てしまいました。。
Avatar
SwiftUIの練習がてらCoreDataで [String]を使ったサンプルアプリを作ってみました。 (edited)
3:37 PM
Contribute to kenmaz/SwiftUISamples development by creating an account on GitHub.
👍 1
Avatar
やりたいことに非常に近い形なのでとても参考になります! ありがとうございます!!
👏 1
Avatar
swiftの配列(Array)について質問させてください。 配列が確保するメモリザイスの初期値を設定する方法がわかりません。 c#では var capacity = 10; var a = new List<int>(capacity); の様なもののことです。 よろしくお願いします。
Avatar
@swift-5.2.5 var items: [Int] = [] items.reserveCapacity(10)
👍 1
Avatar
no output
Avatar
@ryota2357 こうですかね (edited)
Avatar
返信遅くなりました。すみません ありがとうございます!助かりました! (edited)
😆 1
Avatar
cocoapodsについて質問させてください。 https://github.com/tarunon/Instantiate こちらのGItをインストールしたのですが、画像のようなエラーが出てしまいます。対策方法を2時間ほど調べたのですが、見つけきれませんでした。同じパッケージで片方使えて、片方が使えないというのはあるのでしょうか。
Type-safe and constructor injectable InterfaceBuilder protocols. - tarunon/Instantiate
👀 1
2:19 PM
Avatar
これ pod 'InstantiateStandard' もいるかな?
2:25 PM
ワシじゃん
Avatar
もしかしてそもそもいらないものでしたか? Qitaの記事ではどちらもあったんで、ないとだめなものかと。。
Avatar
含まれてる関数を使わないのであれば、入れなくても大丈夫です
2:31 PM
何入ってたかな。些細なものだったと思うのでご自身で定義されても問題ない範囲かと
Avatar
なるほどです!InstantiateStandardの方をなしでもできる方法を探してみます!
2:33 PM
ありがとうございました!
Avatar
SwiftUIでFSCalendarを使おうとしていますが、動作がうまくいきません。 カレンダーの日付を選択したときの動作であるprint("selected")が出力されないので悩んでいます。 UIkit側のイベントをSwiftUIが受け取れていないことが原因だと思いますが、解決策はありませんでしょうか。 import SwiftUI import FSCalendar import UIKit class ViewController: UIViewController, FSCalendarDelegate, FSCalendarDataSource{ @IBOutlet var calender: FSCalendar! override func viewDidLoad() { super.viewDidLoad() calender.delegate = self } func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { print("selected") } } struct UICalender: UIViewRepresentable { func makeUIView(context: Context) -> FSCalendar { return FSCalendar() } func updateUIView(_ uiView: FSCalendar, context: Context) { } } struct CalenderView: View { var body: some View{ UICalender() } } struct CalenderView_Previews: PreviewProvider { static var previews: some View { CalenderView() } }
Avatar
もうちょっと丁寧に回答すると、ViewControllerのオブジェクトを生成出来ていないのが原因です。 UICalenderに宣言されているFSCalendar()はこの行で初めて作られるオブジェクトなので、ViewControllerに宣言されている @IBOutlet var calender: FSCalendar! とは別のインスタンスであり、したがってdelegateはどこにも登録されていません。 ViewControllerのprintを呼び出したいのであれば、UIViewControllerRepresentableを利用し、そこでUIStoryboardからViewControllerのインスタンスを生成して返す必要があります。
Avatar
https://qiita.com/giiiita/items/b2588a78cfda4ecef345 この記事を参考に import Instantiate struct ViewControllerWrapper : UIViewControllerRepresentable { typealias UIViewControllerType = ViewController func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerWrapper>) -> ViewControllerWrapper.UIViewControllerType { return UIViewControllerType.instantiate() } func updateUIViewController(_ uiViewController: ViewControllerWrapper.UIViewControllerType, context: UIViewControllerRepresentableContext<ViewControllerWrapper>) { } } こちらを追加してみたのですが、Instantiate()に対して「Type 'ViewControllerWrapper.UIViewControllerType' (aka 'ViewController') has no member 'instantiate'」というエラーが出てしまいます、、
このはじめに SwiftUIからViewControllerを表示する時のTipsです。 ViewControllerとStoryboard 記事用に作成したViewControllerとStoryboardになります。 ...
Avatar
ViewControllerはStoryboardInstantiatableに適合していますか? 例えば extension ViewController: StoryboardInstantiatable {} の宣言が存在していないのでは
Avatar
https://qiita.com/usagimaru/items/3a32ee63d9e331c98da9 この記事を参考に extension ViewController: StoryboardInstantiatable{ typealias StoryboardInstantiatableViewController = ViewController static var storyboardName: String { return "Main" } } を追加してみましたが、printは動作しないままでした、、
StoryboardからViewControllerのインスタンスを得る仕組みとして <#クラス#>.fromStoryboard() という共通のAPIにまとめてみました。 macOS NSViewControl...
👀 1
Avatar
色んな所にprint文仕込んでみて、どこが動いてないか特定してみては
Avatar
var body: some View{ UICalender() }var body: some View{ ViewControllerWrapper() } に変更したら理想の動作になりました! 何度も質問に答えていただきありがとうございました!貴重なお時間を割いていただき、ありがとうございました!
👍 2
Avatar
やりたいことに非常に近い形なのでとても参考になります! ありがとうございます!!
@maeken な@うたkateinoigakukun#2184> swiftの配列(Array)について質問させてください。
配列が確保するメモリザイスの初期値を設定する方法がわかりません。 c#では var capacity = 10; var a = new List<int>(capacity); の様なもののことです。 よろしくお願いします。
@ryota2357 @Yuta Saito
Avatar
@4ske https://stackoverflow.com/questions/24124417/swift-init-array-with-capacity この記事あたりが参考になるのではないでしょうか。
How do I initialize an Array in swift with a specific capacity? I've tried: var grid = Array <Square> () grid.reserveCapacity(16) but get the error expected declaration
6:39 AM
FSClarendarで日付を選択したときに、その日付に保存してあるDouble型のデータを呼び出したいのですがうまくいきません。NSPredicateが使えそうなのはわかったのですが使い方がよくわかりません。。 (edited)
6:40 AM
教えていただけないでしょうか。
Avatar
これって FSCalendar は関係なくて、 Core Data に保存されたデータを Date で検索して取得したいという話ではないですか? (edited)
Avatar
すみません。余計なとこまで書いてしまったみたいですね。まさにその動作を実装したいです。
Avatar
僕は Core Data を使ったことがないですが、何かの値をキーにして検索するというのはごく基本的な操作ですので、 Core Data の使い方を検索すればすぐに情報が出てきそうに思います。 FSCalendar と組み合わせて検索すると一気に情報が減るでしょうが、 Core Data 単独であればいくらでもありそうかと。
8:42 AM
簡単なユーザーデータを保存したりするにはUserDefaultsを使う方法もありますが、保存する項目が増えたときには扱いが面倒になることがあります。 Core Dataで保存しておけば、強力な機能が使えるのでよさげ。 おおもとのドキ...
Avatar
あ、 Date は年月日じゃなくて秒とかのもっと細かい情報を持っているので、同一年月日だとしてもデータが一致するとは限らないので注意が必要です。
8:52 AM
僕はそういう場合は年月日の文字列(たとえば "2020-08-11" とか)を保存するようにして、文字列で検索しますね。 Core Data でやったことはないので、 Core Data で何か良い方法があるかもしれませんが。
8:52 AM
ただ、 Time Zone とかをよく考えて設計しないと後々問題を引き起こすかもしれません。
8:54 AM
同じ時刻でもタイムゾーン(たとえば日本かアメリカ西海岸か)によって日付が異なることはありますし、カレンダーからの日付の検索というのをどのような仕様とするのか考えておかないと、想定外の挙動を引き起こしてしまうかもしれません。
Avatar
回答ありがとうございます! 記事を参考にやってみたのですが、不明な点があります。。。 ・return[]の行に「Will never be executed」と出ます。 ・fetchEmployees()を使いたいのですが、 DataController.fetchRecordEntity() の()内に何を入力すればいいかわかりません。エディタには(self:DataController)と表示されます。
Avatar
employee はこの Qiita の記事の例なので、まえけんさんのコードでは別の型になりますよね?
10:32 AM
DataController.fetchRecordEntity() はクラスメソッドを呼び出してしまっているので、 DataContorller のインスタンスを生成してインスタンスメソッドを呼び出す必要があるように見えます。(ただし、 Core Data を満足に使ったことがないのでわかってないですが)
10:34 AM
「Will never be executed」と出ます。
これは、その行に到達し得ないようなコードになっているから出ている警告です。それ以前の分岐などで、 return [] まで到達できないコードになっているのではないでしょうか?
Avatar
私の理解力が不十分なので、解決策にたどり着けません。。
Avatar
おそらく、一つ一つの要素に分解して、順を追って理解しないと、いきなり組み合わせられたものの意味を理解するのは難しいと思います。
11:10 AM
DataController.fetchRecordEntity() 一つにしても、インスタンスとクラスの関係がわかっていないと理解が難しいですし、
11:11 AM
「Will never be executed」と出ます。
にしても、どういう状況でその警告が出るのかを理解して、今書いたコードを照らし合わせて何が問題なのかを考えないといけないです。
11:12 AM
コードを書いていて直面する問題というのは、世界で一つだけの自分だけの組み合わせによる問題なので、それがそのまま当てはまる状況を調べようとしても、なかなかそのものは検索してもヒットしません。
11:14 AM
要素に分解して、それらをどう組み合わせてコードが動いているのかを考えて問題にアプローチしないと、なかなか難しいように思います。
Avatar
自分の理解度の低さをわきまえず、質問ばかりしてすみませんでした。1つ1つ分解して考え、1つずつでも理解していけるように地道に勉強していこうと思います。
Avatar
本人じゃないのでエスパーになってしまうんですが、オブジェクト指向プログラミングの一番基礎的な部分に引っ掛かりがあって理解を妨げているのでは?と思います。 オブジェクトとクラスの関係、関数内におけるコンテキストとか、オブジェクト指向プログラミングのメンタルモデルに対する理解を深めると近道になるかも。
Avatar
いえ、質問していただいて大丈夫なんですが、今起こっている問題を丸ごと理解しようとしたときに、分解しないと難しそうだなと思いましたということでした💦
Avatar
オブジェクト思考の基礎となるとswiftの教材は中々見つからないのですが、遠回りになるんですが CSの学部の大学の授業とかは見れるものが結構あると思うので、それらに手を出してみるのもいいかもですね。
Avatar
最近、オブジェクト指向プログラミング1について説明する機会が多く、これからもっと多くなりそうなので、文章にまとめることにしました。 オブジェクト指向とは何かという説明はたくさんありますが、 何のためにオブジェクト指向プログラミングが...
Avatar
ここは何を質問していただいても大丈夫なチャンネルなので遠慮なく質問していただければと思うのですが、色んな問題が絡まっていて、一つずつ理解していかないと何が起こっているのかを理解するのが難しそうだと感じたので↑のような回答になりました。質問しづらいように感じられたらすみません。
Avatar
@tarunon おっしゃるとおりオブジェクト指向の基礎がまだまだ曖昧な自覚があります。。。。まずは基礎を理解することから始めようと思います! @koher いろんなことが絡んだ問題を丸投げしたような形になってしまいすみませんでした。またどうしても躓いたときに、知恵を貸していただけると助かります! @omochimetaru 記事リンクありがとうございます!すぐに読みます! (edited)
🙂 3
Avatar
omochimetaruが貼ってくれたその記事は僕が書いたものなで、質問してもらえれば答えられると思います。
Avatar
Core Data の記事のコードですが、たしかにこれだと will never be executed の警告が出そうですね。 func fetchEmployees() -> [EmployeeMO] { let context = persistentContainer.viewContext let employeesFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Employee") do { let fetchedEmployees = try context.fetch(employeesFetch) as! [EmployeeMO] return fetchedEmployees } catch { fatalError("Failed to fetch employees: \(error)") } return [] }
2:02 PM
理由は、この関数は return fetchedEmployeesfatalError("Failed to fetch employees: \(error)") で必ず終了するからです。
2:03 PM
try context.fetch(employeesFetch)try がマークされているので、ここでエラーが発生したときに catch 節に入るということがわかります。なので、エラーが発生しなければ return fetchedEmployees 、発生したら fatalError("Failed to fetch employees: \(error)")fetchEmployees() は終了します。
2:04 PM
そのため、 return [] が実行されることはなく、コンパイラが will never be executed (決して実行されることがない)と警告しているのです。
2:05 PM
ちょっとこれは、この記事のコードが信頼できるレベルかあやしいですね・・・。貼った記事が良くなかったかもしれません。
2:05 PM
本当は Apple の公式ドキュメント https://developer.apple.com/documentation/coredata を見るのがいいのですが、
2:07 PM
結構断片的で、ざっとみた限りでは基本的なクエリと fetch について書かれている箇所を発見できませんでした。
2:12 PM
ただ、 tarunon さんの言うように、
  • オブジェクト指向の基礎
を身に付けることも必要ですし、↑のコードを理解するには
  • Swift の基本構文や標準ライブラリの基礎(たとえば、↑のコードの tryas! の意味は? fatalError で何が起こる? fatalError の戻り値の型の Never とは?どういうケースで will never be executed の警告が出るか)
  • Core Data の基礎
  • NSPredicate (これ自体は Core Data とは独立に Foundation に存在します)
についての知識も必要になります。
2:16 PM
さらに、 @maeken さんの最初のコードでは SwiftUI と UIKit のコードが混ざっており、 UIKit 側に SwiftUI の @Environment などが用いられているのですが、おそらく何かのコードをみようみまねで書いたのだと思いますが、それらについてどう書くべきかを理解するには SwiftUI について学ぶ必要がありますし、そのためには Property Wrapper や Combine の理解も必要になります。
2:17 PM
それらを一歩一歩分解して理解していくことは、遠回りに見えるかもしれませんが、近道じゃないかと僕は思います。
2:19 PM
僕個人の意見としては、とりあえず最初は SwiftUI を使わずに UIKit で書いた方が理解しやすいと思います。 SwiftUI は Swift の高度な機能が色々使われていて、真に理解するのはとてもむずかしいので。僕もよくわからないことがたくさんあります。
Avatar
@koher とても丁寧な回答ありがとうございます。 ・オブジェクト指向や基本構文等の基礎が固まっていないこと ・SwiftUIは出てきたばかりで参考記事が非常に少ないため初心者には厳しいこと は、重々承知しています。なのでまずは基本からすこしずつでも理解して行こうと思います。 貴重なアドバイスありがとうございます!
🙂 1
Avatar
上から(アプリ制作)攻めるのと、下から(そもそもどうしてSwiftは動くのか? っていうか、CPUとは...?)理解するのはどちらも大切です
5:01 AM
幅の広げ方が一方行だとどこかでキビしくなるんですよね。
5:02 AM
したすぎると流石に辛いけど、OOPとかいろいろ知ってると楽しいし、わかる感が広がって良いと思います。
Avatar
Carthageのようにframeworkをzipで固めて配布するっていうのをcocoapodsでしたいのですが、やったことある人いますか?
6:18 AM
もしくはやってるライブラリご存知であれば知りたいです
Avatar
Kishikawa Katsumi 8/15/2020 9:00 AM
Realmでやってましたよ。Realmの場合は.aだったのでvendored_libraryに指定しています。 Frameworkはvendored_frameworksっていうのに指定したらいいはず。
Avatar
ありがとうございます!参考にしてみます
Avatar
Kishikawa Katsumi 8/15/2020 1:07 PM
ただビルド済みのフレームワークを配布するだけならリポジトリに含めてしまうとパスを指定するだけで簡単。 ビルドに必要な依存関係だったらスクリプトを実行できる手段があるのでそれでダウンロードするなども可能。
Avatar
これってアンチパターンでしょうか? class Interactor { var name: String init(name: String) { self.name = name } } class FirstPresenter { var interactor: Interactor init(interactor: Interactor) { self.interactor = interactor } } class SecondPresenter { var interactor: Interactor init(interactor: Interactor) { self.interactor = interactor } } // メイン処理 let interactor = Interactor(name:"aaa") let firstPresenter = FirstPresenter(interactor: interactor) let secondPresenter = SecondPresenter(interactor: interactor) print(firstPresenter.interactor.name) // aaa print(secondPresenter.interactor.name) // aaa firstPresenter.interactor.name = "bbb" print(firstPresenter.interactor.name) // bbb print(secondPresenter.interactor.name) // bbb secondPresenterからすると、自身の知らないところでinteractorが更新されてて困るケースがあるというのは理解できます。 一方で、複数のPresenterで同じInteractorを共有したい場合は有用かなとも思ったのですが、皆さんはどうやって実現されているのでしょうか?
Avatar
複数のPresenterで同じInteractorを共有したい場合は有用かな
どんな時に、同じInteractorを共有したい感じでしょうか?🤔
5:17 AM
Interactor がどういう位置付けなのかがぱっとわからなかったのですが、あるデータだとしたら、Interactor自体を共有するのではなくって、Interactorを取得する構造体 (僕はよく HogeFugaDataStore とかの名前にします)にするのでも良いのかなと思いました! 投稿が初めてでして、不明点等あったら突っ込んでいただけると助かります! (edited)
Avatar
複数のPresenterで同じInteractorを共有したい場合
これ自体はよくあることなように思います。 VIPER 的にはプロトコルを挟むのが普通なのかもしれませんが。
5:38 AM
自身の知らないところでinteractorが更新されてて困るケース
これは、 FirstPresenter からの入力による変更によって SecondPresenter が何かを View に出力しなければならないのであれば、それが Interactor から SecondPresenter に通知される必要があるのではないでしょうか。
5:42 AM
それは InteractorOutput のメソッドを呼ぶような形かもしれませんし、 name が直接出力に使われるのであれば(たとえば Combine を使うなら) namePublisher にしておいてそれを購読するとか、もしくは Interactor 自体を ObservableObject にするとか、色々な方法があると思います。
Avatar
Interactor がどういう位置付けなのかがぱっとわからなかったのですが、あるデータだとしたら、Interactor自体を共有するのではなくって、Interactorを取得する構造体 (僕はよく HogeFugaDataStore とかの名前にします)にするのでも良いのかなと思いました!
上記発言、申し訳ありません僕の不勉強でした。 もう一度勉強してきます... 🙇
(edited)
Avatar
@h1d3mun3 僕も VIPER よくわかってないですし、色んな方の意見が得られるのは良いことかと思います🙂
🙂 1
Avatar
@h1d3mun3 ご意見ありがとうございます。 例が悪かったです。申し訳ないです。 やりたかったのは、特定のクラスのプロパティに保存された値を複数のPresenterで共有したい、ということでした。なので、別にInteractorじゃなくてもいいです。 FluxでいうStoreって、1つのシングルトンで管理された状態を複数のコンポーネントで共有する仕組みだと思いますが、あれを特定のPresenterでだけで使いたいってイメージです。
🙆‍♂️ 1
😄 1
Avatar
@koher 複数のPresenterから同一インスタンスの参照をもつこと自体はアンチパターンではなくて、もし変更されて困る場合は、それを検知できる仕組みを用意しなさい、ってことですね。 ただ、それって他のPresenterからも変更されることを知っていれば可能なんですが、知らなかったらやらないので、そもそもそういう構造にすべきではないのかな、と思いました。
6:17 AM
上図によると PresenterInteractor を保持するようですし(上記ページによるとプロトコルを介するのが普通なのかもしれませんが)、 Interactor は一つの View に紐づくわけではないですよね?そうすると複数の PresenterInteractor を共有してもおかしくないと思います。
6:19 AM
PresenterInteractor からの通知を受けて、それを View に適した形に変換して通知するものだと思うので、 Presenter からの入力(上図の asks for updates )を受けて Interactor が更新されたときに、必要に応じて InteractorPresenter に更新を通知する必要があると思います。
6:22 AM
Interactor から Presenter への通知については、 VIPER が Clean Architecture の派生であることから推測すると、依存の方向は View → Presenter → Interactor → Entity で Interactor は Presenter を知らないので、 DI を使うなどして、 Interactor が Presenter を知らなくても Presenter に通知を送ることのできる仕組みが必要かと思います。
Avatar
VIPERでやるという前提であれば、複数のPresenterがInteractorを共有するので、PresenterはInteractorの変更を検知できるような実装をしないとダメってことですね。納得です。 ありがとうございました!
🙂 1
Avatar
有識者の意見も聞きたいところですが、僕はそうかなと思います。
😊 1
Avatar
QRコードを読み取り,特定のワードを検出したら別のViewControllerに移動するということをしたく,様々なサイトを見て作成したのですがアプリ起動時に強制終了してしまいました。ビルド時には特にエラーが出ませんでした。原因の部分を教えください。
Avatar
-[x] info.plistにアクセス許可の設定はしてある -[ ] AVCaptureDevice.authorizationStatusは呼び出してある (edited)
Avatar
ソースコードを添付させていただきます
7:49 AM
5.43 KB
Avatar
全てのコード含まれてるか良くわかんないんですけど、少なくともこのコードの中ではauthorizationStatusは呼んでないですね
7:54 AM
あーAVCaptureDevice.requestAccessも必要だった
Avatar
アプリ起動時にクラッシュしているので、最初に処理しているMainViewController はどうなってるでしょうか?
Avatar
えっとInfo.plistに (edited)
7:55 AM
カメラ許可する画面にでる文書をいれておかないと
7:55 AM
Crashします
7:55 AM
なんだっけ、NSなんとかCameraDescriptionみたいなキー
Avatar
そこは設定済みらしいです
Avatar
なるほど
Avatar
PCが勉強会中継設定のままで間違えて書き込みがち
kusa 1
7:56 AM
まーでも無言クラッシュは権限周りの問題だよなという気はするので
7:56 AM
後は有り得るとしたらrequestAccess呼んでないんじゃないかなと思うんですよね (edited)
Avatar
コンソールに何が出てるか読めば良い気がするけれど...
7:57 AM
それがないとなんとも言えない感はある
Avatar
自分は、Projectの最初の呼び出されるStoryboard or ViewControllerが存在しないもののパターンかなと思ったけど、その場合エラーとかでたっけかね
8:00 AM
クラッシュしているので少なくともコンソールに何かしら情報出てると思うので、それ欲しいですね
Avatar
ですね。。
Avatar
MacとiPadを接続した状態で実機テストができず,コンソールから情報を取得できない状態です;;;すみません (edited)
Avatar
iPadで起動できるようになってないとか...
Avatar
Kishikawa Katsumi 8/27/2020 8:03 AM
プロジェクトを丸ごと共有してもらうのが一番早く解決できると思いますよ @WKWK
Avatar
アドバイスありがとうございます 個人情報等を隠した状態に変更しプロジェクトをアップロードさせていただきます
8:08 AM
あもしかしたら原因が分かったかもしれません
8:09 AM
プロジェクトのUITestsファイルの方のInfo.plistを設定してたのですがプロジェクト直下の方を設定しないといけないのでしょうか
Avatar
それはそうですね
Avatar
ありがとうございます
8:11 AM
原因が理解できました ご回答いただいた方々ありがとうございました 🙏
👏 1
👍 1
rtaGl 1
Avatar
昨日質問させて頂いた件でInfo.plistを変更した後起動しても前回と同様,落ちてしまいました。いろいろ改良してみたのですがダメでした;; プロジェクト自体をアップロードさせていただきますのでご確認いただけますと幸いです。
Avatar
別に他意はないけれど、例のvlunarabilityのあとはxcodepojを気軽にひらけなくてわりと気を遣う...
7:12 AM
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x105a060c0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key videoPreview.' terminating with uncaught exception of type NSException
7:15 AM
storyboardで
7:15 AM
指定するclassがViewControllerになってるけれど、実際は名前をQRcodeViewControllerに変えてるからそれが問題 (edited)
7:16 AM
7:16 AM
ここを変えてください
Avatar
了解です 本当にありがとうございます!
Avatar
ファイル名がViewController.swiftのままだし、一致する必要はないけれど、名前がいろいろあるとややこしいので整理したほうがいいと思います。あと関係ないけれど、インデントも... swiftlint とかかけると幸せになるかも。
Avatar
ファイルの整理もしたいと思います swiftlint学習して幸せになります()
Avatar
https://github.com/realm/SwiftLint これですねちなみに。自動でソースコードフォーマットしてスタイルを維持できます。
A tool to enforce Swift style and conventions. Contribute to realm/SwiftLint development by creating an account on GitHub.
Avatar
ありがとうございます
Avatar
初質問失礼します。 xcodeのアセットカタログで、アプリ内で使う画像をフリーサイトからDLして登録しようとしているのですが、いくつかの画像が『the file "○○.png"for the image set "○○"does not exist.』となって使えない状態になってしまいます。 全て同じサイトから同じサイズで取ってきてるものなのですが、原因としては何が考えられますでしょうか...。 https://icooon-mono.com/12563-%e3%82%ab%e3%83%ac%e3%83%b3%e3%83%80%e3%83%bc%e3%81%ae%e3%83%95%e3%83%aa%e3%83%bc%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b316/
Avatar
ファイル名かイメージ名の指定に誤りがあるような気がしますが、エラーってどこに表示されますか?
Avatar
このような感じです。。。
Avatar
@あきと 1x 2x 3x のところに画像をD&Dしてあげれば、本来でないです。 D&Dしてセットしたあとに画像のファイル名変更等するとその警告はでるので、ファイル名変更するなら変更後にD&Dするといいかと。
Avatar
丁寧にありがとうございます。実は他の画像も2x,3x埋めてないのもあるんです、、。ファイル名もD&Dしてからは弄ってないんですよね。 D&Dした後に弄ってはいけない事は知らなかったです、、勉強になりました。
Avatar
ひとまず設定が上手くできていないUnsigned の画像は選択してdeleteでいいと思います。 それでこの警告自体はきえるかと。
11:12 AM
D&Dした後に弄ってはいけない事は知らなかったです、、勉強になりました。
弄る場合は同じフォルダにあるjsonファイルの中身も書き換えてやる必要があります。 jsonファイルでそこらへんは管理されているので
Avatar
@ありぜ わかりました、本当にありがとうございます( .. ) (edited)
Avatar
pngだとラスター形式なので3種類画像埋めることになるんですが、ベクター形式(pdf)なら、single scaleにする事も出来ます
11:20 AM
見た感じai/eps形式もダウンロード出来るみたいなので、pdfに変換とかすれば楽が出来るかも
sorena 1
Avatar
ニュアンス違った風に伝わってそうだったので、こんな感じにでやってみたらいいかと。
11:24 AM
ちなみに同じ画像をDLして空のプロジェクトで設定して特に問題もなかったので、画像自体に問題はないです。
Avatar
@ありぜ 上手くいきました。ggってもなかなか解決できずにいてモヤモヤしていたので、ありがたいです。
👍 1
11:32 AM
@tarunon アプリアイコンはmeke appicon等を使って全て埋めるようにしていたのですが、アプリ内で使う画像については理解が浅かったです...。 PDF変換も試してみます、アドバイスありがとうございます。 (edited)
Avatar
昨日質問させて頂いた件でInfo.plistを変更した後起動しても前回と同様,落ちてしまいました。いろいろ改良してみたのですがダメでした;; プロジェクト自体をアップロードさせていただきますのでご確認いただけますと幸いです。
@WKWK こちらの件の続きなのですがカメラビューはお陰様で表示させることができました。 しかしながらQRコードを認識させようとしたところ認識できませんでした。 通常のカメラの方では読み取れています。 QRコードを作成したのは https://qr.quel.jp/design.php です。
絵(アイコン画像)や文字を真ん中に重ねた、デザイン性のあるQRコードを無料で簡単に作成できます。選べるアイコンは378種類あります。登録不要で累積発行数No.1の信頼性。商用利用でも無期限&無制限、そして無料。かわいい丸い模様のQRコードも人気です。
Avatar
カメラの使用時にQRコード読み取りを可能になる設定してますでしょうか? https://developer.apple.com/documentation/avfoundation/avmetadataobject/objecttype/1618819-qr
Avatar
こちらソースコードですがどこに入れればよろしいでしょうか
5.43 KB
Avatar
https://qiita.com/_asa08_/items/8562fe79ec6528a61b06 この記事でいう↓の記述が該当します。swift カメラ qrコード で検索すると記事がいくつも出てくるので、参考にしてやってみてください。 metadataOutput.metadataObjectTypes = [.qr]
簡単に実装したサンプルです。参考になると幸いです。 asa08/QRreader カメラを設定する import AVFoundationして、AVCaptureSessionをインスタンスを生成します。 private le...
Avatar
了解です! ご回答いただきありがとうございます
Avatar
画面遷移についてなのですが,Main.storyboardのA viewcontrollerのボタンからSub.storyboardのB viewcontrollerに遷移するにはどうすれば良いでしょうか
Avatar
storyboard reference で検索してみましょう
Avatar
質問失礼します。 cocoapodsを導入した際に.xcworkspaceが作成されると思うのですが、今まで開発を進めていた.xcodeprojでライブラリを使うにはどうしたらいいのでしょうか?
Avatar
CocoaPodsで作成された.xcworkspaceを開けば、今まで開発を進めていたxcodeprojにライブラリを取り込んだ状態で構成して開かれます。なので、xcworkspaceを開いてそのまま開発継続して問題ないです (edited)
1:57 AM
Avatar
Kishikawa Katsumi 9/20/2020 2:02 AM
xcodeprojを別に開いてるからですね。1度に1つしか開けないので、xcodeprojを開かずにワークスペースを開いて、ワークスペースに表示されるxcodeprojを使用します。
2:02 AM
CocoaPodsを使った場合は必ずワークスペースを開いて作業しなければなりません。CocoaPodsの仕組みによる制限です。
2:02 AM
CocoaPodsはワークスペースにいろいろ設定をするので。
Avatar
閉じたら、無事にナビゲーターエリアにstoryboard等が出てきました...! .xcworkspace内に.vcodeprojが入っていることは理解できていたのですが、ここから作業を進めようにも。。。となっていたところだったので本当にありがたいです。
2:06 AM
@Kishikawa Katsumi @ありぜ 本当にありがとうございました...!
🙆‍♂️ 1
Avatar
Kishikawa Katsumi 9/20/2020 2:06 AM
よくあるやつです。私も元のを開いたままワークスペースを開いてあれってなることがあります。
😚 1
Avatar
「どの端末でも画面表示サイズを10cmに統一する」というのは可能でしょうか。調べてみると、端末サイズを取得してそのサイズごとにオブジェクトサイズを変更することならできそうなのですが、他に良い方法はないでしょうか。
Avatar
中見てないですけどpixelsPerInchがとれるみたいですね。scaleとscreen sizeと合わせればなんとなくできそう?? https://github.com/lmirosevic/GBDeviceInfo
Detects the hardware, software and display of the current iOS or Mac OS X device at runtime. - lmirosevic/GBDeviceInfo
Avatar
omochimetaru 9/26/2020 1:36 PM
Detects the hardware, software and display of the current iOS or Mac OS X device at runtime. - lmirosevic/GBDeviceInfo
1:36 PM
それ以前調べたことあるんですけど
1:36 PM
iOSのAPIとしては存在しなくて
1:37 PM
全部のデバイスに対して事前にデータ持っておく必要があります。
1:37 PM
このライブラリもそうなってる。
Avatar
当然だけど未知のデバイスに関しては0になるんですね。
1:40 PM
iOSのAPIとして提供して欲しい
Avatar
お世話になっております iOS13で「becomeFirstResponder() をプログラムから呼んでもキーボードが立ち上がらない」という問題に直面しています。。タップイベントでキーボードが起動できた後なら問題ないのですが、初回だけ起動されず。 同じような経験をした方、または解決方法をご存知の方はいらっしゃいますでしょうか? こちらのstackoverflow(https://stackoverflow.com/questions/59582631/becomefirstresponder-is-not-showing-keyboard-until-touch-of-any-uitextfield-at-l )と同じ現象になんですが、解決策で提示されているIntercomを使っていないので解決できず困っている状況です。。
Possible solution at the end. I am developing a UIViewController with three UITextField. The function to open the keyboard when the screen is presented was working for 3 years non-stop, then after...
Avatar
UIViewControllerはfirst responderを自分でなんとかしようと努力してるから
4:04 PM
意味不明な挙動しますね
4:05 PM
その固有の挙動はあまり認識していないけれど、becomeFirstResponder()を読んでも必ずしもfirst responder になるとは限らないので (edited)
4:06 PM
それ自体はAPIとしては間違ってないんですけどね。
Avatar
なるほど、ご助言ありがとうございます! もう少し自分の方で調査してみます 🙇‍♂️
Avatar
こんばんは UIPickerViewについて教えて頂きたいです。 iOS14とそれ以前のOSでUIPickerViewのselectedRowの 背景色が違うようですが、この背景色を統一する方法はありますでしょうか? この部分の色を指定するようなプロパティが見つからず 解決方法が分からなかったので質問させて頂きました。 Xcode12.0.1 (12A7300)で実行してます。 コード側では何もしてません。 宜しくお願い致します。
Avatar
tintColor じゃないのかな?
Avatar
いつもお世話になってます。 体重管理アプリを作っているのですが、ユーザーが入力した体重等の情報を日付と紐付ける処理をしたいのですが、やり方が全くイメージできず悩んでます。。。
8:42 AM
8:42 AM
8:42 AM
8:46 AM
色んな画面の要素を同期するなら、Rxswiftをやったほうがいいと言われたのですが、今はswiftだけでも手一杯なので他に何かやり方あればと思いまして。。(良いものにしたいので、必要なら勉強する気力はあります)
Avatar
やり方が全くイメージできず悩んでます
何に悩んでいるのか詳しく書いた方が良いと思います。 画面デザインの見た目の事なのか、データの保存方法の事なのか、 UIの表示方法の事なのか
(edited)
Avatar
説明不足でした、すみません。デザインではなく保存方法ですね。 ユーザーがTextFieldやImageView入力した情報を投稿した日付と合わせて保存したいのです。
Avatar
なるほど。アプリの他の機能でデータを保存してるものはあるんですか?保存方法はいろいろあるのでそれに合わせたほうが良い
Avatar
上から2枚目の画面でのユーザーがTextFieldに入力する数字の情報と日付、上から3枚目の画面では画像の投稿とメモ欄、その日に体重入力画面で体重を入力していれば下に表示され、これも日付と関連づけしたいです。 他では、1枚目のNavigationVarの設定ボタンからユーザーが目標体重と身長を入力できる欄があるくらいです。 (edited)
9:41 AM
現状保存しているものは、特にないはずです。。 コード上は、各関連付けとPickerViewの中身、Date関数での日時の取得ぐらいしかやってないので。。
9:42 AM
後、カレンダー周りぐらいですかね。
Avatar
ふむふむ。Codableを使ってJSON形式で書き出してファイルとして保存するのはどうでしょうか?
Avatar
あと、まだ後回しにしてるのですが、1枚目の左下にグラフアイコンがあると思うんですけど、上から2つ目の画面でユーザーが入力した体重や体脂肪率をグラフ化みたいなこともしたいなと思ってます( .. )
9:47 AM
Codable!!ggってみます💦
Avatar
グラフはカスタムビューにCoreGraphicsで作画するのが手軽です。
Avatar
Codable、軽くggったのですが理解レベルが追いついてなくて多分2割も理解できてないので勉強しようと思います...!グラフ化についてもありがとうございます...!!!
9:57 AM
やるべき指針が見えてありがたいです。。本当にありがとうございます!
🙂 1
Avatar
@あきと 多分具体的なコードで一連の流れがわかった上で調べた方がわかりやすいと思ったので試しに書いてみました。 import Foundation // 年月日 struct YMD: Codable { var year: Int var month: Int var day: Int } // 日付と体重・体脂肪率の記録 struct Record: Codable { var ymd: YMD var weight: Double // kg var fatRate: Double // 0.0 - 1.0 } // 日々の体重の記録は↓のような [Record] として扱える let records: [Record] = [ Record(ymd: YMD(year: 2020, month: 10, day: 14), weight: 55.2, fatRate: 0.121), Record(ymd: YMD(year: 2020, month: 10, day: 15), weight: 55.4, fatRate: 0.124), Record(ymd: YMD(year: 2020, month: 10, day: 16), weight: 55.5, fatRate: 0.123), ] // JSON ファイルから [Record] を読み込んで追加し保存する一連の処理 do { // ファイルから JSON 形式のバイト列を読み込み let data: Data = try Data(contentsOf: URL(fileURLWithPath: "path/to/records.json")) // JSON から日々の体重の記録を復元 var records: [Record] = try JSONDecoder().decode([Record].self, from: data) // 今日の記録を追加 let record: Record = Record(ymd: YMD(year: 2020, month: 10, day: 17), weight: 55.6, fatRate: 0.125) records.append(record) // JSON 形式のバイト列に変換 let newData: Data = try JSONEncoder().encode(records) // ファイルに保存 try newData.write(to: URL(fileURLWithPath: "path/to/records.json"), options: .atomic) } catch { // エラーハンドリング } (edited)
👏🏼 2
😍 1
2:54 PM
↑の RecordYMD のように Codable に適合した型であれば JSONEncoderJSONDecoder を使って JSON 形式のバイト列に変換・復元することが簡単にできます。
Avatar
@koher ええええええ....!?!?いいんですか。本当にありがとうございます。。。めちゃくちゃ助かります。。。
Avatar
これをコピペして使うというのではなく、これを元に一行ずつ何をやっているのかを確認し、さらにより一般的に Codable が何をするのかということを学ぶと理解が深まると思います。(このコードを使っていただくこと自体は問題ありません。) (edited)
Avatar
はい、質問内容自体もそうだったのですが何から手をつけていいのかすらわかっていない状態だったので本当に助かります。
🙂 1
Avatar
こんばんは。実際のスマホ画面でのViewサイズをどの機種(画面サイズ)でも10cmに統一したいのですが、方法をなかなか見つけることができません。画面サイズを取得し、そのサイズごとにViewのサイズを変更しようと考えています。実際の表示サイズを画面の解像度等から計算することは可能でしょうか。
Avatar
可能だと思いますが、端末によって画素密度が異なるので、端末ごとにそれを踏まえた計算を入れて表示してやることになるので、あまりおすすめできません。 10cmに統一したい理由ってなにかあるんでしょうか? その内容次第では、別のスマートなやり方を提示できるかも。
Avatar
Kishikawa Katsumi 10/27/2020 1:29 PM
https://github.com/marchv/UIScreenExtension/blob/master/Sources/UIScreenExtension/UIScreenExtension.swift ありぜさんのおっしゃる通りで、PPIが違うので簡単じゃないです。このようなコードでやってることを見るとわかります。
An extension to UIScreen that offers information about the pixel density (or point density) of iPhones and iPads. - marchv/UIScreenExtension
1:30 PM
逆にいうと、上記のコードのようにリリース済みの全部のデバイスについてPPIを調べたらできます。 (edited)
Avatar
返信ありがとうございます。現在制作中のアプリが精神科治療で使われているVAS評価というもので、その評価用の先の長さが10cmと決まっており、それをスライダーで再現しようと考えています。https://www.jspm.ne.jp/guidelines/pain/2010/chapter02/02_02_02.php#:~:text=VAS%E3%81%AF%E3%80%81100mm%E3%81%AE%E7%B7%9A,%E8%A9%95%E4%BE%A1%E3%81%99%E3%82%8B%E3%82%82%E3%81%AE%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82
がん医療を中心としたPalliative Medicineの専門性を確立するための学際的かつ学術的研究とその実践、その教育を行う学会
Avatar
Kishikawa Katsumi 10/27/2020 1:34 PM
なるほど。ということは定規アプリを作るのと同じ、、、ですね。 ということなのでデバイスごとのPPIから計算する必要がありますね。
1:36 PM
デバイスごとのPPIはまあWebを調べたらいくつか出てくると思うので見比べて正しいものを参照すればいいと思います。
Avatar
func sliderWidth(SliderWidth: CGFloat, SidewaysAlert: Bool) { if UIScreen.main.nativeBounds.width == 750 {//4.7inch self.SidewaysAlert = true self.SliderWidth = 657.7 }else if UIScreen.main.nativeBounds.width == 1125 {//5.4 5.8inch side self.SidewaysAlert = true self.SliderWidth = 438.5 }else if UIScreen.main.nativeBounds.width == 1242 {//5.5 6.5inch side self.SidewaysAlert = true self.SliderWidth = 326.4 }else if UIScreen.main.nativeBounds.width == 828 {//6.1inch side self.SidewaysAlert = true self.SliderWidth = 489.6 }else if UIScreen.main.nativeBounds.width == 1170 {//6.1inch side self.SidewaysAlert = true self.SliderWidth = 346.5 }else if UIScreen.main.nativeBounds.width == 1248 {//6.7inch side self.SidewaysAlert = true self.SliderWidth = 315.8 }else if UIScreen.main.nativeBounds.width == 768 {//7.9 9.7inch self.SliderWidth = 1142.4 }else if UIScreen.main.nativeBounds.width == 1536 {//7.9 9.7inch self.SliderWidth = 571.2 }else if UIScreen.main.nativeBounds.width == 1620 {//10.2inch self.SliderWidth = 541.6 }else if UIScreen.main.nativeBounds.width == 1668 {//10.5 11.0inch self.SliderWidth = 526 }else if UIScreen.main.nativeBounds.width == 1640 {//10.9inch self.SliderWidth = 535 }else if UIScreen.main.nativeBounds.width == 2048 {//12.9inch self.SliderWidth = 428.4 } } 実機にデモアプリを入れてサイズを確かめ、実機とシミュレータのサイズ比率から計算してみたのですが、実機で検証したもの以外はうまくいきません。 (edited)
1:40 PM
なるほど。ということは定規アプリを作るのと同じ、、、ですね。 ということなのでデバイスごとのPPIから計算する必要がありますね。
@Kishikawa Katsumi その線で検索してみます!ありがとうございます!
Avatar
simulatorは、拡大縮小とかできるので、サイズにズレがでると思います。 メニューバーにあるactual sizeにチェック入れると、もしかしたら上手くいくかもしれません
👍 1
Avatar
とりあえず marchv/UIScreenExtension が持ってる値で試してみたらどうでしょうか。
1:44 PM
そのライブラリは ppi を返してくれるので。
👍 1
1:44 PM
それでもし数字がズレてたら計測してフィードバックしてあげると良いと思います。
Avatar
実機でもcmにずれが生じる場合は、UIScreen.main.nativeBounds.width が同じ値でも端末によってppiは異なるので、そこで計算ずれてると思います。 omochiさんのいうようにまずはライブラリが持ってる値で試すと良さそうです。 (edited)
👍 1
1:48 PM
Physical Sizeを押すと実機とほぼ同じサイズになりました!
👍 1
1:48 PM
(iPhone12と8で比較) (edited)
Avatar
Kishikawa Katsumi 10/27/2020 1:48 PM
「定規アプリ 作り方」「 Ruler app ios」みたいな検索語で調べるとある程度情報が集まると思います。
👍 1
Avatar
@ありぜ @Kishikawa Katsumi @omochimetaru みなさん本当にありがとうございました! (edited)
👍 2
Avatar
お世話になっております 非常に困っているので教えて頂きたいです 前提として以下が環境です Xcode12.1 iOS Development Targetが10.3 SwiftyRSAというライブラリを使っていて、バージョンは1.3.0 このライブラリのバージョンを1.6.0に上げる必要があるのですが 調べてみたらこのライブラリのios.deployment_targetが"11.0"に上がっており iOS10.3の実機を繋いでビルドができなくなってしまいました。。。 iOS10.3をサポートしながら、このライブラリを1.6.0にする方法はありますでしょうか? 以下がこのライブラリの1.6.0バージョンアップ時のコミットです ご教示頂けると幸いです。宜しくお願い致します。 https://github.com/TakeScoop/SwiftyRSA/commit/c4f97d7726b5d1cb9480d7e442be4002716d1be9
Avatar
Kishikawa Katsumi 11/10/2020 9:36 AM
自分でDeployment Targetと必要な部分を書き換えるしかないですね。
Avatar
見た限り10でも動きそうなので、podspecファイルを手元にコピーしてdeployment_targetを書き換えて、アプリ側のPodfileの中でコピーしたpodspecを以下のように指定すると良いと思います。 pod 'SwiftyRSA', :podspec => "./SwiftyRSA.podspec" (edited)
👍 1
Avatar
@Kishikawa Katsumi 回答頂きありがとうございます。 ライブラリ側のDeployment Targetを書き換えて、それに影響される部分の コードを自分で書き換えるって意味合いであってますでしょうか?
Avatar
Kishikawa Katsumi 11/10/2020 9:38 AM
そうです。ただ、シンプルなCommonCryptoのラッパーっぽいし、たぶん @Yuta Saito さんが書いたようにターゲットのバージョンを下げるだけで動きそう。
9:39 AM
もし、ライブラリの全部の機能を使ってないならライブラリのコードを参考にして必要なところだけ組み込んだりするのがいいんじゃないでしょうか。
Avatar
@Yuta Saito @Kishikawa Katsumi 回答ありがとうございます! なるほどアプリ側のPodfileで指定する方法があるんですね。。。 確かに全部の機能を使ってないなら掻い摘んで組み込むのが良さそうな気がします・・・。 少し手を動かしてみるので、詰まったらまた質問させて頂けると助かります! ありがとうございます!
👍 2
Avatar
Shohei Yamamoto 11/16/2020 1:15 PM
XCTAssertEqual で、expectedとactualの順番の決まりはあるのでしょうか? XCTAssertEqual(expected, actual)
Avatar
Kishikawa Katsumi 11/16/2020 1:24 PM
expected, actualという引数名がついているので、厳密に書くなら 第一引数に「期待する結果(たいていはあらかじめ自分で用意したもの)」、第二引数には「実際の結果」を与えます。
1:25 PM
入れ替わっても別に結果は一緒です。失敗したときのログが入れ替わるので順番は上記の順を守った方が何かとわかりやすいです。
Avatar
Shohei Yamamoto 11/16/2020 1:40 PM
@Kishikawa Katsumi ありがとうございます! XCTAssertEqualのドキュメントでは、#define XCTAssertEqual(expression1, expression2, ...) となっており、特にどちらが期待する結果かは書かれていないのですがSwiftを書く人達の中での共通認識や慣習として期待する結果を先に書くというのがあるのでしょうか?
Avatar
Kishikawa Katsumi 11/16/2020 1:45 PM
ああ、なるほど。いや上で XCTAssertEqual(expected, actual) と書かれていたのを見て、最初の引数がexpectedなのだな、と思っただけです。ちょっと調べても見つからなかったのでテストの中で統一されてたらどっちを期待する結果としてもいいのかもしれません。
🙇‍♂️ 1
1:46 PM
入れ替えても一緒なんですけど、バラバラなのは単純にわかりにくいので揃っていた方がいいです。
Avatar
Shohei Yamamoto 11/16/2020 1:48 PM
@Kishikawa Katsumi ありがとうございます!とりあえずプロジェクト内で決めて揃えるのは意識しようとおもいます!
Avatar
Kishikawa Katsumi 11/16/2020 1:50 PM
https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods この辺をみる限り、 XCTAssertEqual(table.rowCount, 0, "Row count was not zero.") XCTAssertEqual(table.columnCount, 0, "Column count was not zero.") と書かれているので XCTAssertEqual(実際の値, 期待する結果) がいいのかもしれません(Appleのドキュメントでそうなので)。
Avatar
Shohei Yamamoto 11/16/2020 1:54 PM
なるほど確かにそうなってますね! この順番でやっていきます!ありがとうございます。
Avatar
こんにちは! UIPageViewControllerについて質問させてください。 現在解決したい問題は以下です。 UIPageViewControllerのtransitionStyleがscrollの場合に UIPageViewControllerDataSource にある以下メソッドの呼び出しが余分に呼ばれたり、呼ばれなかったりする時があります。(初回はスワイプ 時はviewControllerBeforeとviewControllerAfterが同時に呼ばれる。以降で向きを切り替えてスワイプ した際の初回のスワイプ のイベントは呼ばれない) 但しtransitionStyleをpageControlに設定した際は正常な通知になるのですが、scrollに設定する際は他に設定する項目があるのでしょうか? 何かご存知の方がいらっしゃいましたらご教授頂けますと幸いです。 よろしくお願いいたします。 func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?

環境

  • Xcode12.2
  • StoryboardでViewControllerを作成し、ContainerViewでPageViewControllerを設定 # 使用用途
  • 上記DataSourceのメソッドを使用して現在のindexを更新して、表示したいViewControllerを配列から取り出しreturn
(edited)
Avatar
@teru 実装していたのが結構前なのでうろ覚えなのですが、指摘されているUIPageViewControllerの挙動はその通りですが、実際にはそれで正常な挙動だと思います。 そもそもbefore/afterのイベントは、スワイプを開始したことの通知ではなく、前後のページが必要なのでインスタンスを用意する、というメソッドです。 アニメーションをスクロールにした場合は、バウンスアニメーションを行うために、先のページまで読み込む必要があります。またUIPageViewController自体は直近前後1ページについてはキャッシュを持っていて、キャッシュが存在していればbefore/afterは呼び出す必要がなくなる、直前の画面遷移でバウンスのために用意したページをそのまま使う、といった挙動になります。
Avatar
@tarunon ご回答ありがとうございます!
アニメーションをスクロールにした場合は、バウンスアニメーションを行うために、先のページまで読み込む必要があります。
あぁ、なるほど...バウンスがあるから先のページまで読み込まれるのですね。納得です。 それでいうとpageViewControllerのbounceを切るとpageControlと同じ挙動になるんですかね? ちょっと試してみます!ありがとうございました!
Avatar
質問です! iOSで通信速度の下りの速度を取得したいのですが、取得する術はあるのでしょうか。 以下を見るとMacでの計測をしている記事は見つけたのですが、ProcessというクラスがMacOSでしか使用できないものらしく参考記事が見当たらないのです...。 https://qiita.com/Kyome/items/e9f56432fa0d1d3f3165 もしご存知の方がいらっしゃいましたら、ご教授頂けますと幸いです!よろしくお願いいたします。
CapabilitiesのIncoming Connections (Server)またはOutgoing Connections (Client)にチェックを入れる class Network { private ...
Avatar
Process がないという以前に netstat の実行ってできないと思う
6:40 AM
この辺りのAPIを使うんだったと思う。
Avatar
@niw おぉ、ありがとうございます! このあたりを見ると https://developer.apple.com/forums/thread/652680?answerId=618275022#618275022 考え方的には、Network Frameを使用して特定サイズのファイルをダウンロードして、ダウンロード時間から通信速度(kbps/sec)を算出するイメージなのでしょうか?
Avatar
そうですねー、network framework でどのネットワークかがわかるので、それぞれの状況に応じて計測してって感じになるかなと思います。
Avatar
了解です! ご回答ありがとうございましたー!
Avatar
Swift 勉強しようと思い、手元にあるURLリスト(1,000 ドメインくらい) をクローリングするコードを書いて見たのですが、数件取得したのちに A server with the specified hostname could not be found のようにエラーが出てしまい、curl ではアクセスできるURLでもうまくクローリングできません。 何かネットワークの設定などが必要でしょうか? https://gist.github.com/dictav/52e180d8f449912a0c8fe77d53f61b1c URLSession を使っています。 session.dataTask(with: URLRequest(url: self.url)) { (data, response, error) in defer { self.isExecuting = false self.isFinished = true } if let err = error { print(self.url, err.localizedDescription) return } if let res = response as? HTTPURLResponse { print("status: \(res.statusCode)") } }.resume() (edited)
GitHub Gist: instantly share code, notes, and snippets.
Avatar
同時にコネクション作り過ぎて死んでるんじゃないかと思いました。 以下のAPIで同時実行数を制御できるので、試してみては。 https://developer.apple.com/documentation/foundation/operationqueue
Avatar
Kishikawa Katsumi 1/23/2021 11:00 AM
^ 私もこれだと思います。URLSessionはテーブルビューとかで使うだけでも同時実行を制限しなかったらすぐに通信できなくなる印象。
11:01 AM
たぶん10〜20くらいでダメ。
Avatar
ありがとうございます! 同時実行数を5くらいに制御することでクローリングはできました。ただ、クローリングにものすごく時間がかかってしまい実用的とは言えないものになってしまいました。 書き忘れていたのですが、プログラムは macOS 上で走らせています。 試しに同じような振る舞いのプログラムを Go 言語で実装し、Linux 上と macOS 上とで走らせてみたのですが、Linux 上だと同時接続数を 100 などに増やしても問題なく動作するのに対し、macOS 上だと同時接続数を10くらいにすると類似のホストが見つからないエラーがでます。言語の問題ではなく、OSの制約なのかなと思っています。 iOS上であればある程度仕方ないと思うのですが、macOS であればコネクションをたくさん作るようなプログラムを作成することもままあると思います。何かしらOSの設定を変更することでコネクションを作れる数を増やせないものでしょうか?
Avatar
一つのURLSessionで回しているなら httpMaximumConnectionsPerHost を設定しておかないとデフォルト 6 (macOS) らしいです https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1407597-httpmaximumconnectionsperhost
👀 1
Avatar
Kishikawa Katsumi 1/25/2021 5:38 PM
あ、そこの値だったのか!
Avatar
ただ per host なので関係ないかも?もしかしてネームサーバへの同時接続ではじかれてるかも?
👀 1
Avatar
Kishikawa Katsumi 1/25/2021 5:53 PM
ただURLSessionはなんかエラーが返るというよりだんまりになる感じの挙動だったから、ちょっとちゃんと調べる必要あるなあ。わからない。
5:54 PM
^ 私が確認しているテーブルビューとかでたくさんリクエストを発行すると通信不能になるというやつ。
Avatar
試しに同じような振る舞いのプログラムを Go 言語で実装し、Linux 上と macOS 上とで走らせてみたのですが、 Linux 上と macOS 上とで走らせてみたのですが、Linux 上だと同時接続数を 100 などに増やしても問題なく動作するのに対し、macOS 上だと同時接続数を10くらいにすると類似のホストが見つからないエラーがでます。言語の問題ではなく、OSの制約なのかなと思っています。
逆に Linux & Swift でどうなるのか気になりますね👀
Avatar
Linux で Swift だと CoreLibs Foundation の実装依存かなあ。
Avatar
ネームサーバの同時接続で弾かれるというのもあるんですね。なるほど。
Avatar
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
👀 1
4:51 PM
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
4:53 PM
Apple の Foundation が libcurl ってことはないだろうけれど、API的には同じような振る舞いを期待してるんじゃないかな。
Avatar
Swiftでアプリ製作中でUITextViewについて躓いたので教えていただきたいです。 【躓いた点】 シミュレータ上でUITextViewに文字入力しようとしたときに、日本語入力ができない。 【試したこと】 ・シミュレータの言語設定を日本語に ・シミュレータのkeyboradに日本語(Romaji)を追加 同じView内のUITextFieldは問題なく日本語入力できています。 もし解決策があるようであればご教授いただきたいです。 よろしくおねがいします。
Avatar
Avatar
maeken
Swiftでアプリ製作中でUITextViewについて躓いたので教えていただきたいです。 【躓いた点】 シミュレータ上でUITextViewに文字入力しようとしたときに、日本語入力ができない。 【試したこと】 ・シミュレータの言語設定を日本語に ・シミュレータのkeyboradに日本語(Romaji)を追加 同じView内のUITextFieldは問題なく日本語入力できています。 もし解決策があるようであればご教授いただきたいです。 よろしくおねがいします。
text view作り直したら解決しました、、
Avatar
🍤ACエビフライ🔌 2/15/2021 6:56 AM
どこに投げたらいい質問か分からないのでまずこちらに投げさせてください。 社内でApple Developer Programのcertificateを誤って削除してしまう事故が起きたのですが、この再発を防ぐfool proof的な予防策ってございますでしょうか。React Nativeで開発中 expo build:ios --revoke-credentials してしまったようです。 (edited)
Avatar
作り直せばいいからさほど困らない気がするけれど...?
8:58 AM
(答えになってないかもしれないけれど。)
Avatar
Apple DeveloperのRoleでDeveloperを割り当てて、revokeできないようにするくらいでしょうか
3:00 PM
あと、別なアプローチもあると思ってます。 何かしら困りごとを解決しようとしてこのコマンドを実行したのでしょうから、その困りごとをフォローできる人にヘルプお願いしやすい雰囲気を作るとか
Avatar
Avatar
niw
作り直せばいいからさほど困らない気がするけれど...?
🍤ACエビフライ🔌 3/1/2021 3:08 AM
顧客のアプリがつかえなくなって怒られたそうです
😨 1
Avatar
Avatar
nomadmonad
Apple DeveloperのRoleでDeveloperを割り当てて、revokeできないようにするくらいでしょうか
🍤ACエビフライ🔌 3/1/2021 3:08 AM
なるほど
Avatar
Avatar
🍤ACエビフライ🔌
顧客のアプリがつかえなくなって怒られたそうです
ああ、開発用のではなくて、か。
Avatar
Avatar
nomadmonad
あと、別なアプローチもあると思ってます。 何かしら困りごとを解決しようとしてこのコマンドを実行したのでしょうから、その困りごとをフォローできる人にヘルプお願いしやすい雰囲気を作るとか
🍤ACエビフライ🔌 3/1/2021 3:11 AM
何かしら困りごとを解決しようとしてこのコマンドを実行したのでしょうから、その困りごとをフォローできる人にヘルプお願いしやすい雰囲気を作るとか
本来はこれが正しそうなのですが、組織的には道のりが遠そう。
Avatar
証明書周りでお詳しい方教えてください。 実機ビルドをしようとすると、codesignの箇所で下記エラーが表示されてビルドができない状況です。 Warning unable to build chain to self-signed root for signer "(null)" 現状、他の開発メンバーと同じTeamに参加しているAppleアカウントでCertificateを作成し、そのCertificateをSelectしたProvisioning Profileもダウンロードした状態です。 Automatically Manage Signingにはチェック入れる/入れないどちらも試しましたが同じエラーが表示され、証明書の作り直しなども試しましたがビルドできませんでした。 原因や怪しいところがありましたら教えていただけると幸いです。
Avatar
以前、似たような状況にある方の質問に回答したことがあります。何か参考になれば! https://teratail.com/questions/126378
以前実機でアプリがビルド出来ていたのに出来なくなってしまいました。 現在Swiftでアプリ開発を行っており、Udemyで学習しているのですが、昨日完成したアプリをビルドしようとしたところ、 この画面が出てきました。そこで、ログインパスワードを入力して、「許可」のボタンを押しても反応しなかったため
Avatar
Avatar
koogawa
以前、似たような状況にある方の質問に回答したことがあります。何か参考になれば! https://teratail.com/questions/126378
返信ありがとうございます。 実はその記事は事前に確認させていただいていて、中間証明書の再インストールとMacの再起動はやってみたのですが、結果変わらずでした😢
Avatar
Avatar
kojikoji
返信ありがとうございます。 実はその記事は事前に確認させていただいていて、中間証明書の再インストールとMacの再起動はやってみたのですが、結果変わらずでした😢
なるほど。。!すでに試されていましたか🙏
🙏 1
Avatar
certificate 周りはケースバイケースでこうしたら絶対治るってのがないから
3:37 AM
ひとつづつ理解して潰していくしかないかなあ。
3:38 AM
codesignがだしてるエラー的にはルート証明書まで辿れなくて証明書の検証ができないてきな感じに思えるけど、nullになってるあたり、なにか正しい名前か引数が渡されていないように見える。 (edited)
Avatar
Avatar
niw
codesignがだしてるエラー的にはルート証明書まで辿れなくて証明書の検証ができないてきな感じに思えるけど、nullになってるあたり、なにか正しい名前か引数が渡されていないように見える。 (edited)
反応ありがとうございます。 業務で作っているアプリとは別にProjectを一個作ってみて、TeamをPersonal Teamに指定してビルドしてみたんですが、そちらも同じエラーが発生し、nullのところには自分のアカウント(Apple Developer: ○○の形)が表示されていました。
Avatar
こんにちは,本日初めてswiftを触ってみた者です.
4:33 PM
switchやifが標準で値を返すようにしたほうが便利だと思うのですが,皆さんいかがお考えですか?
4:36 PM
ネットでざっと検索したところ,わざわざクロージャーを使うコードが見かけられました
Avatar
swiftだと、scalaで言うところのif式やswitch式は無いです。が、@resultBuilder という機能を使うことで限定されたコンテキストにおいて if式、switch式相当のものを、それも構築される型を指定して組み立てることが出来ます。ざっくりどんなものかは、SwiftUIにおけるViewBuilderを参照してみて下さい。 (edited)
6:29 PM
標準であった方が便利か、と言う問いに対しては個人的な解答になるんですけど。 普段if/switchを使うときに余計な制約が無く、必要に応じて式指向の為のコンテキストを作れるというのは、結構良い塩梅なんじゃないかなと考えています。 (edited)
Avatar
余計な制約
各ブランチの結果型を揃える必要があるとかですか?
Avatar
例えば早期returnをif文で書きたいのにそれが出来なくなるとか、
👍 1
6:33 PM
そう言ったことをイメージしています
6:33 PM
ブランチの結果型は基本的にはvoidで揃いそうだなと思いました
Avatar
if/else式 switch式 に関しては "Commonly Rejected Changes" に明記されていますね https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md#control-flow-closures-optional-binding-and-error-handling
Avatar
omochimetaru 3/27/2021 5:10 AM
早期脱出とif式は両立するよ。 例えばkotlinで実際それができるんだけど、returnしてる側の型はNeverなので、もう片方の型がAなら、ifの型はAになる。Never is Aなので。
Avatar
omochimetaru 3/27/2021 5:30 AM
Kotlinのif式は両辺の型のleast common typeになると思うんだけど、
5:31 AM
SwiftのResultBuilderはEither A B にできて、型的にはそっちのほうが正確だよね
Avatar
Eitherにもできるし、least common typeにすることも出来ますね
5:32 AM
resultBuilderの造りによってそれを決定できる
Avatar
omochimetaru 3/27/2021 5:33 AM
仕組みとしてはEitherにできるようなより柔軟なものが提供されていて、その上でユーザ実装としてLCTを選択できるね。 (edited)
5:33 AM
Kotlinの方式だと Eitherにすることはできなくって
5:34 AM
自分で両方のブランチで Either.left(A) みたいに書く必要がある。
5:36 AM
Commonly Rejected Changes に挙げられていて、 それで解決できることは他の方法で解決できる ←これは同意だけど if式を導入すると大きなトレードオフがある ←実際どんなデメリットがあるのかはあまりよくわからない
5:38 AM
他の方法については、
わざわざクロージャーを使う
対して記述量が変わるわけでもないので別に良いのでは無いか ifexp みたいな高階関数を書いてちょっと楽しても良い ↓以下のlet初期化スタイルでもそんな困らない let a: Int if ... { a = 3 } else { a = 2 } と思っている
Avatar
早期リターンが可能のイメージがつかない
Avatar
omochimetaru 3/27/2021 5:40 AM
val a = if (cond) { exp } else return (edited)
5:40 AM
↑こんな感じ
Avatar
そうするとネストが深くなるのか
Avatar
omochimetaru 3/27/2021 5:40 AM
Swiftだと guard let else return のパターンなら val a = exp ?: return (edited)
5:41 AM
ネストが深いとは?
Avatar
swiftでいうところの if ... { return A } ... return A みたいなものを表現しようとしたときに
5:44 AM
ifが式だと「手前のAを返さず後ろのAを返したい場合」は、elseによってしか実現できないのではないかと
Avatar
omochimetaru 3/27/2021 5:45 AM
func ifx<T>(_ cond: Bool, then: () -> T, else: () -> T) -> T { if cond { return then() } else { return `else`() } } let a = ifx (1 + 1 > 1) { return 2 } else: { return 1 } print(a) // 2 今のSwiftだとこんなのが書けますね。
Avatar
Avatar
tarunon
ifが式だと「手前のAを返さず後ろのAを返したい場合」は、elseによってしか実現できないのではないかと
omochimetaru 3/27/2021 5:46 AM
その形のコードはそのままkotlinでも書けるよ 別にifが式だろうと、式を2つ並べる事は許されているので
Avatar
早期リターンを書くと後ろの式を評価する術がなくならない?
5:48 AM
if式の中のreturn valueを外のコンテキストの返り値にしたいのだから
Avatar
omochimetaru 3/27/2021 5:48 AM
文を分けた場合は
5:48 AM
型は独立する
5:48 AM
一つ一つのif式ごとに型が決まるだけ
5:49 AM
if (foo) { return A } とだけ書いてある場合、このif式の型は Unit( voidみたいなもん) だね。ただ左辺が無いので意味はない。
5:50 AM
then側が Never で else側が書かれてないのでUnitだ
5:51 AM
returnはifに対するreturnになってるんじゃなくて、ifが書いてある関数に対するreturnだよ。
Avatar
ん、そうなるのか
5:51 AM
コンテキスト飛ぶのか、なるほどね
Avatar
omochimetaru 3/27/2021 5:52 AM
Kotlinの文法では val a = if (foo) { 1 } else { 2 } // これはaへの代入 val b = if (foo) { return 1 } else { return 2 } // これはここからの脱出、bは代入されない
👀 1
Avatar
返信が遅れ申し訳ございません.理解するのに時間がかかってしまいました.
7:06 AM
回答していただきありがとうございます.
Avatar
Avatar
omochimetaru
Commonly Rejected Changes に挙げられていて、 それで解決できることは他の方法で解決できる ←これは同意だけど if式を導入すると大きなトレードオフがある ←実際どんなデメリットがあるのかはあまりよくわからない
確かに,具体的なデメリットが書かれておらずざっくりした公式発表ですね
7:09 AM
swiftは関数型プログラミングを意識していると思うのですが,switchやifで値を返してくれないのがswiftに対する大きい不満点です.
7:10 AM
代数的データ型 Koka type color { Red Green Blue Rgb( r : int, g : int, b : int ) } または type color { Red; ...
7:10 AM
関数型を意識した他言語は値を返すものが多いのですが... (edited)
Avatar
omochimetaru 4/5/2021 7:11 AM
その後の会話の内容とも関連するんですが
7:12 AM
if式にして値を返せるようにすると
7:12 AM
「if式のthenブロックの値」を示す文法と、「ifが書かれている関数からのreturn」の混在が起きるという問題はありますね。 (edited)
Avatar
thenブロックとは中括弧の中身のことですか?
👌 1
Avatar
omochimetaru 4/5/2021 7:14 AM
Kotlinみたいに「thenブロックの最後に書いた式の値がthenの値である」ってルールにすることはできなくもないけど
Avatar
if/switchが式なら同様にwhile/forも式になると思うんですが、これらは多分returnじゃなくてyieldでコンテキストの外に値を渡すんじゃないかな。故にif/switchもyieldでコンテキストの外に値を渡せるとして、returnは関数からの脱出ということにすれば
7:15 AM
両立が可能だ
Avatar
omochimetaru 4/5/2021 7:15 AM
「本文が1文であるクロージャやメソッドの返り値はreturnを省略できる」って文法との兼ね合いがあって勘違いを誘発しそう。
Avatar
あとそもそも言語デフォルトでif/switchが提供されてる場合に、その型をどう解決するかという問題があると思うんですが
Avatar
Avatar
tarunon
if/switchが式なら同様にwhile/forも式になると思うんですが、これらは多分returnじゃなくてyieldでコンテキストの外に値を渡すんじゃないかな。故にif/switchもyieldでコンテキストの外に値を渡せるとして、returnは関数からの脱出ということにすれば
omochimetaru 4/5/2021 7:16 AM
yieldが関数レベルコルーチンの中断を表す文として使えなくなるから微妙だと思う。 まあ、例であって、別の文で区別して扱うというのは一つの方向性だね
Avatar
Either<T,F>が採用されるのか、TとFの共通の型が採用されるのか、或いはその両方か
Avatar
omochimetaru 4/5/2021 7:17 AM
たしかKotlinは LCT(T, F) で Either(T, F)ではなかったと思う。
Avatar
両方というのはEitherが自動でprotocolへの準拠を行う、みたいな感じね
7:18 AM
まあこの辺は結局言語のデザインに依存してしまって、あんまり嬉しくないシーンは出てくると思うんですよね
Avatar
omochimetaru 4/5/2021 7:19 AM
個人的には、ブロックの値とreturnの値の共存問題が大きいと思っていて
7:19 AM
Kotlinはそれを受け入れているんだけど、
7:19 AM
Kotlinはそれを突き進めてユーザー定義高階関数もその ブロックの値とreturnの両方を使えるようにするために
7:20 AM
inline funって概念を導入してるんだよね
7:20 AM
確かにうまく使えば便利ではあるんだけど、 高階関数側がパラメータのクロージャをどう呼び出すか、っていう振る舞いが、型に現れない暗黙のAPIになるので
7:21 AM
returnしたときにどういう形で中断されるのかとかが難しいのと
7:21 AM
実際にクロージャだけを脱出したい場合に備えて、ラベルつきreturnを使ったり
7:21 AM
ブロック文法ではない匿名fun式を使い分けたりする必要があって
7:21 AM
そのへんで言語仕様がすごい複雑になっちゃってて、
7:22 AM
シンプルではないんだよね、個人的にはあまり美しくない方向だと思ってる。
Avatar
resultBuilderを使いましょうね、というのは、デフォルトは多少不便になれど、今議論している双方の問題の解たり得るので 尚更そういう意味でも良い塩梅だなと思っている
7:22 AM
型はユーザーサイドで定義するから問題無し。コンテキストはクロージャを潜ることを強制するので問題無し。
Avatar
omochimetaru 4/5/2021 7:22 AM
Swiftではブロックの値と大域returnの共存はできていないので、 当然、returnはブロック(クロージャ)の脱出でしか無いんだけど、
7:23 AM
それで困るか?というと、別に困らなくって、 モナドを正しく使えば内側の結果を外側に伝搬するのは綺麗に書けるので、
7:23 AM
Kotlinは複雑になった割に得たものが少ないなと思ってる
7:25 AM
まあ「組み込みのif文等だけは式の値と大域脱出を両立できる」って線で手を打つ方針はありえるのかもしれない。
Avatar
Avatar
tarunon
resultBuilderを使いましょうね、というのは、デフォルトは多少不便になれど、今議論している双方の問題の解たり得るので 尚更そういう意味でも良い塩梅だなと思っている
omochimetaru 4/5/2021 7:29 AM
Eitherにするかどうか選べるし、 returnがかけないから2通りの制御の混乱もないねえ。
Avatar
@swift-5.3.3 enum Either<R, L> { case right(R) case left(L) } @_functionBuilder struct Expression { public static func buildIf<C>(_ c: C?) -> C? { c } public static func buildEither<T, F>(first: T) -> Either<T, F> { .right(first) } public static func buildEither<T, F>(second: F) -> Either<T, F> { .left(second) } } func exp<T>(@Expression f: () -> T) -> T { f() } let a = exp { if true { "" } else { 1 } } print(type(of: a))
Avatar
swift53 BOT 4/5/2021 7:31 AM
exit status: 11 with stderr:Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux-gnu/debug -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOSHA1/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOWindows/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIODarwin/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOLinux/include -module-cache-path /Libraries/.build/x86_64-unknown-linux-gnu/debug/ModuleCache -D DEBUG -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux-gnu/debug/CNIOHTTPParser.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux-gnu/debug/CNIOSHA1.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux-gnu/debug/CNIOAtomics.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/swift-nio/Sources/CNIOWindows/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux-gnu/debug/CNIODarwin.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux-gnu/debug/CNIOLinux.build/module.modulemap -module-name main -lLibraries 1. Swift version 5.3.3 (swift-5.3.3-RELEASE) 2. While evaluating request TypeCheckSourceFileRequest(source_file "<stdin>") 3. While type-checking statement at [<stdin>:26:1 - line:32:1] RangeText="let a = exp { if true { "" } else { 1 } " 4. Whil
Avatar
だめだったw
Avatar
omochimetaru 4/5/2021 7:32 AM
あれ? Either2View<A, B> とかどうやって作ってるんだ? (edited)
Avatar
多分上のはちょっと制約足りなくて死んだ
Avatar
omochimetaru 4/5/2021 7:33 AM
あ、これaも推論させてるからそうだね
7:36 AM
extension ViewBuilder { public static func buildEither<TrueContent, FalseContent>(first: TrueContent) -> _ConditionalContent<TrueContent, FalseContent> where TrueContent : View, FalseContent : View public static func buildEither<TrueContent, FalseContent>(second: FalseContent) -> _ConditionalContent<TrueContent, FalseContent> where TrueContent : View, FalseContent : View } https://yanamura.hatenablog.com/entry/2019/09/05/150849
potatotips #64でLTした内容です。 SwiftUIのViewで条件によってViewをだしわけたいことがたまにあるかと思います。 SwiftUIでこのように条件によってViewを出し分けるようなコードを書いてみます。 var body: some View { if imageName.isEmpty { return Text("no image") } else { return Image(imageName) } } そうするとこのようなコンパイルエラーになってしまいます。 ! Function declares an opaque return type, but the…
7:36 AM
できることは間違いない。
Avatar
過去に私が書いたコード見ても、外から推論を与えないと上手く行かない事が示唆されてるから
7:40 AM
あんまり便利な感じにはならなさそう
Avatar
@swift-5.3.3 enum Either<R, L> { case right(R) case left(L) } @_functionBuilder struct Expression { static func buildBlock() -> () { return () } static func buildBlock<T1>(_ t1: T1) -> (T1) { return (t1) } public static func buildEither<T, F>(first: T) -> Either<T, F> { return .right(first) } public static func buildEither<T, F>(second: F) -> Either<T, F> { return .left(second) } } func exp<T>(@Expression f: () -> T) -> T { f() } let a = exp { if true { "" } else { 1 } } print(type(of: a))
Avatar
swift53 BOT 4/5/2021 7:40 AM
Either<String, Int>stderr:<stdin>:34:9: warning: will never be executed 1 ^ <stdin>:31:8: note: condition always evaluates to true if true { ^
Avatar
buildBlockが必要
👏 3
Avatar
あああーーー
7:40 AM
なるほどね
Avatar
新しいコンパイラでコンパイルしたらちゃんとしたエラー出て偉かった
Avatar
ifの中で単一式を評価できない状態になってた
7:42 AM
このresultBuilderの機能を使って、コンテキストに合わせた立式を定義できるんで
7:42 AM
やりたいことはかなりカバーできるはず
7:42 AM
while,forもサポートされ…ましたっけ?プロポーザルは見た
7:43 AM
ちなみに Either<L, R> が一般的だと思うよ
😇 1
Avatar
確かにLが左だわね
Avatar
Avatar
omochimetaru
val a = if (cond) { exp } else return (edited)
話の流れを遮ってしまってすみません.理解が追いついていません笑 早期リターンの例を書いてみたのですが,仮にifが値を返すように実装されたとしたらどのような感じになりますか?(学んだばかりで,適切なエラーハンドリングがわからないので,0を返しています.ここも含めてリファクタリングしていただいても結構です) func calculatePaymentPrice(_ price : Int) -> Int{ if price < 0 { return 0 //エラーの代わり } return Int(Double(price)*1.1) } (edited)
Avatar
Avatar
basashi
話の流れを遮ってしまってすみません.理解が追いついていません笑 早期リターンの例を書いてみたのですが,仮にifが値を返すように実装されたとしたらどのような感じになりますか?(学んだばかりで,適切なエラーハンドリングがわからないので,0を返しています.ここも含めてリファクタリングしていただいても結構です) func calculatePaymentPrice(_ price : Int) -> Int{ if price < 0 { return 0 //エラーの代わり } return Int(Double(price)*1.1) } (edited)
omochimetaru 4/5/2021 7:46 AM
返信先のコードはelseでreturnしてるifが式でval aに代入できている例です。 提示されているcalculatePaymentPriceは普通のSwiftに見えますけど質問はなんですか?
Avatar
if式でreturnが問題になるという話は、ifをネストさせると何が問題なのかが解りやすくなると思う (edited)
Avatar
わかりづらくてすみません😢 仮にswiftのifが値を返すとしたら,同じ動きをする関数をどう書いたらよいかという質問です (edited)
Avatar
omochimetaru 4/5/2021 7:49 AM
func calculatePaymentPrice(_ price : Int) -> Int { if price < 0 { 0 } else { Int(Double(price) * 1.1) } } こうなるって話をしてると思ってます。式1つなのでreturnは省略しました。
7:51 AM
ちなみに現状のSwiftでも func calculatePaymentPrice2(_ price : Int) -> Int { price < 0 ? 0 : Int(Double(price) * 1.1) } func calculatePaymentPrice3(_ price : Int) -> Int { ifx (price < 0) { 0 } else: { Int(Double(price) * 1.1) } } ↑この2つの書き方はできます。(ifxは自作の関数)
Avatar
Avatar
omochimetaru
func calculatePaymentPrice(_ price : Int) -> Int { if price < 0 { 0 } else { Int(Double(price) * 1.1) } } こうなるって話をしてると思ってます。式1つなのでreturnは省略しました。
確かに先程の例だと,ifブロックの後ろをelseに入れられますね.例が悪かったかもしれないです.
7:57 AM
いい例えが思いつかないのですが,
7:58 AM
func calculatePaymentPrice(_ price : Int) -> Int{ if price < 0 { return 0 //エラーの代わり } if price = 0 { return 0 //エラーの代わり } return Int(Double(price)*1.1) }
7:58 AM
(無理やりエラー処理をもう一つ追加しました)
7:59 AM
このような場合だとどうなりますか?
Avatar
omochimetaru 4/5/2021 8:00 AM
func calculatePaymentPrice(_ price : Int) -> Int{ if price < 0 { 0 } else if price = 0 { 0 //エラーの代わり } else { Int(Double(price)*1.1) } } こうですか??
8:01 AM
そもそも僕はif式にしなくていいだろうと思っているので、 if式があったらどうなるかと言われても、答えようがないですよ。
8:01 AM
ifが文ではなく式だったらいいのに、と思っているのは @basashi さんなのだから、 「こういうコードが書けたら良いのに」という思いがあるのは、そちらでは。 (edited)
Avatar
if式を採用した場合に発生するコンテキストの問題として、if文の中のreturnが何を指すのかという問題が発生する。 1. if式の返り値として値を採用し、if式から脱出する 2. 関数の返り値として値を採用し、関数から脱出する。この時if式自体の返り値はNever型になる。 1を採用した場合、シンプルなif文を使った早期returnが表現できなくなるか、或いはネストしてif elseで表現することを強制される。 例 if myArray.isEmpty { return -1 } if elseで表現することを強制される、ということはそれは即ちif式での早期脱出の数だけ、本文のネストが深くなるということであり、望ましいものではない。 2を採用した場合、if式の中でif式の値として早期脱出を表現することは不可能になる。 例 let a = if myCond { if myArray.isEmpty { return -1 } // この行は関数の返り値になり、aとして利用することは出来なくなる ... } これらの1,2双方の問題を解決しようとした場合、ラベル付returnのような複雑な仕様が必要となるが、それは望ましくない というのがSwiftでif/switch/for/whileが式として提供されない一般の理由、と考えて良いと思います。 個人的にはラベル付returnよりはResultBuilderの方がシンプルなんじゃないかな、という感想。 (edited)
Avatar
Avatar
omochimetaru
ifが文ではなく式だったらいいのに、と思っているのは @basashi さんなのだから、 「こういうコードが書けたら良いのに」という思いがあるのは、そちらでは。 (edited)
確かにswiftサーバーでお聞きする質問ではなかったですね.すみません
Avatar
型の話はこのコンテキストの課題を超えた先の問題になりますね
Avatar
まずはコンテキストの壁を超えるようにがんばります
Avatar
Avatar
basashi
確かにswiftサーバーでお聞きする質問ではなかったですね.すみません
質問すること自体は良かったと思いますよ。僕は横目で議論を見てif式のメリットとデメリットを確認することができました。ただメリデメがあると分かった上で、basashiさんの「デメリットを引き受けてでもif式で解決したい課題」が説明できるとより良かったかもしれません
👍 2
Avatar
@basashi
swiftは関数型プログラミングを意識していると思うのですが,switchやifで値を返してくれないのがswiftに対する大きい不満点です.
僕は Swift はあまり関数型ではないと思っています。特に、イミュータビリティに対する考え方が異なります。 Swift はイミュータブルクラスの代わりにミュータブルな struct を使うことが多いです。 // イミュータブルクラス final class User { let age: Int = 0 } var user = User() // 年齢を 1 増やす user = User(age: user.age + 1) // struct struct User { var age: Int = 0 } var user = User() // 年齢を 1 増やす user.age += 1
(edited)
8:24 AM
if 文の例で考えると、↓のような違いが生まれます。 // イミュータブルクラス user = if ... { // if 式がほしい User(age: user.age + 1) } else { User(age: user.age + 2) } // struct if ... { // if 文で十分 user.age += 1 } else { user.age += 2 }
8:26 AM
if が式でなく文なのはミュータブルな値型( struct )を多用する Swift と馴染んでおり、適切な言語仕様ではないかと思います。 (edited)
8:29 AM
なお、ミュータブルな値型のインスタンスは共有することができないので(ミュータブルクラスのインスタンスではこれが可能なのでイミュータブルクラスを使いたい)、実質的にイミュータブルクラスのように働きます。
Avatar
swiftに対する先入観が誤っていたかもしれません
8:40 AM
更に勉強してから出直します お騒がせしました🙇🏻
Avatar
ここは何を質問しても良い場なのでまた気軽に質問して下さい🙂
Avatar
親切に回答していただきありがとうございました
Avatar
自分もif式が割と欲しいと思ってる人でして、理由はミュータブル/イミュータブルとかはあまり関係なく、単純に例えばこんな感じなものをif式で書きたいだけです: func connect(parameter: String) { let request: URLRequest if parameter == "abc" { request = URLRequest(/* A */) } else { request = URLRequest(/* B */) } URLSession.shared.dataTask(with: request).resume() } まあ上記の場合は別に URLRequest のFactoryMethod作っちゃうか、CLosure駆使して無理矢理 () -> URLRequest 作っちゃえばいいっちゃいいですけど、単純にそれ面倒だからif式欲しいなって思ってます
Avatar
omochimetaru 4/5/2021 5:45 PM
僕もまさに↑のパターンでif式がほしいと思っていた事があるけど、最近はその書き方でいいやと考えが変わりました。 request を3回書くからコピペで再利用できないと思ったんだけど、同じ変数の一括編集をエディタでできるから別にいいやと。 中間計算で複雑なことをやる場合はクロージャに閉じ込めてます。
Avatar
request を 3 回書くのは同じものを書くだけなのでまだ良いですが、型を明示しないといけなくなるのがたまに辛いですね...
Avatar
omochimetaru 4/5/2021 6:10 PM
そうですね。ここを省略できないのはちょっと嫌。
Avatar
3 回書く件は↓でもいいかも? func connect(parameter: String) { let request: URLRequest if parameter == "abc" { request = .init(/* A */) } else { request = .init(/* B */) } URLSession.shared.dataTask(with: request).resume() }
👍 1
1:41 AM
僕は普段から↓のように書きます。 let foo: Foo = .init(...)
1:44 AM
Failable Initializer で気付かずに Optional になっていて面倒なことが何度もあったので、↑の形で書いておくとコンパイルエラーとして検出できて便利だからこのスタイルで書くようになりました。そして、読むときを考えると型が書いてあった方がやっぱり読みやすいんですよね。 Xcode が教えてくれるにしても、カーソルを合わせる必要もないというのはやっぱり読みやすい。
Avatar
自分は上記connectn場合はcomputed variableを使いますね。値の中身が{}で囲まれるので見やすいと思っています。なお、.init での初期化を関数の引数でも使っていたら使いすぎで現実的な時間で型推論できなくて警告でました...。 func connect(parameter: String) { var request: URLRequest { if parameter == "abc" {   return .init(/* A */) } else { return .init(/* B */) } } URLSession.shared.dataTask(with: request).resume() }
Avatar
自分がそうしたかった、からではないのですが、fileprivate を使う理由ってなにかありますかね。 (そうじゃなきゃいけない場面を除いて。) 最近 private でよいのに、 fileprivate が使いたいということを言われて... (edited)
Avatar
omochimetaru 4/7/2021 2:25 AM
プロジェクト内から使われたくない場合?
2:26 AM
ローカル関数みたいな感じで局所的なもの
Avatar
private でいいとおもうんですよねえ、それなら。
2:28 AM
逆に言えば、private で十分な場合でも、fileprivate を使う必要がある場合はあるのか? という質問になります。 (edited)
Avatar
omochimetaru 4/7/2021 2:29 AM
privateで十分なら十分なはずで
2:30 AM
fileprivateはファイル内で別の型とかに公開する方
2:30 AM
はじめに モバイルアプリサービス部の中安です。 Swift3でスコープの改変が行われ、「private」に加えて、「fileprivate」というスコープが加わりました。 Swift4ではさらにスコープの改変が行われるそ …
Avatar
ふむ。やっぱり妥当な理由はないですよね。
Avatar
omochimetaru 4/7/2021 2:33 AM
Swift2とSwift3とSwift4で仕様変更があったから勘違いしてるのかも
2:33 AM
Swift 4以前は忘れたい
Avatar
今の話と関係あるかわかりませんが、以前に岸川さんとそもそも fileprivate (というアクセスレベル修飾子)を書く箇所があるか?という話をしました。 fileprivate なメソッドを作りたいケースでも private extension にすればアクセスレベルとして fileprivate 扱いになるので、 fileprivate というアクセスレベル修飾子を書く機会がないんじゃないかという話です。 private なトップレベル関数も同様です。
2:54 AM
そして、↓のようなレアケースでは fileprivate 書かないといけないねという話になりました。 https://discord.com/channels/291054398077927425/306995750418513920/805675304340946944
Avatar
Avatar
koher
今の話と関係あるかわかりませんが、以前に岸川さんとそもそも fileprivate (というアクセスレベル修飾子)を書く箇所があるか?という話をしました。 fileprivate なメソッドを作りたいケースでも private extension にすればアクセスレベルとして fileprivate 扱いになるので、 fileprivate というアクセスレベル修飾子を書く機会がないんじゃないかという話です。 private なトップレベル関数も同様です。
おお、面白い... fileprivate は使っててほぼ例外的にコンパイラが無理見えない、って言ってくるときだけにつけてる印象があって、でもやっぱりそうか。ほとんどないですよね... private extension なるほど
7:12 AM
+ “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages
7:13 AM
There has been a ton of debate on the swift-evolution mailing lists about access control in Swift. A couple of days ago, the proposal SE-0159: Fix Private Access Levels was rejected. I want to share my thoughts on this, as...
7:14 AM
読んできたんですけど、やっぱり印象として、fileprivate はなんかゴタゴタの末やむなしで残ってる感じだったんですね。
7:14 AM
あんまり真面目に知ろうとしてなかったので勉強になった
Avatar
トップレベルにprivateって付けると実質的にfileprivateと同等になる。で、fileprivateがあるとトップレベルでextension使って…とやらなくても、その場で適切なアクセス制御が表現できる
7:18 AM
class MyClass { fileprivate func foo() { ... } }private extension MyClass { func foo() { ... } } が等価かな?
Avatar
ふとした疑問なのですが、The Swift Programming Languageの日本語版ってあるのでしょうか?公式サイトにはリンクないなあと思い。 https://swift.org/documentation/#the-swift-programming-language
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
Avatar
shiz
ふとした疑問なのですが、The Swift Programming Languageの日本語版ってあるのでしょうか?公式サイトにはリンクないなあと思い。 https://swift.org/documentation/#the-swift-programming-language
たしかSwiftが出た当初に和訳してた人がいたんですが、その当時オープンソース化もされておらず、ドキュメントを和訳したものをGitHubのリポジトリに置くのはGitHubの規約違反だという意見が出て、結局なくなってしまったと記憶しています。
Avatar
Avatar
koher
たしかSwiftが出た当初に和訳してた人がいたんですが、その当時オープンソース化もされておらず、ドキュメントを和訳したものをGitHubのリポジトリに置くのはGitHubの規約違反だという意見が出て、結局なくなってしまったと記憶しています。
そんな経緯があったんですね😅ありがとうございますmmなんとなく日本語でもみんなで共通で参照できるものがあったらいいなあとふと思ったのですが...
Avatar
Avatar
shiz
そんな経緯があったんですね😅ありがとうございますmmなんとなく日本語でもみんなで共通で参照できるものがあったらいいなあとふと思ったのですが...
あると良さそうですね!
Avatar
Avatar
koher
あると良さそうですね!
機会があれば翻訳なら少しはお役に立てるかもしれません。 他の言語はGitBookを使っているんですね。どうやって作っているのかちょっと見てみます👀 https://docs.gitbook.com
Avatar
Avatar
shiz
機会があれば翻訳なら少しはお役に立てるかもしれません。 他の言語はGitBookを使っているんですね。どうやって作っているのかちょっと見てみます👀 https://docs.gitbook.com
おおお、期待です!
🤏 1
Avatar
プログラム的な内容ではないので こちらでお聞きして良いかわかりかねたのですが、適切なチャンネルがあればご指摘下さい。 App Tracking Transparencyについて、対応して下さいのメールがAppleから来たのですが 理解が非常にあやふやなので、以下について、教えて頂きたいです。 ・App Tracking Transparency対応とは、今まではユーザーの許可無くIdentifier for Advertisersを  取得出来ていたが、iOS14.5以降は、Identifier for Advertisersを取得するためには  ユーザーの許可が必要になったと言う認識で合ってますでしょうか? ・App Tracking Transparency対応の実装内容については、トラッキングの許可のアラートを  iOS14.5移行のユーザーに表示するで合ってますでしょうか? ・トラッキングの許可が得られない場合、具体的にどのようなことが出来なくなるのでしょうか? ・対応していない場合、リジェクトの対象になるのでしょうか? https://developer.apple.com/jp/app-store/user-privacy-and-data-use/ こちらを目を通したのですが、いまいち自分の中で理解がしきれてないので、お答え頂けると幸いです。 宜しくお願いいたします。
App Storeは、世界中の才能あふれるデベロッパが開発したAppをユーザーが安心して見つけられる、安全かつ信頼できる場所となるように作られています。
Avatar
Avatar
飯塚
プログラム的な内容ではないので こちらでお聞きして良いかわかりかねたのですが、適切なチャンネルがあればご指摘下さい。 App Tracking Transparencyについて、対応して下さいのメールがAppleから来たのですが 理解が非常にあやふやなので、以下について、教えて頂きたいです。 ・App Tracking Transparency対応とは、今まではユーザーの許可無くIdentifier for Advertisersを  取得出来ていたが、iOS14.5以降は、Identifier for Advertisersを取得するためには  ユーザーの許可が必要になったと言う認識で合ってますでしょうか? ・App Tracking Transparency対応の実装内容については、トラッキングの許可のアラートを  iOS14.5移行のユーザーに表示するで合ってますでしょうか? ・トラッキングの許可が得られない場合、具体的にどのようなことが出来なくなるのでしょうか? ・対応していない場合、リジェクトの対象になるのでしょうか? https://developer.apple.com/jp/app-store/user-privacy-and-data-use/ こちらを目を通したのですが、いまいち自分の中で理解がしきれてないので、お答え頂けると幸いです。 宜しくお願いいたします。
ATTは難しいからなあ。IDAだけじゃないです。「いかなる」トラッキングも(これはリンク先のトラッキングとは...の文章にあるとおりです)、ユーザーがいいえって答えたら使っちゃダメだったはずです。IDAやトラッキングをするのであれば、確認画面を出して許可もらわないとダメで、出さずにトラッキングしてバレたら追放されると思います。 (edited)
Avatar
・App Tracking Transparency対応とは、今まではユーザーの許可無くIdentifier for Advertisersを 取得出来ていたが、iOS14.5以降は、Identifier for Advertisersを取得するためには ユーザーの許可が必要になったと言う認識で合ってますでしょうか?
いかなるトラッキングを行うのにもユーザーの許可が必要になりました。
・App Tracking Transparency対応の実装内容については、トラッキングの許可のアラートを  iOS14.5移行のユーザーに表示するで合ってますでしょうか?
その通りです。
・トラッキングの許可が得られない場合、具体的にどのようなことが出来なくなるのでしょうか?
トラッキングに該当するような行為ができなくなります。
・対応していない場合、リジェクトの対象になるのでしょうか?
はい
(edited)
👀 1
3:42 PM
送信せずに改行ってどうやるんだ... Option+Enterでもない...
Avatar
Avatar
niw
ATTは難しいからなあ。IDAだけじゃないです。「いかなる」トラッキングも(これはリンク先のトラッキングとは...の文章にあるとおりです)、ユーザーがいいえって答えたら使っちゃダメだったはずです。IDAやトラッキングをするのであれば、確認画面を出して許可もらわないとダメで、出さずにトラッキングしてバレたら追放されると思います。 (edited)
ご回答ありがとうございます。やはり難しいんですね・・・。 該当の文章をもう一度熟読しましたが、やはり難しいです。 例えばFirebaseAnalyticsみたいな収集ツールとか 位置情報を使ったマップアプリなども、トラッキング許可のアラートを出して ユーザーに拒否された場合は、それらが動作しないように制御する必要があるって意味合いでしょうか?
3:43 PM
Shift + Enter でしょうか
Avatar
Avatar
飯塚
Shift + Enter でしょうか
おお、shiftかw
Avatar
Avatar
飯塚
ご回答ありがとうございます。やはり難しいんですね・・・。 該当の文章をもう一度熟読しましたが、やはり難しいです。 例えばFirebaseAnalyticsみたいな収集ツールとか 位置情報を使ったマップアプリなども、トラッキング許可のアラートを出して ユーザーに拒否された場合は、それらが動作しないように制御する必要があるって意味合いでしょうか?
トラッキングとは、自分のAppで収集したユーザーやデバイスに関するデータを、ターゲット広告や広告効果測定を目的として、他社のApp、Webサイト、またはオフラインのプロパティから収集されたユーザーやデバイスに関するデータに紐付ける行為を指します。また、ユーザーやデバイスに関するデータをデータブローカーに共有することもトラッキングに該当します
Firebaseで、たとえば、Crashlytics とかは該当しないと思います。Firebase で、Googleの広告に結びつくやつはダメです。
(edited)
Avatar
広告に関連する様なトラッキングがダメってことですよね?
Avatar
そうですね。
3:49 PM
この文章が多分アップルが考える「トラッキング」が何か、を端的に表していると思います。実際の線引きはAppStoreの審査運用でカバーだと思うんですけど、具体的な例として上がってる項目に抵触する場合は該当すると考えていいと思います。
3:50 PM
ここで言うサードパーティーやデータブローカーはGoogleとかFacebookに置き換えて読んでも問題ないと思います。 (edited)
Avatar
なるほどありがとうございます。 先程の公式のページを必死に読んでいましたが、なんとも理解に自信が持てなかったので 貴重なご意見聞けて少し安心しました!回答し辛い質問だったかもしれませんが お答え頂けて非常に感謝です。ありがとうございました!
Avatar
ATT難しいですよね。でもまあ受け入れるしかないので、カジュアルにサードのSDKや広告を導入できなくなったと考えて差し支えないと思います。
4:07 PM
業界でもIDAの話だけだと思ってた人も多いようなのでわりと厳しい事態になってるところは多いと思います。 (edited)
Avatar
importしただけで動いちゃうライブラリとかは今後厳しいだろうなと思いますね。昔観測したけど今もあるのかな
Avatar
omochimetaru 5/10/2021 4:48 PM
へえ~知らなかった 広告SDK業界が困りそう
4:49 PM
トラッキングが駄目なだけで広告が駄目ってわけじゃないか。どのくらいの困りになるのかよくわからんな。
Avatar
かなり困るはず...
Avatar
omochimetaru 5/10/2021 4:50 PM
そういうもんですか
Avatar
トラッキング切ってGoogleとかニュースサイトとかみるとほんと(言葉悪いけど)ゴミみたいな広告しか出なくなるはず。なんかスキンケアとかそういうやつ。 (edited)
Avatar
omochimetaru 5/10/2021 4:50 PM
もともと広告をゴミだと思ってるので変わらなそう
4:51 PM
最近の行動に依存してると余計気持ち悪さを感じるし。
4:51 PM
少数派か・・・?
Avatar
ただ事実として、SMBがロングテールのインターネットの広告でビジネスが成功しているという現状はあるんですよ
4:52 PM
それを全否定するのは簡単だけどそれってテレビのマスメディアの広告の世界に戻るってことでもあるから
4:52 PM
もうちょっと多角的に見るとおもしろいと思う。
Avatar
omochimetaru 5/10/2021 4:53 PM
なるほど。テレビCMみたいになるのはもっと嫌だな・・・
Avatar
SMBが作るような、よい商品やサービスが多分ターゲット広告以外の露出が得られるような仕組みが世の中に必要。 (edited)
4:55 PM
マーケットを牛耳ってるAppleとかGoogleとかは実はまったく困らなくて、自社で検索ワードやらブラウザやらもうすでに十分なシグナルが得られる状態だから、
4:55 PM
ATTで大負けするのはじつは最終的にはエンドユーザーだったりする
4:56 PM
というと、Facebookの詭弁に聞こえるんだけど不都合な真実だとは思う。
Avatar
スケベ広告やマンガ広告よりはトラッキングされた広告のほうがよいなぁ
Avatar
なので、まあロングテールのSMBとエンドユーザーをつなぐinplicitなトラッキングじゃない仕組みが求められると思います。
4:57 PM
Tカードみたいな感じかな... (edited)
Avatar
トラッキングされて有益な広告、見えて嬉しいものは入札額が少なすぎてすぐに消えてしまって、結局見たくもないやつばかりになってしまう問題がある
Avatar
プラットフォーマーは LiveRamp とかの cookie 代替ID、コンテキストによるターゲッティング、1st Party Data を使ったターゲッティングあたりに注目しているみたいですね。 (edited)
Avatar
どのトピックが適切か悩ましいのでしいのでここで聴いてしまうのですが・・・ AppStoreConnectでリリース中のアプリに対しインストール導線を計測するためにキャンペーン用URLを作成することがあると思いますが、AppStoreConnectであらかじめキャンペーンが作成されてないキャンペーン(正確にはAppStoreConnect上で登録されていないキャンペーントークンを含む)URL経由でのインストールがAppStoreConnect上で集計されるかどうかって、誰かご存じでしょうか? ようはキャンペーンURLをプログラマティックかつAppStoreConnectのAPI叩かずに作りたいという状況なのですが (edited)
Avatar
cocoapods でたとえば、spec.swift_versions を 5.0 にしたとき、Xcode 12.4でビルドしたらそれは Xcode内蔵のSwift5 (5.3) に従う?それとも 5.0 のままですかね (edited)
6:29 AM
ああ、自己解決しました 5.3っぽい (edited)
Avatar
並列処理の実装に関してアドバイスを頂きたいので質問させて下さい 🙇 以下のコードは実際に使っているコードを簡略化したものです。 find の処理を並列化するために DispatchQueue.concurrentPerform を使っています.find は現在の results も使うため、各スレッドで results のコピー localResults を作り、find の結果、他のスレッドによって変更されていなければ results に追加、変更されていれば localResults を更新してやり直し、という感じの処理になっています。 実際のケースでは targets は膨大な量があり、find もそこそこ見つかるので、 localResults のコピーを更新があるごとに作っているのがパフォーマンスに影響しています。理想的には localResults を作らず、どれかのスレッドが result を見つけたら、他のスレッドが find を終わらすのを待った上で、同期的に(複数ありうる) result の中かから一番いいものを選んで results に追加し、それが終わったらまたみんなで find を続ける、という感じにしたいのですが、どう実装したらいいものか迷っています。 最近よく聞く async/await を使うとキレイにできたりするのかなーとか思ってまして、もし良い方法があれば教えて下さい 🙇 import Dispatch var targets = Set(0 ..< 10000) var results: [Int: Int] = [:] let atomic = DispatchQueue(label: "atomic", qos: .userInteractive) DispatchQueue.concurrentPerform(iterations: 4) { _ in // create local copy var localResults = atomic.sync { results } while true { let next = atomic.sync { targets.popFirst() } guard let i = next else { break // all targets popped, exit loop. } if let result = find(in: i, currentResults: localResults) { atomic.sync { // update results if not updated by other threads. if localResults.count == results.count { results[i] = result } else { // otherwise retry i. targets.insert(i) } } } atomic.sync { // update local copy if necessary if localResults.count != results.count { localResults = results } } } } // parallelized function func find(in i: Int, currentResults: [Int: Int]) -> Int? { i % 100 == 0 ? i : nil } print(results.count)
Avatar
Avatar
Taketo Sano
並列処理の実装に関してアドバイスを頂きたいので質問させて下さい 🙇 以下のコードは実際に使っているコードを簡略化したものです。 find の処理を並列化するために DispatchQueue.concurrentPerform を使っています.find は現在の results も使うため、各スレッドで results のコピー localResults を作り、find の結果、他のスレッドによって変更されていなければ results に追加、変更されていれば localResults を更新してやり直し、という感じの処理になっています。 実際のケースでは targets は膨大な量があり、find もそこそこ見つかるので、 localResults のコピーを更新があるごとに作っているのがパフォーマンスに影響しています。理想的には localResults を作らず、どれかのスレッドが result を見つけたら、他のスレッドが find を終わらすのを待った上で、同期的に(複数ありうる) result の中かから一番いいものを選んで results に追加し、それが終わったらまたみんなで find を続ける、という感じにしたいのですが、どう実装したらいいものか迷っています。 最近よく聞く async/await を使うとキレイにできたりするのかなーとか思ってまして、もし良い方法があれば教えて下さい 🙇 import Dispatch var targets = Set(0 ..< 10000) var results: [Int: Int] = [:] let atomic = DispatchQueue(label: "atomic", qos: .userInteractive) DispatchQueue.concurrentPerform(iterations: 4) { _ in // create local copy var localResults = atomic.sync { results } while true { let next = atomic.sync { targets.popFirst() } guard let i = next else { break // all targets popped, exit loop. } if let result = find(in: i, currentResults: localResults) { atomic.sync { // update results if not updated by other threads. if localResults.count == results.count { results[i] = result } else { // otherwise retry i. targets.insert(i) } } } atomic.sync { // update local copy if necessary if localResults.count != results.count { localResults = results } } } } // parallelized function func find(in i: Int, currentResults: [Int: Int]) -> Int? { i % 100 == 0 ? i : nil } print(results.count)
Swift 5.5 を前提にするのであれば、 resultstargets を Actor で守りながら、 findTaskGroup で並行に走らせるのが良いように思います。
Avatar
omochimetaru 6/14/2021 3:44 AM
Actorを使ったとしても、 results をそれぞれのタスクで使うところでコピーが必要な問題は残りますね。 コピーしないなら「共有+利用中はロックで専有する」か「ロックフリーデータ構造を使う」しかないですが、 ロックで専有はSwift concurrencyだとやっちゃいけないので、 ロックフリーデータ構造が良さそうだけど詳しくないです。
Avatar
Avatar
omochimetaru
Actorを使ったとしても、 results をそれぞれのタスクで使うところでコピーが必要な問題は残りますね。 コピーしないなら「共有+利用中はロックで専有する」か「ロックフリーデータ構造を使う」しかないですが、 ロックで専有はSwift concurrencyだとやっちゃいけないので、 ロックフリーデータ構造が良さそうだけど詳しくないです。
targetsresults のミューテーションを Actor に閉じ込めればコピーは要らなくないですか?
3:48 AM
ああ、 resultsfind に渡してるのか。 (edited)
Avatar
omochimetaru 6/14/2021 3:48 AM
計算の入力として使うようだったので。
Avatar
はい,計算の入力に使います.
Avatar
omochimetaru 6/14/2021 3:49 AM
async/await/actorを使えば コードがスッキリするし、競合バグの静的検査による回避が効くので、
3:49 AM
とりあえずその方が良いですね。
Avatar
Avatar
Taketo Sano
はい,計算の入力に使います.
どんな使い方をするか次第ですが、もし find の処理の内、 results を利用する部分だけを Actor に切り離せるのであれば、 find に Actor を渡す形にしてコピー不要にできる可能性はあると思います。
Avatar
ふむふむ…
Avatar
もし find の中で繰り返し results にアクセスしていて、それが処理負荷の中で支配的なようであれば、都度 async/await を通して Actor にアクセスするよりも、事前にコピーして同期アクセスした方が軽そうです。
Avatar
そうですね,頻繁にアクセスします.
Avatar
あと、そもそも Actor 経由になって処理の度に async/await を挟むと、 find の途中で await の度に results が変更されている可能性が存在するので、データ不整合の意味でも厳しいかもしれませんね。
3:58 AM
resultsappend されるだけでなくデータを書き換えられることはありますか? append されるだけならイミュータブルな(でも前方に要素追加は可能な)連結リストを使えばコピー不要にできるかもしれません。
3:59 AM
あ、だめか。 Dictionary か。
Avatar
results はツリーで、find の結果に応じて枝を伸ばしていく感じの処理をしてます.
4:02 AM
実際には results の他に,元となるイミュータブルなデータがあって,それと合わせてツリーを伸ばしてるような処理になってます.
Avatar
Avatar
koher
あと、そもそも Actor 経由になって処理の度に async/await を挟むと、 find の途中で await の度に results が変更されている可能性が存在するので、データ不整合の意味でも厳しいかもしれませんね。
omochimetaru 6/14/2021 4:03 AM
find の途中で await の度に results が変更されている可能性が存在する
findは並行に動いているから、actor境界をまたぐので、resultsは明示的にコピーで受け渡しそう
Avatar
Avatar
Taketo Sano
results はツリーで、find の結果に応じて枝を伸ばしていく感じの処理をしてます.
omochimetaru 6/14/2021 4:03 AM
find の結果に応じて枝を伸ばしていく感じの処理
ロックフリーデータ構造にできそうな希望があるな・・・
Avatar
Avatar
omochimetaru
find の途中で await の度に results が変更されている可能性が存在する
findは並行に動いているから、actor境界をまたぐので、resultsは明示的にコピーで受け渡しそう
results は Actor の中にあって、 find には Actor を渡して都度 async な API を通してアクセスするイメージでした。
Avatar
Avatar
koher
results は Actor の中にあって、 find には Actor を渡して都度 async な API を通してアクセスするイメージでした。
omochimetaru 6/14/2021 4:07 AM
findをasync化するってことですね。 そのアプローチだと結局、Actorのメソッドを呼び出すところでresults(Dictionary)のコピー渡しが生じますね。
Avatar
Avatar
omochimetaru
findをasync化するってことですね。 そのアプローチだと結局、Actorのメソッドを呼び出すところでresults(Dictionary)のコピー渡しが生じますね。
findをasync化
はい。
Actorのメソッドを呼び出すところでresults(Dictionary)のコピー渡し
いえ、 results は Actor の中にあって外から直接さわれなくして、 Actor のメソッドを通して操作するイメージです。 results.contains をしたければ actor.contains みたいなのを呼び出す。
Avatar
Avatar
koher
findをasync化
はい。
Actorのメソッドを呼び出すところでresults(Dictionary)のコピー渡し
いえ、 results は Actor の中にあって外から直接さわれなくして、 Actor のメソッドを通して操作するイメージです。 results.contains をしたければ actor.contains みたいなのを呼び出す。
omochimetaru 6/14/2021 4:09 AM
なるほど。そうすればresults全体のコピーを回避できるかも。
4:09 AM
findCycleFreePivot のロジック次第ですね。僕は今はこれを精査する時間まではないです🙏
Avatar
ただ、 Actor 化作戦は https://discord.com/channels/291054398077927425/291211035438874625/853847425643053136 のコード見てると多分 await 前後で整合性が崩れてダメそうに思います。
Avatar
omochimetaru 6/14/2021 4:16 AM
そこもロジックが変わっちゃいますね。 targetへの結果の集約というレベルでは同じ意味で動く別のロジックを組む事になりそう。
Avatar
(返事遅くなりました) ふーむ,なるほど.async/await の導入で何か本質的な改良が得られるというよりは,コードがキレイになって安全性が高まるという感じで,本質的な改良にはロジックの見直しが必要そうということですね.async/await はまだ触れたことがないので,この機会に色々とやってみようと思います.ありがとうございました🙏
👍 1
5:52 AM
TaskGroup も Swift 5.5 からなんですね.
5:53 AM
https://developer.apple.com/documentation/swift/taskgroup ← このリファレンス,各 OS のバージョンじゃなくて言語のバージョンを書いてくれたらいいのに.
Avatar
コピーを無くすにはmove only typeとかその辺の言語機能が必要な気がしますね
Avatar
omochimetaru 6/14/2021 5:54 AM
move onlyによるコピーカットは所有権のtransferだから、もしあっても今回は使えないねえ
5:54 AM
それぞれのfindが参照しなければならないので。
Avatar
複数から参照してるのか、それはダメだ😞
Avatar
ムーブセマンティクスというかC++ interopも楽しみですね 🙃 (Objective-CもC++もわからずObjective-C++を書いた日々を思い出す)
😆 1
Avatar
omochimetaru 6/14/2021 6:29 AM
C++ interop結構進んでて楽しみですねえ
Avatar
results のコピーを無くした上で,並列処理ごとにできるだけちょうど 1個結果が返ってくるように,並列処理の本数を動的に変える実装にしてみました.(話が盛り上がってるところすみません) var targets = Array(0 ..< 1000000) var results: [Int: Int] = [:] var batch = 1 var itr = 1 while !targets.isEmpty { let next = (0 ..< batch).compactMap { _ in targets.isEmpty ? nil : targets.removeLast() } let candidates = targets.parallelCompactMap { i in find(i, results) // runs in parallel } if let (i, j) = candidates.min(by: { (i, j) in weight(i, j) }) { results[i] = j for (i1, _) in candidates where i1 != i { targets.append(i1) // redo unselected candidates. } } if candidates.count == 0 { batch *= 2 } else if candidates.count >= 2 && batch > 1 { batch /= 2 } itr += 1 } // parallelized function func find(_ i: Int, _ currentResult: [Int: Int]) -> (Int, Int)? { i % 10 == 0 ? (i, i) : nil } print(results.count) (edited)
6:40 AM
結果 1:40 かかってた処理が 1:07 ぐらいになりました🙌
🎉 3
Avatar
利用している C++ 製ライブラリ(Eigen)が OMP という並列計算のためのライブラリをサポートしていて,これを有効にしたいと思って色々やっています.こちらにある方法を参考に, OpenMP on High Sierra https://iscinumpy.gitlab.io/post/omp-on-high-sierra/ brew install libomp した上で,Package.swift を次のように書くと: .target( name: "CEigenBridge", path: "Sources/CEigenBridge", cxxSettings: [ .headerSearchPath("../Eigen/"), .unsafeFlags(["-I/usr/local/opt/libomp/include/", "-Xpreprocessor", "-fopenmp"]), ], linkerSettings: [ .unsafeFlags(["-L/usr/local/opt/libomp/lib/"]), .linkedLibrary("omp") ] ), Debug configuration ではビルドできたのですが,Release ビルドだと次のエラーが出て上手くいきません: ld: warning: ignoring file /usr/local/opt/libomp/lib//libomp.dylib, building for macOS-arm64 but attempting to link with file built for macOS-x86_64 Undefined symbols for architecture arm64: "___kmpc_fork_call", referenced from: ... Release ビルドの仕組みがよく分かってないのですが,arm64 用と x86_64 用の両方を作っていて,前者に対して libomp.dylib をリンクしようとしたら x86_64 用のになってるから無視されて,arm64 用のシンボルが見つからなくてエラー,という感じなのでしょうか?(自分の環境は macOS-x86_64 です) 実行環境用にしかビルドしないという風に SwiftPM (または他の方法で)で設定するということはできるのでしょうか? あるいは他の解決法があれば教えて頂けると嬉しいです🙏 (edited)
Avatar
https://forums.swift.org/t/restrict-macos-builds-to-x86-64-with-spm/42239/9
I think there is currently no solution for this, since the release configuration implies ONLY_ACTIVE_ARCH set to false for packages which means they will always build for all supported architectures.
これによると無理そう?
Avatar
omochimetaru 6/16/2021 3:15 AM
SwiftPMでアーキテクチャ絞り込めない?そう言われれば指定方法を知らないな、無いのかな
3:15 AM
--triple <triple>
swift buildのヘルプを引くとtripleを指定できるみたいですね
3:16 AM
$ swift build --triple x86_64-apple-macosx とか? (edited)
Avatar
おぉ… triple とはなんですか?
Avatar
omochimetaru 6/16/2021 3:17 AM
x86_64-apple-macosx みたいな文字列のことです。 <arch>-<vendor>-<os> だったっけな。
Avatar
なるほどっ
Avatar
omochimetaru 6/16/2021 3:18 AM
GCC界?用語で意味はそのまま三組
3:18 AM
コンパイラに対して指定することで吐き出す実行ファイルの実行環境を指定する。
3:19 AM
クロスコンパイルするときに使う。
Avatar
ふむふむ
3:19 AM
いまコマンドラインからビルドを試みています
3:19 AM
これを Package.swift で指定するのは無理なんですかね?(unsafe flag に指定するとかの方法で)
Avatar
omochimetaru 6/16/2021 3:20 AM
無さそうです swift build自体のオプションなので
Avatar
なるほどなるほど
3:21 AM
おー,ビルドできました!
Avatar
omochimetaru 6/16/2021 3:21 AM
できるんや
3:21 AM
新機能発見w
Avatar
Instruments (Time Profiler) とつなぎたいんですが,それもコマンドラインからできるんですかね?
Avatar
omochimetaru 6/16/2021 3:22 AM
Instruments の CLI があるのかはわからないですが、
3:22 AM
swift build でバイナリファイルが出てると思うんで
3:22 AM
Instrumentsを単体起動して、バイナリ指定して開始すればいいです
Avatar
おぉ,すごいできた🙌
Avatar
omochimetaru 6/16/2021 3:25 AM
お。
Avatar
いやー,毎度ありがとうございます.これも自己解決は無理だったと思います😂
Avatar
omochimetaru 6/16/2021 3:27 AM
今回は運が良かったですね、サクッと解決
Avatar
Instruments で直接バイナリを開けるのも知りませんでした.
Avatar
omochimetaru 6/16/2021 3:29 AM
デバッガは基本的に
3:29 AM
プロセスにアタッチするインターフェースになっていて
3:29 AM
その際に、起動と同時にアタッチするか、すでに実行中のプロセスにアタッチするかの2つがあります
3:30 AM
Xcodeのデバッグ機能もInstrumentsもそれは同じルールで
3:30 AM
ただ、普段使うときは、IDEと連携して、ビルド→実行とアタッチが連動して動いているだけで
3:30 AM
機能としての仕組みは基本的にはビルドとは関係ないんです。 (edited)
Avatar
なーるほど
3:32 AM
そもそも release build で x86_64 用と arm64 用の両方を作ってることも知りませんでした.これビルドが通るようにするには,利用する外部ライブラリも両方のアーキテクチャで用意してないといけないってことですかね?
Avatar
omochimetaru 6/16/2021 3:33 AM
そうですね。
3:33 AM
Xcode開発だと、CPUを絞り込む設定ができますけど
3:33 AM
swift-build は トップレベルだけで、Package.swift ではそこは扱えないみたいですねえ
Avatar
なるほどなるほど.
Avatar
omochimetaru 6/16/2021 3:34 AM
まあ今は普通にやったら両方ビルドするようになるんで
3:34 AM
アセンブラとかCPU固有のAPIを使うような特殊なライブラリだけ困るって感じですね
3:34 AM
OpenMPはまさに特殊なやつですね・・・
Avatar
あー,なるほど.
3:36 AM
x86_64 環境で arm64 用の dylib をインストールすること自体できる…? brew install で両方インストールできるっぽいですが https://stackoverflow.com/a/67414239/1249157
I have a MacBook M1 and have installed a library on my machine that was compiled for an x86 / Intel architecture. I have some source code that uses OpenMP. I would like to compile my code and li...
Avatar
omochimetaru 6/16/2021 3:39 AM
普通は brewでいれたらユニバーサルバイナリ(x64とarmがくっついたやつ)来ると思ってた
Avatar
https://formulae.brew.sh/formula-linux/libomp これを見ると ARM64 も ✅ ついてるんですけどねぇ (edited)
3:41 AM
バージョンが古いとかかな
3:44 AM
brew info libomp libomp: stable 12.0.0 (bottled) LLVM's OpenMP runtime library https://openmp.llvm.org/ /usr/local/Cellar/libomp/12.0.0 (9 files, 1.5MB) * Poured from bottle on 2021-06-15 at 18:40:40 From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/libomp.rb License: MIT ==> Dependencies Build: cmake ✘ ==> Analytics install: 74,860 (30 days), 287,682 (90 days), 1,137,922 (365 days) install-on-request: 9,817 (30 days), 34,605 (90 days), 129,933 (365 days) build-error: 0 (30 days) cmake ✘ のところが何か悪いのかな
Avatar
omochimetaru 6/16/2021 3:53 AM
それはbrewでcmakeを入れてないからビルドはできないよって事じゃないですかね?
3:53 AM
brewってビルド済みのバイナリを直接取ってくる仕組みがあるんで
3:53 AM
影響をうけていないのだと思います
3:54 AM
やったことないけど、何か指定すれば、ソース取ってきて手元でビルドしてインストールできるんだろう。
Avatar
ビルド済みのバイナリがまだ x86_64 しかサポートしてないってことですかね?
3:57 AM
https://formulae.brew.sh/api/bottle-linux/libomp.json "arm64_big_sur" という文字列はあるんだけども🤔
Avatar
omochimetaru 6/16/2021 3:59 AM
bottlesがbrewのバイナリ配布の仕組みの名前ですね。ある感じですねえ。
3:59 AM
armってあれか、最近出たM1マックのためか
3:59 AM
あーじゃあbrewはまだユニバーサルバイナリ対応は普通は無いのかな??
Avatar
それだと思います
Avatar
omochimetaru 6/16/2021 4:00 AM
期待してるのは bigsur のパッケージに、 x64/armのユニバーサルバイナリが入ってることですけど
4:00 AM
これ見る限り、 arm64_big_sur がOSとして別れているので
Avatar
bottleがユニバーサルバイナリを配布するかどうかはforumla依存じゃないかなぁ
Avatar
omochimetaru 6/16/2021 4:01 AM
big_sur 向けには armは入って無さそう。
Avatar
arm64向けが別に配布されてるなら手元でx64向けとくっつけることができそう (edited)
Avatar
ふむふむ…少し事情が分かってきました.
Avatar
Avatar
Yuta Saito
arm64向けが別に配布されてるなら手元でx64向けとくっつけることができそう (edited)
omochimetaru 6/16/2021 4:06 AM
それいいね。
Avatar
とりあえず僕のケースでは Swift PM でなんとかしようとするのはやめて,OMP を有効にしたいときは swift build / run でアーキテクチャも指定した上で直接実行する,という感じにしようと思います! (edited)
👍 1
Avatar
omochimetaru 6/16/2021 4:07 AM
改善してほしい場合は bugs に要望として状況とともに報告するのがいいですね Package.swiftにアーキテクチャの概念をいれてくれって
Avatar
$ swift run -c release -Xcc -DSWM_USE_OMP -Xcc -I/usr/local/opt/libomp/include/ -Xcc -Xpreprocessor -Xcc -fopenmp -Xlinker -lomp -Xlinker -L/usr/local/opt/libomp/lib/ --triple x86_64-apple-macosx mt-enabled: true threads: 4 すごい,できた🙌
Avatar
omochimetaru 6/16/2021 4:44 AM
-Xcc -Xpreprocessor -Xcc
ここ間違ってませんか?
4:44 AM
-X<foo> <foo向けオプション> って指定するものだから
Avatar
swift run -c debug -Xcc -I/usr/local/opt/libomp/include/ -Xpreprocessor -fopenmp -Xlinker -lomp -Xlinker -L/usr/local/opt/libomp/lib/ --triple x86_64-apple-macosx こうすると, error: Missing value for '-c <configuration>' と出ます. (edited)
4:46 AM
-Xpreprocessor -fopenmp を C のコンパイラに渡さないといけないから,両方 -Xcc しなきゃいけないのかなと思いました. (edited)
Avatar
omochimetaru 6/16/2021 4:47 AM
あー Cコンパイラで -Xpreprocessor -fopenmp になって、 さらにその先のプリプロセッサに -fopenmp が渡るのか。
Avatar
多分そうですw
Avatar
omochimetaru 6/16/2021 4:47 AM
-fopenmp が Cコンパイラ向けオプションかと思ってましたが、なるほど。あってそう。
Avatar
Mac で実行するときは -Xpreprocessor をつけないといけないみたいです.Linux ではいらないんだとか.
4:49 AM
https://stackoverflow.com/a/60564952/1249157
You can also use OpenMP with Apple Clang and Homebrew libomp (brew install libomp). Just replace a command like clang -fopenmp test.c with clang -Xpreprocessor -fopenmp test.c -lomp.
(edited)
👀 1
4:50 AM
だいぶ希望が見えてきました✨
Avatar
SPMでのC/C++ライブラリのパッケージング極めたい… (特にアーキテクチャ関係ない内容で悩みまくったので) (edited)
Avatar
作っているアプリをuniversal(iPadでフルスクリーンにするか or iPadでもiPhone用の画面にするか)にしてApp Storeに表示するかしないかって、Xcode のTARGETED_DEVICE_FAMILYで決まるんですかね?
3:02 AM
それともAppStoreConnectになんか設定あります?
Avatar
Kishikawa Katsumi 6/18/2021 4:52 AM
Device familyで決まる、で合ってるはずです。たしか。
Avatar
ありがとうございます!
Avatar
アプリの初回リリース時のことについて教えて頂きたいです。 AppStoreConnectには既にアップロード済みだが まだ初回リリースしてないアプリについて、リリース前に アプリのストアのURLを、取得する方法はあるのでしょうか? 用途としては、レビューや強制アップデートなどで ストアに飛ばしたいので、初回リリース前にストアのURLを知りたいです。 宜しくお願い致します。
Avatar
Avatar
飯塚
アプリの初回リリース時のことについて教えて頂きたいです。 AppStoreConnectには既にアップロード済みだが まだ初回リリースしてないアプリについて、リリース前に アプリのストアのURLを、取得する方法はあるのでしょうか? 用途としては、レビューや強制アップデートなどで ストアに飛ばしたいので、初回リリース前にストアのURLを知りたいです。 宜しくお願い致します。
App Store Connect の この画面にある「App Storeで表示」からストアのURLを確認できたと思います
Avatar
Avatar
koogawa
App Store Connect の この画面にある「App Storeで表示」からストアのURLを確認できたと思います
@koogawa 見落としていました・・・ 確認できました!迅速なご回答ありがとうございました!
👍 1
Avatar
こんばんは、カスタムビューについての質問です。 カスタムビュー上にTextViewやTextFieldを配置しています。 カスタムビューのクラス内で TextViewにプレースホルダーの機能が欲しかったので、textViewDidChangeメソッドにテキストが空のときにPlaceHolder用のLabelを表示する処理や 改行を押した時に次のフィールドに移る処理など幾つかの処理を書いています。 そのカスタムビューを呼び出した側のクラスでtextViewDidChangeメソッドに追加処理を加えたくてdelegateを設定すると、カスタムビューのクラスの方に書いた上記の処理が動かなくなりました。 これはdelegateの仕様上1つのクラスに対してしか使用できないという事でしょうか。 どうにかして元の処理(カスタムクラスの内の処理)をそのままにして、呼び出した側のクラスでtextViewDidChangeのメソッドに追加処理を書く事はできますか。ご教示ください。
Avatar
omochimetaru 7/5/2021 1:08 PM
delegateは一つしか設定できないので異なる目的で2箇所から設定しようとしていると破綻しますね。 難しいしややこしくなるのでオススメはしないけど方法はあります。 TextViewを継承して、delegate プロパティの getter と setter をオーバーライドして、別のプロパティ (userDelegate など) として保存して、本来の super.delegate プロパティに、自前のデリゲートオブジェクト(今プレースホルダの実現に使ってるやつ)を渡します。 自前のデリゲートオブジェクトは、各種デリゲートメソッドの呼び出しを実装して、 userDelegate のメソッドも呼ぶようにすれば、ユーザー側からは普通にデリゲートが使えてるように見えます。
Avatar
TwitterのOSSに当該機能が実装されているので https://github.com/twitter/TwitterTextEditor 参考にしてみると良いかも
A standalone, flexible API that provides a full-featured rich text editor for iOS applications. - twitter/TwitterTextEditor
1:08 PM
面倒ならそのまま使っちゃうのもヨシ
Avatar
Kishikawa Katsumi 7/5/2021 1:30 PM
UITextViewとUITextField?なら、 UITextViewはデリゲートと同じNotificationがあるのでカスタムビューの方ではNotificationを使って変更に反応する手もあります。それなら1対多で使えるし、呼び出し先のクラスでデリゲートを使ってもデリゲートは使ってないので問題ないです。 UITextFieldの方はデリゲートと完全に同じではないですがtarget-actionでeditingChangedのイベントがあるので(たぶんやりたいことはできるはず)そっちを使うと、デリゲートに頼らずにできます。
Avatar
R.swiftで % を出力したいですがなかなかうまくいかない 😇 何かいい方法ありますか? やりたいこと:R.string.url()http%3A%2F%2Fwww.abc.xyz やってみたこと: 1. "url" = "http%3A%2F%2Fwww.abc.xyz"; :普通に %3A を引数にパースしてしまって url(Double, Double, Double) が求められちゃう 2. "url" = "http%%3A%%2F%%2Fwww.abc.xyz";:なぜか出力自体も %% になってしまう 3. "url" = "http\%3A\%2F\%2Fwww.abc.xyz";:1と同じ結果になってしまう 4. "url" = "http\U00253A\U00252F\U00252Fwww.abc.xyz";:1と同じ結果になってしまう (edited)
Avatar
omochimetaru 7/6/2021 7:30 AM
R.swiftの仕様をなんもしらんけど,エスパーで、3の亜種でバックスラッシュを \\ と2個並べるとどうですか? (edited)
👀 1
Avatar
一個でも埋めないといけないものがある時だけ String(format:) を通るみたいなので、2.の手法+一個ダミーの %@ を入れておいて運用でカバーするとか…? (edited)
👀 1
Avatar
Avatar
omochimetaru
R.swiftの仕様をなんもしらんけど,エスパーで、3の亜種でバックスラッシュを \\ と2個並べるとどうですか? (edited)
ダメでしたね、1とかと同じです
😔 1
Avatar
Avatar
rinsuki
一個でも埋めないといけないものがある時だけ String(format:) を通るみたいなので、2.の手法+一個ダミーの %@ を入れておいて運用でカバーするとか…? (edited)
うーん多分これR.swift使わない方法ですよね…?
Avatar
わざと余分な%@を入れて、""を埋めるようにする、ということかと
Avatar
Avatar
lovee
うーん多分これR.swift使わない方法ですよね…?
いや使う方法です。"url" = "http%%3A%%2F%%2Fwww.abc.xyz%@" とかにしておいて運用は R.string.url("") とかで誤魔化す
Avatar
Avatar
rinsuki
いや使う方法です。"url" = "http%%3A%%2F%%2Fwww.abc.xyz%@" とかにしておいて運用は R.string.url("") とかで誤魔化す
ああなるほど、試してみます 👍
7:42 AM
無事行けたっぽいです!ありがとうございます!
Avatar
Avatar
Kishikawa Katsumi
UITextViewとUITextField?なら、 UITextViewはデリゲートと同じNotificationがあるのでカスタムビューの方ではNotificationを使って変更に反応する手もあります。それなら1対多で使えるし、呼び出し先のクラスでデリゲートを使ってもデリゲートは使ってないので問題ないです。 UITextFieldの方はデリゲートと完全に同じではないですがtarget-actionでeditingChangedのイベントがあるので(たぶんやりたいことはできるはず)そっちを使うと、デリゲートに頼らずにできます。
その方法って、textFieldShouldReturn( textField: UITextField) やtextViewDidBeginEditing( textView: UITextView)とかもデリゲート無しでいけますか。
Avatar
didBeginEditingはいけますが、shouldReturnは無理ですね https://developer.apple.com/documentation/uikit/uitextfield
Avatar
Kishikawa Katsumi 7/6/2021 10:31 AM
textFieldShouldReturnでfalseを返す、みたいなのは無理ですがタイミングだけなら editingDidEndOnExit がだいたい同じはずですね。 editingDidEnd も併用するとPlaceholderはDelegateなくても実装できると思います。
Avatar
TwitterTextEditor ときいて
3:32 PM
placeholder は汎用的なの真面目につくると大変です
3:34 PM
改行でつぎのフィールドは、改行文字の貼り付けとかにもちゃんと対応する必要があります
3:34 PM
どちらも TwitterTextEditor に関連するコードはいってるので参考にしてください
3:34 PM
delegate の重複はproxy書くしかないです
Avatar
App Store ConnectのAppアナリティクスの 見方について教えて頂きたいです 1.現在のアプリのインストール数は、当画面のAppユニット数(この画面だと27)で合ってますでしょうか? 2.Appユニット数のパーセントの意味合いが知りたいです(この画面だと-25%) 3.現時点で、7/7日のデータが取得できないですが、取得できるようになるタイミングはどこかに明記されているでしょうか? いずれも、以下のドキュメントを元に探したのですが 見つけられなかったので、ご教示頂けると幸いです。 https://help.apple.com/app-store-connect/#/itc623752a8d
Avatar
Avatar
飯塚
App Store ConnectのAppアナリティクスの 見方について教えて頂きたいです 1.現在のアプリのインストール数は、当画面のAppユニット数(この画面だと27)で合ってますでしょうか? 2.Appユニット数のパーセントの意味合いが知りたいです(この画面だと-25%) 3.現時点で、7/7日のデータが取得できないですが、取得できるようになるタイミングはどこかに明記されているでしょうか? いずれも、以下のドキュメントを元に探したのですが 見つけられなかったので、ご教示頂けると幸いです。 https://help.apple.com/app-store-connect/#/itc623752a8d
1.現在のアプリのインストール数は、当画面のAppユニット数(この画面だと27)で合ってますでしょうか?
あってます。 詳細: https://help.apple.com/app-store-connect/?lang=ja#/dev9bb29239b
2.Appユニット数のパーセントの意味合いが知りたいです(この画面だと-25%)
前期間からの増減比ですね。これの例だと6/24-6/29間のユニット数と比較して25%減少したということだと思います。
3.現時点で、7/7日のデータが取得できないですが、取得できるようになるタイミングはどこかに明記されているでしょうか?
明記はされていなかったと思いますが、大体2日遅れで取得できるようになる印象です。
Avatar
Avatar
koogawa
1.現在のアプリのインストール数は、当画面のAppユニット数(この画面だと27)で合ってますでしょうか?
あってます。 詳細: https://help.apple.com/app-store-connect/?lang=ja#/dev9bb29239b
2.Appユニット数のパーセントの意味合いが知りたいです(この画面だと-25%)
前期間からの増減比ですね。これの例だと6/24-6/29間のユニット数と比較して25%減少したということだと思います。
3.現時点で、7/7日のデータが取得できないですが、取得できるようになるタイミングはどこかに明記されているでしょうか?
明記はされていなかったと思いますが、大体2日遅れで取得できるようになる印象です。
返信頂きありがとうございます! 2は確かに計算してみたら仰る通りの数字になっていました・・・。 3についても、2・3日遅れで取得できるイメージだったので 明記されてるものがないか、改めて調べてみたのですが、やはり明記はされていないですよね。 非常に助かりました!ありがとうございます!
👍 1
Avatar
Miwa / Ensan 7/7/2021 2:56 PM
Xcode13 beta1だとこれがエラーなんですが、なぜか分かりません・・・。 struct Test { func test() async { async let x = 42 // Immutable value 'x' may only be initialized once print(await x) print(await x) } }
Avatar
Avatar
Miwa / Ensan
Xcode13 beta1だとこれがエラーなんですが、なぜか分かりません・・・。 struct Test { func test() async { async let x = 42 // Immutable value 'x' may only be initialized once print(await x) print(await x) } }
おそらく async は非同期に値をセットする宣言なので、対象が実質「変数」でなくてはならないですが、let で宣言してるのは「定数」ですね; まあ多分 lazy var がOKで lazy let はNGと同じ理由かと
Avatar
Miwa / Ensan 7/8/2021 12:18 AM
ありがとうございます。ただ、以下のコードは動いていて、2回await xを書くとエラーになります。 struct Test { func test() async { async let x = 42 print(await x) } } (edited)
Avatar
@swift-main -Xfrontend -enable-experimental-concurrency struct Test { func test() async { async let x = 42 print(await x) } } (edited)
Avatar
swiftNightly BOT 7/8/2021 1:47 AM
no output
Avatar
@swift-main -Xfrontend -enable-experimental-concurrency struct Test { func test() async { async let x = 42 // Immutable value 'x' may only be initialized once print(await x) print(await x) } }
Avatar
swiftNightly BOT 7/8/2021 1:48 AM
exit status: 1 with stderr:<stdin>:3:15: error: immutable value 'x' may only be initialized once async let x = 42 // Immutable value 'x' may only be initialized once ^ <stdin>:3:19: note: initial value already provided in 'let' declaration async let x = 42 // Immutable value 'x' may only be initialized once ^ <stdin>:3:15: note: change 'let' to 'var' to make it mutable async let x = 42 // Immutable value 'x' may only be initialized once ^~~ var
Avatar
@swift-main -Xfrontend -enable-experimental-concurrency struct Test { func test() async { async let x = 42 print(await x) print(x) } }
Avatar
swiftNightly BOT 7/8/2021 1:49 AM
exit status: 1 with stderr:<stdin>:5:9: error: expression is 'async' but is not marked with 'await' print(x) ^~~~~~~~ await <stdin>:5:15: note: reference to async let 'x' is 'async' print(x) ^
Avatar
@swift-main -Xfrontend -enable-experimental-concurrency struct Test { func test() async { async let x = 42 let x2 = await x print(x2) print(x2) } }
Avatar
swiftNightly BOT 7/8/2021 1:50 AM
no output
Avatar
@swift-main -Xfrontend -enable-experimental-concurrency struct Test { func foo() async -> Int { 42 } func test() async { async let x = foo() print(await x) print(await x) } }
Avatar
swiftNightly BOT 7/8/2021 1:52 AM
exit status: 1 with stderr:<stdin>:4:15: error: immutable value 'x' may only be initialized once async let x = foo() ^ <stdin>:4:19: note: initial value already provided in 'let' declaration async let x = foo() ^ <stdin>:4:15: note: change 'let' to 'var' to make it mutable async let x = foo() ^~~ var
Avatar
Avatar
Miwa / Ensan
ありがとうございます。ただ、以下のコードは動いていて、2回await xを書くとエラーになります。 struct Test { func test() async { async let x = 42 print(await x) } } (edited)
仕様なのかバグなのかわかりませんが、 async let x に対して await x は現状 1 回だけ呼び出せるみたいですね。
2:01 AM
これっぽいです
👀 2
2:01 AM
バグみたいですね
Avatar
なるほど。直るまでは↑の x2 みたいにして使うしかなさそうですね。
Avatar
Miwa / Ensan 7/8/2021 2:05 AM
確かに一度代入してしまえば良さそうです、ありがとうございます
Avatar
このレポート、 2 days ago だからめっちゃホットですね。
Avatar
Miwa / Ensan 7/8/2021 2:06 AM
@swift-main -Xfrontend -enable-experimental-concurrency struct Test { func left() async -> String { "l" } func right() async -> String { "r" } func test() async { async let (l, r) = (left(), right()) print(await l) print(await r) } }
Avatar
swiftNightly BOT 7/8/2021 2:06 AM
exit status: 1 with stderr:<stdin>:6:15: error: immutable value 'l' may only be initialized once async let (l, r) = (left(), right()) ^ <stdin>:6:20: note: initial value already provided in 'let' declaration async let (l, r) = (left(), right()) ^ <stdin>:6:15: note: change 'let' to 'var' to make it mutable async let (l, r) = (left(), right()) ^~~ var <stdin>:6:15: error: immutable value 'r' may only be initialized once async let (l, r) = (left(), right()) ^ <stdin>:6:23: note: initial value already provided in 'let' declaration async let (l, r) = (left(), right()) ^ <stdin>:6:15: note: change 'let' to 'var' to make it mutable async let (l, r) = (left(), right()) ^~~ var
Avatar
Miwa / Ensan 7/8/2021 2:07 AM
このバグに加えてawait lと同時にrawaitされる挙動のせいでかなりトリッキーになる
Avatar
Avatar
Miwa / Ensan
Xcode13 beta1だとこれがエラーなんですが、なぜか分かりません・・・。 struct Test { func test() async { async let x = 42 // Immutable value 'x' may only be initialized once print(await x) print(await x) } }
beta5で直ってました、万歳🙌
Avatar
@KIRUA SP#JP1 https://discordapp.com/channels/291054398077927425/291054398077927425/877133063602208838 ↑こういう質問でしたらこちらのチャンネルが適切かと思われます; また、例として出している問題は見る限り何かのテストのように思いますが、それならおそらくその問題に対応する何かのテキストがあるはずかと思いますが、そう言ったものはないでしょうか?そしてそもそも今なにでSwiftの勉強をされているでしょうか?
👍 1
Avatar
教えて頂きたいです。 iOS15から、アプリを跨いでテキストや画像をドラッグドロップが 可能になるとのことですが、アプリ単位でこのドラッグドロップを disableにする方法はあるのでしょうか? そのようなプロパティが見つけられず、解決策をご存知でしたらご教示下さい。 https://japanese.engadget.com/ios15-drug-and-drop-120008487.html
次期iOS 15では画像やテキスト、ファイルなどをアプリ間でドラッグ&ドロップ可能になることが明らかとなりました。
Avatar
iOS14までのDnDの実装はUIInteractionを使っていて https://developer.apple.com/documentation/uikit/uiinteraction これはUIView.interactionsに含まれていて、これを削除することでDnDの動きを抑制することが出来ていましたが、今回のiOS15でもこのテクニックは有効でしょうか?
11:50 AM
15では試したことがないので確認していただければ
Avatar
Avatar
tarunon
iOS14までのDnDの実装はUIInteractionを使っていて https://developer.apple.com/documentation/uikit/uiinteraction これはUIView.interactionsに含まれていて、これを削除することでDnDの動きを抑制することが出来ていましたが、今回のiOS15でもこのテクニックは有効でしょうか?
返信ありがとうございます! UIInteraction知らなかったです・・・試して確認してみます!
Avatar
Avatar
飯塚
返信ありがとうございます! UIInteraction知らなかったです・・・試して確認してみます!
もし良ければ試した結果も共有していただけると嬉しいです!
Avatar
SwiftPackageとして提供されているライブラリを手軽にxcframeworkとしてビルドしておく方法は存在しますか? 動機としてはクリーンビルドするたびにSwiftPackageとして導入したRealmのビルドが走ってしまい、長時間待たされるという状況を回避したいというものです。 結局Swift Package Managerで導入するのは諦めてCarthageで--use-xcframeworkオプションを使う形にしたのですが、せっかくならSPMを活用したいとなぁと考えております…
Avatar
確認ですが、XcodeのSPM機能を直接利用されてる感じでしょうか?
Avatar
XcodeのSPM機能を直接利用されてる
はい、その通りです。Xcodeの「Add Package Dependency...」で追加したものになります。
Avatar
恐らくですが、その構築だとクリーンビルドでライブラリ側が再ビルドになるのは防げないんじゃ無いかなと思います Package.swiftを使って依存を追加する方法がありますので、そちらを参考に構成を変えてみたら改善するかも?(ちょっと試してないので半信半疑ですが)
Avatar
omochimetaru 8/24/2021 8:32 AM
swiftpm構成でもcleanは伝搬する気がする。
Avatar
そしたら厳しいですねぇ
Avatar
omochimetaru 8/24/2021 8:33 AM
で、XCFrameworkを作るためにはxcodeprojが必要なので、
8:33 AM
一般論としては「SwiftPackageとして提供されているライブラリ」のxcframworkをつくるためには
8:33 AM
自分でxcodeproj作らないといけない
8:33 AM
個別回答としては、Realmの場合、xcodeprojは既にありそう。
Avatar
UmbrellaPackageのxcodeprojを作って、そこから成果物としてxcframeworkをはき出して、それをimportする、までやれば
Avatar
omochimetaru 8/24/2021 8:33 AM
でもそのxcodeprojの中にxcframeworkを作る設定のtargetはないだろうから、手はいれないとだめそう。
Avatar
本体側のcleanbuildは伝播しないんじゃないだろうか
Avatar
omochimetaru 8/24/2021 8:34 AM
ああ、なるほど。手で置いてるなら伝搬しないと思う。
8:35 AM
↑SwiftSyntaxというSwiftPM性のライブラリを、xcframeworkにしたくて、
8:35 AM
xcframeworkにするために頑張ったプロジェクトです
8:35 AM
OS同梱の特殊なライブラリまで出荷しようとしているので、より複雑なことをやってますが、参考になるかも・・・?
Avatar
omochimetaru 8/24/2021 8:36 AM
https://github.com/omochi/BinarySwiftSyntax ↑その成果物が落ちてくるxcframework配布版のSwiftPMパッケージ
Contribute to omochi/BinarySwiftSyntax development by creating an account on GitHub.
8:36 AM
まあ結論としては大変なので簡単な方法はないかも
Avatar
Realmが配布してるxcframeworkをbinaryTargetとして使うと良い気がします
😆 1
Avatar
Kishikawa Katsumi 8/24/2021 8:37 AM
Realmに関していうとXCFrameworkは公式のがあります。タイプミスしてるうちに重なった 😅
😂 1
Avatar
確かに。そういえばCarthageのやつもxcframeworkダウンロードしてくるだけでした。
Avatar
SPMで直接指定できるのかな。良さそう
Avatar
自分でbinaryTargetを追加したPackage.swiftを書いてそれをXcodeに見せるというイメージであっていますか?
Avatar
Realmのxcframeworkのzipがこれと互換性あるかは把握してないのですが
Avatar
Avatar
trickart
自分でbinaryTargetを追加したPackage.swiftを書いてそれをXcodeに見せるというイメージであっていますか?
はいその通りです
🙇‍♂️ 1
Avatar
XcodeのGUIだと指定できないのかな?
Avatar
できないんじゃ無いですかね。少なくともローカルパッケージ一つ必要な気がする
Avatar
omochimetaru 8/24/2021 8:39 AM
xcodeから登録するときはローカルパッケージ使えたっけ?
Avatar
ドラッグ&ドロップで行けた気がします
8:40 AM
フワフワした記憶なので確かめてほしい…w
Avatar
omochimetaru 8/24/2021 8:41 AM
まあ少なくともインターネットURLのあるところにホストすればいけますね (edited)
Avatar
Package.swift周りはdateくんの記事めちゃくちゃ良いのでオススメで、私がボイラープレートにしたのがあるので、参考に出来るかも。 https://github.com/tarunon/ios_boilerplate
Contribute to tarunon/ios_boilerplate development by creating an account on GitHub.
👀 1
8:43 AM
大元はisowordsなのでそっちを直参照でも良いかもです
Avatar
gitで引っ張ってくる形だからプライベートリポジトリでも行けるはず…? 何かいい感じにできそうな気がしてきました。皆さん回答有り難うございました! hyper-modularization構成は面白そうですよね(iOSDCが楽しみ)
👍 1
🙌 1
Avatar
Avatar
omochimetaru
xcodeから登録するときはローカルパッケージ使えたっけ?
これはできますね、ドラッグアンドドロップで追加できます
😍 1
😮 1
8:54 AM
pbxproj的には XCSwiftPackageProductDependency という名前で登録されてるっぽい (edited)
Avatar
Package.swiftに対して xcodebuild で操作できるっぽいので、自前でxcframework化もいける?
11:37 AM
ストアアップロードのバリデーションでコケたりも有り得そうなので単純にはいかなそうですが…
Avatar
Miwa / Ensan 9/6/2021 1:43 AM
Xcode13 beta5でApp Storeに提出しようとすると、Validationで「App Store Connect Operation Error: Unable to process app at this time due to a general error」と言われて失敗するのですが、同じ症状の方いますか?
1:43 AM
general errorとしか言われないので、どうすればいいのか全然わからない・・・
Avatar
そもそもbeta版で提出はできなかったはずなので、それによるエラーな気がします
Avatar
Miwa / Ensan 9/6/2021 1:44 AM
え!そうなのか
Avatar
omochimetaru 9/6/2021 1:44 AM
同じことを言おうとしました ベータはサブミットできない
Avatar
GM版できるようになるんでしたっけ
Avatar
Miwa / Ensan 9/6/2021 1:44 AM
じゃあみなさん正式版が出てから提出してるんですか?
Avatar
毎年、Xcode のベータが外れる頃に提出できるようになるはずです
Avatar
Miwa / Ensan 9/6/2021 1:45 AM
なるほど
Avatar
時期的にはAppleの発表イベントと同時にiOSのリリース日が告知されて、イベント後にGM版出てきて、iOSのリリース日までに一斉にみんな提出って流れだった気がします (edited)
🙏 1
Avatar
omochimetaru 9/6/2021 1:47 AM
リリース版とベータ版のどちらでもビルドできるようにしておいて
1:47 AM
ベータ版がリリース版になったら再提出
🙏 1
Avatar
Xcode 13 でビルドしたアプリの受付が開始されたら、Apple からアナウンスがあるはずです ↓参考:昨年は9/16 辺りにアナウンスが出てました https://twitter.com/koogawa/status/1305994820461109248
アップルからも公式アナウンスが出てますな。Xcode 12 GM seed でビルドしたアプリの受付を開始
You can now submit apps built with Xcode 12 GM seed using the SDK for iOS 14 GM seed, tvOS 14 GM seed, and watchOS 7 GM seed to the App Store.
https://t.co/ZquIuWwSaF
👍 1
🙏 1
Avatar
Miwa / Ensan 9/6/2021 1:48 AM
1日困っていたのがあっさり解決しました、ありがとうございます
👍 4
Avatar
omochimetaru 9/6/2021 1:53 AM
今回のバージョンの場合、async awaitとか、@MainActor アトリビュートとか
1:53 AM
全く新しい文法が追加されていて、しかもそれは多くの部分に出現するので
1:54 AM
クロスビルドできるコードを書くのが無理な気がしますね。
Avatar
Miwa / Ensan 9/6/2021 1:58 AM
そうですね、あと1,2週間だと思うので素直に待つことにします😅
Avatar
Xcode 13 RCでApp Store に提出できるようになりましたね😀 iOS 15およびiPadOS 15向けAppのApp Store提出の受付開始 - ニュース - Apple Developer https://developer.apple.com/jp/news/?id=f87q5n2j
世界最先端のモバイルオペレーティングシステムであるiOS 15とiPadOS 15が世界中のユーザーに近日中に公開されます。Swift非同期関数を活用してコードをリファクタリングし、Appのパフォーマンスを向上させましょう。SwiftUIを利用すれば、リスト表示や検索機能を改善し、フォーカスコントロールエリアのサポートを提供できます。その他、新しい通知APIの利用やSafari Web Extensionの提供など、さまざまな利点があります。Xcode 13リリース候補版でAppをビルドし、iOS 15およびiPadOS 15のリリース候補版を実行するデバイスでテストした上、審査に提出しましょう。2022年4月以降、App Storeに提出するiOSおよびiPadOS Appはすべて、...
👍 1
Avatar
Miwa / Ensan 9/15/2021 1:22 AM
なるほど!こういう流れなんですね
💪 1
Avatar
こんばんは、質問があります。TextViewの編集中にカーソルが画面外に行くまでスクロールしてからカーソル位置を変更するとカーソルの位置は変更されるのですが、スクロールが元のカーソルの位置に戻ってしまう現象に悩まされています。これを回避する方法はありますか。 teratailにGIFを載せています↓ https://teratail.com/questions/357940 (edited)
TextViewで編集している時に起きる挙動についてです。現在のカーソル位置から画面外(スクロールしないと見えない行)の場所にカーソルを移動させた際に、カーソル位置は変更されるのですがスクロールが何故かその下のカーソル位置に戻されてしまいます。このスクロールが戻されてしまうのは何が原因なのでしょうか
Avatar
Avatar
Ryota
こんばんは、質問があります。TextViewの編集中にカーソルが画面外に行くまでスクロールしてからカーソル位置を変更するとカーソルの位置は変更されるのですが、スクロールが元のカーソルの位置に戻ってしまう現象に悩まされています。これを回避する方法はありますか。 teratailにGIFを載せています↓ https://teratail.com/questions/357940 (edited)
こちらの内容と同じ状態にあると思われます。 https://developer.apple.com/forums/thread/662056
Avatar
Avatar
Ryota
こちらの内容と同じ状態にあると思われます。 https://developer.apple.com/forums/thread/662056
UITextView自体のバグに見えますね ちょっとデメリット大きいんで良く考えてやらないとですが、UITextViewの.isScrollEnabledを無効にして、UIScrollViewの中に貼ったら回避できそうです。 デメリットですが、全てのテキストがレンダリングされてしまうので、巨大なテキストを扱うのには向いていません。
Avatar
UITextView と聞いて
Avatar
先生…!
Avatar
あー、カーソル位置が取れないやつでしょ
1:43 AM
これバグ
Avatar
これは強制スクロールですね
Avatar
run loop回さないとダメなんだけど、回してないから古い位置を取ってきて
1:43 AM
そこにスクロールしてるんじゃないかなぁ。
Avatar
カーソルが出てるときに、カーソルが動いてなくても、その位置に勝手にスクロールされる。本来は、カーソルが動いたときだけスクロールして欲しい
Avatar
む、ちょっと勘違いしてるかも。
1:45 AM
scroll view in scroll view になってるってことかな。
Avatar
UITextView単体で壊れてそうな感じですね
1:46 AM
条件は何かしらあるかもしれない
1:46 AM
手元のプロジェクトにパッと埋め込んで再現したのは
Avatar
GIFをみると、カーソルの位置を移動すると、そのイベントでスクロールが発生して一個前の位置に戻ってしまう感じ?
Avatar
VStack→ZStack→UITextView(UIViewRepresentable) ですね
1:47 AM
根っこをUITextViewにして再現するか試すか
Avatar
なるほど、その入れ子か…
Avatar
ルートをUITextViewにしたらキーボードのinsetが考慮されなくなったw(代わりに発生しなくなった)
1:53 AM
そして、VStack→ZStack→ScrollView→UITextView(UIViewRepresentable, isScrollEnabled=false) なら治るようでした (edited)
Avatar
scroll view in scroll view の問題っぽいなあ。
1:56 AM
その状態でcursor動かすとscroll viewはスクロールするんだろうか。
Avatar
Avatar
niw
GIFをみると、カーソルの位置を移動すると、そのイベントでスクロールが発生して一個前の位置に戻ってしまう感じ?
SwiftUI入りだと、カーソル移動無くてもつねにねっとりスクロールが発生していました🤕
1:59 AM
間にScrollView挟むようにしたら、カーソル移動時のスクロールは一見大丈夫なように見えています
2:00 AM
カーソル移動時じゃないや、文字入力時にしか移動しなくなってるな
Avatar
TextEditor() だとどう?
Avatar
やってみましょうか
Avatar
やってみた感じ大丈夫そう...?
Avatar
カーソル移動も含めて完璧っぽいですね
Avatar
キーボード逃げるとかもやるんだよねえ。
2:06 AM
でも問題は14+でわりと機能が少ない
Avatar
TextEditorとTextFieldはマジで機能が足りないって言うか
2:07 AM
UITextInputで出来ていたあれこれが全部ないのでかなりキツい
Avatar
発生条件がなぞいなあ
Avatar
これ僕が再現させたのも同じものかはちょっと定かではないですね…
Avatar
VStackに入れるだけではおきない...?
Avatar
SwiftUIに挟むと発生しますね
2:16 AM
えーと
Avatar
struct TextView: UIViewRepresentable { func makeUIView(context: Context) -> UITextView { UITextView() } func updateUIView(_ uiView: UITextView, context: Context) { } } struct ContentView: View { var body: some View { VStack { TextView() } } }
2:17 AM
これでおきる?
2:17 AM
一瞬それらしい挙動がおきたんだけど再現手順がわかってない
Avatar
何ならVStackも要らないかな
2:18 AM
var body: some View { MyTextViewWrapper() } これだけで発生します
Avatar
えー。
Avatar
一応delegate経由のtextのbindingはやってる
Avatar
ふむ...
2:21 AM
あー、bindingどうなってる?
Avatar
CoordinatorにUITextViewDelegate刺して、textViewDidChangeでtext投げるだけ、ですね
2:28 AM
あー、わかった
2:28 AM
すみません、、私の再現してるのは別物でした🤕
Avatar
reloadInputViews()を呼び出してその度にキーボードが動いてた
Avatar
あ、一回起きた
Avatar
どうも、キーボード側が動くとそれにつられてカーソル位置へのスクロールが発生していますね
Avatar
ふむー
Avatar
完全に勘違いしてかき回してしまった😭
Avatar
一回発生したのは、下までscrollしたあとに、scroll upしてカーソルを画面外にだしたあとに長押しで画面内にカーソルを戻して1文字入力で一番下までぶっとぶって感じだったな
2:33 AM
なお2度目はない模様
2:33 AM
本当に1回だけおこるな (edited)
2:34 AM
なんだこれ
2:35 AM
おー、updateUIView(_:context:)が呼ばれるのか。
2:35 AM
なんでだ。
Avatar
入力したときに、textViewDidChangeから外のState書き換えてます? (edited)
Avatar
あー、なんかwarning出てるかも (edited)
Avatar
State書き換わるとその結果が書き戻されるのでupdateUIViewは走りそう
Avatar
それかな。
2:37 AM
setText: すると変な位置にスクロールするのはknown behavior
Avatar
RxSwiftで似たような話があって
2:39 AM
textのstate変更はかなり仰々しい実装になってましたね
2:39 AM
とりあえずここ #beginner-help-archived なので、質問された方への解答をしないと
Avatar
その可能性が高い気がする。
2:40 AM
多分、 1. setText: (textView.text = なんちゃらtextView.attributedText = なんちゃら)が呼ばれていないかデバッガーで確認 (updateView(_:context:)のなかとか?) 2. 呼ばれているなら、呼ばないようにする 3. 呼ばれていないならさらなる調査が必要... (edited)
2:40 AM
かなあ。
Avatar
ぱっと見入力はしてなさそう?なので
Avatar
Avatar
niw
run loop回さないとダメなんだけど、回してないから古い位置を取ってきて
これなのかな?とも思いましたが
2:43 AM
カーソル移動時のスクロールがどうやって起きてるのか(OS標準なのか自前なのか)によっても話がかわりそう
Avatar
それだとしても、うーん、SwiftUIでおこるかなあ。
2:43 AM
iOSのバージョンによるのはあるかも
Avatar
(SwiftUI突っ込んでるのは僕が再現しようとしたもので質問された方の環境にいるとは限らない…)
Avatar
入力してなかっとしてもなんかのイベントでsetText:が走ってるのかもしれない
2:44 AM
それはわからないなあ。
2:44 AM
Scrollしたらstate変わるみたいなのがあるとか?
Avatar
https://github.com/ReactiveX/RxSwift/blob/dcc4795e2146c9207924f19592390b88354889ba/RxCocoa/iOS/UITextView%2BRx.swift#L20-L53 参考に、RxSwiftのTextBinding実装です。 自前でSwiftUIとの接続をやるなら、これを参考にするのが良い。
Reactive Programming in Swift. Contribute to ReactiveX/RxSwift development by creating an account on GitHub.
Avatar
Avatar
niw
多分、 1. setText: (textView.text = なんちゃらtextView.attributedText = なんちゃら)が呼ばれていないかデバッガーで確認 (updateView(_:context:)のなかとか?) 2. 呼ばれているなら、呼ばないようにする 3. 呼ばれていないならさらなる調査が必要... (edited)
@Ryota さん、これ確認してみてください
2:53 AM
RxSwift は textView.text != text とかやってるのか... (edited)
Avatar
!=のチェック実は必須で
Avatar
updateは呼ばれちゃうからそりゃそうだよな。
Avatar
.textの変更は副作用としてカーソル位置が末尾になるだったり、未変換のテキストが確定されるというのがあるので、同じものをセットしたとして同じ状態に遷移するとは限らない。
Avatar
setAttributedTextのwrapperだしねえ。
Avatar
Avatar
niw
@Ryota さん、これ確認してみてください
ご返信ありがとうございます。デバッガーでの確認方法がわからないので教えていただけないでしょうか。お手数おかけしますがよろしくお願いします。
Avatar
Avatar
Ryota
ご返信ありがとうございます。デバッガーでの確認方法がわからないので教えていただけないでしょうか。お手数おかけしますがよろしくお願いします。
例えば、symbolic breakpointでsetText:を作るとか、textView.text = が呼ばれている行にbreakpointを立てるとかそういう感じです。
4:14 AM
Avatar
Avatar
Ryota
ご返信ありがとうございます。デバッガーでの確認方法がわからないので教えていただけないでしょうか。お手数おかけしますがよろしくお願いします。
Avatar
Avatar
niw
例えば、symbolic breakpointでsetText:を作るとか、textView.text = が呼ばれている行にbreakpointを立てるとかそういう感じです。
ご教示ありがとうございます。 確認したところ、カーソル位置を変更したときに呼ばれていました。これを呼ばれないようにする方法はあるのでしょうか。
Avatar
おー、やはり。
5:09 AM
なぜそれが呼ばれるかわかりますか? debuggerで止まった時の stack trace (左側に表示される呼び出しの一覧)か、bt と入力して出る結果を共有してもらえればわかるかもしれません。
5:10 AM
(あと、多分、実際のコードがないと細かく何が原因かはわからないかも)
Avatar
Avatar
niw
(あと、多分、実際のコードがないと細かく何が原因かはわからないかも)
<UIMorphingLabel: 0x1509a3800; frame = (0 0; 0 0); text = ''; hidden = YES; opaque = NO; layer = <CALayer: 0x2809d3200>> <UILabel: 0x14ffc2020; frame = (187.5 31; 0 0); text = ''; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x282bde350>> <UISegmentLabel: 0x15134c500; frame = (0 0; 0 0); opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x282be0280>> 上記のログはまた違うものなのでしょうか。
Avatar
Avatar
Ryota
<UIMorphingLabel: 0x1509a3800; frame = (0 0; 0 0); text = ''; hidden = YES; opaque = NO; layer = <CALayer: 0x2809d3200>> <UILabel: 0x14ffc2020; frame = (187.5 31; 0 0); text = ''; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x282bde350>> <UISegmentLabel: 0x15134c500; frame = (0 0; 0 0); opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x282be0280>> 上記のログはまた違うものなのでしょうか。
とりあえず同じ挙動のものを作ったのでご確認いただけますと幸いです。 https://github.com/no-name241198/Scrolling_issues_in_UITextView
Contribute to no-name241198/Scrolling_issues_in_UITextView development by creating an account on GitHub.
Avatar
Avatar
Ryota
とりあえず同じ挙動のものを作ったのでご確認いただけますと幸いです。 https://github.com/no-name241198/Scrolling_issues_in_UITextView
再現手順ってありますか?
2:29 AM
あとこれSwiftUIの話ではなかったのですね。
2:31 AM
ぱっとみ、UIScrollViewにUITextViewが入ってるケースなので、isScrollEnabled を false にしてみると良いかなとは思います
Avatar
Avatar
niw
ぱっとみ、UIScrollViewにUITextViewが入ってるケースなので、isScrollEnabled を false にしてみると良いかなとは思います
SwiftUIじゃないんです。説明不足で申し訳ないです。 もう今の状態がそうなってると思います。TextViewの編集中にカーソルが画面外に行くまでスクロールしてカーソルの位置を変更するとスクロールの挙動がおかしくなると思われます。
Avatar
手元で試してみてるんですが、この実装だとそもそもカーソル移動ではスクロールは発生しなくて、テキスト入力が伴った場合だけスクロールするように思いますね
Avatar
なぜでしょうか、自分の方ではスクロールされるんです。 となると原因は環境の違いとか設定の問題ですかね。
4:06 AM
とりあえず、実機でテストしていたのでシミュレーターの方で確認してみます。
Avatar
ScrollView -> TextViewの入子にしない、これが一番かと思いますが、そうもいかないと思うので 1. mainView.isScrollEnabled = false をちゃんと入れておく 2. textViewDidChangeSelection でスクロールする実装を加える ということをやるんだと思います。
Avatar
2番について詳しくお聞きしたいです。 mainView.isScrollEnabled = false を書いてもスクロールはされてしまいます。
Avatar
textViewDidChangeSelectionでカーソルの位置を取得して、scrollView.scrollRectToVisibleで指定した位置までスクロールさせます。 このとき、レンダリングが完了していない状態だとカーソルの位置がズレたりするので https://discord.com/channels/291054398077927425/291211035438874625/890413051625500683 色々試行錯誤してみると良いと思います。 またUITextViewはちゃんと取り扱うのが難しい部類ではあるので、様々なワークアラウンドが実装済みのOSSを使うのも良いと思います。 https://github.com/twitter/TwitterTextEditor
A standalone, flexible API that provides a full-featured rich text editor for iOS applications. - GitHub - twitter/TwitterTextEditor: A standalone, flexible API that provides a full-featured rich t...
Avatar
↑このカーソルの位置取得でrunloopいっかい回さないとダメっていうのがあるんですよね (edited)
Avatar
初めて質問します。 画面横断で、エラー検知時にポップアップを出す方法について教えていただきたいです。 ・やりたいこと 画面に依存しない形で、実行している処理 (API実行)について、 エラーを検知したタイミングで、ポップアップのエラーを表示する(どの画面にいても表示される) 上記について、 自分では「アプリの全画面のコードに、エラー検知&ポップアップ表示の処理を愚直に仕込む」方法しか思いつかなかったので、もし他に効率的な方法や便利なライブラリありましたら知りたいです。 SwiftUIを使っていますが、UIKitでのやり方でもよいので参考にさせていただきたいです。どうぞよろしくお願いします。
Avatar
Avatar
tsuruaya
初めて質問します。 画面横断で、エラー検知時にポップアップを出す方法について教えていただきたいです。 ・やりたいこと 画面に依存しない形で、実行している処理 (API実行)について、 エラーを検知したタイミングで、ポップアップのエラーを表示する(どの画面にいても表示される) 上記について、 自分では「アプリの全画面のコードに、エラー検知&ポップアップ表示の処理を愚直に仕込む」方法しか思いつかなかったので、もし他に効率的な方法や便利なライブラリありましたら知りたいです。 SwiftUIを使っていますが、UIKitでのやり方でもよいので参考にさせていただきたいです。どうぞよろしくお願いします。
もっと良い方法があるかも(&何か問題があるかも)しれませんが、 UIWindow をとっておいて、その rootViewController を経由して表示するなどできると思います(経由してというのは、たとえばそれが UINavigationController であれば、さらに topViewController を取得するなどした方が良いかもしれません。ただ、とりあえず SwiftUI かつアラートを出す程度であれば、僕のアプリの構造(根っこで UIWindow を捕まえて↓の方法で保持し、 UIHostingController の中に NavigationView が入っている)の範囲内では UIWindowrootViewController を使って UIAlertControllerpresent するので動いています)。 なお、僕は SwiftUI で UIWindow を保持するのは↓の方法を採用しています。 https://qiita.com/shiz/items/3b829b1521f9723aa875 (edited)
iOS13で変わったこと iOS13以降ではiOSアプリでもマルチウィンドウで使えるようになり アプリの起動経路が変わりました。 ※ マルチウィンドウ自体はオプトインの仕組みで ONにするにはinfo.plistのUIAppl...
Avatar
具体の要件にもよりますが、「エラーを表示するためのコンテナView」を作って使い回すのが楽かも
1:45 AM
ErrorHandleProvider { errorHandler in Button(action: { do { try ... } catch { errorHandler(error) } }) { Text("try") } } ざっくりこんな感じのIFを定義するイメージ (edited)
Avatar
Avatar
tarunon
具体の要件にもよりますが、「エラーを表示するためのコンテナView」を作って使い回すのが楽かも
これは画面をまたぐ場合、どこに記述するのでしょうか? (edited)
Avatar
Navigationを定義してるViewがあればそこに
1:52 AM
Presentは跨げないので各々書く感じですかね
Avatar
それで動くのなら NavigationView.alert 書いても動きそう?
Avatar
動くかな?
Avatar
わかんないです。
Avatar
ただまあ一律処理みたいなのは結構罠なので避けた方が良いかもですね
1:55 AM
Error処理と十把ひとからげに言っても、実際にはエラーを告知して終わりなのか、リトライの選択肢があるのか、或いは致命的なので幾つか画面を戻らせるのか…etcと
1:55 AM
画面ややりたいことによって処理内容が異なるので
1:56 AM
そのパターン全てをSceneやWindowで何とかするよりは
1:56 AM
パターン毎のProviderを用意して画面毎に埋め込むのが無難な実装と思います
Avatar
バックグラウンドでダウンロードやアップロード処理を行っていて、エラーが発生したときのハンドリングはどうするのがいいでしょう?ローカル通知?
Avatar
非同期系のエラーは大体相場が決まっていて
1:58 AM
まずタスク一覧画面が存在していて、そこのステータスをエラーにする、というのが良くあるパターンですね
1:58 AM
これは画面にポップアップなどは出て来ない実装が多いと思います
Avatar
なるほど。
Avatar
返信いただきありがとうございます! 教えていただいた内容を咀嚼する&試す作業が数日後になりそうなため とりあえずお礼のみ伝えさせてください。 (初めてIT系のコミュニティ利用し、反応いただいて感動しました、ありがとうございます)
😆 2
Avatar
ちゃんと理解できていないのですが、Monterey でメモリ周りに何か変更があったようで Go 言語で実行時エラーが観測されています。 Appleが調査を行なっているという書き込みもありました。 https://github.com/golang/go/issues/49138#issuecomment-964473371
First, I know macOS Monterey is still beta. But this problem started after Monterey beta 2 21A5268h (beta 1 21A5248p works), and Apple has been released RC2, so posted (share) this issue. Note that...
Avatar
LLVM の TSAN 周りの話だったようです。パッチが当たりました https://reviews.llvm.org/D114825
Avatar
omochimetaru 12/1/2021 8:48 AM
すごいですねこれ
8:48 AM
Go on linux, darwin and freebsd on x86_64
8:48 AM
特にMonterey用のパッチには見えないし、ずっと間違ってたのかな
Avatar
Montereyのメモリアロケーションでこの辺のアドレスを予約して使うようになってみたいですね たまたま、TSAN が Go 言語用に予約していたアドレス帯と被ったようです 😅 (edited)
10:28 AM
go test -race で race detection を有効にしてテストを走らせることができるのですが、Monterey になってから -race 付けた時だけクラッシュするようになりました。ぼくはこの辺詳しくないですが、 go test -race が LLVM の TSAN を使っていたようです。 (edited)
Avatar
なるほど。OSの挙動的にこれまでは問題なかったけどMontereyがそこを使うようになって干渉が起きたのか。
Avatar
そうみたいですね
Avatar
Xcode 13.2 がリリースされて iOS 13.0+ に Swift Concurrency がバックデプロイされたので、さっそく個人アプリを対応しました。 https://github.com/uhooi/UhooiPicBook/pull/265 ですがかなり難しいですね…。 個人的には MainActor を使おうとすると頭がこんがらがってしまいます。 みなさんはどのような方針で Swift Concurrency に対応させますか? (例えばいつ頃対応するかや、UIViewController に @MainActor を付けるのはまだ行わない、など) あと私の PR(コード整形などが含まれていて見づらくなってしまいましたが、、)で気づいたことがあれば、ご指摘いただけると嬉しいです 🙏
Issue close #223 close #260 Overview Replace completion handler with Swift Concurrency. Checklist Format code with SwiftLint (⌘B in Xcode) Resolve Xcode warning What to check Is the usage o...
Avatar
ほとんどのケースでUI周りにMainActorを置くところから始めるのが幸せになれそう
Avatar
多分そうだと思いつつも、ちゃんと理解していなくて逆に苦しんでいます、、w
Avatar
async関数を作るよりも先に、ActorContextを整理した方が良くて、一番手っ取り早いのがMainActorを付けること、なので。 (edited)
Avatar
なるほど
6:20 AM
とりあえず主要な UIViewController には @MainActor を付けたのですが、UIView や AppDelegate などにも脳死で付けたほうがいいのかなぁ… (edited)
Avatar
UI周りは全部MainActorですよ
6:22 AM
親クラスがMainActorであっても、省略すると挙動が変わることがあるので、全部明示的に宣言しちゃって良いと思います。
👍 1
Avatar
親クラスがMainActorであっても、省略すると挙動が変わることがある
これ罠ですよね。意図的なのかなぁ
Avatar
意図的だとしたら最悪の仕様だと思う
Avatar
実行時の挙動が変わるんでしたっけ?コンパイル時検査だけではなく?
Avatar
コンパイル時検査ですね
6:24 AM
コンパイル時検査といっても、その検査の結果で実行時の挙動も変わりますが
Avatar
型検査だけだったとしても、現状明示的に宣言するにこしたことはないですね
Avatar
理論上の問題は無い気がするので意図的なのかもしれん。
Avatar
Swift 6を正座で待つ
Avatar
あるメソッドfが、@MainActor で保護されているとき、 そのメソッドは、MainActorからの呼び出し→そのまま 他のActorからの呼び出し→async化 というのが型としての挙動で それを継承したサブクラスが @MainActor では無かったとした場合 継承してオーバーライドしたメソッドは、 サブクラスのメソッドとしてみれば、保護が外れているので、 どこから呼び出してもそのままの挙動 つまり、マルチスレッドセーフなメソッドとして実装されているという仮定が置ける。 このマルチスレッドセーフなオーバーライド実装を、 スーパークラスのメソッドとしてアップキャストして見てみると、 @MainActor として保護されている事になるけど、 MainActorからの呼び出し→マルチスレッドセーフな実装にオーバライドされているので問題ない 他のActorからの呼び出し→実装に対しては無意味にasync化するけど、本体はやはりマルチスレッドセーフなので問題ない (edited)
6:31 AM
逆方向は問題が起きると思う。 親クラスのメソッドが何も保護がなければ暗黙にマルチスレッドセーフ 継承先のサブクラスでMainActor保護をかけた場合、 オーバライド呼び出しにおいて、MainActorディスパッチ無しで呼び出されるので、 サブクラス側からみてMainActorコンテキストで実行されるという仮定が破壊される。
Avatar
@uhooi Other Swift Flags に -Xfrontend -warn-concurrency を付けるのをオススメします。これで、 Swift 6 からコンパイルエラーになる違反を警告として上げてくれます。
🙏 1
Avatar
Avatar
Iceman
親クラスがMainActorであっても、省略すると挙動が変わることがある
これ罠ですよね。意図的なのかなぁ
UIViewController が Obj-C だからとかもあるのかなぁと思ってたんですが、 Pure Swift 同士でも起こるんですっけ?
Avatar
とりあえず脳死で AppDelegate などに @MainActor を付けてみた https://github.com/uhooi/UhooiPicBook/pull/265/commits/c680f5a29efca61326e2a7b28c1a48efb1c3f0e7
Issue close #223 close #260 Overview Replace completion handler with Swift Concurrency. Checklist Format code with SwiftLint (⌘B in Xcode) Resolve Xcode warning What to check Is the usage o...
Avatar
Avatar
koher
@uhooi Other Swift Flags に -Xfrontend -warn-concurrency を付けるのをオススメします。これで、 Swift 6 からコンパイルエラーになる違反を警告として上げてくれます。
そうだ、Swift Zoomin' で教えていただいたのに失念していました、、付けます!
Avatar
Avatar
koher
UIViewController が Obj-C だからとかもあるのかなぁと思ってたんですが、 Pure Swift 同士でも起こるんですっけ?
ちょっとうろ覚えなんですがNSObjectかどうかに差はなかった気がするんですよね
Avatar
無かったと思います
Avatar
Avatar
Iceman
ちょっとうろ覚えなんですがNSObjectかどうかに差はなかった気がするんですよね
なるほど。 継承したときに、サブクラスのメンバーが @MainActor (が付与されてる)扱いにならなくても、スーパークラスとして扱われたときの挙動を破壊することはないから、サブクラスで @MainActor 扱いにならなくても実は問題ない? (edited)
6:38 AM
オーバーライドしたものは @MainActor 扱いになるとして。
Avatar
Avatar
koher
オーバーライドしたものは @MainActor 扱いになるとして。
6:39 AM
@MainActor 指定は 関数型に対して、型としては、制約を追加して狭めているように働くので。
Avatar
なるほど。じゃあ VC (のサブクラス)に @MainActor 付けなきゃいけないのは仕様で、 VC を継承したらとりあえず @MainActor 付けとけばいいのか。 (edited)
Avatar
あ、はい。サブクラスで @MainActor 扱いになる必要はないですが、そのサブクラス内部で @MainActor の恩恵をうける(UI操作を呼ぶなど)ために結局はつけることになると思います (edited)
Avatar
viewDidAppear とかはオーバーライドだから @MainActor 付けなくても MainActor-isolated だったと。
Avatar
「サブクラスのメソッドが保護から外れて良い」については、外れるメリットが薄くて
Avatar
↑で考えていたのはたとえオーバーライドでもサブクラス側ではMainActor保護が外れてもいいんじゃないかなという事ですが、オーバーライドする時はMainActor保護が暗黙に付いてくるという仕様のほうが現実的には使いやすそう
Avatar
むしろ逆にActorの保護から明示的に外せる宣言がある上で、サブクラスについては一括で保護するとなっていた方が良かったんだろうなと思う (edited)
6:43 AM
勝手に外れて良いことは殆どないと思います
6:44 AM
(そろそろ beginnerじゃなくなってきましたね
Avatar
viewDidAppear とかが何も書かなくても @MainActor だったかどうかはどうだったかな・・?
6:45 AM
サブクラスで別のglobalActor付与するとさらにややこしくなりそう
Avatar
@swift-5.5.3 @MainActor class ViewController { var isolatedCounter: Int = 0 func viewDidAppear() {} } class XViewController: ViewController { override func viewDidAppear() { self.isolatedCounter += 1 } }
Avatar
Avatar
Yuta Saito
@swift-5.5.3 @MainActor class ViewController { var isolatedCounter: Int = 0 func viewDidAppear() {} } class XViewController: ViewController { override func viewDidAppear() { self.isolatedCounter += 1 } }
no output
Avatar
Avatar
Iceman
viewDidAppear とかが何も書かなくても @MainActor だったかどうかはどうだったかな・・?
保護されてそう?
Avatar
Avatar
omochimetaru
↑で考えていたのはたとえオーバーライドでもサブクラス側ではMainActor保護が外れてもいいんじゃないかなという事ですが、オーバーライドする時はMainActor保護が暗黙に付いてくるという仕様のほうが現実的には使いやすそう
オーバーライドで保護外れたら、リスコフの置換原則に反するのでは?
Avatar
@swift-5.5.3 -warn-concurrency @MainActor class ViewController { var isolatedCounter: Int = 0 func viewDidAppear() {} } @MainActor class State { var value: Int = 0 } class XViewController: ViewController { let state = State() override func viewDidAppear() { state.value += 1 } } (edited)
Avatar
Avatar
Iceman
@swift-5.5.3 -warn-concurrency @MainActor class ViewController { var isolatedCounter: Int = 0 func viewDidAppear() {} } @MainActor class State { var value: Int = 0 } class XViewController: ViewController { let state = State() override func viewDidAppear() { state.value += 1 } } (edited)
no output (edited)
Avatar
保護されてた
Avatar
Avatar
koher
オーバーライドで保護外れたら、リスコフの置換原則に反するのでは?
反しないと思います ↓に考えを書いています https://discord.com/channels/291054398077927425/291211035438874625/920563280509018114 (edited)
Avatar
Actor保護を受けてる関数、第N引数に暗黙でActorを受け取っている、と考えると整理しやすそう (edited)
Avatar
Avatar
tarunon
Actor保護を受けてる関数、第N引数に暗黙でActorを受け取っている、と考えると整理しやすそう (edited)
isolated 引数のstatic版だから引数が見かけ上消えてると考えられるので、それが良いと思います。
6:49 AM
それ自体がクラスではなくactorの場合は isolated 引数指定が 見えない self に付与されていると考えると統一的に整理できる。
Avatar
Avatar
omochimetaru
反しないと思います ↓に考えを書いています https://discord.com/channels/291054398077927425/291211035438874625/920563280509018114 (edited)
ちょっと用事で離脱するので後で読みます。
Avatar
理屈としては成り立ってるのは解るけど、それ以上に現実的な利用のシチュエーションにおいて殆どメリットのない仕様になっていて、あんまり歓迎できる状態じゃないと思う
Avatar
それは同意。
Avatar
難しい、、 VIPER で組んでいるのですが、すべての View・Presenter・Router に @MainActor を付けるようにしてみました↓ https://github.com/uhooi/UhooiPicBook/pull/265/commits/11f446d2ae38d5cab38aaae98dc2c3d5af6afe07
Issue close #223 close #260 Overview Replace completion handler with Swift Concurrency. Checklist Format code with SwiftLint (⌘B in Xcode) Resolve Xcode warning What to check Is the usage o...
Avatar
UI周りのロジックは全部MainActorで問題ないと思いますよ
Avatar
なので Interactor 以外は MainActor にしてみました!
👍 1
7:37 AM
あと Task で括るのは View 層に固定したほうがいいのでしょうか? 例えば View → Presenter → Interactor → Repository で、Repository のメソッド内で async のメソッドを呼び出したいとき、その呼び出しを Task { ... } で括れば Interactor 以下の層のメソッドに async を付ける必要がなくなるので、実装は楽です。 Task { ... } で括らないと I・P それぞれのメソッドに async を付ける必要が出てくるので修正が手間ですが、適切なのはこちらなのかなと考えています。 (edited)
Avatar
ActorIsolatedで安全になっているところでTaskを利用するべきであり、それ以外のところは(必要があれば)async関数で宣言しておく、というのが一番上手く行くと思います (edited)
🙏 1
7:39 AM
つまり、UI層は全てMainActorで守られているので、ここにTaskを宣言する
👍 1
Avatar
actor-isolated の概念がまだちゃんとわかっていないのですが、なんとなくわかってきました…! ありがとうございますm( )m
Avatar
ActorContextが存在するところでTaskを使うと、その中でasync関数を呼んだ場合、返り値を受けるActorが外側のContextと同一になるんですね。 これはRxでいうところのobserve(on: MainScheduler.instance)を自動でやってくれるのと等価です (edited)
✨ 1
Avatar
.observe(on:) ?
Avatar
そっちや
7:48 AM
確か微妙に機能が違うのだが…もう引退したので差はわからない…
Avatar
subscribe(on:) は subscribe スレッドの制御だね
7:48 AM
発火処理の実行コンテキストを制御する。
Avatar
オペレーターの前と後か
7:48 AM
じゃあobserveonが正しい
Avatar
ストリームからイベントが流れてくるコンテキストはobserve
Avatar
逆に言えば、Actorの解らないところでTaskを使うと、これはglobalActorの扱いになるのかな?あんまりプログラマーにとって意図した動作とはなりにくいので
✨ 1
7:49 AM
避けた方が良いパターンとなります
✨ 1
Avatar
あとでレビューしてみようと思ってたんだった
🙏 1
Avatar
↓で前者だと「actor-isolated property 'monsters' cannot be passed 'inout' to 'async' function call」のビルドエラーになるけど、後者のようにローカル変数に退避させたらビルドが通った monsters はプロパティ func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { Task { await presenter.didSelectMonster(monster: monsters[indexPath.row]) } } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { Task { let monster = monsters[indexPath.row] await presenter.didSelectMonster(monster: monster) } }
8:01 AM
この修正方法でいいのかわからない、、
8:04 AM
あと async 関数を投げっぱなしにする方法あるのかな? 以下で interactor.saveForSpotlight() の実行を待たずに router.showMonsterDetail(monster: monster) を実行したい 処理の順番を逆にすればいけそうだけど、微妙な気がする func didSelectMonster(monster: MonsterEntity) async { await interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) }
Avatar
投げっぱなしはawait let使えば何とかなりそう
Avatar
await let なる構文があるのですね!? async let とは別にあるのかな
Avatar
Avatar
omochimetaru
反しないと思います ↓に考えを書いています https://discord.com/channels/291054398077927425/291211035438874625/920563280509018114 (edited)
考えました&読みました。iPhoneからなので読みにくいかもだけど。 @MainActorなクラスのサブクラスからメソッドをオーバーライドするときに、asyncでなくす(同期にする)ことも可能なんじゃないかと思いました。同期の方が型が狭いし。オーバーライドしてactor-isolatedなAPIや非同期APIを触らないのなら。superでオーバーライドされるメソッドを呼ぶ場合は必然的にawaitが必要になり、asyncになる。もしくは、オーバーライド先にも@MainActorを付けて、同期呼び出しする。もしスーパークラスのインスタンスとして扱われて同期的にそのメソッドが呼ばれても、スレッドセーフなので安全。 サブクラスのインスタンスとして扱われてる場合は同期に見えるから、「無意味にasync化」が起こらない。 オーバーライドでも勝手に@MainActor化しない方が、明示的でいい気がしてきた。 (edited)
Avatar
Avatar
uhooi
あと async 関数を投げっぱなしにする方法あるのかな? 以下で interactor.saveForSpotlight() の実行を待たずに router.showMonsterDetail(monster: monster) を実行したい 処理の順番を逆にすればいけそうだけど、微妙な気がする func didSelectMonster(monster: MonsterEntity) async { await interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) }
上記の場合は特に戻り値を使わないから、Taskでラップして、async関数にしないので良いんじゃないかなと思った
Avatar
Avatar
giginet
上記の場合は特に戻り値を使わないから、Taskでラップして、async関数にしないので良いんじゃないかなと思った
なるほど、Task は UI 層で使うのがベターだけど、投げっぱなしにするときは使ってもいいのかな
Avatar
失礼します、Attributesでスレッドを制御する方法は、今は@MainActorしか標準のものはないんですかね? 逆に重い処理を行う関数で必ずglobalで実行するように指定できないのかなって思いました。
Avatar
Avatar
uhooi
await let なる構文があるのですね!? async let とは別にあるのかな
async letの間違いです、すみません
🙏 1
Avatar
Avatar
giginet
上記の場合は特に戻り値を使わないから、Taskでラップして、async関数にしないので良いんじゃないかなと思った
僕は戻り値を使わないときでもTaskでラップするのはViewでやるようにしてますね。元々はメソッド側に書いてましたが、WWDCの↓を見て改宗しました。 SwiftUIのtask modifierとの組み合わせを考えるとそっちが適切そうだったので。 https://developer.apple.com/wwdc21/10019
Discover how you can use Swift's concurrency features to build even better SwiftUI apps. We'll show you how concurrent workflows interact...
Avatar
async let だと非同期関数と同期関数が混ざっているときにどう使えばいいかわからず、、
Avatar
Avatar
uhooi
↓で前者だと「actor-isolated property 'monsters' cannot be passed 'inout' to 'async' function call」のビルドエラーになるけど、後者のようにローカル変数に退避させたらビルドが通った monsters はプロパティ func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { Task { await presenter.didSelectMonster(monster: monsters[indexPath.row]) } } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { Task { let monster = monsters[indexPath.row] await presenter.didSelectMonster(monster: monster) } }
async関数を投げっぱなしにするのは、Task { }で囲むでいいと思います。
🙏 1
Avatar
Avatar
koher
考えました&読みました。iPhoneからなので読みにくいかもだけど。 @MainActorなクラスのサブクラスからメソッドをオーバーライドするときに、asyncでなくす(同期にする)ことも可能なんじゃないかと思いました。同期の方が型が狭いし。オーバーライドしてactor-isolatedなAPIや非同期APIを触らないのなら。superでオーバーライドされるメソッドを呼ぶ場合は必然的にawaitが必要になり、asyncになる。もしくは、オーバーライド先にも@MainActorを付けて、同期呼び出しする。もしスーパークラスのインスタンスとして扱われて同期的にそのメソッドが呼ばれても、スレッドセーフなので安全。 サブクラスのインスタンスとして扱われてる場合は同期に見えるから、「無意味にasync化」が起こらない。 オーバーライドでも勝手に@MainActor化しない方が、明示的でいい気がしてきた。 (edited)
そうですね。 asyncについても、オーバーライドはできるかわからないけど、 () -> ()() -> async () に代入する事は実際できる気がする。 オーバーライドの考え方は、代入できる=親側の型としてみなして呼び出せる、なので。 サブクラス側のシンボルが見えてるときには狭い型として扱えたほうが嬉しい、というのは同期/非同期だとわかりやすいですね。
👍 1
Avatar
Task で括って投げっぱなしにしてみました func saveForSpotlight(_ monster: MonsterEntity) { let key = "spotlight_\(monster.name)" monstersTempRepository.saveMonster(monster, forKey: key) Task { await spotlightRepository.saveMonster(monster, forKey: key) } } ただこうすると単体テストで spotlightRepository.saveMonster() が呼び出されたか確認しづらいですね、、(苦戦中)
Avatar
Avatar
shimastripe
失礼します、Attributesでスレッドを制御する方法は、今は@MainActorしか標準のものはないんですかね? 逆に重い処理を行う関数で必ずglobalで実行するように指定できないのかなって思いました。
適切かわかりませんが、actorを作って、actorのメソッドとして処理を書くとメインスレッド以外で処理させられると思います。Attributeではないですが(@MainActorも、global actorなのでattributeではないですが。今、Swiftで@で書くものは色々あってややこしくて、attribute、property wrapper、result builder、global actor、marker protocolがあります😇)。
t_naruhodo 2
🙏 1
Avatar
Avatar
uhooi
Task で括って投げっぱなしにしてみました func saveForSpotlight(_ monster: MonsterEntity) { let key = "spotlight_\(monster.name)" monstersTempRepository.saveMonster(monster, forKey: key) Task { await spotlightRepository.saveMonster(monster, forKey: key) } } ただこうすると単体テストで spotlightRepository.saveMonster() が呼び出されたか確認しづらいですね、、(苦戦中)
僕ならここでTask.initでラップせずにasyncにして、利用側(didSelectMonster)でラップすると思います。↓の理由で。 https://discord.com/channels/291054398077927425/291211035438874625/920590437981503498
8:44 AM
View以外にTaskを持ち込むと単体テストも難しくなりそうに思います。View以外はasync(並行にしたいときはasync letを利用)で、最後にViewでTaskでラップ(SwiftUIならtask modifier)かなと。
🙏 1
Avatar
ああ、なるほど、理解しました…。
Avatar
ViewでTaskを発火すると( @_implicitSelfCapture だから)selfを気づかずキャプチャして不用意に生き残る気がしましたがこのへんはどうなんでしょうかね
Avatar
それは別にどこでやっても一緒では
Avatar
それもそうか
Avatar
Issue close #223 close #260 Overview Replace completion handler with Swift Concurrency. Checklist Format code with SwiftLint (⌘B in Xcode) Resolve Xcode warning What to check Is the usage o...
8:55 AM
Presenter の処理が気になる Before func didSelectMonster(monster: MonsterEntity) { interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) After func didSelectMonster(monster: MonsterEntity) async { router.showMonsterDetail(monster: monster) await interactor.saveForSpotlight(monster) } ↓だと Ineractor の処理を待つ気がするから、Router による画面遷移の処理と順番を入れ替えた その考えで合っているかはわからない、、 func didSelectMonster(monster: MonsterEntity) async { await interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) }
Avatar
Avatar
uhooi
Presenter の処理が気になる Before func didSelectMonster(monster: MonsterEntity) { interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) After func didSelectMonster(monster: MonsterEntity) async { router.showMonsterDetail(monster: monster) await interactor.saveForSpotlight(monster) } ↓だと Ineractor の処理を待つ気がするから、Router による画面遷移の処理と順番を入れ替えた その考えで合っているかはわからない、、 func didSelectMonster(monster: MonsterEntity) async { await interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) }
Ineractor の処理を待つ気がする
正しいです。
Router による画面遷移の処理と順番を入れ替えた
この場合は問題ないのかもしれませんが、いつでも入れ替えられるとは限らないように思います。 処理が終わるのを待たずに後続処理を始めるためには、↓のように書くことができます( : Void がないと警告が出ます)。 func didSelectMonster(monster: MonsterEntity) async { async let x: Void = interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) await x }
(edited)
👀 1
Avatar
Avatar
koher
Ineractor の処理を待つ気がする
正しいです。
Router による画面遷移の処理と順番を入れ替えた
この場合は問題ないのかもしれませんが、いつでも入れ替えられるとは限らないように思います。 処理が終わるのを待たずに後続処理を始めるためには、↓のように書くことができます( : Void がないと警告が出ます)。 func didSelectMonster(monster: MonsterEntity) async { async let x: Void = interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) await x }
(edited)
おおっ…! Voidにしてasync letに入れ込む技があるのですね…! 使うことがありそうなので覚えておきます🙏
🙂 1
Avatar
Kishikawa Katsumi 12/15/2021 4:09 PM
func didSelectMonster(monster: MonsterEntity) async { router.showMonsterDetail(monster: monster) await interactor.saveForSpotlight(monster) } func didSelectMonster(monster: MonsterEntity) async { async let x: Void = interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) await x } この2つは書き方が違うだけでまったく同じですよね? (edited)
Avatar
全く同じかというと微妙に違うんですが、殆ど問題はないと思います (edited)
4:24 PM
saveXXXのメインスレッド内での処理が、画面遷移の後と先どちらに挟まるかが変わる
Avatar
showMonsterDetailが制御を返さない、みたいな変な場合を除けば一緒じゃないですかね
Avatar
Kishikawa Katsumi 12/15/2021 4:25 PM
saveForSpotlightの処理はどっちもrouterの呼び出しの後だと思うんですけど合ってます? (edited)
4:25 PM
awaitのところですよね?
Avatar
async letの場合は特に保証されないと思います
Avatar
Kishikawa Katsumi 12/15/2021 4:26 PM
そうなんだ。async letはawaitする前に動き始めるのか。
Avatar
動き始めても良い、になると思う
Avatar
Kishikawa Katsumi 12/15/2021 4:26 PM
勘違いしていた。
Avatar
async関数のsaveXXXの先頭n行にawaitがついてない場合にどうなるか、は、ちょっと見てみないことには何とも (edited)
4:28 PM
最適化によっても変わり得ると思います
Avatar
@swift-5.5.3 -Xfrontend -parse-as-library func f() async { async let x = Task<Int, Never> { print("task started"); return 1 }.result } @main struct Main { static func main() async { await f() } } (edited)
Avatar
Avatar
Yuta Saito
@swift-5.5.3 -Xfrontend -parse-as-library func f() async { async let x = Task<Int, Never> { print("task started"); return 1 }.result } @main struct Main { static func main() async { await f() } } (edited)
task startedstderr:<stdin>:2:15: warning: initialization of immutable value 'x' was never used; consider replacing with assignment to '_' or removing it async let x = Task<Int, Never> { print("task started"); return 1 }.result ~~~~^ _ (edited)
Avatar
あれ、トップレベルどうやって書くんだっけ…
4:33 PM
parse-as-libraryだ
Avatar
routerのメソッド呼び出しの副作用でそのTaskのキャンセルが起こりうる点に違いがあると思います
Avatar
それはtry書いてないとまずいw (edited)
Avatar
Kishikawa Katsumi 12/15/2021 4:36 PM
routerのメソッド呼び出しの副作用でそのTaskのキャンセルが起こりうる点に違いがあると思います
これは async let x: Void = interactor.saveForSpotlight(monster) がawaitより先に動き始めた場合ってことですよね?
Avatar
理解しました。画面が消えてdeinitにキャンセルを書いてる場合は、ということね
🛷 1
4:38 PM
これはキャンセルしない方が良いんじゃないかな
Avatar
Kishikawa Katsumi 12/15/2021 4:38 PM
実際にPromiseがあるわけじゃないけどasync letでPromiseを返してawaitでresolveされると考えていいのかしら? (edited)
Avatar
と思ったけど、キャンセル発火してもasync関数の途中状態は残っててawait 箇所ごとに即時キャンセルしながら走り抜けるので変わらない気がしてきました
Avatar
Avatar
Kishikawa Katsumi
実際にPromiseがあるわけじゃないけどasync letでPromiseを返してawaitでresolveされると考えていいのかしら? (edited)
私はその理解です。発火についても約束がないのでどうとでも成り得る。とにかくawaitの行で完了すれば良い
Avatar
キャンセルしたくない場合にはTaskのキャンセルの伝播を避けるためにTaskはdetachしたほうが良いかも? 実際には途中にtryが無ければ走り抜けるけど、tryの有無を頑張って読むのは大変そう (edited)
Avatar
Avatar
Kishikawa Katsumi
実際にPromiseがあるわけじゃないけどasync letでPromiseを返してawaitでresolveされると考えていいのかしら? (edited)
僕もその理解でいます。
Avatar
Kishikawa Katsumi 12/15/2021 4:40 PM
🙏
Avatar
蛇足かもしれませんが、async letの挙動についてはここら辺で解説されてますね(async let時点で処理が開始する)。出てくるスライドが動きを把握するのにわかりやすいかなーと個人的に思ってます。 https://developer.apple.com/videos/play/wwdc2021/10134/?time=0340 内部ではAsyncLetが使われているみたいですね。 https://github.com/apple/swift/blob/fc67ba57f2ad1ca4ce3e3f98fa4ba6114d4de3c7/include/swift/ABI/AsyncLet.h (edited)
When you have code that needs to run at the same time as other code, it's important to choose the right tool for the job. We'll take you...
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
9:37 PM
便乗して質問なのですが…😅、テストを書いている時にawaitをautoclosureで使えないので、XCTAssertEqualなどに入れる前に変数にawaitの結果を入れているのですが、何かもっと良い方法はありますでしょうか? await' in an autoclosure that does not support concurrency (edited)
Avatar
この2つは書き方が違うだけでまったく同じですよね?
全く同じかというと微妙に違うんですが、殆ど問題はないと思います saveXXXのメインスレッド内での処理が、画面遷移の後と先どちらに挟まるかが変わる
↑の話、この例では問題なさそうなんですが、
  • 同期関数がめっちゃ重い
  • async 関数が二つと同期関数が一つ
とかになると順番入れ替えで対応できないので、 async letVoid を受けるべきケースがあるだろうなと思って書きました。
Avatar
なるほど、みなさんありがとうございます! async let では実行タイミングが保証されないとのことなので、できるなら処理の入れ替えで対応したほうがベターということですね!
Avatar
Avatar
shiz
便乗して質問なのですが…😅、テストを書いている時にawaitをautoclosureで使えないので、XCTAssertEqualなどに入れる前に変数にawaitの結果を入れているのですが、何かもっと良い方法はありますでしょうか? await' in an autoclosure that does not support concurrency (edited)
こんな感じのメソッドを用意すると便利ですよー! https://github.com/uhooi/UhooiPicBook/pull/265/commits/b12136c8122e80cadfb93b0cf3da09a2dacde2d9#diff-1423f9a6971f776c2ebc944968a5a3dfb4df741c4e7e31f1fb0487486a8257d1R10-R19 import XCTest func assertEqualAsync<T>( _ actual: @autoclosure () async -> T, _ expected: T, _ message: String = "", file: StaticString = #filePath, line: UInt = #line ) async where T : Equatable { let actual = await actual() XCTAssertEqual(actual, expected, message, file: file, line: line) } 呼び出し方↓ await assertEqualAsync(await self.viewMock.stopIndicatorCallCount, 1) ぎぎにゃんさんの Crossroad を参考にしましたm( )m
Issue close #223 close #260 Overview Replace completion handler with Swift Concurrency. Checklist Format code with SwiftLint (⌘B in Xcode) Resolve Xcode warning What to check Is the usage o...
12:19 AM
(ちなみに私はテストメソッドにも @MainActor を付けたら不要になりました…笑)
Avatar
Avatar
uhooi
こんな感じのメソッドを用意すると便利ですよー! https://github.com/uhooi/UhooiPicBook/pull/265/commits/b12136c8122e80cadfb93b0cf3da09a2dacde2d9#diff-1423f9a6971f776c2ebc944968a5a3dfb4df741c4e7e31f1fb0487486a8257d1R10-R19 import XCTest func assertEqualAsync<T>( _ actual: @autoclosure () async -> T, _ expected: T, _ message: String = "", file: StaticString = #filePath, line: UInt = #line ) async where T : Equatable { let actual = await actual() XCTAssertEqual(actual, expected, message, file: file, line: line) } 呼び出し方↓ await assertEqualAsync(await self.viewMock.stopIndicatorCallCount, 1) ぎぎにゃんさんの Crossroad を参考にしましたm( )m
おーありがとうございます!こういうの公式であってほしいですよね。もしくはautoclosure対応してほしい。
ちなみに私はテストメソッドにも @MainActor を付けたら不要になりました…笑
僕も必要な時はそうしてます。あと@ MainActorのクラスのテストクラスには@ MainActor付けてます(良いのかな?)。
(edited)
Avatar
Avatar
shiz
おーありがとうございます!こういうの公式であってほしいですよね。もしくはautoclosure対応してほしい。
ちなみに私はテストメソッドにも @MainActor を付けたら不要になりました…笑
僕も必要な時はそうしてます。あと@ MainActorのクラスのテストクラスには@ MainActor付けてます(良いのかな?)。
(edited)
いえいえ! ですね、コードによっては頻繁に使うので、公式が用意してくれてもいいと思いました。 あ、テストクラス自体にMainActorを付けているのですね! 自分もそうしようかな…。悩んだのですが、今だと必要なメソッドにのみ付けています。 (公式・非公式に関わらずMainActorの情報が少ない…どこかにないかな…)
Avatar
Avatar
uhooi
いえいえ! ですね、コードによっては頻繁に使うので、公式が用意してくれてもいいと思いました。 あ、テストクラス自体にMainActorを付けているのですね! 自分もそうしようかな…。悩んだのですが、今だと必要なメソッドにのみ付けています。 (公式・非公式に関わらずMainActorの情報が少ない…どこかにないかな…)
僕が知っている限りだと一番まとまっているのがプロポーザルですかねー👀 https://github.com/apple/swift-evolution/blob/5bf0cf0b00169297ba9bc30291477cbbe1343145/proposals/0316-global-actors.md あとはSwiftリポジトリのテスト見てコンパイラがどんなチェックがされるのかを確認するか、forumのコメントに話が出ていたりするのでそこから情報得ていますかね。(これバグだったのかーとかあったりしますw) ここら辺など https://forums.swift.org/t/hang-when-awaiting-call-to-actor/54026/5 https://forums.swift.org/t/mainactor-ignored-by-the-compiler/49533/4 あとSwiftリポジトリのPRのdescriptionにも何が問題でどうしたのかとか書いてあって色々学べるなあと思ってます (edited)
🙏 1
Avatar
Avatar
shiz
僕が知っている限りだと一番まとまっているのがプロポーザルですかねー👀 https://github.com/apple/swift-evolution/blob/5bf0cf0b00169297ba9bc30291477cbbe1343145/proposals/0316-global-actors.md あとはSwiftリポジトリのテスト見てコンパイラがどんなチェックがされるのかを確認するか、forumのコメントに話が出ていたりするのでそこから情報得ていますかね。(これバグだったのかーとかあったりしますw) ここら辺など https://forums.swift.org/t/hang-when-awaiting-call-to-actor/54026/5 https://forums.swift.org/t/mainactor-ignored-by-the-compiler/49533/4 あとSwiftリポジトリのPRのdescriptionにも何が問題でどうしたのかとか書いてあって色々学べるなあと思ってます (edited)
ありがとうございます…!
  • プロポーザルを見る
  • Swift のテストコードを見る
  • フォーラムを見る
すべて見ていませんでした…参考になります 🙏
Avatar
Avatar
uhooi
なるほど、みなさんありがとうございます! async let では実行タイミングが保証されないとのことなので、できるなら処理の入れ替えで対応したほうがベターということですね!
処理を入れ替えた方が良いかは、要件と実装次第でしょうか。今回のケースでは(要件と実装を想像する範囲では)入れ替えても問題なさそうに思います。
🙏 1
Avatar
画面遷移する前にXXしてないとチラつく、みたいなのは割と頻出なので、入れ替えよりは元のコードをなるたけ再現するのが無難だと思いました
Avatar
画面遷移する前にXXしてないとチラつく
という観点では、順番入れ替えも async let もせずに await した方が良いことになりませんか?それが必要なケースもあると思いますが、その場合、インタラクションから遷移まで delay が発生するので、 UX を損ねる可能性が気になります。 saveForSpotlight が体感できないくらい一瞬ならいいですが。あと、 suspend 中は UI スレッドがブロックされてないので(それ自体は悪くないですが)、ボタン連打された場合のケアとかが気になります。 並行で走らせるなら「画面遷移する前にXX」することを保証できないから入れ替えでも問題なさそうに思いますが、元々問題が起こってなくて(かつ、元の saveForSpotlight のコードは並行に走ってて投げっぱなしで結果を待たない実装になってて)、忠実にその挙動を再現するなら、やっぱり async let が良さそうですね。 > Cc: @uhooi
👀 1
Avatar
Avatar
shiz
便乗して質問なのですが…😅、テストを書いている時にawaitをautoclosureで使えないので、XCTAssertEqualなどに入れる前に変数にawaitの結果を入れているのですが、何かもっと良い方法はありますでしょうか? await' in an autoclosure that does not support concurrency (edited)
test自体にasync付けると手っ取り早いかも? func testFoo() async { XCTAssertEqual(await foo(), 1) }
Avatar
Avatar
tarunon
test自体にasync付けると手っ取り早いかも? func testFoo() async { XCTAssertEqual(await foo(), 1) }
それだとawait foo()のところでエラーになるんですよね(あれ?何か勘違いしてます?) 'async' call in an autoclosure that does not support concurrency
Avatar
あれ、そうなのか
Avatar
エラーになりますね👀
Avatar
awaitの外に()でなんとかなる?
Avatar
reasync が必要そう。
2:13 AM
reasync があれば @autoclosureasyncXCTAssertEqualreasync を( Apple が)付けることで↓にできる? await XCTAssertEqual(foo(), 1) (edited)
2:15 AM
オーバーロードがあれば済む話かな・・・。
Avatar
Avatar
tarunon
awaitの外に()でなんとかなる?
同じでした
Avatar
expression1expression2async が付いてないので無理だと思います。 https://developer.apple.com/documentation/xctest/2142776-xctassertequal
👍🏻 2
Avatar
Avatar
koher
reasync が必要そう。
reasync は今後の機能でしょうか?
Avatar
Avatar
uhooi
reasync は今後の機能でしょうか?
はい、 rethrowsasync 版で当初から言及されてたんですが、あまり使いどころがないこともあり現状では入ってないです。この XCTAssertEqual はいいユースケースな気がします。
Avatar
Avatar
koher
はい、 rethrowsasync 版で当初から言及されてたんですが、あまり使いどころがないこともあり現状では入ってないです。この XCTAssertEqual はいいユースケースな気がします。
なるほど、ありがとうございますー!
Avatar
Avatar
uhooi
なるほど、ありがとうございますー!
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0296-async-await.md at main · apple/swift-evolution
👀 1
Avatar
Clock プロトコルは reasync ある前提なので、そろそろ何か動きがあるのかなーと(勝手に)思ってます。 public protocol Clock: Sendable { …. func measure(_ work: () async throws -> Void) reasync rethrows -> Duration } https://github.com/apple/swift-evolution/blob/523636b879cd6cab83124abc11060b6b39c3ac21/proposals/0329-clock-instant-date-duration.md#clock (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0329-clock-instant-date-duration.md at 523636b879cd6cab83124abc11060b6b39c3ac...
Avatar
Avatar
shiz
Clock プロトコルは reasync ある前提なので、そろそろ何か動きがあるのかなーと(勝手に)思ってます。 public protocol Clock: Sendable { …. func measure(_ work: () async throws -> Void) reasync rethrows -> Duration } https://github.com/apple/swift-evolution/blob/523636b879cd6cab83124abc11060b6b39c3ac21/proposals/0329-clock-instant-date-duration.md#clock (edited)
おお、それは楽しみですね!
🙌🏻 1
Avatar
@swift-main -Xfrontend -enable-experimental-concurrency import XCTest extension Result where Failure == Swift.Error { public init(catching body: () async throws -> Success) reasync { do { self = .success(try await body()) } catch { self = .failure(error) } } } public func XCTAssertEqual2<T: Equatable>( _ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line ) reasync { let (result1, result2) = await (Result(catching: expression1), Result(catching: expression2)) XCTAssertEqual(try result1.get(), try result2.get(), message(), file: file, line: line) } func foo() async -> Int { 1 } class ATest: XCTestCase { func testFoo() async { await XCTAssertEqual2(await foo(), 1) } static let allTests = [("testFoo", asyncTest(testFoo))] } XCTMain([testCase(ATest.allTests)]) (edited)
Avatar
Avatar
norio_nomura
@swift-main -Xfrontend -enable-experimental-concurrency import XCTest extension Result where Failure == Swift.Error { public init(catching body: () async throws -> Success) reasync { do { self = .success(try await body()) } catch { self = .failure(error) } } } public func XCTAssertEqual2<T: Equatable>( _ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line ) reasync { let (result1, result2) = await (Result(catching: expression1), Result(catching: expression2)) XCTAssertEqual(try result1.get(), try result2.get(), message(), file: file, line: line) } func foo() async -> Int { 1 } class ATest: XCTestCase { func testFoo() async { await XCTAssertEqual2(await foo(), 1) } static let allTests = [("testFoo", asyncTest(testFoo))] } XCTMain([testCase(ATest.allTests)]) (edited)
swiftNightly BOT 12/16/2021 3:57 AM
Test Suite 'All tests' started at 2021-12-16 04:09:15.831 Test Suite 'bin.xctest' started at 2021-12-16 04:09:15.832 Test Suite 'ATest' started at 2021-12-16 04:09:15.832 Test Case 'ATest.testFoo' started at 2021-12-16 04:09:15.832 Test Case 'ATest.testFoo' passed (0.001 seconds) Test Suite 'ATest' passed at 2021-12-16 04:09:15.833 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds Test Suite 'bin.xctest' passed at 2021-12-16 04:09:15.833 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds Test Suite 'All tests' passed at 2021-12-16 04:09:15.833 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds (edited)
Avatar
個人開発アプリを Swift Concurrency に対応できた!(はず) https://github.com/uhooi/UhooiPicBook/pull/265 Swift Concurrency に関係する差分しか出ないようにした〜 いくつか気になるところを自分でコメントしているので、どなたか見ていただけると嬉しいです… 🙏
Issues close #223 close #260 Overview Use Swift Concurrency. Details Replace completion handler with async function Add @MainActor to All View ( UIViewController , UICollectionViewCell etc) All...
Avatar
自分がまだわかっていないのが、Task { ... } に @ MainActor in を付けるかの判断方法 UI の更新があれば付ける必要があるとは思うんだけど、その判断方法がよくわからず、、 UILabel.text に値を代入するとかわかりやすいのはともかく、伝播して UI を更新する可能性がある場合とかがわからない
9:15 AM
あと @ MainActor が付いたクラスかどうかで挙動が変わるのかな? MainActor のクラスでも Task { ... } 内で非同期関数を呼び出すと、メインスレッド以外のスレッドで非同期に実行される? メインスレッドでの実行を保証するには Task { @ MainActor in ... } 内で呼び出す必要がある?
9:19 AM
プロポーザルを読めばわかるのかな?(英語だからまだ読めていない、、)
Avatar
いや、アクター内でコンテキストは引き継ぐから、MainActor のクラスの場合は @ MainActor を付けなくてもメインスレッドでの動作が保証される? メインスレッド以外で動作させるには Task.detached { ... } とすればいい?
9:27 AM
(Discord に書く前に頭を整理すべきだった、、、)
Avatar
Avatar
uhooi
個人開発アプリを Swift Concurrency に対応できた!(はず) https://github.com/uhooi/UhooiPicBook/pull/265 Swift Concurrency に関係する差分しか出ないようにした〜 いくつか気になるところを自分でコメントしているので、どなたか見ていただけると嬉しいです… 🙏
いい感じですね!全部見たわけではないですが、ぱっと見で気になった箇所にコメントしました。
Avatar
Avatar
koher
いい感じですね!全部見たわけではないですが、ぱっと見で気になった箇所にコメントしました。
うおおありがとうございます…! なるほど、やはりコンテキストはTask内に引き継ぐのですね。
Avatar
Task.init に渡すクロージャは特別で、普通は @Sendable クロージャにはコンテクストが引き継がれないんですが、 Task.init に渡すクロージャだけ例外的にコンテクストが引き継がれます。 @_implicitSelfCapture @_inheritActorContext が付いてるので。 (edited)
👀 1
Avatar
@_inheritActorContext かな?
Avatar
あ、間違えた。
Avatar
Avatar
uhooi
個人開発アプリを Swift Concurrency に対応できた!(はず) https://github.com/uhooi/UhooiPicBook/pull/265 Swift Concurrency に関係する差分しか出ないようにした〜 いくつか気になるところを自分でコメントしているので、どなたか見ていただけると嬉しいです… 🙏
パッと見て一箇所気になったのですが(全然大した話でないです🙇🏻‍♂️ ) UIResponder@MainActorが付いているので、AppDelegateには必要ないかもしれません。
👀 1
Avatar
Avatar
norio_nomura
@swift-main -Xfrontend -enable-experimental-concurrency import XCTest extension Result where Failure == Swift.Error { public init(catching body: () async throws -> Success) reasync { do { self = .success(try await body()) } catch { self = .failure(error) } } } public func XCTAssertEqual2<T: Equatable>( _ expression1: @autoclosure () async throws -> T, _ expression2: @autoclosure () async throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line ) reasync { let (result1, result2) = await (Result(catching: expression1), Result(catching: expression2)) XCTAssertEqual(try result1.get(), try result2.get(), message(), file: file, line: line) } func foo() async -> Int { 1 } class ATest: XCTestCase { func testFoo() async { await XCTAssertEqual2(await foo(), 1) } static let allTests = [("testFoo", asyncTest(testFoo))] } XCTMain([testCase(ATest.allTests)]) (edited)
reasyncはとりあえず入っているけどまだ途中段階なんだと思ってます(rethrowsと連動しているんですかね?)。 https://forums.swift.org/t/pitch-fix-rethrows-checking-and-add-rethrows-unsafe/44863 https://github.com/apple/swift/pull/36007
Avatar
Avatar
shiz
パッと見て一箇所気になったのですが(全然大した話でないです🙇🏻‍♂️ ) UIResponder@MainActorが付いているので、AppDelegateには必要ないかもしれません。
なんと…! @available(iOS 2.0, *) open class UIResponder : NSObject, UIResponderStandardEditActions { ただ UIResponder の定義に飛んでも MainActor が付いていないんですよね、、 別の場所で付いているのでしょうか?
Avatar
Swiftが自動で@MainActorを設定しているものがあって、その場合はなぜか出てこないんですよね(UIViewControllerなども)。ドキュメントやヘルプには出てきます。 https://developer.apple.com/documentation/uikit/uiresponder
Avatar
Avatar
shiz
Swiftが自動で@MainActorを設定しているものがあって、その場合はなぜか出てこないんですよね(UIViewControllerなども)。ドキュメントやヘルプには出てきます。 https://developer.apple.com/documentation/uikit/uiresponder
ホントだ、ヘルプには出てきますね! Discord のどこかで「(少なくとも現時点では)UIViewController は明示的に @MainActor を指定する必要がある」と見たのですが、 AppDelegateSceneDelegate は大丈夫なのでしょうか…?(そのあたりがよくわからず)
1:16 AM
いや、これはメソッドの話か わからぬ…w
Avatar
Avatar
uhooi
ホントだ、ヘルプには出てきますね! Discord のどこかで「(少なくとも現時点では)UIViewController は明示的に @MainActor を指定する必要がある」と見たのですが、 AppDelegateSceneDelegate は大丈夫なのでしょうか…?(そのあたりがよくわからず)
これは現状は @MainActorになるけど、ならない方が良いのでは?ということではないですか? (edited)
Avatar
Avatar
shiz
これは現状は @MainActorになるけど、ならない方が良いのでは?ということではないですか? (edited)
あ、よく見るとそうだ これじゃないです、、
1:20 AM
@the_uhooi 前に教えてもらったんですが、Swift 5.5の時点ではUIViewControllerなどがMainActorなのはオプトインっぽい ので現段階で使いたかったら自分で明示しないとダメそう https://t.co/XBZ1iMMsEw
Avatar
Avatar
uhooi
あ、よく見るとそうだ これじゃないです、、
Concurrencyを使っている場合は強制されるとあるので、今回は明示しなくて良いのではないんですかね? あれ?違うのか?Concurrency使っていればUIViewControllerの@MainActor(unsafe)が有効になるのかと思ってました。 https://twitter.com/rintaro/status/1442543055597301765 (edited)
@giginet https://t.co/aWDroVPvsv UIKitのNS_SWIFT_UI_ACTORはSwift5.5ではMainActor(unsafe) なので利用側が concurrency の機能を使っている時だけ強制されると思います
Avatar
Avatar
shiz
Concurrencyを使っている場合は強制されるとあるので、今回は明示しなくて良いのではないんですかね? あれ?違うのか?Concurrency使っていればUIViewControllerの@MainActor(unsafe)が有効になるのかと思ってました。 https://twitter.com/rintaro/status/1442543055597301765 (edited)
よくわからないんですよね…。 NS_SWIFT_UI_ACTOR の定義を見ても私だと理解できず、、 https://github.com/uhooi/UhooiPicBook/pull/265/files#r770694602 #if __has_attribute(swift_attr) # define NS_SWIFT_UI_ACTOR __attribute__((swift_attr("@UIActor"))) #else # define NS_SWIFT_UI_ACTOR #endif
Issues close #223 close #260 Overview Use Swift Concurrency. Details Replace completion handler with async function Add @MainActor to All View ( UIViewController , UICollectionViewCell etc) All...
Avatar
Avatar
shiz
Swiftが自動で@MainActorを設定しているものがあって、その場合はなぜか出てこないんですよね(UIViewControllerなども)。ドキュメントやヘルプには出てきます。 https://developer.apple.com/documentation/uikit/uiresponder
もしかして SwiftUI の Viewbody が Main Actor Context で実行されるのもそれですか? body@MainActor 付いてないし、どこから来てるんだろうと思ってたんですが。 https://developer.apple.com/documentation/swiftui/view/body-swift.property
Avatar
Avatar
uhooi
よくわからないんですよね…。 NS_SWIFT_UI_ACTOR の定義を見ても私だと理解できず、、 https://github.com/uhooi/UhooiPicBook/pull/265/files#r770694602 #if __has_attribute(swift_attr) # define NS_SWIFT_UI_ACTOR __attribute__((swift_attr("@UIActor"))) #else # define NS_SWIFT_UI_ACTOR #endif
コンパイラ周り全然詳しくないんですが、swift_attrがあればUIActor(MainActor)を付けて、なければ何も付けない、という意味なんですかね?(このswift_attrが何を指しているのかがよくわからないですが…) https://clang.llvm.org/docs/AttributeReference.html#swift-attr __attribute__((swift_attr("swift attribute”)))はattributeをObjective-Cに付けるものみたいですね。 __attribute__((swift_attr("swift attribute"))). A general-purpose Objective-C attribute to allow one to provide Swift attributes directly. In the context of concurrency, this allows Objective-C APIs to be annotated with a global actor (e.g., @MainActor) https://github.com/apple/swift-evolution/blob/5bf0cf0b00169297ba9bc30291477cbbe1343145/proposals/0297-concurrency-objc.md#additional-objective-c-attributes
👀 1
Avatar
Avatar
koher
もしかして SwiftUI の Viewbody が Main Actor Context で実行されるのもそれですか? body@MainActor 付いてないし、どこから来てるんだろうと思ってたんですが。 https://developer.apple.com/documentation/swiftui/view/body-swift.property
これはObjective-Cのヘッダに追加されているものだと思ってました(間違っていたらご指摘ください)。 SwiftUIはわからないですね…確かにどこから来ているんですかね
Avatar
Avatar
shiz
これはObjective-Cのヘッダに追加されているものだと思ってました(間違っていたらご指摘ください)。 SwiftUIはわからないですね…確かにどこから来ているんですかね
UIViewController とかはドキュメント見ても @MainActor 付いてるんですけど、 SwiftUI の View は見た当たらないんですよね。 https://developer.apple.com/documentation/uikit/uiviewcontroller https://developer.apple.com/documentation/swiftui/view https://developer.apple.com/documentation/swiftui/view/body-swift.property
Avatar
.swiftinterfaceみると @_Concurrency.MainActor(unsafe) 書いてありますね @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @_typeEraser(AnyView) public protocol View { static func _makeView(view: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs static func _makeViewList(view: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewListInputs) -> SwiftUI._ViewListOutputs @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) static func _viewListCount(inputs: SwiftUI._ViewListCountInputs) -> Swift.Int? associatedtype Body : SwiftUI.View @SwiftUI.ViewBuilder @_Concurrency.MainActor(unsafe) var body: Self.Body { get } } (edited)
t_naruhodo 1
🙇🏻‍♂️ 1
Avatar
Avatar
shiz
コンパイラ周り全然詳しくないんですが、swift_attrがあればUIActor(MainActor)を付けて、なければ何も付けない、という意味なんですかね?(このswift_attrが何を指しているのかがよくわからないですが…) https://clang.llvm.org/docs/AttributeReference.html#swift-attr __attribute__((swift_attr("swift attribute”)))はattributeをObjective-Cに付けるものみたいですね。 __attribute__((swift_attr("swift attribute"))). A general-purpose Objective-C attribute to allow one to provide Swift attributes directly. In the context of concurrency, this allows Objective-C APIs to be annotated with a global actor (e.g., @MainActor) https://github.com/apple/swift-evolution/blob/5bf0cf0b00169297ba9bc30291477cbbe1343145/proposals/0297-concurrency-objc.md#additional-objective-c-attributes
おおっ詳細にありがとうございますー! そうなると AppDelegateUIViewController などに、明示的に @MainActor を付ける必要はなさそうですね…。
Avatar
UIViewController のサブクラスには明示的に @MainActor を付けないと、 Sendable 扱いにならず、 Task.init のクロージャの中から self にアクセスできずに困ると思います。
Avatar
あとはMainActor(unsafe)とMainActorは別物なので、付けるときに意識してどちらに倒すかは考えることになりそう
Avatar
Avatar
koher
UIViewController のサブクラスには明示的に @MainActor を付けないと、 Sendable 扱いにならず、 Task.init のクロージャの中から self にアクセスできずに困ると思います。
なんと…。なぜ Sendable 扱いにならないのでしょうか?
Avatar
Avatar
tarunon
あとはMainActor(unsafe)とMainActorは別物なので、付けるときに意識してどちらに倒すかは考えることになりそう
unsafe とはどのような意味でしょうか? 直感的には「安全じゃない → 他のアクターコンテキストに渡せない → Sendable でない」のような感じがしますが
Avatar
Actor周りの検査項目ですっ飛ばされるのがどこかにあったはず
3:51 AM
本来警告が出るべきところで出なくなるのがあります。過去ログで見つけたときのが確か…
3:52 AM
https://discord.com/channels/291054398077927425/291054454793306112/900292832726745088 この辺りのログを漁って色々試してみて下さい
Avatar
なるほど、警告が出なくなるのですね そしたらできれば避けたほうがよさそう ありがとうございます!
Avatar
protocolで宣言された関数をMainActorアトリビュートのついたclassに実装するとき、existential経由での呼び出しではActorContextを受け取れない可能性があるためselfメソッドの呼び出しはasyncにしろ、と警告が出る。これが何もつけてないMainActorの挙動。
👀 1
3:57 AM
この検査を無視するのがMainActor(unsafe)です。
3:57 AM
他にも無視される項目があるかもしれない
Avatar
ああそうか。既存の UIKit のオブジェクトの振る舞いを定義しているんだな。
Avatar
delegate側の宣言にもMainActorつけたらそれでいいんだけどね
Avatar
一昨日の話だと、 @MainActor が付与されたクラスのサブクラスは、オーバーライドしたメソッドは @MainActor に保護されるけど、それ以外のメソッドは保護されないって話じゃなかったですっけ?僕の勘違い? import UIKit class ViewController: UIViewController, Sendable { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) print("viewDidAppear 1", Thread.isMainThread) Task { print("viewDidAppear 2", Thread.isMainThread) await Actor().callFoo(of: self) } } func foo() { print("foo 1", Thread.isMainThread) Task { print("foo 2", Thread.isMainThread) } } } actor Actor { func callFoo(of viewController: ViewController) async { print("callFoo", Thread.isMainThread) await viewController.foo() } } viewDidAppear 1 true viewDidAppear 2 true callFoo false foo 1 true foo 2 true
4:06 AM
foononisolated 付けたら↓になるので、 fooMainActor に保護されてるっぽい。 foo 1 false foo 2 false
Avatar
コンパイラオプションによって警告出たりでなかったりなので
4:06 AM
あんまり信用できない
Avatar
警告はともかく、 foo 1foo 2 の結果が truefalse かが異なるので、挙動が変わってるかと。 (edited)
Avatar
その辺りの話も上に貼ったリンクのログの前後にあります
Avatar
これ関係してたりしますかね? https://bugs.swift.org/browse/SR-15131
Avatar
なるほど、 ViewController@MainActor: Sendable を付けなかった場合に、 ViewControllerSendable にならないのがバグなのか。
Avatar
「挙動の理解が難しいから UIViewController にはとりあえず明示的に @MainActor を付ける」という戦略もありかも(私にはちょっと難しい、、)
4:10 AM
付けて困ることはないはず
Avatar
コンパイラオプション全部厳しい方に倒して、警告が出ないように組むのが一番良さそうだと考えています
👀 1
Avatar
Doug Gregor added a comment - 2 days ago This was super fun, to be resolved by https://github.com/apple/swift/pull/40544
2 days ago 😂
(edited)
Avatar
ただまあそれすると結構大変なんですが…
4:10 AM
そこを目指して取り組んでいくのが良さそう
👀 1
Avatar
Avatar
koher
Doug Gregor added a comment - 2 days ago This was super fun, to be resolved by https://github.com/apple/swift/pull/40544
2 days ago 😂
(edited)
そうなんですwなので次のスナップショットで挙動を確認したいと思ってたところだったんですw
Avatar
Avatar
koher
Doug Gregor added a comment - 2 days ago This was super fun, to be resolved by https://github.com/apple/swift/pull/40544
2 days ago 😂
(edited)
こういうのがあると現状で細かいこと考えるの難しいですね
😢 4
Avatar
僕も厳しい方に倒して警告全部解消するのが正解だと思います。現状は Swift 6 への移行期間で、将来的にコンパイルできなくなるはずなので。
👀 1
Avatar
Avatar
omochimetaru
こういうのがあると現状で細かいこと考えるの難しいですね
これが仕様かと思ってたから、オーバーライドしたメソッドのみ MainActor-isolated なのかと思ってたのに。
4:13 AM
サブクラスで追加したプロパティも保護の対象外かと思ってた。ただのバグだったのか・・・。
Avatar
すいませんもう一つ確認したいことが出てきたのですが...GlobalActorプロトコルはSendableを継承してないですよね?(ただドキュメントや定義から見えない訳ではなく) すいません自己解決しました...これが知りたかっただけでした(なんか別の話とごちゃまぜになってました...)🙇🏻‍♂️ A non-protocol type that is annotated with a global actor implicitly conforms to Sendable. https://github.com/apple/swift-evolution/blob/main/proposals/0316-global-actors.md#using-global-actors-on-a-type (edited)
👍 1
Avatar
質問させてください。
Avatar
udemyで買った受講のサンプルコードを含んでいるので、全部貼れないのですが、やりたい事はviewで表示された画像を別クラスから読みこめるようにしたいです。 処理をクラスに分ける前は読み込めていたのですが、クラスで囲ったら読み込めなくなってしまいました。
6:50 AM
import SwiftUI import CoreML import Vision struct ContentView: View { let mlwork = Mlwork() var body: some View { VStack { Text(mlwork.classifLabel) .padding() .font(.title) Image("cat") .resizable() .frame(width: 300, height: 200) Button(action: { mlwork.classfyimage(image: UIImage(named: "cat")!) }, label: { Text("この猫は何猫?") .padding() }) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
6:52 AM
import SwiftUI import CoreML import Vision struct Mlwork { @State var classifLabel = "" //画像を分類する func classfyimage(image: UIImage){ //←ここで読み込めないと思われる guard let ciImage = CIImage(image: image) else{ fatalError("変換出来ません") } let handler = VNImageRequestHandler(ciImage: ciImage) let classificationrequest = classifrequest() do{ try handler.perform([classificationrequest]) } catch { fatalError("失敗しました") } } }
6:52 AM
超初歩的な事だと思いますが良ければ教えてください。
Avatar
// (1) ↓ここの `!` UIImage(named: "cat")! // (2) fatalError("変換出来ません") ↑どっちで失敗してるんでしょうか?
12:00 PM
(1)なら、画像ファイル cat がプロジェクトに追加されてない (2)なら画像ファイル cat が壊れてる、別のファイルになっている などが原因だと予想します。
12:01 PM
コンパイルできているなら、コードに問題は無いと思います。
Avatar
ViewではないMlwork構造体に@Stateを生やしているのがまずいんじゃ無いですかね
Avatar
あー、処理はうまくいってるけど画面にラベルテキストが出てないだけ?
Avatar
おそらく分割する前は classifLabel がContentViewのフィールドとして定義されていて、うまくいっていたんだと思います
naruhodo 1
12:06 PM
これは罠ですねぇ…
Avatar
返事遅れてすいません まだデバックの仕方も良く分からずなのですが、シュミレーションすると、 fopen failed for data file: errno = 2 (No such file or directory) と出るので分割したクラス側で画像を参照できていないのかと思っていました 今現在もググって解決法を模索中です。 もしかしたらラベルが出ていないだけかもしれないので色々試しています。 色んな記事を読むと値渡しがswiftの初心者の壁みたいなの😅
Avatar
fopen failed なら UIImage(named: "cat")! が失敗してそう
2:07 PM
一度に全部やらずに1行ずつコードを足していけばどこで壊れてるか絞り込めますよ
Avatar
ありがとうございます とりあえずこのクラスの呼び方で問題ないのか違うクラス(中に変数だけ)をやってみたところ値は返ってきたので書き方的には問題ないのが分かりました このテストクラスで色々試して見ようと思います。
Avatar
たびたび失礼します。 昨日から色々と試しているのですが、解決出来ておりません。 問題は変数に代入したいというかなりシンプルな問題なのです。 以下のコードをview側、別処理をしているクラスに書いてみたのですが、いずれも変数を更新する事が出来ませんでした。
10:43 AM
import SwiftUI import CoreML import Vision class Mlwork { var classifLabel:String = "" func labelupdate(tmp:String){ classifLabel = tmp print(classifLabel) }
10:44 AM
サンプルコードはググったら幾らでも出て来そう
Avatar
ありがとうございます。
Avatar
インスタンス化の際はinitで代入できるのですが、同じ変数の指定の方法でも入らないので、もうちょっと色々と勉強してから分割に挑戦してみます。 >おそらく分割する前は classifLabel がContentViewのフィールドとして定義されていて、うまくいっていたんだと思います この部分が理解できれば出来そうなのですが、まだ無理なので・・・ またよろしくお願いします🐯
Avatar
まずはSwiftUIの基本的なレンダリングの仕組みについて学ぶのが良さそうですが、いい資料あるかな
Avatar
こちらは読まれましたか? https://developer.apple.com/documentation/swiftui/state
You should only access a state property from inside the view’s body, or from methods called by it. For this reason, declare your state properties as private, to prevent clients of your view from accessing them.
ということで、privateをつけてあげると何かしらの誤用に気づくかもしれません
Avatar
そもそも前提として、プログラミング自体が初学者なのか、それは超えた上でSwiftUIに詰まってるのかで処方箋が違う気もする
Avatar
https://discord.com/channels/291054398077927425/291054398077927425/926360332765626389 を見る感じだと普段はPHPのお仕事をされているそう?
Avatar
そしたらSwiftUIのレンダリングの仕組みを理解するのが一番良さそう
11:45 AM
任意のフィールドに宣言した値は、書き換えるだけでは画面には反映されない。仮想DOMが値をリアルDOMに反映するのはレンダリングをするときのみなので、何かの値を更新したら再度レンダリングを走らせないといけない (edited)
11:46 AM
この役割を担うのがStateやObservableObjectになる、この辺りを理解するのが良さそう
Avatar
画面の再描写もあるのですが、 func labelupdate(tmp:String) -> String{ self.classifLabel = tmp これで代入が出来なくて詰みました。 まだ画面遷移などもやっていないので、もっと難しくなるかと思うと心配です。
Avatar
ちょっと変な実装方法になってしまいましたが、一応出来ました >SwiftUIのレンダリングの仕組みを理解するのが一番良さそう この通りでimport SwiftUI をするとその中の変数の扱われ方が全然把握できてないです ここを理解できると結構自由に色々できそうなのですが、そこに初心者の壁があるとよく書かれているので相当理解するのが難しそうな予感です
Avatar
チュートリアルとしては https://developer.apple.com/tutorials/swiftui/handling-user-input をおさらいしておくと良いかもしれません。
Avatar
ありがとうございます! swiftにもチュートリアルあったんですね
Avatar
aimai (SwiftUI-beginner) 1/30/2022 11:26 AM
SwiftUI初心者です。 .offsetを使って.animetionで動かしたいんですけど、.offsetの座標に変数を割り当てることってできないんですかね、、??
Avatar
やりたいことと困ってることが自明じゃないのでエスパーになりますが 1. Viewの現在のパラメータを知りたい → GeometryReader 2. Viewの中に動的に変更可能な変数を設置したい → @State を使って、目的が達成できるのではないかと思います。公式のドキュメントやサンプルコードをチェックしてみると良いと思います
Avatar
aimai (SwiftUI-beginner) 1/30/2022 11:50 AM
あ!ありがとうございます!
11:50 AM
2で試してたんですけどCGFloatを使用するんですね
11:50 AM
サンプルコードを調べたらできました!
👏 1
Avatar
ハマってたのはCGFloatとDoubleの暗黙変換がなくてかつ、少数リテラルの優先順位がDoubleの方が高かった、とかその辺りかな
Avatar
aimai (SwiftUI-beginner) 1/30/2022 12:34 PM
もう一つ教えていただきたいです!
12:34 PM
画面をタッチした時の座標を取得したいです
12:34 PM
何を使ったらいいのかさっぱりです
12:34 PM
CGPointとか使ったらできるのかなと思うのですが、、、
Avatar
Kishikawa Katsumi 1/31/2022 2:50 AM
DragGestureなら引数にタッチの情報が渡ってきます。 .gesture( DragGesture() .onChanged { (value) in print(value.location) } .onEnded { (value) in print(value.location) } )
Avatar
Avatar
Kishikawa Katsumi
DragGestureなら引数にタッチの情報が渡ってきます。 .gesture( DragGesture() .onChanged { (value) in print(value.location) } .onEnded { (value) in print(value.location) } )
aimai (SwiftUI-beginner) 1/31/2022 9:22 AM
ありがとうございます 帰ったら使ってみます
Avatar
自分が管理していないライブラリ内でextensionを使ってString型に生えてるライブラリ独自のプロパティを利用者側のコードの変更でコンパイルが通らないようにする(もしくはワーニングを出す)ことは可能でしょうか? 自分が試したこととしては
  • SwiftLintのカスタムルール(自分が遭遇したケースは正規表現で絞り切れるものだったので今回はこれを利用しました)
  • プロパティをオーバーライドして@available()でunavailableにする
    • 大元のライブラリの方のプロパティが利用されてしまった
  • プロパティをオーバーライドして@available()でdeprecatedにする
    • 結局コンパイルはできてしまう
    これ以外により良い方法があれば教えていただきたいです。
(edited)
Avatar
extensionに追加したプロパティをinternalにするのが素直な方法かなぁと思いました。
Avatar
自分が管理してるライブラリではないんです..言葉足らずでした。
Avatar
PR投げるとか
Avatar
protocol extensionだったらinternalにできないよなーと思ってました。 このケースだとPRでも解決できないですよね。具体的にどんな理由で呼ばせたくないんでしょうか?
Avatar
Swift based OAuth library for iOS. Contribute to OAuthSwift/OAuthSwift development by creating an account on GitHub.
😰 1
Avatar
何かキツそうな予感
Avatar
ぐへぇ。行儀悪い
Avatar
このライブラリなのですがstring のプロパティが辛くて、チーム開発時に意図せずSwiftGenのリソースを扱う時に.string をつけてしまっているケースが多発していて、それを防ぎたいというモチベーションでした (edited)
1:47 AM
正攻法はstring を消すPRを出すことな気が確かにするのですが、OAuthをする上で需要があるのかなという気もしてよく分からずという感じです (edited)
Avatar
https://github.com/Alamofire/Alamofire/blob/56ce89783d7ebd67444d09d7a0aa20ffa7aa55af/Source/URLConvertible%2BURLRequestConvertible.swift 同じようなのあったよなと思ってalamofire見てみましたがこっちは関数になってるので多少まし?ですね
👍 1
Avatar
この辺のprotocolは露出させずinternalにして、境界の関数を全部overloadで作るのが良いよなと思うんだけど
1:50 AM
それを受け入れられる形でPRを作る自信がない
Avatar
えー、ということであれば、OAuthSwiftを@_implementationOnly付きでimportする別ライブラリXを作って、最小限のインターフェイスのみを露出させ、アプリケーションコードではOAuthSwiftを直接importさせずにXをimportさせるのが良いと思います
👉 1
👀 2
👍 1
😲 3
1:51 AM
@_implementationOnly付けないと多分孫依存のextension見えちゃうんで
Avatar
なるほど!こういうところで@_implementationOnly がつかえるんですね。ありがとうございます! (edited)
Avatar
omochimetaru 2/2/2022 2:39 AM
private importって感じだ
Avatar
Swift と直接は関係ない質問なのですが、プロトコルでなく具体的な型に注入することも DI と呼ぶのでしょうか? 例えば以下です↓ class FooInteractor { private let httpClient: HTTPClient init(httpClient: HTTPClient) { self.httpClient = httpClient // ???: DI ? } } class HTTPClient {} 私は DI ではないと思うのですが、↓の記事のコメントで「一般的には DI と呼ぶ」と書かれているので、どちらなのか気になっています…。 https://qiita.com/uhooi/items/03ec6b7f0adc68610426
はじめに 本記事は Swift/Kotlin愛好会 Advent Calendar 2021 の17日目の記事です。 空いていたので埋めました。 「依存性逆転の原則」と「依存性の注入」を完全に理解したので説明します。 「依...
Avatar
omochimetaru 2/4/2022 10:27 AM
僕はDIだと思ってます。型による抽象化をするかどうかは本質ではないと思います。
Avatar
僕もSwiftのprotocolを使っているかどうかは関係ないと思ってますね。HTTPClient がfinalじゃなかったら機能的にはprotocolと同じじゃないですか?
Avatar
僕も DI だと思いますが、もし HTTPClientfinal なら違うと思います。
10:32 AM
あと、 UIKit とかの delegate も DI だと思ってます。
10:33 AM
あと、プロトコル以外だと、関数を渡す DI とかもありますね。
10:34 AM
僕は型パラメータによる DI もよくやります(これはプロトコルですが)。 @MainActor final class FooViewState<Repository: RepositoryProtocol>: ObservableObject { ... } (edited)
Avatar
おお…そうなのですね…。 まだちょっと納得がいっていなくて、これは Constructor Injection だから DI っぽく見えるだけな気がしてしまうんですよね。 この意見だと Setter Injection でも DI と呼ぶということでしょうか? class FooInteractor { var httpClient: HTTPClient } class HTTPClient {} var interactor = FooInteractor() interactor.httpClient = HTTPClient() // ???: これも DI ? 継承できれば DI ということは、 HTTPClient でなくプリミティブ型だったら DI ではない?
Avatar
その HTTPClient がサブクラスを作って挙動を差し替えるものかどうかによるんじゃないでしょうか?
10:37 AM
HTTPClient を受け取ることを期待しているならそれは DI じゃないですが、サブクラスを受け取ることを期待していたら DI だと思います。
10:38 AM
setter injection でも constructor injection でも。
10:39 AM
HTTPClient 自身も渡せるし、サブクラスも渡せる場合でも、そのサブクラスがモジュールの外で宣言されていたら DI かと。
Avatar
確かに、 HTTPClient を継承した HTTPClientMock を注入することはできますもんね、、 class FooInteractor { private let httpClient: HTTPClient init(httpClient: HTTPClient) { // !!!: `HTTPClientMock` も渡せる self.httpClient = httpClient } } class HTTPClient {} final class HTTPClientMock: HTTPClient {}
Avatar
モジュールの内外も関係ないかな。
Avatar
omochimetaru 2/4/2022 10:40 AM
僕はfinalじゃなくてもstructでもDIだと思ってます、振る舞いの可変制は本質ではない 依存を渡してるからDI たとえばそのstructのプロパティをどうするかなどは隠蔽されてます
Avatar
DIP はモジュールの内外が関係あるけど、 DI 自体は別に同じモジュール内でも DI と言えそう?
Avatar
なるほど、そしたら DI の境目はどこにあるのでしょう? ↓はさすがに DI とは言わないと思うんですよね。そしたらプロパティの代入すべてが DI になるので。 class FooPresenter { var count = 0 } let presenter = FooPresenter() presenter.count = 1 // !!!: これをDIとはいわない
Avatar
Avatar
omochimetaru
僕はfinalじゃなくてもstructでもDIだと思ってます、振る舞いの可変制は本質ではない 依存を渡してるからDI たとえばそのstructのプロパティをどうするかなどは隠蔽されてます
それだと↓も DI になっちゃわない? struct Foo { init(x: Int) } Foo(x: 42) (edited)
Avatar
Avatar
koher
それだと↓も DI になっちゃわない? struct Foo { init(x: Int) } Foo(x: 42) (edited)
omochimetaru 2/4/2022 10:44 AM
気持ちの問題だと思ってて、コードの意味論で線は引けないと思ってます。 モジュールとかコンポーネントの単位であればDI
Avatar
文法による明確な差はなくて、意識付けの問題な気がしてます。 foo.count = 2 だろうと、それがスレッド数を意味してたらDIと言えそう
10:45 AM
さすがにスレッド数はただの設定値かも
Avatar
DIP の D と DI の D を同じものだと考えるなら、モジュールの依存関係が重要そうだけど。
10:47 AM
DIPのD(Dependency)はモジュールの依存関係のことだし、それを実現するための手段としてDIがあるけど、DIのDは必ずしもモジュールの依存関係を指さない気がする。
10:48 AM
そういう意味では気持ちの問題なのかなぁ。振る舞いを注入してる気持ちならDI?
Avatar
omochimetaru 2/4/2022 10:49 AM
dipのpはパターンのpですか?
Avatar
dependency inversion principle
10:50 AM
SOLIDのD
Avatar
omochimetaru 2/4/2022 10:50 AM
逆転の法則のやつか
Avatar
DIPにもDIにもD(Dependency)が入っていて両者は関係してるけど、両者の指すDependencyが異なる(後者のDの方が広い)というのはわかりづらいな・・・。 (edited)
Avatar
omochimetaru 2/4/2022 10:52 AM
DIという言葉が普及したのって、javaのフレームワークで https://ja.m.wikipedia.org/wiki/依存性の注入
10:53 AM
外部の設定ファイルなどでオブジェクトを注入できるようにするソフトウェアパターンである。英
10:53 AM
このXMLファイルで構成を指定して
10:53 AM
ビルド済みのjarバイナリに対して
10:54 AM
リビルドせずに変更できるxmlを駆使して最終デプロイを行う事が流行った経緯と強く関連していると思っていて
10:54 AM
それが後世で、コンストラクターでコードで渡せば良い,リビルドすれば良い、 という派生思想が育ってきた事で
10:55 AM
DIという言葉自体はほぼ意味をもたなくて、コード意味論で言えばほぼなんでもDIと言える状態になったと思っています
10:55 AM
なので現代のこの言葉は実用的には気持ちの問題として設計を整理する時に、何が依存か、という決めだけの問題になるというか。
10:56 AM
逆転の法則の話をする場合にはその定義から抽象化による反転が重要で、それはデザインパターンやベストプラクティスの文脈になっていると思う
Avatar
なるほどDIは気持ちの問題なのですね、、 依存性を注入している気持ちで書いていたらDI、そうでなかったらDIじゃないのか、、
Avatar
Avatar
uhooi
なるほどDIは気持ちの問題なのですね、、 依存性を注入している気持ちで書いていたらDI、そうでなかったらDIじゃないのか、、
omochimetaru 2/4/2022 11:22 AM
元々一つで書いているコードを、二つのコンポーネントに分けて、その注入の表現にできないか? という目線を持つことに実用性があると思っていて、 その目線を持つ上でDIという概念を知っていると便利、みたいな認識です
✨ 1
11:24 AM
MVPみたいなアーキテクチャから話が出発すると、最初からViewとPresenterという二つのものが分離されている世界から話が始まるからそういう効果はないんですけど、より一般的な状況において。
👍 1
Avatar
自分の記事をどう修正するか迷う、、 「DI の定義や考え方は人によって違います」という注意書きを入れた上で、一般的だと思われる考え方をまとめるか、、
Avatar
型レベルの話と値レベルの話があるのは、型のあるプログラミングの話題全般に言えることの気がしますね (edited)
👀 1
Avatar
質問です。 API Design Guidelinesで前置詞句(前置詞と名詞の句)をラベルにする例で、x.removeBoxes(havingLength:)が使われているんですが、"having"は前置詞なんですかね? https://www.swift.org/documentation/api-design-guidelines/#argument-labels
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
これは前置詞省略なんでは?という気がします
😀 1
7:57 AM
前置詞+動詞ingで前置詞が省略されるパターン
Avatar
省略してるパターンなるほど〜。ありがとうございます 🙇‍♂️
Avatar
知ってる方いらっしゃったら教えてほしいですが、Notification Service Extension使って、何かPush通知もらった時に、その通知をもらったよってFirebase通じてイベント送信できますか(Extension内でFirebase SDK使えますか)?
Avatar
Firebase全部使うかはアレですが、以下のようなものも提供されているので、使えると思いますよ。https://firebase.google.com/docs/cloud-messaging?hl=ja
Firebase Cloud Messaging(FCM)は、メッセージを無料で確実に送信するためのクロスプラットフォーム メッセージング ソリューションです。
Avatar
FCMあまり詳しくないですが、それってExtension Bundle内でも使われてるんですか?アプリ本体起動時にTokenの設定とかだけではなくて?
9:24 AM
いけそうなかんじ
9:25 AM
NotificationServiceでいけそうと思ったがこれは本体内の断片的なコードか
Avatar
(ちなみになぜこう言う質問するかというと、今まさにFCM使ってますが、そこで通知受信時に出せるイベントnotification_receiveがAndroidのみでして… 🤔 https://support.google.com/firebase/answer/9234069?hl=ja
アプリまたはサイトでの基本的な操作によってトリガーされたイベントは、自動的に収集されます(以下の表のイベント名に示されるとおり)。SDK
Avatar
検証段階なら一回やってみるのが手っ取り早いんじゃないだろうか
9:26 AM
importしてビルドしてダメなら考えるで良さそう
Avatar
(まあまさに手を動かす前に先人の知恵をお借りしたいところで(ry
Avatar
ググって見つからないなら手を動かしなさいw (edited)
Avatar
Push通知の検証って面倒ですからね 😇
Avatar
それはわかる
9:29 AM
FirebaseがExtensionでビルド通るかどうかだけなら、そっちはすぐ終わりそうなもんだけど
Avatar
問題はその後動くかどうかですよね、そもそもExtensionで外部ライブラリー読み込めるかどうか
Avatar
それは外部ライブラリが、禁止API使ってなければ問題ないはず
9:31 AM
禁止API使ってたらビルド通らないからすぐわかる
Avatar
Avatar
lovee
知ってる方いらっしゃったら教えてほしいですが、Notification Service Extension使って、何かPush通知もらった時に、その通知をもらったよってFirebase通じてイベント送信できますか(Extension内でFirebase SDK使えますか)?
Notification Service Extension使って、何かPush通知もらった時に、その通知をもらったよってFirebase通じてイベント送信できますか
これはやったことがないんですが、 Extension内でFirebase SDK使ったアプリを公開しています。 (Widget Extension ですが)
👀 2
9:35 AM
こんな感じです。 @main struct WidgetExtension: Widget { let kind: String = "WidgetExtension" init() { FirebaseApp.configure() // ここに置いた } // 共有 iOS キーチェーンを使ったアプリ間認証を有効にする try? Auth.auth().useUserAccessGroup("*****") } 今回のケースとはやりたいことが違うと思いますが、なにか参考になれば!
Avatar
ありがとうございます!
👍 1
Avatar
import Foundation @propertyWrapper struct CheckBox: Codable { var wrappedValue: Bool init(wrappedValue: Bool) { self.wrappedValue = wrappedValue } init(from decoder: Decoder) throws { do { _ = try String(from: decoder) self.wrappedValue = true } catch { self.wrappedValue = false } } } struct POST: Decodable { @CheckBox var checked: Bool @CheckBox var unchecked: Bool } let checked = """ { "checked": "on" } """ let post = try JSONDecoder().decode(POST.self, from: checked.data(using: .utf8)!) assert(post.checked == true) assert(post.unchecked == false) Vaporで、<input type="checkbox" /> で送られてきたデータをBoolとしてデコードしたいのですがpropertyWrapperを用いてできないでしょうか? チェックされている場合は文字列が来るのですが、チェックされていない場合はそもそも何も送信されないため、propertyWrapperに処理が渡る前にデコード失敗してしまい不可能な気がしているのですが合っているでしょうか。
Avatar
omochimetaru 3/1/2022 5:03 AM
wrappedValueの型を Bool? にした上で
5:05 AM
5:06 AM
トリックとしては、Codable自動生成では、プロパティの型に対するdecodeが書き下されているんですが、 そこで具象型が書き下されていて、メソッドのオーバーロード解決はSwiftの言語仕様に基づいて通常通り行われるので、 具象型の KeyedDecodingContainer.decode が実装されていれば、そっちが優先するという技です (edited)
Avatar
@swift-5.5.3 import Foundation @propertyWrapper struct CheckBox: Codable { var wrappedValue: Bool init(wrappedValue: Bool) { self.wrappedValue = wrappedValue } init(from decoder: Decoder) throws { do { _ = try String(from: decoder) self.wrappedValue = true } catch { self.wrappedValue = false } } } extension KeyedDecodingContainer { func decode(_ type: CheckBox.Type, forKey key: Self.Key) throws -> CheckBox { try decodeIfPresent(type, forKey: key) ?? CheckBox(wrappedValue: false) } } struct POST: Decodable { @CheckBox var checked: Bool @CheckBox var unchecked: Bool } let checked = """ { "checked": "on" } """ let post = try JSONDecoder().decode(POST.self, from: checked.data(using: .utf8)!) assert(post.checked == true) assert(post.unchecked == false)
Avatar
Avatar
t.ae
@swift-5.5.3 import Foundation @propertyWrapper struct CheckBox: Codable { var wrappedValue: Bool init(wrappedValue: Bool) { self.wrappedValue = wrappedValue } init(from decoder: Decoder) throws { do { _ = try String(from: decoder) self.wrappedValue = true } catch { self.wrappedValue = false } } } extension KeyedDecodingContainer { func decode(_ type: CheckBox.Type, forKey key: Self.Key) throws -> CheckBox { try decodeIfPresent(type, forKey: key) ?? CheckBox(wrappedValue: false) } } struct POST: Decodable { @CheckBox var checked: Bool @CheckBox var unchecked: Bool } let checked = """ { "checked": "on" } """ let post = try JSONDecoder().decode(POST.self, from: checked.data(using: .utf8)!) assert(post.checked == true) assert(post.unchecked == false)
swift55 BOT 3/1/2022 5:08 AM
no output
Avatar
なるほど、extensionで差し込めるわけですね。 wrappedValueはOptionalにしなくてもいいようでした。
Avatar
omochimetaru 3/1/2022 5:09 AM
あー、この場合はnilじゃなくてfalseにしたいのか。そうですね。Optionalにする必要はなかったですね。
Avatar
UIから二値なのは確定なのでBool? にするメリットがないためですね。 これ使って実装進められそうです。ありがとうございました。
Avatar
クロージャのキャプチャリストで強参照した場合( closure { [hoge] in ... }
9:13 AM
クロージャが解放されたらキャプチャリストの変数の参照カウントって-1されるって理解でいいんでしょうかね?何か調べる方法あれば知りたいです。
Avatar
omochimetaru 3/9/2022 9:19 AM
クロージャの開放時に -1 されると思います。
9:19 AM
Instruments の Leaks と一緒に実行される Allocations の方に、オブジェクトに対する retain, release のタイミングも記録されてた気がします。
9:19 AM
あとは、 symbolic breakpoint で swift_release を指定すれば、止まります。
🙇‍♂️ 1
Avatar
ありがとうございます。試してみます。
Avatar
実際の強カウント数を取る方法 @swift-5.5.3 class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [foo] in _ = foo } print("init capture: refCount = \(_getRetainCount(foo))") _ = closure closure = nil } print("deinit capture: refCount = \(_getRetainCount(foo))") (edited)
Avatar
Avatar
Yuta Saito
実際の強カウント数を取る方法 @swift-5.5.3 class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [foo] in _ = foo } print("init capture: refCount = \(_getRetainCount(foo))") _ = closure closure = nil } print("deinit capture: refCount = \(_getRetainCount(foo))") (edited)
swift55 BOT 3/9/2022 9:37 AM
init Foo: refCount = 2 init capture: refCount = 3 deinit capture: refCount = 2 (edited)
Avatar
おお!ありがとうございます。_getRetainCountってのがあったんですね
Avatar
omochimetaru 3/9/2022 9:47 AM
おお しらなかった
Avatar
(キャプチャリストってやっぱりそういうことだったんだ。strongで書いて参照カウントみて意味が実感できた気がする)
Avatar
omochimetaru 3/9/2022 10:38 AM
キャプチャリストはクロージャを生成するときに、クロージャの外側からクロージャの内側に値をコピーする変数のリストって感じですね
10:38 AM
classだとあんまり実感ないけど、値型のプロパティとかをキャプチャリストに書くと、selfから切り離して現在の値をキャプチャできたりします
Avatar
なるほど
Avatar
@swift-5.5.3 class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure?() print("after closure?(): refCount = \(_getRetainCount(foo))") closure?() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil } print("deinit capture: refCount = \(_getRetainCount(foo))") (edited)
Avatar
Avatar
yimajo
@swift-5.5.3 class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure?() print("after closure?(): refCount = \(_getRetainCount(foo))") closure?() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil } print("deinit capture: refCount = \(_getRetainCount(foo))") (edited)
init Foo: refCount = 2 before closure(): refCount = 3 in closure: refCount = 4 after closure?(): refCount = 3 in closure: refCount = 4 after closure?(): refCount = 3 deinit capture: refCount = 2
Avatar
クロージャの呼び出しを変えると結果が変わる例 @swift-5.5.3 let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil }
Avatar
Avatar
yimajo
クロージャの呼び出しを変えると結果が変わる例 @swift-5.5.3 let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil }
exit status: 1 with stderr:<stdin>:1:11: error: cannot find 'Foo' in scope let foo = Foo() ^~~
Avatar
クロージャの呼び出しを変えると結果が変わる例 @swift-5.5.3 class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil }
Avatar
Avatar
yimajo
クロージャの呼び出しを変えると結果が変わる例 @swift-5.5.3 class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil }
init Foo: refCount = 2 before closure(): refCount = 5 in closure: refCount = 5 after closure?(): refCount = 4 in closure: refCount = 4 after closure?(): refCount = 3
Avatar
ブロック内の特定の行でのカウント数は、エイリアス解析とかCode Motion最適化で結構変わるんですよね。同じコードを-O付きでコンパイルした結果↓ @swift-5.5.3 -O class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil } (edited)
😯 1
Avatar
Avatar
Yuta Saito
ブロック内の特定の行でのカウント数は、エイリアス解析とかCode Motion最適化で結構変わるんですよね。同じコードを-O付きでコンパイルした結果↓ @swift-5.5.3 -O class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil } (edited)
init Foo: refCount = 1 before closure(): refCount = 3 in closure: refCount = 3 after closure?(): refCount = 3 in closure: refCount = 3 after closure?(): refCount = 1
Avatar
参照カウントが最適化で変わる件、SILのドキュメントに書いてあったのをしる https://github.com/apple/swift/blob/main/docs/SIL.rst#general-optimization-passes
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
swift に詳しい方にお聞きしたいのですが、swift で typescript の union type 的な型を実現するには、どう書いたらよいでしょうか?? typescript だと以下のような感じです。 type A = { type: 'A' } type B = { type: 'B' } type AB = A | B // union type
Avatar
例のようなtagged unionを表現する言語機能として enum があります。 enum AB { case a case b } func takeAB(ab: AB) { switch ab { case .a: print("a") case .b: print("b") } }
Avatar
正確にはtsのunionはuntagged unionなので、当該機能はswiftには存在しないです
11:56 AM
enumをtagged unionとして代用、という感じですね (edited)
11:57 AM
Optional型だけ、特別扱いで一部untagged union相当の機能(サブタイピング等)が使えるようになっています
Avatar
おお!!tagged union というものがあるんですね。ありがとうございまする!
👍 1
Avatar
もう一つ質問があります! swiftui の View protocol に準拠した struct の union として enum を使う場合、その enum が View に準拠しているということを明示的に記述するにはどうしたらいいですか?? 下記では、 enum Components: View と書くと、エラーが出てしまいます。。。 import SwiftUI enum Components { case a(ComponentA) case b(ComponentB) } struct ComponentA: View { public var body: some View {} } struct ComponentB: View { public var body: some View {} } (edited)
Avatar
enum Components側にも、Viewの宣言をしてswitchで出し分ける実装が必要ですね
2:27 PM
サブタイプの機能はないので。
Avatar
なるほど!ありがとうございます! こうしちゃえばいいんですね。 enum Components: View { public var body: some View {} case a(ComponentA) } struct ComponentA {}
Avatar
そんな感じですね、ComponentAも単体で使うことがあればViewにしてしまって良いと思います。
1:44 AM
ところで、SwiftUIならViewBuilderの構文でif式, switch式を記述すれば、内部にあるEitherViewがあてられますので、enumにせずに意図したコードが記述できる可能性があります (edited)
1:46 AM
@ViewBuilder var body: some View { if hoge { ComponentA() } else { ComponentB() } } こんな感じ、今ってViewBuilderはcomputed propertyでも動きますよね (edited)
Avatar
ふむふむ。jsx 的な ViewBuilder はかなり自由に使えるんですね!勉強になります!
Avatar
またまた質問です!snapshot test を書きたいのですが、snapshot test 用の text file の absolute filepath をどう取得すれば良いのでしょうか? イメージ let bundle = Bundle(for: type(of: self)) guard let url = bundle.url(forResource: "Tests/Structs/Snapshots/snapshot-1/input", withExtension: "json") else { throw NSError(domain: "error", code: 0); // ここで Error } let jsonData = try String(contentsOf: url); print(jsonData); (edited)
Avatar
package.swift に resources を追加すればいいのか!!
Avatar
いけました!
👍 3
Avatar
xcode って file のセーブ時に swift code の型チェックってしてもらえる設定とかあったりますか??
8:29 AM
みなさんは毎度、Command + Shift + R とかを押す癖が付いてる感じですかね。
8:31 AM
それとも vscode とか使ってます?
Avatar
omochimetaru 3/23/2022 8:36 AM
そういう設定や機能は無いと思います。 Cmd + B とか Cmd + Shift + U を適度に押してますね。 (edited)
t_me_too 2
Avatar
ふむふむ!手癖を身につける感じなんですね
Avatar
omochimetaru 3/23/2022 9:25 AM
うーん、というか、コードを書くときに、 Xcodeによる補完入力を前提にしていて、 その補完入力がちゃんと効いてるときは型推論が効いてる時なので、
9:25 AM
型チェックは常にされながらコードを書いてる感覚です
9:26 AM
でも時々Xcodeの調子が悪くなったりするので、 コミットする前とかのタイミングで仕上げに明示的にビルドする感じですね
Avatar
そうなんですね
10:08 AM
今、ちょうど vscode でやってみたら、ちゃんと逐次型チェックしてくれるようにできました!
10:09 AM
xcode だと build しないとエラーが出てくれなかったんですよね。。
Avatar
Swiftソースファイルを単体ファイルで開いてますか? (edited)
Avatar
xcode でプロジェクトレベルで開いてます!
Avatar
それだとちょっと謎ですね・・・
10:13 AM
10:13 AM
Show live issues の設定がオフになっている?
Avatar
true になってました
Avatar
うーむ。
10:15 AM
わからないです。
Avatar
Xcode だと build しないとエラーが出てくれないです。。
10:20 AM
vscode だとうまくいくんですよね。。
Avatar
XCPreviewAgent って cli から出せるのかな。。
Avatar
Kishikawa Katsumi 3/23/2022 10:45 AM
おそらく無理ですね。多くの人が望んでるものだと思いますが。。。
Avatar
みんな望んでるんですねw
10:50 AM
find / -name XCPreviewAgent |& xargs grep XCPreviewAgent これで見つかるかな。。 (edited)
Avatar
ヘッダにプロジェクト名がないので、targetに含まれてないとかでしょうか…?
10:59 AM
特定のプロジェクトだけじゃなくて常に起きるならXcode入れなおしたり祈ったりするのがよさそう…
Avatar
Kishikawa Katsumi 3/23/2022 11:01 AM
祈る🤣
Avatar
ww
11:06 AM
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCPreviewAgent.app/Contents/MacOS/XCPreviewAgent これ叩いたら Hello world 出せたww
Avatar
push通知をAppDelegate等で検知してトークの未読数をアイコンバッジに表示することは可能でしょうか? 未読数は取得できているのですが、通知が来てもバッジが表示されず。。。 (edited)
Avatar
Kishikawa Katsumi 4/7/2022 9:35 AM
表示する値がサーバーサイドでわかっているならPush通知のPayloadにバッジの数を入れたらいいです。 https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification クライアント(アプリ)で何か処理をしないとわからないのであれば、 https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application ^このメソッドが呼ばれるはずなのでそこでバッジの数を更新できると思います。 それかNotification Extensionを作成すればかなり自由に処理を書けるはずです。
Avatar
ありがとうございます!早速やってみたいと思います!
Avatar
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application ^このメソッドの中でAPIを叩くことは可能でしょうか? push通知を受け取った時にAPIを叩いて未読数を取得したいです。 アプリがフォアグラウンド状態のときは叩けているのを確認できました。 ただ、バックグラウンド状態の時はpush通知を作成しているRails側の実装が出来てないので検証できてません。 (edited)
4:21 AM
バックグラウンドの処理でAPIは叩けないというようなことを耳にしたので。。。
Avatar
未読数をpush のペイロードに入れない理由があるのかな…
Avatar
1. APIは叩けます。ですがそのメソッドを用いる場合、バックグラウンドの状態では本体の充電状態やユーザーの利用頻度に応じてOS側が受信を実際に処理するか間引いてしまいます。そのため、Push通知を送るタイミングでほぼ確実に実行したい場合にはこのメソッドは向いていないです。 2. 通知を送る段階で未読数がその Rails サーバーで取得できるなら通知の Payload にバッジの数を設定しておけば未読数をバッジに取得できると思います。 3. あくまでクライアントで処理を行いたい場合は、 Notification Service Extension を利用すると、 Active な通知を受信した段階で画面に表示するまでの30秒ほどの間バックグラウンドでAPIを叩くなどの処理が実装可能です。 https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension
4:10 AM
2, 3 が kishikawa さん、niw さんがあげてくださってる方法です。
Avatar
push通知を作成しているRails側の実装が出来てないので検証できてません
参考になるかわかりませんが、Push送信側の実装ができていなくてもシミュレータで動作は確認できます https://qiita.com/koogawa/items/85c0dd0abd2f1970c5fc
※本記事は一般に公開されている範囲で書いています。スクリーンショットの添付は自粛します Xcode 11.4 からiOSシミュレータがプッシュ通知のシミュレーションをサポートしますね。 Simulator supports si...
Avatar
niwさん、shibastripeさん、koogawaさんご教示ありがとうございます。 未読数をpayloadに入れればそれで解決しそうですね。 クライアントでの処理とどちらも試してみたいと思います。
👍 2
Avatar
widgetの勉強中なのですが、simulatorで実行時にwidgetが表示されず画面が真っ暗になる件は回避策ありますでしょうか? 普通に表示される時もあります。 https://sbapp.net/appnews/app/upinfo/ios15/widget-2-131865 (edited)
iOS15アップデートを適用後、一部のiPhoneでホーム画面に配置したウィジェットが真っ黒(真っ白)になる、エラー「読み込めません」でウィジェットが表示されない不具合が報告されています。 iOS15でウィジェットが表示されない不具合が発生 iOS15アップデート適用後、一部のiPhoneでホーム画面や検索画面(Spotlight検索)に配置したウィジェットが表示されない不具合が報告されています。不具合が発生するとウィジェットが真っ黒も...
Avatar
Kishikawa Katsumi 5/7/2022 8:30 AM
シミュレータだけ問題が起こるのであればiOSやSimulatorの問題かもしれませんが、たいていは表示されない場合は何らかのエラーが起こっています。 デバッガで1行ずつ実行してみるか、ウィジェットはデバッガがうまく動かないことが多いのでログをいろいろなところで出力するようにして正しく動いているかみてみてください。 問題なく処理が実行されているのに表示されないということであればOS等の問題だと思います。
Avatar
ご教授ありがとうございます。もう少し調べてみます。
Avatar
実機では再現なしでした。
Avatar
Kishikawa Katsumi 5/7/2022 8:13 PM
それなら気にしなくていいかもしれませんね。 念のため、問題の切り分けとしてシミュレータで問題がそこそこの頻度で再現するならログなどをたくさん仕込んでどこで処理は意図した通りに終わってるかをどうかをみるといいと思います。 あと考えられるのはシミュレータとデバイスの違い、例えばファイルを扱ってるならシミュレータは大文字小文字の区別がないとかそういう違いの部分で問題が起こるとかはあります。
8:16 PM
逆のケース、デバイスでだけ問題が起こるっていうのはよくあるんですけどね。 Widgetやエクステンションは使えるメモリの制限が非常に厳しいのでシミュレータで平気でもデバイスだとちょっとした画像の読み込みでクラッシュしたりします。
Avatar
omochimetaru 5/8/2022 2:48 AM
シミュレータは大文字小文字の区別がない
そんな違いあったんだ・・・
Avatar
そういえばmacOSのファイルシステムはcase insensitiveですよね… 逆にiPhoneはそうじゃなかったのか…
Avatar
Kishikawa Katsumi 5/8/2022 2:58 AM
厳密にいうとシミュレータはホスト(Mac)のファイルシステムで動きます。なので「シミュレータは大文字小文字の区別がない」は不正確でMacのデフォルトはtrickartさんのおっしゃる通りCase Insensitiveなのでほとんどの場合Case Insensitiveで動きます。
3:01 AM
シミュレータからMacにあるファイルは自由に読めるのでたまにハマったり、シミュレータから/System/Libraryとか覗くとMacのを読むのでハマったり。
👀 1
Avatar
Appleは本当にAPFSにするとに互換制を切り捨てでもmacOSもcasesensitiveにするべきだったと思う。
1:28 AM
case sensitive だとAdobeとか動かないのは知ってるけど。Adobeが悪い。
t_sorena 2
Avatar
Kishikawa Katsumi 5/11/2022 1:28 AM
Adobe悪いですよね!めっちゃ同意です!!
t_desudesu 2
Avatar
お話中すみません、初投稿失礼します。 UIPageViewControllerを用いて実装したページ間で共有する変数を設定することは可能でしょうか? UIPageViewControllerのファイルに変数を宣言して値渡しの要領で変数を共有させようとしたのですが、最初に表示されるViewControllerのみに値渡しされて、スワイプ処理したら出てくるViewControllerに値渡しをするとnilのエラーが出てきます…。どなたかお手隙の際にアドバイスをいただけると有難いです🙇‍♂️
Avatar
質問失礼します。 ビルドして、ユーザー情報を入力しようとしたら画面が暗くなるのですが、原因分かる方いらっしゃいますでしょうか??
Avatar
Avatar
ajj
お話中すみません、初投稿失礼します。 UIPageViewControllerを用いて実装したページ間で共有する変数を設定することは可能でしょうか? UIPageViewControllerのファイルに変数を宣言して値渡しの要領で変数を共有させようとしたのですが、最初に表示されるViewControllerのみに値渡しされて、スワイプ処理したら出てくるViewControllerに値渡しをするとnilのエラーが出てきます…。どなたかお手隙の際にアドバイスをいただけると有難いです🙇‍♂️
Kishikawa Katsumi 5/24/2022 10:12 AM
コードを見たら一発でわかると思うので、書いてるコードをどこでエラーが起こってるのかがわかるように載せてもらえますか?
Avatar
Avatar
龍之介
質問失礼します。 ビルドして、ユーザー情報を入力しようとしたら画面が暗くなるのですが、原因分かる方いらっしゃいますでしょうか??
Kishikawa Katsumi 5/24/2022 10:14 AM
こちらはキーボードを避けるためにViewの縦の位置を動かしていて、それが失敗しているように見えます。 もし自分でキーボードを避ける意図がないのなら使ってるライブラリなどの使い方ですね。 こちらもこの部分のコードを載せることはできますか?
Avatar
1件目、エスパーで、weak の誤用を予想
Avatar
どちらもコードを載せたほうが話が早そうですね
Avatar
値型で共有されてないとかもあるかも。コードあればすぐですね。
Avatar
Xcode再起したらなぜか直りました!!! すいません、、、、、連続になっちゃって誠に申し訳ないのですが、アカウント作成画面で必要な情報を入力しregsterButtonを押して、アカウント作成しようとしたらnillの値があると怒られてます。 self.createdAt = dic["createdAt"] as! Timestampに赤線が入り、 error code Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value エラーに関連してそうな範囲のコードも送らせていただきます。 struct User{ let name: String let createdAt : Timestamp let email: String init(dic: [String: Any]){ //init=クラスのプロバティの初期値を設定 self.name = dic["name"] as! String self.createdAt = dic["createdAt"] as! Timestamp self.email = dic ["email"] as! String 畳み掛けで申し訳ないです。一つ目の解答ありがとうございました🙇‍♂️ (edited)
Avatar
Kishikawa Katsumi 5/24/2022 2:57 PM
たぶんcreatedAtが入ってないですね。 init(dic: [String: Any]){ の直後にprint(dic)dicの中身をログ出力して何が出るか教えてもらえますか? init(dic: [String: Any]){ print(dic) // これを追加 //init=クラスのプロバティの初期値を設定 self.name = dic["name"] as! String self.createdAt = dic["createdAt"] as! Timestamp self.email = dic ["email"] as! String ^ のような感じです。
Avatar
Avatar
Kishikawa Katsumi
コードを見たら一発でわかると思うので、書いてるコードをどこでエラーが起こってるのかがわかるように載せてもらえますか?
皆様、返信ありがとうございます。 PageViewControllerのファイルはこのようになっています。
3:14 PM
import UIKit class PageViewController: UIPageViewController { private var controllers: [UIViewController] = [] var PageTest: String! = "" override func viewDidLoad() { super.viewDidLoad() initPageViewController() // Do any additional setup after loading the view. } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) initPageViewController() } private func initPageViewController() { //VCをインスタンス化 let firstVC = storyboard!.instantiateViewController(withIdentifier: "top1") as! FirstViewController let secondVC = storyboard!.instantiateViewController(withIdentifier: "top2")as! SecondViewController //配列のVCのインスタンスを入れる self.controllers = [ firstVC, secondVC ] setViewControllers([self.controllers[0]], direction: .forward, animated: true, completion: nil) firstVC.FirstTestLabel.text = PageTest secondVC.SecondTestLabel.text = PageTest //エラー,ViewControllerがSetViewControllersでセットされていないのが原因? self.dataSource = self } } extension PageViewController: UIPageViewControllerDataSource { //左スワイプで前の画面に戻る処理 func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?{ if let pageIndex = self.controllers.firstIndex(of: viewController), pageIndex - 1 >= 0 { return self.controllers[pageIndex - 1] } return nil } //右スワイプで次の画面にいく処理 func pageViewController(_ pageViewControlller: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?{ if let pageIndex = self.controllers.firstIndex(of: viewController), pageIndex + 1 < self.controllers.count{ return self.controllers[pageIndex + 1] } return nil } } (edited)
Avatar
Kishikawa Katsumi 5/24/2022 3:18 PM
secondVC.SecondTestLabel.text = PageTest ^ 問題の場所はここってことですよね? この行の前に print(secondVC.SecondTestLabel) を追加して何が出力されるか教えてください。
Avatar
そこです!print文を追加したらnilが出力されました。
Avatar
SecondViewControllerがstoryboardかxibで作成されていて、SecondTestLabelのIBOutletが壊れていて @IBOutlet var SecondTestLabel: UILabel! の部分がnilになってるのではないかと予想しました
Avatar
Kishikawa Katsumi 5/24/2022 3:27 PM
SecondViewControllerのStoryboardファイルを見て、SecondTestLabelがSecondViewControllerのIBOutletのプロパティと繋がっているかどうか確認してください。 ビューコントローラを右クリックで出る黒いウインドウでわかります。 (edited)
Avatar
storyboardからは関連付けしてありました。
Avatar
SecondViewController.swift側からみても関連付けが確認できますか?(SecondTestLabelプロパティの左に○か◎が表示されてると思います)
Avatar
Kishikawa Katsumi 5/24/2022 3:35 PM
Outletってビューがロードされてないとダメとかあるんだっけ
3:35 PM
たしかなかったはず
Avatar
細かいタイミングは忘れましたがinstantiateViewControllerを通ってれば十分だったと思うんですよね
🙏🏻 1
Avatar
確認できました!
Avatar
IBからデシアライズさせるために _ = vc.view みたいなの書きませんでしたっけ?
Avatar
となるとなにかのタイミングでSecondTestLabelを自分で剥がしてるとかかな・・・
3:41 PM
storyboardやSecondViewController.swift全体を貼ってもらえると分かるかもしれません
Avatar
class SecondViewController: UIViewController { @IBOutlet weak var SecondTestLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destination. // Pass the selected object to the new view controller. } */ }
3:43 PM
Avatar
Kishikawa Katsumi 5/24/2022 3:44 PM
試しにweakを消して、StoryboardのSecondViewController
Avatar
ContainerViewでUIPageViewController使っています
3:44 PM
了解です
Avatar
Kishikawa Katsumi 5/24/2022 3:44 PM
のラベルも一度消して再度同じところに追加して、
3:44 PM
Outletを繋ぎ直してみてください。
Avatar
Avatar
Yuta Saito
IBからデシアライズさせるために _ = vc.view みたいなの書きませんでしたっけ?
これ正しいかも・・・
Avatar
Kishikawa Katsumi 5/24/2022 3:46 PM
let secondVC = storyboard!.instantiateViewController(withIdentifier: "top2")as! SecondViewController のすぐ後に _ = secondVC.view を追加するっていうのも試してみてください。
Avatar
たぶん secondVC.loadViewIfNeeded() のほうがより正しいですね (edited)
🙏🏻 1
Avatar
いけました!ありがとうございました!
Avatar
Kishikawa Katsumi 5/24/2022 3:50 PM
何が効果ありました?
Avatar
_ = secondVC.viewでした
3:50 PM
これってどういう効果ですか?
Avatar
firstVCで落ちないのはpageViewControllerの0番目にいるからloadViewされてたのかな〜
Avatar
Kishikawa Katsumi 5/24/2022 3:54 PM
たぶんPageViewControllerが読んでるんでしょうね。
3:55 PM
ビューコントローラは自分の一番ルート(最下層)にあるビューをviewプロパティで持っています。
Avatar
viewWillAppearで諸々の処理書いてますが、0番目のvcへのアクセスはviewDidLoadのタイミングだから、ですね
Avatar
StoryboardはUIViewControllerの状態をXMLで表現したようなファイルです。 状態というのはラベルのテキスト、IBOutletの接続状態などが含まれます。 storyboard.instantiateViewController(withIdentifier:) はStoryboardをベースにUIViewControllerインスタンスを作りますが、この時点ではStoryboardの状態をインスタンスに復元せず、UIViewControllerを表示するタイミングになって初めて復元します。 _ = secondVC.view というのは、UIViewControllerにviewを明示的に要求することで、表示の前に状態を復元させる意図があります。
Avatar
Kishikawa Katsumi 5/24/2022 3:58 PM
ビューコントローラは自分の一番ルート(最下層)にあるビューをviewプロパティで持っています。 Storyboardで見えている一番下にあるビューがそれです。 で、それは表示する直前にloadView()メソッドが自動的に呼ばれてビューとしてロードされます。 表示する直前というのは処理的にはviewプロパティにアクセスした時(コードでいうと例えばsecondVC.view)、に自動的に呼ばれるようになっています。 今回はビューがロードされる前にOutletにアクセスしていてまだOutletが初期化されてなかった、ということのようなので、 secondVC.viewと明示的にプロパティにアクセスして強制的にロードする、というようなことをした、ということです。
Avatar
このへん昔からやってる人は経験的に挙動を理解してますが、ドキュメントとして挙動が明示されものありますっけ?
4:00 PM
近代だとstoryboardは忘れてSwiftUIから入門するほうがいいかもしれない
Avatar
UIKit reestablishes these connections before calling your view controller’s viewDidLoad() method, so you can access the objects in those properties from that method.
https://developer.apple.com/documentation/uikit/view_controllers/displaying_and_managing_views_with_a_view_controller それっぽい記述
t_naruhodo 1
Avatar
わっ皆様丁寧にありがとうございます!明日ゆっくりと読ませていただきます。今日はありがとうございました🙇
Avatar
Avatar
Kishikawa Katsumi
たぶんcreatedAtが入ってないですね。 init(dic: [String: Any]){ の直後にprint(dic)dicの中身をログ出力して何が出るか教えてもらえますか? init(dic: [String: Any]){ print(dic) // これを追加 //init=クラスのプロバティの初期値を設定 self.name = dic["name"] as! String self.createdAt = dic["createdAt"] as! Timestamp self.email = dic ["email"] as! String ^ のような感じです。
すいません、、、ログ出力の意味がよく分からないのですがビルドしてデバックに何が表示されたかを見せたらいいですか?? ["email": test06@gmail.com, "createAt": <FIRTimestamp: seconds=1653438033 nanoseconds=684360000>, "name": 佐々木] chat_App2/ViewController.swift:24: Fatal error: Unexpectedly found nil while unwrapping an Optional value 2022-05-25 09:20:37.452984+0900 chat App2[25919:1186294] chat_App2/ViewController.swift:24: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Avatar
createAtcreatedAt でtypoがあるようですね
Avatar
前画面に値渡す時はクロージャを使っているのですが、ベストプラクティスってありますか?
Avatar
クロージャがベストプラクティスだと思ってます。
🙇‍♂️ 1
Avatar
端末毎に表示するフォントのサイズを変えたくて Labelの横幅に対して表示できる範囲内(省略されない範囲)で最大のフォントサイズにする方法ってありますか。 Labelの幅は比率で設定してるイメージです。 (edited)
Avatar
色々なやり方があると思いますが、画像を用意して引き伸ばすのが手っ取り早いんじゃないかと思います
Avatar
文字が動的に変わる場合はどのような方法がありますか?
1:49 AM
このあたりのメソッドを使えば、文字列を描画したときの大きさがわかるので、 (edited)
1:50 AM
はみ出さないフォントサイズを探索できます
Avatar
UILabelなら、minimumScaleFactorで楽できるかもっすね 1行表示の時のみ使えます https://developer.apple.com/documentation/uikit/uilabel/1620544-minimumscalefactor (edited)
Avatar
Avatar
ありぜ
UILabelなら、minimumScaleFactorで楽できるかもっすね 1行表示の時のみ使えます https://developer.apple.com/documentation/uikit/uilabel/1620544-minimumscalefactor (edited)
omochimetaru 5/27/2022 1:54 AM
あ〜こんなのあったなあ・・・
Avatar
minimumScaleFactorはadjustsFontSizeToFitWidthと組み合わせて使う形になるかもしれませんね。 https://developer.apple.com/documentation/uikit/uilabel/1620546-adjustsfontsizetofitwidth
t_desune 1
Avatar
Avatar
Iceman
createAtcreatedAt でtypoがあるようですね
解決しました。解答してくださった方誠にありがとうございました!! typoがあるのは、どこを見て分かったか教えていただきたいです。
Avatar
Avatar
龍之介
解決しました。解答してくださった方誠にありがとうございました!! typoがあるのは、どこを見て分かったか教えていただきたいです。
https://discord.com/channels/291054398077927425/291211035438874625/978816665708007454 のログ出力をよく見るとdic の中身が書いてありますよ。そこでkeyをtypoしていると気づきました
Avatar
なるほど!ありがとうございます🙇🏻‍♂️
Avatar
連日失礼します、、 m1チップのmacなのですが、このページ(https://qiita.com/Capotasto/items/2a9ec4b4fcb2e0c0af9f) を参考にしながらpod installを行ったのですが、ffiに関係するこんなエラーが出てきてしまいました。 cannot load such file -- 3.1/ffi_c (LoadError) どなたか似たようなエラーを経験している人がいれば、アドバイスを頂けるとありがたいです。よろしくお願い致します。 (edited)
概要 話題のM1チップ搭載のMacを購入したので、早速Xcodeで開発をしようとしたところ Pods が動かない問題があり結構ハマったので記録として残します。将来的にはCocoapods 側で改善されることを願います。 環境...
Avatar
Kishikawa Katsumi 5/28/2022 5:24 PM
これは原因はffiがM1に対応していない古いバージョンであることが原因なのでバージョンを上げたら解決するんですけど、これをテキストチャットでサポートするのは結構難しいですね。 まずMadに最初から入ってるシステムのRubyは古いので新しいRubyを入れて、システムのRubyじゃなくて自分で入れたRubyを使ってCocoaPodsのインストールをやり直すと直るはずです。 rbenvとruby-buildを使ってRubyの最新版をインストール、するのがたぶん簡単ですけどわかりますか? https://github.com/rbenv/rbenv#installation
Manage your app's Ruby environment. Contribute to rbenv/rbenv development by creating an account on GitHub.
Avatar
ffiをインストールする時にpermissionエラーになったので、rbenvをインストールして3.1.2に設定してffiをインストールしたのですが、上手く行きませんでした…
Avatar
Kishikawa Katsumi 5/28/2022 7:10 PM
which ruby と打つと何が表示されますか?
Avatar
/Users/username/.rbenv/shims/ruby とでます
Avatar
ruby2.6じゃだめなんだ (edited)
2:56 AM
なんか、arch -x86_64 すればいい気がする…
2:56 AM
わざわざ苦労してpodするためだけにarm64の使うメリットなさそう
2:57 AM
まじ巷(the internet)にあふれるsudoつかえってやつやばいから全滅したほうがいい
3:01 AM
$ echo "source 'https://rubygems.org' gem 'cocoapods'" > Gemfile (edited)
3:01 AM
まずこれを実行して Gemfile を作ってください
3:01 AM
その後 $ env PATH=/usr/bin:/bin bundle install --path=.bundle (edited)
3:01 AM
です
3:02 AM
で、$ env PATH=/usr/bin:/bin bundle exec pod install (edited)
3:02 AM
とか。
3:02 AM
ruby2.6でいけるし、rbenvいらないし、sudoもいらない
3:04 AM
このQiitaの記事は嘘というか古いというか誤った情報で推奨しません
3:10 AM
ここでつかってるbundleは Bundler https://bundler.io/ ってやつで、rubyのデファクトの依存関係管理管理ツールです。こうするとでpythonのpython -m venv + pip相当になります。/Libraryとかどこも汚さないし、.bundle 以下で完結します。
3:10 AM
env PATH=/usr/bin:/binはsystemにインストールされてる汚されてないrubyだけを使うためです。rbenvやその他のインタープリタ管理ツールはいろいろ汚されていることが多いのでどの環境でも動くを再現できないからmacOSではsystem ruby (2.6, /usr/bin/ruby)が使えるのであればそれを使ったほうが良いと思ってます。 (edited)
3:12 AM
時期macOSでrubyが消えたらちょっと面倒なことになりますね...
3:13 AM
$ env -i HOME=$HOME PATH=/usr/bin:/bin bundle ... のほうがより安全かもしれないなあ。変な環境変数を誰かに入れられてる可能性もある...
Avatar
ありがとうございます! 二番目の $ env PATH=/usr/bin:/bin bundle install --path=.bundle を実行したら /Library/Ruby/Site/2.6.0/rubygems.rb:265:in `find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException) のようなエラーが出てきてしまいました。
Avatar
汚されてますね...
3:46 AM
env -i HOME=$HOME PATH=/usr/bin:/bin GEM_HOME= GEM_PATH= bundle install --path=.bundle (edited)
3:47 AM
これにしてみてください (edited)
3:48 AM
あー
3:48 AM
これだとまずいか
3:49 AM
いや、大丈夫かな。
Avatar
多分、なんらかの過去の sudo つけた操作や管理者パスワードが必要なアプリのインストールで、bundlerが動かなくなってる(gemが壊されてる)ので、/Library/Ruby/Site/以下抹消したほおうがいいかもしれません。これはsudoがいります。 (edited)
3:57 AM
そこにはこれしかないはずなんです:
3:57 AM
$ find /Library/Ruby/Site /Library/Ruby/Site /Library/Ruby/Site/2.6.0 /Library/Ruby/Site/2.6.0/universal-darwin21
Avatar
find /Library/Ruby/Siteを実行してみたら大量に出てきたので、表示されているファイルだけ残して全て削除した後に env -i HOME=$HOME PATH=/usr/bin:/bin GEM_HOME= GEM_PATH= bundle install --path=.bundle を実行したら、 A new major version is available for Algolia! Please now use the https://rubygems.org/gems/algolia gem to get the latest features. と表示されました。これは成功したということでしょうか?
Avatar
はい
Avatar
ありがとうございます!
Avatar
env -i HOME=$HOME PATH=/usr/bin:/bin GEM_HOME= GEM_PATH= bundle exec pod とかしてみてください (edited)
4:07 AM
pod使えるはずです
4:08 AM
こうやってインストールしたpodコマンドはそのディレクトリ専用なので、(.bundleにインストールされてる、依存関係とかがつくったGemfile起点で管理される)、他の場所からは使えないですが、逆に他のプロジェクトとかから改変されることもありません (edited)
Avatar
本当にすみません、ご迷惑をおかけします。 podが使えたので、pod installをしたら、次のように表示されました。 /Users/username/.bundle/ruby/2.6.0/gems/ffi-1.15.5/lib/ffi/library.rb:275: [BUG] Bus Error at 0x0000000101130000 ruby 2.6.8p205 (2021-07-07 revision 67951) [universal.arm64e-darwin21] -- Crash Report log information -------------------------------------------- See Crash Report log file under the one of following: * ~/Library/Logs/DiagnosticReports * /Library/Logs/DiagnosticReports for more details. Don't forget to include the above Crash Report log file in bug reports. まだどこか汚されてるとか可能性ありそうですか?
Avatar
えー、そうなんだ
4:14 AM
なんと...
4:14 AM
いや、これはffiが動かないってやつですね
Avatar
なるほど…ffiはさっき env -i HOME=$HOME PATH=/usr/bin:/bin GEM_HOME= GEM_PATH= bundle install --path=.bundle を実行した時にインストールされていた感じでした。そもそも動かないって感じですかね。
Avatar
LANG=もいるらしい
4:19 AM
えーっとPodfileがある場所で作業されてます?
4:19 AM
/Users/username/.bundle
4:19 AM
この感じ、 ~/のような気が...
Avatar
プロジェクトフォルダで実行してました
4:20 AM
podfileはあります
Avatar
PodfileのあるばしょにGemfileと.bundleもある感じですよね
4:20 AM
(いちおう確認) (edited)
Avatar
.bundleはあるんですけど、Gemfileは見当たらないです (edited)
Avatar
え... (edited)
4:22 AM
$ echo "source 'https://rubygems.org' gem 'cocoapods'" > Gemfile
4:22 AM
でできているはずなんですけどねえというかそれがないとpodインストールされてないはず...
Avatar
source 'https://rubygems.org' gem 'cocoapods'
4:22 AM
こんな内容のファイルがあるはずです。
Avatar
理解しました。。。その命令を~/でやってました…すみません
Avatar
おおお...
4:23 AM
なるほど...
4:23 AM
たぶんGemfileは上にのぼって探されるので
4:24 AM
動いたんだと思います
4:24 AM
.bundleが~/にできたのはそれ原因かな...
4:24 AM
~/のGemfile, Gemfile.lock, .bundleは一旦消して良いです
4:24 AM
Podfileがある場所で、Gemfileをつくってbundle install --path=.bundle するとその場所で完結するはずです
4:25 AM
んで、podの実行はLANGがいるっぽいので、env -i LANG=en_US.UTF-8 HOME=$HOME PATH=/usr/bin:/bin bundle exec pod installですね。
Avatar
あとは ~/Library/Logs/DiagnosticReports/Library/Logs/DiagnosticReports に出来ているはずのクラッシュレポートを貼って頂けると 🙏
Avatar
ffiのエラーは...うーん、多分archの問題?
4:27 AM
直ってないんだっけか...
Avatar
まあ十中八九そうだと思っています
Avatar
~/のgemFileは削除したのですが、やはり同じエラーが出ましtあ。 cloud_firestore: Using Firebase SDK version '8.15.0' defined in 'firebase_core' firebase_core: Using Firebase SDK version '8.15.0' defined in 'firebase_core' /Users/username/AndroidStudioProjects/memo_app/ios/.bundle/ruby/2.6.0/gems/ffi-1.15.5/lib/ffi/library.rb:275: [BUG] Bus Error at 0x0000000104d4c000 ruby 2.6.8p205 (2021-07-07 revision 67951) [universal.arm64e-darwin21] -- Crash Report log information -------------------------------------------- See Crash Report log file under the one of following: * ~/Library/Logs/DiagnosticReports * /Library/Logs/DiagnosticReports for more details. Don't forget to include the above Crash Report log file in bug reports.
4:27 AM
クラッシュレポート探してはります!
Avatar
Firebaseつかうとそうなるんだ
4:27 AM
へー
4:28 AM
arch -x6_64つけて実行しなおすのが最短かも
4:29 AM
.bundle消してから再度env -i HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle install --path=.bundleですね (edited)
4:29 AM
で、env -i LANG=en_US.UTF-8 HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle exec pod install
Avatar
実態のコマンドを呼ぶまでの詠唱がどんどん長くなってる…w
Avatar
どの環境でも絶対動くを実現するのは難しい...
Avatar
これ?がクラッシュレポートだと思います
Avatar
アーキテクチャ違いではなさそう
Avatar
なんだろこれ
Avatar
ffiの拡張ライブラリをビルドするときのrubyヘッダのバージョンが違うのかな
Avatar
あー
4:32 AM
それだ
4:33 AM
macOSいくつですか?
4:33 AM
あと、Xcodeのバージョンとxcode-select -p
Avatar
macOS Monterey ver 12.2.1です
Avatar
Xcode 12.xの可能性
Avatar
xcodeが13.3でした
4:35 AM
いま、bundleからやり直すってやつやってるんですけど
4:35 AM
pos installができてるっぽいです
Avatar
おお??えーarchなの...
Avatar
Avatar
niw
.bundle消してから再度env -i HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle install --path=.bundleですね (edited)
これが正常に動いてます
Avatar
おお?
Avatar
ああ、bundle installですね (edited)
Avatar
それならdlopenするときに怒られるはずなんだけどなぁ
Avatar
そっちはどっちでも動きます
Avatar
ああ
Avatar
Avatar
niw
で、env -i LANG=en_US.UTF-8 HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle exec pod install
こっちも動きました
Avatar
えーw
Avatar
w
Avatar
nazoい
4:36 AM
確かにxcode13ならsdkのバージョンあってるからヘッダー違いはないんだよなあ... (edited)
Avatar
消してもらう前に ffi_c.bundle のアーキテクチャ見てもらえばよかった
Avatar
確かに
4:38 AM
まあpod installなんて1回しかしないし... 当面は...
4:39 AM
この方法でcocoapodsいれて実行する分には作ったGmefile, Gemfile.lockと.bundle消せば全部なかったことになるので将来おかしくなったときはやり直せば良いと思います。 (edited)
Avatar
了解です!お手数をおかけしました。本当にありがとうございます。
Avatar
env -i LANG=en_US.UTF-8 HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle exec pod install 呪文長いですが、説明しておくと、env -i で既にある環境変数(GEM_PATHとかRUBY_OPTSとかはrubyや、gemの挙動を変えてしまいます)を無効して、必要最低限のLANGとHOMEを設定、PATHをシステムのものだけにして(/usr/binや/binはSIPで通常は勝手には改変されない)、arch -x86_64でrosetta2を有効にしてbundle exec podで、Gemfileでbundlerを使ってインストールした.bundleにあるpodを実行、です。 (edited)
Avatar
ご丁寧にありがとうございます、よく理解出来ました。これから環境構築周辺も勉強していこうと思います🙇
👍 1
Avatar
ディスコードのようなサーバー・チャンネル機能を実装したチャットアプリを作りたいのですが、参考になるドキュメント等共有していただければありがたいです。 自分で調べた中では、シンプルなトークルーム作成のみが多く、グループ作成(LINE)や、サーバー・チャンネル(discord)のようなものが作ってみたいです。 (edited)
Avatar
Kishikawa Katsumi 5/31/2022 8:39 AM
Discordは非常に大規模で複雑なシステムなのでそういったものを丸っと解説した文書はおそらくありません。 シンプルなトークルーム作成ができているのであれば、グループ作成やサーバー・チャンネルを作るにあたって、どのようなことを調べて、試して、現在何で困っているのか、ということを1つずつブレークダウンして書いていただくと、回答できる人がいるかもしれません。
🙇🏻‍♂️ 1
Avatar
すみません。3DCGアニメーションについて知見お持ちの方がいらっしゃれば教えていただきたいです。 下記のような「インタラクティブに状態が変わる3Dアニメーション」を画面上に描画しようと考えているのですが、下記どのように考慮したかご教示いただきたいです。 1. そもそも1s~3s未満の描画速度を実現可能か 2. どのようなライブラリ・API・SDKを用いるのが適切か 3. 適切な動画のファイル形式 https://drive.google.com/file/d/1rTL4MJ3rT9MeVZ-LJnrAA5985UmpzX4Q/view?usp=sharing
Avatar
iOSとSwiftで作るならSceneKitを使うのが簡単だと思います。 リアルタイムCGが出せます。 動画に書き出すところはVideoToolBoxとかAVFoundationでできると思いますが、SceneKitのレンダリング結果を引き渡すところでどうやるのがいいのかは知らないです。 光ってるようなエフェクトなのでシェーダーを自作する必要があるかもです。
👍 1
Avatar
Avatar
masatojames
すみません。3DCGアニメーションについて知見お持ちの方がいらっしゃれば教えていただきたいです。 下記のような「インタラクティブに状態が変わる3Dアニメーション」を画面上に描画しようと考えているのですが、下記どのように考慮したかご教示いただきたいです。 1. そもそも1s~3s未満の描画速度を実現可能か 2. どのようなライブラリ・API・SDKを用いるのが適切か 3. 適切な動画のファイル形式 https://drive.google.com/file/d/1rTL4MJ3rT9MeVZ-LJnrAA5985UmpzX4Q/view?usp=sharing
インタラクティブな3DCGを描画するのは↑で言及されているようにSceneKitが良いと思いますが、「1s~3s未満の描画速度」「適切な動画のファイル形式」というのがよくわかりませんでした。ユーザーが3DCGをインタラクティブに操作する様子を録画して、後から動画ファイルに書き出したいということでしょうか? 単にインタラクティブな3DCGを実現するなら、プログラムでCGをレンダリングすることになるので動画は必要ないと思います。また、インタラクティブな3DCGは「1s~3s未満の描画速度」ではなく、60fps(秒間60回)などの高速な描画が必要になると思います。
Avatar
aimai (SwiftUI-beginner) 6/9/2022 9:58 AM
独学でSwiftUIのお勉強を始めてしばらく経ちました。 NavigationViewやTabViewなど、基本的なViewは理解できたと思います。 次のステップとして、もう少し実用的なものを作るのに、デバイスのカメラロールから写真を選択してアプリにインポートする方法を調べました。 調べた方法ではどうやらUIKitが必要っぽいです。SwiftUIだけで実装はできないですか?? また、SwiftUIだけで多機能なアプリを作り切るのはできないものですか??
Avatar
Kishikawa Katsumi 6/9/2022 1:50 PM
アプリケーションによります。Pure SwiftUIということならSwiftUIに用意されていないコンポーネントはUIKitと組み合わせる必要があります。
1:56 PM
写真の選択は次のiOS 16に搭載されるSwiftUIにはPhotosPickerというコンポーネントが追加されるのでPure SwiftUIで書けます。 例えばMapなども最初はSwiftUIにはなく、MKMapViewをブリッジする必要がありましたが今はSwiftUIにMapというのが提供されています。 というようにSwiftUIから提供されてない機能はまだいろいろあるのでSwiftUIだけで書くならそういう機能を使ってるものは難しいです。基本的にSwiftUIはUIKitと手軽に連携できるのが良いところなのでSwiftUIだけで書くことにこだわらずに使っていくのがいいと思います。
Avatar
SwiftUIに標準でない機能をライブラリで探して、ライブラリの使い方とか学んでいくと、楽できたり機能の幅が広がったりするので、そういうのもありかなと。 OSSのライブラリを使って、どういう処理しているかソースコードを覗いてみるとそれもまた良い糧になったりしますし。 (edited)
Avatar
aimai (SwiftUI-beginner) 6/9/2022 10:37 PM
Kishikawaさん、Aryzaeさん、ありがとうございます。 SwiftUIはまだまだこれからの部分が多いんですね! SwiftUIの機能が揃う前でUIKitが習得できるように頑張って勉強してみます! まだライブラリを使うという発想すらなかったです! ライブラリを糧にするのと同時に、すでに自分で一つ一つ作って行ったお試しのアプリを、ライブラリを使ってコードの簡略化ができないかやってみます!
Avatar
こんにちは。App Store Connectの話なので微妙に範囲外かもしれませんが、未リリースのアプリについてApp Store campaign link を生成したことがある or する方法をご存知の方はいますか? ここで見つけたworkaroundは、Activeなアプリを持っておらず使えなかったもので、困っています。 https://developer.apple.com/forums/thread/5729
Avatar
お疲れ様です。 https://discord.com/channels/291054398077927425/430242233468452865/988291537727291452 こちらに書かせていただいたコードがエラーになる理由が分からず、どなたか教えていただけないでしょうか🙏 MainActorのArray型のプロパティを更新する際に、特定のindexのみ更新することはできないのでしょうか? (edited)
Avatar
@swift-5.6.3 import Foundation struct Test { var id: Int var text: String } class Model: @unchecked Sendable { @MainActor var list: [Test] = [ Test(id: 1, text: ""), Test(id: 2, text: "") ] func f() { Task { @MainActor in self.list[0].text = "updated" } Task { await MainActor.run { @MainActor in self.list[0].text = "updated" } } } }
Avatar
Avatar
Iceman
@swift-5.6.3 import Foundation struct Test { var id: Int var text: String } class Model: @unchecked Sendable { @MainActor var list: [Test] = [ Test(id: 1, text: ""), Test(id: 2, text: "") ] func f() { Task { @MainActor in self.list[0].text = "updated" } Task { await MainActor.run { @MainActor in self.list[0].text = "updated" } } } }
exit status: 1 with stderr:<stdin>:21:22: error: actor-isolated property 'list' cannot be passed 'inout' to 'async' function call self.list[0].text = "updated" ^ <stdin>:9:20: note: property declared here @MainActor var list: [Test] = [ ^
Avatar
これは謎だ・・
Avatar
omochimetaru 6/20/2022 4:43 AM
コンパイラーのバグに思える。
Avatar
ありがとうございます やっぱり変ですよね... 確認できてよかったです! https://discord.com/channels/291054398077927425/430242233468452865/988311341020368896 こんな風に外出しすれば動くのでコンパイラのバグみたいですね🤔 (edited)
Avatar
omochimetaru 6/20/2022 5:18 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
5:18 AM
↑報告しても良いかもです。
Avatar
self.listが一段目のTask.initでinoutキャプチャされてるからじゃないですかね (edited)
Avatar
omochimetaru 6/20/2022 5:20 AM
Task.initに @MainActor 明記してるからactor境界をまたぐ部分がなくない?
5:20 AM
キャプチャされているのは self.list じゃなくて self でしょ
Avatar
一段目っていうのは Task { // << ここ await MainActor.run { @MainActor in
5:28 AM
self.listはselfのinoutキャプチャを通して間接的に…
5:30 AM
メソッド呼び出しにするとinoutキャプチャが無くなるので通る
Avatar
参照型でもキャプチャされるときはinoutつくんでしょうか?
Avatar
selfのinoutキャプチャは嘘ですね。参照型の方にはinout付かないんですが、フィールドにアクセスするとき付きます
Avatar
omochimetaru 6/20/2022 5:40 AM
キャプチャのキャプチャのときにselfじゃなくてフィールドのキャプチャになるマジ?
Avatar
Avatar
Yuta Saito
一段目っていうのは Task { // << ここ await MainActor.run { @MainActor in
omochimetaru 6/20/2022 5:43 AM
5:44 AM
ちなみにフィールドアクセスはselfが参照型の場合はshared渡しだったはず。 self自体を変更する必要はないから。 このエラーメッセージにでてるinoutは、arrayのsubscriptアクセスによるものだと思う。 (edited)
fummicc1 started a thread. 6/20/2022 5:45 AM
Avatar
あれ、 Model.list!modify でselfのinoutが必要かと思ったけど違うのか
Avatar
omochimetaru 6/20/2022 5:50 AM
let で宣言したオブジェクトのフィールド書き換えられるのと同じ理屈
5:51 AM
参照型の値それ自体はオブジェクトじゃなくてポインタの事を意味している
Avatar
そりゃそうか
Avatar
質問です!periscopeなどのライブアプリでよくあるハートをタップしたら上に流れていくアニメーションって何で実装するのが簡単に作れますか。それっぽい記事とかなくて困ってます。 ↓イメージはこんな感じです
Avatar
SpriteKitは透過させた時のパフォーマンスが微妙に悪くて結局CALayerとかで作った記憶があります。
👍 1
2:45 PM
一時期盛り上がっていたので探すとそれっぽい実装が見つかると思います https://github.com/saidmarouf/FloatingHearts https://github.com/itsaark/HeartAnimation
Periscope-Like flowing hearts animation. Contribute to saidmarouf/FloatingHearts development by creating an account on GitHub.
Periscope like/love fly animation. Contribute to itsaark/HeartAnimation development by creating an account on GitHub.
Avatar
Avatar
noppe
一時期盛り上がっていたので探すとそれっぽい実装が見つかると思います https://github.com/saidmarouf/FloatingHearts https://github.com/itsaark/HeartAnimation
ありがとうございます、助かります!
Avatar
https://stackoverflow.com/questions/29764603/how-to-implement-periscopes-heart-animation これでそれっぽいアニメーションは作れるのですが、一つ問題があってemitterをどんどんaddで描画していくとメモリも増えていくようです。 アニメーションの終了したものはcompletionでremoveFromParent()してやる必要があ流ということでしょうか。どうすればメモリが増えていかずにこれ作れますかね。
I want to implement something similar like what periscope does to their live streaming app. To be specific, the countless floating heart emitted when user touch the screen. Is this could easily be
Avatar
Kishikawa Katsumi 8/18/2022 9:44 AM
この画面がなくなれば全部解放されますけど画面が長いこと表示されているものだったらEmittterNodeを適宜removeFromParent()するといいですね。
9:45 AM
https://stackoverflow.com/a/31731439/1733883 これとか参考になると思います。
I added SKEmitterNode as a childNode of my mainScene and than expected that It would be removed when particleLifetime ends, described like apple docs. Added emitters like this; var emitterPat...
👀 1
Avatar
@Kishikawa Katsumi つまりSKEmitterNodeじゃ一つ一つ解放するのは厳しいってことでしょうか。
Avatar
Kishikawa Katsumi 8/18/2022 10:56 AM
アニメーションが終了したタイミングでSKEmitterNodeをremoveFromParent()すればいいです。上記のStack Overflowの回答にだいたい載ってますよ。
🙇‍♂️ 1
Avatar
iOS16からUIScreen.main が deprecatedになると思うのですが、画面の幅や高さを取得するときの別の方法って何がありますか? (edited)
Avatar
omochimetaru 8/29/2022 7:43 AM
UIView.windowUIWindow.windowSceneUIWindowScene.screen を取ってくるのが良いのではないでしょうか (edited)
👀 1
Avatar
Apple discourages the use of this symbol. Use a UIScreen instance found through context instead. For example, reference the screen that displays a view through the screen property on the window scene managing the window containing the view.
deprecatedになるときは何かしら代替案を提示してくれていることが多いので、この辺りを読むと良いと思います。で、おもちさんの提示している方法がまさに書かれています。 https://developer.apple.com/documentation/uikit/uiscreen/1617815-main
🙇 2
Avatar
Avatar
Yuta Saito
Apple discourages the use of this symbol. Use a UIScreen instance found through context instead. For example, reference the screen that displays a view through the screen property on the window scene managing the window containing the view.
deprecatedになるときは何かしら代替案を提示してくれていることが多いので、この辺りを読むと良いと思います。で、おもちさんの提示している方法がまさに書かれています。 https://developer.apple.com/documentation/uikit/uiscreen/1617815-main
ありがとうございます。勉強になります。
Avatar
Kishikawa Katsumi 8/29/2022 7:50 AM
基本的にウインドウの幅が必要なことはそんなにないので、ViewControllerのビューの大きさなどを使うほうが簡単だし安定します。
Avatar
wkwebviewが昔init時のframeに妥当な幅を入れないとレンダリングがバグることがあったので、そういう系のを踏むと横幅欲しくなりますね (edited)
😲 1
Avatar
Kishikawa Katsumi 8/29/2022 7:54 AM
まあViewControllerもdidLoadのタイミングだと大きさが決まってないとかはありますね。
Avatar
swift build において、 xcrun --find swift で出力されるのと異なるツールチェーンが使われてしまうのですが、原因や解決策がわかる方はいますでしょうか…? $ xcrun --find swift /Applications/Xcode-14.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift $ xcode-select -p /Applications/Xcode-14.0.0.app/Contents/Developer # なぜか `Xcode-14.0.0.app` でなく `Xcode-14.0.0-Beta.app` が使われる $ swift build -c release --package-path Tools/UhooiPicBookTools --product swiftlint --verbose Copying /Users/uhooi/Documents/Repos/GitHub/uhooi/UhooiPicBook/Tools/UhooiPicBookTools/.build/artifacts/swift-syntax/_InternalSwiftSyntaxParser.xcframework/macos-arm64_x86_64/lib_InternalSwiftSyntaxParser.dylib /Applications/Xcode-14.0.0-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -fobjc-arc ... ... やったことは↓に雑にまとめています。 必要に応じてログなども採取できます。 https://twitter.com/the_uhooi/status/1563343711790313472?s=20&t=yVYzDQETN4_8nRFfjB3avQ (edited)
Xcode 13 をアクティブにしているのに、ターミナルだとなぜか Xcode 14 が使われてエラーになるな、、
Avatar
swift package clean.build の削除は試しました?
Avatar
Kishikawa Katsumi 9/14/2022 2:26 AM
なんか環境変数を設定してしまってたりしないかな。 env で出力した環境変数を載せられます?(右辺は適当にマスクして大丈夫です)
Avatar
あ、 .build.swiftpm を消したらいけそうです 今実行中です
2:28 AM
swift package clean は実行してもエラーのままでした
2:28 AM
行けました!!!
👍 2
2:29 AM
失礼しました 🙇
Avatar
こういった Task の使い方って問題あったりしますか? actor Executer { var currentTask: Task<Void, Never>? func append(_ body: () async -> Void) { let old = currentTask currentTask = Task { await old?.value await body() } } }
Avatar
omochimetaru 9/23/2022 5:48 AM
動作としては期待通りになりそうですけど、過去のTaskが解放されずに無限につながっていってメモリリークしませんかね?
5:49 AM
Taskの実装として、処理完了時に自身のクロージャを破棄するようになっていれば大丈夫ですが・・・
Avatar
ありがとうございます!
6:34 AM
class Buffer {     let data: Data     init(data: Data) {         self.data = data     }     deinit {         print("deinit buffer", data)     } } actor ViewModel: ObservableObject {     var currentTask: Task<Buffer, Never>?     func action(_ new: @escaping () async -> Data) {         let old = currentTask         currentTask = Task {             _ = await old?.value             let data = await new()             print("allocated", data)             return Buffer(data: data)         }     } }
6:35 AM
こんな感じにしてみて memory graph の様子をしばらく見てみましたが怪しく増えるオブジェクトはなさそうでした
6:36 AM
Buffer はひとつ遅れて開放されるので若干リークといえるかもしれませんが…
Avatar
Avatar
omochimetaru
Taskの実装として、処理完了時に自身のクロージャを破棄するようになっていれば大丈夫ですが・・・
Taskヒープオブジェクトはクロージャで与えられたasync operationが完了した後 swift_release されるので、Task構造体のキャプチャがチェインしていてもリークの心配は無さそうです。 https://github.com/apple/swift/blob/dd00a7571acd512873b13d9329bb7d159cf2568c/stdlib/public/Concurrency/Task.cpp#L489
Avatar
Avatar
Yuta Saito
Taskヒープオブジェクトはクロージャで与えられたasync operationが完了した後 swift_release されるので、Task構造体のキャプチャがチェインしていてもリークの心配は無さそうです。 https://github.com/apple/swift/blob/dd00a7571acd512873b13d9329bb7d159cf2568c/stdlib/public/Concurrency/Task.cpp#L489
omochimetaru 9/23/2022 7:31 AM
Concurrency.Task は値型だから、ヒープ上の実体オブジェクトがあって、それがここでreleaseしてるって事かな? 終了したTaskに対して後から task.value で取れるけど、これは Cocurrency.Task に保存されてる?
7:31 AM
Task がコピーされてるときってどうなってるんだ
Avatar
値を返すTask(Future)は、Taskヒープオブジェクトの中の FutureFragment という領域に結果を保持しています。終了したTaskでも .value を呼べるならTaskヒープオブジェクトは生きてるのでそこから取ってくる。
7:43 AM
TaskをコピーするときはTask構造体のフィールドにNativeObjectがあるのでそれがリテインされる
7:45 AM
だからよく考えると今回のキャプチャチェインの問題は↑の swift_releaseは関係なかったです。キャプチャ時のretainに対応するreleaseが _ = await old?.value の直後に入るのでキャプチャする側のクロージャが解放される前にTaskを手放せるからリークしない、ということでした。 (edited)
Avatar
Avatar
Yuta Saito
Taskヒープオブジェクトはクロージャで与えられたasync operationが完了した後 swift_release されるので、Task構造体のキャプチャがチェインしていてもリークの心配は無さそうです。 https://github.com/apple/swift/blob/dd00a7571acd512873b13d9329bb7d159cf2568c/stdlib/public/Concurrency/Task.cpp#L489
このretainはユーザコードが誰もTaskを参照していない状態でもオブジェクトが消えないようにTask生成時に+1 retainされる分とバランスするやつ
Avatar
Avatar
Yuta Saito
だからよく考えると今回のキャプチャチェインの問題は↑の swift_releaseは関係なかったです。キャプチャ時のretainに対応するreleaseが _ = await old?.value の直後に入るのでキャプチャする側のクロージャが解放される前にTaskを手放せるからリークしない、ということでした。 (edited)
omochimetaru 9/23/2022 8:15 AM
あーここに入ってるんだ。 それだと元コードの安全性は微妙だな。
8:16 AM
@nanasi oldvar にして、以下のように明示的に解放すると確実に安全で良いと思います。 現状リークしないのはコンパイラのコード生成のブレに依存してるようです。 _ = await old?.value old = nil
Avatar
なるほど…
10:11 AM
var 変数のキャプチャになってしまうのでひと手間必要そうですね
10:13 AM
上の例なら currentTask と同様に actor のプロパティにしてしまうのが簡単そう? 🤔
Avatar
EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64に設定していてSPMを利用する場合、M1のマシンでx86_64シミュレータのバイナリが見つからないのですが、何か解決策はないでしょうか。
Avatar
Kishikawa Katsumi 9/30/2022 5:20 PM
無理そうですね。Swift Packageと本体アプリが同じアーキテクチャでビルドされたらいいのですが、どうやってもSwift Packageはarm64でビルドされてしまいますね。 解決法はたぶんXcodeをロゼッタを使って起動する、じゃないでしょうか。
5:21 PM
もしくは、 コマンドラインならなぜかVALID_ARCHSが効くので、 xcodebuild -project SwiftUIQuestionSample.xcodeproj -scheme SwiftUIQuestionSample -destination 'platform=iOS Simulator,name=iPhone 13 Pro' VALID_ARCHS=x86_64 build のようにするとビルドできます。
5:21 PM
コマンドラインから全部やるならたぶんいける
Avatar
Kishikawa Katsumi 9/30/2022 9:03 PM
ちなみにx86_64でビルドしたいのは他に利用する予定のライブラリが対応してないからですか?
Avatar
回答ありがとうございます! そうですね…とある広告フレームワークが対応してくれず。。。😢 (edited)
😲 1
Avatar
Kishikawa Katsumi 10/1/2022 3:47 AM
ロゼッタで動かす以外にSwiftPMの方をx86でビルドする方法があるといいんですけどね。VALID_ARCHSがそれのはずなんだけどXcodeからは完全に無視されてしまうし。
Avatar
VALID_ARCHSはdeprecatedになってユーザー定義になったみたいなのを見たような気がしますが、関係あるでしょうか?
Avatar
Kishikawa Katsumi 10/1/2022 11:29 AM
あると思います。ユーザー定義で作ってもダメでした😢
👀 1
Avatar
ファイルを削除しようとして見つからなかった時のエラーハンドリングを、今まで以下のように書いていましたが、 do { try FileManager.default.removeItem(at: .documentsDirectory.appendingPathComponent("aaa")) } catch let error as NSError { if error.domain == "NSCocoaErrorDomain", error.code == 4 { print("削除しようとしたファイルが見つからなかった") } } こちらの記事を読んでCocoaError.fileNoSuchFileでcatchできることを知りました。 https://developer.apple.com/documentation/swift/handling-cocoa-errors-in-swift do { try FileManager.default.removeItem(at: .documentsDirectory.appendingPathComponent("aaa")) } catch CocoaError.fileNoSuchFile { print("削除しようとしたファイルが見つからなかった") } 後者のほうが見やすいのでこれは良いのですが、 Error(NSError)からCocoaError.fileNoSuchFileにたどり着く方法が分からずじまいです。 せいぜいドメイン(NSCocoaErrorDomain)とコード(4)までしか分からないのですが、何かいい方法があるのでしょうか?
😮 1
Avatar
他にも URLError POSIXError などがありますね。 そういえばたどり着き方はどこでわかるんだろう・・・ 実装は public struct URLError : _BridgedStoredNSError { ... } って感じでここにあるみたいですけど https://github.com/apple/swift-corelibs-foundation/blob/eec4b26deee34edb7664ddd9c1222492a399d122/Darwin/Foundation-swiftoverlay/NSError.swift
9:55 AM
URLErrorの個別のリファレンスはあるけど、NSErrorからどうやって辿るのか・・・?
9:57 AM
ここにErrorDomain一覧(ほんとか?)はあるので、 探すヒントにはなりそうですが
Avatar
たどり着けるんですかね。 CocoaError.CodeCocoaError.fileNoSuchFile とかの型)に static func ~=(match: Self, error: Error) -> Bool は定義されているので、逆側からマッチングする( fileNoSuchFile かどうか調べる)のはできそうですけどね。上のcatchはこれでマッチングしてますよね。 https://developer.apple.com/documentation/foundation/cocoaerror/code/3726493
Avatar
catchの後ろに値を書けることを知らなかった・・・
Avatar
catchしてからswitch-caseしなくても、絞り込み付きのcatchを複数並べる書き方でswitch無しにできますね (edited)
Avatar
エラーコードの意味自体は文字列リソースから網羅できたりします https://applelocalization.com/?c=key&o=startsWith&q=Err&l=Japanese
Avatar
Objective-C の頃はヘッダ定義に飛んで直値をすぐに見れたんですが、自分も面倒くさく思ってます
wakaru 3
Avatar
なるほどやはりたどり着く方法は気合しか無いのですね、、 それでも参考になるリンクいただき感謝です。 ありがとうございました!
Avatar
精神論コーディングw
3:05 PM
ヘッダファイルがない、というのはやはり辛い面も多い
3:06 PM
多分にツールの問題なので、解決されるといいな。
Avatar
以前むしゃくしゃして書いた
8:55 AM
NSCocoaErrorDomainのエラーコードとエラー名の対応表 let array: [(Int, String)] = [ (NSFileNoSuchFileError, "NSFileNoSuchFileError...
Avatar
Avatar
We
ファイルを削除しようとして見つからなかった時のエラーハンドリングを、今まで以下のように書いていましたが、 do { try FileManager.default.removeItem(at: .documentsDirectory.appendingPathComponent("aaa")) } catch let error as NSError { if error.domain == "NSCocoaErrorDomain", error.code == 4 { print("削除しようとしたファイルが見つからなかった") } } こちらの記事を読んでCocoaError.fileNoSuchFileでcatchできることを知りました。 https://developer.apple.com/documentation/swift/handling-cocoa-errors-in-swift do { try FileManager.default.removeItem(at: .documentsDirectory.appendingPathComponent("aaa")) } catch CocoaError.fileNoSuchFile { print("削除しようとしたファイルが見つからなかった") } 後者のほうが見やすいのでこれは良いのですが、 Error(NSError)からCocoaError.fileNoSuchFileにたどり着く方法が分からずじまいです。 せいぜいドメイン(NSCocoaErrorDomain)とコード(4)までしか分からないのですが、何かいい方法があるのでしょうか?
自分も面倒だったので、エラードメイン名で絞り込んで一覧を表示するサイトを作ってみました https://cocoa-errors.onrender.com/
Cocoa Errors Wardrobe
9:56 AM
NS_ERROR_ENUM をキーに抽出しているので抜けが多々ありそうですが (edited)
Avatar
@swift-5.6.3 func todoInt() -> Int { fatalError("TODO") } func todoSequence() -> some Sequence { fatalError("TODO") // Return type of global function 'todoSequence()' requires that 'Never' conform to 'Sequence' }
Avatar
Avatar
t.ae
@swift-5.6.3 func todoInt() -> Int { fatalError("TODO") } func todoSequence() -> some Sequence { fatalError("TODO") // Return type of global function 'todoSequence()' requires that 'Never' conform to 'Sequence' }
exit status: 1 with stderr:<stdin>:6:5: error: return type of global function 'todoSequence()' requires that 'Never' conform to 'Sequence' fatalError("TODO") // Return type of global function 'todoSequence()' requires that 'Never' conform to 'Sequence' ^ <stdin>:5:24: note: opaque return type declared here func todoSequence() -> some Sequence { ^~~~~~~~~~~~~
Avatar
返り値someの場合fatalErrorでTODOにしておくのができない?
Avatar
ortの真の型の判定と混ざってそうだな
6:24 AM
その下にreturn []ってかけない?
Avatar
ダミーを用意すればいいですけど、protocolと関数が先にあって実装が後回しになってるケースもあるかなと
Avatar
aimai (SwiftUI-beginner) 10/31/2022 10:47 PM
このtabViewみたいなToggleみたいなこれは何ていうview ですか?? 調べようがないことで困ってます💦
Avatar
Kishikawa Katsumi 10/31/2022 10:51 PM
Segmented Controlですね。Pickerに.segmentedスタイルを指定すると作れます。 https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-a-segmented-control-and-read-values-from-it
Learn Swift coding for iOS with these free tutorials
Avatar
aimai (SwiftUI-beginner) 10/31/2022 10:52 PM
ありがとうございます😭 早速使います♪
Avatar
UIButtonのテキストのみを回転させることって可能でしょうか? 端末を横向きにすると縦読みできるイメージです。 CoreTextやNSMutableAttributedStringを使って実現できるのかなと思い調べていますが、全く実装方法が浮かばず。そもそも可能なのか?と思い質問させていただきました。
Avatar
縦書きということでしょうか? 例えば、横書きと縦書きでは、"。”や"「"の位置が違うので、単純な90度回転だと難しいのかなと思いました。
Avatar
Avatar
m_yukio
縦書きということでしょうか? 例えば、横書きと縦書きでは、"。”や"「"の位置が違うので、単純な90度回転だと難しいのかなと思いました。
仰る通り縦書きです。 今回は"。"や"「"は無いので単純に90度回転させたいです。
Avatar
縦書き自体は難しくて、表示する文字列が固定なら縦書きの画像を作って入れ替えるのが楽だと思いますよ
t_naruhodo 1
Avatar
staticなものの表示だけなら画像が楽ですね。iOSDCで縦書きエディタの開発についての話がありましたので、紹介しておきます。 https://m.youtube.com/watch?v=92ia8grso50
t_kansha 1
Avatar
iPhoneカメラの画面ロックしてても向きを検知して回転してくれる仕組みってCoreMotion使ってますか?
Avatar
Kishikawa Katsumi 11/17/2022 7:06 AM
そうですね。CoreMotionを使ってセンサーの情報から向きを判定しているはずです。
Avatar
Avatar
Kishikawa Katsumi
そうですね。CoreMotionを使ってセンサーの情報から向きを判定しているはずです。
ありがとうございます!
Avatar
FigmaのViewに対して、エフェクトの背景ぼかしをつけたとしてそれをSwiftで再現する方法わかる方いませんか。 インスペクタのコード(CSS)を見るとbackdrop-filter: blur(50px);になっています。 iOSにすると指定がなさそうです。 (edited)
Avatar
Kishikawa Katsumi 11/29/2022 11:58 AM
SwiftUIだと View.blur(radius:opaque:) があります。ぼかしの程度の指定がCSSの指定と異なりますがradiusパラメータを同じような感じになるように調整するとうまくいくと思います。
t_naruhodo 1
Avatar
SwiftUI使わないやり方だとどうでしょうか。
Avatar
Kishikawa Katsumi 11/29/2022 12:53 PM
UIVisualEffectViewを使います。その場合、UIVisualEffectViewにはBlurのかかり具合を調整するプロパティは公開されてないので、UIViewPropertyAnimatorを使ってeffectに対してアニメーションさせてfractionCompleteの値を使ってBlurのかかり具合を調整します。
Avatar
ExtraLight 、Light 、Darkの3種類から選んでfractionCompleteで一番近いものを目視で決めるってことですね。
1:11 PM
fractionCompleteが決まれば、その値を指定してアニメーションを一時停止する?という認識であってますか。
Avatar
Kishikawa Katsumi 11/29/2022 1:13 PM
そうですね。アニメーションはそもそも開始しないでfractionCompleteを設定するだけでいけると思います。
Avatar
なるほど、分かりやすくありがとうございます。それでやってみます!
Avatar
Shinichi Katayama 11/29/2022 7:10 PM
以下のようなクラッシュが発生するSwiftファイルを作成し、swiftコマンドで実行するとクラッシュトレースが出力されるのですが、クラッシュが発生した行番号を出力する方法をご存知の方がいれば教えていただけないでしょうか?ちなみに llvm-symbolizerはPATHに存在します。OSはMonterey 12.6、M1 Macbook Proです。 foo.swift let a = [Int]() a[0] ❯ which llvm-symbolizer /opt/homebrew/opt/llvm@13/bin/llvm-symbolizer ❯ swift --version swift-driver version: 1.62.15 Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51) Target: arm64-apple-macosx12.0
Avatar
結論から言うと、swift コマンドで実行した場合はスクリプト側の行番号などはスタックトレースに表示できません。swift コマンドでの実行にこだわりがなければ、 swiftc -g foo.swift でデバッグ情報付きの実行ファイルを作って、lldbなどで実行した上で、クラッシュ時のバックトレースをみるのが良いと思います。
5:07 AM
こんなかんじです tmp.naXATKx4$ swiftc foo.swift -g foo.swift:2:2: warning: expression of type 'Int' is unused a[0] ~^~~ foo.swift:2:2: warning: expression of type 'Int' is unused a[0] ~^~~ tmp.naXATKx4$ lldb ./foo (lldb) target create "./foo" Current executable set to '/var/folders/k2/q6yzck31253_q1j4kxkzq5jh0000gn/T/tmp.naXATKx4/foo' (arm64). (lldb) run Process 11150 launched: '/var/folders/k2/q6yzck31253_q1j4kxkzq5jh0000gn/T/tmp.naXATKx4/foo' (arm64) Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range 2022-11-30 14:06:07.610207+0900 foo[11150:3677660] Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range Process 11150 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = Fatal error: Index out of range frame #0: 0x0000000193d93ae8 libswiftCore.dylib`_swift_runtime_on_report libswiftCore.dylib`: -> 0x193d93ae8 <+0>: ret libswiftCore.dylib`: 0x193d93aec <+0>: b 0x193d93ae8 ; _swift_runtime_on_report libswiftCore.dylib`: 0x193d93af0 <+0>: adrp x8, 308504 0x193d93af4 <+4>: ldrb w0, [x8, #0x6dc] Target 0: (foo) stopped. (lldb) thread backtrace * thread #1, queue = 'com.apple.main-thread', stop reason = Fatal error: Index out of range ... frame #8: 0x0000000100003f88 foo`main at foo.swift:2:2 frame #9: 0x00000001859a7e50 dyld`start + 2544 (lldb)
Avatar
やってみた できた
Avatar
いつもXcodeで動かすからあれ?出なかったっけ…ってなってた
wakaru 1
Avatar
Xcodeのプロジェクトとして実行するのが簡単でオススメですね。
Avatar
Avatar
Yuta Saito
結論から言うと、swift コマンドで実行した場合はスクリプト側の行番号などはスタックトレースに表示できません。swift コマンドでの実行にこだわりがなければ、 swiftc -g foo.swift でデバッグ情報付きの実行ファイルを作って、lldbなどで実行した上で、クラッシュ時のバックトレースをみるのが良いと思います。
swift コマンドからだと出ないんだね、気づいてなかったわ
Avatar
(ここからは読み飛ばしてもらって大丈夫です)swift コマンドでうまく行かない理由ですが、 swift コマンドでの実行はLLVM JIT経由でコンパイラプロセス内でスクリプトが実行されるんですが、その場合にDWARFが正しく作られていない、もしくはllvm-symbolizerがexecutable memory上にマップされたDWARFセクションを読めてないか、が原因だと思います。
Avatar
Avatar
omochimetaru
swift コマンドからだと出ないんだね、気づいてなかったわ
ぼくも言われて初めて気がつきましたw
5:12 AM
swiftコマンドはなんか難しいのであんまり使わない
Avatar
結構前の質問なので、メンションも飛ばしておきましょうか @Shinichi Katayama
Avatar
Shinichi Katayama 11/30/2022 6:07 AM
@Yuta Saito ありがとうございます!内部の仕組みまで詳しく教えていただき勉強になります。
6:09 AM
コンテキストとしては競プロ練習用にVSCodeにSwift拡張機能を入れてSwiftを書いているのですが、Run Swift Script を実行するとどうも内部でswiftコマンドで実行されるらしく、クラッシュした時に行番号が見れないのに困っています。素直にXcodeでやった方が良さそうですね。
naruhodo 1
Avatar
Avatar
Shinichi Katayama
コンテキストとしては競プロ練習用にVSCodeにSwift拡張機能を入れてSwiftを書いているのですが、Run Swift Script を実行するとどうも内部でswiftコマンドで実行されるらしく、クラッシュした時に行番号が見れないのに困っています。素直にXcodeでやった方が良さそうですね。
ご参考までに、 Xcodeだと New > Project > macOS > Command Line Tool で競プロやってる人が多いと思います。 #atcoder チャンネルに Swift で競プロやってる人がたくさんいます。
Avatar
Avatar
koher
ご参考までに、 Xcodeだと New > Project > macOS > Command Line Tool で競プロやってる人が多いと思います。 #atcoder チャンネルに Swift で競プロやってる人がたくさんいます。
Shinichi Katayama 11/30/2022 7:23 AM
なるほど、ありがとうございます!
🙂 1
Avatar
UINavigationBarAppearanceを使って透明な状態からスクロールすると少しずつLight Blurが表示されるような実装をしたいです。 let appearance = UINavigationBarAppearance() appearance.shadowImage = UIImage() appearance.shadowColor = .clear let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light) appearance.backgroundEffect = blurEffect
2:33 PM
この指定でブラーはかけれますが、BlueEffectにalphaの指定はできないようなので、そこをどうするか悩んでいます。
2:35 PM
UINavigationBarAppearanceは諦めて、UINavigationBarに対してViewをaddSubViewするべきでしょうか
Avatar
Kishikawa Katsumi 12/1/2022 2:37 PM
UIAppearanceでできるかな。NavigationBarに直接UIVisualEffectViewを置くか、NavigationBarは透明にしてその位置にUIVisualEffectViewをしいて(Safe Areaを使うとNavigationBarと一致する形が取れる)、UIVisualEffectViewをスクロールの位置によってUIViewPropertyAnimatorのfractionCompleteを使って変化させていくのがいいと思います。
2:38 PM
私ならNavigationBarの下にUIVisualEffectViewをしく方法を取ります。
2:38 PM
NavigationBarはグローバルな存在なのでそこにビューを追加したりしてしまうと他の画面で使わない、というときに面倒なので。 (edited)
Avatar
@Kishikawa Katsumi ご返信ありがとうございます。先日教えていただいたUIViewPropertyAnimatorをここでも使う感じですね。 SafeAreaInset.topで大きさ取ってVIewを敷く実装で作ってみます。 (edited)
Avatar
Kishikawa Katsumi 12/1/2022 2:51 PM
大きさを取るんじゃなくてSuperviewの上とSafe Areaの上に制約を付けるんですよ。そうするとSuperviewからSafeareaを引いた形になるので。大きさを取るとAutolayoutを使う利点がなくなって、UINavigationBarの高さが変わったときとかにおかしくなります。
t_naruhodo 1
2:57 PM
下にしくビューをビューAとすると、SuperviewのTopとビューAのTop、SafeareaのTopとビューAのBottomを付ける、横はSuperViewの左右にそれぞれビューAの左右をつける、ってします。
Avatar
今晩は、UICollectionViewを使ってMenuを作りたいのですが、アイテムのUICollectionViewCellのサイズが違うからギャップが有る。 今はこのスクリンショットと同じ結果ができたのですが、どうすればポジションを直すことができるのか迷っています。
8:34 PM
Avatar
Kishikawa Katsumi 12/2/2022 8:39 PM
全部同じ大きさにしたいのですか?
Avatar
Avatar
Kishikawa Katsumi
全部同じ大きさにしたいのですか?
いえいえ、カードのポジションが他のカードと同じにしたいのです
8:47 PM
大きさが違うから、ポジションだけが直したい
Avatar
Kishikawa Katsumi 12/2/2022 8:58 PM
縦のスペースを全部同じにしたいということですか?
8:59 PM
セルの幅はすべて同じで、高さがセルごとに異なるということですか?
Avatar
Avatar
Kishikawa Katsumi
縦のスペースを全部同じにしたいということですか?
はい!
Avatar
Avatar
Kishikawa Katsumi
セルの幅はすべて同じで、高さがセルごとに異なるということですか?
こんな感じですね、高さはできたのですが、スペースは違う
Avatar
Kishikawa Katsumi 12/2/2022 9:20 PM
なるほど、高さが130と180のセルがあるんですね。
Avatar
はい、そうです
Avatar
Kishikawa Katsumi 12/2/2022 10:08 PM
2つのColumnの両方に同じframe.yの値を入れてしまっているので揃ってしまうのではないでしょうか。 override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let attributes = super.layoutAttributesForElements(in: rect)? .map { $0.copy() } as? [UICollectionViewLayoutAttributes] var offsetYLeft = spacing var offsetYRight = spacing if let attributes { for attribute in attributes { if attribute.indexPath.item % 2 == 0 { attribute.frame.origin.y = offsetYLeft offsetYLeft += attribute.frame.height + spacing } else { attribute.frame.origin.y = offsetYRight offsetYRight += attribute.frame.height + spacing } } } return attributes } ^ こんな感じで左の列と右の列でframe.yの値を別々に計算して設定していけばできると思います。 (edited)
10:15 PM
^ は実際には見えてる部分しかoffsetYを足してないのでスクロールしてもoffsetYを保持して足していけるようにindexPathをキーにしたDictionaryなどで管理する必要があると思います。
Avatar
なるほどね、分かりやすく説明ありがとうございます、あなたのソルーションを使って続きます
Avatar
Avatar
Kishikawa Katsumi
^ は実際には見えてる部分しかoffsetYを足してないのでスクロールしてもoffsetYを保持して足していけるようにindexPathをキーにしたDictionaryなどで管理する必要があると思います。
はい、スクロールすればポジーションはバラバラになるのですからね
10:22 PM
本当にありがとうございます、助かりました!
Avatar
hogeImageView.frame.sizeよりhogeImageView.image?.sizeの方が大きい数がprintされるのですが、後者はなんのサイズを表しているのでしょうか? また、UIImageView.imageのCGRectを取得することは可能でしょうか?
Avatar
hogeImageView.frame.size は View のサイズですが、 hogeImageView.image?.sizeUIImage のサイズなので↓になります。 https://developer.apple.com/documentation/uikit/uiimage/1624105-size
This value reflects the logical size of the image and takes the image’s current orientation into account. Multiply the size values by the value in the scale property to get the pixel dimensions of the image.
5:04 AM
得られたサイズに scale を掛けると画像自体のピクセル単位での解像度になるようですね。
5:06 AM
たとえば、 600x400の画像を Hoge@2x として読み込むと size は300x200、 scale は 2 になるようです。これを 120x80 の UIImageView にセットすると、 homeImageView.frame.size は 120x80 、 homeImageView.image?.size は 300x200 です。 (edited)
Avatar
ありがとうございます! なるほど、imageView.frame.sizeとはまた違ったsizeなのですね、、、 imageView.imageのサイズぴったりにviewを置きたいのですが、AspectFitで表示していて画像によってサイズが違う(UIImageViewに余白?ができる)のでどうにかimageView.image.frame.sizeみたいな値をとりたいのですが全くわからず。。。
Avatar
UIImageView のアスペクト比を画像のアスペクト比と同じにしたいということでしょうか?
Avatar
Kishikawa Katsumi 12/9/2022 5:32 AM
グレーがImageViewとして、青の枠線のCGRectが取りたいってことですか?
Avatar
Avatar
koher
UIImageView のアスペクト比を画像のアスペクト比と同じにしたいということでしょうか?
いえ、全く別のUIViewです。imageView.imageの上に重ねて置きたいです。
Avatar
Avatar
Kishikawa Katsumi
グレーがImageViewとして、青の枠線のCGRectが取りたいってことですか?
その通りです!
Avatar
Kishikawa Katsumi 12/9/2022 5:33 AM
それなら、AVMakeRectWithAspectRatioInsideRectで青線の部分の座標とサイズが取れます。
5:34 AM
https://blog.kishikawakatsumi.com/entry/20130524/1369329430 こちらを参考に。Objective-Cですがだいたい一緒なのでわかるかと。
↓ 例えばこんなふうに UIImageView に 'Aspect Fit' を指定して表示させたときの領域を知りたいことってありますよね。 がんばって計算してもいいのですが、AVFoundation.framework の次の関数で簡単に取得できます。 CGRect AVMakeRectWithAspectRatioInsideRect(CGSize aspectRatio, CGRect boundingRect); ドキュメントによると、ムービーを CALayer に表示するときに領域にフィットさせるのに便利ということですが、画像に使っても便利です。 上記の画像だと UIImageVie…
👀 2
5:34 AM
たぶんAVMakeRectWithAspectRatioInsideRectで調べたらSwiftの参考になる記事もあるかと思います。
5:35 AM
こんなのあったんですね。知りませんでした。計算用のライブラリ自作してました。 https://github.com/koher/cgrect-fit
Avatar
Avatar
Kishikawa Katsumi
https://blog.kishikawakatsumi.com/entry/20130524/1369329430 こちらを参考に。Objective-Cですがだいたい一緒なのでわかるかと。
ありがとうございます!
Avatar
知らなかったこんなのあるんですね。いつもその場で算数してました
Avatar
Kishikawa Katsumi 12/9/2022 5:36 AM
自分で計算しても全然問題ないですよね。
Avatar
CollectionViewなどでセルをドラッグして別のセルに対してドロップするのってどうやって実装するかわかりますか。できれば並び替えも同時にできるような(メモ帳アプリみたいな)のを実装したいのですが、調べてもそれらしきものが見つかりませんでした。ModernCollectionViewとかで作れたりするのでしょうか。 (edited)
Avatar
Kishikawa Katsumi 12/11/2022 5:42 AM
https://phosphor-bronze.blogspot.com/2018/07/uicollectionview.html 単純並べ替えはcanMoveItemAtmoveItemAtを実装すればいいです。
並び替えが出来るUICollectionViewに関する備忘録です。 まず、単純にUICollectionViewを表示するプロジェクトを作成しておきます。セルにラベルを用意して、番号を表示させているだけです。storyboardで、セルに色を付けておくと動作チェックがやり...
5:43 AM
https://phosphor-bronze.blogspot.com/2018/07/uicollectionviewios11.html Drag and Dropで画像とかをセルに、みたいな処理はDragDelegateを実装します。
「UICollectionViewの並び替え(よくある編)」 のつづきです。 並び替えの出来るUICollectionViewは 前回の方法 で実現できますが、iOS11で追加されたドラッグ・アンド・ドロップの機能を使った方法もあります。 このドラッグ・アンド・ドロップ...
Avatar
@Kishikawa Katsumi 無事にできました、ありがとうございます。 これCollectionViewの場合はinsertAtDestinationIndexPathinsertIntoDestinationIndexPathを同時に扱う.automaticというintentは存在しないのですね。残念です。
Avatar
以下のコードは2022/11/06と次の日を出力しているのですが、 端末の時間帯がロサンゼルスの時は 2022-11-06 07:00:00 +0000 2022-11-07 08:00:00 +0000 と正しい日付が表示されるのですが、端末の時間帯が東京だと 2022-11-06 07:00:00 +0000 2022-11-07 07:00:00 +0000 となってしまいます。 端末の設定に依存せずに日付の加算をするには、どうしたらいいでしょうか? let caledar = Calendar(identifier: .gregorian) let timeZone = TimeZone(identifier: "America/Los_Angeles")! let dateComponents = DateComponents(calendar: caledar, timeZone: timeZone, year: 2022, month: 11, day: 6) let date = dateComponents.date! let nextDate = caledar.date(byAdding: DateComponents(calendar: caledar, timeZone: timeZone, day: 1), to: date)! print(date) print(nextDate)
Avatar
CalendarにtimeZoneをセットするといいと思いますよ
Avatar
@Iceman ありがとうございます。正しい日付が表示されました。
👍 1
Avatar
この警告が出た際にどっちを選ぶかで何か変わることってありますか。 キャプチャリストを使った方がselfの数が減るのでいいのかなって思ってましたが、それ以上のことはよくわかっていません。
Avatar
実行時の挙動としては変わらないと思います。 つまり単にコードの見た目の違いです。 ただもしその関数にローカル変数の let backgroundImage があった場合、 キャプチャリストで書くと backgroundImage が ローカル変数を意味するのか、self のプロパティを意味するのかがわかりにくい、といった違いがありそう。
t_naruhodo 1
Avatar
@omochimetaru 分かりやすい説明ありがとうございます。 以前からこの書き方に違いがあるのかどうか気になっていたので助かりました。
Avatar
aimai (SwiftUI-beginner) 12/31/2022 8:18 AM
質問失礼します。SwiftUIです。
8:18 AM
CoreDataは一つの構造体につき一つのエンティティしか使えないのですか、、?
8:19 AM
普通に使おうとしてもエラーが出て使えないのですが、複数のエンティティを使う場合は特別な表記があるのですか??
Avatar
Kishikawa Katsumi 12/31/2022 10:49 AM
@FetchRequestdata2のプロパティにはついてないからですね。 @FetchRequest というProperty Wrapperは指定したプロパティに自動的にCoreDataからデータを検索して詰めてくれるものですが、プロパティごとなのでこのコードだとdata1には@FetchRequestによってデータが入りますが、data2には何も指定がなくてただのプロパティなのでデータが入らないので、data2が未初期化だということでエラーになっています。
Avatar
aimai (SwiftUI-beginner) 12/31/2022 1:46 PM
ありがとうございます!! できました!! リクエストは各エンティティごとに必要なんですね!
1:46 PM
皆さん、ついでになってしまいますが、今年は有難うございました。 よいお年をお迎えください!
Avatar
質問失礼いたします。 Xcodeをターミナルから開けるCLIツールを作っているのですが、Xcodeを開こうとするとエラーになってしまい詰まっています。 Xcode以外のアプリは開けるようでした。(Safariなど) CLIツールの構成方法は、SPMを使っておりexecutableのProductとして定義しています。 ミニマムの再現コードは以下になります。 let xcodeURL = URL(fileURLWithPath: "/Applications/Xcode13.2.1.app") NSWorkspace.shared.open(xcodeURL) Thread.sleep(forTimeInterval: 2) exit(0) これでXcode自体は起動できるのですが、 Required content for platform watchOS is missing. Please reinstall Xcode. というメッセージが起動したXcode13.2.1から表示されます。 (もちろんFinderからだと正常に開くことが可能なアプリです) Terminal のopen コマンドを使用したらいけるのではと思ったのですが、同じ結果でした。 sudo をつけると正常に起動できるようです。 また、CocoaアプリケーションとしてWindowが表示されるようなアプリを作った場合、 同じコードでDebug, Releaseビルドだと同じエラーになりますが、Archiveを作成して実行した場合は正常に起動ができました。。 何かPermissionが足りないのでしょうか? どなたか何かわかることがある方がいらっしゃれば教えていただけますと幸いです。 (edited)
Avatar
Kishikawa Katsumi 1/7/2023 3:30 PM
再現しなかったです。私の環境だと同じコードでFinderからダブルクリックで起動したときと同じように起動しました。何が違うんでしょうね。macOSのバージョンはいくつですか?私はMontereyの最新(12.6)です。 (edited)
Avatar
岸川さん、ご確認いただいてありがとうございます。 私の使用しているmacOSも同様に Montereyの最新 (12.6) でした。 同じバージョンでも挙動が異なるのですね。。 会社管理のPCなので、内部の細かい挙動が管理されているなどあるのですかね。ちょっと把握できておりませんが。
Avatar
詳しくないですが,そのエラーは xcode-select でどの Xcode も選択されていない場合や,インストール時の Xcode のコピーが不完全だった場合に起こるようです.Xcode13.2.1.app 以外のバージョンの Xcode を select して使っているわけじゃなければ sudo xcode-select -s /Applications/Xcode13.2.1.app を実行してみるのはいかがでしょうか? https://developer.apple.com/forums/thread/117347
Avatar
keboさん、ありがとうございます。 確認してみます。 自分は複数のXcodeバージョンを普段から切り替えて使っているので、CLIツールの中で sudo xcode-select をするのも使いづらい気もしています。 sudoを使うとパスワード入力が必要になってしまうので。。 普段使用しているXcodeは /Applications/Xcode.app で、xcode-select のpathもそれに設定されているのでおかしな挙動になってしまっている可能性もありそうでした。 Xcode13.2.1Xcode にrenameしてから、Scriptのpathを /Applications/Xcode.appに変更して実行したところ正常に実行できてしまいました。 (edited)
Avatar
あ、いや、毎回じゃなくてこれはその環境で一度実行すれば大丈夫です.(CI 環境みたいに実行するたびに違うマシンが使われる状況とかだと厄介ですが)
Avatar
伝わりづらくすみません。 myscript -v 13.2.1 のように自分のScriptを起動して、任意のXcodeバージョンを開くことができるようにしたいので、 毎回 xcode-select を実行する必要があるのかなと思いました。 実行はローカルを想定しています。
Avatar
なるほど.一つ確実に存在するメインのバージョンの Xcode.app があればそれを select しておけばすみそうなんですけれどね. (edited)
Avatar
現状だと実在する Xcode.app のpathに設定しているのですが、 Xcode13.2.1.app を起動しようとするとエラーになるのですよね。
Avatar
おそらくですが,/Applcations/Xcode.app が select されているのに /Applications/Xcode.app が存在していないということがエラーの原因だと思います.存在するものが select されてさえいれば,必ずしも開きたい Xcode が select されている必要はないはずですよ. (edited)
11:40 PM
select されているパスが実在しないということが問題なのであれば,指定するバージョンを変えるたびに select し直す必要はないと思います.
Avatar
すみません、わかりづらかったですね。 xcode-select しているアプリは実在していて、現状Applicationディレクトリは添付スクショのようになっています。 $ xcode-select -p /Applications/Xcode.app/Contents/Developer (edited)
Avatar
そうなのですね.すみません.
🙇‍♂️ 1
Avatar
ちなみに、開きたいxcodeバージョンをxcode-selectで指定した上でスクリプトを実行しても同様のエラーになってしまいました。 ですが、sudo でスクリプトを実行すると正常に開けるという挙動です。。
Avatar
norio_nomura 1/8/2023 8:01 AM
xedDEVELOPER_DIR環境変数でXcodeのパスを渡せば、任意のXcodeを開けたような。 DEVELOPER_DIR=/Applications/Xcode13.2.1.app xed . (edited)
👀 1
Avatar
ありがとうございます。 試してみたところそのコマンドでも同様にRequired content for platform watchOS is missing. Please reinstall Xcode. のエラーになってしまうようでした。 自分の環境がおかしいのかもしれません...。
Avatar
sudo で起動したshellの中で実行したところ、xedで任意のXcodeを開くことができました。 こちらを参考にもう少し検証してみます 🙇‍♂️
Avatar
iOSのビルド周りが未だにさっぱりわからないので教えて頂きたいです。 certificate?Profile?Automatically manage signingは取り敢えずチェック付けとけばいいのかな?ってレベルです。 [前提] AppleDeveloperProgramのアカウントは持っています。 [やりたいこと] プッシュ通知の機能があるアプリをTestFlightに配信したい。 [お聞きしたいこと]
  • certificate作成時の種類はどれを選択すれば良いのか?(xxx Development、xxx Distribution・・・)
  • Profileの作成はマストでしょうか?(Automatically manage signingに取り敢えずチェック付ければ良いわけではない?)
  • Deviceの登録はTestFlightからアプリをインストールするときも必須でしょうか? 質問が断片的でお答えにくいかもしれないですが、そろそろきちんと理解したいのでご教示頂けると幸いです。
またこの辺りいつもわからなくなるので、何かまとまった記事や情報があれば教えて頂きたいです。
Avatar
- certificate作成時の種類はどれを選択すれば良いのか?(xxx Development、xxx Distribution・・・)
Test Flight に配信する場合であれば iOS Distribution じゃないと届かないと思います。
- Profileの作成はマストでしょうか?
モバイルプロビジョニングプロファイルのことであれば基本的にAutomatically manage signingにチェックを入れていれば不要かと思います。
- Deviceの登録はTestFlightからアプリをインストールするときも必須でしょうか?
招待用のリンクを使えば端末登録は不要だった気がします。 ※2年くらい前の知識なので、間違っていたり、古かったらごめんなさい 🙏
(edited)
Avatar
古い情報ですが、『iOSプログラミング ビルド&リリース』という電子書籍があります。 https://www.oreilly.co.jp/books/9784873115610/
iOS上で動作するアプリケーションをビルドし、リリースするまでのプロセスを解説した書籍です。iOSデベロッパープログラムに参加し、アプリケーションIDの登録、開発用と配布用証明書のセットアップ、テスト用デバイスの登録、開発用と配布用のプロファイルをセットアップ、Xcodeを用いたビルドなどの一連のプロセス。またコマンドラインによるビルドの自動化について、コンパクトにまとめています。なお本書はEbookのみの販売となります。
Avatar
Avatar
s2mr
質問失礼いたします。 Xcodeをターミナルから開けるCLIツールを作っているのですが、Xcodeを開こうとするとエラーになってしまい詰まっています。 Xcode以外のアプリは開けるようでした。(Safariなど) CLIツールの構成方法は、SPMを使っておりexecutableのProductとして定義しています。 ミニマムの再現コードは以下になります。 let xcodeURL = URL(fileURLWithPath: "/Applications/Xcode13.2.1.app") NSWorkspace.shared.open(xcodeURL) Thread.sleep(forTimeInterval: 2) exit(0) これでXcode自体は起動できるのですが、 Required content for platform watchOS is missing. Please reinstall Xcode. というメッセージが起動したXcode13.2.1から表示されます。 (もちろんFinderからだと正常に開くことが可能なアプリです) Terminal のopen コマンドを使用したらいけるのではと思ったのですが、同じ結果でした。 sudo をつけると正常に起動できるようです。 また、CocoaアプリケーションとしてWindowが表示されるようなアプリを作った場合、 同じコードでDebug, Releaseビルドだと同じエラーになりますが、Archiveを作成して実行した場合は正常に起動ができました。。 何かPermissionが足りないのでしょうか? どなたか何かわかることがある方がいらっしゃれば教えていただけますと幸いです。 (edited)
🙇‍♂️ 1
Avatar
すみません、ありがとうございます
Avatar
Avatar
m_yukio
古い情報ですが、『iOSプログラミング ビルド&リリース』という電子書籍があります。 https://www.oreilly.co.jp/books/9784873115610/
こちら初めて知りました、ありがとうございます!
Avatar
Avatar
log5
- certificate作成時の種類はどれを選択すれば良いのか?(xxx Development、xxx Distribution・・・)
Test Flight に配信する場合であれば iOS Distribution じゃないと届かないと思います。
- Profileの作成はマストでしょうか?
モバイルプロビジョニングプロファイルのことであれば基本的にAutomatically manage signingにチェックを入れていれば不要かと思います。
- Deviceの登録はTestFlightからアプリをインストールするときも必須でしょうか?
招待用のリンクを使えば端末登録は不要だった気がします。 ※2年くらい前の知識なので、間違っていたり、古かったらごめんなさい 🙏
(edited)
ご回答頂きありがとうございます。
Test Flight に配信する場合であれば iOS Distribution じゃないと届かないと思います。
追加の質問で恐縮ですがこちらもう少し詳しく知りたいです。
  • Distributionは、Apple DistributionとiOS Distributionの2種類があると思うのですが、iOSのスマホアプリ開発においてはiOS Distributionを作成すれば良いで認識合ってますでしょうか?
  • Distributionのcertificateは最大3つまでしか作れない認識なのですが、既に3つある状態で新たなアプリを作成してTestFlightに配信したい場合は、既にあるものをRevokeして作成しないとTestFlightに配信するためのアプリをビルドできないで認識あってますでしょうか?
Avatar
Kishikawa Katsumi 1/12/2023 3:46 AM
Apple distributionはiOS distributionの上位互換なので新しく作るのならAppleを作ればいいです。
3:48 AM
Certificateは同じものを複数のアプリで使います。Revokeして作り直しても別に問題はありませんが、マシンを買い替えたとかでもなければ普通は期限が来るまでは使い続けます。
Avatar
Avatar
Kishikawa Katsumi
Certificateは同じものを複数のアプリで使います。Revokeして作り直しても別に問題はありませんが、マシンを買い替えたとかでもなければ普通は期限が来るまでは使い続けます。
ご回答ありがとうございます。
Apple distributionはiOS distributionの上位互換なので新しく作るのならAppleを作ればいいです。
なるほどです把握できました。
Certificateは同じものを複数のアプリで使います。
ここは自分の認識がズレていました。 例えば岸川さんが既にApple distributionのCertificateAを作成済みで、それを用いてアプリAを開発していたとして 新たに私がアプリBを作ることになり、Apple distributionのCertificateが必要になった際に 新規でApple distributionのCertificateBを作成する必要があると解釈していましたが、この場合は岸川さんの作成した CertificateAをDeveloperのコンソールからダウンロードして使えば良いということであってますか? CertificateをDeveloperのコンソールで作成する際に、キーチェーンアプリから認証局?に問い合わせて作成した CertificateSigningRequest.certSigningRequest をアップロードして作成すると思うのですが このアップロードするファイルを作成する際に、メールアドレスを入力すると思うので 他人のメールアドレスで作成したCertificateを、他のアプリで他人が使って問題ないのかなと少し疑問に思いました。
Avatar
Avatar
飯塚
ご回答ありがとうございます。
Apple distributionはiOS distributionの上位互換なので新しく作るのならAppleを作ればいいです。
なるほどです把握できました。
Certificateは同じものを複数のアプリで使います。
ここは自分の認識がズレていました。 例えば岸川さんが既にApple distributionのCertificateAを作成済みで、それを用いてアプリAを開発していたとして 新たに私がアプリBを作ることになり、Apple distributionのCertificateが必要になった際に 新規でApple distributionのCertificateBを作成する必要があると解釈していましたが、この場合は岸川さんの作成した CertificateAをDeveloperのコンソールからダウンロードして使えば良いということであってますか? CertificateをDeveloperのコンソールで作成する際に、キーチェーンアプリから認証局?に問い合わせて作成した CertificateSigningRequest.certSigningRequest をアップロードして作成すると思うのですが このアップロードするファイルを作成する際に、メールアドレスを入力すると思うので 他人のメールアドレスで作成したCertificateを、他のアプリで他人が使って問題ないのかなと少し疑問に思いました。
(Apple Developer Program の) 同じ Team 内だったら Distribution 系証明書は使い回すもので、メールアドレスが違う人のものを使っても特に問題は起きないはずです (というか確か3枚までみたいな制限があるので、リリースビルドはCIにやらせるとかでない限り使い回さないと足りなくなってしまう)。 あと、developer.apple.comからのDLでは証明書しか落とせないので、秘密鍵ごとキーチェーンアクセス.appからエクスポートして共有する必要があります。 (edited)
Avatar
Avatar
rinsuki
(Apple Developer Program の) 同じ Team 内だったら Distribution 系証明書は使い回すもので、メールアドレスが違う人のものを使っても特に問題は起きないはずです (というか確か3枚までみたいな制限があるので、リリースビルドはCIにやらせるとかでない限り使い回さないと足りなくなってしまう)。 あと、developer.apple.comからのDLでは証明書しか落とせないので、秘密鍵ごとキーチェーンアクセス.appからエクスポートして共有する必要があります。 (edited)
ご回答ありがとうございます!
(Apple Developer Program の) 同じ Team 内だったら Distribution 系証明書は使い回すもので、
なるほどです納得できました! この辺りも恐らくちゃんと調べれば公式なドキュメントに明記されているはずですよね・・・? 皆さんある程度経験則もあるのかなと思いつつ、公式で記載されてるものも目を通さないとなと改めて思いました。
あと、developer.apple.comからのDLでは証明書しか落とせないので、秘密鍵ごとキーチェーンアクセス.appからエクスポートして共有する必要があります。
そうなのですねありがとうございます!
Avatar
うまく説明できるか自信はありませんが。 証明書は昔はiOSとmacOS毎でしたが、両方で動くようになったのでAppleというのが出てきました。 証明書はアプリを署名するためのもので、開発用は開発者毎、配布用は配布元を示すものなので、使いまわすべきもの。 例えば、村上がアプリAとアプリBをストアからリリースした場合、リリース元は村上ですので、村上の証明書で署名されるべきで、村上aや村上bが存在したら困っちゃう。という感じでしょうか。
Avatar
iOSでのカルーセルの実装はUIPageViewControllerを使用するのでしょうか? またはUICollectionViewやCompositionalLayoutsを使用しますか? はたまた上記以外で実装するのでしょうか?
Avatar
Kishikawa Katsumi 1/20/2023 4:27 AM
要件次第です。縦スクロールの画面に横スクロールが混ざる場合、CompositionalLayoutを使用するのが一番シンプルに書けます。ただCompositionalLayoutは横方向のスクロールビューに対する制御ができないので、自動で動かすとか、ループさせるとかボタンでも動かせるようにする、ページインジケータをつける、といった凝ったUIはできないです。 その場合は縦はCollection Viewでカルーセル部分はUIPageViewControllerを使用したりします。 UIPageViewControllerでもできない細かい制御をしたい場合はそれも使わずに自分でスクロールビューを組み合わせて作ったり、カルーセルのUIを提供する要件に一致するライブラリを探してもいいです。
t_kansha 1
Avatar
正方形のUIButtonのimageにalignment縦横fillで.circleを表示しているのですが、.circleの縁にそってクリッピング(縁より外の部分を消す)することは可能でしょうか? 単純にUIButtonをcornerRadiusを使って正円にするだけでは、.circleの縁の周りに余白が生まれるのでその余白を無くしたいです。
Avatar
目一杯広げたい時はUIImageViewをaddSubViewしちゃった方が勝手がいいかもしれないですね。
9:46 AM
と思ったけどSFSymbols自体にちょっとだけpaddingがあるのか…
9:47 AM
あくまで同じ見た目のものを自分が作るならcornerRadius + borderColorで作ると思います。
t_kansha 1
Avatar
NavigationBarは白のままで、ステータスバーだけを青にすることは可能でしょうか?
Avatar
ステータスバーのtintColorは基本的にはいじれなくて、interfaceStyleに合わせて白か黒に切り替わるだけですね
Avatar
Kishikawa Katsumi 2/3/2023 3:49 PM
ステータスバーの下にその色のビューをしく、っていうのがよくある解決方法だと思います。
Avatar
SwiftUIで@Stateの変数にdidSetを書くとおかしな動作になる(didSet内が呼ばれない)。という記事をちらほら見かけたのですが私の環境では正しく動作しました。古い記事なので今は使えるみたいなことありますでしょうか?下記コードは私の環境では正しく動作しているように見えます。 やりたいこととしては、 enum AlertType { case responseError, internetConnectionError, unknownError } @State private var alertType: AlertType = .responseError { didSet { isShowAlert.toggle() } } @State private var isShowAlert = false のようにalertTypeに代入するだけでアラートを表示するようにしたいです。 (edited)
Avatar
Avatar
udo223
SwiftUIで@Stateの変数にdidSetを書くとおかしな動作になる(didSet内が呼ばれない)。という記事をちらほら見かけたのですが私の環境では正しく動作しました。古い記事なので今は使えるみたいなことありますでしょうか?下記コードは私の環境では正しく動作しているように見えます。 やりたいこととしては、 enum AlertType { case responseError, internetConnectionError, unknownError } @State private var alertType: AlertType = .responseError { didSet { isShowAlert.toggle() } } @State private var isShowAlert = false のようにalertTypeに代入するだけでアラートを表示するようにしたいです。 (edited)
自分も理解できていなかったので今調べてみました。 @StateはdidSetだと全ての変更の際に呼ばれないため、@Stateの変更をトリガーにしたい場合は.onChangeを使うべきのようです。 alertType = .responseErrorではなく、alertType.wrappedValue = responseErrorのようにwrappedValueに直接変更を加えた時、wrappedValueはnonmutating setの値なのでdidSetは呼ばれません。Bindingした値を変更した時もwrappedValueが変更されるので同様です。 ここからは質問の回答とは逸れるのですが、 alertを表示していない時にもalertTypeに値が入っているのは違和感を感じたので、optionalにするかcaseにnoneを入れるのが良いかと思いました。 仮にoptionalにしたとして、今度は、alertが閉じられてshowAlertがfalseになった時にalertTypeをnilにしないといけないためshowAlertの変更を検知しないといけなさそうです。 それは冗長な気がするので、私はBinding時にこう書いてしまった方がわかりやすいと思いました。 Button { alertType = .responseError } label: { Text("アラート表示") } .alert( "alert", isPresented: .init( get: { alertType != nil }, set: { alertType = $0 ? alertType : nil } ), actions: {} ) 他の皆さんのご意見も聞いてみたいです。また、@Stateの解釈に誤りなどがありましたらご指摘いただけますと幸いです。
t_kansha 1
Avatar
Avatar
teeeeee
自分も理解できていなかったので今調べてみました。 @StateはdidSetだと全ての変更の際に呼ばれないため、@Stateの変更をトリガーにしたい場合は.onChangeを使うべきのようです。 alertType = .responseErrorではなく、alertType.wrappedValue = responseErrorのようにwrappedValueに直接変更を加えた時、wrappedValueはnonmutating setの値なのでdidSetは呼ばれません。Bindingした値を変更した時もwrappedValueが変更されるので同様です。 ここからは質問の回答とは逸れるのですが、 alertを表示していない時にもalertTypeに値が入っているのは違和感を感じたので、optionalにするかcaseにnoneを入れるのが良いかと思いました。 仮にoptionalにしたとして、今度は、alertが閉じられてshowAlertがfalseになった時にalertTypeをnilにしないといけないためshowAlertの変更を検知しないといけなさそうです。 それは冗長な気がするので、私はBinding時にこう書いてしまった方がわかりやすいと思いました。 Button { alertType = .responseError } label: { Text("アラート表示") } .alert( "alert", isPresented: .init( get: { alertType != nil }, set: { alertType = $0 ? alertType : nil } ), actions: {} ) 他の皆さんのご意見も聞いてみたいです。また、@Stateの解釈に誤りなどがありましたらご指摘いただけますと幸いです。
ご回答ありがとうございます! iOS13をサポートしていますのでonChangeは使えません。。。 .alert( isPresented: .init( get: { alertType != nil }, set: { alertType = $0 ? alertType : nil } ) ) { switch alertType { case .responseError: return Alert(title: Text("responseError", dismissButton: .default(Text("OK"))) case .internetConnectionError: return Alert(title: Text("internetConnectionError", dismissButton: .default(Text("OK"))) default: break } } このように書き換えてみましたが.alertではAlertを返さないといけないためbreakをすると当然ですがMissing return in closure expected to return 'Alert' のエラーになってしまいます。これの回避策があるということでしょうか?理解不足ですみません。。。
Avatar
Avatar
udo223
ご回答ありがとうございます! iOS13をサポートしていますのでonChangeは使えません。。。 .alert( isPresented: .init( get: { alertType != nil }, set: { alertType = $0 ? alertType : nil } ) ) { switch alertType { case .responseError: return Alert(title: Text("responseError", dismissButton: .default(Text("OK"))) case .internetConnectionError: return Alert(title: Text("internetConnectionError", dismissButton: .default(Text("OK"))) default: break } } このように書き換えてみましたが.alertではAlertを返さないといけないためbreakをすると当然ですがMissing return in closure expected to return 'Alert' のエラーになってしまいます。これの回避策があるということでしょうか?理解不足ですみません。。。
treastrain / Tanaka.R 2/13/2023 7:37 AM
質問の一部となってしまいますが…
iOS13をサポートしていますのでonChangeは使えません。。。
onChange(of: hogehoge) { ... }onReceive(Just(hogehoge)) { ... } とできる場合があるので、iOS 14 未満の場合はそちらで代替する…… という手段があります。 https://github.com/treastrain/TRETJapanNFCReader/blob/98c7b9051a6f3b86d04ab75a74c264d419b8434c/Sources/NativeTag/NFCNativeTagReaderViewModifier.swift#L86-L92
Avatar
Avatar
treastrain / Tanaka.R
質問の一部となってしまいますが…
iOS13をサポートしていますのでonChangeは使えません。。。
onChange(of: hogehoge) { ... }onReceive(Just(hogehoge)) { ... } とできる場合があるので、iOS 14 未満の場合はそちらで代替する…… という手段があります。 https://github.com/treastrain/TRETJapanNFCReader/blob/98c7b9051a6f3b86d04ab75a74c264d419b8434c/Sources/NativeTag/NFCNativeTagReaderViewModifier.swift#L86-L92
ありがとうございます! これは試していたのですが、 enum AlertType { case hoge, fuga, piyo } @State private var alertType: AlertType = .hoge @State private var isShowAlert = false --- Button { alertType = .fuga } label { Text("アラート表示") } .onReceive(Just(alertType)) { isShowAlert.toggle() } 上記のようなコードを書いていたのですが、この画面に遷移するタイミングで画面が固まってしまい原因が分からず諦めておりました。
👀 1
Avatar
Avatar
udo223
ありがとうございます! これは試していたのですが、 enum AlertType { case hoge, fuga, piyo } @State private var alertType: AlertType = .hoge @State private var isShowAlert = false --- Button { alertType = .fuga } label { Text("アラート表示") } .onReceive(Just(alertType)) { isShowAlert.toggle() } 上記のようなコードを書いていたのですが、この画面に遷移するタイミングで画面が固まってしまい原因が分からず諦めておりました。
treastrain / Tanaka.R 2/13/2023 7:55 AM
なるほどです… 私も同様のコードを書いてみましたが、 onReceive によって print は実行されたので、その箇所に限っては 特に問題はなさそうに見えます……。 (はじめ、body の一番外側の View ではなく Button の modifier としてしまっているからでは?と思いましたが、そこは問題ではなさそうでした。)
Avatar
Avatar
treastrain / Tanaka.R
なるほどです… 私も同様のコードを書いてみましたが、 onReceive によって print は実行されたので、その箇所に限っては 特に問題はなさそうに見えます……。 (はじめ、body の一番外側の View ではなく Button の modifier としてしまっているからでは?と思いましたが、そこは問題ではなさそうでした。)
私の手元でもprint は実行されます。しかしisShowAlert.toggle() に書き換えた途端に動かなくなってしまいますね。。。
👍 1
8:11 AM
そもそもenumの値が変わったらisShowAlert.toggle() しようとするのが間違いなんですかね。。。
8:15 AM
複数アラートをenumで持ってるのでその度にtoggle()を呼ぶのは冗長だと思いtoggle()を1箇所で呼ぼうと考えています。 今は、 Button { showAlert(type: .hoge) } label { Text("hogeアラート表示") } private func showAlert(type: AlertType) { alertType = type isShowAlert.toggle() } のように関数にしています。
Avatar
SwiftUIの部品の分割についてなのですが、1ファイル1部品だとファイル数が膨大になると思うのですが、その場合はある程度関係する部品(同一画面など)で1ファイルにまとめたりするものでしょうか?
Avatar
Kishikawa Katsumi 2/19/2023 5:37 AM
好みですね。ファイル数が増えるといってもiOSアプリ程度ならたかがしれてるので細かくファイルをわけてもいいですし、まとめたほうが把握しやすいならまとめます。
t_kansha 1
Avatar
[connection] nw_connection_add_timestamp_locked_on_nw_queue [C4] Hit maximum timestamp count, will start dropping events 動作確認をしているとデバックエリアに上記のメッセージが表示されたのですが、ネットで調べても情報が出てきませんでした。もし何か分かる方いましたらご教示いただけると助かります。 上記が出た経緯は下記のようにDelegateをバケツリレーのように渡すようにしたら出るようになりました。 protocol HogeDelegate { func hoge() } struct CellView: View { let delegate: HogeDelegate Button { delegate.hoge() } } final class Cell: UITableViewCell { init(delegate: HogeDelegate) { let vc = UIHostingController(rootView: CellView(delegate: delegate) } } final class ViewController: UITableViewDataSource, HogeDelegate { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = Cell(delegate: self) return cell } func hoge() {} } (edited)
Avatar
こちらのAppleMusicの様な完全フルスクリーンのモーダル画面を実装する方法ってありますか? ご存知の方がいましたらご教示お願いします。 (edited)
Avatar
Kishikawa Katsumi 3/2/2023 10:03 PM
Modalの画面遷移アニメーションをUIViewControllerAnimatedTransitioningとUIPercentDrivenInteractiveTransitionを使ってカスタマイズする、というのが良くやる方法です。 https://thorntech.com/ios-tutorial-close-modal-dragging/ ^ これが基本形で、 https://qiita.com/keisei_1092/items/1a4e22a189c2c5dfdf7c ^ NavigationControllerがある場合、 https://qiita.com/trueSuperior/items/59c971042440393baf99 ScrollViewがある場合、 とこの辺りを参考にして実装できると思います。
Ever since iOS 7, users have been swiping from the left edge of the screen to go back. This swipe-back feature is interactive, so the animation tracks as
UIKitでは、ViewController→ViewControllerの遷移をカスタムできます。 上の画像のようにボタンを押すと下から出てきて 引っ張ると閉じることができるモーダルを実装してみます。 当初こちらのチュート...
ごきげんよ〜 ( ∴ )/ ぼくたちのスマホのディスプレイが巨大化していく一方で、モーダルウィンドウの上部に配置されがちなもどるボタンはユーザーの指からどんどん離れていってます。モーダルウィンドウは閉じて本来の作業に戻ることが目的であ...
t_naruhodo 1
Avatar
UITableViewDataSourceのcellForRowAt内でUIHostingControllerを使ってSwiftUIで作ったViewをCellに表示した場合、iOS16未満だとスクロール時にレイアウトが崩れるのですがワークアラウンドご存知の方いましたらご教示お願いいたします。 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") let hostingController = UIHostingController(rootView: SwiftUICellView()) cell.contentView.addSubview(hostingController.view) hostingController.view.translatesAutoresizingMaskIntoConstraints = false [ hostingController.view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor), hostingController.view.topAnchor.constraint(equalTo: cell.contentView.topAnchor), hostingController.view.leftAnchor.constraint(equalTo: cell.contentView.leftAnchor), hostingController.view.rightAnchor.constraint(equalTo: cell.contentView.rightAnchor) ].forEach { $0.isActive = true } return cell } (edited)
Avatar
UIHostingControllerはUIViewControllerなので、viewだけ取り出して使う、というのは不安定になるかと思います。iOS14以降であれば、UIHostingConfigurationが使えるので、そちらの利用を試してみて下さい
Avatar
Avatar
tarunon
UIHostingControllerはUIViewControllerなので、viewだけ取り出して使う、というのは不安定になるかと思います。iOS14以降であれば、UIHostingConfigurationが使えるので、そちらの利用を試してみて下さい
ありがとうございます! そうなんですね...iOS13をサポートしているので諦めるか😭
Avatar
原因の切り分けはすると良いかなと思います。 一旦、iOS14以降でだけレンダリング可能なCellということにして、UIHostingConfigurationの実装を試す -> うまくいけば、UIHostingControllerの接続がうまくいっていない -> うまくいかなければ、SwiftUICellViewの実装に問題がある うまくいくのであれば、UIHostingControllerの接続部分をちゃんと書くのも手かもしれないです。
t_kansha 1
Avatar
shimastripe 3/3/2023 3:49 AM
UIContentConfiguration ですかね? ( UIHostingConfiguration は iOS 16 からのやつじゃないかと......!! ) https://developer.apple.com/documentation/uikit/uicontentconfiguration https://developer.apple.com/documentation/SwiftUI/UIHostingConfiguration
Avatar
ああ、混ざってた。すみません
3:58 AM
UIContentConfigurationで、あってます
🙏 1
Avatar
Avatar
Kishikawa Katsumi
Modalの画面遷移アニメーションをUIViewControllerAnimatedTransitioningとUIPercentDrivenInteractiveTransitionを使ってカスタマイズする、というのが良くやる方法です。 https://thorntech.com/ios-tutorial-close-modal-dragging/ ^ これが基本形で、 https://qiita.com/keisei_1092/items/1a4e22a189c2c5dfdf7c ^ NavigationControllerがある場合、 https://qiita.com/trueSuperior/items/59c971042440393baf99 ScrollViewがある場合、 とこの辺りを参考にして実装できると思います。
返信ありがとうございます。 iOS標準のpresentモーダルは奥の画面が上にくっついてるのではなく、少し浮いてるようなデザインになってると思います。これでmodalPresentationStyleをfullscreenにするとその浮いてるような状態ではなくなり画面全体にくっついてるようになってしまいます。 ですがAppleMusicの場合はフルスクリーンでもその仕様になっています。これと同じような作りの画面を実装したいのですが、これって公開されていないのでしょうか。
Avatar
Kishikawa Katsumi 3/4/2023 9:37 AM
標準のAPIにはないですね。上記のTransition Animationで奥のビューを少し縮小する効果を足す感じでできます
Avatar
Kishikawa Katsumi 3/4/2023 9:59 AM
結局カスタムのトランジションを実装する必要があるので、とりあえず記事を参考にモーダルを実装してみてそこに縮小の効果を付ける、とやってみるといいんじゃないでしょうか。
t_naruhodo 1
Avatar
Avatar
Kishikawa Katsumi
結局カスタムのトランジションを実装する必要があるので、とりあえず記事を参考にモーダルを実装してみてそこに縮小の効果を付ける、とやってみるといいんじゃないでしょうか。
わかりました。ちょっと大変そうですが試行錯誤してみます!ありがとうございます。
Avatar
Assets.xcssetsのColor Setをリネームしても差分が出ないのですがそういうものなのでしょうか?新しく作り直すしかないでしょうか?
Avatar
Kishikawa Katsumi 3/7/2023 4:07 AM
実際のディレクトリを見てみてXXX.colorset の名前は変わってますか?
Avatar
大文字から小文字場合だと差分でないかもです。
Avatar
そもそもmacOSのファイルシステムはデフォルトだとcase insensitiveですよね
Avatar
Avatar
Kishikawa Katsumi
実際のディレクトリを見てみてXXX.colorset の名前は変わってますか?
フォルダ名は変わってるのですが差分に出てこないという感じですね。
6:12 AM
新しく作りなおす対応を取りました🙇‍♂️
Avatar
Kishikawa Katsumi 3/7/2023 6:14 AM
フォルダ名がちゃんと変わってるなら名前がgitignoreにたまたま当たるような設定になっているとかそんな感じじゃないかと思います。Gitの方の問題ですね。 git statusしても何も出てこないですか? (edited)
🙇‍♂️ 1
Avatar
1画面だけNavigationBarを他より高く見せるためにNavigationBarの下に同色のUIViewを表示するやり方は良いのでしょうか?意図した表示にはなってるのですがやり方として適切かどうかお聞きしたいです🙇‍♂️
Avatar
Kishikawa Katsumi 3/12/2023 6:38 AM
Demonstrates how to use the UINavigationController and UIViewController classes as building blocks to your application's user interface.
👀 1
6:38 AM
^ このサンプルコードは今はなんか不完全な状態になってしまっていますが。
Avatar
Avatar
Kishikawa Katsumi
ありがとうございます! これってnavigationBarにUIViewを代入して高く見せてるということでしょうか? 私の言う下とは重なり的な下ではなくそのままNavigationBarの下と言うことでした🙇‍♂️ storyboardの一番上にUIViewを追加するイメージです🙇‍♂️
Avatar
Kishikawa Katsumi 3/12/2023 7:23 AM
私の言う下とは重なり的な下ではなくそのままNavigationBarの下と言うことでした
^ こちらですね。Appleのサンプルでは自然に見せるためにもともとの透過をなしに、下部の境界線(shadowImage)を削除、追加したビューにもともとのNavigation Barにあったような1ピクセルの境界線を追加、のようにして見た目を整えるテクニックが示されていました。
Avatar
なるほど!このやり方で良いということですね!ありがとうございます!🙇‍♂️
Avatar
Kishikawa Katsumi 3/12/2023 7:47 AM
このサンプルに関しては、おおっと思って見に行ったらビューをそれらしく見せてるだけだったのがすごく衝撃だったのでよく覚えてます。
t_kami 1
Avatar
Swiftのフォントサイズの単位て決まってたりしますでしょうか?pxにしては小さくないか?と思いました。気のせいであればすみません。。。 -> ptなんですね。そしてpt == pxでは無いのですね。pxをptに計算しなおして使うのでしょうか?それとも大体pxにプラスしてpt指定するものなんでしょうか? (edited)
Avatar
新規のプロジェクトであれば、強い理由がなければ直接フォントサイズの指定はせずにTextStyleに則るのがおすすめです。 https://developer.apple.com/documentation/uikit/uifont/textstyle (edited)
Constants that describe the preferred styles for fonts.
t_kansha 1
7:59 AM
DynamicTypeのサポートとか後で考え始めるとそれはそれは面倒なので、可能ならUIKit標準の仕組みに乗っかって楽をしたいところですね (edited)
Avatar
px単位でUIをレイアウトする時代は随分前に終わりましたね
t_kansha 1
8:19 AM
ラベルの大きさは常に変化しうるため、それに依存しない実装やデザインにする必要があります
8:20 AM
例えばOSのマイナーアップデートでも変化します
Avatar
iOSにおける1ptが何ピクセルに相当するかは状況によって異なります。 それぞれの機種のディスプレイの解像度によって1pt=2pxだったり1pt=3pxだったりします。 https://qiita.com/eKushida/items/ff1ecaacdb54ce7f9f5c よってiOSのデザインではサイズはpxではなくptで考えることになると思います。 ただtarunonさんやIcemanさんがおっしゃるとおり、厳密なpt数でレイアウトを組むのはあまりおすすめできません。 年々iPhoneの画面サイズのバリエーションは増えており、iPhone 5とiPhone 14 Pro Maxでは縦のpt数が568と932と1.6倍以上の差があるためです。 いわゆるレスポンシブデザインの考えが必要になるでしょう。 (edited)
t_kansha 1
Avatar
Dynamic Typeは開発者がフォントサイズを直接指定していると無効化されてしまい、UXを損なう原因にもなります。
Avatar
UIViewPropertyAnimatorについての質問があります。 こちらのコードでアニメーションが再生終了してから逆再生ボタンを押して逆再生させたいのですが、うまくいきません。何が問題なのでしょうか。 animator = UIViewPropertyAnimator(duration: 2, curve: .easeIn) { self.animationView.transform = CGAffineTransform(scaleX: 2.0, y: 2.0) } } @objc func startAnimation() { animator?.isReversed = false animator?.startAnimation() } @objc func reverseAnimation() { animator?.isReversed = true animator?.startAnimation() }
Avatar
Kishikawa Katsumi 3/16/2023 10:14 AM
pausesOnCompletiontrueにしてみてください。
Avatar
@Kishikawa Katsumi ありがとうございます、動きました。 これってpausesOnCompletionをtrueにするとaddCompletionが呼ばれなくなると思うんですけど、addCompletionも動く様にしつつ、後から逆再生する方法ってないでしょうか。 拡大したViewを、そのまま置いといて後で逆再生したいです。
Avatar
Kishikawa Katsumi 3/16/2023 5:21 PM
なるほど、そういうことですか。1つのanimatorをずっと使うやり方だと無理なので毎回作り直すのがいいんじゃないでしょうか。
Avatar
classのData型の初期化について質問させてください。 var string: String = "" var int: Int = 0 var bool: Bool = false var data: Data = Data() Data型に初期値をもたせる場合はData()で良いのでしょうか? それともvar data: Data? でoptionalにすべきでしょうか?
Avatar
Avatar
udo223
classのData型の初期化について質問させてください。 var string: String = "" var int: Int = 0 var bool: Bool = false var data: Data = Data() Data型に初期値をもたせる場合はData()で良いのでしょうか? それともvar data: Data? でoptionalにすべきでしょうか?
どのような初期値を持たせたいかによりますね。 var data: Data = Data() と書くと、 0 バイトのバイト列を表す Data インスタンスとして初期化されます。
3:02 AM
たとえば、 0 バイトのバイト列を作って、これからそのバイト列にデータを書き込んで行きたい場合は、 Data 型にして Data() を初期値で持たせるのが良いと思います。
3:02 AM
一方で、これから Data 型を値を代入したいけど、今はまだデータが存在しないことを示したいなら Data? 型にして nil で初期化するのが良いと思います。
3:03 AM
(あと、余談気味ですが、 Data はクラスではなく struct ですね。 https://developer.apple.com/documentation/foundation/data
Avatar
Avatar
koher
どのような初期値を持たせたいかによりますね。 var data: Data = Data() と書くと、 0 バイトのバイト列を表す Data インスタンスとして初期化されます。
ありがとうございます! 必ず何か書き込むのでDataにしたいですが、data = try! Data(contensOf: hogeURL) のようにtry!になるのが怖いというのがあります。ただData?だと取り出す時にやや面倒だなと思いました。ただ安全側に倒すならData?にしたほうが安全ではありそうですかね。
Avatar
Avatar
udo223
ありがとうございます! 必ず何か書き込むのでDataにしたいですが、data = try! Data(contensOf: hogeURL) のようにtry!になるのが怖いというのがあります。ただData?だと取り出す時にやや面倒だなと思いました。ただ安全側に倒すならData?にしたほうが安全ではありそうですかね。
エラーハンドリングしたいということであれば、↓のようにするのがいいかもしれません。 do { let data = try Data(contensOf: hogeURL) // data を使う処理 } catch { // エラーハンドリング } catch の中では error にアクセスすることで、エラー情報を取得することができます。 try? にしてしまうとエラー情報が失われてしまい、原因を特定したり、原因によってエラーハンドリングの仕方(アラートを表示する、リトライする、無視してログ出力するなど)を変更することもできなくなってしまいます。 (edited)
t_kansha 1
3:18 AM
また、 Swift ではエラーの意味で nil が返されるメソッド等が存在はしますが(たとえば String(data: data, using: .utf8) など)、エラーの意味で返された nil をそのまま保持し続けるのも望ましくありません。 エラーが throw されるのではなく nil が返されるケースは、原則としてエラーの原因が自明な場合です( String(data: data, using: .utf8) なら、 UTF-8 として解釈できないバイト列が渡された場合)。その場でエラーハンドリングすれば原因がわかりますが、持ち続けてしまうとどこから nil が混入したのかわからなくなり、原因を究明するのが困難になります。エラーとして nil が返される場合には、↓のように即座にエラーハンドリングするのが望ましいです。 guard let string = String(data: data, using: .utf8) else { // エラーハンドリング( data が UTF-8 として解釈できない場合) } // string を使う処理 (edited)
t_naruhodo 1
Avatar
Avatar
Kishikawa Katsumi
なるほど、そういうことですか。1つのanimatorをずっと使うやり方だと無理なので毎回作り直すのがいいんじゃないでしょうか。
つまり再利用することは不可能なので再生するたびに作成するのがいいということでしょうか。
Avatar
Kishikawa Katsumi 3/17/2023 3:42 AM
そうです。
t_naruhodo 1
Avatar
UIContentConfigurationを使ったUICollectionViewListCellについて質問があります。 iPhone標準のShortcutアプリ、ショートカット一覧画面の選択モード時の、「振動する、右上のボタンが選択アイコンに変わる」というセルの挙動を再現したいと思っています。 初めはViewControllerで編集モードのボタンを押した際にcollectionView.indexPathsForVisibleItems.forEachで見えている範囲に振動のアニメーションを適用したのですが、再利用されたcellでは当然ですがアニメーションはしませんでした。 この再利用されたセルにアニメーションを与えるためにcollectionViewのisEditingをUIContentConfigurationに渡して、UIContentView側でその変更を見てCAKeyframeAnimationを追加(削除)できないものかと思いましたがcellRegistrationだとcollectionViewを参照できないため渡せませんでした。 CollectionViewの選択モードをUICollectionViewListCellに伝える方法としてUIContentConfigurationは適当ではないんでしょうか。適当でないとすればこれを使う、などキーワードだけでも有難くそこから調べていきますのでご教授いただけると幸いです。 内容が意味不明だったらすみません…
Avatar
Kishikawa Katsumi 4/15/2023 1:16 AM
collectionViewをプロパティに持つなどすればcellRegistrationの中から参照できると思いますが何かそのようにできないような状況ですか?
1:18 AM
class MainViewController: UIViewController, UICollectionViewDelegate { ... @IBOutlet private var collectionView: UICollectionView! // <= プロパティで持つ private var dataSource: UICollectionViewDiffableDataSource<Int, Status>! override func viewDidLoad() { super.viewDidLoad() ... let cellRegistration = UICollectionView.CellRegistration<DeviceCell, Status>(cellNib: UINib(nibName: "DeviceCell", bundle: nil)) { (cell, indexPath, item) in ... self.collectionView ... // <= ここでプロパティのcollectionViewを参照する ... ^ たいていはこんな感じじゃないかと思います。 (edited)
t_kansha 1
Avatar
ありがとうございます。自分のコードの問題点がわかりました。cellRegistrationとdataSourceをStored propertyにしていたのが直接の問題だったことですね、サンプルがみんなStored propertyにしていたので、何も考えずお作法的にしてしまってました。 参考コードありがとうございます、助かりました。(以下参考にもならないですが、こう書いてました) class ListViewController: UIViewController { // MARK: IBOutlet @IBOutlet private weak var collectionView: UICollectionView! let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell,GameEntity>{ (cell, indexPath, item) in var contentConfiguration = cell.customGameContentConfiguration() contentConfiguration.isEditing = self.collectionView.isEditing //<- selfにアクセスできない cell.contentConfiguration = contentConfiguration } lazy var dataSource = UICollectionViewDiffableDataSource<Section, GameEntity>(collectionView: collectionView, cellProvider: { [unowned self] (collectionView, indexPath, item ) in return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item) }) override func viewDidLoad() { super.viewDidLoad() } ...
Avatar
アプリの配信についてお聞きしたいのですが、輸出コンプライアンスの対応ってどこまでやるべきなのでしょうか。色々調べていると一般的なアプリ(HTTPS通信)はこれに該当するので年次自己分類報告書を作成して指定の機関に送る必要があると認識しているのですがあっていますか。ネットで調べてもあまり情報もなく、やらなくても審査には影響しないという認識のためどこまで徹底するべきなのか悩んでいます。詳しい方がいましたらご教示ください。 https://fortee.jp/iosdc-japan-2019/proposal/a972c654-1928-47e7-ba2a-24eb5152fecc
iOSアプリを審査に提出するときに回答が必要となる「輸出コンプライアンス情報」についての質問。あなたは毎回、正しく理解して最適な答えを選ぶことが出来ている、と胸を張って言えますか? HTTPSも暗号化に含まれるの?暗号化を使用しているけれど、EAR(米国輸出管理規則)の免除資格を満たしているか曖昧だ、など不安を抱えながら回答している、という方もいらっしゃるのではないでしょうか。 本トークでは5分間でフローチャートを交えながらこの「輸出コンプライアンス情報」にあなたのアプリがどう回答するべきなのかを説明します。このトークさえしっかり聞けば、明日以降のiOSアプリの申請では自信を持って「輸出コンプライアンス情報」に回答することができるようになるでしょう。
Avatar
Avatar
Ryota
アプリの配信についてお聞きしたいのですが、輸出コンプライアンスの対応ってどこまでやるべきなのでしょうか。色々調べていると一般的なアプリ(HTTPS通信)はこれに該当するので年次自己分類報告書を作成して指定の機関に送る必要があると認識しているのですがあっていますか。ネットで調べてもあまり情報もなく、やらなくても審査には影響しないという認識のためどこまで徹底するべきなのか悩んでいます。詳しい方がいましたらご教示ください。 https://fortee.jp/iosdc-japan-2019/proposal/a972c654-1928-47e7-ba2a-24eb5152fecc
Kishikawa Katsumi 4/19/2023 12:43 PM
輸出コンプライアンスの話は法律の分野なのでなかなか答えるのが難しいためちょうど #ask-to-apple チャンネルができたのでもう一度そちらで聞いてみると適切な案内がされるのではないでしょうか?
apple_rainbow 1
t_arigatou 1
Avatar
Swiftのprotocolのfuncデフォルト実装で、変数をプロトコル型として使用したときに、デフォルト実装に引っ張られてしまうのって防げないでしょうか? protocol SomeProtocol { } extension SomeProtocol { func somePrint() { print("First") } } struct SomeModel: SomeProtocol { func somePrint() { print("Second") } } let someModel: some SomeProtocol = SomeModel() someModel.somePrint() // First
Avatar
omochimetaru 5/6/2023 10:13 AM
protocolのrequirementsにsomePrintを定義するとSecondになりませんか? そのコードだと、二つのsomePrintは特に関連のない別のエントリになっています
Avatar
protocolのrequirementsというのはextensionではなく、宣言?した時の方ということでしょうか?
Avatar
omochimetaru 5/6/2023 10:16 AM
はい、そうです。
Avatar
protocolのrequirementsにはデフォルト実装ができないという認識だったので、extensionにだけ書けばいいと思っていたのですが、extensionのみだと関連性を持つことができないのですね。ありがとうございます! 教えてくださったrequirementsにsomePrint()を追加することでSecondとprintすることができました! protocol SomeProtocol { func somePrint() } extension SomeProtocol { func somePrint() { print("First") } } struct SomeModel: SomeProtocol { func somePrint() { print("Second") } } let someModel: some SomeProtocol = SomeModel() someModel.somePrint() // Second
Avatar
omochimetaru 5/6/2023 10:24 AM
そうです。 そのようにrequirementsがあって初めて、protocolのextensionや、structにおける同名のfuncエントリが、「プロトコルのメソッドを実装している」事になります。 知らないとハマるポイントですね〜
❤️ 1
Avatar
見逃すとこだったのでハマっといてよかったです。ありがとうございます!
🙆‍♂️ 2
Avatar
Objective-Cのコールバック関数が自動でasync functionに変換される機能について質問です。 https://github.com/apple/swift-evolution/blob/main/proposals/0297-concurrency-objc.md 以下のようにObjective-Cで、メインスレッドかどうか確かめる文を含めたコールバック関数を作成し // MyClass.h #import <Foundation/Foundation.h> @interface MyClass : NSObject - (void)callbackWithCompletion:(void (^)(void))completion; @end // MyClass.m #import "MyClass.h" @implementation MyClass - (void)callbackWithCompletion:(void (^)(void))completion { NSLog(@"%d", [NSThread isMainThread]); // メインスレッドかどうか確かめる if (completion) { completion(); } } @end 以下のようにSwiftで呼び出しました // main.swift import Foundation Task { @MainActor in let myclass = MyClass() await myclass.callback() } RunLoop.main.run(until: Date(timeIntervalSinceNow: 10)) // 出力 1 通常のasync関数はMainActorで await hogeAsync() と呼び出してもhogeAsync の中身は MainActorで実行されない と思いますが 今回の callback はMainActorで await myclass.callback() と呼び出すと、callback の中身も MainActorで実行されている みたいでした つまり、このConcurrency Interoperability with Objective-C は 「シンタックス上の機能だけで、特別な処理(Objective-CのコールバックをSwiftのasyncに内部的に対応させる等)は行なっていない」 という理解であってますでしょうか? (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0297-concurrency-objc.md at main · apple/swift-evolution
Avatar
おお、面白い挙動ですね。ちなみにこれって Task { let myclass = MyClass() await myclass.callback() } としてMainActor指定を外して実行すると[NSThread isMainThread]はNOになるのでしょうか?
Avatar
はい、NOになりました
12:06 PM
経緯としては、使っているObjective-Cのライブラリにコールバック関数があり それがConcurrency Interoperability with Objective-C によってasync functionになっていたので使いたいのですが 元々「メインスレッドで呼ぶように」という注意があったので試しに Task { @MainActor in await callback() } というコードを書いたら動いたので、「なんだこれ...気持ち悪い...」となりました (edited)
Avatar
面白いですね。通常async関数の呼び出しを同期で行えるのはwithCheckedContinuation系統くらいですが、こんな裏技があったとは。
Avatar
新たな黒魔術w
Avatar
このへんは わいわいswiftc #22 で取り上げられていたので、当時の議論などから現在のコードを追えば具体的な挙動がわかるかもしれません (edited)
😻 1
12:17 PM
# わいわいswiftc #22 オンライン 昨今の社会的情勢を鑑みて、当面はオンライン開催を致します。 swift-developers-japanのDiscordサーバー上でオンライン配信を行う予定です。 https://medium.com/swift-column/discord-ios-20d586e373c0 詳細な参加方法については、下記をご覧ください。 # わいわいswiftc わいわいswiftcは、Swift Compilerとその周辺技術に関する勉強会です。初心者・上級者を問わず、情報交換とディスカッションの場として機能することを目的としています。 s...
Avatar
ありがとうございます!見てみます
Avatar
あんまり詳しくないので完全に追えてないんですが ASTをいじってるだけで特別なことはやってないように見えます https://github.com/apple/swift/pull/33674 「Concurrency Interoperability with Objective-Cはただのシンタックシュガー」という仮定の上で アドバイスとしてどなたかにお聞きしたいんですが メインスレッドからの呼び出しが必須で(そうでないとクラッシュする) Objective-Cで書かれたライブラリの関数 : application.acquireToken()があった時 asyncなのにMainActorが伝播するこの仕様を意図的に使う選択をどう思われますか? (自分だったら使わない、くらいの感想で良いので聞かせていただけたら) 「変な」挙動を使う危険性 vs 可読性 実際のコードは↓みたいな感じで、ログイン画面の起動です (ユーザーが6-7000人くらいいるリリースしているサービスで、ここが壊れると致命傷ではあります) // 既存の書き方 public func signInA() async throws -> AuthResult { try await withCheckedThrowingContinuation { continuation in Task { @MainActor in application.acquireToken() { result, error in if let error = error { continuation.resume(throwing: self.createError(from: error)) return } if let result = result { continuation.resume(returning: .init(accessToken: result.accessToken)) return } continuation.resume(throwing: AuthError.unknown) } } } } // asyncへの自動変換を使った書き方 @MainActor public func signInB() async throws -> AuthResult { try await application.acquireToken() } (edited)
When a given Objective-C method has a completion handler parameter with an appropriate signature, import that Objective-C method as async. For example, consider the following CloudKit API:
  • (void)...
Avatar
関数にMainActorをつけておくこと自体は、Mainスレッドでの呼び出しを強制する意図なら特に問題ないような…? 強いて言えばacquireToken()自体もMainActorになってると良いんじゃないかと思いました。 Objective-Cを経由して同期的に〜とかは避けた方が良いかな、という感覚です
Avatar
すみません、説明不足でした acquireToken()がObjective-Cのライブラリの関数で、自動でasync関数化されています ここでMainActorをつけているのは、主にpplication.acquireToken() にMainActorContextを引き継がせる意図でした。 (普通のasync関数は引き継がないけど、自動でasync化された関数は引き継ぐ仕様があるから、それを意図的に使っていいのか、という懸念です) @MainActor public func signInB() async throws -> AuthResult { try await application.acquireToken() } (edited)
Avatar
明示的なActorの指定が無い関数に関しては実行されるスレッドはコンパイラの気持ち次第なので、基本的に保証されないと考えるほうが安全だと思います。
🙇‍♂️ 1
4:54 PM
Objective-Cのメソッドに対して明示的なActorを付ける方法としてこういう書き方があります。 #define MAIN_ACTOR __attribute__((__swift_attr__("@MainActor"))) @interface MyClass : NSObject - (void)callbackWithCompletion:(void (^)(void))completion MAIN_ACTOR; @end
t_naruhodo 1
4:55 PM
ただ、これは若干ClangImporterが怪しくて、completionの自動async化と組み合わせたときにActorの指定が無視されてそうな動きをしています。
4:58 PM
なので、恒久的に挙動を保証する場合、@MainActor な関数の下でacquireToken をコールバックを取る同期関数として呼び出す書き方であれば意味を漏れなく記述できると思います。
👍 1
Avatar
ただ、これは若干ClangImporterが怪しくて、completionの自動async化と組み合わせたときにActorの指定が無視されてそうな動きをしています。
ありがとうございます、バグの可能性もあるって感じなんですね、それなら使う選択肢はないかなと自分でも思いました
Avatar
Avatar
kntk
あんまり詳しくないので完全に追えてないんですが ASTをいじってるだけで特別なことはやってないように見えます https://github.com/apple/swift/pull/33674 「Concurrency Interoperability with Objective-Cはただのシンタックシュガー」という仮定の上で アドバイスとしてどなたかにお聞きしたいんですが メインスレッドからの呼び出しが必須で(そうでないとクラッシュする) Objective-Cで書かれたライブラリの関数 : application.acquireToken()があった時 asyncなのにMainActorが伝播するこの仕様を意図的に使う選択をどう思われますか? (自分だったら使わない、くらいの感想で良いので聞かせていただけたら) 「変な」挙動を使う危険性 vs 可読性 実際のコードは↓みたいな感じで、ログイン画面の起動です (ユーザーが6-7000人くらいいるリリースしているサービスで、ここが壊れると致命傷ではあります) // 既存の書き方 public func signInA() async throws -> AuthResult { try await withCheckedThrowingContinuation { continuation in Task { @MainActor in application.acquireToken() { result, error in if let error = error { continuation.resume(throwing: self.createError(from: error)) return } if let result = result { continuation.resume(returning: .init(accessToken: result.accessToken)) return } continuation.resume(throwing: AuthError.unknown) } } } } // asyncへの自動変換を使った書き方 @MainActor public func signInB() async throws -> AuthResult { try await application.acquireToken() } (edited)
すごく細かいんですが、TaskでMainActorを指定するより、signInA 自体に @MainActorを付けるほうが無駄なスイッチが減ります。
Avatar
ありがとうございます!!
Avatar
import APIKit class HogeViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let request = HogeRequest() Session.send(request) { result in switch result { case .success(_): print("success") case .failure(_): print("failure") } } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) Session.cancelRequests(with: HogeRequest.self) } } 通信中に画面を離れるタイミングでキャンセルしたいのですが、うまく動作せず通信成功してしまいます。 原因が全くわかりません。 どこかおかしいところありましたらご教示頂けると助かります🙇‍♂️ https://github.com/ishkawa/APIKit/blob/master/Documentation/GettingStarted.md#canceling-request (edited)
Type-safe networking abstraction layer that associates request type with response type. - APIKit/GettingStarted.md at master · ishkawa/APIKit
Avatar
Avatar
udo223
import APIKit class HogeViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let request = HogeRequest() Session.send(request) { result in switch result { case .success(_): print("success") case .failure(_): print("failure") } } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) Session.cancelRequests(with: HogeRequest.self) } } 通信中に画面を離れるタイミングでキャンセルしたいのですが、うまく動作せず通信成功してしまいます。 原因が全くわかりません。 どこかおかしいところありましたらご教示頂けると助かります🙇‍♂️ https://github.com/ishkawa/APIKit/blob/master/Documentation/GettingStarted.md#canceling-request (edited)
omochimetaru 5/26/2023 8:02 AM
まず確認したいのは viewWillDisapper が本当に呼び出されているかどうかですね。 それは確認できていますか? その上で、 Session のコードを見ないと判断できないですね (edited)
Avatar
Avatar
omochimetaru
まず確認したいのは viewWillDisapper が本当に呼び出されているかどうかですね。 それは確認できていますか? その上で、 Session のコードを見ないと判断できないですね (edited)
viewWillDisappearは呼び出されています。 override func viewDidLoad() { super.viewDidLoad() let request = HogeRequest() Session.send(request) { result in switch result { case .success(_): print("success") case .failure(_): print("failure") } } Session.cancelRequests(with: HogeRequest.self) } 試しに上記にしてみたらリクエストしてすぐにキャンセルできました。 (edited)
Avatar
omochimetaru 5/26/2023 8:12 AM
なるほど。 うまく動かないとしたら、原因は Session.sendSession.cancelRequests の実装次第だと思います。
Avatar
Avatar
omochimetaru
なるほど。 うまく動かないとしたら、原因は Session.sendSession.cancelRequests の実装次第だと思います。
もうちょっと調べたいと思います。 ありがとうございます🙇
Avatar
APIKitやURLSessionについて詳しい方おられましたらご教示お願い致します🙇‍♂️ 画面AのviewDidLoad()で Session.send(ARequest()) した後、通信中の状態ですぐに画面Bに遷移してviewDidLoad()で Session.send(BRequest()) すると、ARequestのレスポンスを待ってBRequestが送信される?のですが、 待たずにBRequestのレスポンスが欲しいため、試しに画面Aを let adapter = URLSessionAdapter(configuration: .default) Session(adapter: adapter).send(ARequest()) とすると、2つ同時に通信してくれるようになりました。 ただ、なぜこうなるのかがいまいち理解できません。 URLSessionがマルチスレッド?並列?に処理してくれているのでしょうか。
Avatar
omochimetaru 6/4/2023 4:32 PM
まず、 URLSession は同時に複数の通信を行う事ができます。 ただ、そのコードがどのように動くかは、 その URLSessionAdapterSession の実装次第です。 それらは iOS SDK のクラスではないのでコードを見ないとわかりません。 APIKit で提供されているクラスなんですか?
Avatar
APIKitはデフォルトではURLSessionを使っているようですね。 (SessionAdapterというprotocolがあって、URLSessionAdapterはそれに準拠したデフォルトの実装) https://github.com/ishkawa/APIKit/blob/master/Sources/APIKit/SessionAdapter/URLSessionAdapter.swift SeesionがcallbackQueueというのを持っているので、こいつで直列化するか?などを制御していそうです。 https://github.com/ishkawa/APIKit/blob/1a5e7ae0aed3f19c1ed9903792ead248f97fa38a/Sources/APIKit/Session.swift#L11 通信に使用しているSessionの設定次第によって変わるかと思います。
Avatar
Sessionの引数にURLSessionAdapterを渡すことでURLSessionでの通信に切り替えてくれるということなんですかね。だから複数の同時通信が可能になっている。。。? (edited)
Avatar
どうして直列になるのかはよくわからないですが、Session.sendでもデフォルトではURLSessionAdapterを使っているようですよ https://github.com/ishkawa/APIKit/blob/1a5e7ae0aed3f19c1ed9903792ead248f97fa38a/Sources/APIKit/Session.swift#L24
Avatar
ほんとですね。。なぜだろう。。。
Avatar
URLSessionはqueueの引数をnilで作ると直列で云々と書かれているのでそれの影響かもですね。 (URLSessionAdapterはsharedとかじゃなく独自にURLSessionをinitしてるらしい)
If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.
https://developer.apple.com/documentation/foundation/urlsession/1411597-init https://github.com/ishkawa/APIKit/blob/1a5e7ae0aed3f19c1ed9903792ead248f97fa38a/Sources/APIKit/SessionAdapter/URLSessionAdapter.swift#L24
Avatar
omochimetaru 6/5/2023 2:44 AM
URLSessionのその直列というのは並行アクセスを防ぐためにイベント処理を同一スレッドからアクセスされる事を言っていて、非同期な処理全体を順番に実行する制御の話ではないと思います (edited)
Avatar
もう1点、画面を離れる場合に通信中であればキャンセルしたいです。 private var task: SessionTask? //viewDidLoad sessionTask = Session.send(request) { result in ... } if let sessionTask = sessionTask as? URLSessionTask { print(sessionTask.state) //running } //viewWillDisappear if let sessionTask = sessionTask as? URLSessionTask { print(sessionTask.state) //completed sessionTask.cancel() //not working } としているのですが、通信中なのにタスクが完了状態となってキャンセルできないようです。 これは正しい動作なのでしょうか? APIのレスポンスを受け取るまでは、running状態だと思っていました。 (edited)
Avatar
omochimetaru 6/5/2023 8:37 AM
コメントによるとURLSessionTaskがcompletedなのでしょうか? それは既に通信完了しているのでcancelは意味がないと思います。 「APIのレスポンスを受け取るまでは」というのはAPIKitのAPIでコールバックが呼ばれるまでは、という意味でしょうかね? 一般的には非同期APIは確かに結果を受け取る前にcancelしたら割り込んで中断終了するのが望ましい設計ですね。 APIKitに対するキャンセルをしているならAPIKitの結果はキャンセルされてほしいですが、 APIKitについては知らないのでよくわかりません ただsessionTaskはAPIKitの内部状態にすぎないので、 sessionTaskを中断してもAPIKitは中断しない、という話ならおかしくはないと思います。 (edited)
Avatar
>「APIのレスポンスを受け取るまでは」というのはAPIKitのAPIでコールバックが呼ばれるまでは、という意味でしょうかね? その通りです。 URLSessionでの非同期処理は通信中であってもcancelしたら割り込んで中断終了するのでしょうか?
Avatar
omochimetaru 6/5/2023 9:20 AM
URLSessionは通信中であればcancelしたら割り込んで中断します。 この例のように、cancelする時点で既にcompletedであればcancelしても意味はないです。 (edited)
t_kansha 1
Avatar
RealmSwiftを使用しています。 let results = realm.objects(Item.self).sorted(byKeyPath: keyPath) let filterResults = results.filter(…) この場合、filterResultsの並び順は最初にsortした並び順になることが保証されていますでしょうか?
Avatar
「保証されているか」と言われると難しいんですが 一般的な(ソートができるような)コレクションのfilterで順序が壊れることはない(壊す意味がない) という点と ドキュメントを見る感じ何も書いてない https://www.mongodb.com/docs/realm-sdks/swift/latest/Protocols/RealmCollection.html#/Filtering ので同じ並び順になると思います (自分もRealmを長らく使ってますが、その様な現象に遭遇したことはないですね) 怖かったらfilterを先にやるってのもアリかなと思いました (edited)
👀 1
t_kansha 1
Avatar
RealmはRDSなので、filterの内容がクエリで表現できる場合はsortと併せてクエリの時点で書いてしまった方が良いですね。使い方にもよりますがオブジェクト群としてメモリに読み込むと、大量のレコードでリソースを圧迫する場合があります。 (edited)
👀 2
t_kansha 1
Avatar
SQLiteの話にはなりますが、全件取得してアプリケーションコードでfilterするのをSQLのWHEREで絞るようにしたら10倍以上速くなったりしました。 なるべくデータベース側でやった方がメモリ消費も処理速度もよくなる傾向にあると思います。 (edited)
👍 2
t_kansha 1
Avatar
ちなみになんですがRealmは確かそこら辺をLazyにやる仕組みが入ってたと思います (が、クエリでやれたらそっちの方が良いってのは同意です) クエリに関しては.where だった気がします
Results are lazily evaluated the first time they are accessed; they only run queries when the result of the query is requested. This means that chaining several temporary Results to sort and filter your data does not perform any unnecessary work processing the intermediate state.
https://github.com/realm/realm-swift/blob/45ea4a0ec4bb3161c807be0a9a4921161dbe60a2/RealmSwift/Results.swift#L103
(edited)
Realm is a mobile database: a replacement for Core Data & SQLite - realm-swift/Results.swift at 45ea4a0ec4bb3161c807be0a9a4921161dbe60a2 · realm/realm-swift
Avatar
SVProgressHUDを使用して、プログレス表示中に右上にボタンを配置することは可能でしょうか? 同じ階層に表示したいのですが、SVProgressHUD.show() するとどうしてもプログレスが最前面にきてしまいボタンをタップできなくて困っています。 https://github.com/SVProgressHUD/SVProgressHUD
A clean and lightweight progress HUD for your iOS and tvOS app. - GitHub - SVProgressHUD/SVProgressHUD: A clean and lightweight progress HUD for your iOS and tvOS app.
Avatar
Kishikawa Katsumi 6/15/2023 12:39 AM
可能かどうかでいうと可能ですがあまりそういうUIには向いてないですね。 SVProgressHUDは内部でWindowを作って一番前におくということをしてるのでアプリケーションのUIコンポーネントは気基本的に全部SVProgressHUDより後ろになります。 方法の1つとしてSVProgressHUDはcontainerViewをセットできるのでcontainerViewをセットしてそれを使うようにしてそこにボタンなどを置けばやりたいことはできると思います。 ただSVProgressHUDを使わずに処理中を示すUIを自分で書いてボタンを妨害しないところに配置するとした方が構造としていい感じになると思います。
Avatar
ありがとうございます! ひとまずSVProgressHUDのcontainerViewで対応しようと思ったのですがうまく機能しないですね。。。 やり方が間違っているかもしれませんが。 表示している画面でSVProgressHUD.setContainerView(self.view)とすると機能してるようなのですが、自作したカスタムViewを指定すると何も表示されませんでした。古いですが似たような方もいました。 https://stackoverflow.com/questions/45012710/svprogresshud-isnt-showing-when-using-setcontainerview
I'm having an issue with the setContainerView, the progress is not showing at all when I assign it to a custom view. I've tried everything with my UIView which is perfectly fine, but the progress r...
Avatar
野良UIライブラリは実装時間を短縮する代わりにそのライブラリの思想や実装の制約に縛られる諸刃の剣で、自身のプロダクトで需要が満たせなくなった場合は自作のコンポーネントに置き換えていくべきだと思います。
t_kansha 1
t_wakaru 1
Avatar
Kishikawa Katsumi 6/15/2023 8:23 AM
containerView勘違いしてたかも。ProgressViewに使われる一番下のビューだと思ってたんですけどProgressViewを載せるビューを設定するものかも(特にセットしない場合は自動的にWindowが作られるけどcontainerViewをセットした場合はcontainerViewにプログレスビューがのる。)。今の要件はSVProgressHUDだと満たせない気がしますね。
Avatar
なるほど、画面の一部にプログレスを表示したいみたいな時に使うんですかね? ありがとうございます。自作のコンポーネントに置き換えるしかなさそうですね。
Avatar
下記コードのようにresultにcase .none が必要になる設計は好ましくないでしょうか? func fetchData(completion: @escaping ((Result<String, Error>)?) -> Void) {...} fetchData { result in switch result { case .some(.success(let data)): print("Success: \(data)") case .some(.failure(let error)): print("Error: \(error)") case .none: print("Result is nil") } }
Avatar
Kishikawa Katsumi 6/19/2023 11:43 AM
一般論でいうとわかりにくいので良くはないですね。 その上でこの設計が妥当かどうかは場合によります。ErrorでもなくResult自体がnilになるというのはどういう状況で起こるのですか?
Avatar
func fetchData(completion: @escaping ((Result<String, Error>)?) -> Void) { fetch { switch result { case .some(.success(let data)): completion(.success(data)) case .some(.failure(let error)): if error == .commonError { completion(nil) return } completion(.failure(error)) } } すでにfetchDataを複数の画面で呼んでいる状況で新たに.commonErrorを追加したためif error == .commonError {}の判定をすべてに追加するよりラッパーを作成して1箇所で済まないか模索してました。どちららにせよすべてにcase .noneを追加する必要があるので手間はあまり変わらないかもしれませんが。。
Avatar
Kishikawa Katsumi 6/19/2023 12:59 PM
つまりcommonErrorをnilに変換してるってことですね。それはだいぶ良くないと思います。
1:00 PM
結局nilが返ってくる理由が呼び出す側はわからなくて実装を見に行かないといけないし、実装を見てもたぶんわからないです。
Avatar
呼び出す側で'switch error'する方が良さそうですね、ありがとうございます
Avatar
以下のコードのようにProcessを使ってコマンドをasync/awaitでキャンセルできるように呼び出すことを考えています。 https://gist.github.com/pommdau/6d0e1089f52ec50748b6732413303194 例としてechoの場合はうまくいくのですが、xcodebuildを呼び出した際にProcessのisRunningがいつまでもfalseにならず、 処理が終了しない状態となっています。 Processの処理の仕方に問題があるのか、またはxcodebuildの取り扱い方に問題があるのか原因が分かる方いらっしゃるでしょうか。 [環境] macOS: 13.4 (22F66) Xcode: Version 14.3.1 (14E300c)
GitHub Gist: instantly share code, notes, and snippets.
Avatar
omochimetaru 6/26/2023 7:24 AM
handleButtonClicked から辿ってみていくと、 Swift Concurrencyで管理しているスレッド (Task.init のbody)の中で、 whileによるビジーループをしているのが、Swift Concurrencyの規則に違反していてぶっ壊れているような気がします。 echo がうまくいくのは、プロセスが一瞬で終了するために、最初のwhileに入らずに済んでいるからかも。 1. echo "start" && sleep 3 && echo "end" だったらうまくいきますか? 2. 0.5秒のsleepを終了待ちではなく whileループの中に入れたらどうなりますか? 3. async版executeの withCheckedThrowingContinuation の冒頭で、同期版 execute の実行を専用に用意したDispatchQueueに退避したらどうなりますか? 4(おまけ) Process.waitUntilExit という便利なメソッドがありますよ。
Avatar
ご回答ありがとうございます!取り急ぎ下記に、記載いただいた内容を試した結果を記載します。 >echo "start" && sleep 3 && echo "end" だったらうまくいきますか? はい、うまく動作します。 start end >0.5秒のsleepを終了待ちではなく whileループの中に入れたらどうなりますか?
  • 下記の通り変更しました。
  • 動作としては変化なしで、xcodebuildの処理が終了しない状態です。
// Processが完了するまで、Taskがキャンセルされていないかを監視 while process.isRunning { // xcodebuildを呼び出した際にここがfalseにならない do { try Task.checkCancellation() } catch { process.terminate() completion(.failure(.cancel)) return } Thread.sleep(forTimeInterval: 0.5) } let data = pipe.fileHandleForReading.readDataToEndOfFile() // Thread.sleep(forTimeInterval: 0.5) // Taskの終了を待つためのDelay(必要?) >async版executeの withCheckedThrowingContinuation の冒頭で、同期版 execute の実行を専用に用意したDispatchQueueに退避したらどうなりますか?
  • 下記の通り変更しました。
  • 動作としては変化なしで、xcodebuildの処理が終了しない状態となります。
/// async版 @discardableResult static func execute(command: String, currentDirectoryURL: URL? = nil) async throws -> String { try await withCheckedThrowingContinuation { continuation in DispatchQueue.global(qos: .background).async { execute(command: command, currentDirectoryURL: currentDirectoryURL) { result in do { let output = try result.get() continuation.resume(returning: output) } catch { continuation.resume(throwing: error) } } } } }
8:07 AM
>4(おまけ) Process.waitUntilExit という便利なメソッドがありますよ。
  • 下記のコードで試しましたが、waitUntilExitの部分でxcodebuildの処理が終了しない状態となりました。
do { try process.run() } catch { completion(.failure(.failedInRunning)) return } process.waitUntilExit() // xcodebuildを呼び出した際にここで止まってしまう let data = pipe.fileHandleForReading.readDataToEndOfFile()
Avatar
omochimetaru 6/26/2023 8:08 AM
あれ、ダメでしたか。 そうするとビジーループが問題で壊れているのではなくて、 本当に xcodebuild プロセスが終了していないっぽいですね。
🙇 1
8:13 AM
次の手はすぐに思いつきそうにないです。
Avatar
はい、xcodebuildが怪しそうですよね、もう少しxcodebuild周りを調べてみます。 またご指摘いただいたビジーループの部分の書き方も見直してみます。
Avatar
"-[NSConcreteNotification endRefreshing]: unrecognized selector sent to instance 0x~~~" というエラーでクラッシュしました。原因としては下記のようにNotificationCenterを使用して通知を受けた場合、senderUIRefreshingControlではなくNSConcreteNotificationが入っているのにendRefreshing()を呼んだからだと思うのですがこれは正しい動きでしょうか? NotificationCenter.default.addObserver( self, selector: #selector(didReceive), name: .HogeNotification, object: nil ) @objc func didReceive(sender: UIRefreshControl) { print(“結果: \(sender)“) // NSConcreteNotification sender.endRefreshing() }
Avatar
.HogeNotificationを呼び出してる箇所の実装に依存するのでなんとも言えないと思います
8:49 AM
すみません間違えました。senderはNSNotification固定でした
8:50 AM
NSNotificationのペイロードにUIRefreshingControlが入っているかどうか、が呼び出し箇所に依存するということでした
Avatar
Avatar
IKEH
以下のコードのようにProcessを使ってコマンドをasync/awaitでキャンセルできるように呼び出すことを考えています。 https://gist.github.com/pommdau/6d0e1089f52ec50748b6732413303194 例としてechoの場合はうまくいくのですが、xcodebuildを呼び出した際にProcessのisRunningがいつまでもfalseにならず、 処理が終了しない状態となっています。 Processの処理の仕方に問題があるのか、またはxcodebuildの取り扱い方に問題があるのか原因が分かる方いらっしゃるでしょうか。 [環境] macOS: 13.4 (22F66) Xcode: Version 14.3.1 (14E300c)
zshを通している理由がよくわからないんですが直接xcodebuildを起動してもダメですか?
Avatar
ご回答ありがとうございます! 直接xcodebuildを起動というのは、下記のコードの意図であっているでしょうか。 (xcodebuildの場所の確認) where xcodebuild /usr/bin/xcodebuild let pipe = Pipe() let process = Process() process.launchPath = "/usr/bin/xcodebuild" process.arguments = [ "-scheme", "BuildSampleProject", "-project", "/Users/ikeh/Downloads/tmp/BuildSampleProject/BuildSampleProject.xcodeproj", "-configuration", "Release", "-archivePath", "/Users/ikeh/Downloads/tmp/BuildSampleProject/build/BuildSampleProject.xcarchive", "archive", ] process.standardOutput = pipe process.launch() // isRunningがfalseにならない while process.isRunning { Thread.sleep(forTimeInterval: 0.5) } // process.waitUntilExit() // 同様にここで処理が止まる let data = pipe.fileHandleForReading.readDataToEndOfFile() let str = String(data: data, encoding: .utf8) ?? "" print(str) (edited)
Avatar
Pipeって無限バッファではないはずなので、xcodebuildがstdout/stderr書きたいのに止まってる、とかだったりしませんか? cat /path/to/適当にでかい(テキスト)ファイル とかで試してみたいです
2:24 PM
(あるいはstdout/stderrを全部 /dev/null に繋げてみるとか)
Avatar
あー、ありそう。そうか、これだと実行中にパイプを吸い出せてないですね。
Avatar
ありがとうございます!その点が原因のようでした。 >cat /path/to/適当にでかい(テキスト)ファイル >Objective-C, NSTask Buffer Limitation >The NSPipe buffer limit seems to be 4096 bytes 上記の通り4096 bytesが制限という話が見つかりました。 ただし10kbのテキストファイルで試した所、問題なく処理が完了し、出力も全て出力される動きでした。 >(あるいはstdout/stderrを全部 /dev/null に繋げてみるとか) 下記とした場合に処理が完了しました。 static var xcodebuild: String { """ xcodebuild \ -scheme "BuildSampleProject" \ -project ~/"Downloads/tmp/BuildSampleProject/BuildSampleProject.xcodeproj" \ -configuration "Release" \ -archivePath ~"/Downloads/tmp/BuildSampleProject/build/BuildSampleProject.xcarchive" \ archive \ 1>/dev/null 2>&1 """ } (edited)
I'm using NSTask to run an external utility which returns a long string of data. The problem is that when the returned string exceeds a large amount of data (around 32759 chars) it becomes null or
2:45 AM
また実行中にPipeを随時吸い出せるように下記の通り書いてみたところ、こちらもxcodebuildの処理が無事に完了しました。 /// completion版 static func execute(command: String, currentDirectoryURL: URL? = nil, completion: @escaping (Result<String, CommandError>) -> ()) { let process = Process() process.launchPath = "/bin/zsh" process.arguments = ["-cl", command] process.currentDirectoryURL = currentDirectoryURL let pipe = Pipe() process.standardOutput = pipe process.standardError = pipe process.standardOutput = pipe process.standardError = pipe do { try process.run() } catch { completion(.failure(.failedInRunning)) return } var output = "" let saveOutputInProgress = { guard let _output = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) else { return } output += _output Thread.sleep(forTimeInterval: 0.5) } // Processが完了するまで、Taskがキャンセルされていないかを監視 while process.isRunning { do { try Task.checkCancellation() } catch { process.terminate() completion(.failure(.cancel)) return } saveOutputInProgress() } saveOutputInProgress() if process.terminationStatus != 0 { completion(.failure(.exitStatusIsInvalid(process.terminationStatus, output))) return } completion(.success(output)) }
🎉 5
Avatar
//viewDidLoad NotificationCenter.default.addObserver(self, selector: #selector(), name: .hogehoge, object: nil) deinitが呼ばれない実装になっている場合、viewDidLoadが呼ばれる度に通知が登録されると思うのですが、引数に指定しているselfはその時のオブジェクト(本来であればdeinitが呼ばれて解放されて欲しいオブジェクト)を保持し続けているのでしょうか?
Avatar
「deinitが呼ばれない実装」というのはどこかでインスタンスを保持していて、インスタンスが解放されることがないようにしているということでしょうか? それともそのカスタムクラスがdeinitをオーバーライドしていないということでしょうか?
Avatar
UIViewController の派生クラスだと仮定して、viewDidLoad はそのクラスのインスタンスの生存期間で(自分で呼ぶなどの違反行為をしていない限り)、高々1回しか呼ばれることはない(self.viewが作られた時)はずです。 (edited)
12:07 AM
従って、"deinitが呼ばれない" = クラスのインスタンスが保持される, "viewDidLoad が呼ばれる度に"、は同時に成立しないはずなので、何か違反行為があるように思います。
Avatar
どこかでインスタンスを保持していて、インスタンスが解放されることがないようにしているということでしょうか?
勿論あえてしている訳ではなく意図せず循環参照している場合ですね。 画面AとBがあり、画面BでaddObserverしている場合、画面A>B>A>Bのようにpushとpopを繰り返すと画面Bを表示するたびにaddObserverが走ると思います。その場合画面Aに戻った時にdeinitが走らないと通知が解除されないためpostされたら登録した回数分の処理が走ると思います。下記コードで確認すると異なるアドレスが出力されるため、登録した時のインスタンスを保持したままになっているという解釈であっているのか気になりました。 //selector @objc func didReceive() { print(ObjectIdentifier(self)) }
Avatar
その場合、最初のABと次のABは別のインスタンスになるはずです。(そうでないならばなにか不思議なことが起こると思います...) (edited)
3:24 AM
で、そうであるならばBが2つ存在して1つの通知は異なる両方のBで受け取っていると思います。
3:25 AM
deinitが呼ばれないは最初のABについて、ということですね。pushしているのであればそれは期待する動作です。
3:27 AM
NSNotificationCenter (Swift の NotificationCenter)はobserverを保持(所有)しません。ですので「登録時のインスタンスを保持したままになっている」というより、登録時のインスタンスを弱参照しているがより正しいです。
3:28 AM
しかし、それぞれのView Controllerはnavigationのスタックに保持(所有)されているので、その所有が続く限りはそれらのView Controllerすべてに通知が届きます。
3:31 AM
なお正確には NSNotificationCenter は弱参照と同時に通知の登録情報を保持します。この登録情報は unregisterするか、次回通知を送るときに参照先がなくなったときにしかメモリから消去されません。ですので、observeしている通知がレアなものであるばあい、登録情報がリークします。(これはドキュメントにうっすら書かれているだけなのであまり知られていないのですが...) ですので、必要がないと書かれているインターネットの情報は多いと思いますが実際は observer (この場合、ViewController) の deinit() で unregister するほうが良いです。 (edited)
Avatar
ありがとうございます!!
Avatar
必要がないと書かれているインターネットの情報は多いと思いますが実際は observer (この場合、ViewController) の deinit() で unregister するほうが良いです。
これ、Swift Concurrencyの世界だとdeinitでは @MainActor なクラスであるUIViewController自体(self)を触れないので今後できなくなる気がします。 SE-0371が入ればdeinitでMainActorなクラスを触れるようになるっぽい? https://github.com/apple/swift-evolution/blob/main/proposals/0371-isolated-synchronous-deinit.md 今のところはViewに関係ないNotificationはViewControllerではないクラスで受け取るのがいいのかも (MainActorでなければdeinitでselfに触れるので)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
👀 1
Avatar
連投すみません🙇‍♂️ class ParentViewController: UIViewController { override func viewDidLoad { let childView = ChildView(delegate: self) let hosting = UIHostingController(rootView: childView) ~~~省略~~~ } deinit { //deinitが呼ばれない } } extension ParentViewController: HogeDelegate { func hoge() {} } protocol: HogeDelegate { func hoge() } struct ChildView: View { let delegate: HogeDelegate var body: some View { Button("") { delegate.hoge() } } } SwiftUIでdelegateを使いたくてネットの記事を参考にこのような実装をしたのですが、これだとdeinitが呼ばれないようです。このやり方はアンチパターンでしょうか?また、この場合のベストプラクティス等はありますでしょうか? (edited)
Avatar
ChildView.delegateで循環参照が起きてますね delegateパターンを使うときは弱参照にするのはほぼ必須です SwiftUIではちょっと使いにくいと思うので、ハンドラパターンにすることが多いのではないかと思います
Avatar
Avatar
trickart
必要がないと書かれているインターネットの情報は多いと思いますが実際は observer (この場合、ViewController) の deinit() で unregister するほうが良いです。
これ、Swift Concurrencyの世界だとdeinitでは @MainActor なクラスであるUIViewController自体(self)を触れないので今後できなくなる気がします。 SE-0371が入ればdeinitでMainActorなクラスを触れるようになるっぽい? https://github.com/apple/swift-evolution/blob/main/proposals/0371-isolated-synchronous-deinit.md 今のところはViewに関係ないNotificationはViewControllerではないクラスで受け取るのがいいのかも (MainActorでなければdeinitでselfに触れるので)
なるほどー。まあ、Notification Center トリビアでiOSアプリなら殆どの場合長時間動作するまえにプロセスが死ぬと思うのでまあ大規模なアプリで長時間使われるものでなければ大丈夫かな。でもmacCatalyst化してmacOSで動かすとかなるとだいぶ問題になる。あとは、blockベースのAPIに変えるとかかなあ。確か挙動が違うはず。 (edited)
Avatar
Avatar
tarunon
ChildView.delegateで循環参照が起きてますね delegateパターンを使うときは弱参照にするのはほぼ必須です SwiftUIではちょっと使いにくいと思うので、ハンドラパターンにすることが多いのではないかと思います
ありがとうございます。 ChildViewがParentVCを強参照しているということでしょうか? 弱参照がほぼ必須なdelegateパターンはstructでは使えないのですね。 ハンドラパターンとはこのような感じですかね。 class ParentViewController: UIViewController { override func viewDidLoad() { let childView = ChildView() { print("hoge") } } } struct ChildView: View { let closure: () -> Void }
Avatar
handlerを渡す場合でも、print(“hoge”) のブロックでselfは参照しないかするなら[weak self]にしないとですね。
Avatar
Avatar
niw
handlerを渡す場合でも、print(“hoge”) のブロックでselfは参照しないかするなら[weak self]にしないとですね。
ありがとうございます!
Avatar
アプリ全体でフォントをNoto Sansで統一することは可能でしょうか? 実装難易度やデメリット等あればご教示いただけると嬉しいです🙇‍♂️ (edited)
Avatar
Kishikawa Katsumi 7/19/2023 3:23 AM
カスタムフォントを使用するにはフォントをアプリに同梱してInfo.plistにフォントの名前と場所の記述を追加するだけなので難しいことはまったくないです。 全体で使えるかというとほとんどの場所では使えますが、AlertやActionSheetなどOSのコンポーネントでフォントを変更できるようなAPIが提供されてない部分には使えません。 デメリットはシステムフォントとNoto Sansで表現力に大した違いはないのであらゆる画面でそのフォントを使用するという手間をかけるのに見合うかどうかだと思います。
Avatar
omochimetaru 7/19/2023 3:47 AM
ポイントとしては「デフォルトのフォントを設定する」みたいな機能は提供されてないので、 抜け漏れなく全部の場所でそのフォントを使うようにコードを組む必要がありますね。
Avatar
カスタムフォントはすごーい大変です
3:48 AM
過去に某アプリの開発でかなりハックを書きました。例えば絵文字がズレるとか。 (edited)
Avatar
Kishikawa Katsumi 7/19/2023 3:50 AM
確かに自分で用意したテキストだけじゃなくてユーザーの入力も対象になるとだいぶ難易度が上がります。
Avatar
iOSでは少なくともシステムフォントは特別扱いされていて、
3:51 AM
様々な追加の挙動が発生しています。
Avatar
omochimetaru 7/19/2023 3:51 AM
絵文字ズレるなるほど・・・最近カスタムフォントなアプリ作ったけど未知の問題ありそう・・・
Avatar
これらが全部動かなくなるのでその補填みたなことをしないといけません。
3:52 AM
これに追加でフォントフォールバックが起こるので
3:52 AM
中華フォント問題も関係してきます。
3:53 AM
あとバグっててクラッシュするケースもありました。
3:54 AM
カスタムフォントをUIに使うのは、8割動くものはそれなりの努力でできると思いますが、9割以上動くものにするのは相応の努力が必要になる印象です。 (edited)
Avatar
皆様ありがとうございます。かなりの拘りがなければ標準フォントを使用した方が安心ですね。
Avatar
質問です 最近CoreDataを学び始めたものなのですが、XcodeでCoreDataのEntityを定義して、manualでclassを生成しているのですが、作られたclassのプロパティが意図せずoptionalになってしまいます。 そのプロパティを使う時に毎回アンラップしないといけないのがしんどいです。どうするのがいいか知っていたら教えていただきたいです。
Avatar
Kishikawa Katsumi 7/20/2023 4:36 AM
Core DataのEntityの属性がOptionalでないということはSwiftのクラスのプロパティがOptionalでないということとは異なるのでCore Dataが生成するクラスのプロパティは常にOptionalになります。 Core DataのEntity定義でOptionalではないというのは保存するときに値が入っていればいいということなので、途中までnilが入る状態があることは構わない、というのがCore Dataの方針のようです。 また、生成されたクラスを修正してNon-Optionalにすることはできますが、XXEntity(context: persistentContainer.viewContext) のように引数を何も与えずにEntityを生成することができるのでその場合、Non-Optionalなプロパティにもかかわらずnilであるということが起こるのでNon-Optionalのプロパティである意味がありません。 ということであまりいい方法はないと思います。
Avatar
なるほど〜ご丁寧にありがとうございます!
Avatar
struct ContentView: View { @State private var location: CGPoint = CGPoint(x: 50, y: 50) @State private var timeRemaining = 600 @State private var timerRunning = false var body: some View { VStack { ZStack { Circle() .fill(Color.blue) .frame(width: 50, height: 50) .position(location) .gesture( DragGesture() .onChanged { value in location = value.location } ) } .frame(maxWidth: .infinity, maxHeight: .infinity) .border(Color.black, width: 2) TimerView(timerRunning: $timerRunning, timeRemaining: $timeRemaining)// 枠線を追加 } } } struct TimerView: View { @Binding var timerRunning: Bool @Binding var timeRemaining: Int let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() var body: some View { VStack { HStack { Text("\(String(format: "%02d", timeRemaining / 60)):\(String(format: "%02d", timeRemaining % 60))") .font(.system(size: 48)) .fontWeight(.bold) .onTapGesture { timerRunning.toggle() } .onReceive(timer) { _ in if timeRemaining > 0 && timerRunning { timeRemaining -= 1 } else if timeRemaining == 0 { timerRunning = false } } } } } }
9:32 AM
質問です。こんな感じの普通のTimerとdragで物体が動くViewを作ったとき、物体を動かしているときにTimerが止まってしまいます。どうすればDragしている間でもTimerを更新することができますか?
Avatar
dragに関する処理はtimerがとまる現象と関係ありそうですか? またtimerをStateに保持してみてはどうでしょうか
Avatar
Stateに保持したら直りました。ありがとうございます! これなぜ、stateに保持すると動くのでしょうか...?教えていただきたいです。
Avatar
timerはclassで、参照を持つことを前提として動きます
9:45 AM
SwiftUIでは参照を持つために、StateやObservableObjectといった機能を使う必要がある。この辺りだと思います。
Avatar
ありがとうございます!力不足で理解できませんでしたが、勉強して理解できるようにします。
Avatar
質問です。現在cocoapodを使ってアプリを作っているのですが、ビルド時に以下のようなエラーが出てしまいます。cocoapodを再インストールしたり、キャッシュをクリアしたりしても状況は変わらないです。Podfileに記載しているライブラリと実際にインストールされたライブラリが違うので気になっているのですが、ここに原因があるのでしょうか?ご教授いただけますと幸いです。
Avatar
Kishikawa Katsumi 8/19/2023 1:14 PM
Podfileはどうなっていますか?
Avatar
このようになっています
Avatar
再度ビルドさせたところ、1枚目の通りRealm内でのエラーのみになりました。ビルドして失敗するとRLMUtil.mmファイルの2枚目の部分が表示されています。 ChatGPTに聞いたところ、 clang++ -c RLMUtil.mm -o RLMUtil.o -std=c++11 -stdlib=libc++ ターミナルで以上のようにコマンドを実行させるとあるのですが、その通りにして良いのでしょうか? (edited)
Avatar
Kishikawa Katsumi 8/19/2023 1:27 PM
Xcodeのバージョンはいくつですか?
Avatar
12.4になります
Avatar
Kishikawa Katsumi 8/19/2023 1:29 PM
だいぶ古いですね。去年の段階でRealmはXcode 12はサポートしなくなってますがインストールしたRealmのバージョンはいくつですか?
Avatar
最新のものにしてしまっています。
Avatar
Kishikawa Katsumi 8/19/2023 1:44 PM
Xcode 12.5でやってみましたがRealmはビルドできないですね。10.25.2がXcode 12をサポートしていた最後のバージョンなのでRealmのバージョンを10.25.2に下げてみたらビルドできますか?
1:45 PM
ただ、Xcode 12でビルドしたアプリはもう審査に出せないと思いますが大丈夫ですか?
1:46 PM
あと基本的に使ってるライブラリが全部古いですね。Xcodeのバージョンを上げるのが根本的には解決になると思いますが、おそらく使おうとしているライブラリはそのままだと最新のXcodeではビルドできないですね。
Avatar
なるほど。ご回答くださりありがとうございます!まずはXcodeのバージョンを上げてみようと思います。
Avatar
SwiftUIについてご質問させてください。 以下コードはTODOリストを実装したものです。TodoItemには完了/未完了を表すチェックボックスがあり、完了した項目は下になるようソートしています。 ですがObservableObjectがネストしているためチェックボックスの変更通知がContentViewまで届かず、リストが再描画されません。 この問題についてはobjectWillChangeとコールバック関数を組み合わせて解決しましたが、どうもSwiftUIの設計思想に反している気がします。 もっとSwiftの流儀に則ったうまい解決方法はありますでしょうか。 import SwiftUI struct ContentView: View { @StateObject var viewModel = TodoList() var body: some View { List { Button("Add Item") { viewModel.add() } ForEach(viewModel.items.sorted { !$0.completed && $1.completed }) { TodoItemView(viewModel: $0) } } } } class TodoList: ObservableObject { @Published var items: [TodoItem] = [] func add() { items.append(TodoItem(text: "item: \(items.count)") { self.objectWillChange.send() }) } } class TodoItem: ObservableObject, Identifiable { @Published var completed = false { didSet { onChanged() } } @Published var text: String private let onChanged: () -> Void init(text: String, onChanged: @escaping () -> Void) { self.text = text self.onChanged = onChanged } } struct TodoItemView: View { @StateObject var viewModel: TodoItem var body: some View { HStack { Button(action: { viewModel.completed.toggle() }, label: { Image(systemName: viewModel.completed ? "checkmark.square.fill" : "square") }) TextField("", text: $viewModel.text) } } }
Avatar
Avatar
We
SwiftUIについてご質問させてください。 以下コードはTODOリストを実装したものです。TodoItemには完了/未完了を表すチェックボックスがあり、完了した項目は下になるようソートしています。 ですがObservableObjectがネストしているためチェックボックスの変更通知がContentViewまで届かず、リストが再描画されません。 この問題についてはobjectWillChangeとコールバック関数を組み合わせて解決しましたが、どうもSwiftUIの設計思想に反している気がします。 もっとSwiftの流儀に則ったうまい解決方法はありますでしょうか。 import SwiftUI struct ContentView: View { @StateObject var viewModel = TodoList() var body: some View { List { Button("Add Item") { viewModel.add() } ForEach(viewModel.items.sorted { !$0.completed && $1.completed }) { TodoItemView(viewModel: $0) } } } } class TodoList: ObservableObject { @Published var items: [TodoItem] = [] func add() { items.append(TodoItem(text: "item: \(items.count)") { self.objectWillChange.send() }) } } class TodoItem: ObservableObject, Identifiable { @Published var completed = false { didSet { onChanged() } } @Published var text: String private let onChanged: () -> Void init(text: String, onChanged: @escaping () -> Void) { self.text = text self.onChanged = onChanged } } struct TodoItemView: View { @StateObject var viewModel: TodoItem var body: some View { HStack { Button(action: { viewModel.completed.toggle() }, label: { Image(systemName: viewModel.completed ? "checkmark.square.fill" : "square") }) TextField("", text: $viewModel.text) } } }
子View(TodoItemView)でデータを変更したい場合は、Bindingを使用するのがSwiftUIでは使いやすいと思います。 Bindingするもの(TodoItem)はclassではなく、structでないとUIが更新されません。 objectWillChangeは使用場面は少ないと思います。 delegateなので値が変わるなどの際には、使用する機会があるかもしれません。 struct ContentView: View { @StateObject var viewModel = TodoList() var body: some View { List { Button("Add Item") { viewModel.add() } ForEach($viewModel.items.sorted { !$0.wrappedValue.completed && $1.wrappedValue.completed }) { TodoItemView(item: $0) } } } } class TodoList: ObservableObject { @Published var items: [TodoItem] = [] func add() { items.append(TodoItem(text: "item: \(items.count)")) } } struct TodoItem: Identifiable { let id = UUID() var completed = false var text: String init(text: String) { self.text = text } } struct TodoItemView: View { @Binding var item: TodoItem var body: some View { HStack { Button( action: { item.completed.toggle() }, label: { Image(systemName: item.completed ? "checkmark.square.fill" : "square") } ) TextField("", text: $item.text) } } } (edited)
Avatar
Avatar
zunda
子View(TodoItemView)でデータを変更したい場合は、Bindingを使用するのがSwiftUIでは使いやすいと思います。 Bindingするもの(TodoItem)はclassではなく、structでないとUIが更新されません。 objectWillChangeは使用場面は少ないと思います。 delegateなので値が変わるなどの際には、使用する機会があるかもしれません。 struct ContentView: View { @StateObject var viewModel = TodoList() var body: some View { List { Button("Add Item") { viewModel.add() } ForEach($viewModel.items.sorted { !$0.wrappedValue.completed && $1.wrappedValue.completed }) { TodoItemView(item: $0) } } } } class TodoList: ObservableObject { @Published var items: [TodoItem] = [] func add() { items.append(TodoItem(text: "item: \(items.count)")) } } struct TodoItem: Identifiable { let id = UUID() var completed = false var text: String init(text: String) { self.text = text } } struct TodoItemView: View { @Binding var item: TodoItem var body: some View { HStack { Button( action: { item.completed.toggle() }, label: { Image(systemName: item.completed ? "checkmark.square.fill" : "square") } ) TextField("", text: $item.text) } } } (edited)
おお〜!@Bindingは思いつきませんでした! ↓この書き方もとても参考になりました✨ ありがとうございます! ForEach($viewModel.items.sorted { !$0.wrappedValue.completed && $1.wrappedValue.completed }) { TodoItemView(item: $0) }
Avatar
モーダル遷移後の処理について質問があります。 現在ハンバーガーメニューを実装するために、2つViewControllerを用意しており(遷移元の、遷移元のRecordViewController、遷移先のSideMenuViewControllerです)RecordVCからSideMenuVCまでがコード上でモーダル遷移しているのですが、SideMenuVCからRecordVCに戻る際に「SideMenuVCのモーダル遷移後に、値の受け渡しを行い、RecordVCの関数を呼び出す」ことができず困っております。 https://tech.amefure.com/swift-uikit-modal-dismiss こちらの記事を参考に、presentationControllerを使う方法を実践したのですが、モーダル遷移が終了する前に呼び出されてしまい、値の受け渡しができませんでした。 self.dismiss(animated: true) { let recordViewController: RecordViewController = self.storyboard?.instantiateViewController(withIdentifier: "RecordViewController") as! RecordViewController recordViewController.afterSideViewController() このようにクロージャーを用いた方法も試してみたのですが、遷移後に呼ばれるafterSideViewControllerにて値の受け渡しはうまくいきましたが、UILabelを表示させようとしたところ、Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional valueと出てしまいました。(他のところで同じラベルを表示させようとするとうまくいくためUILabelに問題があるわけではないようです。) どのようにすれば希望通りの動作になりますでしょうか。ご回答いただけますと幸いです。 (edited)
SwiftのUIKitでモーダルを閉じたことを検知する方法は2種類あり、viewWillAppearメソッドで検知する方法とpresentationControllerDidDismissメソッドで検知する方法です。iOS12とiOS13でfullScreenから変更されているため明示的なスタイルの指定が必要になります。またモーダルの場合は親側のメソッドを子側から呼び出そうとした際に起きたエラーもあわせて解説していきます。
Avatar
えっとまず UIKit の UIViewController は presentingViewController が presentedViewController を管理するので、基本的には UIViewController が自身のpresentation状態をコントロールするのはオカシイです。例えば、modal view controller が自分自身を dismiss するような実装は UIKit のルールに反しています。(encapsulation... とか思ってそういうAPIを提供したり、実装してしまうことは多いのですが。)
1:22 AM
したがって正しくは、presentedViewControllerはdismissのイベントをpresentingViewControllerに渡すだけで、dismissするかどうかはpresentingViewControllerで実装するようにします。具体的にはdelegateなどでイベントを渡します。
1:23 AM
そのような実装の場合、presentingViewControllerはpresentedViewControllerのライフサイクル、状態すべてに責任があり、またそれらにアクセスできるため、例えば、modalで表示されたview controllerで設定された値を受け取ることは素直に実装できるはずです。
Avatar
Avatar
We
SwiftUIについてご質問させてください。 以下コードはTODOリストを実装したものです。TodoItemには完了/未完了を表すチェックボックスがあり、完了した項目は下になるようソートしています。 ですがObservableObjectがネストしているためチェックボックスの変更通知がContentViewまで届かず、リストが再描画されません。 この問題についてはobjectWillChangeとコールバック関数を組み合わせて解決しましたが、どうもSwiftUIの設計思想に反している気がします。 もっとSwiftの流儀に則ったうまい解決方法はありますでしょうか。 import SwiftUI struct ContentView: View { @StateObject var viewModel = TodoList() var body: some View { List { Button("Add Item") { viewModel.add() } ForEach(viewModel.items.sorted { !$0.completed && $1.completed }) { TodoItemView(viewModel: $0) } } } } class TodoList: ObservableObject { @Published var items: [TodoItem] = [] func add() { items.append(TodoItem(text: "item: \(items.count)") { self.objectWillChange.send() }) } } class TodoItem: ObservableObject, Identifiable { @Published var completed = false { didSet { onChanged() } } @Published var text: String private let onChanged: () -> Void init(text: String, onChanged: @escaping () -> Void) { self.text = text self.onChanged = onChanged } } struct TodoItemView: View { @StateObject var viewModel: TodoItem var body: some View { HStack { Button(action: { viewModel.completed.toggle() }, label: { Image(systemName: viewModel.completed ? "checkmark.square.fill" : "square") }) TextField("", text: $viewModel.text) } } }
ObservableObjectがネストしているためチェックボックスの変更通知がContentViewまで届かず(略) どうもSwiftUIの設計思想に反している気がします。
こういうの悩ましいですよね。もうすぐObservation(↓)が追加され、それを利用すればネストしたモデルの変更も通知されるようになるので、iOSのバージョンが許せばそれを利用するのが良いかもしれません。 https://developer.apple.com/videos/play/wwdc2023/10149/ https://github.com/apple/swift-evolution/blob/main/proposals/0395-observability.md
Simplify your SwiftUI data models with Observation. We'll share how the Observable macro can help you simplify models and improve your...
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
👏 1
🙇‍♂️ 1
Avatar
Avatar
niw
えっとまず UIKit の UIViewController は presentingViewController が presentedViewController を管理するので、基本的には UIViewController が自身のpresentation状態をコントロールするのはオカシイです。例えば、modal view controller が自分自身を dismiss するような実装は UIKit のルールに反しています。(encapsulation... とか思ってそういうAPIを提供したり、実装してしまうことは多いのですが。)
ご回答くださりありがとうございます!ご指摘いただきました通り、delegateなどでイベントを渡すようにしたところ、値の受け渡しも、ラベルの表示もうまくいきました!ありがとうございます🙇‍♀️
💯 1
Avatar
自動生成されるNavigationBarのbackボタンのタップアクションをpopToRootViewControllerにすることは可能でしょうか? スワイプバック不可になるのを受け入れてカスタムボタンを使用するしかないでしょうか?
Avatar
Kishikawa Katsumi 8/31/2023 12:01 PM
はい。それで合ってます。 ただ、Backボタンを押したときの動作がRoot View Controllerに戻したいという意味であれば(つまり途中に戻るということは不可能で戻る場合は全部最初からになる、みたいな)PushしたタイミングでviewControllersプロパティをセットし直して、必ずRootView => 現在のViewとなるようにするとできるはずです。SwiftUIの場合は同じことができるかはわかりません。 (edited)
Avatar
ありがとうございます! rootと自身以外のViewControllerがあればremoveするようにしたら理想の動きになりました。 (HogeViewControllerをUIHostingControllerでラップした途端に壊れそうで怖いですが、、、) class HogeViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.navigationController?.viewControllers.forEach { if !($0 is UIHostingController<HogeRootView>) && !($0 is HogeViewController) { $0.removeFromParent() } } } }
Avatar
Kishikawa Katsumi 8/31/2023 2:07 PM
これはビューをはがしているだけでNavigationControllerが管理しているViewControllerのスタックがそのままなのですでに壊れてますね。 ビューをはがすのではなくてNavigationControllerが持つviewControllersプロパティを変更します。
2:09 PM
PushするたびにviewControllersにViewControllerが追加されて、PopでviewControllersから取り除かれるのですが、viewControllersプロパティは自分で状態をセットできます。典型的には途中から再開したりするためですが、今回のような目的にも使えます。
Avatar
Avatar
Kishikawa Katsumi
これはビューをはがしているだけでNavigationControllerが管理しているViewControllerのスタックがそのままなのですでに壊れてますね。 ビューをはがすのではなくてNavigationControllerが持つviewControllersプロパティを変更します。
なるほど。このような感じでしょうか? こちらも正しく動いているように見えます。 var viewControllers: [UIViewController] = [] self.navigationController?.viewControllers.forEach { if $0 is UIHostingController<HogeRootView> || $0 is HogeViewController { viewControllers.append($0) } } self.navigationController?.setViewControllers(viewControllers, animated: true)
Avatar
Kishikawa Katsumi 8/31/2023 2:40 PM
はい。そんな感じです。私が書くならviewControllersをループして探すよりRootと今表示しているViewControllerを自分で管理した方が堅牢だと思うのでそうしますがとりあえず問題がないならいいと思います。
🙇‍♂️ 1
t_kansha 1
Avatar
浅漬けの素 9/4/2023 1:04 PM
初学者です。Actorを利用した共有リソースについての質問です(既出でしたら申し訳ありません)。 Actor内の静的プロパティを複数スレッドで非同期に更新し、共有リソースとして様々なメソッドで参照しています。が、更新・参照の際にデータ競合?と思われるエラーが頻発します。 伺いたい点は主に 1.actorのメソッド、プロパティの使い方が正しいか 2.キャッシュのような使い方をしているので、最悪参照がうまくいかなくてもよく、もし同様の目的でもっといい方法があれば… 3.できれば、同期的なメソッド内でプロパティを参照したい 4.await無しで使えてしまっていて困惑している 何卒ご教授いただけないでしょうか..!
1:04 PM
Struct AccountData { let accountId : String let accountName : String //省略 } actor AccountDataStore { //******Error: EXC_BAD_ACCESS など static var accountDataStore : [String:AccountData] = [:] //******Error: unrecognized selector sent to instance など static func addAccountData(_ data: AccountData) { AccountDataStore.accountDataStore[data.accountId] = data } static func addAccountDataArray(_ data: [AccountData]){ for data in data{ AccountDataStore.accountDataStore.updateValue(data, forKey: data.accountId) } } static func removeAccountData(_ accountId: String) { AccountDataStore.accountDataStore.removeValue(forKey: accountId) } static func removeAccountAllData(){ AccountDataStore.accountDataStore.removeAll() } static func removeAccountDataArray(_ data:[String]){ for data in data{ AccountDataStore.accountDataStore.removeValue(forKey: data) } } } //利用例 func getAccount(id:String)->[AccountData]{ if let account = AccountDataStore.accountDataStore[id]{ return account }else{ //server request AccountDataStore.addAccountData(data) return data } } func getAccountAsync(id:String) async -> [AccountData]{ if let account = AccountDataStore.accountDataStore[id]{ return account }else{ //server request AccountDataStore.addAccountData(data) return data } } func addAccountDataWithIdsAsync(accountIds:[String]) async throws { try await withThrowingTaskGroup(of: AccountData.self){ group in for id in accountIds{ group.addTask{ return try await getAccountAsync(id:id) } } for try await (id, data) in group{ await AccountDataStore.addAccountData(data) } } }
Avatar
unrecognized selector って objective-c の runtime error なので、関係ないような...
Avatar
浅漬けの素 9/4/2023 1:13 PM
ありがとうございます、別のところに根本的な問題がありそうですかね..精査してみます
Avatar
利用例を見ると await なしで操作しているので static var だと actor isolation が働いてないように見えます 例えばシングルトン経由でアクセスするようにするとよさそうです
Avatar
浅漬けの素 9/4/2023 5:33 PM
ありがとうございます!どうしても同期的なメソッドの中で参照したかったので、Continuationなどでどうにかできないかやってたんですが、基本的にActorのプロパティは同期的にはアクセスできないという認識で行こうと思います。
Avatar
質問です import SwiftUI import CoreData struct ContentView: View { @State var selectedString: String? = nil @State var showCover = false let strings: [String] = ["a","b","c"] var body: some View { VStack{ List{ ForEach(strings, id: \.self){ string in Button(action:{ selectedString = string showCover = true }){ Text(string) } } } }.fullScreenCover(isPresented: $showCover){ if let string = selectedString { Text(string) } }.onChange(of: selectedString){ newValue in print(selectedString) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } このコードは .onChange(of: selectedString){ newValue in print(selectedString) } があると正常に選んだ文字がモーダルに表示されるのですが、このコードを消すと、真っ白なモーダルが表示されてしまいます。 fullScreenCover(item: selectedString)で表示をすれば正常に動作することは分かったのですが、どうして表示に関係のないonChangeを書くだけで正常に表示されるのか疑問に思ったためもしわかる方いれば教えていただきたいです
Avatar
onChangeを記述せずに body の先頭に let _ = selectedString を記載した場合はどうなりますか?
Avatar
正常に表示されました!
7:57 AM
なぜなのでしょう...?
Avatar
@Stateで修飾されたプロパティはbody内部で触った瞬間に変更検知の対象になっているのだと思います。 つまり、selectedStringが変化した瞬間に.fullScreenCoverのクロージャの中身を更新します。 元々の実装はBindingである$showCoverしか変化が起こっていなかったために、showCoverが変化した際にbodyの再実行が行われず、初回に.fullScreenCoverのクロージャにキャプチャされた無のselectedStringがそのまま表示されたんだと思います
Avatar
buttonのactionでshow coverを先に変更したら動作変わるのかなあ (edited)
Avatar
よく考えたらif let string = selectedString {で参照してるselectedStringは実際はself.selectedStringのはずだから、@Stateごしの値の取得になってるはずで最新値が常に反映されそうな気もするなぁ
Avatar
元々の実装はBindingである$showCoverしか変化が起こっていなかったために、showCoverが変化した際にbodyの再実行が行われず
selectedString = string ここで$selectedStringの変化が起こっていると思っているのですが違いますか?
Avatar
Avatar
niw
buttonのactionでshow coverを先に変更したら動作変わるのかなあ (edited)
これは動作変わりませんでした!(正常に表示できませんでした)
Avatar
SwiftUIは最適化のために、使ってない@Stateの変更を無視するようです。bodyの中で一度も使われなかった selectedStringは変化が起こったとしても無視されてるということですね
Avatar
めちゃくちゃ理解です!ありがとうございました!!
Avatar
なるほど。
Avatar
Actorの初学者です、もしどなたかわかりましたら.. iOS17で使える MainActor.assertIsolated() で以下のようなコードを書いた時に、 自分の理解では Task の処理は Actor Context を引き継いで MainActor で実行されると考えていたのですが、 Taskに入った瞬間にクラッシュします、明示的な MainActor などの付与が無い限り Actor Context は存在しないという理解であっていそうでしょうか? func request<T>(_ request: T) -> Single<T.Response> { return Single.create { single in if #available(iOS 17.0, *) { // ここではクラッシュしない MainActor.assertIsolated() } let task = Task { if #available(iOS 17.0, *) { // ここはクラッシュする Thread 14: Fatal error: Incorrect actor executor assumption; Expected 'UnownedSerialExecutor(executor: (Opaque Value))' executor. MainActor.assertIsolated() } ... (edited)
Avatar
Avatar
tanako8031
Actorの初学者です、もしどなたかわかりましたら.. iOS17で使える MainActor.assertIsolated() で以下のようなコードを書いた時に、 自分の理解では Task の処理は Actor Context を引き継いで MainActor で実行されると考えていたのですが、 Taskに入った瞬間にクラッシュします、明示的な MainActor などの付与が無い限り Actor Context は存在しないという理解であっていそうでしょうか? func request<T>(_ request: T) -> Single<T.Response> { return Single.create { single in if #available(iOS 17.0, *) { // ここではクラッシュしない MainActor.assertIsolated() } let task = Task { if #available(iOS 17.0, *) { // ここはクラッシュする Thread 14: Fatal error: Incorrect actor executor assumption; Expected 'UnownedSerialExecutor(executor: (Opaque Value))' executor. MainActor.assertIsolated() } ... (edited)
Actor Contextの引き継ぎは(実行時ではなくコンパイル時に)静的に解決されるものだと思うので、 request (かその元の型)に @MainActor が付与されていない場合、 Task.initMainActor Contextで実行されないと思います。
2:58 PM
MainActor Contextで実行するだけなら Task { @MainActor in にするという方法もありますが、おそらく質問の趣旨はActor Contextの引き継ぎについてではないかと思ったので。
t_kansha 1
Avatar
Avatar
koher
Actor Contextの引き継ぎは(実行時ではなくコンパイル時に)静的に解決されるものだと思うので、 request (かその元の型)に @MainActor が付与されていない場合、 Task.initMainActor Contextで実行されないと思います。
ありがとうございます、やはり明示的なActorの付与が必要なんですね、Actor Contextの引き継ぎも静的に解決されるものとは理解できていませんでした..仰るとおり1ホップ(1フレ)増えると思うのですがAPIリクエスト完了の都度位のオーバーヘッドなら許容できそうと思いTask { @MainActor in で回避しています。 (edited)
👍 1
Avatar
Avatar
tanako8031
ありがとうございます、やはり明示的なActorの付与が必要なんですね、Actor Contextの引き継ぎも静的に解決されるものとは理解できていませんでした..仰るとおり1ホップ(1フレ)増えると思うのですがAPIリクエスト完了の都度位のオーバーヘッドなら許容できそうと思いTask { @MainActor in で回避しています。 (edited)
オーバーヘッドと言っても、メインスレッドで実行したい処理であれば必要なことですし、従来 DispatchQueue.main.async{ } してたのと変わらないと思いますので、気にする必要はないと思います。 ただ、個人的に↓のようなケースは気になってます。従来はなかった遅延だと思うので、 Task.init の中でボタン無効化したりしていたら、それまでに割り込まれる可能性がありますし。 func buttonPressed(sender: UIButton) { Task { ... } } (edited)
Avatar
Avatar
koher
オーバーヘッドと言っても、メインスレッドで実行したい処理であれば必要なことですし、従来 DispatchQueue.main.async{ } してたのと変わらないと思いますので、気にする必要はないと思います。 ただ、個人的に↓のようなケースは気になってます。従来はなかった遅延だと思うので、 Task.init の中でボタン無効化したりしていたら、それまでに割り込まれる可能性がありますし。 func buttonPressed(sender: UIButton) { Task { ... } } (edited)
従来 DispatchQueue.main.async{ } してたのと変わらない
なるほど、確かにそうですね。これで良いのかと不安に思っていたのでありがたいです。 buttonPressedに関しては @MainActor が付与されていれば Task も MainActor と同じExecutorで実行されるのでhopがなく遅延も無いと思っていたんですがhopが無いだけでenqueueする遅延は起きるということですかね。
(edited)
Avatar
Avatar
tanako8031
従来 DispatchQueue.main.async{ } してたのと変わらない
なるほど、確かにそうですね。これで良いのかと不安に思っていたのでありがたいです。 buttonPressedに関しては @MainActor が付与されていれば Task も MainActor と同じExecutorで実行されるのでhopがなく遅延も無いと思っていたんですがhopが無いだけでenqueueする遅延は起きるということですかね。
(edited)
Task.init のクロージャはたとえActor Contextを引き継いだ場合でも同期的に実行されないので、↓のような順で実行されます。 @MainActor func foo() { // 1️⃣ Task { // 3️⃣ 1サイクル遅れる } // 2️⃣ } (edited)
Avatar
Avatar
koher
Task.init のクロージャはたとえActor Contextを引き継いだ場合でも同期的に実行されないので、↓のような順で実行されます。 @MainActor func foo() { // 1️⃣ Task { // 3️⃣ 1サイクル遅れる } // 2️⃣ } (edited)
なるほど、基本的なところが抜けていました.. これは問題起きそうですね.. 皆さんどう対処しているんでしょうか (ボタン無効化を1に回せばいいのかな) (edited)
Avatar
まあ、Task {} の前にボタンを無効化すればいいんですが、ViewModelとかに切り出して、非同期処理を開始する( async メソッドを呼び出す)ときとかに困るんですよね。
Avatar
Avatar
koher
まあ、Task {} の前にボタンを無効化すればいいんですが、ViewModelとかに切り出して、非同期処理を開始する( async メソッドを呼び出す)ときとかに困るんですよね。
ちゃんと理解できていないのですが、ここでの困りは「従来はなかった遅延」は解決しない部分ですかね? (edited)
Avatar
Avatar
tanako8031
ちゃんと理解できていないのですが、ここでの困りは「従来はなかった遅延」は解決しない部分ですかね? (edited)
これまで非同期関数を呼び出すときに、コールバック方式だったら実際に非同期処理が始まるまでの部分は同期的に実行されていたんですが、 async の場合は Task.init に包んだ時点で非同期になるという点がこれまでと異なっている点だと思います。
3:50 PM
解決できないかというと解決しようはあるんですが( Task.init の外に書くとか)、ちょっとやりたいことと違う形になっちゃうんですよね。 (edited)
Avatar
Avatar
koher
これまで非同期関数を呼び出すときに、コールバック方式だったら実際に非同期処理が始まるまでの部分は同期的に実行されていたんですが、 async の場合は Task.init に包んだ時点で非同期になるという点がこれまでと異なっている点だと思います。
あーありがとうございます、先程も勘違いしましたが、そこは大きく違う点ですね、慣れるまで時間がかかりそうです.. Task.init の外に書かれてると一瞬読み手としても意図を考えるコストはかかりそうですね。 (edited)
Avatar
僕はViewModelの中ではなくView側に Task.init を書くスタイルでコードを書いているのでボタン無効化のタイミングが遅れて困っていましたが、 Task.init をViewModel側に書けば問題なく対応できそうな気がしてきました・・・。 func onButtonPressed(sender: UIButton) { viewModel.fetchFoo() } @MainActor final class ViewModel: ObservableObject { ... func fetchFoo() { isButtonDisabled = true Task { defer { isButtonDisabled = false } ... // 非同期処理 } } }
Avatar
ボタン無効化をViewModel側に閉じ込めるんですね(自分は自然に感じました)でもView側でキャンセルが扱いにくくなるんでしたっけ (以前koherさんのセッションでお聞きしたような) (edited)
Avatar
TaskViewModel 側でとっておけばキャンセルできますね。 @MainActor final class ViewModel: ObservableObject { ... private var task: Task? func fetchFoo() { guard task = nil isButtonDisabled = true task = Task { [self] in defer { self.task = nil isButtonDisabled = false } ... // 非同期処理 } } func cancelFetchingFoo() { task.cancel() task = nil } }
t_naruhodo 1
t_kansha 1
Avatar
こんにちは。GCPに関して質問があります。現在、CloudNaturalLanguageを使ってテキストの感情分析ができるアプリを作ろうとしているのですが、GCPのドキュメントを見てもSwift向けにクライアントライブラリが用意されていないです。この場合は直接REST APIを使用する方法しかないのでしょうか?
Avatar
特にライブラリが無い場合はAPI直叩きしかないですね。 公式に無い場合はサードパーティーや個人がライブラリを作って公開してることもあるんですが、その場合もAPI直叩きした方がいいかな?という感覚です。
Avatar
GCPは認証まわりの共通の仕組みが曲者で、認証方式が多岐に渡ってて1から実装するの難しいという悩みがありますね
Avatar
APIKey無かったっけ
2:25 AM
使えないエンドポイントもあるのか
Avatar
Application Default Credential全部に対応するのは大変なので、Service Account Credentialに絞って実装するのが初手としてはいいと思います
2:27 AM
APIKeyで使えるエンドポイントもあるんでしょうかね?何らか(色々)の手段でアクセストークンを手に入れてAuthorizationヘッダにのせるものが多いと思います
Avatar
なるほど。ご回答くださりありがとうございます。調べたところGCP以外でIBM Watson Natural Language Understanding、Amazon Comprehend、プリトレーニング済みのモデルを使用する方法などがあったのですが、みなさんだったらテキストのネガポジを判定する機能をつける方法として何を選択されますか?このままGCPを使ったほうが良いですか?
Avatar
GCPのライブラリ、恐らくですが認証通すだけの機能はあると思うのでそれを使うのが良いでしょうか? 個人的にはiOSクライアントから直接GCPのAPIを叩く作りは避けた方が良さそうかな?とは思いました。自分で立ててるAPIサーバーを経由して使うのが理想な気がします。 1. 利用状況を監視・コントロールできる 2. 何か間違えても鍵の流出リスクが低い 3. 他のAPIやインハウスのモデルへのシームレスな置き換えが実現可能になる この辺りがメリットでしょうか (edited)
Avatar
なるほど。ご丁寧にありがとうございます。初めて自作のアプリを作るのでAPIサーバーを自分で構築するのは少しハードに感じます。ChatGPTに聞いたところ「Google Cloud APIはRESTfulなエンドポイントを提供しており、Swiftから直接HTTPリクエストを行うことでGoogle Cloud Natural Languageを使用できる」とのことなのでとりあえずAPI直叩きで実装してみようと思います。
Avatar
手元で実験する分には何も問題ないと思います。もし公開される場合は、ハードリミットを厳しめに設定しておくと(GCPできましたっけ...)、間違いがあったりバズったりしたときのお財布へのダメージを軽減できるので、それはやっておくと良いと思います。
Avatar
わかりました!迅速なご回答大変助かりました。ありがとございます🙇‍♀️
Avatar
余談ですがiOSネイティブであればこれも使えそう?なので、精度に不満があるか試すところからやってみても良いかもしれません。 https://developer.apple.com/documentation/naturallanguage/ (edited)
Analyze natural language text and deduce its language-specific metadata.
🙇‍♀️ 1
Avatar
アプリ内課金について質問させてください。 自動更新サブスクリプションの新規購入の停止(既存契約者は継続)を計画しているのですが、アプリ側で導線を削除するだけで良いのでしょうか? 既存契約者は継続したいためApp Store Connect側で配信から削除は行えないと思います。 その場合、設定appの「サブスクリプション > すべてのプランを表示」に表示されて購入できそうな気がするのですがこのあたりご存知でしたら教えて頂きたいです。
Avatar
@udo223 設定アプリのすべてのプランについては、購入済みのサブスクリプションのあるアプリしか出ないような気がしますが、これは回答になってるでしょうか? 同じ状況を体験した人が少なそうなので、Appleの公式のサポートか、 #ask-to-apple で聞いてみるのが確実な気はします。
🙇‍♂️ 1
Avatar
Avatar
tarunon
@udo223 設定アプリのすべてのプランについては、購入済みのサブスクリプションのあるアプリしか出ないような気がしますが、これは回答になってるでしょうか? 同じ状況を体験した人が少なそうなので、Appleの公式のサポートか、 #ask-to-apple で聞いてみるのが確実な気はします。
設定アプリのすべてのプランについては、購入済みのサブスクリプションのあるアプリしか出ない
これはおっしゃる通りです。 なので新規購入を停止するためにアプリ側の導線を削除したプランに、既に別のプランを購入済みのユーザーが設定appから購入できてしまうのではないか?ということを懸念しています。 情報が足りておらず申し訳ございません。
Avatar
購入済みユーザのプラン変更などが問題になる、という事ですね
Avatar
おっしゃる通りです こちらの記事を見て
- 自動更新サブスクリプションの新規購入の停止 - アプリ側で導線の削除を実施
とだけ書かれていたので本当にこれだけで良いのか気になった次第です https://zenn.dev/tsuruo/scraps/2c3e4f031664af#comment-9744c55679fa22
Avatar
サブスクは App Store の奥底にある画面からいろいろできたはず
10:49 PM
アプリに同線がなくても。
10:51 PM
購入できなくした場合、既にサブスクしてる人がどうなるかとかむっちゃむずいので(値上げして新規のSKUつくるか?とか)状況次第でどうするか変わる気がしますね...
Avatar
...という会話がすでになされてますね。
11:00 PM
SKU別に2つプランがあった場合はどうだったかなあ。その切り替えはできなかった気がする。
Avatar
Avatar
niw
SKU別に2つプランがあった場合はどうだったかなあ。その切り替えはできなかった気がする。
既に購入しているユーザーはそのままで新規購入のみを制限したいケースというのはあまり無いのですかね... ドキュメント見ても配信の停止についてしか書かれておらず... ちなみにSKUとは何の略でしょうか?
3:35 AM
に載っていますが、一般名詞で、こう商品IDみたいやなつのことです
3:35 AM
例えば、色違いの商品が複数ある場合、SKUが違うみたいな言い方します。
3:36 AM
Stock Keeping Unitの略かな。在庫管理の世界から来てる単語なのかなあ。
3:41 AM
あーちょっと思い出してきた。Subscription Group ってのがあって、それが違うと切り替えとかはできないんだっけか... (edited)
3:43 AM
Subscription group: A set of subscription products with varying levels and durations. Users can subscribe to one subscription product per group at a time.
3:45 AM
うーん、なんかでもできなかった気がするなあ、そしてそんな奥底にあるやつを操作する人は少ないし、将来的には停止するとかでまあしゃーないってことにしたんだった気もする
3:45 AM
すみません、Subscriptionやってたの結構前なので記憶が。
Avatar
Avatar
niw
すみません、Subscriptionやってたの結構前なので記憶が。
ありがとうございます! 1つのプランの新規購入を停止したいだけで他プランのアップグレード、ダウングレードは行えるようにしたいのと、ユーザーはどれか1つのプランしか購入しないのでSubscription Groupを複数作るということは考えていません。Appleも推奨していないようですし。 https://developer.apple.com/jp/app-store/subscriptions/#groups もう少し調べてみようと思います。
アプリで自動更新サブスクリプションをシームレスに提供する条件を満たすサブスクリプションは1年経過後から収益率が増加し、より柔軟な価格設定などを行うことができます。
Avatar
Groupはまあ、そうですよね。結構、できないことが多かった気がするので、割り切りが必要だったきがします。
Avatar
購読について、調べたことはありますが、本番向けの実装はしたことはないので詳しくないです。 古いドキュメント『In-App Purchaseプログラミングガイド』を読んでみましたが、質問されていることそのものの説明を見つけることができませんでした。 関係ありそうなことを挙げてみます。
  • App Connectではプロダクトに購入可能(cleared for sale)のチェックがある。
  • App Connectに設定されている全プロダクトのリストを取得する仕組みはない。
    • アプリで表示する商品リストを制御できる。
  • 設定/Apple ID/サブスクリプションで表示されるのは、購読しているもののみ?
    • すべてのプランを表示、というのがあるので、気になりますね。
  • App Store/アカウント/サブスクリプションの内容は設定と同じようですね。 本件は、App Connectの設定のお話だと思いますので、サポート範囲だと思いますので、developerサイトで質問してみてもよろしいのではと思いました。
(edited)
Avatar
これも古い情報ですが。 https://help.apple.com/app-store-connect/ja.lproj/static.html#dev43b8efdec サブスクリプションの配信状況は、App Store Connect の各サブスクリプションのページにある「配信可能」チェックボックスで管理します。App 内課金をテスト、または App 内課金を提出する際は、App 内課金を配信可能に設定する必要はありません。 自動更新サブスクリプションの配信を停止する前に、まずはストアでの販売を停止して、サブスクリプションの登録や更新が新たに行われないようにします。ストアでの販売を停止するタイミングは、サブスクリプションの更新間隔に合わせることを推奨します。たとえば、月単位のサブスクリプションの配信を停止する場合は、遅くとも配信停止日の 31 日前までにストアでの販売を停止するようにします。 削除と、配信停止は別で、新たな登録/更新防止に配信停止が使える?
8:15 AM
サンドボックスのテストで、配信停止しても既存は更新されるかは、試せそうですね。
8:19 AM
現在のドキュメントで、お探しのパターンは説明されていませんね。 https://developer.apple.com/jp/help/app-store-connect/manage-in-app-purchases/set-availability-for-in-app-purchases
Avatar
ありがとうございます! サポートに質問しました。 返事を待ちつつ色々試してみようと思います
Avatar
新規購入後、クラッシュなどで中断して、その間に、新規登録できなくして、その後、アプリ起動時に購入中の決済があったら、レシート検証してトランザクション終了になると思いますが、しプロダクトは消せないので、有効で処理されるのか、気になりました。 ちなみに、StoreKit2でしょうか? (edited)
Avatar
iOS14をサポートしているのでStoreKit2は使ってないです 中断などのトラブルはどうなるのか全く分からないですね... ふと思いましたが、設定やApp Storeから購入できるのは既存契約者のプラン変更だけなのでアプリ側で導線を消すと完全な新規購入を防げそうですね
🙇 1
Avatar
App内課金でサブスクリプショングループを複数作成した場合、
  • アプリ内のプラン一覧画面でグループAは表示、グループBは非表示などの実装が可能か
  • 設定appやApp Storeからプランを表示した場合、作成しているサブスクリプショングループがすべて表示されるのか、表示非表示が可能か
このあたりご存知の方いましたらご教示いただきたいです。 サブスクリプショングループについてのドキュメントがあまり見当たらず… また複数のサブスクリプショングループがあるアプリなどご存知であれば教えて頂きたいです。
(edited)
Avatar
設定appやApp Storeからプランを表示した場合、作成しているサブスクリプショングループがすべて表示されるのか、表示非表示が可能か
表示非表示が可能かどうかは分かりませんが、購読しているグループしか表示されないようですね https://developer.apple.com/forums/thread/87410
Avatar
購読の商品情報取得は、サブスクリプショングループができても、プロダクトID(sku)のリストを渡して得るのではないかと思いますので、アプリ内の表示については、アプリで決めているのではないかと思いますが、何か勘違いしているでしょうか?
Avatar
以前あった『In-App Purchaseプログラミングガイド』は公開されなくなりましたが、英語ですが同様な内容をサイトに掲載しています。 商品情報取得のおおまかな流れはこちらで説明されていまして、 https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/loading_in-app_product_identifiers プロダクトID(sku)から商品情報を取得しているコードの説明はこちらになります、 https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/fetching_product_information_from_the_app_store オリジナルStoreKitはサブスクリプショングループ登場前から用意されたものなので、商品情報取得ではサブスクリプショングループは出てきませんが、取得した商品情報から分かるようです。 https://developer.apple.com/documentation/storekit/skproduct#2940381 AppStoreには、アプリで表示しないプロダクトも登録できて、アプリが扱いプロダクトのIDのリストを渡して、商品情報を得るという流れなので、アプリで表示する商品はアプリで制御ということになるのではと思います。 (edited)
Avatar
すみません私が勘違いしてました🙇 アプリ側の表示はアプリで制御できますね、失礼しました🙇
Avatar
AppStoreで設定したプロダクトが設定アプリだと自動で表示されてしまうと、アプリの表示と差が出てしまいますので、設定アプリには何が表示されるのか気になっています。
表示非表示が可能かどうかは分かりませんが、購読しているグループしか表示されないようですね
5:12 AM
購読しているサブスクリプションにアプリで表示していないプロダクトも表示される?
Avatar
購読しているサブスクリプションにアプリで表示していないプロダクトも表示される?
おそらく表示されると思います。 ちなみにサブスクリプショングループが複数ある場合は購読しているアイテムが存在するグループのみが表示されるようです。 https://developer.apple.com/forums/thread/87410
Avatar
サポートに質問してみるのはどうでしょうか? 自分も質問してみようとしたのですが、アプリ内課金のアプリを持っていないので、質問できませんでした。 また、直接質問できる機会がありますので、それを活用するとかはいかがでしょうか? https://developer.apple.com/events/view/upcoming-events?shouldHideClosedEvents=true もしかしたら、できないというより、許していない可能性もございますので。
t_kansha 1
Avatar
質問です。 iPad専用のアプリを今まで作っていたのですが、iPhone版も出したい気持ちになってきてしまいました。 SwiftUIで実装しているのですが、世の中のアプリはこう言う時どのような実装方法をとっているのでしょうか? 自分が知っているのは以下の実装方法です。
  • Geometry Readerを使って実装する(この場合fontのsizeを変えるのに結局条件分岐が必要になってしまう?)
  • iPadかiPhoneで条件分岐をする
  • targetをiPad用とiPhone用で分けて実装する おすすめの実装方法があれば教えていただきたいです。
Avatar
場合によりけりなことが多いですが、基本的には分岐を少なくしたいのでiPadでもiPhoneでも問題なく動くようなレイアウトを組む、のが一番ですね
11:31 PM
マージン以外で絶対値を使用しない、スクロール可能にする、フォントもシステムフォントを使って可変サイズにする、など色々工夫の余地があります
Avatar
Avatar
Iceman
場合によりけりなことが多いですが、基本的には分岐を少なくしたいのでiPadでもiPhoneでも問題なく動くようなレイアウトを組む、のが一番ですね
回答ありがとうございます。 システムフォントを使って可変サイズにするのはどうやるのでしょうか? 画面幅に応じて可変サイズになるようにオリジナルのモディファイアを実装したりすると言うことでしょうか?
Avatar
SwiftUIにおいては何もしなくてもdynamic Typeに対応していたと思います。端末のフォントサイズ設定を変えてみてください
1:28 AM
dynamic Type対応をすると自然と分岐のいらないレイアウトになってると思いますが、分岐のいらないレイアウトを組んだ後の一手先の話でした。趣旨がずれていたので忘れてください (edited)
Avatar
Avatar
Iceman
場合によりけりなことが多いですが、基本的には分岐を少なくしたいのでiPadでもiPhoneでも問題なく動くようなレイアウトを組む、のが一番ですね
まずは分岐のいらないレイアウトを組むのが基本ということですね。ご丁寧に回答いただきありがとうございます!
Avatar
iPadの場合はSplit Viewに正しく対応できていれば自然とiPhoneにも対応したコードになってると思います
Avatar
サイドバー (NavigationSplitView) とタブバー (TabView) を切り替えるなどどうしても分岐が必要な場合は,例えば Apple の標準アプリだと @Environment(\.horizontalSizeClass).regular なのか .compact なのかによって切り替えているので,それを真似するとうまくいくことが多いですね.
Avatar
自動更新サブスクリプションのプランを新規購入、既存の更新ともに停止したいのですが「配信から削除」するとアプリ側でも即SKProductを取得できなくなるのでしょうか? (その場合既存の購読者はどうなるの?) サンドボックスやStoreKit Testingでテスト可能であればしたいのですが方法がわかっていません。 https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-availability-for-an-auto-renewable-subscription/ (edited)
Avatar
最近はStoreKit Configuration Fileを用意すればローカルでもテストできるようになりました。 サンドボックスでのテストですが、デバッグ版とAdHoc版でテストできます。 https://developer.apple.com/documentation/storekit/in-app_purchase/testing_at_all_stages_of_development_with_xcode_and_the_sandbox テストで使用するApple IDはApp Store ConnectのユーザーとアクセスのSandboxテスターで登録したものです。サンドボックスでのテストは、更新頻度が短くなっているので、更新のテストなどが試しやすくなっています。
Verify your implementation of in-app purchases by testing your code throughout its development.
Avatar
サンドボックスでのテストはApp Store Connectで用意している環境を実際に課金される事なくテスト出来るものと理解してます。 であれば、配信から削除してしまうと実際のユーザーにも影響があるのでこのようなケースではテスト出来ないのでは?と思いました。
Avatar
別バンドルIDで確認するのはどうでしょうか? また、配信から削除はプロダクトとしては削除されないのではと思います。逆にプロダクトは削除できないと思います。プラットフォームの方針として。 (edited)
Avatar
別バンドルでテストする際、プロダクトのskuはテスト用にして、テスト用プロダクトの挙動を確認するにした方が、事故らないで安心ではないかと思います。
👀 1
Avatar
ネストされたstruct内にTopレベルと同じ名前のstructがある場合でも、Topレベルのstructを指定する方法はありますか? struct User { } struct Nest { // TopレベルのUserにしたいがNest.Userになってしまう let user: User struct User { } } let value = Nest(user: .init()) print(value) (edited)
Avatar
Kishikawa Katsumi 10/15/2023 12:28 PM
<モジュール名>.User で参照できます。
12:32 PM
モジュール名はライブラリだったらライブラリ名、iOSアプリケーションだったらアプリケーション名になるはずです。
Avatar
すいません1つ忘れていました。 ライブラリ名と同じ名前のstructがある状態でした。そのため名前の干渉をしていました。
GitHubAPIというライブラリで、GitHubAPIという名前のstructがある
この場合の解決策はあるでしょうか?
(edited)
Avatar
Kishikawa Katsumi 10/15/2023 1:18 PM
確かにその場合はモジュール名が参照できなくなるので上記では解決しませんね。 トップレベルのstruct User { } に対してTypealiasを設定するというのはどうでしょう? struct User { } typealias U = User // これを追加する。 struct Nest { // TopレベルのUserにしたいがNest.Userになってしまう let user: U // typealiasで参照する struct User { } }
Avatar
ありがとうございます。うまくいきました!
Avatar
モジュール名とトップレベルの型名が重複している場合、トップレベルの型名がモジュール名を上書きしてしまって修飾名でアクセスできないです。
2:20 PM
なのでモジュール名に型名とかぶる名前をつけないほうが良い事が知られていて
2:21 PM
swift-collections などでは DequeModule などのように モジュール名に Module サフィックスを付けられていたりします。
2:22 PM
そのライブラリも GitHubAPIModule などにモジュール名を変えたほうが良いと思います。
Avatar
そのモジュールが自分で作ったものじゃない場合,そう言うパターンって moduleAliases で解決できませんでしたっけ? https://github.com/apple/swift-package-manager/blob/main/Documentation/ModuleAliasing.md
The Package Manager for the Swift Programming Language - apple/swift-package-manager
Avatar
Avatar
kebo
そのモジュールが自分で作ったものじゃない場合,そう言うパターンって moduleAliases で解決できませんでしたっけ? https://github.com/apple/swift-package-manager/blob/main/Documentation/ModuleAliasing.md
完全に忘れてました。そのとおりですね。まさにその機能の用途の一つ。
Avatar
そんなのがあったんですね。使用側でも指定できるのですね。
Avatar
@udo223 サブスク削除について質問しました。回答をそのまま掲載してはよろしくないのかなと思いまして、自分の方でまとめてみます。
  • 自動更新サブスクをストアから削除する場合は、サブスク機関の合わせてタイミングを測るのはおすすめ。
  • 新規ユーザーが購入するのを防ぐのと、既存ユーザーの更新を防ぐため。
  • 削除をユーザーに伝える。プロモーションをやめる。
サブスクを削除しても既存ユーザーが継続して利用する、ということはできないとのことです。
(edited)
Avatar
Avatar
m_yukio
@udo223 サブスク削除について質問しました。回答をそのまま掲載してはよろしくないのかなと思いまして、自分の方でまとめてみます。
  • 自動更新サブスクをストアから削除する場合は、サブスク機関の合わせてタイミングを測るのはおすすめ。
  • 新規ユーザーが購入するのを防ぐのと、既存ユーザーの更新を防ぐため。
  • 削除をユーザーに伝える。プロモーションをやめる。
サブスクを削除しても既存ユーザーが継続して利用する、ということはできないとのことです。
(edited)
ありがとうございます!! 2ヶ月前からユーザーに数回アナウンスして削除することにしました (edited)
Avatar
#beginner-help というチャンネルで、フォーラム機能の試験運用をやっています。良ければ試して感想を教えてください。
👏 5
Avatar
https://discord.com/channels/291054398077927425/1173963500167626843 投稿してみました!よろしくお願いします!
Avatar
よろしく、お願いします。 すいません、全くの初心者なので、申し訳ございません。 Xcodeを、ダウンロードしました。 2021年10月発行の、本に基づいて勉強しました。 簡単な地図アプリを、作ってみました。 次に、日記アプリを作ってみようと、2015年12月発行の本を、開いてみました。 そうしたら、本のXcode画面が、Macの画面と、全く違っていました。 例えば、本にあるViewController.swiftが、MacのXcodeにはありません。 HelpにViewControllerと入力しても、それらしきものは、表示されません。 2020 ~ 21年ごろに、大幅に変更があったのかな、と思っています。 どうしたら良いか、ご教授いただけると、幸いです。 それと、何年の何月頃に変更になつたのか、教えて下さると、幸甚です。 お手数を、お掛けいたします。
Avatar
@k Xcodeはほとんど毎年大幅な変更があります。現在のメジャーバージョンは15なので、それから数字が離れれば離れるほど、過去の資料はアテにならないです。2015年はSwift出たての頃なので、ちょっと厳しいですね。 どこからはじめるのが良いだろう、今だとiPadのSwiftPlaygroundが丁度良かったりするのでしょうか?
Avatar
早速、お返事いただき、有り難うございます。 「毎年大幅な変更があります。」ですか・・・。 カレンダー(スケジュール)アプリを作りたいと思っています。 参考になる、本は、ございますでしょうか。 お教えいただけますと、幸いです。
Avatar
Xcodeの変更で躓きたくないのであればSwiftUIチュートリアルでレイアウト周り学んでカレンダー作っていくのがよさそう。 https://developer.apple.com/tutorials/swiftui 最初からカレンダーや日記を作るチュートリアルみたいなのはあんまり見かけないので、手元の本で進めたいのであればXcodeとかSwiftの変更箇所を調べながら進めていくのがよさそう。 毎年大幅に変わるとは言ってもそんなに破壊的な変更は無いので時間かけて調べていけばいけるはず (edited)
SwiftUI is a modern way to declare user interfaces for any Apple platform. Create beautiful, dynamic apps faster than ever before.
4:37 AM
多分ViewController.swiftが無いっていうのはプロジェクト作る時にSwiftUIのプロジェクトとして作ってるからかな
naruhodo 1
t_sorena 1
Avatar
SwiftUIチュートリアル、お教えいただき、ありがとうございます。 学んでみます、深く感謝申し上げます。
Avatar
https://apps.apple.com/jp/app/swift-playgrounds/id1496833156?mt=12 ちょっと実際に触ったわけではないのでエアプになってしまって恐縮なんですが、SwiftPlaygroundsでコーディングの基礎が学べるのでやってみても良いかもしれません。
‎Swift Playgroundsでは、楽しみながらプログラミングを学び、本物のAppを作ることができます。“コーディングを始めよう”では、説明に従ってインタラクティブな問題に取り組み、“Appの作成を始めよう”では、Appを作成するための基礎を身につけます。さまざまな課題やサンプルを試すことで、ユニークなコーディング体験が得られます。 Swift Playgroundsはプログラミングの経験がなくても遊べるので、8歳から108歳まで、これからプログラミングを始めようという方にピッタリです。Appleが開発し、世界中で多くの人気Appの作成に使われているパワフルなプログラミングテクノロジーで…
Avatar
ご親切な、アドバイス、有り難うございます。 深く深く、感謝申し上げます。
Avatar
初投稿です 自分はアニメーターです アニメの勉強のために自作の練習ツールを作りたいのですが、 ・動画読み込みボタン ・再生・停止・スキップボタン
 ・コマ送りボタン
 ・コマ送りフレーム数指定ボタン ・自動コマ送りボタン
 ・自動コマ送り秒数指定ボタン 以上のUIを備え、 ①ファイルをドラッグ&ドロップでユーザーがmp4ファイルを読み込ませることができる ②以上の読み込ませたmp4ファイルに以下の操作を実行させられる ・等速で再生・停止、10秒スキップ
・1フレームごとにコマ送りさせることができる(コマ送りするフレーム数を1~5の範囲で設定できる) ・30秒ごとに1フレームずつ自動でコマ送りできる(秒数を15秒、30秒、60秒を設定できる) こんな感じのMAC OS用のアプリを作りたいです 必要になれば自力で機能を追加したいので自力でコードを書くべく、Xcode上でググりながら試行錯誤していたのですが限界を感じここで質問させていただく形になりました 以上の条件では素人がDIYするのは難しかったりしますでしょうか 恐縮ですが教えていただけると幸いです。
Avatar
AVPlayer など基本的なコンポーネントを組み合わせていけば作れる仕様だと思うので、 初心者が挑戦するのにちょうどいい課題感だと思います。 AVPlayer: https://developer.apple.com/documentation/avfoundation/avplayer/ ただmacOS向けの開発の情報はネット上も書籍も少ないのでそこが難しいかもしれません。 あと「フレーム単位でシークする」のは実はちょっと難しいです。 動画のデータ構造ってフレームレートが一定とは限らない作りになっているので、プレイヤーに対して「1フレーム進める」みたいなフレーム単位操作の司令ができないからです。 (ビデオデコーダを直接制御すればできますが、実装難易度が一気に増加します) まあアニメのデータの場合は実際のところ安定しているでしょうから、そのへんは ↓のseekメソッドに渡すtorelanceパラメータに前後 0.5フレーム幅を渡したら現実的にはうまくいくと思います。 https://developer.apple.com/documentation/avfoundation/avplayer/1387741-seek
Avatar
Avatar
omochimetaru
AVPlayer など基本的なコンポーネントを組み合わせていけば作れる仕様だと思うので、 初心者が挑戦するのにちょうどいい課題感だと思います。 AVPlayer: https://developer.apple.com/documentation/avfoundation/avplayer/ ただmacOS向けの開発の情報はネット上も書籍も少ないのでそこが難しいかもしれません。 あと「フレーム単位でシークする」のは実はちょっと難しいです。 動画のデータ構造ってフレームレートが一定とは限らない作りになっているので、プレイヤーに対して「1フレーム進める」みたいなフレーム単位操作の司令ができないからです。 (ビデオデコーダを直接制御すればできますが、実装難易度が一気に増加します) まあアニメのデータの場合は実際のところ安定しているでしょうから、そのへんは ↓のseekメソッドに渡すtorelanceパラメータに前後 0.5フレーム幅を渡したら現実的にはうまくいくと思います。 https://developer.apple.com/documentation/avfoundation/avplayer/1387741-seek
ありがとうございます 参考にしてみます mp4データをファイルピッカーで取り込めるようにしたいんですけど参考などありますか
Avatar
この辺の解説を読むと良さそうです https://developer.apple.com/documentation/appkit/drag_and_drop このサンプルを動かして、コード読んでみたら、わかりそう https://developer.apple.com/documentation/appkit/documents_data_and_pasteboard/supporting_drag_and_drop_through_file_promises
Avatar
player.currentItem?.step(byCount: 1)
5:58 AM
じゃだめですかね...
6:03 AM
雑ですが。
😲 1
Avatar
こんなのあったんですね、知らなかったです。 そして AVPlayer じゃなくて item のメソッドを直接叩いてもいいのか。
Avatar
1. DocumentGroup (Document based app)でファイル開くなどを手抜き (Documentはつかってない) 2. VideoPlayer は playback controller 消せないので AVPlayerView を自分でwrapしてる。これは残念ながら必要。 3. @Observable つかってるので macOS 14 いります 4. 一度再生したらseekする方法がないので1フレームづつ戻るか再起動するしかないw
6:06 AM
ちょっと手抜きとかで変なところ(Document based appのくせに使ってない)があるけれど、わりとシンプルに実装できたかなと思います...
6:08 AM
ちなみに、Document 真面目に実装すると、NSDataからAVAsset作るというかなりだるい実装が必要になるので... Document based にしないで、onOpen(url:) と onDrop(of:isTargeted:perform:) 自分で実装する方が早いかも。 (edited)
6:09 AM
ただしその場合、NSItemProvider の非同期処理が入るのでちょっと面倒かも。 (edited)
6:10 AM
ファイルタイプを無視して(public.movieじゃなくても)いいなら、dropDestination(for:action:isTargeted:) にURL.selfのほうが楽かな? (edited)
6:13 AM
Discoardにzip貼り付けると危ないぞっ!てでるのかw
6:14 AM
GitHubより気軽でGistよりGitHubな場所が欲しい
👈 1
Avatar
AVFoundationとAVKitって何が違うんですか?
Avatar
別のmoduleですね
8:25 AM
AVFoundationのほうが低レベルのAPIかな... (edited)
Avatar
あれ?逆かと思ってました
Avatar
AVKitはUIまわりのはず
Avatar
ボタンとテキストを配置するところまではいけたんですけどAVPlayerのurlをファイルパスから指定する方法で頓挫してます
Avatar
Avatar
niw
AVKitはUIまわりのはず
とりあえずAVKitを使ってます
Avatar
Bundle.main.url使ってもダメです...
Avatar
init使って解決しました
Avatar
Stepperを操作した時に関数を呼び出したいのですが可能でしょうか
Avatar
テーブルを横に並べることは可能でしょうか
noppe started a thread. 11/21/2023 3:21 PM
Avatar
Avatar
niw
player.currentItem?.step(byCount: 1)
動画の総フレーム数と現在のフレーム数を取得することは可能ですか?
Avatar
Avatar
Bela Kudaken
とりあえずAVKitを使ってます
import で読み込まれるmoduleは、ほとんどの場合 transitively に依存するmoduleを読み込みます。通常はそのスコープ(ファイル)で最も最小のmoduleを読み込む方が名前空間の処理などを考えてもおすすめです。AVPlayerはAVFoundationにあるAPIです。AVKitが必要になるのは、AVPlayerViewを使う場合なので、VideoPlayer()を使う上では必要ありません。
Avatar
Avatar
Bela Kudaken
動画の総フレーム数と現在のフレーム数を取得することは可能ですか?
frameRateや現在の時間が取れるので、割り算で取れると思いますが... step(byCount:)は多分そこまで正確ではないので、真面目にやるともうちょっと工夫が必要な気がします。 いや、これちょっと難しいな。AVAssetのAPIがほとんどasyncになってて、相当面倒な記述が必要だ... (edited)
Avatar
Original message was deleted or could not be loaded.
老婆心というか... 仮置きの文字とかでもあまりこういうコミュニティで共有することを考えると公共の場で大声でいっても問題ない文字列を使用することをお勧めします。ちなみに、この Discord は完全にインターネットに公開されていて、検索もできます...
Avatar
Avatar
niw
老婆心というか... 仮置きの文字とかでもあまりこういうコミュニティで共有することを考えると公共の場で大声でいっても問題ない文字列を使用することをお勧めします。ちなみに、この Discord は完全にインターネットに公開されていて、検索もできます...
すみません、ふざけて使ってました
Avatar
いちおうできたけどこれ初学習でつくるの結構大変です
2:33 AM
複雑さの原因はさきのコメントでもちょっと書いたのですが、video周りのAPIが全部asyncになっていて、それをUIと連携させるのにゼロからだとわりと複雑な実装が必要です (edited)
2:38 AM
よければ参考にしてください...
2:39 AM
2:40 AM
簡略化するなら、多分最初一回めで全部この辺計算して変わらない前提で state とかに覚えてしまうのが良いかも。
2:41 AM
あとminimumFrameDurationから全部計算してるけど多分間違ってるよなあ...
Avatar
前似たようなの作ったことあるんですが、可変フレームレートまで考慮すると一度全部舐めないといけないの大変ですよね
Avatar
ですね...
Avatar
大抵はこれでそれっぽい数値はでるけど、正確ではない
Avatar
一応アニメが前提になってるのでフレームレートは24固定でいいです
Avatar
真面目にやると現時点でのframeのdurationとってこないといけない...
Avatar
1フレームずつ正しく確認したい場合、このへんがズボラだと1フレーム何故か抜けたりしちゃうんですよね
Avatar
movieファイルからfpsとか取ってこなくてよくてそう言う固定値なんだ、っていうことなら全部固定値で時間だけ計算すればよかも。
Avatar
Avatar
Iceman
1フレームずつ正しく確認したい場合、このへんがズボラだと1フレーム何故か抜けたりしちゃうんですよね
ですね... この実装は抜けます
Avatar
Avatar
時間とカウンタは進むけど...
Avatar
一応ここまで行けました
2:44 AM
力技なんですけども
Avatar
すごい
Avatar
コマ数出てるやついいですね
Avatar
var time:Float64 = CMTimeGetSeconds(player.currentItem!.currentTime())*24 time = currentPlayerFrame + Double(frameStep) let cm :CMTime = CMTimeMakeWithSeconds(time/24, preferredTimescale: 24) player.seek(to: cm,toleranceBefore: .zero, toleranceAfter: .zero) currentPlayerFrame += Double(frameStep)
2:44 AM
これでなんとか
2:44 AM
初めてでしたがなんとかなりました
Avatar
.zero, .zero だと seek(to:) と同じことなのでいらないかも。
Avatar
これ消したらバグるんですよ
Avatar
同じなのは.infinity, .infinityの場合っぽいですね
Avatar
あー、そうか
Avatar
Passing kCMTimePositiveInfinity for both toleranceBefore and toleranceAfter is the same as messaging seek(to:) directly.
https://developer.apple.com/documentation/avfoundation/avplayer/1387741-seek
Avatar
なるほどなるほど
Avatar
だから大雑把なシークになってバグってるように見えるんだと思います
Avatar
上の文字はデバッグ用で 一番上から動画の現在時刻(秒)*24 真ん中がcurrentFrame(スクリプト上で制御している変数のフレーム数) 一番下が動画の総尺です
Avatar
fps (or duration per frame) 固定なら時間が信頼できるから多分動くですよね (edited)
2:48 AM
そういうのファイルからちゃんと読もうとすると大変なことにw
Avatar
例えば24fpsのところ 12.5フレームのところで止めれば切り捨てで12フレームにseekするようにしました
2:49 AM
後は下のタイムラインをなんとかしたいのですが
Avatar
現在地がスクロールの範囲外にいっちゃうのをなんとか、って言う感じですかね
Avatar
2:51 AM
一番上が秒、 その下が24フレーム刻みのフレーム 一番下が現在表示してるフレームをしめす青四角です (edited)
2:53 AM
この青四角を一つ上のフレームのボックスの真下に表示させたいんですよね
2:53 AM
2:54 AM
現在0フレーム目に表示してるので、0+1フレームの一番左の箱の下です
2:59 AM
いやいけました!...が
3:00 AM
3:00 AM
なんかスクロールバーがめちゃバグります
Avatar
paddingなのか...
Avatar
3:14 AM
なんとかスクロールバグ問題は解決したのですがCGFLoatがマイナスになると言うことを聞いてくれなくなります
Avatar
paddingは余白を決める機能なので、負の値は受け付けられないですね。 Viewの位置調整はoffsetやpositionを使うのが良いです。 viewに細かく色を付けたりしてデバッグすると、実際に何が起きているかを観測しやすくなります。 (edited)
Avatar
そうなんですね...助かります。 ありがとうございます
Avatar
これはlazyhgridなのかな?
Avatar
そうですね
Avatar
だとしたらこの青い四角もgridの一部できる気がするけれど...
Avatar
いやすみませ
3:21 AM
んLazyHStackでした
Avatar
LazyHGrid { ForEach(frames) { VStack { Text for second; Text for frame; Ragtangle for frame; Rectangle for current frame} } } みたいな。あんまつかったことないのではっきりこれでできる、みたいなことは言えないですが...
Avatar
やってみます
Avatar
ああ、LazyHGridはGridItemとサイズを渡すのか。できそう。
Avatar
Avatar
niw
ああ、LazyHGridはGridItemとサイズを渡すのか。できそう。
LazyHgridのrowsってなんですか?
Avatar
ScrollView(.horizontal) { LazyHGrid(rows: [ GridItem(.fixed(30.0), spacing: 0.0), GridItem(.fixed(30.0), spacing: 0.0), GridItem(.fixed(30.0), spacing: 0.0), GridItem(.fixed(10.0), spacing: 0.0) ], spacing: 0.0) { ForEach(0..<frames, id: \.self) { frame in if framesPerSecond != 0 && frame % Int(framesPerSecond) == 0 { let seconds = Int(Double(frame + 1) / framesPerSecond) Text("\(seconds)") .frame(width: 30.0) } else { Spacer() .frame(width: 30.0) } Text("\(frame)") .frame(width: 30.0) Rectangle() .stroke(lineWidth: 1.0) .frame(width: 30.0) if frame == animationPlayer.currentFrame { Rectangle() .fill(.blue) .frame(width: 30.0) } else { Spacer().frame(width: 30.0) } } } } (edited)
3:34 AM
雑にこんな感じかと...
3:34 AM
rows: で GridItem を使って、縦方向の大きさや空き幅グリッドの数を指定する感じっぽい (edited)
Avatar
Avatar
niw
rows: で GridItem を使って、縦方向の大きさや空き幅グリッドの数を指定する感じっぽい (edited)
ありがとうございます! いけました!
💯 1
Avatar
.scrollTargetLayout()をLazyHGridにつけて、ScrollViewに.scrollPosition(id: $scrollPosition)とかして、scrollPositionをframeが変わったときに調整すれば自動でスクロールできるようになります。 https://github.com/niw/AnimationPlayer/blob/master/AnimationPlayer/Sources/AnimationPlayerView.swift#L107-L111 (edited)
Avatar
Publishing changes from within view updates is not allowed, this will cause undefined behavior.
4:35 AM
と出る問題はどうすればよういでしょうか
4:37 AM
4:38 AM
ゲージのvalueで自作したTimeLibra関数を呼び出し
4:38 AM
4:42 AM
timeLibra関数で上から ①タイマー残り時間>設定していた時間だった場合1を返す ②タイマー残り時間が0を下回った場合コマ送り(もし動画の長さ上限よりコマ送りする場合動画の最後のフレームにseek) ③タイマーのタイマー残り時間が0を下回っていないばあいタイマー残り時間/設定していた時間を返す
4:43 AM
このうち②の pleyer.seekと currentPlayerFrame+=Double(frameStep) が動いてくれません (edited)
4:44 AM
print上では通ってくれてるんですが
Avatar
Avatar
Bela Kudaken
このうち②の pleyer.seekと currentPlayerFrame+=Double(frameStep) が動いてくれません (edited)
解析したらpleyer.seekは動いていたのですがcurrentPlayerFrame+=Double(frameStep)が動いてくれてません
Avatar
currentPlayerFrameってViewのstateですか?
Avatar
Avatar
niw
currentPlayerFrameってViewのstateですか?
今表示しているフレーム数です
Avatar
@State 付きで View の struct に body の外に書いてあります?
Avatar
6:02 AM
こんな感じです
Avatar
ですね。
6:03 AM
SwiftUIがUIとして動作する仕組みは、@state で指定された変数(など)で表される「状態」が変わったときに、body を再評価してその結果(View という画面を作る設計図的な画面の定義)を元に画面を描画します (edited)
6:05 AM
なので、body を評価しているときに、Guage(value: timeLibrar()) を評価して、そのときに timeLibra() を評価して、そのときに @StatecurrentPlayerFrame が変更されてしまいます。 (edited)
6:06 AM
すると、SwiftUI 的には、あれー、「今」の状態で bodyView つくったのに作ってる間に状態変えられた...って思うわけですよ (edited)
Avatar
ひえー
6:06 AM
そうなんですね
Avatar
で、じゃあまたbodyつくるかーってなると、無限に繰り返すことになりますよね。
6:06 AM
だから、それはしないんだけど、もう「今」の状態ではないViewができちゃったので、
6:06 AM
warningが出たのです
Avatar
なるほど
6:07 AM
@state外してやればいいってことですか
Avatar
えーっとまず currentPlayerFrame が変わったときになにが起こるか考えてください
6:09 AM
もし、その変数の状態が描画に影響を与えるなら、それは「状態」です。なので @State は必要でしょう。
6:12 AM
ちょっとコード全体が見えないのでなんとも言えませんが、通常あるfunctionを読んだときに状態を変えるようなものをViewの地の文からは呼べません。なので、もしそのfunctionが他の状態を変えるようなものの場合は、onChange(of:) で副次効果として読んだり、状態がわに押し込んだり(@Observableなview model を作ったり)一つのデータの流れを作る必要があります (edited)
6:13 AM
あるfunctionが値を返すときに、外の世界かえちゃったりする function はとある業界では副作用があると言って、こういう問題がおこるので嫌われます (edited)
Avatar
onChangeって画面更新のタイミングで毎回呼ばれるんですか?
Avatar
ほかのSwiftUIが監視してる状態が変わったとき、かな。of: で指定します。 (edited)
6:15 AM
画面更新のまさにそのタイミングではなかったかな... (edited)
Avatar
とりあえずやってみます 親切にありがとうございます
Avatar
Avatar
niw
ほかのSwiftUIが監視してる状態が変わったとき、かな。of: で指定します。 (edited)
できました! 本当にありがとうございます!
👍 1
Avatar
簡単な質問ですみません forを逆順で回すにはどうすればいいですか
7:48 AM
解決しました
Avatar
おかげさまでここまで作れました
✨ 2
👏🏻 2
9:03 AM
あとはファイルドロップで動画をすり替えられるようにするだけです
Avatar
Avatar
Bela Kudaken
あとはファイルドロップで動画をすり替えられるようにするだけです
これcocoaじゃないとできないんですか
Avatar
Avatar
Bela Kudaken
これcocoaじゃないとできないんですか
そんなことないですよ
9:13 AM
一番簡単な、UIだけでやる方法は dropDestination(for:action:isTargeted:) を App なかで ContentView につけて、そこでURL.selfを指定することですね。 (edited)
9:15 AM
でも、dockのアイコンにdropとかに対応するためには 1. Info.plist にCFBundleDocumentTypesを追加する、2. onOpen(url:) を追加する、が必要です
9:16 AM
あるいは、DocumentGroupをつかってDocument-based AppにしてURLだけ使うという手抜きの方法もありますね。その場合1画面1ビデオになったりいろいろ状態保存されたりmacアプリらしい動作をします (edited)
9:17 AM
その場合でも Info.plist にCFBundleDocumentTypesを追加するのは必要です。
Avatar
Avatar
Avatar
niw
一番簡単な、UIだけでやる方法は dropDestination(for:action:isTargeted:) を App なかで ContentView につけて、そこでURL.selfを指定することですね。 (edited)
receivedTitlesやらなんやらの意味がわからないです
Avatar
locationは無視していいです、どこのdropしたかの座標だったかな。
9:34 AM
なんでtitlesって名前になってるかわからないですが、それがdropされたファイルのURLの配列になってるはずです
9:34 AM
複数のファイルがdropされることもあるので。
9:35 AM
gurad let url = urls.first else { return } みたいに最初1つだけ取って使ってみてください
Avatar
9:36 AM
これでいいんですか
Avatar
.dropDestination(for: URL.self) { urls, _ in guard let url = urls.first else { return } ... }
9:37 AM
こんな感じ
Avatar
9:39 AM
こうですか
9:40 AM
この下にplayer=AVPlayer(url:url)ってやればええんですか
Avatar
まあそうですね
9:41 AM
@State player = ... になっていれば。
9:41 AM
urlをstateにするか、playerをstateにするかで変わってきます
9:41 AM
後者ならそれで動くはず
9:42 AM
あー、これbool返さないといけないので、guardのelseはreturn falseにしてください
9:42 AM
player = AVPlayer(url: url) のあとに return true もいります
Avatar
Avatar
Avatar
niw
player = AVPlayer(url: url) のあとに return true もいります
一番下のところでエラーが出ます
Avatar
.dropDestination(for: URL.self) { urls, _ in guard let url = urls.first else { return false } player = AVPlayer(url: url) return true }
9:45 AM
です
Avatar
ありがとうございます
Avatar
guard 〜はguard 構文なので else ... みたいな書き方をします: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow/#Early-Exit
Avatar
できました 完成です
💯 1
9:47 AM
本当にありがとうございます
9:48 AM
手助けがなければ初めてでここまでできることが絶対できませんでした
👍 1
🎉 2
Avatar
最後の最後でBuildができません...
11:32 AM
😢
Avatar
なんか player.assets.durationがダメみたいでplayer.assets.load(.duration)を代用しなくちゃいけないみたいなんですがtry awaitだのasyncだのでめちゃくちゃなことになってます
12:17 PM
できる限り自力で頑張ったのですがここでErrors thrown from here are not handledと出てしまいます
12:21 PM
do catchでなんとかしました
12:26 PM
できました!!
Avatar
Buildしたはいいものの開いた瞬間落ちるんですけども
😭 1
Avatar
breakpoint navigator開いて、 Swift ErrorSwift Error BreakpointException Breakpoint 追加して実行したら、落ちる直前で実行がとまったりしないですかね?
Avatar
Avatar
ありぜ
breakpoint navigator開いて、 Swift ErrorSwift Error BreakpointException Breakpoint 追加して実行したら、落ちる直前で実行がとまったりしないですかね?
Build/Products/Debug/の中に入ってたやつなんですけどもこれって正しいビルドデータなんですか
Avatar
Avatar
Bela Kudaken
Build/Products/Debug/の中に入ってたやつなんですけどもこれって正しいビルドデータなんですか
すみません
Build/Products/Debug/
がなにを指しているのかちょっとわからないです
Avatar
Avatar
ありぜ
すみません
Build/Products/Debug/
がなにを指しているのかちょっとわからないです
すぐ落ちたデータが格納されていた場所です
1:29 PM
普通のRunは問題なく動作します Buildすると問題が起きます
Avatar
今10分ほど通話できる方いますか
1:36 PM
通話しながらビルドの手順を教えていただけないか...
Avatar
Avatar
Bela Kudaken
すぐ落ちたデータが格納されていた場所です
なるほど
Build/Products/Release/
↑がApp Store等で配布されるDebugに不要な情報を抜いたものが生成される場所で
Build/Products/Debug/
↑は、Appを作っていく上でDebugに必要な情報等が入ったものが生成される場所なので、 Appを作る上で正しいビルドデータではあります
Avatar
Avatar
ありぜ
なるほど
Build/Products/Release/
↑がApp Store等で配布されるDebugに不要な情報を抜いたものが生成される場所で
Build/Products/Debug/
↑は、Appを作っていく上でDebugに必要な情報等が入ったものが生成される場所なので、 Appを作る上で正しいビルドデータではあります
すぐ落ちたのはやっぱりデータが悪いってことですかね
Avatar
Avatar
Bela Kudaken
すぐ落ちたのはやっぱりデータが悪いってことですかね
もしかして、
Build/Products/Debug/
に生成された 作成した.app を直接double click等で実行しようとしてすぐ落ちてるという話ですか?
Avatar
そうです!!
Avatar
そこに生成されたものはXcodeからDebug実行時経由で動かすためのものなので、そのまま直接実行しようとしても起動しないです。 一般的には、XcodeのMenuBar(画面1番上のメニュー) > Product > Archive をやってStore等に申請しますが、たぶん個人で使ってStore申請するとかでないのであれば、以下ですかね --- スクショの位置からEdit Schemeを選ぶ > RunBuild Configurationrelease に変更してXcodeからappを実行 Build/Products/Release/作成した.app ができると思いので、これを実行でいけないですかね?
Avatar
ダメでした..
2:02 PM
2:02 PM
デバッグログです 自分のような素人が見てもなにがなにやら
Avatar
・RUNはできます ・BuildしたらBuild Succeedと出ます ・ただしBuild/Products/Release/からダブルクリックしたら落ちます
Avatar
いまから23時30分まででよければ、画面共有してもらいながらで通話どうでしょう? 力になれるかわかりませんが…
Avatar
よろしくお願いします
Avatar
let videoURL: URL = Bundle.main.url(forResource: "Dammy", withExtension: "mp4")! player = AVPlayer(url: url) (edited)
Avatar
皆様のおかげで無事、本当に無事ビルドして完成まで漕ぎ着けることができました! 本当にありがとうございました!
👏🏻 6
Avatar
Avatar
Bela Kudaken
皆様のおかげで無事、本当に無事ビルドして完成まで漕ぎ着けることができました! 本当にありがとうございました!
すみません、Xcodeを閉じてappを起動すると相変わらず即落ちします...
Avatar
Kishikawa Katsumi 11/23/2023 3:19 AM
見ればわかると思うのでプロジェクト全体をアップロードできますか?
Avatar
Avatar
Kishikawa Katsumi
見ればわかると思うのでプロジェクト全体をアップロードできますか?
ありがたや... こちらです
3:52 AM
きったないコードですが...
Avatar
Kishikawa Katsumi 11/23/2023 3:56 AM
これはプロジェクトファイルしか含まれてませんね。プロジェクトのフォルダ全体を共有してください。
Avatar
プロジェクトフォルダ全体ってどこにありますか?
3:59 AM
無料大容量 ファイル転送サービス GigaFile(ギガファイル)便!「3日~100日」選べる7種類のファイルの保持期限に加え、1ファイル300Gまでアップロード、共有可能!もちろん容量無制限でアンチウイルス装備。会員登録も不要です。
3:59 AM
これで大丈夫ですか?
Avatar
Kishikawa Katsumi 11/23/2023 4:01 AM
大丈夫そうです。このコードで調べてみます。
Avatar
ありがとうございます.... ありがとうございます....
Avatar
Kishikawa Katsumi 11/23/2023 4:48 AM
@Bela Kudaken これは難しいですね。わからなくて当たり前です。 AppleのバグでAVKit.frameworkを明示的にリンクしないと起動時にAVKit.frameworkが読み込めなくてクラッシュするみたいです。 AVKit.frameworkを明示的にリンクする方法は実際の作業の画面録画を添付するのでそれを見てやってみてください。
4:50 AM
プロジェクトファイルの青いアイコンを選択して、GeneralタブのFramework, Libraries, and Embedded Contentセクションの「+」ボタンを押してAVKit.frameworkを追加、です。
4:50 AM
録画の最後の方を見るとわかるように、この作業をすると、Xcodeから実行じゃなくてビルドされた.appを直接ダブルクリックして起動してもクラッシュしません。 (edited)
Avatar
Avatar
Kishikawa Katsumi
録画の最後の方を見るとわかるように、この作業をすると、Xcodeから実行じゃなくてビルドされた.appを直接ダブルクリックして起動してもクラッシュしません。 (edited)
神様ですか
4:51 AM
ありがとうございます 本当にありがとうございます
4:56 AM
いけたあああああああ
4:56 AM
ここで聞かないと詰んでた案件
Avatar
Kishikawa Katsumi 11/23/2023 4:57 AM
しかしこれはひどいバグだな。Xcodeから起動したときは問題ないっていうのが最悪だ。
Avatar
ググってもググっても出てこなくて
5:00 AM
万事休す状態やったんですよ
5:00 AM
いやもう本当に 本っ当に助けられた (edited)
Avatar
Kishikawa Katsumi 11/23/2023 5:05 AM
これSwiftUIのプレビューもクラッシュして全然プレビューされなかったと思うんですけどプレビューなしで作ってたんすか?
Avatar
Avatar
Kishikawa Katsumi
これSwiftUIのプレビューもクラッシュして全然プレビューされなかったと思うんですけどプレビューなしで作ってたんすか?
なんかAVKit入れたらプレビューできなくなったんで気合いでなんとかしてました
😂 1
Avatar
あー、確かにPreviewクラッシュしてたな。
7:00 AM
あんまり考えてなかった。
7:01 AM
Xcode 15 のバグ?
Avatar
Kishikawa Katsumi 11/23/2023 7:02 AM
https://swiftui-lab.com/videoplayer-bug/ 事象を調べてみるとどうやら3年以上前からそのままっぽいですね。
Using the VideoPlayer view in some macOS versions may result in a crash, with the following message: Note that the crash only occurs when the app is not being debugged. This happens when you launch the app from Finder, instead of Xcode, or if you disable debugging mode from the project’s Scheme. To make matters ... Read more
7:07 AM
LC_LINKER_OPTION がぶっ壊れてるとかかなあ
7:11 AM
.o には入ってるなあ...
Avatar
Kishikawa Katsumi 11/23/2023 7:11 AM
調べたらわかるものですかねえ。 import AVKit って書いてるのにAVKitがリンクされてないっていうのはだいぶおかしな挙動(WebKitとか他のフレームワークは問題ないのにAVKitだけおかしい?)じゃないですか?
Avatar
Load command 53 cmd LC_LINKER_OPTION cmdsize 40 count 2 string #1 -framework string #2 _AVKit_SwiftUI Load command 54 cmd LC_LINKER_OPTION cmdsize 32 count 2 string #1 -framework string #2 AVKit
7:12 AM
import AVFoundationとかAVKitとかしてる.swiftに対する.oにはLC_LINKER_OPTIONはいってるからLinkerのバグっぽい
7:12 AM
SwiftUI独自の問題かな...
7:12 AM
だとしたらこの_AVKit_SwiftUIは怪しそう
Avatar
Kishikawa Katsumi 11/23/2023 7:13 AM
_AVKit_SwiftUIは怪しいですね。
7:13 AM
AVKitの構成がなんか特殊なのか。
Avatar
SwiftUIつかってないモジュールでimport AVKitしたらオブジェクトファイルどうなるかみてみてリンクされるか試してみるのが最初のステップかな
7:16 AM
お、つかない。
7:16 AM
これは怪しい...
7:16 AM
_AVKit_SwiftUIってなんですかね...
7:17 AM
import AVKit _ = AVPlayerView()をコンパイルしてもAVKitしか-frameworkを足されないですね。
7:19 AM
import SwiftUI を足すとこの怪しい_AVKit_SwiftUIが足される
7:20 AM
そしてリンクまでしようとすると JIT session error: Symbols not found: [ _OBJC_CLASS_$_AVPlayerView ]とか言ってくる
Avatar
あれ、なんか再現できないな。ちゃんとlinkしてるように思える
Avatar
タイムラインを自動でスクロールする機能を追加しようとしたところ、@Binding var items: [Item]と入力したらCannot find type 'Item' in scopeと出てきてしまいます
10:17 AM
これってどうしたらいいでしょうか
11:29 AM
あとカウントダウン音を追加しようとしているのですがThread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional valueに阻まれてます
Avatar
前者は、 Item 型が存在しないのに [Item] と指定しているので、入れたい本来の型を指定してあげればよいです。 後者は、 NSDataAsset(name: "CountDown") が音源参照して引っ張ってくることができず nil になっているためクラッシュしています。 NSDataAsset を使うのであれば、
Initializes and returns an object with a reference to the named data asset in an asset catalog.
https://developer.apple.com/documentation/uikit/nsdataasset とあるようにAsset Catalogへ音源を登録必要があると思うので、Asset Catalogに登録してやれば上手くいくかもしれません。
(edited)
An object from a data set type stored in an asset catalog.
Avatar
Avatar
ありぜ
前者は、 Item 型が存在しないのに [Item] と指定しているので、入れたい本来の型を指定してあげればよいです。 後者は、 NSDataAsset(name: "CountDown") が音源参照して引っ張ってくることができず nil になっているためクラッシュしています。 NSDataAsset を使うのであれば、
Initializes and returns an object with a reference to the named data asset in an asset catalog.
https://developer.apple.com/documentation/uikit/nsdataasset とあるようにAsset Catalogへ音源を登録必要があると思うので、Asset Catalogに登録してやれば上手くいくかもしれません。
(edited)
detaの方はうまくいきました Itemの方はRectAngleとかButtonとか入れてやればいいってことですか?
Avatar
Avatar
Bela Kudaken
detaの方はうまくいきました Itemの方はRectAngleとかButtonとか入れてやればいいってことですか?
itemsが何の配列かわかりませんが、型という意味では、↑で書かれてるような型(RectAngleやButton等)を入れてあげればいいです。 itemsに入れて管理したい型名を書けばよいです (edited)
Avatar
Avatar
ありぜ
itemsが何の配列かわかりませんが、型という意味では、↑で書かれてるような型(RectAngleやButton等)を入れてあげればいいです。 itemsに入れて管理したい型名を書けばよいです (edited)
Associates a binding to be updated when a scroll view within this view scrolls.
Avatar
scrollPosition(id:anchor) を説明する上での、scrollView+VStackViewで表示してscrollPositionを指定する例として何かしらの表示する物をItemとして定義して説明しているだけで、実在する型とかではなさそうです scrollPosition(id:anchor) を使うのであれば、structでItem型になるものを独自で定義することになると思います (edited)
Avatar
Avatar
ありぜ
scrollPosition(id:anchor) を説明する上での、scrollView+VStackViewで表示してscrollPositionを指定する例として何かしらの表示する物をItemとして定義して説明しているだけで、実在する型とかではなさそうです scrollPosition(id:anchor) を使うのであれば、structでItem型になるものを独自で定義することになると思います (edited)
ありがとうございます
12:47 PM
やってみます
Avatar
なんか作ったやつが某スタジオに買い取っていただけそうなのですがmac版だと厳しいらしいです windowsでも使えるようにできますか
t_oltsu 1
Avatar
多くの依存ライブラリがmacOS上で成り立っているので、1から作り直すレベルで作業が必要ですね
7:53 AM
SwiftUI、AVFoundationに強く依存していると思うので。
Avatar
ではipad版は
Avatar
iPadなら楽に移植できるんじゃないでしょうか
Avatar
まじっすか
7:54 AM
やってみます!
Avatar
ただコミュニティーのサポートを手厚く受けてできたソフトウェアを個人が商用利用することは際どいラインだと思うのですが、どうなんでしょうね
Avatar
確かにそうですね...
Avatar
Kishikawa Katsumi 11/24/2023 7:57 AM
私は別に気にしないです。
Avatar
業務の質問する人もいたりするし、別に商取引が問題になることは無いと思いますよ
Avatar
Kishikawa Katsumi 11/24/2023 7:58 AM
今回かかわった人ははっきりしてるし気にするなら個別にコンタクトして了承取ればいいと思います。
Avatar
取り引きや、回答者から了解を得ることも含めて良いチャレンジだと思うので頑張って欲しいです
Avatar
Kishikawa Katsumi 11/24/2023 8:02 AM
Windows版作れる人がいたら作ったらよさそうだな。
Avatar
AVFoundationやSwiftUIを移植するのめっちゃマッチョ…
😂 1
Avatar
とりあえずIpad移植を試みてみます 全て皆様のご助力のお陰です! ありがとうございます
Avatar
icemanの懸念は、例えばお客様との間で「windows版出来ます」みたいな責任を取れない約束をした上で、質問として持ってこられても困る、と言うことかな
8:08 AM
ソフトウェアにおける商取引は成果物に対しての責任も含めての値付けになるので、少なくとも売ったソフトウェアで起きる諸問題は自分で解決できるべきではありますね。 私は個人的にはその辺りも含めてチャレンジしたら良いと考えています。 (edited)
Avatar
あいや、僕はアドバイスを中心に生まれた成果物(=一部または多くの実装がアドバイス者のコードになっている)をそのままお金に替えられてしまうのは不快に思う人がいるのかもと思ったためです (edited)
Avatar
よっぽど短いコード片でない限り書いた人に著作権があって、その人の意図に反して使用する(商業利用など含む)と訴えられかねないので注意したほうがいいかもですね。 そこまで厳密にやらないにしても「仕事で困ってて〜」とか「アプリ自体を売る予定があって」などあらかじめどの様に利用されうるかは明示しておくとトラブルを避けやすいかも。
Avatar
その理屈で行くとAWSやGCPがRedisやMySQLを使うのは…😂 (edited)
😂 1
Avatar
MySQLはライセンスされてるから良いんでは? 気になるのはniwさんの書いたコードベースがライセンス明示されてないところくらいかな。beginner-helpであんまり萎縮するような話したく無いけどw
sorena 2
Avatar
成果物の割合で行くと、質問する前からそこそこ形になっていそうな感じはしてたけど…中身は見てないのでわからん
Avatar
AVFoundationとSwiftUIにフル依存してるからWindowsサポートは全部作り直す事になりそう
8:23 AM
1.ビデオ処理層をffmpegに切り替える 2.ビデオ処理層とUIのインターフェースを抽象化して分離する 3.具象としてWindowsのUI実装を注入する (edited)
8:24 AM
WindowsはいまはC#がメインだけどC++からも使えるんだったかな? それならSwiftのC++ interopが役に立ちそう
8:26 AM
かなり難易度は高いけどSwift for Windowsのアプリケーションが広く商用利用される事になったら嬉しいですね。 (edited)
Avatar
サポートを受けたこと気にするなら、例えば謝辞としてクレジットするといいんじゃないかな。
Avatar
Kishikawa Katsumi 11/24/2023 1:16 PM
あ、それがキレイだ。
Avatar
えっと、僕のコードはMITです。他の方のアドバイスやコードがどのような立場で考えられるかはわからないですが... (edited)
9:57 PM
少なくとも参考に作った最初にここにはったzipファイルや、同じもののGitHubにあるプロジェクトはMITと明記してありますし、ここに貼ったのもその一部がほとんどなのでMITです。 (edited)
9:59 PM
なので、まあ端的に言えばdateさんのいうとおり謝辞とか、あとちゃんとやるなら、法的にCopyright表記とMITのあの文言をどこかに入れるとかすればよいと思います。(あの文言はこれ → https://github.com/niw/AnimationPlayer/blob/master/LICENSE) (edited)
10:01 PM
で、それをビジネスに使おうか儲けようがそれはご自由に、です。法的にも、個人的な感情においても。というかスタジオで必要とされているものを自作されて役にたつというステップがとても素晴らしいですね。応援してます。 (edited)
👍 3
10:01 PM
iPad版をつくるにあたっては Documet ベースに変えるとよいと思います。Files 勝手に対応されてほぼ何もせずにiPadで動画ファイルに対応した動きにできるはずです。 (edited)
10:02 PM
Windows版はもうほぼ違うものになると... omochimetaruさんが言ってることが正解だと思います。
10:02 PM
Swiftや互換レイヤーで無理するのはよりしんどそう (edited)
Avatar
ちょっと考えたんですがしばらくは売らずに個人で独占してアニメーション力を磨こうと思います
Avatar
ところでメニューバーのnew windowから作成したviewって子viewって扱いなんですか なんかObservedObjectのプロパティが共有されちゃうみたいで StateObjectにしたら正常に動作しました
11:13 AM
UserDefaultsの値が一次元配列か否かを調べる関数を作ってるんですが
11:13 AM
これってどうすればいいんですか
Avatar
Kishikawa Katsumi 11/27/2023 12:23 PM
if let playerURLs = UserDefaults.standard.array(forKey: playerURL) { ... } UserDefaults.array(forKey:)は中身がArrayじゃなかったらnilを返すので上記のようなコードでいいですよ。
Avatar
Avatar
Kishikawa Katsumi
if let playerURLs = UserDefaults.standard.array(forKey: playerURL) { ... } UserDefaults.array(forKey:)は中身がArrayじゃなかったらnilを返すので上記のようなコードでいいですよ。
配列は配列でも二次元配列か一次元配列かを調べたいのですがそれは可能ですか?
Avatar
Kishikawa Katsumi 11/27/2023 12:55 PM
if let playerURLs = UserDefaults.standard.array(forKey: playerURL) as? [String] { ... }
12:55 PM
例えばこんな感じですね。Stringの一次配列のときだけIfの中に入ります。
12:56 PM
ただ、何が入ってるかわからないっていうのをやめて違うものが入ってるなら名前を変えて分けて保存する、って書いたほうがわかりやすいコードになりますよ。 (edited)
Avatar
Avatar
Kishikawa Katsumi
ただ、何が入ってるかわからないっていうのをやめて違うものが入ってるなら名前を変えて分けて保存する、って書いたほうがわかりやすいコードになりますよ。 (edited)
ありがとうございます! いけました!
Avatar
Rollbarというエラーモニタリング用のライブラリについてご存知の方がおられましたらご教示いただきたいです。 色んなError通知が飛んでくるので内容を絞って通知したいのですが、例えばEXC_BREAKPOINT (SIGTRAP)のエラーは通知しないようにする制御って可能でしょうか? https://docs.rollbar.com/docs/apple (edited)
Rollbar SDK for Apple platforms
Avatar
Avatar
udo223
Rollbarというエラーモニタリング用のライブラリについてご存知の方がおられましたらご教示いただきたいです。 色んなError通知が飛んでくるので内容を絞って通知したいのですが、例えばEXC_BREAKPOINT (SIGTRAP)のエラーは通知しないようにする制御って可能でしょうか? https://docs.rollbar.com/docs/apple (edited)
Kishikawa Katsumi 12/11/2023 6:03 AM
https://github.com/rollbar/rollbar-apple/blob/c2b6a51b90694953734882146e0d566bbca25c09/Examples/RollbarDemo/RollbarDemo/RollbarDemoApp.swift#L44 使ったことはないですけど見た感じあまり柔軟に送るレポートを選択できるような設定は提供されてないようです。おそらく見る方でフィルタするのを推奨しているように思います。 それでも送る対象をフィルタするのであれば checkIgnoreRollbarData でクラッシュレポートの中身を見てSIGTRAPだったらfalseを返す、とするしかないと思います。
Objective-C & Swift library for remote crash, exception, error reporting, and logging with Rollbar. It works on all Apple *OS platforms (macOS, iOS, tvOS, watchOS, etc). - rollbar/rollbar-apple
Avatar
Avatar
Kishikawa Katsumi
https://github.com/rollbar/rollbar-apple/blob/c2b6a51b90694953734882146e0d566bbca25c09/Examples/RollbarDemo/RollbarDemo/RollbarDemoApp.swift#L44 使ったことはないですけど見た感じあまり柔軟に送るレポートを選択できるような設定は提供されてないようです。おそらく見る方でフィルタするのを推奨しているように思います。 それでも送る対象をフィルタするのであれば checkIgnoreRollbarData でクラッシュレポートの中身を見てSIGTRAPだったらfalseを返す、とするしかないと思います。
ありがとうございます!そうなのですね、、
クラッシュレポートの中身を見てSIGTRAPだったらfalseを返す
こういうことができるのですね、この方向で一度試してみます!
Avatar
Kishikawa Katsumi 12/11/2023 6:25 AM
ただ見たところSIGTRAPのクラッシュ、のような分類があるわけでもなく、送られるレポートの文字列を見て判断することになるので面倒だとは思います
6:26 AM
ライブラリのソースコードを変えていいならシグナルハンドラをインストールしないとかシグナルハンドラのところで判定するとかするのが簡単だと思います。
6:27 AM
例外やシグナルを送るかどうかのコントロールはあるのですがどうも設定できる項目として公開されてないみたいなんですよね。
Avatar
詳細までご確認いただきありがとうございます。 ライブラリのソースコードを変えるとなるとメンテコストがこれから発生していったりするのでしょうか?
Avatar
Kishikawa Katsumi 12/11/2023 6:40 AM
そうなりますね。勝手に変更するってことはライブラリに更新があるたびにその変更をやり直すことになるので。
Avatar
シグナルハンドラを外せばいいのかも
6:41 AM
ライブラリ編集じゃなくてユーザー側コードで (edited)
Avatar
Kishikawa Katsumi 12/11/2023 6:48 AM
おおー、確かに。
Avatar
強引だw
Avatar
シグナルハンドラを外せばいいのかも
これを行うとXcodeでこのエラーを補足することがなくなるということでしょうか? Attempted to dereference garbage pointer 0x80000001c. abort() called EXC_BREAKPOINT (SIGTRAP): Application terminated この3つのエラーを送るのを止めようと考えているのですが、メモリ管理(メモリリークではない?)によるものやプログラムを意図的に終了させた時に起こるエラーというぼんやりした認識なのですか合ってますでしょうか?(優先して拾いたいエラーがありノイズになるので今は止めたいです)
(edited)
Avatar
rollbarというライブラリがそのシグナルに反応しなくなるだけで、メモリエラーなどでシグナルが飛ぶことがなくなるわけではないので、Xcodeは通常通り(rollbarを利用しない時と同じように)シグナルを捕捉してコンソールにログを出します。 その引用してるメッセージがrollbarが出している文字列ならそれは出なくなります。xcodeが出しているものならそのまま出ます。 (edited)
Avatar
ありがとうございます!
シグナルハンドラを外せばいいのかも ライブラリ編集じゃなくてユーザー側コードで
この方法を取りたいのですが、シグナルハンドラというのを初めて知りました。 ライブラリを拡張してシグナルハンドラを無効にする?ような実装をするのでしょうか?
Avatar
https://discord.com/channels/291054398077927425/291211035438874625/1183659757307969556 ↑ここで言ってるように、ライブラリは変更しません。 「ライブラリのソースコードを変えるとメンテナンスが大変」という話の流れでのアイデアです。
2:32 AM
シグナルハンドラというのは↑このあたりのOSのAPIで扱います。 そもそも rollbar が、OSに対してシグナルハンドラを登録することによって、シグナル発生時に処理を実行しているはずなのです。
2:34 AM
シグナルハンドラ関係のAPIには、「現在のシグナルハンドラを取得」とか「現在のシグナルハンドラを上書き」とかできたはずなので
2:35 AM
rollbar が設定したハンドラを後から消してしまえば、rollbarはシグナルに反応しなくなるはず、という理屈です。
2:38 AM
僕も細かく触ったことはないのですが、 rollbar が内部でシグナルハンドラを登録している部分のコードを調べれば、APIの利用方法や、適切な上書きの方法がわかると思います。
Avatar
単にデフォルト動作に戻すならsignal(SIGTRAP, SIG_DFL); をrollbarのセットアップ後に呼べばいいと思いますが、基本的には通知は受け取り側で制御(フィルタリング)したほうが良いとは思いますね。
Avatar
シグナルAPIはハンドラをプロセスで1つしか持てない都合上、 シグナルを監視するライブラリを2つ入れるような状況では、アプリ側でどっちを勝たせるか初期化順序を制御して決めるか、アプリ側でまとめて受けてライブラリに分配するか、するしかないので、 そこまでアンチパターンでもないと思っています。 (edited)
2:57 AM
例えば Vapor とかでも Ctrl-C をフックしようとしてたりするし、ちょっとしたことで奪い合いになりそう。 (edited)
Avatar
僕はシグナルハンドラ云々よりは、受け取り手の問題を送り手の変更で修正すること自体に、余計な副作用を危惧した感じですね
3:00 AM
例えば今回の例だとAttempted to dereference garbage pointerみたいなシンプルにまずそうなエラーを全部スルーすることになるので、あとから問題調査をしようとしたときに特定のバージョンからエラーレポートがなくなって困ってしまうので。
Avatar
なるほど。まあrollbarに細かい設定が可能なのがここでは理想ですね。 (edited)
3:01 AM
まずそうなエラーを全部スルーすることになる
これはでも、話の出発点がそうだったので・・・
3:02 AM
一番いいのはエラーを無視させることじゃなくてエラーが出ないように直すことですよね。
t_desune 1
Avatar
Swift Concurrencyでこんなことやりたいのですがどうすればいいでしょう? final class MyClass { var dispatchGroup: DispatchGroup? func a() { guard dispatchGroup == nil else { return } let group = DispatchGroup() dispatchGroup = group group.enter() group.wait() } func b() { dispatchGroup?.leave() } } 要するに何がやりたいかというと、サーバで何か処理のリクエストを投げた時、そのリクエストの実行結果は別の購読で戻ってくるんです(なぜサーバこんな仕様なのかはツッコまないとして…)が、その動作自体をある程度隠蔽して、await a() で処理が終わるまで待って欲しいです 😇
Avatar
ご無沙汰しております AVPlayerのコントローラー
1:32 PM
1:32 PM
これですね
1:32 PM
これを表示しないようにする方法ってありますか?
Avatar
Avatar
lovee
Swift Concurrencyでこんなことやりたいのですがどうすればいいでしょう? final class MyClass { var dispatchGroup: DispatchGroup? func a() { guard dispatchGroup == nil else { return } let group = DispatchGroup() dispatchGroup = group group.enter() group.wait() } func b() { dispatchGroup?.leave() } } 要するに何がやりたいかというと、サーバで何か処理のリクエストを投げた時、そのリクエストの実行結果は別の購読で戻ってくるんです(なぜサーバこんな仕様なのかはツッコまないとして…)が、その動作自体をある程度隠蔽して、await a() で処理が終わるまで待って欲しいです 😇
treastrain / Tanaka.R 12/19/2023 2:25 PM
delegate に値が返ってくるパターンに似ているなと感じました。 withCheckedContinuation(function:_:) で得られる CheckedContinuation を使って待たせる方法はいかがでしょうか?
👀 1
Avatar
Kishikawa Katsumi 12/19/2023 11:30 PM
@Bela Kudaken SwiftUIのVideoPlayerを使う場合はおそらく無理ですね。その部分をコントロールできるようなAPIがないです。 カスタマイズが必要ならVideoPlayerではなくてAVPlayerViewなどを使って表示する必要があると思います。
Avatar
Avatar
treastrain / Tanaka.R
delegate に値が返ってくるパターンに似ているなと感じました。 withCheckedContinuation(function:_:) で得られる CheckedContinuation を使って待たせる方法はいかがでしょうか?
ありがとうございます!無事動きました!!(完全に withCheckedContinuation の存在自体忘れてましたw
🙌 1
Avatar
あ、今ちょっとリファクタリングしてて、たまにデータレース起きてるっぽいから @MainActor 入れたのですが、withCheckedContinuation の場合そのクロージャの中でそのまま自身のプロパティーの書き込みができないっぽいですが、これってどうすればいいですかね? こんな感じのコードです: await withCheckedContinuation { continuation in // Cannot pass function of type '(CheckedContinuation<Void, Never>) async -> ()' to parameter expecting synchronous function type await self.continuations[id] = continuation }
Avatar
Avatar
Kishikawa Katsumi
@Bela Kudaken SwiftUIのVideoPlayerを使う場合はおそらく無理ですね。その部分をコントロールできるようなAPIがないです。 カスタマイズが必要ならVideoPlayerではなくてAVPlayerViewなどを使って表示する必要があると思います。
自力で頑張ってみたのですがここで詰まってしまってます
12:22 PM
Type 'AVPlayerControllerRepresented' does not conform to protocol 'NSViewRepresentable' (edited)
12:41 PM
Viewでも実装しようとしたらこの通りです
Avatar
Underlying type for opaque result type 'some View' could not be inferred from return expression 不透明な結果型「some View」の基礎となる型を戻り式から推論できませんでした
Avatar
Kishikawa Katsumi 12/20/2023 1:06 PM
https://github.com/wxxsw/VideoPlayer こういう既存のライブラリを利用してみてソースコードを参考にしたらどうでしょう。
📽 A video player for SwiftUI, support for caching, preload and custom control view. SwiftUI 视频播放器,支持边下边播、预加载、自定义控制层 - GitHub - wxxsw/VideoPlayer: 📽 A video player for SwiftUI, support for caching, ...
Avatar
Avatar
Kishikawa Katsumi
https://github.com/wxxsw/VideoPlayer こういう既存のライブラリを利用してみてソースコードを参考にしたらどうでしょう。
なんとかいけました! ありがとうございます!
Avatar
Avatar
lovee
あ、今ちょっとリファクタリングしてて、たまにデータレース起きてるっぽいから @MainActor 入れたのですが、withCheckedContinuation の場合そのクロージャの中でそのまま自身のプロパティーの書き込みができないっぽいですが、これってどうすればいいですかね? こんな感じのコードです: await withCheckedContinuation { continuation in // Cannot pass function of type '(CheckedContinuation<Void, Never>) async -> ()' to parameter expecting synchronous function type await self.continuations[id] = continuation }
エラーになってるのは withCheckedContinuationbody 引数は asyncではない関数を受け取るのに、 クロージャの中で await しているから async な関数ができてしまって、渡せなくなってるからですね。 そこに await がつかないようにするのがいいと思うので、クラス全体のコードを貼ってください
Avatar
4:19 AM
水色のラインでThread 1: "Attempt to insert non-property list objectと出てしまって詰んでます
Avatar
Avatar
omochimetaru
エラーになってるのは withCheckedContinuationbody 引数は asyncではない関数を受け取るのに、 クロージャの中で await しているから async な関数ができてしまって、渡せなくなってるからですね。 そこに await がつかないようにするのがいいと思うので、クラス全体のコードを貼ってください
業務のコードなので全体は貼れないですが、ものすごい単純化したものならこんな感じです: @Observable @MainActor final class MyClass { var continuations: [String: CheckedContinuation<Void, Never>] func demo(id: String) async { await withCheckedContinuation { continuation in await continuations[id] = continuation } } } MyClass@MainActor がつくので、continuations がMain-Actor Isolatedになるから、withCheckeContinuation の中だとどうしても await が付くんですね… (edited)
Avatar
4:43 AM
unarchiveTopLevelObjectWithData' was deprecated in macOS 10.14: Use unarchivedObject(ofClass:from:) instead
4:43 AM
とか出るんですけど
4:44 AM
これってどうしたらいいんですか
4:50 AM
4:50 AM
このofclassってなんなんでしょうか
Avatar
Avatar
lovee
業務のコードなので全体は貼れないですが、ものすごい単純化したものならこんな感じです: @Observable @MainActor final class MyClass { var continuations: [String: CheckedContinuation<Void, Never>] func demo(id: String) async { await withCheckedContinuation { continuation in await continuations[id] = continuation } } } MyClass@MainActor がつくので、continuations がMain-Actor Isolatedになるから、withCheckeContinuation の中だとどうしても await が付くんですね… (edited)
var continuations も、 withCheckedContinuation に渡してるクロージャも、どちらも @MainActor なので isolation 違反ではないです。 以下のように書いたらいけました。 @MainActor final class MyClass { init() {} var continuations: [String: CheckedContinuation<Void, Never>] = [:] func demo(id: String) async { await withCheckedContinuation { (continuation) in self.continuations.merge([id: continuation]) { $1 } } } }
4:57 AM
self.continuations[id] = と、subscript access を左辺に持ってくると、ダメみたいです。バグなのか理由があるのかはわからないです。
Avatar
単発ならまだしも、複数の待ち合わせを組み合わせるならAsyncChannelの利用も検討してみてはどうでしょうか
Avatar
self.continuations.merge([id: continuation]) { $1 } // OK self.continuations[id] = continuation //Actor-isolated property 'continuations' cannot be passed 'inout' to 'async' function call ですね、謎です 🤔
Avatar
Async Algorithms for Swift. Contribute to apple/swift-async-algorithms development by creating an account on GitHub.
👀 1
Avatar
ありがとうございます!検討します!
Avatar
5:00 AM
characterの二次元配列を解凍したいです
Avatar
Avatar
Bela Kudaken
characterの二次元配列を解凍したいです
unarchivedObject はたしかclassにしか使えないはず(記憶違いでしたらごめんなさい)なので、NSDictionary として解凍するか CodableJSONEncoder()JSONDecoder() 使うのはどうでしょう?
Avatar
Avatar
lovee
unarchivedObject はたしかclassにしか使えないはず(記憶違いでしたらごめんなさい)なので、NSDictionary として解凍するか CodableJSONEncoder()JSONDecoder() 使うのはどうでしょう?
一次元配列は一応できるらしいのですが...
5:06 AM
やはりuserdefaultsは厳しいですかね
Avatar
Avatar
Bela Kudaken
やはりuserdefaultsは厳しいですかね
保存したいデータ型自体を Codable に適合させれば、JSONEncoder でエンコードしたものを UserDefaults に保存したり、逆にそこに保存したデータを JSONDecoer で解凍したり簡単にできます
5:09 AM
例えばこんな感じで: struct SaveData: Codable { var characters: [[Character]] }
5:09 AM
ただし Codable は内包するデータも Codable 適合が必要なので、この場合ですと struct Character: Codable も必要です
Avatar
すみません、Codableってなんですか
Avatar
簡単にいうとデータ型をエンコード/デコードするための仕組みです
Avatar
つまりデータにしやすくするクラスってことですか
5:14 AM
Codableを使うとJSONにしやすいとかですかね
5:16 AM
5:16 AM
とりあえずぶち込みました
Avatar
struct MyData: Codable { var int: Int } do { let myData = MyData(int: 1) let encoder = JSONEncoder() let encoded = try encoder.encode(myData) UserDefaults.standard.setValue(encoded, forKey: "key") let saved = UserDefaults.standard.value(forKey: "key") as! Data let decoder = JSONDecoder() let decodedMyData = try decoder.decode(MyData.self, from: saved) // MyData(int: 1) } catch { print(error) } 使い方だいたいこんな感じです
5:17 AM
Character 自体も Codable に適合する必要があるので、宣言のところに : Codable 追加するとだいたい大丈夫です
Avatar
5:18 AM
こういうことですか?
Avatar
Avatar
Bela Kudaken
こういうことですか?
いえ、Character の宣言のところです
Avatar
5:25 AM
エラー消えたのですがこれで合ってますか
5:31 AM
5:31 AM
Type 'ContentView.SaveData.Type' cannot conform to 'Encodable'
5:31 AM
ってエラーが消えません
Avatar
いえ違います、Character はどこで宣言していますか?
Avatar
5:39 AM
Viewの中にCodableの構造体を作ってます
Avatar
var characters の宣言ではなく、Character という型の宣言です
5:41 AM
struct Character もしくは class Character のどっちかだと思いますがそのところです
Avatar
5:42 AM
多分これstructですかね
Avatar
yutailang0119 12/21/2023 5:42 AM
SwiftのCharacterなのでは
Avatar
ああそっちか
5:42 AM
長年使ってないから存在忘れてた
5:43 AM
でしたら文字列の扱いの方がやりやすいので、[[Character]] より [String] の方が使いやすいかと思います
Avatar
了解です
5:46 AM
5:47 AM
このGenPosをStringにしたらuserdefaltをそのままぶっこめるっぽいのですが
5:47 AM
そっちの方がいいですかね
Avatar
" ", "a", "b" を切り分けたいだけでしたら、別に文字結合しないので [[String]] でも大丈夫かと思います
Avatar
自分がなぜcharを選んだかというとbyteをくわず軽いからなんですが
5:52 AM
stringも同じ感じですかね
Avatar
所詮 " ", "a", "b" しかないので、どっちも1byteだから変わらないと思います
Avatar
ありがとうございます それでいきます
👍 1
Avatar
問題なく動きました! ありがとうございます (edited)
🎉 1
Avatar
Avatar
Bela Kudaken
自分がなぜcharを選んだかというとbyteをくわず軽いからなんですが
Swiftの Character は1byteではないのでご注意ください。Swiftにおける文字とはgrapheme clusterのことなので、1文字が巨大なこともあります。 @swift-5.9.2 print("👨‍👩‍👦‍👦".count) // 1 (edited)
Avatar
CharacterとStringの差でパフォーマンスが変わるのを実感するにはよほど他が高速になったときなのでひとまず気にしないでも良さそうですね。
Avatar
Avatar
koher
Swiftの Character は1byteではないのでご注意ください。Swiftにおける文字とはgrapheme clusterのことなので、1文字が巨大なこともあります。 @swift-5.9.2 print("👨‍👩‍👦‍👦".count) // 1 (edited)
1
Avatar
Avatar
koher
Swiftの Character は1byteではないのでご注意ください。Swiftにおける文字とはgrapheme clusterのことなので、1文字が巨大なこともあります。 @swift-5.9.2 print("👨‍👩‍👦‍👦".count) // 1 (edited)
1
Avatar
スケジュールアプリを、作りたいと、思っています。 教材を本やネットで、探しましたが、良いものが見つかりません。 資料を、教えていただけると、幸いです。 Xcode15~11、が使用出来る環境です。 FSCalendarやRealmなどが、使えます。 お手数をお掛け致します、何卒よろしくお願い申し上げます。
Avatar
初歩的な内容で申し訳ございません。 bundleという形式があると思いますが、 https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Bundle.html 自分は、この形式のものとして、.appや.frameworkがあると思っています。 気づいていなかったのですが、XcodeのテンプレートにBundleというのがあるのに気がついて、試しにプロジェクトを作ってみたら空っぽでした。 Plug-insのような使われ方をするライブラリをBundle形式で拡張子.bundleにするというのが一般的なのでしょうか?Unityなどで、.bundleが出てきて、理解できますが、なんで、.bundleなんだろうと悩んでおりました。 (edited)
Avatar
Avatar
k
スケジュールアプリを、作りたいと、思っています。 教材を本やネットで、探しましたが、良いものが見つかりません。 資料を、教えていただけると、幸いです。 Xcode15~11、が使用出来る環境です。 FSCalendarやRealmなどが、使えます。 お手数をお掛け致します、何卒よろしくお願い申し上げます。
Kishikawa Katsumi 12/28/2023 2:03 AM
作りたいものそのままの教材がある可能性はほとんどないです。また、スケジュールアプリという漠然とした質問で答えられる人もほとんどいません。 なのでまず必要なことを分解して、例えば「カレンダーを表示する」「予定を入力する」「予定を検索する」etc.のように具体的にして調べていくことをオススメします。 例えば「スケジュールアプリのカレンダーを作っているが〜〜で困っている」という具体的な質問であれば答えられる人はいると思います。 FSCalendarを使っているということなので https://blog.logrocket.com/working-calendars-swift/ の記事を見てまずカレンダーの部分を作ってみるというのはどうでしょうか?
Implement a calendar for handling and manipulating dates in a SwiftUI application using a CalendarView UI and the DatePicker control.
Avatar
Avatar
m_yukio
初歩的な内容で申し訳ございません。 bundleという形式があると思いますが、 https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Bundle.html 自分は、この形式のものとして、.appや.frameworkがあると思っています。 気づいていなかったのですが、XcodeのテンプレートにBundleというのがあるのに気がついて、試しにプロジェクトを作ってみたら空っぽでした。 Plug-insのような使われ方をするライブラリをBundle形式で拡張子.bundleにするというのが一般的なのでしょうか?Unityなどで、.bundleが出てきて、理解できますが、なんで、.bundleなんだろうと悩んでおりました。 (edited)
Kishikawa Katsumi 12/28/2023 2:32 AM
プラグインのような実行時に動的にコードを追加するようなものを.bundleにするのは昔からある仕組みでおそらくMacでは一般的だと思います。 https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1 ^ の最後に載っているLoadable Bundlesだと思います。
Explains how to use bundle objects to organize resources.
Avatar
Avatar
Kishikawa Katsumi
プラグインのような実行時に動的にコードを追加するようなものを.bundleにするのは昔からある仕組みでおそらくMacでは一般的だと思います。 https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1 ^ の最後に載っているLoadable Bundlesだと思います。
ありがとうございます。しっかりと説明されていますね。 とても助かります!
Avatar
岸川さんの一つ目の回答参考になる
Avatar
ご丁重な、アドバイス、ありがとうございます。 文章が正確でなくて、申し訳ございませんでした。 FSCalendarにて「カレンダーを表示する」のは、なんとかなりました。 その先の、Realmを用いて「予定を入力する」「予定を検索する」のところが、どうしたら良いかわかりません。 ご指導していただけると、幸いです。 お手数をお掛け致します、何卒よろしくお願い申し上げます。
Avatar
初歩的な質問失礼します。 ARKitFaceExample(https://developer.apple.com/documentation/arkit/arkit_in_ios/content_anchors/tracking_and_visualizing_faces) というフェイストラッキングのサンプルコードを手元で実行したところ、実行中にエラーが起きてしまいました。Bundle.main.url()でnilが返ってきてしまっているようです。インターネットやChatGPTで一通り調べて、解決策を試してみたのですが、解決しませんでした。解決の糸口を思いついた方がいらっしゃったら教えていただきたいです。

エラー文

ARKitFaceExample/Utilities.swift:39: Fatal error: Unexpectedly found nil while unwrapping an Optional value

エラー箇所

let url = Bundle.main.url(forResource: resourceName, withExtension: "scn", subdirectory: "Models.scnassets")!

実行時のパラメータ

resourceName = “coordinateOrigin”

該当ファイルの場所

ARKitFaceExample/Resources/Models.scnassets/coordinateOrigin.scn

実行環境

  • PC:MacBook Air M1 2020
  • OS:Ventura 13.0
  • Xcode:Version14.3
  • 実機:iPhone13(iOS16.7.2) ## 試したこと
  • resourceName, subdirectory名が正しいことを確認した
  • subdirectoryの部分に相対パスを入力して試してみた
    • 状況は変わらず
  • Finderに該当ファイルがあることを確認した
  • Copy Bundle ResourcesにModels.scnassetsがあることを確認した
  • Models.scnassetsのインスペクター内のTarget Membershipが正しいことを確認した
  • Clean Build Folderを行った
  • iPhoneを再起動した
  • Macを再起動した
Detect faces in a front-camera AR experience, overlay virtual content, and animate facial expressions in real-time.
Avatar
質問重なると深堀しづらいと思うので、 #beginner-help を使っていくのがおすすめです
Avatar
Avatar
toman
初歩的な質問失礼します。 ARKitFaceExample(https://developer.apple.com/documentation/arkit/arkit_in_ios/content_anchors/tracking_and_visualizing_faces) というフェイストラッキングのサンプルコードを手元で実行したところ、実行中にエラーが起きてしまいました。Bundle.main.url()でnilが返ってきてしまっているようです。インターネットやChatGPTで一通り調べて、解決策を試してみたのですが、解決しませんでした。解決の糸口を思いついた方がいらっしゃったら教えていただきたいです。

エラー文

ARKitFaceExample/Utilities.swift:39: Fatal error: Unexpectedly found nil while unwrapping an Optional value

エラー箇所

let url = Bundle.main.url(forResource: resourceName, withExtension: "scn", subdirectory: "Models.scnassets")!

実行時のパラメータ

resourceName = “coordinateOrigin”

該当ファイルの場所

ARKitFaceExample/Resources/Models.scnassets/coordinateOrigin.scn

実行環境

  • PC:MacBook Air M1 2020
  • OS:Ventura 13.0
  • Xcode:Version14.3
  • 実機:iPhone13(iOS16.7.2) ## 試したこと
  • resourceName, subdirectory名が正しいことを確認した
  • subdirectoryの部分に相対パスを入力して試してみた
    • 状況は変わらず
  • Finderに該当ファイルがあることを確認した
  • Copy Bundle ResourcesにModels.scnassetsがあることを確認した
  • Models.scnassetsのインスペクター内のTarget Membershipが正しいことを確認した
  • Clean Build Folderを行った
  • iPhoneを再起動した
  • Macを再起動した
.scnassets ディレクトリの中身の scn ファイルを直接開くという手順に違和感があります。
👀 1
9:57 AM
scnassets という拡張子がついているなら、ビルド時にSceneKitでコンパイルされた何かになって、SceneKitでそれ用のインターフェースを介して中身にアクセスする作法ではないのかなと思いました。 それについて詳しく知らないのでわからないですが。
Avatar
Avatar
toman
初歩的な質問失礼します。 ARKitFaceExample(https://developer.apple.com/documentation/arkit/arkit_in_ios/content_anchors/tracking_and_visualizing_faces) というフェイストラッキングのサンプルコードを手元で実行したところ、実行中にエラーが起きてしまいました。Bundle.main.url()でnilが返ってきてしまっているようです。インターネットやChatGPTで一通り調べて、解決策を試してみたのですが、解決しませんでした。解決の糸口を思いついた方がいらっしゃったら教えていただきたいです。

エラー文

ARKitFaceExample/Utilities.swift:39: Fatal error: Unexpectedly found nil while unwrapping an Optional value

エラー箇所

let url = Bundle.main.url(forResource: resourceName, withExtension: "scn", subdirectory: "Models.scnassets")!

実行時のパラメータ

resourceName = “coordinateOrigin”

該当ファイルの場所

ARKitFaceExample/Resources/Models.scnassets/coordinateOrigin.scn

実行環境

  • PC:MacBook Air M1 2020
  • OS:Ventura 13.0
  • Xcode:Version14.3
  • 実機:iPhone13(iOS16.7.2) ## 試したこと
  • resourceName, subdirectory名が正しいことを確認した
  • subdirectoryの部分に相対パスを入力して試してみた
    • 状況は変わらず
  • Finderに該当ファイルがあることを確認した
  • Copy Bundle ResourcesにModels.scnassetsがあることを確認した
  • Models.scnassetsのインスペクター内のTarget Membershipが正しいことを確認した
  • Clean Build Folderを行った
  • iPhoneを再起動した
  • Macを再起動した
Kishikawa Katsumi 12/28/2023 12:11 PM
プロジェクトをダウンロードして実行してみましたが特に問題なかったです。たぶんどこか知らないうちに変更してしまったのだと思うので再度ダウンロードしてやってみたらどうでしょうか。
Avatar
Avatar
k
ご丁重な、アドバイス、ありがとうございます。 文章が正確でなくて、申し訳ございませんでした。 FSCalendarにて「カレンダーを表示する」のは、なんとかなりました。 その先の、Realmを用いて「予定を入力する」「予定を検索する」のところが、どうしたら良いかわかりません。 ご指導していただけると、幸いです。 お手数をお掛け致します、何卒よろしくお願い申し上げます。
Kishikawa Katsumi 12/28/2023 12:14 PM
もう少し具体的に教えてください。 どんな画面や機能を作ろうとしていますか? 困っているのはRealmの使い方ですか?それとも入力や検索のUIの作り方ですか? 具体的に何かエラーが起こっていますか? 可能なら現状のコードを提示するとさらにアドバイスしやすくなります。
Avatar
ご指導、ありがとうございます、感謝いたします。 お手数をお掛けして、誠に申し訳ございません。 現段階で、具体的なエラーは、起こっておりません。 ネットにある情報にて、FSCalendarを用いて、見ようみまねでカレンダー表示は、出来たと思います。 次の段階である、Realmを使って、予定を入力したり検索する機能を、どう作ったら良いかわかりません。 ご教授いただけると、幸いです。 現状のコードの画像を、添付させていただきます。 次とその次の画像は、appleカレンダーの入力画面ですが、こんな感じのものが、出来れば幸いです。 何卒よろしく、お願い申し上げます。
Avatar
Avatar
k
ご指導、ありがとうございます、感謝いたします。 お手数をお掛けして、誠に申し訳ございません。 現段階で、具体的なエラーは、起こっておりません。 ネットにある情報にて、FSCalendarを用いて、見ようみまねでカレンダー表示は、出来たと思います。 次の段階である、Realmを使って、予定を入力したり検索する機能を、どう作ったら良いかわかりません。 ご教授いただけると、幸いです。 現状のコードの画像を、添付させていただきます。 次とその次の画像は、appleカレンダーの入力画面ですが、こんな感じのものが、出来れば幸いです。 何卒よろしく、お願い申し上げます。
まずは目標を小さな目標に分解すると良いですよ 「予定を入力する機能」 だったら、 「予定を入力する画面を表示する」 「予定を入力する画面に、日付を設定するフィールドを配置する」 「予定を入力する画面に、予定を入力するフィールドを配置する」 「予定入力を完了するボタンを配置する」 「予定をRealmに保存する」 など。 (edited)
6:14 AM
「予定をRealmに保存する」も、さらに分解できて、 「Realmのライブラリをアプリに組み込む」 「Realmの初期化処理をする」 「Realmにしまうデータ構造を決める」 「Realmにしまうデータを構築する」 「Realmに構築したデータを書き込む」 などなど。
6:14 AM
それと、画像の添付を忘れていますよ。
Avatar
ご教授、ありがとうございます。 深く、感謝いたします。 すいません、画像添付、出来ませんでした。
7:00 AM
(edited)
7:05 AM
Avatar
まずは、新規予定入力画面を出すところを目指してはどうでしょうか?
Avatar
Avatar
Kishikawa Katsumi
プロジェクトをダウンロードして実行してみましたが特に問題なかったです。たぶんどこか知らないうちに変更してしまったのだと思うので再度ダウンロードしてやってみたらどうでしょうか。
再度ダウンロードして実行しましたが、同じエラーが起こりました。行なった手順を以下に書きます。 zipファイルをダウンロード→開く→Xcodeのopen a project or fileでxcodeprojファイルを選択→チームを選択→ビルドして実機で起動→顔が映った瞬間にエラーになる 何か手順に過不足あれば教えていただきたいです。 また、添付画像のようにタブの表示が少しおかしいのも気になりました
Avatar
サンプルをダウンロードしてそのまま実行し、顔が映ったところでエラーになるのですね
Avatar
Avatar
omochimetaru
scnassets という拡張子がついているなら、ビルド時にSceneKitでコンパイルされた何かになって、SceneKitでそれ用のインターフェースを介して中身にアクセスする作法ではないのかなと思いました。 それについて詳しく知らないのでわからないですが。
私もSCN用のロード関数をなぜ使わないのか疑問に思っていました。 ただ、Apple公式のサンプルコードなので、何か意味があるのだろうとそのままにしておいています
Avatar
僕も岸川さんと同じでダウンロードして署名まわり変更しただけでうまく動いたので、実機かXcodeの問題そうですね
9:28 AM
とりあえずXcodeが最新ではないようですので、最新のXcodeをダウンロードしてみてはいかがでしょうか
Avatar
Avatar
Iceman
とりあえずXcodeが最新ではないようですので、最新のXcodeをダウンロードしてみてはいかがでしょうか
承知しました!
9:34 AM
@Iceman @Kishikawa Katsumi うまくいったお二方のXcodeのバージョンはいくつでしょうか? (15.2betaか15.1のどちらをダウンロードするべきか分からなくて...!)
Avatar
僕は15.0 (15A240d)でした。今は15.1がいいと思います
🫡 1
Avatar
Kishikawa Katsumi 12/30/2023 1:04 AM
https://www.mongodb.com/docs/realm/sdk/swift/swiftui/write/ RealmのドキュメントにSwiftUIを使ってテキスト入力フィールドを表示、入力した内容を保存するというのがあるのでこれをそのまま写してみて、うまくいったらテキスト入力フィールドを日付、予定に変更してみる、のようにやっていくといいのではないでしょうか。
Avatar
ありがとうございます。 チャレンジしてみます。 いつも、親切に教えていただき、感謝しています。
Avatar
#beginner-help は使いづらいでしょうか?混線することもあるので、できればフォーラムになっているotameshiの方も試して欲しいです。使い辛いのであれば、それも教えて欲しいです。
Avatar
@Kishikawa Katsumi @omochimetaru @Iceman Xcodeをアップデートしたら無事動きました!ありがとうございました!
👀 1
Avatar
Avatar
tarunon
#beginner-help は使いづらいでしょうか?混線することもあるので、できればフォーラムになっているotameshiの方も試して欲しいです。使い辛いのであれば、それも教えて欲しいです。
すみません、次から使ってみます!
🙏 1
Exported 6,371 message(s)
Timezone: UTC+0