代码如下
import Foundation DispatchQueue.global().async { // 耗时操作(如网络请求、文件处理) let data = downloadData() DispatchQueue.main.async { updateUI(with: data) } } func downloadData() -> String{ sleep(2) return "a" } func updateUI(with: Any) { print("updateUI") } sleep(10)
为什么我无法输出 updateUI
我应该如何在切换到主线程时候,让主线程输出 updateUI
]]>import Foundation import ArgumentParser @main struct Ripripgrep: ParsableCommand { @Option(name: .shortAndLong) var patterns: [String] @Argument(help: "use stdin if no args") var files: [String] = [] func validate() throws { if patterns.isEmpty { fatalError("no patterns!") } } struct Worker { var line: UnsafeMutablePointer<CChar>? var linecap = 0 let patterns: [Regex<AnyRegexOutput>] mutating func start(stream: UnsafeMutablePointer<FILE>) { while case let linelen = getline(&line, &linecap, stream), linelen > 0 { let line = String(decoding: UnsafeRawBufferPointer(start: line!, count: linelen-1), as: UTF8.self) if patterns.allSatisfy({ line.contains($0) }) { print(line) } } } } func run() throws { var worker = Worker(patterns: try patterns.map { try Regex($0).ignoresCase() }) if files.isEmpty { // use stdin worker.start(stream: stdin) } else { for file in files { let stream = fopen(file, "rb")! defer { fclose(stream) } worker.start(stream: stream) } } } }
]]>我们的目标是简化您的学习过程,让 Swift 开发变得前所未有的简单。
]]>本身是个前端开发,最近一个月因业务需要在使用 Swift 和 UIKit 开发 iOS 应用。但是旧项目中各种代理和协议,都让代码跳来跳出,另外项目中没有规范的 MVVM 开发方式,让状态流和 UI 命令式更新,像蜘蛛网一样各种乱闯,看得我脑壳疼,所以动手做了个 ListKit 项目,求各位大佬指点下,这样写是不是有什么问题,或者有什么更好的建议?
ps:目前我在使用声明式的方式写复杂配置的时候,会遇到 Swift 提示编译器无法解析,让我拆分表达式的问题😭!
]]>removeFromSuperlayer
,还是直接sublayers = []
? class Mycalayer: CALayer { func update () { // insert some Sublayers here ..... } func refresh () { // reset all sublayers self.sublayers?.forEach { layer in layer.removeFromSuperlayer() } // OR Just self.sublayers = [] } }
]]>在开发相机组件时遇到一个问题,AVCapturePhotoCaptureDelegate 契约用自定义 UIView/UIViewController 实现没问题, 换成独立的类实现就回调不了,不是什么原因。
上代码:
import Foundation import AVFoundation import UIKit public typealias TakePhotoCallback = ((String, String) -> Void)?; class TakePhotoWithCompletion : NSObject, AVCapturePhotoCaptureDelegate { // ... var completion: TakePhotoCallback; init(callback: TakePhotoCallback) { self.completion = callback; super.init(); } func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { // todo sth self.completion!("{file path}", "{error}"); } }
import AVFoundation import UIKit class CameraxView: UIView { // ... @objc func takePhoto(options: Dictionary<String, String>, completion: TakePhotoCallback) { let photoSettings = AVCapturePhotoSettings.init(format:[AVVideoCodecKey:AVVideoCodecType.jpeg]) let delegate = TakePhotoWithCompletion.init(callback: completion) imageOutPut?.capturePhoto(with:photoSettings, delegate: delegate) } // ... }
import AVFoundation import UIKit class CameraxView: UIView, AVCapturePhotoCaptureDelegate { // ... var completion: TakePhotoCallback = nil; @objc func takePhoto(options: Dictionary<String, String>) { let photoSettings = AVCapturePhotoSettings.init(format:[AVVideoCodecKey:AVVideoCodecType.jpeg]) self.completion = completion imageOutPut?.capturePhoto(with:photoSettings, delegate: self) } @objc func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { // todo sth self.completion!("{file path}", "{error}"); } // ... }
import SwiftUI import ScreenCaptureKit struct ContentView: View { @State private var showingScreenshotAlert = false @State private var screenshotRect = CGRect(x: 100, y: 100, width: 400, height: 300) // 示例区域 @State private var cc = "截图 1" var body: some View { VStack { Text("点击下方按钮进行截图") .padding() Button(action: takeScreenshot) { Text(cc) .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(8) } } .alert(isPresented: $showingScreenshotAlert) { Alert(title: Text("截图完成"), message: Text("截图已保存至桌面"), dismissButton: .default(Text("确定"))) } } class MyStreamOutput: NSObject, SCStreamOutput { var onCaptureCompletion: (() -> Void)? // 闭包,用于通知截图完成 func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { // 每当捕获到新的样本帧时打印消息 print("Captured a new frame of type") onCaptureCompletion?()// 调用闭包通知截图完成 } } func takeScreenshot() { cc = "在截图 1..." showingScreenshotAlert = true SCShareableContent.getWithCompletionHandler { (content, error) in if let error = error { print("Error: \(error)") } else if let cOntent= content { print("Displays: \(content.displays)") print("Displays: \(content.displays[0])") print("Displays: \(content.displays[0].width)") print("Displays: \(content.displays[0].height)") print("Windows:\(content.windows[23])") print("Windows ID:\(content.windows[23].windowID)") print("Windows Count:\(content.windows.count)") // MARK: - 创建 // 创建一个过滤器以捕获整个屏幕 let filter1 = SCContentFilter(display: content.displays[0], excludingWindows: []) let config1 = SCStreamConfiguration() let stream1 = SCStream(filter: filter1, configuration: config1, delegate: nil) // 实例化我们的输出处理类 let streamOutput = MyStreamOutput() // 定义截图完成时的动作 streamOutput.OnCaptureCompletion= { DispatchQueue.main.async { cc = "截图完成了" print("-----------") } } // 添加输出 do { try stream1.addStreamOutput(streamOutput, type: .screen, sampleHandlerQueue: DispatchQueue.main) print("流输出已成功添加") } catch { print("添加流输出时出错: \(error)") } stream1.startCapture { error in if let error = error { print("Failed to start capture: \(error)") } else { print("Capture started successfully!") } } } } } }
]]>我试了网上各种方法都不行,用了官方文档说可以的UIDevice.current.orientation
,也不行。。。
Unable to Add for Review The items below are required to start the review process: You must provide an Internet Content Provider (ICP) Filing Number to make this app available on the App Store in China mainland. Go to App Information
然而我的 app 是可以离线运行的,不需要联网,也没有 server 端,在 Xcode 的项目中也把 networkextension 从 Signing&Capabilities 中删除了。
大家是否遇到过类似情况?不太明白 App store connect 是如何判断是否应该需要 ICP 的。
]]> var body: some View{ ScrollView(showsIndicators: false){ LazyVStack(spacing:0){ ForEach(1...10, id: \.self){ index in ScrollView(.horizontal,showsIndicators: false){ LazyHStack(spacing:0){ VStack { Text("Left View \(index)") .font(.system(.largeTitle)) .foregroundStyle(.white) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.black) .containerRelativeFrame([.horizontal,.vertical]) VStack { Text("Right View \(index)") .font(.system(.largeTitle)) .foregroundStyle(.white) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.blue) .containerRelativeFrame([.horizontal,.vertical]) }.scrollTargetLayout() } .ignoresSafeArea() .containerRelativeFrame([.horizontal,.vertical]) .scrollTargetBehavior(.paging) .onAppear(perform: { UIScrollView.appearance().bounces = false UIScrollView.appearance().alwaysBounceVertical = false UIScrollView.appearance().alwaysBounceHorizOntal= false }) } }.scrollTargetLayout() } .ignoresSafeArea() .containerRelativeFrame([.horizontal,.vertical]) .scrollTargetBehavior(.paging) }
目前用这种方式实现,但是有个问题,滑动到 RightView 可以上下滑动到下一层,有什么办法在滑动到 RightView 时只允许左滑回 Left View
当我同时创建多个 Widget 实例时,无论点击哪个 Widget 实例进行打卡,它们更新的都是第一个 Thing ,看起来多个 Widget 都重复指向了同一个 Thing 。
我后面经过排查,发现是我的 AppIntent 中,Parameter 并不起作用,用户无论选择哪个 thing,perform 中的 thing 都是 EntityQuery 中的 defaultResult 的返回值
struct ConfigurationAppIntent: WidgetConfigurationIntent { @Parameter(title:"Select thing") var thing: ThingData func perform() async throws -> some IntentResult { print("perform thing: \(thing)") // 这里会直接返回 defaultResult 的结果,而不是用户选择的 thing } } // EntityQuery 中的代码 // AppIntent 中的 thing ,永远是这里的返回结果,而不是用户选择的结果 func defaultResult() async -> ThingData? { logger.info("Entering defaultResult()") let cOntext= PersistenceController.shared.viewContext let fetchRequest: NSFetchRequest<Thing> = Thing.fetchRequest() fetchRequest.fetchLimit = 1 do { let things = try context.fetch(fetchRequest) things.forEach { logger.info("Default Thing: \($0.description)") } logger.info("Exiting defaultResult()") return things.first?.toThingData() } catch { logger.error("Error fetching default result: \(error.localizedDescription)") logger.info("Exiting defaultResult()") return nil } }
而且这样会有一个问题,比如说我有五六个 thing ,用户为每个 thing 都添加了一个 widget ,但是由于这个 bug 的存在,导致只有 defaultResult 返回的 Thing 会更新,其他都不会更新
哪位大佬知道怎么解决吗?修了两天了,文档、视频、教程看了一遍,都没发现解决办法。。真的很痛苦 T_T
]]>比如下面的代码:
@SceneBuilder private func menuBarExtra() -> some Scene { if #available(macOS 13.0, *) { MenuBarExtra(isInserted: $statusMenu){ AppMenu() } label: { let image: NSImage = { let ratio = $0.size.height / $0.size.width $0.size.height = 18 $0.size.width = 18 / ratio return $0 }(NSImage(named: "Finder")!) Image(nsImage: image) } }
struct AppMenu: View { var body: some View { HStack{ Text("1") Text("2") Text("3") } } }
我的期望是,三个 text 应该是水平布局吧.为什么实际出来会是垂直布局呢?
请各位大佬解惑,我去问过 gpt, 没问出来结果.
]]>写了一个 1000 多行的代码, 没有用 xcode 开发, 直接 vscode 撸的,
运行时 直接 ./main.swift (代码首行 #!env swift ) 或者 swiftc main.swift -o main.bin , 然后 ./main.bin 运行
现在程序大体稳定, 但是偶尔会崩溃一下, 崩溃时只是提示 crash 和很少信息, 搞不清楚哪里错误。
也试过 swiftc -g main.swift -o main.bin 然后有 lldb ./main.bin , 再 run, crash 的时候提示 error: No auto repeat.com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
(lldb) me #0: 0x0000000192db0154 CoreFoundationCFGetTypeID + 100
就不会了。。。
有没有可能像 python 那些,crash 了告诉我是哪行因为什么原因错掉的呢??
谢谢各位大佬!
]]>简化代码如下:
@State private var showStudentDetail: Bool = false @State private var studentDetail: Student? ... VStack(alignment: .leading, spacing: 12) { ForEach(students) { student in CardView(student: student) .onTapGesture { studentDetail = student showStudentDetail.toggle() } } .sheet(isPresented: $showStudentDetail) { if let studentDetail = studentDetail { StudentDetailView(student: studentDetail) } } }
]]>有像 web 开发中的 flex wrap 属性吗?
大概像是这个图的效果:
比如图片翻页浏览这些
]]>VStack{ Image(systemName: "globe") Text("👻").font(.largeTitle) }
上面是一段 swiftui 代码,它能创建一个垂直排列的 view ,里面的闭包是作为 VStack.init 中 content 的参数,查看源码可知 content 的类型是()->Content 。 我的疑问是
Image(systemName: "globe") Text("👻").font(.largeTitle)
是什么语法,他为什么能返回一个 Content ,我所了解的是要是只有一行代码的话才可以忽略掉 return ,这里不是有两行嘛,求解答。
]]>无法访问用户选择的文件夹下的文件,这个问题我也发到Stackoverflow中,大佬们能否看看👀,在这里或者 stackoverflow 中回答都可以!
应用的目标是获取文件夹下的所有视频,储存成一个数组,在需要的时候使用 URL 加载视频。调查了几款视频播放 App 都能支持,不知道为什么我按照网上的教程操作后,仍然无法支持
我想用 SwiftUI 中的.help 修饰符在 hover 的时候显示 tooltip ,但是在 macOS 14.0 中无法生效,其他系统版本未测试
]]>贴个链接: https://github.com/YugenFring/swift-tutorial-quickstart
感谢解答
]]>如果想实现播放网络或者本地的音乐数据( flac/wav/mp3/aac/wma/ogg )应该用到哪些库?都是起到什么作用?
我理解的是,应该使用 ffmpeg 先进行 demux 解封装,然后再对 stream 进行 decode 获取到 PCM sample ,最后调用上面某一个库(可能是 Audio Engine )进行播放。
但我说的这个方法是软解码么?如果苹果自己支持的格式比如 mp3 等,是否可以不使用 ffmpeg 来解码?那应该用上面哪个库来处理?
还有音乐文件的 metadata 解析(音乐名/艺术家/封面/歌词等信息),如何提取 metadata? 苹果自家的仅支持 ID3 或者 iTunes ,对于其他格式的比如 wav/flac 等,应该怎么处理?
下面两个链接是我看过的参考资料,好像已经过时了。经过搜索也没有找到新的比较靠谱的讲解。
]]>目前查到的一个解决方案是在 xcconfig 里加上这 3 条把这个新功能暂时禁用。
ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS = NO; ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOL_FRAMEWORKS = ""; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIOnS= NO;
]]>做着做着,身边的同学也不选择小组件的应用。没同学可以请教。只能寻求网上厉害的大佬。
我遇到的问题是: 我想实现时钟小组件添加到桌面后能自动刷新。我只做到了小组件的秒针跑了几圈,然后就停下来了。
要是有大佬能够解答,愿意请大佬喝杯奶茶(学生党,请谅解)😂😂😂
]]>var a: Int? = nil print("\(type(of: a))") print("\(a is String?)") var b: Int? = 1 print("\(type(of: b))") print("\(b is String?)") /* output:: Optional<Int> true Optional<Int> false */
下面是 GPT 的答案
]]>似乎可以替代自带的 URLSession.shared.dataTask 进行网络请求及自动解析 json 文件
可以极大简化开发难度
推荐使用吗,会不会遇到什么问题
]]>class GlobalData { // static let shared = GlobalData() // 不使用单例模式,没有实例,直接调用类 static var allProblems: [Problem] = getAllProblems() static var allContests: [Contest] = getAllContests() }
问题其一是使用 static 加载速度太慢了,必须等其加载完才能显示 APP 的内容
给出其中一个调用 GlobalData 的样例
struct HistoryContestsView: View { @State var contests: [Contest] = GlobalData.allContests @State var allProblems: [Problem] = GlobalData.allProblems var body: some View { NavigationView { // ... } .refreshable { reloadHistoryContests() } } private func reloadHistoryContests() { GlobalData.allProblems = getAllProblems() allProblems = GlobalData.allProblems GlobalData.allCOntests= getAllContests() cOntests= GlobalData.allContests print("Successfully reload history contests") } }
其二是 reloadHistoryContests 内容显得十分冗余
目前想到的策略是定义一个 ObservableObject 类 HistoryContestsView 就可以直接订阅 GlobalData 类 并且在 .task 中异步加载数据,也能解决性能问题
class GlobalData: ObservableObject { @Published var allProblems: [Problem] = [] @Published var allContests: [Contest] = [] func loadData() { // 加载数据的代码 // ... self.allProblems = getAllProblems() self.allCOntests= getAllContests() } }
但又出现了个问题,在其他 model 文件中,原本调用 GlobalData.allContests 的函数,都无法使用了
func getPredictiveContestList(by userid: String) -> [User.AttendedContest] { let predictiveCOntests= Global.allContests.filter { $0.avgRatingOfProblems == nil } // print(predictiveContests) var res: [User.AttendedContest] = [] for contest in predictiveContests { /// 参加了且有了预测结果 // TODO - 后面统计参加了还没有结果的 if let tmp = predictRatingOfUser(by: contest.titleSlug, userid: userid) { res.append(tmp) } } return res }
如何解决?
]]>NSArray
,NSMutableArray
,NSDictionary
,NSMutableDictionary
。 每次看到从这些类型中取值、设置值都很头疼(好几年没写 OC 了):
var dict = NSMutableDictionary() dict = NSMutableDictionary(dictionary: te as! NSDictionary) dict.setValue("\((index as! NSDictionary).object(forKey: "foo")!)", forKey: "foo")
完全不使用 Swift
的语言特性,一些高级函数都无法使用,关键这是一个 Swift 项目。
虽然其中有一些是从 16 年就有的代码,但是最近开发的功能还这么做,就很无语。
就像是用 TypeScript
进行项目开发,但是所有的类型都是 Any
诶,什么时候 Swift
能把 OC 踢出去呀