class DrawOp : public Op { // DrawOp通过Pipiline实现多个_colors纹理对象及_masks蒙版的绘制 std::vector<std::unique_ptr<FragmentProcessor>> _colors; std::vector<std::unique_ptr<FragmentProcessor>> _masks; };
配置为免密码登录之后,还可以进一步使用 USB 有线连接的方式登录到手机。如果你经常使用 WiFi 这种方式远程登录调试就会发现偶尔会碰到指令输入,响应卡顿,反应慢的情况,这样的体验显然让人感到不爽。所以,在大部分情况下,更推荐使用 USB 有线连接登录到 iPhone 上,这样使用的过程中,就像在本地输入命令操作一样流畅。
structtestModel: ExAutoCodable { @ExCodable var courseId: Int = -1 @ExCodable var totalSectionCount: Int = -1// 总的章节 @ExCodable var courseImageUrl: String = "" @ExCodable var tudiedSectionCount: Int = 0// 已经学习章节 }
既然他这么好,那就用起来啰喂,,,,等等,等等
定义模型这样,竟然不行:
structtestModel: ExAutoCodable { @ExCodable var jumpParam: [String: Any]? = [:] @ExCodable var matchs: [Any] = [] }
struct NotificationToastView: View { var notificationImage: String var notificationTitle: String var notificationContent: String var notificationTime: String
struct ItemModel { var section: Int = -1 // cell的section索引 var item: Int = -1 // cell的item索引 var name: String = "" // 名称 var isAdded: Bool = false // 是否添加到首页应用(第0区) var id: String { // 唯一标识,可以用这个来命名图片的名称,也可以用来作判断 get { "\(section)_\(item)" } } init(){} }
看得出来,ItemModel的属性section + item = IndexPath,可以根据 model 知道当前cell的所在位置了。
笔者这用的是 struct ,感觉用 class 会更好点,因为后续会改变数组中Model的属性值。已经写了就懒得再改了。
存在2个数组数据:
var editItems = [ItemModel](),由前一页传入的、可编辑、拖拽的数据,位于UICollectionView的第0个Section。
var datas = [[ItemModel]](),按照Section的顺序,存放所有的数据。
注意:Section要从1开始,因为第0个Section是可以编辑拖拽的区域。
datas中存放全部的数据:
for i in 0..<names.count { let subNames = names[i] var items = [ItemModel]() for j in 0..<subNames.count { var model = ItemModel() model.section = i+1 // 注意这里的Section要从1开始 model.item = j model.name = subNames[j] model.isAdded = editItems.contains(where: { $0.id == model.id}) items.append(model) } datas.append(items) }
根据数据布局UICollectionView。
移动动画
移动只要2个操作,添加应用和删除应用。
添加
笔者这里规定了最多可以添加8个应用。
大致思路:
获取当前点击的 cell,为了得到其坐标作为动画起始位置
在 collectionView 中插入一个空白的 cell 占位,此举是为了增加或减少行数的动画过渡更自然;对应也应该在 editItems 中添加一个空白的 model 作为数据源,等移动动画结束后再给model重新赋值。
这是一个全新的平台。熟悉的框架和工具。请准备好为 Apple vision Pro 设计和构建全新的应用程序和游戏世界。
沉浸的光谱。
Apple vision Pro 提供无限的空间画布供您探索、试验和玩耍,让您自由地完全重新思考您的 3D 体验。人们可以在与周围环境保持联系的同时与您的应用互动,或者完全沉浸在您创造的世界中。您的体验可以是流畅的:从一个窗口开始,引入 3D 内容,过渡到完全身临其境的场景,然后马上回来。
选择权在您手中,这一切都始于 visionOS 上的空间计算构建块。
窗口(Windows)
您可以在 visionOS 应用程序中创建一个或多个窗口。它们使用 SwiftUI 构建,包含传统视图和控件,您可以通过添加 3D 内容来增加体验的深度。
体积(Volumes)
使用 3D 体积为您的应用添加深度。 Volumes 是一种 SwiftUI 场景,可以使用 RealityKit 或 Unity 展示 3D 内容,从而创建可从共享空间或应用程序的完整空间中的任何角度观看的体验。
空间(Space)
默认情况下,应用程序启动到共享空间,在那里它们并排存在——很像 Mac 桌面上的多个应用程序。应用程序可以使用窗口和音量来显示内容,用户可以将这些元素重新放置在他们喜欢的任何位置。为了获得更身临其境的体验,应用程序可以打开一个专用的完整空间,其中只会显示该应用程序的内容。在完整空间内,应用程序可以使用窗口和体积、创建无限的 3D 内容、打开通往不同世界的门户,甚至可以让某人完全沉浸在某个环境中。
使用 Apple 的 3D 渲染引擎 RealityKit 在您的应用程序中呈现 3D 内容、动画和视觉效果。 RealityKit 可以自动调整物理光照条件并投射阴影、打开通往不同世界的门户、构建令人惊叹的视觉效果等等。为了创作您的材料,RealityKit 采用了 MaterialX,这是一种用于指定表面和几何着色器的开放标准,由领先的电影、视觉效果、娱乐和游戏公司使用。
ARKit
在 vision Pro 上,ARKit 可以完全了解一个人的周围环境,为您的应用提供与周围空间交互的新方式。默认情况下,ARKit 支持内核系统功能,您的应用程序在共享空间中时会自动受益于这些功能——但是当您的应用程序移动到完整空间并请求许可时,您可以利用强大的 ARKit API,例如平面估计、场景重建、图像锚点、世界轨道和骨骼手部轨道。所以在墙上泼水。从地板上弹起一个球。通过将现实世界与您的内容融合在一起,打造令人惊叹的体验。
Accessibility
visionOS 的设计考虑了可访问性,适用于希望完全通过眼睛、声音或两者的组合与设备交互的人。对于喜欢以不同方式导航内容的人,Pointer Control 允许他们选择食指、手腕或头部作为替代指针。您可以使用已在其他 Apple 平台上使用的相同技术和工具为 visionOS 创建易于访问的应用程序,并帮助使 vision Pro 成为每个人的绝佳体验。
let attributes = TestWidgetAttributes() let initialConetntState = TestWidgetAttributes.TestWidgetState(dataModel: dataModel) do { let activity = try Activity.request( attributes: attributes, content: .init(state: initialConetntState, staleDate: nil), pushType: nil // pushType: .token ) print("请求开启实时活动: \(activity.id)") } catch (let error) { print("请求开启实时出错: \(error.localizedDescription)") }
更新
let updateState = TestWidgetAttributes.TestWidgetState(dataModel: dataModel) let alertConfig = AlertConfiguration( title: "\(dataModel.nameDes) has taken a critical hit!", body: "Open the app and use a potion to heal \(dataModel.nameDes)", sound: .default ) await activity.update( ActivityContent<TestWidgetAttributes.ContentState>( state: updateState, staleDate: nil ), alertConfiguration: alertConfig ) print("更新实时活动: \(activity.id)")
Cannot form weak reference to instance (0x1107c6200) of class _UIRemoteInputViewController. It is possible that this object was over-released, or is in the process of deallocation. 无法 weak 引用类型为 _UIRemoteInputViewController 的对象。可能是因为这个对象被过度释放了,或者正在被释放。weak 引用已经释放或者正在释放的对象会 crash,这种崩溃业务侧经常见于在 dealloc 里面使用 __weak 修饰 self。 _UIRemoteInputViewController 明显和键盘相关,看了下用户的日志也都是在弹出键盘后崩了。
id weak_register_no_lock(weak_table_t *weak_table, id referent_id, id *referrer_id, WeakRegisterDeallocatingOptions deallocatingOptions) { objc_object *referent = (objc_object *)referent_id; if (deallocatingOptions == ReturnNilIfDeallocating || deallocatingOptions == CrashIfDeallocating) { bool deallocating; if (!referent->ISA()->hasCustomRR()) { deallocating = referent->rootIsDeallocating(); } else { deallocating = ! (*allowsWeakReference)(referent, @selector(allowsWeakReference)); }
if (deallocating) { if (deallocatingOptions == CrashIfDeallocating) { _objc_fatal("Cannot form weak reference to instance (%p) of " <=== 崩溃 "class %s. It is possible that this object was " "over-released, or is in the process of deallocation.", (void*)referent, object_getClassName((id)referent)); } else { return nil; } } } }
当使用此新的 Camera service 进行单元测试时,我们希望确保 AVCaptureSession 没有被真的创建。我们仅仅希望确认 camera service 被测试系统(SUT)正确的调用了,而不是去测试 camera service 本身。 因此,创建一个协议的 mock 实现,使用空方法和一组变量来帮助我们进行单元测试,并断言(asset)进行了正确的调用是有意义的。这是软件开发中非常常见的一个场景,如果你曾维护过一个包含大量单元测试的大型代码库,这么做也可能有点乏味。 好吧~不用担心!Sourcery 会帮助你!⭐️ 它有一个叫做 AutoMockable[2] 的模板,此模板会为任意输入文件中遵守 AutoMockable 协议的协议生成 mock 实现。
let listOfArticles = ArticlesList() var searchKeyword: NSAttributedString? = NSAttributedString(string: "keyword") let filteredArticles = await listOfArticles.filteredArticles { article in
// Error: Reference to captured var 'searchKeyword' in concurrently-executing code guard let searchKeyword = searchKeyword else { return false } return article.title == searchKeyword.string }
我们建立Reader和Book之间的联系的时候,发现他们的联系逻辑之间还漏了一个环节。假设一本书被一个读者借走了,它就不能被另一个读者借走,而当一个读者借书时,却可以借很多本书。也就是说,一本书只能对应一个读者,而一个读者却可以对应多本书。这就是 一对一→to one 和 一对多→to many 。Core Data允许我们配置这种联系,具体做法就是在RelationShip栏点击对应的关系栏,它将会出现在右侧的栏目中。(栏目如果没出现可以在xcode右上角的按钮调出,如果点击后栏目没出现Relationship配置项,可以多点击几下,这是xcode的小bug)。在Relationship的配置项里,有一项项名为Type,点击后有两个选项,一个是To One(默认值),另一个就是To Many了。
private func readBooks(container: NSPersistentContainer) { let context = container.viewContext let fetchBooks = NSFetchRequest<Book>(entityName: "Book") do { let books = try context.fetch(fetchBooks) print("Books count = \(books.count)") for book in books { print("Book name = \(book.name!)") } } catch {
let context = container.viewContext let fetchBooks = NSFetchRequest<Book>(entityName: "Book") fetchBooks.predicate = NSPredicate(format: "isbm = \"9787115293800\"") do { let books = try context.fetch(fetchBooks) for book in books { context.delete(books[0]) } if context.hasChanges { try context.save() } } catch { print("\(error)") }