Ios 是否在运行时获取资源调配配置文件的过期日期?

Ios 是否在运行时获取资源调配配置文件的过期日期?,ios,notifications,runtime,provisioning,profiles,Ios,Notifications,Runtime,Provisioning,Profiles,我有一个应用程序,我经常通过临时分发方法分发给测试人员。这些测试人员中的一些人“很在行”,对资源调配配置文件和季度到期时间有足够的了解,可以(如果我忘了的话)给我一个提示,让我重新构建一个新版本供他们测试 然而,一些用户似乎总是到了它停止运行,然后抱怨的地步——尽管他们可能会拒绝iOS级别的提醒 我的问题是,我是否可以在运行时通过编程获得过期日期,并执行我自己的“应用程序内”警报或系统通知,以提醒他们下载新版本?您正在寻找类似 "<key>ExpirationDate</key

我有一个应用程序,我经常通过临时分发方法分发给测试人员。这些测试人员中的一些人“很在行”,对资源调配配置文件和季度到期时间有足够的了解,可以(如果我忘了的话)给我一个提示,让我重新构建一个新版本供他们测试

然而,一些用户似乎总是到了它停止运行,然后抱怨的地步——尽管他们可能会拒绝iOS级别的提醒


我的问题是,我是否可以在运行时通过编程获得过期日期,并执行我自己的“应用程序内”警报或系统通知,以提醒他们下载新版本?

您正在寻找类似

"<key>ExpirationDate</key><date>2014-12-06T00:26:10Z</date>" in [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]
[[NSBundle mainBundle]路径中的“ExpirationDate2014-12-06T00:26:10Z”用于资源:@“embedded”类型:@“mobileprovision”] 但要做到这一点并不容易!该代码可以改进,部分代码基于其他stackoverflow帖子。注意:另一个选项是加载项目plist之间的所有内容 和/或插入…一本词典。但既然我们已经在那里了,我们就只能手工找到兄弟姐妹了

