如何在儿童版块中为 iOS 应用设置家长门

Posted

技术标签:

【中文标题】如何在儿童版块中为 iOS 应用设置家长门【英文标题】:how to implement a parental gate for iOS apps in the kid's section 【发布时间】:2013-10-02 03:54:47 【问题描述】:

由于 App Store 拒绝二进制文件,我正在更新我的应用程序,因为我的应用程序在“信用”页面中包含指向网站的链接。我需要实现一个家长门来限制对“信用”视图控制器的访问。

我找到了一个检查应用内购买权限的代码。但我想我不能为此目的使用相同的?

如何在打开视图控制器之前检查父母的许可?

【问题讨论】:

【参考方案1】:

我发布了一个开源 Parental Gate SDK,该 SDK 已用于已成功通过 Apple 新 24.3 规则审核的应用程序中,该规则要求应用程序内购买的“家长门”以及任何将用户体验带到网。您可以在此处阅读有关 SDK 的更多信息并获取代码:

MKParentalGate Open Source SDK

【讨论】:

【参考方案2】:

我的申请因同样的原因被拒绝。我在应用程序升级时添加了家长网关,但我的应用程序中有广告,因此它再次被拒绝,因为点击广告离开应用程序并打开 itune 商店。我不确定是否有人可以在点击广告后和打开外部链接之前问父母问题。

我看到两个解决方案 1.从应用程序中删除广告 2. 取消选择 Made for Kids

这是否意味着我们不能为面向儿童的应用程序投放广告?

【讨论】:

【参考方案3】:

我最近刚刚与 Apple 讨论过这个问题。

首先,他们将把它留给开发人员来实施,而不必告诉我们他们将接受什么。但是,我确实设法从 Apple 那里得知,它实际上也取决于您所针对的年龄组。如果您要为年龄较大的人群服务,那么父母的门一定更难克服。

一个简单的弹出窗口告诉用户只有在那之后它是成年人是行不通的。必须有其他东西阻止用户。建议接受多点触控滑动、数学问题和历史问题。

我担心的是,我认识很多家长,他们无法进行我见过的一些(45+62 等)中使用的简单算术运算。历史问题会很困难,因为我国的历史与你们的不同(班诺克本战役是什么时候?)。我见过的解决这个问题的一种方法是给出多项选择答案,但是如果有三个选项,那么有 33% 的可能性猜测就足够了!多点触控滑动太容易了。

理想情况下,Apple 确实应该将这作为需要密码的 ios 的一部分。至少它会标准化父母门。

根据第二行选项和不同问题的要求,我选择了四个选项之一,从而设置了父母门。我在这里的目标是让测验对父母来说足够容易,但同时随机猜测不太可能解决难题。四个选项是 25% 的机会是正确的,第二个问题降低到 6%。我认为这将适用于我的目标在年轻端的要求。

** 我的父母门版本被接受。从第一个视图控制器我会调用父母门。如果失败,它将关闭并创建一个 UIAlertView 说明它失败。如果它通过了,那么它也会关闭并在完成时发送成功通知。调用视图控制器收到通知,然后执行如果它不必做父母门会做的任何事情!

【讨论】:

所以,我假设如果你有一个父母门,它总是在那里?例如,是否无法从使用 Apple ID 登录的用户那里获取年龄范围并绕过某些用户的大门?我只是在想这个,因为虽然我的应用程序对孩子们很感兴趣,但对成年人也很感兴趣,而且总是强迫成年人通过大门似乎是一种糟糕的用户体验。另外:每次启动应用程序时都必须出现这个门吗?或者结果可以永久存储吗? 非常好的问题,我没有资格回答!我不是苹果,但我的印象是苹果喜欢你每次都问;不要做假设。 我在 Game Kit 之前做过这个,你可以得到一个未成年人的条件。也许如果用户已登录并且不是未成年人,您可以跳过门。 [GKLocalPlayer localPlayer].underage 好的--谢谢!我会调查的。【参考方案4】:

鉴于似乎仍然存在很多不确定性,我想我会分享我自己的经验。

因为我为年幼的孩子(六岁或类似的孩子)制作应用程序,所以我可以假设父母之门不需要太难。目前我实现了一个简单的 UIAlertView 来询问一个数学问题。由于其他答案之一中的评论,我实际上正在使该问题变得更简单。

