[発生環境] Xcode 13.5 iOS 15.5 iPhone 13 Pro Simulator [解決したい問題] xxxが表示されない xxxが表示されるようにしたい [発生手順] 1. Aボタンをタップする 2. Bボタンをタップする [コード] コードを見せても問題ない人はリンクは貼ったり、記述したり 最小限で発生するコードだと尚望ましいswift testで走らせないテストの指定ってできないですか? Xcodeだとdisableできるので重宝するのですがswift package generate-xcodeproj して Xcode 上で実行はダメですか?swift testもやらないで良いわけじゃないですよね? パフォーマンステスト等機能に直結しないものは走らせたくないという状況です。swift testを極力しないという方針で回避が良いか。SWIFT_PACKAGEの存在自体知らなかったです。SWIFT_PACKAGE 定義が含まれているので、それを消した方が良いです。ex をもつプロトコロルを作成してそれに準拠させるという実装スタイルがあるNonError_1_Contents.swiftとNonError_2_Contents.swiftは associatedtype CompatibleType と associatedtype CompatibleTyp になっていますよ。Error_Contents.swiftと同じ状態になります。Error_Contents.swift において、 extension String: ACompatible { } から推測される String. associatedtype の型はAExample<Self>
extension String: BCompatible { }から推測される String. associatedtype の型はBExample<Self> で、型が一致していないのでエラーになりますね。 (edited)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> { ^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 initializedprivate とはいえ、そこから public 呼べますからね。!! 演算子で明示的にクラッシュケースを書いた場...
class Digest() { val str: String init { str = makeString() } private fun makeString(): String { return "hoge" } }let と var でゼロコストでミュータビリティを変えられる Swift 最強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]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 convenience init() { self.init(item: self) }self.initにselfが渡せるのがもうおかしい気が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) // "" <- ?Foo() 1(75709,0x70000aac2000) malloc: *** error for object 0x6180000129ec: Invalid pointer dequeued from free list *** set a breakpoint in malloc_error_break to debugモダンなSwiftのExtension ですけど、 UIColor.hoge は view.backgroundColor = .hoge できるけど UIColor.ex.hoge は view.backgroundColor = .ex.hoge できないってどうなんですかね?func mockFetch() -> Observable<Bool> { return Observable.create { observer in observer.on(.next(true)) observer.on(.completed) return Disposables.create() } }mockFetch().subscribe(onNext: { _ in print("done") }).disposed(by: disposeBag)Emits zero elements Emits a completion event, or an error Doesn't share side effects.subscribe(onComplete: {}) で拾うという手があるかも?ignoreElementsが使えそう<Void> にして気にしないとかcreate で書かずに .just でもかけますよ。下請けに本当の非同期処理がある場合は create ですね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 fiplatform :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 endPODS: - 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)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.1diff "${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 fiecho "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. このメッセージは出て無くて、差分はないと思います。URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil) で解決しました(この方法だとアプリ全体でキャッシュが効かなくなりますが、画像周りは独自のキャッシュを実装していたので今回は影響がなかったNSAttributedStringで、リンクをタップした際の挙動をSafariを開く挙動から自分で定義した挙動に変更するにはどうしたらいいのでしょうClean Clean build folder Quit Xcode Open Finder then go to ~/Library/Developer/Xcode/DerivedData then deleated everything inside Open Xcode Build# frozen_string_literal: true # A sample Gemfile source "https://rubygems.org" gem "fastlane" gem 'cocoapods' gem 'cocoapods-keys'source "https://rubygems.org" gem "cocoapods", '1.2.1' gem "fastlane", '2.11.0'let storyboard = UIStoryboard(name: "ViewController", bundle: Bundle.main) let vc = storyboard.instantiateInitialViewController() as! ViewController vc.inject([1, 2, 3])
import Instantiate import InstantiateStandard extension ViewController: StoryboardInstantiatable {} let vc = ViewController(with: [1, 2, 3])
ViewController.init(with:) を 呼ぶことを忘れなければうまくいくけどinject みたいに「あるメソッドを通過」が外から呼び出すことを意図しているなら、 assert を書く人と呼び出す人が別な気がするので「assertはいらない」ことにならない気がするんですが・・・。
(edited)@available(*, unavailable, scope: public) 的な (edited)Username for 'https://github.com': omochi Password for 'https://omochi@github.com': remote: Invalid username or password.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-sshimport 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 }numbers.prefix(3).map { $0 } が ambiguous use of 'prefix' になる理由がわからず。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 ファイルを読み込んで生成された NSImage の tiffRepresentation は正しく動作します。 https://github.com/koher/EasyImagy/blob/05db8c28d034a36cef3a8271d2daa214c8ad5ee4/EasyImagy/ImageCoreGraphics.swift#L133-L147 var data = Data(length: length) で初期化しないと、capacity あっても直接イニシャライズすると length は 0 のままなので。 (edited)init(capacity:) で生成して、 data.length = length で拡張するか。← データ突っ込んだ後にやると 0 で初期化されるので注意 (edited)Data.init(count:) だ。 issue からリンクされているプロジェクトでは NSMutableData だった。NSMutableData(length:)で正常に取得できることを確認しました。capacityとlength/countは盲点でした…… ポインタと合わせる場合は特に要注意ですねData の使い方を間違えている可能性をまったく考えませんでした・・・。UIView.animate(withDuration: 1.0, animations: { someView.alpha = 0.0 }) { _ in someView.removeFromSuperview() }UIView.animate( withDuration: 1.0, animations: { someView.alpha = 0.0 }, completion: { _ in someView.removeFromSuperview() } )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]]Swift Standard Library.playground とか https://developer.apple.com/documentation/swift ここのドキュメントとか https://developer.apple.com/jp/documentation/a とか b とか付けてたので。概念自体は理解できると思いますが、(自然)言語の壁がありそうです・・・。int が Integer に[NSValue valueWithInt: 3] とかやってたけど、 iOS5ぐらいから @(5) って、アット丸括弧構文でboxingできるようになったとか、昔はあった// Java List<Integer> list = new ArrayList<Integer>(); list.add(new Integer(42)); // boxing// Java List<Integer> list = new ArrayList<Integer>(); list.add(42); // auto boxingint に対して Integer をラッパークラスと言います。C.self is AnyObject 問題があったから、 Swift の型システムとして表現したい世界と、 ObjC 互換のために現実的にどうなってるかとを区別して考えないといけないかも?struct S{} var s = S() print(type(of: s as AnyObject)) // _SwiftValue var f: () -> Int = { 33 } print(type(of: f as AnyObject)) // _SwiftValue ↑SwiftValueの例#if __OBJC__ @class _SwiftValue; #else typedef struct _SwiftValue _SwiftValue; #endif#if SWIFT_OBJC_INTEROP で @interface _SwiftValue : NSObject <NSCopying> だから is AnyObject が Mac だと true になるんだ。 (edited)S.self でもそのはず?class List<T: AnyObject> {} これがJavaのListの定義class ArrayList { private Object[] elements; } こんな風になってたのをclass ArrayList<E> { private E[] elements; } と書いているだけなので、int[] とか float[] みたいな、値型の配列も作れるんだけど、 List<int> のときにそれを内部で使わせる記法も仕組みもない あと、これは鶏卵だけど、ジェネリクスの型パラメータのところに値型が書けない・・・Object で持ってるのと同じです。コンパイル時に型チェックできるようになっただけで、実行時の挙動はジェネリクス以前と同じで Object です。List<int> を導入する話が出てたような?List は List<Object> と書いてるのと同じですね。List<Integer> a = new ArrayList<Integer>(); List<String> s = (List<String>)(List<Object>)a;
[Int]() as? [String] これを嫌がる理由がint foo(List<Integer> list) { ... } int foo(List<Double> list) { ... }associatedType ?let cell = tableView.dequeueReusableCell(withIdentifier: "hogeCell", for: indexPath) ?? UITableViewCell(style: .subtitle, reuseIdentifier: "hogeCell") ③ その他 ただstyleが違うだけなのにイニシャライザだけ定義した、UITableViewCellのサブクラスつくるのが面倒なので良い方法があったりしないかな…と思った感じです。 (edited)indexPath を2番目の引数に取る dequeueReusableCell() はnilを返さないので、2の書き方はindexPath を取らない方のメソッドを呼ぶ必要があります。細かいツッコミですけど。Frameworksの下に参照が作られるから、それをEmbedded~へ入れる様にしてる。[Int: Any] を [String: Any] にしたいみたいなときってどう書くのが一番綺麗なんでしょうlet source = [1: "1", 2: "2", 3: "3"] Dictionary(uniqueKeysWithValues: source.map { ("\($0.key)", $0.value) }) こう?addSubview(_:)とremoveFromSuperView()をしてしまうと、結果としてビューが外された最後の状態でUIが更新されます。download()は同期的な処理ですか?最も望ましいと思われる解決はdownload()メソッドを非同期処理にして完了時点でコールバックを受け取れるようにして、addSubview(_:) を呼んでからdownload()、ここまでは同じで、removeFromSuperView()をダウンロード完了のコールバック内で呼ぶことです。addSubview(_:)の直後に一度イベントループに処理を戻してUIを更新して、download()、removeFromSuperView()を呼びます。view.addSubview(uiView) DispatchQueue.main.async { self.download() uiView.removeFromSuperView() }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 }struct Hoge: C { typealias TypeA = String typealias TypeB = String } これなら通りますね。TypeAとTypeBが別々だと通らなくなるので同一チェックもされてるようです。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 } }protocol A { associatedtype TypeA } protocol B { associatedtype TypeB } protocol C: A, B { associatedtype TypeB = TypeA } struct Hoge: C { typealias TypeA = String }C のそこ associatedtype になるんですね。 typealias で書いてエラーになってあきらめてました。protocol A { associatedtype E } protocol B { associatedtype E } struct C: A, B { typealias A.E = Int typealias B.E = String } これはどうあがいてもムリです。 (edited)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 + 4guessMIMETypeCurrent だからContent-Typeを付け足してみて試すとか。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--if (image){ のとこではContent-Type指定してあるんですね。CFNetwork -[__NSCFURLLocalSessionConnection _tick_sniffNow] + 348 でNSのプレフィックスが付いているのでobjcから呼ばれた通信でバグっているのはあっているのでしょうか?CoreFoundation _CFRelease + 1252 こっちじゃないかなあ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. 大丈夫そうだなあ・・・UIImage の↓の二つのプロパティは、ドキュメントを素直に読めば片方が nil のときはもう片方は nil でないということになると思うんですが、それは保証されているんでしょうか? var cgImage: CGImage? { get }
var ciImage: CIImage? { get }
! に失敗しない)んでしょうか?より良い書き方がありますか? if let cgImage = uiImage.cgImage { // `cgImage` を使う処理 } else { let ciImage = uiImage.ciImage! // forced unwrap // `ciImage` を使う処理 } (edited)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 になるとは書いてありますが、 それ以外の関係性が書いてないので switch で書いたのは単純に好みなのですが、 こっちの方が網羅性があるので CIImage, CGImage どっちかがあれば とう意味では読みやすいかなと思いますnil になりますね・・・。NULL / nil にならないとは言ってないってことですね。
UIImage の init() ってObj-C の NSObject 由来で、 public に使われることは想定されてないんでしょうか?ドキュメントにも記載されてない・・・。 https://developer.apple.com/documentation/uikit/uiimageUIImage() 作って渡してた記憶が…nil 渡すとデフォルト画像が使われちゃうので UIImage() で渡してたはず、なんのコンポネントかは忘れたけど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 ... { を落とすことができなくて悲しい・・・。CoreImage 使ったことなかったんですが、↓を発見して頭を抱えてますpublic init(uiImage: UIImage, clampedTo rect: CGRect? = nil) とかはありかもしれないけど、 fatalError が順当そう。CFNetwork URLResponse::guessMIMETypeCurrent(__CFData const*) のバグを質問したものですが、バグの解消できました!いろいろアドバイスくれた方々、本当にありがとうございました!いろいろ対策をしたのでどれが解決になったのかわかりませんが、おそらく URLSessionをsharedで呼べばいいのに不要にConfigurationを組み立てたり、奇妙なタイミングで finishTasksAndInvalidate している通信クラスがあり、そいつが原因だったように思います。お騒がせしました! (edited)[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.[C] のチェックを外すと@available(*, unavailable) をつけてみると@available(*, unavailable)つけて、エラーが出たものを@available(*, deprecated)に置き換えて残ったものを消す、deprecatedは使ってる箇所でwarningになるのでグローバル変数を減らしていく、とするとうまくいくのかなGCC_WARN_UNUSED_FUNCTION GCC_WARN_UNUSED_LABEL GCC_WARN_UNUSED_PARAMETER GCC_WARN_UNUSED_VALUE GCC_WARN_UNUSED_VARIABLE っていう設定がありますが、 Swift には効かないです。aと 全角 aみたいな。 (edited)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通らなくて済むからできそうですね 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 }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)NSPredicate(format:"SELF MATCHES %@", emailReg) おおNSPredicate式だ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").init は消せそう。[a-zA-Z0-9._%+-/:~$^()&!'] は . と (最後の)- をエスケープしないと意図とちがうことになりそう (edited)// valid regexp は try! にかかってるのかJSONSerialization で一度 Data 化してから JSONDecoder を利用する方法かなと思いますが JSONDecoder 内で JSONSerialization で Dictionary というか Any 化されてるんですね。 https://github.com/apple/swift/blob/5836ea4d11ff5eb66f9c74ec1c0202585a467a9d/stdlib/public/SDK/Foundation/JSONEncoder.swift#L1060 なんか非効率だなーと感じるので、他に良い方法があれば知りたいです。最悪 JSONDecoder を丸々コピって DictionaryDecoder みたいなものを作る事になるのかなと思うんですが JSONDecoder が同じ処理をしてると思うとそれも非効率に感じます。。[String: T] where T : Codable に encode/decode するライブラリとかあるといいのになと思います。Codable にあまり詳しくないので、何かいい方法があるかもしれません。 @norio_nomura さんとか詳しそうです。[String: Any], [Any] or Any as payload.ObjectEncoder 使わせてもらおうとしたんですが、JSONEncoder.DateEncodingStrategyに相当するものが無いのに気づきDateEncodingStrategyとか要りますかね。僕の用途では不要だったので付けなかったのですが…DateDecodingStrategyの方か。DateDecodingStrategy .deferredToDate 扱いか (edited)StringからDate?を作るメソッドを指定できる仕組みがあれば良いのかな?Anyからか。keyEncodingStrategyとかも既にSwift 4.1に入ってるのか。 import Foundation let encoder = JSONEncoder() encoder.keyEncodingStrategy = .convertToSnakeCaseObjectEncoderで任意の型に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)Foo を作って 2. module.modulemap ファイルを作って、アンブレラヘッダー( <Foundation/Foundation.h>のようなもの)を作って参照できるように書く module Foo { header "../Foo.h" export * } 3. SWIFT_INCLUDE_PATHSにモジュールまでのパス(Fooディレクトリまでのパス)を設定する 4. import FooできればOKmodule.modulemapは極力使わない様にしてる。SwiftPM対応しないなら関係ないけど。#include の世界が シンボルベースの世界に変換されてmodule.modulemapを自動生成します。 (edited)@_exported import の裏技とかは、stringByDefaultEncodingWithData の呼び出しまでしか確認してないけど、modulemapファイルにlibiconvをリンクする設定がいるかも。NSString+iconv.h/mを1つのモジュール(IconvWrapper.framework)にしてそれをsample.framework(およびTestApp)からインポート。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) } ↑で、これが動いたので、OKswift package generate-xcodeprojで再生成したものを修正してる。let intIconv: iconv_t = iconv_open("UTF-16//IGNORE", "SHIFT-JIS") guard Int(bitPattern: intIconv) != -1 else { throw EncodingErrors.invalidEncodingName }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)let suit: Suit = .heart と書くと init では代入できない。init(suit: Suit, rank: Rank) {} で渡しているパラメータは self.suit には代入できないので別のことに使うしかない。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) override func viewDidLoad() { super.viewDidLoad() provider.reload() } struct Provider { var cache = Cache() mutating func reload() { layout() } func layout() { } }No enforcement is required for immutable memory, like a let binding or property, because all accesses must be reads.Int.advanced(by:) や Array.filter(_:) のような、同じ型の新しいインスタンスを返すメソッドのことを、ゲッター、セッター、ミューテーターみたいな分類でいうと何と言いますか? (edited)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であってますでしょうかii は Computed Property です。// Stored property. var p1: Int = 1 // Computed property. var p2 Int { get { return 1 } set { /* ... */ } } // Computed property ( 暗黙のgetのみ ) var p3: Int { return 1 } (edited)extension UIView { var a = 0 }extension UIView { var ii : Int { get { return 0 } set(i) { backgroundColor = UIColor.red } } } と、classにある値を変更するのは、よくないでしょうか?set した値を get で取り出せるようにすべきだと思いますよ。func example<T>(_ type: T.Type) { }
example(Int.self)example<Int>() こう呼べても良いような気もちょっとだけする(T.Type) -> (T) -> ()でexample(Int)とかできませんかねfunc example<T>(type: T.Type=T.self) -> (T) -> () { return { arg in print(arg) } } let intE = example(type: Int.self)intE は Int が引数の関数でしょexample<Int>() で呼べるのかfunc example<T>(arg: T) -> () { print(arg) } func example<T>(type: T.Type=T.self) -> (T) -> () { return example } let intE = example(type: Int.self)honest がすでにBool型なところにnilを入れたいということなら Bool? なり適切なモデル型なりに型を変える必要ありそうJSONSerialization とかでgrepしてみたらどうでしょうか<=だったかな、うろ覚えですが 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 }Non-public API usage で、bitcode有効にすると通りましたextension<T: SomeProtocol> Array where Element == T みたいなジェネリックなエクステンションってまだできないですよね?- 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.LIO...
|[ A ] [ B ]| | [ C ]| こういう感じで、BとCがそれぞれ可変サイズだとして、Aの右端が、BかCのどちらかより長い方の左端にくっつく ってAutoLayoutでどうやって書くんです? (edited)|[A]-(>=10@1000)-[B]| |[A]-(>=10@1000)-[C]| |[A]-(0@750)-| ではだめですかね? (edited)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.blue.right = max(stack.left, long.left, greater.left, long2.left) 的な感じで書けそう (edited)blue.right = max(stack.left, long.left, greater.left, long2.left) ってかいたらそのまんまやりたいことがAutoLayout制約としてセットアップされたら一番嬉しいlayoutSubviews() の中に書いとけばあとは自動でやってくれるじゃん?label.sizeThatFits(label.size) を取れば大きい方はわかる…はずletを使うとDecoder.decodeで読むデータにそのプロパティに対応するものがあってもなくても初期値が入る(例外も出ない)、という挙動を見つけたのですが、この挙動ってどうなんでしょうか 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)!)private(set) varを使えば想定する動きをすることがわかったのでそちらを使っているのですが、初期値なしletは正常に動作するので、そちらと混ぜるとコードがデコボコして見栄えがよろしくないことになってしまってさらに letのためですね。letでデフォルト値が与えられているのでそれ以上代入することができないのです。varにして試してみてください。たぶん、init(decoder:)を書いてみるとわかると思います。-Wl,-stack_size,1000000 to the Other Linker Flags field of the Build Styles pane. 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) なるものが出てしまった…AppDelegateだけの空っぽのアプリで構わないです。テスト中に生きてさえいればいい。swift testの場合はわからないです。HOST_APPっていう環境変数がきくかもしれない(たぶんきかない)。 (edited)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 の結果がおかしくなりますSWIFT_FORCE_DYNAMIC_LINK_STDLIB=YESとSWIFT_FORCE_STATIC_LINK_STDLIB=NOをUser Defined Settingで追加してみてください。func updateTableView() { ... tableView.reloadData() // 1 ... tableView.scrollTo(latestIndexPath) // 2 ... } のようになっています。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)AとB、 AA と BB で循環しているので、循環まわりはまだまだ安定していない印象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 { ^
1protocol 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)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 で試してみたらちゃんとエラーになりましたstruct A { var name = "a" } print(A()) struct B { var name = "b" } extension B: CustomDebugStringConvertible { var debugDescription: String { return "{\(name)}" } } print(B())Swift version 4.1 (swift-4.1-RELEASE)A(name: "a") {b} 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 だとやっぱり変わらないようなHello Worldまでの手順は記事がいっぱいあるので割愛します。 サーバーサイドに慣れてないSwift開発者だけど、自分でもできそう! ...while true { } って書いてみましたがずっと動いてるようですwSwift Tweets 2018 Spring 2018-04-14 21:00 JST "Swift Playgroundを作ろう" @k_katsumienum 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() } } うーんやりたくないfunc hoge() -> Never { return unsafeBitCast((), to: Never.self) } guard 1 == 0 else { hoge() } print("離脱してないよー")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:2unsafeBitCast((), to: Never.self) これでNever型のインスタンス作れるの @Yuta Saito が気づいたfunc coodinator() -> NSPersistentStoreCoordinator { do { return try makeCoodinator() } catch { //エラー処理 アラートを出してterminate } } という関数であった場合 func coodinator(_ f: () throws -> NSPersistentStoreCoordinator) -> NSPersistentStoreCoordinator { do { return try f() } catch { //エラー処理 アラートを出してterminate } } にしてテスト時にthrowする関数を与えるような感じ? だとおかしいですね... ちょっと考えてみます#if TEST func myPrecondition() -> Never { ... } #else func myPrecondition<T: FatalObjectCompatible>() -> T { return T.fatal() } #endif-Xfrontend -debug-time-function-bodies や -Xfrontend -debug-time-expression-type-checking が使えます。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 が出てしまいます FooType より FooProtocol という命名の方が主流だと思います。標準ライブラリがそのように変わったので。↓など。 https://developer.apple.com/documentation/swift/iteratorprotocolimport 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)Swift version 4.1 (swift-4.1-RELEASE)8import 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)Swift version 4.1 (swift-4.1-RELEASE)8[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 + 425984863110 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// // 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)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))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>>res.composed の直前の res は Map<Int, Int> なのに、直後の composed の中の self は Map<Map<Int, Int>, Map<Int, Int>> になってる。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()Dictionary<String, String>.Type Dictionary<Dictionary<String, String>, Dictionary<String, String>>.Type==で束縛してConditional Conformanceを使い、それを他のGenerics ParameterのConditionに利用して関数を呼ぶとTypeが壊れる (edited)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 helpimport 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))Swift version 4.2-dev (LLVM d14a2b25f2, Clang c38020c511, Swift 22530b922f)/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)CommandLine.arguments で配列取れませんでしたっけ?swift package generate-xcodeproj で作ったプロジェクトでフォルダの順番を入れ替えたりすると Xcode クラッシュしません? generate-xcodeproj で作ったばかりのプロジェクトでフォルダの順番を変えようとすると落ちます typealias でRename動かなかったり、 func test() { typealias Alias = String _ = Alias(12) // こっちをリネーム } (edited)realm-swift-3.5.0/examples/ios/swift-4.1 のディレクトリ内にあるProjectの設定がSwift3.3 らしいです。
dyld: Library not loadedの実行時エラーが出ます。$ 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"}}swiftlintのバージョンを固定したい時に。 Carthageはバイナリの配布をサポートしていないのでCocoaPodsで管理する。 が、他のライブラリをCarthageで管理している場合、バイ...shtnkgm/GPUImageの0773513209ae9f066db82497fd2342e0241d4fa2は通りました*** 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"}}rm -rf ~/Library/Developer/Xcode/DerivedData/ //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)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[Result]: FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(...encoding:部分不要ぽいですね。 func getWiki() { Alamofire.request(urlString, method: .get, parameters: parameters) .responseJSON { response in debugPrint(response) } } これで正しくJSON返ってくるInit(...)という関数が見つからないというエラーです。Use of unresolved identifier Initなので、Initを呼び出しているけどどこにも見つからなかった、というエラーです。 ConfigurationBlock.swiftで定義されている関数なのでそのファイルを忘れてませんか? (edited)Init(value: になっているから、使う側も今のSwiftの文法なら Init(value: で呼び出す必要がありますね、昔Swift 2までは一つめの引数がデフォルトでラベルとして使わなかったので@noescape が怒られてるんじゃないか?@escaping ってクロージャ型の左側(コロンの右側)に書くけどclass ResCell: UITableViewCell { static var textViewLeftMargin: CGFloat { return 16 } } class ResCell2: ResCell { /// override static var textViewLeftMargin: CGFloat { return 8 } } これ書いたら,怒られた.static varはoverrideできんと.なんだろう,これはstaticは,継承によって挙動が左右されないことを保証するためにあるってことですかね 心は,こういうこと?class ResCell: UITableViewCell { class let textViewLeftMargin: CGFloat = 16 } classでもlet宣言はoverrideできないとかあるclass内のstaticはfinal classですよね。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 と仮定されて怒られているようです deadline で指定された時間に main キューで execute のクロージャ式の中身を実行という意味ですね。 (edited)DispatchQueue についてちゃんと理解するためには↓あたりを読むと確実です。(もし並行処理について詳しくなければ Introduction から読んだ方が良いです。が、並行処理はそれだけで本が一冊書けるような分野なので、まずは日本語で並行処理について書かれた本を読んで概念を習得した方が良いかもしれません。) https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW11. 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) と出て通らなくなってしまいました [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.0var unions: Set<Set<Self>> = Set() ... return unions .sorted{ $0.count < $1.count } .map{ FiniteSubgroupStructure(allElements: $0) } (edited)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)昨日は普通にできてたんですが… クラッシュ再現しないです。 こちらもビルドできた。 Abort trap: 6ってことはコンパイラがクラッシュしてるので、コンパイラのバグを踏んだかもしれませんね コンパイラのメモリ関連バグ?マシン再起動したら直ったりしませんか? (edited)layoutMarginsGuide がありますcontentView があって、それはlayoutMarginsの中にあるじゃなかったっけ 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
FooのgetHogeProtocol() の返り値で各structの型を返したいのですが、HogeProtocol型になってしまいます。 各structの型を返す方法はありますでしょうか。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() // OKprotocol 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() // OKswift-4.1.1-RELEASEfunc getHogeProtocol<T : HogeProtocol>() -> T? にして as? T にすべきだとは思いますが。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 こうするのはどうですかswitch foo.getHogeProtocol() { case .hoge(let hoge): // なにかする case .fuga(let fuga): // なにかする } これで型安全ですenum Foo { case hoge case fuga } で、どっちかを最初に選んで使うので、選んだ後に場合分けが入ってしまうと使うの側のコードが増えてしまうなと言う印象なのです... (edited)enum FooHogeProtocolValue を HogeProtocol に準拠させれば、分岐消せますね。 (edited)let hoge: Fuga = Foo.hoge.getHogeProtocol() だとクラッシュですね...unowned let hoge: Hoge という宣言をしているコードを見かけたのですが、これってどういう挙動のものなんでしょうか そのクラスにはインスタンスは保持されずに他で保持されてなければhogeは即解放されてしまう…?weak の場合は解放されたときに nil にしてくれますが、 unowned の場合はそういう安全機構がありません。SIGABRT吐いちゃいますね…。 これがweakの場合はnilになっていると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.unowned(unsafe) の場合は未定義ですね。普通の unowned はドキュメントの通り、実行時エラーが保証されています。-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)unowned(unsafe) の有用性を認めるのであれば、 unsafePrecondition とかも認めないといけないような-Ounchecked でコントロールスタイルじゃないのかな・・・。-Ounchecked 自体deprecatedじゃないかな。。。-Ounchecked を使わないと、十分に安全性が確保されたパフォーマンスを追求するコードで一体どうやって precondition のチェックを無効化したらいいんでしょう?assert で書く?private プロパティなどを Codable の対象から外す簡単な方法ってありましたっけ?Codable でない型にしたら encode init(from:) を自前実装しないといけないのでは?CodingKeys だけ書いたら encode と init(from:) は自動生成されるんだっけ?
(edited)struct Foo: Codable { private enum CodingKeys: CodingKey { case a } var a: Int private var _b: String }struct Foo: Codable { private enum CodingKeys: CodingKey { case a } var a: Int private var _b: String }swift-4.1.1-RELEASE/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 ^encode, decode を自前実装しないといけないのか・・・。面倒だなぁ。-O なら assetionFailure は有効にならないはずです。-O (Optimize for Speed)になってるんですよね。-O による assertion の除去がされているか確認するために、 おしたら assertionFailure するだけのボタンをアプリに置いてみるなどはどうでしょう。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)start inserted 100003 100001import 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)start inserted 100000 100001dispatchMain()とかで待たないと、実行されない場合がありますよ。let total = ... の行については、そのキューの中では実行されてないです。Array の API リファレンスも The Swift Programming Language にも書かれてなさそう( thread で検索してみただけだけど)。標準ライブラリのコードから実態としてスレッドセーフじゃないということでしょうか?
(edited)Array自体はスレッドセーフなのでは?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()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)start ....................................inserted .................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 100000 100001すみません Swift42 bot 落としちゃったかも 受け取ったコードは別プロセスで実行されるので、ボット自体が落ちることはあまりないです。受け取ったコードは別プロセスで実行されるので、ボット自体が落ちることはあまりないです。 あいや落ちてHerokuが復帰させてた… var supportedPositions でカスタマイズできそうな雰囲気ですが、それはダメでしたか?
1insetFor(position:) で返す値を .tip: 0, .half: 100, .full: 400
initialPosition を .tip とし コードで表示・非表示を行う場合は func show() { fpc.move(to: .half) }
func hide() { fpc.move(to: .tip) } とすれば、それっぽい動きになりそうですね。 (このやり方だと隠れていても FloatingPanel 自体は存在する形になってしまいますが)let a = [1] let b = [1] if a == b {} // コンパイル通る if [1] == [1] {} // コンパイル通らない このように配列を比較したときに、 一旦定数に入れたものと、そうでないものとで結果が違うのは何故でしょうか??a, b は型が Array<Int> に確定しているので、 if a == b {} は問題ないのですが、 リテラルを直接書いた場合( if [1] == [1] {} )は、 演算子 == リテラルをどの型として評価すべきか1つに定まらないから、ですね。 ちなみに問題は == に配列リテラルを渡したときに、配列リテラルからインスタンスできる型が複数あるからですね。(IndexzSetとIndexPath?) 例えばFoundationをImportしなければそれは存在しないので、上記のコードもコンパイルできます。 (edited)どの型として評価すべきか1つに定まらないが 他の型ではArrayに定まるからなんですねif [1] as IndexPath == [1] {} このように左側だけキャストしてもコンパイルが通るのは、 勝手に右側も合わせてくれるからなのですか??== は static func == (Self, Self) -> Bool なので、どちらか一方が決まるともう片方も決まることになります。import SomeFramework public typealias Dog = SomeFramework.Dog public typealias Cat = SomeFramework.Cat@_exported import SomeFramework という記述ができますよ、非公式仕様ですが$ 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)swift-DEVELOPMENT-SNAPSHOT-2019-03-26-aでは直ってるみたいですね。swift-5.0-branchでは直ってないので、放っておくと5.1まで直らないのでは。ParameterというprotocolがRoutingの中で宣言されています。 Vaporというpackageの中で先日お聞きしたような@_exportedやtypealiasは使われていなかったのですが、MyProjectで import Vaporとしただけで、Parameterという名前を使えるのが不思議です。 SwiftPMで依存しているライブラリの名前は全て展開されるということなのでしょうか? https://github.com/vapor/routing.git
https://github.com/vapor/vapor.git @_exported import CryptoKit @_exported import HTTPKit @_exported import RoutingKit @_exported import ServiceKit @_exported import ConsoleKit @_exported import Foundation@_exported で検索すると多分アットマークがユーザー名の意味とかになってしまいますね、exportedで検索したら出ました。UIKit.UITableView などのようにSubmodule化することはできるのでしょうか? http://nsomar.com/modular-framework-creating-and-using-them/ この記事を読んでみたのですが、理解できていません。 (modulemapというのはObjective-Cなどで書かれたFrameworkの内部を切り分けるために使われるものでSwiftオンリーで書かれたものにはあまり関係ないのかなと朧げに理解しています) (edited)MyFramework.Sub1.Hoge
MyFramework.Sub2.Hogeimport 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を貼るのもすごく面倒なのでもっといいやり方があるのではないかと思っています。import MyFramework fileprivate typealias Hoge = Sub1.Hoge とかやるしか無いと思います。 それかパッケージをわけてMyFrameworkSub1とMyFrameworkSub2を作る。 その上でMyFrameworkも作って、MyFrameworkSub1とMyFrameworkSub2をexportすれば、 ユーザ側で import MyFrameworkSub1 とできるようになります。import class UIKit.UITableViewController
https://thoughtbot.com/blog/swift-importsMyFrameworkのなかで以下のようにしておけば @_exported import Sub1 @_exported import Sub2 MyFrameworkのユーザー側で下記のようにSub1, Sub2を使えるのですね。 let hoge1 = Sub1.Hoge() let hoge2 = Sub2.Hoge() 名前の衝突が問題だったので、やりたかった事はこれで解決できました。ありがとうございます。 (@_exported importをすると、Sub1やSub2などの名前空間は消失してしまうのかと思っていました。)@_exported ってそんなに便利なものじゃないのでこの場合だと MyFramework と Sub1、Sub2をそれぞれ個別に、あるいはSub1、Sub2のフレームワークとして提供する方がいいと思いますよ。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になることに気がつけずにハマってしまい気になりました。Promise の then が resolve 済でも同期的に実行されない仕様なことに気づかずハマったことがあります。 console.log("1"); new Promise(resolve => { resolve(42); }).then(value => { console.log("2"); }); console.log("3");
1 3 2 (edited)async/await は async -> Foo でも同期であり得るという認識。 (edited)非同期コールバックを同期的に呼び出してはいけない の部分は、わかりやすくていいなと思っているんですが、ただし多用すると遅くなる 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") } }var environment: AppConfigProvider// 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)AppConfigProvider で受け取るのではなくて、 AnyAppConfigProvider で受け取るようにします。 代入するときは AnyAppConfigProvider.init<X> で明示的に包み込みます。RxSwift.ReactiveCompatible の var rx: Reactive<Self> のところで、 プロトコル型それ自身を Self として使おうとしているからです。
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 } }a.config
a.rx.config みたいに分けたいのですが、難しいですかね・・・?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)rx のオーバーロード定義の fatalError() のところは実際には return Reactive(self) とする必要ありですか? (edited)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 }<stdin>:39:21: error: protocol type 'AppConfigProvider' cannot conform to 'AppConfigProvider' because only concrete types can conform to protocols _ = provider.rx.config ^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.'extension Reactive whare Base == AppConfigProvider にしていないから、KeyPath版の方にfallしたんじゃないですかね。== にしてみたらどうでしょう?Ambiguous reference to member 'observe(_:_:options:retainSelf:)'@objc can only be used with members of classes, @objc protocols, and concrete extensions of classespublic protocol AppConfigProvider: NSObject { @objc var config: AppConfig { get set } var rx_config: Observable<AppConfig> { get } }Property cannot be a member of an @objc protocol because its type cannot be represented in Objective-Cや Protocol '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 } }observe を使いたい場合は (base as NSObject).rx.~~~ でできると思います
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") } }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 } }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()Decodable.hoge String.hoge==のほうが強い、みたいな規則があります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()<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() { ^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()Decodable.hoge Encodable.hogeNo such module と言われてしまい、対処法がわかりません。 App : アプリ本体のFramework。他の全てのFrameworkに依存。 Feature1 : ある機能の画面やロジックなどが入ったFramework Feature2 : ある機能の画面やロジックなどが入ったFramework AppCore : AppやFeature1、Feature2などが依存するFramework こんな感じの構成でして、 AppからはCPのframeworkを使用できるのですが、その他のFrameworkでは使えなくて困っています。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 endworkspace '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' endwindow.rootViewController = vc とかをやっていると、present(nextView) で表示してますか? (edited)dismissを呼び出す対象のオブジェクトが間違ってるかもしれません。self.navigationController?.dismiss() を呼ぶとどうなるんですか?self.navigationController?.dismiss() の self がDelete sc.と表現されているViewControllerなら、Cover sc.のViewControllerまでは戻りそうな気がぼくもしてたんですけど。self.navigationController?.presentingViewController?.presentingViewController?.dismiss(animated: true)self.navigationController?.presentingViewController?.presentingViewController?.presentingViewController?.dismiss(animated: true)AppDelegateのプロパティとかにloginVCをプロパティで持っておいて(UIApplication.shared.delegate as! AppDelegate).loginVC?.dismiss(animated: true)class ViewController : UIViewController { @IBOutlet var textField: UITextField! let keyboardCloseHelper = KeyboardCloseHelper() override func viewDidLoad() { super.viewDidLoad() keyboardCloseHelper.add(textField) } }
self.view.endEditing(true) でそのビューに乗っているビュー全部に対して resignFirstResponder を呼んでくれるので、それを適当なタイミングで呼んだらいいと思いますよ。// swift-tools-version:5.0buttonItemsStatus の先頭あたりでいったん titleTextField.text と detailTextView.text の値を、それぞれ別の変数に入れてみてデバッガで止めるなり、ログに出すなりしてその値がどうなってるか見てみるとかしますね。buttonItemsStatus が呼ばれているだろうか?というあたりですかね。debugQuickLookObject生やすとXcode上でプレビューを表示する機能ありますけど これってstructでも同様にプレビュー表示したい場合なにか対応方法あるでしょうか? classに生やす場合@objc func debugQuickLookObject() -> AnyObject?で定義するため、structだとそもそも宣言できません。- (id)debugQuickLookObject メソッドで実現されてるので無理そうじゃない?@_specialize で複数の型パラメータを特殊化するのってできないでしょうか? 行列の計算を @_specialize(where R == Int, Double) のようにして、頻用されるものについては特殊化して高速化したいのが目的です。@_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>) { }.pointeeにアクセスしてよいのは「初期化済み」のときだけです。label.numberOfLines = 1 にしてからもう一回 sizeToFit() してみましょうか? sizeToFit() はラベルのサイズを動的に調節するメソッドではなく、ラベルのサイズを呼び出された時点のコンテンツに合わせて調節するメソッドですsizeThatFits(_:) メソッドは親ビューにこのメソッド呼ばれた時の返してあげたいサイズを返すメソッドですので、それ呼ばれても特にサイズの変更はありませんleave のとこで EXC_BAD_INSTRUCTION が出てしまいます。count を 1 にすると通るのですが。 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)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] と出て欲しい_iに置いてみました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)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)let x = ... のところに、重い処理が入る予定。parallelMap実装を1年以上使ってます。 https://github.com/realm/SwiftLint/blob/740e398f9115f1f16048ea6979060f4e83a36b1c/Source/SwiftLintFramework/Extensions/Array%2BSwiftLint.swift#L56-L64 (edited)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)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))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))swift-4.2.1-RELEASEtrue falselayoutSubviews で label の frame を更新するか、 AutoLayout を使うといいですよclass PlaceHolderTextView: UITextView { override func layoutSubviews() { super.layoutSubviews() placeHolderLabel.frame = bounds.insetBy(dx: 6, dy: 6) } }layoutSubviewsでも問題は解決できます...)CGRect(x: 0, y: 0, width: 100, height: 50).insetBy(dx: 5, dy: 5) とすれば {x 5 y 5 w 90 h 40}と内側に dx, dy分インセットした領域を返す関数です
createLabelのoriginを持ってきたからですfirstBaselineなど駆使する感じですねplaceholderLabel.sizeToFit()を付け足せばうまくいきそうですstrongly discourage (非常に非推奨)だけですのでOne-click with Heroku とあるので 下記リンクのDeploy to HerokuをクリックするだけでHeroku側の設定は完了するかと。 https://github.com/bih/spotify-token-swap-service#one-click-with-herokuClient ID と Client Secret をアプリに持たせると解読等された場合に悪用される可能性あるから、 Client Secret はサーバ側に持たせることで、サーバ経由のToken更新を行い、セキュアな状態にするためみたいDeploy to Herokuをクリック 2. https://github.com/bih/spotify-token-swap-service#configuration の環境変数項目のRequiredを最低限設定する --- /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)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)typealias GridChainComplex = ChainComplex1<FreeModule<TensorGenerator<MonomialGenerator<_Un>, GridDiagram.Generator>, 𝐙₂>> extension GridChainComplex { // こう書きたい }public typealias Single<Element> = PrimitiveSequence<SingleTrait, Element>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 Python.import って動かないですか? 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)swift -frontend -replで起動して、インポートして:print_module <モジュール名>ですね。xcode-selectでXcode-beta.appを選択していない場合、-sdkパラメータも追加で渡す必要があるぽい。$ 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):print_module Pythonしたら4000行ぐらい出てきた@_exported import Python.import_ これは見えるけど import_は無いなあ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)allowsMultipleSelectionDuringEditingメソッドで、タップをしたらチェックマークがつくのって、どういう仕組みなのでしょうか? https://developer.apple.com/documentation/uikit/uitableview/1614944-allowsmultipleselectionduringedi (edited)$ 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 : . fatal error: 'Foundation/Foundation.h' file not found #import <Foundation/Foundation.h> ^~~~~~~~~~~~~~~~~~~~~~~~~ と出ました。Obj-C をビルドするのに何かがいるのかな sudo apt-get install gnustep gnustep-devel gobjc で /usr/include/GNUstep/ 下に Foundation/ が入りましたが,これはどうやって SwiftPM で指定するのかしら"-I", " /usr/include/GNUstep" をcxxSettingsに追加したらどうなります?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.extern "C" { } で包むのとextern "C" { } は C++の中で使うC言語対応させる文法なので#ifdef __cplusplus extern "C" { #endif // ここに Swift に expose する struct や関数を書く #ifdef __cplusplus } #endif#ifdef __cplusplus extern "C" { #endif void hehe(); #ifdef __cplusplus } #endif hoge.cpp #include "hoge.h" void hehe() { std::cout << "hehe" << std::endl; } これが動いたのであとは頑張れば行けそうです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_Nullable, _Nonnullとか使えるので、その辺りをちゃんと使うとSwift側でのポインタの扱いを簡単に出来たりします。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 にしたい)#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnullability-completeness" ... #pragma clang diagnostic pop これで行けました#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 #endifASSUME_NONNULL_BEGINとかを自前で定義してしまえば良いのでは。 (edited)#if __has_feature(assume_nonnull) #ifndef NS_ASSUME_NONNULL_BEGIN #define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #endif #endif こういう感じにするのかなと思ってました(将来的に衝突が起きると面倒なので) (edited)NS_はFoundation用のprefixなので、NS_をつけないのが望ましいですね。#pragma に展開されるマクロだと思うので、_Pragmaを定義する必要は無いですね#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) __has_feature(assume_nonnull) も絶対YESなのでいらないきがしますが#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)#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 これでいいと思います。#pragma直接書けばいい気もする#ifdef __CLANG__ #define _Pragma(x) #pragma x #else #define _Pragma(x) #endif__CLANG__は今適当に書いた) (edited)#pragma onceはgccでもvcでも使えるな。 #pragma clang assume_nonnull beginは使えないと思いますけど(clangって入ってるし・・・)_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)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)xcomps_ptrの型は UnsafeMutablePointer<LBVectorComponent>?にしたほうが良いのでは?を使いたい、!型は避けたい。_Nullableは明示したい。clang -Xpreprocessor -fopenmp -lomp myfile.c という風にオプションをつけるとできるそうなのですが,swift build や Xcode からのビルドでこのオプションを設定するのはどうやったらいいか分かりますか?swift build -Xcc -Xpreprocessor -Xcc -fopenmp これは通ってるっぽいです(°_°)-lomp 指定するのはどうしたらいいんでしょう?ld: library not found for -lomp って言われてしまいます… export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/usr/local/lib してみたんですがダメでした。 (edited)swift run -Xcc -Xpreprocessor -Xcc -fopenmp -Xlinker -L/usr/local/lib -Xlinker -lomp これで実行はできました!…が並列処理は効いてなさそう/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)#pragma omp for for(int n=0; n<1000; ++n) { printf(" %d", n); } printf(".\n"); ↑ この謎の pragma を入れるだけで並列処理になるというwexport 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 と出ました-Xpreprocessor -fopenmp と指定すればいけました .target( name: "...", cSettings: [ .unsafeFlags(["-Xpreprocessor", "-fopenmp"]) ], linkerSettings: [ .unsafeFlags(["-L/usr/local/lib"]), .linkedLibrary("omp") ] ), (edited)realloc failed: Cannot allocate memory と最後の言葉を残して終了したのですが、こういうメモリエラーをキャッチする方法ってあるんでしょうか? (アプリなら didReceiveMemoryWarning 系のものがあるけど)そもそも RuntimeException 的な仕組みがないのでどう対処したものかとcatch (...) { <= この ... は文字どおり ... です、とかで捕まえられるかも。 それかreallocを入れ替えるとか。/usr/bin/swiftが請け負ってくれているので。
(edited)import SwiftBacktraceを出来るようにはしてありますが。 (edited)coreを使ってスタックトレースを出力、lldb下で実行して出力、が取れる選択肢かな。dockerとかでcore出力を制限されていたりlldbを使えなかったりする場合は実行ファイルが自前で出力するしかないので、SwiftBacktraceを作りました。core出力もlldbも使えません。そのため、ボットが受け取ったコードの実行には使っていませんが、ボット自身のクラッシュを解析する用途としてはSwiftBacktraceを使っています。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... が出続けるisCancelled みたいなプロパティがあるのでそれを見て自分でキャンセルします。if isCanceled { // cleanup etc. return } // 処理A if isCanceled { // cleanup etc. return } // 処理B ...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) }ExpressibleByIntegerLiteral 適合させると予期できない暗黙キャストが起きてカオスになるので、特定の型を fileprivate に ExpressibleByIntegerLiteral に適合できたらいいと思ったのですが、 conditional conformance があると fileprivate extension できないんですね… これは何故なのでしょう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)fileprivate extension Polynomial: ExpressibleByIntegerLiteral, InheritingIntegerLiteralExpression where BaseRing: ExpressibleByIntegerLiteral { typealias Inheritee = BaseRing } とするイメージ. (edited)// ファイル A public func something<T: SomeProtocol>(_ value: T) { ... } // ファイルB private extension Foo: SomeProtocol { ... } something(Foo()) 最も単純な例はこれですかね、somethingの実装側からはFooのSomeProtocolに対する実装は見えていないはずなので、実行できなくなりそうです。(できると可視性がおかしなことになってくる)"${PODS_ROOT}/SwiftLint/swiftlint"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) とした方が良いという記事をいくつか見てそうしてます.concurrent にしたらダメじゃないですか? concurrent にした上で write を async(flags: .barrier) にすると write で sync を待たなくて済むのでより良い,というようなことが書かれてたもので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)a[i] = i print(a[i]) のようにgetが呼ばれるコードを後に足すと終了すると思います。start end: 0.481503963470459 Program ended with exit code: 0print(a[n-1]) のところを消しても同じぐらいかかりますね.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)syncが呼び出しスレッドで実行されるのはqueueに実行待ちのアイテムが無い時で、asyncでアイテムが登録されてるとasyncで登録されたアイテムが実行されるスレッドで実行されるのをsyncが待つ様な実装になってたと記憶。
(edited).concurrentだと違うのかな? (edited)async用のスレッドで実行する場合があったかと。
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) } }scrollIndicatorInsets をセットした↑scrollViewDidEndDecelerating が拾えなくなってしまうと思います実装例: 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)initial commitと書いてあるコミットは9月だなw (edited)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)a.withUnsafeMutableBufferPointer { buff in var sub = buff[3 ..< 6] for i in sub.indices { sub[i] *= 2 } }a[3..<6].withUnsafeMutableBufferPointer { buff in for i in 0..<buff.count { print(i) buff[i] *= 2 } } こういうのもできます。buff[.start + i] って書けるようにする案が審査落ちしました。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 でいけましたwithUnsafeMutableBufferPointer を使ったやり方では、最初から let threads = 8 とか決めうちしちゃって、大っきな ContiguousArray 作ってスライスしたものを各スレッド(もどき)で使い回す、というようなことをしたのですが。enum hogeError: Error { case hoge var localizedDescription: String { "hoge" } } func sayError(_ e: Error) { print(e.localizedDescription) } sayError(hogeError.hoge) sayErrorメソッド内でhogeErrorにキャストすれば実現できますが、 発生し得るエラーの種類が多いため、すべて列挙するのはあまり現実的でありません。 うまい解決方法はないでしょうか。import Foundation enum hogeError: LocalizedError { case hoge var errorDescription: String? { "hoge" } } func sayError(_ e: Error) { print(e.localizedDescription) } sayError(hogeError.hoge)Errorの代わりにFoundation.LocalizedErrorに準拠して、errorDescriptionの実装を与えると、 .localizedDescriptionが変更できますよ。import Foundationやimport UIKitなどを書かなければfunc sayError(_ e: Error) { print(e.localizedDescription) } ↑これがそもそもコンパイルエラーになります.localizedDescriptionはFoundation.NSErrorのメソッドで、Swift.Errorには無いメソッドだからです。import Foundationすると、ErrorからNSErrorへの暗黙の変換が起こるようになって、呼び出せるようになる。@Binding か @ObservedObject で用意して、TextのBindingにその変数を指定します。 これで変数として持っている状態がTextに自動的に反映されるようになります。 あとは非同期処理が完了するタイミングで適宜その変数を更新します。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)@GestureStateについて追記しました。BackgroundTask、 ●Background Processing Tasks - 数分かかる処理 - 延期可能なメンテ処理やCoreMLによるトレーニングを想定 ●Background App Refresh Tasks - 30秒のランタイム - アプリを最新の状態に保つための用途を想定 - performFetchのAPI が代わりにdeprecatedに みたいな感じの仕様らしいのですが、background processの数分ってのは実際どれぐらい処理が続く感じなんでしょうか。 また BackgroundTask では実現できないなら他の案をご教授いただきたいです。 既存アプリのGoogleフォトとかはバックグラウンドで常に写真のアップロードを監視してたりするのでできないことはないと思うのですが、どうやってバックグラウンドで常時処理をするのかが気になりました。よかったらどなたか強い人回答お願いします。 https://github.com/nshhhin/Background-Accel-Swift .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" というエラーが出てビルドできませんautoreconf --install ./configure --enable-openmp make make check make install しました. (edited)make install のインストール先をプロジェクト内にしてしまって、brew install libomp libtool もしました../configure --prefix=$PWD/dist make install ^ のようにすると$PWD/distにライブラリがインストールされます。./configure --prefix=$PWD/dist --enable-openmp ビルドが終わるとdistは以下のようになります。 dist ├── include └── libdist ├── 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.pclibm4ri.aだけなんですけど、 ^ のdistディレクトリを自分のプロジェクトの中に入れてしまって (configureでそうなるようにして)SwiftPMからはそれを参照するようにすると、SystemLibraryとか気にせずに単にプロジェクト内にあるStatic Libを参照するだけ、となるはず。(というのを今試しています). ├── 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 リポジトリの構成をこのようにするとしてmodulemapは例えばこうなる module Cm4ri { header "include/m4ri.h" link "m4ri" } (modulemapはいろんな解があるんでいったん簡単なやつで試す) (edited)# 構成 ├── 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で遅延実行しています)dequeueReusableCell を使用せずに、cellを生成すれば良いのでしょうか?protocol Cat があって KawaiiNeko: Cat と CuteNaNeko: Cat は作ってあるけど勝手に KawaikunaiNeko: Cat は作られたくないんです。protocl じゃなくてもなんらかの表現でこの制約が与えられた良いのですが...enumは近そうなんですがちょっとキツい感じが。enum Cat { case kawaiiNeko(KawaiiNeko) case cuteNaNeko(CuteNaNeko) } protocol CatProtocol { } struct KawaiiNeko: CatProtocol {}enum Cat に対して CatProtocol のメソッドを全部実装しちゃえば、extension Cat { func asCatProtocol() -> CAtProtocol }open classではなくpublic classでサブクラス化を抑制できそうですねtryがあります。 このような場合インターフェースとしてはどのようなものが好ましいと思いますか? 1. throwsにする ユーザー側で毎回ハンドリングが必要なのでロガーとしてはいまいちな気がします。 2. 中でcatchして別途設定したハンドラに渡す 今はこれになっています。ハンドラはエラーだけを取っていますが、コールスタック等の情報も入れたほうがいいのかと考えています。 (edited)do-catch { errorHandler() } が何度も出現してるから、実装は高階関数にしたほうが良さそうと思った あと合成する場合は一番上だけでcatchfunc addText(...) { wrap { try w.addText(...) } }try wrap(w.addText(:))(...) こういうのもできるかもwstruct CategoryHome: View { var categories: [String: [Landmark]] { Dictionary( grouping: landmarkData, by: { $0.category.rawValue } ) } var featured: [Landmark] { landmarkData.filter { $0.isFeatured } } ... }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 } } } ... }categories, featured はComputed Propertyと呼ばれるもので、Property(プロパティ、メンバ変数、インスタンス変数)の一種ですが、実際の値を変数に保持しているわけではなく、アクセスがあったときに書かれている処理を実行して動的に値を返すことができる、というものです。let home = CategoryHome() let categories = home.categories このように通常のプロパティと同じようにアクセスしますが、 Computed Propertyはアクセスされたときに書かれている処理(ここでは get { ... } の中カッコの部分)を実行して値を返します。get と set の両方を定義できて、この例ではget の場合だけが定義されています。 (edited)getしかない場合はget { ... } と書くのを省略できて、中カッコだけにできます。 (edited)struct CategoryHome: View { var categories: [String: [Landmark]] { return Dictionary( grouping: landmarkData, by: { $0.category.rawValue } ) } ... }struct CategoryHome: View { var categories: [String: [Landmark]] { Dictionary( grouping: landmarkData, by: { $0.category.rawValue } ) } ... }func boardView(_ boardView: BoardView, didSelectCellAtX x: Int, y: Int) ですね。ViewController 中の当該部分は↓です。 https://github.com/refactoring-challenge/reversi-ios/blob/master/Reversi/ViewController.swift#L388-L402AVAssetWriterInput とかですかねー。AVVideoCompositionCoreAnimationTool かあ...AVAssetExportSession はバグ多いんですが、#if os(iOS) to conditionally import this framework when building for iOS. No such module 'GitHub' Xcodeを使ってライブラリをリンクさせたことがありませんので、何か基本的な事を間違えているのだと思いますが、どなたか教えていただけると幸いです。
1#import GitHub と書いた部分にエラーが出ましたLink Binary With Libraries セクションでGitHub.frameworkが選べるようになると思います。GitHub と Github で H の大文字小文字がときどきブレてるのが気になります。 家庭くんと岸川さんの書いてるように、 フレームワークファイルを手作りしないで済む方法(プロジェクト依存またはCocoaPods)のほうが無難です。GitHub.xcworkspace ひらけば何もせずにGitHub scheme一回ビルドしてから palygorundのやつ全部動くと思いますよGeneric iOS Device のところをシミューレータにするとシミュレーター向けのビルドになりますgit clone --depth=1 https://github.com/peaks-cc/iOS_architecture_samplecode.git して試したので。macOS 11.15.4, Xcode 11.4.1。 (edited)GitHub > Generic iOS DeviceiPhone 11 Pro Max とかに変えてclass SomeClass { init(cancelHandler: (() -> Void)?, submitHandler: (() -> Void)?) { } }class Parent { var child: Child init(child: Child) } extension Parent: Autohority {}
protocol Authority: AnyObject {} class Child { weak var autority: Authority? init(authority: Authoority) } こうかですね↑ (edited)Parent 作るのに Child 必要、でも Child を作るのに Authority として Parent が必要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)struct ResponseA { let isHoge:Bool } struct ResponseB { let str:String } func requestA() -> Observable<ResponseA> { //通信処理 } func requestB() -> Observable<ResponseB> { //通信処理 }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) } }func accept(responseA: ResponseA, responseB: ResponseB) { ... } だったとしたら、という擬似コードでした。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の時に実装を切り替えることです。 いろいろ試しているのですがうまくいきません。 方法があれば教えてください。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 } } }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() }makeIterator A makeIterator A makeIterator A makeIterator Bstruct 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 {} }DirectProductIterator DirectProductIterator2for では無理だったのでイニシャライザで型情報を埋め込みました。makeIterator を無駄に呼んでるのが気持ち悪いですが・・・。Left や Right に参照型のコレクション渡されると壊れるけど。Sequence と Collection でもいける気がしますね。Sequence で Iterator1 、 Collection where Element == Int で Iterator2 が返されるようにしました。 https://gist.github.com/koher/550ea1e9625e66758bac85eb5063196fimport 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) } } } }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つのクロージャは簡単なクロージャでいったん型の推測が可能になるのでだいたい問題が解決します。無理な場合はもっと細かく分解します。scrollView.setContentOffset にスクロールさせたい 座標をCGPointで渡せばいいことまではわかったのですが xib内のUIコンポーネントの座標を渡してみたところ 常にその座標が(x:0.0,y:0.0)になってしまい 自分が想定しているところまでスクロール出来ず困っています 具体的に、スクリーンショットの Second Input Viewの黒字のタイトルと書かれている UILabelの上までスクロールさせたいのですが この座標を取得するにはどうしたら宜しいでしょうか? 黄色塗りされている部分がxibとなっております。 ご教示頂けると幸いです。宜しくお願いします。 (edited)let frame = secondInputView.titleLabel.convert(secondInputView.titleLabel.bounds, to: scrollView) print(frame) ^ このコードを追加して値を調べてみてください。titleLabel.frame はSuper Viewからの相対座標なので、secondInputViewから見た座標になります。 Scroll Viewでどの位置か、というのはScrollViewから見た座標に変換する必要があります。(20.0, 174.66666666666669, 63.66666666666666, 20.333333333333343) になり frame.origin.y を渡してあげたら、想定した位置までスクロールしました! 調べた中でconvertは出てきたんですけど、ややこしくていまいち理解が出来ずに 避けてしまったので、もう一度ドキュメントをよく見てみます。 非常に助かりましたありがとうございました! (edited)UIGestureRecognizerのdelegate設定したいいんじゃないでしょうか? (edited)UICollectionViewは(UITableViewとかも)コンテンツへのタップデフォルトでは遅らせるようになっていて(だからスクロール中にボタンとかに反応せずにスクロールがスムーズにできる) (edited)modalTransitionStyle にcrossDissolve を指定してpresent で遷移したときの フワッと遷移する際の、durationの値を変更することは可能でしょうか? また不可能な場合、代替策としてどのような実装がありますでしょうか・・・? ご教示頂けると幸いです。viewController.modalPresentationStyle = .custom viewController.transitioningDelegate = self としてカスタムトランジションを実装するのが一般的な方法です。 クロスディゾルブくらいなら遷移元と先でalphaを1=>0/0=>1するだけなので実装も難しくないです。CATransaction.setAnimationDuration()あたりでまずは試してみると雰囲気わかるかも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)UITabelViewDataSouce で調べてみてくださいMediaViewControllerがUITableViewControllerとして作られているので、それ自身がUITableViewDataSourceになっています。MPMedoaPickerControllerで選択されたMPMediaItemを誰かがUITabelViewCellにしないと結果として表示されません...MPMedoaPickerControllerで選択されたMPMediaItemを誰かがUITabelViewCellにしないと結果として表示されません... tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCellで、なにかしらする必要があります。mediaIDは多分なんか識別用の内部的なヤツで表示しても意味ないかも。 (edited)cell.titleLabel.text = mediaItem.title じゃダメですかね//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)let contentView = ContentView().environmentObject(HistoryEntity())//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) } } } }Thread 1: Fatal error: No ObservableObject of type HistoryEntity found. A View.environmentObject(_:) for HistoryEntity may be missing as an ancestor of this view.''' これはどこで起こってるんですか?ForEach(0..<histroy.UserName.count){ ←この行に表示されています (edited)Button(action: { self.isShowingSheet = true })//AddView.swift @EnvironmentObject var histroy: HistoryEntity これでは渡せていないということでしょうかlet contentView = ContentView().environmentObject(HistoryEntity()) ContentViewに渡してるようなこういうenvironmentObjectのModifierを使ってる部分です。EnvironmentObject って自動的に共有されるんじゃないですっけ?@ObservedObject 使ってるのであまり自信ないですが)AddView(isShowingSheet: self.$isShowingSheet).environmentObject(self.histroy) なのでこう書くとまあ解決します。 サブビューなら伝播してくれるんですけど、sheetは別のビュー階層扱いなんでしょうね。NavigationLink は大丈夫なのに .sheet はダメなんですね・・・。NavigationLink は引数に渡すからつながってるけど、 .sheet はクロージャだから途切れてるのか。HistoryEntity を AddView から先で使わないなら、 AddView は @EnvironmentObject じゃなくて @ObservedObject で持ってもいいかもしれませんね。struct AddView: View { @ObservedObject var histroy: HistoryEntity ... }
Text("追加") } .sheet(isPresented: $isShowingSheet){ AddView(histroy: self.histroy, isShowingSheet: self.$isShowingSheet) }})histroy は history の typo だと思いますが元のままにしてます・・・)@EnvironmentObject は複数の View の間で広く(暗黙的に)共有するためのもので、 @ObservedObject は必要なときに明示的に渡すものです。この場合、 .sheet で @EnvironmentObject が途切れてしまうようなので、 AddView にだけ渡すのであれば @ObservedObject で十分かなと思いました。 AddView から先でも広く共有したい種類のものであれば @EnvironmentObject が良いと思います。@EnvironmentObject だからといって大きな不利益があるわけではないですが、必要なものは必要最小限のスコープで狭く使っておいた方が管理が簡単だと思うので、 @EnvironmentObject である必要がないのであれば @ObservedObject でもいいのかなと思いました。 (edited)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() } }@IBOutlet var calender: FSCalendar! とは別のインスタンスであり、したがってdelegateはどこにも登録されていません。 ViewControllerのprintを呼び出したいのであれば、UIViewControllerRepresentableを利用し、そこでUIStoryboardからViewControllerのインスタンスを生成して返す必要があります。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'」というエラーが出てしまいます、、extension ViewController: StoryboardInstantiatable {} の宣言が存在していないのではextension ViewController: StoryboardInstantiatable{ typealias StoryboardInstantiatableViewController = ViewController static var storyboardName: String { return "Main" } } を追加してみましたが、printは動作しないままでした、、 var body: some View{ UICalender() } を var body: some View{ ViewControllerWrapper() } に変更したら理想の動作になりました! 何度も質問に答えていただきありがとうございました!貴重なお時間を割いていただき、ありがとうございました!Date で検索して取得したいという話ではないですか? (edited)Date は年月日じゃなくて秒とかのもっと細かい情報を持っているので、同一年月日だとしてもデータが一致するとは限らないので注意が必要です。"2020-08-11" とか)を保存するようにして、文字列で検索しますね。 Core Data でやったことはないので、 Core Data で何か良い方法があるかもしれませんが。return[]の行に「Will never be executed」と出ます。 ・fetchEmployees()を使いたいのですが、 DataController.fetchRecordEntity() の()内に何を入力すればいいかわかりません。エディタには(self:DataController)と表示されます。DataController.fetchRecordEntity() はクラスメソッドを呼び出してしまっているので、 DataContorller のインスタンスを生成してインスタンスメソッドを呼び出す必要があるように見えます。(ただし、 Core Data を満足に使ったことがないのでわかってないですが)return [] まで到達できないコードになっているのではないでしょうか?
DataController.fetchRecordEntity() 一つにしても、インスタンスとクラスの関係がわかっていないと理解が難しいですし、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 [] }return fetchedEmployees か fatalError("Failed to fetch employees: \(error)") で必ず終了するからです。try context.fetch(employeesFetch) に try がマークされているので、ここでエラーが発生したときに catch 節に入るということがわかります。なので、エラーが発生しなければ return fetchedEmployees 、発生したら fatalError("Failed to fetch employees: \(error)") で fetchEmployees() は終了します。return [] が実行されることはなく、コンパイラが will never be executed (決して実行されることがない)と警告しているのです。try や as! の意味は? fatalError で何が起こる? fatalError の戻り値の型の Never とは?どういうケースで will never be executed の警告が出るか)NSPredicate (これ自体は Core Data とは独立に Foundation に存在します)@Environment などが用いられているのですが、おそらく何かのコードをみようみまねで書いたのだと思いますが、それらについてどう書くべきかを理解するには SwiftUI について学ぶ必要がありますし、そのためには Property Wrapper や Combine の理解も必要になります。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を共有したい場合は有用かなとも思ったのですが、皆さんはどうやって実現されているのでしょうか?HogeFugaDataStore とかの名前にします)にするのでも良いのかなと思いました! 投稿が初めてでして、不明点等あったら突っ込んでいただけると助かります! (edited)FirstPresenter からの入力による変更によって SecondPresenter が何かを View に出力しなければならないのであれば、それが Interactor から SecondPresenter に通知される必要があるのではないでしょうか。
InteractorOutput のメソッドを呼ぶような形かもしれませんし、 name が直接出力に使われるのであれば(たとえば Combine を使うなら) name を Publisher にしておいてそれを購読するとか、もしくは Interactor 自体を ObservableObject にするとか、色々な方法があると思います。Presenter は Interactor を保持するようですし(上記ページによるとプロトコルを介するのが普通なのかもしれませんが)、 Interactor は一つの View に紐づくわけではないですよね?そうすると複数の Presenter が Interactor を共有してもおかしくないと思います。Presenter は Interactor からの通知を受けて、それを View に適した形に変換して通知するものだと思うので、 Presenter からの入力(上図の asks for updates )を受けて Interactor が更新されたときに、必要に応じて Interactor は Presenter に更新を通知する必要があると思います。MainViewController はどうなってるでしょうか?
1*** 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 NSException1x 2x 3x のところに画像をD&Dしてあげれば、本来でないです。 D&Dしてセットしたあとに画像のファイル名変更等するとその警告はでるので、ファイル名変更するなら変更後にD&Dするといいかと。Unsigned の画像は選択してdeleteでいいと思います。 それでこの警告自体はきえるかと。
1swift カメラ qrコード で検索すると記事がいくつも出てくるので、参考にしてやってみてください。 metadataOutput.metadataObjectTypes = [.qr].xcworkspaceを開けば、今まで開発を進めていたxcodeprojにライブラリを取り込んだ状態で構成して開かれます。なので、xcworkspaceを開いてそのまま開発継続して問題ないです (edited)becomeFirstResponder() をプログラムから呼んでもキーボードが立ち上がらない」という問題に直面しています。。タップイベントでキーボードが起動できた後なら問題ないのですが、初回だけ起動されず。 同じような経験をした方、または解決方法をご存知の方はいらっしゃいますでしょうか? こちらのstackoverflow(https://stackoverflow.com/questions/59582631/becomefirstresponder-is-not-showing-keyboard-until-touch-of-any-uitextfield-at-l )と同じ現象になんですが、解決策で提示されているIntercomを使っていないので解決できず困っている状況です。。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)Record や YMD のように Codable に適合した型であれば JSONEncoder や JSONDecoder を使って JSON 形式のバイト列に変換・復元することが簡単にできます。Codable が何をするのかということを学ぶと理解が深まると思います。(このコードを使っていただくこと自体は問題ありません。) (edited) 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)marchv/UIScreenExtension が持ってる値で試してみたらどうでしょうか。UIScreen.main.nativeBounds.width が同じ値でも端末によってppiは異なるので、そこで計算ずれてると思います。 omochiさんのいうようにまずはライブラリが持ってる値で試すと良さそうです。 (edited)pod 'SwiftyRSA', :podspec => "./SwiftyRSA.podspec" (edited) XCTAssertEqual(expected, actual) #define XCTAssertEqual(expression1, expression2, ...) となっており、特にどちらが期待する結果かは書かれていないのですがSwiftを書く人達の中での共通認識や慣習として期待する結果を先に書くというのがあるのでしょうか?XCTAssertEqual(expected, actual) と書かれていたのを見て、最初の引数がexpectedなのだな、と思っただけです。ちょっと調べても見つからなかったのでテストの中で統一されてたらどっちを期待する結果としてもいいのかもしれません。 XCTAssertEqual(table.rowCount, 0, "Row count was not zero.") XCTAssertEqual(table.columnCount, 0, "Column count was not zero.") と書かれているので XCTAssertEqual(実際の値, 期待する結果) がいいのかもしれません(Appleのドキュメントでそうなので)。UIPageViewControllerDataSource にある以下メソッドの呼び出しが余分に呼ばれたり、呼ばれなかったりする時があります。(初回はスワイプ 時はviewControllerBeforeとviewControllerAfterが同時に呼ばれる。以降で向きを切り替えてスワイプ した際の初回のスワイプ のイベントは呼ばれない) 但しtransitionStyleをpageControlに設定した際は正常な通知になるのですが、scrollに設定する際は他に設定する項目があるのでしょうか? 何かご存知の方がいらっしゃいましたらご教授頂けますと幸いです。 よろしくお願いいたします。 func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?
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)httpMaximumConnectionsPerHost を設定しておかないとデフォルト 6 (macOS) らしいです https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1407597-httpmaximumconnectionsperhostWarning unable to build chain to self-signed root for signer "(null)" 現状、他の開発メンバーと同じTeamに参加しているAppleアカウントでCertificateを作成し、そのCertificateをSelectしたProvisioning Profileもダウンロードした状態です。 Automatically Manage Signingにはチェック入れる/入れないどちらも試しましたが同じエラーが表示され、証明書の作り直しなども試しましたがビルドできませんでした。 原因や怪しいところがありましたら教えていただけると幸いです。@resultBuilder という機能を使うことで限定されたコンテキストにおいて if式、switch式相当のものを、それも構築される型を指定して組み立てることが出来ます。ざっくりどんなものかは、SwiftUIにおけるViewBuilderを参照してみて下さい。 (edited)Either.left(A) みたいに書く必要がある。Commonly Rejected Changes に挙げられていて、 それで解決できることは他の方法で解決できる ←これは同意だけど if式を導入すると大きなトレードオフがある ←実際どんなデメリットがあるのかはあまりよくわからないifexp みたいな高階関数を書いてちょっと楽しても良い ↓以下のlet初期化スタイルでもそんな困らない let a: Int if ... { a = 3 } else { a = 2 } と思っているval a = if (cond) { exp } else return (edited)val a = exp ?: return (edited)if ... { return A } ... return A みたいなものを表現しようとしたときに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だとこんなのが書けますね。if (foo) { return A } とだけ書いてある場合、このif式の型は Unit( voidみたいなもん) だね。ただ左辺が無いので意味はない。val a = if (foo) { 1 } else { 2 } // これはaへの代入 val b = if (foo) { return 1 } else { return 2 } // これはここからの脱出、bは代入されないCommonly Rejected Changes に挙げられていて、 それで解決できることは他の方法で解決できる ←これは同意だけど if式を導入すると大きなトレードオフがある ←実際どんなデメリットがあるのかはあまりよくわからない 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))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. Whilextension 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/150849enum 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))Either<String, Int>stderr:<stdin>:34:9: warning: will never be executed 1 ^ <stdin>:31:8: note: condition always evaluates to true if true { ^val a = if (cond) { exp } else return (edited)func calculatePaymentPrice(_ price : Int) -> Int{ if price < 0 { return 0 //エラーの代わり } return Int(Double(price)*1.1) } (edited)func calculatePaymentPrice(_ price : Int) -> Int{ if price < 0 { return 0 //エラーの代わり } return Int(Double(price)*1.1) } (edited)func calculatePaymentPrice(_ price : Int) -> Int { if price < 0 { 0 } else { Int(Double(price) * 1.1) } } こうなるって話をしてると思ってます。式1つなのでreturnは省略しました。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は自作の関数)func calculatePaymentPrice(_ price : Int) -> Int { if price < 0 { 0 } else { Int(Double(price) * 1.1) } } こうなるって話をしてると思ってます。式1つなのでreturnは省略しました。 func calculatePaymentPrice(_ price : Int) -> Int{ if price < 0 { return 0 //エラーの代わり } if price = 0 { return 0 //エラーの代わり } return Int(Double(price)*1.1) }func calculatePaymentPrice(_ price : Int) -> Int{ if price < 0 { 0 } else if price = 0 { 0 //エラーの代わり } else { Int(Double(price)*1.1) } } こうですか??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)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)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 }if が式でなく文なのはミュータブルな値型( struct )を多用する Swift と馴染んでおり、適切な言語仕様ではないかと思います。 (edited)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式欲しいなって思ってますrequest を3回書くからコピペで再利用できないと思ったんだけど、同じ変数の一括編集をエディタでできるから別にいいやと。 中間計算で複雑なことをやる場合はクロージャに閉じ込めてます。request を 3 回書くのは同じものを書くだけなのでまだ良いですが、型を明示しないといけなくなるのがたまに辛いですね...func connect(parameter: String) { let request: URLRequest if parameter == "abc" { request = .init(/* A */) } else { request = .init(/* B */) } URLSession.shared.dataTask(with: request).resume() }let foo: Foo = .init(...)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() }fileprivate を使う理由ってなにかありますかね。 (そうじゃなきゃいけない場面を除いて。) 最近 private でよいのに、 fileprivate が使いたいということを言われて... (edited)fileprivate (というアクセスレベル修飾子)を書く箇所があるか?という話をしました。 fileprivate なメソッドを作りたいケースでも private extension にすればアクセスレベルとして fileprivate 扱いになるので、 fileprivate というアクセスレベル修飾子を書く機会がないんじゃないかという話です。 private なトップレベル関数も同様です。fileprivate 書かないといけないねという話になりました。 https://discord.com/channels/291054398077927425/306995750418513920/805675304340946944fileprivate (というアクセスレベル修飾子)を書く箇所があるか?という話をしました。 fileprivate なメソッドを作りたいケースでも private extension にすればアクセスレベルとして fileprivate 扱いになるので、 fileprivate というアクセスレベル修飾子を書く機会がないんじゃないかという話です。 private なトップレベル関数も同様です。 fileprivate は使っててほぼ例外的にコンパイラが無理見えない、って言ってくるときだけにつけてる印象があって、でもやっぱりそうか。ほとんどないですよね... private extension なるほどfileprivate はなんかゴタゴタの末やむなしで残ってる感じだったんですね。class MyClass { fileprivate func foo() { ... } } と private extension MyClass { func foo() { ... } } が等価かな?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)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) results や targets を Actor で守りながら、 find を TaskGroup で並行に走らせるのが良いように思います。results をそれぞれのタスクで使うところでコピーが必要な問題は残りますね。 コピーしないなら「共有+利用中はロックで専有する」か「ロックフリーデータ構造を使う」しかないですが、 ロックで専有はSwift concurrencyだとやっちゃいけないので、 ロックフリーデータ構造が良さそうだけど詳しくないです。results をそれぞれのタスクで使うところでコピーが必要な問題は残りますね。 コピーしないなら「共有+利用中はロックで専有する」か「ロックフリーデータ構造を使う」しかないですが、 ロックで専有はSwift concurrencyだとやっちゃいけないので、 ロックフリーデータ構造が良さそうだけど詳しくないです。 targets や results のミューテーションを Actor に閉じ込めればコピーは要らなくないですか?results は find に渡してるのか。 (edited)find の処理の内、 results を利用する部分だけを Actor に切り離せるのであれば、 find に Actor を渡す形にしてコピー不要にできる可能性はあると思います。find の中で繰り返し results にアクセスしていて、それが処理負荷の中で支配的なようであれば、都度 async/await を通して Actor にアクセスするよりも、事前にコピーして同期アクセスした方が軽そうです。async/await を挟むと、 find の途中で await の度に results が変更されている可能性が存在するので、データ不整合の意味でも厳しいかもしれませんね。results は append されるだけでなくデータを書き換えられることはありますか? append されるだけならイミュータブルな(でも前方に要素追加は可能な)連結リストを使えばコピー不要にできるかもしれません。async/await を挟むと、 find の途中で await の度に results が変更されている可能性が存在するので、データ不整合の意味でも厳しいかもしれませんね。 results は Actor の中にあって、 find には Actor を渡して都度 async な API を通してアクセスするイメージでした。results は Actor の中にあって、 find には Actor を渡して都度 async な API を通してアクセスするイメージでした。 results は Actor の中にあって外から直接さわれなくして、 Actor のメソッドを通して操作するイメージです。 results.contains をしたければ actor.contains みたいなのを呼び出す。
results は Actor の中にあって外から直接さわれなくして、 Actor のメソッドを通して操作するイメージです。 results.contains をしたければ actor.contains みたいなのを呼び出す。
findCycleFreePivot のロジック次第ですね。僕は今はこれを精査する時間まではないですawait 前後で整合性が崩れてダメそうに思います。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)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 (または他の方法で)で設定するということはできるのでしょうか? あるいは他の解決法があれば教えて頂けると嬉しいです$ swift build --triple x86_64-apple-macosx とか? (edited)x86_64-apple-macosx みたいな文字列のことです。 <arch>-<vendor>-<os> だったっけな。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 ✘ のところが何か悪いのかなarm64_big_sur がOSとして別れているのでbig_sur 向けには armは入って無さそう。$ 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 すごい,できた-X<foo> <foo向けオプション> って指定するものだから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)-Xpreprocessor -fopenmp を C のコンパイラに渡さないといけないから,両方 -Xcc しなきゃいけないのかなと思いました. (edited)-Xpreprocessor -fopenmp になって、 さらにその先のプリプロセッサに -fopenmp が渡るのか。-fopenmp が Cコンパイラ向けオプションかと思ってましたが、なるほど。あってそう。clang -fopenmp test.c with clang -Xpreprocessor -fopenmp test.c -lomp.delegate プロパティの getter と setter をオーバーライドして、別のプロパティ (userDelegate など) として保存して、本来の super.delegate プロパティに、自前のデリゲートオブジェクト(今プレースホルダの実現に使ってるやつ)を渡します。 自前のデリゲートオブジェクトは、各種デリゲートメソッドの呼び出しを実装して、 userDelegate のメソッドも呼ぶようにすれば、ユーザー側からは普通にデリゲートが使えてるように見えます。% を出力したいですがなかなかうまくいかない 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)String(format:) を通るみたいなので、2.の手法+一個ダミーの %@ を入れておいて運用でカバーするとか…? (edited)\\ と2個並べるとどうですか? (edited)String(format:) を通るみたいなので、2.の手法+一個ダミーの %@ を入れておいて運用でカバーするとか…? (edited)"url" = "http%%3A%%2F%%2Fwww.abc.xyz%@" とかにしておいて運用は R.string.url("") とかで誤魔化す"url" = "http%%3A%%2F%%2Fwww.abc.xyz%@" とかにしておいて運用は R.string.url("") とかで誤魔化す editingDidEndOnExit がだいたい同じはずですね。 editingDidEnd も併用するとPlaceholderはDelegateなくても実装できると思います。struct Test { func test() async { async let x = 42 // Immutable value 'x' may only be initialized once print(await x) print(await x) } }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と同じ理由かとawait xを書くとエラーになります。 struct Test { func test() async { async let x = 42 print(await x) } } (edited)struct Test { func test() async { async let x = 42 print(await x) } } (edited)struct Test { func test() async { async let x = 42 // Immutable value 'x' may only be initialized once print(await x) print(await x) } }<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 ^~~ varstruct Test { func test() async { async let x = 42 print(await x) print(x) } }<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) ^struct Test { func test() async { async let x = 42 let x2 = await x print(x2) print(x2) } }struct Test { func foo() async -> Int { 42 } func test() async { async let x = foo() print(await x) print(await x) } }<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() ^~~ varawait xを書くとエラーになります。 struct Test { func test() async { async let x = 42 print(await x) } } (edited)async let x に対して await x は現状 1 回だけ呼び出せるみたいですね。x2 みたいにして使うしかなさそうですね。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) } }<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()) ^~~ varawait lと同時にrもawaitされる挙動のせいでかなりトリッキーになるstruct Test { func test() async { async let x = 42 // Immutable value 'x' may only be initialized once print(await x) print(await x) } } XCSwiftPackageProductDependency という名前で登録されてるっぽい (edited)xcodebuild で操作できるっぽいので、自前でxcframework化もいける?@MainActor アトリビュートとかstruct TextView: UIViewRepresentable { func makeUIView(context: Context) -> UITextView { UITextView() } func updateUIView(_ uiView: UITextView, context: Context) { } } struct ContentView: View { var body: some View { VStack { TextView() } } }setText: すると変な位置にスクロールするのはknown behaviorsetText: (textView.text = なんちゃら か textView.attributedText = なんちゃら)が呼ばれていないかデバッガーで確認 (updateView(_:context:)のなかとか?) 2. 呼ばれているなら、呼ばないようにする 3. 呼ばれていないならさらなる調査が必要... (edited)setText: (textView.text = なんちゃら か textView.attributedText = なんちゃら)が呼ばれていないかデバッガーで確認 (updateView(_:context:)のなかとか?) 2. 呼ばれているなら、呼ばないようにする 3. 呼ばれていないならさらなる調査が必要... (edited)textView.text != text とかやってるのか... (edited)UIWindow をとっておいて、その rootViewController を経由して表示するなどできると思います(経由してというのは、たとえばそれが UINavigationController であれば、さらに topViewController を取得するなどした方が良いかもしれません。ただ、とりあえず SwiftUI かつアラートを出す程度であれば、僕のアプリの構造(根っこで UIWindow を捕まえて↓の方法で保持し、 UIHostingController の中に NavigationView が入っている)の範囲内では UIWindow の rootViewController を使って UIAlertController を present するので動いています)。 なお、僕は SwiftUI で UIWindow を保持するのは↓の方法を採用しています。 https://qiita.com/shiz/items/3b829b1521f9723aa875 (edited)ErrorHandleProvider { errorHandler in Button(action: { do { try ... } catch { errorHandler(error) } }) { Text("try") } } ざっくりこんな感じのIFを定義するイメージ (edited)NavigationView に .alert 書いても動きそう?go test -race で race detection を有効にしてテストを走らせることができるのですが、Monterey になってから -race 付けた時だけクラッシュするようになりました。ぼくはこの辺詳しくないですが、 go test -race が LLVM の TSAN を使っていたようです。 (edited)@MainActor を付けるのはまだ行わない、など) あと私の PR(コード整形などが含まれていて見づらくなってしまいましたが、、)で気づいたことがあれば、ご指摘いただけると嬉しいです @MainActor を付けたのですが、UIView や AppDelegate などにも脳死で付けたほうがいいのかなぁ… (edited)@MainActor で保護されているとき、 そのメソッドは、MainActorからの呼び出し→そのまま 他のActorからの呼び出し→async化 というのが型としての挙動で それを継承したサブクラスが @MainActor では無かったとした場合 継承してオーバーライドしたメソッドは、 サブクラスのメソッドとしてみれば、保護が外れているので、 どこから呼び出してもそのままの挙動 つまり、マルチスレッドセーフなメソッドとして実装されているという仮定が置ける。 このマルチスレッドセーフなオーバーライド実装を、 スーパークラスのメソッドとしてアップキャストして見てみると、 @MainActor として保護されている事になるけど、 MainActorからの呼び出し→マルチスレッドセーフな実装にオーバライドされているので問題ない 他のActorからの呼び出し→実装に対しては無意味にasync化するけど、本体はやはりマルチスレッドセーフなので問題ない (edited)-Xfrontend -warn-concurrency を付けるのをオススメします。これで、 Swift 6 からコンパイルエラーになる違反を警告として上げてくれます。UIViewController が Obj-C だからとかもあるのかなぁと思ってたんですが、 Pure Swift 同士でも起こるんですっけ?AppDelegate などに @MainActor を付けてみた https://github.com/uhooi/UhooiPicBook/pull/265/commits/c680f5a29efca61326e2a7b28c1a48efb1c3f0e7-Xfrontend -warn-concurrency を付けるのをオススメします。これで、 Swift 6 からコンパイルエラーになる違反を警告として上げてくれます。 UIViewController が Obj-C だからとかもあるのかなぁと思ってたんですが、 Pure Swift 同士でも起こるんですっけ? @MainActor (が付与されてる)扱いにならなくても、スーパークラスとして扱われたときの挙動を破壊することはないから、サブクラスで @MainActor 扱いにならなくても実は問題ない? (edited)@MainActor 扱いになるとして。@MainActor 扱いになるとして。 @MainActor 指定は 関数型に対して、型としては、制約を追加して狭めているように働くので。@MainActor 付けなきゃいけないのは仕様で、 VC を継承したらとりあえず @MainActor 付けとけばいいのか。 (edited)@MainActor 扱いになる必要はないですが、そのサブクラス内部で @MainActor の恩恵をうける(UI操作を呼ぶなど)ために結局はつけることになると思います (edited)viewDidAppear とかはオーバーライドだから @MainActor 付けなくても MainActor-isolated だったと。viewDidAppear とかが何も書かなくても @MainActor だったかどうかはどうだったかな・・?@MainActor class ViewController { var isolatedCounter: Int = 0 func viewDidAppear() {} } class XViewController: ViewController { override func viewDidAppear() { self.isolatedCounter += 1 } }@MainActor class ViewController { var isolatedCounter: Int = 0 func viewDidAppear() {} } class XViewController: ViewController { override func viewDidAppear() { self.isolatedCounter += 1 } } viewDidAppear とかが何も書かなくても @MainActor だったかどうかはどうだったかな・・? @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)@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)isolated 引数のstatic版だから引数が見かけ上消えてると考えられるので、それが良いと思います。isolated 引数指定が 見えない self に付与されていると考えると統一的に整理できる。@MainActor を付けるようにしてみました↓ https://github.com/uhooi/UhooiPicBook/pull/265/commits/11f446d2ae38d5cab38aaae98dc2c3d5af6afe07Task { ... } で括れば Interactor 以下の層のメソッドに async を付ける必要がなくなるので、実装は楽です。 Task { ... } で括らないと I・P それぞれのメソッドに async を付ける必要が出てくるので修正が手間ですが、適切なのはこちらなのかなと考えています。 (edited).observe(on:) ?subscribe(on:) は subscribe スレッドの制御だね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) } }interactor.saveForSpotlight() の実行を待たずに router.showMonsterDetail(monster: monster) を実行したい 処理の順番を逆にすればいけそうだけど、微妙な気がする func didSelectMonster(monster: MonsterEntity) async { await interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) }interactor.saveForSpotlight() の実行を待たずに router.showMonsterDetail(monster: monster) を実行したい 処理の順番を逆にすればいけそうだけど、微妙な気がする func didSelectMonster(monster: MonsterEntity) async { await interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) } 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 () に代入する事は実際できる気がする。 オーバーライドの考え方は、代入できる=親側の型としてみなして呼び出せる、なので。 サブクラス側のシンボルが見えてるときには狭い型として扱えたほうが嬉しい、というのは同期/非同期だとわかりやすいですね。 func saveForSpotlight(_ monster: MonsterEntity) { let key = "spotlight_\(monster.name)" monstersTempRepository.saveMonster(monster, forKey: key) Task { await spotlightRepository.saveMonster(monster, forKey: key) } } ただこうすると単体テストで spotlightRepository.saveMonster() が呼び出されたか確認しづらいですね、、(苦戦中)
2 func saveForSpotlight(_ monster: MonsterEntity) { let key = "spotlight_\(monster.name)" monstersTempRepository.saveMonster(monster, forKey: key) Task { await spotlightRepository.saveMonster(monster, forKey: key) } } ただこうすると単体テストで spotlightRepository.saveMonster() が呼び出されたか確認しづらいですね、、(苦戦中) @_implicitSelfCapture だから)selfを気づかずキャプチャして不用意に生き残る気がしましたがこのへんはどうなんでしょうかね 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) } 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) } : Void がないと警告が出ます)。 func didSelectMonster(monster: MonsterEntity) async { async let x: Void = interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) await x }
(edited): Void がないと警告が出ます)。 func didSelectMonster(monster: MonsterEntity) async { async let x: Void = interactor.saveForSpotlight(monster) router.showMonsterDetail(monster: monster) await x }
(edited)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)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)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)async let x: Void = interactor.saveForSpotlight(monster) がawaitより先に動き始めた場合ってことですよね?
async 関数が二つと同期関数が一つasync let で Void を受けるべきケースがあるだろうなと思って書きました。
async let では実行タイミングが保証されないとのことなので、できるなら処理の入れ替えで対応したほうがベターということですね!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@MainActor を付けたら不要になりました…笑)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 async let では実行タイミングが保証されないとのことなので、できるなら処理の入れ替えで対応したほうがベターということですね! async let もせずに await した方が良いことになりませんか?それが必要なケースもあると思いますが、その場合、インタラクションから遷移まで delay が発生するので、 UX を損ねる可能性が気になります。 saveForSpotlight が体感できないくらい一瞬ならいいですが。あと、 suspend 中は UI スレッドがブロックされてないので(それ自体は悪くないですが)、ボタン連打された場合のケアとかが気になります。 並行で走らせるなら「画面遷移する前にXX」することを保証できないから入れ替えでも問題なさそうに思いますが、元々問題が起こってなくて(かつ、元の saveForSpotlight のコードは並行に走ってて投げっぱなしで結果を待たない実装になってて)、忠実にその挙動を再現するなら、やっぱり async let が良さそうですね。 > Cc: @uhooi
func testFoo() async { XCTAssertEqual(await foo(), 1) }func testFoo() async { XCTAssertEqual(await foo(), 1) } await foo()のところでエラーになるんですよね(あれ?何か勘違いしてます?) 'async' call in an autoclosure that does not support concurrencyreasync があれば @autoclosure に async 、 XCTAssertEqual に reasync を( Apple が)付けることで↓にできる? await XCTAssertEqual(foo(), 1) (edited)expression1 と expression2 に async が付いてないので無理だと思います。 https://developer.apple.com/documentation/xctest/2142776-xctassertequalreasync は今後の機能でしょうか? rethrows の async 版で当初から言及されてたんですが、あまり使いどころがないこともあり現状では入ってないです。この XCTAssertEqual はいいユースケースな気がします。rethrows の async 版で当初から言及されてたんですが、あまり使いどころがないこともあり現状では入ってないです。この XCTAssertEqual はいいユースケースな気がします。 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)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)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)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)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)Task.init に渡すクロージャは特別で、普通は @Sendable クロージャにはコンテクストが引き継がれないんですが、 Task.init に渡すクロージャだけ例外的にコンテクストが引き継がれます。 @_implicitSelfCapture@_inheritActorContext が付いてるので。 (edited)@_inheritActorContext かな?UIResponderに@MainActorが付いているので、AppDelegateには必要ないかもしれません。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/36007UIResponderに@MainActorが付いているので、AppDelegateには必要ないかもしれません。 @available(iOS 2.0, *) open class UIResponder : NSObject, UIResponderStandardEditActions { ただ UIResponder の定義に飛んでも MainActor が付いていないんですよね、、 別の場所で付いているのでしょうか?@MainActor を指定する必要がある」と見たのですが、 AppDelegate や SceneDelegate は大丈夫なのでしょうか…?(そのあたりがよくわからず)@MainActor を指定する必要がある」と見たのですが、 AppDelegate や SceneDelegate は大丈夫なのでしょうか…?(そのあたりがよくわからず) 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 #endifView の body が Main Actor Context で実行されるのもそれですか? body に @MainActor 付いてないし、どこから来てるんだろうと思ってたんですが。 https://developer.apple.com/documentation/swiftui/view/body-swift.propertyNS_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-attributesView の body が Main Actor Context で実行されるのもそれですか? body に @MainActor 付いてないし、どこから来てるんだろうと思ってたんですが。 https://developer.apple.com/documentation/swiftui/view/body-swift.property 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@_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)
1swift_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 AppDelegate や UIViewController などに、明示的に @MainActor を付ける必要はなさそうですね…。UIViewController のサブクラスには明示的に @MainActor を付けないと、 Sendable 扱いにならず、 Task.init のクロージャの中から self にアクセスできずに困ると思います。UIViewController のサブクラスには明示的に @MainActor を付けないと、 Sendable 扱いにならず、 Task.init のクロージャの中から self にアクセスできずに困ると思います。 Sendable 扱いにならないのでしょうか?unsafe とはどのような意味でしょうか? 直感的には「安全じゃない → 他のアクターコンテキストに渡せない → Sendable でない」のような感じがしますが@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 truefoo に nonisolated 付けたら↓になるので、 foo も MainActor に保護されてるっぽい。 foo 1 false foo 2 falsefoo 1 と foo 2 の結果が true か false かが異なるので、挙動が変わってるかと。 (edited)ViewController に @MainActor や : Sendable を付けなかった場合に、 ViewController が Sendable にならないのがバグなのか。UIViewController にはとりあえず明示的に @MainActor を付ける」という戦略もありかも(私にはちょっと難しい、、)MainActor-isolated なのかと思ってたのに。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)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() } }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("失敗しました") } } }// (1) ↓ここの `!` UIImage(named: "cat")! // (2) fatalError("変換出来ません") ↑どっちで失敗してるんでしょうか?cat がプロジェクトに追加されてない (2)なら画像ファイル cat が壊れてる、別のファイルになっている などが原因だと予想します。classifLabel がContentViewのフィールドとして定義されていて、うまくいっていたんだと思います
1fopen failed for data file: errno = 2 (No such file or directory) と出るので分割したクラス側で画像を参照できていないのかと思っていました 今現在もググって解決法を模索中です。 もしかしたらラベルが出ていないだけかもしれないので色々試しています。 色んな記事を読むと値渡しがswiftの初心者の壁みたいなのfopen failed なら UIImage(named: "cat")! が失敗してそうimport SwiftUI import CoreML import Vision class Mlwork { var classifLabel:String = "" func labelupdate(tmp:String){ classifLabel = tmp print(classifLabel) }func labelupdate(tmp:String) -> String{ self.classifLabel = tmp これで代入が出来なくて詰みました。 まだ画面遷移などもやっていないので、もっと難しくなるかと思うと心配です。import SwiftUI をするとその中の変数の扱われ方が全然把握できてないです ここを理解できると結構自由に色々できそうなのですが、そこに初心者の壁があるとよく書かれているので相当理解するのが難しそうな予感ですGeometryReader 2. Viewの中に動的に変更可能な変数を設置したい → @State を使って、目的が達成できるのではないかと思います。公式のドキュメントやサンプルコードをチェックしてみると良いと思います.gesture( DragGesture() .onChanged { (value) in print(value.location) } .onEnded { (value) in print(value.location) } ).gesture( DragGesture() .onChanged { (value) in print(value.location) } .onEnded { (value) in print(value.location) } ) extensionを使ってString型に生えてるライブラリ独自のプロパティを利用者側のコードの変更でコンパイルが通らないようにする(もしくはワーニングを出す)ことは可能でしょうか? 自分が試したこととしては @available()でunavailableにする @available()でdeprecatedにする string のプロパティが辛くて、チーム開発時に意図せずSwiftGenのリソースを扱う時に.string をつけてしまっているケースが多発していて、それを防ぎたいというモチベーションでした (edited)string を消すPRを出すことな気が確かにするのですが、OAuthをする上で需要があるのかなという気もしてよく分からずという感じです (edited)@_implementationOnly がつかえるんですね。ありがとうございます! (edited)class FooInteractor { private let httpClient: HTTPClient init(httpClient: HTTPClient) { self.httpClient = httpClient // ???: DI ? } } class HTTPClient {} 私は DI ではないと思うのですが、↓の記事のコメントで「一般的には DI と呼ぶ」と書かれているので、どちらなのか気になっています…。 https://qiita.com/uhooi/items/03ec6b7f0adc68610426HTTPClient がfinalじゃなかったら機能的にはprotocolと同じじゃないですか?HTTPClient が final なら違うと思います。delegate も DI だと思ってます。@MainActor final class FooViewState<Repository: RepositoryProtocol>: ObservableObject { ... } (edited)class FooInteractor { var httpClient: HTTPClient } class HTTPClient {} var interactor = FooInteractor() interactor.httpClient = HTTPClient() // ???: これも DI ? 継承できれば DI ということは、 HTTPClient でなくプリミティブ型だったら DI ではない?HTTPClient がサブクラスを作って挙動を差し替えるものかどうかによるんじゃないでしょうか?HTTPClient を受け取ることを期待しているならそれは DI じゃないですが、サブクラスを受け取ることを期待していたら DI だと思います。HTTPClient 自身も渡せるし、サブクラスも渡せる場合でも、そのサブクラスがモジュールの外で宣言されていたら DI かと。HTTPClient を継承した HTTPClientMock を注入することはできますもんね、、 class FooInteractor { private let httpClient: HTTPClient init(httpClient: HTTPClient) { // !!!: `HTTPClientMock` も渡せる self.httpClient = httpClient } } class HTTPClient {} final class HTTPClientMock: HTTPClient {}class FooPresenter { var count = 0 } let presenter = FooPresenter() presenter.count = 1 // !!!: これをDIとはいわないstruct Foo { init(x: Int) } Foo(x: 42) (edited)struct Foo { init(x: Int) } Foo(x: 42) (edited)foo.count = 2 だろうと、それがスレッド数を意味してたらDIと言えそうx.removeBoxes(havingLength:)が使われているんですが、"having"は前置詞なんですかね? https://www.swift.org/documentation/api-design-guidelines/#argument-labels@main struct WidgetExtension: Widget { let kind: String = "WidgetExtension" init() { FirebaseApp.configure() // ここに置いた } // 共有 iOS キーチェーンを使ったアプリ間認証を有効にする try? Auth.auth().useUserAccessGroup("*****") } 今回のケースとはやりたいことが違うと思いますが、なにか参考になれば!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に処理が渡る前にデコード失敗してしまい不可能な気がしているのですが合っているでしょうか。Bool? にした上でKeyedDecodingContainer.decode が実装されていれば、そっちが優先するという技です (edited)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)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) Bool? にするメリットがないためですね。 これ使って実装進められそうです。ありがとうございました。closure { [hoge] in ... })swift_release を指定すれば、止まります。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)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)init Foo: refCount = 2 init capture: refCount = 3 deinit capture: refCount = 2 (edited)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)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 = 2let 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 }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 } <stdin>:1:11: error: cannot find 'Foo' in scope let foo = Foo() ^~~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 }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 = 3class 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)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 = 1type A = { type: 'A' } type B = { type: 'B' } type AB = A | B // union typeenum があります。 enum AB { case a case b } func takeAB(ab: AB) { switch ab { case .a: print("a") case .b: print("b") } }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)enum Components: View { public var body: some View {} case a(ComponentA) } struct ComponentA {}@ViewBuilder var body: some View { if hoge { ComponentA() } else { ComponentB() } } こんな感じ、今ってViewBuilderはcomputed propertyでも動きますよね (edited)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)find / -name XCPreviewAgent |& xargs grep XCPreviewAgent これで見つかるかな。。 (edited)/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCPreviewAgent.app/Contents/MacOS/XCPreviewAgent これ叩いたら Hello world 出せたww
2weak の誤用を予想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 ^ のような感じです。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)secondVC.SecondTestLabel.text = PageTest ^ 問題の場所はここってことですよね? この行の前に print(secondVC.SecondTestLabel) を追加して何が出力されるか教えてください。SecondViewControllerがstoryboardかxibで作成されていて、SecondTestLabelのIBOutletが壊れていて @IBOutlet var SecondTestLabel: UILabel! の部分がnilになってるのではないかと予想しましたSecondTestLabelプロパティの左に○か◎が表示されてると思います)_ = vc.view みたいなの書きませんでしたっけ?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. } */ }weakを消して、StoryboardのSecondViewControllerlet secondVC = storyboard!.instantiateViewController(withIdentifier: "top2")as! SecondViewController のすぐ後に _ = secondVC.view を追加するっていうのも試してみてください。storyboard.instantiateViewController(withIdentifier:) はStoryboardをベースにUIViewControllerインスタンスを作りますが、この時点ではStoryboardの状態をインスタンスに復元せず、UIViewControllerを表示するタイミングになって初めて復元します。 _ = secondVC.view というのは、UIViewControllerにviewを明示的に要求することで、表示の前に状態を復元させる意図があります。
1init(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 ^ のような感じです。 createAt と createdAt でtypoがあるようですね
1createAt と createdAt でtypoがあるようですね dic の中身が書いてありますよ。そこでkeyをtypoしていると気づきましたcannot load such file -- 3.1/ffi_c (LoadError) どなたか似たようなエラーを経験している人がいれば、アドバイスを頂けるとありがたいです。よろしくお願い致します。 (edited)which ruby と打つと何が表示されますか?$ echo "source 'https://rubygems.org' gem 'cocoapods'" > Gemfile (edited)$ env PATH=/usr/bin:/bin bundle install --path=.bundle (edited)$ env PATH=/usr/bin:/bin bundle exec pod install (edited)bundleは Bundler https://bundler.io/ ってやつで、rubyのデファクトの依存関係管理管理ツールです。こうするとでpythonのpython -m venv + pip相当になります。/Libraryとかどこも汚さないし、.bundle 以下で完結します。env PATH=/usr/bin:/binはsystemにインストールされてる汚されてないrubyだけを使うためです。rbenvやその他のインタープリタ管理ツールはいろいろ汚されていることが多いのでどの環境でも動くを再現できないからmacOSではsystem ruby (2.6, /usr/bin/ruby)が使えるのであればそれを使ったほうが良いと思ってます。 (edited)$ env -i HOME=$HOME PATH=/usr/bin:/bin bundle ... のほうがより安全かもしれないなあ。変な環境変数を誰かに入れられてる可能性もある...$ 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) のようなエラーが出てきてしまいました。env -i HOME=$HOME PATH=/usr/bin:/bin GEM_HOME= GEM_PATH= bundle install --path=.bundle (edited)/Library/Ruby/Site/以下抹消したほおうがいいかもしれません。これはsudoがいります。 (edited)$ find /Library/Ruby/Site /Library/Ruby/Site /Library/Ruby/Site/2.6.0 /Library/Ruby/Site/2.6.0/universal-darwin21env -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. と表示されました。これは成功したということでしょうか?env -i HOME=$HOME PATH=/usr/bin:/bin GEM_HOME= GEM_PATH= bundle exec pod とかしてみてください (edited)/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. まだどこか汚されてるとか可能性ありそうですか?env -i HOME=$HOME PATH=/usr/bin:/bin GEM_HOME= GEM_PATH= bundle install --path=.bundle を実行した時にインストールされていた感じでした。そもそも動かないって感じですかね。$ echo "source 'https://rubygems.org' gem 'cocoapods'" > Gemfilesource 'https://rubygems.org' gem 'cocoapods'env -i LANG=en_US.UTF-8 HOME=$HOME PATH=/usr/bin:/bin bundle exec pod installですね。~/Library/Logs/DiagnosticReports か /Library/Logs/DiagnosticReports に出来ているはずのクラッシュレポートを貼って頂けると 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. env -i HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle install --path=.bundleですね (edited)env -i LANG=en_US.UTF-8 HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle exec pod installenv -i HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle install --path=.bundleですね (edited)env -i LANG=en_US.UTF-8 HOME=$HOME PATH=/usr/bin:/bin arch -x86_64 bundle exec pod install ffi_c.bundle のアーキテクチャ見てもらえばよかった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)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" } } } }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" } } } } <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] = [ ^@MainActor 明記してるからactor境界をまたぐ部分がなくない?self.list じゃなくて self でしょ Task { // << ここ await MainActor.run { @MainActor in Task { // << ここ await MainActor.run { @MainActor in Model.list!modify でselfのinoutが必要かと思ったけど違うのかlet で宣言したオブジェクトのフィールド書き換えられるのと同じ理屈UIView.window → UIWindow.windowScene → UIWindowScene.screen を取ってくるのが良いのではないでしょうか (edited)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)swift package clean や .build の削除は試しました?env で出力した環境変数を載せられます?(右辺は適当にマスクして大丈夫です).build と .swiftpm を消したらいけそうです 今実行中ですswift package clean は実行してもエラーのままでしたactor Executer { var currentTask: Task<Void, Never>? func append(_ body: () async -> Void) { let old = currentTask currentTask = Task { await old?.value await body() } } }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) } } }Buffer はひとつ遅れて開放されるので若干リークといえるかもしれませんが…swift_release されるので、Task構造体のキャプチャがチェインしていてもリークの心配は無さそうです。 https://github.com/apple/swift/blob/dd00a7571acd512873b13d9329bb7d159cf2568c/stdlib/public/Concurrency/Task.cpp#L489swift_release されるので、Task構造体のキャプチャがチェインしていてもリークの心配は無さそうです。 https://github.com/apple/swift/blob/dd00a7571acd512873b13d9329bb7d159cf2568c/stdlib/public/Concurrency/Task.cpp#L489 Concurrency.Task は値型だから、ヒープ上の実体オブジェクトがあって、それがここでreleaseしてるって事かな? 終了したTaskに対して後から task.value で取れるけど、これは Cocurrency.Task に保存されてる?Task がコピーされてるときってどうなってるんだFutureFragment という領域に結果を保持しています。終了したTaskでも .value を呼べるならTaskヒープオブジェクトは生きてるのでそこから取ってくる。swift_releaseは関係なかったです。キャプチャ時のretainに対応するreleaseが _ = await old?.value の直後に入るのでキャプチャする側のクロージャが解放される前にTaskを手放せるからリークしない、ということでした。 (edited)swift_release されるので、Task構造体のキャプチャがチェインしていてもリークの心配は無さそうです。 https://github.com/apple/swift/blob/dd00a7571acd512873b13d9329bb7d159cf2568c/stdlib/public/Concurrency/Task.cpp#L489 swift_releaseは関係なかったです。キャプチャ時のretainに対応するreleaseが _ = await old?.value の直後に入るのでキャプチャする側のクロージャが解放される前にTaskを手放せるからリークしない、ということでした。 (edited)old を var にして、以下のように明示的に解放すると確実に安全で良いと思います。 現状リークしないのはコンパイラのコード生成のブレに依存してるようです。 _ = await old?.value old = nilcurrentTask と同様に actor のプロパティにしてしまうのが簡単そう? EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64に設定していてSPMを利用する場合、M1のマシンでx86_64シミュレータのバイナリが見つからないのですが、何か解決策はないでしょうか。xcodebuild -project SwiftUIQuestionSample.xcodeproj -scheme SwiftUIQuestionSample -destination 'platform=iOS Simulator,name=iPhone 13 Pro' VALID_ARCHS=x86_64 build のようにするとビルドできます。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)までしか分からないのですが、何かいい方法があるのでしょうか?URLError POSIXError などがありますね。 そういえばたどり着き方はどこでわかるんだろう・・・ 実装は public struct URLError : _BridgedStoredNSError { ... } って感じでここにあるみたいですけど https://github.com/apple/swift-corelibs-foundation/blob/eec4b26deee34edb7664ddd9c1222492a399d122/Darwin/Foundation-swiftoverlay/NSError.swiftCocoaError.Code (CocoaError.fileNoSuchFile とかの型)に static func ~=(match: Self, error: Error) -> Bool は定義されているので、逆側からマッチングする( fileNoSuchFile かどうか調べる)のはできそうですけどね。上のcatchはこれでマッチングしてますよね。 https://developer.apple.com/documentation/foundation/cocoaerror/code/3726493do { 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)までしか分からないのですが、何かいい方法があるのでしょうか? NS_ERROR_ENUM をキーに抽出しているので抜けが多々ありそうですが (edited)func todoInt() -> Int { fatalError("TODO") } func todoSequence() -> some Sequence { fatalError("TODO") // Return type of global function 'todoSequence()' requires that 'Never' conform to 'Sequence' }func todoInt() -> Int { fatalError("TODO") } func todoSequence() -> some Sequence { fatalError("TODO") // Return type of global function 'todoSequence()' requires that 'Never' conform to 'Sequence' } <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 { ^~~~~~~~~~~~~
1View.blur(radius:opaque:) があります。ぼかしの程度の指定がCSSの指定と異なりますがradiusパラメータを同じような感じになるように調整するとうまくいくと思います。
1swiftコマンドで実行するとクラッシュトレースが出力されるのですが、クラッシュが発生した行番号を出力する方法をご存知の方がいれば教えていただけないでしょうか?ちなみに 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.0swift コマンドで実行した場合はスクリプト側の行番号などはスタックトレースに表示できません。swift コマンドでの実行にこだわりがなければ、 swiftc -g foo.swift でデバッグ情報付きの実行ファイルを作って、lldbなどで実行した上で、クラッシュ時のバックトレースをみるのが良いと思います。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)swift コマンドで実行した場合はスクリプト側の行番号などはスタックトレースに表示できません。swift コマンドでの実行にこだわりがなければ、 swiftc -g foo.swift でデバッグ情報付きの実行ファイルを作って、lldbなどで実行した上で、クラッシュ時のバックトレースをみるのが良いと思います。 swift コマンドからだと出ないんだね、気づいてなかったわswift コマンドでうまく行かない理由ですが、 swift コマンドでの実行はLLVM JIT経由でコンパイラプロセス内でスクリプトが実行されるんですが、その場合にDWARFが正しく作られていない、もしくはllvm-symbolizerがexecutable memory上にマップされたDWARFセクションを読めてないか、が原因だと思います。Run Swift Script を実行するとどうも内部でswiftコマンドで実行されるらしく、クラッシュした時に行番号が見れないのに困っています。素直にXcodeでやった方が良さそうですね。
1Run Swift Script を実行するとどうも内部でswiftコマンドで実行されるらしく、クラッシュした時に行番号が見れないのに困っています。素直にXcodeでやった方が良さそうですね。 let appearance = UINavigationBarAppearance() appearance.shadowImage = UIImage() appearance.shadowColor = .clear let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light) appearance.backgroundEffect = blurEffect
1override 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)hogeImageView.frame.sizeよりhogeImageView.image?.sizeの方が大きい数がprintされるのですが、後者はなんのサイズを表しているのでしょうか? また、UIImageView.imageのCGRectを取得することは可能でしょうか?hogeImageView.frame.size は View のサイズですが、 hogeImageView.image?.size は UIImage のサイズなので↓になります。 https://developer.apple.com/documentation/uikit/uiimage/1624105-size
scale を掛けると画像自体のピクセル単位での解像度になるようですね。size は300x200、 scale は 2 になるようです。これを 120x80 の UIImageView にセットすると、 homeImageView.frame.size は 120x80 、 homeImageView.image?.size は 300x200 です。 (edited)imageView.frame.sizeとはまた違ったsizeなのですね、、、 imageView.imageのサイズぴったりにviewを置きたいのですが、AspectFitで表示していて画像によってサイズが違う(UIImageViewに余白?ができる)のでどうにかimageView.image.frame.sizeみたいな値をとりたいのですが全くわからず。。。UIImageView のアスペクト比を画像のアスペクト比と同じにしたいということでしょうか?UIImageView のアスペクト比を画像のアスペクト比と同じにしたいということでしょうか? imageView.imageの上に重ねて置きたいです。AVMakeRectWithAspectRatioInsideRectで青線の部分の座標とサイズが取れます。canMoveItemAtとmoveItemAtを実装すればいいです。insertAtDestinationIndexPathとinsertIntoDestinationIndexPathを同時に扱う.automaticというintentは存在しないのですね。残念です。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)let backgroundImage があった場合、 キャプチャリストで書くと backgroundImage が ローカル変数を意味するのか、self のプロパティを意味するのかがわかりにくい、といった違いがありそう。
1@FetchRequest が data2のプロパティにはついてないからですね。 @FetchRequest というProperty Wrapperは指定したプロパティに自動的にCoreDataからデータを検索して詰めてくれるものですが、プロパティごとなのでこのコードだとdata1には@FetchRequestによってデータが入りますが、data2には何も指定がなくてただのプロパティなのでデータが入らないので、data2が未初期化だということでエラーになっています。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)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/117347sudo xcode-select をするのも使いづらい気もしています。 sudoを使うとパスワード入力が必要になってしまうので。。 普段使用しているXcodeは /Applications/Xcode.app で、xcode-select のpathもそれに設定されているのでおかしな挙動になってしまっている可能性もありそうでした。 Xcode13.2.1 を Xcode にrenameしてから、Scriptのpathを /Applications/Xcode.appに変更して実行したところ正常に実行できてしまいました。 (edited)myscript -v 13.2.1 のように自分のScriptを起動して、任意のXcodeバージョンを開くことができるようにしたいので、 毎回 xcode-select を実行する必要があるのかなと思いました。 実行はローカルを想定しています。$ xcode-select -p /Applications/Xcode.app/Contents/Developer (edited)xedにDEVELOPER_DIR環境変数でXcodeのパスを渡せば、任意のXcodeを開けたような。 DEVELOPER_DIR=/Applications/Xcode13.2.1.app xed . (edited)Required content for platform watchOS is missing. Please reinstall Xcode. のエラーになってしまうようでした。 自分の環境がおかしいのかもしれません...。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)CertificateSigningRequest.certSigningRequest をアップロードして作成すると思うのですが このアップロードするファイルを作成する際に、メールアドレスを入力すると思うので 他人のメールアドレスで作成したCertificateを、他のアプリで他人が使って問題ないのかなと少し疑問に思いました。CertificateSigningRequest.certSigningRequest をアップロードして作成すると思うのですが このアップロードするファイルを作成する際に、メールアドレスを入力すると思うので 他人のメールアドレスで作成したCertificateを、他のアプリで他人が使って問題ないのかなと少し疑問に思いました。
1
1enum AlertType { case responseError, internetConnectionError, unknownError } @State private var alertType: AlertType = .responseError { didSet { isShowAlert.toggle() } } @State private var isShowAlert = false のようにalertTypeに代入するだけでアラートを表示するようにしたいです。 (edited)enum AlertType { case responseError, internetConnectionError, unknownError } @State private var alertType: AlertType = .responseError { didSet { isShowAlert.toggle() } } @State private var isShowAlert = false のようにalertTypeに代入するだけでアラートを表示するようにしたいです。 (edited)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の解釈に誤りなどがありましたらご指摘いただけますと幸いです。
1alertType = .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の解釈に誤りなどがありましたらご指摘いただけますと幸いです。 .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' のエラーになってしまいます。これの回避策があるということでしょうか?理解不足ですみません。。。.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' のエラーになってしまいます。これの回避策があるということでしょうか?理解不足ですみません。。。 onChange(of: hogehoge) { ... } は onReceive(Just(hogehoge)) { ... } とできる場合があるので、iOS 14 未満の場合はそちらで代替する…… という手段があります。 https://github.com/treastrain/TRETJapanNFCReader/blob/98c7b9051a6f3b86d04ab75a74c264d419b8434c/Sources/NativeTag/NFCNativeTagReaderViewModifier.swift#L86-L92onChange(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() } 上記のようなコードを書いていたのですが、この画面に遷移するタイミングで画面が固まってしまい原因が分からず諦めておりました。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() } 上記のようなコードを書いていたのですが、この画面に遷移するタイミングで画面が固まってしまい原因が分からず諦めておりました。 onReceive によって print は実行されたので、その箇所に限っては 特に問題はなさそうに見えます……。 (はじめ、body の一番外側の View ではなく Button の modifier としてしまっているからでは?と思いましたが、そこは問題ではなさそうでした。)onReceive によって print は実行されたので、その箇所に限っては 特に問題はなさそうに見えます……。 (はじめ、body の一番外側の View ではなく Button の modifier としてしまっているからでは?と思いましたが、そこは問題ではなさそうでした。) print は実行されます。しかしisShowAlert.toggle() に書き換えた途端に動かなくなってしまいますね。。。isShowAlert.toggle() しようとするのが間違いなんですかね。。。Button { showAlert(type: .hoge) } label { Text("hogeアラート表示") } private func showAlert(type: AlertType) { alertType = type isShowAlert.toggle() } のように関数にしています。
1[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)
1func 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)
1
1XXX.colorset の名前は変わってますか?XXX.colorset の名前は変わってますか?
1
1
1 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() }pausesOnCompletionをtrueにしてみてください。var string: String = "" var int: Int = 0 var bool: Bool = false var data: Data = Data() Data型に初期値をもたせる場合はData()で良いのでしょうか? それともvar data: Data? でoptionalにすべきでしょうか?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 インスタンスとして初期化されます。Data 型にして Data() を初期値で持たせるのが良いと思います。Data 型を値を代入したいけど、今はまだデータが存在しないことを示したいなら Data? 型にして nil で初期化するのが良いと思います。Data はクラスではなく struct ですね。 https://developer.apple.com/documentation/foundation/data )var data: Data = Data() と書くと、 0 バイトのバイト列を表す Data インスタンスとして初期化されます。 data = try! Data(contensOf: hogeURL) のようにtry!になるのが怖いというのがあります。ただData?だと取り出す時にやや面倒だなと思いました。ただ安全側に倒すならData?にしたほうが安全ではありそうですかね。data = try! Data(contensOf: hogeURL) のようにtry!になるのが怖いというのがあります。ただData?だと取り出す時にやや面倒だなと思いました。ただ安全側に倒すならData?にしたほうが安全ではありそうですかね。 do { let data = try Data(contensOf: hogeURL) // data を使う処理 } catch { // エラーハンドリング }
catch の中では error にアクセスすることで、エラー情報を取得することができます。 try? にしてしまうとエラー情報が失われてしまい、原因を特定したり、原因によってエラーハンドリングの仕方(アラートを表示する、リトライする、無視してログ出力するなど)を変更することもできなくなってしまいます。 (edited)
1nil が返されるメソッド等が存在はしますが(たとえば 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)
1class 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)
1class 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() } ...
1
1protocol SomeProtocol { } extension SomeProtocol { func somePrint() { print("First") } } struct SomeModel: SomeProtocol { func somePrint() { print("Second") } } let someModel: some SomeProtocol = SomeModel() someModel.somePrint() // FirstSecondと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// 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)Task { let myclass = MyClass() await myclass.callback() } としてMainActor指定を外して実行すると[NSThread isMainThread]はNOになるのでしょうか?Task { @MainActor in await callback() } というコードを書いたら動いたので、「なんだこれ...気持ち悪い...」となりました (edited) // 既存の書き方 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)pplication.acquireToken() にMainActorContextを引き継がせる意図でした。 (普通のasync関数は引き継がないけど、自動でasync化された関数は引き継ぐ仕様があるから、それを意図的に使っていいのか、という懸念です) @MainActor public func signInB() async throws -> AuthResult { try await application.acquireToken() } (edited)#define MAIN_ACTOR __attribute__((__swift_attr__("@MainActor"))) @interface MyClass : NSObject - (void)callbackWithCompletion:(void (^)(void))completion MAIN_ACTOR; @end
1@MainActor な関数の下でacquireToken をコールバックを取る同期関数として呼び出す書き方であれば意味を漏れなく記述できると思います。 // 既存の書き方 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)signInA 自体に @MainActorを付けるほうが無駄なスイッチが減ります。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) } } 通信中に画面を離れるタイミングでキャンセルしたいのですが、うまく動作せず通信成功してしまいます。 原因が全くわかりません。 どこかおかしいところありましたらご教示頂けると助かります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) } } 通信中に画面を離れるタイミングでキャンセルしたいのですが、うまく動作せず通信成功してしまいます。 原因が全くわかりません。 どこかおかしいところありましたらご教示頂けると助かりますviewWillDisapper が本当に呼び出されているかどうかですね。 それは確認できていますか? その上で、 Session のコードを見ないと判断できないですね (edited)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)Session.send と Session.cancelRequests の実装次第だと思います。Session.send と Session.cancelRequests の実装次第だと思います。 Session.send(ARequest()) した後、通信中の状態ですぐに画面Bに遷移してviewDidLoad()で Session.send(BRequest()) すると、ARequestのレスポンスを待ってBRequestが送信される?のですが、 待たずにBRequestのレスポンスが欲しいため、試しに画面Aを let adapter = URLSessionAdapter(configuration: .default) Session(adapter: adapter).send(ARequest()) とすると、2つ同時に通信してくれるようになりました。 ただ、なぜこうなるのかがいまいち理解できません。 URLSessionがマルチスレッド?並列?に処理してくれているのでしょうか。URLSession は同時に複数の通信を行う事ができます。 ただ、そのコードがどのように動くかは、 その URLSessionAdapter と Session の実装次第です。 それらは iOS SDK のクラスではないのでコードを見ないとわかりません。 APIKit で提供されているクラスなんですか?Session.sendでもデフォルトではURLSessionAdapterを使っているようですよ https://github.com/ishkawa/APIKit/blob/1a5e7ae0aed3f19c1ed9903792ead248f97fa38a/Sources/APIKit/Session.swift#L24private 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)
1let results = realm.objects(Item.self).sorted(byKeyPath: keyPath) let filterResults = results.filter(…) この場合、filterResultsの並び順は最初にsortした並び順になることが保証されていますでしょうか?
1
1
1.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. SVProgressHUD.setContainerView(self.view)とすると機能してるようなのですが、自作したカスタムViewを指定すると何も表示されませんでした。古いですが似たような方もいました。 https://stackoverflow.com/questions/45012710/svprogresshud-isnt-showing-when-using-setcontainerview
1
1case .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") } }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を追加する必要があるので手間はあまり変わらないかもしれませんが。。echoの場合はうまくいくのですが、xcodebuildを呼び出した際にProcessのisRunningがいつまでもfalseにならず、 処理が終了しない状態となっています。 Processの処理の仕方に問題があるのか、またはxcodebuildの取り扱い方に問題があるのか原因が分かる方いらっしゃるでしょうか。 [環境] macOS: 13.4 (22F66) Xcode: Version 14.3.1 (14E300c)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 という便利なメソッドがありますよ。start end >0.5秒のsleepを終了待ちではなく whileループの中に入れたらどうなりますか? // 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に退避したらどうなりますか? /// 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) } } } } } do { try process.run() } catch { completion(.failure(.failedInRunning)) return } process.waitUntilExit() // xcodebuildを呼び出した際にここで止まってしまう let data = pipe.fileHandleForReading.readDataToEndOfFile()xcodebuild プロセスが終了していないっぽいですね。senderにUIRefreshingControlではなくNSConcreteNotificationが入っているのにendRefreshing()を呼んだからだと思うのですがこれは正しい動きでしょうか? NotificationCenter.default.addObserver( self, selector: #selector(didReceive), name: .HogeNotification, object: nil ) @objc func didReceive(sender: UIRefreshControl) { print(“結果: \(sender)“) // NSConcreteNotification sender.endRefreshing() }echoの場合はうまくいくのですが、xcodebuildを呼び出した際にProcessのisRunningがいつまでもfalseにならず、 処理が終了しない状態となっています。 Processの処理の仕方に問題があるのか、またはxcodebuildの取り扱い方に問題があるのか原因が分かる方いらっしゃるでしょうか。 [環境] macOS: 13.4 (22F66) Xcode: Version 14.3.1 (14E300c) (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)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) /// 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)) }selfはその時のオブジェクト(本来であればdeinitが呼ばれて解放されて欲しいオブジェクト)を保持し続けているのでしょうか?//selector @objc func didReceive() { print(ObjectIdentifier(self)) }
@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に触れるので)
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)@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に触れるので)
class ParentViewController: UIViewController { override func viewDidLoad() { let childView = ChildView() { print("hoge") } } } struct ChildView: View { let closure: () -> Void }XXEntity(context: persistentContainer.viewContext) のように引数を何も与えずにEntityを生成することができるのでその場合、Non-Optionalなプロパティにもかかわらずnilであるということが起こるのでNon-Optionalのプロパティである意味がありません。 ということであまりいい方法はないと思います。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 } } } } } }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) } } }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) } } } 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)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) ForEach($viewModel.items.sorted { !$0.wrappedValue.completed && $1.wrappedValue.completed }) { TodoItemView(item: $0) }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)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) } } } class HogeViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.navigationController?.viewControllers.forEach { if !($0 is UIHostingController<HogeRootView>) && !($0 is HogeViewController) { $0.removeFromParent() } } } }var viewControllers: [UIViewController] = [] self.navigationController?.viewControllers.forEach { if $0 is UIHostingController<HogeRootView> || $0 is HogeViewController { viewControllers.append($0) } } self.navigationController?.setViewControllers(viewControllers, animated: true)
1Struct 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) } } }await なしで操作しているので static var だと actor isolation が働いてないように見えます 例えばシングルトン経由でアクセスするようにするとよさそうです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を書くだけで正常に表示されるのか疑問に思ったためもしわかる方いれば教えていただきたいですonChangeを記述せずに body の先頭に let _ = selectedString を記載した場合はどうなりますか?@Stateで修飾されたプロパティはbody内部で触った瞬間に変更検知の対象になっているのだと思います。 つまり、selectedStringが変化した瞬間に.fullScreenCoverのクロージャの中身を更新します。 元々の実装はBindingである$showCoverしか変化が起こっていなかったために、showCoverが変化した際にbodyの再実行が行われず、初回に.fullScreenCoverのクロージャにキャプチャされた無のselectedStringがそのまま表示されたんだと思いますif let string = selectedString {で参照してるselectedStringは実際はself.selectedStringのはずだから、@Stateごしの値の取得になってるはずで最新値が常に反映されそうな気もするなぁselectedString = string ここで$selectedStringの変化が起こっていると思っているのですが違いますか?
@Stateの変更を無視するようです。bodyの中で一度も使われなかった selectedStringは変化が起こったとしても無視されてるということですね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)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)request (かその元の型)に @MainActor が付与されていない場合、 Task.init は MainActor Contextで実行されないと思います。MainActor Contextで実行するだけなら Task { @MainActor in にするという方法もありますが、おそらく質問の趣旨はActor Contextの引き継ぎについてではないかと思ったので。
1request (かその元の型)に @MainActor が付与されていない場合、 Task.init は MainActor Contextで実行されないと思います。 DispatchQueue.main.async{ } してたのと変わらないと思いますので、気にする必要はないと思います。 ただ、個人的に↓のようなケースは気になってます。従来はなかった遅延だと思うので、 Task.init の中でボタン無効化したりしていたら、それまでに割り込まれる可能性がありますし。 func buttonPressed(sender: UIButton) { Task { ... } } (edited)DispatchQueue.main.async{ } してたのと変わらないと思いますので、気にする必要はないと思います。 ただ、個人的に↓のようなケースは気になってます。従来はなかった遅延だと思うので、 Task.init の中でボタン無効化したりしていたら、それまでに割り込まれる可能性がありますし。 func buttonPressed(sender: UIButton) { Task { ... } } (edited)@MainActor が付与されていれば Task も MainActor と同じExecutorで実行されるのでhopがなく遅延も無いと思っていたんですがhopが無いだけでenqueueする遅延は起きるということですかね。
(edited)@MainActor が付与されていれば Task も MainActor と同じExecutorで実行されるのでhopがなく遅延も無いと思っていたんですがhopが無いだけでenqueueする遅延は起きるということですかね。
(edited)Task.init のクロージャはたとえActor Contextを引き継いだ場合でも同期的に実行されないので、↓のような順で実行されます。 @MainActor func foo() { // 1️⃣ Task { // 3️⃣ 1サイクル遅れる } // 2️⃣ } (edited)Task.init のクロージャはたとえActor Contextを引き継いだ場合でも同期的に実行されないので、↓のような順で実行されます。 @MainActor func foo() { // 1️⃣ Task { // 3️⃣ 1サイクル遅れる } // 2️⃣ } (edited)Task {} の前にボタンを無効化すればいいんですが、ViewModelとかに切り出して、非同期処理を開始する( async メソッドを呼び出す)ときとかに困るんですよね。Task {} の前にボタンを無効化すればいいんですが、ViewModelとかに切り出して、非同期処理を開始する( async メソッドを呼び出す)ときとかに困るんですよね。 async の場合は Task.init に包んだ時点で非同期になるという点がこれまでと異なっている点だと思います。Task.init の外に書くとか)、ちょっとやりたいことと違う形になっちゃうんですよね。 (edited)async の場合は Task.init に包んだ時点で非同期になるという点がこれまでと異なっている点だと思います。 Task.init を書くスタイルでコードを書いているのでボタン無効化のタイミングが遅れて困っていましたが、 Task.init をViewModel側に書けば問題なく対応できそうな気がしてきました・・・。 func onButtonPressed(sender: UIButton) { viewModel.fetchFoo() }
@MainActor final class ViewModel: ObservableObject { ... func fetchFoo() { isButtonDisabled = true Task { defer { isButtonDisabled = false } ... // 非同期処理 } } }Task を ViewModel 側でとっておけばキャンセルできますね。 @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 } }
1
1
1NavigationSplitView) とタブバー (TabView) を切り替えるなどどうしても分岐が必要な場合は,例えば Apple の標準アプリだと @Environment(\.horizontalSizeClass) が .regular なのか .compact なのかによって切り替えているので,それを真似するとうまくいくことが多いですね.struct User { } struct Nest { // TopレベルのUserにしたいがNest.Userになってしまう let user: User struct User { } } let value = Nest(user: .init()) print(value) (edited)<モジュール名>.User で参照できます。struct User { } に対してTypealiasを設定するというのはどうでしょう? struct User { } typealias U = User // これを追加する。 struct Nest { // TopレベルのUserにしたいがNest.Userになってしまう let user: U // typealiasで参照する struct User { } }swift-collections などでは DequeModule などのように モジュール名に Module サフィックスを付けられていたりします。GitHubAPIModule などにモジュール名を変えたほうが良いと思います。moduleAliases で解決できませんでしたっけ? https://github.com/apple/swift-package-manager/blob/main/Documentation/ModuleAliasing.mdmoduleAliases で解決できませんでしたっけ? https://github.com/apple/swift-package-manager/blob/main/Documentation/ModuleAliasing.md
1
1AVPlayer など基本的なコンポーネントを組み合わせていけば作れる仕様だと思うので、 初心者が挑戦するのにちょうどいい課題感だと思います。 AVPlayer: https://developer.apple.com/documentation/avfoundation/avplayer/ ただmacOS向けの開発の情報はネット上も書籍も少ないのでそこが難しいかもしれません。 あと「フレーム単位でシークする」のは実はちょっと難しいです。 動画のデータ構造ってフレームレートが一定とは限らない作りになっているので、プレイヤーに対して「1フレーム進める」みたいなフレーム単位操作の司令ができないからです。 (ビデオデコーダを直接制御すればできますが、実装難易度が一気に増加します) まあアニメのデータの場合は実際のところ安定しているでしょうから、そのへんは ↓のseekメソッドに渡すtorelanceパラメータに前後 0.5フレーム幅を渡したら現実的にはうまくいくと思います。 https://developer.apple.com/documentation/avfoundation/avplayer/1387741-seekAVPlayer など基本的なコンポーネントを組み合わせていけば作れる仕様だと思うので、 初心者が挑戦するのにちょうどいい課題感だと思います。 AVPlayer: https://developer.apple.com/documentation/avfoundation/avplayer/ ただmacOS向けの開発の情報はネット上も書籍も少ないのでそこが難しいかもしれません。 あと「フレーム単位でシークする」のは実はちょっと難しいです。 動画のデータ構造ってフレームレートが一定とは限らない作りになっているので、プレイヤーに対して「1フレーム進める」みたいなフレーム単位操作の司令ができないからです。 (ビデオデコーダを直接制御すればできますが、実装難易度が一気に増加します) まあアニメのデータの場合は実際のところ安定しているでしょうから、そのへんは ↓のseekメソッドに渡すtorelanceパラメータに前後 0.5フレーム幅を渡したら現実的にはうまくいくと思います。 https://developer.apple.com/documentation/avfoundation/avplayer/1387741-seek player.currentItem?.step(byCount: 1)AVPlayer じゃなくて item のメソッドを直接叩いてもいいのか。player.currentItem?.step(byCount: 1) .infinity, .infinityの場合っぽいですね 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)@state で指定された変数(など)で表される「状態」が変わったときに、body を再評価してその結果(View という画面を作る設計図的な画面の定義)を元に画面を描画します (edited)body を評価しているときに、Guage(value: timeLibrar()) を評価して、そのときに timeLibra() を評価して、そのときに @State な currentPlayerFrame が変更されてしまいます。 (edited)body の View つくったのに作ってる間に状態変えられた...って思うわけですよ (edited)@State は必要でしょう。.dropDestination(for: URL.self) { urls, _ in guard let url = urls.first else { return } ... }.dropDestination(for: URL.self) { urls, _ in guard let url = urls.first else { return false } player = AVPlayer(url: url) return true }Swift ErrorSwift Error Breakpoint や Exception Breakpoint 追加して実行したら、落ちる直前で実行がとまったりしないですかね?Swift ErrorSwift Error Breakpoint や Exception Breakpoint 追加して実行したら、落ちる直前で実行がとまったりしないですかね? 作成した.app を直接double click等で実行しようとしてすぐ落ちてるという話ですか?Run の Build Configuration を release に変更してXcodeからappを実行 Build/Products/Release/ に 作成した.app ができると思いので、これを実行でいけないですかね? let videoURL: URL = Bundle.main.url(forResource: "Dammy", withExtension: "mp4")! player = AVPlayer(url: url) (edited)import AVKit って書いてるのにAVKitがリンクされてないっていうのはだいぶおかしな挙動(WebKitとか他のフレームワークは問題ないのにAVKitだけおかしい?)じゃないですか?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_AVKit_SwiftUIは怪しそう_AVKit_SwiftUIってなんですかね...import AVKit _ = AVPlayerView()をコンパイルしてもAVKitしか-frameworkを足されないですね。import SwiftUI を足すとこの怪しい_AVKit_SwiftUIが足されるJIT session error: Symbols not found: [ _OBJC_CLASS_$_AVPlayerView ]とか言ってくるItem 型が存在しないのに [Item] と指定しているので、入れたい本来の型を指定してあげればよいです。 後者は、 NSDataAsset(name: "CountDown") が音源参照して引っ張ってくることができず nil になっているためクラッシュしています。 NSDataAsset を使うのであれば、 Item 型が存在しないのに [Item] と指定しているので、入れたい本来の型を指定してあげればよいです。 後者は、 NSDataAsset(name: "CountDown") が音源参照して引っ張ってくることができず nil になっているためクラッシュしています。 NSDataAsset を使うのであれば、 scrollPosition(id:anchor) を説明する上での、scrollView+VStackViewで表示してscrollPositionを指定する例として何かしらの表示する物をItemとして定義して説明しているだけで、実在する型とかではなさそうです scrollPosition(id:anchor) を使うのであれば、structでItem型になるものを独自で定義することになると思います (edited)scrollPosition(id:anchor) を説明する上での、scrollView+VStackViewで表示してscrollPositionを指定する例として何かしらの表示する物をItemとして定義して説明しているだけで、実在する型とかではなさそうです scrollPosition(id:anchor) を使うのであれば、structでItem型になるものを独自で定義することになると思います (edited)
2if let playerURLs = UserDefaults.standard.array(forKey: playerURL) { ... }
UserDefaults.array(forKey:)は中身がArrayじゃなかったらnilを返すので上記のようなコードでいいですよ。if let playerURLs = UserDefaults.standard.array(forKey: playerURL) { ... }
UserDefaults.array(forKey:)は中身がArrayじゃなかったらnilを返すので上記のようなコードでいいですよ。 if let playerURLs = UserDefaults.standard.array(forKey: playerURL) as? [String] { ... }EXC_BREAKPOINT (SIGTRAP)のエラーは通知しないようにする制御って可能でしょうか? https://docs.rollbar.com/docs/apple (edited)EXC_BREAKPOINT (SIGTRAP)のエラーは通知しないようにする制御って可能でしょうか? https://docs.rollbar.com/docs/apple (edited)checkIgnoreRollbarData でクラッシュレポートの中身を見てSIGTRAPだったらfalseを返す、とするしかないと思います。checkIgnoreRollbarData でクラッシュレポートの中身を見てSIGTRAPだったらfalseを返す、とするしかないと思います。 Attempted to dereference garbage pointer 0x80000001c. abort() called EXC_BREAKPOINT (SIGTRAP): Application terminated この3つのエラーを送るのを止めようと考えているのですが、メモリ管理(メモリリークではない?)によるものやプログラムを意図的に終了させた時に起こるエラーというぼんやりした認識なのですか合ってますでしょうか?(優先して拾いたいエラーがありノイズになるので今は止めたいです)
(edited)signal(SIGTRAP, SIG_DFL); をrollbarのセットアップ後に呼べばいいと思いますが、基本的には通知は受け取り側で制御(フィルタリング)したほうが良いとは思いますね。Ctrl-C をフックしようとしてたりするし、ちょっとしたことで奪い合いになりそう。 (edited)Attempted to dereference garbage pointerみたいなシンプルにまずそうなエラーを全部スルーすることになるので、あとから問題調査をしようとしたときに特定のバージョンからエラーレポートがなくなって困ってしまうので。
1final 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() で処理が終わるまで待って欲しいです 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() で処理が終わるまで待って欲しいです withCheckedContinuation(function:_:) で得られる CheckedContinuation を使って待たせる方法はいかがでしょうか?withCheckedContinuation(function:_:) で得られる CheckedContinuation を使って待たせる方法はいかがでしょうか? withCheckedContinuation の存在自体忘れてましたw@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 }@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 } withCheckedContinuation の body 引数は asyncではない関数を受け取るのに、 クロージャの中で await しているから async な関数ができてしまって、渡せなくなってるからですね。 そこに await がつかないようにするのがいいと思うので、クラス全体のコードを貼ってくださいwithCheckedContinuation の body 引数は 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)@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 } } } }self.continuations[id] = と、subscript access を左辺に持ってくると、ダメみたいです。バグなのか理由があるのかはわからないです。 self.continuations.merge([id: continuation]) { $1 } // OK self.continuations[id] = continuation //Actor-isolated property 'continuations' cannot be passed 'inout' to 'async' function call ですね、謎です unarchivedObject はたしかclassにしか使えないはず(記憶違いでしたらごめんなさい)なので、NSDictionary として解凍するか Codable で JSONEncoder()と JSONDecoder() 使うのはどうでしょう?unarchivedObject はたしかclassにしか使えないはず(記憶違いでしたらごめんなさい)なので、NSDictionary として解凍するか Codable で JSONEncoder()と JSONDecoder() 使うのはどうでしょう? Codable に適合させれば、JSONEncoder でエンコードしたものを UserDefaults に保存したり、逆にそこに保存したデータを JSONDecoer で解凍したり簡単にできますstruct SaveData: Codable { var characters: [[Character]] }Codable は内包するデータも Codable 適合が必要なので、この場合ですと struct Character: Codable も必要です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) } 使い方だいたいこんな感じですCharacter 自体も Codable に適合する必要があるので、宣言のところに : Codable 追加するとだいたい大丈夫ですCharacter はどこで宣言していますか?var characters の宣言ではなく、Character という型の宣言ですstruct Character もしくは class Character のどっちかだと思いますがそのところです[[Character]] より [String] の方が使いやすいかと思います" ", "a", "b" を切り分けたいだけでしたら、別に文字結合しないので [[String]] でも大丈夫かと思います" ", "a", "b" しかないので、どっちも1byteだから変わらないと思いますCharacter は1byteではないのでご注意ください。Swiftにおける文字とはgrapheme clusterのことなので、1文字が巨大なこともあります。 @swift-5.9.2
print("👨👩👦👦".count) // 1 (edited)Character は1byteではないのでご注意ください。Swiftにおける文字とはgrapheme clusterのことなので、1文字が巨大なこともあります。 @swift-5.9.2
print("👨👩👦👦".count) // 1 (edited)1Character は1byteではないのでご注意ください。Swiftにおける文字とはgrapheme clusterのことなので、1文字が巨大なこともあります。 @swift-5.9.2
print("👨👩👦👦".count) // 1 (edited)1ARKitFaceExample/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")!
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")!
.scnassets ディレクトリの中身の scn ファイルを直接開くという手順に違和感があります。scnassets という拡張子がついているなら、ビルド時にSceneKitでコンパイルされた何かになって、SceneKitでそれ用のインターフェースを介して中身にアクセスする作法ではないのかなと思いました。 それについて詳しく知らないのでわからないですが。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")!
scnassets という拡張子がついているなら、ビルド時にSceneKitでコンパイルされた何かになって、SceneKitでそれ用のインターフェースを介して中身にアクセスする作法ではないのかなと思いました。 それについて詳しく知らないのでわからないですが。