swift3日期到数据,数据转换日期

时间:2017-07-13 09:53:18

标签: ios objective-c swift swift3

我正在努力将目标c中创建的代码更改为swift3 我想将下面的代码更改为使用目标c创建的swift3代码。

目标c NSDate到NSData代码:

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSDayCalendarUnit |NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:[NSDate date]];

NSInteger year = components.year;
NSMutableData *yearData = [[NSMutableData alloc] initWithBytes:&year length:sizeof(year)];
int year1 = *(int *)[[yearData subdataWithRange:NSMakeRange(0, 1)] bytes];
int year2 = *(int *)[[yearData subdataWithRange:NSMakeRange(1, 1)] bytes];
int month = components.month;
int day = components.day;
int hour = components.hour;
int min = components.minute;
int second = components.second;

char bytes[7];
bytes[0] = year1;
bytes[1] = year2;
bytes[2] = month;
bytes[3] = day;
bytes[4] = hour;
bytes[5] = min;
bytes[6] = second;
NSData *data = [[NSData alloc] initWithBytes:&bytes length:sizeof(bytes)];

目标c NSData到NSDate代码:

NSData *date = [[NSData alloc] initWithData:characteristic.value];
int year = *(int *)[[date subdataWithRange:NSMakeRange(0, 2)] bytes];
int month = *(int *)[[date subdataWithRange:NSMakeRange(2, 1)] bytes];
int day = *(int *)[[date subdataWithRange:NSMakeRange(3, 1)] bytes];
int hour = *(int *)[[date subdataWithRange:NSMakeRange(4, 1)] bytes];
int minutes = *(int *)[[date subdataWithRange:NSMakeRange(5, 1)] bytes];
int seconds = *(int *)[[date subdataWithRange:NSMakeRange(6, 1)] bytes];

NSLog(@"year %d month %d day %d hour %d minutes %d second %d", year, month, day, hour, minutes, seconds); //year 2017 month 7 day 13 hour 16 minutes 8 second 2

NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:year];
[components setMonth:month];
[components setDay:day];
[components setHour:hour];
[components setMinute:minutes];
[components setSecond:seconds];
NSCalendar *calendar = [NSCalendar currentCalendar];
self.time = [calendar dateFromComponents:components];

Swift Date to Data code:

let cal = Calendar(identifier: .gregorian)
var comp = cal.dateComponents([.day,.month,.year,.hour,.minute,.second], from: Date())
var year = comp.year
let yearData:Data = Data(bytes: &year, count: MemoryLayout.size(ofValue: year))
let year1:Data = yearData.subdata(in: 0..<1)
let year2:Data = yearData.subdata(in: 1..<2)
let settingArray = [UInt8]([
      UInt8(year1[0])
    , UInt8(year2[0])
    , UInt8(comp.month!)
    , UInt8(comp.day!)
    , UInt8(comp.hour!)
    , UInt8(comp.minute!)
    , UInt8(comp.second!)
])
let settingData:Data = Data(bytes: settingArray, count: MemoryLayout.size(ofValue: settingArray))

Swift Data to Date代码:

var yearVal:UInt8 = 0
let year = characteristic.value?.subdata(in: 0..<2)
year?.copyBytes(to: &yearVal, count: MemoryLayout.size(ofValue: year))
var month = characteristic.value?.subdata(in: 2..<3)
var day = characteristic.value?.subdata(in: 3..<4)
var hour = characteristic.value?.subdata(in: 4..<5)
var minutes = characteristic.value?.subdata(in: 5..<6)
var seconds = characteristic.value?.subdata(in: 6..<7)
print("year = \(yearVal), month = \(Int((month?[0])!)), day = \(Int((day?[0])!)), hour = \(Int((hour?[0])!)), minutes = \(Int((minutes?[0])!)), seconds = \(Int((seconds?[0])!))") // year = 225, month = 7, day = 13, hour = 15, minutes = 56, seconds = 56

修改let year = characteristic.value?.subdata(in: 0..<2)部分时,转化价值应为2017。但是,仅输出225个值。我不知道如何解决这个问题。

请帮帮我。

2 个答案:

答案 0 :(得分:1)

你很幸运,你的Objective-C代码在读取未分配的内存并忽略端序问题时起作用。

考虑一下:

int month = *(int *)[[date subdataWithRange:NSMakeRange(2, 1)] bytes];

在这里,您将获取指向单个字节的指针,将其转换为指向4个字节(int上的大小)的指针,然后读取4个字节并将其存储在month中。 幸运,您读取的额外三个字节恰好为零。

然后是endian问题,不同的cpu架构在内存中以不同的顺序存储多字节值。 little-endian架构首先存储最低有效字节,最重要的是big-endian字节。

E.g。 4字节整数0xDEADBEEF作为字节序列EFBEADDE存储在小端机器上,并作为{{1 }},DEADBE在big-endian上。就上面的EF值而言,这意味着如果字节为month,那么当您读取这4个字节时,您可能会返回整数06(并且只有当这些额外的字节是零)。

对于0x06000000情况,您可以加载该字节,然后转换为整数:

month

将年份转换为两个字节时,您需要经过漫长的过程:

int month = (int *)(*(Byte *)[[date subdataWithRange:NSMakeRange(2, 1)] bytes]);

这会将一个整数转换为NSMutableData *yearData = [[NSMutableData alloc] initWithBytes:&year length:sizeof(year)]; int year1 = *(int *)[[yearData subdataWithRange:NSMakeRange(0, 1)] bytes]; int year2 = *(int *)[[yearData subdataWithRange:NSMakeRange(1, 1)] bytes]; ,生成更多NSData个值,每个值包含1个字节,然后为每个加载4个字节 - 与上面相同的问题,但在这种情况下,您将只有在NSData数组中存储1个字节,如果额外的字节是垃圾,则无关紧要。

这个过程很复杂,你最好坚持使用整数运算来获得这两个值。您可以使用除法和余数运算或逐位移位和掩码运算来获取各个字节。

E.g。首先使用小数来演示:

bytes

要提取字节,只需更改除数:

int year = 2017;
int firstDigit = year % 10;           // the remainder of year / 10 => 7
int secondDigit = (year / 10) % 10;   // 1
int thirdDigit = (year / 100) % 10;   // 0
int fourthDigit = (year / 1000) % 10; // 2

最后,您可以使用逐位移位和屏蔽:

int year = 2017;                 // = 0x7E1
int loByte = year % 256;         // = 0xE1
int hiByte = (year / 256) % 256; // = 0x7

使用逐位运算会使字节分割更加明显,但除法和余数会达到相同的结果。

对于Objective-C代码,这一切意味着什么?那么你可以写出两种方法中的第二种:

int year = 2017;                 // = 0x7E1
int loByte = year & 0xFF;        // = 0xE1
int hiByte = (year >> 8) & 0xFF; // = 0x7

这不太复杂,不会读取随机内存,并且更容易转换为Swift

按照相同的方法,这是你在Swift中的第一个方法:

+ (NSDate *) dataToDate:(NSData *)data
{
   NSDateComponents *components = [[NSDateComponents alloc] init];
   const Byte *bytes = data.bytes;
   components.year = (NSInteger)bytes[0] | ((NSInteger)bytes[1] << 8); // reassemble 2-byte value
   components.month = (NSInteger)bytes[2];
   components.day = (NSInteger)bytes[3];
   components.hour = (NSInteger)bytes[4];
   components.minute = (NSInteger)bytes[5];
   components.second = (NSInteger)bytes[6];

   NSCalendar *calendar = [NSCalendar currentCalendar];

   return[calendar dateFromComponents:components];
}

最后,您可以将Swift欲望中的func toData(_ date : Date) -> Data { let cal = Calendar(identifier: .gregorian) let comp = cal.dateComponents([.day,.month,.year,.hour,.minute,.second], from: date) let year = comp.year! let yearLo = UInt8(year & 0xFF) // mask to avoid overflow error on conversion to UInt8 let yearHi = UInt8(year >> 8) let settingArray = [UInt8]([ yearLo , yearHi , UInt8(comp.month!) , UInt8(comp.day!) , UInt8(comp.hour!) , UInt8(comp.minute!) , UInt8(comp.second!) ]) return Data(bytes: settingArray) } 类型索引为数组,因此上面的Objective-C行:

Data

来自调用components.month = (NSInteger)bytes[2]; 的{​​{1}}的{​​{1}}可以直接在Swift中编写:

bytes

其中NSDatabytes值。

上述方法无法解决您实际遇到的问题,因为它避免了将数据值拆分为位并尝试从中获取额外值的麻烦 - 只需索引字节并使用强制转换进行转换。

您需要的其余代码留作练习!

HTH

答案 1 :(得分:0)

你取得年份值为UInt8,其范围只有0-255,所以使用UInt32

var yearVal: UInt32 = 0
(year as! NSData).getBytes(&yearVal, length: MemoryLayout.size(ofValue: year))