我正在做的是取两个 10 到 30 之间的随机数,并要求用户添加它们并输入答案。不幸的是,因为我目前正在 UIAlertView 中执行此操作并且我需要一个编辑字段,这将 iOS 使用的标准提高到了 5.0。查看我的应用程序的 Flurry 数据,在过去的一个月里,iOS 5 下的任何东西几乎没有注册(不到总数的 1%),所以我不太担心。

我仍在考虑是否不能在我们所学到的数学知识的基础上让成人变得更简单,但不一定对孩子来说更简单。例如,确保要添加的任何数字都是偶数,这可能会使许多人更容易。与五的倍数一起工作会更容易,而我认为孩子们根本没有学会这些技巧,所以对他们来说不会有太大的不同。

我在 App Store 中有三个不同的应用程序使用相同的方法并且它们都被接受了,即使它们得到了不同的人的审查(我可以看出他们在其他方面的决定有多么愚蠢)所以我假设这种做法得到认可。我还没有做的是尝试想出一种方法来判断用户是否觉得这很烦人,或者大多数人是否可以不用太担心来处理这个问题。

【讨论】:

【参考方案5】:

您可能想试试这个 cocoapod 库: https://cocoapods.org/pods/HYParentalGate

【讨论】:

【参考方案6】:

我用 swiftUI 为需要它的人创建了一个。

它会生成 3 个随机数,然后要求您按该顺序按下数字按钮,如果正确,它会隐藏不透明的门,所以我在加载时需要门的屏幕上使用它,所以当门隐藏时,它显示下面的另一个视图。 如果按下的数字不正确,它会关闭门并将视图关闭并返回原始视图。

import SwiftUI

struct GateScreen: View 
@Environment(\.presentationMode) var presentationMode
@State var tInput1 = "1"
@State var tInput2 = "2"
@State var tInput3 = "3"
@State var nP = ""
@State var npP = ""
@State var pressedN  = ""
@State var randN = 0
@State var showingAbout = false
@State var hiddenOpp = 1.0


var body: some View 
    ZStack 
        Color(.white)
    VStack 
        Capsule()
         .fill(Color.gray)
       .frame(width: 80, height: 5)
            .padding(.vertical)
        Spacer()
        Text("""
            This area is for parents only.
            Please press the numbers shown, in order.
            """)
            .padding()
            .font(.system(size: 20))
            .multilineTextAlignment(.center)
            .frame(width: 400)
        Spacer()
        HStack 
            Text(tInput1)
                .font(.system(size: 30))
                .frame(width: 40, height: 40, alignment: .center)
                .overlay(
                        RoundedRectangle(cornerRadius: 16)
                            .stroke(Color.black, lineWidth: 2)
                    )
                .multilineTextAlignment(.center)
                
            Text(tInput2)
                .font(.system(size: 30))
                .frame(width: 40, height: 40, alignment: .center)
                .overlay(
                        RoundedRectangle(cornerRadius: 16)
                            .stroke(Color.black, lineWidth: 2)
                    )
                .multilineTextAlignment(.center)
            
            Text(tInput3)
                .font(.system(size: 30))
                .frame(width: 40, height: 40, alignment: .center)
                .overlay(
                        RoundedRectangle(cornerRadius: 16)
                            .stroke(Color.black, lineWidth: 2)
                    )
                .multilineTextAlignment(.center)
        
        .padding()
        Spacer()
            HStack 
                Group 

                    Button(action: 
                       pressedN = "0"
                        numbersPressed()
                    ) 
                        Text("0")
                            .font(.system(size: 20))
                                            .fontWeight(.heavy)
                                            .foregroundColor(Color.blue)
                                            .multilineTextAlignment(.center)
                                            .padding(20.0)
                                            .overlay(
                                                    RoundedRectangle(cornerRadius: 16)
                                                        .stroke(Color.blue, lineWidth: 4)
                                                )
                            
                    
                    Button(action: 
                        pressedN = "1"
                        numbersPressed()
                    ) 
        Text("1")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
            
         
                    Button(action: 
                        pressedN = "2"
                        numbersPressed()
                    ) 
        Text("2")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
                    
                    Button(action: 
                        pressedN = "3"
                        numbersPressed()
                    ) 
        Text("3")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
                    
                    Button(action: 
                        pressedN = "4"
                        numbersPressed()
                    ) 
        Text("4")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
                    
            
        
        HStack 
            Group 
                Button(action: 
                    pressedN = "5"
                    numbersPressed()
                ) 
        Text("5")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
                
                Button(action: 
                    pressedN = "6"
                    numbersPressed()
                ) 
        Text("6")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
                
                Button(action: 
                    pressedN = "7"
                    numbersPressed()
                ) 
        Text("7")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
                
                Button(action: 
                    pressedN = "8"
                    numbersPressed()
                ) 
        Text("8")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
                
                Button(action: 
                    pressedN = "9"
                    numbersPressed()
                ) 
        Text("9")
            .font(.system(size: 20))
            .fontWeight(.heavy)
            .foregroundColor(Color.blue)
            .multilineTextAlignment(.center)
            .padding(20.0)
            .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(Color.blue, lineWidth: 4)
                )
                
                
            
        Spacer()
        
    
    .opacity(hiddenOpp)
    .onAppear() 
       setNums()
        
    


