8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何在 TS 上从 Iphone 访问加速度计?

Melloware 3月前

41 0

在为 Telegram 开发 Web 应用程序时,我遇到了一个相当有趣的案例。最重要的是,我需要获得手机用户(特别是 iPhone 用户)的许可(或拒绝)......

在为 Telegram 开发 Web 应用程序时,我遇到了一个相当有趣的案例。

最重要的是,我需要在第一个应用程序上获得手机用户(特别是 iPhone 用户)的许可(或拒绝),并且我可以使用手机的加速度计来识别某些事件。

本地 - 它可以工作(如果有人感兴趣,可以使用 zrok 作为层,因为 Telegram 不会在没有证书的情况下打开本地版本)

但是,部署后,iPhone 上的工作没有任何停止。Android 上的情况要好得多)

以下是我为了明确获得 iPhone 所有者的许可而编写的代码部分......


  async approve(): Promise<boolean> {
    if (typeof this._approved === 'undefined') {
      if (!('DeviceMotionEvent' in window)) return (this._approved = false)
      try {
        type PermissionRequestFn = () => Promise<PermissionState>
        type DME = typeof DeviceMotionEvent & { requestPermission: PermissionRequestFn }
        if (typeof (DeviceMotionEvent as DME).requestPermission === 'function') {
          const permissionState = await (DeviceMotionEvent as DME).requestPermission()
          this._approved = permissionState === 'granted'
        } else this._approved = true
      } catch {
        this._approved = false
      }
    }
    return this._approved
  }
