[発生環境] 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 initialized
private
とはいえ、そこから 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 fi
platform :ios, '9.0' target 'XXXXX' do pod 'CorePlot', '2.2' pod 'Google-Mobile-Ads-SDK', '7.20.0' pod 'FBSDKCoreKit', '4.23.0' pod 'FBSDKLoginKit', '4.23.0' pod 'FBSDKShareKit', '4.23.0' pod 'Flurry-iOS-SDK/FlurrySDK', '8.1.0' pod 'Fabric', '1.6.11' pod 'TwitterKit', '2.8.1' pod 'TwitterCore', '2.8.0' pod 'Crashlytics', '3.8.4' pod 'SVProgressHUD', '2.1.2' pod 'Realm', '2.7.0' pod 'Repro', '2.4.0' pod 'SwiftLint', '0.19.0' end post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['CLANG_WARN_DOCUMENTATION_COMMENTS'] = 'NO' end end end
PODS: - Bolts (1.8.4): - Bolts/AppLinks (= 1.8.4) - Bolts/Tasks (= 1.8.4) - Bolts/AppLinks (1.8.4): - Bolts/Tasks - Bolts/Tasks (1.8.4) - CorePlot (2.2) - Crashlytics (3.8.4): - Fabric (~> 1.6.3) - Fabric (1.6.11) - FBSDKCoreKit (4.23.0): - Bolts (~> 1.7) - FBSDKLoginKit (4.23.0): - FBSDKCoreKit - FBSDKShareKit (4.23.0): - FBSDKCoreKit - Flurry-iOS-SDK/FlurrySDK (8.1.0) - Google-Mobile-Ads-SDK (7.20.0) - Realm (2.7.0): - Realm/Headers (= 2.7.0) - Realm/Headers (2.7.0) - Repro (2.4.0) - SVProgressHUD (2.1.2) - SwiftLint (0.19.0) - TwitterCore (2.8.0): - Fabric - TwitterKit (2.8.1): - TwitterCore (>= 2.8) DEPENDENCIES: - CorePlot (= 2.2) - Crashlytics (= 3.8.4) - Fabric (= 1.6.11) - FBSDKCoreKit (= 4.23.0) - FBSDKLoginKit (= 4.23.0) - FBSDKShareKit (= 4.23.0) - Flurry-iOS-SDK/FlurrySDK (= 8.1.0) - Google-Mobile-Ads-SDK (= 7.20.0) - Realm (= 2.7.0) - Repro (= 2.4.0) - SVProgressHUD (= 2.1.2) - SwiftLint (= 0.19.0) - TwitterCore (= 2.8.0) - TwitterKit (= 2.8.1)
SPEC CHECKSUMS: Bolts: 8a7995239dbe724f9cba2248b766d48b7ebdd322 CorePlot: cbe0c6e14220705e32e06a89c7d6a5a908b7d7d8 Crashlytics: 79e236942ca1e7fc641df1feb9a275360a78ab6a Fabric: 5911403591946b8228ab1c51d98f1d7137e863c6 FBSDKCoreKit: d7829f5a69901cd7296105328e4c3c3fc7da6518 FBSDKLoginKit: 6b92bd65f319d669d2b0730e49db495ef1660566 FBSDKShareKit: 65751c3b9937ab9d594e6c37611ecc115ceeb448 Flurry-iOS-SDK: 51065be4436f3e21fc8d3d7bb0b7d6869df6333d Google-Mobile-Ads-SDK: 168312cdc167fa22746d4ea8e839fc4825dd2966 Realm: 07e5d3a9e0e41d65fd5f9f05150ed6295d0f093b Repro: e69274efa79b1e8f25ec14177356968d9a8e8224 SVProgressHUD: c404a55d78acbeb7ebb78b76d3faf986475a6994 SwiftLint: 3537a05b34060e78e7510f04fb7537d738247803 TwitterCore: e959987be23c767004d29eb7fab8d85d8585a2e5 TwitterKit: 3b6044a7320340326a4098f3e37aa1dbaeb94942 PODFILE CHECKSUM: 47c07dc78a6793f29d1576ffa394f4c5e5b5076e COCOAPODS: 1.2.1
diff "${PODS_PODFILE_DIR_PATH}/Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null if [ $? != 0 ] ; then # print error to STDERR echo "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." >&2 exit 1 fi
echo "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-ssh
import UIKit let numbers = (1...5).map(String.init) print(numbers) // ["1", "2", "3", "4", "5"] var a: [String] = [] // No Error a = Array(numbers.prefix(3)).map { $0 } print(a) // ["1", "2", "3"] // No Error let arraySlice: ArraySlice<String> = numbers.prefix(3) a = arraySlice.map { $0 } print(a) // ["1", "2", "3"] // Error(error: ambiguous use of 'prefix')→ なぜエラーに? // a = numbers.prefix(3).map { $0 }
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 boxing
int
に対して 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 + 4
guessMIMETypeCurrent
だから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 = .convertToSnakeCase
ObjectEncoder
で任意の型にCoding Strategyを設定できる様になりそう。 https://github.com/norio-nomura/ObjectEncoder/pull/11
var encoder = ObjectEncoder() encoder.encodingStrategies[Date.self] = .iso8601 let encoded = try encoder.encode(Date(timeIntervalSince1970: 1000)) encoded == "1970-01-01T00:16:40Z" // true var decoder = ObjectDecoder() decoder.decodingStrategies[Date.self] = .iso8601 let decoded = try decoder.decode(Date.self, from: encoded) decoded == Date(timeIntervalSince1970: 1000) // true
(edited)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 の結果がおかしくなります workspace は SwiftyAlgebra/Workspace/Sandbox/TimeProfile/ 下にあります。 https://github.com/taketo1024/SwiftyAlgebra/tree/TimeProfile (edited)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 { ^
protocol ViewProtocol: class { associatedtype Presenter: PresenterProtocol var presenter: Presenter! { get } } protocol PresenterProtocol: class { associatedtype View: ViewProtocol weak var view: View? { get } }
1ファイルにこれ書くとbuild通るんですけど、それぞれのprotocolを別のファイルに書くとbuild通らないのがよくわからないんですがどうしてなんでしょう? (edited)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_katsumi
enum UnrecoverableError: Error { case preconditionFailure } struct Hoge { func テストしたいメソッド() throws { if true { throw UnrecoverableError.preconditionFailure } } } let hoge = Hoge() do { try hoge.テストしたいメソッド() } catch let error as UnrecoverableError { switch error { case .preconditionFailure: preconditionFailure() } }
うーんやりたくない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:2
unsafeBitCast((), 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 が出てしまいます protocol で関数値を取る init を置いてるのがまずいんでしょうか…?わかる方いたら教えてください (edited)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)
8
import Foundation public protocol EndType where DomainType == CodomainType { associatedtype DomainType associatedtype CodomainType init(_ fnc: @escaping (DomainType) -> CodomainType) func applied(to x: DomainType) -> CodomainType static var identity: Self { get } func composed(with f: Self) -> Self } public extension EndType { public static var identity: Self { return Self { x in x } } public func composed(with g: Self) -> Self { let fnc: (DomainType) -> DomainType = { x1 in let x2: DomainType = g.applied(to: x1) let x3: DomainType = self.applied(to: x2) return x3 } return Self.init(fnc) } } public struct Map<Domain>: EndType { internal let fnc: (Domain) -> Domain public init(_ fnc: @escaping (Domain) -> Domain) { self.fnc = fnc } public func applied(to x: Domain) -> Domain { return fnc(x) } } public extension Array where Element: EndType { func composed() -> Element { return self.reduce(Element.identity) { (res, f) in res.composed(with: f) } } } let f: Map<Int> = Map { x in 2 * x } let fs: Array<Map<Int>> = [f, f, f] let g: Map<Int> = fs.composed() let t: Int = g.applied(to: 1) print(t)
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 + 4259848631
10 libswiftCore.dylib 0x0000000109f2a187 _T0s8SequencePsE6reduceqd__qd___qd__qd___7ElementQztKctKlF + 4259846807 11 swift 0x0000000103606c0a llvm::MCJIT::runFunction(llvm::Function*, llvm::ArrayRef<llvm::GenericValue>) + 362 12 swift 0x000000010360d30c llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 1004 13 swift 0x0000000102928735 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 48709 14 swift 0x000000010291ae64 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 7908 15 swift 0x00000001028cf8b5 main + 18917 16 libdyld.dylib 0x00007fff5508a015 start + 1 17 libdyld.dylib 0x000000000000000a start + 2868338678 Stack dump: 0. Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret a.swift -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk -color-diagnostics -module-name a Segmentation fault: 11
// // 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 help
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))
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 と仮定されて怒られているようです (edited)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)
と出て通らなくなってしまいました コミットを過去まで遡ってもダメなので、恐らく Xcode のバージョンをあげたことによるものだと思うのですが、原因のわかる方いたらお助けください (edited)[omochi@omochi-iMac-PC43 SwiftyMath (master=)]$ swift build Compile Swift Module 'SwiftyMath' (70 sources) Compile Swift Module 'SwiftyLieGroups' (12 sources) Compile Swift Module 'SwiftyHomology' (10 sources) Compile Swift Module 'SwiftyKnots' (9 sources) Compile Swift Module 'SwiftyTopology' (15 sources) Linking ./.build/x86_64-apple-macosx10.10/debug/libdSwiftyMath.dylib Compile Swift Module 'Sample' (1 sources) Linking ./.build/x86_64-apple-macosx10.10/debug/Sample [omochi@omochi-iMac-PC43 SwiftyMath (master=)]$ swift --version Apple Swift version 4.1.2 (swiftlang-902.0.54 clang-902.0.39.2) Target: x86_64-apple-darwin17.6.0
var 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の中にあるじゃなかったっけ 詳しい仕様忘れましたが (edited)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() // OK
protocol HogeProtocol { } struct Hoge: HogeProtocol { func setHoge() {} } struct Fuga: HogeProtocol { func setFuga() {} } enum Foo { case hoge case fuga func getHogeProtocol<T : HogeProtocol>() -> T { switch self { case .hoge: return Hoge() as! T case .fuga: return Fuga() as! T } } } // use let hoge: Hoge = Foo.hoge.getHogeProtocol() // HogeProtocol型 hoge.setHoge() // OK
swift-4.1.1-RELEASE
func 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 100001
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 100000 100001
dispatchMain()
とかで待たないと、実行されない場合がありますよ。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が復帰させてた… (edited)var supportedPositions
でカスタマイズできそうな雰囲気ですが、それはダメでしたか?insetFor(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.Hoge
import Sub1 import Sub2 public typealias Sub1 = Sub1 public typealias Sub2 = Sub2
みたいに書いたり import Sub1 import Sub2 public struct Sub1 { public typealias Hoge = Sub1.Hoge } public struct Sub2 { public typealias Hoge = Sub2.Hoge }
みたいに書いたりできないかなーと模索しているのですが。structの名前とsub frameworkの名前をずらせばこれでも書けない事はないのですが、全部aliasを貼るのもすごく面倒なのでもっといいやり方があるのではないかと思っています。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 classes
public 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.hoge
No 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 end
workspace 'App.xcworkspace' target 'App' do project 'Sources/App/App.xcodeproj' use_frameworks! install_pods target 'AppTests' do inherit! :search_paths end end target 'Feature1' do project 'Sources/Features/Feature1/Feature1.xcodeproj' install_pods target 'Feature1Tests' do inherit! :search_paths end end def install_pods use_frameworks! pod 'Firebase/Core' pod 'Fabric', '~> 1.10.0' pod 'Crashlytics', '~> 3.13.0' end
window.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.0
buttonItemsStatus
の先頭あたりでいったん 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-RELEASE
true false
layoutSubviews
で 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 で指定するのかしら (edited)"-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; }
これが動いたのであとは頑張れば行けそうです (edited)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
これで行けました (このやり方で大丈夫でしょうか?) (edited)#if __has_feature(assume_nonnull) #define CF_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #define CF_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") #else #define CF_ASSUME_NONNULL_BEGIN #define CF_ASSUME_NONNULL_END #endif
ASSUME_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 できないんですね… これは何故なのでしょう 特に ExpressibleByIntegerLiteral な型を wrap する型を再び ExpressibleByIntegerLiteral にして、init では内部の型に丸投げする多くて,↓ こういう protocol を作って必要に応じて適合させられたらいいと思ったのですが…
public protocol InheritingIntegerLiteralExpression: ExpressibleByIntegerLiteral where IntegerLiteralType == Inheritee.IntegerLiteralType { associatedtype Inheritee: ExpressibleByIntegerLiteral init(_ inheritee: Inheritee) } extension InheritingIntegerLiteralExpression { public init(integerLiteral value: IntegerLiteralType) { self.init(Inheritee(integerLiteral: value)) } }
(edited)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: 0
print(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
でいけました (edited)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" というエラーが出てビルドできません (edited)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 └── lib
dist ├── include │ └── m4ri │ ├── brilliantrussian.h │ ├── debug_dump.h │ ├── djb.h │ ├── echelonform.h │ ├── graycode.h │ ├── io.h │ ├── m4ri.h │ ├── m4ri_config.h │ ├── misc.h │ ├── mmc.h │ ├── mp.h │ ├── mzd.h │ ├── mzp.h │ ├── parity.h │ ├── ple.h │ ├── ple_russian.h │ ├── ple_russian_template.h │ ├── solve.h │ ├── strassen.h │ ├── triangular.h │ ├── triangular_russian.h │ ├── xor.h │ └── xor_template.h └── lib ├── libm4ri-0.0.20140914.dylib ├── libm4ri.a ├── libm4ri.dylib -> libm4ri-0.0.20140914.dylib ├── libm4ri.la └── pkgconfig └── m4ri.pc
libm4ri.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を使ってライブラリをリンクさせたことがありませんので、何か基本的な事を間違えているのだと思いますが、どなたか教えていただけると幸いです。#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 Device
iPhone 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 B
struct DirectProduct<Left: Collection, Right: Collection> { let left: Left let right: Right let iteratorType: DirectProductIterator<Left, Right>.Type init(_ left: Left, _ right: Right) { self.left = left self.right = right iteratorType = DirectProductIterator.self } } extension DirectProduct where Left.Index == Int, Right.Index == Int { init(_ left: Left, _ right: Right) { self.left = left self.right = right iteratorType = DirectProductIterator2.self } } extension DirectProduct: Sequence { func makeIterator() -> DirectProductIterator<Left, Right> { iteratorType.init(left, right) } } class DirectProductIterator<Left: Collection, Right: Collection>: IteratorProtocol { fileprivate let left: Left fileprivate let right: Right required init(_ left: Left, _ right: Right) { self.left = left self.right = right } func next() -> (Left.Element, Right.Element)? { print("DirectProductIterator") return nil } } class DirectProductIterator2<Left: Collection, Right: Collection>: DirectProductIterator<Left, Right> where Left.Index == Int, Right.Index == Int { required init(_ left: Left, _ right: Right) { super.init(left, right) } override func next() -> (Left.Element, Right.Element)? { print("DirectProductIterator2") return nil } } do { let p = DirectProduct([2, 3, 5], ["X", "Y", "Z"] as Set<String>) for (_, _) in p {} } print() do { let p = DirectProduct([2, 3, 5], ["X", "Y", "Z"]) for (_, _) in p {} }
DirectProductIterator DirectProductIterator2
for
では無理だったのでイニシャライザで型情報を埋め込みました。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
はどうなってるでしょうか?*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x105a060c0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key videoPreview.' terminating with uncaught exception of type NSException
1x
2x
3x
のところに画像をD&Dしてあげれば、本来でないです。 D&Dしてセットしたあとに画像のファイル名変更等するとその警告はでるので、ファイル名変更するなら変更後にD&Dするといいかと。Unsigned
の画像は選択してdeleteでいいと思います。 それでこの警告自体はきえるかと。swift カメラ 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. Whil
extension ViewBuilder { public static func buildEither<TrueContent, FalseContent>(first: TrueContent) -> _ConditionalContent<TrueContent, FalseContent> where TrueContent : View, FalseContent : View public static func buildEither<TrueContent, FalseContent>(second: FalseContent) -> _ConditionalContent<TrueContent, FalseContent> where TrueContent : View, FalseContent : View }
https://yanamura.hatenablog.com/entry/2019/09/05/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(...)
connect
n場合は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 (または他の方法で)で設定するということはできるのでしょうか? あるいは他の解決法があれば教えて頂けると嬉しいです (edited)$ 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 ^~~ var
struct 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() ^~~ var
await 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()) ^~~ var
await 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()
が呼び出されたか確認しづらいですね、、(苦戦中) 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 started
stderr:<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 concurrency
reasync
があれば @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 #endif
View
の 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)swift_attr
があればUIActor
(MainActor
)を付けて、なければ何も付けない、という意味なんですかね?(このswift_attr
が何を指しているのかがよくわからないですが…) https://clang.llvm.org/docs/AttributeReference.html#swift-attr
__attribute__((swift_attr("swift attribute”)))
はattributeをObjective-Cに付けるものみたいですね。 __attribute__((swift_attr("swift attribute"))). A general-purpose Objective-C attribute to allow one to provide Swift attributes directly. In the context of concurrency, this allows Objective-C APIs to be annotated with a global actor (e.g., @MainActor)
https://github.com/apple/swift-evolution/blob/5bf0cf0b00169297ba9bc30291477cbbe1343145/proposals/0297-concurrency-objc.md#additional-objective-c-attributes 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 true
foo
に nonisolated
付けたら↓になるので、 foo
も MainActor
に保護されてるっぽい。 foo 1 false foo 2 false
foo 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のフィールドとして定義されていて、うまくいっていたんだと思いますfopen 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 = 2
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 }
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 = 3
class Foo {} let foo = Foo() print("init Foo: refCount = \(_getRetainCount(foo))") do { var closure: (() -> ())? = { [bar = foo] in print("in closure: refCount = \(_getRetainCount(bar))") } print("before closure(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure!() print("after closure?(): refCount = \(_getRetainCount(foo))") closure = nil }
(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 = 1
type A = { type: 'A' } type B = { type: 'B' } type AB = A | B // union type
enum
があります。 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 出せたwwweak
の誤用を予想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を明示的に要求することで、表示の前に状態を復元させる意図があります。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
^ のような感じです。 createAt
と createdAt
でtypoがあるようですねcreateAt
と 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-darwin21
env -i HOME=$HOME PATH=/usr/bin:/bin GEM_HOME= GEM_PATH= bundle install --path=.bundle
を実行したら、 A new major version is available for Algolia! Please now use the https://rubygems.org/gems/algolia gem to get the latest features.
と表示されました。これは成功したということでしょうか?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'" > Gemfile
source '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 install
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 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 = nil
currentTask
と同様に 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 { ^~~~~~~~~~~~~
View.blur(radius:opaque:)
があります。ぼかしの程度の指定がCSSの指定と異なりますがradiusパラメータを同じような感じになるように調整するとうまくいくと思います。swift
コマンドで実行するとクラッシュトレースが出力されるのですが、クラッシュが発生した行番号を出力する方法をご存知の方がいれば教えていただけないでしょうか?ちなみに llvm-symbolizer
はPATHに存在します。OSはMonterey 12.6、M1 Macbook Proです。 foo.swift let a = [Int]() a[0]
❯ which llvm-symbolizer /opt/homebrew/opt/llvm@13/bin/llvm-symbolizer
❯ swift --version swift-driver version: 1.62.15 Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51) Target: arm64-apple-macosx12.0
swift
コマンドで実行した場合はスクリプト側の行番号などはスタックトレースに表示できません。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でやった方が良さそうですね。Run Swift Script
を実行するとどうも内部でswiftコマンドで実行されるらしく、クラッシュした時に行番号が見れないのに困っています。素直にXcodeでやった方が良さそうですね。 let appearance = UINavigationBarAppearance() appearance.shadowImage = UIImage() appearance.shadowColor = .clear let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light) appearance.backgroundEffect = blurEffect
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let attributes = super.layoutAttributesForElements(in: rect)? .map { $0.copy() } as? [UICollectionViewLayoutAttributes] var offsetYLeft = spacing var offsetYRight = spacing if let attributes { for attribute in attributes { if attribute.indexPath.item % 2 == 0 { attribute.frame.origin.y = offsetYLeft offsetYLeft += attribute.frame.height + spacing } else { attribute.frame.origin.y = offsetYRight offsetYRight += attribute.frame.height + spacing } } } return attributes }
^ こんな感じで左の列と右の列でframe.yの値を別々に計算して設定していけばできると思います。 (edited)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
のプロパティを意味するのかがわかりにくい、といった違いがありそう。@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を、他のアプリで他人が使って問題ないのかなと少し疑問に思いました。 enum 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の解釈に誤りなどがありましたらご指摘いただけますと幸いです。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の解釈に誤りなどがありましたらご指摘いただけますと幸いです。 .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() }
のように関数にしています。[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)func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") let hostingController = UIHostingController(rootView: SwiftUICellView()) cell.contentView.addSubview(hostingController.view) hostingController.view.translatesAutoresizingMaskIntoConstraints = false [ hostingController.view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor), hostingController.view.topAnchor.constraint(equalTo: cell.contentView.topAnchor), hostingController.view.leftAnchor.constraint(equalTo: cell.contentView.leftAnchor), hostingController.view.rightAnchor.constraint(equalTo: cell.contentView.rightAnchor) ].forEach { $0.isActive = true } return cell }
(edited)XXX.colorset
の名前は変わってますか?XXX.colorset
の名前は変わってますか? 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)nil
が返されるメソッド等が存在はしますが(たとえば String(data: data, using: .utf8)
など)、エラーの意味で返された nil
をそのまま保持し続けるのも望ましくありません。 エラーが throw
されるのではなく nil
が返されるケースは、原則としてエラーの原因が自明な場合です( String(data: data, using: .utf8)
なら、 UTF-8 として解釈できないバイト列が渡された場合)。その場でエラーハンドリングすれば原因がわかりますが、持ち続けてしまうとどこから nil
が混入したのかわからなくなり、原因を究明するのが困難になります。エラーとして nil
が返される場合には、↓のように即座にエラーハンドリングするのが望ましいです。 guard let string = String(data: data, using: .utf8) else { // エラーハンドリング( data が UTF-8 として解釈できない場合) } // string を使う処理
(edited)class MainViewController: UIViewController, UICollectionViewDelegate { ... @IBOutlet private var collectionView: UICollectionView! // <= プロパティで持つ private var dataSource: UICollectionViewDiffableDataSource<Int, Status>! override func viewDidLoad() { super.viewDidLoad() ... let cellRegistration = UICollectionView.CellRegistration<DeviceCell, Status>(cellNib: UINib(nibName: "DeviceCell", bundle: nil)) { (cell, indexPath, item) in ... self.collectionView ... // <= ここでプロパティのcollectionViewを参照する ...
^ たいていはこんな感じじゃないかと思います。 (edited)class ListViewController: UIViewController { // MARK: IBOutlet @IBOutlet private weak var collectionView: UICollectionView! let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell,GameEntity>{ (cell, indexPath, item) in var contentConfiguration = cell.customGameContentConfiguration() contentConfiguration.isEditing = self.collectionView.isEditing //<- selfにアクセスできない cell.contentConfiguration = contentConfiguration } lazy var dataSource = UICollectionViewDiffableDataSource<Section, GameEntity>(collectionView: collectionView, cellProvider: { [unowned self] (collectionView, indexPath, item ) in return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item) }) override func viewDidLoad() { super.viewDidLoad() } ...
protocol SomeProtocol { } extension SomeProtocol { func somePrint() { print("First") } } struct SomeModel: SomeProtocol { func somePrint() { print("Second") } } let someModel: some SomeProtocol = SomeModel() someModel.somePrint() // First
Second
とprintすることができました! protocol SomeProtocol { func somePrint() } extension SomeProtocol { func somePrint() { print("First") } } struct SomeModel: SomeProtocol { func somePrint() { print("Second") } } let someModel: some SomeProtocol = SomeModel() someModel.somePrint() // Second
// 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
@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) } }
通信中に画面を離れるタイミングでキャンセルしたいのですが、うまく動作せず通信成功してしまいます。 原因が全くわかりません。 どこかおかしいところありましたらご教示頂けると助かります♂️ https://github.com/ishkawa/APIKit/blob/master/Documentation/GettingStarted.md#canceling-request (edited)import APIKit class HogeViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let request = HogeRequest() Session.send(request) { result in switch result { case .success(_): print("success") case .failure(_): print("failure") } } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) Session.cancelRequests(with: HogeRequest.self) } }
通信中に画面を離れるタイミングでキャンセルしたいのですが、うまく動作せず通信成功してしまいます。 原因が全くわかりません。 どこかおかしいところありましたらご教示頂けると助かります♂️ https://github.com/ishkawa/APIKit/blob/master/Documentation/GettingStarted.md#canceling-request (edited)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)let results = realm.objects(Item.self).sorted(byKeyPath: keyPath) let filterResults = results.filter(…)
この場合、filterResultsの並び順は最初にsortした並び順になることが保証されていますでしょうか?.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-setcontainerviewcase .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)
Struct AccountData { let accountId : String let accountName : String //省略 } actor AccountDataStore { //******Error: EXC_BAD_ACCESS など static var accountDataStore : [String:AccountData] = [:] //******Error: unrecognized selector sent to instance など static func addAccountData(_ data: AccountData) { AccountDataStore.accountDataStore[data.accountId] = data } static func addAccountDataArray(_ data: [AccountData]){ for data in data{ AccountDataStore.accountDataStore.updateValue(data, forKey: data.accountId) } } static func removeAccountData(_ accountId: String) { AccountDataStore.accountDataStore.removeValue(forKey: accountId) } static func removeAccountAllData(){ AccountDataStore.accountDataStore.removeAll() } static func removeAccountDataArray(_ data:[String]){ for data in data{ AccountDataStore.accountDataStore.removeValue(forKey: data) } } } //利用例 func getAccount(id:String)->[AccountData]{ if let account = AccountDataStore.accountDataStore[id]{ return account }else{ //server request AccountDataStore.addAccountData(data) return data } } func getAccountAsync(id:String) async -> [AccountData]{ if let account = AccountDataStore.accountDataStore[id]{ return account }else{ //server request AccountDataStore.addAccountData(data) return data } } func addAccountDataWithIdsAsync(accountIds:[String]) async throws { try await withThrowingTaskGroup(of: AccountData.self){ group in for id in accountIds{ group.addTask{ return try await getAccountAsync(id:id) } } for try await (id, data) in group{ await AccountDataStore.addAccountData(data) } } }
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の引き継ぎについてではないかと思ったので。request
(かその元の型)に @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 } }
NavigationSplitView
) とタブバー (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 AVPlayer
など基本的なコンポーネントを組み合わせていけば作れる仕様だと思うので、 初心者が挑戦するのにちょうどいい課題感だと思います。 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)if 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
みたいなシンプルにまずそうなエラーを全部スルーすることになるので、あとから問題調査をしようとしたときに特定のバージョンからエラーレポートがなくなって困ってしまうので。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()
で処理が終わるまで待って欲しいです 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)1
Character
は1byteではないのでご注意ください。Swiftにおける文字とはgrapheme clusterのことなので、1文字が巨大なこともあります。 @swift-5.9.2
print("👨👩👦👦".count) // 1
(edited)1
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")!
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でそれ用のインターフェースを介して中身にアクセスする作法ではないのかなと思いました。 それについて詳しく知らないのでわからないですが。