func setNums() 
    for _ in 0..<3 
    randN = Int.random(in: 0..<10)
        npP = npP + "\(randN)"
    print("Tony numbers are \(npP)")

    let char1 = npP[npP.index(npP.startIndex, offsetBy: 0)]
        tInput1 = "\(char1)"
    
   let char2 = npP[npP.index(npP.startIndex, offsetBy: 1)]
        tInput2 = "\(char2)"
    
    let char3 = npP[npP.index(npP.startIndex, offsetBy: 2)]
        tInput3 = "\(char3)"


func numbersPressed()
    if nP == "" 
        nP = pressedN
        print("Tony numbers are \(nP)")
    else 
        if nP.count == 1 
        nP = nP + pressedN
            print("Tony numbers are \(nP)")
    else 
        nP = nP + pressedN
        print("Tony numbers are \(nP)")
        if nP == "\(npP)" 
            npP = ""
            nP = ""
            print("Tony Corect numbers")
                hiddenOpp = 0.0
        else 
            self.presentationMode.wrappedValue.dismiss()
           print("Tony Incorect numbers")
            npP = ""
            nP = ""
            setNums()
        
    





【讨论】:

【参考方案7】:

这是我今天做的一个。我还没有得到苹果的回复。它已通过应用审核

import SwiftUI

struct Triangle: Shape 
    func path(in rect: CGRect) -> Path 
        var path = Path()

        path.move(to: CGPoint(x: rect.midX, y: rect.minY))
        path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))

        return path
    


struct ParentalGateView: View 

    // MARK: - Properties
    var onClose: (() -> Void)?
    var onCancel: (() -> Void)?
    @State private var circleTapped: Bool = false

    // MARK: - UI Layout
    var body: some View 
        VStack(alignment: .center, spacing: 60) 
            HStack 
                Image(systemName: "arrow.left")
                    .resizable()
                    .frame(width: 40, height: 33)
                    .foregroundColor(.red)
                    .onTapGesture 
                        HapticEngine.select.selectionChanged()
                        onCancel?()
                    
                Spacer()
            .padding([.leading, .top], 24)

            Text("Ask your parents")
                .font(.largeTitle)
                .fontWeight(.black)
                .foregroundColor(.blue)

            Spacer()
            HStack(spacing: 130) 
                Button("") 
                .background(Triangle()
                                .foregroundColor(.green)
                                .frame(width: 100, height: 100)
                                .onTapGesture  !circleTapped ? onCancel?() : print("") 
                                .onLongPressGesture  circleTapped ? onClose?() : onCancel?() )

                Button("") 
                .background(Rectangle()
                                .foregroundColor(.blue)
                                .frame(width: 100, height: 100))
                                .onTapGesture  onCancel?() 

                Button("") 
                .background(Circle()
                                .foregroundColor(circleTapped ? .green : .yellow)
                                .frame(width: 100, height: 100)
                                .animation(.easeInOut)
                                .onTapGesture(count: 4)  circleTapped = true )
            .padding()

            Text("Tap inside the circle until the circle turns green, then hold triangle.")
                .multilineTextAlignment(.center)
                .font(.headline)
                .padding([.leading, .trailing], 16)
                .foregroundColor(.orange)
            Spacer()
        
    


struct ParentalGateView_Previews: PreviewProvider 
    static var previews: some View 
        ParentalGateView()
            .preferredColorScheme(.dark)
    


【讨论】:

以上是关于如何在儿童版块中为 iOS 应用设置家长门的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS中为整个应用程序设置隐藏状态栏?

如何在 iOS 应用程序中为 iFrame 设置透明背景?

如何在同一应用程序中为 iOS 6 和 iOS 7 版本设置默认启动图像

我们如何在 iOS 9 中为整个应用程序设置状态栏的 Light Content 样式?

儿童智能机器人如何破发展难关?卡努比实用与互动才是关键

如何在 iOS 10 中为推送通知设置徽章计数?