我正在努力将目标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
个值。我不知道如何解决这个问题。
请帮帮我。
答案 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
作为字节序列EF
,BE
,AD
,DE
存储在小端机器上,并作为{{1 }},DE
,AD
,BE
在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
其中NSData
是bytes
值。
上述方法无法解决您实际遇到的问题,因为它避免了将数据值拆分为位并尝试从中获取额外值的麻烦 - 只需索引字节并使用强制转换进行转换。
您需要的其余代码留作练习!
HTH
答案 1 :(得分:0)
你取得年份值为UInt8,其范围只有0-255,所以使用UInt32
var yearVal: UInt32 = 0
(year as! NSData).getBytes(&yearVal, length: MemoryLayout.size(ofValue: year))