- (NSString*) getExpiry{

    NSString *profilePath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
    // Check provisioning profile existence
    if (profilePath)
    {
        // Get hex representation
        NSData *profileData = [NSData dataWithContentsOfFile:profilePath];
        NSString *profileString = [NSString stringWithFormat:@"%@", profileData];

        // Remove brackets at beginning and end
        profileString = [profileString stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""];
        profileString = [profileString stringByReplacingCharactersInRange:NSMakeRange(profileString.length - 1, 1) withString:@""];

        // Remove spaces
        profileString = [profileString stringByReplacingOccurrencesOfString:@" " withString:@""];


        // Convert hex values to readable characters
        NSMutableString *profileText = [NSMutableString new];
        for (int i = 0; i < profileString.length; i += 2)
        {
            NSString *hexChar = [profileString substringWithRange:NSMakeRange(i, 2)];
            int value = 0;
            sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
            [profileText appendFormat:@"%c", (char)value];
        }

        // Remove whitespaces and new lines characters
        NSArray *profileWords = [profileText componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

        //There must be a better word to search through this as a structure! Need 'date' sibling to <key>ExpirationDate</key>, or use regex
        BOOL sibling = false;
        for (NSString* word in profileWords){
            if ([word isEqualToString:@"<key>ExpirationDate</key>"]){
                NSLog(@"Got to the key, now need the date!");
                sibling = true;
            }
            if (sibling && ([word rangeOfString:@"<date>"].location != NSNotFound)) {
                NSLog(@"Found it, you win!");
                NSLog(@"Expires: %@",word);
                return word;
            }
        }

    }

    return @"";
}
-(NSString*)getExpiry{
NSString*profilePath=[[NSBundle mainBundle]pathForResource:@“embedded”类型:@“mobileprovision”];
//检查配置文件是否存在
if(profilePath)
{
//获取十六进制表示
NSData*profileData=[NSData dataWithContentsOfFile:profilePath];
NSString*profileString=[NSString stringWithFormat:@“%@”,profileData];
//拆下开始和结束处的支架
profileString=[profileString StringByReplacingCharactersRange:NSMakeRange(0,1)和字符串@”“;
profileString=[profileString StringByReplacingCharactersRange:nsMakerRange(profileString.length-1,1)with string:@”“;
//删除空格
profileString=[profileString StringByReplacingOfString:@“with String:@]”发生率;
//将十六进制值转换为可读字符
NSMutableString*profileText=[NSMutableString新建];
对于(int i=0;i
Swift版本:

// Returns `nil` if it fails
private func getProvisioningProfileExpirationDateAsString() -> String? {
    guard
        let profilePath = Bundle.main.path(forResource: "embedded", ofType: "mobileprovision"),
        let profileData = try? Data(contentsOf: URL(fileURLWithPath: profilePath)),
        // Note: We use `NSString` instead of `String`, because it makes it easier working with regex, ranges, substring etc.
        let profileNSString = NSString(data: profileData, encoding: String.Encoding.ascii.rawValue)
        else {
        print("WARNING: Could not find or read `embedded.mobileprovision`. If running on Simulator, there are no provisioning profiles.")
        return nil
    }


    // NOTE: We have the `[\\W]*?` check to make sure that variations in number of tabs or new lines in the future does not influence the result.
    guard let regex = try? NSRegularExpression(pattern: "<key>ExpirationDate</key>[\\W]*?<date>(.*?)</date>", options: []) else {
        print("Warning: Could not create regex.")
        return nil
    }

    let regExMatches = regex.matches(in: profileNSString as String, options: [], range: NSRange(location: 0, length: profileNSString.length))

    // NOTE: range `0` corresponds to the full regex match, so to get the first capture group, we use range `1`
    guard let rangeOfCapturedGroupForDate = regExMatches.first?.range(at: 1) else {
        print("Warning: Could not find regex match or capture group.")
        return nil
    }

    let dateAsString = profileNSString.substring(with: rangeOfCapturedGroupForDate)
    return dateAsString
}
//如果失败,则返回'nil'
私有函数getProvisioningProfileExpirationDateAsString()->字符串?{
警卫
让profilePath=Bundle.main.path(forResource:“embedded”,类型为“mobileprovision”),
让profileData=try?Data(contentsOf:URL(fileURLWithPath:profilePath)),
//注意:我们使用'NSString'而不是'String',因为它使使用regex、ranges、substring等更容易。
让profileNSString=NSString(数据:profileData,编码:String.encoding.ascii.rawValue)
否则{
打印(“警告:无法找到或读取`embedded.mobileprovision`。如果在模拟器上运行,则没有配置文件。”)
归零
}
//注意:我们进行了“[\\W]*?”检查,以确保将来选项卡数或新行数的变化不会影响结果。
guard let regex=try?NSRegularExpression(模式:“ExpirationDate[\\W]*?(.*)”,选项:[])其他{
打印(“警告:无法创建正则表达式。”)
归零
}
让regExMatches=regex.matches(in:profileNSString作为字符串,选项:[],范围:NSRange(位置:0,长度:profileNSString.length))
//注意:范围“0”对应于完整的正则表达式匹配,因此要获得第一个捕获组,我们使用范围“1”`
guard let rangeOfCapturedGroupForDate=regExMatches.first?range(at:1)else{
打印(“警告:找不到正则表达式匹配或捕获组。”)
归零
}
让dateAsString=profileNSString.substring(带:rangeOfCapturedGroupForDate)
返回日期字符串
}

在iOS 13中,它不起作用。NSData的描述从

{0x30822755 06092a86 4886f70d 010702a0…889bfcbe ed768bac}

{length=…,bytes=0x30822755 06092a86 4886f70d 010702a0…889bfcbe ed768bac}

请尝试以下代码:

NSData *data = ....;
NSUInteger dataLength = [data length];
NSMutableString *string =[NSMutableString stringWithCapacity:dataLength*2];

const unsigned char *dataBytes = [data bytes];
for (NSInteger idx = 0; idx < dataLength; ++idx)
{
    [string appendFormat:@"%02x", dataBytes[idx]];
}
NSData*data=。。。。;
NSU整数数据长度=[数据长度];
NSMutableString*string=[NSMutableString stringWithCapacity:dataLength*2];
常量无符号字符*数据字节=[数据字节];
对于(NSInteger idx=0;idx
在iOS 13中,为了简化Ttnka的建议,您可以使用profileData。debugDescription创建profileString(从最初发布的Objective-C代码):


参考:

第一行的profilePath本身返回nil。我正在使用xcode 8.2.1,并将objective-c代码与swift一起使用。您是否在模拟器中运行该代码?它没有签名,因此在模拟器上运行时将没有embedded.mobileprovision文件。尝试在物理设备上运行代码(必须对代码进行签名并嵌入代码)。
NSString *profileString = [NSString stringWithFormat:@"%@", profileData.debugDescription];