iOS 스킨 케 어 기능 을 위 한 간단 한 처리 프레임 워 크(소스 코드)
스킨 케 어 기능 은 앱 개발 과정 에서 만 나 는 비교적 많은 장면 으로 더 나 은 사용자 체험 을 제공 하기 위해 많은 앱 이 사용자 에 게 테 마 를 전환 하 는 기능 을 제공한다.테마 색상 관리 와 관련 된 절차 는
색상 설정
사용 색상
UI 요소 의 동적 변경 능력동적 수정 설정
테마 패키지 관리
어떻게 실시 합 니까?
최적화
효 과 는 다음 과 같 습 니 다:
DEMO 코드:https://gitee.com/dhar/iosdemos/tree/master/YTThemeManagerDemo
색상 설정
다양한 설정 과 관련 되 어 있 기 때문에 코드 로 색상 실천 과 유 지 를 정의 하 는 것 이 어렵 습 니 다.적당 한 방안 은-색상 설정 은 설정 파일 형식 으로 가 져 옵 니 다.설정 파일 은 변환 절 차 를 거 쳐 최종 적 으로 코드 등급 의 설정 을 형성 하고 전역 적 인 방식 으로 각 모듈 에 제공 합 니 다.여 기 는 하나의 색상 관리자 의 개념 과 관련 됩 니 다.일반적으로 이 는 하나의 사례 대상 으로 전체 방문 인 터 페 이 스 를 제공 합 니 다.같은 APP 에서 서로 다른 모듈 에 서로 다른 테마 색상 설정 을 저장 하고 서로 다른 등급 에서 도 서로 다른 테마 색상 설정 이 존재 할 수 있 습 니 다.등급 간 의 설정 차이 와 관련 되 기 때문에 색상 의 설정 은 하나의 등급 의 개념 을 도입 해 야 합 니 다.보통 고 층 색상 의 설정 등급 은 낮은 등급 보다 높 습 니 다.같은 설정 이 존재 합 니 다.높 은 등급 의 설정 은 낮은 등급 의 설정 을 덮어 씁 니 다.
우리 가 사용 하 는 색상 설정 의 파일 형 은 아래 와 같 습 니 다.왜 json 파일 의 colorkey 아래 에 있 습 니까?미래의 확장 성 을 고려 하기 위해 서 입 니 다.만약 에 서로 다른 주제 가 사이즈 값 의 차별 화 와 관련 될 경우 dimensionskey 를 추가 하여 확장 설정 을 할 수 있 습 니 다.
{
"color": {
"Black_A":"323232",
"Black_AT":"323232",
"Black_B":"888888",
"Black_BT":"888888",
"White_A":"ffffff",
"White_AT":"ffffff",
"White_AN":"ffffff",
"Red_A":"ff87a0",
"Red_AT":"ff87a0",
"Red_B":"ff5073",
"Red_BT":"ff5073",
"Colour_A":"377ce4",
"Colour_B":"6aaafa",
"Colour_C":"ff8c55",
"Colour_D":"ffa200",
"Colour_E":"c4a27a",
}
}
이상 의 설정 이 있 습 니 다.색상 설정 작업 은 주로 이 프로필 을 분석 하고 설정 을 하나의 단일 대상 에 저장 하면 됩 니 다.이 부분의 주요 절 차 는 다음 과 같 습 니 다.설정 파일 클래스 표 는 등급 에 따라 정렬 됩 니 다
- (void)loadConfigWithFileName:(NSString *)fileName level:(NSInteger)level {
if (fileName.length == 0) {
return;
}
pthread_rwlock_wrlock(&_rwlock);
__block BOOL finded = NO;
[self.configFileQueue enumerateObjectsUsingBlock:^(YTThemeConfigFile *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
if ([obj.fileName isEqualToString:fileName]) {
finded = YES;
*stop = YES;
}
}];
if (!finded) {
//
YTThemeConfigFile *file = [[YTThemeConfigFile alloc] init];
file.fileName = fileName;
file.level = level;
[self.configFileQueue addObject:file];
//
[self.configFileQueue sortUsingComparator:^NSComparisonResult(YTThemeConfigFile *_Nonnull obj1, YTThemeConfigFile *_Nonnull obj2) {
if (obj1.level > obj2.level) {
return NSOrderedDescending;
}
return NSOrderedAscending;
}];
[self setupConfigFilesContainDefault:YES];
}
pthread_rwlock_unlock(&_rwlock);
}
- (void)setupConfigFilesContainDefault:(BOOL)containDefault {
NSMutableDictionary *defaultColorDict = nil, *currentColorDict = nil;
//
if (containDefault) {
defaultColorDict = [NSMutableDictionary dictionary];
[self loadConfigDataWithColorMap:defaultColorDict valueMap:nil isDefault:YES];
self.defaultColorMap = defaultColorDict;
}
//
if (_themePath.length > 0) {
currentColorDict = [NSMutableDictionary dictionary];
[self loadConfigDataWithColorMap:currentColorDict valueMap:nil isDefault:NO];
self.currentColorMap = currentColorDict;
}
//
[self notifyThemeDidChange];
}
- (void)notifyThemeDidChange {
NSArray *allActionObjects = self.actionMap.objectEnumerator.allObjects;
for (YTThemeAction *action in allActionObjects) {
[action notifyThemeDidChange];
}
}
- (void)loadConfigDataWithColorMap:(NSMutableDictionary *)colorMap valueMap:(NSMutableDictionary *)valueMap isDefault:(BOOL)isDefault {
// , ,
[self.configFileQueue enumerateObjectsUsingBlock:^(YTThemeConfigFile *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
NSDictionary *dict = nil;
if (isDefault) {
dict = obj.defaultDict;
} else {
dict = obj.currentDict;
}
if (dict.count > 0) {
[self loadThemeColorTo:colorMap from:dict]; // color colorMap
}
}];
}
- (void)loadThemeColorTo:(NSMutableDictionary *)dictionary from:(NSDictionary *)from {
NSDictionary<NSString *, NSString *> *colors = from[@"color"];
[colors enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, NSString *_Nonnull obj, BOOL *_Nonnull stop) {
// UIColor
UIColor *color = [UIColor yt_nullcolorWithHexString:obj];
if (color) {
[dictionary setObject:color forKey:key];
} else {
[dictionary setObject:obj forKey:key];
}
}];
}
관리자 가 처리 설정 을 처리 하 는 동시에 외부 인 터 페 이 스 를 클 라 이언 트 에 노출 시 켜 서로 다른 주제 에 대응 하 는 색상 값,이미지 자원,사이즈 정보 등 주제 와 관련 된 정 보 를 얻 을 수 있 도록 해 야 합 니 다.예 를 들 어 저 희 는 colorForKey 방법 을 제공 하여 서로 다른 주제 에서 같은 key 에 대응 하 는 색상 값 을 얻 습 니 다.색상 값 을 얻 는 대략적인 절 차 는 다음 과 같 습 니 다.현재 테마 설정 에서 가 져 오기기본 테마 설정 에서 가 져 오기
/**
*/
- (UIColor *)colorForKey:(NSString *)key {
pthread_rwlock_rdlock(&_rwlock);
UIColor *color = [self colorForKey:key isReserveKey:NO redirectCount:0];
pthread_rwlock_unlock(&_rwlock);
return color;
}
- (UIColor *)colorForKey:(NSString *)key isReserveKey:(BOOL)isReserveKey redirectCount:(NSInteger)redirectCount {
if (key == nil) {
return nil;
}
///
id colorObj = [_currentColorMap objectForKey:key];
if (colorObj == nil) {
colorObj = [_defaultColorMap objectForKey:key];
}
if (isReserveKey && colorObj == nil) {
return nil;
}
/// key
if (colorObj == nil) {
NSString *reserveKey = [_reserveKeyMap objectForKey:key];
if (reserveKey) {
colorObj = [self colorForKey:reserveKey isReserveKey:YES redirectCount:redirectCount];
}
}
/// key color
if (colorObj == nil) {
colorObj = [UIColor yt_colorWithHexString:key];
}
if ([colorObj isKindOfClass:[UIColor class]]) {
/// key color colorDict
// :"Red_A":"Red_B",
if (redirectCount > 0 || isReserveKey) {
[_currentColorMap ?: _defaultColorMap setObject:colorObj forKey:key];
}
return colorObj;
} else {
if (redirectCount < 3) { //
return [self colorForKey:colorObj isReserveKey:NO redirectCount:redirectCount + 1];
} else {
return [UIColor blackColor];
}
}
}
색상 사용색상 의 사용 도 관리자 의 편 의 를 위해 색상 매크로 를 정의 하여 클 라 이언 트 에 게 제공 합 니 다.
#define YTThemeColor(key) ([[YTThemeManager sharedInstance] colorForKey:key])
클 라 이언 트 가 사용 하 는 코드 는 다음 과 같 습 니 다.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 200, 40)];
label.text = @"Text";
label.textColor = YTThemeColor(kCK_Red_A);
label.backgroundColor = YTThemeColor(kCK_Black_H);
[self.view addSubview:label];
또한,색상 설정 키 는 문자열 형식 이기 때문에 문자열 상수 를 직접 사용 하 는 것 은 좋 은 방법 이 아니 므 로 해당 하 는 문자열 을 매크로 로 정의 하 는 것 이 좋 은 방법 입 니 다.첫 번 째 는 사용 하기 편리 하고 코드 알림 을 사용 할 수 있 습 니 다.두 번 째 는 실수 가 쉽 지 않 습 니 다.특히 긴 문자열 입 니 다.세 번 째 도 어느 정도 효율 을 높 일 수 있다.YTColorDefine 클래스 의 매크로 정의
// .h
///Black
FOUNDATION_EXTERN NSString *kCK_Black_A;
FOUNDATION_EXTERN NSString *kCK_Black_AT;
FOUNDATION_EXTERN NSString *kCK_Black_B;
FOUNDATION_EXTERN NSString *kCK_Black_BT;
// .m
NSString *kCK_Black_A = @"Black_A";
NSString *kCK_Black_AT = @"Black_AT";
NSString *kCK_Black_B = @"Black_B";
NSString *kCK_Black_BT = @"Black_BT";
테마 패키지 관리실제 착지 항목 에서 테마 패키지 관리 와 관련 된 사항 은 테마 패키지 다운로드 와 압축 해제,동적 로드 테마 패키지 등 내용 을 포함 합 니 다.마지막 단 계 는 테마 프로필 이 있 는 설정 경 로 를 바 꾸 는 것 입 니 다.프 리 젠 테 이 션 의 편 의 를 위해 서로 다른 테마 자원 을 bundle 의 특정한 폴 더 에 두 겠 습 니 다.관리자 의 테마 경로 설정 을 전환 하여 테마 전환 효 과 를 얻 습 니 다.동적 다운로드 로 테 마 를 바 꾸 는 절차 와 같 습 니 다.
관리 자 는 테마 설정 의 설정 경 로 를 설정 하 는 방법 을 제공 합 니 다.이 방법 에서 설정 경 로 를 바 꾸 는 동시에 설정 을 다시 불 러 오 면 됩 니 다.코드 는 다음 과 같 습 니 다.
/**
@param themePath
*/
- (void)setupThemePath:(NSString *)themePath {
pthread_rwlock_wrlock(&_rwlock);
_themePath = [themePath copy];
self.currentColorMap = nil;
if ([_themePath.lowercaseString isEqualToString:[[NSBundle mainBundle] resourcePath].lowercaseString]) {
_themePath = nil;
}
self.currentThemePath = _themePath;
for (int i = 0; i < self.configFileQueue.count; i++) {
YTThemeConfigFile *obj = [self.configFileQueue objectAtIndex:i];
[obj resetCurrentDict];
}
[self setupConfigFilesContainDefault:NO];
pthread_rwlock_unlock(&_rwlock);
}
어떻게 실시 합 니까?이상 의 절 차 는 iOS 플랫폼 아래 의 기술 솔 루 션 과 관련 되 고 실제 실천 과정 에서 안 드 로 이 드 플랫폼,웹 페이지,UI 에서 그림 을 표시 하 는 것 과 관련 될 수 있 습 니 다.이런 것들 은 통일 적 으로 처리 해 야 각 부분 에서 일치 하 는 체험 을 할 수 있 습 니 다.첫 번 째 단 계 는 합 리 적 인 색채 규범 을 제정 하고 규범 을 각 측의 이해관계 자 에 게 동기 화 하 는 것 이다.두 번 째 부분 은 UI 그림 색상 이 규범 화 된 색상 정의 값 입 니 다.예 를 들 어\#ffff 와 같은 색상 이 아 닙 니 다.예 를 들 어 White 가 필요 합 니 다.A.이렇게 규범 화 된 색상 정의 값 을 사용 하면 클 라 이언 트 가 처리 하 는 것 은 White 입 니 다.A.이 값 은 서로 다른 주제 에서 서로 다른 색채 표현 형식 에 신경 쓰 지 않 아 도 됩 니 다.
최적화 하 다.
loadConfigData With ColorMap 방법 호출 최적화
모듈 이 많 으 면 모듈 마다 loadConfigWith FileName 을 호출 하여 프로필 을 불 러 옵 니 다.loadConfigData With ColorMap 방법 으로 파일 을 처리 하 는 시간 복잡 도 는 O(N*N)입 니 다.불필요 한 작업 을 반복 적 으로 처리 합 니 다.이상 적 인 방법 은 기본 에 공유 색상 설정 을 저장 한 다음 에 APP 층 에 맞 춤 형 설정 을 불 러 오 는 것 입 니 다.모듈 에 테마 설정 파일 을 더 이상 불 러 오지 않 아 도 효율 을 높 일 수 있 습 니 다.
첨부:읽 기와 쓰기 자물쇠 pthreadrwlock_t 의 사용
읽 기와 쓰기 자 물 쇠 는 독자 의 문 제 를 해결 하 는 데 쓰 이 는 것 이다.읽 기 동작 은 공유 할 수 있 고 쓰기 동작 은 배타 적 이다.읽 기 동작 은 여러 개 만 읽 을 수 있 고 쓰 기 는 유일 하 게 쓰 고 쓸 때 읽 을 수 없다.
강 한 독자 동기 화 와 강 한 쓰기 자 동기 화 두 가지 형식 을 가지 고 있다.
강 한 독자 동기 화:작성 자가 쓰기 조작 을 하지 않 으 면 독자 가 방문 할 수 있다.
강 한 작성 자 동기 화:모든 작성 자가 다 쓴 후에 야 읽 기 작업 을 할 수 있 고 독 자 는 최신 정 보 를 필요 로 한다.일부 사실 성 이 높 은 시스템 은 이 곳,예 를 들 어 예약 표 와 같은 것 을 사용 할 수 있다.
자물쇠 읽 기 동작:
읽 기와 쓰기 자물쇠 의 초기 화:
정의 읽 기와 쓰기 잠 금: pthread_rwlock_t m_rw_lock;
함수 원형: pthread_rwlock_init(pthread_rwlock_t * ,pthread_rwattr_t *);
반환 값:0,성공 표시,0 이 아 닌 오류 코드
읽 기와 쓰기 자물쇠 의 소각:
함수 원형: pthread_rwlock_destroy(pthread_rwlock_t* );
반환 값:0,성공 표시,0 이 아 닌 오류 표시
읽 기와 쓰기 자 물 쇠 를 가 져 오 는 읽 기 자 물 쇠 를 가 져 옵 니 다.읽 기와 쓰기 자 물 쇠 를 한 쓰기 자가 가지 고 있 으 면 쓰기 자 물 쇠 를 풀 때 까지 읽 기 스 레 드 가 막 힙 니 다.
차단 식:
함수 원형:pthreadrwlock_rdlock(pthread_rwlock_t*);
비 차단 식:
함수 원형:pthreadrwlock_tryrdlock(pthread_rwlock_t*);
반환 값:0,성공 을 표시 합 니 다.0 이 아 닌 오류 코드 를 표시 합 니 다.차단 되 지 않 으 면 ebusy 로 돌아 가 스 레 드 를 기다 리 지 않 습 니 다.
읽 기와 쓰기 자 물 쇠 를 가 져 오 는 쓰기 동작:차단 과 비 차단 으로 나 뉘 는데 해당 하 는 읽 기와 쓰기 자 물 쇠 를 다른 작성 자가 가지 고 있 거나 읽 기와 쓰기 자 물 쇠 를 독자 가 가지 고 있 으 면 이 스 레 드 는 기다 리 는 것 을 막 습 니 다.
차단 식:
함수 원형:pthreadrwlock_wrlock(pthread_rwlock_t*);
비 차단 식:
함수 원형:pthreadrwlock_trywrlock(pthread_rwlock_t*);
반환 값:0,성공 표시
읽 기와 쓰기 잠 금 해제:
함수 원형:pthreadrwlock_unlock(pthread_rwlock_t*);
요약(전환):
상호 배척 자물쇠 와 읽 기와 쓰기 자물쇠 의 차이 점:
임계 구역 자원 에 접근 할 때(방문 의 의 미 는 모든 조작:읽 기와 쓰기 포함)상호 배척 자물쇠 가 필요 합 니 다.
데이터(상호 배척 자물쇠 의 임계 구역 자원)를 읽 을 때 읽 기 자 물 쇠 를 올 려 야 합 니 다.데 이 터 를 기록 할 때 자 물 쇠 를 올 려 야 합 니 다.
읽 기와 쓰기 자물쇠 의 장점:
읽 기 데이터 가 수정 데이터 보다 빈번 한 응용 에 대해 서 는 상호 배척 잠 금 대신 읽 기 쓰기 잠 금 을 사용 하면 효율 을 높 일 수 있다.상호 배척 자 물 쇠 를 사용 할 때 데 이 터 를 읽 는 것(임계 구역 자원 을 조작 하 는 것 과 같 음)도 서로 배척 하 는 자 물 쇠 를 사용 해 야 하기 때문에 읽 기와 쓰기 자 물 쇠 를 사용 하면 어느 순간 에 여러 읽 는 사람 이 존재 하도록 허용 하고 더 높 은 병행 도 를 높 일 수 있 으 며 특정한 기록 자가 데 이 터 를 수정 하 는 동안 이 데 이 터 를 보호 하여 다른 읽 는 사람 이나 기록 자의 간섭 을 피 할 수 있 기 때문이다.
읽 기 및 쓰기 잠 금 설명:
읽 기 및 쓰기 자 물 쇠 를 가 져 오 는 것 을 공유 자물쇠 라 고 합 니 다.읽 기 및 쓰기 자 물 쇠 를 가 져 오 는 것 을 독점 자물쇠 라 고 합 니 다.따라서 주어진 자원 에 대한 공유 접근 을 공유-독점 자물쇠 라 고도 합 니 다.
이러한 유형의 문제(여러 읽 기 및 쓰기 자)에 대한 다른 설 은 읽 기 및 쓰기 자 문제 및 다 중 읽 기-단일 쓰기 자 잠 금 이 있 습 니 다.
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Swift의 패스트 패스Objective-C를 대체하기 위해 만들어졌지만 Xcode는 Objective-C 런타임 라이브러리를 사용하기 때문에 Swift와 함께 C, C++ 및 Objective-C를 컴파일할 수 있습니다. Xcode는 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.