export const Home = observer(() => {

  const { x, y, z } = useShake()
  const shaker = new Shake({ threshold: 5, timeout: 50 })

  const handleApproval = (evt: React.MouseEvent<HTMLButtonElement>) => {
    evt.preventDefault()

    shaker.approve()
  }



  const { handleSuccessHaptic } = useHaptic()

  useEffect(() => {
      shaker.addEventListener('shake', () => {
      game.onClick()
      handleSuccessHaptic()
    })

    shaker.start()

    return () => {
      shaker.stop()
    }
  }, [handleSuccessHaptic, shaker])

  const handleClicks = () => {
    console.log('It work')
  }

 
  return (
    <div className={'flex flex-col gap-10'}>
     
          <Button className={'w-full'} onClick={handleApproval}>
        GET APPROVE
      </Button>

      <ul>
        <li>X: {x}</li>
        <li>Y: {y}</li>
        <li>Z: {z}</li>
      </ul>
    </div>
  )
})
帖子版权声明 1、本帖标题:如何在 TS 上从 Iphone 访问加速度计?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Melloware在本站《iphone》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我正在运行 xcode v. 15.3、Swift v. 5.10,并在 iPhone iOS v. 17.4.1 上进行测试。在尝试实现简单的共享表功能时,我不断遇到一个奇怪的错误,这将允许......

    我正在运行 xcode v. 15.3、Swift v. 5.10,在 iPhone iOS v. 17.4.1 上进行测试

    我在尝试实现简单的共享表功能(允许用户共享存储的图像)时一直遇到一个奇怪的错误。我花了两天时间尝试在线寻找解决方案,但没有成功。

    起初我以为是存储问题,因此我尝试了 SwiftData、CoreData 和文件系统存储,结果相同。

    单击带有图像的待办事项,然后单击底部的共享图标。应该显示共享表,但什么也没有显示,我在日志中看到以下错误

    Couldn't read values in CFPrefsPlistSource<0x302f410e0> (Domain: com.apple.country.carrier_2, User: kCFPreferencesCurrentUser, ByHost: No, Container: /var/mobile/Library/CountryBundles/, Contents Need Refresh: Yes): accessing preferences outside an application's container requires user-preference-read or file-read-data sandbox access
    
    Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)" UserInfo={NSLocalizedFailureReason=(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)}>
    (501) personaAttributesForPersonaType for type:0 failed with error Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.mobile.usermanagerd.xpc was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.apple.mobile.usermanagerd.xpc was invalidated: failed at lookup with error 159 - Sandbox restriction.}
    
    Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
    elapsedCPUTimeForFrontBoard couldn't generate a task port
    Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
    Attempt to present <UIActivityViewController: 0x10582e800> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x10301e800> (from <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x10301e800>) which is already presenting <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x10700ee00>.
    connection invalidated
    

    完整应用程序代码:

    //
    //  ToDosApp.swift
    //  ToDos
    //
    //  Created by Tunde Adegoroye on 06/06/2023.
    //
    
    import SwiftUI
    import SwiftData
    
    @main
    struct ToDosApp: App {
    
        @AppStorage("isFirstTimeLaunch") private var isFirstTimeLaunch: Bool = true
        
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
            .modelContainer(ItemsContainer.create(shouldCreateDefaults: &isFirstTimeLaunch))
        }
    }
    
    //
    //  ContentView.swift
    //  ToDos
    //
    //  Created by Tunde Adegoroye on 06/06/2023.
    //
    
    import SwiftUI
    import SwiftData
    import SwiftUIImageViewer
    
    enum SortOption: String, CaseIterable {
        case title
        case date
        case category
    }
    
    extension SortOption {
        
        var systemImage: String {
            switch self {
            case .title:
                "textformat.size.larger"
            case .date:
                "calendar"
            case .category:
                "folder"
            }
        }
    }
    
    struct ContentView: View {
        
        @Environment(\.modelContext) private var modelContext
        @Query private var items: [Item]
        
        @State private var searchQuery = ""
        @State private var showCreateCategory = false
        @State private var showCreateToDo = false
        @State private var toDoToEdit: Item?
        
        @State private var isImageViewerPresented = false
        
        @State private var selectedSortOption = SortOption.allCases.first!
        
        var filteredItems: [Item] {
            
            if searchQuery.isEmpty {
                return items.sort(on: selectedSortOption)
            }
            
            let filteredItems = items.compactMap { item in
                
                let titleContainsQuery = item.title.range(of: searchQuery,
                                                          options: .caseInsensitive) != nil
                
                let categoryTitleContainsQuery = item.category?.title.range(of: searchQuery,
                                                                            options: .caseInsensitive) != nil
                
                return (titleContainsQuery || categoryTitleContainsQuery) ? item : nil
            }
            
            return filteredItems.sort(on: selectedSortOption)
            
        }
        
        var body: some View {
            NavigationStack {
                List {
                    ForEach(filteredItems) { item in
                        VStack {
                            HStack {
                                VStack(alignment: .leading) {
                                    
                                    if item.isCritical {
                                        Image(systemName: "exclamationmark.3")
                                            .symbolVariant(.fill)
                                            .foregroundColor(.red)
                                            .font(.largeTitle)
                                            .bold()
                                    }
                                    
                                    Text(item.title)
                                        .font(.largeTitle)
                                        .bold()
                                    
                                    Text("\(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .shortened))")
                                        .font(.callout)
                                    
                                    if let category = item.category {
                                        Text(category.title)
                                            .foregroundStyle(Color.blue)
                                            .bold()
                                            .padding(.horizontal)
                                            .padding(.vertical, 8)
                                            .background(Color.blue.opacity(0.1),
                                                        in: RoundedRectangle(cornerRadius: 8,
                                                                             style: .continuous))
                                    }
                                    
                                }
                                
                                
                                Spacer()
                                
                                Button {
                                    withAnimation {
                                        item.isCompleted.toggle()
                                    }
                                } label: {
                                    
                                    Image(systemName: "checkmark")
                                        .symbolVariant(.circle.fill)
                                        .foregroundStyle(item.isCompleted ? .green : .gray)
                                        .font(.largeTitle)
                                }
                                .buttonStyle(.plain)
                            }
                                if let selectedPhotoData = item.image,
                                   let uiImage = UIImage(data: selectedPhotoData) {
                                    Image(uiImage: uiImage)
                                        .resizable()
                                        .scaledToFill()
                                        .frame(maxWidth: .infinity, maxHeight: 120)
                                        .clipShape(RoundedRectangle(cornerRadius: 10,
                                                                    style: .continuous))
                                        .onTapGesture {
                                            isImageViewerPresented = true
                                        }
                                        .fullScreenCover(isPresented: $isImageViewerPresented) {
                                            SwiftUIImageViewer(image: Image(uiImage: uiImage))
                                                .overlay(alignment: .topTrailing) {
                                                    Button {
                                                        isImageViewerPresented = false
                                                    } label: {
                                                        Image(systemName: "xmark")
                                                            .font(.headline)
                                                    }
                                                    .buttonStyle(.bordered)
                                                    .clipShape(Circle())
                                                    .tint(.purple)
                                                    .padding()
                                                }
                                            
                                            Button(action: {
                                                                            shareImage(uiImage)
                                                                        }) {
                                                                            Label("Share", systemImage: "square.and.arrow.up")
                                                                                .foregroundColor(.blue)
                                                                        }
                                                                        .buttonStyle(.plain)
                                        }
                                }
                            
                        }
                        .swipeActions {
                            
                            Button(role: .destructive) {
                                
                                withAnimation {
                                    modelContext.delete(item)
                                }
                                
                            } label: {
                                Label("Delete", systemImage: "trash.fill")
                            }
                            
                            Button {
                                toDoToEdit = item
                            } label: {
                                Label("Edit", systemImage: "pencil")
                            }
                            .tint(.orange)
                            
                        }
                    }
                }
                .navigationTitle("My To Do List")
                .animation(/*@START_MENU_TOKEN@*/.easeIn/*@END_MENU_TOKEN@*/, value: filteredItems)
                .searchable(text: $searchQuery,
                            prompt: "Search for a to do or a category")
                .overlay {
                    if filteredItems.isEmpty {
                        ContentUnavailableView.search
                    }
                }
                .sheet(item: $toDoToEdit,
                       onDismiss: {
                    toDoToEdit = nil
                },
                       content: { editItem in
                    NavigationStack {
                        UpdateToDoView(item: editItem)
                            .interactiveDismissDisabled()
                    }
                })
                .sheet(isPresented: $showCreateCategory,
                       content: {
                    NavigationStack {
                        CreateCategoryView()
                    }
                })
                .sheet(isPresented: $showCreateToDo,
                       content: {
                    NavigationStack {
                        CreateTodoView()
                    }
                })
                .toolbar {
                    
                    ToolbarItemGroup(placement: .primaryAction) {
                        Button {
                            showCreateCategory.toggle()
                        } label: {
                            Image(systemName: "plus")
                        }
                    }
                    
                    ToolbarItemGroup(placement: .topBarTrailing) {
                        
                        Menu {
                            Picker("", selection: $selectedSortOption) {
                                ForEach(SortOption.allCases,
                                        id: \.rawValue) { option in
                                    Label(option.rawValue.capitalized,
                                          systemImage: option.systemImage)
                                    .tag(option)
                                }
                            }
                            .labelsHidden()
                            
                        } label: {
                            Image(systemName: "ellipsis")
                                .symbolVariant(.circle)
                        }
                        
                    }
                    
                }
                .safeAreaInset(edge: .bottom,
                               alignment: .leading) {
                    Button(action: {
                        showCreateToDo.toggle()
                    }, label: {
                        Label("New ToDo", systemImage: "plus")
                            .bold()
                            .font(.title2)
                            .padding(8)
                            .background(.gray.opacity(0.1),
                                        in: Capsule())
                            .padding(.leading)
                            .symbolVariant(.circle.fill)
                        
                    })
                    
                }
            }
        }
        private func shareImage(_ image: UIImage) {
            let activityController = UIActivityViewController(activityItems: [image], applicationActivities: nil)
    
            // Selecting the appropriate scene
            let targetScene = UIApplication.shared.connectedScenes
                                 .filter { $0.activationState == .foregroundActive }
                                 .first(where: { $0 is UIWindowScene }) as? UIWindowScene
    
            guard let rootViewController = targetScene?.windows
                                                     .first(where: { $0.isKeyWindow })?
                                                     .rootViewController else {
                return
            }
    
            // Present the activity controller
            rootViewController.present(activityController, animated: true, completion: nil)
        }
    
        private func delete(item: Item) {
            withAnimation {
                modelContext.delete(item)
            }
        }
    }
    
    private extension [Item] {
        
        func sort(on option: SortOption) -> [Item] {
            switch option {
            case .title:
                self.sorted(by: { $0.title < $1.title })
            case .date:
                self.sorted(by: { $0.timestamp < $1.timestamp })
            case .category:
                self.sorted(by: {
                    guard let firstItemTitle = $0.category?.title,
                          let secondItemTitle = $1.category?.title else { return false }
                    return firstItemTitle < secondItemTitle
                })
            }
        }
    }
    
    
    //
    //  TodoView.swift
    //  ToDos
    //
    //  Created by Tunde Adegoroye on 06/06/2023.
    //
    
    import SwiftUI
    
    struct TodoView: View {
        
        let item: Item
        @State private var isShareSheetPresented = false
        
        var body: some View {
            VStack(alignment: .leading) {
                
                if item.isCritical {
                    Image(systemName: "exclamationmark.3")
                        .symbolVariant(.fill)
                        .foregroundColor(.red)
                        .font(.largeTitle)
                        .bold()
                }
    
                Text(item.title)
                    .font(.largeTitle)
                    .bold()
            
                Text("\(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
                    .font(.callout)
                
                
            }
            
        }
    }
    
    
    //
    //  Item.swift
    //  ToDos
    //
    //  Created by Tunde Adegoroye on 06/06/2023.
    //
    
    import Foundation
    import SwiftData
    
    @Model
    final class Item {
        var title: String
        var timestamp: Date
        var isCritical: Bool
        var isCompleted: Bool
    
        @Relationship(deleteRule: .nullify, inverse: \Category.items)
        var category: Category?
        
        @Attribute(.externalStorage)
        var image: Data?
        
        init(title: String = "",
             timestamp: Date = .now,
             isCritical: Bool = false,
             isCompleted: Bool = false) {
            self.title = title
            self.timestamp = timestamp
            self.isCritical = isCritical
            self.isCompleted = isCompleted
        }
    }
    
    extension Item {
        
        static var dummy: Item {
            .init(title: "Item 1",
                  timestamp: .now,
                  isCritical: true)
        }
    }
    
    
返回
作者最近主题: