Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 62 additions & 38 deletions DYYY.xm
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,7 @@ static BOOL DYYYShouldHandleSpeedFeatures(void) {

NSString *cacheKey = cityCode.length > 0 ? cityCode : regionCode;

// 优先级 0:查缓存
NSString *cachedLocation = [locationCache objectForKey:cacheKey];
if (cachedLocation) {
updateLabelWithLocation(label, cachedLocation);
Expand All @@ -1634,67 +1635,90 @@ static BOOL DYYYShouldHandleSpeedFeatures(void) {
return label;
}

// 优先级 1:根据 cityCode 查本地城市映射表
NSString *displayLocation = nil;

if (cityCode.length > 0) {
displayLocation = [CityManager.sharedInstance getCityNameWithCode:cityCode];
}

if (!displayLocation && regionCode.length > 0) {
displayLocation = [CityManager.sharedInstance getCountryNameWithCode:regionCode];
// 本地映射命中,直接返回
if (displayLocation) {
[locationCache setObject:displayLocation forKey:cacheKey];
updateLabelWithLocation(label, displayLocation);

NSString *ipScaleValue = [[NSUserDefaults standardUserDefaults] objectForKey:@"DYYYNicknameScale"];
if (ipScaleValue.length > 0) {
UIFont *originalFont = label.font;
CGFloat offset = DYYYGetFloat(@"DYYYIPLabelVerticalOffset");
if (offset > 0) {
label.transform = CGAffineTransformMakeTranslation(0, -offset);
} else {
label.transform = CGAffineTransformMakeTranslation(0, -3);
}
label.font = originalFont;
}
return label;
}

if (!displayLocation) {
@synchronized(inFlight) {
if ([inFlight containsObject:cityCode]) {
return label;
}
[inFlight addObject:cityCode];
// 优先级 2:通过 GeoNames API 查询(需要有 cityCode)
if (cityCode.length > 0) {
@synchronized(inFlight) {
if ([inFlight containsObject:cityCode]) {
return label;
}
[inFlight addObject:cityCode];
}

[CityManager fetchLocationWithGeonameId:cityCode completionHandler:^(NSDictionary *locationInfo, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
@synchronized(inFlight) {
[inFlight removeObject:cityCode];
}
__block NSString *capturedRegionCode = [regionCode copy];
[CityManager fetchLocationWithGeonameId:cityCode completionHandler:^(NSDictionary *locationInfo, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
@synchronized(inFlight) {
[inFlight removeObject:cityCode];
}

NSString *apiLocation = nil;
NSString *apiLocation = nil;

if (!error && locationInfo) {
NSString *cityName = locationInfo[@"adminName1"];
NSString *countryName = locationInfo[@"countryName"];
if (!error && locationInfo) {
NSString *cityName = locationInfo[@"adminName1"];
NSString *countryName = locationInfo[@"countryName"];

if (cityName && countryName) {
if ([cityName isEqualToString:countryName]) {
apiLocation = countryName;
} else {
apiLocation = [NSString stringWithFormat:@"%@ %@", countryName, cityName];
}
} else if (countryName) {
if (cityName && countryName) {
if ([cityName isEqualToString:countryName]) {
apiLocation = countryName;
} else if (cityName) {
apiLocation = cityName;
} else {
apiLocation = [NSString stringWithFormat:@"%@ %@", countryName, cityName];
}
} else if (countryName) {
apiLocation = countryName;
} else if (cityName) {
apiLocation = cityName;
}
}

if (apiLocation) {
[locationCache setObject:apiLocation forKey:cacheKey];
updateLabelWithLocation(label, apiLocation);
}
});
}];
// 优先级 3:API 失败/无结果时,根据 region 国家代码兜底
if (!apiLocation && capturedRegionCode.length > 0) {
apiLocation = [CityManager.sharedInstance getCountryNameWithCode:capturedRegionCode];
}

return label;
}
if (apiLocation) {
[locationCache setObject:apiLocation forKey:cacheKey];
updateLabelWithLocation(label, apiLocation);
} else {
updateLabelWithLocation(label, @"未知地区");
}
});
}];

return label;
}

if (!displayLocation && !cityCode && regionCode.length > 0) {
// 没有 cityCode,仅有 regionCode 时直接用 region 兜底
if (regionCode.length > 0) {
displayLocation = [CityManager.sharedInstance getCountryNameWithCode:regionCode];
}

if (!displayLocation) {
displayLocation = @"未知地区";
updateLabelWithLocation(label, displayLocation);
return label;
}

[locationCache setObject:displayLocation forKey:cacheKey];
Expand Down
119 changes: 87 additions & 32 deletions DYYYUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -442,16 +442,55 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
NSString *originalText = label.text ?: @"";
NSString *cityCode = model.cityCode;

if (cityCode.length == 0) {
// 获取 region 国家代码
NSString *regionCode = nil;
if ([model respondsToSelector:@selector(region)]) {
regionCode = [model performSelector:@selector(region)];
}

if (cityCode && ([cityCode isEqualToString:@"0"] || [cityCode integerValue] == 0)) {
cityCode = nil;
}

if (cityCode.length == 0 && regionCode.length == 0) {
return;
}

objc_setAssociatedObject(label, kCurrentIPRequestCityCodeKey, cityCode, OBJC_ASSOCIATION_COPY_NONATOMIC);
NSString *requestKey = cityCode.length > 0 ? cityCode : regionCode;
objc_setAssociatedObject(label, kCurrentIPRequestCityCodeKey, requestKey, OBJC_ASSOCIATION_COPY_NONATOMIC);

NSString *cityName = [CityManager.sharedInstance getCityNameWithCode:cityCode];
NSString *provinceName = [CityManager.sharedInstance getProvinceNameWithCode:cityCode];
// 优先级 1:根据 cityCode 查本地城市映射表
if (cityCode.length > 0) {
NSString *cityName = [CityManager.sharedInstance getCityNameWithCode:cityCode];
NSString *provinceName = [CityManager.sharedInstance getProvinceNameWithCode:cityCode];

if (cityName.length > 0) {
// 本地映射命中,直接显示
if (![originalText containsString:cityName]) {
BOOL isDirectCity = [provinceName isEqualToString:cityName] || ([cityCode hasPrefix:@"11"] || [cityCode hasPrefix:@"12"] || [cityCode hasPrefix:@"31"] || [cityCode hasPrefix:@"50"]);
if (!model.ipAttribution) {
if (isDirectCity) {
label.text = [NSString stringWithFormat:@"%@ IP属地:%@", originalText, cityName];
} else {
label.text = [NSString stringWithFormat:@"%@ IP属地:%@ %@", originalText, provinceName, cityName];
}
} else {
BOOL containsProvince = provinceName.length > 0 && [originalText containsString:provinceName];
BOOL containsCity = [originalText containsString:cityName];
if (containsProvince && !isDirectCity && !containsCity) {
label.text = [NSString stringWithFormat:@"%@ %@", originalText, cityName];
} else if (isDirectCity && !containsCity) {
label.text = [NSString stringWithFormat:@"%@ IP属地:%@", originalText, cityName];
}
}
[DYYYUtils applyColorSettingsToLabel:label colorHexString:colorHexString];
}
return;
}
}

if (!cityName || cityName.length == 0) {
// 优先级 2:通过 GeoNames API 查询(需要有 cityCode)
if (cityCode.length > 0) {
NSString *cacheKey = cityCode;
static NSCache *geoNamesCache = nil;
static dispatch_once_t onceToken;
Expand All @@ -461,7 +500,7 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
geoNamesCache.countLimit = 1000;
});

// 1 & 2. 查内存和磁盘缓存
// 查内存和磁盘缓存
NSDictionary *cachedData = [geoNamesCache objectForKey:cacheKey];
if (!cachedData) {
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
Expand All @@ -479,7 +518,6 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
}
}

// 3. 处理缓存数据或发起网络请求
if (cachedData) {
NSString *countryName = cachedData[@"countryName"];
NSString *adminName1 = cachedData[@"adminName1"];
Expand All @@ -498,22 +536,32 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
displayLocation = localName;
}

// API 缓存结果仍为"未知"时,用 region 兜底
if (displayLocation.length == 0 || [displayLocation isEqualToString:@"未知"]) {
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
if (fallbackLocation.length > 0) {
displayLocation = fallbackLocation;
if (regionCode.length > 0) {
NSString *regionName = [CityManager.sharedInstance getCountryNameWithCode:regionCode];
if (regionName.length > 0) {
displayLocation = regionName;
}
}
if (displayLocation.length == 0 || [displayLocation isEqualToString:@"未知"]) {
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
if (fallbackLocation.length > 0) {
displayLocation = fallbackLocation;
}
}
}

dispatch_async(dispatch_get_main_queue(), ^{
NSString *currentRequestCode = objc_getAssociatedObject(label, kCurrentIPRequestCityCodeKey);
if (![currentRequestCode isEqualToString:cityCode]) {
if (![currentRequestCode isEqualToString:requestKey]) {
return;
}

DYYYApplyDisplayLocationToLabel(label, displayLocation, colorHexString);
});
} else {
__block NSString *capturedRegionCode = [regionCode copy];
[CityManager fetchLocationWithGeonameId:cityCode
completionHandler:^(NSDictionary *locationInfo, NSError *error) {
__block NSString *displayLocation = @"未知";
Expand All @@ -523,6 +571,15 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
displayLocation = [DYYYUtils displayLocationForGeoNamesError:error model:model];
} else {
NSLog(@"[DYYY] GeoNames fetch failed: %@", error.localizedDescription);
}
// 优先级 3:API 失败时用 region 兜底
if ([displayLocation isEqualToString:@"未知"] && capturedRegionCode.length > 0) {
NSString *regionName = [CityManager.sharedInstance getCountryNameWithCode:capturedRegionCode];
if (regionName.length > 0) {
displayLocation = regionName;
}
}
if ([displayLocation isEqualToString:@"未知"]) {
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
if (fallbackLocation.length > 0) {
displayLocation = fallbackLocation;
Expand All @@ -548,10 +605,19 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode
shouldCacheLocation = YES;
}

// API 返回空数据时用 region 兜底
if (displayLocation.length == 0 || [displayLocation isEqualToString:@"未知"]) {
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
if (fallbackLocation.length > 0) {
displayLocation = fallbackLocation;
if (capturedRegionCode.length > 0) {
NSString *regionName = [CityManager.sharedInstance getCountryNameWithCode:capturedRegionCode];
if (regionName.length > 0) {
displayLocation = regionName;
}
}
if (displayLocation.length == 0 || [displayLocation isEqualToString:@"未知"]) {
NSString *fallbackLocation = [DYYYUtils fallbackLocationFromIPAttribution:model];
if (fallbackLocation.length > 0) {
displayLocation = fallbackLocation;
}
}
shouldCacheLocation = NO;
}
Expand All @@ -567,34 +633,23 @@ + (void)processAndApplyIPLocationToLabel:(UILabel *)label forModel:(AWEAwemeMode

dispatch_async(dispatch_get_main_queue(), ^{
NSString *currentRequestCode = objc_getAssociatedObject(label, kCurrentIPRequestCityCodeKey);
if (![currentRequestCode isEqualToString:cityCode]) {
if (![currentRequestCode isEqualToString:requestKey]) {
return;
}

DYYYApplyDisplayLocationToLabel(label, displayLocation, colorHexString);
});
}];
}
return;
}

else if (![originalText containsString:cityName]) {
BOOL isDirectCity = [provinceName isEqualToString:cityName] || ([cityCode hasPrefix:@"11"] || [cityCode hasPrefix:@"12"] || [cityCode hasPrefix:@"31"] || [cityCode hasPrefix:@"50"]);
if (!model.ipAttribution) {
if (isDirectCity) {
label.text = [NSString stringWithFormat:@"%@ IP属地:%@", originalText, cityName];
} else {
label.text = [NSString stringWithFormat:@"%@ IP属地:%@ %@", originalText, provinceName, cityName];
}
} else {
BOOL containsProvince = [originalText containsString:provinceName];
BOOL containsCity = [originalText containsString:cityName];
if (containsProvince && !isDirectCity && !containsCity) {
label.text = [NSString stringWithFormat:@"%@ %@", originalText, cityName];
} else if (isDirectCity && !containsCity) {
label.text = [NSString stringWithFormat:@"%@ IP属地:%@", originalText, cityName];
}
// 优先级 3:没有 cityCode,仅有 regionCode 时直接用 region 兜底
if (regionCode.length > 0) {
NSString *regionName = [CityManager.sharedInstance getCountryNameWithCode:regionCode];
if (regionName.length > 0) {
DYYYApplyDisplayLocationToLabel(label, regionName, colorHexString);
}
[DYYYUtils applyColorSettingsToLabel:label colorHexString:colorHexString];
}
}

Expand Down
Loading